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

icsm-au / DynAdjust / 13494567994

24 Feb 2025 09:15AM UTC coverage: 81.168% (+2.0%) from 79.161%
13494567994

push

github

web-flow
Merge pull request #234 from icsm-au/1.2.8

Version 1.2.8 (fixes, ehnacements, improved datum management)

6131 of 8137 new or added lines in 90 files covered. (75.35%)

162 existing lines in 33 files now uncovered.

32214 of 39688 relevant lines covered (81.17%)

11775.25 hits per line

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

81.28
/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 std::string& out_file, project_settings* p, const std::string& header)
100✔
33
{
34
        // Print formatted header
35
        print_file_header(*f_out, header);
100✔
36

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

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

52
        if (!p->i.input_files.empty())
100✔
53
        {
54
                _it_vstr _it_files(p->i.input_files.begin());
93✔
55
                std::string str("Input files:");
93✔
56
                while (_it_files!=p->i.input_files.end())
93✔
57
                {
58
                        *f_out << std::setw(PRINT_VAR_PAD) << std::left << str << *_it_files++ << std::endl;
224✔
59
                        str = " ";
317✔
60
                }
61
        }
93✔
62

63
        // If a reference frame has been supplied, report it.  
64
        // If not, the assumption is, the project frame will be adopted from the first file and
65
        // in this case, it will be reported later
66
        if (p->i.user_supplied_frame)
100✔
67
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Project reference frame:" << p->i.reference_frame << " (user supplied)" << std::endl;
43✔
68
        else
69
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Project reference frame:" << "To be adopted from the first input file" << std::endl;
57✔
70

71
        if (p->i.override_input_rfame)
100✔
72
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Override input file ref frame:" << yesno_string(p->i.override_input_rfame) << std::endl;
18✔
73

74
        UINT32 epsgCode(epsgCodeFromName<UINT32, std::string>(p->i.reference_frame));
100✔
75

76
        if (isEpsgDatumStatic(epsgCode) && p->i.user_supplied_frame)
100✔
77
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Project epoch:" << p->i.epoch << " (adopted reference epoch of " << p->i.reference_frame << ")" << std::endl;
9✔
78
        else
79
        {
80
                if (p->i.user_supplied_epoch)
91✔
81
                        *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Project epoch:" << p->i.epoch << " (user supplied)" << std::endl;
15✔
82
                else
83
                        *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Project epoch:" << "To be adopted from the first input file" << std::endl;
76✔
84
        }
85
        
86
        if (!p->i.include_msrs.empty())
100✔
87
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Strip all measurements except:" << p->i.include_msrs << std::endl;
2✔
88
        else if (!p->i.exclude_msrs.empty())
98✔
89
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Strip measurement types:" << p->i.exclude_msrs << std::endl;
1✔
90

91
        if (p->i.ignore_insufficient_msrs == 1)
100✔
NEW
92
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Ignore insufficient measurements:" << "yes" << std::endl;
×
93
        
94
        if (p->i.search_nearby_stn)
100✔
95
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Search for nearby stations:" << "tolerance = " << p->i.search_stn_radius << "m" << std::endl;
3✔
96
        if (p->i.search_similar_msr)
100✔
97
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Search for similar measurements:" << "yes" << std::endl;
6✔
98
        if (p->i.search_similar_msr_gx)
100✔
99
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Search for similar GNSS measurements:" << "yes" << std::endl;
2✔
100
        
101
        if (!p->i.bounding_box.empty())
100✔
102
        {
103
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Bounding box: " << p->i.bounding_box << std::endl;
1✔
104
                if (p->i.split_clusters)
1✔
105
                        *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Split GNSS clusters: " << (p->i.split_clusters ? "Yes" : "No") << std::endl;
1✔
106
        }
107
        else 
108
        {
109
                if (!p->i.stn_associated_msr_include.empty())
99✔
110
                        *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Stations to include: " << p->i.stn_associated_msr_include << std::endl;
5✔
111
                if (!p->i.stn_associated_msr_exclude.empty())
99✔
112
                        *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Stations to exclude: " << p->i.stn_associated_msr_exclude << std::endl;
1✔
113

114
                if (p->i.split_clusters)
99✔
115
                        *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Split GNSS clusters: " << (p->i.split_clusters ? "Yes" : "No") << std::endl;
4✔
116
        }
117

118
        if (!p->i.seg_file.empty())
100✔
119
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Segmentation file:" << boost::filesystem::system_complete(p->i.seg_file).string() << std::endl;
3✔
120

121
        if (p->i.import_block)
100✔
122
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Import stns & msrs from block: " << p->i.import_block_number << std::endl;
5✔
123
        else if (p->i.import_network)
95✔
124
                *f_out << std::setw(PRINT_VAR_PAD) << std::left << "Import stns & msrs from network: " << p->i.import_network_number << std::endl;
3✔
125
        
126
        *f_out << OUTPUTLINE << std::endl << std::endl;
100✔
127
}
100✔
128
        
129
int ParseCommandLineOptions(const int& argc, char* argv[], const boost::program_options::variables_map& vm, project_settings& p)
95✔
130
{
131
        // capture command line arguments
132
        for (int cmd_arg(0); cmd_arg<argc; ++cmd_arg)
843✔
133
        {
134
                 p.i.command_line_arguments += argv[cmd_arg];
748✔
135
                 p.i.command_line_arguments += " ";
748✔
136
        }
137

138
        if (vm.count(PROJECT_FILE))
190✔
139
        {
140
                if (boost::filesystem::exists(p.g.project_file))
4✔
141
                {
142
                        try {
1✔
143
                                CDnaProjectFile projectFile(p.g.project_file, importSetting);
1✔
UNCOV
144
                                p = projectFile.GetSettings();
×
145
                        }
×
146
                        catch (const std::runtime_error& e) {
1✔
147
                                std::cout << std::endl << "- Error: " << e.what() << std::endl;
1✔
148
                                return EXIT_FAILURE;
1✔
149
                        }
1✔
150
                        
UNCOV
151
                        return EXIT_SUCCESS;
×
152
                }
153

154
                std::cout << std::endl << "- Error: project file " << p.g.project_file << " does not exist." << std::endl << std::endl;
1✔
155
                return EXIT_FAILURE;
1✔
156
        }
157

158
        if (!vm.count(IMPORT_FILE) && !vm.count(IMPORT_SEG_BLOCK) && !vm.count(IMPORT_CONTIG_NET) && !vm.count(SEG_FILE))
197✔
159
        {
160
                std::cout << std::endl << "- Nothing to do - no files specified. " << std::endl << std::endl;  
1✔
161
                return EXIT_FAILURE;
1✔
162
        }
163

164
        if (vm.count(EPOCH) && !vm.count(REFERENCE_FRAME))
214✔
165
        {
NEW
166
                std::cout << std::endl << "- A reference frame must be provided when providing an epoch. " << std::endl << std::endl;
×
UNCOV
167
                return EXIT_FAILURE;
×
168
        }
169

170
        // Normalise files using input folder
171
        for_each(p.i.input_files.begin(), p.i.input_files.end(),
92✔
172
                [&p] (std::string& file) { 
191✔
173
                        formPath<std::string>(p.g.input_folder, file);
382✔
174
                }
191✔
175
        );
176

177
        //////////////////////////////////////////////////////////////////////////////
178
        // General options and file paths
179
        // Network name
180
        if (p.g.network_name == "network1")
92✔
181
        {
182
                // Iterate through network1, network2, network3, etc 
183
                // until the first name not used is found
184
                std::stringstream netname_ss;
2✔
185
                std::string networkASL;
2✔
186
                UINT32 networkID(1);
2✔
187
                
188
                // This loop terminates when a file name cannot be found
189
                while (true)
4✔
190
                {
191
                        // 1. Form ASL file and see if it exists
192
                        networkASL = formPath<std::string>(p.g.output_folder, p.g.network_name, "asl");
9✔
193

194
                        // 2. Does this network exist?
195
                        if (!boost::filesystem::exists(networkASL))
6✔
196
                                break;
197

198
                        // 3. Flush and look for the next network
199
                        netname_ss.str("");
3✔
200
                        netname_ss << "network" << ++networkID;
1✔
201
                        p.g.network_name = netname_ss.str();                        
2✔
202
                }
203
        }
2✔
204

205
        p.g.project_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "dnaproj");
276✔
206

207
        // binary station file location (output)
208
        if (vm.count(BIN_STN_FILE))
184✔
NEW
209
                p.i.bst_file = formPath<std::string>(p.g.output_folder, p.i.bst_file);
×
210
        else
211
                p.i.bst_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "bst");
276✔
212
        
213
        // binary station file location (output)
214
        if (vm.count(BIN_MSR_FILE))
184✔
NEW
215
                p.i.bms_file = formPath<std::string>(p.g.output_folder, p.i.bms_file);
×
216
        else
217
                p.i.bms_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "bms");
276✔
218

219
        if (vm.count(IMPORT_GEO_FILE))
184✔
220
                p.i.import_geo_file = 1;
2✔
221

222
        // output files
223
        p.i.asl_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "asl");        // associated stations list
276✔
224
        p.i.aml_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "aml");        // associated measurements list
276✔
225
        p.i.map_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "map");        // station names map
276✔
226
        p.i.dst_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "dst");        // duplicate stations
276✔
227
        p.i.dms_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "dms");        // duplicate measurements
276✔
228
        p.i.imp_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "imp");        // log
276✔
229
        
230
        //////////////////////////////////////////////////////////////////////////////
231
        // Ref frame options
232
        if (vm.count(OVERRIDE_INPUT_FRAME))
184✔
233
                p.i.override_input_rfame = 1;
5✔
234
        if (vm.count(REFERENCE_FRAME))
184✔
235
        {
236
                p.i.reference_frame = str_upper<std::string>(p.i.reference_frame);
43✔
237
                p.i.user_supplied_frame = 1;
43✔
238
        }
239

240
        if (vm.count(EPOCH))
184✔
241
        {
242
                // Get today's date?
243
                if (boost::iequals(p.i.epoch, "today"))
15✔
244
                        p.i.epoch = stringFromToday<boost::gregorian::date>();
2✔
245
                // Has the user supplied the year only?
246
                else if (p.i.epoch.rfind(".") == std::string::npos)
14✔
247
                        p.i.epoch.insert(0, "01.01.");
1✔
248
                
249
                if (p.i.epoch.length() < 10)
15✔
250
                {
251
                        std::string dateStr = FormatDateString(p.i.epoch);                        
3✔
252
                        if (dateStr.empty())
3✔
253
                        {
NEW
254
                                std::cout << std::endl << "- Error: Cannot parse date '" << p.i.epoch << "'." << std::endl <<
×
NEW
255
                                        "  Please supply date in the format dd.mm.yyyy" << std::endl << std::endl;
×
NEW
256
                                return EXIT_FAILURE;
×
257
                        }
258
                        p.i.epoch = dateStr;
6✔
259
                }
3✔
260

261
                p.i.user_supplied_epoch = 1;
15✔
262
        }        
263

264
        //////////////////////////////////////////////////////////////////////////////
265
        // Data screening options
266
        if (vm.count(GET_MSRS_TRANSCENDING_BOX))
184✔
267
                p.i.include_transcending_msrs = 1;
2✔
268

269
        if (vm.count(SPLIT_CLUSTERS))
184✔
270
                p.i.split_clusters = 1;
5✔
271

272
        if (vm.count(IMPORT_SEG_BLOCK) && vm.count(IMPORT_CONTIG_NET))
194✔
273
        {
NEW
274
                std::cout << std::endl << "- Error: Cannot import stations and measurements using both options" << std::endl << "  --" << IMPORT_SEG_BLOCK << " and --" << IMPORT_CONTIG_NET << "." << std::endl <<
×
NEW
275
                        "  Please supply only one option." << std::endl << std::endl;
×
UNCOV
276
                return EXIT_FAILURE;
×
277
        }
278

279
        // Import stations and measurements from a block
280
        if (vm.count(IMPORT_SEG_BLOCK))
184✔
281
        {
282
                p.i.import_block = 1;
5✔
283
                if (p.i.import_block_number < 1)
5✔
284
                        p.i.import_block_number = 1;
×
285
        }
286

287
        // Import stations and measurements from a contiguous network
288
        if (vm.count(IMPORT_CONTIG_NET))
184✔
289
                p.i.import_network = 1;
2✔
290
        
291
        // User supplied segmentation file
292
        if (vm.count(SEG_FILE))
184✔
293
        {
294
                // Does it exist?
295
                if (!boost::filesystem::exists(p.i.seg_file))
2✔
296
                        // Look for it in the input folder
297
                        p.i.seg_file = formPath<std::string>(p.g.input_folder, leafStr<std::string>(p.i.seg_file));
3✔
298
        }
299

300
        // convert all single X measurements to G measurements?
301
        if (vm.count(PREFER_X_MSR_AS_G))
184✔
302
                p.i.prefer_single_x_as_g = 1;
3✔
303

304
        if (vm.count(TEST_NEARBY_STNS))
184✔
305
                p.i.search_nearby_stn = 1;
2✔
306

307
        if (vm.count(TEST_SIMILAR_MSRS))
184✔
308
                p.i.search_similar_msr = 1;
3✔
309

310
        if (vm.count(TEST_SIMILAR_GNSS_MSRS))
184✔
311
                p.i.search_similar_msr_gx = 1;
1✔
312

313
        if (vm.count(IGNORE_SIMILAR_MSRS))
184✔
314
                p.i.ignore_similar_msr = 1;
2✔
315

316
        if (vm.count(IGNORE_INSUFFICIENT_MSRS))
184✔
317
                p.i.ignore_insufficient_msrs = 1;
×
318

319
        if (vm.count(REMOVE_IGNORED_MSRS))
184✔
320
                p.i.remove_ignored_msr = 1;
1✔
321

322
        if (vm.count(FLAG_UNUSED_STNS))
184✔
323
                p.i.flag_unused_stn = 1;
16✔
324

325
        if (vm.count(TEST_INTEGRITY))
184✔
326
                p.i.test_integrity = 1;
2✔
327
        
328
        //////////////////////////////////////////////////////////////////////////////
329
        // GNSS scaling
330
        if (vm.count(VSCALE) ||
275✔
331
                vm.count(PSCALE) ||
365✔
332
                vm.count(LSCALE) ||
365✔
333
                vm.count(HSCALE) ||
457✔
334
                vm.count(SCALAR_FILE))
274✔
335
                p.i.apply_scaling = 1;
2✔
336

337
        if (vm.count(SCALAR_FILE))
184✔
338
                if (!boost::filesystem::exists(p.i.scalar_file))                        // does it exist?
2✔
339
                        // No.  Assume it is a filename contained in the input folder.  import will throw
340
                        // an exception if it cannot be found.
NEW
341
                        p.i.scalar_file = formPath<std::string>(p.g.input_folder, p.i.scalar_file);        
×
342
        
343
        //////////////////////////////////////////////////////////////////////////////
344
        // Export options
345
        
346
        if (vm.count(OUTPUT_MSR_TO_STN))
184✔
347
                p.o._msr_to_stn = 1;
6✔
348

349
        p.o._m2s_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "m2s");        // measurement to stations table
276✔
350

351
        // Create file name based on the provided block number or contiguous network number
352
        std::string fileName(p.g.network_name);
92✔
353
        if (p.i.import_block)
92✔
354
        {
355
                std::stringstream blk("");
10✔
356
                blk << ".block-" << p.i.import_block_number;
5✔
357
                fileName += blk.str();
10✔
358
        }
5✔
359
        else if (p.i.import_network)
87✔
360
        {
361
                std::stringstream net("");
4✔
362
                net << ".network-" << p.i.import_network_number;
2✔
363
                fileName += net.str();
4✔
364
        }
2✔
365

366
        // Export to dynaml?
367
        if (vm.count(EXPORT_XML_FILES))
184✔
368
        {
369
                p.i.export_dynaml = 1;
10✔
370
        
371
                //// Export from binary
372
                //if (vm.count(EXPORT_FROM_BINARY))
373
                //        p.i.export_from_bfiles = 1;
374

375
                // single file for both stations and measurements
376
                if (vm.count(EXPORT_SINGLE_XML_FILE))
20✔
377
                {
378
                        p.i.export_single_xml_file = 1;
2✔
379
                        p.i.xml_outfile = formPath<std::string>(p.g.output_folder, 
6✔
380
                                fileName, "xml");
2✔
381
                }
382
                // unique files for stations and measurements
383
                else
384
                {
385
                        p.i.export_single_xml_file = 0;
8✔
386
                        p.i.xml_stnfile = formPath<std::string>(p.g.output_folder, 
32✔
387
                                fileName + "stn", "xml");
24✔
388
                        p.i.xml_msrfile = formPath<std::string>(p.g.output_folder, 
32✔
389
                                fileName + "msr", "xml");
24✔
390
                }
391
        }
392

393
        // Export dna files
394
        if (vm.count(EXPORT_DNA_FILES))
184✔
395
        {
396
                p.i.export_dna_files = 1;                
12✔
397
                p.i.dna_stnfile = formPath<std::string>(p.g.output_folder, 
36✔
398
                        fileName, "stn");
12✔
399
                p.i.dna_msrfile = formPath<std::string>(p.g.output_folder, 
36✔
400
                        fileName, "msr");
12✔
401
        }
402

403
        if (vm.count(EXPORT_ASL_FILE))
184✔
404
                p.i.export_asl_file = 1;
5✔
405
        if (vm.count(EXPORT_AML_FILE))
184✔
406
                p.i.export_aml_file = 1;
5✔
407
        if (vm.count(EXPORT_MAP_FILE))
184✔
408
                p.i.export_map_file = 1;
5✔
409
        if (vm.count(EXPORT_DISCONT_FILE))
184✔
410
                p.i.export_discont_file = 1;
1✔
411
        
412
        // Simulate
413
        if (vm.count(SIMULATE_MSR_FILE))
184✔
414
        {
415
                p.i.simulate_measurements = 1;
1✔
416
                p.i.simulate_msrfile = formPath<std::string>(p.g.output_folder,
3✔
417
                        p.g.network_name, "simulated.msr");
1✔
418
        }
419

420
        // Station renaming file
421
        if (vm.count(STATION_RENAMING_FILE))
184✔
422
                p.i.rename_stations = 1;
1✔
423

424
        return EXIT_SUCCESS;
92✔
425
}
92✔
426

427
void PrintMeasurementstoStations(MsrTally* parsemsrTally, dna_import* parserDynaML, 
82✔
428
        project_settings* p, pvASLPtr vAssocStnList)
429
{
430
        // Print measurements to stations table
431
        if (p->o._msr_to_stn)
82✔
432
        {
433
                if (!p->g.quiet)
6✔
434
                {
435
                        std::cout << "+ Printing summary of measurements connected to each station...";
6✔
436
                        std::cout.flush();
6✔
437
                }
438
                parserDynaML->PrintMeasurementsToStations(p->o._m2s_file, parsemsrTally, 
6✔
439
                        p->i.bst_file, p->i.bms_file, p->i.aml_file, vAssocStnList);
6✔
440
                if (!p->g.quiet)
6✔
441
                        std::cout << " done." << std::endl;
6✔
442
        }
443
}
82✔
444

