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

icsm-au / DynAdjust / 5021344802

pending completion
5021344802

push

github

GitHub
Merge pull request #222 from rogerfraser/master

159 of 159 new or added lines in 7 files covered. (100.0%)

30774 of 38869 relevant lines covered (79.17%)

3959.78 hits per line

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

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

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

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

52
        if (!p->i.input_files.empty())
75✔
53
        {
54
                _it_vstr _it_files(p->i.input_files.begin());
70✔
55
                string str("Input files:");
70✔
56
                while (_it_files!=p->i.input_files.end())
70✔
57
                {
58
                        *f_out << setw(PRINT_VAR_PAD) << left << str << *_it_files++ << endl;
178✔
59
                        str = " ";
248✔
60
                }
61
        }
70✔
62
        
63
        if (!p->i.reference_frame.empty())
75✔
64
                *f_out << setw(PRINT_VAR_PAD) << left << "Default reference frame:" << p->i.reference_frame << endl;
75✔
65
        
66
        if (!p->i.include_msrs.empty())
75✔
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())
73✔
69
                *f_out << setw(PRINT_VAR_PAD) << left << "Strip measurement types:" << p->i.exclude_msrs << endl;
1✔
70

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

263
        if (vm.count(IGNORE_INSUFFICIENT_MSRS))
65✔
264
                p.i.ignore_insufficient_msrs = 1;
×
265

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

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

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

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

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

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

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

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

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

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

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

371
        return EXIT_SUCCESS;
65✔
372
}
68✔
373

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

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

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

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

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

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

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

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

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

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

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

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

465
                        dms_file.close();
4✔
466

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

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

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

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

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

511
        return EXIT_SUCCESS;
512

513
}
4✔
514
        
515

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

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

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

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

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

598
        }
599

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

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

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

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

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

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

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

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

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

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

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

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

680
        return EXIT_SUCCESS;
681
}
682

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

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

692
        // Import stations and measurements from a particular block
693
        if (!p.g.quiet)
6✔
694
                cout << endl << "+ Importing stations and measurements from block " << p.i.import_block_number << " of\n  " << p.i.seg_file << "... ";
6✔
695

696
        try {
6✔
697
                parserDynaML.ImportStnsMsrsFromBlock(vStations, vMeasurements, p);
6✔
698
        }
699
        catch (const XMLInteropException& e) {
1✔
700
                stringstream ss;
1✔
701
                ss << endl << endl << "- Error: " << e.what();
1✔
702
                cout << ss.str() << endl;
1✔
703
                return EXIT_FAILURE;
1✔
704
        }
1✔
705

706
        *parsestnTally += parserDynaML.GetStnTally();
5✔
707
        *parsemsrTally += parserDynaML.GetMsrTally();
5✔
708
        if (!p.g.quiet)
5✔
709
                cout << "Done. " << endl;
5✔
710

711
        // Restore seg_file to null
712
        if (!userSuppliedSegFile)
5✔
713
                p.i.seg_file = "";
6✔
714

715
        return EXIT_SUCCESS;
716
}
717

718
int ImportContiguousNetwork(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements,
2✔
719
        StnTally* parsestnTally, MsrTally* parsemsrTally, project_settings& p)
720
{
721
        // Form default seg file path
722
        bool userSuppliedSegFile(false);
2✔
723

724
        if (PrepareImportSegmentedData(p, userSuppliedSegFile) != EXIT_SUCCESS)
2✔
725
                return EXIT_FAILURE;
726

727
        // Import stations and measurements from a particular block
728
        if (!p.g.quiet)
2✔
729
                cout << endl << "+ Importing stations and measurements from contiguous network " << p.i.import_network_number << " of\n  " << p.i.seg_file << "... ";
2✔
730

731
        try {
2✔
732
                parserDynaML.ImportStnsMsrsFromNetwork(vStations, vMeasurements, p);
2✔
733
        }
734
        catch (const XMLInteropException& e) {
1✔
735
                stringstream ss;
1✔
736
                ss << endl << endl << "- Error: " << e.what();
1✔
737
                cout << ss.str() << endl;
1✔
738
                return EXIT_FAILURE;
1✔
739
        }
1✔
740

741
        *parsestnTally += parserDynaML.GetStnTally();
1✔
742
        *parsemsrTally += parserDynaML.GetMsrTally();
1✔
743
        if (!p.g.quiet)
1✔
744
                cout << "Done. " << endl;
1✔
745

746
        // Restore seg_file to null
747
        if (!userSuppliedSegFile)
1✔
748
                p.i.seg_file = "";
2✔
749

750
        return EXIT_SUCCESS;
751
}
752
        
753

754
int ImportDataFiles(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements,
57✔
755
                vdnaStnPtr* vstationsTotal, vdnaMsrPtr* vmeasurementsTotal,
756
                std::ofstream* imp_file, vifm_t* vinput_file_meta, StnTally* parsestnTally, MsrTally* parsemsrTally, 
757
                UINT32& errorCount, project_settings& p)
758
{
759
        // For consideration:  
760
        //        - All input files could be read concurrently using multi-thread for faster input
761
        //        - The number of files that can be processed concurrently should be restricted to
762
        //          the number of available cores
763
        //        - If multi-threading is to be used, then the progress thread will need to be redesigned.
764
        //          Currently, the progress of each file (as a percentage) is written to cout as each file
765
        //          is processed. If files are processed concurrently, progress reporting will need to be
766
        //    redesigned if multiple progress threads are writing to cout.
767
        //        - There is significant gain in using multi-thread.
768
        //        - The catch will be the need to carefully design one progress thread that captures progress
769
        //          of all other "read" threads (rather than one progress for each), and somehow write to 
770
        //          cout the respective progress.  For example, loading four files could be displayed as 
771
        //          follows:
772
        //
773
        //          + Parsing file1.xml (32%), file2.xml (16%), file3.xml (86%), file4.xml (56%)
774
        //            Done: Loaded 190 stations from file3.xml in 00.032s
775
        //          + Parsing file1.xml (72%), file2.xml (48%), file4.xml (91%)
776
        //            Done: Loaded 236 stations from file4.xml in 00.050s
777
        //          + Parsing file1.xml (87%), file2.xml (76%)
778
        //            Done: Loaded 1596 measurements from file1.xml in 01.380s
779
        //            Done: Loaded 3142 measurements from file2.xml in 02.034s
780
        //
781
        UINT32 stnCount(0), msrCount(0), clusterID(0);
57✔
782
        
783
        // obtain the project reference frame
784
        string epsgCode(epsgStringFromName<string>(p.i.reference_frame));
57✔
785
        
786
        size_t pos = string::npos;
57✔
787
        size_t strlen_arg = 0;
57✔
788
        for_each(p.i.input_files.begin(), p.i.input_files.end(),
57✔
789
                [&strlen_arg](string& file) {
200✔
790
                        if (leafStr<string>(file).length() > strlen_arg)
133✔
791
                                strlen_arg = leafStr<string>(file).length();
67✔
792
        });
133✔
793

794
        strlen_arg += (6 + PROGRESS_PERCENT_04);
57✔
795

796
        size_t i, nfiles(p.i.input_files.size());                // for each file...
57✔
797
        string input_file, ss, status_msg;
57✔
798
        vstring input_files;
57✔
799
        ostringstream ss_time, ss_msg;
57✔
800
        input_file_meta_t input_file_meta;
57✔
801
        milliseconds elapsed_time(milliseconds(0));
57✔
802
        ptime pt;
57✔
803

804
        if (!p.g.quiet)
57✔
805
                cout << "+ Parsing: " << endl;
56✔
806
        *imp_file << "+ Parsing " << endl;
57✔
807

808
        for (i=0; i<nfiles; i++)
185✔
809
        {
810
                stnCount = msrCount = 0;
131✔
811
                input_file = p.i.input_files.at(i);
131✔
812
                if (!exists(input_file))
131✔
813
                {
814
                        input_file = formPath<string>(p.g.input_folder, input_file);
3✔
815
                        if (!exists(input_file))
3✔
816
                        {        
817
                                cout << "- Error:  " << input_file << " does not exist" << endl;
3✔
818
                                return EXIT_FAILURE;
3✔
819
                        }
820
                }
821
                        
822
                input_files.push_back(input_file);
128✔
823
                ss = leafStr<string>(p.i.input_files.at(i)) + "... ";
128✔
824
                if (!p.g.quiet)
128✔
825
                        cout << "  " << setw(strlen_arg) << left << ss;
126✔
826
                *imp_file << "  " << setw(strlen_arg) << left << ss;
128✔
827

828
                running = true;
128✔
829
                thread_group ui_interop_threads;
128✔
830
                if (!p.g.quiet)
128✔
831
                        ui_interop_threads.create_thread(dna_import_progress_thread(&parserDynaML, &p));
126✔
832
                ui_interop_threads.create_thread(dna_import_thread(&parserDynaML, &p, input_file,
128✔
833
                        vStations, &stnCount, vMeasurements, &msrCount,
834
                        &clusterID, &input_file_meta, &status_msg,
835
                        &elapsed_time));
836
                ui_interop_threads.join_all();
128✔
837

838
                switch (parserDynaML.GetStatus())
128✔
839
                {
840
                case PARSE_EXCEPTION_RAISED:
×
841
                        *imp_file << endl << status_msg;
×
842
                        running = false;
×
843
                        return EXIT_FAILURE;
×
844
                        break;
×
845
                case PARSE_UNRECOGNISED_FILE:
×
846
                        *imp_file << status_msg << endl;
×
847
                        errorCount++;
×
848
                        continue;
×
849
                case PARSE_SUCCESS:
128✔
850
                        running = false;
128✔
851
                        break;
128✔
852
                default:
×
853
                        errorCount++;
×
854
                        cout << endl;
×
855
                        continue;
×
856
                }
857

858
                vinput_file_meta->push_back(input_file_meta);
128✔
859

860
                ss_time.str("");
256✔
861

862
                if (stnCount > 0 || msrCount > 0) // stations or measurements only
128✔
863
                {                        
864
                        ss_time << "  Done. Loaded ";
126✔
865
                        if (stnCount)
126✔
866
                                ss_time << stnCount << " stations";
64✔
867
                        if (stnCount && msrCount)
126✔
868
                                ss_time << " and ";
8✔
869
                        if (msrCount)
126✔
870
                                ss_time << msrCount << " measurements";
70✔
871
                        ss_time << " in ";
126✔
872
                                
873
                        pt = ptime(gregorian::day_clock::local_day(), elapsed_time);
126✔
874
                        if (elapsed_time < seconds(3))
126✔
875
                        {
876
                                time_facet* facet(new time_facet("%s"));
126✔
877
                                ss_time.imbue(locale(ss_time.getloc(), facet));
126✔
878
                                ss_time << pt << "s";                        
126✔
879
                        }
880
                        else if (elapsed_time < seconds(61))
×
881
                        {                
882
                                time_facet* facet(new time_facet("%S"));
×
883
                                ss_time.imbue(locale(ss_time.getloc(), facet));
×
884
                                ss_time << pt << "s";
×
885
                        }
886
                        else
887
                                ss_time << elapsed_time;
×
888

889
                        string time_message = ss_time.str();
126✔
890
                        while ((pos = time_message.find("0s")) != string::npos)
609✔
891
                                time_message = time_message.substr(0, pos) + "s";
483✔
892

893
                        if ((pos = time_message.find(" 00.")) != string::npos)
126✔
894
                                time_message = time_message.replace(pos, 4, " 0.");
126✔
895
                        if ((pos = time_message.find(" 0.s")) != string::npos)
126✔
896
                                time_message = time_message.replace(pos, 4, " 0s");
31✔
897

898
                        if (!p.g.quiet)
126✔
899
                        {
900
                                if (isatty(fileno(stdout)))
124✔
901
                                        cout << PROGRESS_BACKSPACE_04;
×
902
                                cout << time_message << endl;
124✔
903
                        }
904
                        *imp_file << time_message << endl;
126✔
905

906
                        // Produce a warning if the input file's default reference frame
907
                        // is different to the project reference frame
908
                        string inputFileEpsg;
126✔
909
                        try {
126✔
910
                                inputFileEpsg = datumFromEpsgString<string>(input_file_meta.epsgCode);
126✔
911
                        }
912
                        catch (...) {
×
913
                                inputFileEpsg = epsgCode;
×
914
                        }
×
915

916
                        if (!iequals(epsgCode, input_file_meta.epsgCode))
126✔
917
                        {
918
                                stringstream ssEpsgWarning;
55✔
919
                                
920
                                ssEpsgWarning << "- Warning: Input file reference frame (" << inputFileEpsg <<
55✔
921
                                        ") does not match the " << endl << "  default reference frame.";
55✔
922
                                if (!p.g.quiet)
55✔
923
                                        cout << ssEpsgWarning.str() << endl;
53✔
924
                                *imp_file << ssEpsgWarning.str() << endl;
55✔
925
                        }
55✔
926
                }
126✔
927

928
                // Handle discontinuities for non-sinex files, if and only if a discontinuity file has been loaded.
929
                // NOTE: If a station is marked as a discontinuity site, and that same station is in the renaming
930
                // file, station renaming for that site will not occur.  This is because the site name will be changed
931
                // to <site-name>_yyyymmdd.
932
                // If renaming must still occur, then it might be possible to rename using the first part of the name.
933
                
934

935
                if (stnCount > 0) // stations only
128✔
936
                {
937
                        //vstationsTotal.reserve(vstationsTotal.size() + stnCount);
938
                        // combine stations and station tally
939
                        vstationsTotal->insert(vstationsTotal->end(), vStations->begin(), vStations->end());
64✔
940
                        *parsestnTally += parserDynaML.GetStnTally();
64✔
941
                        vStations->clear();
64✔
942
                }
943
                if (msrCount > 0) // measurements only
128✔
944
                {                
945
                        //vmeasurementsTotal.reserve(vmeasurementsTotal.size() + msrCount);
946
                        // combine measurements
947
                        vmeasurementsTotal->insert(vmeasurementsTotal->end(), vMeasurements->begin(), vMeasurements->end());
70✔
948
                        *parsemsrTally += parserDynaML.GetMsrTally();
70✔
949
                        vMeasurements->clear();
70✔
950
                }
951
        }
128✔
952

953
        if (errorCount == nfiles || (vstationsTotal->empty() && vmeasurementsTotal->empty()))
54✔
954
                return EXIT_FAILURE;
955

956
        running = false;
53✔
957
        return EXIT_SUCCESS;
53✔
958
}
57✔
959

