• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

icsm-au / DynAdjust / 4857311097

pending completion
4857311097

Pull #219

github

GitHub
Merge 3814a6b3c into dd0bd4fb6
Pull Request #219: Initial fixes and code enhancements for 1.2.8

419 of 419 new or added lines in 16 files covered. (100.0%)

30621 of 38760 relevant lines covered (79.0%)

3958.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.93
/dynadjust/dynadjust/dnaimportwrapper/dnaimportwrapper.cpp
1
//============================================================================
2
// Name         : dnaimportwrapper.cpp
3
// Author       : Roger Fraser
4
// Contributors :
5
// Version      : 1.00
6
// Copyright    : Copyright 2017 Geoscience Australia
7
//
8
//                Licensed under the Apache License, Version 2.0 (the "License");
9
//                you may not use this file except in compliance with the License.
10
//                You may obtain a copy of the License at
11
//               
12
//                http ://www.apache.org/licenses/LICENSE-2.0
13
//               
14
//                Unless required by applicable law or agreed to in writing, software
15
//                distributed under the License is distributed on an "AS IS" BASIS,
16
//                WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
//                See the License for the specific language governing permissions and
18
//                limitations under the License.
19
//
20
// Description  : DynAdjust Interoperability library Executable
21
//============================================================================
22

23
#include <dynadjust/dnaimportwrapper/dnaimportwrapper.hpp>
24
#include <include/parameters/dnaepsg.hpp>
25

26
using namespace dynadjust;
27
using namespace dynadjust::epsg;
28

29
bool running;
30
boost::mutex cout_mutex;
31

32
void PrintOutputFileHeaderInfo(std::ofstream* f_out, const string& out_file, project_settings* p, const string& header)
68✔
33
{
34
        // Print formatted header
35
        print_file_header(*f_out, header);
68✔
36

37
        *f_out << setw(PRINT_VAR_PAD) << left << "File name:" << system_complete(out_file).string() << endl << endl;
68✔
38
        
39
        *f_out << setw(PRINT_VAR_PAD) << left << "Command line arguments: ";
68✔
40
        *f_out << p->i.command_line_arguments << endl << endl;
68✔
41

42
        *f_out << setw(PRINT_VAR_PAD) << left << "Network name:" <<  p->g.network_name << endl;
68✔
43
        *f_out << setw(PRINT_VAR_PAD) << left << "Input folder: " << system_complete(p->g.input_folder).string() << endl;
68✔
44
        *f_out << setw(PRINT_VAR_PAD) << left << "Output folder: " << system_complete(p->g.output_folder).string() << endl;
68✔
45
        *f_out << setw(PRINT_VAR_PAD) << left << "Stations file:" << system_complete(p->i.bst_file).string() << endl;
68✔
46
        *f_out << setw(PRINT_VAR_PAD) << left << "Measurements file:" << system_complete(p->i.bms_file).string() << endl;
68✔
47
        *f_out << setw(PRINT_VAR_PAD) << left << "Associated station file:" << system_complete(p->i.asl_file).string() << endl;
68✔
48
        *f_out << setw(PRINT_VAR_PAD) << left << "Associated measurement file:" << system_complete(p->i.aml_file).string() << endl;
68✔
49
        *f_out << setw(PRINT_VAR_PAD) << left << "Duplicate stations output file:" <<  system_complete(p->i.dst_file).string() << endl;
68✔
50
        *f_out << setw(PRINT_VAR_PAD) << left << "Similar measurement output file:" <<  system_complete(p->i.dms_file).string() << endl;
68✔
51

52
        if (!p->i.input_files.empty())
68✔
53
        {
54
                _it_vstr _it_files(p->i.input_files.begin());
68✔
55
                string str("Input files:");
68✔
56
                while (_it_files!=p->i.input_files.end())
68✔
57
                {
58
                        *f_out << setw(PRINT_VAR_PAD) << left << str << *_it_files++ << endl;
166✔
59
                        str = " ";
234✔
60
                }
61
        }
68✔
62
        
63
        if (!p->i.reference_frame.empty())
68✔
64
                *f_out << setw(PRINT_VAR_PAD) << left << "Default reference frame:" << p->i.reference_frame << endl;
68✔
65
        
66
        if (!p->i.include_msrs.empty())
68✔
67
                *f_out << setw(PRINT_VAR_PAD) << left << "Strip all measurements except:" << p->i.include_msrs << endl;
2✔
68
        else if (!p->i.exclude_msrs.empty())
66✔
69
                *f_out << setw(PRINT_VAR_PAD) << left << "Strip measurement types:" << p->i.exclude_msrs << endl;
1✔
70

71
        if (p->i.exclude_insufficient_msrs == 1)
68✔
72
                *f_out << setw(PRINT_VAR_PAD) << left << "Exclude insufficient measurements:" << "yes" << endl;
×
73
        
74
        if (p->i.search_nearby_stn)
68✔
75
                *f_out << setw(PRINT_VAR_PAD) << left << "Search for nearby stations:" << "tolerance = " << p->i.search_stn_radius << "m" << endl;
3✔
76
        if (p->i.search_similar_msr)
68✔
77
                *f_out << setw(PRINT_VAR_PAD) << left << "Search for similar measurements:" << "yes" << endl;
6✔
78
        if (p->i.search_similar_msr_gx)
68✔
79
                *f_out << setw(PRINT_VAR_PAD) << left << "Search for similar GNSS measurements:" << "yes" << endl;
2✔
80
        
81
        if (!p->i.bounding_box.empty())
68✔
82
        {
83
                *f_out << setw(PRINT_VAR_PAD) << left << "Bounding box: " << p->i.bounding_box << endl;
1✔
84
                if (p->i.split_clusters)
1✔
85
                        *f_out << setw(PRINT_VAR_PAD) << left << "Split GNSS clusters: " << (p->i.split_clusters ? "Yes" : "No") << endl;
1✔
86
        }
87
        else 
88
        {
89
                if (!p->i.stn_associated_msr_include.empty())
67✔
90
                        *f_out << setw(PRINT_VAR_PAD) << left << "Stations to include: " << p->i.stn_associated_msr_include << endl;
5✔
91
                if (!p->i.stn_associated_msr_exclude.empty())
67✔
92
                        *f_out << setw(PRINT_VAR_PAD) << left << "Stations to exclude: " << p->i.stn_associated_msr_exclude << endl;
1✔
93

94
                if (p->i.split_clusters)
67✔
95
                        *f_out << setw(PRINT_VAR_PAD) << left << "Split GNSS clusters: " << (p->i.split_clusters ? "Yes" : "No") << endl;
4✔
96
        }
97

98
        if (!p->i.seg_file.empty())
68✔
99
                *f_out << setw(PRINT_VAR_PAD) << left << "Segmentation file:" << system_complete(p->i.seg_file).string() << endl;
1✔
100

101
        if (p->i.import_block)
68✔
102
                *f_out << setw(PRINT_VAR_PAD) << left << "Import stns & msrs from block: " << p->i.import_block_number << endl;
4✔
103
        else if (p->i.import_network)
64✔
104
                *f_out << setw(PRINT_VAR_PAD) << left << "Import stns & msrs from network: " << p->i.import_network_number << endl;
×
105
        
106
        *f_out << OUTPUTLINE << endl << endl;
68✔
107
}
68✔
108
        
109
int ParseCommandLineOptions(const int& argc, char* argv[], const variables_map& vm, project_settings& p)
63✔
110
{
111
        // capture command line arguments
112
        for (int cmd_arg(0); cmd_arg<argc; ++cmd_arg)
549✔
113
        {
114
                 p.i.command_line_arguments += argv[cmd_arg];
486✔
115
                 p.i.command_line_arguments += " ";
486✔
116
        }
117

118
        if (vm.count(PROJECT_FILE))
63✔
119
        {
120
                if (exists(p.g.project_file))
2✔
121
                {
122
                        try {
1✔
123
                                CDnaProjectFile projectFile(p.g.project_file, importSetting);
1✔
124
                                p = projectFile.GetSettings();
1✔
125
                        }
×
126
                        catch (const runtime_error& e) {
×
127
                                cout << endl << "- Error: " << e.what() << endl;
×
128
                                return EXIT_FAILURE;
×
129
                        }
×
130
                        
131
                        return EXIT_SUCCESS;
1✔
132
                }
133

134
                cout << endl << "- Error: project file " << p.g.project_file << " does not exist." << endl << endl;
1✔
135
                return EXIT_FAILURE;
1✔
136
        }
137

138
        if (!vm.count(IMPORT_FILE) && !vm.count(IMPORT_SEG_BLOCK) && !vm.count(IMPORT_CONTIG_NET) && !vm.count(SEG_FILE))
64✔
139
        {
140
                cout << endl << "- Nothing to do - no files specified. " << endl << endl;  
1✔
141
                return EXIT_FAILURE;
1✔
142
        }
143

144
        // Normalise files using input folder
145
        for_each(p.i.input_files.begin(), p.i.input_files.end(),
60✔
146
                [&p] (string& file) { 
270✔
147
                        formPath<string>(p.g.input_folder, file);
270✔
148
                }
135✔
149
        );
150

151
        //////////////////////////////////////////////////////////////////////////////
152
        // General options and file paths
153
        // Network name
154
        if (p.g.network_name == "network1")
60✔
155
        {
156
                // Iterate through network1, network2, network3, etc 
157
                // until the first name not used is found
158
                stringstream netname_ss;
2✔
159
                string networkASL;
2✔
160
                UINT32 networkID(1);
2✔
161
                
162
                // This loop terminates when a file name cannot be found
163
                while (true)
4✔
164
                {
165
                        // 1. Form ASL file and see if it exists
166
                        networkASL = formPath<string>(p.g.output_folder, p.g.network_name, "asl");
3✔
167

168
                        // 2. Does this network exist?
169
                        if (!exists(networkASL))
3✔
170
                                break;
171

172
                        // 3. Flush and look for the next network
173
                        netname_ss.str("");
2✔
174
                        netname_ss << "network" << ++networkID;
1✔
175
                        p.g.network_name = netname_ss.str();                        
1✔
176
                }
177
        }
2✔
178

179
        p.g.project_file = formPath<string>(p.g.output_folder, p.g.network_name, "dnaproj");
60✔
180

181
        // binary station file location (output)
182
        if (vm.count(BIN_STN_FILE))
60✔
183
                p.i.bst_file = formPath<string>(p.g.output_folder, p.i.bst_file);
×
184
        else
185
                p.i.bst_file = formPath<string>(p.g.output_folder, p.g.network_name, "bst");
60✔
186
        
187
        // binary station file location (output)
188
        if (vm.count(BIN_MSR_FILE))
60✔
189
                p.i.bms_file = formPath<string>(p.g.output_folder, p.i.bms_file);
×
190
        else
191
                p.i.bms_file = formPath<string>(p.g.output_folder, p.g.network_name, "bms");
60✔
192

193
        if (vm.count(IMPORT_GEO_FILE))
60✔
194
                p.i.import_geo_file = 1;
2✔
195

196
        // output files
197
        p.i.asl_file = formPath<string>(p.g.output_folder, p.g.network_name, "asl");        // associated stations list
60✔
198
        p.i.aml_file = formPath<string>(p.g.output_folder, p.g.network_name, "aml");        // associated measurements list
60✔
199
        p.i.map_file = formPath<string>(p.g.output_folder, p.g.network_name, "map");        // station names map
60✔
200
        p.i.dst_file = formPath<string>(p.g.output_folder, p.g.network_name, "dst");        // fuplicate stations
60✔
201
        p.i.dms_file = formPath<string>(p.g.output_folder, p.g.network_name, "dms");        // duplicate measurements
60✔
202
        p.i.imp_file = formPath<string>(p.g.output_folder, p.g.network_name, "imp");        // log
60✔
203
        
204
        //////////////////////////////////////////////////////////////////////////////
205
        // Ref frame options
206
        if (vm.count(OVERRIDE_INPUT_FRAME))
60✔
207
                p.i.override_input_rfame = 1;
5✔
208
        if (vm.count(REFERENCE_FRAME))
60✔
209
                p.i.user_supplied_frame = 1;
16✔
210

211
        //////////////////////////////////////////////////////////////////////////////
212
        // Data screening options
213
        if (vm.count(GET_MSRS_TRANSCENDING_BOX))
60✔
214
                p.i.include_transcending_msrs = 1;
2✔
215

216
        if (vm.count(SPLIT_CLUSTERS))
60✔
217
                p.i.split_clusters = 1;
5✔
218

219
        if (vm.count(IMPORT_SEG_BLOCK) && vm.count(IMPORT_CONTIG_NET))
66✔
220
        {
221
                cout << endl << "- Error: Cannot import stations and measurements using both options" << endl << "  --" << IMPORT_SEG_BLOCK << " and --" << IMPORT_CONTIG_NET << "." << endl <<
×
222
                        "  Please supply only one option." << endl << endl;
×
223
                return EXIT_FAILURE;
×
224
        }
225

226
        // Import stations and measurements from a block
227
        if (vm.count(IMPORT_SEG_BLOCK))
60✔
228
        {
229
                p.i.import_block = 1;
3✔
230
                if (p.i.import_block_number < 1)
3✔
231
                        p.i.import_block_number = 1;
×
232
        }
233

234
        // Import stations and measurements from a contiguous network
235
        if (vm.count(IMPORT_CONTIG_NET))
60✔
236
                p.i.import_network = 1;
×
237
        
238
        // User supplied segmentation file
239
        if (vm.count(SEG_FILE))
60✔
240
        {
241
                // Does it exist?
242
                if (!exists(p.i.seg_file))
1✔
243
                        // Look for it in the input folder
244
                        p.i.seg_file = formPath<string>(p.g.input_folder, leafStr<string>(p.i.seg_file));
1✔
245
        }
246

247
        // convert all single X measurements to G measurements?
248
        if (vm.count(PREFER_X_MSR_AS_G))
60✔
249
                p.i.prefer_single_x_as_g = 1;
3✔
250

251
        if (vm.count(TEST_NEARBY_STNS))
60✔
252
                p.i.search_nearby_stn = 1;
2✔
253

254
        if (vm.count(TEST_SIMILAR_MSRS))
60✔
255
                p.i.search_similar_msr = 1;
3✔
256

257
        if (vm.count(TEST_SIMILAR_GNSS_MSRS))
60✔
258
                p.i.search_similar_msr_gx = 1;
1✔
259

260
        if (vm.count(IGNORE_SIMILAR_MSRS))
60✔
261
                p.i.ignore_similar_msr = 1;
2✔
262

263
        if (vm.count(EXCLUDE_INSUFFICIENT_MSRS))
60✔
264
                p.i.exclude_insufficient_msrs = 1;
×
265

266
        if (vm.count(REMOVE_IGNORED_MSRS))
60✔
267
                p.i.remove_ignored_msr = 1;
1✔
268

269
        if (vm.count(FLAG_UNUSED_STNS))
60✔
270
                p.i.flag_unused_stn = 1;
5✔
271

272
        if (vm.count(TEST_INTEGRITY))
60✔
273
                p.i.test_integrity = 1;
2✔
274
        
275
        //////////////////////////////////////////////////////////////////////////////
276
        // GNSS scaling
277
        if (vm.count(VSCALE) ||
179✔
278
                vm.count(PSCALE) ||
178✔
279
                vm.count(LSCALE) ||
178✔
280
                vm.count(HSCALE) ||
238✔
281
                vm.count(SCALAR_FILE))
178✔
282
                p.i.apply_scaling = 1;
2✔
283

284
        if (vm.count(SCALAR_FILE))
60✔
285
                if (!exists(p.i.scalar_file))                        // does it exist?
1✔
286
                        // No.  Assume it is a filename contained in the input folder.  import will throw
287
                        // an exception if it cannot be found.
288
                        p.i.scalar_file = formPath<string>(p.g.input_folder, p.i.scalar_file);        
×
289
        
290
        //////////////////////////////////////////////////////////////////////////////
291
        // Export options
292
        
293
        if (vm.count(OUTPUT_MSR_TO_STN))
60✔
294
                p.o._msr_to_stn = 1;
6✔
295

296
        p.o._m2s_file = formPath<string>(p.g.output_folder, p.g.network_name, "m2s");        // measurement to stations table
60✔
297

298
        // Create file name based on the provided block number or contiguous network number
299
        string fileName(p.g.network_name);
60✔
300
        if (p.i.import_block)
60✔
301
        {
302
                stringstream blk("");
3✔
303
                blk << ".block-" << p.i.import_block_number;
3✔
304
                fileName += blk.str();
6✔
305
        }
3✔
306
        else if (p.i.import_network)
57✔
307
        {
308
                stringstream net("");
×
309
                net << ".network-" << p.i.import_network_number;
×
310
                fileName += net.str();
×
311
        }
×
312

313
        // Export to dynaml?
314
        if (vm.count(EXPORT_XML_FILES))
60✔
315
        {
316
                p.i.export_dynaml = 1;
10✔
317
        
318
                //// Export from binary
319
                //if (vm.count(EXPORT_FROM_BINARY))
320
                //        p.i.export_from_bfiles = 1;
321

322
                // single file for both stations and measurements
323
                if (vm.count(EXPORT_SINGLE_XML_FILE))
10✔
324
                {
325
                        p.i.export_single_xml_file = 1;
2✔
326
                        p.i.xml_outfile = formPath<string>(p.g.output_folder, 
4✔
327
                                fileName, "xml");
2✔
328
                }
329
                // unique files for stations and measurements
330
                else
331
                {
332
                        p.i.export_single_xml_file = 0;
8✔
333
                        p.i.xml_stnfile = formPath<string>(p.g.output_folder, 
24✔
334
                                fileName + "stn", "xml");
24✔
335
                        p.i.xml_msrfile = formPath<string>(p.g.output_folder, 
32✔
336
                                fileName + "msr", "xml");
24✔
337
                }
338
        }
339

340
        // Export dna files
341
        if (vm.count(EXPORT_DNA_FILES))
60✔
342
        {
343
                p.i.export_dna_files = 1;                
8✔
344
                p.i.dna_stnfile = formPath<string>(p.g.output_folder, 
16✔
345
                        fileName, "stn");
8✔
346
                p.i.dna_msrfile = formPath<string>(p.g.output_folder, 
16✔
347
                        fileName, "msr");
8✔
348
        }
349

350
        if (vm.count(EXPORT_ASL_FILE))
60✔
351
                p.i.export_asl_file = 1;
4✔
352
        if (vm.count(EXPORT_AML_FILE))
60✔
353
                p.i.export_aml_file = 1;
4✔
354
        if (vm.count(EXPORT_MAP_FILE))
60✔
355
                p.i.export_map_file = 1;
4✔
356
        if (vm.count(EXPORT_DISCONT_FILE))
60✔
357
                p.i.export_discont_file = 1;
1✔
358
        
359
        // Simulate
360
        if (vm.count(SIMULATE_MSR_FILE))
60✔
361
        {
362
                p.i.simulate_measurements = 1;
1✔
363
                p.i.simulate_msrfile = formPath<string>(p.g.output_folder,
2✔
364
                        p.g.network_name, "simulated.msr");
1✔
365
        }
366

367
        // Station renaming file
368
        if (vm.count(STATION_RENAMING_FILE))
60✔
369
                p.i.rename_stations = 1;
1✔
370

371
        return EXIT_SUCCESS;
60✔
372
}
63✔
373