445
int SearchForSimilarMeasurements(dna_import* parserDynaML, project_settings* p, std::ofstream* imp_file,
4✔
446
        vdnaMsrPtr* vmeasurementsTotal)
447
{
448
        std::ofstream dms_file;
4✔
449
        UINT32 msr;
4✔
450
        vdnaMsrPtr vSimilarMeasurements;
4✔
451
        std::string comment("");
4✔
452

453
        try {
4✔
454
                if (!p->g.quiet)
4✔
455
                {
456
                        std::cout << "+ Searching for similar measurements... ";
3✔
457
                        std::cout.flush();
3✔
458
                }
459
                *imp_file << "+ Searching for similar measurements... ";
4✔
460

461
                // at this stage, perform only one search option, giving preference to GNSS searching 
462
                // if both are provided
463
                if (p->i.search_similar_msr_gx)
4✔
464
                        msr = parserDynaML->FindSimilarGXMeasurements(vmeasurementsTotal, &vSimilarMeasurements);
1✔
465
                else
466
                        msr = parserDynaML->FindSimilarMeasurements(vmeasurementsTotal, &vSimilarMeasurements);
3✔
467

468
                if (!vSimilarMeasurements.empty())
4✔
469
                {
470
                        std::ostringstream ss_msg;
4✔
471
                        if (!p->i.ignore_similar_msr)
4✔
472
                                ss_msg << std::endl << "- Warning: ";
2✔
473
                        else
474
                                ss_msg << std::endl << "- Note: ";
2✔
475

476
                        ss_msg << msr << " measurement" << (msr > 1 ? "s were" : " was") << 
4✔
477
                                " found to be very similar (if not identical)\n  to " << 
478
                                (msr > 1 ? "other measurements" : "another measurement") << 
479
                                ".  See " << p->i.dms_file << " for details." << std::endl;
4✔
480

481
                        *imp_file << ss_msg.str();
4✔
482
                        if (!p->g.quiet)
4✔
483
                                std::cout << ss_msg.str();
6✔
484
                        ss_msg.str("");
12✔
485

486
                        try {
4✔
487
                                // Create duplicate measurements file
488
                                file_opener(dms_file, p->i.dms_file);
4✔
489
                        }
NEW
490
                        catch (const std::ios_base::failure& f) {
×
NEW
491
                                std::stringstream ss;
×
NEW
492
                                ss << "- Error: Could not open " << p->i.dms_file << "." << std::endl;
×
NEW
493
                                ss << "  Check that the file exists and that the file is not already opened." << std::endl << f.what();
×
494
                                if (!p->g.quiet)
×
NEW
495
                                        std::cout << ss.str();
×
496
                                *imp_file << ss.str();
×
497
                                imp_file->close();
×
498
                                return EXIT_FAILURE;
×
499
                        }
×
500

501
                        PrintOutputFileHeaderInfo(&dms_file, p->i.dms_file, p, "DUPLICATE MEASUREMENTS FILE");
8✔
502

503
                        // output message
504
                        dms_file << std::endl << "- " << msr << " measurement" << (msr > 1 ? "s were" : " was") << 
4✔
505
                                " found to be very similar (if not identical)\n  to " << 
506
                                (msr > 1 ? "other measurements." : "another measurement.  ");
4✔
507

508
                        if (p->i.ignore_similar_msr)
4✔
509
                                dms_file << std::endl << "+ These measurements have been ignored.";
2✔
510
                        dms_file << std::endl << std::endl;
4✔
511

512
                        // dump measurements to dms file
513
                        for_each (vSimilarMeasurements.begin(), vSimilarMeasurements.end(),
4✔
514
                                [&dms_file, &comment] (dnaMsrPtr& m) {
59✔
515
                                        m->WriteDynaMLMsr(&dms_file, comment);
59✔
516
                        });
59✔
517

518
                        dms_file.close();
4✔
519

520
                        if (p->i.ignore_similar_msr)
4✔
521
                                ss_msg << "  These measurements have been ignored." << std::endl;
2✔
522
                        else
523
                                ss_msg << std::endl <<
2✔
524
                                "  If the listed measurements are true duplicates, either remove each duplicate " << std::endl <<
2✔
525
                                "  from the measurement file and re-run " << __BINARY_NAME__ << ", or re-run " << __BINARY_NAME__ << " with the" << std::endl <<
2✔
526
                                "  --" << IGNORE_SIMILAR_MSRS << " option.  Alternatively, if each measurement " << std::endl <<
2✔
527
                                "  is unique, then call " << __BINARY_NAME__ << " without the --" << TEST_SIMILAR_MSRS << " option." << std::endl << std::endl;
2✔
528

529
                        if (!p->g.quiet)
4✔
530
                                std::cout << ss_msg.str();
6✔
531
                        *imp_file << ss_msg.str();
4✔
532

533
                        if (!p->i.ignore_similar_msr)
4✔
534
                        {
535
                                //imp_file->close();
536
                                return EXIT_SUCCESS;
537
                        }
538
                }
4✔
539
                else
540
                {
541
                        *imp_file << "Done. ";
×
542
                        if (!p->g.quiet)
×
543
                        {
NEW
544
                                std::cout << "Done. ";
×
NEW
545
                                std::cout.flush();
×
546
                        }
547
                }
548

549
                *imp_file << std::endl;
2✔
550
                if (!p->g.quiet)
2✔
551
                {
552
                        std::cout << std::endl;
2✔
553
                        std::cout.flush();
2✔
554
                }
555

556
        } 
557
        catch (const XMLInteropException& e) {
×
NEW
558
                std::cout << std::endl << "- Error: " << e.what() << std::endl;
×
NEW
559
                *imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
560
                imp_file->close();
×
561
                return EXIT_FAILURE;
×
562
        }
×
563

564
        return EXIT_SUCCESS;
565

566
}
4✔
567

568
void ReportExportedData(const project_settings& p, std::ostream& out, const size_t& file_type,
38✔
569
        const UINT32& stnCount, const UINT32& msrCount)
570
{
571
        std::string dataExported;
38✔
572
        if (stnCount > 0 && msrCount == 0)
38✔
573
                dataExported = "stations";
2✔
574
        else if (stnCount == 0 && msrCount > 0)
36✔
NEW
575
                dataExported = "measurements";
×
576
        else if (stnCount > 0 && msrCount > 0)
36✔
577
                dataExported = "stations and measurements";
36✔
578

579
        std::string stn_file, msr_file, single_file;
38✔
580
        bool print_single_xml = (p.i.export_single_xml_file && p.i.export_dynaml);
38✔
581

582
        switch (file_type)
38✔
583
        {
584
        case dna:
18✔
585
                stn_file =  leafStr<std::string>(p.i.dna_stnfile);
18✔
586
                msr_file =  leafStr<std::string>(p.i.dna_msrfile);
18✔
587
                break;
18✔
588
        case dynaml:
20✔
589
                if (print_single_xml)
20✔
590
                        single_file = leafStr<std::string>(p.i.xml_outfile);
8✔
591
                else
592
                {
593
                        stn_file = leafStr<std::string>(p.i.xml_stnfile);
16✔
594
                        msr_file = leafStr<std::string>(p.i.xml_msrfile);
32✔
595
                }
596
                break;
597
        default:
598
                break;
599
        }
600

601
        out << "+ Exporting " << dataExported << " to:" << std::endl;
38✔
602
        if (file_type == dynaml && print_single_xml)
38✔
603
                out << "  - " << single_file << "... ";
4✔
604
        else
605
        {
606
                if (stnCount > 0)
34✔
607
                {
608
                        out << "  - " << stn_file;
34✔
609
                        if (msrCount > 0)
34✔
610
                                out << std::endl;
32✔
611
                }
612
                if (msrCount > 0)
34✔
613
                        out << "  - " << msr_file;
32✔
614
                out << "... ";
34✔
615
        }
616
        out.flush();
38✔
617
}
152✔
618
        
619

620
void ExportStationsandMeasurements(dna_import* parserDynaML, const project_settings& p, std::ofstream* imp_file, vifm_t* vinput_file_meta,
14✔
621
        vdnaStnPtr* vstationsTotal, vdnaMsrPtr* vmeasurementsTotal, const UINT32& stnCount, const UINT32& msrCount)
622
{
623
        std::stringstream ssEpsgWarning;
14✔
624
        bool displayEpsgWarning(false);
14✔
625
        std::string epsgCode(epsgStringFromName<std::string>(p.i.reference_frame));
14✔
626

627
        // Check inconsistent reference frames
628
        if ((p.i.export_dynaml || p.i.export_dna_files) && !p.i.override_input_rfame)
14✔
629
        {
630
                for (UINT32 i(0); i<vinput_file_meta->size(); ++i)
34✔
631
                {
632
                        if (!boost::iequals(epsgCode, vinput_file_meta->at(i).epsgCode))
23✔
633
                        {
634
                                std::string inputFrame(datumFromEpsgString<std::string>(vinput_file_meta->at(i).epsgCode));
4✔
635
                                ssEpsgWarning << std::endl << "- Warning: The default reference frame (" << p.i.reference_frame  << ")" << 
4✔
636
                                        " used for all exported" << std::endl <<
4✔
637
                                        "  files does not match the reference frame of one or more input files." << std::endl <<
2✔
638
                                        "  To suppress this warning, override the default reference frame using" << std::endl <<
2✔
639
                                        "  --reference-frame, or provide --override-input-ref-frame.";
2✔
640
                                displayEpsgWarning = true;
2✔
641
                                break;
2✔
642
                        }
2✔
643
                }
644
        }
645

646
        // Sort on original file order
647
        parserDynaML->SortStationsForExport(vstationsTotal);
14✔
648

649
        // DynaML file format
650
        if (p.i.export_dynaml && (stnCount > 0 || msrCount > 0)) 
14✔
651
        {
652
                if (!p.g.quiet)
10✔
653
                        ReportExportedData(p, std::cout, dynaml, stnCount, msrCount);
10✔
654
                ReportExportedData(p, *imp_file, dynaml, stnCount, msrCount);
10✔
655
                
656
                if (p.i.export_single_xml_file)
10✔
657
                {
658
                        // Single output file
659
                        parserDynaML->SerialiseDynaMLfromMemory(
2✔
660
                                vstationsTotal, vmeasurementsTotal, 
661
                                p.i.xml_outfile, p, vinput_file_meta, (p.i.flag_unused_stn ? true : false));
2✔
662
                }
663
                else
664
                {
665
                        // Separate output files (default)
666
                        parserDynaML->SerialiseDynaMLSepfromMemory(
8✔
667
                                vstationsTotal, vmeasurementsTotal,
668
                                p.i.xml_stnfile, p.i.xml_msrfile, p, vinput_file_meta, (p.i.flag_unused_stn ? true : false));
8✔
669
                }
670
                if (!p.g.quiet)
10✔
671
                {
672
                        std::cout << "Done." << std::endl;
10✔
673
                        std::cout.flush();
10✔
674
                }
675
                *imp_file << "Done." << std::endl;                
10✔
676
        }
677

678
        // DNA file format
679
        if (p.i.export_dna_files && (stnCount > 0 || msrCount > 0)) 
14✔
680
        {
681
                // Separate output files (default)
682
                if (!p.g.quiet)
9✔
683
                        ReportExportedData(p, std::cout, dna, stnCount, msrCount);
9✔
684
                ReportExportedData(p, *imp_file, dna, stnCount, msrCount);
9✔
685

686
                parserDynaML->SerialiseDNA(
9✔
687
                        vstationsTotal, vmeasurementsTotal,
688
                        p.i.dna_stnfile, p.i.dna_msrfile, p, vinput_file_meta, (p.i.flag_unused_stn ? true : false));
9✔
689

690
                if (!p.g.quiet)
9✔
691
                        std::cout << "Done." << std::endl;
9✔
692
                *imp_file << "Done." << std::endl;
9✔
693
        }
694

695
        if (displayEpsgWarning)
14✔
696
        {
697
                std::cout << ssEpsgWarning.str() << std::endl;
2✔
698
                *imp_file << ssEpsgWarning.str() << std::endl;
2✔
699
                std::cout.flush();
2✔
700
        }
701
}
14✔
702

703
int PrepareImportSegmentedData(project_settings& p, bool& userSuppliedSegFile)
7✔
704
{
705
        // Form default seg file path
706
        userSuppliedSegFile = false;
7✔
707

708
        // Has the user provided a segmentation file?
709
        if (!p.i.seg_file.empty())
7✔
710
                userSuppliedSegFile = true;
1✔
711
        else
712
                p.i.seg_file = formPath<std::string>(p.g.input_folder, p.g.network_name, "seg");
18✔
713

714
        if (!boost::filesystem::exists(p.i.seg_file))
14✔
715
        {
NEW
716
                std::cout << std::endl << "- Error: The required segmentation file does not exist:" << std::endl <<
×
NEW
717
                        "         " << p.i.seg_file << std::endl << std::endl <<
×
NEW
718
                        "  Run  'segment " << p.g.network_name << "' to create a segmentation file" << std::endl << std::endl;
×
UNCOV
719
                return EXIT_FAILURE;
×
720
        }
721

722
        if (!boost::filesystem::exists(p.i.bst_file))
14✔
723
        {
NEW
724
                std::cout << std::endl << "- Error: The required binary station file does not exist:" << std::endl <<
×
NEW
725
                        "         " << p.i.bst_file << std::endl << std::endl;
×
UNCOV
726
                return EXIT_FAILURE;
×
727
        }
728

729
        if (!boost::filesystem::exists(p.i.bms_file))
14✔
730
        {
NEW
731
                std::cout << std::endl << "- Error: The required binary measurement file does not exist:" << std::endl <<
×
NEW
732
                        "         " << p.i.bms_file << std::endl << std::endl;
×
UNCOV
733
                return EXIT_FAILURE;
×
734
        }
735

736
        // If the user has not provided a seg file, check the meta of the default file
737
        if (!userSuppliedSegFile)
7✔
738
        {
739
                if (boost::filesystem::last_write_time(p.i.seg_file) < boost::filesystem::last_write_time(p.i.bst_file) ||
18✔
740
                        boost::filesystem::last_write_time(p.i.seg_file) < boost::filesystem::last_write_time(p.i.bms_file))
18✔
741
                {
742
                        // Has import been run after the segmentation file was created?
743
                        binary_file_meta_t bst_meta, bms_meta;
×
744
                        dna_io_bst bst;
×
745
                        dna_io_bms bms;
×
746
                        bst.load_bst_file_meta(p.i.bst_file, bst_meta);
×
747
                        bms.load_bms_file_meta(p.i.bms_file, bms_meta);
×
748

NEW
749
                        bool bst_meta_import(boost::iequals(bst_meta.modifiedBy, __import_app_name__) ||
×
NEW
750
                                boost::iequals(bst_meta.modifiedBy, __import_dll_name__));
×
NEW
751
                        bool bms_meta_import(boost::iequals(bms_meta.modifiedBy, __import_app_name__) ||
×
NEW
752
                                boost::iequals(bms_meta.modifiedBy, __import_dll_name__));
×
753

NEW
754
                        if ((bst_meta_import && (boost::filesystem::last_write_time(p.i.seg_file) < boost::filesystem::last_write_time(p.i.bst_file))) ||
×
NEW
755
                                (bms_meta_import && (boost::filesystem::last_write_time(p.i.seg_file) < boost::filesystem::last_write_time(p.i.bms_file))))
×
756
                        {
757

NEW
758
                                std::cout << std::endl << std::endl <<
×
NEW
759
                                        "- Error: The raw stations and measurements have been imported after" << std::endl <<
×
NEW
760
                                        "  the segmentation file was created:" << std::endl;
×
761

NEW
762
                                time_t t_bst(boost::filesystem::last_write_time(p.i.bst_file)), t_bms(boost::filesystem::last_write_time(p.i.bms_file));
×
NEW
763
                                time_t t_seg(boost::filesystem::last_write_time(p.i.seg_file));
×
764

NEW
765
                                std::cout << "   " << leafStr<std::string>(p.i.bst_file) << "  last modified on  " << ctime(&t_bst);
×
NEW
766
                                std::cout << "   " << leafStr<std::string>(p.i.bms_file) << "  last modified on  " << ctime(&t_bms) << std::endl;
×
NEW
767
                                std::cout << "   " << leafStr<std::string>(p.i.seg_file) << "  created on  " << ctime(&t_seg) << std::endl;
×
NEW
768
                                std::cout << "  Run 'segment " << p.g.network_name << " [options]' to re-create the segmentation file, or re-run" << std::endl <<
×
NEW
769
                                        "  the import using the " << SEG_FILE << " option if this segmentation file must\n  be used." << std::endl << std::endl;
×
UNCOV
770
                                return EXIT_FAILURE;
×
771
                        }
772
                }
×
773
        }
774

775
        return EXIT_SUCCESS;
776
}
777

778
int ImportSegmentedBlock(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements, 
5✔
779
                StnTally* parsestnTally, MsrTally* parsemsrTally, project_settings& p)
780
{        
781
        // Form default seg file path
782
        bool userSuppliedSegFile(false);
5✔
783

784
        if (PrepareImportSegmentedData(p, userSuppliedSegFile) != EXIT_SUCCESS)
5✔
785
                return EXIT_FAILURE;
786

787
        // Import stations and measurements from a particular block
788
        if (!p.g.quiet)
5✔
789
                std::cout << std::endl << "+ Importing stations and measurements from block " << p.i.import_block_number << " of\n  " << p.i.seg_file << "... ";
5✔
790

791
        try {
5✔
792
                parserDynaML.ImportStnsMsrsFromBlock(vStations, vMeasurements, p);
5✔
793
        }
794
        catch (const XMLInteropException& e) {
1✔
795
                std::stringstream ss;
1✔
796
                ss << std::endl << std::endl << "- Error: " << e.what();
1✔
797
                std::cout << ss.str() << std::endl;
1✔
798
                return EXIT_FAILURE;
1✔
799
        }
1✔
800

801
        *parsestnTally += parserDynaML.GetStnTally();
4✔
802
        *parsemsrTally += parserDynaML.GetMsrTally();
4✔
803
        if (!p.g.quiet)
4✔
804
                std::cout << "Done. " << std::endl;
4✔
805

806
        // Restore seg_file to null
807
        if (!userSuppliedSegFile)
4✔
808
                p.i.seg_file = "";
5✔
809

810
        return EXIT_SUCCESS;
811
}
812

813
int ImportContiguousNetwork(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements,
2✔
814
        StnTally* parsestnTally, MsrTally* parsemsrTally, project_settings& p)