960
int main(int argc, char* argv[])
81✔
961
{
962
        // create banner message
963
        string cmd_line_banner;
81✔
964
        fileproc_help_header(&cmd_line_banner);
81✔
965

966
        project_settings p;
81✔
967

968
        variables_map vm;
81✔
969
        positional_options_description positional_options;
81✔
970

971
        options_description standard_options("+ " + string(ALL_MODULE_STDOPT), PROGRAM_OPTIONS_LINE_LENGTH);
162✔
972
        options_description ref_frame_options("+ " + string(IMPORT_MODULE_FRAME), PROGRAM_OPTIONS_LINE_LENGTH);
162✔
973
        options_description data_screening_options("+ " + string(IMPORT_MODULE_SCREEN), PROGRAM_OPTIONS_LINE_LENGTH);
162✔
974
        options_description gnss_scaling_options("+ " + string(IMPORT_MODULE_GNSS_VAR), PROGRAM_OPTIONS_LINE_LENGTH);
162✔
975
        options_description simulation_options("+ " + string(IMPORT_MODULE_SIMULATE), PROGRAM_OPTIONS_LINE_LENGTH);
162✔
976
        options_description output_options("+ " + string(ALL_MODULE_OUTPUT), PROGRAM_OPTIONS_LINE_LENGTH);
162✔
977
        options_description export_options("+ " + string(ALL_MODULE_EXPORT), PROGRAM_OPTIONS_LINE_LENGTH);
162✔
978
        options_description generic_options("+ " + string(ALL_MODULE_GENERIC), PROGRAM_OPTIONS_LINE_LENGTH);
162✔
979

980
        string cmd_line_usage("+ ");
81✔
981
        cmd_line_usage.append(__BINARY_NAME__).append(" usage:  ").append(__BINARY_NAME__).append(" [options] [files]...");
81✔
982
        options_description allowable_options(cmd_line_usage, PROGRAM_OPTIONS_LINE_LENGTH);
81✔
983

984
        try {
81✔
985
                // Declare a group of options that will be 
986
                // allowed only on command line                
987
                standard_options.add_options()
81✔
988
                        (PROJECT_FILE_P, value<string>(&p.g.project_file),
81✔
989
                                "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.")
990
                        (NETWORK_NAME_N, value<string>(&p.g.network_name), 
81✔
991
                                "Network name. User defined name for all input and output files. Default is \"network#\", where # is incremented until the first available network is reached.")
992
                        (IMPORT_FILE_F, value< vstring >(&p.i.input_files), 
81✔
993
                                "Station and measurement input file(s). Switch is not required.")
994
                        (IMPORT_GEO_FILE_G, value<string>(&p.i.geo_file),
81✔
995
                                "Import DNA geoid file.")
996
                        (INPUT_FOLDER_I, value<string>(&p.g.input_folder),
81✔
997
                                "Path containing all input files.")
998
                        (OUTPUT_FOLDER_O, value<string>(&p.g.output_folder),                // default is ./,
81✔
999
                                "Path for all output files.")
1000
                        (BIN_STN_FILE_S, value<string>(&p.i.bst_file),
81✔
1001
                                "Binary station output file name. Overrides network name.")
1002
                        (BIN_MSR_FILE_M, value<string>(&p.i.bms_file),
81✔
1003
                                "Binary measurement output file name. Overrides network name.")
1004
                        ;
1005

1006
                ref_frame_options.add_options()
81✔
1007
                        (REFERENCE_FRAME_R, value<string>(&p.i.reference_frame), 
81✔
1008
                        (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 ") +
162✔
1009
                                p.i.reference_frame + ".").c_str())
162✔
1010
                        (OVERRIDE_INPUT_FRAME,
81✔
1011
                                "Override the reference frame specified for each measurement in input files.")
1012
                        ;
1013

1014
                data_screening_options.add_options()
81✔
1015
                        (BOUNDING_BOX, value<string>(&p.i.bounding_box),
81✔
1016
                                "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.")
1017
                        (GET_MSRS_TRANSCENDING_BOX,
81✔
1018
                                "Include measurements which transcend bounding box, including associated stations.")
1019
                        (INCLUDE_STN_ASSOC_MSRS, value<string>(&p.i.stn_associated_msr_include),
81✔
1020
                                "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.")
1021
                        (EXCLUDE_STN_ASSOC_MSRS, value<string>(&p.i.stn_associated_msr_exclude),
81✔
1022
                                "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.")
1023
                        (SPLIT_CLUSTERS,
81✔
1024
                                "Allow bounding-box or get-stns-and-assoc-msrs to split GNSS point and baseline cluster measurements.")
1025
                        (IMPORT_SEG_BLOCK, value<UINT32>(&p.i.import_block_number),
81✔
1026
                                "Extract stations and measurements from this block.")
1027
                        (IMPORT_CONTIG_NET, value<UINT32>(&p.i.import_network_number),
81✔
1028
                                "Extract stations and measurements from this contiguous network.")
1029
                        (SEG_FILE, value<string>(&p.i.seg_file),
81✔
1030
                                "Network segmentation input file. Filename overrides network name.")
1031
                        (PREFER_X_MSR_AS_G,
81✔
1032
                                "Import single baseline cluster measurements (X) as single baselines (G).")
1033
                        (INCLUDE_MSRS, value<string>(&p.i.include_msrs),
81✔
1034
                                "Import the specified measurement types. arg is a non-delimited string of measurement types (eg \"GXY\").")
1035
                        (EXCLUDE_MSRS, value<string>(&p.i.exclude_msrs),
81✔
1036
                                "Exclude the specified measurement types. arg is a non-delimited string of measurement typs (eg \"IJK\").")
1037
                        (STATION_RENAMING_FILE, value<string>(&p.i.stn_renamingfile),
81✔
1038
                                "Station renaming file")
1039
                        (STATION_DISCONTINUITY_FILE, value<string>(&p.i.stn_discontinuityfile),
81✔
1040
                                "Station discontinuity file.  Applies discontinuity dates to station names in station and measurement files.")
1041
                        (TEST_NEARBY_STNS,
81✔
1042
                                "Search for nearby stations.")
1043
                        (TEST_NEARBY_STN_DIST, value<double>(&p.i.search_stn_radius),
81✔
1044
                                (string("Specify the radius of the circle within which to search for nearby stations.  Default is ")+
162✔
1045
                                StringFromT(STN_SEARCH_RADIUS)+string("m")).c_str())
324✔
1046
                        (TEST_SIMILAR_GNSS_MSRS,
81✔
1047
                                "Search and provide warnings for GNSS baselines (G) and baseline clusters (X) which appear to have been derived from the same source data.")
1048
                        (TEST_SIMILAR_MSRS,
81✔
1049
                                "Search and provide warnings for similar measurements.")
1050
                        (IGNORE_INSUFFICIENT_MSRS,
81✔
1051
                                "Ignore measurements which do not sufficiently constrain a station in two dimensions.")
1052
                        (IGNORE_SIMILAR_MSRS,
81✔
1053
                                "Ignore similar measurements.")
1054
                        (REMOVE_IGNORED_MSRS,
81✔
1055
                                "Remove ignored measurements.")
1056
                        (FLAG_UNUSED_STNS,
81✔
1057
                                "Mark unused stations in binary file.  Stations marked will be excluded from any further processing.")
1058
                        (TEST_INTEGRITY,
81✔
1059
                                "Test the integrity of the association lists and binary files.")
1060
                        ;
1061

1062
                gnss_scaling_options.add_options()
81✔
1063
                        (VSCALE, value<double>(&p.i.vscale),
81✔
1064
                                (string("Global variance (v) matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
162✔
1065
                                StringFromT(p.i.vscale)+string(".")).c_str())
324✔
1066
                        (PSCALE, value<double>(&p.i.pscale),
81✔
1067
                                (string("Latitude (p=phi) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
162✔
1068
                                StringFromT(p.i.pscale)+string(".")).c_str())
324✔
1069
                        (LSCALE, value<double>(&p.i.lscale),
81✔
1070
                                (string("Longitude (l=lambda) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
162✔
1071
                                StringFromT(p.i.lscale)+string(".")).c_str())
324✔
1072
                        (HSCALE, value<double>(&p.i.hscale),
81✔
1073
                                (string("Height (h) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
162✔
1074
                                StringFromT(p.i.hscale)+string(".")).c_str())
324✔
1075
                        (SCALAR_FILE, value<string>(&p.i.scalar_file),
81✔
1076
                                "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.")
1077
                        ;
1078

1079
                output_options.add_options()
81✔
1080
                        (OUTPUT_MSR_TO_STN,
81✔
1081
                                "Output summary of measurements connected to each station.")
1082
                        (OUTPUT_MSR_TO_STN_SORTBY, value<UINT16>(&p.o._sort_msr_to_stn),
81✔
1083
                                string("Sort order for measurement to stations summary.\n  " +
324✔
1084
                                        StringFromT(orig_stn_sort_ui) + ": Original station order (default)\n  " +
324✔
1085
                                        StringFromT(meas_stn_sort_ui) + ": Measurement count").c_str())
81✔
1086
                        ;
1087

1088
                export_options.add_options()
81✔
1089
                        (EXPORT_XML_FILES,
81✔
1090
                                "Export stations and measurements to DynaML (DynAdjust XML) format.")
1091
                        (EXPORT_SINGLE_XML_FILE,
81✔
1092
                                "Create a single DynaML file for stations and measurements.")
1093
                        // Nice, but somewhat redundant functionality that offers no
1094
                        // benefit to the user
1095
                        //(EXPORT_FROM_BINARY,
1096
                        //        "Create DynaML output file using binary files. Default option uses internal memory.")
1097
                        (EXPORT_DNA_FILES,
81✔
1098
                                "Export stations and measurements to DNA STN and MSR format.")
1099
                        (EXPORT_ASL_FILE,
81✔
1100
                                "Export the ASL file as raw text.")
1101
                        (EXPORT_AML_FILE,
81✔
1102
                                "Export the AML file as raw text.")
1103
                        (EXPORT_MAP_FILE,
81✔
1104
                                "Export the MAP file as raw text.")
1105
                        (EXPORT_DISCONT_FILE,
81✔
1106
                                "Export discontinuity information as raw text.")
1107
                        ;
1108

1109
                simulation_options.add_options()
81✔
1110
                        (SIMULATE_MSR_FILE,
81✔
1111
                                "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.")
1112
                        ;
1113

1114
                generic_options.add_options()
81✔
1115
                        (VERBOSE, value<UINT16>(&p.g.verbose),
81✔
1116
                                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())
81✔
1117
                        (QUIET,
81✔
1118
                                string("Suppresses all explanation of what ").append(__BINARY_NAME__).append(" is doing unless an error occurs.").c_str())
162✔
1119
                        (VERSION_V, "Display the current program version.")
81✔
1120
                        (HELP_H, "Show this help message.")
81✔
1121
                        (HELP_MODULE, value<string>(),
81✔
1122
                                "Provide help for a specific help category.")
1123
                        ;
1124

1125
                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);
81✔
1126

1127
                // add "positional options" to handle command line tokens which have no option name
1128
                positional_options.add(IMPORT_FILE, -1);
81✔
1129
                
1130
                command_line_parser parser(argc, argv);
81✔
1131
                store(parser.options(allowable_options).positional(positional_options).run(), vm);
81✔
1132
                notify(vm);
80✔
1133
        }
1✔
1134
        catch(const std::exception& e) 
1✔
1135
        {
1136
                cout << "- Error: " << e.what() << endl;
1✔
1137
                cout << cmd_line_banner << allowable_options << endl;
1✔
1138
                return EXIT_FAILURE;
1✔
1139
        }
1✔
1140
        catch (...) 
×
1141
        {
1142
                cout << "+ Exception of unknown type!\n";
×
1143
                return EXIT_FAILURE;
×
1144
        }
×
1145

1146
        if (argc < 2)
80✔
1147
        {
1148
                cout << endl << "- Nothing to do - no options provided. " << endl << endl;  
1✔
1149
                cout << cmd_line_banner << allowable_options << endl;
1✔
1150
                return EXIT_FAILURE;
1151
        }
1152

1153
        if (vm.count(VERSION))
79✔
1154
        {
1155
                cout << cmd_line_banner << endl;
1✔
1156
                return EXIT_SUCCESS;
1157
        }
1158

1159
        if (vm.count(HELP))
78✔
1160
        {
1161
                cout << cmd_line_banner << allowable_options << endl;
1✔
1162
                return EXIT_SUCCESS;
1163
        }
1164

1165
        if (vm.count(HELP_MODULE)) 
77✔
1166
        {
1167
                cout << cmd_line_banner;
9✔
1168
                string original_text = vm[HELP_MODULE].as<string>();
18✔
1169
                string help_text = str_upper<string>(original_text);
9✔
1170
                
1171
                if (str_upper<string, char>(ALL_MODULE_STDOPT).find(help_text) != string::npos) {
18✔
1172
                        cout << standard_options << endl;
1✔
1173
                }
1174
                else if (str_upper<string, char>(IMPORT_MODULE_FRAME).find(help_text) != string::npos) {
16✔
1175
                        cout << ref_frame_options << endl;
1✔
1176
                } 
1177
                else if (str_upper<string, char>(IMPORT_MODULE_SCREEN).find(help_text) != string::npos) {
14✔
1178
                        cout << data_screening_options << endl;
1✔
1179
                } 
1180
                else if (str_upper<string, char>(IMPORT_MODULE_GNSS_VAR).find(help_text) != string::npos) {
12✔
1181
                        cout << gnss_scaling_options << endl;
1✔
1182
                } 
1183
                else if (str_upper<string, char>(IMPORT_MODULE_SIMULATE).find(help_text) != string::npos) {
10✔
1184
                        cout << simulation_options << endl;
1✔
1185
                } 
1186
                else if (str_upper<string, char>(ALL_MODULE_OUTPUT).find(help_text) != string::npos) {
8✔
1187
                        cout << output_options << endl;
1✔
1188
                } 
1189
                else if (str_upper<string, char>(ALL_MODULE_EXPORT).find(help_text) != string::npos) {
6✔
1190
                        cout << export_options << endl;
1✔
1191
                } 
1192
                else if (str_upper<string, char>(ALL_MODULE_GENERIC).find(help_text) != string::npos) {
4✔
1193
                        cout << generic_options << endl;
1✔
1194
                } 
1195
                else {
1196
                        cout << endl << "- Error: Help module '" <<
1✔
1197
                                original_text << "' is not in the list of options." << endl;
9✔
1198
                        return EXIT_FAILURE;
1199
                }
1200

1201
                return EXIT_SUCCESS;
8✔
1202
        }
9✔
1203

1204
        bool userSuppliedSegFile(false);
68✔
1205
        if (!p.i.seg_file.empty())
68✔
1206
                userSuppliedSegFile = true;
1✔
1207
        bool userSuppliedBstFile(false);
68✔
1208
        if (!p.i.bst_file.empty())
68✔
1209
                userSuppliedBstFile = true;
×
1210
        bool userSuppliedBmsFile(false);
68✔
1211
        if (!p.i.bms_file.empty())
68✔
1212
                userSuppliedBmsFile = true;
×
1213

1214
        if (ParseCommandLineOptions(argc, argv, vm, p) != EXIT_SUCCESS)
68✔
1215
                return EXIT_FAILURE;
1216

1217
        UINT32 errorCount(0);
66✔
1218
        bool stn_map_created = false, measurements_mapped = false;
66✔
1219

1220
        string input_file;
66✔
1221
        vstring input_files;
66✔
1222
        string status_msg;
66✔
1223

1224
        std::ofstream imp_file;
66✔
1225
        try {
66✔
1226
                // Create import log file.  Throws runtime_error on failure.
1227
                file_opener(imp_file, p.i.imp_file);
66✔
1228
        }
1229
        catch (const runtime_error& e) {
×
1230
                stringstream ss;
×
1231
                ss << "- Error: Could not open " << p.i.imp_file << ". \n  Check that the file exists and that the file is not already opened." << endl;
×
1232
                cout << ss.str() << e.what() << endl;
×
1233
                return EXIT_FAILURE;
×
1234
        }
×
1235

1236
        vdnaStnPtr vStations, vstationsTotal;
66✔
1237
        vdnaMsrPtr vMeasurements, vmeasurementsTotal;
66✔
1238
        vdnaMsrPtr::iterator _itm;
66✔
1239
        vASLPtr associatedSL;
66✔
1240
        vUINT32 associatedML;
66✔
1241
        v_string_uint32_pair vStnsMap_sortName;        // Station Name Map sorted on name (string)
66✔
1242
        
1243
        vstationsTotal.clear();
66✔
1244
        vmeasurementsTotal.clear();
66✔
1245

1246
        if (vm.count(QUIET))
66✔
1247
                p.g.quiet = 1;
1✔
1248
        
1249
        if (!p.g.quiet)
66✔
1250
        {
1251
                cout << endl << cmd_line_banner;
65✔
1252

1253
                cout << "+ Options:" << endl; 
65✔
1254
                cout << setw(PRINT_VAR_PAD) << left << "  Network name: " <<  p.g.network_name << endl;
65✔
1255
                cout << setw(PRINT_VAR_PAD) << left << "  Input folder: " << p.g.input_folder << endl;
65✔
1256
                cout << setw(PRINT_VAR_PAD) << left << "  Output folder: " << p.g.output_folder << endl;
65✔
1257
                cout << setw(PRINT_VAR_PAD) << left << "  Associated station file: " << p.i.asl_file << endl;
65✔
1258
                cout << setw(PRINT_VAR_PAD) << left << "  Associated measurement file: " << p.i.aml_file << endl;
65✔
1259
                cout << setw(PRINT_VAR_PAD) << left << "  Binary station output file: " << p.i.bst_file << endl;
65✔
1260
                cout << setw(PRINT_VAR_PAD) << left << "  Binary measurement output file: " << p.i.bms_file << endl;
65✔
1261
                
1262
                if (!p.i.reference_frame.empty())
65✔
1263
                        cout << setw(PRINT_VAR_PAD) << left << "  Default reference frame:" << p.i.reference_frame << endl;
65✔
1264
        
1265
                if (p.i.override_input_rfame)
65✔
1266
                        cout << setw(PRINT_VAR_PAD) << left << "  Override input file ref frame:" << yesno_string(p.i.override_input_rfame) << endl;
8✔
1267

1268
                if (p.i.export_dynaml)
65✔
1269
                {
1270
                        if (p.i.export_single_xml_file)
10✔
1271
                                cout << setw(PRINT_VAR_PAD) << left << "  DynaML output file: " << p.i.xml_outfile << endl;
2✔
1272
                        else
1273
                        {
1274
                                cout << setw(PRINT_VAR_PAD) << left << "  DynaML station file: " << p.i.xml_stnfile << endl;
8✔
1275
                                cout << setw(PRINT_VAR_PAD) << left << "  DynaML measurement file: " << p.i.xml_msrfile << endl;
8✔
1276
                        }                                
1277
                }
1278
                if (p.i.export_dna_files)
65✔
1279
                {
1280
                        cout << setw(PRINT_VAR_PAD) << left << "  DNA station file: " << p.i.dna_stnfile << endl;
12✔
1281
                        cout << setw(PRINT_VAR_PAD) << left << "  DNA measurement file: " << p.i.dna_msrfile << endl;
12✔
1282
                }
1283

1284
                if (p.i.simulate_measurements)
65✔
1285
                {
1286
                        cout << setw(PRINT_VAR_PAD) << left << "  DNA simulated msr file: " << p.i.simulate_msrfile << endl;
1✔
1287
                }
1288
                
1289
                if (!p.i.bounding_box.empty())
65✔
1290
                {
1291
                        cout << setw(PRINT_VAR_PAD) << left << "  Bounding box: " << p.i.bounding_box << endl;
1✔
1292
                        if (p.i.split_clusters)
1✔
1293
                                cout << setw(PRINT_VAR_PAD) << left << "  Split GNSS clusters: " << (p.i.split_clusters ? "Yes" : "No") << endl;
1✔
1294
                }
1295
                else
1296
                {
1297
                        if (!p.i.stn_associated_msr_include.empty())
64✔
1298
                                cout << setw(PRINT_VAR_PAD) << left << "  Stations to include: " << p.i.stn_associated_msr_include << endl;
5✔
1299
                        if (!p.i.stn_associated_msr_exclude.empty())
64✔
1300
                                cout << setw(PRINT_VAR_PAD) << left << "  Stations to exclude: " << p.i.stn_associated_msr_exclude << endl;
1✔
1301
                        
1302
                        if (p.i.split_clusters)
64✔
1303
                                cout << setw(PRINT_VAR_PAD) << left << "  Split GNSS clusters: " << (p.i.split_clusters ? "Yes" : "No") << endl;
4✔
1304
                }
1305
                
1306
                if (p.i.import_block)
65✔
1307
                {
1308
                        if (!p.i.seg_file.empty())
6✔
1309
                                cout << setw(PRINT_VAR_PAD) << left << "  Segmentation file: " << p.i.seg_file << endl;
1✔
1310
                        cout << setw(PRINT_VAR_PAD) << left << "  Import stns & msrs from block: " << p.i.import_block_number << endl;
6✔
1311
                }
1312
                else if (p.i.import_network)
59✔
1313
                {
1314
                        if (!p.i.seg_file.empty())
2✔
1315
                                cout << setw(PRINT_VAR_PAD) << left << "  Segmentation file: " << p.i.seg_file << endl;
×
1316
                        cout << setw(PRINT_VAR_PAD) << left << "  Import stns & msrs from network: " << p.i.import_network_number << endl;
2✔
1317
                }
1318

1319
                if (!p.i.scalar_file.empty())
65✔
1320
                        cout << setw(PRINT_VAR_PAD) << left << "  GNSS baseline scalar file: " << p.i.scalar_file << endl;
1✔
1321
                
1322
                cout << endl;
65✔
1323
        }
1324

1325
        PrintOutputFileHeaderInfo(&imp_file, p.i.imp_file, &p, "DYNADJUST IMPORT LOG FILE");
66✔
1326

1327
        dna_import parserDynaML;
66✔
1328
        MsrTally parsemsrTally;
66✔
1329
        StnTally parsestnTally;
66✔
1330

1331
        CDnaProjection projection(UTM);
66✔
1332

1333
        vifm_t vinput_file_meta;
66✔
1334

1335
        // First things first!
1336
        // Set the 'default' reference frame for the binary station and measurement files
1337
        try {
66✔
1338
                // Initialise the 'default' datum for the project.
1339
                parserDynaML.InitialiseDatum(p.i.reference_frame);
66✔
1340
        }
1341
        catch (const XMLInteropException& e) {
1✔
1342
                stringstream ss;
1✔
1343
                ss << "- Error: ";
1✔
1344
                cout << ss.str() << e.what() << endl;
1✔
1345
                return EXIT_FAILURE;
1✔
1346
        }
1✔
1347

1348
        // obtain the project reference frame
1349
        UINT32 epsgCode(epsgCodeFromName<UINT32>(p.i.reference_frame));
65✔
1350

1351
        // set the default output reference frame and epoch, so that
1352
        // if adjust is called without reftran, it reflects the datum 
1353
        // supplied on import
1354
        p.r.reference_frame = p.i.reference_frame;
65✔
1355
        p.r.epoch = referenceepochFromEpsgCode<UINT32>(epsgCode);
65✔
1356

1357
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////
1358
        // start "total" time
1359
        cpu_timer time;
65✔
1360
        
1361
        
1362
        // Import discontinuity file and apply discontinuities
1363
        // Due to the structure and format of SINEX files, it is essential that
1364
        // discontinuities be parsed prior to reading any SINEX files.
1365
        if (vm.count(STATION_DISCONTINUITY_FILE))
65✔
1366
        {
1367
                p.i.apply_discontinuities = true;
4✔
1368
                
1369
                // Does it exist?
1370
                if (!exists(p.i.stn_discontinuityfile))
4✔
1371
                {
1372
                        path discontPath(p.i.stn_discontinuityfile);
×
1373
                        stringstream ss;
×
1374
                        ss << "- Warning: The station discontinuity file " << discontPath.filename().string() << " does not exist... ignoring discontinuity input." << endl;
×
1375
                        imp_file << endl << ss.str();
×
1376
                }
×
1377
                else
1378
                {
1379
                        if (!p.g.quiet)
4✔
1380
                        {
1381
                                cout << "+ Importing station discontinuities from " << p.i.stn_discontinuityfile << "... ";
4✔
1382
                                cout.flush();
4✔
1383
                        }
1384
                        imp_file << "+ Importing station discontinuities from " << p.i.stn_discontinuityfile << "... ";
4✔
1385

1386
                        parserDynaML.ParseDiscontinuities(p.i.stn_discontinuityfile);
4✔
1387

1388
                        if (!p.g.quiet)
4✔
1389
                                cout << "Done." << endl;
4✔
1390
                        imp_file << "Done." << endl;
4✔
1391
                }
1392

1393
                if (p.i.export_discont_file)
4✔
1394
                {
1395
                        if (!p.g.quiet)
1✔
1396
                        {
1397
                                cout << "+ Exporting discontinuity information to text file... ";
1✔
1398
                                cout.flush();
1✔
1399
                        }
1400
                        imp_file << "+ Exporting discontinuity information to text file... ";
1✔
1401
                        parserDynaML.SerialiseDiscontTextFile(p.i.stn_discontinuityfile);
1✔
1402
                        if (!p.g.quiet)
1✔
1403
                        {
1404
                                cout << "Done." << endl;
1✔
1405
                                cout.flush();
1✔
1406
                        }
1407
                        imp_file << "Done." << endl;
1✔
1408
                }
1409
        }
1410

1411
        // Import network information based on a segmentation block?
1412
        if (p.i.import_block)
65✔
1413
        {
1414
                imp_file << "+ Extracting stations and measurements from segmented block " << 
6✔
1415
                        p.i.import_block_number << "... ";
6✔
1416
                
1417
                if (ImportSegmentedBlock(parserDynaML, &vstationsTotal, &vmeasurementsTotal, 
6✔
1418
                        &parsestnTally, &parsemsrTally, p) != EXIT_SUCCESS)
1419
                        return EXIT_FAILURE;
1420

1421
                imp_file << "Done." << endl;
5✔
1422
        }
1423
        // Import network information based on a contiguous network?
1424
        else if (p.i.import_network)
59✔
1425
        {
1426
                imp_file << "+ Extracting stations and measurements from contiguous network " <<
2✔
1427
                        p.i.import_network_number << "... ";
2✔
1428
                
1429
                if (ImportContiguousNetwork(parserDynaML, &vstationsTotal, &vmeasurementsTotal,
2✔
1430
                        &parsestnTally, &parsemsrTally, p) != EXIT_SUCCESS)
1431
                        return EXIT_FAILURE;
1432

1433
                imp_file << "Done." << endl;
1✔
1434
        }
1435
        // Import data as normal
1436
        else
1437
        {
1438
                // Import all data as-is.
1439
                // All filtering is performed later below
1440
                if (ImportDataFiles(parserDynaML, &vStations, &vMeasurements, &vstationsTotal, &vmeasurementsTotal,
57✔
1441
                        &imp_file, &vinput_file_meta, &parsestnTally, &parsemsrTally, errorCount, p) != EXIT_SUCCESS)
1442
                        return EXIT_FAILURE;
1443
        }        
1444

1445
        if (!p.g.quiet)
59✔
1446
                cout << endl;
58✔
1447

1448
        // Now, set the 'default' epoch in the binary station and measurement files
1449
        try {
59✔
1450
                // Initialise the 'default' datum for the project.
1451
                parserDynaML.UpdateEpoch(&vinput_file_meta);
59✔
1452
        }
1453
        catch (const XMLInteropException& e) {
×
1454
                stringstream ss;
×
1455
                ss << "- Error: ";
×
1456
                cout << ss.str() << e.what() << endl;
×
1457
                return EXIT_FAILURE;
×
1458
        }
×
1459

1460
        vstring vPoorlyConstrainedStns;
59✔
1461

1462
        // Ignore measurements that do not sufficiently (in themselves) allow for a station to be estimated
1463
        if (p.i.ignore_insufficient_msrs == 1)
59✔
1464
        {
1465
                size_t msrCount = vmeasurementsTotal.size();
×
1466
                if (!p.g.quiet)
×
1467
                {
1468
                        cout << "+ Identifying stations with insufficient measurements";
×
1469
                        cout.flush();
×
1470
                }
1471
                imp_file << "+ Identifying stations with insufficient measurements...";
×
1472
                parserDynaML.IgnoreInsufficientMeasurements(&vstationsTotal, &vmeasurementsTotal, &vPoorlyConstrainedStns);
×
1473
                if (!p.g.quiet)
×
1474
                {
1475
                        cout << " Done. " << endl;
×
1476
                        if (msrCount > vmeasurementsTotal.size())
×
1477
                                cout << "+ Removed " << (msrCount - vmeasurementsTotal.size()) << " measurements which alone do not sufficiently allow for" << endl <<
×
1478
                                        "  the estimation of 2D coordinates." << endl;
×
1479

1480
                }
1481
                imp_file << " Done. " << endl;
×
1482
                if (msrCount > vmeasurementsTotal.size())
×
1483
                        imp_file << "+ Removed " << (msrCount - vmeasurementsTotal.size()) << " measurements which alone do not sufficiently allow for" << endl <<
×
1484
                                "  the estimation of 2D coordinates." << endl;
×
1485

1486
                if (!vPoorlyConstrainedStns.empty())
×
1487
                {
1488
                        if (vPoorlyConstrainedStns.size() == 1)
×
1489
                        {
1490
                                if (p.g.verbose > 2)
×
1491
                                {
1492
                                        if (!p.g.quiet)
×
1493
                                                cout << "- Warning: station " << vPoorlyConstrainedStns.at(0) << " is not associated with sufficient measurements." << endl;
×
1494
                                        imp_file << "- Warning: station " << vPoorlyConstrainedStns.at(0) << " is not associated with sufficient measurements." << endl;
×
1495
                                }
1496
                                else
1497
                                {
1498
                                        if (!p.g.quiet)
×
1499
                                                cout << "- Warning: 1 station is not associated with sufficient measurements." << endl;
×
1500
                                        imp_file << "- Warning: 1 station is not associated with sufficient measurements." << endl;
×
1501
                                }
1502
                        }
1503
                        else
1504
                        {
1505
                                if (p.g.verbose > 2)
×
1506
                                {
1507
                                        if (!p.g.quiet)
×
1508
                                                cout << "- Warning: The following " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << endl;
×
1509
                                        imp_file << "- Warning: The following " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << endl;
×
1510
                                        _it_vstr poorly;
×
1511
                                        for (poorly = vPoorlyConstrainedStns.begin(); poorly != vPoorlyConstrainedStns.end(); poorly++)
×
1512
                                        {
1513
                                                if (!p.g.quiet)
×
1514
                                                        outputObject(string("  - " + *poorly + "\n"), cout);
×
1515
                                                outputObject(string("  - " + *poorly + "\n"), imp_file);
×
1516
                                        }
1517
                                }
1518
                                else
1519
                                {
1520
                                        if (!p.g.quiet)
×
1521
                                                cout << "- Warning: " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << endl;
×
1522
                                        imp_file << "- Warning: " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << endl;
×
1523
                                }
1524
                        }
1525
                }
1526
        }
1527

1528
        // Remove ignored measurements (if supplied)
1529
        if (p.i.remove_ignored_msr)
59✔
1530
        {
1531
                if (!p.g.quiet)
1✔
1532
                {
1533
                        cout << "+ Removing ignored measurements... ";
1✔
1534
                        cout.flush();
1✔
1535
                }
1536
                imp_file << "+ Removing ignored measurements... ";
1✔
1537
                parserDynaML.RemoveIgnoredMeasurements(&vmeasurementsTotal, &parsemsrTally);
1✔
1538
                if (!p.g.quiet)
1✔
1539
                        cout << "Done. " << endl;
1✔
1540
                imp_file << "Done. " << endl;
1✔
1541
        }
1542

1543
        // Strip all measurements except required measurements (if supplied)
1544
        if (!p.i.include_msrs.empty())
59✔
1545
        {
1546
                if (!p.g.quiet)
2✔
1547
                {
1548
                        cout << "+ Stripping all measurements except types " << p.i.include_msrs << "... ";
2✔
1549
                        cout.flush();
2✔
1550
                }
1551
                imp_file << "+ Stripping all measurements except types " << p.i.include_msrs << "... ";
2✔
1552
                parserDynaML.IncludeMeasurementTypes(p.i.include_msrs, &vmeasurementsTotal, &parsemsrTally);
2✔
1553
                if (!p.g.quiet)
2✔
1554
                        cout << "Done. " << endl;
2✔
1555
                imp_file << "Done. " << endl;
2✔
1556
        }
1557
        
1558
        // Strip all unwanted measurements (if supplied)
1559
        if (!p.i.exclude_msrs.empty())
59✔
1560
        {
1561
                if (!p.g.quiet)
2✔
1562
                {
1563
                        cout << "+ Stripping measurement types " << p.i.exclude_msrs << "... ";
2✔
1564
                        cout.flush();
2✔
1565
                }
1566
                imp_file << "+ Stripping measurement types " << p.i.exclude_msrs << "... ";
2✔
1567
                parserDynaML.ExcludeMeasurementTypes(p.i.exclude_msrs, &vmeasurementsTotal, &parsemsrTally);
2✔
1568
                if (!p.g.quiet)
2✔
1569
                        cout << "Done. " << endl;
2✔
1570
                imp_file << "Done. " << endl;
2✔
1571
        }
1572

1573
        // Reduce stations.
1574
        // But, only reduce stations if not importing for a segmentation block or network
1575
        // The reason stations are not reduced if IMPORT_SEG_BLOCK or IMPORT_CONTIG_NET has been set is
1576
        // because stations in the binary file will have already been reduced
1577
        // on last import!
1578
        if (p.i.import_block == 0 && p.i.import_network == 0 && vstationsTotal.size())
59✔
1579
        {
1580
                // reduce stations (e.g. convert from UTM to LLH)
1581
                try {
53✔
1582
                        if (!p.g.quiet)
53✔
1583
                        {
1584
                                cout << "+ Reducing stations... ";
52✔
1585
                                cout.flush();
52✔
1586
                        }
1587
                        imp_file << "+ Reducing stations... ";
53✔
1588
                        parserDynaML.ReduceStations(&vstationsTotal, projection);
53✔
1589
                        if (!p.g.quiet)
53✔
1590
                                cout << "Done." << endl;
52✔
1591
                        imp_file << "Done." << endl;
53✔
1592
                } 
1593
                catch (const XMLInteropException& e) {
×
1594
                        cout << endl << "- Error: " << e.what() << endl;
×
1595
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1596
                        imp_file.close();
×
1597
                        return EXIT_FAILURE;
×
1598
                }
×
1599
        }
1600

1601
        /////////////////////////////////////////////////////////////////////////
1602
        // Add discontinuity sites to vStations
1603
        //
1604
        // WARNING: If discontinuity sites are present in the renaming file, and
1605
        // the renaming file changes the name from the four-character id in the 
1606
        // discontinuity file to another name, this function call will not work
1607
        // properly. Hence, sites in the discontinuity file must be consistently
1608
        // named in the station and measurement files and not renamed to another
1609
        // name.
1610
        if (p.i.apply_discontinuities && !vstationsTotal.empty())
59✔
1611
                parserDynaML.AddDiscontinuityStations(&vstationsTotal);
4✔
1612

1613
        UINT32 stn;
59✔
1614

1615
        // Extract user-defined stations and all connected measurements
1616
        if (vstationsTotal.size() &&        // cannot be empty
59✔
1617
                (!p.i.stn_associated_msr_include.empty() || !p.i.stn_associated_msr_exclude.empty()))
59✔
1618
        {
1619
                vstring vUnusedStns;
6✔
1620
                bool splitXmsrs(false), splitYmsrs(false);
6✔
1621

1622
                try {
6✔
1623
                        if (!p.g.quiet)
6✔
1624
                        {
1625
                                cout << "+ Extracting stations and associated measurements... ";
6✔
1626
                                cout.flush();
6✔
1627
                        }
1628
                        imp_file << "+ Extracting stations and associated measurements... ";
6✔
1629

1630
                        // this method reforms asl and aml
1631
                        parserDynaML.ExtractStnsAndAssociatedMsrs(p.i.stn_associated_msr_include, p.i.stn_associated_msr_exclude, &vstationsTotal, &vmeasurementsTotal, 
6✔
1632
                                &parsestnTally, &parsemsrTally, &vUnusedStns, p, splitXmsrs, splitYmsrs);
1633
                } 
1634
                catch (const XMLInteropException& e) {
×
1635
                        cout << "- Error: " << e.what() << endl;
×
1636
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1637
                        imp_file.close();
×
1638
                        return EXIT_FAILURE;
×
1639
                }
×
1640

1641
                if (!p.g.quiet)
6✔
1642
                        cout << "Done. " << endl;
6✔
1643
                imp_file << "Done." << endl;
6✔
1644

1645
                //msrCount = vmeasurementsTotal.size();
1646
        }        
6✔
1647

1648
        // Now strip all stations outside the bounding box (if supplied)
1649
        if (vstationsTotal.size() &&        // cannot be empty
59✔
1650
                !p.i.bounding_box.empty())
58✔
1651
        {
1652
                vstring vUnusedStns;
1✔
1653
                bool splitXmsrs(false), splitYmsrs(false);
1✔
1654

1655
                try {
1✔
1656
                        if (!p.g.quiet)
1✔
1657
                        {
1658
                                cout << "+ Stripping stations and measurements outside the bounding box... ";
1✔
1659
                                cout.flush();
1✔
1660
                        }
1661
                        imp_file << "+ Stripping stations and measurements outside the bounding box... ";
1✔
1662
                        parserDynaML.ExcludeAllOutsideBoundingBox(&vstationsTotal, &vmeasurementsTotal, 
1✔
1663
                                &parsestnTally, &parsemsrTally, &vUnusedStns, p, splitXmsrs, splitYmsrs);
1664
                } 
1665
                catch (const XMLInteropException& e) {
×
1666
                        cout << "- Error: " << e.what() << endl;
×
1667
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1668
                        imp_file.close();
×
1669
                        return EXIT_FAILURE;
×
1670
                }
×
1671

1672
                if (!p.g.quiet)
1✔
1673
                        cout << "Done. " << endl;
1✔
1674
                imp_file << "Done." << endl;
1✔
1675

1676
                if (!vUnusedStns.empty())
1✔
1677
                {
1678
                        ostringstream ss_msg;
1✔
1679
                        ss_msg << "  - " << vstationsTotal.size() << (vstationsTotal.size() == 1 ? " station is" : " stations are") << 
1✔
1680
                                " within the bounding box." << endl;
2✔
1681
                        imp_file << ss_msg.str();
1✔
1682
                        if (!p.g.quiet)
1✔
1683
                                cout << ss_msg.str();
1✔
1684
                        ss_msg.str("");
2✔
1685
                        ss_msg << "  - ";
1✔
1686
                        if (vUnusedStns.size() > 1)
1✔
1687
                        {
1688
                                ss_msg << vUnusedStns.size() << " stations were";
1✔
1689
                        }
1690
                        else
1691
                                ss_msg << "Station " << vUnusedStns.at(0) << " was";
×
1692

1693
                        ss_msg << " found outside the bounding box and " << (vUnusedStns.size() > 1 ? "have been" : "has been") << endl <<
1✔
1694
                                "    removed together with the corresponding measurements." << endl;
1✔
1695
                        if (p.i.split_clusters && (splitXmsrs || splitYmsrs))
1✔
1696
                        {
1697
                                ss_msg << "  - Note: GPS ";
1✔
1698
                                if (splitXmsrs && splitYmsrs)
1✔
1699
                                        ss_msg << "point and baseline";
×
1700
                                else if (splitXmsrs)
1✔
1701
                                        ss_msg << "baseline";
×
1702
                                else //if (splitYmsrs)
1703
                                        ss_msg << "point";
1✔
1704
                                ss_msg << " cluster measurements straddling the limits of" << endl << 
1✔
1705
                                "    the bounding box have been split." << endl;
1✔
1706
                        }
1707
                        imp_file << ss_msg.str() << "  - Excluded stations:" << endl;
1✔
1708
                        if (!p.g.quiet)
1✔
1709
                                cout << ss_msg.str() << endl;
1✔
1710
                        
1711
                        for (stn=0; stn<vUnusedStns.size(); ++stn)
13✔
1712
                                imp_file << "     " << vUnusedStns.at(stn) << endl;
12✔
1713
                        imp_file << endl;
1✔
1714
                }
1✔
1715
                else
1716
                {
1717
                        imp_file << "  - No stations were found outside the bounding box." << endl;
×
1718
                        if (!p.g.quiet)
×
1719
                                cout << "  - No stations were found outside the bounding box." << endl;
×
1720
                }
1721
        }
1✔
1722

1723
        UINT32 msrRead(parsemsrTally.TotalCount());
59✔
1724
        UINT32 stnCount(static_cast<UINT32>(vstationsTotal.size()));
59✔
1725
        UINT32 msrCount(static_cast<UINT32>(vmeasurementsTotal.size()));
59✔
1726

1727
        if (!p.g.quiet)
59✔
1728
                cout << endl;
58✔
1729
        imp_file << endl;
59✔
1730

1731
        ///////////////////////////////////////////////////////////////////////
1732
        // Ok, now that unwanted stations and measurements have been stripped,
1733
        // provide station and measurement Summary
1734
        //
1735
        if ((stnCount + msrCount) > 0)
59✔
1736
        {
1737
                if (p.i.import_block || p.i.import_network)
58✔
1738
                {
1739
                        if (!p.g.quiet)
6✔
1740
                                cout << "+ Binary file ";
6✔
1741
                        imp_file << "+ Binary file ";
6✔
1742
                }
1743
                else
1744
                {
1745
                        if (!p.g.quiet)
52✔
1746
                                cout << "+ File ";
51✔
1747
                        imp_file << "+ File ";
52✔
1748
                }
1749
                
1750
                if (!p.g.quiet)
58✔
1751
                        cout << "parsing summary:" << endl << endl;
57✔
1752
                imp_file << "parsing summary:" << endl << endl;
58✔
1753
        }
1754
        
1755
        //
1756
        // Station summary
1757
        if (stnCount)
59✔
1758
        {
1759
                if (!p.g.quiet)
58✔
1760
                {
1761
                        parsestnTally.coutSummary(cout, string("  Read"));
57✔
1762
                        cout << endl;
57✔
1763
                }
1764
                parsestnTally.coutSummary(imp_file, string("  Read"));
58✔
1765
                imp_file << endl;
58✔
1766
        }
1767
        
1768
        //
1769
        // Measurement summary
1770
        if (msrCount)
59✔
1771
        {
1772
                if (!p.g.quiet)
56✔
1773
                {
1774
                        parsemsrTally.coutSummary(cout, string("  Read"));
55✔
1775
                        cout << endl;
55✔
1776
                }
1777
                parsemsrTally.coutSummary(imp_file, string("  Read"));
56✔
1778
                imp_file << endl;
56✔
1779
        }
1780

1781
        ////////////////////////////////////////////////////////////////////////
1782
        // Can we proceed?
1783
        if (stnCount < 1)
59✔
1784
        {
1785
                imp_file << "- No further processing can be done as no stations were loaded." << endl;
1✔
1786
                if (!p.g.quiet)
1✔
1787
                        cout << "- No further processing can be done as no stations were loaded." << endl;
1✔
1788
                imp_file.close();
1✔
1789
                return PARSE_SUCCESS;
1790
        }
1791

1792
        /////////////////////////////////////////////////////////////////////////
1793
        // Rename stations
1794
        if (p.i.rename_stations && (stnCount > 0 || msrCount > 0))
58✔
1795
        {
1796
                // Does it exist?
1797
                if (!exists(p.i.stn_renamingfile))
1✔
1798
                        // Look for it in the input folder
1799
                        p.i.stn_renamingfile = formPath<string>(p.g.input_folder, leafStr<string>(p.i.stn_renamingfile));
×
1800

1801
                // Apply renaming
1802
                try {
1✔
1803
                        if (!p.g.quiet)
1✔
1804
                        {
1805
                                cout << "+ Renaming stations... ";
1✔
1806
                                cout.flush();
1✔
1807
                        }
1808
                        imp_file << "+ Renaming stations... ";
1✔
1809
                        parserDynaML.RenameStations(&vstationsTotal, &vmeasurementsTotal, &p);
1✔
1810
                        if (!p.g.quiet)
1✔
1811
                                cout << "Done." << endl;
1✔
1812
                        imp_file << "Done." << endl;
1✔
1813
                } 
1814
                catch (const XMLInteropException& e) {
×
1815
                        cout << endl << "- Error: " << e.what() << endl;
×
1816
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1817
                        imp_file.close();
×
1818
                        return EXIT_FAILURE;
×
1819
                }
×
1820
        }
1821

1822
        // Apply GNSS scaling (if required)
1823
        if (p.i.import_block == 0 && p.i.import_network == 0 && p.i.apply_scaling)
58✔
1824
        {
1825
                // Apply scaling
1826
                try {
2✔
1827
                        if (!p.g.quiet)
2✔
1828
                        {
1829
                                cout << "+ Applying scalars to GNSS measurements... ";
2✔
1830
                                cout.flush();
2✔
1831
                        }
1832
                        imp_file << "+ Applying scalars to GNSS measurements... ";
2✔
1833
                        parserDynaML.EditGNSSMsrScalars(&vmeasurementsTotal, &p);
2✔
1834
                        if (!p.g.quiet)
2✔
1835
                                cout << "Done." << endl;
2✔
1836
                        imp_file << "Done." << endl;
2✔
1837
                } 
1838
                catch (const XMLInteropException& e) {
×
1839
                        cout << endl << "- Error: " << e.what() << endl;
×
1840
                        imp_file << endl << "- Error: " << e.what() << endl;
×
1841
                        imp_file.close();
×
1842
                        return EXIT_FAILURE;
×
1843
                }
×
1844
        }
1845

1846
        std::ofstream dst_file;
58✔
1847

1848
        // flush duplicate stations/measurements files
1849
        try {
58✔
1850
                if (exists(p.i.dst_file))
58✔
1851
                        remove(p.i.dst_file);
2✔
1852
                if (exists(p.i.dms_file))
58✔
1853
                        remove(p.i.dms_file);
3✔
1854
        }
1855
        catch (const ios_base::failure& f) { 
×
1856
                // do nothing on failure.
1857
                imp_file << endl << "- Warning: " << f.what() << endl;
×
1858
        }
×
1859

1860
        // Prepare file names if importing from a segmentation block or contiguous network
1861
        if (p.i.import_block == 1 || p.i.import_network == 1)
58✔
1862
        {
1863
                stringstream modifier("");
6✔
1864
                if (p.i.import_block == 1)
6✔
1865
                        modifier << ".block-" << p.i.import_block_number;
5✔
1866
                else if (p.i.import_network == 1)
1✔
1867
                        modifier << ".network-" << p.i.import_network_number;
1✔
1868

1869
                // create new output file names based on block number
1870
                // reform file name for each so as to preserve full path for each file
1871
                stringstream ss("");
6✔
1872
                ss << formPath<string>(path(p.i.bst_file).parent_path().generic_string(), path(p.i.bst_file).stem().generic_string());
18✔
1873
                ss << modifier.str() << ".bst";
6✔
1874
                p.i.bst_file = ss.str();
6✔
1875

1876
                ss.str("");
12✔
1877
                ss << formPath<string>(path(p.i.bms_file).parent_path().generic_string(), path(p.i.bms_file).stem().generic_string());
18✔
1878
                ss << modifier.str() << ".bms";
6✔
1879
                p.i.bms_file = ss.str();
6✔
1880

1881
                ss.str("");
12✔
1882
                ss << formPath<string>(path(p.i.asl_file).parent_path().generic_string(), path(p.i.asl_file).stem().generic_string());
18✔
1883
                ss << modifier.str() << ".asl";
6✔
1884
                p.i.asl_file = ss.str();
6✔
1885

1886
                ss.str("");
12✔
1887
                ss << formPath<string>(path(p.i.aml_file).parent_path().generic_string(), path(p.i.aml_file).stem().generic_string());
18✔
1888
                ss << modifier.str() << ".aml";
6✔
1889
                p.i.aml_file = ss.str();
6✔
1890

1891
                ss.str("");
12✔
1892
                ss << formPath<string>(path(p.i.map_file).parent_path().generic_string(), path(p.i.map_file).stem().generic_string());
18✔
1893
                ss << modifier.str() << ".map";
6✔
1894
                p.i.map_file = ss.str();
6✔
1895

1896
                ss.str("");
12✔
1897
                ss << formPath<string>(path(p.i.map_file).parent_path().generic_string(), path(p.i.map_file).stem().generic_string());
18✔
1898
                ss << ".dbid";
6✔
1899
                p.i.dbid_file = ss.str();
6✔
1900
        }
6✔
1901

1902
        // Remove duplicate stations. If required, test nearby stations
1903
        if (stnCount > 0) {
58✔
1904
                
1905
                vstring vduplicateStns;
58✔
1906
                v_stringstring_doubledouble_pair vnearbyStns;
58✔
1907

1908
                // Remove duplicates and, if required, identify station pairs 
1909
                // separated by distances less than search_stn_radius
1910
                try {
58✔
1911
                        ostringstream ss_msg;
58✔
1912
                        if (p.i.search_nearby_stn)
58✔
1913
                                ss_msg << "+ Testing for duplicate and nearby stations... ";
2✔
1914
                        else
1915
                                ss_msg << "+ Testing for duplicate stations... ";
56✔
1916
                        
1917
                        if (!p.g.quiet)
58✔
1918
                        {
1919
                                cout << ss_msg.str();
57✔
1920
                                cout.flush();
57✔
1921
                        }
1922

1923
                        imp_file << ss_msg.str();                        
58✔
1924
                        
1925
                        stn = parserDynaML.RemoveDuplicateStations(&vstationsTotal, &vduplicateStns, &vnearbyStns);
58✔
1926
                        
1927
                        if (!p.g.quiet)
58✔
1928
                                cout << "Done. ";
57✔
1929
                        imp_file << "Done. ";
58✔
1930

1931
                        if (stn > 0)
58✔
1932
                        {
1933
                                try {
5✔
1934
                                        // Create duplicate station file
1935
                                        file_opener(dst_file, p.i.dst_file);
5✔
1936
                                }
1937
                                catch (const runtime_error& e) {
×
1938
                                        ss_msg << "- Error: Could not open " << p.i.dst_file << ". \n  Check that the file exists and that the file is not already opened." << 
×
1939
                                                endl << e.what() << endl;
×
1940
                                        if (!p.g.quiet)
×
1941
                                                cout << ss_msg.str();
×
1942
                                        imp_file << ss_msg.str();
×
1943
                                        imp_file.close();
×
1944
                                        return EXIT_FAILURE;
×
1945
                                }
×
1946
                                                
1947
                                PrintOutputFileHeaderInfo(&dst_file, p.i.dst_file, &p, "DUPLICATE STATION FILE");
5✔
1948

1949
                                if (!vduplicateStns.empty())
5✔
1950
                                {
1951
                                        ss_msg.str("");
8✔
1952
                                        ss_msg << "Removed " << vduplicateStns.size() << " duplicate station" << (vduplicateStns.size() > 1 ? "s" : "");
7✔
1953
                                        
1954
                                        // print message to .dst file
1955
                                        dst_file << ss_msg.str() << ":" << endl;
4✔
1956
                                        for (stn=0; stn<vduplicateStns.size(); ++stn)
10✔
1957
                                                dst_file << "  - " << vduplicateStns.at(stn) << endl;
6✔
1958
                                        dst_file << endl;
4✔
1959

1960
                                        ss_msg << "." << endl << "  See " << p.i.dst_file << " for details." << endl;
4✔
1961

1962
                                        imp_file << ss_msg.str();
4✔
1963
                                        if (!p.g.quiet)
4✔
1964
                                                cout << endl << "- Warning: " << ss_msg.str();                                        
4✔
1965
                                }                                
1966

1967
                                if (!vnearbyStns.empty())
5✔
1968
                                {
1969
                                        ss_msg.str("");
2✔
1970
                                        ss_msg << vnearbyStns.size() << (vnearbyStns.size() > 1 ? " pairs of stations were" : " pair of station was") << 
1✔
1971
                                                " found to be separated by less than " << setprecision(3) << p.i.search_stn_radius << "m.";
1✔
1972

1973
                                        imp_file << endl << "- Warning: " << ss_msg.str() << endl << 
1✔
1974
                                                "  See " << p.i.dst_file << " for details." << endl << endl;
1✔
1975
                                        
1976
                                        if (!p.g.quiet)
1✔
1977
                                                cout << endl << "- Warning: " << ss_msg.str() << endl << 
2✔
1978
                                                "  See " << p.i.dst_file << " for details." << endl << endl;
1✔
1979
                                        ss_msg.str("");
2✔
1980

1981
                                        // output message
1982
                                        dst_file << "Nearby station search results:" << endl << ss_msg.str() << endl << endl;
1✔
1983

1984
                                        dst_file <<  
1✔
1985
                                                setw(HEADER_20) << left << "First station" << 
1✔
1986
                                                setw(HEADER_20) << "Nearby station" << 
1987
                                                setw(HEADER_20) << right << "Separation (m)" << 
1✔
1988
                                                setw(HEADER_20) << "Diff height (m)" << 
1✔
1989
                                                endl;
81✔
1990

1991
                                        for (UINT32 i(0); i<(HEADER_20*4); ++i)
81✔
1992
                                                dst_file << "-";
80✔
1993
                                        dst_file << endl;
1✔
1994

1995
                                        // dump nearby stations to dst file
1996
                                        for (stn=0; stn<vnearbyStns.size(); ++stn)
50✔
1997
                                        {
1998
                                                dst_file <<
49✔
1999
                                                        setw(HEADER_20) << left << vnearbyStns.at(stn).first.first <<                                                                         // First
49✔
2000
                                                        setw(HEADER_20) << vnearbyStns.at(stn).first.second <<                                                                        // Nearby
49✔
2001
                                                        setw(HEADER_20) << setprecision(3) << fixed << right << vnearbyStns.at(stn).second.first <<                // Separation (m)
98✔
2002
                                                        setw(HEADER_20) << setprecision(3) << fixed << vnearbyStns.at(stn).second.second <<                // Diff height (m)
49✔
2003
                                                        endl;
49✔
2004
                                        }
2005

2006
                                        ss_msg <<
1✔
2007
                                                "  If the names in each pair refer to the same station, then update the " << endl <<
1✔
2008
                                                "  station and measurement files with the correct station name and re-run " << __BINARY_NAME__ << "." << endl <<
1✔
2009
                                                "  Alternatively, if the names in each pair are unique, either call " << __BINARY_NAME__ << endl <<
1✔
2010
                                                "  without the --" << TEST_NEARBY_STNS << " option, or decrease the radial search " << endl <<
1✔
2011
                                                "  distance using --" << TEST_NEARBY_STN_DIST << "." << endl << endl;
1✔
2012

2013
                                        if (!p.g.quiet)
1✔
2014
                                                cout << ss_msg.str();
1✔
2015
                                        imp_file << ss_msg.str();
1✔
2016
                                        imp_file.close();
1✔
2017
                                        dst_file.close();
1✔
2018
                                        return EXIT_FAILURE;
2019
                                }
2020
                                else if (p.g.verbose == 3)
4✔
2021
                                {
2022
                                        if (!p.g.quiet)
×
2023
                                                cout << "+ Total number of unique stations is " << vstationsTotal.size() << endl;
×
2024
                                        imp_file << "+ Total number of unique stations is " << vstationsTotal.size() << endl;
×
2025
                                }
2026

2027
                                // If this line is reached, then there are no nearby stations
2028
                                dst_file.close();
4✔
2029
                        }
2030
                        if (!p.g.quiet)
57✔
2031
                                cout << endl;
56✔
2032
                        imp_file << endl;
57✔
2033
                } 
58✔
2034
                catch (const XMLInteropException& e) {
×
2035
                        cout << endl << "- Error: " << e.what() << endl;
×
2036
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2037
                        imp_file.close();
×
2038
                        return EXIT_FAILURE;
×
2039
                }                
×
2040

2041
                /////////////////////////////////////////////////////////////////
2042
                // Now commence sorting and mapping
2043
                // 1. Sort stations
2044
                // 2. Create station map
2045
                try {
57✔
2046
                        if (!p.g.quiet)
57✔
2047
                        {
2048
                                cout << "+ Sorting stations... ";
56✔
2049
                                cout.flush();
56✔
2050
                        }
2051
                        imp_file << "+ Sorting stations... ";
57✔
2052
                        parserDynaML.FullSortandMapStations((vdnaStnPtr*) &vstationsTotal, &vStnsMap_sortName);
57✔
2053
                        if (!p.g.quiet)
57✔
2054
                        {
2055
                                cout << "Done." << endl << "+ Serialising station map... ";
56✔
2056
                                cout.flush();
56✔
2057
                        }
2058
                        imp_file << "Done." << endl << "+ Serialising station map... ";                        
57✔
2059
                        parserDynaML.SerialiseMap(p.i.map_file);                // parserDynaML keeps the map in memory
57✔
2060
                        stn_map_created = true;
57✔
2061
                        if (!p.g.quiet)
57✔
2062
                        {
2063
                                cout << "Done." << endl;
56✔
2064
                                cout.flush();
56✔
2065
                        }
2066
                        imp_file << "Done." << endl;
57✔
2067

2068
                        if (p.i.export_map_file)
57✔
2069
                        {
2070
                                if (!p.g.quiet)
4✔
2071
                                {
2072
                                        cout << "+ Exporting station map to text file... ";
4✔
2073
                                        cout.flush();
4✔
2074
                                }
2075
                                imp_file << "+ Exporting station map to text file... ";
4✔
2076
                                parserDynaML.SerialiseMapTextFile(p.i.map_file);
4✔
2077
                                if (!p.g.quiet)
4✔
2078
                                {
2079
                                        cout << "Done." << endl;
4✔
2080
                                        cout.flush();
4✔
2081
                                }
2082
                                imp_file << "Done." << endl;                                
4✔
2083
                        }
2084
                } 
2085
                catch (const XMLInteropException& e) {
×
2086
                        cout << endl << "- Error: " << e.what() << endl;
×
2087
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2088
                        imp_file.close();
×
2089
                        return EXIT_FAILURE;
×
2090
                }        
×
2091
        }
58✔
2092

2093
        // Search for similar measurements
2094
        if (msrCount > 0 && (p.i.search_similar_msr || p.i.search_similar_msr_gx || p.i.ignore_similar_msr)) 
57✔
2095
        {
2096
                if (SearchForSimilarMeasurements(&parserDynaML, &p, &imp_file,
4✔
2097
                        &vmeasurementsTotal) != EXIT_SUCCESS)
2098
                        return EXIT_FAILURE;        
2099
        }
2100

2101
        // Import DNA geoid file
2102
        if (p.i.import_geo_file && p.i.import_block == 0 && p.i.import_network == 0 && vstationsTotal.size())
57✔
2103
        {
2104
                if (!exists(p.i.geo_file))
2✔
2105
                {
2106
                        path geoPath(p.i.geo_file);
×
2107
                        stringstream ss;
×
2108
                        ss << "- Error: The geoid file " << geoPath.filename().string() << " does not exist." << endl;
×
2109
                        cout << endl << ss.str();
×
2110
                        imp_file << endl << ss.str();
×
2111
                        return EXIT_FAILURE;
×
2112
                }
×
2113

2114
                if (!p.g.quiet)
2✔
2115
                {
2116
                        cout << "+ Importing geoid information from " << p.i.geo_file << "... ";
2✔
2117
                        cout.flush();
2✔
2118
                }
2119
                imp_file << "+ Importing geoid information from " << p.i.geo_file << "... ";
2✔
2120

2121
                parserDynaML.LoadDNAGeoidFile(p.i.geo_file, &vstationsTotal);
2✔
2122

2123
                if (!p.g.quiet)
2✔
2124
                        cout << "Done." << endl;
2✔
2125
                imp_file << "Done." << endl;
2✔
2126
        }
2127

2128
        UINT32 ignMsrCount, mapCount;
57✔
2129
        vstring vunusedStations;
57✔
2130
        vUINT32 vignoredMeasurements;
57✔
2131

2132
        // Map measurements to stations
2133
        if (stn_map_created) 
57✔
2134
        {        
2135
                try {
57✔
2136
                        if (!p.g.quiet)
57✔
2137
                        {
2138
                                cout << "+ Mapping measurements to stations... ";
56✔
2139
                                cout.flush();
56✔
2140
                        }
2141
                        imp_file << "+ Mapping measurements to stations... ";
57✔
2142
                        
2143
                        parserDynaML.MapMeasurementStations((vdnaMsrPtr*) &vmeasurementsTotal,        &associatedSL, &mapCount, 
57✔
2144
                                &vunusedStations, &vignoredMeasurements);
2145
                        
2146
                        if (!p.g.quiet)
56✔
2147
                                cout << "Done." << endl;
55✔
2148
                        imp_file << "Done. ";
56✔
2149

2150
                        if (msrCount > 0)
56✔
2151
                        {
2152
                                measurements_mapped = true;
54✔
2153
                                imp_file << "Mapped " << mapCount << " measurements to " << vStnsMap_sortName.size() - vunusedStations.size() << " stations." << endl;
54✔
2154
                        }
2155
                        else
2156
                                imp_file << endl;
2✔
2157

2158
                        if (!vunusedStations.empty())
56✔
2159
                        {
2160
                                if (vunusedStations.size() == 1)
17✔
2161
                                {
2162
                                        if (p.g.verbose > 2)
13✔
2163
                                        {
2164
                                                if (!p.g.quiet)
×
2165
                                                        cout << "- Warning: station " << vunusedStations.at(0) << " was not associated with any measurements." << endl;
×
2166
                                                imp_file << "- Warning: station " << vunusedStations.at(0) << " was not associated with any measurements." << endl;
×
2167
                                        }
2168
                                        else
2169
                                        {
2170
                                                if (!p.g.quiet)
13✔
2171
                                                        cout << "- Warning: " << vunusedStations.size() << " station was not associated with any measurements." << endl;
13✔
2172
                                                imp_file << "- Warning: " << vunusedStations.size() << " station was not associated with any measurements." << endl;
13✔
2173
                                        }
2174
                                }
2175
                                else
2176
                                {
2177
                                        if (p.g.verbose > 2)
4✔
2178
                                        {
2179
                                                if (!p.g.quiet)
×
2180
                                                        cout << "- Warning: The following " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
×
2181
                                                imp_file << "- Warning: The following " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
×
2182
                                                _it_vstr unused;
×
2183
                                                for (unused = vunusedStations.begin(); unused!=vunusedStations.end(); unused++)
×
2184
                                                {
2185
                                                        if (!p.g.quiet)
×
2186
                                                                outputObject(string("  - " + *unused + "\n"), cout);
×
2187
                                                        outputObject(string("  - " + *unused + "\n"), imp_file);
×
2188
                                                }
2189
                                        }
2190
                                        else
2191
                                        {
2192
                                                if (!p.g.quiet)
4✔
2193
                                                        cout << "- Warning: " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
4✔
2194
                                                imp_file << "- Warning: " << vunusedStations.size() << " stations were not associated with any measurements." << endl;
4✔
2195
                                        }
2196
                                }
2197
                        }
2198

2199
                        if (msrRead < mapCount && vignoredMeasurements.empty())
56✔
2200
                        {
2201
                                if (!p.g.quiet)
×
2202
                                        cout << "- Warning: Not all measurements were mapped: " << msrRead << " msrs read vs. " << mapCount
×
2203
                                                << " msrs mapped." << endl;
×
2204
                        }
2205
                        else if (msrRead != mapCount && !vignoredMeasurements.empty())
56✔
2206
                        {
2207
                                ignMsrCount = parserDynaML.ComputeMeasurementCount(&vmeasurementsTotal, vignoredMeasurements);        
×
2208
                                if (!p.g.quiet)
×
2209
                                {
2210
                                        cout << "- Warning: " << ignMsrCount << " ignored measurements were not mapped." << endl;
×
2211
                                        if ((msrRead - mapCount) != ignMsrCount)
×
2212
                                                cout << "-          " << msrRead << " m.read vs. " << mapCount << " m.mapped." << endl;
×
2213
                                }
2214
                        }
2215
                        if (!p.g.quiet)
56✔
2216
                                cout.flush();
55✔
2217
                } 
2218
                catch (const XMLInteropException& e) {
1✔
2219
                        cout << endl << "- Error: " << e.what() << endl;
1✔
2220
                        imp_file << endl << "- Error: " << e.what() << endl;
1✔
2221
                        imp_file.close();
1✔
2222
                        return EXIT_FAILURE;
1✔
2223
                }
1✔
2224
        }
2225

2226
        stnCount = static_cast<UINT32>(vstationsTotal.size());
56✔
2227
        if (stnCount > static_cast<UINT32>(associatedSL.size()))
56✔
2228
                stnCount = static_cast<UINT32>(associatedSL.size());
×
2229
        
2230
        // Does the user want to simulate measurements?
2231
        if (p.i.simulate_measurements && stnCount > 0 && msrCount > 0) 
56✔
2232
        {
2233
                // No need for the following code if the outer 'if' statement checks 
2234
                // for non-zero stnCount value
2235
                //
2236
                // if (stnCount == 0)
2237
                // {
2238
                //         if (!p.g.quiet)
2239
                //                 cout << "- Error: there are no stations from which to simulate measurements." << endl;
2240
                //         imp_file << "- Error: there are no stations from which to simulate measurements." << endl;
2241
                //         imp_file.close();
2242
                //         return EXIT_FAILURE;
2243
                // }        
2244
        
2245
                try {
1✔
2246
                        // Simulate measurements
2247
                        if (!p.g.quiet)
1✔
2248
                        {
2249
                                cout << "+ Simulating and exporting measurements to " << leafStr<string>(p.i.simulate_msrfile) << "... ";
2✔
2250
                                cout.flush();
1✔
2251
                        }
2252
                        imp_file << "+ Simulating and exporting measurements to " << leafStr<string>(p.i.simulate_msrfile) << "... ";
2✔
2253
                        parserDynaML.SimulateMSR(
1✔
2254
                                ((vdnaStnPtr*) &vstationsTotal), 
2255
                                ((vdnaMsrPtr*) &vmeasurementsTotal), 
2256
                                p.i.simulate_msrfile, p);
2257
                        if (!p.g.quiet)
1✔
2258
                                cout << "Done." << endl;
1✔
2259
                        imp_file << "Done." << endl;
1✔
2260
                }
2261
                catch (const XMLInteropException& e) {
×
2262
                        cout.flush();
×
2263
                        cout << endl << "- Error: " << e.what() << endl;
×
2264
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2265
                        imp_file.close();
×
2266
                        return EXIT_FAILURE;
×
2267
                }
×
2268
        }
2269

2270
        // Create association lists
2271
        if (measurements_mapped) 
56✔
2272
        {
2273
                try {
54✔
2274
                        if (!p.g.quiet)
54✔
2275
                        {
2276
                                cout << "+ Creating association lists... ";
53✔
2277
                                cout.flush();
53✔
2278
                        }
2279
                        imp_file << "+ Creating association lists... ";
54✔
2280
                        parserDynaML.CompleteAssociationLists(&vmeasurementsTotal, &associatedSL, &associatedML);
54✔
2281
                        if (!p.g.quiet)
54✔
2282
                        {
2283
                                cout << "Done." << endl;
53✔
2284
                                cout.flush();
53✔
2285
                        }
2286
                        imp_file << "Done." << endl;
54✔
2287
                } 
2288
                catch (const XMLInteropException& e) {
×
2289
                        cout << "- Error: " << e.what() << endl;
×
2290
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2291
                        imp_file.close();
×
2292
                        return EXIT_FAILURE;
×
2293
                }
×
2294

2295
                try {
54✔
2296
                        if (!p.g.quiet)
54✔
2297
                        {
2298
                                cout << "+ Serialising association lists... ";
53✔
2299
                                cout.flush();
53✔
2300
                        }
2301
                        imp_file << "+ Serialising association lists... ";
54✔
2302
                        parserDynaML.SerialiseAsl(p.i.asl_file, &associatedSL);
54✔
2303
                        parserDynaML.SerialiseAml(p.i.aml_file, &associatedML);
54✔
2304
                        if (!p.g.quiet)
54✔
2305
                        {
2306
                                cout << "Done." << endl;
53✔
2307
                                cout.flush();
53✔
2308
                        }
2309
                        imp_file << "Done." << endl;
54✔
2310
                } 
2311
                catch (const XMLInteropException& e) {
×
2312
                        cout << "- Error: " << e.what() << endl;
×
2313
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2314
                        imp_file.close();
×
2315
                        return EXIT_FAILURE;
×
2316
                }
×
2317
        }
2318

2319
        // Create binary station file.
2320
        // Binary station file can be serialised without measurements
2321
        if (stnCount > 0)
56✔
2322
        {
2323
                try {
56✔
2324
                        if (!vstationsTotal.empty())
56✔
2325
                        {
2326
                                if (!p.g.quiet)
56✔
2327
                                {
2328
                                        cout << "+ Serialising binary station file " << leafStr<string>(p.i.bst_file) << "... ";
110✔
2329
                                        cout.flush();
55✔
2330
                                }
2331
                                imp_file << "+ Serialising binary station file " << leafStr<string>(p.i.bst_file) << "... ";
112✔
2332
                                
2333
                                parserDynaML.SerialiseBst(
56✔
2334
                                        p.i.bst_file, ((vdnaStnPtr*) &vstationsTotal), &vunusedStations,
2335
                                        vinput_file_meta, (p.i.flag_unused_stn ? true : false));
56✔
2336
                                if (!p.g.quiet)
56✔
2337
                                {
2338
                                        cout << "Done." << endl;
55✔
2339
                                        cout.flush();
55✔
2340
                                }
2341
                                imp_file << "Done." << endl;
56✔
2342
                        }
2343
                } 
2344
                catch (const XMLInteropException& e) {
×
2345
                        cout << "- Error: " << e.what() << endl;
×
2346
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2347
                        imp_file.close();
×
2348
                        return EXIT_FAILURE;
×
2349
                }
×
2350
        }
2351

2352
        // Create binary measurement file.
2353
        // Binary measurement file can be serialised without stations
2354
        if (msrCount > 0) 
56✔
2355
        {
2356
                try {
54✔
2357
                        if (!vmeasurementsTotal.empty())
54✔
2358
                        {
2359
                                if (!p.g.quiet)
54✔
2360
                                {
2361
                                        cout << "+ Serialising binary measurement file " << leafStr<string>(p.i.bms_file) << "... ";
106✔
2362
                                        cout.flush();
53✔
2363
                                }
2364
                                imp_file << "+ Serialising binary measurement file " << leafStr<string>(p.i.bms_file) << "... ";
108✔
2365

2366
                                parserDynaML.SerialiseBms(
54✔
2367
                                        p.i.bms_file, ((vdnaMsrPtr*) &vmeasurementsTotal),
2368
                                        vinput_file_meta);
2369
                                if (!p.g.quiet)
54✔
2370
                                {
2371
                                        cout << "Done." << endl;
53✔
2372
                                        cout.flush();
53✔
2373
                                }
2374
                                imp_file << "Done." << endl;
54✔
2375
                        }
2376
                } 
2377
                catch (const XMLInteropException& e) {
×
2378
                        cout << "- Error: " << e.what() << endl;
×
2379
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2380
                        imp_file.close();
×
2381
                        return EXIT_FAILURE;
×
2382
                }
×
2383
        }
2384

2385
        // Export ASL and AML to text if required
2386
        if (measurements_mapped) 
56✔
2387
        {
2388
                try {
54✔
2389
                        if (p.i.export_asl_file)
54✔
2390
                        {
2391
                                if (!p.g.quiet)
4✔
2392
                                {
2393
                                        cout << "+ Exporting associated station list to text file... ";
4✔
2394
                                        cout.flush();
4✔
2395
                                }
2396
                                imp_file << "+ Exporting associated station list to text file... ";
4✔
2397
                                parserDynaML.SerialiseAslTextFile(p.i.asl_file, &associatedSL, (vdnaStnPtr*) &vstationsTotal);
4✔
2398
                                if (!p.g.quiet)
4✔
2399
                                {
2400
                                        cout << "Done." << endl;
4✔
2401
                                        cout.flush();
4✔
2402
                                }
2403
                                imp_file << "Done." << endl;                                
4✔
2404
                        }
2405
                } 
2406
                catch (const XMLInteropException& e) {
×
2407
                        cout << "- Error: " << e.what() << endl;
×
2408
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2409
                        imp_file.close();
×
2410
                        return EXIT_FAILURE;
×
2411
                }
×
2412

2413
                try {
54✔
2414
                        if (p.i.export_aml_file)
54✔
2415
                        {
2416
                                if (!p.g.quiet)
4✔
2417
                                {
2418
                                        cout << "+ Exporting associated measurement list to text file... ";
4✔
2419
                                        cout.flush();
4✔
2420
                                }
2421
                                imp_file << "+ Exporting associated measurement list to text file... ";
4✔
2422
                                parserDynaML.SerialiseAmlTextFile(p.i.bms_file, p.i.aml_file, &associatedML, &associatedSL, (vdnaStnPtr*) &vstationsTotal);
4✔
2423
                                if (!p.g.quiet)
4✔
2424
                                {
2425
                                        cout << "Done." << endl;
4✔
2426
                                        cout.flush();
4✔
2427
                                }
2428
                                imp_file << "Done." << endl;                                
4✔
2429
                        }
2430
                }
2431
                catch (const XMLInteropException& e) {
×
2432
                        cout << "- Error: " << e.what() << endl;
×
2433
                        imp_file << endl << "- Error: " << e.what() << endl;
×
2434
                        imp_file.close();
×
2435
                        return EXIT_FAILURE;
×
2436
                }
×
2437

2438
                if (p.i.test_integrity)
54✔
2439
                {
2440
                        if (!p.g.quiet)
2✔
2441
                        {
2442
                                cout << "+ Testing internal integrity of ASL, AML and binary files... ";
2✔
2443
                                cout.flush();
2✔
2444
                        }
2445
                        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✔
2446
                        if (!binaryMS.good())
2✔
2447
                        {
2448
                                cout << endl << "- Could not open binary file for reading." << endl;
×
2449
                                imp_file << endl << "- Could not open binary file for reading." << endl;
×
2450
                                imp_file.close();
×
2451
                                return EXIT_FAILURE;
×
2452
                        }
2453
                        // get size, then go back to beginning
2454
                        size_t sFileSize = (size_t)binaryMS.tellg();
2✔
2455
                        binaryMS.seekg(0, ios::beg);
2✔
2456

2457
                        measurement_t measRecord;
2✔
2458
                        
2459
                        UINT32 amlcount, amlindex, msr;
2✔
2460
                        for (stn=0; stn<stnCount; stn++)
90✔
2461
                        {
2462
                                amlcount = associatedSL.at(stn).get()->GetAssocMsrCount();
86✔
2463
                                
2464
                                // The following is to be used when reading from binary file
2465
                                for (msr=0; msr<amlcount; msr++)
624✔
2466
                                {
2467
                                        amlindex = associatedSL.at(stn).get()->GetAMLStnIndex() + msr;
538✔
2468
                                        if (associatedML.at(amlindex) * sizeof(measurement_t) >= sFileSize)
538✔
2469
                                        {
2470
                                                cout << "Error: index " << associatedML.at(amlindex) << " is out of range for the binary file." << endl;
×
2471
                                                continue;
×
2472
                                        }
2473
                                        binaryMS.seekg(sizeof(UINT32) + associatedML.at(amlindex) * sizeof(measurement_t), ios::beg);
538✔
2474
                                        binaryMS.read(reinterpret_cast<char *>(&measRecord), sizeof(measurement_t));
538✔
2475
                                }
2476
                        }
2477
                        binaryMS.close();
2✔
2478
                        if (!p.g.quiet)
2✔
2479
                                cout << "OK." << endl;
2✔
2480
                }
2✔
2481
        }
2482

2483
        try {
56✔
2484
                // Print measurements to stations table
2485
                PrintMeasurementstoStations(&parsemsrTally, &parserDynaML, &p, &associatedSL);
56✔
2486
        }
2487
        catch (const XMLInteropException& e) {
×
2488
                cout.flush();
×
2489
                cout << endl << "- Error: " << e.what() << endl;
×
2490
                imp_file << endl << "- Error: " << e.what() << endl;
×
2491
                imp_file.close();
×
2492
                return EXIT_FAILURE;
×
2493
        }
×
2494

2495

2496
        // Serialise database ids
2497
        if (p.i.import_block == 1 || p.i.import_network == 1)
56✔
2498
        {
2499
                // dbid_file filename formed earlier
2500
                parserDynaML.SerialiseDatabaseId(p.i.dbid_file, &vmeasurementsTotal);
6✔
2501
        }
2502
        else
2503
        {
2504
                p.i.dbid_file = formPath<string>(p.g.output_folder, p.g.network_name, "dbid");
50✔
2505
                parserDynaML.SerialiseDatabaseId(p.i.dbid_file, &vmeasurementsTotal);
50✔
2506
        }
2507

2508

2509
        
2510

2511
        // Export stations and measurements
2512
        try {
56✔
2513
                if (p.i.export_dynaml || p.i.export_dna_files)
56✔
2514
                        ExportStationsandMeasurements(&parserDynaML, p, &imp_file, &vinput_file_meta, 
14✔
2515
                                &vstationsTotal, &vmeasurementsTotal, stnCount, msrCount);
2516
        }
2517
        catch (const XMLInteropException& e) {
×
2518
                cout.flush();
×
2519
                cout << endl << "- Error: " << e.what() << endl;
×
2520
                imp_file << endl << "- Error: " << e.what() << endl;
×
2521
                imp_file.close();
×
2522
                return EXIT_FAILURE;
×
2523
        }
×
2524
        
2525
        if (!userSuppliedSegFile)
56✔
2526
                p.i.seg_file = "";
55✔
2527
        if (!userSuppliedBstFile)
56✔
2528
                p.i.bst_file = "";
56✔
2529
        if (!userSuppliedBmsFile)
56✔
2530
                p.i.bms_file = "";
56✔
2531

2532
        // Look for a project file.  If it exists, open and load it.
2533
        // Update the import settings.
2534
        // Print the project file. If it doesn't exist, it will be created.
2535
        CDnaProjectFile projectFile;
56✔
2536
        if (exists(p.g.project_file))
56✔
2537
                projectFile.LoadProjectFile(p.g.project_file);
25✔
2538
        
2539
        projectFile.UpdateSettingsImport(p);
56✔
2540
        projectFile.UpdateSettingsReftran(p);
56✔
2541
        projectFile.UpdateSettingsOutput(p);
56✔
2542
        projectFile.PrintProjectFile();
56✔
2543

2544
        if (msrCount == 0)
56✔
2545
        {
2546
                cout << "- Warning: there are no measurements to process." << endl;
2✔
2547
                imp_file << "- Warning: there are no measurements to process." << endl;
2✔
2548
        }
2549
        
2550
        if (errorCount)
56✔
2551
        {
2552
                cout << "- Warning: some files were not parsed - please read the log file for more details." << endl;
×
2553
                imp_file << "- Warning: some files were not parsed - please read the log file for more details." << endl;
×
2554
        }
2555

2556
        // Produce a warning if an ensemble is set as the default reference frame
2557
        if (isEpsgWGS84Ensemble(epsgCode))
56✔
2558
        {
2559
                stringstream ssEnsembleWarning;
×
2560
                ssEnsembleWarning << endl <<
×
2561
                        "- Warning:  The '" << p.i.reference_frame << "' reference frame set for this project refers to the" << endl <<
×
2562
                        "  \"World Geodetic System 1984 (WGS 84) ensemble\".  The WGS 84 ensemble is" << endl <<
×
2563
                        "  only suitable for low accuracy (metre level) positioning and does not" << endl <<
×
2564
                        "  provide for precise transformations to other well-known reference frames." << endl <<
×
2565
                        "  To achieve reliable adjustment results from data on WGS 84, please refer" << endl <<
×
2566
                        "  to \"Configuring import options\" in the DynAdjust User's Guide." << endl;
×
2567
                if (!p.g.quiet)
×
2568
                        cout << ssEnsembleWarning.str();
×
2569
                imp_file << ssEnsembleWarning.str();
×
2570
        }
×
2571
        
2572
        milliseconds elapsed_time(milliseconds(time.elapsed().wall/MILLI_TO_NANO));
56✔
2573
        string time_message = formatedElapsedTime<string>(&elapsed_time, "+ Total file handling process took ");
56✔
2574

2575
        if (!p.g.quiet)
56✔
2576
                cout << endl << time_message << endl;
55✔
2577
        imp_file << endl << time_message << endl;
56✔
2578
        
2579
        if (stnCount > 0 && msrCount > 0)
56✔
2580
        {
2581
                if (!p.g.quiet)
54✔
2582
                        cout << "+ Binary station and measurement files are now ready for processing." << endl << endl;
53✔
2583
                imp_file << "+ Binary station and measurement files are now ready for processing." << endl << endl;
54✔
2584
        }
2585

2586
        imp_file.close();
56✔
2587
        return PARSE_SUCCESS;
56✔
2588
}
343✔
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