• 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

82.54
/dynadjust/dynadjust/dnasegment/dnasegment.cpp
1
//============================================================================
2
// Name         : dnasegment.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 Network Segmentation library
21
//============================================================================
22

23
#include <dynadjust/dnasegment/dnasegment.hpp>
24

25
namespace dynadjust { 
26
namespace networksegment {
27

28
dna_segment::dna_segment()
17✔
29
        : isProcessing_(false)
17✔
30
{
31
        network_name_ = "";
17✔
32
}
17✔
33

34
dna_segment::~dna_segment()
17✔
35
{
36

37
}
51✔
38
        
39

40
double dna_segment::GetProgress() const
×
41
{ 
42
        return ((bstBinaryRecords_.size() - vfreeStnList_.size()) * 100. / bstBinaryRecords_.size()); 
×
43
}
44

45
void dna_segment::LoadNetFile()
2✔
46
{
47
        // Get stations listed in net file
48
        std::ifstream net_file;
2✔
49
        try {
2✔
50
                // Load net file.  Throws runtime_error on failure.
51
                file_opener(net_file, projectSettings_.s.net_file, 
2✔
52
                        std::ios::in, ascii, true);
53
        }
NEW
54
        catch (const std::runtime_error& e) {
×
55
                SignalExceptionSerialise(e.what(), 0, NULL);
×
56
        }
×
57

58
        std::string station;
2✔
59
        char line[PROGRAM_OPTIONS_LINE_LENGTH];
2✔
60
        
61
        // read header lines
62
        net_file.ignore(PRINT_LINE_LENGTH, '\n');                                        // -------------------------------------------
2✔
63
        net_file.getline(line, PROGRAM_OPTIONS_LINE_LENGTH);                //            DYNADJUST BLOCK 1 STATIONS FILE
2✔
64

65
        vinitialStns_.clear();
2✔
66

67
        try {
2✔
68

69
                while (!net_file.eof())
8✔
70
                {
71
                        net_file.getline(line, PROGRAM_OPTIONS_LINE_LENGTH);                // Stations
4✔
72
                        station = line;
4✔
73
                        if ((station = trimstr(station)).empty())
8✔
74
                                continue;
2✔
75
                        // add this station to the list
76
                        vinitialStns_.push_back(station);
2✔
77
                }
78
        }
NEW
79
        catch (const std::ios_base::failure& f) {
×
80

81
                if (!net_file.eof())
×
82
                {
NEW
83
                        std::stringstream ss;
×
NEW
84
                        ss << "ParseStartingStations(): An error was encountered when reading " << projectSettings_.s.net_file << "." << std::endl << f.what();
×
85
                        SignalExceptionSerialise(ss.str(), 0, "i", &net_file);        
×
86
                }
×
87
        }
×
88

89
        net_file.close();
2✔
90
}
2✔
91

92
void dna_segment::ParseStartingStations()
17✔
93
{
94
        // Get stations listed in net file (if it exists)
95
        // Rememeber, calling app should make sure that 
96
        // projectSettings_.s.net_file contains a valid path if
97
        // the user wants to use a net file.
98
        if (boost::filesystem::exists(projectSettings_.s.net_file.c_str()))
34✔
99
                LoadNetFile();
2✔
100

101
        // OK, now get the additionalstations on the command line
102
        if (projectSettings_.s.seg_starting_stns.empty())
17✔
103
                return;
13✔
104

105
        vstring cmd_line_stations;
4✔
106

107
        try {
4✔
108
                // Extract stations from comma delimited string
109
                SplitDelimitedString<std::string>(
8✔
110
                        projectSettings_.s.seg_starting_stns,        // the comma delimited string
4✔
111
                        std::string(","),                                                        // the delimiter
8✔
112
                        &cmd_line_stations);                                                // the respective values
113
        }
114
        catch (...) {
×
115
                return;
×
116
        }
×
117

118
        if (!cmd_line_stations.empty())
4✔
119
                vinitialStns_.insert(vinitialStns_.end(), cmd_line_stations.begin(), cmd_line_stations.end());
4✔
120
                
121
        if (!vinitialStns_.empty())
4✔
122
                strip_duplicates(vinitialStns_);
4✔
123
}
4✔
124
        
125

126
void dna_segment::PrepareSegmentation(project_settings* p)
17✔
127
{
128
        projectSettings_ = *p;
17✔
129

130
        ParseStartingStations();
17✔
131

132
        network_name_ = p->g.network_name;
17✔
133

134
        LoadBinaryFiles(p->s.bst_file, p->s.bms_file);
17✔
135
        LoadAssociationFiles(p->s.asl_file, p->s.aml_file);
16✔
136
        LoadStationMap(p->s.map_file);
16✔
137
        BuildFreeStationAvailabilityList();
16✔
138
        
139
        SortbyMeasurementCount(&vfreeStnList_);
16✔
140
}
16✔
141

142

143
void dna_segment::InitialiseSegmentation()
17✔
144
{
145
        segmentStatus_ = SEGMENT_SUCCESS;
17✔
146
        isProcessing_ = false;        
17✔
147
        currentBlock_ = 0;
17✔
148

149
        network_name_ = "network_name";                // network name
17✔
150
        
151
        vinitialStns_.clear();
17✔
152
        vCurrJunctStnList_.clear();
17✔
153
        vCurrInnerStnList_.clear();
17✔
154
        vCurrMeasurementList_.clear();
17✔
155
        
156
        bstBinaryRecords_.clear();
17✔
157
        bmsBinaryRecords_.clear();
17✔
158
        vAssocStnList_.clear();
17✔
159
        vAssocMsrList_.clear();
17✔
160
        vfreeStnList_.clear();
17✔
161
        vfreeMsrList_.clear();
17✔
162
        stnsMap_.clear();
17✔
163

164
        vJSL_.clear();
17✔
165
        vISL_.clear();
17✔
166
        vCML_.clear();
17✔
167
}
17✔
168
        
169

170
_SEGMENT_STATUS_ dna_segment::SegmentNetwork(project_settings* p)
16✔
171
{
172
        isProcessing_ = true;        
16✔
173

174
        output_folder_ = p->g.output_folder;
16✔
175

176
        if ((debug_level_ = p->g.verbose) > 2)
16✔
177
        {
178
                std::string s(p->s.seg_file + ".trace");
5✔
179
                try {
5✔
180
                        // Create trace file.  Throws runtime_error on failure.
181
                        file_opener(trace_file, s);
5✔
182
                        print_file_header(trace_file, "DYNADJUST SEGMENTATION TRACE FILE");
10✔
183
                        trace_file << OUTPUTLINE << std::endl << std::endl;
5✔
184
                }
NEW
185
                catch (const std::runtime_error& e) {
×
186
                        SignalExceptionSerialise(e.what(), 0, NULL);
×
187
                }
×
188
        }
5✔
189
        
190
        if ((debug_level_ = p->g.verbose) > 1)
16✔
191
        {
192
                std::string s(p->s.seg_file + ".debug");
5✔
193
                        
194
                try {
5✔
195
                        // Create debug file.  Throws runtime_error on failure.
196
                        file_opener(debug_file, s);
5✔
197
                }
NEW
198
                catch (const std::ios_base::failure& f) {
×
199
                        SignalExceptionSerialise(f.what(), 0, NULL);
×
200
                }
×
201
        }
5✔
202

203
        segmentStatus_ = SEGMENT_SUCCESS;
16✔
204
        std::ostringstream ss;
16✔
205

206
        if (debug_level_ > 2)
16✔
207
                WriteFreeStnListSortedbyASLMsrCount();
5✔
208

209
        currentBlock_ = 1;
16✔
210

211
        if (debug_level_ > 2)
16✔
212
                trace_file << "Block " << currentBlock_ << "..." << std::endl;
5✔
213
        
214
        boost::timer::cpu_timer time;
16✔
215

216
        v_ContiguousNetList_.clear();
16✔
217
        v_ContiguousNetList_.push_back(currentNetwork_ = 0);
16✔
218

219
        if (bstBinaryRecords_.empty())
16✔
220
                SignalExceptionSerialise("SegmentNetwork(): the binary stations file has not been loaded into memory yet.", 0, NULL);
×
221
        if (bmsBinaryRecords_.empty())
16✔
222
                SignalExceptionSerialise("SegmentNetwork(): the binary measurements file has not been loaded into memory yet.", 0, NULL);
×
223
        if (vAssocStnList_.empty())
16✔
224
                SignalExceptionSerialise("SegmentNetwork(): the Associated Station List (ASL) has not been loaded into memory yet.", 0, NULL);
×
225
        if (vAssocFreeMsrList_.empty())
16✔
226
                SignalExceptionSerialise("SegmentNetwork(): the Associated Measurements List (AML) has not been loaded into memory yet.", 0, NULL);
×
227
        if (stnsMap_.empty())
16✔
228
                SignalExceptionSerialise("SegmentNetwork(): the station map has not been loaded into memory yet.", 0, NULL);
×
229

230
        // The inner stations for the first block are created from segmentCriteria._initialStns
231
        // Junction stations are retrieved from measurements connected to the inner stations
232
        BuildFirstBlock();
16✔
233
        
234
        while (!vfreeStnList_.empty())
30✔
235
        {
236
                isProcessing_ = true;
30✔
237

238
                currentBlock_++;
30✔
239

240
                if (debug_level_ > 2)
30✔
241
                        trace_file << "Block " << currentBlock_ << "..." << std::endl;
12✔
242

243
                v_ContiguousNetList_.push_back(currentNetwork_);
30✔
244

245
                // The inner stations for the next block are the junction stations from the previous block
246
                // The junction stations are retrieved from measurements connected to the inner stations
247
                // BuildNextBlock applies the min and max station constraints using segmentCriteria
248
                BuildNextBlock();
30✔
249
        
250
                if (vfreeStnList_.empty())
30✔
251
                        break;
252
        }
253

254
        boost::posix_time::milliseconds elapsed_time(boost::posix_time::milliseconds(0));
16✔
255
        if (debug_level_ > 1)
16✔
256
                elapsed_time = boost::posix_time::milliseconds(time.elapsed().wall/MILLI_TO_NANO);
5✔
257
        
258
        isProcessing_ = false;        
16✔
259

260
        CalculateAverageBlockSize();
16✔
261

262
        char valid_stations(0);
16✔
263
        char valid_measurements_not_included(0);
16✔
264
        if (vfreeStnList_.size())
16✔
265
        {
266
                valid_stations = 1;
×
267
                ss.str("");
×
NEW
268
                ss << std::endl << "- Warning: The following stations were not used:" << std::endl;
×
269
                ss << "  ";
×
270
                it_vUINT32_const _it_freestn(vfreeStnList_.begin());
×
271
                for (; _it_freestn!=vfreeStnList_.end(); ++_it_freestn)
×
272
                        ss << bstBinaryRecords_.at(*_it_freestn).stationName << " ";
×
NEW
273
                ss << std::endl;
×
NEW
274
                ss << "- Possible reasons why these stations were not used include:" << std::endl;
×
NEW
275
                ss << "  - No measurements to these stations were found," << std::endl;
×
NEW
276
                ss << "  - The network is made up of non-contiguous blocks," << std::endl;
×
NEW
277
                ss << "  - There is a bug in this program." << std::endl;
×
278

279
                if (debug_level_ > 1)
×
280
                        debug_file << ss.str();
×
281
        }
282

283
        if (debug_level_ > 1)
16✔
284
        {
285
                debug_file << formatedElapsedTime<std::string>(&elapsed_time, "+ Network segmentation took ") <<
15✔
286
                        " The network is now ready for adjustment." << std::endl;
10✔
287
                debug_file.close();
5✔
288
        }
289

290
        isProcessing_ = false;        
16✔
291

292
        if (valid_measurements_not_included || valid_stations)
16✔
293
                return (segmentStatus_ = SEGMENT_BLOCK_ERROR);
×
294

295
        return (segmentStatus_ = SEGMENT_SUCCESS);
16✔
296
}
16✔
297
        
298

299
void dna_segment::CalculateAverageBlockSize()
16✔
300
{
301
        vUINT32 blockSizes;
16✔
302
        blockSizes.resize(vISL_.size());
16✔
303

304
        it_vUINT32 _it_count;
16✔
305
        it_vvUINT32 _it_isl, _it_jsl;
16✔
306
        for (_it_count=blockSizes.begin(), _it_isl=vISL_.begin(), _it_jsl=vJSL_.begin(); 
16✔
307
                _it_isl!=vISL_.end(); 
62✔
308
                ++_it_count, ++_it_isl, ++_it_jsl)
46✔
309
                *_it_count = static_cast<UINT32>(_it_isl->size() + _it_jsl->size());
46✔
310

311
        averageBlockSize_ = average<double, UINT32, it_vUINT32>(blockSizes.begin(), blockSizes.end(), stationSolutionCount_);
16✔
312

313
        maxBlockSize_ = *(max_element(blockSizes.begin(), blockSizes.end()));
16✔
314
        minBlockSize_ = *(min_element(blockSizes.begin(), blockSizes.end()));
16✔
315
}
16✔
316

317

318
std::string dna_segment::DefaultStartingStation()
22✔
319
{
320
        if (vfreeStnList_.empty())
22✔
321
                return "";
×
322
        if (bstBinaryRecords_.empty())
22✔
323
                return "";
×
324
        return bstBinaryRecords_.at(vfreeStnList_.at(0)).stationName;
22✔
325
}
326
        
327

328
vstring dna_segment::StartingStations()
16✔
329
{
330
        return vinitialStns_;
16✔
331
}
332
        
333

334
// throws NetSegmentException on failure
335
void dna_segment::BuildFirstBlock()
16✔
336
{        
337
        vCurrJunctStnList_.clear();
16✔
338
        vCurrInnerStnList_.clear();
16✔
339
        vCurrMeasurementList_.clear();
16✔
340

341
        if (vinitialStns_.empty())
16✔
342
                // no station specified? then pick the first one on the free list
343
                // Remember, vfreeStnList_ is not sorted alphabetically, but according
344
                // to the number of measurements connected to each station
345
                vinitialStns_.push_back(bstBinaryRecords_.at(vfreeStnList_.at(0)).stationName);
33✔
346
        else        
347
                RemoveDuplicateStations(&vinitialStns_);                // remove duplicates
5✔
348
        
349
        // First pass to validate stations
350
        VerifyStationsandBuildBlock(true);
16✔
351

352
        // Second pass to build the block
353
        VerifyStationsandBuildBlock();
16✔
354

355
        FinaliseBlock();
16✔
356
}
16✔
357

358
void dna_segment::VerifyStationsandBuildBlock(bool validationOnly)
32✔
359
{
360
#ifdef _MSDEBUG
361
        UINT32 stn_index;
362
#endif
363

364
        it_vUINT32 _it_freeisl;
32✔
365
        _it_vstr_const _it_name(vinitialStns_.begin());
32✔
366
        it_pair_string_vUINT32 it_stnmap_range;
32✔
367
        v_string_uint32_pair::iterator _it_stnmap(stnsMap_.begin());
32✔
368

369
        // For each station name specified as the initial stations
370
        for (_it_name=vinitialStns_.begin(); _it_name!=vinitialStns_.end(); ++_it_name)
66✔
371
        {
372
                // Retrieve the ASL index
373
                it_stnmap_range = equal_range(stnsMap_.begin(), stnsMap_.end(), *_it_name, StationNameIDCompareName());
34✔
374
                
375
                if (it_stnmap_range.first == it_stnmap_range.second)
34✔
376
                {
377
                        // If this point is reached, _it_stnmap->second is not a known network station
NEW
378
                        std::stringstream ss;
×
379
                        ss << "VerifyStationsandBuildBlock(): " << *_it_name << " is not in the list of network stations.";
×
380
                        SignalExceptionSerialise(ss.str(), 0, NULL);
×
381
                }
×
382

383
                _it_stnmap = it_stnmap_range.first;
34✔
384

385
#ifdef _MSDEBUG
386
                stn_index = _it_stnmap->second;
387
#endif
388
                // add this station to inner station list if it is on the free stations list only.
389
                // vfreeStnList_ is sorted according to the number of measurements connected to each station
390
                // hence, a binary_search (or lower_bound or similar) cannot be used here
391

392
                // Check if this station is available before trying to find it.  Why?
393
                // find_if over a large vector is not fast like binary_search
394
                if (vfreeStnAvailability_.at(_it_stnmap->second).isfree())
34✔
395
                {                        
396
                        // Ok, find it and remove it
397
                        //if ((_it_freeisl = find_if(vfreeStnList_.begin(), vfreeStnList_.end(),
398
                        //        bind1st(std::equal_to<UINT32>(), _it_stnmap->second))) != vfreeStnList_.end())
399
                        if ((_it_freeisl = find_if(vfreeStnList_.begin(), vfreeStnList_.end(),
34✔
400
                                [&_it_stnmap](const UINT32& freeStn) {
172✔
401
                                        return freeStn == _it_stnmap->second; } )) != vfreeStnList_.end())
99✔
402
                        {
403
                                if (!validationOnly)
34✔
404
                                        MoveFreeStnToInnerList(_it_freeisl, _it_stnmap->second);
17✔
405
                        }
406
                }
407
                else
408
                {
409
                        if (validationOnly)
×
410
                        {
411
                                // If this point is reached, _it_stnmap->second is a known network station but is 
412
                                // invalid or has no measurements connected to it.
NEW
413
                                std::stringstream ss;
×
414
                                ss << "VerifyStationsandBuildBlock(): " << bstBinaryRecords_.at(_it_stnmap->second).stationName << " does not have any measurements connected to it.";
×
415
                                SignalExceptionSerialise(ss.str(), 0, NULL);
×
416
                        }
×
417
                }
418
        
419
                if (!validationOnly)
17✔
420
                        // Retrieve JSL (all stations connected to this station) and
421
                        // add AML indices to CML for all measurements connected to this station
422
                        GetInnerMeasurements(_it_stnmap->second);
17✔
423
        }
424
}
32✔
425

426
UINT32 dna_segment::SelectInner()
735✔
427
{
428
        // Sort the list of junction stations by the number of measurements 
429
        // connected to them, and begin with the station that has the lowest 
430
        // number of measurements
431
        SortbyMeasurementCount(&vCurrJunctStnList_);
735✔
432
        
433
        it_vUINT32 it_currjsl(vCurrJunctStnList_.begin());
735✔
434
        UINT32 stn_index = *it_currjsl;
735✔
435

436
        if (debug_level_ > 2)
735✔
437
                trace_file << " + Inner '" << bstBinaryRecords_.at(stn_index).stationName << "'" << std::endl;
191✔
438

439
#ifdef _MSDEBUG
440
        std::string station_name =  bstBinaryRecords_.at(stn_index).stationName;
441
#endif
442

443
        // add this junction station to inner station list
444
        MoveStation(vCurrJunctStnList_, it_currjsl, vCurrInnerStnList_, stn_index);
735✔
445

446
        return stn_index;
735✔
447
}
448
        
449

450
// Get the next free station and push it to the junction list
451
// This method should only be reached when the junction list is empty,
452
// but measurements still remain and stations exist in the free list.
453
void dna_segment::SelectJunction()
8✔
454
{
455
        SortbyMeasurementCount(&vfreeStnList_);
8✔
456
        
457
        it_vUINT32 it_newjsl(vfreeStnList_.begin());
8✔
458

459
        MoveFreeStnToJunctionList(it_newjsl, *it_newjsl);
8✔
460
}
8✔
461

462

463
it_vUINT32 dna_segment::MoveStation(vUINT32& fromList, it_vUINT32 it_from, vUINT32& toList, const UINT32& stn_index)
1,795✔
464
{
465
        // Move a station from one list to another list
466
        toList.push_back(stn_index);        
1,795✔
467
        return fromList.erase(it_from);
1,795✔
468
}
469
        
470

471
void dna_segment::MoveFreeStn(it_vUINT32 it_freeisl, vUINT32& toList, const UINT32& stn_index, const std::string& type)
906✔
472
{
473
        if (debug_level_ > 2)
906✔
474
                trace_file << " + New " << type << " station (" << stn_index << ") '" << 
249✔
475
                        bstBinaryRecords_.at(stn_index).stationName << "'" << std::endl;
249✔
476
        
477
#ifdef _MSDEBUG
478
        std::string station_name =  bstBinaryRecords_.at(stn_index).stationName;
479
#endif
480

481
        // Mark this station as unavailable
482
        vfreeStnAvailability_.at(stn_index).consume();
906✔
483

484
        // Move a station from the free station list to the specified list
485
        // stnList may be either inner or junction list
486
        MoveStation(vfreeStnList_, it_freeisl, toList, stn_index);
906✔
487
}
906✔
488
        
489

490
void dna_segment::MoveFreeStnToJunctionList(it_vUINT32 it_freeisl, const UINT32& stn_index)
889✔
491
{
492
        // Move a station from the free station list to the junction list
493
        MoveFreeStn(it_freeisl, vCurrJunctStnList_, stn_index, "junction");        
1,778✔
494
}
889✔
495
        
496

497
void dna_segment::MoveFreeStnToInnerList(it_vUINT32 it_freeisl, const UINT32& stn_index)
17✔
498
{
499
        // Move a station from the free station list to the junction list
500
        MoveFreeStn(it_freeisl, vCurrInnerStnList_, stn_index, "inner");
34✔
501
}
17✔
502
        
503

504
// throws NetSegmentException on failure
505
void dna_segment::BuildNextBlock()
30✔
506
{
507
        // vCurrJunctStnList_ carries the previous block's junction stations. Thus,
508
        // don't clear it as these stations will become the inners for the next block
509
        vCurrInnerStnList_.clear();
30✔
510
        vCurrMeasurementList_.clear();
30✔
511

512
#ifdef _MSDEBUG
513
        std::string station_name;
514
#endif
515

516
        // Select a new junction station if there are none on the JSL
517
        // that have free measurements left
518
        if (vCurrJunctStnList_.empty() && !vfreeStnList_.empty())
30✔
519
        {
520
                if (!projectSettings_.s.force_contiguous_blocks)
5✔
521
                        v_ContiguousNetList_.back() = ++currentNetwork_;
4✔
522

523
                if (debug_level_ > 1)
5✔
524
                {
525
                        debug_file << "+ Non-contiguous block found... creating a new block using " << bstBinaryRecords_.at(vfreeStnList_.at(0)).stationName << std::endl;
3✔
526
                        if (debug_level_ > 2)
3✔
527
                                trace_file << " + Non-contiguous block found... creating a new block using " << bstBinaryRecords_.at(vfreeStnList_.at(0)).stationName << std::endl;
3✔
528
                }
529

530
                // Select a new junction from the free station list
531
                SelectJunction();
5✔
532
        }
533
        
534
        if (vCurrJunctStnList_.empty())
30✔
535
        {
536
                coutSummary();
×
537
                SignalExceptionSerialise("BuildNextBlock(): An invalid junction list has been created.  This is most likely a bug.", 0, NULL);
×
538
        }
539

540
        UINT32 stn_index;
541
        UINT32 currentTotalSize;
542
        bool block_threshold_reached = false;
749✔
543

544
        // Until the threshold is reached...
545
        //  - Go through the list of junction stations (copied from the previous block) and
546
        //    make them inner stations if there are new stations connected to them
547
        //  - If the list is exhausted, add new junctions
548
        while (!block_threshold_reached)
749✔
549
        {
550
                // Attempt to add non-contiguous blocks to this block if the 
551
                // station limit hasn't been reached
552
                if (vfreeStnList_.empty() /*|| vfreeMsrList_.empty()*/)
749✔
553
                        break;
554

555
                // Is the junction list empty?  force_contiguous_blocks determines what to 
556
                // do in this instance.
557
                if (projectSettings_.s.force_contiguous_blocks)
737✔
558
                {
559
                        // Add non-contiguous blocks to this block if the 
560
                        // station limit hasn't been reached
561
                        if (vCurrJunctStnList_.empty())
669✔
562
                                SelectJunction();
3✔
563
                }
564
                else if (vCurrJunctStnList_.empty())
68✔
565
                        break;
566

567
                // Get next station from current junction list
568
                stn_index = SelectInner();
735✔
569

570
                // Retrieve JSL (all stations connected to this station) and
571
                // add AML indices to CML for all measurements connected to this station
572
                GetInnerMeasurements(stn_index);
735✔
573

574
                currentTotalSize = static_cast<UINT32>(vCurrInnerStnList_.size() + vCurrJunctStnList_.size());
735✔
575

576
                // Has the station count threshold been exceeded?
577
                //if (currentTotalSize >= seg_max_total_stations_)
578
                if (currentTotalSize >= projectSettings_.s.max_total_stations)
735✔
579
                {
580
                        if (vCurrInnerStnList_.size() < projectSettings_.s.min_inner_stations)
75✔
581
                                continue;
59✔
582
                        block_threshold_reached = true;
583
                        break;
584
                }
585
        }
586

587
        if (debug_level_ > 2)
30✔
588
        {
589
                if (block_threshold_reached)
12✔
590
                        trace_file << " + Block size threshold exceeded... finishing block." << std::endl;
10✔
591
                else
592
                        trace_file << " + Block " << currentBlock_ << " complete." << std::endl;
2✔
593
        }
594

595
        FinaliseBlock();
30✔
596
}
30✔
597
        
598
void dna_segment::FinaliseBlock()
46✔
599
{
600
        FindCommonMeasurements();
46✔
601
        MoveJunctiontoISL();
46✔
602

603
        // Sort lists
604
        std::sort(vCurrInnerStnList_.begin(), vCurrInnerStnList_.end());
46✔
605
        std::sort(vCurrJunctStnList_.begin(), vCurrJunctStnList_.end());
46✔
606
        strip_duplicates(vCurrMeasurementList_);                // remove duplicates and sort
46✔
607

608
        vISL_.push_back(vCurrInnerStnList_);
46✔
609
        vJSL_.push_back(vCurrJunctStnList_);
46✔
610
        vCML_.push_back(vCurrMeasurementList_);
46✔
611

612
        if (debug_level_ > 1)
46✔
613
        {
614
                coutCurrentBlockSummary(debug_file);
17✔
615

616
                if (debug_level_ > 2)
17✔
617
                {
618
                        UINT32 currentISLSize, currentJSLSize, currentTotalSize, currentMsrSize;
17✔
619
                        currentISLSize = static_cast<UINT32>(vCurrInnerStnList_.size());
17✔
620
                        currentJSLSize = static_cast<UINT32>(vCurrJunctStnList_.size());
17✔
621
                        currentTotalSize = currentISLSize + currentJSLSize;
17✔
622
                        currentMsrSize = static_cast<UINT32>(vCurrMeasurementList_.size());
17✔
623
                
624
                        trace_file << " + Done." << std::endl;
17✔
625
                        trace_file << " + BLOCK " << currentBlock_ << " SUMMARY:" << std::endl;
17✔
626
                        trace_file << "   - " << currentISLSize << " inner stations, " << currentJSLSize << " junction stations, ";
17✔
627
                        trace_file << currentTotalSize << " total stations, " << currentMsrSize << " measurements." << std::endl;
17✔
628
                
629
                        trace_file << "   - Inners (" << currentISLSize << "):" << std::endl << "     ";
17✔
630
                        it_vUINT32_const _it_freeisl(vfreeStnList_.end());
17✔
631
                        for (_it_freeisl=vCurrInnerStnList_.begin(); _it_freeisl!=vCurrInnerStnList_.end(); ++_it_freeisl)
266✔
632
                                trace_file << "'" << bstBinaryRecords_.at(*_it_freeisl).stationName << "' ";
249✔
633
                        trace_file << std::endl;
17✔
634

635
                        trace_file << "   - Junctions (" << currentJSLSize << "):" << std::endl << "     ";
17✔
636
                        for (_it_freeisl=vCurrJunctStnList_.begin(); _it_freeisl!=vCurrJunctStnList_.end(); ++_it_freeisl)
57✔
637
                                trace_file << "'" << bstBinaryRecords_.at(*_it_freeisl).stationName << "' ";
40✔
638
                
639
                        trace_file << std::endl << " + ------------------------------------------" << std::endl;
17✔
640
                }
641
        }
642
}
46✔
643
        
644

645
//bool dna_segment::IncrementNextAvailableAMLIndex(UINT32& amlIndex, const UINT32& lastamlIndex)
646
//{
647
//        // Already at the last measurement?
648
//        if (amlIndex > lastamlIndex)
649
//                return false;
650
//
651
//        while (!vAssocFreeMsrList_.at(amlIndex).available)
652
//        {
653
//                // Already at the last measurement?
654
//                if (amlIndex == lastamlIndex)
655
//                        return false;
656
//
657
//                // Get the next measurement record tied 
658
//                // to this measurement
659
//                ++amlIndex;                        
660
//        }
661
//        return true;
662
//}
663
//        
664
//
665
//bool dna_segment::IncrementNextAvailableAMLIndex(it_aml_pair& _it_aml, const it_aml_pair& _it_lastaml)
666
//{
667
//        // Already at the last measurement?
668
//        if (_it_aml > _it_lastaml)
669
//                return false;
670
//
671
//        while (!_it_aml->available)
672
//        {
673
//                // Already at the last measurement?
674
//                if (_it_aml == _it_lastaml)
675
//                        return false;
676
//
677
//                // Get the next measurement record tied 
678
//                // to this measurement
679
//                ++_it_aml;                        
680
//        }
681
//        return true;
682
//}
683
        
684

685
// Name:                                GetInnerMeasurements
686
// Purpose:                                Gets all measurements tied to the subject station (innerStation) and stations tied to
687
//                      those measurements
688
// Called by:                        BuildFirstBlock(), BuildNextBlock()
689
// Calls:                                AddtoCurrentMsrList(), AddtoJunctionStnList()
690
void dna_segment::GetInnerMeasurements(const UINT32& innerStation)
752✔
691
{
692
        if (debug_level_ > 2)
752✔
693
                trace_file << " + GetInnerMeasurements()" << std::endl;
197✔
694
                
695
#ifdef _MSDEBUG
696
        std::string from, to, to2;
697
#endif
698

699
        measurement_t measRecord;
752✔
700
        vUINT32 msrStations;
752✔
701

702
        // Get the original measurement count
703
        UINT32 m, msrCount(vASLCount_.at(innerStation));
752✔
704
        // Get the aml index, initialised to the last measurement for this station
705
        UINT32 amlIndex(
752✔
706
                vAssocStnList_.at(innerStation).GetAMLStnIndex()        // beginning of the measurements associated with this station
752✔
707
                + msrCount - 1);                                                                        // the number of associated measurements
752✔
708

709
        for (m=0; m<msrCount; ++m, --amlIndex)
10,459✔
710
        {
711
                // is this measurement ignored or already used?
712
                if (!vAssocFreeMsrList_.at(amlIndex).available)
9,707✔
713
                        continue;
5,457✔
714
                
715
                measRecord = bmsBinaryRecords_.at(vAssocFreeMsrList_.at(amlIndex).bmsr_index);
4,250✔
716

717
                if (measRecord.ignore)
4,250✔
718
                        continue;
×
719

720
#ifdef _MSDEBUG
721
                from = bstBinaryRecords_.at(measRecord.station1).stationName;
722
                if (MsrTally::Stations(measRecord.measType) >= TWO_STATION)
723
                {
724
                        to = bstBinaryRecords_.at(measRecord.station2).stationName;
725
                        if (MsrTally::Stations(measRecord.measType) == THREE_STATION)
726
                                to2 = bstBinaryRecords_.at(measRecord.station3).stationName;
727
                }
728
#endif
729

730
                // When a non-measurement element is found (i.e. Y or Z or covariance component),
731
                // continue to next element.  Hence, only pointers to the starting element of each
732
                // measurement are kept. See declaration of measRecord.measStart for more info.
733
                switch (measRecord.measType)
4,250✔
734
                {
735
                case 'G':
656✔
736
                case 'X':
656✔
737
                case 'Y':
656✔
738
                        if (measRecord.measStart != xMeas)
656✔
739
                                continue;
×
740
                }                
741

742
                // Get all the stations associated with this measurement
743
                GetMsrStations(bmsBinaryRecords_, vAssocFreeMsrList_.at(amlIndex).bmsr_index, msrStations);
4,250✔
744

745
                // Add this measurement to the current measurement list
746
                AddtoCurrentMsrList(amlIndex, msrStations);
4,250✔
747

748
                // if this station is not on JSL, move it from the freestnlist to JSL
749
                AddtoJunctionStnList(msrStations);
4,250✔
750
        }
751
}
752✔
752

753
// If this measurement is "available", then:
754
//        - consume this measurement and all other occurences of it on the AML
755
//        - add this measurement to the current list of measurements for this block.
756
bool dna_segment::AddtoCurrentMsrList(const UINT32& amlIndex, const vUINT32& msrStations)
5,528✔
757
{
758
        if (!vAssocFreeMsrList_.at(amlIndex).available)
5,528✔
759
                return false;
760
        
761
        UINT32 m, msrCount, bmsrindex(vAssocFreeMsrList_.at(amlIndex).bmsr_index);
5,528✔
762

763
#ifdef _MSDEBUG
764
        measurement_t msr(bmsBinaryRecords_.at(bmsrindex));
765
        char measType(msr.measType);
766
        std::string station;
767
        UINT32 stn_index;
768
#endif
769

770
        UINT32 firstIndex(GetFirstMsrIndex<UINT32>(bmsBinaryRecords_, bmsrindex));
5,528✔
771

772
        // Add the index of the first binary measurement record to the measurement list
773
        vCurrMeasurementList_.push_back(firstIndex);
5,528✔
774

775
        if (debug_level_ > 2)
5,528✔
776
        {
777
                trace_file << "   - Measurement '" << bmsBinaryRecords_.at(bmsrindex).measType << "' ";
1,511✔
778
                if (bmsBinaryRecords_.at(bmsrindex).ignore)
1,511✔
779
                        trace_file << "(ignored) ";
×
780
                trace_file << "associated with station(s): ";
1,511✔
781
        }
782

783
        it_aml_pair _it_aml;
5,528✔
784
        it_vUINT32_const _it_stn, _it_msr;
5,528✔
785
        
786
        // 1) consume each occurrence of this measurement (and all other
787
        //          measurements within a cluster) on the AML, then
788
        // 2) Decrement the measurement count for all stations associated 
789
        //          with this measurement.
790
        for (_it_stn=msrStations.begin(); _it_stn!=msrStations.end(); ++_it_stn)
17,727✔
791
        {
792
                // Consume the occurrences of this measurement (and other measurements in a cluster)
793
                // in the aml for the stations in msrStations
794

795
#ifdef _MSDEBUG
796
                stn_index = *_it_stn;
797
                station = bstBinaryRecords_.at(*_it_stn).stationName;
798
#endif
799

800
                if (debug_level_ > 2)
12,199✔
801
                        trace_file << bstBinaryRecords_.at(*_it_stn).stationName << " ";
3,359✔
802
        
803
                // set _it_aml to point to the first aml entry for station *_it_stn
804
                _it_aml = vAssocFreeMsrList_.begin() + vAssocStnList_.at(*_it_stn).GetAMLStnIndex();
12,199✔
805
                msrCount = vASLCount_.at(*_it_stn);
12,199✔
806
                
807
                // consume measurement and decrement measurement count
808
                for (m=0; m<msrCount; ++m, ++_it_aml)
131,962✔
809
                {
810
                        // is this measurement ignored or already used?
811
                        if (!_it_aml->available)
131,962✔
812
                                continue;
58,148✔
813
                        
814
                        if (_it_aml->bmsr_index == bmsrindex)
73,814✔
815
                        {
816
                                // Consume the measurement
817
                                _it_aml->consume();
12,199✔
818

819
                                // Decrement the measurement count.
820
                                vAssocStnList_.at(*_it_stn).DecrementMsrCount();
24,398✔
821
                                break;
822
                        }
823
                }
824
        }        
825

826
        if (debug_level_ > 2)
5,528✔
827
                trace_file << std::endl;
1,511✔
828

829
        return true;
830
}
831
        
832

833
// Name:                                FindCommonMeasurements
834
// Purpose:                                Gets all measurements tied only to junction stations.
835
//                                                Measurements between two inners, and between an inner
836
//                      and a junction are captured by GetInnerMeasurements()
837
// Called by:                        BuildFirstBlock(), BuildNextBlock()
838
void dna_segment::FindCommonMeasurements()
46✔
839
{
840
        // Create a temporary vector
841
        vUINT32 vCurrBlockStnList(vCurrJunctStnList_), msrStations;
46✔
842
        
843
        std::sort(vCurrBlockStnList.begin(), vCurrBlockStnList.end());
46✔
844

845
        it_vUINT32 _it_stn, _it_mstn;
46✔
846
        measurement_t measRecord;
46✔
847
        bool inList;
46✔
848

849
        if (debug_level_ > 2)
46✔
850
                trace_file << " + FindCommonMeasurements()" << std::endl;
17✔
851

852
#ifdef _MSDEBUG
853
        std::string stn;
854
#endif
855

856
        UINT32 m, msrCount, amlIndex;
46✔
857

858
        for (_it_stn=vCurrBlockStnList.begin(); _it_stn!=vCurrBlockStnList.end(); ++_it_stn)
314✔
859
        {
860
                // Get the original measurement count
861
                msrCount = vASLCount_.at(*_it_stn);
268✔
862
                amlIndex = vAssocStnList_.at(*_it_stn).GetAMLStnIndex();
268✔
863

864
#ifdef _MSDEBUG
865
                stn = bstBinaryRecords_.at(*_it_stn).stationName;
866
#endif
867

868
                for (m=0; m<msrCount; ++m, ++amlIndex)
5,608✔
869
                {
870
                        // is this measurement ignored or already used?
871
                        if (!vAssocFreeMsrList_.at(amlIndex).available)
5,340✔
872
                                continue;
3,133✔
873
                        
874
                        measRecord = bmsBinaryRecords_.at(vAssocFreeMsrList_.at(amlIndex).bmsr_index);
2,207✔
875

876
                        if (measRecord.ignore)
2,207✔
877
                                continue;
×
878

879
                        // Get all the stations associated with this measurement
880
                        GetMsrStations(bmsBinaryRecords_, vAssocFreeMsrList_.at(amlIndex).bmsr_index, msrStations);
2,207✔
881

882
                        // Since a single station measurement is not associated with other stations,
883
                        // add the measurement to the list
884
                        if (msrStations.size() == 1)
2,207✔
885
                        {
886
                                // Add this measurement to the current measurement list
887
                                AddtoCurrentMsrList(amlIndex, msrStations);
88✔
888
                                continue;
88✔
889
                        }
890
                        
891
                        // Assume this measurement is common to the stations on vCurrBlockStnList.
892
                        // inList will be set to false if a measurement station is not found on 
893
                        // the list
894
                        inList = true;
2,119✔
895
                        
896
                        // Two or more station measurements
897
                        for (_it_mstn=msrStations.begin(); _it_mstn!=msrStations.end(); ++_it_mstn)
5,165✔
898
                        {
899
                                // If one station in msrStations (which are all stations 
900
                                // associated with the current measurement) is not in the junction list,
901
                                // then this cannot be a "common measurement".
902
                                if (!binary_search(vCurrBlockStnList.begin(), vCurrBlockStnList.end(), *_it_mstn))
3,975✔
903
                                {
904
                                        // The station at _it_mstn is not in vCurrBlockStnList, so this is not a
905
                                        // "common measurement" - break out of loop.
906
                                        inList = false;
907
                                        break;
908
                                }
909
                        }
910
                
911
                        // If all stations in msrStations are found within vCurrBlockStnList, then
912
                        // add this measurement to the current measurement list
913
                        if (inList)
2,119✔
914
                                AddtoCurrentMsrList(amlIndex, msrStations);
1,190✔
915
                }
916
        }
917
}
46✔
918

919
UINT32 dna_segment::GetAvailableMsrCount(const UINT32& stn_index)
272✔
920
{
921
        return vAssocStnList_.at(stn_index).GetAvailMsrCount();
272✔
922
}
923

924

925
// Name:                                MoveJunctiontoISL
926
// Purpose:                                Moves stations on the inner list to the junction list.  The
927
//                                                condition for moving a station is that there are no more
928
//                                                available measurements connected to the junction station.
929
// Called by:                        BuildFirstBlock(), BuildNextBlock()
930
// Calls:                                
931
void dna_segment::MoveJunctiontoISL()
46✔
932
{
933
        // Move stations on the current junction station list to the inner station list if
934
        // there are no more measurements tied to this station
935
        if (debug_level_ > 2)
46✔
936
                trace_file << " + MoveJunctiontoISL()" << std::endl;        
17✔
937
        
938
#ifdef _MSDEBUG
939
        std::string station_name;
940
#endif
941

942
        it_vUINT32 _it_currjsl(vCurrJunctStnList_.begin());
46✔
943
        UINT32 stn_index;
46✔
944

945
        while (!vCurrJunctStnList_.empty())
274✔
946
        {
947
                stn_index = *_it_currjsl;
272✔
948

949
#ifdef _MSDEBUG                
950
                station_name = bstBinaryRecords_.at(stn_index).stationName;
951
#endif
952

953
                // Are there no more available measurements connected to this station?
954
                if (GetAvailableMsrCount(stn_index) == 0)
272✔
955
                {
956
                        if (debug_level_ > 2)
154✔
957
                                trace_file << "   - Junction station '" << 
52✔
958
                                        bstBinaryRecords_.at(static_cast<UINT32>(stn_index)).stationName << 
52✔
959
                                        "' was moved to inner list (no more available measurements)." << std::endl;
104✔
960

961
                        // Move this station from the junctions list to inners list
962
                        _it_currjsl = MoveStation(vCurrJunctStnList_, _it_currjsl, 
154✔
963
                                vCurrInnerStnList_, stn_index);
154✔
964

965
                        // Have all JSLs been removed?
966
                        if (vCurrJunctStnList_.empty())
154✔
967
                                // end the while loop
968
                                break;
969
                        else if (_it_currjsl == vCurrJunctStnList_.end())
135✔
970
                                // reset the iterator to the previous junction station
971
                                --_it_currjsl;
4✔
972

973
                        continue;
135✔
974
                }
975
                
976
                // move to the next junction, unless the iterator is 
977
                // pointing to the last
978
                if (++_it_currjsl == vCurrJunctStnList_.end())
118✔
979
                        break;
980
        }
981
}
46✔
982

983
void dna_segment::AddtoJunctionStnList(const vUINT32& msrStations)
4,250✔
984
{
985
        it_vUINT32_const _it_stn;
4,250✔
986
        it_vUINT32 _it_freeisl;
4,250✔
987
        for (_it_stn=msrStations.begin(); _it_stn!=msrStations.end(); ++_it_stn)
13,766✔
988
        {
989
                // If First station is not already in the junction list...
990
                //if (find_if(vCurrJunctStnList_.begin(), vCurrJunctStnList_.end(),
991
                //        bind1st(equal_to<UINT32>(), *_it_stn)) == vCurrJunctStnList_.end())
992
                if (find_if(vCurrJunctStnList_.begin(), vCurrJunctStnList_.end(),
9,516✔
993
                        [&_it_stn](const UINT32& junctionStn) {
97,319✔
994
                                return junctionStn == *_it_stn; }) == vCurrJunctStnList_.end())
42,501✔
995
                {
996
                        // If the first station is available, get an iterator to it and move it
997
                        if (vfreeStnAvailability_.at(*_it_stn).isfree())
5,131✔
998
                        {
999
                                // Move it to the list of junctions
1000
                                //if ((_it_freeisl = find_if(vfreeStnList_.begin(), vfreeStnList_.end(),
1001
                                //        bind1st(equal_to<UINT32>(), *_it_stn))) != vfreeStnList_.end())
1002
                                if ((_it_freeisl = find_if(vfreeStnList_.begin(), vfreeStnList_.end(),
881✔
1003
                                        [&_it_stn](const UINT32& freeStn) {
22,327✔
1004
                                                return freeStn == *_it_stn; })) != vfreeStnList_.end())
6,922✔
1005
                                {
1006
                                        MoveFreeStnToJunctionList(_it_freeisl, *_it_stn);
881✔
1007
                                }
1008
                        }
1009
                }
1010
        }
1011
}
4,250✔
1012

1013

1014
// Name:                                SignalExceptionSerialise
1015
// Purpose:                                Closes all files (if file pointers are passed in) and throws NetSegmentException
1016
// Called by:                        Any
1017
// Calls:                                NetSegmentException()
1018
void dna_segment::SignalExceptionSerialise(const std::string& msg, const int& i, const char *streamType, ...)
1✔
1019
{
1020
        isProcessing_ = false;
1✔
1021
        segmentStatus_ = SEGMENT_EXCEPTION_RAISED;
1✔
1022

1023
        if (debug_level_ > 1)
1✔
1024
                if (debug_file.is_open())
1✔
1025
                        debug_file.close();
×
1026

1027
        if (debug_level_ > 2)
1✔
1028
                if (trace_file.is_open())
1✔
1029
                        trace_file.close();
×
1030

1031
        if (streamType == NULL)
1✔
1032
                throw NetSegmentException(msg, i);
1✔
1033
        
1034
        std::ofstream* ofsDynaML;
×
1035
        std::ifstream* ifsbinaryFile;
×
1036

1037
        va_list argptr; 
×
1038
        va_start(argptr, streamType);
×
1039

1040
        while (*streamType != '\0')
×
1041
        {
1042
                //ifstream
1043
                if (*streamType == 'i' )
×
1044
                {
1045
                        ifsbinaryFile = va_arg(argptr, std::ifstream*);
×
1046
                        ifsbinaryFile->close();
×
1047
                }
1048
                //ofstream
1049
                if (*streamType == 'o' )
×
1050
                {
1051
                        ofsDynaML = va_arg(argptr, std::ofstream*);
×
1052
                        ofsDynaML->close();
×
1053
                }
1054
                streamType++;
×
1055
        }
1056

1057
        va_end(argptr);
×
1058

1059
        throw NetSegmentException(msg, i);
×
1060
}
1061

1062
void dna_segment::LoadAssociationFiles(const std::string& aslfileName, const std::string& amlfileName)
16✔
1063
{
1064
        UINT32 stn, stnCount(0);
16✔
1065
        
1066
        try {
16✔
1067
                dna_io_asl asl;
16✔
1068
                stnCount = asl.load_asl_file(aslfileName, &vAssocStnList_, &vfreeStnList_);
16✔
1069
        }
16✔
NEW
1070
        catch (const std::runtime_error& e) {
×
1071
                SignalExceptionSerialise(e.what(), 0, NULL);
×
1072
        }
×
1073

1074
        // Dertmine original measurement count for each station
1075
        vASLCount_.clear();
16✔
1076
        vASLCount_.resize(stnCount);
16✔
1077
        
1078
        _it_vasl _it_asl;
16✔
1079
        for (stn=0, _it_asl=vAssocStnList_.begin();
16✔
1080
                _it_asl!=vAssocStnList_.end();
949✔
1081
                ++_it_asl, ++stn)
933✔
1082
        {
1083
                vASLCount_.at(stn) = _it_asl->GetAssocMsrCount();                // original measurement count
933✔
1084
        }
1085

1086
        // remove stations from the free list that are invalid
1087
        RemoveInvalidFreeStations();
16✔
1088

1089
        // Load associated measurements list.  Throws runtime_error on failure.
1090
        try {
16✔
1091
                dna_io_aml aml;
16✔
1092
                aml.load_aml_file(amlfileName, &vAssocFreeMsrList_, &bmsBinaryRecords_);
16✔
1093
        }
16✔
NEW
1094
        catch (const std::runtime_error& e) {
×
1095
                SignalExceptionSerialise(e.what(), 0, NULL);
×
1096
        }
×
1097

1098
        // set available msr count
1099
        SetAvailableMsrCount();
16✔
1100
}
16✔
1101

1102
        
1103
void dna_segment::LoadStationMap(const std::string& stnmap_file)
16✔
1104
{
1105
        try {
16✔
1106
                dna_io_map map;
16✔
1107
                map.load_map_file(stnmap_file, &stnsMap_);
16✔
1108
        }
16✔
NEW
1109
        catch (const std::runtime_error& e) {
×
1110
                SignalExceptionSerialise(e.what(), 0, NULL);
×
1111
        }
×
1112
}
16✔
1113

1114
void dna_segment::LoadBinaryFiles(const std::string& bstrfileName, const std::string& bmsrfileName)
17✔
1115
{
1116
        binary_file_meta_t        bst_meta_, bms_meta_;
17✔
1117
        try {
17✔
1118
                // Load binary stations data.  Throws runtime_error on failure.
1119
                dna_io_bst bst;
17✔
1120
                bst.load_bst_file(bstrfileName, &bstBinaryRecords_, bst_meta_);
17✔
1121
        
1122
                // Load binary measurements data.  Throws runtime_error on failure.
1123
                dna_io_bms bms;
17✔
1124
                bms.load_bms_file(bmsrfileName, &bmsBinaryRecords_, bms_meta_);
17✔
1125
        }
17✔
NEW
1126
        catch (const std::runtime_error& e) {
×
1127
                SignalExceptionSerialise(e.what(), 0, NULL);
×
1128
        }
×
1129
        
1130
        // Update the Cluster comparison functor with the AML binary vector
1131
        clusteridCompareFunc_.SetAMLPointer(const_cast<pvmsr_t>(&bmsBinaryRecords_));
17✔
1132

1133
        // count the number of measurements not ignored
1134
        MsrTally msrTally;
17✔
1135
        UINT32 m = msrTally.CreateTally(bmsBinaryRecords_, true);
17✔
1136

1137
        // throw an exception if no measurements are available        
1138
        if (m == 0)
17✔
1139
        {
1140
                std::stringstream ss;
1✔
1141
                ss << "No measurements were found." << std::endl << 
1✔
1142
                        "  If measurements were successfully loaded on import, ensure that\n  all measurements have not been ignored." << std::endl;
1✔
1143
                SignalExceptionSerialise(ss.str(), 0, NULL);
2✔
1144
        }
1✔
1145
}
33✔
1146
        
1147

1148
void dna_segment::IdentifyInnerMsrsandAssociatedStns(const UINT32& innerStation, vUINT32& totalStations)
666✔
1149
{
1150
        it_vmsr_t measRecord;
666✔
1151
        vUINT32 msrStations;
666✔
1152
        
1153
        // Get the original measurement count
1154
        UINT32 m, msrCount(vASLCount_.at(innerStation));
666✔
1155
        // Get the aml index, initialised to the last measurement for this station
1156
        UINT32 amlIndex(
666✔
1157
                vAssocStnList_.at(innerStation).GetAMLStnIndex()        // beginning of the measurements associated with this station
666✔
1158
                + msrCount - 1);                                                                        // the number of associated measurements
666✔
1159

1160
        for (m=0; m<msrCount; ++m, --amlIndex)
12,844✔
1161
        {
1162
                // is this measurement ignored or already used?
1163
                if (!vAssocFreeMsrList_.at(amlIndex).available)
12,178✔
1164
                        continue;
4,522✔
1165
                
1166
                measRecord = bmsBinaryRecords_.begin() + vAssocFreeMsrList_.at(amlIndex).bmsr_index;
7,656✔
1167

1168
                if (measRecord->ignore)
7,656✔
1169
                        continue;
×
1170

1171
                // When a non-measurement element is found (i.e. Y or Z or covariance component),
1172
                // continue to next element.  Hence, only pointers to the starting element of each
1173
                // measurement are kept. See declaration of measRecord.measStart for more info.
1174
                switch (measRecord->measType)
7,656✔
1175
                {
1176
                case 'G':
2,650✔
1177
                case 'X':
2,650✔
1178
                case 'Y':
2,650✔
1179
                        if (measRecord->measStart != xMeas)
2,650✔
1180
                                continue;
×
1181
                }
1182

1183
                // Get all the stations associated with this measurement
1184
                GetMsrStations(bmsBinaryRecords_, vAssocFreeMsrList_.at(amlIndex).bmsr_index, msrStations);
7,656✔
1185

1186
                totalStations.insert(totalStations.end(), msrStations.begin(), msrStations.end());
7,656✔
1187
        }
1188

1189
        strip_duplicates(totalStations);
666✔
1190
}
666✔
1191

1192
void dna_segment::IdentifyLowestStationAssociation(pvUINT32 vStnList, vUINT32& totalStations, const int currentLevel, const int maxLevel, pvUINT32 vStnCount)
102✔
1193
{
1194
        it_vUINT32 it_stn;
102✔
1195
        vUINT32 msrStations, subStations;
102✔
1196

1197
        //if (currentLevel == 0)
1198
        //{
1199
        //        TRACE("Stations to examine:\n");
1200
        //        for_each(vStnList->begin(), vStnList->end(),
1201
        //                [this] (UINT32& stn) { 
1202
        //                        TRACE("%d ", stn);
1203
        //        });
1204
        //        TRACE("\n");
1205
        //}
1206

1207
        for (it_stn=vStnList->begin(); it_stn!=vStnList->end(); ++it_stn)
768✔
1208
        {
1209
                if (currentLevel == 0)
666✔
1210
                        vStnCount->push_back(0);
82✔
1211

1212
                //TRACE("Level %d  Station %d: ", currentLevel, *it_stn);
1213
                IdentifyInnerMsrsandAssociatedStns(*it_stn, msrStations);
666✔
1214

1215
                //for_each(msrStations.begin(), msrStations.end(),
1216
                //        [this] (UINT32& stn) { 
1217
                //                TRACE("%d ", stn);
1218
                //});
1219
                //TRACE("\n  ");
1220

1221
                if (currentLevel < maxLevel)
666✔
1222
                        IdentifyLowestStationAssociation(&msrStations, subStations, currentLevel + 1, maxLevel, vStnCount);
82✔
1223

1224
                subStations.insert(subStations.end(), msrStations.begin(), msrStations.end());
666✔
1225

1226
                if (currentLevel == 0)
666✔
1227
                {
1228
                        // get total stations associated with this station
1229
                        strip_duplicates(subStations);
82✔
1230
                        vStnCount->back() = static_cast<UINT32>(subStations.size());
82✔
1231
                }
1232
        }
1233

1234
        if (currentLevel == 0)
102✔
1235
                return;
20✔
1236

1237
        totalStations.insert(totalStations.end(), subStations.begin(), subStations.end());
82✔
1238
        strip_duplicates(totalStations);
82✔
1239

1240
        //TRACE("Summary (%d stations): ", totalStations.size());
1241
        //for_each(totalStations.begin(), totalStations.end(),
1242
        //        [this] (UINT32& stn) { 
1243
        //                TRACE("%d ", stn);
1244
        //});
1245
        //TRACE("\n\n");
1246
}
102✔
1247

1248
void dna_segment::SortbyMeasurementCount(pvUINT32 vStnList)
759✔
1249
{
1250
        if (vStnList->size() < 2)
759✔
1251
                return;
759✔
1252
        // sort vStnList by number of measurements to each station (held by vAssocStnList
1253
        CompareMeasCount<CAStationList, UINT32> msrcountCompareFunc(&vAssocStnList_);
737✔
1254
        std::sort(vStnList->begin(), vStnList->end(), msrcountCompareFunc);
737✔
1255

1256
        // Search lower level
1257
        if (projectSettings_.s.seg_search_level == 0)
737✔
1258
                return;
1259

1260
        vUINT32 msrStations;
20✔
1261
        vUINT32 stnList, stnCount;
20✔
1262
        stnList.insert(stnList.end(), vStnList->begin(), 
20✔
1263
                (vStnList->begin() + minVal(vUINT32::size_type(5),vStnList->size())));
20✔
1264
        IdentifyLowestStationAssociation(&stnList, msrStations, 0, projectSettings_.s.seg_search_level, &stnCount);
20✔
1265

1266
        UINT32 lowestStnCount(*(min_element(stnCount.begin(), stnCount.end())));
20✔
1267
        
1268
        if (stnCount.front() == lowestStnCount)
20✔
1269
                return;
1270

1271
        it_vUINT32 it_stn(vStnList->begin()), it_count;
×
1272
        for (it_count=stnCount.begin(); it_count!=stnCount.end(); ++it_stn, ++it_count)
×
1273
        {
1274
                if (lowestStnCount == *it_count)
×
1275
                        break;
1276
        }
1277

1278
        if (vStnList->size() < 2)
×
1279
                return;
1280

1281
        lowestStnCount = *it_stn;
×
1282
        vStnList->erase(it_stn);
×
1283
        vStnList->insert(vStnList->begin(), lowestStnCount);
×
1284

1285
}
20✔
1286
        
1287

1288
void dna_segment::SetAvailableMsrCount()
16✔
1289
{
1290
        _it_vasl _it_asl;
16✔
1291

1292
        UINT32 stn_index, msrCount, amlIndex;
16✔
1293

1294
        for (_it_asl=vAssocStnList_.begin();
949✔
1295
                _it_asl!=vAssocStnList_.end();
949✔
1296
                ++_it_asl)
933✔
1297
        {
1298
                stn_index = static_cast<UINT32>(std::distance(vAssocStnList_.begin(), _it_asl));
933✔
1299

1300
                _it_asl->SetAvailMsrCount(_it_asl->GetAssocMsrCount());
933✔
1301

1302
                if (_it_asl->GetAssocMsrCount() == 0)
933✔
1303
                        continue;
27✔
1304

1305
                msrCount = vASLCount_.at(stn_index);        // original measurement count
906✔
1306
                amlIndex = vAssocStnList_.at(stn_index).GetAMLStnIndex();
906✔
1307

1308
                // if a measurement is ignored, it will not be available
1309
                for (UINT32 m(0); m<msrCount; ++m, ++amlIndex)
13,594✔
1310
                {
1311
                        if (!vAssocFreeMsrList_.at(amlIndex).available)
12,688✔
1312
                                _it_asl->DecrementAvailMsrCount();
13,177✔
1313
                }                
1314
        }
1315
}
16✔
1316
        
1317

1318
void dna_segment::RemoveInvalidFreeStations()
16✔
1319
{
1320
        CompareValidity<CAStationList, UINT32> aslValidityCompareFunc(&vAssocStnList_, FALSE);
16✔
1321
        std::sort(vfreeStnList_.begin(), vfreeStnList_.end(), aslValidityCompareFunc);
16✔
1322
        erase_if(vfreeStnList_, aslValidityCompareFunc);
16✔
1323
}
16✔
1324

1325

1326
void dna_segment::BuildFreeStationAvailabilityList()
16✔
1327
{
1328
        dna_io_seg seg;
16✔
1329
        seg.build_free_stn_availability(vAssocStnList_, vfreeStnAvailability_);
16✔
1330
}                
16✔
1331

1332
void dna_segment::RemoveDuplicateStations(pvstring vStations)
5✔
1333
{
1334
        if (vStations->size() < 2)
5✔
1335
                return;
1336
        
1337
        // A prior sort on name is essential, since the criteria for removing duplicates 
1338
        // is based upon two successive station entries in an ordered vector being equal
1339
        strip_duplicates(vStations);
1✔
1340
}
1341
        
1342
//void dna_segment::RemoveNonMeasurements()
1343
//{
1344
//        if (vfreeMsrList_.size() < 2)
1345
//                return;
1346
//        CompareNonMeasStart<measurement_t, UINT32> measstartCompareFunc(&bmsBinaryRecords_, xMeas);
1347
//        std::sort(vfreeMsrList_.begin(), vfreeMsrList_.end(), measstartCompareFunc);
1348
//        erase_if(vfreeMsrList_, measstartCompareFunc);
1349
//        
1350
//}
1351
        
1352

1353
//void dna_segment::RemoveIgnoredMeasurements()
1354
//{
1355
//        if (vfreeMsrList_.size() < 2)
1356
//                return;
1357
//        CompareIgnoreedMeas<measurement_t, UINT32> ignoremeasCompareFunc(&bmsBinaryRecords_);
1358
//        std::sort(vfreeMsrList_.begin(), vfreeMsrList_.end(), ignoremeasCompareFunc);
1359
//        erase_if(vfreeMsrList_, ignoremeasCompareFunc);
1360
//        
1361
//}
1362
        
1363

1364
void dna_segment::WriteFreeStnListSortedbyASLMsrCount()
5✔
1365
{
1366
        if (!boost::filesystem::exists(output_folder_))
10✔
1367
        {
NEW
1368
                std::stringstream ss("WriteFreeStnListSortedbyASLMsrCount(): Path does not exist... \n\n    ");
×
1369
                ss << output_folder_ << ".";
×
1370
                SignalExceptionSerialise(ss.str(), 0, NULL);
×
1371
        }
×
1372

1373
        std::string file(output_folder_ + "/free_stn_sorted_by_msr_count.lst");
5✔
1374
        std::ofstream freestnlist(file.c_str());
5✔
1375
        UINT32 x(0);
5✔
1376
        std::string s;
5✔
1377
        UINT32 u, msrCount, m, amlindex;
5✔
1378
        for (; x<vfreeStnList_.size(); ++x)
254✔
1379
        {
1380
                u = vfreeStnList_.at(x);
249✔
1381
                s = bstBinaryRecords_.at(vfreeStnList_.at(x)).stationName;
249✔
1382
                s.insert(0, "'");
249✔
1383
                s += "'";
249✔
1384
                msrCount = vAssocStnList_.at(vfreeStnList_.at(x)).GetAssocMsrCount();
249✔
1385
                freestnlist << std::left << std::setw(10) << u << std::left << std::setw(14) << s << std::left << std::setw(5) << msrCount;
249✔
1386

1387
                for (m=0; m<msrCount; m++)
3,825✔
1388
                {
1389
                        // get the measurement record (holds other stations tied to this measurement)
1390
                        amlindex = vAssocStnList_.at(vfreeStnList_.at(x)).GetAMLStnIndex() + m;        // get the AML index
3,576✔
1391
                        freestnlist << std::left << std::setw(HEADER_20) << amlindex;
3,576✔
1392
                }
1393
                freestnlist << std::endl;
249✔
1394
        }
1395
        freestnlist.close();
5✔
1396
}
10✔
1397
        
1398

1399
void dna_segment::coutCurrentBlockSummary(std::ostream &os)
17✔
1400
{
1401
        try {
17✔
1402
                dna_io_seg seg;
17✔
1403
                seg.write_seg_block(os, 
17✔
1404
                        vCurrInnerStnList_, vCurrJunctStnList_, vCurrMeasurementList_, 
17✔
1405
                        currentBlock_,
17✔
1406
                        &bstBinaryRecords_, &bmsBinaryRecords_, 
17✔
1407
                        true);
1408
        }
17✔
NEW
1409
        catch (const std::runtime_error& e) {
×
1410
                SignalExceptionSerialise(e.what(), 0, NULL);
×
1411
        }
×
1412
        
1413
        if (!vfreeStnList_.empty())
17✔
1414
                os << "+ Free stations remaining:     " << std::setw(10) << std::right << vfreeStnList_.size() << std::endl;
12✔
1415
        if (!vfreeMsrList_.empty())
17✔
NEW
1416
                os << "+ Free measurements remaining: " << std::setw(10) << std::right << vfreeMsrList_.size() << std::endl;
×
1417
}
17✔
1418
        
1419
void dna_segment::coutSummary() const
5✔
1420
{
1421
        UINT32 stns(0), msrs(0);
5✔
1422
        vvUINT32::const_iterator _it_isl, _it_jsl, _it_cml;
5✔
1423

1424
        char BLOCK = 10;
5✔
1425
        char INNER = 12;
5✔
1426
        char JUNCT = 15;
5✔
1427
        char TOTAL = 12;
5✔
1428
        char MEASR = 14;
5✔
1429

1430
        for (_it_cml = vCML_.begin(); _it_cml!=vCML_.end(); ++_it_cml)
22✔
1431
                msrs += static_cast<UINT32>(_it_cml->size());
17✔
1432
        for (_it_isl = vISL_.begin(); _it_isl!=vISL_.end(); ++_it_isl)
22✔
1433
                stns += static_cast<UINT32>(_it_isl->size());
17✔
1434

1435
        std::cout << "+ Segmentation summary:" << std::endl << std::endl;
5✔
1436
        std::cout << std::setw(BLOCK) << std::left << "  Block" << std::setw(JUNCT) << std::left << "Junction stns" << std::setw(INNER) << std::left << "Inner stns" << std::setw(MEASR) << std::left << "Measurements" << std::setw(TOTAL) << std::left << "Total stns"  << std::endl;
5✔
1437
        std::cout << "  ";
5✔
1438
        for (char dash=BLOCK+NETID+INNER+JUNCT+TOTAL+MEASR; dash>2; dash--)
380✔
1439
                std::cout << "-";
375✔
1440
        std::cout << std::endl;
5✔
1441
        UINT32 b = 1;
5✔
1442
        _it_jsl = vJSL_.begin();
5✔
1443
        _it_cml = vCML_.begin();
5✔
1444
        for (_it_isl=vISL_.begin(); _it_isl!=vISL_.end(); ++_it_isl)
22✔
1445
        {
1446
                // block
1447
                std::cout << "  " << std::setw(BLOCK-2) << std::left << b;
17✔
1448

1449
                // junction stns
1450
                if (_it_jsl!=vJSL_.end())
17✔
1451
                        std::cout << std::setw(JUNCT) << std::left << _it_jsl->size();
17✔
1452
                else
NEW
1453
                        std::cout << std::setw(JUNCT) << " ";
×
1454
                
1455
                // inner stns
1456
                std::cout << std::setw(INNER) << std::left << _it_isl->size();
17✔
1457
                
1458
                // total measurements
1459
                if (_it_cml!=vCML_.end())
17✔
1460
                        std::cout << std::setw(MEASR) << std::left << _it_cml->size();
17✔
1461
                else
NEW
1462
                        std::cout << std::setw(MEASR) << " ";
×
1463

1464
                // total stns
1465
                if (_it_jsl!=vJSL_.end())
17✔
1466
                        std::cout << std::setw(TOTAL) << std::left << (_it_isl->size() + _it_jsl->size());
17✔
1467
                else
NEW
1468
                        std::cout << std::setw(TOTAL) << std::left << _it_isl->size();
×
1469
                
1470
                std::cout << std::endl;
17✔
1471

1472
                ++_it_jsl;
17✔
1473
                ++_it_cml;
17✔
1474
                b++;
17✔
1475
        }
1476

1477
        std::cout << std::endl;
5✔
1478

1479
        std::cout << "+ Stations used:       " << std::setw(10) << std::right << stns << std::endl;
5✔
1480
        std::cout << "+ Measurements used:   " << std::setw(10) << std::right << msrs << std::endl;
5✔
1481
        if (!vfreeStnList_.empty())
5✔
NEW
1482
                std::cout << "+ Unused stations:     " << std::setw(10) << std::right << vfreeStnList_.size() << std::endl;
×
1483
        //if (!vfreeMsrList_.empty())
1484
        //        std::cout << "+ Unused measurements: " << std::setw(10) << std::right << vfreeMsrList_.size() << std::endl;
1485
}
5✔
1486
        
1487
void dna_segment::WriteSegmentedNetwork(const std::string& segfileName)
16✔
1488
{
1489
        if (bstBinaryRecords_.empty())
16✔
1490
                SignalExceptionSerialise("WriteSegmentedNetwork(): the binary stations file has not been loaded into memory yet.", 0, NULL);
×
1491
        if (bmsBinaryRecords_.empty())
16✔
1492
                SignalExceptionSerialise("WriteSegmentedNetwork(): the binary measurements file has not been loaded into memory yet.", 0, NULL);
×
1493
        if (vJSL_.empty())
16✔
1494
                SignalExceptionSerialise("WriteSegmentedNetwork(): the junction stations list is empty, most likely because the network has not been segmented yet.", 0, NULL);
×
1495
        if (vISL_.empty())
16✔
1496
                SignalExceptionSerialise("WriteSegmentedNetwork(): the inner stations list is empty, most likely because the network has not been segmented yet.", 0, NULL);
×
1497
        if (vCML_.empty())
16✔
1498
                SignalExceptionSerialise("WriteSegmentedNetwork(): the block measurementslist is empty, most likely because the network has not been segmented yet.", 0, NULL);
×
1499
        
1500
        try {
16✔
1501
                dna_io_seg seg;
16✔
1502
                seg.write_seg_file(segfileName, projectSettings_.s.bst_file, projectSettings_.s.bms_file,
16✔
1503
                        projectSettings_.s.min_inner_stations, projectSettings_.s.max_total_stations,
16✔
1504
                        projectSettings_.s.seg_starting_stns, vinitialStns_,
16✔
1505
                        projectSettings_.s.command_line_arguments, 
16✔
1506
                        vISL_, vJSL_, vCML_,
1507
                        v_ContiguousNetList_, &bstBinaryRecords_, &bmsBinaryRecords_);
16✔
1508
        }
16✔
NEW
1509
        catch (const std::runtime_error& e) {
×
1510
                SignalExceptionSerialise(e.what(), 0, NULL);
×
1511
        }
×
1512
        catch (...) {
×
1513
                SignalExceptionSerialise("WriteSegmentedNetwork(): failed to print segmentation file.", 0, NULL);
×
1514
        }
×
1515
}
16✔
1516

1517
void dna_segment::VerifyStationConnections()
16✔
1518
{
1519
        UINT32 block, blockCount(static_cast<UINT32>(vISL_.size()));
16✔
1520

1521
        for (block=0; block<blockCount; ++block)
62✔
1522
                VerifyStationConnections_Block(block);
46✔
1523
}
16✔
1524

1525
void dna_segment::VerifyStationConnections_Block(const UINT32& block)
46✔
1526
{
1527
        vUINT32::const_iterator _it_isl, _it_jsl, _it_cml;
46✔
1528
        bool stationAssociated;
46✔
1529
        vUINT32 unusedStns, msrStations, allmsrStations;
46✔
1530

1531
#ifdef _MSDEBUG
1532
        std::string isl_stn_name;
1533
#endif
1534

1535
        // get all stations connected with measurements
1536
        for (_it_cml=vCML_.at(block).begin(); _it_cml!=vCML_.at(block).end(); ++_it_cml)
5,574✔
1537
        {
1538
                // Get all the stations associated with this measurement
1539
                GetMsrStations(bmsBinaryRecords_, *_it_cml, msrStations);
5,528✔
1540
                // Append to master station list
1541
                allmsrStations.insert(allmsrStations.end(), msrStations.begin(), msrStations.end());
5,528✔
1542
        }
1543

1544
        strip_duplicates(allmsrStations);
46✔
1545
        
1546
        // Check all isl stations are associated with a measurement
1547
        // No need to check jsl stations as a junction may appear in a block
1548
        // as a result of being carried forward without any measurements
1549
        for (_it_isl=vISL_.at(block).begin(); _it_isl!=vISL_.at(block).end(); ++_it_isl)
952✔
1550
        {
1551
                stationAssociated = false;
906✔
1552
                if (binary_search(allmsrStations.begin(), allmsrStations.end(), *_it_isl))
906✔
1553
                        stationAssociated = true;
1554
                
1555
                if (!stationAssociated)
×
1556
                {
1557
                        unusedStns.push_back(*_it_isl);
×
1558

1559
#ifdef _MSDEBUG
1560
                        isl_stn_name = bstBinaryRecords_.at(*_it_isl).stationName;
1561
#endif
1562
                }
1563
        }
1564

1565
        if (!unusedStns.empty())
46✔
1566
        {
NEW
1567
                std::stringstream ss;
×
NEW
1568
                ss << "The following station(s) are not associated with any" << std::endl <<
×
NEW
1569
                        "  measurements in block " << block+1 << ":" << std::endl;
×
1570
                for_each(unusedStns.begin(), unusedStns.end(),
×
1571
                        [this, &ss](UINT32& stn){
×
NEW
1572
                                ss << "  " << bstBinaryRecords_.at(stn).stationName << " (" << stn << ")" << std::endl;
×
1573
                });
×
1574
                SignalExceptionSerialise(ss.str(), 0, NULL);
×
1575
        }
×
1576

1577
}
46✔
1578

1579
}        // namespace networksegment
1580
}        // namespace dynadjust
1581

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

© 2025 Coveralls, Inc