815
{
816
        // Form default seg file path
817
        bool userSuppliedSegFile(false);
2✔
818

819
        if (PrepareImportSegmentedData(p, userSuppliedSegFile) != EXIT_SUCCESS)
2✔
820
                return EXIT_FAILURE;
821

822
        // Import stations and measurements from a particular block
823
        if (!p.g.quiet)
2✔
824
                std::cout << std::endl << "+ Importing stations and measurements from contiguous network " << p.i.import_network_number << " of\n  " << p.i.seg_file << "... ";
2✔
825

826
        try {
2✔
827
                parserDynaML.ImportStnsMsrsFromNetwork(vStations, vMeasurements, p);
2✔
828
        }
829
        catch (const XMLInteropException& e) {
1✔
830
                std::stringstream ss;
1✔
831
                ss << std::endl << std::endl << "- Error: " << e.what();
1✔
832
                std::cout << ss.str() << std::endl;
1✔
833
                return EXIT_FAILURE;
1✔
834
        }
1✔
835

836
        *parsestnTally += parserDynaML.GetStnTally();
1✔
837
        *parsemsrTally += parserDynaML.GetMsrTally();
1✔
838
        if (!p.g.quiet)
1✔
839
                std::cout << "Done. " << std::endl;
1✔
840

841
        // Restore seg_file to null
842
        if (!userSuppliedSegFile)
1✔
843
                p.i.seg_file = "";
2✔
844

845
        return EXIT_SUCCESS;
846
}
847
        
848

849
int ImportDataFiles(dna_import& parserDynaML, vdnaStnPtr* vStations, vdnaMsrPtr* vMeasurements,
84✔
850
                vdnaStnPtr* vstationsTotal, vdnaMsrPtr* vmeasurementsTotal,
851
                std::ofstream* imp_file, vifm_t* vinput_file_meta, StnTally* parsestnTally, MsrTally* parsemsrTally, 
852
                UINT32& errorCount, project_settings& p)
853
{
854
        // For consideration:  
855
        //        - All input files could be read concurrently using multi-thread for faster input
856
        //        - The number of files that can be processed concurrently should be restricted to
857
        //          the number of available cores
858
        //        - If multi-threading is to be used, then the progress thread will need to be redesigned.
859
        //          Currently, the progress of each file (as a percentage) is written to cout as each file
860
        //          is processed. If files are processed concurrently, progress reporting will need to be
861
        //    redesigned if multiple progress threads are writing to cout.
862
        //        - There is significant gain in using multi-thread.
863
        //        - The catch will be the need to carefully design one progress thread that captures progress
864
        //          of all other "read" threads (rather than one progress for each), and somehow write to 
865
        //          cout the respective progress.  For example, loading four files could be displayed as 
866
        //          follows:
867
        //
868
        //          + Parsing file1.xml (32%), file2.xml (16%), file3.xml (86%), file4.xml (56%)
869
        //            Done: Loaded 190 stations from file3.xml in 00.032s
870
        //          + Parsing file1.xml (72%), file2.xml (48%), file4.xml (91%)
871
        //            Done: Loaded 236 stations from file4.xml in 00.050s
872
        //          + Parsing file1.xml (87%), file2.xml (76%)
873
        //            Done: Loaded 1596 measurements from file1.xml in 01.380s
874
        //            Done: Loaded 3142 measurements from file2.xml in 02.034s
875
        //
876
        UINT32 stnCount(0), msrCount(0), clusterID(0);
84✔
877
        
878
        size_t pos = std::string::npos;
84✔
879
        size_t strlen_arg = 0;
84✔
880
        for_each(p.i.input_files.begin(), p.i.input_files.end(),
84✔
881
                [&strlen_arg](std::string& file) {
187✔
882
                        if (leafStr<std::string>(file).length() > strlen_arg)
374✔
883
                                strlen_arg = leafStr<std::string>(file).length();
188✔
884
        });
187✔
885

886
        strlen_arg += (6 + PROGRESS_PERCENT_04);
84✔
887

888
        size_t i, nfiles(p.i.input_files.size());                // for each file...
84✔
889
        std::string input_file, ss, status_msg;
84✔
890
        std::ostringstream ss_time, ss_msg;
84✔
891
        input_file_meta_t input_file_meta;
84✔
892
        boost::posix_time::milliseconds elapsed_time(boost::posix_time::milliseconds(0));
84✔
893
        boost::posix_time::ptime pt;
84✔
894

895
        if (!p.g.quiet)
84✔
896
                std::cout << "+ Parsing: " << std::endl;
83✔
897
        *imp_file << "+ Parsing " << std::endl;
84✔
898

899
        bool firstFile;
84✔
900

901
        // obtain the (default) project reference frame epsg code
902
        std::string projectEpsgCode(epsgStringFromName<std::string>(p.i.reference_frame));
84✔
903

904
        for (i=0; i<nfiles; i++)
265✔
905
        {
906
                stnCount = msrCount = 0;
185✔
907
                input_file = p.i.input_files.at(i);
185✔
908
                if (!boost::filesystem::exists(input_file))
370✔
909
                {
910
                        input_file = formPath<std::string>(p.g.input_folder, input_file);
8✔
911
                        if (!boost::filesystem::exists(input_file))
8✔
912
                        {        
913
                                std::cout << "- Error:  " << input_file << " does not exist" << std::endl;
4✔
914
                                return EXIT_FAILURE;
4✔
915
                        }
916
                }
917
                        
918
                ss = leafStr<std::string>(p.i.input_files.at(i)) + "... ";
543✔
919
                if (!p.g.quiet)
181✔
920
                        std::cout << "  " << std::setw(strlen_arg) << std::left << ss;
179✔
921
                *imp_file << "  " << std::setw(strlen_arg) << std::left << ss;
181✔
922

923
                running = true;
181✔
924
                firstFile = bool(i == 0);
181✔
925

926
                boost::thread_group ui_interop_threads;
181✔
927
                if (!p.g.quiet)
181✔
928
                        ui_interop_threads.create_thread(dna_import_progress_thread(&parserDynaML, &p));
179✔
929
                ui_interop_threads.create_thread(dna_import_thread(&parserDynaML, &p, input_file,
181✔
930
                        vStations, &stnCount, vMeasurements, &msrCount,
931
                        &clusterID, &input_file_meta, firstFile, &status_msg,
932
                        &elapsed_time));
933
                ui_interop_threads.join_all();
181✔
934

935
                switch (parserDynaML.GetStatus())
181✔
936
                {
937
                case PARSE_EXCEPTION_RAISED:
×
NEW
938
                        *imp_file << std::endl << status_msg;
×
939
                        running = false;
×
940
                        return EXIT_FAILURE;
×
941
                        break;
×
942
                case PARSE_UNRECOGNISED_FILE:
×
NEW
943
                        *imp_file << status_msg << std::endl;
×
944
                        errorCount++;
×
945
                        continue;
×
946
                case PARSE_SUCCESS:
181✔
947
                        running = false;
181✔
948
                        break;
181✔
949
                default:
×
950
                        errorCount++;
×
NEW
951
                        std::cout << std::endl;
×
952
                        continue;
×
953
                }
954

955
                vinput_file_meta->push_back(input_file_meta);
181✔
956

957
                ss_time.str("");
543✔
958

959
                if (stnCount > 0 || msrCount > 0) // stations or measurements only
181✔
960
                {                        
961
                        ss_time << "  Done. Loaded ";
180✔
962
                        if (stnCount)
180✔
963
                                ss_time << stnCount << " stations";
91✔
964
                        if (stnCount && msrCount)
180✔
965
                                ss_time << " and ";
8✔
966
                        if (msrCount)
180✔
967
                                ss_time << msrCount << " measurements";
97✔
968
                        ss_time << " in ";
180✔
969
                                
970
                        pt = boost::posix_time::ptime(boost::gregorian::day_clock::local_day(), elapsed_time);
180✔
971
                        if (elapsed_time < boost::posix_time::seconds(3))
180✔
972
                        {
973
                                boost::posix_time::time_facet* facet(new boost::posix_time::time_facet("%s"));
180✔
974
                                ss_time.imbue(std::locale(ss_time.getloc(), facet));
180✔
975
                                ss_time << pt << "s";                        
180✔
976
                        }
NEW
977
                        else if (elapsed_time < boost::posix_time::seconds(61))
×
978
                        {                
NEW
979
                                boost::posix_time::time_facet* facet(new boost::posix_time::time_facet("%S"));
×
NEW
980
                                ss_time.imbue(std::locale(ss_time.getloc(), facet));
×
UNCOV
981
                                ss_time << pt << "s";
×
982
                        }
983
                        else
984
                                ss_time << elapsed_time;
×
985

986
                        std::string time_message = ss_time.str();
180✔
987
                        while ((pos = time_message.find("0s")) != std::string::npos)
1,160✔
988
                                time_message = time_message.substr(0, pos) + "s";
3,920✔
989

990
                        if ((pos = time_message.find(" 00.")) != std::string::npos)
180✔
991
                                time_message = time_message.replace(pos, 4, " 0.");
180✔
992
                        if ((pos = time_message.find(" 0.s")) != std::string::npos)
180✔
993
                                time_message = time_message.replace(pos, 4, " 0s");
130✔
994

995
                        if (!p.g.quiet)
180✔
996
                        {
997
                                if (isatty(fileno(stdout)))
178✔
NEW
998
                                        std::cout << PROGRESS_BACKSPACE_04;
×
999
                                std::cout << time_message << std::endl;
178✔
1000
                        }
1001
                        *imp_file << time_message << std::endl;
180✔
1002

1003
                        // Capture the input file's default reference frame and set the
1004
                        // project reference frame (if not specified on the command-line)
1005
                        std::string inputFileEpsg(""), inputFileDatum(""), inputFileEpoch("");
180✔
1006
                        UINT32 inputFileEpsgi;
180✔
1007
                        try {
180✔
1008
                                inputFileDatum = datumFromEpsgString<std::string>(input_file_meta.epsgCode);
540✔
1009
                                inputFileEpsg = input_file_meta.epsgCode;
180✔
1010
                                inputFileEpsgi = LongFromString<UINT32>(inputFileEpsg);
180✔
1011
                                inputFileEpoch = input_file_meta.epoch;
180✔
1012
                        }
NEW
1013
                        catch (...) 
×
1014
                        {
1015
                                // Do nothing, revert to defaults
1016
                                // p.i.reference_frame
1017
                                // p.i.epoch
UNCOV
1018
                        }
×
1019

1020
                        // Is this the first file?  If so, attempt to set the default datum from
1021
                        // the input file (if applicable).
1022
                        
1023
                        bool referenceframeChanged(false);
180✔
1024
                        bool epochChanged(false);
180✔
1025
                        
1026
                        if (firstFile)
180✔
1027
                        {
1028
                                bool isStaticFrame(false);
80✔
1029

1030
                                // If the user has not provided a reference frame, then inspect the file reference frame
1031
                                // If the file does not contain a reference frame (e.g. SNX) or the user has left it blank, 
1032
                                // fileEpsg will be empty. Thus, no change will occur (retain the default GDA2020).
1033
                                if (!inputFileEpsg.empty() && !p.i.user_supplied_frame)
80✔
1034
                                {
1035
                                        // Set the project defaults
1036
                                        referenceframeChanged = true;
38✔
1037
                                        
1038
                                        p.i.reference_frame = inputFileDatum;
38✔
1039
                                        p.r.reference_frame = inputFileDatum;
38✔
1040
                                        projectEpsgCode = epsgStringFromName<std::string>(p.i.reference_frame);
76✔
1041
                                }
1042

1043
                                isStaticFrame = isEpsgDatumStatic(LongFromString<UINT32>(projectEpsgCode));
80✔
1044
                                
1045
                                // Has the user supplied a static reference frame?  
1046
                                // If so, set the epoch
1047
                                if (p.i.user_supplied_frame && isStaticFrame)
80✔
1048
                                {
1049
                                        p.i.epoch = referenceepochFromEpsgString<std::string>(projectEpsgCode);
9✔
1050
                                        p.r.epoch = p.i.epoch;
9✔
1051
                                }
1052
                                else if (!p.i.user_supplied_epoch)
71✔
1053
                                {
1054
                                        if (inputFileEpoch.empty())
56✔
1055
                                        {                                                
1056
                                                // revert to epoch of the file frame
NEW
1057
                                                p.i.epoch = referenceepochFromEpsgCode<UINT32>(inputFileEpsgi);                                                
×
NEW
1058
                                                p.r.epoch = p.i.epoch;
×
1059
                                        }
1060
                                        else
1061
                                        {
1062
                                                p.i.epoch = inputFileEpoch;
56✔
1063
                                                p.r.epoch = p.i.epoch;
56✔
1064
                                        }
1065
                                }
1066
                                                        
1067

1068
                                try {
80✔
1069
                                        // Initialise the 'default' datum (frame and epoch) for the project, from the first file, unless the
1070
                                        // frame and epoch have been set by the user, in which case InitialiseDatum has already initialised the datum.
1071
                                        parserDynaML.InitialiseDatum(p.i.reference_frame, p.i.epoch);
80✔
1072
                                }
NEW
1073
                                catch (const XMLInteropException& e) {
×
NEW
1074
                                        std::stringstream ss;
×
NEW
1075
                                        ss << "- Error: ";
×
NEW
1076
                                        std::cout << ss.str() << e.what() << std::endl;
×
NEW
1077
                                        return EXIT_FAILURE;
×
NEW
1078
                                }
×
1079

1080
                                if (p.i.import_block || p.i.import_network)
80✔
NEW
1081
                                        continue;
×
1082

1083
                                // When the user has not supplied a frame on the command line
1084
                                if (!p.i.user_supplied_frame)
80✔
1085
                                {
1086
                                        // reference frame
1087
                                        std::stringstream datumSource;
38✔
1088
                                        switch (input_file_meta.filetype)
38✔
1089
                                        {
NEW
1090
                                        case sinex:
×
NEW
1091
                                                datumSource << ". DynAdjust default (frame not present within SNX file)";
×
1092
                                                break;
1093
                                        default:
38✔
1094
                                                if (parserDynaML.filespecifiedReferenceFrame())
38✔
1095
                                                        datumSource << ". Taken from " << FormatFileType<std::string>(input_file_meta.filetype) << " header.";
114✔
1096
                                                else
NEW
1097
                                                        datumSource << ". Reference frame not supplied in " << FormatFileType<std::string>(input_file_meta.filetype) << " header.";
×
1098
                                        }
1099

1100
                                        if (!p.g.quiet)
38✔
1101
                                                std::cout << std::left << "  Project reference frame set to " << p.i.reference_frame << datumSource.str() << std::endl;
76✔
1102
                                        *imp_file << std::left << "  Project reference frame set to " << p.i.reference_frame << datumSource.str() << std::endl;
38✔
1103
                                }                                
38✔
1104
                                // When the user has supplied a frame on the command line, and the input file datum field is blank
1105
                                else if (!parserDynaML.filespecifiedReferenceFrame())
42✔
1106
                                {
1107
                                        std::stringstream ssEpsgWarning;
6✔
1108
                                        switch (input_file_meta.filetype)
6✔
1109
                                        {
1110
                                        case sinex:
6✔
1111
                                                ssEpsgWarning << "  - Warning: SNX reference frame set to " << p.i.reference_frame << ".";
6✔
1112
                                                break;
NEW
1113
                                        default:
×
NEW
1114
                                                ssEpsgWarning << "  - Warning: Input file reference frame not supplied. Adopting " << inputFileDatum << ".";
×
1115
                                        }                                
1116

1117
                                        if (!p.g.quiet)
6✔
1118
                                                std::cout << ssEpsgWarning.str() << std::endl;
12✔
1119
                                        *imp_file << ssEpsgWarning.str() << std::endl;
6✔
1120
                                }
6✔
1121
                                // when reference frame has been supplied and the value in the file doesn't match
1122
                                else if (p.i.user_supplied_frame)
36✔
1123
                                {
1124
                                        if (!boost::iequals(projectEpsgCode, input_file_meta.epsgCode))
36✔
1125
                                        {
1126
                                                std::stringstream ssEpsgWarning;
34✔
1127
                                                ssEpsgWarning << "  - Warning: File reference frame (" << inputFileDatum << ") differs from project frame (" << p.i.reference_frame << ").";
34✔
1128
                                                if (!p.g.quiet)
34✔
1129
                                                        std::cout << ssEpsgWarning.str() << std::endl;
66✔
1130
                                                *imp_file << ssEpsgWarning.str() << std::endl;
34✔
1131
                                        }
34✔
1132
                                }
1133

1134
                                // When the user has not supplied an epoch on the command line
1135
                                if (!p.i.user_supplied_epoch)
80✔
1136
                                {
1137
                                        // epoch
1138
                                        std::stringstream epochSource;
65✔
1139
                                        if (isStaticFrame)
65✔
1140
                                        {
1141
                                                epochSource << "  - Warning: File epoch (" << inputFileEpoch << ") will be ignored." << std::endl;
42✔
1142
                                                if (!p.g.quiet)
42✔
1143
                                                        std::cout << epochSource.str();
84✔
1144
                                                *imp_file << epochSource.str();
84✔
1145
                                        }
1146
                                        else
1147
                                        {
1148
                                                if (parserDynaML.filespecifiedEpoch())
23✔
1149
                                                {
1150
                                                        if (isEpsgDatumStatic(inputFileEpsgi))
23✔
1151
                                                                epochSource << " (adopted reference epoch of " << inputFileDatum << ").";
10✔
1152
                                                        else
1153
                                                                epochSource << ". Taken from " << FormatFileType<std::string>(input_file_meta.filetype) << " header.";
39✔
1154
                                                }
1155
                                                else
NEW
1156
                                                        epochSource << ". Epoch not supplied in " << FormatFileType<std::string>(input_file_meta.filetype) << " header.";
×
1157
                                                if (!p.g.quiet)
23✔
1158
                                                        std::cout << std::left << "  Project epoch set to " << p.i.epoch << epochSource.str() << std::endl;
44✔
1159
                                                *imp_file << std::left << "  Project epoch set to " << p.i.epoch << epochSource.str() << std::endl;
23✔
1160
                                                epochChanged = true;
23✔
1161
                                        }
1162
                                }                                
65✔
1163
                                // When the user has supplied an epoch on the command line, and the input file epoch field is blank
1164
                                else if (!parserDynaML.filespecifiedEpoch())
15✔
1165
                                {
NEW
1166
                                        std::stringstream ssEpochWarning;
×
NEW
1167
                                        ssEpochWarning << "  - Warning: Input file epoch not supplied. Adopting " << p.i.epoch << ".";
×
1168

NEW
1169
                                        if (!p.g.quiet)
×
NEW
1170
                                                std::cout << ssEpochWarning.str() << std::endl;
×
NEW
1171
                                        *imp_file << ssEpochWarning.str() << std::endl;
×
NEW
1172
                                }
×
1173
                                // when epoch has been supplied and the value in the file doesn't match
1174
                                else if (p.i.user_supplied_epoch)
15✔
1175
                                {
1176
                                        if (!boost::iequals(p.i.epoch, input_file_meta.epoch))
15✔
1177
                                        {
1178
                                                std::stringstream ssEpochWarning;
15✔
1179
                                                ssEpochWarning << "  - Warning: File epoch (" << inputFileEpoch << ") differs from project epoch (" << p.i.epoch << ").";
15✔
1180
                                                if (!p.g.quiet)
15✔
1181
                                                        std::cout << ssEpochWarning.str() << std::endl;
30✔
1182
                                                *imp_file << ssEpochWarning.str() << std::endl;
15✔
1183
                                        }
15✔
1184
                                }
1185

1186
                                if (referenceframeChanged || epochChanged)
80✔
1187
                                {
1188
                                        if (!p.g.quiet)
56✔
1189
                                                std::cout << std::endl;
55✔
1190
                                        *imp_file << std::endl;
180✔
1191
                                }
1192
                        }
1193
                        else
1194
                        {
1195
                                if (p.i.import_block || p.i.import_network)
100✔
NEW
1196
                                        continue;
×
1197

1198
                                // Was the datum field empty in the file?
1199
                                if (!parserDynaML.filespecifiedReferenceFrame())
100✔
1200
                                {                                        
1201
                                        std::stringstream ssEpsgWarning;
2✔
1202
                                        ssEpsgWarning << "  - Warning: Input file reference frame not supplied. Adopting " << inputFileDatum << ".";
2✔
1203
                                        if (!p.g.quiet)
2✔
1204
                                                std::cout << ssEpsgWarning.str() << std::endl;
4✔
1205
                                        *imp_file << ssEpsgWarning.str() << std::endl;                                        
2✔
1206
                                }
2✔
1207
                                // Is the datum in the file different to the project datum?
1208
                                else if (!boost::iequals(projectEpsgCode, input_file_meta.epsgCode))
98✔
1209
                                {
1210
                                        std::stringstream ssEpsgWarning;
51✔
1211
                                        if (referenceframeChanged)
51✔
1212
                                        {
1213
                                                ssEpsgWarning << "  - Warning: The project reference frame has been set to the default" << std::endl <<
1214
                                                        "    file datum of " << leafStr<std::string>(p.i.input_files.at(i)) << " (" << inputFileDatum << ").";
1215

1216
                                                // set the project reference frame epsg code
1217
                                                projectEpsgCode = epsgStringFromName<std::string>(p.i.reference_frame);
1218
                                        }
1219
                                        else
1220
                                        {
1221
                                                ssEpsgWarning << "  - Warning: File reference frame (" << inputFileDatum << ") differs from project frame (" << p.i.reference_frame << ").";
51✔
1222
                                        }
1223

1224
                                        if (!p.g.quiet)
51✔
1225
                                                std::cout << ssEpsgWarning.str() << std::endl;
100✔
1226
                                        *imp_file << ssEpsgWarning.str() << std::endl;
51✔
1227
                                }
51✔
1228

1229
                                // Was the epoch field empty in the file?
1230
                                if (!parserDynaML.filespecifiedEpoch())
100✔
1231
                                {
1232
                                        std::stringstream ssEpochWarning;
1✔
1233
                                        ssEpochWarning << "  - Warning: Input file epoch not supplied. Adopting " << p.i.epoch << ".";
1✔
1234
                                        if (!p.g.quiet)
1✔
1235
                                                std::cout << ssEpochWarning.str() << std::endl;
2✔
1236
                                        *imp_file << ssEpochWarning.str() << std::endl;
1✔
1237
                                }
1✔
1238
                                // Is the epoch in the file different to the project epoch?
1239
                                else if (!boost::iequals(p.i.epoch, input_file_meta.epoch))
99✔
1240
                                {
1241
                                        std::stringstream ssEpochWarning;
41✔
1242
                                        
1243
                                        ssEpochWarning << "  - Warning: File epoch (" << inputFileEpoch << ") differs from project epoch (" << p.i.epoch << ").";
41✔
1244

1245
                                        if (!p.g.quiet)
41✔
1246
                                                std::cout << ssEpochWarning.str() << std::endl;
82✔
1247
                                        *imp_file << ssEpochWarning.str() << std::endl;
41✔
1248
                                }
41✔
1249
                        }
1250
                }
720✔
1251

1252
                // Handle discontinuities for non-sinex files, if and only if a discontinuity file has been loaded.
1253
                // NOTE: If a station is marked as a discontinuity site, and that same station is in the renaming
1254
                // file, station renaming for that site will not occur.  This is because the site name will be changed
1255
                // to <site-name>_yyyymmdd.
1256
                // If renaming must still occur, then it might be possible to rename using the first part of the name.
1257
                
1258

1259
                if (stnCount > 0) // stations only
181✔
1260
                {
1261
                        //vstationsTotal.reserve(vstationsTotal.size() + stnCount);
1262
                        // combine stations and station tally
1263
                        vstationsTotal->insert(vstationsTotal->end(), vStations->begin(), vStations->end());
91✔
1264
                        *parsestnTally += parserDynaML.GetStnTally();
91✔
1265
                        vStations->clear();
91✔
1266
                }
1267
                if (msrCount > 0) // measurements only
181✔
1268
                {                
1269
                        //vmeasurementsTotal.reserve(vmeasurementsTotal.size() + msrCount);
1270
                        // combine measurements
1271
                        vmeasurementsTotal->insert(vmeasurementsTotal->end(), vMeasurements->begin(), vMeasurements->end());
97✔
1272
                        *parsemsrTally += parserDynaML.GetMsrTally();
97✔
1273
                        vMeasurements->clear();
97✔
1274
                }
1275
        }
181✔
1276

1277
        if (errorCount == nfiles || (vstationsTotal->empty() && vmeasurementsTotal->empty()))
80✔
1278
                return EXIT_FAILURE;
1279

1280
        running = false;
80✔
1281
        return EXIT_SUCCESS;
80✔
1282
}
336✔
1283