374
void PrintMeasurementstoStations(MsrTally* parsemsrTally, dna_import* parserDynaML, 
53✔
375
        project_settings* p, pvASLPtr vAssocStnList)
376
{
377
        // Print measurements to stations table
378
        if (p->o._msr_to_stn)
53✔
379
        {
380
                if (!p->g.quiet)
6✔
381
                {
382
                        cout << "+ Printing summary of measurements connected to each station...";
6✔
383
                        cout.flush();
6✔
384
                }
385
                parserDynaML->PrintMeasurementsToStations(p->o._m2s_file, parsemsrTally, 
6✔
386
                        p->i.bst_file, p->i.bms_file, p->i.aml_file, vAssocStnList);
6✔
387
                if (!p->g.quiet)
6✔
388
                        cout << " done." << endl;
6✔
389
        }
390
}
53✔
391

392
int SearchForSimilarMeasurements(dna_import* parserDynaML, project_settings* p, std::ofstream* imp_file,
4✔
393
        vdnaMsrPtr* vmeasurementsTotal)
394
{
395
        std::ofstream dms_file;
4✔
396
        UINT32 msr;
4✔
397
        vdnaMsrPtr vSimilarMeasurements;
4✔
398
        string comment("");
4✔
399

400
        try {
4✔
401
                if (!p->g.quiet)
4✔
402
                {
403
                        cout << "+ Searching for similar measurements... ";
3✔
404
                        cout.flush();
3✔
405
                }
406
                *imp_file << "+ Searching for similar measurements... ";
4✔
407

408
                // at this stage, perform only one search option, giving preference to GNSS searching 
409
                // if both are provided
410
                if (p->i.search_similar_msr_gx)
4✔
411
                        msr = parserDynaML->FindSimilarGXMeasurements(vmeasurementsTotal, &vSimilarMeasurements);
1✔
412
                else
413
                        msr = parserDynaML->FindSimilarMeasurements(vmeasurementsTotal, &vSimilarMeasurements);
3✔
414

415
                if (!vSimilarMeasurements.empty())
4✔
416
                {
417
                        ostringstream ss_msg;
4✔
418
                        if (!p->i.ignore_similar_msr)
4✔
419
                                ss_msg << endl << "- Warning: ";
2✔
420
                        else
421
                                ss_msg << endl << "- Note: ";
2✔
422

423
                        ss_msg << msr << " measurement" << (msr > 1 ? "s were" : " was") << 
4✔
424
                                " found to be very similar (if not identical)\n  to " << 
425
                                (msr > 1 ? "other measurements" : "another measurement") << 
426
                                ".  See " << p->i.dms_file << " for details." << endl;
4✔
427

428
                        *imp_file << ss_msg.str();
4✔
429
                        if (!p->g.quiet)
4✔
430
                                cout << ss_msg.str();
3✔
431
                        ss_msg.str("");
8✔
432

433
                        try {
4✔
434
                                // Create duplicate measurements file
435
                                file_opener(dms_file, p->i.dms_file);
4✔
436
                        }
437
                        catch (const ios_base::failure& f) {
×
438
                                stringstream ss;
×
439
                                ss << "- Error: Could not open " << p->i.dms_file << "." << endl;
×
440
                                ss << "  Check that the file exists and that the file is not already opened." << endl << f.what();
×
441
                                if (!p->g.quiet)
×
442
                                        cout << ss.str();
×
443
                                *imp_file << ss.str();
×
444
                                imp_file->close();
×
445
                                return EXIT_FAILURE;
×
446
                        }
×
447

448
                        PrintOutputFileHeaderInfo(&dms_file, p->i.dms_file, p, "DUPLICATE MEASUREMENTS FILE");
4✔
449

450
                        // output message
451
                        dms_file << endl << "- " << msr << " measurement" << (msr > 1 ? "s were" : " was") << 
4✔
452
                                " found to be very similar (if not identical)\n  to " << 
453
                                (msr > 1 ? "other measurements." : "another measurement.  ");
4✔
454

455
                        if (p->i.ignore_similar_msr)
4✔
456
                                dms_file << endl << "+ These measurements have been ignored.";
2✔
457
                        dms_file << endl << endl;
4✔
458

459
                        // dump measurements to dms file
460
                        for_each (vSimilarMeasurements.begin(), vSimilarMeasurements.end(),
4✔
461
                                [&dms_file, &comment] (dnaMsrPtr& m) {
118✔
462
                                        m->WriteDynaMLMsr(&dms_file, comment);
59✔
463
                        });
59✔
464

465
                        dms_file.close();
4✔
466

467
                        if (p->i.ignore_similar_msr)
4✔
468
                                ss_msg << "  These measurements have been ignored." << endl;
2✔
469
                        else
470
                                ss_msg << endl <<
2✔
471
                                "  If the listed measurements are true duplicates, either remove each duplicate " << endl <<
2✔
472
                                "  from the measurement file and re-run " << __BINARY_NAME__ << ", or re-run " << __BINARY_NAME__ << " with the" << endl <<
2✔
473
                                "  --" << IGNORE_SIMILAR_MSRS << " option.  Alternatively, if each measurement " << endl <<
2✔
474
                                "  is unique, then call " << __BINARY_NAME__ << " without the --" << TEST_SIMILAR_MSRS << " option." << endl << endl;
2✔
475

476
                        if (!p->g.quiet)
4✔
477
                                cout << ss_msg.str();
3✔
478
                        *imp_file << ss_msg.str();
4✔
479

480
                        if (!p->i.ignore_similar_msr)
4✔
481
                        {
482
                                //imp_file->close();
483
                                return EXIT_SUCCESS;
484
                        }
485
                }
4✔
486
                else
487
                {
488
                        *imp_file << "Done. ";
×
489
                        if (!p->g.quiet)
×
490
                        {
491
                                cout << "Done. ";
×
492
                                cout.flush();
×
493
                        }
494
                }
495

496
                *imp_file << endl;
2✔
497
                if (!p->g.quiet)
2✔
498
                {
499
                        cout << endl;
2✔
500
                        cout.flush();
2✔
501
                }
502

503
        } 
504
        catch (const XMLInteropException& e) {
×
505
                cout << endl << "- Error: " << e.what() << endl;
×
506
                *imp_file << endl << "- Error: " << e.what() << endl;
×
507
                imp_file->close();
×
508
                return EXIT_FAILURE;
×
509
        }
×
510

511
        return EXIT_SUCCESS;
512

513
}
4✔
514
        
515

516
void ExportStationsandMeasurements(dna_import* parserDynaML, const project_settings& p, std::ofstream* imp_file, vifm_t* vinput_file_meta,
12✔
517
        vdnaStnPtr* vstationsTotal, vdnaMsrPtr* vmeasurementsTotal, const UINT32& stnCount, const UINT32& msrCount)
518
{
519
        stringstream ssEpsgWarning;
12✔
520
        bool displayEpsgWarning(false);
12✔
521
        string epsgCode(epsgStringFromName<string>(p.i.reference_frame));
12✔
522

523
        // Check inconsistent reference frames
524
        if ((p.i.export_dynaml || p.i.export_dna_files) && !p.i.override_input_rfame && !p.i.user_supplied_frame)
12✔
525
        {
526
                for (UINT32 i(0); i<vinput_file_meta->size(); ++i)
23✔
527
                {
528
                        if (!iequals(epsgCode, vinput_file_meta->at(i).epsgCode))
18✔
529
                        {
530
                                string inputFrame(datumFromEpsgString<string>(vinput_file_meta->at(i).epsgCode));
3✔
531
                                ssEpsgWarning << endl << "- Warning: The default reference frame (used for all exported files)" << endl << 
3✔
532
                                        "  does not match the reference frame of one or more input files. To" << endl <<
3✔
533
                                        "  suppress this warning, override the default reference frame using" << endl <<
3✔
534
                                        "  --reference-frame, or provide --override-input-ref-frame.";
3✔
535
                                displayEpsgWarning = true;
3✔
536
                                break;
3✔
537
                        }
3✔
538
                }
539
        }
540

541
        // Sort on original file order
542
        parserDynaML->SortStationsForExport(vstationsTotal);
12✔
543

544
        // DynaML file format
545
        if (p.i.export_dynaml && (stnCount > 0 || msrCount > 0)) 
12✔
546
        {                
547
                if (p.i.export_single_xml_file)
10✔
548
                {
549
                        // Single output file
550
                        if (!p.g.quiet)
2✔
551
                        {
552
                                cout << "+ Exporting stations and measurements to " << leafStr<string>(p.i.xml_outfile) << "... ";
4✔
553
                                cout.flush();
2✔
554
                        }
555
                        *imp_file << "+ Exporting stations and measurements to " << leafStr<string>(p.i.xml_outfile) << "... ";
4✔
556
                        parserDynaML->SerialiseDynaMLfromMemory(
2✔
557
                                vstationsTotal, vmeasurementsTotal, 
558
                                p.i.xml_outfile, p, vinput_file_meta, (p.i.flag_unused_stn ? true : false));
2✔
559
                }
560
                else
561
                {
562
                        // Separate output files (default)
563
                        if (!p.g.quiet)
8✔
564
                        {
565
                                cout << "+ Exporting stations and measurements to " << leafStr<string>(p.i.xml_stnfile) << " and " << leafStr<string>(p.i.xml_msrfile) << "... ";
32✔
566
                                cout.flush();
8✔
567
                        }
568
                        *imp_file << "+ Exporting stations and measurements to " << leafStr<string>(p.i.xml_stnfile) << " and " << leafStr<string>(p.i.xml_msrfile) << "... ";
32✔
569
                        parserDynaML->SerialiseDynaMLSepfromMemory(
8✔
570
                                vstationsTotal, vmeasurementsTotal,
571
                                p.i.xml_stnfile, p.i.xml_msrfile, p, vinput_file_meta, (p.i.flag_unused_stn ? true : false));
8✔
572
                }
573
                if (!p.g.quiet)
10✔
574
                {
575
                        cout << "Done." << endl;
10✔
576
                        cout.flush();
10✔
577
                }
578
                *imp_file << "Done." << endl;                
10✔
579
        }
580

581
        // DNA file format
582
        if (p.i.export_dna_files && (stnCount > 0 || msrCount > 0)) 
12✔
583
        {
584
                // Separate output files (default)
585
                if (!p.g.quiet)
7✔
586
                {
587
                        cout << "+ Exporting stations and measurements to " << leafStr<string>(p.i.dna_stnfile) << " and " << leafStr<string>(p.i.dna_msrfile) << "... ";
28✔
588
                        cout.flush();
7✔
589
                }
590
                *imp_file << "+ Exporting stations and measurements to " << leafStr<string>(p.i.dna_msrfile) << " and " << leafStr<string>(p.i.dna_msrfile) << "... ";
28✔
591
                parserDynaML->SerialiseDNA(
7✔
592
                        vstationsTotal, vmeasurementsTotal,
593
                        p.i.dna_stnfile, p.i.dna_msrfile, p, vinput_file_meta, (p.i.flag_unused_stn ? true : false));
7✔
594
                if (!p.g.quiet)
7✔
595
                        cout << "Done." << endl;
7✔
596
                *imp_file << "Done." << endl;
7✔
597

598
        }
599

600
        if (displayEpsgWarning)
12✔
601
        {
602
                cout << ssEpsgWarning.str() << endl;
3✔
603
                *imp_file << ssEpsgWarning.str() << endl;
3✔
604
                cout.flush();
3✔
605
        }
606
}
12✔
607

