artdaq_demo_hdf5  v1_02_00
highFiveGeoSplitPDSPSample_dataset.cc
1 #include "tracemf.h"
2 #define TRACE_NAME "HighFiveGeoSplitPDSPSample"
3 #define TLVL_INSERTONE 6
4 #define TLVL_INSERTHEADER 7
5 #define TLVL_WRITEFRAGMENT 8
6 #define TLVL_WRITEFRAGMENT_V 9
7 #define TLVL_READNEXTEVENT 10
8 #define TLVL_READNEXTEVENT_V 11
9 #define TLVL_READFRAGMENT 12
10 #define TLVL_READFRAGMENT_V 13
11 #define TLVL_GETEVENTHEADER 14
12 
13 #include <unordered_map>
14 #include "artdaq-core/Data/ContainerFragmentLoader.hh"
15 #include "artdaq-core/Utilities/TimeUtils.hh"
16 #include "artdaq-demo-hdf5/HDF5/FragmentDataset.hh"
17 #include "artdaq-demo-hdf5/HDF5/highFive/HighFive/include/highfive/H5File.hpp"
18 
19 namespace artdaq {
20 namespace hdf5 {
25 {
26 public:
31  HighFiveGeoSplitPDSPSample(fhicl::ParameterSet const& ps);
36 
41  void insertOne(artdaq::Fragment const& frag) override;
46  void insertMany(artdaq::Fragments const& frags) override;
51  void insertHeader(artdaq::detail::RawEventHeader const& hdr) override;
56  std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> readNextEvent() override;
62  std::unique_ptr<artdaq::detail::RawEventHeader> getEventHeader(artdaq::Fragment::sequence_id_t const& seqID) override;
63 
64 private:
65  std::unique_ptr<HighFive::File> file_;
66  size_t eventIndex_;
67  HighFive::DataSetCreateProps fragmentCProps_;
68  HighFive::DataSetAccessProps fragmentAProps_;
69 
70  void writeFragment_(HighFive::Group& group, artdaq::Fragment const& frag);
71  artdaq::FragmentPtr readFragment_(HighFive::DataSet const& dataset);
72 
73  bool typeOfInterest(artdaq::Fragment::type_t theType);
74  std::array<int, 4> typesOfInterest;
75  int apaOfInterest;
76 };
77 } // namespace hdf5
78 } // namespace artdaq
79 
81  : FragmentDataset(ps, ps.get<std::string>("mode", "write")), file_(nullptr), eventIndex_(0)
82 {
83  TLOG(TLVL_DEBUG) << "HighFiveGeoSplitPDSPSample CONSTRUCTOR BEGIN";
84  if (mode_ == FragmentDatasetMode::Read)
85  {
86  file_.reset(new HighFive::File(ps.get<std::string>("fileName"), HighFive::File::ReadOnly));
87  }
88  else
89  {
90  file_.reset(new HighFive::File(ps.get<std::string>("fileName"), HighFive::File::OpenOrCreate | HighFive::File::Truncate));
91  }
92 
93  typesOfInterest = ps.get<std::array<int, 4>>("fragmentTypesOfInterest");
94  apaOfInterest = ps.get<int>("apaOfInterest");
95 
96  TLOG(TLVL_DEBUG) << "HighFiveGeoSplitPDSPSample CONSTRUCTOR END";
97 }
98 
100 {
101  TLOG(TLVL_DEBUG) << "~HighFiveGeoSplitPDSPSample Begin/End ";
102  // file_->flush();
103 }
104 
105 void artdaq::hdf5::HighFiveGeoSplitPDSPSample::insertOne(artdaq::Fragment const& frag)
106 {
107  TLOG(TLVL_TRACE) << "insertOne BEGIN";
108  if (!file_->exist(std::to_string(frag.sequenceID())))
109  {
110  TLOG(TLVL_INSERTONE) << "insertOne: Creating group for sequence ID " << frag.sequenceID();
111  file_->createGroup(std::to_string(frag.sequenceID()));
112  }
113  auto eventGroup = file_->getGroup(std::to_string(frag.sequenceID()));
114 
115  if (frag.type() == Fragment::ContainerFragmentType)
116  {
117  TLOG(TLVL_INSERTONE) << "insertOne: Processing ContainerFragment";
118  ContainerFragment cf(frag);
119 
120  if (typeOfInterest(cf.fragment_type()))
121  {
122  if (cf.fragment_type() != 10 && (cf.block_count() > 1 || cf.fragment_type() == 9))
123  {
124  TLOG(TLVL_INSERTONE) << "insertOne: Getting Fragment type name";
125  auto fragPtr = cf.at(0);
126  auto typeName = nameHelper_->GetInstanceNameForFragment(*fragPtr).second;
127  if (!eventGroup.exist(typeName))
128  {
129  TLOG(TLVL_INSERTONE) << "insertOne: Creating group for type " << typeName;
130  eventGroup.createGroup(typeName);
131  }
132 
133  TLOG(TLVL_INSERTONE) << "insertOne: Creating group and setting attributes";
134  auto typeGroup = eventGroup.getGroup(typeName);
135  std::string containerName = "Container0";
136 
137  int counter = 1;
138  while (typeGroup.exist(containerName))
139  {
140  //TLOG(TLVL_WRITEFRAGMENT) << "writeFragment_: Duplicate Fragment ID " << frag.fragmentID() << " detected. If this is a ContainerFragment, this is expected, otherwise check configuration!";
141  containerName = "Container" + std::to_string(counter);
142  counter++;
143  }
144 
145  auto containerGroup = typeGroup.createGroup(containerName);
146  containerGroup.createAttribute("version", frag.version());
147  containerGroup.createAttribute("type", frag.type());
148  containerGroup.createAttribute("sequence_id", frag.sequenceID());
149  containerGroup.createAttribute("fragment_id", frag.fragmentID());
150  containerGroup.createAttribute("timestamp", frag.timestamp());
151 
152  containerGroup.createAttribute("container_block_count", cf.block_count());
153  containerGroup.createAttribute("container_fragment_type", cf.fragment_type());
154  containerGroup.createAttribute("container_version", cf.metadata()->version);
155  containerGroup.createAttribute("container_missing_data", cf.missing_data());
156 
157  TLOG(TLVL_INSERTONE) << "insertOne: Writing Container contained Fragments";
158  for (size_t ii = 0; ii < cf.block_count(); ++ii)
159  {
160  if (ii != 0)
161  {
162  fragPtr = cf.at(ii);
163  }
164  writeFragment_(containerGroup, *fragPtr);
165  }
166  }
167  else if (cf.block_count() == 1 || cf.fragment_type() == 10)
168  {
169  TLOG(TLVL_INSERTONE) << "insertOne: Getting Fragment type name";
170  auto fragPtr = cf.at(0);
171  auto typeName = nameHelper_->GetInstanceNameForFragment(*fragPtr).second;
172  if (!eventGroup.exist(typeName))
173  {
174  TLOG(TLVL_INSERTONE) << "insertOne: Creating group for type " << typeName;
175  eventGroup.createGroup(typeName);
176  }
177 
178  TLOG(TLVL_INSERTONE) << "insertOne: Creating type group";
179  auto typeGroup = eventGroup.getGroup(typeName);
180  for (size_t ii = 0; ii < cf.block_count(); ++ii)
181  {
182  if (ii != 0)
183  {
184  fragPtr = cf.at(ii);
185  }
186  writeFragment_(typeGroup, *fragPtr);
187  }
188  }
189 #if 0
190  else
191  {
192  TLOG(TLVL_INSERTONE) << "insertOne: Writing Empty Container Fragment as standard Fragment";
193  auto typeName = nameHelper_->GetInstanceNameForFragment(frag).second;
194  if (!eventGroup.exist(typeName))
195  {
196  TLOG(TLVL_INSERTONE) << "insertOne: Creating group for type " << typeName;
197  eventGroup.createGroup(typeName);
198  }
199  auto typeGroup = eventGroup.getGroup(typeName);
200 
201  writeFragment_(typeGroup, frag);
202  }
203 #endif
204  }
205  }
206  else if (frag.type() == 5) // Timing
207  {
208  if (typeOfInterest(frag.type()))
209  {
210  TLOG(TLVL_INSERTONE) << "insertOne: Writing Timing Fragment";
211  writeFragment_(eventGroup, frag);
212  }
213  }
214  else
215  {
216  if (typeOfInterest(frag.type()))
217  {
218  TLOG(TLVL_INSERTONE) << "insertOne: Writing non-Container Fragment";
219  auto typeName = nameHelper_->GetInstanceNameForFragment(frag).second;
220  if (!eventGroup.exist(typeName))
221  {
222  TLOG(TLVL_INSERTONE) << "insertOne: Creating group for type " << typeName;
223  eventGroup.createGroup(typeName);
224  }
225  auto typeGroup = eventGroup.getGroup(typeName);
226 
227  writeFragment_(typeGroup, frag);
228  }
229  }
230  TLOG(TLVL_TRACE) << "insertOne END";
231 }
232 
234 {
235  TLOG(TLVL_TRACE) << "insertMany BEGIN";
236  for (auto& f : fs) insertOne(f);
237  TLOG(TLVL_TRACE) << "insertMany END";
238 }
239 
240 void artdaq::hdf5::HighFiveGeoSplitPDSPSample::insertHeader(artdaq::detail::RawEventHeader const& hdr)
241 {
242  TLOG(TLVL_TRACE) << "insertHeader BEGIN";
243  if (!file_->exist(std::to_string(hdr.sequence_id)))
244  {
245  TLOG(TLVL_INSERTHEADER) << "insertHeader: Creating group for event " << hdr.sequence_id;
246  file_->createGroup(std::to_string(hdr.sequence_id));
247  }
248  auto eventGroup = file_->getGroup(std::to_string(hdr.sequence_id));
249  eventGroup.createAttribute("run_id", hdr.run_id);
250  eventGroup.createAttribute("subrun_id", hdr.subrun_id);
251  eventGroup.createAttribute("event_id", hdr.event_id);
252  eventGroup.createAttribute("is_complete", hdr.is_complete);
253  TLOG(TLVL_TRACE) << "insertHeader END";
254 }
255 
256 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> artdaq::hdf5::HighFiveGeoSplitPDSPSample::readNextEvent()
257 {
258  TLOG(TLVL_DEBUG) << "readNextEvent BEGIN";
259  std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> output;
260 
261  TLOG(TLVL_READNEXTEVENT) << "readNextEvent: Finding next event group in file";
262  auto groupNames = file_->listObjectNames();
263  while (eventIndex_ < groupNames.size() && file_->getObjectType(groupNames[eventIndex_]) != HighFive::ObjectType::Group)
264  {
265  eventIndex_++;
266  }
267 
268  if (groupNames.size() <= eventIndex_)
269  {
270  TLOG(TLVL_INFO) << "readNextEvent: No more events in file!";
271  }
272  else
273  {
274  TLOG(TLVL_READNEXTEVENT) << "readNextEvent: Getting event group " << groupNames[eventIndex_];
275  auto event_group = file_->getGroup(groupNames[eventIndex_]);
276  auto fragment_type_names = event_group.listObjectNames();
277 
278  for (auto& fragment_type : fragment_type_names)
279  {
280  if (event_group.getObjectType(fragment_type) != HighFive::ObjectType::Group)
281  {
282  continue;
283  }
284  TLOG(TLVL_READNEXTEVENT) << "readNextEvent: Reading Fragment type " << fragment_type;
285  auto type_group = event_group.getGroup(fragment_type);
286  auto fragment_names = type_group.listObjectNames();
287 
288  for (auto& fragment_name : fragment_names)
289  {
290  TLOG(TLVL_READNEXTEVENT) << "readNextEvent: Reading Fragment " << fragment_name;
291  auto node_type = type_group.getObjectType(fragment_name);
292  if (node_type == HighFive::ObjectType::Group)
293  {
294  TLOG(TLVL_READNEXTEVENT) << "readNextEvent: Fragment " << fragment_name << " is a Container";
295  auto container_group = type_group.getGroup(fragment_name);
296  Fragment::type_t type;
297  container_group.getAttribute("type").read<Fragment::type_t>(type);
298  Fragment::sequence_id_t seqID;
299  container_group.getAttribute("sequence_id").read(seqID);
300  Fragment::timestamp_t timestamp;
301  container_group.getAttribute("timestamp").read(timestamp);
302  Fragment::fragment_id_t fragID;
303  container_group.getAttribute("fragment_id").read(fragID);
304  if (!output.count(type))
305  {
306  output[type].reset(new Fragments());
307  }
308  output[type]->emplace_back(seqID, fragID);
309  output[type]->back().setTimestamp(timestamp);
310  output[type]->back().setSystemType(type);
311 
312  TLOG(TLVL_READNEXTEVENT) << "readNextEvent: Creating ContainerFragmentLoader for reading Container Fragments";
313  ContainerFragmentLoader cfl(output[type]->back());
314 
315  Fragment::type_t container_fragment_type;
316  int missing_data;
317  container_group.getAttribute("container_fragment_type").read(container_fragment_type);
318  container_group.getAttribute("container_missing_data").read(missing_data);
319 
320  cfl.set_fragment_type(container_fragment_type);
321  cfl.set_missing_data(missing_data);
322 
323  TLOG(TLVL_READNEXTEVENT) << "readNextEvent: Reading ContainerFragment Fragments";
324  auto fragments = container_group.listObjectNames();
325  for (auto& fragname : fragments)
326  {
327  if (container_group.getObjectType(fragname) != HighFive::ObjectType::Dataset) continue;
328  TLOG(TLVL_READNEXTEVENT_V) << "readNextEvent: Calling readFragment_ BEGIN";
329  auto frag = readFragment_(container_group.getDataSet(fragname, fragmentAProps_));
330  TLOG(TLVL_READNEXTEVENT_V) << "readNextEvent: Calling readFragment_ END";
331 
332  TLOG(TLVL_READNEXTEVENT_V) << "readNextEvent: Calling addFragment BEGIN";
333  cfl.addFragment(frag);
334  TLOG(TLVL_READNEXTEVENT_V) << "readNextEvent: addFragment END";
335  }
336  }
337  else if (node_type == HighFive::ObjectType::Dataset)
338  {
339  TLOG(TLVL_READNEXTEVENT_V) << "readNextEvent: Calling readFragment_ BEGIN";
340  auto frag = readFragment_(type_group.getDataSet(fragment_name, fragmentAProps_));
341  TLOG(TLVL_READNEXTEVENT_V) << "readNextEvent: Calling readFragment_ END";
342 
343  TLOG(TLVL_READNEXTEVENT) << "readNextEvent: Adding Fragment to output";
344  if (!output.count(frag->type()))
345  {
346  output[frag->type()].reset(new artdaq::Fragments());
347  }
348  output[frag->type()]->push_back(*frag.release());
349  }
350  }
351  }
352  }
353  ++eventIndex_;
354 
355  TLOG(TLVL_DEBUG)
356  << "readNextEvent END output.size() = " << output.size();
357  return output;
358 }
359 
360 std::unique_ptr<artdaq::detail::RawEventHeader> artdaq::hdf5::HighFiveGeoSplitPDSPSample::getEventHeader(artdaq::Fragment::sequence_id_t const& seqID)
361 {
362  TLOG(TLVL_TRACE) << "GetEventHeader BEGIN seqID=" << seqID;
363  if (!file_->exist(std::to_string(seqID)))
364  {
365  TLOG(TLVL_ERROR) << "Sequence ID " << seqID << " not found in input file!";
366  return nullptr;
367  }
368  auto seqIDGroup = file_->getGroup(std::to_string(seqID));
369 
370  uint32_t runID, subrunID, eventID;
371  uint64_t timestamp;
372  seqIDGroup.getAttribute("run_id").read(runID);
373  seqIDGroup.getAttribute("subrun_id").read(subrunID);
374  seqIDGroup.getAttribute("event_id").read(eventID);
375  seqIDGroup.getAttribute("timestamp").read(timestamp);
376 
377  TLOG(TLVL_GETEVENTHEADER) << "Creating EventHeader with runID " << runID << ", subrunID " << subrunID << ", eventID " << eventID << ", timestamp " << timestamp << " (seqID " << seqID << ")";
378  artdaq::detail::RawEventHeader hdr(runID, subrunID, eventID, seqID, timestamp);
379  seqIDGroup.getAttribute("is_complete").read(hdr.is_complete);
380 
381  TLOG(TLVL_TRACE) << "GetEventHeader END";
382  return std::make_unique<artdaq::detail::RawEventHeader>(hdr);
383 }
384 
385 void artdaq::hdf5::HighFiveGeoSplitPDSPSample::writeFragment_(HighFive::Group& group, artdaq::Fragment const& frag)
386 {
387  TLOG(TLVL_TRACE) << "writeFragment_ BEGIN";
388 
389  std::string datasetNameBase = "TimeSlice";
390  std::string datasetName = "TimeSlice0";
391  int apaNumber = -1;
392 
393  switch (frag.type())
394  {
395  case 2: // TPC
396  apaNumber = 3;
397  datasetNameBase = "APA3." + std::to_string((int)(frag.fragmentID() % 10));
398  datasetName = datasetNameBase;
399  break;
400  case 3: // Photon
401  apaNumber = (int)(frag.fragmentID() / 10);
402  datasetNameBase = "APA" + std::to_string(apaNumber) + "." + std::to_string(-1 + (int)(frag.fragmentID() % 10));
403  datasetName = datasetNameBase;
404  break;
405  case 5: // Timing
406  datasetNameBase = "Timing";
407  datasetName = datasetNameBase;
408  break;
409  case 8: // FELIX
410  apaNumber = ((int)(frag.fragmentID() / 10)) % 10;
411  if (apaNumber == 3) { apaNumber = 2; }
412  datasetNameBase = "APA" + std::to_string(apaNumber) + "." + std::to_string((int)(frag.fragmentID() % 10));
413  datasetName = datasetNameBase;
414  break;
415  }
416 
417  if (apaNumber != apaOfInterest) { return; }
418 
419  int counter = 1;
420  while (group.exist(datasetName))
421  {
422  //TLOG(TLVL_WRITEFRAGMENT) << "writeFragment_: Duplicate Fragment ID " << frag.fragmentID() << " detected. If this is a ContainerFragment, this is expected, otherwise check configuration!";
423  datasetName = datasetNameBase + std::to_string(counter);
424  counter++;
425  }
426 
427  TLOG(TLVL_WRITEFRAGMENT) << "writeFragment_: Creating DataSpace";
428  HighFive::DataSpace fragmentSpace = HighFive::DataSpace({frag.size() - frag.headerSizeWords(), 1});
429  auto fragDset = group.createDataSet<RawDataType>(datasetName, fragmentSpace, fragmentCProps_, fragmentAProps_);
430 
431  TLOG(TLVL_WRITEFRAGMENT) << "writeFragment_: Creating Attributes from Fragment Header";
432  auto fragHdr = frag.fragmentHeader();
433  fragDset.createAttribute("word_count", fragHdr.word_count);
434  fragDset.createAttribute("fragment_data_size", frag.size() - frag.headerSizeWords());
435  fragDset.createAttribute("version", fragHdr.version);
436  fragDset.createAttribute("type", fragHdr.type);
437  fragDset.createAttribute("metadata_word_count", fragHdr.metadata_word_count);
438 
439  fragDset.createAttribute("sequence_id", fragHdr.sequence_id);
440  fragDset.createAttribute("fragment_id", fragHdr.fragment_id);
441 
442  fragDset.createAttribute("timestamp", fragHdr.timestamp);
443 
444  fragDset.createAttribute("valid", fragHdr.valid);
445  fragDset.createAttribute("complete", fragHdr.complete);
446  //fragDset.createAttribute("atime_ns", fragHdr.atime_ns);
447  //fragDset.createAttribute("atime_s", fragHdr.atime_s);
448 
449  double duneTime = fragHdr.timestamp * 0.000000020;
450  timespec tsp;
451  tsp.tv_sec = (time_t)duneTime;
452  tsp.tv_nsec = (long)((duneTime - tsp.tv_sec) * 1000000000.0);
453  std::string timeString = artdaq::TimeUtils::convertUnixTimeToString(tsp);
454  fragDset.createAttribute("time_string", timeString);
455 
456  TLOG(TLVL_WRITEFRAGMENT_V) << "writeFragment_: Writing Fragment payload START";
457  fragDset.write(frag.headerBegin() + frag.headerSizeWords());
458  TLOG(TLVL_WRITEFRAGMENT_V) << "writeFragment_: Writing Fragment payload DONE";
459  TLOG(TLVL_TRACE) << "writeFragment_ END";
460 }
461 
462 artdaq::FragmentPtr artdaq::hdf5::HighFiveGeoSplitPDSPSample::readFragment_(HighFive::DataSet const& dataset)
463 {
464  TLOG(TLVL_TRACE) << "readFragment_ BEGIN";
465  size_t fragSize;
466  dataset.getAttribute("fragment_data_size").read(fragSize);
467  TLOG(TLVL_READFRAGMENT) << "readFragment_: Fragment size " << fragSize << ", dataset size " << dataset.getDimensions()[0];
468 
469  artdaq::FragmentPtr frag(new Fragment(fragSize));
470 
471  artdaq::Fragment::type_t type;
472  size_t metadata_size;
473  artdaq::Fragment::sequence_id_t seqID;
474  artdaq::Fragment::fragment_id_t fragID;
475  artdaq::Fragment::timestamp_t timestamp;
476  int valid, complete, atime_ns, atime_s;
477 
478  TLOG(TLVL_READFRAGMENT) << "readFragment_: Reading Fragment header fields from dataset attributes";
479  dataset.getAttribute("type").read(type);
480  dataset.getAttribute("metadata_word_count").read(metadata_size);
481 
482  dataset.getAttribute("sequence_id").read(seqID);
483  dataset.getAttribute("fragment_id").read(fragID);
484 
485  dataset.getAttribute("timestamp").read(timestamp);
486 
487  dataset.getAttribute("valid").read(valid);
488  dataset.getAttribute("complete").read(complete);
489  dataset.getAttribute("atime_ns").read(atime_ns);
490  dataset.getAttribute("atime_s").read(atime_s);
491 
492  auto fragHdr = frag->fragmentHeader();
493  fragHdr.type = type;
494  fragHdr.metadata_word_count = metadata_size;
495 
496  fragHdr.sequence_id = seqID;
497  fragHdr.fragment_id = fragID;
498 
499  fragHdr.timestamp = timestamp;
500 
501  fragHdr.valid = valid;
502  fragHdr.complete = complete;
503  fragHdr.atime_ns = atime_ns;
504  fragHdr.atime_s = atime_s;
505 
506  TLOG(TLVL_READFRAGMENT) << "readFragment_: Copying header into Fragment";
507  memcpy(frag->headerAddress(), &fragHdr, sizeof(fragHdr));
508 
509  TLOG(TLVL_READFRAGMENT_V) << "readFragment_: Reading payload data into Fragment BEGIN";
510  dataset.read(frag->headerAddress() + frag->headerSizeWords());
511  TLOG(TLVL_READFRAGMENT_V) << "readFragment_: Reading payload data into Fragment END";
512 
513  TLOG(TLVL_TRACE) << "readFragment_ END";
514  return frag;
515 }
516 
517 // fragment_type_map: [[1, "MISSED"], [2, "TPC"], [3, "PHOTON"], [4, "TRIGGER"], [5, "TIMING"], [6, "TOY1"], [7, "TOY2"], [8, "FELIX"], [9, "CRT"], [10, "CTB"], [11, "CPUHITS"], [12, "DEVBOARDHITS"], [13, "UNKNOWN"]]
518 
519 bool artdaq::hdf5::HighFiveGeoSplitPDSPSample::typeOfInterest(artdaq::Fragment::type_t theType)
520 {
521  for (unsigned int idx = 0; idx < typesOfInterest.size(); ++idx)
522  {
523  if (theType == typesOfInterest[idx]) { return true; }
524  }
525  return false;
526 }
527 
528 DEFINE_ARTDAQ_DATASET_PLUGIN(artdaq::hdf5::HighFiveGeoSplitPDSPSample)
virtual ~HighFiveGeoSplitPDSPSample()
HighFiveGeoSplitPDSPSample Destructor.
HighFiveGeoSplitPDSPSample(fhicl::ParameterSet const &ps)
HighFiveGeoSplitPDSPSample Constructor.
void insertMany(artdaq::Fragments const &frags) override
Write Fragments to HDF5.
std::unique_ptr< artdaq::detail::RawEventHeader > getEventHeader(artdaq::Fragment::sequence_id_t const &seqID) override
Read an Event Header from HDF55.
Sample ProtoDUNE HDF5 writer that only writes certain Fragment types to output.
void insertHeader(artdaq::detail::RawEventHeader const &hdr) override
Write a RawEventHeader to HDF5.
FragmentDatasetMode mode_
Mode of this FragmentDataset, either FragmentDatasetMode::Write or FragmentDatasetMode::Read.
Base class that defines methods for reading and writing to HDF5 files via various implementation plug...
void insertOne(artdaq::Fragment const &frag) override
Write a Fragment to HDF5.
std::unordered_map< artdaq::Fragment::type_t, std::unique_ptr< artdaq::Fragments > > readNextEvent() override
Read event data from HDF5.