1284
int main(int argc, char* argv[])
108✔
1285
{
1286
        // create banner message
1287
        std::string cmd_line_banner;
108✔
1288
        fileproc_help_header(&cmd_line_banner);
108✔
1289

1290
        project_settings p;
108✔
1291

1292
        boost::program_options::variables_map vm;
108✔
1293
        boost::program_options::positional_options_description positional_options;
108✔
1294

1295
        boost::program_options::options_description standard_options("+ " + std::string(ALL_MODULE_STDOPT), PROGRAM_OPTIONS_LINE_LENGTH);
324✔
1296
        boost::program_options::options_description ref_frame_options("+ " + std::string(IMPORT_MODULE_FRAME), PROGRAM_OPTIONS_LINE_LENGTH);
324✔
1297
        boost::program_options::options_description data_screening_options("+ " + std::string(IMPORT_MODULE_SCREEN), PROGRAM_OPTIONS_LINE_LENGTH);
324✔
1298
        boost::program_options::options_description gnss_scaling_options("+ " + std::string(IMPORT_MODULE_GNSS_VAR), PROGRAM_OPTIONS_LINE_LENGTH);
324✔
1299
        boost::program_options::options_description simulation_options("+ " + std::string(IMPORT_MODULE_SIMULATE), PROGRAM_OPTIONS_LINE_LENGTH);
324✔
1300
        boost::program_options::options_description output_options("+ " + std::string(ALL_MODULE_OUTPUT), PROGRAM_OPTIONS_LINE_LENGTH);
324✔
1301
        boost::program_options::options_description export_options("+ " + std::string(ALL_MODULE_EXPORT), PROGRAM_OPTIONS_LINE_LENGTH);
324✔
1302
        boost::program_options::options_description generic_options("+ " + std::string(ALL_MODULE_GENERIC), PROGRAM_OPTIONS_LINE_LENGTH);
324✔
1303

1304
        std::string cmd_line_usage("+ ");
108✔
1305
        cmd_line_usage.append(__BINARY_NAME__).append(" usage:  ").append(__BINARY_NAME__).append(" [options] [files]...");
108✔
1306
        boost::program_options::options_description allowable_options(cmd_line_usage, PROGRAM_OPTIONS_LINE_LENGTH);
108✔
1307

1308
        try {
108✔
1309
                // Declare a group of options that will be 
1310
                // allowed only on command line                
1311
                standard_options.add_options()
108✔
1312
                        (PROJECT_FILE_P, boost::program_options::value<std::string>(&p.g.project_file),
108✔
1313
                                "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.")
1314
                        (NETWORK_NAME_N, boost::program_options::value<std::string>(&p.g.network_name), 
108✔
1315
                                "Network name. User defined name for all input and output files. Default is \"network#\", where # is incremented until the first available network is reached.")
1316
                        (IMPORT_FILE_F, boost::program_options::value< vstring >(&p.i.input_files), 
108✔
1317
                                "Station and measurement input file(s). Switch is not required.")
1318
                        (IMPORT_GEO_FILE_G, boost::program_options::value<std::string>(&p.i.geo_file),
108✔
1319
                                "Import DNA geoid file.")
1320
                        (INPUT_FOLDER_I, boost::program_options::value<std::string>(&p.g.input_folder),
108✔
1321
                                "Path containing all input files.")
1322
                        (OUTPUT_FOLDER_O, boost::program_options::value<std::string>(&p.g.output_folder),                // default is ./,
108✔
1323
                                "Path for all output files.")
1324
                        (BIN_STN_FILE_S, boost::program_options::value<std::string>(&p.i.bst_file),
108✔
1325
                                "Binary station output file name. Overrides network name.")
1326
                        (BIN_MSR_FILE_M, boost::program_options::value<std::string>(&p.i.bms_file),
108✔
1327
                                "Binary measurement output file name. Overrides network name.")
1328
                        ;
1329

1330
                ref_frame_options.add_options()
108✔
1331
                        (REFERENCE_FRAME_R, boost::program_options::value<std::string>(&p.i.reference_frame), 
108✔
1332
                        (std::string("Project reference frame for all stations, measurements, and preliminary reductions on the ellipsoid when input files do not specify a reference frame. Default is ") +
324✔
1333
                                p.i.reference_frame + ".").c_str())
216✔
1334
                        (EPOCH_E, boost::program_options::value<std::string>(&p.i.epoch),
108✔
1335
                        (std::string("Project epoch for all stations and measurements when input files do not specify an epoch. Default is ") +
324✔
1336
                                p.i.epoch + ".").c_str())
324✔
1337
                        (OVERRIDE_INPUT_FRAME,
108✔
1338
                                (std::string("Replace the reference frame specified in the input files with the reference frame specified by arg in --") +
432✔
1339
                                std::string(REFERENCE_FRAME)).c_str())
216✔
1340
                        ;
1341

1342
                data_screening_options.add_options()
108✔
1343
                        (BOUNDING_BOX, boost::program_options::value<std::string>(&p.i.bounding_box),
108✔
1344
                                "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.")
1345
                        (GET_MSRS_TRANSCENDING_BOX,
108✔
1346
                                "Include measurements which transcend bounding box, including associated stations.")
1347
                        (INCLUDE_STN_ASSOC_MSRS, boost::program_options::value<std::string>(&p.i.stn_associated_msr_include),
108✔
1348
                                "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.")
1349
                        (EXCLUDE_STN_ASSOC_MSRS, boost::program_options::value<std::string>(&p.i.stn_associated_msr_exclude),
108✔
1350
                                "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.")
1351
                        (SPLIT_CLUSTERS,
108✔
1352
                                "Allow bounding-box or get-stns-and-assoc-msrs to split GNSS point and baseline cluster measurements.")
1353
                        (IMPORT_SEG_BLOCK, boost::program_options::value<UINT32>(&p.i.import_block_number),
108✔
1354
                                "Extract stations and measurements from this block.")
1355
                        (IMPORT_CONTIG_NET, boost::program_options::value<UINT32>(&p.i.import_network_number),
108✔
1356
                                "Extract stations and measurements from this contiguous network.")
1357
                        (SEG_FILE, boost::program_options::value<std::string>(&p.i.seg_file),
108✔
1358
                                "Network segmentation input file. Filename overrides network name.")
1359
                        (PREFER_X_MSR_AS_G,
108✔
1360
                                "Import single baseline cluster measurements (X) as single baselines (G).")
1361
                        (INCLUDE_MSRS, boost::program_options::value<std::string>(&p.i.include_msrs),
108✔
1362
                                "Import the specified measurement types. arg is a non-delimited string of measurement types (eg \"GXY\").")
1363
                        (EXCLUDE_MSRS, boost::program_options::value<std::string>(&p.i.exclude_msrs),
108✔
1364
                                "Exclude the specified measurement types. arg is a non-delimited string of measurement typs (eg \"IJK\").")
1365
                        (STATION_RENAMING_FILE, boost::program_options::value<std::string>(&p.i.stn_renamingfile),
108✔
1366
                                "Station renaming file")
1367
                        (STATION_DISCONTINUITY_FILE, boost::program_options::value<std::string>(&p.i.stn_discontinuityfile),
108✔
1368
                                "Station discontinuity file.  Applies discontinuity dates to station names in station and measurement files.")
1369
                        (TEST_NEARBY_STNS,
108✔
1370
                                "Search for nearby stations.")
1371
                        (TEST_NEARBY_STN_DIST, boost::program_options::value<double>(&p.i.search_stn_radius),
108✔
1372
                                (std::string("Specify the radius of the circle within which to search for nearby stations.  Default is ")+
324✔
1373
                                StringFromT(STN_SEARCH_RADIUS)+std::string("m")).c_str())
540✔
1374
                        (TEST_SIMILAR_GNSS_MSRS,
108✔
1375
                                "Search and provide warnings for GNSS baselines (G) and baseline clusters (X) which appear to have been derived from the same source data.")
1376
                        (TEST_SIMILAR_MSRS,
108✔
1377
                                "Search and provide warnings for similar measurements.")
1378
                        (IGNORE_INSUFFICIENT_MSRS,
108✔
1379
                                "Ignore measurements which do not sufficiently constrain a station in two dimensions.")
1380
                        (IGNORE_SIMILAR_MSRS,
108✔
1381
                                "Ignore similar measurements.")
1382
                        (REMOVE_IGNORED_MSRS,
108✔
1383
                                "Remove ignored measurements.")
1384
                        (FLAG_UNUSED_STNS,
108✔
1385
                                "Mark unused stations in binary file.  Stations marked will be excluded from any further processing.")
1386
                        (TEST_INTEGRITY,
108✔
1387
                                "Test the integrity of the association lists and binary files.")
1388
                        ;
1389

1390
                gnss_scaling_options.add_options()
108✔
1391
                        (VSCALE, boost::program_options::value<double>(&p.i.vscale),
108✔
1392
                                (std::string("Global variance (v) matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
324✔
1393
                                StringFromT(p.i.vscale)+std::string(".")).c_str())
540✔
1394
                        (PSCALE, boost::program_options::value<double>(&p.i.pscale),
108✔
1395
                                (std::string("Latitude (p=phi) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
324✔
1396
                                StringFromT(p.i.pscale)+std::string(".")).c_str())
540✔
1397
                        (LSCALE, boost::program_options::value<double>(&p.i.lscale),
108✔
1398
                                (std::string("Longitude (l=lambda) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
324✔
1399
                                StringFromT(p.i.lscale)+std::string(".")).c_str())
540✔
1400
                        (HSCALE, boost::program_options::value<double>(&p.i.hscale),
108✔
1401
                                (std::string("Height (h) variance matrix scalar for all GNSS measurements.  Replaces existing scalar.  Default is ")+
324✔
1402
                                StringFromT(p.i.hscale)+std::string(".")).c_str())
540✔
1403
                        (SCALAR_FILE, boost::program_options::value<std::string>(&p.i.scalar_file),
108✔
1404
                                "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.")
1405
                        ;
1406

1407
                output_options.add_options()
108✔
1408
                        (OUTPUT_MSR_TO_STN,
108✔
1409
                                "Output summary of measurements connected to each station.")
1410
                        (OUTPUT_MSR_TO_STN_SORTBY, boost::program_options::value<UINT16>(&p.o._sort_msr_to_stn),
108✔
1411
                                std::string("Sort order for measurement to stations summary.\n  " +
432✔
1412
                                        StringFromT(orig_stn_sort_ui) + ": Original station order (default)\n  " +
540✔
1413
                                        StringFromT(meas_stn_sort_ui) + ": Measurement count").c_str())
108✔
1414
                        ;
1415

1416
                export_options.add_options()
108✔
1417
                        (EXPORT_XML_FILES,
108✔
1418
                                "Export stations and measurements to DynaML (DynAdjust XML) format.")
1419
                        (EXPORT_SINGLE_XML_FILE,
108✔
1420
                                "Create a single DynaML file for stations and measurements.")
1421
                        // Nice, but somewhat redundant functionality that offers no
1422
                        // benefit to the user
1423
                        //(EXPORT_FROM_BINARY,
1424
                        //        "Create DynaML output file using binary files. Default option uses internal memory.")
1425
                        (EXPORT_DNA_FILES,
108✔
1426
                                "Export stations and measurements to DNA STN and MSR format.")
1427
                        (EXPORT_ASL_FILE,
108✔
1428
                                "Export the ASL file as raw text.")
1429
                        (EXPORT_AML_FILE,
108✔
1430
                                "Export the AML file as raw text.")
1431
                        (EXPORT_MAP_FILE,
108✔
1432
                                "Export the MAP file as raw text.")
1433
                        (EXPORT_DISCONT_FILE,
108✔
1434
                                "Export discontinuity information as raw text.")
1435
                        ;
1436

1437
                simulation_options.add_options()
108✔
1438
                        (SIMULATE_MSR_FILE,
108✔
1439
                                "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.")
1440
                        ;
1441

1442
                generic_options.add_options()
108✔
1443
                        (VERBOSE, boost::program_options::value<UINT16>(&p.g.verbose),
108✔
1444
                                std::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())
216✔
1445
                        (QUIET,
108✔
1446
                                std::string("Suppresses all explanation of what ").append(__BINARY_NAME__).append(" is doing unless an error occurs.").c_str())
216✔
1447
                        (VERSION_V, "Display the current program version.")
108✔
1448
                        (HELP_H, "Show this help message.")
108✔
1449
                        (HELP_MODULE_H, boost::program_options::value<std::string>(),
108✔
1450
                                "Provide help for a specific help category.")
1451
                        ;
1452

1453
                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);
108✔
1454

1455
                // add "positional options" to handle command line tokens which have no option name
1456
                positional_options.add(IMPORT_FILE, -1);
108✔
1457
                
1458
                boost::program_options::command_line_parser parser(argc, argv);
108✔
1459
                store(parser.options(allowable_options).positional(positional_options).run(), vm);
108✔
1460
                notify(vm);
107✔
1461
        }
1✔
1462
        catch(const std::exception& e) 
1✔
1463
        {
1464
                std::cout << "- Error: " << e.what() << std::endl;
1✔
1465
                std::cout << cmd_line_banner << allowable_options << std::endl;
1✔
1466
                return EXIT_FAILURE;
1✔
1467
        }
1✔
1468
        catch (...) 
×
1469
        {
NEW
1470
                std::cout << "+ Exception of unknown type!\n";
×
1471
                return EXIT_FAILURE;
×
1472
        }
×
1473

1474
        if (argc < 2)
107✔
1475
        {
1476
                std::cout << std::endl << "- Nothing to do - no options provided. " << std::endl << std::endl;  
1✔
1477
                std::cout << cmd_line_banner << allowable_options << std::endl;
1✔
1478
                return EXIT_FAILURE;
1479
        }
1480

1481
        if (vm.count(VERSION))
212✔
1482
        {
1483
                std::cout << cmd_line_banner << std::endl;
1✔
1484
                return EXIT_SUCCESS;
1485
        }
1486

1487
        if (vm.count(HELP))
210✔
1488
        {
1489
                std::cout << cmd_line_banner << allowable_options << std::endl;
1✔
1490
                return EXIT_SUCCESS;
1491
        }
1492

1493
        if (vm.count(HELP_MODULE)) 
208✔
1494
        {
1495
                std::cout << cmd_line_banner;
9✔
1496
                std::string original_text = vm[HELP_MODULE].as<std::string>();
27✔
1497
                std::string help_text = str_upper<std::string>(original_text);
9✔
1498
                
1499
                if (str_upper<std::string, char>(ALL_MODULE_STDOPT).find(help_text) != std::string::npos) {
27✔
1500
                        std::cout << standard_options << std::endl;
1✔
1501
                }
1502
                else if (str_upper<std::string, char>(IMPORT_MODULE_FRAME).find(help_text) != std::string::npos) {
24✔
1503
                        std::cout << ref_frame_options << std::endl;
1✔
1504
                } 
1505
                else if (str_upper<std::string, char>(IMPORT_MODULE_SCREEN).find(help_text) != std::string::npos) {
21✔
1506
                        std::cout << data_screening_options << std::endl;
1✔
1507
                } 
1508
                else if (str_upper<std::string, char>(IMPORT_MODULE_GNSS_VAR).find(help_text) != std::string::npos) {
18✔
1509
                        std::cout << gnss_scaling_options << std::endl;
1✔
1510
                } 
1511
                else if (str_upper<std::string, char>(IMPORT_MODULE_SIMULATE).find(help_text) != std::string::npos) {
15✔
1512
                        std::cout << simulation_options << std::endl;
1✔
1513
                } 
1514
                else if (str_upper<std::string, char>(ALL_MODULE_OUTPUT).find(help_text) != std::string::npos) {
12✔
1515
                        std::cout << output_options << std::endl;
1✔
1516
                } 
1517
                else if (str_upper<std::string, char>(ALL_MODULE_EXPORT).find(help_text) != std::string::npos) {
9✔
1518
                        std::cout << export_options << std::endl;
1✔
1519
                } 
1520
                else if (str_upper<std::string, char>(ALL_MODULE_GENERIC).find(help_text) != std::string::npos) {
6✔
1521
                        std::cout << generic_options << std::endl;
1✔
1522
                } 
1523
                else {
1524
                        std::cout << std::endl << "- Error: Help module '" <<
1✔
1525
                                original_text << "' is not in the list of options." << std::endl;
9✔
1526
                        return EXIT_FAILURE;
1527
                }
1528

1529
                return EXIT_SUCCESS;
8✔
1530
        }
18✔
1531

1532
        bool userSuppliedSegFile(false);
95✔
1533
        if (!p.i.seg_file.empty())
95✔
1534
                userSuppliedSegFile = true;
1✔
1535
        bool userSuppliedBstFile(false);
95✔
1536
        if (!p.i.bst_file.empty())
95✔
1537
                userSuppliedBstFile = true;
×
1538
        bool userSuppliedBmsFile(false);
95✔
1539
        if (!p.i.bms_file.empty())
95✔
1540
                userSuppliedBmsFile = true;
×
1541

1542
        if (ParseCommandLineOptions(argc, argv, vm, p) != EXIT_SUCCESS)
95✔
1543
                return EXIT_FAILURE;
1544

1545
        UINT32 errorCount(0);
92✔
1546
        bool stn_map_created = false, measurements_mapped = false;
92✔
1547

1548
        std::string input_file;
92✔
1549
        vstring input_files;
92✔
1550
        std::string status_msg;
92✔
1551

1552
        std::ofstream imp_file;
92✔
1553
        try {
92✔
1554
                // Create import log file.  Throws runtime_error on failure.
1555
                file_opener(imp_file, p.i.imp_file);
92✔
1556
        }
NEW
1557
        catch (const std::runtime_error& e) {
×
NEW
1558
                std::stringstream ss;
×
NEW
1559
                ss << "- Error: Could not open " << p.i.imp_file << ". \n  Check that the file exists and that the file is not already opened." << std::endl;
×
NEW
1560
                std::cout << ss.str() << e.what() << std::endl;
×
1561
                return EXIT_FAILURE;
×
1562
        }
×
1563

1564
        vdnaStnPtr vStations, vstationsTotal;
92✔
1565
        vdnaMsrPtr vMeasurements, vmeasurementsTotal;
92✔
1566
        vdnaMsrPtr::iterator _itm;
92✔
1567
        vASLPtr associatedSL;
92✔
1568
        vUINT32 associatedML;
92✔
1569
        v_string_uint32_pair vStnsMap_sortName;        // Station Name Map sorted on name (string)
92✔
1570
        
1571
        vstationsTotal.clear();
92✔
1572
        vmeasurementsTotal.clear();
92✔
1573

1574
        dna_import parserDynaML;
92✔
1575

1576
        ////////////////////////////////////////////////////////////////////////////////////
1577
        // First things first!
1578
        // Set the 'default' reference frame for the binary station and measurement files
1579
        // At this point, the frame may be the hard-coded default, or a user-specified 
1580
        // frame via:   -r [--reference-frame] arg
1581
        // See comments in InitialiseDatum()
1582
        try {
92✔
1583
                // Initialise the 'default' datum for the project.
1584
                parserDynaML.InitialiseDatum(p.i.reference_frame, p.i.epoch);
93✔
1585
        }
1586
        catch (const XMLInteropException& e) {
1✔
1587

1588
                std::cout << std::endl << cmd_line_banner;
1✔
1589
                imp_file << std::endl << cmd_line_banner;
1✔
1590
                
1591
                std::stringstream ss;
1✔
1592
                ss << "- Error: ";
1✔
1593
                std::cout << ss.str() << e.what() << std::endl;
1✔
1594
                imp_file << ss.str() << e.what() << std::endl;
1✔
1595
                return EXIT_FAILURE;
1✔
1596
        }
1✔
1597

1598
        // obtain the project reference frame
1599
        UINT32 epsgCode(epsgCodeFromName<UINT32>(p.i.reference_frame));
91✔
1600

1601
        // set the default output reference frame and epoch, so that
1602
        // if adjust is called without reftran, it reflects the datum 
1603
        // supplied on import
1604
        p.r.reference_frame = p.i.reference_frame;
91✔
1605

1606
        // if the reference frame supplied is static, then force the epoch
1607
        // to be the reference epoch
1608
        if (isEpsgDatumStatic(epsgCode))
91✔
1609
        {
1610
                p.i.epoch = referenceepochFromEpsgCode<UINT32>(epsgCode);
58✔
1611
                p.r.epoch = p.i.epoch;
58✔
1612
        }
1613
        else
1614
        {
1615
                // Dynamic reference frame.  For this code to be reached, which
1616
                // is prior to the input files been parsed, the user must have
1617
                // supplied a dynamic reference frame on the command line.
1618
                // 
1619
                // Has the user not supplied an epoch?
1620
                if (!p.i.user_supplied_epoch)
33✔
1621
                        // No, so set the "default" epoch for the project to be the
1622
                        // reference epoch of the supplied dynamic reference frame
1623
                        p.i.epoch = referenceepochFromEpsgCode<UINT32>(epsgCode);
36✔
1624
                
1625
                // Set the project epoch for reftran also
1626
                p.r.epoch = p.i.epoch;
33✔
1627
        }
1628

1629
        ////////////////////////////////////////////////////////////////////////////////////
1630

1631
        if (vm.count(QUIET))
182✔
1632
                p.g.quiet = 1;
1✔
1633

1634
        if (!p.g.quiet)
91✔
1635
        {
1636
                std::cout << std::endl << cmd_line_banner;
90✔
1637

1638
                std::cout << "+ Options:" << std::endl; 
90✔
1639
                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Network name: " <<  p.g.network_name << std::endl;
90✔
1640
                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Input folder: " << p.g.input_folder << std::endl;
90✔
1641
                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Output folder: " << p.g.output_folder << std::endl;
90✔
1642
                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Associated station file: " << p.i.asl_file << std::endl;
90✔
1643
                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Associated measurement file: " << p.i.aml_file << std::endl;
90✔
1644
                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Binary station output file: " << p.i.bst_file << std::endl;
90✔
1645
                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Binary measurement output file: " << p.i.bms_file << std::endl;
90✔
1646
                
1647
                // If a reference frame and epoch have been supplied, report them.
1648
                // If not, the assumption is, the project frame and epoch will be adopted from the first file and
1649
                // in this case, it will be reported later
1650
                if (p.i.user_supplied_frame)
90✔
1651
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Project reference frame:" << p.i.reference_frame << " (user supplied)" << std::endl;
41✔
1652
                else
1653
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Project reference frame:" << "To be adopted from the first input file" << std::endl;
49✔
1654
                
1655
                if (p.i.override_input_rfame)
90✔
1656
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Override input file ref frame:" << yesno_string(p.i.override_input_rfame) << std::endl;
12✔
1657

1658
                if (isEpsgDatumStatic(epsgCode) && p.i.user_supplied_frame)
90✔
1659
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Project epoch:" << p.i.epoch << " (adopted reference epoch of " << p.i.reference_frame << ")" << std::endl;
9✔
1660
                else
1661
                {
1662
                        if (p.i.user_supplied_epoch)
81✔
1663
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Project epoch:" << p.i.epoch << " (user supplied)" << std::endl;
15✔
1664
                        else
1665
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Project epoch:" << "To be adopted from the first input file" << std::endl;
66✔
1666
                }
1667

1668
                if (p.i.export_dynaml)
90✔
1669
                {
1670
                        if (p.i.export_single_xml_file)
10✔
1671
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  DynaML output file: " << p.i.xml_outfile << std::endl;
2✔
1672
                        else
1673
                        {
1674
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  DynaML station file: " << p.i.xml_stnfile << std::endl;
8✔
1675
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  DynaML measurement file: " << p.i.xml_msrfile << std::endl;
8✔
1676
                        }                                
1677
                }
1678
                if (p.i.export_dna_files)
90✔
1679
                {
1680
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  DNA station file: " << p.i.dna_stnfile << std::endl;
12✔
1681
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  DNA measurement file: " << p.i.dna_msrfile << std::endl;
12✔
1682
                }
1683

1684
                if (p.i.simulate_measurements)
90✔
1685
                {
1686
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  DNA simulated msr file: " << p.i.simulate_msrfile << std::endl;
1✔
1687
                }
1688
                
1689
                if (!p.i.bounding_box.empty())
90✔
1690
                {
1691
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Bounding box: " << p.i.bounding_box << std::endl;
1✔
1692
                        if (p.i.split_clusters)
1✔
1693
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Split GNSS clusters: " << (p.i.split_clusters ? "Yes" : "No") << std::endl;
1✔
1694
                }
1695
                else
1696
                {
1697
                        if (!p.i.stn_associated_msr_include.empty())
89✔
1698
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Stations to include: " << p.i.stn_associated_msr_include << std::endl;
5✔
1699
                        if (!p.i.stn_associated_msr_exclude.empty())
89✔
1700
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Stations to exclude: " << p.i.stn_associated_msr_exclude << std::endl;
1✔
1701
                        
1702
                        if (p.i.split_clusters)
89✔
1703
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Split GNSS clusters: " << (p.i.split_clusters ? "Yes" : "No") << std::endl;
4✔
1704
                }
1705
                
1706
                if (p.i.import_block)
90✔
1707
                {
1708
                        if (!p.i.seg_file.empty())
5✔
1709
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Segmentation file: " << p.i.seg_file << std::endl;
1✔
1710
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Import stns & msrs from block: " << p.i.import_block_number << std::endl;
5✔
1711
                }
1712
                else if (p.i.import_network)
85✔
1713
                {
1714
                        if (!p.i.seg_file.empty())
2✔
NEW
1715
                                std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Segmentation file: " << p.i.seg_file << std::endl;
×
1716
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  Import stns & msrs from network: " << p.i.import_network_number << std::endl;
2✔
1717
                }
1718

1719
                if (!p.i.scalar_file.empty())
90✔
1720
                        std::cout << std::setw(PRINT_VAR_PAD) << std::left << "  GNSS baseline scalar file: " << p.i.scalar_file << std::endl;
1✔
1721
                
1722
                std::cout << std::endl;
90✔
1723
        }
1724

1725
        PrintOutputFileHeaderInfo(&imp_file, p.i.imp_file, &p, "DYNADJUST IMPORT LOG FILE");
182✔
1726

1727
        MsrTally parsemsrTally;
91✔
1728
        StnTally parsestnTally;
91✔
1729

1730
        CDnaProjection projection(UTM);
91✔
1731

1732
        vifm_t vinput_file_meta;
91✔
1733

1734
        ///////////////////////////////////////////////////////////////////////////////////////////////////////////
1735
        // start "total" time
1736
        boost::timer::cpu_timer time;
91✔
1737
        
1738
        
1739
        // Import discontinuity file and apply discontinuities
1740
        // Due to the structure and format of SINEX files, it is essential that
1741
        // discontinuities be parsed prior to reading any SINEX files.
1742
        if (vm.count(STATION_DISCONTINUITY_FILE))
182✔
1743
        {
1744
                p.i.apply_discontinuities = true;
4✔
1745
                
1746
                // Does it exist?
1747
                if (!boost::filesystem::exists(p.i.stn_discontinuityfile))
8✔
1748
                {
NEW
1749
                        boost::filesystem::path discontPath(p.i.stn_discontinuityfile);
×
NEW
1750
                        std::stringstream ss;
×
NEW
1751
                        ss << "- Warning: The station discontinuity file " << discontPath.filename().string() << " does not exist... ignoring discontinuity input." << std::endl;
×
NEW
1752
                        imp_file << std::endl << ss.str();
×
UNCOV
1753
                }
×
1754
                else
1755
                {
1756
                        if (!p.g.quiet)
4✔
1757
                        {
1758
                                std::cout << "+ Importing station discontinuities from " << p.i.stn_discontinuityfile << "... ";
4✔
1759
                                std::cout.flush();
4✔
1760
                        }
1761
                        imp_file << "+ Importing station discontinuities from " << p.i.stn_discontinuityfile << "... ";
4✔
1762

1763
                        parserDynaML.ParseDiscontinuities(p.i.stn_discontinuityfile);
4✔
1764

1765
                        if (!p.g.quiet)
4✔
1766
                                std::cout << "Done." << std::endl;
4✔
1767
                        imp_file << "Done." << std::endl;
4✔
1768
                }
1769

1770
                if (p.i.export_discont_file)
4✔
1771
                {
1772
                        if (!p.g.quiet)
1✔
1773
                        {
1774
                                std::cout << "+ Exporting discontinuity information to text file... ";
1✔
1775
                                std::cout.flush();
1✔
1776
                        }
1777
                        imp_file << "+ Exporting discontinuity information to text file... ";
1✔
1778
                        parserDynaML.SerialiseDiscontTextFile(p.i.stn_discontinuityfile);
1✔
1779
                        if (!p.g.quiet)
1✔
1780
                        {
1781
                                std::cout << "Done." << std::endl;
1✔
1782
                                std::cout.flush();
1✔
1783
                        }
1784
                        imp_file << "Done." << std::endl;
1✔
1785
                }
1786
        }
1787

1788
        // Now, set the 'default' epoch in the binary station and measurement files
1789
        std::string default_datum = p.i.reference_frame;
91✔
1790
        
1791
        // Import network information based on a segmentation block?
1792
        if (p.i.import_block)
91✔
1793
        {
1794
                imp_file << "+ Extracting stations and measurements from segmented block " << 
5✔
1795
                        p.i.import_block_number << "... ";
5✔
1796
                
1797
                if (ImportSegmentedBlock(parserDynaML, &vstationsTotal, &vmeasurementsTotal, 
5✔
1798
                        &parsestnTally, &parsemsrTally, p) != EXIT_SUCCESS)
1799
                        return EXIT_FAILURE;
1800

1801
                imp_file << "Done." << std::endl;
4✔
1802
        }
1803
        // Import network information based on a contiguous network?
1804
        else if (p.i.import_network)
86✔
1805
        {
1806
                imp_file << "+ Extracting stations and measurements from contiguous network " <<
2✔
1807
                        p.i.import_network_number << "... ";
2✔
1808
                
1809
                if (ImportContiguousNetwork(parserDynaML, &vstationsTotal, &vmeasurementsTotal,
2✔
1810
                        &parsestnTally, &parsemsrTally, p) != EXIT_SUCCESS)
1811
                        return EXIT_FAILURE;
1812

1813
                imp_file << "Done." << std::endl;
1✔
1814
        }
1815
        // Import data as normal
1816
        else
1817
        {
1818
                // Import all data as-is.
1819
                // All filtering is performed later below
1820
                if (ImportDataFiles(parserDynaML, &vStations, &vMeasurements, &vstationsTotal, &vmeasurementsTotal,
84✔
1821
                        &imp_file, &vinput_file_meta, &parsestnTally, &parsemsrTally, errorCount, p) != EXIT_SUCCESS)
1822
                        return EXIT_FAILURE;
1823
        }
1824

1825
        epsgCode = epsgCodeFromName<UINT32>(p.i.reference_frame);
85✔
1826

1827
        if (!p.g.quiet)
85✔
1828
                std::cout << std::endl;
84✔
1829
        imp_file << std::endl;
85✔
1830

1831
        vstring vPoorlyConstrainedStns;
85✔
1832

1833
        // Ignore measurements that do not sufficiently (in themselves) allow for a station to be estimated
1834
        if (p.i.ignore_insufficient_msrs == 1)
85✔
1835
        {
1836
                size_t msrCount = vmeasurementsTotal.size();
×
1837
                if (!p.g.quiet)
×
1838
                {
NEW
1839
                        std::cout << "+ Identifying stations with insufficient measurements";
×
NEW
1840
                        std::cout.flush();
×
1841
                }
1842
                imp_file << "+ Identifying stations with insufficient measurements...";
×
1843
                parserDynaML.IgnoreInsufficientMeasurements(&vstationsTotal, &vmeasurementsTotal, &vPoorlyConstrainedStns);
×
1844
                if (!p.g.quiet)
×
1845
                {
NEW
1846
                        std::cout << " Done. " << std::endl;
×
1847
                        if (msrCount > vmeasurementsTotal.size())
×
NEW
1848
                                std::cout << "+ Removed " << (msrCount - vmeasurementsTotal.size()) << " measurements which alone do not sufficiently allow for" << std::endl <<
×
NEW
1849
                                        "  the estimation of 2D coordinates." << std::endl;
×
1850

1851
                }
NEW
1852
                imp_file << " Done. " << std::endl;
×
1853
                if (msrCount > vmeasurementsTotal.size())
×
NEW
1854
                        imp_file << "+ Removed " << (msrCount - vmeasurementsTotal.size()) << " measurements which alone do not sufficiently allow for" << std::endl <<
×
NEW
1855
                                "  the estimation of 2D coordinates." << std::endl;
×
1856

1857
                if (!vPoorlyConstrainedStns.empty())
×
1858
                {
1859
                        if (vPoorlyConstrainedStns.size() == 1)
×
1860
                        {
1861
                                if (p.g.verbose > 2)
×
1862
                                {
1863
                                        if (!p.g.quiet)
×
NEW
1864
                                                std::cout << "- Warning: station " << vPoorlyConstrainedStns.at(0) << " is not associated with sufficient measurements." << std::endl;
×
NEW
1865
                                        imp_file << "- Warning: station " << vPoorlyConstrainedStns.at(0) << " is not associated with sufficient measurements." << std::endl;
×
1866
                                }
1867
                                else
1868
                                {
1869
                                        if (!p.g.quiet)
×
NEW
1870
                                                std::cout << "- Warning: 1 station is not associated with sufficient measurements." << std::endl;
×
NEW
1871
                                        imp_file << "- Warning: 1 station is not associated with sufficient measurements." << std::endl;
×
1872
                                }
1873
                        }
1874
                        else
1875
                        {
1876
                                if (p.g.verbose > 2)
×
1877
                                {
1878
                                        if (!p.g.quiet)
×
NEW
1879
                                                std::cout << "- Warning: The following " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << std::endl;
×
NEW
1880
                                        imp_file << "- Warning: The following " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << std::endl;
×
1881
                                        _it_vstr poorly;
×
1882
                                        for (poorly = vPoorlyConstrainedStns.begin(); poorly != vPoorlyConstrainedStns.end(); poorly++)
×
1883
                                        {
1884
                                                if (!p.g.quiet)
×
NEW
1885
                                                        outputObject(std::string("  - " + *poorly + "\n"), std::cout);
×
NEW
1886
                                                outputObject(std::string("  - " + *poorly + "\n"), imp_file);
×
1887
                                        }
1888
                                }
1889
                                else
1890
                                {
1891
                                        if (!p.g.quiet)
×
NEW
1892
                                                std::cout << "- Warning: " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << std::endl;
×
NEW
1893
                                        imp_file << "- Warning: " << vPoorlyConstrainedStns.size() << " stations are not associated with sufficient measurements." << std::endl;
×
1894
                                }
1895
                        }
1896
                }
1897
        }
1898

1899
        // Remove ignored measurements (if supplied)
1900
        if (p.i.remove_ignored_msr)
85✔
1901
        {
1902
                if (!p.g.quiet)
1✔
1903
                {
1904
                        std::cout << "+ Removing ignored measurements... ";
1✔
1905
                        std::cout.flush();
1✔
1906
                }
1907
                imp_file << "+ Removing ignored measurements... ";
1✔
1908
                parserDynaML.RemoveIgnoredMeasurements(&vmeasurementsTotal, &parsemsrTally);
1✔
1909
                if (!p.g.quiet)
1✔
1910
                        std::cout << "Done. " << std::endl;
1✔
1911
                imp_file << "Done. " << std::endl;
1✔
1912
        }
1913

1914
        // Strip all measurements except required measurements (if supplied)
1915
        if (!p.i.include_msrs.empty())
85✔
1916
        {
1917
                if (!p.g.quiet)
2✔
1918
                {
1919
                        std::cout << "+ Stripping all measurements except types " << p.i.include_msrs << "... ";
2✔
1920
                        std::cout.flush();
2✔
1921
                }
1922
                imp_file << "+ Stripping all measurements except types " << p.i.include_msrs << "... ";
2✔
1923
                parserDynaML.IncludeMeasurementTypes(p.i.include_msrs, &vmeasurementsTotal, &parsemsrTally);
2✔
1924
                if (!p.g.quiet)
2✔
1925
                        std::cout << "Done. " << std::endl;
2✔
1926
                imp_file << "Done. " << std::endl;
2✔
1927
        }
1928
        
1929
        // Strip all unwanted measurements (if supplied)
1930
        if (!p.i.exclude_msrs.empty())
85✔
1931
        {
1932
                if (!p.g.quiet)
2✔
1933
                {
1934
                        std::cout << "+ Stripping measurement types " << p.i.exclude_msrs << "... ";
2✔
1935
                        std::cout.flush();
2✔
1936
                }
1937
                imp_file << "+ Stripping measurement types " << p.i.exclude_msrs << "... ";
2✔
1938
                parserDynaML.ExcludeMeasurementTypes(p.i.exclude_msrs, &vmeasurementsTotal, &parsemsrTally);
2✔
1939
                if (!p.g.quiet)
2✔
1940
                        std::cout << "Done. " << std::endl;
2✔
1941
                imp_file << "Done. " << std::endl;
2✔
1942
        }
1943

1944
        // Reduce stations.
1945
        // But, only reduce stations if not importing for a segmentation block or network
1946
        // The reason stations are not reduced if IMPORT_SEG_BLOCK or IMPORT_CONTIG_NET has been set is
1947
        // because stations in the binary file will have already been reduced
1948
        // on last import!
1949
        if (p.i.import_block == 0 && p.i.import_network == 0 && vstationsTotal.size())
85✔
1950
        {
1951
                // reduce stations (e.g. convert from UTM to LLH)
1952
                try {
80✔
1953
                        if (!p.g.quiet)
80✔
1954
                        {
1955
                                std::cout << "+ Reducing stations... ";
79✔
1956
                                std::cout.flush();
79✔
1957
                        }
1958
                        imp_file << "+ Reducing stations... ";
80✔
1959
                        parserDynaML.ReduceStations(&vstationsTotal, projection);
80✔
1960
                        if (!p.g.quiet)
80✔
1961
                                std::cout << "Done." << std::endl;
79✔
1962
                        imp_file << "Done." << std::endl;
80✔
1963
                } 
1964
                catch (const XMLInteropException& e) {
×
NEW
1965
                        std::cout << std::endl << "- Error: " << e.what() << std::endl;
×
NEW
1966
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
1967
                        imp_file.close();
×
1968
                        return EXIT_FAILURE;
×
1969
                }
×
1970
        }
1971
        
1972
        /////////////////////////////////////////////////////////////////////////
1973
        // Add discontinuity sites to vStations
1974
        //
1975
        // WARNING: If discontinuity sites are present in the renaming file, and
1976
        // the renaming file changes the name from the four-character id in the 
1977
        // discontinuity file to another name, this function call will not work
1978
        // properly. Hence, sites in the discontinuity file must be consistently
1979
        // named in the station and measurement files and not renamed to another
1980
        // name.
1981
        if (p.i.apply_discontinuities && !vstationsTotal.empty())
85✔
1982
                parserDynaML.AddDiscontinuityStations(&vstationsTotal);
4✔
1983

1984
        UINT32 stn;
85✔
1985

1986
        // Extract user-defined stations and all connected measurements
1987
        if (vstationsTotal.size() &&        // cannot be empty
85✔
1988
                (!p.i.stn_associated_msr_include.empty() || !p.i.stn_associated_msr_exclude.empty()))
85✔
1989
        {
1990
                vstring vUnusedStns;
6✔
1991
                bool splitXmsrs(false), splitYmsrs(false);
6✔
1992

1993
                try {
6✔
1994
                        if (!p.g.quiet)
6✔
1995
                        {
1996
                                std::cout << "+ Extracting stations and associated measurements... ";
6✔
1997
                                std::cout.flush();
6✔
1998
                        }
1999
                        imp_file << "+ Extracting stations and associated measurements... ";
6✔
2000

2001
                        // this method reforms asl and aml
2002
                        parserDynaML.ExtractStnsAndAssociatedMsrs(p.i.stn_associated_msr_include, p.i.stn_associated_msr_exclude, &vstationsTotal, &vmeasurementsTotal, 
6✔
2003
                                &parsestnTally, &parsemsrTally, &vUnusedStns, p, splitXmsrs, splitYmsrs);
2004
                } 
2005
                catch (const XMLInteropException& e) {
×
NEW
2006
                        std::cout << "- Error: " << e.what() << std::endl;
×
NEW
2007
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2008
                        imp_file.close();
×
2009
                        return EXIT_FAILURE;
×
2010
                }
×
2011

2012
                if (!p.g.quiet)
6✔
2013
                        std::cout << "Done. " << std::endl;
6✔
2014
                imp_file << "Done." << std::endl;
6✔
2015

2016
                //msrCount = vmeasurementsTotal.size();
2017
        }        
6✔
2018

2019
        // Now strip all stations outside the bounding box (if supplied)
2020
        if (vstationsTotal.size() &&        // cannot be empty
85✔
2021
                !p.i.bounding_box.empty())
84✔
2022
        {
2023
                vstring vUnusedStns;
1✔
2024
                bool splitXmsrs(false), splitYmsrs(false);
1✔
2025

2026
                try {
1✔
2027
                        if (!p.g.quiet)
1✔
2028
                        {
2029
                                std::cout << "+ Stripping stations and measurements outside the bounding box... ";
1✔
2030
                                std::cout.flush();
1✔
2031
                        }
2032
                        imp_file << "+ Stripping stations and measurements outside the bounding box... ";
1✔
2033
                        parserDynaML.ExcludeAllOutsideBoundingBox(&vstationsTotal, &vmeasurementsTotal, 
1✔
2034
                                &parsestnTally, &parsemsrTally, &vUnusedStns, p, splitXmsrs, splitYmsrs);
2035
                } 
2036
                catch (const XMLInteropException& e) {
×
NEW
2037
                        std::cout << "- Error: " << e.what() << std::endl;
×
NEW
2038
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2039
                        imp_file.close();
×
2040
                        return EXIT_FAILURE;
×
2041
                }
×
2042

2043
                if (!p.g.quiet)
1✔
2044
                        std::cout << "Done. " << std::endl;
1✔
2045
                imp_file << "Done." << std::endl;
1✔
2046

2047
                if (!vUnusedStns.empty())
1✔
2048
                {
2049
                        std::ostringstream ss_msg;
1✔
2050
                        ss_msg << "  - " << vstationsTotal.size() << (vstationsTotal.size() == 1 ? " station is" : " stations are") << 
1✔
2051
                                " within the bounding box." << std::endl;
2✔
2052
                        imp_file << ss_msg.str();
1✔
2053
                        if (!p.g.quiet)
1✔
2054
                                std::cout << ss_msg.str();
2✔
2055
                        ss_msg.str("");
3✔
2056
                        ss_msg << "  - ";
1✔
2057
                        if (vUnusedStns.size() > 1)
1✔
2058
                        {
2059
                                ss_msg << vUnusedStns.size() << " stations were";
1✔
2060
                        }
2061
                        else
2062
                                ss_msg << "Station " << vUnusedStns.at(0) << " was";
×
2063

2064
                        ss_msg << " found outside the bounding box and " << (vUnusedStns.size() > 1 ? "have been" : "has been") << std::endl <<
1✔
2065
                                "    removed together with the corresponding measurements." << std::endl;
1✔
2066
                        if (p.i.split_clusters && (splitXmsrs || splitYmsrs))
1✔
2067
                        {
2068
                                ss_msg << "  - Note: GPS ";
1✔
2069
                                if (splitXmsrs && splitYmsrs)
1✔
2070
                                        ss_msg << "point and baseline";
×
2071
                                else if (splitXmsrs)
1✔
2072
                                        ss_msg << "baseline";
×
2073
                                else //if (splitYmsrs)
2074
                                        ss_msg << "point";
1✔
2075
                                ss_msg << " cluster measurements straddling the limits of" << std::endl << 
1✔
2076
                                "    the bounding box have been split." << std::endl;
1✔
2077
                        }
2078
                        imp_file << ss_msg.str() << "  - Excluded stations:" << std::endl;
1✔
2079
                        if (!p.g.quiet)
1✔
2080
                                std::cout << ss_msg.str() << std::endl;
2✔
2081
                        
2082
                        for (stn=0; stn<vUnusedStns.size(); ++stn)
13✔
2083
                                imp_file << "     " << vUnusedStns.at(stn) << std::endl;
12✔
2084
                        imp_file << std::endl;
1✔
2085
                }
1✔
2086
                else
2087
                {
NEW
2088
                        imp_file << "  - No stations were found outside the bounding box." << std::endl;
×
2089
                        if (!p.g.quiet)
×
NEW
2090
                                std::cout << "  - No stations were found outside the bounding box." << std::endl;
×
2091
                }
2092
        }
1✔
2093

2094
        UINT32 msrRead(parsemsrTally.TotalCount());
85✔
2095
        UINT32 stnCount(static_cast<UINT32>(vstationsTotal.size()));
85✔
2096
        UINT32 msrCount(static_cast<UINT32>(vmeasurementsTotal.size()));
85✔
2097

2098
        if (!p.g.quiet)
85✔
2099
                std::cout << std::endl;
84✔
2100
        imp_file << std::endl;
85✔
2101

2102
        ///////////////////////////////////////////////////////////////////////
2103
        // Ok, now that unwanted stations and measurements have been stripped,
2104
        // provide station and measurement Summary
2105
        //
2106
        if ((stnCount + msrCount) > 0)
85✔
2107
        {
2108
                if (p.i.import_block || p.i.import_network)
84✔
2109
                {
2110
                        if (!p.g.quiet)
5✔
2111
                                std::cout << "+ Binary file ";
5✔
2112
                        imp_file << "+ Binary file ";
5✔
2113
                }
2114
                else
2115
                {
2116
                        if (!p.g.quiet)
79✔
2117
                                std::cout << "+ File ";
78✔
2118
                        imp_file << "+ File ";
79✔
2119
                }
2120
                
2121
                if (!p.g.quiet)
84✔
2122
                        std::cout << "parsing summary:" << std::endl << std::endl;
83✔
2123
                imp_file << "parsing summary:" << std::endl << std::endl;
84✔
2124
        }
2125
        
2126
        //
2127
        // Station summary
2128
        if (stnCount)
85✔
2129
        {
2130
                if (!p.g.quiet)
84✔
2131
                {
2132
                        parsestnTally.coutSummary(std::cout, std::string("  Read"));
166✔
2133
                        std::cout << std::endl;
83✔
2134
                }
2135
                parsestnTally.coutSummary(imp_file, std::string("  Read"));
168✔
2136
                imp_file << std::endl;
84✔
2137
        }
2138
        
2139
        //
2140
        // Measurement summary
2141
        if (msrCount)
85✔
2142
        {
2143
                if (!p.g.quiet)
82✔
2144
                {
2145
                        parsemsrTally.coutSummary(std::cout, std::string("  Read"));
162✔
2146
                        std::cout << std::endl;
81✔
2147
                }
2148
                parsemsrTally.coutSummary(imp_file, std::string("  Read"));
164✔
2149
                imp_file << std::endl;
82✔
2150
        }
2151

2152
        ////////////////////////////////////////////////////////////////////////
2153
        // Can we proceed?
2154
        if (stnCount < 1)
85✔
2155
        {
2156
                imp_file << "- No further processing can be done as no stations were loaded." << std::endl;
1✔
2157
                if (!p.g.quiet)
1✔
2158
                        std::cout << "- No further processing can be done as no stations were loaded." << std::endl;
1✔
2159
                imp_file.close();
1✔
2160
                return PARSE_SUCCESS;
2161
        }
2162

2163
        /////////////////////////////////////////////////////////////////////////
2164
        // Rename stations
2165
        if (p.i.rename_stations && (stnCount > 0 || msrCount > 0))
84✔
2166
        {
2167
                // Does it exist?
2168
                if (!boost::filesystem::exists(p.i.stn_renamingfile))
2✔
2169
                        // Look for it in the input folder
NEW
2170
                        p.i.stn_renamingfile = formPath<std::string>(p.g.input_folder, leafStr<std::string>(p.i.stn_renamingfile));
×
2171

2172
                // Apply renaming
2173
                try {
1✔
2174
                        if (!p.g.quiet)
1✔
2175
                        {
2176
                                std::cout << "+ Renaming stations... ";
1✔
2177
                                std::cout.flush();
1✔
2178
                        }
2179
                        imp_file << "+ Renaming stations... ";
1✔
2180
                        parserDynaML.RenameStations(&vstationsTotal, &vmeasurementsTotal, &p);
1✔
2181
                        if (!p.g.quiet)
1✔
2182
                                std::cout << "Done." << std::endl;
1✔
2183
                        imp_file << "Done." << std::endl;
1✔
2184
                } 
2185
                catch (const XMLInteropException& e) {
×
NEW
2186
                        std::cout << std::endl << "- Error: " << e.what() << std::endl;
×
NEW
2187
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2188
                        imp_file.close();
×
2189
                        return EXIT_FAILURE;
×
2190
                }
×
2191
        }
2192

2193
        // Apply GNSS scaling (if required)
2194
        if (p.i.import_block == 0 && p.i.import_network == 0 && p.i.apply_scaling)
84✔
2195
        {
2196
                // Apply scaling
2197
                try {
2✔
2198
                        if (!p.g.quiet)
2✔
2199
                        {
2200
                                std::cout << "+ Applying scalars to GNSS measurements... ";
2✔
2201
                                std::cout.flush();
2✔
2202
                        }
2203
                        imp_file << "+ Applying scalars to GNSS measurements... ";
2✔
2204
                        parserDynaML.EditGNSSMsrScalars(&vmeasurementsTotal, &p);
2✔
2205
                        if (!p.g.quiet)
2✔
2206
                                std::cout << "Done." << std::endl;
2✔
2207
                        imp_file << "Done." << std::endl;
2✔
2208
                } 
2209
                catch (const XMLInteropException& e) {
×
NEW
2210
                        std::cout << std::endl << "- Error: " << e.what() << std::endl;
×
NEW
2211
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2212
                        imp_file.close();
×
2213
                        return EXIT_FAILURE;
×
2214
                }
×
2215
        }
2216

2217
        std::ofstream dst_file;
84✔
2218

2219
        // flush duplicate stations/measurements files
2220
        try {
84✔
2221
                if (boost::filesystem::exists(p.i.dst_file))
168✔
2222
                        boost::filesystem::remove(p.i.dst_file);
4✔
2223
                if (boost::filesystem::exists(p.i.dms_file))
168✔
2224
                        boost::filesystem::remove(p.i.dms_file);
6✔
2225
        }
NEW
2226
        catch (const std::ios_base::failure& f) { 
×
2227
                // do nothing on failure.
NEW
2228
                imp_file << std::endl << "- Warning: " << f.what() << std::endl;
×
2229
        }
×
2230

2231
        // Prepare file names if importing from a segmentation block or contiguous network
2232
        if (p.i.import_block == 1 || p.i.import_network == 1)
84✔
2233
        {
2234
                std::stringstream modifier("");
10✔
2235
                if (p.i.import_block == 1)
5✔
2236
                        modifier << ".block-" << p.i.import_block_number;
4✔
2237
                else if (p.i.import_network == 1)
1✔
2238
                        modifier << ".network-" << p.i.import_network_number;
1✔
2239

2240
                // create new output file names based on block number
2241
                // reform file name for each so as to preserve full path for each file
2242
                std::stringstream ss("");
10✔
2243
                ss << formPath<std::string>(boost::filesystem::path(p.i.bst_file).parent_path().generic_string(), boost::filesystem::path(p.i.bst_file).stem().generic_string());
40✔
2244
                ss << modifier.str() << ".bst";
5✔
2245
                p.i.bst_file = ss.str();
5✔
2246

2247
                ss.str("");
15✔
2248
                ss << formPath<std::string>(boost::filesystem::path(p.i.bms_file).parent_path().generic_string(), boost::filesystem::path(p.i.bms_file).stem().generic_string());
40✔
2249
                ss << modifier.str() << ".bms";
5✔
2250
                p.i.bms_file = ss.str();
5✔
2251

2252
                ss.str("");
15✔
2253
                ss << formPath<std::string>(boost::filesystem::path(p.i.asl_file).parent_path().generic_string(), boost::filesystem::path(p.i.asl_file).stem().generic_string());
40✔
2254
                ss << modifier.str() << ".asl";
5✔
2255
                p.i.asl_file = ss.str();
5✔
2256

2257
                ss.str("");
15✔
2258
                ss << formPath<std::string>(boost::filesystem::path(p.i.aml_file).parent_path().generic_string(), boost::filesystem::path(p.i.aml_file).stem().generic_string());
40✔
2259
                ss << modifier.str() << ".aml";
5✔
2260
                p.i.aml_file = ss.str();
5✔
2261

2262
                ss.str("");
15✔
2263
                ss << formPath<std::string>(boost::filesystem::path(p.i.map_file).parent_path().generic_string(), boost::filesystem::path(p.i.map_file).stem().generic_string());
40✔
2264
                ss << modifier.str() << ".map";
5✔
2265
                p.i.map_file = ss.str();
5✔
2266

2267
                ss.str("");
15✔
2268
                ss << formPath<std::string>(boost::filesystem::path(p.i.map_file).parent_path().generic_string(), boost::filesystem::path(p.i.map_file).stem().generic_string());
40✔
2269
                ss << ".dbid";
5✔
2270
                p.i.dbid_file = ss.str();
5✔
2271
        }
5✔
2272

2273
        // Remove duplicate stations. If required, test nearby stations
2274
        if (stnCount > 0) {
84✔
2275
                
2276
                vstring vduplicateStns;
84✔
2277
                v_stringstring_doubledouble_pair vnearbyStns;
84✔
2278

2279
                // Remove duplicates and, if required, identify station pairs 
2280
                // separated by distances less than search_stn_radius
2281
                try {
84✔
2282
                        std::ostringstream ss_msg;
84✔
2283
                        if (p.i.search_nearby_stn)
84✔
2284
                                ss_msg << "+ Testing for duplicate and nearby stations... ";
2✔
2285
                        else
2286
                                ss_msg << "+ Testing for duplicate stations... ";
82✔
2287
                        
2288
                        if (!p.g.quiet)
84✔
2289
                        {
2290
                                std::cout << ss_msg.str();
83✔
2291
                                std::cout.flush();
83✔
2292
                        }
2293

2294
                        imp_file << ss_msg.str();                        
84✔
2295
                        
2296
                        stn = parserDynaML.RemoveDuplicateStations(&vstationsTotal, &vduplicateStns, &vnearbyStns);
84✔
2297
                        
2298
                        if (!p.g.quiet)
84✔
2299
                                std::cout << "Done. ";
83✔
2300
                        imp_file << "Done. ";
84✔
2301

2302
                        if (stn > 0)
84✔
2303
                        {
2304
                                try {
5✔
2305
                                        // Create duplicate station file
2306
                                        file_opener(dst_file, p.i.dst_file);
5✔
2307
                                }
NEW
2308
                                catch (const std::runtime_error& e) {
×
2309
                                        ss_msg << "- Error: Could not open " << p.i.dst_file << ". \n  Check that the file exists and that the file is not already opened." << 
×
NEW
2310
                                                 std::endl << e.what() << std::endl;
×
2311
                                        if (!p.g.quiet)
×
NEW
2312
                                                std::cout << ss_msg.str();
×
2313
                                        imp_file << ss_msg.str();
×
2314
                                        imp_file.close();
×
2315
                                        return EXIT_FAILURE;
×
2316
                                }
×
2317
                                                
2318
                                PrintOutputFileHeaderInfo(&dst_file, p.i.dst_file, &p, "DUPLICATE STATION FILE");
10✔
2319

2320
                                if (!vduplicateStns.empty())
5✔
2321
                                {
2322
                                        ss_msg.str("");
12✔
2323
                                        ss_msg << "Removed " << vduplicateStns.size() << " duplicate station" << (vduplicateStns.size() > 1 ? "s" : "");
7✔
2324
                                        
2325
                                        // print message to .dst file
2326
                                        dst_file << ss_msg.str() << ":" << std::endl;
4✔
2327
                                        for (stn=0; stn<vduplicateStns.size(); ++stn)
10✔
2328
                                                dst_file << "  - " << vduplicateStns.at(stn) << std::endl;
6✔
2329
                                        dst_file << std::endl;
4✔
2330

2331
                                        ss_msg << "." << std::endl << "  See " << p.i.dst_file << " for details." << std::endl;
4✔
2332

2333
                                        imp_file << ss_msg.str();
4✔
2334
                                        if (!p.g.quiet)
4✔
2335
                                                std::cout << std::endl << "- Warning: " << ss_msg.str();                                        
8✔
2336
                                }                                
2337

2338
                                if (!vnearbyStns.empty())
5✔
2339
                                {
2340
                                        ss_msg.str("");
3✔
2341
                                        ss_msg << vnearbyStns.size() << (vnearbyStns.size() > 1 ? " pairs of stations were" : " pair of station was") << 
1✔
2342
                                                " found to be separated by less than " << std::setprecision(3) << p.i.search_stn_radius << "m.";
1✔
2343

2344
                                        imp_file << std::endl << "- Warning: " << ss_msg.str() << std::endl << 
1✔
2345
                                                "  See " << p.i.dst_file << " for details." << std::endl << std::endl;
1✔
2346
                                        
2347
                                        if (!p.g.quiet)
1✔
2348
                                                std::cout << std::endl << "- Warning: " << ss_msg.str() << std::endl << 
2✔
2349
                                                "  See " << p.i.dst_file << " for details." << std::endl << std::endl;
1✔
2350
                                        ss_msg.str("");
3✔
2351

2352
                                        // output message
2353
                                        dst_file << "Nearby station search results:" << std::endl << ss_msg.str() << std::endl << std::endl;
1✔
2354

2355
                                        dst_file <<  
1✔
2356
                                                std::setw(HEADER_20) << std::left << "First station" << 
1✔
2357
                                                std::setw(HEADER_20) << "Nearby station" << 
2358
                                                std::setw(HEADER_20) << std::right << "Separation (m)" << 
1✔
2359
                                                std::setw(HEADER_20) << "Diff height (m)" << 
1✔
2360
                                                 std::endl;
81✔
2361

2362
                                        for (UINT32 i(0); i<(HEADER_20*4); ++i)
81✔
2363
                                                dst_file << "-";
80✔
2364
                                        dst_file << std::endl;
1✔
2365

2366
                                        // dump nearby stations to dst file
2367
                                        for (stn=0; stn<vnearbyStns.size(); ++stn)
50✔
2368
                                        {
2369
                                                dst_file <<
49✔
2370
                                                        std::setw(HEADER_20) << std::left << vnearbyStns.at(stn).first.first <<                                                                         // First
49✔
2371
                                                        std::setw(HEADER_20) << vnearbyStns.at(stn).first.second <<                                                                        // Nearby
49✔
2372
                                                        std::setw(HEADER_20) << std::setprecision(3) << std::fixed << std::right << vnearbyStns.at(stn).second.first <<                // Separation (m)
98✔
2373
                                                        std::setw(HEADER_20) << std::setprecision(3) << std::fixed << vnearbyStns.at(stn).second.second <<                // Diff height (m)
49✔
2374
                                                         std::endl;
49✔
2375
                                        }
2376

2377
                                        ss_msg <<
1✔
2378
                                                "  If the names in each pair refer to the same station, then update the " << std::endl <<
1✔
2379
                                                "  station and measurement files with the correct station name and re-run " << __BINARY_NAME__ << "." << std::endl <<
1✔
2380
                                                "  Alternatively, if the names in each pair are unique, either call " << __BINARY_NAME__ << std::endl <<
1✔
2381
                                                "  without the --" << TEST_NEARBY_STNS << " option, or decrease the radial search " << std::endl <<
1✔
2382
                                                "  distance using --" << TEST_NEARBY_STN_DIST << "." << std::endl << std::endl;
1✔
2383

2384
                                        if (!p.g.quiet)
1✔
2385
                                                std::cout << ss_msg.str();
2✔
2386
                                        imp_file << ss_msg.str();
1✔
2387
                                        imp_file.close();
1✔
2388
                                        dst_file.close();
1✔
2389
                                        return EXIT_FAILURE;
2390
                                }
2391
                                else if (p.g.verbose == 3)
4✔
2392
                                {
2393
                                        if (!p.g.quiet)
×
NEW
2394
                                                std::cout << "+ Total number of unique stations is " << vstationsTotal.size() << std::endl;
×
NEW
2395
                                        imp_file << "+ Total number of unique stations is " << vstationsTotal.size() << std::endl;
×
2396
                                }
2397

2398
                                // If this line is reached, then there are no nearby stations
2399
                                dst_file.close();
4✔
2400
                        }
2401
                        if (!p.g.quiet)
83✔
2402
                                std::cout << std::endl;
82✔
2403
                        imp_file << std::endl;
83✔
2404
                } 
84✔
2405
                catch (const XMLInteropException& e) {
×
NEW
2406
                        std::cout << std::endl << "- Error: " << e.what() << std::endl;
×
NEW
2407
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2408
                        imp_file.close();
×
2409
                        return EXIT_FAILURE;
×
2410
                }                
×
2411

2412
                /////////////////////////////////////////////////////////////////
2413
                // Now commence sorting and mapping
2414
                // 1. Sort stations
2415
                // 2. Create station map
2416
                try {
83✔
2417
                        if (!p.g.quiet)
83✔
2418
                        {
2419
                                std::cout << "+ Sorting stations... ";
82✔
2420
                                std::cout.flush();
82✔
2421
                        }
2422
                        imp_file << "+ Sorting stations... ";
83✔
2423
                        parserDynaML.FullSortandMapStations((vdnaStnPtr*) &vstationsTotal, &vStnsMap_sortName);
83✔
2424
                        if (!p.g.quiet)
83✔
2425
                        {
2426
                                std::cout << "Done." << std::endl << "+ Serialising station map... ";
82✔
2427
                                std::cout.flush();
82✔
2428
                        }
2429
                        imp_file << "Done." << std::endl << "+ Serialising station map... ";                        
83✔
2430
                        parserDynaML.SerialiseMap(p.i.map_file);                // parserDynaML keeps the map in memory
83✔
2431
                        stn_map_created = true;
83✔
2432
                        if (!p.g.quiet)
83✔
2433
                        {
2434
                                std::cout << "Done." << std::endl;
82✔
2435
                                std::cout.flush();
82✔
2436
                        }
2437
                        imp_file << "Done." << std::endl;
83✔
2438

2439
                        if (p.i.export_map_file)
83✔
2440
                        {
2441
                                if (!p.g.quiet)
5✔
2442
                                {
2443
                                        std::cout << "+ Exporting station map to text file... ";
5✔
2444
                                        std::cout.flush();
5✔
2445
                                }
2446
                                imp_file << "+ Exporting station map to text file... ";
5✔
2447
                                parserDynaML.SerialiseMapTextFile(p.i.map_file);
5✔
2448
                                if (!p.g.quiet)
5✔
2449
                                {
2450
                                        std::cout << "Done." << std::endl;
5✔
2451
                                        std::cout.flush();
5✔
2452
                                }
2453
                                imp_file << "Done." << std::endl;                                
5✔
2454
                        }
2455
                } 
2456
                catch (const XMLInteropException& e) {
×
NEW
2457
                        std::cout << std::endl << "- Error: " << e.what() << std::endl;
×
NEW
2458
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2459
                        imp_file.close();
×
2460
                        return EXIT_FAILURE;
×
2461
                }        
×
2462
        }
84✔
2463

2464
        // Search for similar measurements
2465
        if (msrCount > 0 && (p.i.search_similar_msr || p.i.search_similar_msr_gx || p.i.ignore_similar_msr)) 
83✔
2466
        {
2467
                if (SearchForSimilarMeasurements(&parserDynaML, &p, &imp_file,
4✔
2468
                        &vmeasurementsTotal) != EXIT_SUCCESS)
2469
                        return EXIT_FAILURE;        
2470
        }
2471

2472
        // Import DNA geoid file
2473
        if (p.i.import_geo_file && p.i.import_block == 0 && p.i.import_network == 0 && vstationsTotal.size())
83✔
2474
        {
2475
                if (!boost::filesystem::exists(p.i.geo_file))
4✔
2476
                {
NEW
2477
                        boost::filesystem::path geoPath(p.i.geo_file);
×
NEW
2478
                        std::stringstream ss;
×
NEW
2479
                        ss << "- Error: The geoid file " << geoPath.filename().string() << " does not exist." << std::endl;
×
NEW
2480
                        std::cout << std::endl << ss.str();
×
NEW
2481
                        imp_file << std::endl << ss.str();
×
2482
                        return EXIT_FAILURE;
×
2483
                }
×
2484

2485
                if (!p.g.quiet)
2✔
2486
                {
2487
                        std::cout << "+ Importing geoid information from " << p.i.geo_file << "... ";
2✔
2488
                        std::cout.flush();
2✔
2489
                }
2490
                imp_file << "+ Importing geoid information from " << p.i.geo_file << "... ";
2✔
2491

2492
                parserDynaML.LoadDNAGeoidFile(p.i.geo_file, &vstationsTotal);
2✔
2493

2494
                if (!p.g.quiet)
2✔
2495
                        std::cout << "Done." << std::endl;
2✔
2496
                imp_file << "Done." << std::endl;
2✔
2497
        }
2498

2499
        UINT32 ignMsrCount, mapCount;
83✔
2500
        vstring vunusedStations;
83✔
2501
        vUINT32 vignoredMeasurements;
83✔
2502

2503
        // Map measurements to stations
2504
        if (stn_map_created) 
83✔
2505
        {        
2506
                try {
83✔
2507
                        if (!p.g.quiet)
83✔
2508
                        {
2509
                                std::cout << "+ Mapping measurements to stations... ";
82✔
2510
                                std::cout.flush();
82✔
2511
                        }
2512
                        imp_file << "+ Mapping measurements to stations... ";
83✔
2513
                        
2514
                        parserDynaML.MapMeasurementStations((vdnaMsrPtr*) &vmeasurementsTotal,        &associatedSL, &mapCount, 
83✔
2515
                                &vunusedStations, &vignoredMeasurements);
2516
                        
2517
                        if (!p.g.quiet)
82✔
2518
                                std::cout << "Done." << std::endl;
81✔
2519
                        imp_file << "Done. ";
82✔
2520

2521
                        if (msrCount > 0)
82✔
2522
                        {
2523
                                measurements_mapped = true;
80✔
2524
                                imp_file << "Mapped " << mapCount << " measurements to " << vStnsMap_sortName.size() - vunusedStations.size() << " stations." << std::endl;
80✔
2525
                        }
2526
                        else
2527
                                imp_file << std::endl;
2✔
2528

2529
                        if (!vunusedStations.empty())
82✔
2530
                        {
2531
                                if (vunusedStations.size() == 1)
17✔
2532
                                {
2533
                                        if (p.g.verbose > 2)
13✔
2534
                                        {
2535
                                                if (!p.g.quiet)
×
NEW
2536
                                                        std::cout << "- Warning: station " << vunusedStations.at(0) << " was not associated with any measurements." << std::endl;
×
NEW
2537
                                                imp_file << "- Warning: station " << vunusedStations.at(0) << " was not associated with any measurements." << std::endl;
×
2538
                                        }
2539
                                        else
2540
                                        {
2541
                                                if (!p.g.quiet)
13✔
2542
                                                        std::cout << "- Warning: " << vunusedStations.size() << " station was not associated with any measurements." << std::endl;
13✔
2543
                                                imp_file << "- Warning: " << vunusedStations.size() << " station was not associated with any measurements." << std::endl;
13✔
2544
                                        }
2545
                                }
2546
                                else
2547
                                {
2548
                                        if (p.g.verbose > 2)
4✔
2549
                                        {
2550
                                                if (!p.g.quiet)
×
NEW
2551
                                                        std::cout << "- Warning: The following " << vunusedStations.size() << " stations were not associated with any measurements." << std::endl;
×
NEW
2552
                                                imp_file << "- Warning: The following " << vunusedStations.size() << " stations were not associated with any measurements." << std::endl;
×
2553
                                                _it_vstr unused;
×
2554
                                                for (unused = vunusedStations.begin(); unused!=vunusedStations.end(); unused++)
×
2555
                                                {
2556
                                                        if (!p.g.quiet)
×
NEW
2557
                                                                outputObject(std::string("  - " + *unused + "\n"), std::cout);
×
NEW
2558
                                                        outputObject(std::string("  - " + *unused + "\n"), imp_file);
×
2559
                                                }
2560
                                        }
2561
                                        else
2562
                                        {
2563
                                                if (!p.g.quiet)
4✔
2564
                                                        std::cout << "- Warning: " << vunusedStations.size() << " stations were not associated with any measurements." << std::endl;
4✔
2565
                                                imp_file << "- Warning: " << vunusedStations.size() << " stations were not associated with any measurements." << std::endl;
4✔
2566
                                        }
2567
                                }
2568
                        }
2569

2570
                        if (msrRead < mapCount && vignoredMeasurements.empty())
82✔
2571
                        {
2572
                                if (!p.g.quiet)
3✔
2573
                                        std::cout << "- Warning: Not all measurements were mapped: " << msrRead << " msrs read vs. " << mapCount
3✔
2574
                                                << " msrs mapped." << std::endl;
3✔
2575
                        }
2576
                        else if (msrRead != mapCount && !vignoredMeasurements.empty())
79✔
2577
                        {
2578
                                ignMsrCount = parserDynaML.ComputeMeasurementCount(&vmeasurementsTotal, vignoredMeasurements);        
6✔
2579
                                if (!p.g.quiet)
6✔
2580
                                {
2581
                                        std::cout << "- Warning: " << ignMsrCount << " ignored measurements were not mapped." << std::endl;
6✔
2582
                                        if ((msrRead - mapCount) != ignMsrCount)
6✔
2583
                                                std::cout << "-          " << msrRead << " m.read vs. " << mapCount << " m.mapped." << std::endl;
6✔
2584
                                }
2585
                        }
2586
                        if (!p.g.quiet)
82✔
2587
                                std::cout.flush();
81✔
2588
                } 
2589
                catch (const XMLInteropException& e) {
1✔
2590
                        std::cout << std::endl << "- Error: " << e.what() << std::endl;
1✔
2591
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
1✔
2592
                        imp_file.close();
1✔
2593
                        return EXIT_FAILURE;
1✔
2594
                }
1✔
2595
        }
2596

2597
        stnCount = static_cast<UINT32>(vstationsTotal.size());
82✔
2598
        if (stnCount > static_cast<UINT32>(associatedSL.size()))
82✔
2599
                stnCount = static_cast<UINT32>(associatedSL.size());
×
2600
        
2601
        // Does the user want to simulate measurements?
2602
        if (p.i.simulate_measurements && stnCount > 0 && msrCount > 0) 
82✔
2603
        {
2604
                // No need for the following code if the outer 'if' statement checks 
2605
                // for non-zero stnCount value
2606
                //
2607
                // if (stnCount == 0)
2608
                // {
2609
                //         if (!p.g.quiet)
2610
                //                 std::cout << "- Error: there are no stations from which to simulate measurements." << std::endl;
2611
                //         imp_file << "- Error: there are no stations from which to simulate measurements." << std::endl;
2612
                //         imp_file.close();
2613
                //         return EXIT_FAILURE;
2614
                // }        
2615
        
2616
                try {
1✔
2617
                        // Simulate measurements
2618
                        if (!p.g.quiet)
1✔
2619
                        {
2620
                                std::cout << "+ Simulating and exporting measurements to " << leafStr<std::string>(p.i.simulate_msrfile) << "... ";
2✔
2621
                                std::cout.flush();
1✔
2622
                        }
2623
                        imp_file << "+ Simulating and exporting measurements to " << leafStr<std::string>(p.i.simulate_msrfile) << "... ";
2✔
2624
                        parserDynaML.SimulateMSR(
1✔
2625
                                ((vdnaStnPtr*) &vstationsTotal), 
2626
                                ((vdnaMsrPtr*) &vmeasurementsTotal), 
2627
                                p.i.simulate_msrfile, p);
2628
                        if (!p.g.quiet)
1✔
2629
                                std::cout << "Done." << std::endl;
1✔
2630
                        imp_file << "Done." << std::endl;
1✔
2631
                }
2632
                catch (const XMLInteropException& e) {
×
NEW
2633
                        std::cout.flush();
×
NEW
2634
                        std::cout << std::endl << "- Error: " << e.what() << std::endl;
×
NEW
2635
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2636
                        imp_file.close();
×
2637
                        return EXIT_FAILURE;
×
2638
                }
×
2639
        }
2640

2641
        // Create association lists
2642
        if (measurements_mapped) 
82✔
2643
        {
2644
                try {
80✔
2645
                        if (!p.g.quiet)
80✔
2646
                        {
2647
                                std::cout << "+ Creating association lists... ";
79✔
2648
                                std::cout.flush();
79✔
2649
                        }
2650
                        imp_file << "+ Creating association lists... ";
80✔
2651
                        parserDynaML.CompleteAssociationLists(&vmeasurementsTotal, &associatedSL, &associatedML);
80✔
2652
                        if (!p.g.quiet)
80✔
2653
                        {
2654
                                std::cout << "Done." << std::endl;
79✔
2655
                                std::cout.flush();
79✔
2656
                        }
2657
                        imp_file << "Done." << std::endl;
80✔
2658
                } 
2659
                catch (const XMLInteropException& e) {
×
NEW
2660
                        std::cout << "- Error: " << e.what() << std::endl;
×
NEW
2661
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2662
                        imp_file.close();
×
2663
                        return EXIT_FAILURE;
×
2664
                }
×
2665

2666
                try {
80✔
2667
                        if (!p.g.quiet)
80✔
2668
                        {
2669
                                std::cout << "+ Serialising association lists... ";
79✔
2670
                                std::cout.flush();
79✔
2671
                        }
2672
                        imp_file << "+ Serialising association lists... ";
80✔
2673
                        parserDynaML.SerialiseAsl(p.i.asl_file, &associatedSL);
80✔
2674
                        parserDynaML.SerialiseAml(p.i.aml_file, &associatedML);
80✔
2675
                        if (!p.g.quiet)
80✔
2676
                        {
2677
                                std::cout << "Done." << std::endl;
79✔
2678
                                std::cout.flush();
79✔
2679
                        }
2680
                        imp_file << "Done." << std::endl;
80✔
2681
                } 
2682
                catch (const XMLInteropException& e) {
×
NEW
2683
                        std::cout << "- Error: " << e.what() << std::endl;
×
NEW
2684
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2685
                        imp_file.close();
×
2686
                        return EXIT_FAILURE;
×
2687
                }
×
2688
        }
2689

2690
        // Create binary station file.
2691
        // Binary station file can be serialised without measurements
2692
        if (stnCount > 0)
82✔
2693
        {
2694
                try {
82✔
2695
                        if (!vstationsTotal.empty())
82✔
2696
                        {
2697
                                if (!p.g.quiet)
82✔
2698
                                {
2699
                                        std::cout << "+ Serialising binary station file " << leafStr<std::string>(p.i.bst_file) << "... ";
162✔
2700
                                        std::cout.flush();
81✔
2701
                                }
2702
                                imp_file << "+ Serialising binary station file " << leafStr<std::string>(p.i.bst_file) << "... ";
164✔
2703
                                
2704
                                parserDynaML.SerialiseBst(
82✔
2705
                                        p.i.bst_file, ((vdnaStnPtr*) &vstationsTotal), &vunusedStations,
2706
                                        vinput_file_meta, (p.i.flag_unused_stn ? true : false));
82✔
2707
                                if (!p.g.quiet)
82✔
2708
                                {
2709
                                        std::cout << "Done." << std::endl;
81✔
2710
                                        std::cout.flush();
81✔
2711
                                }
2712
                                imp_file << "Done." << std::endl;
82✔
2713
                        }
2714
                } 
2715
                catch (const XMLInteropException& e) {
×
NEW
2716
                        std::cout << "- Error: " << e.what() << std::endl;
×
NEW
2717
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2718
                        imp_file.close();
×
2719
                        return EXIT_FAILURE;
×
2720
                }
×
2721
        }
2722

2723
        // Create binary measurement file.
2724
        // Binary measurement file can be serialised without stations
2725
        if (msrCount > 0) 
82✔
2726
        {
2727
                try {
80✔
2728
                        if (!vmeasurementsTotal.empty())
80✔
2729
                        {
2730
                                if (!p.g.quiet)
80✔
2731
                                {
2732
                                        std::cout << "+ Serialising binary measurement file " << leafStr<std::string>(p.i.bms_file) << "... ";
158✔
2733
                                        std::cout.flush();
79✔
2734
                                }
2735
                                imp_file << "+ Serialising binary measurement file " << leafStr<std::string>(p.i.bms_file) << "... ";
160✔
2736

2737
                                parserDynaML.SerialiseBms(
80✔
2738
                                        p.i.bms_file, ((vdnaMsrPtr*) &vmeasurementsTotal),
2739
                                        vinput_file_meta);
2740
                                if (!p.g.quiet)
80✔
2741
                                {
2742
                                        std::cout << "Done." << std::endl;
79✔
2743
                                        std::cout.flush();
79✔
2744
                                }
2745
                                imp_file << "Done." << std::endl;
80✔
2746
                        }
2747
                } 
2748
                catch (const XMLInteropException& e) {
×
NEW
2749
                        std::cout << "- Error: " << e.what() << std::endl;
×
NEW
2750
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2751
                        imp_file.close();
×
2752
                        return EXIT_FAILURE;
×
2753
                }
×
2754
        }
2755

2756
        // Export ASL and AML to text if required
2757
        if (measurements_mapped) 
82✔
2758
        {
2759
                try {
80✔
2760
                        if (p.i.export_asl_file)
80✔
2761
                        {
2762
                                if (!p.g.quiet)
5✔
2763
                                {
2764
                                        std::cout << "+ Exporting associated station list to text file... ";
5✔
2765
                                        std::cout.flush();
5✔
2766
                                }
2767
                                imp_file << "+ Exporting associated station list to text file... ";
5✔
2768
                                parserDynaML.SerialiseAslTextFile(p.i.asl_file, &associatedSL, (vdnaStnPtr*) &vstationsTotal);
5✔
2769
                                if (!p.g.quiet)
5✔
2770
                                {
2771
                                        std::cout << "Done." << std::endl;
5✔
2772
                                        std::cout.flush();
5✔
2773
                                }
2774
                                imp_file << "Done." << std::endl;                                
5✔
2775
                        }
2776
                } 
2777
                catch (const XMLInteropException& e) {
×
NEW
2778
                        std::cout << "- Error: " << e.what() << std::endl;
×
NEW
2779
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2780
                        imp_file.close();
×
2781
                        return EXIT_FAILURE;
×
2782
                }
×
2783

2784
                try {
80✔
2785
                        if (p.i.export_aml_file)
80✔
2786
                        {
2787
                                if (!p.g.quiet)
5✔
2788
                                {
2789
                                        std::cout << "+ Exporting associated measurement list to text file... ";
5✔
2790
                                        std::cout.flush();
5✔
2791
                                }
2792
                                imp_file << "+ Exporting associated measurement list to text file... ";
5✔
2793
                                parserDynaML.SerialiseAmlTextFile(p.i.bms_file, p.i.aml_file, &associatedML, &associatedSL, (vdnaStnPtr*) &vstationsTotal);
5✔
2794
                                if (!p.g.quiet)
5✔
2795
                                {
2796
                                        std::cout << "Done." << std::endl;
5✔
2797
                                        std::cout.flush();
5✔
2798
                                }
2799
                                imp_file << "Done." << std::endl;                                
5✔
2800
                        }
2801
                }
2802
                catch (const XMLInteropException& e) {
×
NEW
2803
                        std::cout << "- Error: " << e.what() << std::endl;
×
NEW
2804
                        imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2805
                        imp_file.close();
×
2806
                        return EXIT_FAILURE;
×
2807
                }
×
2808

2809
                if (p.i.test_integrity)
80✔
2810
                {
2811
                        if (!p.g.quiet)
2✔
2812
                        {
2813
                                std::cout << "+ Testing internal integrity of ASL, AML and binary files... ";
2✔
2814
                                std::cout.flush();
2✔
2815
                        }
2816
                        std::ifstream binaryMS(p.i.bms_file.c_str(), std::ios::in | std::ios::binary | std::ifstream::ate);        /// Open and seek to end immediately after opening.
2✔
2817
                        if (!binaryMS.good())
2✔
2818
                        {
NEW
2819
                                std::cout << std::endl << "- Could not open binary file for reading." << std::endl;
×
NEW
2820
                                imp_file << std::endl << "- Could not open binary file for reading." << std::endl;
×
2821
                                imp_file.close();
×
2822
                                return EXIT_FAILURE;
×
2823
                        }
2824
                        // get size, then go back to beginning
2825
                        size_t sFileSize = (size_t)binaryMS.tellg();
2✔
2826
                        binaryMS.seekg(0, std::ios::beg);
2✔
2827

2828
                        measurement_t measRecord;
2✔
2829
                        
2830
                        UINT32 amlcount, amlindex, msr;
2✔
2831
                        for (stn=0; stn<stnCount; stn++)
90✔
2832
                        {
2833
                                amlcount = associatedSL.at(stn).get()->GetAssocMsrCount();
86✔
2834
                                
2835
                                // The following is to be used when reading from binary file
2836
                                for (msr=0; msr<amlcount; msr++)
624✔
2837
                                {
2838
                                        amlindex = associatedSL.at(stn).get()->GetAMLStnIndex() + msr;
538✔
2839
                                        if (associatedML.at(amlindex) * sizeof(measurement_t) >= sFileSize)
538✔
2840
                                        {
NEW
2841
                                                std::cout << "Error: index " << associatedML.at(amlindex) << " is out of range for the binary file." << std::endl;
×
2842
                                                continue;
×
2843
                                        }
2844
                                        binaryMS.seekg(sizeof(UINT32) + associatedML.at(amlindex) * sizeof(measurement_t), std::ios::beg);
538✔
2845
                                        binaryMS.read(reinterpret_cast<char *>(&measRecord), sizeof(measurement_t));
538✔
2846
                                }
2847
                        }
2848
                        binaryMS.close();
2✔
2849
                        if (!p.g.quiet)
2✔
2850
                                std::cout << "OK." << std::endl;
2✔
2851
                }
2✔
2852
        }
2853

2854
        try {
82✔
2855
                // Print measurements to stations table
2856
                PrintMeasurementstoStations(&parsemsrTally, &parserDynaML, &p, &associatedSL);
82✔
2857
        }
2858
        catch (const XMLInteropException& e) {
×
NEW
2859
                std::cout.flush();
×
NEW
2860
                std::cout << std::endl << "- Error: " << e.what() << std::endl;
×
NEW
2861
                imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2862
                imp_file.close();
×
2863
                return EXIT_FAILURE;
×
2864
        }
×
2865

2866

2867
        // Serialise database ids
2868
        if (p.i.import_block == 1 || p.i.import_network == 1)
82✔
2869
        {
2870
                // dbid_file filename formed earlier
2871
                parserDynaML.SerialiseDatabaseId(p.i.dbid_file, &vmeasurementsTotal);
5✔
2872
        }
2873
        else
2874
        {
2875
                p.i.dbid_file = formPath<std::string>(p.g.output_folder, p.g.network_name, "dbid");
231✔
2876
                parserDynaML.SerialiseDatabaseId(p.i.dbid_file, &vmeasurementsTotal);
77✔
2877
        }
2878

2879
        // Export stations and measurements
2880
        try {
82✔
2881
                if (p.i.export_dynaml || p.i.export_dna_files)
82✔
2882
                        ExportStationsandMeasurements(&parserDynaML, p, &imp_file, &vinput_file_meta, 
14✔
2883
                                &vstationsTotal, &vmeasurementsTotal, stnCount, msrCount);
2884
        }
2885
        catch (const XMLInteropException& e) {
×
NEW
2886
                std::cout.flush();
×
NEW
2887
                std::cout << std::endl << "- Error: " << e.what() << std::endl;
×
NEW
2888
                imp_file << std::endl << "- Error: " << e.what() << std::endl;
×
2889
                imp_file.close();
×
2890
                return EXIT_FAILURE;
×
2891
        }
×
2892
        
2893
        if (!userSuppliedSegFile)
82✔
2894
                p.i.seg_file = "";
81✔
2895
        if (!userSuppliedBstFile)
82✔
2896
                p.i.bst_file = "";
82✔
2897
        if (!userSuppliedBmsFile)
82✔
2898
                p.i.bms_file = "";
82✔
2899

2900
        // Look for a project file.  If it exists, open and load it.
2901
        // Update the import settings.
2902
        // Print the project file. If it doesn't exist, it will be created.
2903
        CDnaProjectFile projectFile;
82✔
2904
        if (boost::filesystem::exists(p.g.project_file))
164✔
2905
                projectFile.LoadProjectFile(p.g.project_file);
33✔
2906
        
2907
        projectFile.UpdateSettingsImport(p);
82✔
2908
        projectFile.UpdateSettingsReftran(p);
82✔
2909
        projectFile.UpdateSettingsOutput(p);
82✔
2910
        projectFile.PrintProjectFile();
82✔
2911

2912
        if (msrCount == 0)
82✔
2913
        {
2914
                std::cout << "- Warning: there are no measurements to process." << std::endl;
2✔
2915
                imp_file << "- Warning: there are no measurements to process." << std::endl;
2✔
2916
        }
2917
        
2918
        if (errorCount)
82✔
2919
        {
NEW
2920
                if (!p.g.quiet)
×
NEW
2921
                        std::cout << "- Warning: some files were not parsed - please read the log file for more details." << std::endl;
×
NEW
2922
                imp_file << "- Warning: some files were not parsed - please read the log file for more details." << std::endl;
×
2923
        }
2924

2925
        // Produce a warning if an ensemble is set as the default reference frame
2926
        if (isEpsgWGS84Ensemble(epsgCode))
82✔
2927
        {
2928
                std::stringstream ssEnsembleWarning;
3✔
2929
                ssEnsembleWarning << std::endl <<
3✔
2930
                        "- Warning:  The '" << p.i.reference_frame << "' reference frame set for this project refers to the" << std::endl <<
3✔
2931
                        "  \"World Geodetic System 1984 (WGS 84) ensemble\".  The WGS 84 ensemble is" << std::endl <<
3✔
2932
                        "  only suitable for low accuracy (metre level) positioning and does not" << std::endl <<
3✔
2933
                        "  provide for precise transformations to other well-known reference frames." << std::endl <<
3✔
2934
                        "  To achieve reliable adjustment results from data on WGS 84, please refer" << std::endl <<
3✔
2935
                        "  to \"Configuring import options\" in the DynAdjust User's Guide." << std::endl;
3✔
2936
                if (!p.g.quiet)
3✔
2937
                        std::cout << ssEnsembleWarning.str();
6✔
2938
                imp_file << ssEnsembleWarning.str();
3✔
2939
        }
3✔
2940
        
2941
        boost::posix_time::milliseconds elapsed_time(boost::posix_time::milliseconds(time.elapsed().wall/MILLI_TO_NANO));
82✔
2942
        std::string time_message = formatedElapsedTime<std::string>(&elapsed_time, "+ Total file handling process took ");
164✔
2943

2944
        if (!p.g.quiet)
82✔
2945
                std::cout << std::endl << time_message << std::endl;
81✔
2946
        imp_file << std::endl << time_message << std::endl;
82✔
2947
        
2948
        if (stnCount > 0 && msrCount > 0)
82✔
2949
        {
2950
                if (!p.g.quiet)
80✔
2951
                        std::cout << "+ Binary station and measurement files are now ready for processing." << std::endl << std::endl;
79✔
2952
                imp_file << "+ Binary station and measurement files are now ready for processing." << std::endl << std::endl;
80✔
2953
        }
2954

2955
        imp_file.close();
82✔
2956
        return PARSE_SUCCESS;
82✔
2957
}
593✔
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