Coverage Report

Created: 2025-07-11 06:33

/src/bag/api/bag_trackinglist.cpp
Line
Count
Source (jump to first uncovered line)
1
2
#include "bag_private.h"
3
#include "bag_trackinglist.h"
4
5
#include <array>
6
#include <H5Cpp.h>
7
8
9
namespace BAG {
10
11
//! The HDF5 DataSet chunk size.
12
constexpr hsize_t kChunkSize = 10;
13
14
//! Constructor
15
/*!
16
\param dataset
17
    The BAG Dataset the tracking list belongs to.
18
*/
19
TrackingList::TrackingList(const Dataset& dataset)
20
242
    : m_pBagDataset(dataset.shared_from_this())
21
242
{
22
242
    m_pH5dataSet = openH5dataSet();
23
242
}
24
25
//! Constructor
26
/*!
27
\param dataset
28
    The BAG Dataset the tracking list belongs to.
29
\param compressionLevel
30
    The compression level the HDF5 DataSet will use.
31
*/
32
TrackingList::TrackingList(
33
    const Dataset& dataset,
34
    int compressionLevel)
35
0
    : m_pBagDataset(dataset.shared_from_this())
36
0
{
37
0
    m_pH5dataSet = createH5dataSet(compressionLevel);
38
0
}
39
40
41
//! Retrieve an iterator to the first item in the tracking list.
42
/*!
43
\return
44
    An iterator to the first item in the tracking list.
45
*/
46
TrackingList::iterator TrackingList::begin() & noexcept
47
0
{
48
0
    return std::begin(m_items);
49
0
}
50
51
//! Retrieve an iterator to the first item in the tracking list.
52
/*!
53
\return
54
    An iterator to the first item in the tracking list.
55
*/
56
TrackingList::const_iterator TrackingList::begin() const & noexcept
57
24
{
58
24
    return std::begin(m_items);
59
24
}
60
61
//! Retrieve an iterator to the first item in the tracking list.
62
/*!
63
\return
64
    An iterator to the first item in the tracking list.
65
*/
66
TrackingList::const_iterator TrackingList::cbegin() const & noexcept
67
0
{
68
0
    return std::cbegin(m_items);
69
0
}
70
71
//! Retrieve an iterator to one past the last item in the tracking list.
72
/*!
73
\return
74
    An iterator to one past the last item in the tracking list.
75
*/
76
TrackingList::const_iterator TrackingList::cend() const & noexcept
77
0
{
78
0
    return std::cend(m_items);
79
0
}
80
81
//! Determine if the tracking list is empty.
82
/*!
83
\return
84
    \e true if the tracking list is empty.
85
    \e false otherwise.
86
*/
87
bool TrackingList::empty() const noexcept
88
0
{
89
0
    return m_items.empty();
90
0
}
91
92
//! Retrieve an iterator to one past the last item in the tracking list.
93
/*!
94
\return
95
    An iterator to one past the last item in the tracking list.
96
*/
97
TrackingList::iterator TrackingList::end() & noexcept
98
0
{
99
0
    return std::end(m_items);
100
0
}
101
102
//! Retrieve an iterator to one past the last item in the tracking list.
103
/*!
104
\return
105
    An iterator to one past the last item in the tracking list.
106
*/
107
TrackingList::const_iterator TrackingList::end() const & noexcept
108
24
{
109
24
    return std::end(m_items);
110
24
}
111
112
//! Retrieve the item at the specified index.
113
/*!
114
\return
115
    The item at the specified index.
116
*/
117
TrackingList::reference TrackingList::operator[](size_t index) & noexcept
118
0
{
119
0
    return m_items[index];
120
0
}
121
122
//! Retrieve the item at the specified index.
123
/*!
124
\return
125
    The item at the specified index.
126
*/
127
TrackingList::const_reference TrackingList::operator[](
128
    size_t index) const & noexcept
129
0
{
130
0
    return m_items[index];
131
0
}
132
133
//! Retrieve the number of items in the tracking list.
134
/*!
135
\return
136
    The number of items in the tracking list.
137
*/
138
size_t TrackingList::size() const noexcept
139
24
{
140
24
    return m_items.size();
141
24
}
142
143
//! Empty the tracking list.
144
void TrackingList::clear() noexcept
145
0
{
146
0
    m_items.clear();
147
0
}
148
149
//! Add an item to the end of the tracking list.
150
/*!
151
\param value
152
    The item to add.
153
*/
154
void TrackingList::push_back(const value_type& value)
155
0
{
156
0
    m_items.push_back(value);
157
0
}
158
159
//! Add an item to the end of the tracking list.
160
/*!
161
\param value
162
    The item to add.
163
*/
164
void TrackingList::push_back(value_type&& value)
165
0
{
166
0
    m_items.push_back(value);
167
0
}
168
169
//! Retrieve the first item in the tracking list.
170
/*!
171
\return
172
    The first item in the tracking list.
173
*/
174
TrackingList::reference TrackingList::front() &
175
0
{
176
0
    return m_items.front();
177
0
}
178
179
//! Retrieve the first item in the tracking list.
180
/*!
181
\return
182
    The first item in the tracking list.
183
*/
184
TrackingList::const_reference TrackingList::front() const &
185
0
{
186
0
    return m_items.front();
187
0
}
188
189
//! Retrieve the last item in the tracking list.
190
/*!
191
\return
192
    The last item in the tracking list.
193
*/
194
TrackingList::reference TrackingList::back() &
195
0
{
196
0
    return m_items.back();
197
0
}
198
199
//! Retrieve the last item in the tracking list.
200
/*!
201
\return
202
    The last item in the tracking list.
203
*/
204
TrackingList::const_reference TrackingList::back() const &
205
0
{
206
0
    return m_items.back();
207
0
}
208
209
//! Reserve more space in the tracking list.
210
/*!
211
    Reserve more space in the tracking list.  If the amount to be reserved is
212
    less than the current capacity, do nothing.
213
214
\param newCapacity
215
    The new capacity of the tracking list.
216
*/
217
void TrackingList::reserve(size_t newCapacity)
218
0
{
219
0
    m_items.reserve(newCapacity);
220
0
}
221
222
//! Resize the tracking list to the new value.
223
/*!
224
\param count
225
    The new size of the tracking list.
226
*/
227
void TrackingList::resize(size_t count)
228
0
{
229
0
    m_items.resize(count);
230
0
}
231
232
//! Retrieve a pointer to the first item in the tracking list.
233
/*!
234
\return
235
    A pointer to the first item in the tracking list.
236
*/
237
TrackingList::value_type* TrackingList::data() & noexcept
238
0
{
239
0
    return m_items.data();
240
0
}
241
242
//! Retrieve a pointer to the first item in the tracking list.
243
/*!
244
\return
245
    A pointer to the first item in the tracking list.
246
*/
247
const TrackingList::value_type* TrackingList::data() const & noexcept
248
0
{
249
0
    return m_items.data();
250
0
}
251
252
//! Create the HDF5 DataSet the tracking list wraps.
253
/*!
254
\param compressionLevel
255
    The compression level the HDF5 DataSet will use.
256
257
\return
258
    The HDF5 DataSet the tracking list wraps.
259
*/
260
std::unique_ptr<::H5::DataSet, DeleteH5dataSet>
261
TrackingList::createH5dataSet(
262
    int compressionLevel)
263
0
{
264
0
    if (m_pBagDataset.expired())
265
0
        throw DatasetNotFound{};
266
267
0
    auto pDataset = m_pBagDataset.lock();
268
269
0
    const auto& h5file = pDataset->getH5file();
270
271
0
    constexpr hsize_t numEntries = 0;
272
0
    constexpr hsize_t kUnlimitedSize = H5F_UNLIMITED;
273
0
    const ::H5::DataSpace h5dataSpace{1, &numEntries, &kUnlimitedSize};
274
275
0
    const ::H5::CompType h5dataType{sizeof(value_type)};
276
277
0
    h5dataType.insertMember("row", HOFFSET(value_type, row),
278
0
        ::H5::PredType::NATIVE_UINT32);
279
0
    h5dataType.insertMember("col", HOFFSET(value_type, col),
280
0
        ::H5::PredType::NATIVE_UINT32);
281
0
    h5dataType.insertMember("depth", HOFFSET(value_type, depth),
282
0
        ::H5::PredType::NATIVE_FLOAT);
283
0
    h5dataType.insertMember("uncertainty", HOFFSET(value_type, uncertainty),
284
0
        ::H5::PredType::NATIVE_FLOAT);
285
0
    h5dataType.insertMember("track_code", HOFFSET(value_type, track_code),
286
0
        ::H5::PredType::NATIVE_UCHAR);
287
0
    h5dataType.insertMember("list_series", HOFFSET(value_type, list_series),
288
0
        ::H5::PredType::NATIVE_SHORT);
289
290
0
    const ::H5::DSetCreatPropList h5createPropList{};
291
0
    h5createPropList.setChunk(1, &kChunkSize);
292
293
0
    if (compressionLevel > 0 && compressionLevel <= kMaxCompressionLevel)
294
0
        h5createPropList.setDeflate(compressionLevel);
295
296
0
    const auto h5dataSet = h5file.createDataSet(TRACKING_LIST_PATH,
297
0
        h5dataType, h5dataSpace, h5createPropList);
298
299
0
    const ::H5::DataSpace listLengthDataSpace{};
300
0
    const auto listLengthAtt = h5dataSet.createAttribute(
301
0
        TRACKING_LIST_LENGTH_NAME, ::H5::PredType::NATIVE_UINT32,
302
0
        listLengthDataSpace);
303
304
0
    const uint32_t length = 0;
305
0
    listLengthAtt.write(::H5::PredType::NATIVE_UINT32, &length);
306
307
0
    return std::unique_ptr<::H5::DataSet, DeleteH5dataSet>(
308
0
        new ::H5::DataSet{h5dataSet}, DeleteH5dataSet{});
309
0
}
310
311
//! Open an existing HDF5 DataSet the tracking list wraps.
312
/*!
313
\return
314
    The HDF5 DataSet the tracking list wraps.
315
*/
316
std::unique_ptr<::H5::DataSet, DeleteH5dataSet>
317
TrackingList::openH5dataSet()
318
242
{
319
242
    if (m_pBagDataset.expired())
320
0
        throw DatasetNotFound{};
321
322
242
    m_items.clear();
323
324
242
    auto pDataset = m_pBagDataset.lock();
325
326
    // Read the tracking list from the BAG.
327
    // Get the attribute TRACKING_LIST_LENGTH_NAME
328
242
    const auto h5dataSet = pDataset->getH5file().openDataSet(TRACKING_LIST_PATH);
329
242
    const auto attribute = h5dataSet.openAttribute(TRACKING_LIST_LENGTH_NAME);
330
331
242
    uint32_t length = 0;
332
242
    attribute.read(attribute.getDataType(), &length);
333
334
242
    if (length == 0)
335
158
        return std::unique_ptr<::H5::DataSet, DeleteH5dataSet>(
336
158
            new ::H5::DataSet{h5dataSet}, DeleteH5dataSet{});
337
338
    // Read the rank to size m_items properly.
339
84
    const auto h5dataSpace = h5dataSet.getSpace();
340
84
    std::array<hsize_t, H5S_MAX_RANK> dims{};
341
84
    const int ndims = h5dataSpace.getSimpleExtentDims(dims.data(), nullptr);
342
343
84
    size_t numItems = 1;
344
128
    for (int i=0; i<ndims; ++i)
345
44
        numItems *= dims[i];
346
347
84
    m_items.resize(numItems);
348
349
    // Set up the structure for reading.
350
84
    ::H5::CompType h5type(sizeof(value_type));
351
84
    h5type.insertMember("row", HOFFSET(value_type, row),
352
84
        ::H5::PredType::NATIVE_UINT32);
353
84
    h5type.insertMember("col", HOFFSET(value_type, col),
354
84
        ::H5::PredType::NATIVE_UINT32);
355
84
    h5type.insertMember("depth", HOFFSET(value_type, depth),
356
84
        ::H5::PredType::NATIVE_FLOAT);
357
84
    h5type.insertMember("uncertainty", HOFFSET(value_type, uncertainty),
358
84
        ::H5::PredType::NATIVE_FLOAT);
359
84
    h5type.insertMember("track_code", HOFFSET(value_type, track_code),
360
84
        ::H5::PredType::NATIVE_UINT8);
361
84
    h5type.insertMember("list_series", HOFFSET(value_type, list_series),
362
84
        ::H5::PredType::NATIVE_INT16);
363
364
84
    h5dataSet.read(m_items.data(), h5type);
365
366
84
    return std::unique_ptr<::H5::DataSet, DeleteH5dataSet>(
367
84
        new ::H5::DataSet{h5dataSet}, DeleteH5dataSet{});
368
242
}
369
370
//! Write the tracking list to the HDF5 DataSet.
371
void TrackingList::write() const
372
0
{
373
0
    if (m_pBagDataset.expired() || !m_pH5dataSet)
374
0
        throw DatasetNotFound{};
375
376
    // Write the Attribute.
377
0
    const ::H5::DataSpace listLengthDataSpace{};
378
0
    const ::H5::Attribute listLengthAtt = m_pH5dataSet->openAttribute(
379
0
        TRACKING_LIST_LENGTH_NAME);
380
381
0
    const uint32_t length = static_cast<uint32_t>(m_items.size());
382
0
    listLengthAtt.write(::H5::PredType::NATIVE_UINT32, &length);
383
384
    // Resize the DataSet to reflect the new data size.
385
0
    const hsize_t numItems = length;
386
0
    m_pH5dataSet->extend(&numItems);
387
388
    // Write the data.
389
0
    const ::H5::CompType h5type{sizeof(value_type)};
390
391
0
    h5type.insertMember("row", HOFFSET(value_type, row),
392
0
        ::H5::PredType::NATIVE_UINT32);
393
0
    h5type.insertMember("col", HOFFSET(value_type, col),
394
0
        ::H5::PredType::NATIVE_UINT32);
395
0
    h5type.insertMember("depth", HOFFSET(value_type, depth),
396
0
        ::H5::PredType::NATIVE_FLOAT);
397
0
    h5type.insertMember("uncertainty", HOFFSET(value_type, uncertainty),
398
0
        ::H5::PredType::NATIVE_FLOAT);
399
0
    h5type.insertMember("track_code", HOFFSET(value_type, track_code),
400
0
        ::H5::PredType::NATIVE_UINT8);
401
0
    h5type.insertMember("list_series", HOFFSET(value_type, list_series),
402
0
        ::H5::PredType::NATIVE_INT16);
403
404
0
    constexpr hsize_t kMaxSize = H5F_UNLIMITED;
405
406
0
    ::H5::DataSpace h5memSpace{1, &numItems, &kMaxSize};
407
408
0
    ::H5::DataSpace h5fileSpace{1, &numItems, &kMaxSize};
409
410
0
    m_pH5dataSet->write(m_items.data(), h5type, h5memSpace, h5fileSpace);
411
0
}
412
413
}   //namespace BAG
414