608
int PrepareImportSegmentedData(project_settings& p, bool& userSuppliedSegFile)
4✔
609
{
610
        // Form default seg file path
611
        userSuppliedSegFile = false;
4✔
612

613
        // Has the user provided a segmentation file?
614
        if (!p.i.seg_file.empty())
4✔
615
                userSuppliedSegFile = true;
1✔
616
        else
617
                p.i.seg_file = formPath<string>(p.g.input_folder, p.g.network_name, "seg");
3✔
618

619
        if (!exists(p.i.seg_file))
4✔
620
        {
621
                cout << endl << "- Error: The required segmentation file does not exist:" << endl <<
×
622
                        "         " << p.i.seg_file << endl << endl <<
×
623
                        "  Run  'segment " << p.g.network_name << "' to create a segmentation file" << endl << endl;
×
624
                return EXIT_FAILURE;
×
625
        }
626

627
        if (!exists(p.i.bst_file))
4✔
628
        {
629
                cout << endl << "- Error: The required binary station file does not exist:" << endl <<
×
630
                        "         " << p.i.bst_file << endl << endl;
×
631
                return EXIT_FAILURE;
×
632
        }
633

634
        if (!exists(p.i.bms_file))
4✔
635
        {
636
                cout << endl << "- Error: The required binary measurement file does not exist:" << endl <<
×
637
                        "         " << p.i.bms_file << endl << endl;
×
638
                return EXIT_FAILURE;
×
639
        }
640

641
        // If the user has not provided a seg file, check the meta of the default file
642
        if (!userSuppliedSegFile)
4✔
643
        {
644
                if (last_write_time(p.i.seg_file) < last_write_time(p.i.bst_file) ||
6✔
645
                        last_write_time(p.i.seg_file) < last_write_time(p.i.bms_file))
9✔
646
                {
647
                        // Has import been run after the segmentation file was created?
648
                        binary_file_meta_t bst_meta, bms_meta;
×
649
                        dna_io_bst bst;
×
650
                        dna_io_bms bms;
×
651
                        bst.load_bst_file_meta(p.i.bst_file, bst_meta);
×
652
                        bms.load_bms_file_meta(p.i.bms_file, bms_meta);
×
653

654
                        bool bst_meta_import(iequals(bst_meta.modifiedBy, __import_app_name__) ||
×
655
                                iequals(bst_meta.modifiedBy, __import_dll_name__));
×
656
                        bool bms_meta_import(iequals(bms_meta.modifiedBy, __import_app_name__) ||
×
657
                                iequals(bms_meta.modifiedBy, __import_dll_name__));
×
658

659
                        if ((bst_meta_import && (last_write_time(p.i.seg_file) < last_write_time(p.i.bst_file))) ||
×
660
                                (bms_meta_import && (last_write_time(p.i.seg_file) < last_write_time(p.i.bms_file))))
×
661
                        {
662

663
                                cout << endl << endl <<
×
664
                                        "- Error: The raw stations and measurements have been imported after" << endl <<
×
665
                                        "  the segmentation file was created:" << endl;
×
666

667
                                time_t t_bst(last_write_time(p.i.bst_file)), t_bms(last_write_time(p.i.bms_file));
×
668
                                time_t t_seg(last_write_time(p.i.seg_file));
×
669

670
                                cout << "   " << leafStr<string>(p.i.bst_file) << "  last modified on  " << ctime(&t_bst);
×
671
                                cout << "   " << leafStr<string>(p.i.bms_file) << "  last modified on  " << ctime(&t_bms) << endl;
×
672
                                cout << "   " << leafStr<string>(p.i.seg_file) << "  created on  " << ctime(&t_seg) << endl;
×
673
                                cout << "  Run 'segment " << p.g.network_name << " [options]' to re-create the segmentation file, or re-run" << endl <<
×
674
                                        "  the import using the " << SEG_FILE << " option if this segmentation file must\n  be used." << endl << endl;
×
675
                                return EXIT_FAILURE;
×
676
                        }
677
                }
×
678
        }
679

680
        return EXIT_SUCCESS;
681
}
682

683
int ImportSegmentedBlock(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements, 
4✔
684
                StnTally* parsestnTally, MsrTally* parsemsrTally, project_settings& p)
685
{        
686
        // Form default seg file path
687
        bool userSuppliedSegFile(false);
4✔
688

689
        if (PrepareImportSegmentedData(p, userSuppliedSegFile) != EXIT_SUCCESS)
4✔
690
                return EXIT_FAILURE;
691

692
        // Import stations and measurements from a particular block
693
        if (!p.g.quiet)
4✔
694
                cout << endl << "+ Importing stations and measurements from block " << p.i.import_block_number << " of\n  " << p.i.seg_file << "... ";
4✔
695
        parserDynaML.ImportStnsMsrsFromBlock(vStations, vMeasurements, p);
4✔
696
        *parsestnTally += parserDynaML.GetStnTally();
4✔
697
        *parsemsrTally += parserDynaML.GetMsrTally();
4✔
698
        if (!p.g.quiet)
4✔
699
                cout << "Done. " << endl;
4✔
700

701
        // Restore seg_file to null
702
        if (!userSuppliedSegFile)
4✔
703
                p.i.seg_file = "";
3✔
704

705
        return EXIT_SUCCESS;
706
}
707

708
int ImportContiguousNetwork(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements,
×
709
        StnTally* parsestnTally, MsrTally* parsemsrTally, project_settings& p)
710
{
711
        // Form default seg file path
712
        bool userSuppliedSegFile(false);
×
713

714
        if (PrepareImportSegmentedData(p, userSuppliedSegFile) != EXIT_SUCCESS)
×
715
                return EXIT_FAILURE;
716

717
        // Import stations and measurements from a particular block
718
        if (!p.g.quiet)
×
719
                cout << endl << "+ Importing stations and measurements from contiguous network " << p.i.import_network_number << " of\n  " << p.i.seg_file << "... ";
×
720
        parserDynaML.ImportStnsMsrsFromNetwork(vStations, vMeasurements, p);
×
721
        *parsestnTally += parserDynaML.GetStnTally();
×
722
        *parsemsrTally += parserDynaML.GetMsrTally();
×
723
        if (!p.g.quiet)
×
724
                cout << "Done. " << endl;
×
725

726
        // Restore seg_file to null
727
        if (!userSuppliedSegFile)
×
728
                p.i.seg_file = "";
×
729

730
        return EXIT_SUCCESS;
731
}
732
        
733

734
int ImportDataFiles(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements,
56✔
735
                vdnaStnPtr* vstationsTotal, vdnaMsrPtr* vmeasurementsTotal,
736
                std::ofstream* imp_file, vifm_t* vinput_file_meta, StnTally* parsestnTally, MsrTally* parsemsrTally, 
737
                UINT32& errorCount, project_settings& p)
738
{
739
        // For consideration:  
740
        //        - All input files could be read concurrently using multi-thread for faster input
741
        //        - The number of files that can be processed concurrently should be restricted to
742
        //          the number of available cores
743
        //        - If multi-threading is to be used, then the progress thread will need to be redesigned.
744
        //          Currently, the progress of each file (as a percentage) is written to cout as each file
745
        //          is processed. If files are processed concurrently, progress reporting will need to be
746
        //    redesigned if multiple progress threads are writing to cout.
747
        //        - There is significant gain in using multi-thread.
748
        //        - The catch will be the need to carefully design one progress thread that captures progress
749
        //          of all other "read" threads (rather than one progress for each), and somehow write to 
750
        //          cout the respective progress.  For example, loading four files could be displayed as 
751
        //          follows:
752
        //
753
        //          + Parsing file1.xml (32%), file2.xml (16%), file3.xml (86%), file4.xml (56%)
754
        //            Done: Loaded 190 stations from file3.xml in 00.032s
755
        //          + Parsing file1.xml (72%), file2.xml (48%), file4.xml (91%)
756
        //            Done: Loaded 236 stations from file4.xml in 00.050s
757
        //          + Parsing file1.xml (87%), file2.xml (76%)
758
        //            Done: Loaded 1596 measurements from file1.xml in 01.380s
759
        //            Done: Loaded 3142 measurements from file2.xml in 02.034s
760
        //
761
        UINT32 stnCount(0), msrCount(0), clusterID(0);
56✔
762
        
763
        // obtain the project reference frame
764
        string epsgCode(epsgStringFromName<string>(p.i.reference_frame));
56✔
765
        
766
        size_t pos = string::npos;
56✔
767
        size_t strlen_arg = 0;
56✔
768
        for_each(p.i.input_files.begin(), p.i.input_files.end(),
56✔
769
                [&strlen_arg](string& file) {
192✔
770
                        if (leafStr<string>(file).length() > strlen_arg)
127✔
771
                                strlen_arg = leafStr<string>(file).length();
65✔
772
        });
127✔
773

774
        strlen_arg += (6 + PROGRESS_PERCENT_04);
56✔
775

776
        size_t i, nfiles(p.i.input_files.size());                // for each file...
56✔
777
        string input_file, ss, status_msg;
56✔
778
        vstring input_files;
56✔
779
        ostringstream ss_time, ss_msg;
56✔
780
        input_file_meta_t input_file_meta;
56✔
781
        milliseconds elapsed_time(milliseconds(0));
56✔
782
        ptime pt;
56✔
783

784
        if (!p.g.quiet)
56✔
785
                cout << "+ Parsing: " << endl;
55✔
786
        *imp_file << "+ Parsing " << endl;
56✔
787

788
        for (i=0; i<nfiles; i++)
178✔
789
        {
790
                stnCount = msrCount = 0;
125✔
791
                input_file = p.i.input_files.at(i);
125✔
792
                if (!exists(input_file))
125✔
793
                {
794
                        input_file = formPath<string>(p.g.input_folder, input_file);
3✔
795
                        if (!exists(input_file))
3✔
796
                        {        
797
                                cout << "- Error:  " << input_file << " does not exist" << endl;
3✔
798
                                return EXIT_FAILURE;
3✔
799
                        }
800
                }
801
                        
802
                input_files.push_back(input_file);
122✔
803
                ss = leafStr<string>(p.i.input_files.at(i)) + "... ";
122✔
804
                if (!p.g.quiet)
122✔
805
                        cout << "  " << setw(strlen_arg) << left << ss;
120✔
806
                *imp_file << "  " << setw(strlen_arg) << left << ss;
122✔
807

808
                running = true;
122✔
809
                thread_group ui_interop_threads;
122✔
810
                if (!p.g.quiet)
122✔
811
                        ui_interop_threads.create_thread(dna_import_progress_thread(&parserDynaML, &p));
120✔
812
                ui_interop_threads.create_thread(dna_import_thread(&parserDynaML, &p, input_file,
122✔
813
                        vStations, &stnCount, vMeasurements, &msrCount,
814
                        &clusterID, &input_file_meta, &status_msg,
815
                        &elapsed_time));
816
                ui_interop_threads.join_all();
122✔
817

818
                switch (parserDynaML.GetStatus())
122✔
819
                {
820
                case PARSE_EXCEPTION_RAISED:
×
821
                        *imp_file << endl << status_msg;
×
822
                        running = false;
×
823
                        return EXIT_FAILURE;
×
824
                        break;
×
825
                case PARSE_UNRECOGNISED_FILE:
×
826
                        *imp_file << status_msg << endl;
×
827
                        errorCount++;
×
828
                        continue;
×
829
                case PARSE_SUCCESS:
122✔
830
                        running = false;
122✔
831
                        break;
122✔
832
                default:
×
833
                        errorCount++;
×
834
                        cout << endl;
×
835
                        continue;
×
836
                }
837

838
                vinput_file_meta->push_back(input_file_meta);
122✔
839

840
                ss_time.str("");
244✔
841

842
                if (stnCount > 0 || msrCount > 0) // stations or measurements only
122✔
843
                {                        
844
                        ss_time << "  Done. Loaded ";
120✔
845
                        if (stnCount)
120✔
846
                                ss_time << stnCount << " stations";
61✔
847
                        if (stnCount && msrCount)
120✔
848
                                ss_time << " and ";
8✔
849
                        if (msrCount)
120✔
850
                                ss_time << msrCount << " measurements";
67✔
851
                        ss_time << " in ";
120✔
852
                                
853
                        pt = ptime(gregorian::day_clock::local_day(), elapsed_time);
120✔
854
                        if (elapsed_time < seconds(3))
120✔
855
                        {
856
                                time_facet* facet(new time_facet("%s"));
120✔
857
                                ss_time.imbue(locale(ss_time.getloc(), facet));
120✔
858
                                ss_time << pt << "s";                        
120✔
859
                        }
860
                        else if (elapsed_time < seconds(61))
×
861
                        {                
862
                                time_facet* facet(new time_facet("%S"));
×
863
                                ss_time.imbue(locale(ss_time.getloc(), facet));
×
864
                                ss_time << pt << "s";
×
865
                        }
866
                        else
867
                                ss_time << elapsed_time;
×
868

869
                        string time_message = ss_time.str();
120✔
870
                        while ((pos = time_message.find("0s")) != string::npos)
560✔
871
                                time_message = time_message.substr(0, pos) + "s";
440✔
872

873
                        if ((pos = time_message.find(" 00.")) != string::npos)
120✔
874
                                time_message = time_message.replace(pos, 4, " 0.");
120✔
875
                        if ((pos = time_message.find(" 0.s")) != string::npos)
120✔
876
                                time_message = time_message.replace(pos, 4, " 0s");
26✔
877

878
                        if (!p.g.quiet)
120✔
879
                        {
880
                                if (isatty(fileno(stdout)))
118✔
881
                                        cout << PROGRESS_BACKSPACE_04;
×
882
                                cout << time_message << endl;
118✔
883
                        }
884
                        *imp_file << time_message << endl;
120✔
885

886
                        // Produce a warning if the input file's default reference frame
887
                        // is different to the project reference frame
888
                        string inputFileEpsg;
120✔
889
                        try {
120✔
890
                                inputFileEpsg = datumFromEpsgString<string>(input_file_meta.epsgCode);
120✔
891
                        }
892
                        catch (...) {
×
893
                                inputFileEpsg = epsgCode;
×
894
                        }
×
895

896
                        if (!iequals(epsgCode, input_file_meta.epsgCode))
120✔
897
                        {
898
                                stringstream ssEpsgWarning;
53✔
899
                                
900
                                ssEpsgWarning << "- Warning: Input file reference frame (" << inputFileEpsg <<
53✔
901
                                        ") does not match the " << endl << "  default reference frame.";
53✔
902
                                if (!p.g.quiet)
53✔
903
                                        cout << ssEpsgWarning.str() << endl;
51✔
904
                                *imp_file << ssEpsgWarning.str() << endl;
53✔
905
                        }
53✔
906
                }
120✔
907

908
                // Handle discontinuities for non-sinex files, if and only if a discontinuity file has been loaded.
909
                // NOTE: If a station is marked as a discontinuity site, and that same station is in the renaming
910
                // file, station renaming for that site will not occur.  This is because the site name will be changed
911
                // to <site-name>_yyyymmdd.
912
                // If renaming must still occur, then it might be possible to rename using the first part of the name.
913
                
914

915
                if (stnCount > 0) // stations only
122✔
916
                {
917
                        //vstationsTotal.reserve(vstationsTotal.size() + stnCount);
918
                        // combine stations and station tally
919
                        vstationsTotal->insert(vstationsTotal->end(), vStations->begin(), vStations->end());
61✔
920
                        *parsestnTally += parserDynaML.GetStnTally();
61✔
921
                        vStations->clear();
61✔
922
                }
923
                if (msrCount > 0) // measurements only
122✔
924
                {                
925
                        //vmeasurementsTotal.reserve(vmeasurementsTotal.size() + msrCount);
926
                        // combine measurements
927
                        vmeasurementsTotal->insert(vmeasurementsTotal->end(), vMeasurements->begin(), vMeasurements->end());
67✔
928
                        *parsemsrTally += parserDynaML.GetMsrTally();
67✔
929
                        vMeasurements->clear();
67✔
930
                }
931
        }
122✔
932

933
        if (errorCount == nfiles || (vstationsTotal->empty() && vmeasurementsTotal->empty()))
53✔
934
                return EXIT_FAILURE;
935

936
        running = false;
52✔
937
        return EXIT_SUCCESS;
52✔
938
}
56✔
939

