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
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"
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;
65 std::unique_ptr<HighFive::File> file_;
67 HighFive::DataSetCreateProps fragmentCProps_;
68 HighFive::DataSetAccessProps fragmentAProps_;
70 void writeFragment_(HighFive::Group& group, artdaq::Fragment
const& frag);
71 artdaq::FragmentPtr readFragment_(HighFive::DataSet
const& dataset);
73 bool typeOfInterest(artdaq::Fragment::type_t theType);
74 std::array<int, 4> typesOfInterest;
81 :
FragmentDataset(ps, ps.get<std::string>(
"mode",
"write")), file_(nullptr), eventIndex_(0)
83 TLOG(TLVL_DEBUG) <<
"HighFiveGeoSplitPDSPSample CONSTRUCTOR BEGIN";
84 if (
mode_ == FragmentDatasetMode::Read)
86 file_.reset(
new HighFive::File(ps.get<std::string>(
"fileName"), HighFive::File::ReadOnly));
90 file_.reset(
new HighFive::File(ps.get<std::string>(
"fileName"), HighFive::File::OpenOrCreate | HighFive::File::Truncate));
93 typesOfInterest = ps.get<std::array<int, 4>>(
"fragmentTypesOfInterest");
94 apaOfInterest = ps.get<
int>(
"apaOfInterest");
96 TLOG(TLVL_DEBUG) <<
"HighFiveGeoSplitPDSPSample CONSTRUCTOR END";
101 TLOG(TLVL_DEBUG) <<
"~HighFiveGeoSplitPDSPSample Begin/End ";
107 TLOG(TLVL_TRACE) <<
"insertOne BEGIN";
108 if (!file_->exist(std::to_string(frag.sequenceID())))
110 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for sequence ID " << frag.sequenceID();
111 file_->createGroup(std::to_string(frag.sequenceID()));
113 auto eventGroup = file_->getGroup(std::to_string(frag.sequenceID()));
115 if (frag.type() == Fragment::ContainerFragmentType)
117 TLOG(TLVL_INSERTONE) <<
"insertOne: Processing ContainerFragment";
118 ContainerFragment cf(frag);
120 if (typeOfInterest(cf.fragment_type()))
122 if (cf.fragment_type() != 10 && (cf.block_count() > 1 || cf.fragment_type() == 9))
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))
129 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
130 eventGroup.createGroup(typeName);
133 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group and setting attributes";
134 auto typeGroup = eventGroup.getGroup(typeName);
135 std::string containerName =
"Container0";
138 while (typeGroup.exist(containerName))
141 containerName =
"Container" + std::to_string(counter);
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());
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());
157 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing Container contained Fragments";
158 for (
size_t ii = 0; ii < cf.block_count(); ++ii)
164 writeFragment_(containerGroup, *fragPtr);
167 else if (cf.block_count() == 1 || cf.fragment_type() == 10)
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))
174 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
175 eventGroup.createGroup(typeName);
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)
186 writeFragment_(typeGroup, *fragPtr);
192 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing Empty Container Fragment as standard Fragment";
193 auto typeName = nameHelper_->GetInstanceNameForFragment(frag).second;
194 if (!eventGroup.exist(typeName))
196 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
197 eventGroup.createGroup(typeName);
199 auto typeGroup = eventGroup.getGroup(typeName);
201 writeFragment_(typeGroup, frag);
206 else if (frag.type() == 5)
208 if (typeOfInterest(frag.type()))
210 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing Timing Fragment";
211 writeFragment_(eventGroup, frag);
216 if (typeOfInterest(frag.type()))
218 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing non-Container Fragment";
219 auto typeName = nameHelper_->GetInstanceNameForFragment(frag).second;
220 if (!eventGroup.exist(typeName))
222 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
223 eventGroup.createGroup(typeName);
225 auto typeGroup = eventGroup.getGroup(typeName);
227 writeFragment_(typeGroup, frag);
230 TLOG(TLVL_TRACE) <<
"insertOne END";
235 TLOG(TLVL_TRACE) <<
"insertMany BEGIN";
236 for (
auto& f : fs) insertOne(f);
237 TLOG(TLVL_TRACE) <<
"insertMany END";
242 TLOG(TLVL_TRACE) <<
"insertHeader BEGIN";
243 if (!file_->exist(std::to_string(hdr.sequence_id)))
245 TLOG(TLVL_INSERTHEADER) <<
"insertHeader: Creating group for event " << hdr.sequence_id;
246 file_->createGroup(std::to_string(hdr.sequence_id));
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";
258 TLOG(TLVL_DEBUG) <<
"readNextEvent BEGIN";
259 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> output;
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)
268 if (groupNames.size() <= eventIndex_)
270 TLOG(TLVL_INFO) <<
"readNextEvent: No more events in file!";
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();
278 for (
auto& fragment_type : fragment_type_names)
280 if (event_group.getObjectType(fragment_type) != HighFive::ObjectType::Group)
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();
288 for (
auto& fragment_name : fragment_names)
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)
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))
306 output[type].reset(
new Fragments());
308 output[type]->emplace_back(seqID, fragID);
309 output[type]->back().setTimestamp(timestamp);
310 output[type]->back().setSystemType(type);
312 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Creating ContainerFragmentLoader for reading Container Fragments";
313 ContainerFragmentLoader cfl(output[type]->back());
315 Fragment::type_t container_fragment_type;
317 container_group.getAttribute(
"container_fragment_type").read(container_fragment_type);
318 container_group.getAttribute(
"container_missing_data").read(missing_data);
320 cfl.set_fragment_type(container_fragment_type);
321 cfl.set_missing_data(missing_data);
323 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Reading ContainerFragment Fragments";
324 auto fragments = container_group.listObjectNames();
325 for (
auto& fragname : fragments)
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";
332 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling addFragment BEGIN";
333 cfl.addFragment(frag);
334 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: addFragment END";
337 else if (node_type == HighFive::ObjectType::Dataset)
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";
343 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Adding Fragment to output";
344 if (!output.count(frag->type()))
346 output[frag->type()].reset(
new artdaq::Fragments());
348 output[frag->type()]->push_back(*frag.release());
356 <<
"readNextEvent END output.size() = " << output.size();
362 TLOG(TLVL_TRACE) <<
"GetEventHeader BEGIN seqID=" << seqID;
363 if (!file_->exist(std::to_string(seqID)))
365 TLOG(TLVL_ERROR) <<
"Sequence ID " << seqID <<
" not found in input file!";
368 auto seqIDGroup = file_->getGroup(std::to_string(seqID));
370 uint32_t runID, subrunID, eventID;
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);
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);
381 TLOG(TLVL_TRACE) <<
"GetEventHeader END";
382 return std::make_unique<artdaq::detail::RawEventHeader>(hdr);
385 void artdaq::hdf5::HighFiveGeoSplitPDSPSample::writeFragment_(HighFive::Group& group, artdaq::Fragment
const& frag)
387 TLOG(TLVL_TRACE) <<
"writeFragment_ BEGIN";
389 std::string datasetNameBase =
"TimeSlice";
390 std::string datasetName =
"TimeSlice0";
397 datasetNameBase =
"APA3." + std::to_string((
int)(frag.fragmentID() % 10));
398 datasetName = datasetNameBase;
401 apaNumber = (int)(frag.fragmentID() / 10);
402 datasetNameBase =
"APA" + std::to_string(apaNumber) +
"." + std::to_string(-1 + (
int)(frag.fragmentID() % 10));
403 datasetName = datasetNameBase;
406 datasetNameBase =
"Timing";
407 datasetName = datasetNameBase;
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;
417 if (apaNumber != apaOfInterest) {
return; }
420 while (group.exist(datasetName))
423 datasetName = datasetNameBase + std::to_string(counter);
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_);
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);
439 fragDset.createAttribute(
"sequence_id", fragHdr.sequence_id);
440 fragDset.createAttribute(
"fragment_id", fragHdr.fragment_id);
442 fragDset.createAttribute(
"timestamp", fragHdr.timestamp);
444 fragDset.createAttribute(
"valid", fragHdr.valid);
445 fragDset.createAttribute(
"complete", fragHdr.complete);
449 double duneTime = fragHdr.timestamp * 0.000000020;
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);
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";
462 artdaq::FragmentPtr artdaq::hdf5::HighFiveGeoSplitPDSPSample::readFragment_(HighFive::DataSet
const& dataset)
464 TLOG(TLVL_TRACE) <<
"readFragment_ BEGIN";
466 dataset.getAttribute(
"fragment_data_size").read(fragSize);
467 TLOG(TLVL_READFRAGMENT) <<
"readFragment_: Fragment size " << fragSize <<
", dataset size " << dataset.getDimensions()[0];
469 artdaq::FragmentPtr frag(
new Fragment(fragSize));
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;
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);
482 dataset.getAttribute(
"sequence_id").read(seqID);
483 dataset.getAttribute(
"fragment_id").read(fragID);
485 dataset.getAttribute(
"timestamp").read(timestamp);
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);
492 auto fragHdr = frag->fragmentHeader();
494 fragHdr.metadata_word_count = metadata_size;
496 fragHdr.sequence_id = seqID;
497 fragHdr.fragment_id = fragID;
499 fragHdr.timestamp = timestamp;
501 fragHdr.valid = valid;
502 fragHdr.complete = complete;
503 fragHdr.atime_ns = atime_ns;
504 fragHdr.atime_s = atime_s;
506 TLOG(TLVL_READFRAGMENT) <<
"readFragment_: Copying header into Fragment";
507 memcpy(frag->headerAddress(), &fragHdr,
sizeof(fragHdr));
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";
513 TLOG(TLVL_TRACE) <<
"readFragment_ END";
519 bool artdaq::hdf5::HighFiveGeoSplitPDSPSample::typeOfInterest(artdaq::Fragment::type_t theType)
521 for (
unsigned int idx = 0; idx < typesOfInterest.size(); ++idx)
523 if (theType == typesOfInterest[idx]) {
return true; }
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.