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

icsm-au / DynAdjust / 4558627370

pending completion
4558627370

Pull #213

github

GitHub
Merge c078a4c77 into 9331be4bf
Pull Request #213: Version 1.2.7 (various fixes and enhancements)

949 of 949 new or added lines in 30 files covered. (100.0%)

30356 of 38394 relevant lines covered (79.06%)

3987.35 hits per line

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

76.1
/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)
65✔
33
{
34
        // Print formatted header
35
        print_file_header(*f_out, header);
65✔
36

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

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

52
        if (!p->i.input_files.empty())
65✔
53
        {
54
                _it_vstr _it_files(p->i.input_files.begin());
65✔
55
                string str("Input files:");
65✔
56
                while (_it_files!=p->i.input_files.end())
65✔
57
                {
58
                        *f_out << setw(PRINT_VAR_PAD) << left << str << *_it_files++ << endl;
160✔
59
                        str = " ";
225✔
60
                }
61
        }
65✔
62
        
63
        if (!p->i.reference_frame.empty())
65✔
64
                *f_out << setw(PRINT_VAR_PAD) << left << "Default reference frame:" << p->i.reference_frame << endl;
65✔
65
        
66
        if (!p->i.include_msrs.empty())
65✔
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())
63✔
69
                *f_out << setw(PRINT_VAR_PAD) << left << "Strip measurement types:" << p->i.exclude_msrs << endl;
1✔
70
        
71
        if (p->i.search_nearby_stn)
65✔
72
                *f_out << setw(PRINT_VAR_PAD) << left << "Search for nearby stations:" << "tolerance = " << p->i.search_stn_radius << "m" << endl;
3✔
73
        if (p->i.search_similar_msr)
65✔
74
                *f_out << setw(PRINT_VAR_PAD) << left << "Search for similar measurements:" << "yes" << endl;
6✔
75
        if (p->i.search_similar_msr_gx)
65✔
76
                *f_out << setw(PRINT_VAR_PAD) << left << "Search for similar GNSS measurements:" << "yes" << endl;
2✔
77
        
78
        if (!p->i.bounding_box.empty())
65✔
79
        {
80
                *f_out << setw(PRINT_VAR_PAD) << left << "Bounding box: " << p->i.bounding_box << endl;
1✔
81
                if (p->i.split_clusters)
1✔
82
                        *f_out << setw(PRINT_VAR_PAD) << left << "Split GNSS clusters: " << (p->i.split_clusters ? "Yes" : "No") << endl;
1✔
83
        }
84
        else 
85
        {
86
                if (!p->i.stn_associated_msr_include.empty())
64✔
87
                        *f_out << setw(PRINT_VAR_PAD) << left << "Stations to include: " << p->i.stn_associated_msr_include << endl;
5✔
88
                if (!p->i.stn_associated_msr_exclude.empty())
64✔
89
                        *f_out << setw(PRINT_VAR_PAD) << left << "Stations to exclude: " << p->i.stn_associated_msr_exclude << endl;
1✔
90

91
                if (p->i.split_clusters)
64✔
92
                        *f_out << setw(PRINT_VAR_PAD) << left << "Split GNSS clusters: " << (p->i.split_clusters ? "Yes" : "No") << endl;
4✔
93
        }
94

95
        if (!p->i.seg_file.empty())
65✔
96
        {
97
                *f_out << setw(PRINT_VAR_PAD) << left << "Segmentation file:" << system_complete(p->i.seg_file).string() << endl;
×
98
                *f_out << setw(PRINT_VAR_PAD) << left << "Import stns & msrs from block: " << p->i.import_block_number << endl;
×
99
        }
100

101
        *f_out << OUTPUTLINE << endl << endl;
65✔
102
}
65✔
103
        
104
int ParseCommandLineOptions(const int& argc, char* argv[], const variables_map& vm, project_settings& p)
60✔
105
{
106
        // capture command line arguments
107
        for (int cmd_arg(0); cmd_arg<argc; ++cmd_arg)
523✔
108
        {
109
                 p.i.command_line_arguments += argv[cmd_arg];
463✔
110
                 p.i.command_line_arguments += " ";
463✔
111
        }
112

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

129
                cout << endl << "- Error: project file " << p.g.project_file << " does not exist." << endl << endl;
1✔
130
                return EXIT_FAILURE;
1✔
131
        }
132

133
        if (!vm.count(IMPORT_FILE) && !vm.count(IMPORT_SEG_BLOCK) && !vm.count(SEG_FILE))
60✔
134
        {
135
                cout << endl << "- Nothing to do - no files specified. " << endl << endl;  
1✔
136
                return EXIT_FAILURE;
1✔
137
        }
138

139
        // Normalise files using input folder
140
        for_each(p.i.input_files.begin(), p.i.input_files.end(),
57✔
141
                [&p] (string& file) { 
258✔
142
                        formPath<string>(p.g.input_folder, file);
258✔
143
                }
129✔
144
        );
145

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

163
                        // 2. Does this network exist?
164
                        if (!exists(networkASL))
3✔
165
                                break;
166

167
                        // 3. Flush and look for the next network
168
                        netname_ss.str("");
2✔
169
                        netname_ss << "network" << ++networkID;
1✔
170
                        p.g.network_name = netname_ss.str();                        
1✔
171
                }
172
        }
2✔
173

174
        p.g.project_file = formPath<string>(p.g.output_folder, p.g.network_name, "dnaproj");
57✔
175

176
        // binary station file location (output)
177
        if (vm.count(BIN_STN_FILE))
57✔
178
                p.i.bst_file = formPath<string>(p.g.output_folder, p.i.bst_file);
×
179
        else
180
                p.i.bst_file = formPath<string>(p.g.output_folder, p.g.network_name, "bst");
57✔
181
        
182
        // binary station file location (output)
183
        if (vm.count(BIN_MSR_FILE))
57✔
184
                p.i.bms_file = formPath<string>(p.g.output_folder, p.i.bms_file);
×
185
        else
186
                p.i.bms_file = formPath<string>(p.g.output_folder, p.g.network_name, "bms");
57✔
187

188
        if (vm.count(IMPORT_GEO_FILE))
57✔
189
                p.i.import_geo_file = 1;
2✔
190

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

206
        //////////////////////////////////////////////////////////////////////////////
207
        // Data screening options
208
        if (vm.count(GET_MSRS_TRANSCENDING_BOX))
57✔
209
                p.i.include_transcending_msrs = 1;
2✔
210

211
        if (vm.count(SPLIT_CLUSTERS))
57✔
212
                p.i.split_clusters = 1;
5✔
213

214
        // User supplied segmentation file
215
        if (vm.count(IMPORT_SEG_BLOCK))
57✔
216
                p.i.import_block = 1;
×
217

218
        // User supplied segmentation file
219
        if (vm.count(SEG_FILE))
57✔
220
        {
221
                // Does it exist?
222
                if (!exists(p.i.seg_file))
×
223
                        // Look for it in the input folder
224
                        p.i.seg_file = formPath<string>(p.g.input_folder, leafStr<string>(p.i.seg_file));
×
225
        }
226

227
        // convert all single X measurements to G measurements?
228
        if (vm.count(PREFER_X_MSR_AS_G))
57✔
229
                p.i.prefer_single_x_as_g = 1;
3✔
230

231
        if (vm.count(TEST_NEARBY_STNS))
57✔
232
                p.i.search_nearby_stn = 1;
2✔
233

234
        if (vm.count(TEST_SIMILAR_MSRS))
57✔
235
                p.i.search_similar_msr = 1;
3✔
236

237
        if (vm.count(TEST_SIMILAR_GNSS_MSRS))
57✔
238
                p.i.search_similar_msr_gx = 1;
1✔
239

240
        if (vm.count(IGNORE_SIMILAR_MSRS))
57✔
241
                p.i.ignore_similar_msr = 1;
2✔
242

243
        if (vm.count(REMOVE_IGNORED_MSRS))
57✔
244
                p.i.remove_ignored_msr = 1;
1✔
245

246
        if (vm.count(FLAG_UNUSED_STNS))
57✔
247
                p.i.flag_unused_stn = 1;
5✔
248

249
        if (vm.count(TEST_INTEGRITY))
57✔
250
                p.i.test_integrity = 1;
2✔
251
        
252
        //////////////////////////////////////////////////////////////////////////////
253
        // GNSS scaling
254
        if (vm.count(VSCALE) ||
170✔
255
                vm.count(PSCALE) ||
169✔
256
                vm.count(LSCALE) ||
169✔
257
                vm.count(HSCALE) ||
226✔
258
                vm.count(SCALAR_FILE))
169✔
259
                p.i.apply_scaling = 1;
2✔
260

261
        if (vm.count(SCALAR_FILE))
57✔
262
                if (!exists(p.i.scalar_file))                        // does it exist?
1✔
263
                        // No.  Assume it is a filename contained in the input folder.  import will throw
264
                        // an exception if it cannot be found.
265
                        p.i.scalar_file = formPath<string>(p.g.input_folder, p.i.scalar_file);        
×
266
        
267
        //////////////////////////////////////////////////////////////////////////////
268
        // Export options
269
        
270
        if (vm.count(OUTPUT_MSR_TO_STN))
57✔
271
                p.o._msr_to_stn = 1;
6✔
272

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

275
        // Create file name based on the provided block
276
        string fileName(p.g.network_name);
57✔
277
        if (p.i.import_block)
57✔
278
        {
279
                stringstream blk("");
×
280
                blk << ".block-" << p.i.import_block_number;
×
281
                fileName += blk.str();
×
282
        }
×
283

284
        // Export to dynaml?
285
        if (vm.count(EXPORT_XML_FILES))
57✔
286
        {
287
                p.i.export_dynaml = 1;
10✔
288
        
289
                //// Export from binary
290
                //if (vm.count(EXPORT_FROM_BINARY))
291
                //        p.i.export_from_bfiles = 1;
292

293
                // single file for both stations and measurements
294
                if (vm.count(EXPORT_SINGLE_XML_FILE))
10✔
295
                {
296
                        p.i.export_single_xml_file = 1;
2✔
297
                        p.i.xml_outfile = formPath<string>(p.g.output_folder, 
4✔
298
                                fileName, "xml");
2✔
299
                }
300
                // unique files for stations and measurements
301
                else
302
                {
303
                        p.i.export_single_xml_file = 0;
8✔
304
                        p.i.xml_stnfile = formPath<string>(p.g.output_folder, 
24✔
305
                                fileName + "stn", "xml");
24✔
306
                        p.i.xml_msrfile = formPath<string>(p.g.output_folder, 
32✔
307
                                fileName + "msr", "xml");
24✔
308
                }
309
        }
310

311
        // Export dna files
312
        if (vm.count(EXPORT_DNA_FILES))
57✔
313
        {
314
                p.i.export_dna_files = 1;                
8✔
315
                p.i.dna_stnfile = formPath<string>(p.g.output_folder, 
16✔
316
                        fileName, "stn");
8✔
317
                p.i.dna_msrfile = formPath<string>(p.g.output_folder, 
16✔
318
                        fileName, "msr");
8✔
319
        }
320

321
        if (vm.count(EXPORT_ASL_FILE))
57✔
322
                p.i.export_asl_file = 1;
4✔
323
        if (vm.count(EXPORT_AML_FILE))
57✔
324
                p.i.export_aml_file = 1;
4✔
325
        if (vm.count(EXPORT_MAP_FILE))
57✔
326
                p.i.export_map_file = 1;
4✔
327
        if (vm.count(EXPORT_DISCONT_FILE))
57✔
328
                p.i.export_discont_file = 1;
1✔
329
        
330
        // Simulate
331
        if (vm.count(SIMULATE_MSR_FILE))
57✔
332
        {
333
                p.i.simulate_measurements = 1;
1✔
334
                p.i.simulate_msrfile = formPath<string>(p.g.output_folder,
2✔
335
                        p.g.network_name, "simulated.msr");
1✔
336
        }
337

338
        // Station renaming file
339
        if (vm.count(STATION_RENAMING_FILE))
57✔
340
                p.i.rename_stations = 1;
1✔
341

342
        return EXIT_SUCCESS;
57✔
343
}
60✔
344

345
void PrintMeasurementstoStations(MsrTally* parsemsrTally, dna_import* parserDynaML, 
49✔
346
        project_settings* p, pvASLPtr vAssocStnList)
347
{
348
        // Print measurements to stations table
349
        if (p->o._msr_to_stn)
49✔
350
        {
351
                if (!p->g.quiet)
6✔
352
                {
353
                        cout << "+ Printing summary of measurements connected to each station...";
6✔
354
                        cout.flush();
6✔
355
                }
356
                parserDynaML->PrintMeasurementsToStations(p->o._m2s_file, parsemsrTally, 
6✔
357
                        p->i.bst_file, p->i.bms_file, p->i.aml_file, vAssocStnList);
6✔
358
                if (!p->g.quiet)
6✔
359
                        cout << " done." << endl;
6✔
360
        }
361
}
49✔
362

363
int SearchForSimilarMeasurements(dna_import* parserDynaML, project_settings* p, std::ofstream* imp_file,
4✔
364
        vdnaMsrPtr* vmeasurementsTotal)
