Line data Source code
1 : /**
2 : * This is part of the DUNE DAQ Application Framework, copyright 2020.
3 : * Licensing/copyright details are in the COPYING file that you should have
4 : * received with this code.
5 : *
6 : */
7 :
8 : #include "hdf5libs/HDF5FileLayout.hpp"
9 :
10 : #include <stdexcept>
11 : #include <string>
12 : #include <vector>
13 :
14 : namespace dunedaq {
15 : namespace hdf5libs {
16 :
17 43 : HDF5FileLayout::HDF5FileLayout(HDF5FileLayoutParameters conf,
18 43 : uint32_t version) // NOLINT(build/unsigned)
19 43 : : m_conf_params(conf)
20 43 : , m_version(version)
21 : {
22 43 : if (m_version < 2)
23 0 : m_conf_params = get_v0_file_layout_params();
24 :
25 43 : fill_path_params_maps(m_conf_params);
26 :
27 43 : check_config();
28 43 : }
29 :
30 : void
31 43 : HDF5FileLayout::check_config()
32 : {
33 : // for now, don't do additional config checks for old versions
34 43 : if (m_version < 2)
35 : return;
36 :
37 43 : if (m_conf_params.record_name_prefix.compare("TriggerRecord") == 0) {
38 31 : if (m_conf_params.digits_for_sequence_number == 0) {
39 0 : ers::error(FileLayoutSequenceIDsCannotBeZero(ERS_HERE, 4));
40 0 : m_conf_params.digits_for_sequence_number = 4;
41 : }
42 12 : } else if (m_conf_params.record_name_prefix.compare("TimeSlice") == 0) {
43 12 : if (m_conf_params.digits_for_sequence_number != 0) {
44 0 : ers::warning(InvalidSequenceDigits(ERS_HERE, m_conf_params.record_name_prefix, 0));
45 0 : m_conf_params.digits_for_sequence_number = 0;
46 : }
47 : } else {
48 0 : throw InvalidRecordName(ERS_HERE, m_conf_params.record_name_prefix);
49 : }
50 : }
51 :
52 : HDF5PathParameters
53 0 : HDF5FileLayout::get_path_params(daqdataformats::SourceID::Subsystem type) const
54 : {
55 0 : try {
56 0 : return m_path_params_map.at(type);
57 0 : } catch (std::out_of_range&) {
58 0 : throw FileLayoutUnconfiguredSubsystem(ERS_HERE, type, daqdataformats::SourceID::subsystem_to_string(type));
59 0 : }
60 : }
61 :
62 : std::string
63 1755 : HDF5FileLayout::get_record_number_string(uint64_t record_number, // NOLINT(build/unsigned)
64 : daqdataformats::sequence_number_t seq_num) const
65 : {
66 1755 : std::ostringstream record_number_string;
67 :
68 1755 : int width = m_conf_params.digits_for_record_number;
69 1755 : record_number_string << m_conf_params.record_name_prefix << std::setw(width) << std::setfill('0') << record_number;
70 :
71 1755 : if (m_conf_params.digits_for_sequence_number > 0) {
72 :
73 1435 : width = m_conf_params.digits_for_sequence_number;
74 1435 : record_number_string << "." << std::setw(width) << std::setfill('0') << seq_num;
75 : }
76 :
77 3510 : return record_number_string.str();
78 1755 : }
79 :
80 : std::string
81 1655 : HDF5FileLayout::get_trigger_number_string(daqdataformats::trigger_number_t trig_num,
82 : daqdataformats::sequence_number_t seq_num) const
83 : {
84 1655 : return get_record_number_string(trig_num, seq_num);
85 : }
86 :
87 : std::string
88 60 : HDF5FileLayout::get_timeslice_number_string(daqdataformats::timeslice_number_t ts_num) const
89 : {
90 60 : return get_record_number_string(ts_num);
91 : }
92 :
93 : /**
94 : * @brief get the correct path for the TriggerRecordHeader
95 : */
96 : std::vector<std::string>
97 75 : HDF5FileLayout::get_path_elements(const daqdataformats::TriggerRecordHeader& trh) const
98 : {
99 :
100 75 : std::vector<std::string> path_elements;
101 :
102 : // first the Trigger string
103 75 : path_elements.push_back(get_trigger_number_string(trh.get_trigger_number(), trh.get_sequence_number()));
104 :
105 : // then the RawData group name
106 75 : path_elements.push_back(m_conf_params.raw_data_group_name);
107 :
108 : // then the SourceID plus record header name
109 75 : path_elements.push_back(trh.get_header().element_id.to_string() + "_" +
110 75 : m_conf_params.record_header_dataset_name);
111 :
112 75 : return path_elements;
113 0 : }
114 :
115 : /**
116 : * @brief get the correct path for the TimeSliceHeader
117 : */
118 : std::vector<std::string>
119 30 : HDF5FileLayout::get_path_elements(const daqdataformats::TimeSliceHeader& tsh) const
120 : {
121 :
122 30 : std::vector<std::string> path_elements;
123 :
124 : // first the Trigger string
125 30 : path_elements.push_back(get_timeslice_number_string(tsh.timeslice_number));
126 :
127 : // then the RawData group name
128 30 : path_elements.push_back(m_conf_params.raw_data_group_name);
129 :
130 : // then the SourceID plus record header name
131 30 : path_elements.push_back(tsh.element_id.to_string() + "_" + m_conf_params.record_header_dataset_name);
132 :
133 30 : return path_elements;
134 0 : }
135 :
136 : /**
137 : * @brief get the correct path for the Fragment
138 : */
139 : std::vector<std::string>
140 1580 : HDF5FileLayout::get_path_elements(const daqdataformats::FragmentHeader& fh) const
141 : {
142 :
143 1580 : std::vector<std::string> path_elements;
144 :
145 : // first the Trigger string
146 : // note, this still works for TimeSlices through enforced proper configuration of layout parameters
147 1580 : path_elements.push_back(get_trigger_number_string(fh.trigger_number, fh.sequence_number));
148 :
149 : // then the RawData group name
150 1580 : path_elements.push_back(m_conf_params.raw_data_group_name);
151 :
152 : // then the SourceID plus FragmentType
153 1580 : path_elements.push_back(
154 3160 : fh.element_id.to_string() + "_" +
155 3160 : daqdataformats::fragment_type_to_string(static_cast<daqdataformats::FragmentType>(fh.fragment_type)));
156 :
157 1580 : return path_elements;
158 0 : }
159 :
160 : /**
161 : * @brief get the path for the TimeSliceHeader as a single string
162 : */
163 : std::string
164 30 : HDF5FileLayout::get_path_string(const daqdataformats::TimeSliceHeader& tsh) const
165 : {
166 30 : std::ostringstream path_string;
167 30 : path_string << "/" << get_timeslice_number_string(tsh.timeslice_number)
168 30 : << "/" << m_conf_params.raw_data_group_name
169 60 : << "/" << tsh.element_id.to_string() << "_" << m_conf_params.record_header_dataset_name;
170 60 : return path_string.str();
171 30 : }
172 :
173 : /**
174 : * @brief get the full path for a record header dataset based on trig/seq number
175 : */
176 : std::string
177 0 : HDF5FileLayout::get_record_header_path(uint64_t rec_num, // NOLINT (build/unsigned)
178 : daqdataformats::sequence_number_t seq_num) const
179 : {
180 0 : return get_record_number_string(rec_num, seq_num) + "/" + m_conf_params.record_header_dataset_name;
181 : }
182 :
183 : /**
184 : * @brief get the full path for a TriggerRecordHeader dataset based on trig/seq number
185 : */
186 : std::string
187 0 : HDF5FileLayout::get_trigger_record_header_path(daqdataformats::trigger_number_t trig_num,
188 : daqdataformats::sequence_number_t seq_num) const
189 : {
190 0 : return get_trigger_number_string(trig_num, seq_num) + "/" + m_conf_params.record_header_dataset_name;
191 : }
192 :
193 : /**
194 : * @brief get the full path for a TimeSliceHeader dataset based on ts number
195 : */
196 : std::string
197 0 : HDF5FileLayout::get_timeslice_header_path(daqdataformats::timeslice_number_t ts_num) const
198 : {
199 0 : return get_timeslice_number_string(ts_num) + "/" + m_conf_params.record_header_dataset_name;
200 : }
201 :
202 : /**
203 : * @brief get the full path for a Fragment dataset based on trig/seq number and element ID
204 : */
205 : std::string
206 0 : HDF5FileLayout::get_fragment_path(uint64_t trig_num, // NOLINT(build/unsigned)
207 : daqdataformats::sequence_number_t seq_num,
208 : daqdataformats::SourceID element_id) const
209 : {
210 :
211 0 : auto const& path_params = get_path_params(element_id.subsystem);
212 :
213 0 : std::ostringstream path_string;
214 0 : path_string << get_trigger_number_string(trig_num, seq_num) << "/" << path_params.detector_group_name << "/"
215 0 : << path_params.element_name_prefix << std::setw(path_params.digits_for_element_number)
216 0 : << std::setfill('0') << element_id.id;
217 0 : return path_string.str();
218 0 : }
219 :
220 : /**
221 : * @brief get the full path for a Fragment dataset based on trig/seq number, give element_id pieces
222 : */
223 : std::string
224 0 : HDF5FileLayout::get_fragment_path(uint64_t trig_num, // NOLINT(build/unsigned)
225 : daqdataformats::sequence_number_t seq_num,
226 : daqdataformats::SourceID::Subsystem type,
227 : uint32_t element_id) const // NOLINT(build/unsigned)
228 : {
229 0 : daqdataformats::SourceID sid{ type, element_id };
230 0 : return get_fragment_path(trig_num, seq_num, sid);
231 : }
232 :
233 : /**
234 : * @brief get the full path for a Fragment dataset based on trig/seq number, give element_id pieces
235 : */
236 : std::string
237 0 : HDF5FileLayout::get_fragment_path(uint64_t trig_num, // NOLINT(build/unsigned)
238 : daqdataformats::sequence_number_t seq_num,
239 : const std::string& typestring,
240 : uint32_t element_id) const // NOLINT(build/unsigned)
241 : {
242 0 : daqdataformats::SourceID sid{ daqdataformats::SourceID::string_to_subsystem(typestring), element_id };
243 0 : return get_fragment_path(trig_num, seq_num, sid);
244 : }
245 :
246 : /**
247 : * @brief get the path for a Fragment type group based on trig/seq number and type
248 : */
249 : std::string
250 0 : HDF5FileLayout::get_fragment_type_path(uint64_t trig_num, // NOLINT(build/unsigned)
251 : daqdataformats::sequence_number_t seq_num,
252 : daqdataformats::SourceID::Subsystem type) const
253 : {
254 0 : auto const& path_params = get_path_params(type);
255 :
256 0 : std::ostringstream path_string;
257 0 : path_string << get_trigger_number_string(trig_num, seq_num) << "/" << path_params.detector_group_name;
258 0 : return path_string.str();
259 0 : }
260 :
261 : /**
262 : * @brief get the path for a Fragment type group based on trig/seq number and type
263 : */
264 : std::string
265 0 : HDF5FileLayout::get_fragment_type_path(uint64_t trig_num, // NOLINT(build/unsigned)
266 : daqdataformats::sequence_number_t seq_num,
267 : std::string typestring) const
268 : {
269 0 : return get_fragment_type_path(trig_num, seq_num, daqdataformats::SourceID::string_to_subsystem(typestring));
270 : }
271 :
272 : daqdataformats::SourceID
273 0 : HDF5FileLayout::get_source_id_from_path_elements(std::vector<std::string> const& path_elements) const
274 : {
275 : // ignore first path element, which is for the record group
276 : // second path element is detector name.
277 0 : daqdataformats::SourceID::Subsystem systype = m_detector_group_name_to_type_map.at(path_elements[1]);
278 :
279 : // get back the path parameters for this system type from the file layout
280 0 : auto path_params = get_path_params(systype);
281 :
282 : // fourth path element is element. remove prefix and translate to numbers
283 0 : auto ele_id = std::stoi(path_elements[3].substr(path_params.element_name_prefix.size()));
284 :
285 0 : return daqdataformats::SourceID(systype, ele_id);
286 0 : }
287 :
288 : void
289 43 : HDF5FileLayout::fill_path_params_maps(HDF5FileLayoutParameters const& flp)
290 : {
291 86 : for (auto const& path_param : flp.path_params_list) {
292 43 : auto sys_type = daqdataformats::SourceID::string_to_subsystem(path_param.detector_group_type);
293 :
294 43 : if (sys_type == daqdataformats::SourceID::Subsystem::kUnknown)
295 0 : throw FileLayoutInvalidSubsystem(ERS_HERE, path_param.detector_group_type);
296 :
297 43 : m_path_params_map[sys_type] = path_param;
298 43 : m_detector_group_name_to_type_map[path_param.detector_group_name] = sys_type;
299 : }
300 43 : }
301 :
302 : /**
303 : * @brief Version0 FileLayout parameters, for backward compatibility
304 : */
305 : HDF5FileLayoutParameters
306 0 : HDF5FileLayout::get_v0_file_layout_params()
307 : {
308 0 : HDF5FileLayoutParameters flp;
309 0 : flp.record_name_prefix = "TriggerRecord";
310 0 : flp.digits_for_record_number = 6;
311 0 : flp.digits_for_sequence_number = 0;
312 0 : flp.record_header_dataset_name = "TriggerRecordHeader";
313 :
314 0 : HDF5PathParameters pp;
315 :
316 0 : pp.detector_group_type = "TPC";
317 0 : pp.detector_group_name = "TPC";
318 0 : pp.element_name_prefix = "Link";
319 0 : pp.digits_for_element_number = 2;
320 0 : flp.path_params_list.push_back(pp);
321 :
322 0 : pp.detector_group_type = "PDS";
323 0 : pp.detector_group_name = "PDS";
324 0 : pp.element_name_prefix = "Element";
325 0 : pp.digits_for_element_number = 2;
326 0 : flp.path_params_list.push_back(pp);
327 :
328 0 : pp.detector_group_type = "NDLArTPC";
329 0 : pp.detector_group_name = "NDLArTPC";
330 0 : pp.element_name_prefix = "Element";
331 0 : pp.digits_for_element_number = 2;
332 0 : flp.path_params_list.push_back(pp);
333 :
334 0 : pp.detector_group_type = "NDLArPDS";
335 0 : pp.detector_group_name = "NDLArPDS";
336 0 : pp.element_name_prefix = "Element";
337 0 : pp.digits_for_element_number = 2;
338 0 : flp.path_params_list.push_back(pp);
339 :
340 0 : pp.detector_group_type = "DataSelection";
341 0 : pp.detector_group_name = "Trigger";
342 0 : pp.element_name_prefix = "Element";
343 0 : pp.digits_for_element_number = 2;
344 0 : flp.path_params_list.push_back(pp);
345 :
346 0 : return flp;
347 0 : }
348 :
349 : } // namespace hdf5libs
350 : } // namespace dunedaq
|