Coverage Report

Created: 2025-07-11 06:33

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