365
{
366
        std::ofstream dms_file;
4✔
367
        UINT32 msr;
4✔
368
        vdnaMsrPtr vSimilarMeasurements;
4✔
369
        string comment("");
4✔
370

371
        try {
4✔
372
                if (!p->g.quiet)
4✔
373
                {
374
                        cout << "+ Searching for similar measurements... ";
3✔
375
                        cout.flush();
3✔
376
                }
377
                *imp_file << "+ Searching for similar measurements... ";
4✔
378

379
                // at this stage, perform only one search option, giving preference to GNSS searching 
380
                // if both are provided
381
                if (p->i.search_similar_msr_gx)
4✔
382
                        msr = parserDynaML->FindSimilarGXMeasurements(vmeasurementsTotal, &vSimilarMeasurements);
1✔
383
                else
384
                        msr = parserDynaML->FindSimilarMeasurements(vmeasurementsTotal, &vSimilarMeasurements);
3✔
385

386
                if (!vSimilarMeasurements.empty())
4✔
387
                {
388
                        ostringstream ss_msg;
4✔
389
                        if (!p->i.ignore_similar_msr)
4✔
390
                                ss_msg << endl << "- Warning: ";
2✔
391
                        else
392
                                ss_msg << endl << "- Note: ";
2✔
393

394
                        ss_msg << msr << " measurement" << (msr > 1 ? "s were" : " was") << 
4✔
395
                                " found to be very similar (if not identical)\n  to " << 
396
                                (msr > 1 ? "other measurements" : "another measurement") << 
397
                                ".  See " << p->i.dms_file << " for details." << endl;
4✔
398

399
                        *imp_file << ss_msg.str();
4✔
400
                        if (!p->g.quiet)
4✔
401
                                cout << ss_msg.str();
3✔
402
                        ss_msg.str("");
8✔
403

404
                        try {
4✔
405
                                // Create duplicate measurements file
406
                                file_opener(dms_file, p->i.dms_file);
4✔
407
                        }
408
                        catch (const ios_base::failure& f) {
×
409
                                stringstream ss;
×
410
                                ss << "- Error: Could not open " << p->i.dms_file << "." << endl;
×
411
                                ss << "  Check that the file exists and that the file is not already opened." << endl << f.what();
×
412
                                if (!p->g.quiet)
×
413
                                        cout << ss.str();
×
414
                                *imp_file << ss.str();
×
415
                                imp_file->close();
×
416
                                return EXIT_FAILURE;
×
417
                        }
×
418

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

421
                        // output message
422
                        dms_file << endl << "- " << msr << " measurement" << (msr > 1 ? "s were" : " was") << 
4✔
423
                                " found to be very similar (if not identical)\n  to " << 
424
                                (msr > 1 ? "other measurements." : "another measurement.  ");
4✔
425

426
                        if (p->i.ignore_similar_msr)
4✔
427
                                dms_file << endl << "+ These measurements have been ignored.";
2✔
428
                        dms_file << endl << endl;
4✔
429

430
                        // dump measurements to dms file
431
                        for_each (vSimilarMeasurements.begin(), vSimilarMeasurements.end(),
4✔
432
                                [&dms_file, &comment] (dnaMsrPtr& m) {
118✔
433
                                        m->WriteDynaMLMsr(&dms_file, comment);
59✔
434
                        });
59✔
435

436
                        dms_file.close();
4✔
437

438
                        if (p->i.ignore_similar_msr)
4✔
439
                                ss_msg << "  These measurements have been ignored." << endl;
2✔
440
                        else
441
                                ss_msg << endl <<
2✔
442
                                "  If the listed measurements are true duplicates, either remove each duplicate " << endl <<
2✔
443
                                "  from the measurement file and re-run " << __BINARY_NAME__ << ", or re-run " << __BINARY_NAME__ << " with the" << endl <<
2✔
444
                                "  --" << IGNORE_SIMILAR_MSRS << " option.  Alternatively, if each measurement " << endl <<
2✔
445
                                "  is unique, then call " << __BINARY_NAME__ << " without the --" << TEST_SIMILAR_MSRS << " option." << endl << endl;
2✔
446

447
                        if (!p->g.quiet)
4✔
448
                                cout << ss_msg.str();
3✔
449
                        *imp_file << ss_msg.str();
4✔
450

451
                        if (!p->i.ignore_similar_msr)
4✔
452
                        {
453
                                //imp_file->close();
454
                                return EXIT_SUCCESS;
455
                        }
456
                }
4✔
457
                else
458
                {
459
                        *imp_file << "Done. ";
×
460
                        if (!p->g.quiet)
×
461
                        {
462
                                cout << "Done. ";
×
463
                                cout.flush();
×
464
                        }
465
                }
466

467
                *imp_file << endl;
2✔
468
                if (!p->g.quiet)
2✔
469
                {
470
                        cout << endl;
2✔
471
                        cout.flush();
2✔
472
                }
473

474
        } 
475
        catch (const XMLInteropException& e) {
×
476
                cout << endl << "- Error: " << e.what() << endl;
×
477
                *imp_file << endl << "- Error: " << e.what() << endl;
×
478
                imp_file->close();
×
479
                return EXIT_FAILURE;
×
480
        }
×
481

482
        return EXIT_SUCCESS;
483

484
}
4✔
485
        
486

487
void ExportStationsandMeasurements(dna_import* parserDynaML, const project_settings& p, std::ofstream* imp_file, vifm_t* vinput_file_meta,
12✔
488
        vdnaStnPtr* vstationsTotal, vdnaMsrPtr* vmeasurementsTotal, const UINT32& stnCount, const UINT32& msrCount)
489
{
490
        stringstream ssEpsgWarning;
12✔
491
        bool displayEpsgWarning(false);
12✔
492
        string epsgCode(epsgStringFromName<string>(p.i.reference_frame));
12✔
493

494
        // Check inconsistent reference frames
495
        if ((p.i.export_dynaml || p.i.export_dna_files) && !p.i.override_input_rfame && !p.i.user_supplied_frame)
12✔
496
        {
497
                for (UINT32 i(0); i<vinput_file_meta->size(); ++i)
23✔
498
                {
499
                        if (!iequals(epsgCode, vinput_file_meta->at(i).epsgCode))
18✔
500
                        {
501
                                string inputFrame(datumFromEpsgString<string>(vinput_file_meta->at(i).epsgCode));
3✔
502
                                ssEpsgWarning << endl << "- Warning: The default reference frame (used for all exported files)" << endl << 
3✔
503
                                        "  does not match the reference frame of one or more input files. To" << endl <<
3✔
504
                                        "  suppress this warning, override the default reference frame using" << endl <<
3✔
505
                                        "  --reference-frame, or provide --override-input-ref-frame.";
3✔
506
                                displayEpsgWarning = true;
3✔
507
                                break;
3✔
508
                        }
3✔
509
                }
510
        }
511

512
        // Sort on original file order
513
        parserDynaML->SortStationsForExport(vstationsTotal);
12✔
514

515
        // DynaML file format
516
        if (p.i.export_dynaml && (stnCount > 0 || msrCount > 0)) 
12✔
517
        {                
518
                if (p.i.export_single_xml_file)
10✔
519
                {
520
                        // Single output file
521
                        if (!p.g.quiet)
2✔
522
                        {
523
                                cout << "+ Exporting stations and measurements to " << leafStr<string>(p.i.xml_outfile) << "... ";
4✔
524
                                cout.flush();
2✔
525
                        }
526
                        *imp_file << "+ Exporting stations and measurements to " << leafStr<string>(p.i.xml_outfile) << "... ";
4✔
527
                        parserDynaML->SerialiseDynaMLfromMemory(
2✔
528
                                vstationsTotal, vmeasurementsTotal, 
529
                                p.i.xml_outfile, p, vinput_file_meta, (p.i.flag_unused_stn ? true : false));
2✔
530
                }
531
                else
532
                {
533
                        // Separate output files (default)
534
                        if (!p.g.quiet)
8✔
535
                        {
536
                                cout << "+ Exporting stations and measurements to " << leafStr<string>(p.i.xml_stnfile) << " and " << leafStr<string>(p.i.xml_msrfile) << "... ";
32✔
537
                                cout.flush();
8✔
538
                        }
539
                        *imp_file << "+ Exporting stations and measurements to " << leafStr<string>(p.i.xml_stnfile) << " and " << leafStr<string>(p.i.xml_msrfile) << "... ";
32✔
540
                        parserDynaML->SerialiseDynaMLSepfromMemory(
8✔
541
                                vstationsTotal, vmeasurementsTotal,
542
                                p.i.xml_stnfile, p.i.xml_msrfile, p, vinput_file_meta, (p.i.flag_unused_stn ? true : false));
8✔
543
                }
544
                if (!p.g.quiet)
10✔
545
                {
546
                        cout << "Done." << endl;
10✔
547
                        cout.flush();
10✔
548
                }
549
                *imp_file << "Done." << endl;                
10✔
550
        }
551

552
        // DNA file format
553
        if (p.i.export_dna_files && (stnCount > 0 || msrCount > 0)) 
12✔
554
        {
555
                // Separate output files (default)
556
                if (!p.g.quiet)
7✔
557
                {
558
                        cout << "+ Exporting stations and measurements to " << leafStr<string>(p.i.dna_stnfile) << " and " << leafStr<string>(p.i.dna_msrfile) << "... ";
28✔
559
                        cout.flush();
7✔
560
                }
561
                *imp_file << "+ Exporting stations and measurements to " << leafStr<string>(p.i.dna_msrfile) << " and " << leafStr<string>(p.i.dna_msrfile) << "... ";
28✔
562
                parserDynaML->SerialiseDNA(
7✔
563
                        vstationsTotal, vmeasurementsTotal,
564
                        p.i.dna_stnfile, p.i.dna_msrfile, p, vinput_file_meta, (p.i.flag_unused_stn ? true : false));
7✔
565
                if (!p.g.quiet)
7✔
566
                        cout << "Done." << endl;
7✔
567
                *imp_file << "Done." << endl;
7✔
568

569
        }
570

571
        if (displayEpsgWarning)
12✔
572
        {
573
                cout << ssEpsgWarning.str() << endl;
3✔
574
                *imp_file << ssEpsgWarning.str() << endl;
3✔
575
                cout.flush();
3✔
576
        }
577
}
12✔
578

579
int ImportSegmentedBlock(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements, 
×
580
                StnTally* parsestnTally, MsrTally* parsemsrTally, project_settings& p)
581
{        
582
        // Form default seg file path
583
        bool userSuppliedSegFile(false);
×
584

585
        // Has the user provided a segmentation file?
586
        if (!p.i.seg_file.empty())
×
587
                userSuppliedSegFile = true;
588
        else
589
                p.i.seg_file = formPath<string>(p.g.input_folder, p.g.network_name, "seg");
×
590

591
        if (!exists(p.i.seg_file))
×
592
        {
593
                cout << endl << "- Error: The required segmentation file does not exist:" << endl <<  
×
594
                        "         " << p.i.seg_file << endl << endl <<
×
595
                        "  Run  'segment " << p.g.network_name << "' to create a segmentation file" << endl << endl;
×
596
                return EXIT_FAILURE;
×
597
        }
598

599
        if (!exists(p.i.bst_file))
×
600
        {
601
                cout << endl << "- Error: The required binary station file does not exist:" << endl << 
×
602
                        "         " << p.i.bst_file << endl << endl;
×
603
                return EXIT_FAILURE;
×
604
        }
605

606
        if (!exists(p.i.bms_file))
×
607
        {
608
                cout << endl << "- Error: The required binary measurement file does not exist:" << endl << 
×
609
                        "         " << p.i.bms_file << endl << endl;
×
610
                return EXIT_FAILURE;
×
611
        }
612

613
        // If the user has not provided a seg file, check the meta of the default file
614
        if (!userSuppliedSegFile)
×
615
        {
616
                if (last_write_time(p.i.seg_file) < last_write_time(p.i.bst_file) ||
×
617
                        last_write_time(p.i.seg_file) < last_write_time(p.i.bms_file))
×
618
                {                        
619
                        // Has import been run after the segmentation file was created?
620
                        binary_file_meta_t bst_meta, bms_meta;
×
621
                        dna_io_bst bst;
×
622
                        dna_io_bms bms;
×
623
                        bst.load_bst_file_meta(p.i.bst_file, bst_meta);
×
624
                        bms.load_bms_file_meta(p.i.bms_file, bms_meta);
×
625

626
                        bool bst_meta_import(iequals(bst_meta.modifiedBy, __import_app_name__) ||
×
627
                                iequals(bst_meta.modifiedBy, __import_dll_name__));
×
628
                        bool bms_meta_import(iequals(bms_meta.modifiedBy, __import_app_name__) ||
×
629
                                iequals(bms_meta.modifiedBy, __import_dll_name__));
×
630

631
                        if ((bst_meta_import && (last_write_time(p.i.seg_file) < last_write_time(p.i.bst_file))) || 
×
632
                                (bms_meta_import && (last_write_time(p.i.seg_file) < last_write_time(p.i.bms_file))))
×
633
                        {
634

635
                                cout << endl << endl << 
×
636
                                        "- Error: The raw stations and measurements have been imported after" << endl <<
×
637
                                        "  the segmentation file was created:" << endl;
×
638

639
                                time_t t_bst(last_write_time(p.i.bst_file)), t_bms(last_write_time(p.i.bms_file));
×
640
                                time_t t_seg(last_write_time(p.i.seg_file));
×
641

642
                                cout << "   " << leafStr<string>(p.i.bst_file) << "  last modified on  " << ctime(&t_bst);
×
643
                                cout << "   " << leafStr<string>(p.i.bms_file) << "  last modified on  " << ctime(&t_bms) << endl;
×
644
                                cout << "   " << leafStr<string>(p.i.seg_file) << "  created on  " << ctime(&t_seg) << endl;
×
645
                                cout << "  Run 'segment " << p.g.network_name << " [options]' to re-create the segmentation file, or re-run" << endl << 
×
646
                                        "  the import using the " << SEG_FILE << " option if this segmentation file must\n  be used." << endl << endl;
×
647
                                return EXIT_FAILURE;
×
648
                        }
649
                }
×
650
        }
651

652
        // Import stations and measurements from a particular block
653
        if (!p.g.quiet)
×
654
                cout << endl << "+ Importing stations and measurements from block " << p.i.import_block_number << " of\n  " << p.i.seg_file << "... ";
×
655
        parserDynaML.ImportStnsMsrsFromBlock(vStations, vMeasurements, p);
×
656
        *parsestnTally += parserDynaML.GetStnTally();
×
657
        *parsemsrTally += parserDynaML.GetMsrTally();
×
658
        if (!p.g.quiet)
×
659
                cout << "Done. " << endl;
×
660

661
        // Restore seg_file to null
662
        if (!userSuppliedSegFile)
×
663
                p.i.seg_file = "";
×
664

665
        return EXIT_SUCCESS;
666
}
667

668
int ImportDataFiles(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements,
57✔
669
                vdnaStnPtr* vstationsTotal, vdnaMsrPtr* vmeasurementsTotal,
670
                std::ofstream* imp_file, vifm_t* vinput_file_meta, StnTally* parsestnTally, MsrTally* parsemsrTally, 
671
                UINT32& errorCount, project_settings& p)