940
int main(int argc, char* argv[])
76✔
941
{
942
        // create banner message
943
        string cmd_line_banner;
76✔
944
        fileproc_help_header(&cmd_line_banner);
76✔
945

946
        project_settings p;
76✔
947

948
        variables_map vm;
76✔
949
        positional_options_description positional_options;
76✔
950

951
        options_description standard_options("+ " + string(ALL_MODULE_STDOPT), PROGRAM_OPTIONS_LINE_LENGTH);
152✔
952
        options_description ref_frame_options("+ " + string(IMPORT_MODULE_FRAME), PROGRAM_OPTIONS_LINE_LENGTH);
152✔
953
        options_description data_screening_options("+ " + string(IMPORT_MODULE_SCREEN), PROGRAM_OPTIONS_LINE_LENGTH);
152✔
954
        options_description gnss_scaling_options("+ " + string(IMPORT_MODULE_GNSS_VAR), PROGRAM_OPTIONS_LINE_LENGTH);
152✔
955
        options_description simulation_options("+ " + string(IMPORT_MODULE_SIMULATE), PROGRAM_OPTIONS_LINE_LENGTH);
152✔
956
        options_description output_options("+ " + string(ALL_MODULE_OUTPUT), PROGRAM_OPTIONS_LINE_LENGTH);
152✔
957
        options_description export_options("+ " + string(ALL_MODULE_EXPORT), PROGRAM_OPTIONS_LINE_LENGTH);
152✔
958
        options_description generic_options("+ " + string(ALL_MODULE_GENERIC), PROGRAM_OPTIONS_LINE_LENGTH);
152✔
959

960
        string cmd_line_usage("+ ");
76✔
961
        cmd_line_usage.append(__BINARY_NAME__).append(" usage:  ").append(__BINARY_NAME__).append(" [options] [files]...");
76✔
962
        options_description allowable_options(cmd_line_usage, PROGRAM_OPTIONS_LINE_LENGTH);
76✔
963

964
        try {
76✔
965
                // Declare a group of options that will be 
966
                // allowed only on command line                
967
                standard_options.add_options()
76✔
968
                        (PROJECT_FILE_P, value<string>(&p.g.project_file),
76✔
969
                                "Project file name. Full path to project file. If none specified, a new file is created using input-folder and network-name.  If a project file exists, the file is used to set all command line options.")
970
                        (NETWORK_NAME_N, value<string>(&p.g.network_name), 
76✔
971
                                "Network name. User defined name for all input and output files. Default is \"network#\", where # is incremented until the first available network is reached.")
972
                        (IMPORT_FILE_F, value< vstring >(&p.i.input_files), 
76✔
973
                                "Station and measurement input file(s). Switch is not required.")
974
                        (IMPORT_GEO_FILE_G, value<string>(&p.i.geo_file),
76✔
975
                                "Import DNA geoid file.")
976
                        (INPUT_FOLDER_I, value<string>(&p.g.input_folder),
76✔
977
                                "Path containing all input files.")
978
                        (OUTPUT_FOLDER_O, value<string>(&p.g.output_folder),                // default is ./,
76✔
979
                                "Path for all output files.")
980
                        (BIN_STN_FILE_S, value<string>(&p.i.bst_file),
76✔
981
                                "Binary station output file name. Overrides network name.")
982
                        (BIN_MSR_FILE_M, value<string>(&p.i.bms_file),
76✔
983
                                "Binary measurement output file name. Overrides network name.")
984
                        ;
985

986
                ref_frame_options.add_options()
76✔
987
                        (REFERENCE_FRAME_R, value<string>(&p.i.reference_frame), 
76✔
988
                        (string("Default reference frame for all stations and measurements, and for preliminary reductions on the ellipsoid when input files do not specify a reference frame. Default is ") +
152✔
989
                                p.i.reference_frame + ".").c_str())
152✔
990
                        (OVERRIDE_INPUT_FRAME,
76✔
991
                                "Override the reference frame specified for each measurement in input files.")
992
                        ;
993

994
                data_screening_options.add_options()
76✔
995
                        (BOUNDING_BOX, value<string>(&p.i.bounding_box),
76✔
996
                                "Import stations and measurements within bounding box. arg is a comma delimited string \"lat1,lon1,lat2,lon2\" (in dd.mmss) defining the upper-left and lower-right limits.")
997
                        (GET_MSRS_TRANSCENDING_BOX,
76✔
998
                                "Include measurements which transcend bounding box, including associated stations.")
999
                        (INCLUDE_STN_ASSOC_MSRS, value<string>(&p.i.stn_associated_msr_include),
76✔
1000
                                "Include stations and all associated measurements. arg is a comma delimited string \"stn 1,stn 2,stn 3,...,stn N\" of the stations to include.")
1001
                        (EXCLUDE_STN_ASSOC_MSRS, value<string>(&p.i.stn_associated_msr_exclude),
76✔
1002
                                "Exclude stations and all associated measurements. arg is a comma delimited string \"stn 1,stn 2,stn 3,...,stn N\" of the stations to exclude.")
1003
                        (SPLIT_CLUSTERS,
76✔
1004
                                "Allow bounding-box or get-stns-and-assoc-msrs to split GNSS point and baseline cluster measurements.")
1005
                        (IMPORT_SEG_BLOCK, value<UINT32>(&p.i.import_block_number),
76✔
1006
                                "Extract stations and measurements from this block.")
1007
                        (IMPORT_CONTIG_NET, value<UINT32>(&p.i.import_network_number),
76✔
1008
                                "Extract stations and measurements from this contiguous network.")
1009
                        (SEG_FILE, value<string>(&p.i.seg_file),
76✔
1010
                                "Network segmentation input file. Filename overrides network name.")
1011
                        (PREFER_X_MSR_AS_G,
76✔
1012
                                "Import single baseline cluster measurements (X) as single baselines (G).")
1013
                        (INCLUDE_MSRS, value<string>(&p.i.include_msrs),
76✔
1014
                                "Import the specified measurement types. arg is a non-delimited string of measurement types (eg \"GXY\").")
1015
                        (EXCLUDE_MSRS, value<string>(&p.i.exclude_msrs),
76✔
1016
                                "Exclude the specified measurement types. arg is a non-delimited string of measurement typs (eg \"IJK\").")
1017
                        (STATION_RENAMING_FILE, value<string>(&p.i.stn_renamingfile),
76✔
1018
                                "Station renaming file")
1019
                        (STATION_DISCONTINUITY_FILE, value<string>(&p.i.stn_discontinuityfile),
76✔
1020
                                "Station discontinuity file.  Applies discontinuity dates to station names in station and measurement files.")
1021
                        (TEST_NEARBY_STNS,
76✔
1022
                                "Search for nearby stations.")
1023
                        (TEST_NEARBY_STN_DIST, value<double>(&p.i.search_stn_radius),
76✔
1024
                                (string("Specify the radius of the circle within which to search for nearby stations.  Default is ")+
152✔
1025
                                StringFromT(STN_SEARCH_RADIUS)+string("m")).c_str())
304✔
1026
                        (TEST_SIMILAR_GNSS_MSRS,
76✔
1027
                                "Search and provide warnings for GNSS baselines (G) and baseline clusters (X) which appear to have been derived from the same source data.")
1028
                        (TEST_SIMILAR_MSRS,
76✔
1029
                                "Search and provide warnings for similar measurements.")
1030
                        (EXCLUDE_INSUFFICIENT_MSRS,
76✔
1031
                                "Exclude measurements which do not sufficiently constrain a station in two dimensions.")
1032
                        (IGNORE_SIMILAR_MSRS,
76✔
1033
                                "Ignore similar measurements.")
1034
                        (REMOVE_IGNORED_MSRS,
76✔
1035
                                "Remove ignored measurements.")
1036
                        (FLAG_UNUSED_STNS,
76✔
1037
                                "Mark unused stations in binary file.  Stations marked will be excluded from any further processing.")
1038
                        (TEST_INTEGRITY,
76✔
1039
                                "Test the integrity of the association lists and binary files.")
1040
                        ;
1041

1042
                gnss_scaling_options.add_options()
76✔
1043
                        (VSCALE, value<double>(&p.i.vscale),
76✔
1044
                                (string("Global variance (v) matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
152✔
1045
                                StringFromT(p.i.vscale)+string(".")).c_str())
304✔
1046
                        (PSCALE, value<double>(&p.i.pscale),
76✔
1047
                                (string("Latitude (p=phi) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
152✔
1048
                                StringFromT(p.i.pscale)+string(".")).c_str())
304✔
1049
                        (LSCALE, value<double>(&p.i.lscale),
76✔
1050
                                (string("Longitude (l=lambda) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
152✔
1051
                                StringFromT(p.i.lscale)+string(".")).c_str())
304✔
1052
                        (HSCALE, value<double>(&p.i.hscale),
76✔
1053
                                (string("Height (h) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
152✔
1054
                                StringFromT(p.i.hscale)+string(".")).c_str())
304✔
1055
                        (SCALAR_FILE, value<string>(&p.i.scalar_file),
76✔
1056
                                "File containing v, p, l and h scalars for GNSS baseline measurements between specific station pairs.  Scalar file values do not apply to GNSS point or baseline clusters.")
1057
                        ;
1058

1059
                output_options.add_options()
76✔
1060
                        (OUTPUT_MSR_TO_STN,
76✔
1061
                                "Output summary of measurements connected to each station.")
1062
                        (OUTPUT_MSR_TO_STN_SORTBY, value<UINT16>(&p.o._sort_msr_to_stn),
76✔
1063
                                string("Sort order for measurement to stations summary.\n  " +
304✔
1064
                                        StringFromT(orig_stn_sort_ui) + ": Original station order (default)\n  " +
304✔
1065
                                        StringFromT(meas_stn_sort_ui) + ": Measurement count").c_str())
76✔
1066
                        ;
1067

1068
                export_options.add_options()
76✔
1069
                        (EXPORT_XML_FILES,
76✔
1070
                                "Export stations and measurements to DynaML (DynAdjust XML) format.")
1071
                        (EXPORT_SINGLE_XML_FILE,
76✔
1072
                                "Create a single DynaML file for stations and measurements.")
1073
                        // Nice, but somewhat redundant functionality that offers no
1074
                        // benefit to the user
1075
                        //(EXPORT_FROM_BINARY,
1076
                        //        "Create DynaML output file using binary files. Default option uses internal memory.")
1077
                        (EXPORT_DNA_FILES,
76✔
1078
                                "Export stations and measurements to DNA STN and MSR format.")
1079
                        (EXPORT_ASL_FILE,
76✔
1080
                                "Export the ASL file as raw text.")
1081
                        (EXPORT_AML_FILE,
76✔
1082
                                "Export the AML file as raw text.")
1083
                        (EXPORT_MAP_FILE,
76✔
1084
                                "Export the MAP file as raw text.")
1085
                        (EXPORT_DISCONT_FILE,
76✔
1086
                                "Export discontinuity information as raw text.")
1087
                        ;
1088

1089
                simulation_options.add_options()
76✔
1090
                        (SIMULATE_MSR_FILE,
76✔
1091
                                "Simulate exact measurements corresponding to the input measurements using the coordinates in the station file. To apply geoid--ellipsoid separations and deflections of the vertical to the simulated measurements, introduce a geoid file using the --geo-file option.")
1092
                        ;
1093

1094
                generic_options.add_options()
76✔
1095
                        (VERBOSE, value<UINT16>(&p.g.verbose),
76✔
1096
                                string("Give detailed information about what ").append(__BINARY_NAME__).append(" is doing.\n  0: No information (default)\n  1: Helpful information\n  2: Extended information\n  3: Debug level information").c_str())
76✔
1097
                        (QUIET,
76✔
1098
                                string("Suppresses all explanation of what ").append(__BINARY_NAME__).append(" is doing unless an error occurs.").c_str())
152✔
1099
                        (VERSION_V, "Display the current program version.")
76✔
1100
                        (HELP_H, "Show this help message.")
76✔
1101
                        (HELP_MODULE, value<string>(),
76✔
1102
                                "Provide help for a specific help category.")
1103
                        ;
1104

1105
                allowable_options.add(standard_options).add(ref_frame_options).add(data_screening_options).add(gnss_scaling_options).add(simulation_options).add(output_options).add(export_options).add(generic_options);
76✔
1106

1107
                // add "positional options" to handle command line tokens which have no option name
1108
                positional_options.add(IMPORT_FILE, -1);
76✔
1109
                
1110
                command_line_parser parser(argc, argv);
76✔
1111
                store(parser.options(allowable_options).positional(positional_options).run(), vm);
76✔
1112
                notify(vm);
75✔
1113
        }
1✔
1114
        catch(const std::exception& e) 
1✔
1115
        {
1116
                cout << "- Error: " << e.what() << endl;
1✔
1117
                cout << cmd_line_banner << allowable_options << endl;
1✔
1118
                return EXIT_FAILURE;
1✔
1119
        }
1✔
1120
        catch (...) 
×
1121
        {
1122
                cout << "+ Exception of unknown type!\n";
×
1123
                return EXIT_FAILURE;
×
1124
        }
×
1125

1126
        if (argc < 2)
75✔
1127
        {
1128
                cout << endl << "- Nothing to do - no options provided. " << endl << endl;  
1✔
1129
                cout << cmd_line_banner << allowable_options << endl;
1✔
1130
                return EXIT_FAILURE;
1131
        }
1132

1133
        if (vm.count(VERSION))
74✔
1134
        {
1135
                cout << cmd_line_banner << endl;
1✔
1136
                return EXIT_SUCCESS;
1137
        }
1138

1139
        if (vm.count(HELP))
73✔
1140
        {
1141
                cout << cmd_line_banner << allowable_options << endl;
1✔
1142
                return EXIT_SUCCESS;
1143
        }
1144

1145
        if (vm.count(HELP_MODULE)) 
72✔
1146
        {
1147
                cout << cmd_line_banner;
9✔
1148
                string original_text = vm[HELP_MODULE].as<string>();
18✔
1149
                string help_text = str_upper<string>(original_text);
9✔
1150
                
1151
                if (str_upper<string, char>(ALL_MODULE_STDOPT).find(help_text) != string::npos) {
18✔
1152
                        cout << standard_options << endl;
1✔
1153
                }
1154
                else if (str_upper<string, char>(IMPORT_MODULE_FRAME).find(help_text) != string::npos) {
16✔
1155
                        cout << ref_frame_options << endl;
1✔
1156
                } 
1157
                else if (str_upper<string, char>(IMPORT_MODULE_SCREEN).find(help_text) != string::npos) {
14✔
1158
                        cout << data_screening_options << endl;
1✔
1159
                } 
1160
                else if (str_upper<string, char>(IMPORT_MODULE_GNSS_VAR).find(help_text) != string::npos) {
12✔
1161
                        cout << gnss_scaling_options << endl;
1✔
1162
                } 
1163
                else if (str_upper<string, char>(IMPORT_MODULE_SIMULATE).find(help_text) != string::npos) {
10✔
1164
                        cout << simulation_options << endl;
1✔
1165
                } 
1166
                else if (str_upper<string, char>(ALL_MODULE_OUTPUT).find(help_text) != string::npos) {
8✔
1167
                        cout << output_options << endl;
1✔
1168
                } 
1169
                else if (str_upper<string, char>(ALL_MODULE_EXPORT).find(help_text) != string::npos) {
6✔
1170
                        cout << export_options << endl;
1✔
1171
                } 
1172
                else if (str_upper<string, char>(ALL_MODULE_GENERIC).find(help_text) != string::npos) {
4✔
1173
                        cout << generic_options << endl;
1✔
1174
                } 
1175
                else {
1176
                        cout << endl << "- Error: Help module '" <<
1✔
1177
                                original_text << "' is not in the list of options." << endl;
9✔
1178
                        return EXIT_FAILURE;
1179
                }
1180

1181
                return EXIT_SUCCESS;
8✔
1182
        }
9✔
1183

1184
        bool userSuppliedSegFile(false);
63✔
1185
        if (!p.i.seg_file.empty())
63✔
1186
                userSuppliedSegFile = true;
1✔
1187
        bool userSuppliedBstFile(false);
63✔
1188
        if (!p.i.bst_file.empty())
63✔
1189
                userSuppliedBstFile = true;
×
1190
        bool userSuppliedBmsFile(false);
63✔
1191
        if (!p.i.bms_file.empty())
63✔
1192
                userSuppliedBmsFile = true;
×
1193

1194
        if (ParseCommandLineOptions(argc, argv, vm, p) != EXIT_SUCCESS)
63✔
1195
                return EXIT_FAILURE;
1196

1197
        UINT32 errorCount(0);
61✔
1198
        bool stn_map_created = false, measurements_mapped = false;
61✔
1199

1200
        string input_file;
61✔
1201
        vstring input_files;
61✔
1202
        string status_msg;
61✔
1203

1204
        std::ofstream imp_file;
61✔
1205
        try {
61✔
1206
                // Create import log file.  Throws runtime_error on failure.
1207
                file_opener(imp_file, p.i.imp_file);
61✔
1208
        }
1209
        catch (const runtime_error& e) {
×
1210
                stringstream ss;
×
1211
                ss << "- Error: Could not open " << p.i.imp_file << ". \n  Check that the file exists and that the file is not already opened." << endl;
×
1212
                cout << ss.str() << e.what() << endl;
×
1213
                return EXIT_FAILURE;
×
1214
        }
×
1215

1216
        vdnaStnPtr vStations, vstationsTotal;
61✔
1217
        vdnaMsrPtr vMeasurements, vmeasurementsTotal;
61✔
1218
        vdnaMsrPtr::iterator _itm;
61✔
1219
        vASLPtr associatedSL;
61✔
1220
        vUINT32 associatedML;
61✔
1221
        v_string_uint32_pair vStnsMap_sortName;        // Station Name Map sorted on name (string)
61✔
1222
        
1223
        vstationsTotal.clear();
61✔
1224
        vmeasurementsTotal.clear();
61✔
1225

1226
        if (vm.count(QUIET))
61✔
1227
                p.g.quiet = 1;
1✔
1228
        
1229
        if (!p.g.quiet)
61✔
1230
        {
1231
                cout << endl << cmd_line_banner;
60✔
1232

1233
                cout << "+ Options:" << endl; 
60✔
1234
                cout << setw(PRINT_VAR_PAD) << left << "  Network name: " <<  p.g.network_name << endl;
60✔
1235
                cout << setw(PRINT_VAR_PAD) << left << "  Input folder: " << p.g.input_folder << endl;
60✔
1236
                cout << setw(PRINT_VAR_PAD) << left << "  Output folder: " << p.g.output_folder << endl;
60✔
1237
                cout << setw(PRINT_VAR_PAD) << left << "  Associated station file: " << p.i.asl_file << endl;
60✔
1238
                cout << setw(PRINT_VAR_PAD) << left << "  Associated measurement file: " << p.i.aml_file << endl;
60✔
1239
                cout << setw(PRINT_VAR_PAD) << left << "  Binary station output file: " << p.i.bst_file << endl;
60✔
1240
                cout << setw(PRINT_VAR_PAD) << left << "  Binary measurement output file: " << p.i.bms_file << endl;
60✔
1241
                
1242
                if (!p.i.reference_frame.empty())
60✔
1243
                        cout << setw(PRINT_VAR_PAD) << left << "  Default reference frame:" << p.i.reference_frame << endl;
60✔
1244
        
1245
                if (p.i.override_input_rfame)
60✔
1246
                        cout << setw(PRINT_VAR_PAD) << left << "  Override input file ref frame:" << yesno_string(p.i.override_input_rfame) << endl;
8✔
1247

1248
                if (p.i.export_dynaml)
60✔
1249
                {
1250
                        if (p.i.export_single_xml_file)
10✔
1251
                                cout << setw(PRINT_VAR_PAD) << left << "  DynaML output file: " << p.i.xml_outfile << endl;
2✔
1252
                        else
1253
                        {
1254
                                cout << setw(PRINT_VAR_PAD) << left << "  DynaML station file: " << p.i.xml_stnfile << endl;
8✔
1255
                                cout << setw(PRINT_VAR_PAD) << left << "  DynaML measurement file: " << p.i.xml_msrfile << endl;
8✔
1256
                        }                                
1257
                }
1258
                if (p.i.export_dna_files)
60✔
1259
                {
1260
                        cout << setw(PRINT_VAR_PAD) << left << "  DNA station file: " << p.i.dna_stnfile << endl;
8✔
1261
                        cout << setw(PRINT_VAR_PAD) << left << "  DNA measurement file: " << p.i.dna_msrfile << endl;
8✔
1262
                }
1263

1264
                if (p.i.simulate_measurements)
60✔
1265
                {
1266
                        cout << setw(PRINT_VAR_PAD) << left << "  DNA simulated msr file: " << p.i.simulate_msrfile << endl;
1✔
1267
                }
1268
                
1269
                if (!p.i.bounding_box.empty())
60✔
1270
                {
1271
                        cout << setw(PRINT_VAR_PAD) << left << "  Bounding box: " << p.i.bounding_box << endl;
1✔
1272
                        if (p.i.split_clusters)
1✔
1273
                                cout << setw(PRINT_VAR_PAD) << left << "  Split GNSS clusters: " << (p.i.split_clusters ? "Yes" : "No") << endl;
1✔
1274
                }
1275
                else
1276
                {
1277
                        if (!p.i.stn_associated_msr_include.empty())
59✔
1278
                                cout << setw(PRINT_VAR_PAD) << left << "  Stations to include: " << p.i.stn_associated_msr_include << endl;
5✔
1279
                        if (!p.i.stn_associated_msr_exclude.empty())
59✔
1280
                                cout << setw(PRINT_VAR_PAD) << left << "  Stations to exclude: " << p.i.stn_associated_msr_exclude << endl;
1✔
1281
                        
1282
                        if (p.i.split_clusters)
59✔
1283
                                cout << setw(PRINT_VAR_PAD) << left << "  Split GNSS clusters: " << (p.i.split_clusters ? "Yes" : "No") << endl;
4✔
1284
                }
1285
                
1286
                if (p.i.import_block)
60✔
1287
                {
1288
                        if (!p.i.seg_file.empty())
4✔
1289
                                cout << setw(PRINT_VAR_PAD) << left << "  Segmentation file: " << p.i.seg_file << endl;
1✔
1290
                        cout << setw(PRINT_VAR_PAD) << left << "  Import stns & msrs from block: " << p.i.import_block_number << endl;
4✔
1291
                }
1292
                else if (p.i.import_network)
56✔
1293
                {
1294
                        if (!p.i.seg_file.empty())
×
1295
                                cout << setw(PRINT_VAR_PAD) << left << "  Segmentation file: " << p.i.seg_file << endl;
×
1296
                        cout << setw(PRINT_VAR_PAD) << left << "  Import stns & msrs from network: " << p.i.import_network_number << endl;
×
1297
                }
1298

1299
                if (!p.i.scalar_file.empty())
60✔
1300
                        cout << setw(PRINT_VAR_PAD) << left << "  GNSS baseline scalar file: " << p.i.scalar_file << endl;
1✔
1301
                
1302
                cout << endl;
60✔
1303
        }
1304

1305
        PrintOutputFileHeaderInfo(&imp_file, p.i.imp_file, &p, "DYNADJUST IMPORT LOG FILE");
61✔
1306

1307
        dna_import parserDynaML;
61✔
1308
        MsrTally parsemsrTally;
61✔
1309
        StnTally parsestnTally;
61✔
1310

1311
        CDnaProjection projection(UTM);
61✔
1312

1313
        vifm_t vinput_file_meta;
61✔
1314

1315
        // First things first!
1316
        // Set the 'default' reference frame for the binary station and measurement files
1317
        try {
61✔
1318
                // Initialise the 'default' datum for the project.
1319
                parserDynaML.InitialiseDatum(p.i.reference_frame);
61✔
1320
        }
1321
        catch (const XMLInteropException& e) {
1✔
1322
                stringstream ss;
1✔
1323
                ss << "- Error: ";
1✔
1324
                cout << ss.str() << e.what() << endl;
1✔
1325
                return EXIT_FAILURE;
1✔
1326
        }
1✔
1327

1328
        // obtain the project reference frame
1329
        UINT32 epsgCode(epsgCodeFromName<UINT32>(p.i.reference_frame));
60✔
1330

1331
        // set the default output reference frame and epoch, so that
1332
        // if adjust is called without reftran, it reflects the datum 
1333
        // supplied on import
1334
        p.r.reference_frame = p.i.reference_frame;
60✔
1335
        p.r.epoch = referenceepochFromEpsgCode<UINT32>(epsgCode);
60✔
1336

1337
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////
1338
        // start "total" time
1339
        cpu_timer time;
60✔
1340
        
1341
        
1342
        // Import discontinuity file and apply discontinuities
1343
        // Due to the structure and format of SINEX files, it is essential that
1344
        // discontinuities be parsed prior to reading any SINEX files.
1345
        if (vm.count(STATION_DISCONTINUITY_FILE))
60✔
1346
        {
1347
                p.i.apply_discontinuities = true;
4✔
1348
                
1349
                // Does it exist?
1350
                if (!exists(p.i.stn_discontinuityfile))
4✔
1351
                {
1352
                        path discontPath(p.i.stn_discontinuityfile);
×
1353
                        stringstream ss;
×
1354
                        ss << "- Warning: The station discontinuity file " << discontPath.filename().string() << " does not exist... ignoring discontinuity input." << endl;
×
1355
                        imp_file << endl << ss.str();
×
1356
                }
×
1357
                else
1358
                {
1359
                        if (!p.g.quiet)
4✔
1360
                        {
1361
                                cout << "+ Importing station discontinuities from " << p.i.stn_discontinuityfile << "... ";
4✔
1362
                                cout.flush();
4✔
1363
                        }
1364
                        imp_file << "+ Importing station discontinuities from " << p.i.stn_discontinuityfile << "... ";
4✔
1365

1366
                        parserDynaML.ParseDiscontinuities(p.i.stn_discontinuityfile);
4✔
1367

1368
                        if (!p.g.quiet)
4✔
1369
                                cout << "Done." << endl;
4✔
1370
                        imp_file << "Done." << endl;
4✔
1371
                }
1372

1373
                if (p.i.export_discont_file)
4✔
1374
                {
1375
                        if (!p.g.quiet)
1✔
1376
                        {
1377
                                cout << "+ Exporting discontinuity information to text file... ";
1✔
1378
                                cout.flush();
1✔
1379
                        }
1380
                        imp_file << "+ Exporting discontinuity information to text file... ";
1✔
1381
                        parserDynaML.SerialiseDiscontTextFile(p.i.stn_discontinuityfile);
1✔
1382
                        if (!p.g.quiet)
1✔
1383
                        {
1384
                                cout << "Done." << endl;
1✔
1385
                                cout.flush();
1✔
1386
                        }
1387
                        imp_file << "Done." << endl;
1✔
1388
                }
1389
        }
1390

1391
        // Import network information based on a segmentation block?
1392
        if (p.i.import_block)
60✔
1393
        {
1394
                imp_file << "+ Extracting stations and measurements from segmented block " << 
4✔
1395
                        p.i.import_block_number << "... ";
4✔
1396
                
1397
                if (ImportSegmentedBlock(parserDynaML, &vstationsTotal, &vmeasurementsTotal, 
4✔
1398
                        &parsestnTally, &parsemsrTally, p) != EXIT_SUCCESS)
1399
                        return EXIT_FAILURE;
1400

1401
                imp_file << "Done." << endl;
4✔
1402
        }
1403
        // Import network information based on a contiguous network?
1404
        else if (p.i.import_network)
56✔
1405
        {
1406
                imp_file << "+ Extracting stations and measurements from contiguous network " <<
×
1407
                        p.i.import_network_number << "... ";
×
1408
                
1409
                if (ImportContiguousNetwork(parserDynaML, &vstationsTotal, &vmeasurementsTotal,
×
1410
                        &parsestnTally, &parsemsrTally, p) != EXIT_SUCCESS)
1411
                        return EXIT_FAILURE;
1412

1413
                imp_file << "Done." << endl;
×
1414
        }
1415
        // Import data as normal
1416
        else
1417
        {
1418
                // Import all data as-is.
1419
                // All filtering is performed later below
1420
                if (ImportDataFiles(parserDynaML, &vStations, &vMeasurements, &vstationsTotal, &vmeasurementsTotal,
56✔
1421
                        &imp_file, &vinput_file_meta, &parsestnTally, &parsemsrTally, errorCount, p) != EXIT_SUCCESS)
1422
                        return EXIT_FAILURE;
1423
        }        
1424

1425
        if (!p.g.quiet)
56✔
1426
                cout << endl;
55✔
1427

1428
        // Now, set the 'default' epoch in the binary station and measurement files
1429
        try {
56✔
1430
                // Initialise the 'default' datum for the project.
1431
                parserDynaML.UpdateEpoch(&vinput_file_meta);
56✔
1432
        }
1433
        catch (const XMLInteropException& e) {
×
1434
                stringstream ss;
×
1435
                ss << "- Error: ";
×
1436
                cout << ss.str() << e.what() << endl;
×
1437
                return EXIT_FAILURE;
×
1438
        }
×
1439

1440
        vstring vPoorlyConstrainedStns;
56✔
1441

1442
        // Exclude measurements that do not sufficiently (in themselves) allow for a station to be estimated
1443
        if (p.i.exclude_insufficient_msrs == 1)
56✔
1444
        {
1445
                size_t msrCount = vmeasurementsTotal.size();
×
1446
                if (!p.g.quiet)
×
1447
                {
1448
                        cout << "+ Identifying stations with insufficient measurements";
×
1449
                        cout.flush();
×
1450
                }
1451
                imp_file << "+ Identifying stations with insufficient measurements...";
×
1452
                parserDynaML.IgnoreInsufficientMeasurements(&vstationsTotal, &vmeasurementsTotal, &vPoorlyConstrainedStns);
×
1453
                if (!p.g.quiet)
×
1454
                {
1455
                        cout << " Done. " << endl;
×
1456
                        if (msrCount > vmeasurementsTotal.size())
×
1457
                                cout << "+ Removed " << (msrCount - vmeasurementsTotal.size()) << " measurements which alone do not sufficiently allow for" << endl <<
×
1458
                                        "  the estimation of 2D coordinates." << endl;
×
1459

1460
                }
1461
                imp_file << " Done. " << endl;
×
1462
                if (msrCount > vmeasurementsTotal.size())
×
1463
                        imp_file << "+ Removed " << (msrCount - vmeasurementsTotal.size()) << " measurements which alone do not sufficiently allow for" << endl <<
×
1464
                                "  the estimation of 2D coordinates." << endl;
×
1465

1466
                if (!vPoorlyConstrainedStns.empty())
×
1467
                {
1468
                        if (vPoorlyConstrainedStns.size() == 1)
×
1469
                        {
1470
                                if (p.g.verbose > 2)
×
1471
                                {
1472
                                        if (!p.g.quiet)
×
1473
                                                cout << "- Warning: station " << vPoorlyConstrainedStns.at(0) << " is not associated with sufficient measurements." << endl;
×
1474
                                        imp_file << "- Warning: station " << vPoorlyConstrainedStns.at(0) << " is not associated with sufficient measurements." << endl;
×
1475
                                }
1476
                                else
1477
                                {
1478
                                        if (!p.g.quiet)
×
1479
                                                cout << "- Warning: 1 station is not associated with sufficient measurements." << endl;
×
1480
                                        imp_file << "- Warning: 1 station is not associated with sufficient measurements." << endl;
×
1481
                                }
1482
                        }
1483
                        else
1484
                        {
1485
                                if (p.g.verbose > 2)
×
1486
                                {
1487
                                        if (!p.g.quiet)
×
1488
                                                cout << "- Warning: The following " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << endl;
×
1489
                                        imp_file << "- Warning: The following " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << endl;
×
1490
                                        _it_vstr poorly;
×
1491
                                        for (poorly = vPoorlyConstrainedStns.begin(); poorly != vPoorlyConstrainedStns.end(); poorly++)
×
1492
                                        {
1493
                                                if (!p.g.quiet)
×
1494
                                                        outputObject(string("  - " + *poorly + "\n"), cout);
×
1495
                                                outputObject(string("  - " + *poorly + "\n"), imp_file);
×
1496
                                        }
1497
                                }
1498
                                else
1499
                                {
1500
                                        if (!p.g.quiet)
×
1501
                                                cout << "- Warning: " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << endl;
×
1502
                                        imp_file << "- Warning: " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << endl;
×
1503
                                }
1504
                        }
1505
                }
1506
        }
1507

1508
        // Remove ignored measurements (if supplied)
1509
        if (p.i.remove_ignored_msr)
56✔
1510
        {
1511
                if (!p.g.quiet)
1✔
1512
                {
1513
                        cout << "+ Removing ignored measurements... ";
1✔
1514
                        cout.flush();
1✔
1515
                }
1516
                imp_file << "+ Removing ignored measurements... ";
1✔
1517
                parserDynaML.RemoveIgnoredMeasurements(&vmeasurementsTotal, &parsemsrTally);
1✔
1518
                if (!p.g.quiet)
1✔
1519
                        cout << "Done. " << endl;
1✔
1520
                imp_file << "Done. " << endl;
1✔
1521
        }
1522

1523
        // Strip all measurements except required measurements (if supplied)
1524
        if (!p.i.include_msrs.empty())
56✔
1525
        {
1526
                if (!p.g.quiet)
2✔
1527
                {
1528
                        cout << "+ Stripping all measurements except types " << p.i.include_msrs << "... ";
2✔
1529
                        cout.flush();
2✔
1530
                }
1531
                imp_file << "+ Stripping all measurements except types " << p.i.include_msrs << "... ";
2✔
1532
                parserDynaML.IncludeMeasurementTypes(p.i.include_msrs, &vmeasurementsTotal, &parsemsrTally);
2✔
1533
                if (!p.g.quiet)
2✔
1534
                        cout << "Done. " << endl;
2✔
1535
                imp_file << "Done. " << endl;
2✔
1536
        }
1537
        
1538
        // Strip all unwanted measurements (if supplied)
1539
        if (!p.i.exclude_msrs.empty())
56✔
1540
        {
1541
                if (!p.g.quiet)
2✔
1542
                {
1543
                        cout << "+ Stripping measurement types " << p.i.exclude_msrs << "... ";
2✔
1544
                        cout.flush();
2✔
1545
                }
1546
                imp_file << "+ Stripping measurement types " << p.i.exclude_msrs << "... ";
2✔
1547
                parserDynaML.ExcludeMeasurementTypes(p.i.exclude_msrs, &vmeasurementsTotal, &parsemsrTally);
2✔
1548
                if (!p.g.quiet)
2✔
1549
                        cout << "Done. " << endl;
2✔
1550
                imp_file << "Done. " << endl;
2✔
1551
        }
1552

1553
        // Reduce stations.
1554
        // But, only reduce stations if not importing for a segmentation block or network
1555
        // The reason stations are not reduced if IMPORT_SEG_BLOCK or IMPORT_CONTIG_NET has been set is
1556
        // because stations in the binary file will have already been reduced
1557
        // on last import!
1558
        if (p.i.import_block == 0 && p.i.import_network == 0 && vstationsTotal.size())
56✔
1559
        {
1560
                // reduce stations (e.g. convert from UTM to LLH)
1561
                try {
52✔
1562
                        if (!p.g.quiet)
52✔
1563
                        {
1564
                                cout << "+ Reducing stations... ";
51✔
1565
                                cout.flush();
51✔
1566
                        }
1567
                        imp_file << "+ Reducing stations... ";
52✔
1568
                        parserDynaML.ReduceStations(&vstationsTotal, projection);
52✔
1569
                        if (!p.g.quiet)
52✔
1570
                                cout << "Done." << endl;
51✔
1571
                        imp_file << "Done." << endl;
52✔
1572
                } 
1573
                catch (const XMLInteropException& e) {
×
1574
                        cout << endl << "- Error: " << e.what() << endl;
×
1575
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1576
                        imp_file.close();
×
1577
                        return EXIT_FAILURE;
×
1578
                }
×
1579
        }
1580

1581
        /////////////////////////////////////////////////////////////////////////
1582
        // Add discontinuity sites to vStations
1583
        //
1584
        // WARNING: If discontinuity sites are present in the renaming file, and
1585
        // the renaming file changes the name from the four-character id in the 
1586
        // discontinuity file to another name, this function call will not work
1587
        // properly. Hence, sites in the discontinuity file must be consistently
1588
        // named in the station and measurement files and not renamed to another
1589
        // name.
1590
        if (p.i.apply_discontinuities && !vstationsTotal.empty())
56✔
1591
                parserDynaML.AddDiscontinuityStations(&vstationsTotal);
4✔
1592

1593
        UINT32 stn;
56✔
1594

1595
        // Extract user-defined stations and all connected measurements
1596
        if (vstationsTotal.size() &&        // cannot be empty
56✔
1597
                (!p.i.stn_associated_msr_include.empty() || !p.i.stn_associated_msr_exclude.empty()))
56✔
1598
        {
1599
                vstring vUnusedStns;
6✔
1600
                bool splitXmsrs(false), splitYmsrs(false);
6✔
1601

1602
                try {
6✔
1603
                        if (!p.g.quiet)
6✔
1604
                        {
1605
                                cout << "+ Extracting stations and associated measurements... ";
6✔
1606
                                cout.flush();
6✔
1607
                        }
1608
                        imp_file << "+ Extracting stations and associated measurements... ";
6✔
1609

1610
                        // this method reforms asl and aml
1611
                        parserDynaML.ExtractStnsAndAssociatedMsrs(p.i.stn_associated_msr_include, p.i.stn_associated_msr_exclude, &vstationsTotal, &vmeasurementsTotal, 
6✔
1612
                                &parsestnTally, &parsemsrTally, &vUnusedStns, p, splitXmsrs, splitYmsrs);
1613
                } 
1614
                catch (const XMLInteropException& e) {
×
1615
                        cout << "- Error: " << e.what() << endl;
×
1616
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1617
                        imp_file.close();
×
1618
                        return EXIT_FAILURE;
×
1619
                }
×
1620

1621
                if (!p.g.quiet)
6✔
1622
                        cout << "Done. " << endl;
6✔
1623
                imp_file << "Done." << endl;
6✔
1624

1625
                //msrCount = vmeasurementsTotal.size();
1626
        }        
6✔
1627

1628
        // Now strip all stations outside the bounding box (if supplied)
1629
        if (vstationsTotal.size() &&        // cannot be empty
56✔
1630
                !p.i.bounding_box.empty())
55✔
1631
        {
1632
                vstring vUnusedStns;
1✔
1633
                bool splitXmsrs(false), splitYmsrs(false);
1✔
1634

1635
                try {
1✔
1636
                        if (!p.g.quiet)
1✔
1637
                        {
1638
                                cout << "+ Stripping stations and measurements outside the bounding box... ";
1✔
1639
                                cout.flush();
1✔
1640
                        }
1641
                        imp_file << "+ Stripping stations and measurements outside the bounding box... ";
1✔
1642
                        parserDynaML.ExcludeAllOutsideBoundingBox(&vstationsTotal, &vmeasurementsTotal, 
1✔
1643
                                &parsestnTally, &parsemsrTally, &vUnusedStns, p, splitXmsrs, splitYmsrs);
1644
                } 
1645
                catch (const XMLInteropException& e) {
×
1646
                        cout << "- Error: " << e.what() << endl;
×
1647
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1648
                        imp_file.close();
×
1649
                        return EXIT_FAILURE;
×
1650
                }
×
1651

1652
                if (!p.g.quiet)
1✔
1653
                        cout << "Done. " << endl;
1✔
1654
                imp_file << "Done." << endl;
1✔
1655

1656
                if (!vUnusedStns.empty())
1✔
1657
                {
1658
                        ostringstream ss_msg;
1✔
1659
                        ss_msg << "  - " << vstationsTotal.size() << (vstationsTotal.size() == 1 ? " station is" : " stations are") << 
1✔
1660
                                " within the bounding box." << endl;
2✔
1661
                        imp_file << ss_msg.str();
1✔
1662
                        if (!p.g.quiet)
1✔
1663
                                cout << ss_msg.str();
1✔
1664
                        ss_msg.str("");
2✔
1665
                        ss_msg << "  - ";
1✔
1666
                        if (vUnusedStns.size() > 1)
1✔
1667
                        {
1668
                                ss_msg << vUnusedStns.size() << " stations were";
1✔
1669
                        }
1670
                        else
1671
                                ss_msg << "Station " << vUnusedStns.at(0) << " was";
×
1672

1673
                        ss_msg << " found outside the bounding box and " << (vUnusedStns.size() > 1 ? "have been" : "has been") << endl <<
1✔
1674
                                "    removed together with the corresponding measurements." << endl;
1✔
1675
                        if (p.i.split_clusters && (splitXmsrs || splitYmsrs))
1✔
1676
                        {
1677
                                ss_msg << "  - Note: GPS ";
1✔
1678
                                if (splitXmsrs && splitYmsrs)
1✔
1679
                                        ss_msg << "point and baseline";
×
1680
                                else if (splitXmsrs)
1✔
1681
                                        ss_msg << "baseline";
×
1682
                                else //if (splitYmsrs)
1683
                                        ss_msg << "point";
1✔
1684
                                ss_msg << " cluster measurements straddling the limits of" << endl << 
1✔
1685
                                "    the bounding box have been split." << endl;
1✔
1686
                        }
1687
                        imp_file << ss_msg.str() << "  - Excluded stations:" << endl;
1✔
1688
                        if (!p.g.quiet)
1✔
1689
                                cout << ss_msg.str() << endl;
1✔
1690
                        
1691
                        for (stn=0; stn<vUnusedStns.size(); ++stn)
13✔
1692
                                imp_file << "     " << vUnusedStns.at(stn) << endl;
12✔
1693
                        imp_file << endl;
1✔
1694
                }
1✔
1695
                else
1696
                {
1697
                        imp_file << "  - No stations were found outside the bounding box." << endl;
×
1698
                        if (!p.g.quiet)
×
1699
                                cout << "  - No stations were found outside the bounding box." << endl;
×
1700
                }
1701
        }
1✔
1702

1703
        UINT32 msrRead(parsemsrTally.TotalCount());
56✔
1704
        UINT32 stnCount(static_cast<UINT32>(vstationsTotal.size()));
56✔
1705
        UINT32 msrCount(static_cast<UINT32>(vmeasurementsTotal.size()));
56✔
1706

1707
        if (!p.g.quiet)
56✔
1708
                cout << endl;
55✔
1709
        imp_file << endl;
56✔
1710

1711
        ///////////////////////////////////////////////////////////////////////
1712
        // Ok, now that unwanted stations and measurements have been stripped,
1713
        // provide station and measurement Summary
1714
        //
1715
        if ((stnCount + msrCount) > 0)
56✔
1716
        {
1717
                if (p.i.import_block || p.i.import_network)
55✔
1718
                {
1719
                        if (!p.g.quiet)
4✔
1720
                                cout << "+ Binary file ";
4✔
1721
                        imp_file << "+ Binary file ";
4✔
1722
                }
1723
                else
1724
                {
1725
                        if (!p.g.quiet)
51✔
1726
                                cout << "+ File ";
50✔
1727
                        imp_file << "+ File ";
51✔
1728
                }
1729
                
1730
                if (!p.g.quiet)
55✔
1731
                        cout << "parsing summary:" << endl << endl;
54✔
1732
                imp_file << "parsing summary:" << endl << endl;
55✔
1733
        }
1734
        
1735
        //
1736
        // Station summary
1737
        if (stnCount)
56✔
1738
        {
1739
                if (!p.g.quiet)
55✔
1740
                {
1741
                        parsestnTally.coutSummary(cout, string("  Read"));
54✔
1742
                        cout << endl;
54✔
1743
                }
1744
                parsestnTally.coutSummary(imp_file, string("  Read"));
55✔
1745
                imp_file << endl;
55✔
1746
        }
1747
        
1748
        //
1749
        // Measurement summary
1750
        if (msrCount)
56✔
1751
        {
1752
                if (!p.g.quiet)
53✔
1753
                {
1754
                        parsemsrTally.coutSummary(cout, string("  Read"));
52✔
1755
                        cout << endl;
52✔
1756
                }
1757
                parsemsrTally.coutSummary(imp_file, string("  Read"));
53✔
1758
                imp_file << endl;
53✔
1759
        }
1760

1761
        ////////////////////////////////////////////////////////////////////////
1762
        // Can we proceed?
1763
        if (stnCount < 1)
56✔
1764
        {
1765
                imp_file << "- No further processing can be done as no stations were loaded." << endl;
1✔
1766
                if (!p.g.quiet)
1✔
1767
                        cout << "- No further processing can be done as no stations were loaded." << endl;
1✔
1768
                imp_file.close();
1✔
1769
                return PARSE_SUCCESS;
1770
        }
1771

1772
        /////////////////////////////////////////////////////////////////////////
1773
        // Rename stations
1774
        if (p.i.rename_stations && (stnCount > 0 || msrCount > 0))
55✔
1775
        {
1776
                // Does it exist?
1777
                if (!exists(p.i.stn_renamingfile))
1✔
1778
                        // Look for it in the input folder
1779
                        p.i.stn_renamingfile = formPath<string>(p.g.input_folder, leafStr<string>(p.i.stn_renamingfile));
×
1780

1781
                // Apply renaming
1782
                try {
1✔
1783
                        if (!p.g.quiet)
1✔
1784
                        {
1785
                                cout << "+ Renaming stations... ";
1✔
1786
                                cout.flush();
1✔
1787
                        }
1788
                        imp_file << "+ Renaming stations... ";
1✔
1789
                        parserDynaML.RenameStations(&vstationsTotal, &vmeasurementsTotal, &p);
1✔
1790
                        if (!p.g.quiet)
1✔
1791
                                cout << "Done." << endl;
1✔
1792
                        imp_file << "Done." << endl;
1✔
1793
                } 
1794
                catch (const XMLInteropException& e) {
×
1795
                        cout << endl << "- Error: " << e.what() << endl;
×
1796
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1797
                        imp_file.close();
×
1798
                        return EXIT_FAILURE;
×
1799
                }
×
1800
        }
1801

1802
        // Apply GNSS scaling (if required)
1803
        if (p.i.import_block == 0 && p.i.import_network == 0 && p.i.apply_scaling)
55✔
1804
        {
1805
                // Apply scaling
1806
                try {
2✔
1807
                        if (!p.g.quiet)
2✔
1808
                        {
1809
                                cout << "+ Applying scalars to GNSS measurements... ";
2✔
1810
                                cout.flush();
2✔
1811
                        }
1812
                        imp_file << "+ Applying scalars to GNSS measurements... ";
2✔
1813
                        parserDynaML.EditGNSSMsrScalars(&vmeasurementsTotal, &p);
2✔
1814
                        if (!p.g.quiet)
2✔
1815
                                cout << "Done." << endl;
2✔
1816
                        imp_file << "Done." << endl;
2✔
1817
                } 
1818
                catch (const XMLInteropException& e) {
×
1819
                        cout << endl << "- Error: " << e.what() << endl;
×
1820
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1821
                        imp_file.close();
×
1822
                        return EXIT_FAILURE;
×
1823
                }
×
1824
        }
1825

1826
        std::ofstream dst_file;
55✔
1827

1828
        // flush duplicate stations/measurements files
1829
        try {
55✔
1830
                if (exists(p.i.dst_file))
55✔
1831
                        remove(p.i.dst_file);
1✔
1832
                if (exists(p.i.dms_file))
55✔
1833
                        remove(p.i.dms_file);
3✔
1834
        }
1835
        catch (const ios_base::failure& f) { 
×
1836
                // do nothing on failure.
1837
                imp_file << endl << "- Warning: " << f.what() << endl;
×
1838
        }
×
1839

1840
        // Prepare file names if importing from a segmentation block or contiguous network
1841
        if (p.i.import_block == 1 || p.i.import_network == 1)
55✔
1842
        {
1843
                stringstream modifier("");
4✔
1844
                if (p.i.import_block == 1)
4✔
1845
                        modifier << ".block-" << p.i.import_block_number;
4✔
1846
                else if (p.i.import_network == 1)
×
1847
                        modifier << ".network-" << p.i.import_network_number;
×
1848

1849
                // create new output file names based on block number
1850
                // reform file name for each so as to preserve full path for each file
1851
                stringstream ss("");
4✔
1852
                ss << formPath<string>(path(p.i.bst_file).parent_path().generic_string(), path(p.i.bst_file).stem().generic_string());
12✔
1853
                ss << modifier.str() << ".bst";
4✔
1854
                p.i.bst_file = ss.str();
4✔
1855

1856
                ss.str("");
8✔
1857
                ss << formPath<string>(path(p.i.bms_file).parent_path().generic_string(), path(p.i.bms_file).stem().generic_string());
12✔
1858
                ss << modifier.str() << ".bms";
4✔
1859
                p.i.bms_file = ss.str();
4✔
1860

1861
                ss.str("");
8✔
1862
                ss << formPath<string>(path(p.i.asl_file).parent_path().generic_string(), path(p.i.asl_file).stem().generic_string());
12✔
1863
                ss << modifier.str() << ".asl";
4✔
1864
                p.i.asl_file = ss.str();
4✔
1865

1866
                ss.str("");
8✔
1867
                ss << formPath<string>(path(p.i.aml_file).parent_path().generic_string(), path(p.i.aml_file).stem().generic_string());
12✔
1868
                ss << modifier.str() << ".aml";
4✔
1869
                p.i.aml_file = ss.str();
4✔
1870

1871
                ss.str("");
8✔
1872
                ss << formPath<string>(path(p.i.map_file).parent_path().generic_string(), path(p.i.map_file).stem().generic_string());
12✔
1873
                ss << modifier.str() << ".map";
4✔
1874
                p.i.map_file = ss.str();
4✔
1875

1876
                ss.str("");
8✔
1877
                ss << formPath<string>(path(p.i.map_file).parent_path().generic_string(), path(p.i.map_file).stem().generic_string());
12✔
1878
                ss << ".dbid";
4✔
1879
                p.i.dbid_file = ss.str();
4✔
1880
        }
4✔
1881

1882
        // Remove duplicate stations. If required, test nearby stations
1883
        if (stnCount > 0) {
55✔
1884
                
1885
                vstring vduplicateStns;
55✔
1886
                v_stringstring_doubledouble_pair vnearbyStns;
55✔
1887

1888
                // Remove duplicates and, if required, identify station pairs 
1889
                // separated by distances less than search_stn_radius
1890
                try {
55✔
1891
                        ostringstream ss_msg;
55✔
1892
                        if (p.i.search_nearby_stn)
55✔
1893
                                ss_msg << "+ Testing for duplicate and nearby stations... ";
2✔
1894
                        else
1895
                                ss_msg << "+ Testing for duplicate stations... ";
53✔
1896
                        
1897
                        if (!p.g.quiet)
55✔
1898
                        {
1899
                                cout << ss_msg.str();
54✔
1900
                                cout.flush();
54✔
1901
                        }
1902

1903
                        imp_file << ss_msg.str();                        
55✔
1904
                        
1905
                        stn = parserDynaML.RemoveDuplicateStations(&vstationsTotal, &vduplicateStns, &vnearbyStns);
55✔
1906
                        
1907
                        if (!p.g.quiet)
55✔
1908
                                cout << "Done. ";
54✔
1909
                        imp_file << "Done. ";
55✔
1910

1911
                        if (stn > 0)
55✔
1912
                        {
1913
                                try {
3✔
1914
                                        // Create duplicate station file
1915
                                        file_opener(dst_file, p.i.dst_file);
3✔
1916
                                }
1917
                                catch (const runtime_error& e) {
×
1918
                                        ss_msg << "- Error: Could not open " << p.i.dst_file << ". \n  Check that the file exists and that the file is not already opened." << 
×
1919
                                                endl << e.what() << endl;
×
1920
                                        if (!p.g.quiet)
×
1921
                                                cout << ss_msg.str();
×
1922
                                        imp_file << ss_msg.str();
×
1923
                                        imp_file.close();
×
1924
                                        return EXIT_FAILURE;
×
1925
                                }
×
1926
                                                
1927
                                PrintOutputFileHeaderInfo(&dst_file, p.i.dst_file, &p, "DUPLICATE STATION FILE");
3✔
1928

1929
                                if (!vduplicateStns.empty())
3✔
1930
                                {
1931
                                        ss_msg.str("");
4✔
1932
                                        ss_msg << "Removed " << vduplicateStns.size() << " duplicate station" << (vduplicateStns.size() > 1 ? "s" : "");
3✔
1933
                                        
1934
                                        // print message to .dst file
1935
                                        dst_file << ss_msg.str() << ":" << endl;
2✔
1936
                                        for (stn=0; stn<vduplicateStns.size(); ++stn)
6✔
1937
                                                dst_file << "  - " << vduplicateStns.at(stn) << endl;
4✔
1938
                                        dst_file << endl;
2✔
1939

1940
                                        ss_msg << "." << endl << "  See " << p.i.dst_file << " for details." << endl;
2✔
1941

1942
                                        imp_file << ss_msg.str();
2✔
1943
                                        if (!p.g.quiet)
2✔
1944
                                                cout << endl << "- Warning: " << ss_msg.str();                                        
2✔
1945
                                }                                
1946

1947
                                if (!vnearbyStns.empty())
3✔
1948
                                {
1949
                                        ss_msg.str("");
2✔
1950
                                        ss_msg << vnearbyStns.size() << (vnearbyStns.size() > 1 ? " pairs of stations were" : " pair of station was") << 
1✔
1951
                                                " found to be separated by less than " << setprecision(3) << p.i.search_stn_radius << "m.";
1✔
1952

1953
                                        imp_file << endl << "- Warning: " << ss_msg.str() << endl << 
1✔
1954
                                                "  See " << p.i.dst_file << " for details." << endl << endl;
1✔
1955
                                        
1956
                                        if (!p.g.quiet)
1✔
1957
                                                cout << endl << "- Warning: " << ss_msg.str() << endl << 
2✔
1958
                                                "  See " << p.i.dst_file << " for details." << endl << endl;
1✔
1959
                                        ss_msg.str("");
2✔
1960

1961
                                        // output message
1962
                                        dst_file << "Nearby station search results:" << endl << ss_msg.str() << endl << endl;
1✔
1963

1964
                                        dst_file <<  
1✔
1965
                                                setw(HEADER_20) << left << "First station" << 
1✔
1966
                                                setw(HEADER_20) << "Nearby station" << 
1967
                                                setw(HEADER_20) << right << "Separation (m)" << 
1✔
1968
                                                setw(HEADER_20) << "Diff height (m)" << 
1✔
1969
                                                endl;
81✔
1970

1971
                                        for (UINT32 i(0); i<(HEADER_20*4); ++i)
81✔
1972
                                                dst_file << "-";
80✔
1973
                                        dst_file << endl;
1✔
1974

1975
                                        // dump nearby stations to dst file
1976
                                        for (stn=0; stn<vnearbyStns.size(); ++stn)
50✔
1977
                                        {
1978
                                                dst_file <<
49✔
1979
                                                        setw(HEADER_20) << left << vnearbyStns.at(stn).first.first <<                                                                         // First
49✔
1980
                                                        setw(HEADER_20) << vnearbyStns.at(stn).first.second <<                                                                        // Nearby
49✔
1981
                                                        setw(HEADER_20) << setprecision(3) << fixed << right << vnearbyStns.at(stn).second.first <<                // Separation (m)
98✔
1982
                                                        setw(HEADER_20) << setprecision(3) << fixed << vnearbyStns.at(stn).second.second <<                // Diff height (m)
49✔
1983
                                                        endl;
49✔
1984
                                        }
1985

1986
                                        ss_msg <<
1✔
1987
                                                "  If the names in each pair refer to the same station, then update the " << endl <<
1✔
1988
                                                "  station and measurement files with the correct station name and re-run " << __BINARY_NAME__ << "." << endl <<
1✔
1989
                                                "  Alternatively, if the names in each pair are unique, either call " << __BINARY_NAME__ << endl <<
1✔
1990
                                                "  without the --" << TEST_NEARBY_STNS << " option, or decrease the radial search " << endl <<
1✔
1991
                                                "  distance using --" << TEST_NEARBY_STN_DIST << "." << endl << endl;
1✔
1992

1993
                                        if (!p.g.quiet)
1✔
1994
                                                cout << ss_msg.str();
1✔
1995
                                        imp_file << ss_msg.str();
1✔
1996
                                        imp_file.close();
1✔
1997
                                        dst_file.close();
1✔
1998
                                        return EXIT_FAILURE;
1999
                                }
2000
                                else if (p.g.verbose == 3)
2✔
2001
                                {
2002
                                        if (!p.g.quiet)
×
2003
                                                cout << "+ Total number of unique stations is " << vstationsTotal.size() << endl;
×
2004
                                        imp_file << "+ Total number of unique stations is " << vstationsTotal.size() << endl;
×
2005
                                }
2006

2007
                                // If this line is reached, then there are no nearby stations
2008
                                dst_file.close();
2✔
2009
                        }
2010
                        if (!p.g.quiet)
54✔
2011
                                cout << endl;
53✔
2012
                        imp_file << endl;
54✔
2013
                } 
55✔
2014
                catch (const XMLInteropException& e) {
×
2015
                        cout << endl << "- Error: " << e.what() << endl;
×
2016
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2017
                        imp_file.close();
×
2018
                        return EXIT_FAILURE;
×
2019
                }                
×
2020

2021
                /////////////////////////////////////////////////////////////////
2022
                // Now commence sorting and mapping
2023
                // 1. Sort stations
2024
                // 2. Create station map
2025
                try {
54✔
2026
                        if (!p.g.quiet)
54✔
2027
                        {
2028
                                cout << "+ Sorting stations... ";
53✔
2029
                                cout.flush();
53✔
2030
                        }
2031
                        imp_file << "+ Sorting stations... ";
54✔
2032
                        parserDynaML.FullSortandMapStations((vdnaStnPtr*) &vstationsTotal, &vStnsMap_sortName);
54✔
2033
                        if (!p.g.quiet)
54✔
2034
                        {
2035
                                cout << "Done." << endl << "+ Serialising station map... ";
53✔
2036
                                cout.flush();
53✔
2037
                        }
2038
                        imp_file << "Done." << endl << "+ Serialising station map... ";                        
54✔
2039
                        parserDynaML.SerialiseMap(p.i.map_file);                // parserDynaML keeps the map in memory
54✔
2040
                        stn_map_created = true;
54✔
2041
                        if (!p.g.quiet)
54✔
2042
                        {
2043
                                cout << "Done." << endl;
53✔
2044
                                cout.flush();
53✔
2045
                        }
2046
                        imp_file << "Done." << endl;
54✔
2047

2048
                        if (p.i.export_map_file)
54✔
2049
                        {
2050
                                if (!p.g.quiet)
4✔
2051
                                {
2052
                                        cout << "+ Exporting station map to text file... ";
4✔
2053
                                        cout.flush();
4✔
2054
                                }
2055
                                imp_file << "+ Exporting station map to text file... ";
4✔
2056
                                parserDynaML.SerialiseMapTextFile(p.i.map_file);
4✔
2057
                                if (!p.g.quiet)
4✔
2058
                                {
2059
                                        cout << "Done." << endl;
4✔
2060
                                        cout.flush();
4✔
2061
                                }
2062
                                imp_file << "Done." << endl;                                
4✔
2063
                        }
2064
                } 
2065
                catch (const XMLInteropException& e) {
×
2066
                        cout << endl << "- Error: " << e.what() << endl;
×
2067
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2068
                        imp_file.close();
×
2069
                        return EXIT_FAILURE;
×
2070
                }        
×
2071
        }
55✔
2072

2073
        // Search for similar measurements
2074
        if (msrCount > 0 && (p.i.search_similar_msr || p.i.search_similar_msr_gx || p.i.ignore_similar_msr)) 
54✔
2075
        {
2076
                if (SearchForSimilarMeasurements(&parserDynaML, &p, &imp_file,
4✔
2077
                        &vmeasurementsTotal) != EXIT_SUCCESS)
2078
                        return EXIT_FAILURE;        
2079
        }
2080

2081
        // Import DNA geoid file
2082
        if (p.i.import_geo_file && p.i.import_block == 0 && p.i.import_network == 0 && vstationsTotal.size())
54✔
2083
        {
2084
                if (!exists(p.i.geo_file))
2✔
2085
                {
2086
                        path geoPath(p.i.geo_file);
×
2087
                        stringstream ss;
×
2088
                        ss << "- Error: The geoid file " << geoPath.filename().string() << " does not exist." << endl;
×
2089
                        cout << endl << ss.str();
×
2090
                        imp_file << endl << ss.str();
×
2091
                        return EXIT_FAILURE;
×
2092
                }
×
2093

2094
                if (!p.g.quiet)
2✔
2095
                {
2096
                        cout << "+ Importing geoid information from " << p.i.geo_file << "... ";
2✔
2097
                        cout.flush();
2✔
2098
                }
2099
                imp_file << "+ Importing geoid information from " << p.i.geo_file << "... ";
2✔
2100

2101
                parserDynaML.LoadDNAGeoidFile(p.i.geo_file, &vstationsTotal);
2✔
2102

2103
                if (!p.g.quiet)
2✔
2104
                        cout << "Done." << endl;
2✔
2105
                imp_file << "Done." << endl;
2✔
2106
        }
2107

2108
        UINT32 ignMsrCount, mapCount;
54✔
2109
        vstring vunusedStations;
54✔
2110
        vUINT32 vignoredMeasurements;
54✔
2111

2112
        // Map measurements to stations
2113
        if (stn_map_created) 
54✔
2114
        {        
2115
                try {
54✔
2116
                        if (!p.g.quiet)
54✔
2117
                        {
2118
                                cout << "+ Mapping measurements to stations... ";
53✔
2119
                                cout.flush();
53✔
2120
                        }
2121
                        imp_file << "+ Mapping measurements to stations... ";
54✔
2122
                        
2123
                        parserDynaML.MapMeasurementStations((vdnaMsrPtr*) &vmeasurementsTotal,        &associatedSL, &mapCount, 
54✔
2124
                                &vunusedStations, &vignoredMeasurements);
2125
                        
2126
                        if (!p.g.quiet)
53✔
2127
                                cout << "Done." << endl;
52✔
2128
                        imp_file << "Done. ";
53✔
2129

2130
                        if (msrCount > 0)
53✔
2131
                        {
2132
                                measurements_mapped = true;
51✔
2133
                                imp_file << "Mapped " << mapCount << " measurements to " << vStnsMap_sortName.size() - vunusedStations.size() << " stations." << endl;
51✔
2134
                        }
2135
                        else
2136
                                imp_file << endl;
2✔
2137

2138
                        if (!vunusedStations.empty())
53✔
2139
                        {
2140
                                if (vunusedStations.size() == 1)
17✔
2141
                                {
2142
                                        if (p.g.verbose > 2)
13✔
2143
                                        {
2144
                                                if (!p.g.quiet)
×
2145
                                                        cout << "- Warning: station " << vunusedStations.at(0) << " was not associated with any measurements." << endl;
×
2146
                                                imp_file << "- Warning: station " << vunusedStations.at(0) << " was not associated with any measurements." << endl;
×
2147
                                        }
2148
                                        else
2149
                                        {
2150
                                                if (!p.g.quiet)
13✔
2151
                                                        cout << "- Warning: " << vunusedStations.size() << " station was not associated with any measurements." << endl;
13✔
2152
                                                imp_file << "- Warning: " << vunusedStations.size() << " station was not associated with any measurements." << endl;
13✔
2153
                                        }
2154
                                }
2155
                                else
2156
                                {
2157
                                        if (p.g.verbose > 2)
4✔
2158
                                        {
2159
                                                if (!p.g.quiet)
×
2160
                                                        cout << "- Warning: The following " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
×
2161
                                                imp_file << "- Warning: The following " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
×
2162
                                                _it_vstr unused;
×
2163
                                                for (unused = vunusedStations.begin(); unused!=vunusedStations.end(); unused++)
×
2164
                                                {
2165
                                                        if (!p.g.quiet)
×
2166
                                                                outputObject(string("  - " + *unused + "\n"), cout);
×
2167
                                                        outputObject(string("  - " + *unused + "\n"), imp_file);
×
2168
                                                }
2169
                                        }
2170
                                        else
2171
                                        {
2172
                                                if (!p.g.quiet)
4✔
2173
                                                        cout << "- Warning: " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
4✔
2174
                                                imp_file << "- Warning: " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
4✔
2175
                                        }
2176
                                }
2177
                        }
2178

2179
                        if (msrRead < mapCount && vignoredMeasurements.empty())
53✔
2180
                        {
2181
                                if (!p.g.quiet)
×
2182
                                        cout << "- Warning: Not all measurements were mapped: " << msrRead << " msrs read vs. " << mapCount
×
2183
                                                << " msrs mapped." << endl;
×
2184
                        }
2185
                        else if (msrRead != mapCount && !vignoredMeasurements.empty())
53✔
2186
                        {
2187
                                ignMsrCount = parserDynaML.ComputeMeasurementCount(&vmeasurementsTotal, vignoredMeasurements);        
×
2188
                                if (!p.g.quiet)
×
2189
                                {
2190
                                        cout << "- Warning: " << ignMsrCount << " ignored measurements were not mapped." << endl;
×
2191
                                        if ((msrRead - mapCount) != ignMsrCount)
×
2192
                                                cout << "-          " << msrRead << " m.read vs. " << mapCount << " m.mapped." << endl;
×
2193
                                }
2194
                        }
2195
                        if (!p.g.quiet)
53✔
2196
                                cout.flush();
52✔
2197
                } 
2198
                catch (const XMLInteropException& e) {
1✔
2199
                        cout << endl << "- Error: " << e.what() << endl;
1✔
2200
                        imp_file << endl << "- Error: " << e.what() << endl;
1✔
2201
                        imp_file.close();
1✔
2202
                        return EXIT_FAILURE;
1✔
2203
                }
1✔
2204
        }
2205

2206
        stnCount = static_cast<UINT32>(vstationsTotal.size());
53✔
2207
        if (stnCount > static_cast<UINT32>(associatedSL.size()))
53✔
2208
                stnCount = static_cast<UINT32>(associatedSL.size());
×
2209
        
2210
        // Does the user want to simulate measurements?
2211
        if (p.i.simulate_measurements && stnCount > 0 && msrCount > 0) 
53✔
2212
        {
2213
                // No need for the following code if the outer 'if' statement checks 
2214
                // for non-zero stnCount value
2215
                //
2216
                // if (stnCount == 0)
2217
                // {
2218
                //         if (!p.g.quiet)
2219
                //                 cout << "- Error: there are no stations from which to simulate measurements." << endl;
2220
                //         imp_file << "- Error: there are no stations from which to simulate measurements." << endl;
2221
                //         imp_file.close();
2222
                //         return EXIT_FAILURE;
2223
                // }        
2224
        
2225
                try {
1✔
2226
                        // Simulate measurements
2227
                        if (!p.g.quiet)
1✔
2228
                        {
2229
                                cout << "+ Simulating and exporting measurements to " << leafStr<string>(p.i.simulate_msrfile) << "... ";
2✔
2230
                                cout.flush();
1✔
2231
                        }
2232
                        imp_file << "+ Simulating and exporting measurements to " << leafStr<string>(p.i.simulate_msrfile) << "... ";
2✔
2233
                        parserDynaML.SimulateMSR(
1✔
2234
                                ((vdnaStnPtr*) &vstationsTotal), 
2235
                                ((vdnaMsrPtr*) &vmeasurementsTotal), 
2236
                                p.i.simulate_msrfile, p);
2237
                        if (!p.g.quiet)
1✔
2238
                                cout << "Done." << endl;
1✔
2239
                        imp_file << "Done." << endl;
1✔
2240
                }
2241
                catch (const XMLInteropException& e) {
×
2242
                        cout.flush();
×
2243
                        cout << endl << "- Error: " << e.what() << endl;
×
2244
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2245
                        imp_file.close();
×
2246
                        return EXIT_FAILURE;
×
2247
                }
×
2248
        }
2249

2250
        // Create association lists
2251
        if (measurements_mapped) 
53✔
2252
        {
2253
                try {
51✔
2254
                        if (!p.g.quiet)
51✔
2255
                        {
2256
                                cout << "+ Creating association lists... ";
50✔
2257
                                cout.flush();
50✔
2258
                        }
2259
                        imp_file << "+ Creating association lists... ";
51✔
2260
                        parserDynaML.CompleteAssociationLists(&vmeasurementsTotal, &associatedSL, &associatedML);
51✔
2261
                        if (!p.g.quiet)
51✔
2262
                        {
2263
                                cout << "Done." << endl;
50✔
2264
                                cout.flush();
50✔
2265
                        }
2266
                        imp_file << "Done." << endl;
51✔
2267
                } 
2268
                catch (const XMLInteropException& e) {
×
2269
                        cout << "- Error: " << e.what() << endl;
×
2270
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2271
                        imp_file.close();
×
2272
                        return EXIT_FAILURE;
×
2273
                }
×
2274

2275
                try {
51✔
2276
                        if (!p.g.quiet)
51✔
2277
                        {
2278
                                cout << "+ Serialising association lists... ";
50✔
2279
                                cout.flush();
50✔
2280
                        }
2281
                        imp_file << "+ Serialising association lists... ";
51✔
2282
                        parserDynaML.SerialiseAsl(p.i.asl_file, &associatedSL);
51✔
2283
                        parserDynaML.SerialiseAml(p.i.aml_file, &associatedML);
51✔
2284
                        if (!p.g.quiet)
51✔
2285
                        {
2286
                                cout << "Done." << endl;
50✔
2287
                                cout.flush();
50✔
2288
                        }
2289
                        imp_file << "Done." << endl;
51✔
2290
                } 
2291
                catch (const XMLInteropException& e) {
×
2292
                        cout << "- Error: " << e.what() << endl;
×
2293
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2294
                        imp_file.close();
×
2295
                        return EXIT_FAILURE;
×
2296
                }
×
2297
        }
2298

2299
        // Create binary station file.
2300
        // Binary station file can be serialised without measurements
2301
        if (stnCount > 0)
53✔
2302
        {
2303
                try {
53✔
2304
                        if (!vstationsTotal.empty())
53✔
2305
                        {
2306
                                if (!p.g.quiet)
53✔
2307
                                {
2308
                                        cout << "+ Serialising binary station file " << leafStr<string>(p.i.bst_file) << "... ";
104✔
2309
                                        cout.flush();
52✔
2310
                                }
2311
                                imp_file << "+ Serialising binary station file " << leafStr<string>(p.i.bst_file) << "... ";
106✔
2312
                                
2313
                                parserDynaML.SerialiseBst(
53✔
2314
                                        p.i.bst_file, ((vdnaStnPtr*) &vstationsTotal), &vunusedStations,
2315
                                        vinput_file_meta, (p.i.flag_unused_stn ? true : false));
53✔
2316
                                if (!p.g.quiet)
53✔
2317
                                {
2318
                                        cout << "Done." << endl;
52✔
2319
                                        cout.flush();
52✔
2320
                                }
2321
                                imp_file << "Done." << endl;
53✔
2322
                        }
2323
                } 
2324
                catch (const XMLInteropException& e) {
×
2325
                        cout << "- Error: " << e.what() << endl;
×
2326
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2327
                        imp_file.close();
×
2328
                        return EXIT_FAILURE;
×
2329
                }
×
2330
        }
2331

2332
        // Create binary measurement file.
2333
        // Binary measurement file can be serialised without stations
2334
        if (msrCount > 0) 
53✔
2335
        {
2336
                try {
51✔
2337
                        if (!vmeasurementsTotal.empty())
51✔
2338
                        {
2339
                                if (!p.g.quiet)
51✔
2340
                                {
2341
                                        cout << "+ Serialising binary measurement file " << leafStr<string>(p.i.bms_file) << "... ";
100✔
2342
                                        cout.flush();
50✔
2343
                                }
2344
                                imp_file << "+ Serialising binary measurement file " << leafStr<string>(p.i.bms_file) << "... ";
102✔
2345

2346
                                parserDynaML.SerialiseBms(
51✔
2347
                                        p.i.bms_file, ((vdnaMsrPtr*) &vmeasurementsTotal),
2348
                                        vinput_file_meta);
2349
                                if (!p.g.quiet)
51✔
2350
                                {
2351
                                        cout << "Done." << endl;
50✔
2352
                                        cout.flush();
50✔
2353
                                }
2354
                                imp_file << "Done." << endl;
51✔
2355
                        }
2356
                } 
2357
                catch (const XMLInteropException& e) {
×
2358
                        cout << "- Error: " << e.what() << endl;
×
2359
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2360
                        imp_file.close();
×
2361
                        return EXIT_FAILURE;
×
2362
                }
×
2363
        }
2364

2365
        // Export ASL and AML to text if required
2366
        if (measurements_mapped) 
53✔
2367
        {
2368
                try {
51✔
2369
                        if (p.i.export_asl_file)
51✔
2370
                        {
2371
                                if (!p.g.quiet)
4✔
2372
                                {
2373
                                        cout << "+ Exporting associated station list to text file... ";
4✔
2374
                                        cout.flush();
4✔
2375
                                }
2376
                                imp_file << "+ Exporting associated station list to text file... ";
4✔
2377
                                parserDynaML.SerialiseAslTextFile(p.i.asl_file, &associatedSL, (vdnaStnPtr*) &vstationsTotal);
4✔
2378
                                if (!p.g.quiet)
4✔
2379
                                {
2380
                                        cout << "Done." << endl;
4✔
2381
                                        cout.flush();
4✔
2382
                                }
2383
                                imp_file << "Done." << endl;                                
4✔
2384
                        }
2385
                } 
2386
                catch (const XMLInteropException& e) {
×
2387
                        cout << "- Error: " << e.what() << endl;
×
2388
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2389
                        imp_file.close();
×
2390
                        return EXIT_FAILURE;
×
2391
                }
×
2392

2393
                try {
51✔
2394
                        if (p.i.export_aml_file)
51✔
2395
                        {
2396
                                if (!p.g.quiet)
4✔
2397
                                {
2398
                                        cout << "+ Exporting associated measurement list to text file... ";
4✔
2399
                                        cout.flush();
4✔
2400
                                }
2401
                                imp_file << "+ Exporting associated measurement list to text file... ";
4✔
2402
                                parserDynaML.SerialiseAmlTextFile(p.i.bms_file, p.i.aml_file, &associatedML, &associatedSL, (vdnaStnPtr*) &vstationsTotal);
4✔
2403
                                if (!p.g.quiet)
4✔
2404
                                {
2405
                                        cout << "Done." << endl;
4✔
2406
                                        cout.flush();
4✔
2407
                                }
2408
                                imp_file << "Done." << endl;                                
4✔
2409
                        }
2410
                }
2411
                catch (const XMLInteropException& e) {
×
2412
                        cout << "- Error: " << e.what() << endl;
×
2413
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2414
                        imp_file.close();
×
2415
                        return EXIT_FAILURE;
×
2416
                }
×
2417

2418
                if (p.i.test_integrity)
51✔
2419
                {
2420
                        if (!p.g.quiet)
2✔
2421
                        {
2422
                                cout << "+ Testing internal integrity of ASL, AML and binary files... ";
2✔
2423
                                cout.flush();
2✔
2424
                        }
2425
                        std::ifstream binaryMS(p.i.bms_file.c_str(), ios::in | ios::binary | std::ifstream::ate);        /// Open and seek to end immediately after opening.
2✔
2426
                        if (!binaryMS.good())
2✔
2427
                        {
2428
                                cout << endl << "- Could not open binary file for reading." << endl;
×
2429
                                imp_file << endl << "- Could not open binary file for reading." << endl;
×
2430
                                imp_file.close();
×
2431
                                return EXIT_FAILURE;
×
2432
                        }
2433
                        // get size, then go back to beginning
2434
                        size_t sFileSize = (size_t)binaryMS.tellg();
2✔
2435
                        binaryMS.seekg(0, ios::beg);
2✔
2436

2437
                        measurement_t measRecord;
2✔
2438
                        
2439
                        UINT32 amlcount, amlindex, msr;
2✔
2440
                        for (stn=0; stn<stnCount; stn++)
90✔
2441
                        {
2442
                                amlcount = associatedSL.at(stn).get()->GetAssocMsrCount();
86✔
2443
                                
2444
                                // The following is to be used when reading from binary file
2445
                                for (msr=0; msr<amlcount; msr++)
624✔
2446
                                {
2447
                                        amlindex = associatedSL.at(stn).get()->GetAMLStnIndex() + msr;
538✔
2448
                                        if (associatedML.at(amlindex) * sizeof(measurement_t) >= sFileSize)
538✔
2449
                                        {
2450
                                                cout << "Error: index " << associatedML.at(amlindex) << " is out of range for the binary file." << endl;
×
2451
                                                continue;
×
2452
                                        }
2453
                                        binaryMS.seekg(sizeof(UINT32) + associatedML.at(amlindex) * sizeof(measurement_t), ios::beg);
538✔
2454
                                        binaryMS.read(reinterpret_cast<char *>(&measRecord), sizeof(measurement_t));
538✔
2455
                                }
2456
                        }
2457
                        binaryMS.close();
2✔
2458
                        if (!p.g.quiet)
2✔
2459
                                cout << "OK." << endl;
2✔
2460
                }
2✔
2461
        }
2462

2463
        try {
53✔
2464
                // Print measurements to stations table
2465
                PrintMeasurementstoStations(&parsemsrTally, &parserDynaML, &p, &associatedSL);
53✔
2466
        }
2467
        catch (const XMLInteropException& e) {
×
2468
                cout.flush();
×
2469
                cout << endl << "- Error: " << e.what() << endl;
×
2470
                imp_file << endl << "- Error: " << e.what() << endl;
×
2471
                imp_file.close();
×
2472
                return EXIT_FAILURE;
×
2473
        }
×
2474

2475

2476
        // Serialise database ids
2477
        if (p.i.import_block == 1 || p.i.import_network == 1)
53✔
2478
        {
2479
                // dbid_file filename formed earlier
2480
                parserDynaML.SerialiseDatabaseId(p.i.dbid_file, &vmeasurementsTotal);
4✔
2481
        }
2482
        else
2483
        {
2484
                p.i.dbid_file = formPath<string>(p.g.output_folder, p.g.network_name, "dbid");
49✔
2485
                parserDynaML.SerialiseDatabaseId(p.i.dbid_file, &vmeasurementsTotal);
49✔
2486
        }
2487

2488

2489
        
2490

2491
        // Export stations and measurements
2492
        try {
53✔
2493
                if (p.i.export_dynaml || p.i.export_dna_files)
53✔
2494
                        ExportStationsandMeasurements(&parserDynaML, p, &imp_file, &vinput_file_meta, 
12✔
2495
                                &vstationsTotal, &vmeasurementsTotal, stnCount, msrCount);
2496
        }
2497
        catch (const XMLInteropException& e) {
×
2498
                cout.flush();
×
2499
                cout << endl << "- Error: " << e.what() << endl;
×
2500
                imp_file << endl << "- Error: " << e.what() << endl;
×
2501
                imp_file.close();
×
2502
                return EXIT_FAILURE;
×
2503
        }
×
2504
        
2505
        if (!userSuppliedSegFile)
53✔
2506
                p.i.seg_file = "";
52✔
2507
        if (!userSuppliedBstFile)
53✔
2508
                p.i.bst_file = "";
53✔
2509
        if (!userSuppliedBmsFile)
53✔
2510
                p.i.bms_file = "";
53✔
2511

2512
        // Look for a project file.  If it exists, open and load it.
2513
        // Update the import settings.
2514
        // Print the project file. If it doesn't exist, it will be created.
2515
        CDnaProjectFile projectFile;
53✔
2516
        if (exists(p.g.project_file))
53✔
2517
                projectFile.LoadProjectFile(p.g.project_file);
23✔
2518
        
2519
        projectFile.UpdateSettingsImport(p);
53✔
2520
        projectFile.UpdateSettingsReftran(p);
53✔
2521
        projectFile.UpdateSettingsOutput(p);
53✔
2522
        projectFile.PrintProjectFile();
53✔
2523

2524
        if (msrCount == 0)
53✔
2525
        {
2526
                cout << "- Warning: there are no measurements to process." << endl;
2✔
2527
                imp_file << "- Warning: there are no measurements to process." << endl;
2✔
2528
        }
2529
        
2530
        if (errorCount)
53✔
2531
        {
2532
                cout << "- Warning: some files were not parsed - please read the log file for more details." << endl;
×
2533
                imp_file << "- Warning: some files were not parsed - please read the log file for more details." << endl;
×
2534
        }
2535

2536
        // Produce a warning if an ensemble is set as the default reference frame
2537
        if (isEpsgWGS84Ensemble(epsgCode))
53✔
2538
        {
2539
                stringstream ssEnsembleWarning;
×
2540
                ssEnsembleWarning << endl <<
×
2541
                        "- Warning:  The '" << p.i.reference_frame << "' reference frame set for this project refers to the" << endl <<
×
2542
                        "  \"World Geodetic System 1984 (WGS 84) ensemble\".  The WGS 84 ensemble is" << endl <<
×
2543
                        "  only suitable for low accuracy (metre level) positioning and does not" << endl <<
×
2544
                        "  provide for precise transformations to other well-known reference frames." << endl <<
×
2545
                        "  To achieve reliable adjustment results from data on WGS 84, please refer" << endl <<
×
2546
                        "  to \"Configuring import options\" in the DynAdjust User's Guide." << endl;
×
2547
                if (!p.g.quiet)
×
2548
                        cout << ssEnsembleWarning.str();
×
2549
                imp_file << ssEnsembleWarning.str();
×
2550
        }
×
2551
        
2552
        milliseconds elapsed_time(milliseconds(time.elapsed().wall/MILLI_TO_NANO));
53✔
2553
        string time_message = formatedElapsedTime<string>(&elapsed_time, "+ Total file handling process took ");
53✔
2554

2555
        if (!p.g.quiet)
53✔
2556
                cout << endl << time_message << endl;
52✔
2557
        imp_file << endl << time_message << endl;
53✔
2558
        
2559
        if (stnCount > 0 && msrCount > 0)
53✔
2560
        {
2561
                if (!p.g.quiet)
51✔
2562
                        cout << "+ Binary station and measurement files are now ready for processing." << endl << endl;
50✔
2563
                imp_file << "+ Binary station and measurement files are now ready for processing." << endl << endl;
51✔
2564
        }
2565

2566
        imp_file.close();
53✔
2567
        return PARSE_SUCCESS;
53✔
2568
}
322✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc