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

icsm-au / DynAdjust / 5021237816

pending completion
5021237816

Pull #222

github

GitHub
Merge 6e730fa5a into 72bc8feb8
Pull Request #222: Upgrade to C++17 and various enhancements

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

30773 of 38869 relevant lines covered (79.17%)

3959.82 hits per line

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

82.5
/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
#ifdef _MSDEBUG
25
#include <include/ide/trace.hpp>
26
#endif
27

28
namespace dynadjust { namespace networksegment {
29

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

36
dna_segment::~dna_segment()
17✔
37
{
38

39
}
17✔
40
        
41

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

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

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

67
        vinitialStns_.clear();
2✔
68

69
        try {
70

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

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

91
        net_file.close();
2✔
92
}
2✔
93

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

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

107
        vstring cmd_line_stations;
4✔
108

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

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

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

132
        ParseStartingStations();
17✔
133

134
        network_name_ = p->g.network_name;
17✔
135

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

144

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

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

166
        vJSL_.clear();
17✔
167
        vISL_.clear();
17✔
168
        vCML_.clear();
17✔
169
}
17✔
170
        
171

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

176
        output_folder_ = p->g.output_folder;
16✔
177

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

205
        segmentStatus_ = SEGMENT_SUCCESS;
16✔
206
        ostringstream ss;
16✔
207

208
        if (debug_level_ > 2)
16✔
209
                WriteFreeStnListSortedbyASLMsrCount();
5✔
210

211
        currentBlock_ = 1;
16✔
212

213
        if (debug_level_ > 2)
16✔
214
                trace_file << "Block " << currentBlock_ << "..." << endl;
5✔
215
        
216
        cpu_timer time;
16✔
217

218
        v_ContiguousNetList_.clear();
16✔
219
        v_ContiguousNetList_.push_back(currentNetwork_ = 0);
16✔
220

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

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

240
                currentBlock_++;
30✔
241

242
                if (debug_level_ > 2)
30✔
243
                        trace_file << "Block " << currentBlock_ << "..." << endl;
12✔
244

245
                v_ContiguousNetList_.push_back(currentNetwork_);
30✔
246

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

256
        milliseconds elapsed_time(milliseconds(0));
16✔
257
        if (debug_level_ > 1)
16✔
258
                elapsed_time = milliseconds(time.elapsed().wall/MILLI_TO_NANO);
5✔
259
        
260
        isProcessing_ = false;        
16✔
261

262
        CalculateAverageBlockSize();
16✔
263

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

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

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

292
        isProcessing_ = false;        
16✔
293

294
        if (valid_measurements_not_included || valid_stations)
16✔
295
                return (segmentStatus_ = SEGMENT_BLOCK_ERROR);
×
296

297
        return (segmentStatus_ = SEGMENT_SUCCESS);
16✔
298
}
16✔
299
        
300

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

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

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

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

319

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

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

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

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

354
        // Second pass to build the block
355
        VerifyStationsandBuildBlock();
16✔
356

357
        FinaliseBlock();
16✔
358
}
16✔
359

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

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

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

385
                _it_stnmap = it_stnmap_range.first;
34✔
386

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

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

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

438
        if (debug_level_ > 2)
735✔
439
                trace_file << " + Inner '" << bstBinaryRecords_.at(stn_index).stationName << "'" << endl;
191✔
440

441
#ifdef _MSDEBUG
442
        string station_name =  bstBinaryRecords_.at(stn_index).stationName;
443
#endif
444

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

448
        return stn_index;
735✔
449
}
450
        
451

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

461
        MoveFreeStnToJunctionList(it_newjsl, *it_newjsl);
8✔
462
}
8✔
463

464

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

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

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

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

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

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

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

514
#ifdef _MSDEBUG
515
        string station_name;
516
#endif
517

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

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

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

542
        UINT32 stn_index;
543
        UINT32 currentTotalSize;
544
        bool block_threshold_reached = false;
749✔
545

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

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

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

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

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

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

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

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

605
        // Sort lists
606
        sort(vCurrInnerStnList_.begin(), vCurrInnerStnList_.end());
46✔
607
        sort(vCurrJunctStnList_.begin(), vCurrJunctStnList_.end());
46✔
608
        strip_duplicates(vCurrMeasurementList_);                // remove duplicates and sort
46✔
609

610
        vISL_.push_back(vCurrInnerStnList_);
46✔
611
        vJSL_.push_back(vCurrJunctStnList_);
46✔
612
        vCML_.push_back(vCurrMeasurementList_);
46✔
613

614
        if (debug_level_ > 1)
46✔
615
        {
616
                coutCurrentBlockSummary(debug_file);
17✔
617

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

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

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

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

701
        measurement_t measRecord;
752✔
702
        vUINT32 msrStations;
752✔
703

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

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

719
                if (measRecord.ignore)
4,250✔
720
                        continue;
×
721

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

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

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

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

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

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

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

772
        UINT32 firstIndex(GetFirstMsrIndex<UINT32>(bmsBinaryRecords_, bmsrindex));
5,528✔
773

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

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

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

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

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

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

828
        if (debug_level_ > 2)
5,528✔
829
                trace_file << endl;
1,511✔
830

831
        return true;
832
}
833
        
834

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

847
        it_vUINT32 _it_stn, _it_mstn;
46✔
848
        measurement_t measRecord;
46✔
849
        bool inList;
46✔
850

851
        if (debug_level_ > 2)
46✔
852
                trace_file << " + FindCommonMeasurements()" << endl;
17✔
853

854
#ifdef _MSDEBUG
855
        string stn;
856
#endif
857

858
        UINT32 m, msrCount, amlIndex;
46✔
859

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

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

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

878
                        if (measRecord.ignore)
2,207✔
879
                                continue;
×
880

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

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

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

926

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

944
        it_vUINT32 _it_currjsl(vCurrJunctStnList_.begin());
46✔
945
        UINT32 stn_index;
46✔
946

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

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

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

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

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

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

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

1015

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

1025
        if (debug_level_ > 1)
1✔
1026
                if (debug_file.is_open())
1✔
1027
                        debug_file.close();
×
1028

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

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

1039
        va_list argptr; 
×
1040
        va_start(argptr, streamType);
×
1041

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

1059
        va_end(argptr);
×
1060

1061
        throw NetSegmentException(msg, i);
×
1062
}
1063

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

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

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

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

1100
        // set available msr count
1101
        SetAvailableMsrCount();
16✔
1102
}
16✔
1103

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

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

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

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

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

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

1170
                if (measRecord->ignore)
7,656✔
1171
                        continue;
×
1172

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

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

1188
                totalStations.insert(totalStations.end(), msrStations.begin(), msrStations.end());
7,656✔
1189
        }
1190

1191
        strip_duplicates(totalStations);
666✔
1192
}
666✔
1193

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

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

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

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

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

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

1226
                subStations.insert(subStations.end(), msrStations.begin(), msrStations.end());
666✔
1227

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

1236
        if (currentLevel == 0)
102✔
1237
                return;
20✔
1238

1239
        totalStations.insert(totalStations.end(), subStations.begin(), subStations.end());
82✔
1240
        strip_duplicates(totalStations);
82✔
1241

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

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

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

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

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

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

1280
        if (vStnList->size() < 2)
×
1281
                return;
1282

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

1287
}
779✔
1288
        
1289

1290
void dna_segment::SetAvailableMsrCount()
16✔
1291
{
1292
        _it_vasl _it_asl;
16✔
1293

1294
        UINT32 stn_index, msrCount, amlIndex;
16✔
1295

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

1302
                _it_asl->SetAvailMsrCount(_it_asl->GetAssocMsrCount());
933✔
1303

1304
                if (_it_asl->GetAssocMsrCount() == 0)
933✔
1305
                        continue;
27✔
1306

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

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

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

1327

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

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

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

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

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

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

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

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

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

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

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

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

1474
                ++_it_jsl;
17✔
1475
                ++_it_cml;
17✔
1476
                b++;
17✔
1477
        }
1478

1479
        cout << endl;
5✔
1480

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

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

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

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

1533
#ifdef _MSDEBUG
1534
        string isl_stn_name;
1535
#endif
1536

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

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

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

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

1579
}
46✔
1580

1581
}        // namespace networksegment
1582
}        // namespace dynadjust
1583

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