672
{
673
        // For consideration:  
674
        //        - All input files could be read concurrently using multi-thread for faster input
675
        //        - The number of files that can be processed concurrently should be restricted to
676
        //          the number of available cores
677
        //        - If multi-threading is to be used, then the progress thread will need to be redesigned.
678
        //          Currently, the progress of each file (as a percentage) is written to cout as each file
679
        //          is processed. If files are processed concurrently, progress reporting will need to be
680
        //    redesigned if multiple progress threads are writing to cout.
681
        //        - There is significant gain in using multi-thread.
682
        //        - The catch will be the need to carefully design one progress thread that captures progress
683
        //          of all other "read" threads (rather than one progress for each), and somehow write to 
684
        //          cout the respective progress.  For example, loading four files could be displayed as 
685
        //          follows:
686
        //
687
        //          + Parsing file1.xml (32%), file2.xml (16%), file3.xml (86%), file4.xml (56%)
688
        //            Done: Loaded 190 stations from file3.xml in 00.032s
689
        //          + Parsing file1.xml (72%), file2.xml (48%), file4.xml (91%)
690
        //            Done: Loaded 236 stations from file4.xml in 00.050s
691
        //          + Parsing file1.xml (87%), file2.xml (76%)
692
        //            Done: Loaded 1596 measurements from file1.xml in 01.380s
693
        //            Done: Loaded 3142 measurements from file2.xml in 02.034s
694
        //
695
        UINT32 stnCount(0), msrCount(0), clusterID(0);
57✔
696
        
697
        // obtain the project reference frame
698
        string epsgCode(epsgStringFromName<string>(p.i.reference_frame));
57✔
699
        
700
        size_t pos = string::npos;
57✔
701
        size_t strlen_arg = 0;
57✔
702
        for_each(p.i.input_files.begin(), p.i.input_files.end(),
57✔
703
                [&strlen_arg](string& file) {
196✔
704
                        if (leafStr<string>(file).length() > strlen_arg)
129✔
705
                                strlen_arg = leafStr<string>(file).length();
67✔
706
        });
129✔
707

708
        strlen_arg += (6 + PROGRESS_PERCENT_04);
57✔
709

710
        size_t i, nfiles(p.i.input_files.size());                // for each file...
57✔
711
        string input_file, ss, status_msg;
57✔
712
        vstring input_files;
57✔
713
        ostringstream ss_time, ss_msg;
57✔
714
        input_file_meta_t input_file_meta;
57✔
715
        milliseconds elapsed_time(milliseconds(0));
57✔
716
        ptime pt;
57✔
717

718
        if (!p.g.quiet)
57✔
719
                cout << "+ Parsing: " << endl;
56✔
720
        *imp_file << "+ Parsing " << endl;
57✔
721

722
        for (i=0; i<nfiles; i++)
180✔
723
        {
724
                stnCount = msrCount = 0;
127✔
725
                input_file = p.i.input_files.at(i);
127✔
726
                if (!exists(input_file))
127✔
727
                {
728
                        input_file = formPath<string>(p.g.input_folder, input_file);
4✔
729
                        if (!exists(input_file))
4✔
730
                        {        
731
                                cout << "- Error:  " << input_file << " does not exist" << endl;
4✔
732
                                return EXIT_FAILURE;
4✔
733
                        }
734
                }
735
                        
736
                input_files.push_back(input_file);
123✔
737
                ss = leafStr<string>(p.i.input_files.at(i)) + "... ";
123✔
738
                if (!p.g.quiet)
123✔
739
                        cout << "  " << setw(strlen_arg) << left << ss;
121✔
740
                *imp_file << "  " << setw(strlen_arg) << left << ss;
123✔
741

742
                running = true;
123✔
743
                thread_group ui_interop_threads;
123✔
744
                if (!p.g.quiet)
123✔
745
                        ui_interop_threads.create_thread(dna_import_progress_thread(&parserDynaML, &p));
121✔
746
                ui_interop_threads.create_thread(dna_import_thread(&parserDynaML, &p, input_file,
123✔
747
                        vStations, &stnCount, vMeasurements, &msrCount,
748
                        &clusterID, &input_file_meta, &status_msg,
749
                        &elapsed_time));
750
                ui_interop_threads.join_all();
123✔
751

752
                switch (parserDynaML.GetStatus())
123✔
753
                {
754
                case PARSE_EXCEPTION_RAISED:
×
755
                        *imp_file << endl << status_msg;
×
756
                        running = false;
×
757
                        return EXIT_FAILURE;
×
758
                        break;
×
759
                case PARSE_UNRECOGNISED_FILE:
×
760
                        *imp_file << status_msg << endl;
×
761
                        errorCount++;
×
762
                        continue;
×
763
                case PARSE_SUCCESS:
123✔
764
                        running = false;
123✔
765
                        break;
123✔
766
                default:
×
767
                        errorCount++;
×
768
                        cout << endl;
×
769
                        continue;
×
770
                }
771

772
                vinput_file_meta->push_back(input_file_meta);
123✔
773

774
                ss_time.str("");
246✔
775

776
                if (stnCount > 0 || msrCount > 0) // stations or measurements only
123✔
777
                {                        
778
                        ss_time << "  Done. Loaded ";
121✔
779
                        if (stnCount)
121✔
780
                                ss_time << stnCount << " stations";
62✔
781
                        if (stnCount && msrCount)
121✔
782
                                ss_time << " and ";
9✔
783
                        if (msrCount)
121✔
784
                                ss_time << msrCount << " measurements";
68✔
785
                        ss_time << " in ";
121✔
786
                                
787
                        pt = ptime(gregorian::day_clock::local_day(), elapsed_time);
121✔
788
                        if (elapsed_time < seconds(3))
121✔
789
                        {
790
                                time_facet* facet(new time_facet("%s"));
121✔
791
                                ss_time.imbue(locale(ss_time.getloc(), facet));
121✔
792
                                ss_time << pt << "s";                        
121✔
793
                        }
794
                        else if (elapsed_time < seconds(61))
×
795
                        {                
796
                                time_facet* facet(new time_facet("%S"));
×
797
                                ss_time.imbue(locale(ss_time.getloc(), facet));
×
798
                                ss_time << pt << "s";
×
799
                        }
800
                        else
801
                                ss_time << elapsed_time;
×
802

803
                        string time_message = ss_time.str();
121✔
804
                        while ((pos = time_message.find("0s")) != string::npos)
563✔
805
                                time_message = time_message.substr(0, pos) + "s";
442✔
806

807
                        if ((pos = time_message.find(" 00.")) != string::npos)
121✔
808
                                time_message = time_message.replace(pos, 4, " 0.");
121✔
809
                        if ((pos = time_message.find(" 0.s")) != string::npos)
121✔
810
                                time_message = time_message.replace(pos, 4, " 0s");
25✔
811

812
                        if (!p.g.quiet)
121✔
813
                        {
814
                                if (isatty(fileno(stdout)))
119✔
815
                                        cout << PROGRESS_BACKSPACE_04;
×
816
                                cout << time_message << endl;
119✔
817
                        }
818
                        *imp_file << time_message << endl;
121✔
819

820
                        // Produce a warning if the input file's default reference frame
821
                        // is different to the project reference frame
822
                        string inputFileEpsg;
121✔
823
                        try {
121✔
824
                                inputFileEpsg = datumFromEpsgString<string>(input_file_meta.epsgCode);
121✔
825
                        }
826
                        catch (...) {
×
827
                                inputFileEpsg = epsgCode;
×
828
                        }
×
829

830
                        if (!iequals(epsgCode, input_file_meta.epsgCode))
121✔
831
                        {
832
                                stringstream ssEpsgWarning;
53✔
833
                                
834
                                ssEpsgWarning << "- Warning: Input file reference frame (" << inputFileEpsg <<
53✔
835
                                        ") does not match the " << endl << "  default reference frame.";
53✔
836
                                if (!p.g.quiet)
53✔
837
                                        cout << ssEpsgWarning.str() << endl;
51✔
838
                                *imp_file << ssEpsgWarning.str() << endl;
53✔
839
                        }
53✔
840
                }
121✔
841

842
                // Handle discontinuities for non-sinex files, if and only if a discontinuity file has been loaded.
843
                // NOTE: If a station is marked as a discontinuity site, and that same station is in the renaming
844
                // file, station renaming for that site will not occur.  This is because the site name will be changed
845
                // to <site-name>_yyyymmdd.
846
                // If renaming must still occur, then it might be possible to rename using the first part of the name.
847
                
848

849
                if (stnCount > 0) // stations only
123✔
850
                {
851
                        //vstationsTotal.reserve(vstationsTotal.size() + stnCount);
852
                        // combine stations and station tally
853
                        vstationsTotal->insert(vstationsTotal->end(), vStations->begin(), vStations->end());
62✔
854
                        *parsestnTally += parserDynaML.GetStnTally();
62✔
855
                        vStations->clear();
62✔
856
                }
857
                if (msrCount > 0) // measurements only
123✔
858
                {                
859
                        //vmeasurementsTotal.reserve(vmeasurementsTotal.size() + msrCount);
860
                        // combine measurements
861
                        vmeasurementsTotal->insert(vmeasurementsTotal->end(), vMeasurements->begin(), vMeasurements->end());
68✔
862
                        *parsemsrTally += parserDynaML.GetMsrTally();
68✔
863
                        vMeasurements->clear();
68✔
864
                }
865
        }
123✔
866

867
        if (errorCount == nfiles || (vstationsTotal->empty() && vmeasurementsTotal->empty()))
53✔
868
                return EXIT_FAILURE;
869

870
        running = false;
52✔
871
        return EXIT_SUCCESS;
52✔
872
}
57✔
873

