/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 | | |