874
int main(int argc, char* argv[])
73✔
875
{
876
        // create banner message
877
        string cmd_line_banner;
73✔
878
        fileproc_help_header(&cmd_line_banner);
73✔
879

880
        project_settings p;
73✔
881

882
        variables_map vm;
73✔
883
        positional_options_description positional_options;
73✔
884

885
        options_description standard_options("+ " + string(ALL_MODULE_STDOPT), PROGRAM_OPTIONS_LINE_LENGTH);
146✔
886
        options_description ref_frame_options("+ " + string(IMPORT_MODULE_FRAME), PROGRAM_OPTIONS_LINE_LENGTH);
146✔
887
        options_description data_screening_options("+ " + string(IMPORT_MODULE_SCREEN), PROGRAM_OPTIONS_LINE_LENGTH);
146✔
888
        options_description gnss_scaling_options("+ " + string(IMPORT_MODULE_GNSS_VAR), PROGRAM_OPTIONS_LINE_LENGTH);
146✔
889
        options_description simulation_options("+ " + string(IMPORT_MODULE_SIMULATE), PROGRAM_OPTIONS_LINE_LENGTH);
146✔
890
        options_description output_options("+ " + string(ALL_MODULE_OUTPUT), PROGRAM_OPTIONS_LINE_LENGTH);
146✔
891
        options_description export_options("+ " + string(ALL_MODULE_EXPORT), PROGRAM_OPTIONS_LINE_LENGTH);
146✔
892
        options_description generic_options("+ " + string(ALL_MODULE_GENERIC), PROGRAM_OPTIONS_LINE_LENGTH);
146✔
893

894
        string cmd_line_usage("+ ");
73✔
895
        cmd_line_usage.append(__BINARY_NAME__).append(" usage:  ").append(__BINARY_NAME__).append(" [options] [files]...");
73✔
896
        options_description allowable_options(cmd_line_usage, PROGRAM_OPTIONS_LINE_LENGTH);
73✔
897

898
        try {
73✔
899
                // Declare a group of options that will be 
900
                // allowed only on command line                
901
                standard_options.add_options()
73✔
902
                        (PROJECT_FILE_P, value<string>(&p.g.project_file),
73✔
903
                                "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.")
904
                        (NETWORK_NAME_N, value<string>(&p.g.network_name), 
73✔
905
                                "Network name. User defined name for all input and output files. Default is \"network#\", where # is incremented until the first available network is reached.")
906
                        (IMPORT_FILE_F, value< vstring >(&p.i.input_files), 
73✔
907
                                "Station and measurement input file(s). Switch is not required.")
908
                        (IMPORT_GEO_FILE_G, value<string>(&p.i.geo_file),
73✔
909
                                "Import DNA geoid file.")
910
                        (INPUT_FOLDER_I, value<string>(&p.g.input_folder),
73✔
911
                                "Path containing all input files.")
912
                        (OUTPUT_FOLDER_O, value<string>(&p.g.output_folder),                // default is ./,
73✔
913
                                "Path for all output files.")
914
                        (BIN_STN_FILE_S, value<string>(&p.i.bst_file),
73✔
915
                                "Binary station output file name. Overrides network name.")
916
                        (BIN_MSR_FILE_M, value<string>(&p.i.bms_file),
73✔
917
                                "Binary measurement output file name. Overrides network name.")
918
                        ;
919

920
                ref_frame_options.add_options()
73✔
921
                        (REFERENCE_FRAME_R, value<string>(&p.i.reference_frame), 
73✔
922
                        (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 ") +
146✔
923
                                p.i.reference_frame + ".").c_str())
146✔
924
                        (OVERRIDE_INPUT_FRAME,
73✔
925
                                "Override the reference frame specified for each measurement in input files.")
926
                        ;
927

928
                data_screening_options.add_options()
73✔
929
                        (BOUNDING_BOX, value<string>(&p.i.bounding_box),
73✔
930
                                "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.")
931
                        (GET_MSRS_TRANSCENDING_BOX,
73✔
932
                                "Include measurements which transcend bounding box, including associated stations.")
933
                        (INCLUDE_STN_ASSOC_MSRS, value<string>(&p.i.stn_associated_msr_include),
73✔
934
                                "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.")
935
                        (EXCLUDE_STN_ASSOC_MSRS, value<string>(&p.i.stn_associated_msr_exclude),
73✔
936
                                "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.")
937
                        (SPLIT_CLUSTERS,
73✔
938
                                "Allow bounding-box or get-stns-and-assoc-msrs to split GNSS point and baseline cluster measurements.")
939
                        (IMPORT_SEG_BLOCK, value<UINT32>(&p.i.import_block_number),
73✔
940
                                "Extract stations and measurements from this block.")
941
                        (SEG_FILE, value<string>(&p.i.seg_file),
73✔
942
                                "Network segmentation input file. Filename overrides network name.")
943
                        (PREFER_X_MSR_AS_G,
73✔
944
                                "Import single baseline cluster measurements (X) as single baselines (G).")
945
                        (INCLUDE_MSRS, value<string>(&p.i.include_msrs),
73✔
946
                                "Import the specified measurement types. arg is a non-delimited string of measurement types (eg \"GXY\").")
947
                        (EXCLUDE_MSRS, value<string>(&p.i.exclude_msrs),
73✔
948
                                "Exclude the specified measurement types. arg is a non-delimited string of measurement typs (eg \"IJK\").")
949
                        (STATION_RENAMING_FILE, value<string>(&p.i.stn_renamingfile),
73✔
950
                                "Station renaming file")
951
                        (STATION_DISCONTINUITY_FILE, value<string>(&p.i.stn_discontinuityfile),
73✔
952
                                "Station discontinuity file.  Applies discontinuity dates to station names in station and measurement files.")
953
                        (TEST_NEARBY_STNS,
73✔
954
                                "Search for nearby stations.")
955
                        (TEST_NEARBY_STN_DIST, value<double>(&p.i.search_stn_radius),
73✔
956
                                (string("Specify the radius of the circle within which to search for nearby stations.  Default is ")+
146✔
957
                                StringFromT(STN_SEARCH_RADIUS)+string("m")).c_str())
292✔
958
                        (TEST_SIMILAR_GNSS_MSRS,
73✔
959
                                "Search and provide warnings for GNSS baselines (G) and baseline clusters (X) which appear to have been derived from the same source data.")
960
                        (TEST_SIMILAR_MSRS,
73✔
961
                                "Search and provide warnings for similar measurements.")
962
                        (IGNORE_SIMILAR_MSRS,
73✔
963
                                "Ignore similar measurements.")
964
                        (REMOVE_IGNORED_MSRS,
73✔
965
                                "Remove ignored measurements.")
966
                        (FLAG_UNUSED_STNS,
73✔
967
                                "Mark unused stations in binary file.  Stations marked will be excluded from any further processing.")
968
                        (TEST_INTEGRITY,
73✔
969
                                "Test the integrity of the association lists and binary files.")
970
                        ;
971

972
                gnss_scaling_options.add_options()
73✔
973
                        (VSCALE, value<double>(&p.i.vscale),
73✔
974
                                (string("Global variance (v) matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
146✔
975
                                StringFromT(p.i.vscale)+string(".")).c_str())
292✔
976
                        (PSCALE, value<double>(&p.i.pscale),
73✔
977
                                (string("Latitude (p=phi) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
146✔
978
                                StringFromT(p.i.pscale)+string(".")).c_str())
292✔
979
                        (LSCALE, value<double>(&p.i.lscale),
73✔
980
                                (string("Longitude (l=lambda) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
146✔
981
                                StringFromT(p.i.lscale)+string(".")).c_str())
292✔
982
                        (HSCALE, value<double>(&p.i.hscale),
73✔
983
                                (string("Height (h) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
146✔
984
                                StringFromT(p.i.hscale)+string(".")).c_str())
292✔
985
                        (SCALAR_FILE, value<string>(&p.i.scalar_file),
73✔
986
                                "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.")
987
                        ;
988

989
                output_options.add_options()
73✔
990
                        (OUTPUT_MSR_TO_STN,
73✔
991
                                "Output summary of measurements connected to each station.")
992
                        (OUTPUT_MSR_TO_STN_SORTBY, value<UINT16>(&p.o._sort_msr_to_stn),
73✔
993
                                string("Sort order for measurement to stations summary.\n  " +
292✔
994
                                        StringFromT(orig_stn_sort_ui) + ": Original station order (default)\n  " +
292✔
995
                                        StringFromT(meas_stn_sort_ui) + ": Measurement count").c_str())
73✔
996
                        ;
997

998
                export_options.add_options()
73✔
999
                        (EXPORT_XML_FILES,
73✔
1000
                                "Export stations and measurements to DynaML (DynAdjust XML) format.")
1001
                        (EXPORT_SINGLE_XML_FILE,
73✔
1002
                                "Create a single DynaML file for stations and measurements.")
1003
                        // Nice, but somewhat redundant functionality that offers no
1004
                        // benefit to the user
1005
                        //(EXPORT_FROM_BINARY,
1006
                        //        "Create DynaML output file using binary files. Default option uses internal memory.")
1007
                        (EXPORT_DNA_FILES,
73✔
1008
                                "Export stations and measurements to DNA STN and MSR format.")
1009
                        (EXPORT_ASL_FILE,
73✔
1010
                                "Export the ASL file as raw text.")
1011
                        (EXPORT_AML_FILE,
73✔
1012
                                "Export the AML file as raw text.")
1013
                        (EXPORT_MAP_FILE,
73✔
1014
                                "Export the MAP file as raw text.")
1015
                        (EXPORT_DISCONT_FILE,
73✔
1016
                                "Export discontinuity information as raw text.")
1017
                        ;
1018

1019
                simulation_options.add_options()
73✔
1020
                        (SIMULATE_MSR_FILE,
73✔
1021
                                "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.")
1022
                        ;
1023

1024
                generic_options.add_options()
73✔
1025
                        (VERBOSE, value<UINT16>(&p.g.verbose),
73✔
1026
                                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())
73✔
1027
                        (QUIET,
73✔
1028
                                string("Suppresses all explanation of what ").append(__BINARY_NAME__).append(" is doing unless an error occurs.").c_str())
146✔
1029
                        (VERSION_V, "Display the current program version.")
73✔
1030
                        (HELP_H, "Show this help message.")
73✔
1031
                        (HELP_MODULE, value<string>(),
73✔
1032
                                "Provide help for a specific help category.")
1033
                        ;
1034

1035
                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);
73✔
1036

1037
                // add "positional options" to handle command line tokens which have no option name
1038
                positional_options.add(IMPORT_FILE, -1);
73✔
1039
                
1040
                command_line_parser parser(argc, argv);
73✔
1041
                store(parser.options(allowable_options).positional(positional_options).run(), vm);
73✔
1042
                notify(vm);
72✔
1043
        }
1✔
1044
        catch(const std::exception& e) 
1✔
1045
        {
1046
                cout << "- Error: " << e.what() << endl;
1✔
1047
                cout << cmd_line_banner << allowable_options << endl;
1✔
1048
                return EXIT_FAILURE;
1✔
1049
        }
1✔
1050
        catch (...) 
×
1051
        {
1052
                cout << "+ Exception of unknown type!\n";
×
1053
                return EXIT_FAILURE;
×
1054
        }
×
1055

1056
        if (argc < 2)
72✔
1057
        {
1058
                cout << endl << "- Nothing to do - no options provided. " << endl << endl;  
1✔
1059
                cout << cmd_line_banner << allowable_options << endl;
1✔
1060
                return EXIT_FAILURE;
1061
        }
1062

1063
        if (vm.count(VERSION))
71✔
1064
        {
1065
                cout << cmd_line_banner << endl;
1✔
1066
                return EXIT_SUCCESS;
1067
        }
1068

1069
        if (vm.count(HELP))
70✔
1070
        {
1071
                cout << cmd_line_banner << allowable_options << endl;
1✔
1072
                return EXIT_SUCCESS;
1073
        }
1074

1075
        if (vm.count(HELP_MODULE)) 
69✔
1076
        {
1077
                cout << cmd_line_banner;
9✔
1078
                string original_text = vm[HELP_MODULE].as<string>();
18✔
1079
                string help_text = str_upper<string>(original_text);
9✔
1080
                
1081
                if (str_upper<string, char>(ALL_MODULE_STDOPT).find(help_text) != string::npos) {
18✔
1082
                        cout << standard_options << endl;
1✔
1083
                }
1084
                else if (str_upper<string, char>(IMPORT_MODULE_FRAME).find(help_text) != string::npos) {
16✔
1085
                        cout << ref_frame_options << endl;
1✔
1086
                } 
1087
                else if (str_upper<string, char>(IMPORT_MODULE_SCREEN).find(help_text) != string::npos) {
14✔
1088
                        cout << data_screening_options << endl;
1✔
1089
                } 
1090
                else if (str_upper<string, char>(IMPORT_MODULE_GNSS_VAR).find(help_text) != string::npos) {
12✔
1091
                        cout << gnss_scaling_options << endl;
1✔
1092
                } 
1093
                else if (str_upper<string, char>(IMPORT_MODULE_SIMULATE).find(help_text) != string::npos) {
10✔
1094
                        cout << simulation_options << endl;
1✔
1095
                } 
1096
                else if (str_upper<string, char>(ALL_MODULE_OUTPUT).find(help_text) != string::npos) {
8✔
1097
                        cout << output_options << endl;
1✔
1098
                } 
1099
                else if (str_upper<string, char>(ALL_MODULE_EXPORT).find(help_text) != string::npos) {
6✔
1100
                        cout << export_options << endl;
1✔
1101
                } 
1102
                else if (str_upper<string, char>(ALL_MODULE_GENERIC).find(help_text) != string::npos) {
4✔
1103
                        cout << generic_options << endl;
1✔
1104
                } 
1105
                else {
1106
                        cout << endl << "- Error: Help module '" <<
1✔
1107
                                original_text << "' is not in the list of options." << endl;
9✔
1108
                        return EXIT_FAILURE;
1109
                }
1110

1111
                return EXIT_SUCCESS;
8✔
1112
        }
9✔
1113

1114
        bool userSuppliedSegFile(false);
60✔
1115
        if (!p.i.seg_file.empty())
60✔
1116
                userSuppliedSegFile = true;
×
1117
        bool userSuppliedBstFile(false);
60✔
1118
        if (!p.i.bst_file.empty())
60✔
1119
                userSuppliedBstFile = true;
×
1120
        bool userSuppliedBmsFile(false);
60✔
1121
        if (!p.i.bms_file.empty())
60✔
1122
                userSuppliedBmsFile = true;
×
1123

1124
        if (ParseCommandLineOptions(argc, argv, vm, p) != EXIT_SUCCESS)
60✔
1125
                return EXIT_FAILURE;
1126

1127
        UINT32 errorCount(0);
58✔
1128
        bool stn_map_created = false, measurements_mapped = false;
58✔
1129

1130
        string input_file;
58✔
1131
        vstring input_files;
58✔
1132
        string status_msg;
58✔
1133

1134
        std::ofstream imp_file;
58✔
1135
        try {
58✔
1136
                // Create import log file.  Throws runtime_error on failure.
1137
                file_opener(imp_file, p.i.imp_file);
58✔
1138
        }
1139
        catch (const runtime_error& e) {
×
1140
                stringstream ss;
×
1141
                ss << "- Error: Could not open " << p.i.imp_file << ". \n  Check that the file exists and that the file is not already opened." << endl;
×
1142
                cout << ss.str() << e.what() << endl;
×
1143
                return EXIT_FAILURE;
×
1144
        }
×
1145

1146
        vdnaStnPtr vStations, vstationsTotal;
58✔
1147
        vdnaMsrPtr vMeasurements, vmeasurementsTotal;
58✔
1148
        vdnaMsrPtr::iterator _itm;
58✔
1149
        vASLPtr associatedSL;
58✔
1150
        vUINT32 associatedML;
58✔
1151
        v_string_uint32_pair vStnsMap_sortName;        // Station Name Map sorted on name (string)
58✔
1152
        
1153
        vstationsTotal.clear();
58✔
1154
        vmeasurementsTotal.clear();
58✔
1155

1156
        if (vm.count(QUIET))
58✔
1157
                p.g.quiet = 1;
1✔
1158
        
1159
        if (!p.g.quiet)
58✔
1160
        {
1161
                cout << endl << cmd_line_banner;
57✔
1162

1163
                cout << "+ Options:" << endl; 
57✔
1164
                cout << setw(PRINT_VAR_PAD) << left << "  Network name: " <<  p.g.network_name << endl;
57✔
1165
                cout << setw(PRINT_VAR_PAD) << left << "  Input folder: " << p.g.input_folder << endl;
57✔
1166
                cout << setw(PRINT_VAR_PAD) << left << "  Output folder: " << p.g.output_folder << endl;
57✔
1167
                cout << setw(PRINT_VAR_PAD) << left << "  Associated station file: " << p.i.asl_file << endl;
57✔
1168
                cout << setw(PRINT_VAR_PAD) << left << "  Associated measurement file: " << p.i.aml_file << endl;
57✔
1169
                cout << setw(PRINT_VAR_PAD) << left << "  Binary station output file: " << p.i.bst_file << endl;
57✔
1170
                cout << setw(PRINT_VAR_PAD) << left << "  Binary measurement output file: " << p.i.bms_file << endl;
57✔
1171
                
1172
                if (!p.i.reference_frame.empty())
57✔
1173
                        cout << setw(PRINT_VAR_PAD) << left << "  Default reference frame:" << p.i.reference_frame << endl;
57✔
1174
        
1175
                if (p.i.override_input_rfame)
57✔
1176
                        cout << setw(PRINT_VAR_PAD) << left << "  Override input file ref frame:" << yesno_string(p.i.override_input_rfame) << endl;
8✔
1177

1178
                if (p.i.export_dynaml)
57✔
1179
                {
1180
                        if (p.i.export_single_xml_file)
11✔
1181
                                cout << setw(PRINT_VAR_PAD) << left << "  DynaML output file: " << p.i.xml_outfile << endl;
2✔
1182
                        else
1183
                        {
1184
                                cout << setw(PRINT_VAR_PAD) << left << "  DynaML station file: " << p.i.xml_stnfile << endl;
9✔
1185
                                cout << setw(PRINT_VAR_PAD) << left << "  DynaML measurement file: " << p.i.xml_msrfile << endl;
9✔
1186
                        }                                
1187
                }
1188
                if (p.i.export_dna_files)
57✔
1189
                {
1190
                        cout << setw(PRINT_VAR_PAD) << left << "  DNA station file: " << p.i.dna_stnfile << endl;
9✔
1191
                        cout << setw(PRINT_VAR_PAD) << left << "  DNA measurement file: " << p.i.dna_msrfile << endl;
9✔
1192
                }
1193

1194
                if (p.i.simulate_measurements)
57✔
1195
                {
1196
                        cout << setw(PRINT_VAR_PAD) << left << "  DNA simulated msr file: " << p.i.simulate_msrfile << endl;
1✔
1197
                }
1198
                
1199
                if (!p.i.bounding_box.empty())
57✔
1200
                {
1201
                        cout << setw(PRINT_VAR_PAD) << left << "  Bounding box: " << p.i.bounding_box << endl;
1✔
1202
                        if (p.i.split_clusters)
1✔
1203
                                cout << setw(PRINT_VAR_PAD) << left << "  Split GNSS clusters: " << (p.i.split_clusters ? "Yes" : "No") << endl;
1✔
1204
                }
1205
                else
1206
                {
1207
                        if (!p.i.stn_associated_msr_include.empty())
56✔
1208
                                cout << setw(PRINT_VAR_PAD) << left << "  Stations to include: " << p.i.stn_associated_msr_include << endl;
5✔
1209
                        if (!p.i.stn_associated_msr_exclude.empty())
56✔
1210
                                cout << setw(PRINT_VAR_PAD) << left << "  Stations to exclude: " << p.i.stn_associated_msr_exclude << endl;
1✔
1211
                        
1212
                        if (p.i.split_clusters)
56✔
1213
                                cout << setw(PRINT_VAR_PAD) << left << "  Split GNSS clusters: " << (p.i.split_clusters ? "Yes" : "No") << endl;
4✔
1214
                }
1215
                
1216
                if (p.i.import_block)
57✔
1217
                {
1218
                        cout << setw(PRINT_VAR_PAD) << left << "  Segmentation file: " << p.i.seg_file << endl;
×
1219
                        cout << setw(PRINT_VAR_PAD) << left << "  Import stns & msrs from block: " << p.i.import_block_number << endl;
×
1220
                }
1221

1222
                if (!p.i.scalar_file.empty())
57✔
1223
                        cout << setw(PRINT_VAR_PAD) << left << "  GNSS baseline scalar file: " << p.i.scalar_file << endl;
1✔
1224
                
1225
                cout << endl;
57✔
1226
        }
1227

1228
        PrintOutputFileHeaderInfo(&imp_file, p.i.imp_file, &p, "DYNADJUST IMPORT LOG FILE");
58✔
1229

1230
        dna_import parserDynaML;
58✔
1231
        MsrTally parsemsrTally;
58✔
1232
        StnTally parsestnTally;
58✔
1233

1234
        CDnaProjection projection(UTM);
58✔
1235

1236
        vifm_t vinput_file_meta;
58✔
1237

1238
        // First things first!
1239
        // Set the 'default' reference frame for the binary station and measurement files
1240
        try {
58✔
1241
                // Initialise the 'default' datum for the project.
1242
                parserDynaML.InitialiseDatum(p.i.reference_frame);
58✔
1243
        }
1244
        catch (const XMLInteropException& e) {
1✔
1245
                stringstream ss;
1✔
1246
                ss << "- Error: ";
1✔
1247
                cout << ss.str() << e.what() << endl;
1✔
1248
                return EXIT_FAILURE;
1✔
1249
        }
1✔
1250

1251
        // obtain the project reference frame
1252
        UINT32 epsgCode(epsgCodeFromName<UINT32>(p.i.reference_frame));
57✔
1253

1254
        // set the default output reference frame and epoch, so that
1255
        // if adjust is called without reftran, it reflects the datum 
1256
        // supplied on import
1257
        p.r.reference_frame = p.i.reference_frame;
57✔
1258
        p.r.epoch = referenceepochFromEpsgCode<UINT32>(epsgCode);
57✔
1259

1260
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////
1261
        // start "total" time
1262
        cpu_timer time;
57✔
1263
        
1264
        
1265
        // Import discontinuity file and apply discontinuities
1266
        // Due to the structure and format of SINEX files, it is essential that
1267
        // discontinuities be parsed prior to reading any SINEX files.
1268
        if (vm.count(STATION_DISCONTINUITY_FILE))
57✔
1269
        {
1270
                p.i.apply_discontinuities = true;
4✔
1271
                
1272
                // Does it exist?
1273
                if (!exists(p.i.stn_discontinuityfile))
4✔
1274
                {
1275
                        path discontPath(p.i.stn_discontinuityfile);
×
1276
                        stringstream ss;
×
1277
                        ss << "- Warning: The station discontinuity file " << discontPath.filename().string() << " does not exist... ignoring discontinuity input." << endl;
×
1278
                        imp_file << endl << ss.str();
×
1279
                }
×
1280
                else
1281
                {
1282
                        if (!p.g.quiet)
4✔
1283
                        {
1284
                                cout << "+ Importing station discontinuities from " << p.i.stn_discontinuityfile << "... ";
4✔
1285
                                cout.flush();
4✔
1286
                        }
1287
                        imp_file << "+ Importing station discontinuities from " << p.i.stn_discontinuityfile << "... ";
4✔
1288

1289
                        parserDynaML.ParseDiscontinuities(p.i.stn_discontinuityfile);
4✔
1290

1291
                        if (!p.g.quiet)
4✔
1292
                                cout << "Done." << endl;
4✔
1293
                        imp_file << "Done." << endl;
4✔
1294
                }
1295

1296
                if (p.i.export_discont_file)
4✔
1297
                {
1298
                        if (!p.g.quiet)
1✔
1299
                        {
1300
                                cout << "+ Exporting discontinuity information to text file... ";
1✔
1301
                                cout.flush();
1✔
1302
                        }
1303
                        imp_file << "+ Exporting discontinuity information to text file... ";
1✔
1304
                        parserDynaML.SerialiseDiscontTextFile(p.i.stn_discontinuityfile);
1✔
1305
                        if (!p.g.quiet)
1✔
1306
                        {
1307
                                cout << "Done." << endl;
1✔
1308
                                cout.flush();
1✔
1309
                        }
1310
                        imp_file << "Done." << endl;
1✔
1311
                }
1312
        }
1313

1314
        // Import network information based on a segmentation block?
1315
        if (p.i.import_block)
57✔
1316
        {
1317
                if (ImportSegmentedBlock(parserDynaML, &vstationsTotal, &vmeasurementsTotal, 
×
1318
                        &parsestnTally, &parsemsrTally, p) != EXIT_SUCCESS)
1319
                        return EXIT_FAILURE;
1320
        }
1321
        // Import data as normal
1322
        else
1323
        {
1324
                // Import all data as-is.
1325
                // All filtering is performed later below
1326
                if (ImportDataFiles(parserDynaML, &vStations, &vMeasurements, &vstationsTotal, &vmeasurementsTotal,
57✔
1327
                        &imp_file, &vinput_file_meta, &parsestnTally, &parsemsrTally, errorCount, p) != EXIT_SUCCESS)
1328
                        return EXIT_FAILURE;
1329
        }        
1330

1331
        if (!p.g.quiet)
52✔
1332
                cout << endl;
51✔
1333

1334
        // Now, set the 'default' epoch in the binary station and measurement files
1335
        try {
52✔
1336
                // Initialise the 'default' datum for the project.
1337
                parserDynaML.UpdateEpoch(&vinput_file_meta);
52✔
1338
        }
1339
        catch (const XMLInteropException& e) {
×
1340
                stringstream ss;
×
1341
                ss << "- Error: ";
×
1342
                cout << ss.str() << e.what() << endl;
×
1343
                return EXIT_FAILURE;
×
1344
        }
×
1345

1346
        // Remove ignored measurements (if supplied)
1347
        if (p.i.remove_ignored_msr)
52✔
1348
        {
1349
                if (!p.g.quiet)
1✔
1350
                {
1351
                        cout << "+ Removing ignored measurements... ";
1✔
1352
                        cout.flush();
1✔
1353
                }
1354
                imp_file << "+ Removing ignored measurements... ";
1✔
1355
                parserDynaML.RemoveIgnoredMeasurements(&vmeasurementsTotal, &parsemsrTally);
1✔
1356
                if (!p.g.quiet)
1✔
1357
                        cout << "Done. " << endl;
1✔
1358
                imp_file << "Done. " << endl;
1✔
1359
        }
1360

1361
        // Strip all measurements except required measurements (if supplied)
1362
        if (!p.i.include_msrs.empty())
52✔
1363
        {
1364
                if (!p.g.quiet)
2✔
1365
                {
1366
                        cout << "+ Stripping all measurements except types " << p.i.include_msrs << "... ";
2✔
1367
                        cout.flush();
2✔
1368
                }
1369
                imp_file << "+ Stripping all measurements except types " << p.i.include_msrs << "... ";
2✔
1370
                parserDynaML.IncludeMeasurementTypes(p.i.include_msrs, &vmeasurementsTotal, &parsemsrTally);
2✔
1371
                if (!p.g.quiet)
2✔
1372
                        cout << "Done. " << endl;
2✔
1373
                imp_file << "Done. " << endl;
2✔
1374
        }
1375
        
1376
        // Strip all unwanted measurements (if supplied)
1377
        if (!p.i.exclude_msrs.empty())
52✔
1378
        {
1379
                if (!p.g.quiet)
2✔
1380
                {
1381
                        cout << "+ Stripping measurement types " << p.i.exclude_msrs << "... ";
2✔
1382
                        cout.flush();
2✔
1383
                }
1384
                imp_file << "+ Stripping measurement types " << p.i.exclude_msrs << "... ";
2✔
1385
                parserDynaML.ExcludeMeasurementTypes(p.i.exclude_msrs, &vmeasurementsTotal, &parsemsrTally);
2✔
1386
                if (!p.g.quiet)
2✔
1387
                        cout << "Done. " << endl;
2✔
1388
                imp_file << "Done. " << endl;
2✔
1389
        }
1390

1391
        // Reduce stations.
1392
        // But, only reduce stations if not importing for a segmentation block
1393
        // The reason stations are not reduced if IMPORT_SEG_BLOCK has been set is
1394
        // because stations in the binary file will have already been reduced
1395
        // on last import!
1396
        if (p.i.import_block == 0 && vstationsTotal.size())
52✔
1397
        {
1398
                // reduce stations (e.g. convert from UTM to LLH)
1399
                try {
52✔
1400
                        if (!p.g.quiet)
52✔
1401
                        {
1402
                                cout << "+ Reducing stations... ";
51✔
1403
                                cout.flush();
51✔
1404
                        }
1405
                        imp_file << "+ Reducing stations... ";
52✔
1406
                        parserDynaML.ReduceStations(&vstationsTotal, projection);
52✔
1407
                        if (!p.g.quiet)
52✔
1408
                                cout << "Done." << endl;
51✔
1409
                        imp_file << "Done." << endl;
52✔
1410
                } 
1411
                catch (const XMLInteropException& e) {
×
1412
                        cout << endl << "- Error: " << e.what() << endl;
×
1413
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1414
                        imp_file.close();
×
1415
                        return EXIT_FAILURE;
×
1416
                }
×
1417
        }
1418

1419
        /////////////////////////////////////////////////////////////////////////
1420
        // Add discontinuity sites to vStations
1421
        //
1422
        // WARNING: If discontinuity sites are present in the renaming file, and
1423
        // the renaming file changes the name from the four-character id in the 
1424
        // discontinuity file to another name, this function call will not work
1425
        // properly. Hence, sites in the discontinuity file must be consistently
1426
        // named in the station and measurement files and not renamed to another
1427
        // name.
1428
        if (p.i.apply_discontinuities && !vstationsTotal.empty())
52✔
1429
                parserDynaML.AddDiscontinuityStations(&vstationsTotal);
4✔
1430

1431
        UINT32 stn;
52✔
1432

1433
        // Extract user-defined stations and all connected measurements
1434
        if (vstationsTotal.size() &&        // cannot be empty
52✔
1435
                (!p.i.stn_associated_msr_include.empty() || !p.i.stn_associated_msr_exclude.empty()))
52✔
1436
        {
1437
                vstring vUnusedStns;
6✔
1438
                bool splitXmsrs(false), splitYmsrs(false);
6✔
1439

1440
                try {
6✔
1441
                        if (!p.g.quiet)
6✔
1442
                        {
1443
                                cout << "+ Extracting stations and associated measurements... ";
6✔
1444
                                cout.flush();
6✔
1445
                        }
1446
                        imp_file << "+ Extracting stations and associated measurements... ";
6✔
1447

1448
                        // this method reforms asl and aml
1449
                        parserDynaML.ExtractStnsAndAssociatedMsrs(p.i.stn_associated_msr_include, p.i.stn_associated_msr_exclude, &vstationsTotal, &vmeasurementsTotal, 
6✔
1450
                                &parsestnTally, &parsemsrTally, &vUnusedStns, p, splitXmsrs, splitYmsrs);
1451
                } 
1452
                catch (const XMLInteropException& e) {
×
1453
                        cout << "- Error: " << e.what() << endl;
×
1454
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1455
                        imp_file.close();
×
1456
                        return EXIT_FAILURE;
×
1457
                }
×
1458

1459
                if (!p.g.quiet)
6✔
1460
                        cout << "Done. " << endl;
6✔
1461
                imp_file << "Done." << endl;
6✔
1462

1463
                //msrCount = vmeasurementsTotal.size();
1464
        }        
6✔
1465

1466
        // Now strip all stations outside the bounding box (if supplied)
1467
        if (vstationsTotal.size() &&        // cannot be empty
52✔
1468
                !p.i.bounding_box.empty())
51✔
1469
        {
1470
                vstring vUnusedStns;
1✔
1471
                bool splitXmsrs(false), splitYmsrs(false);
1✔
1472

1473
                try {
1✔
1474
                        if (!p.g.quiet)
1✔
1475
                        {
1476
                                cout << "+ Stripping stations and measurements outside the bounding box... ";
1✔
1477
                                cout.flush();
1✔
1478
                        }
1479
                        imp_file << "+ Stripping stations and measurements outside the bounding box... ";
1✔
1480
                        parserDynaML.ExcludeAllOutsideBoundingBox(&vstationsTotal, &vmeasurementsTotal, 
1✔
1481
                                &parsestnTally, &parsemsrTally, &vUnusedStns, p, splitXmsrs, splitYmsrs);
1482
                } 
1483
                catch (const XMLInteropException& e) {
×
1484
                        cout << "- Error: " << e.what() << endl;
×
1485
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1486
                        imp_file.close();
×
1487
                        return EXIT_FAILURE;
×
1488
                }
×
1489

1490
                if (!p.g.quiet)
1✔
1491
                        cout << "Done. " << endl;
1✔
1492
                imp_file << "Done." << endl;
1✔
1493

1494
                if (!vUnusedStns.empty())
1✔
1495
                {
1496
                        ostringstream ss_msg;
1✔
1497
                        ss_msg << "  - " << vstationsTotal.size() << (vstationsTotal.size() == 1 ? " station is" : " stations are") << 
1✔
1498
                                " within the bounding box." << endl;
2✔
1499
                        imp_file << ss_msg.str();
1✔
1500
                        if (!p.g.quiet)
1✔
1501
                                cout << ss_msg.str();
1✔
1502
                        ss_msg.str("");
2✔
1503
                        ss_msg << "  - ";
1✔
1504
                        if (vUnusedStns.size() > 1)
1✔
1505
                        {
1506
                                ss_msg << vUnusedStns.size() << " stations were";
1✔
1507
                        }
1508
                        else
1509
                                ss_msg << "Station " << vUnusedStns.at(0) << " was";
×
1510

1511
                        ss_msg << " found outside the bounding box and " << (vUnusedStns.size() > 1 ? "have been" : "has been") << endl <<
1✔
1512
                                "    removed together with the corresponding measurements." << endl;
1✔
1513
                        if (p.i.split_clusters && (splitXmsrs || splitYmsrs))
1✔
1514
                        {
1515
                                ss_msg << "  - Note: GPS ";
1✔
1516
                                if (splitXmsrs && splitYmsrs)
1✔
1517
                                        ss_msg << "point and baseline";
×
1518
                                else if (splitXmsrs)
1✔
1519
                                        ss_msg << "baseline";
×
1520
                                else //if (splitYmsrs)
1521
                                        ss_msg << "point";
1✔
1522
                                ss_msg << " cluster measurements straddling the limits of" << endl << 
1✔
1523
                                "    the bounding box have been split." << endl;
1✔
1524
                        }
1525
                        imp_file << ss_msg.str() << "  - Excluded stations:" << endl;
1✔
1526
                        if (!p.g.quiet)
1✔
1527
                                cout << ss_msg.str() << endl;
1✔
1528
                        
1529
                        for (stn=0; stn<vUnusedStns.size(); ++stn)
13✔
1530
                                imp_file << "     " << vUnusedStns.at(stn) << endl;
12✔
1531
                        imp_file << endl;
1✔
1532
                }
1✔
1533
                else
1534
                {
1535
                        imp_file << "  - No stations were found outside the bounding box." << endl;
×
1536
                        if (!p.g.quiet)
×
1537
                                cout << "  - No stations were found outside the bounding box." << endl;
×
1538
                }
1539
        }
1✔
1540

1541
        UINT32 msrRead(parsemsrTally.TotalCount());
52✔
1542
        UINT32 stnCount(static_cast<UINT32>(vstationsTotal.size()));
52✔
1543
        UINT32 msrCount(static_cast<UINT32>(vmeasurementsTotal.size()));
52✔
1544

1545
        if (!p.g.quiet)
52✔
1546
                cout << endl;
51✔
1547
        imp_file << endl;
52✔
1548

1549
        ///////////////////////////////////////////////////////////////////////
1550
        // Ok, now that unwanted stations and measurements have been stripped,
1551
        // provide station and measurement Summary
1552
        //
1553
        if ((stnCount + msrCount) > 0)
52✔
1554
        {
1555
                if (p.i.import_block)
51✔
1556
                {
1557
                        if (!p.g.quiet)
×
1558
                                cout << "+ Binary file ";
×
1559
                        imp_file << "+ Binary file ";
×
1560
                }
1561
                else
1562
                {
1563
                        if (!p.g.quiet)
51✔
1564
                                cout << "+ File ";
50✔
1565
                        imp_file << "+ File ";
51✔
1566
                }
1567
                
1568
                if (!p.g.quiet)
51✔
1569
                        cout << "parsing summary:" << endl << endl;
50✔
1570
                imp_file << "parsing summary:" << endl << endl;
51✔
1571
        }
1572
        
1573
        //
1574
        // Station summary
1575
        if (stnCount)
52✔
1576
        {
1577
                if (!p.g.quiet)
51✔
1578
                {
1579
                        parsestnTally.coutSummary(cout, string("  Read"));
50✔
1580
                        cout << endl;
50✔
1581
                }
1582
                parsestnTally.coutSummary(imp_file, string("  Read"));
51✔
1583
                imp_file << endl;
51✔
1584
        }
1585
        
1586
        //
1587
        // Measurement summary
1588
        if (msrCount)
52✔
1589
        {
1590
                if (!p.g.quiet)
49✔
1591
                {
1592
                        parsemsrTally.coutSummary(cout, string("  Read"));
48✔
1593
                        cout << endl;
48✔
1594
                }
1595
                parsemsrTally.coutSummary(imp_file, string("  Read"));
49✔
1596
                imp_file << endl;
49✔
1597
        }
1598

1599
        ////////////////////////////////////////////////////////////////////////
1600
        // Can we proceed?
1601
        if (stnCount < 1)
52✔
1602
        {
1603
                imp_file << "- No further processing can be done as no stations were loaded." << endl;
1✔
1604
                if (!p.g.quiet)
1✔
1605
                        cout << "- No further processing can be done as no stations were loaded." << endl;
1✔
1606
                imp_file.close();
1✔
1607
                return PARSE_SUCCESS;
1608
        }
1609

1610
        /////////////////////////////////////////////////////////////////////////
1611
        // Rename stations
1612
        if (p.i.rename_stations && (stnCount > 0 || msrCount > 0))
51✔
1613
        {
1614
                // Does it exist?
1615
                if (!exists(p.i.stn_renamingfile))
1✔
1616
                        // Look for it in the input folder
1617
                        p.i.stn_renamingfile = formPath<string>(p.g.input_folder, leafStr<string>(p.i.stn_renamingfile));
×
1618

1619
                // Apply renaming
1620
                try {
1✔
1621
                        if (!p.g.quiet)
1✔
1622
                        {
1623
                                cout << "+ Renaming stations... ";
1✔
1624
                                cout.flush();
1✔
1625
                        }
1626
                        imp_file << "+ Renaming stations... ";
1✔
1627
                        parserDynaML.RenameStations(&vstationsTotal, &vmeasurementsTotal, &p);
1✔
1628
                        if (!p.g.quiet)
1✔
1629
                                cout << "Done." << endl;
1✔
1630
                        imp_file << "Done." << endl;
1✔
1631
                } 
1632
                catch (const XMLInteropException& e) {
×
1633
                        cout << endl << "- Error: " << e.what() << endl;
×
1634
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1635
                        imp_file.close();
×
1636
                        return EXIT_FAILURE;
×
1637
                }
×
1638
        }
1639

1640
        // Apply GNSS scaling (if required)
1641
        if (p.i.import_block != 1 && p.i.apply_scaling)
51✔
1642
        {
1643
                // Apply scaling
1644
                try {
2✔
1645
                        if (!p.g.quiet)
2✔
1646
                        {
1647
                                cout << "+ Applying scalars to GNSS measurements... ";
2✔
1648
                                cout.flush();
2✔
1649
                        }
1650
                        imp_file << "+ Applying scalars to GNSS measurements... ";
2✔
1651
                        parserDynaML.EditGNSSMsrScalars(&vmeasurementsTotal, &p);
2✔
1652
                        if (!p.g.quiet)
2✔
1653
                                cout << "Done." << endl;
2✔
1654
                        imp_file << "Done." << endl;
2✔
1655
                } 
1656
                catch (const XMLInteropException& e) {
×
1657
                        cout << endl << "- Error: " << e.what() << endl;
×
1658
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1659
                        imp_file.close();
×
1660
                        return EXIT_FAILURE;
×
1661
                }
×
1662
        }
1663

1664
        std::ofstream dst_file;
51✔
1665

1666
        // flush duplicate stations/measurements files
1667
        try {
51✔
1668
                if (exists(p.i.dst_file))
51✔
1669
                        remove(p.i.dst_file);
1✔
1670
                if (exists(p.i.dms_file))
51✔
1671
                        remove(p.i.dms_file);
3✔
1672
        }
1673
        catch (const ios_base::failure& f) { 
×
1674
                // do nothing on failure.
1675
                imp_file << endl << "- Warning: " << f.what() << endl;
×
1676
        }
×
1677

1678
        // Prepare file names if importing from a segmentation block
1679
        if (p.i.import_block)
51✔
1680
        {
1681
                stringstream blk("");
×
1682
                blk << ".block-" << p.i.import_block_number;
×
1683

1684
                // create new output file names based on block number
1685
                // reform file name for each so as to preserve full path for each file
1686
                stringstream ss("");
×
1687
                ss << formPath<string>(path(p.i.bst_file).parent_path().generic_string(), path(p.i.bst_file).stem().generic_string());
×
1688
                ss << blk.str() << ".bst";
×
1689
                p.i.bst_file = ss.str();
×
1690

1691
                ss.str("");
×
1692
                ss << formPath<string>(path(p.i.bms_file).parent_path().generic_string(), path(p.i.bms_file).stem().generic_string());
×
1693
                ss << blk.str() << ".bms";
×
1694
                p.i.bms_file = ss.str();
×
1695

1696
                ss.str("");
×
1697
                ss << formPath<string>(path(p.i.asl_file).parent_path().generic_string(), path(p.i.asl_file).stem().generic_string());
×
1698
                ss << blk.str() << ".asl";
×
1699
                p.i.asl_file = ss.str();
×
1700

1701
                ss.str("");
×
1702
                ss << formPath<string>(path(p.i.aml_file).parent_path().generic_string(), path(p.i.aml_file).stem().generic_string());
×
1703
                ss << blk.str() << ".aml";
×
1704
                p.i.aml_file = ss.str();
×
1705

1706
                ss.str("");
×
1707
                ss << formPath<string>(path(p.i.map_file).parent_path().generic_string(), path(p.i.map_file).stem().generic_string());
×
1708
                ss << blk.str() << ".map";
×
1709
                p.i.map_file = ss.str();
×
1710
        }
×
1711

1712
        // Remove duplicate stations. If required, test nearby stations
1713
        if (stnCount > 0) {
51✔
1714
                
1715
                vstring vduplicateStns;
51✔
1716
                v_stringstring_doubledouble_pair vnearbyStns;
51✔
1717

1718
                // Remove duplicates and, if required, identify station pairs 
1719
                // separated by distances less than search_stn_radius
1720
                try {
51✔
1721
                        ostringstream ss_msg;
51✔
1722
                        if (p.i.search_nearby_stn)
51✔
1723
                                ss_msg << "+ Testing for duplicate and nearby stations... ";
2✔
1724
                        else
1725
                                ss_msg << "+ Testing for duplicate stations... ";
49✔
1726
                        
1727
                        if (!p.g.quiet)
51✔
1728
                        {
1729
                                cout << ss_msg.str();
50✔
1730
                                cout.flush();
50✔
1731
                        }
1732

1733
                        imp_file << ss_msg.str();                        
51✔
1734
                        
1735
                        stn = parserDynaML.RemoveDuplicateStations(&vstationsTotal, &vduplicateStns, &vnearbyStns);
51✔
1736
                        
1737
                        if (!p.g.quiet)
51✔
1738
                                cout << "Done. ";
50✔
1739
                        imp_file << "Done. ";
51✔
1740

1741
                        if (stn > 0)
51✔
1742
                        {
1743
                                try {
3✔
1744
                                        // Create duplicate station file
1745
                                        file_opener(dst_file, p.i.dst_file);
3✔
1746
                                }
1747
                                catch (const runtime_error& e) {
×
1748
                                        ss_msg << "- Error: Could not open " << p.i.dst_file << ". \n  Check that the file exists and that the file is not already opened." << 
×
1749
                                                endl << e.what() << endl;
×
1750
                                        if (!p.g.quiet)
×
1751
                                                cout << ss_msg.str();
×
1752
                                        imp_file << ss_msg.str();
×
1753
                                        imp_file.close();
×
1754
                                        return EXIT_FAILURE;
×
1755
                                }
×
1756
                                                
1757
                                PrintOutputFileHeaderInfo(&dst_file, p.i.dst_file, &p, "DUPLICATE STATION FILE");
3✔
1758

1759
                                if (!vduplicateStns.empty())
3✔
1760
                                {
1761
                                        ss_msg.str("");
4✔
1762
                                        ss_msg << "Removed " << vduplicateStns.size() << " duplicate station" << (vduplicateStns.size() > 1 ? "s" : "");
3✔
1763
                                        
1764
                                        // print message to .dst file
1765
                                        dst_file << ss_msg.str() << ":" << endl;
2✔
1766
                                        for (stn=0; stn<vduplicateStns.size(); ++stn)
6✔
1767
                                                dst_file << "  - " << vduplicateStns.at(stn) << endl;
4✔
1768
                                        dst_file << endl;
2✔
1769

1770
                                        ss_msg << "." << endl << "  See " << p.i.dst_file << " for details." << endl;
2✔
1771

1772
                                        imp_file << ss_msg.str();
2✔
1773
                                        if (!p.g.quiet)
2✔
1774
                                                cout << endl << "- Warning: " << ss_msg.str();                                        
2✔
1775
                                }                                
1776

1777
                                if (!vnearbyStns.empty())
3✔
1778
                                {
1779
                                        ss_msg.str("");
2✔
1780
                                        ss_msg << vnearbyStns.size() << (vnearbyStns.size() > 1 ? " pairs of stations were" : " pair of station was") << 
1✔
1781
                                                " found to be separated by less than " << setprecision(3) << p.i.search_stn_radius << "m.";
1✔
1782

1783
                                        imp_file << endl << "- Warning: " << ss_msg.str() << endl << 
1✔
1784
                                                "  See " << p.i.dst_file << " for details." << endl << endl;
1✔
1785
                                        
1786
                                        if (!p.g.quiet)
1✔
1787
                                                cout << endl << "- Warning: " << ss_msg.str() << endl << 
2✔
1788
                                                "  See " << p.i.dst_file << " for details." << endl << endl;
1✔
1789
                                        ss_msg.str("");
2✔
1790

1791
                                        // output message
1792
                                        dst_file << "Nearby station search results:" << endl << ss_msg.str() << endl << endl;
1✔
1793

1794
                                        dst_file <<  
1✔
1795
                                                setw(HEADER_20) << left << "First station" << 
1✔
1796
                                                setw(HEADER_20) << "Nearby station" << 
1797
                                                setw(HEADER_20) << right << "Separation (m)" << 
1✔
1798
                                                setw(HEADER_20) << "Diff height (m)" << 
1✔
1799
                                                endl;
81✔
1800

1801
                                        for (UINT32 i(0); i<(HEADER_20*4); ++i)
81✔
1802
                                                dst_file << "-";
80✔
1803
                                        dst_file << endl;
1✔
1804

1805
                                        // dump nearby stations to dst file
1806
                                        for (stn=0; stn<vnearbyStns.size(); ++stn)
50✔
1807
                                        {
1808
                                                dst_file <<
49✔
1809
                                                        setw(HEADER_20) << left << vnearbyStns.at(stn).first.first <<                                                                         // First
49✔
1810
                                                        setw(HEADER_20) << vnearbyStns.at(stn).first.second <<                                                                        // Nearby
49✔
1811
                                                        setw(HEADER_20) << setprecision(3) << fixed << right << vnearbyStns.at(stn).second.first <<                // Separation (m)
98✔
1812
                                                        setw(HEADER_20) << setprecision(3) << fixed << vnearbyStns.at(stn).second.second <<                // Diff height (m)
49✔
1813
                                                        endl;
49✔
1814
                                        }
1815

1816
                                        ss_msg <<
1✔
1817
                                                "  If the names in each pair refer to the same station, then update the " << endl <<
1✔
1818
                                                "  station and measurement files with the correct station name and re-run " << __BINARY_NAME__ << "." << endl <<
1✔
1819
                                                "  Alternatively, if the names in each pair are unique, either call " << __BINARY_NAME__ << endl <<
1✔
1820
                                                "  without the --" << TEST_NEARBY_STNS << " option, or decrease the radial search " << endl <<
1✔
1821
                                                "  distance using --" << TEST_NEARBY_STN_DIST << "." << endl << endl;
1✔
1822

1823
                                        if (!p.g.quiet)
1✔
1824
                                                cout << ss_msg.str();
1✔
1825
                                        imp_file << ss_msg.str();
1✔
1826
                                        imp_file.close();
1✔
1827
                                        dst_file.close();
1✔
1828
                                        return EXIT_FAILURE;
1829
                                }
1830
                                else if (p.g.verbose == 3)
2✔
1831
                                {
1832
                                        if (!p.g.quiet)
×
1833
                                                cout << "+ Total number of unique stations is " << vstationsTotal.size() << endl;
×
1834
                                        imp_file << "+ Total number of unique stations is " << vstationsTotal.size() << endl;
×
1835
                                }
1836

1837
                                // If this line is reached, then there are no nearby stations
1838
                                dst_file.close();
2✔
1839
                        }
1840
                        if (!p.g.quiet)
50✔
1841
                                cout << endl;
49✔
1842
                        imp_file << endl;
50✔
1843
                } 
51✔
1844
                catch (const XMLInteropException& e) {
×
1845
                        cout << endl << "- Error: " << e.what() << endl;
×
1846
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1847
                        imp_file.close();
×
1848
                        return EXIT_FAILURE;
×
1849
                }                
×
1850

1851
                /////////////////////////////////////////////////////////////////
1852
                // Now commence sorting and mapping
1853
                // 1. Sort stations
1854
                // 2. Create station map
1855
                try {
50✔
1856
                        if (!p.g.quiet)
50✔
1857
                        {
1858
                                cout << "+ Sorting stations... ";
49✔
1859
                                cout.flush();
49✔
1860
                        }
1861
                        imp_file << "+ Sorting stations... ";
50✔
1862
                        parserDynaML.FullSortandMapStations((vdnaStnPtr*) &vstationsTotal, &vStnsMap_sortName);
50✔
1863
                        if (!p.g.quiet)
50✔
1864
                        {
1865
                                cout << "Done." << endl << "+ Serialising station map... ";
49✔
1866
                                cout.flush();
49✔
1867
                        }
1868
                        imp_file << "Done." << endl << "+ Serialising station map... ";                        
50✔
1869
                        parserDynaML.SerialiseMap(p.i.map_file);                // parserDynaML keeps the map in memory
50✔
1870
                        stn_map_created = true;
50✔
1871
                        if (!p.g.quiet)
50✔
1872
                        {
1873
                                cout << "Done." << endl;
49✔
1874
                                cout.flush();
49✔
1875
                        }
1876
                        imp_file << "Done." << endl;
50✔
1877

1878
                        if (p.i.export_map_file)
50✔
1879
                        {
1880
                                if (!p.g.quiet)
4✔
1881
                                {
1882
                                        cout << "+ Exporting station map to text file... ";
4✔
1883
                                        cout.flush();
4✔
1884
                                }
1885
                                imp_file << "+ Exporting station map to text file... ";
4✔
1886
                                parserDynaML.SerialiseMapTextFile(p.i.map_file);
4✔
1887
                                if (!p.g.quiet)
4✔
1888
                                {
1889
                                        cout << "Done." << endl;
4✔
1890
                                        cout.flush();
4✔
1891
                                }
1892
                                imp_file << "Done." << endl;                                
4✔
1893
                        }
1894
                } 
1895
                catch (const XMLInteropException& e) {
×
1896
                        cout << endl << "- Error: " << e.what() << endl;
×
1897
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1898
                        imp_file.close();
×
1899
                        return EXIT_FAILURE;
×
1900
                }        
×
1901
        }
51✔
1902

1903
        // Search for similar measurements
1904
        if (msrCount > 0 && (p.i.search_similar_msr || p.i.search_similar_msr_gx || p.i.ignore_similar_msr)) 
50✔
1905
        {
1906
                if (SearchForSimilarMeasurements(&parserDynaML, &p, &imp_file,
4✔
1907
                        &vmeasurementsTotal) != EXIT_SUCCESS)
1908
                        return EXIT_FAILURE;        
1909
        }
1910

1911
        // Import DNA geoid file
1912
        if (p.i.import_geo_file && p.i.import_block == 0 && vstationsTotal.size())
50✔
1913
        {
1914
                if (!exists(p.i.geo_file))
2✔
1915
                {
1916
                        path geoPath(p.i.geo_file);
×
1917
                        stringstream ss;
×
1918
                        ss << "- Error: The geoid file " << geoPath.filename().string() << " does not exist." << endl;
×
1919
                        cout << endl << ss.str();
×
1920
                        imp_file << endl << ss.str();
×
1921
                        return EXIT_FAILURE;
×
1922
                }
×
1923

1924
                if (!p.g.quiet)
2✔
1925
                {
1926
                        cout << "+ Importing geoid information from " << p.i.geo_file << "... ";
2✔
1927
                        cout.flush();
2✔
1928
                }
1929
                imp_file << "+ Importing geoid information from " << p.i.geo_file << "... ";
2✔
1930

1931
                parserDynaML.LoadDNAGeoidFile(p.i.geo_file, &vstationsTotal);
2✔
1932

1933
                if (!p.g.quiet)
2✔
1934
                        cout << "Done." << endl;
2✔
1935
                imp_file << "Done." << endl;
2✔
1936
        }
1937

1938
        UINT32 ignMsrCount, mapCount;
50✔
1939
        vstring vunusedStations;
50✔
1940
        vUINT32 vignoredMeasurements;
50✔
1941

1942
        // Map measurements to stations
1943
        if (stn_map_created) 
50✔
1944
        {        
1945
                try {
50✔
1946
                        if (!p.g.quiet)
50✔
1947
                        {
1948
                                cout << "+ Mapping measurements to stations... ";
49✔
1949
                                cout.flush();
49✔
1950
                        }
1951
                        imp_file << "+ Mapping measurements to stations... ";
50✔
1952
                        
1953
                        parserDynaML.MapMeasurementStations((vdnaMsrPtr*) &vmeasurementsTotal,        &associatedSL, &mapCount, &vunusedStations, &vignoredMeasurements);
50✔
1954
                        
1955
                        if (!p.g.quiet)
49✔
1956
                                cout << "Done." << endl;
48✔
1957
                        imp_file << "Done. ";
49✔
1958

1959
                        if (msrCount > 0)
49✔
1960
                        {
1961
                                measurements_mapped = true;
47✔
1962
                                imp_file << "Mapped " << mapCount << " measurements to " << vStnsMap_sortName.size() - vunusedStations.size() << " stations." << endl;
47✔
1963
                        }
1964
                        else
1965
                                imp_file << endl;
2✔
1966

1967
                        if (!vunusedStations.empty())
49✔
1968
                        {
1969
                                if (vunusedStations.size() == 1)
17✔
1970
                                {
1971
                                        if (p.g.verbose > 2)
13✔
1972
                                        {
1973
                                                if (!p.g.quiet)
×
1974
                                                        cout << "- Warning: station " << vunusedStations.at(0) << " was not associated with any measurements." << endl;
×
1975
                                                imp_file << "- Warning: station " << vunusedStations.at(0) << " was not associated with any measurements." << endl;
×
1976
                                        }
1977
                                        else
1978
                                        {
1979
                                                if (!p.g.quiet)
13✔
1980
                                                        cout << "- Warning: " << vunusedStations.size() << " station was not associated with any measurements." << endl;
13✔
1981
                                                imp_file << "- Warning: " << vunusedStations.size() << " station was not associated with any measurements." << endl;
13✔
1982
                                        }
1983
                                }
1984
                                else
1985
                                {
1986
                                        if (p.g.verbose > 2)
4✔
1987
                                        {
1988
                                                if (!p.g.quiet)
×
1989
                                                        cout << "- Warning: The following " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
×
1990
                                                imp_file << "- Warning: The following " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
×
1991
                                                _it_vstr unused;
×
1992
                                                for (unused = vunusedStations.begin(); unused!=vunusedStations.end(); unused++)
×
1993
                                                {
1994
                                                        if (!p.g.quiet)
×
1995
                                                                outputObject(string("  - " + *unused + "\n"), cout);
×
1996
                                                        outputObject(string("  - " + *unused + "\n"), imp_file);
×
1997
                                                }
1998
                                        }
1999
                                        else
2000
                                        {
2001
                                                if (!p.g.quiet)
4✔
2002
                                                        cout << "- Warning: " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
4✔
2003
                                                imp_file << "- Warning: " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
4✔
2004
                                        }
2005
                                }
2006
                        }
2007
                        if (msrRead < mapCount && vignoredMeasurements.empty())
49✔
2008
                        {
2009
                                if (!p.g.quiet)
×
2010
                                        cout << "- Warning: Not all measurements were mapped: " << msrRead << " msrs read vs. " << mapCount
×
2011
                                                << " msrs mapped." << endl;
×
2012
                        }
2013
                        else if (msrRead != mapCount && !vignoredMeasurements.empty())
49✔
2014
                        {
2015
                                ignMsrCount = parserDynaML.ComputeMeasurementCount(&vmeasurementsTotal, vignoredMeasurements);        
×
2016
                                if (!p.g.quiet)
×
2017
                                {
2018
                                        cout << "- Warning: " << ignMsrCount << " ignored measurements were not mapped." << endl;
×
2019
                                        if ((msrRead - mapCount) != ignMsrCount)
×
2020
                                                cout << "-          " << msrRead << " m.read vs. " << mapCount << " m.mapped." << endl;
×
2021
                                }
2022
                        }
2023
                        if (!p.g.quiet)
49✔
2024
                                cout.flush();
48✔
2025
                } 
2026
                catch (const XMLInteropException& e) {
1✔
2027
                        cout << endl << "- Error: " << e.what() << endl;
1✔
2028
                        imp_file << endl << "- Error: " << e.what() << endl;
1✔
2029
                        imp_file.close();
1✔
2030
                        return EXIT_FAILURE;
1✔
2031
                }
1✔
2032
        }
2033

2034
        stnCount = static_cast<UINT32>(vstationsTotal.size());
49✔
2035
        if (stnCount > static_cast<UINT32>(associatedSL.size()))
49✔
2036
                stnCount = static_cast<UINT32>(associatedSL.size());
×
2037
        
2038
        // Does the user want to simulate measurements?
2039
        if (p.i.simulate_measurements && stnCount > 0 && msrCount > 0) 
49✔
2040
        {
2041
                // No need for the following code if the outer 'if' statement checks 
2042
                // for non-zero stnCount value
2043
                //
2044
                // if (stnCount == 0)
2045
                // {
2046
                //         if (!p.g.quiet)
2047
                //                 cout << "- Error: there are no stations from which to simulate measurements." << endl;
2048
                //         imp_file << "- Error: there are no stations from which to simulate measurements." << endl;
2049
                //         imp_file.close();
2050
                //         return EXIT_FAILURE;
2051
                // }        
2052
        
2053
                try {
1✔
2054
                        // Simulate measurements
2055
                        if (!p.g.quiet)
1✔
2056
                        {
2057
                                cout << "+ Simulating and exporting measurements to " << leafStr<string>(p.i.simulate_msrfile) << "... ";
2✔
2058
                                cout.flush();
1✔
2059
                        }
2060
                        imp_file << "+ Simulating and exporting measurements to " << leafStr<string>(p.i.simulate_msrfile) << "... ";
2✔
2061
                        parserDynaML.SimulateMSR(
1✔
2062
                                ((vdnaStnPtr*) &vstationsTotal), 
2063
                                ((vdnaMsrPtr*) &vmeasurementsTotal), 
2064
                                p.i.simulate_msrfile, p);
2065
                        if (!p.g.quiet)
1✔
2066
                                cout << "Done." << endl;
1✔
2067
                        imp_file << "Done." << endl;
1✔
2068
                }
2069
                catch (const XMLInteropException& e) {
×
2070
                        cout.flush();
×
2071
                        cout << endl << "- Error: " << e.what() << endl;
×
2072
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2073
                        imp_file.close();
×
2074
                        return EXIT_FAILURE;
×
2075
                }
×
2076
        }
2077

2078
        // Create association lists
2079
        if (measurements_mapped) 
49✔
2080
        {
2081
                try {
47✔
2082
                        if (!p.g.quiet)
47✔
2083
                        {
2084
                                cout << "+ Creating association lists... ";
46✔
2085
                                cout.flush();
46✔
2086
                        }
2087
                        imp_file << "+ Creating association lists... ";
47✔
2088
                        parserDynaML.CompleteAssociationLists(&vmeasurementsTotal, &associatedSL, &associatedML);
47✔
2089
                        if (!p.g.quiet)
47✔
2090
                        {
2091
                                cout << "Done." << endl;
46✔
2092
                                cout.flush();
46✔
2093
                        }
2094
                        imp_file << "Done." << endl;
47✔
2095
                } 
2096
                catch (const XMLInteropException& e) {
×
2097
                        cout << "- Error: " << e.what() << endl;
×
2098
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2099
                        imp_file.close();
×
2100
                        return EXIT_FAILURE;
×
2101
                }
×
2102

2103
                try {
47✔
2104
                        if (!p.g.quiet)
47✔
2105
                        {
2106
                                cout << "+ Serialising association lists... ";
46✔
2107
                                cout.flush();
46✔
2108
                        }
2109
                        imp_file << "+ Serialising association lists... ";
47✔
2110
                        parserDynaML.SerialiseAsl(p.i.asl_file, &associatedSL);
47✔
2111
                        parserDynaML.SerialiseAml(p.i.aml_file, &associatedML);
47✔
2112
                        if (!p.g.quiet)
47✔
2113
                        {
2114
                                cout << "Done." << endl;
46✔
2115
                                cout.flush();
46✔
2116
                        }
2117
                        imp_file << "Done." << endl;
47✔
2118
                } 
2119
                catch (const XMLInteropException& e) {
×
2120
                        cout << "- Error: " << e.what() << endl;
×
2121
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2122
                        imp_file.close();
×
2123
                        return EXIT_FAILURE;
×
2124
                }
×
2125
        }
2126

2127
        // Create binary station file.
2128
        // Binary station file can be serialised without measurements
2129
        if (stnCount > 0)
49✔
2130
        {
2131
                try {
49✔
2132
                        if (!vstationsTotal.empty())
49✔
2133
                        {
2134
                                if (!p.g.quiet)
49✔
2135
                                {
2136
                                        cout << "+ Serialising binary station file " << leafStr<string>(p.i.bst_file) << "... ";
96✔
2137
                                        cout.flush();
48✔
2138
                                }
2139
                                imp_file << "+ Serialising binary station file " << leafStr<string>(p.i.bst_file) << "... ";
98✔
2140
                                
2141
                                parserDynaML.SerialiseBst(
49✔
2142
                                        p.i.bst_file, ((vdnaStnPtr*) &vstationsTotal), &vunusedStations,
2143
                                        vinput_file_meta, (p.i.flag_unused_stn ? true : false));
49✔
2144
                                if (!p.g.quiet)
49✔
2145
                                {
2146
                                        cout << "Done." << endl;
48✔
2147
                                        cout.flush();
48✔
2148
                                }
2149
                                imp_file << "Done." << endl;
49✔
2150
                        }
2151
                } 
2152
                catch (const XMLInteropException& e) {
×
2153
                        cout << "- Error: " << e.what() << endl;
×
2154
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2155
                        imp_file.close();
×
2156
                        return EXIT_FAILURE;
×
2157
                }
×
2158
        }
2159

2160
        // Create binary measurement file.
2161
        // Binary measurement file can be serialised without stations
2162
        if (msrCount > 0) 
49✔
2163
        {
2164
                try {
47✔
2165
                        if (!vmeasurementsTotal.empty())
47✔
2166
                        {
2167
                                if (!p.g.quiet)
47✔
2168
                                {
2169
                                        cout << "+ Serialising binary measurement file " << leafStr<string>(p.i.bms_file) << "... ";
92✔
2170
                                        cout.flush();
46✔
2171
                                }
2172
                                imp_file << "+ Serialising binary measurement file " << leafStr<string>(p.i.bms_file) << "... ";
94✔
2173

2174
                                parserDynaML.SerialiseBms(
47✔
2175
                                        p.i.bms_file, ((vdnaMsrPtr*) &vmeasurementsTotal),
2176
                                        vinput_file_meta);
2177
                                if (!p.g.quiet)
47✔
2178
                                {
2179
                                        cout << "Done." << endl;
46✔
2180
                                        cout.flush();
46✔
2181
                                }
2182
                                imp_file << "Done." << endl;
47✔
2183
                        }
2184
                } 
2185
                catch (const XMLInteropException& e) {
×
2186
                        cout << "- Error: " << e.what() << endl;
×
2187
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2188
                        imp_file.close();
×
2189
                        return EXIT_FAILURE;
×
2190
                }
×
2191
        }
2192

2193
        // Export ASL and AML to text if required
2194
        if (measurements_mapped) 
49✔
2195
        {
2196
                try {
47✔
2197
                        if (p.i.export_asl_file)
47✔
2198
                        {
2199
                                if (!p.g.quiet)
4✔
2200
                                {
2201
                                        cout << "+ Exporting associated station list to text file... ";
4✔
2202
                                        cout.flush();
4✔
2203
                                }
2204
                                imp_file << "+ Exporting associated station list to text file... ";
4✔
2205
                                parserDynaML.SerialiseAslTextFile(p.i.asl_file, &associatedSL, (vdnaStnPtr*) &vstationsTotal);
4✔
2206
                                if (!p.g.quiet)
4✔
2207
                                {
2208
                                        cout << "Done." << endl;
4✔
2209
                                        cout.flush();
4✔
2210
                                }
2211
                                imp_file << "Done." << endl;                                
4✔
2212
                        }
2213
                } 
2214
                catch (const XMLInteropException& e) {
×
2215
                        cout << "- Error: " << e.what() << endl;
×
2216
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2217
                        imp_file.close();
×
2218
                        return EXIT_FAILURE;
×
2219
                }
×
2220

2221
                try {
47✔
2222
                        if (p.i.export_aml_file)
47✔
2223
                        {
2224
                                if (!p.g.quiet)
4✔
2225
                                {
2226
                                        cout << "+ Exporting associated measurement list to text file... ";
4✔
2227
                                        cout.flush();
4✔
2228
                                }
2229
                                imp_file << "+ Exporting associated measurement list to text file... ";
4✔
2230
                                parserDynaML.SerialiseAmlTextFile(p.i.bms_file, p.i.aml_file, &associatedML, &associatedSL, (vdnaStnPtr*) &vstationsTotal);
4✔
2231
                                if (!p.g.quiet)
4✔
2232
                                {
2233
                                        cout << "Done." << endl;
4✔
2234
                                        cout.flush();
4✔
2235
                                }
2236
                                imp_file << "Done." << endl;                                
4✔
2237
                        }
2238
                }
2239
                catch (const XMLInteropException& e) {
×
2240
                        cout << "- Error: " << e.what() << endl;
×
2241
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2242
                        imp_file.close();
×
2243
                        return EXIT_FAILURE;
×
2244
                }
×
2245

2246
                if (p.i.test_integrity)
47✔
2247
                {
2248
                        if (!p.g.quiet)
2✔
2249
                        {
2250
                                cout << "+ Testing internal integrity of ASL, AML and binary files... ";
2✔
2251
                                cout.flush();
2✔
2252
                        }
2253
                        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✔
2254
                        if (!binaryMS.good())
2✔
2255
                        {
2256
                                cout << endl << "- Could not open binary file for reading." << endl;
×
2257
                                imp_file << endl << "- Could not open binary file for reading." << endl;
×
2258
                                imp_file.close();
×
2259
                                return EXIT_FAILURE;
×
2260
                        }
2261
                        // get size, then go back to beginning
2262
                        size_t sFileSize = (size_t)binaryMS.tellg();
2✔
2263
                        binaryMS.seekg(0, ios::beg);
2✔
2264

2265
                        measurement_t measRecord;
2✔
2266
                        
2267
                        UINT32 amlcount, amlindex, msr;
2✔
2268
                        for (stn=0; stn<stnCount; stn++)
90✔
2269
                        {
2270
                                amlcount = associatedSL.at(stn).get()->GetAssocMsrCount();
86✔
2271
                                
2272
                                // The following is to be used when reading from binary file
2273
                                for (msr=0; msr<amlcount; msr++)
624✔
2274
                                {
2275
                                        amlindex = associatedSL.at(stn).get()->GetAMLStnIndex() + msr;
538✔
2276
                                        if (associatedML.at(amlindex) * sizeof(measurement_t) >= sFileSize)
538✔
2277
                                        {
2278
                                                cout << "Error: index " << associatedML.at(amlindex) << " is out of range for the binary file." << endl;
×
2279
                                                continue;
×
2280
                                        }
2281
                                        binaryMS.seekg(sizeof(UINT32) + associatedML.at(amlindex) * sizeof(measurement_t), ios::beg);
538✔
2282
                                        binaryMS.read(reinterpret_cast<char *>(&measRecord), sizeof(measurement_t));
538✔
2283
                                }
2284
                        }
2285
                        binaryMS.close();
2✔
2286
                        if (!p.g.quiet)
2✔
2287
                                cout << "OK." << endl;
2✔
2288
                }
2✔
2289
        }
2290

2291
        try {
49✔
2292
                // Print measurements to stations table
2293
                PrintMeasurementstoStations(&parsemsrTally, &parserDynaML, &p, &associatedSL);
49✔
2294
        }
2295
        catch (const XMLInteropException& e) {
×
2296
                cout.flush();
×
2297
                cout << endl << "- Error: " << e.what() << endl;
×
2298
                imp_file << endl << "- Error: " << e.what() << endl;
×
2299
                imp_file.close();
×
2300
                return EXIT_FAILURE;
×
2301
        }
×
2302

2303
        // Serialise database ids
2304
        string dbid_file = formPath<string>(p.g.output_folder, p.g.network_name, "dbid");
49✔
2305
        parserDynaML.SerialiseDatabaseId(dbid_file, &vmeasurementsTotal);
49✔
2306

2307
        // Export stations and measurements
2308
        try {
49✔
2309
                if (p.i.export_dynaml || p.i.export_dna_files)
49✔
2310
                        ExportStationsandMeasurements(&parserDynaML, p, &imp_file, &vinput_file_meta, 
12✔
2311
                                &vstationsTotal, &vmeasurementsTotal, stnCount, msrCount);
2312
        }
2313
        catch (const XMLInteropException& e) {
×
2314
                cout.flush();
×
2315
                cout << endl << "- Error: " << e.what() << endl;
×
2316
                imp_file << endl << "- Error: " << e.what() << endl;
×
2317
                imp_file.close();
×
2318
                return EXIT_FAILURE;
×
2319
        }
×
2320
        
2321
        if (!userSuppliedSegFile)
49✔
2322
                p.i.seg_file = "";
49✔
2323
        if (!userSuppliedBstFile)
49✔
2324
                p.i.bst_file = "";
49✔
2325
        if (!userSuppliedBmsFile)
49✔
2326
                p.i.bms_file = "";
49✔
2327

2328
        // Look for a project file.  If it exists, open and load it.
2329
        // Update the import settings.
2330
        // Print the project file. If it doesn't exist, it will be created.
2331
        CDnaProjectFile projectFile;
49✔
2332
        if (exists(p.g.project_file))
49✔
2333
                projectFile.LoadProjectFile(p.g.project_file);
19✔
2334
        
2335
        projectFile.UpdateSettingsImport(p);
49✔
2336
        projectFile.UpdateSettingsReftran(p);
49✔
2337
        projectFile.UpdateSettingsOutput(p);
49✔
2338
        projectFile.PrintProjectFile();
49✔
2339

2340
        if (msrCount == 0)
49✔
2341
        {
2342
                cout << "- Warning: there are no measurements to process." << endl;
2✔
2343
                imp_file << "- Warning: there are no measurements to process." << endl;
2✔
2344
        }
2345
        
2346
        if (errorCount)
49✔
2347
        {
2348
                cout << "- Warning: some files were not parsed - please read the log file for more details." << endl;
×
2349
                imp_file << "- Warning: some files were not parsed - please read the log file for more details." << endl;
×
2350
        }
2351

2352
        // Produce a warning if an ensemble is set as the default reference frame
2353
        if (isEpsgWGS84Ensemble(epsgCode))
49✔
2354
        {
2355
                stringstream ssEnsembleWarning;
×
2356
                ssEnsembleWarning << endl <<
×
2357
                        "- Warning:  The '" << p.i.reference_frame << "' reference frame set for this project refers to the" << endl <<
×
2358
                        "  \"World Geodetic System 1984 (WGS 84) ensemble\".  The WGS 84 ensemble is" << endl <<
×
2359
                        "  only suitable for low accuracy (metre level) positioning and does not" << endl <<
×
2360
                        "  provide for precise transformations to other well-known reference frames." << endl <<
×
2361
                        "  To achieve reliable adjustment results from data on WGS 84, please refer" << endl <<
×
2362
                        "  to \"Configuring import options\" in the DynAdjust User's Guide." << endl;
×
2363
                if (!p.g.quiet)
×
2364
                        cout << ssEnsembleWarning.str();
×
2365
                imp_file << ssEnsembleWarning.str();
×
2366
        }
×
2367
        
2368
        milliseconds elapsed_time(milliseconds(time.elapsed().wall/MILLI_TO_NANO));
49✔
2369
        string time_message = formatedElapsedTime<string>(&elapsed_time, "+ Total file handling process took ");
49✔
2370

2371
        if (!p.g.quiet)
49✔
2372
                cout << endl << time_message << endl;
48✔
2373
        imp_file << endl << time_message << endl;
49✔
2374
        
2375
        if (stnCount > 0 && msrCount > 0)
49✔
2376
        {
2377
                if (!p.g.quiet)
47✔
2378
                        cout << "+ Binary station and measurement files are now ready for processing." << endl << endl;
46✔
2379
                imp_file << "+ Binary station and measurement files are now ready for processing." << endl << endl;
47✔
2380
        }
2381

2382
        imp_file.close();
49✔
2383
        return PARSE_SUCCESS;
49✔
2384
}
353✔
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