2 #define TRACE_NAME "HighFiveGeoCmpltPDSPSample"
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-demo-hdf5/HDF5/FragmentDataset.hh"
16 #include "artdaq-demo-hdf5/HDF5/highFive/HighFive/include/highfive/H5File.hpp"
17 #include "artdaq-core/Utilities/TimeUtils.hh"
27 void insertOne(artdaq::Fragment
const& frag)
override;
28 void insertMany(artdaq::Fragments
const& frags)
override;
29 void insertHeader(artdaq::detail::RawEventHeader
const& hdr)
override;
30 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>>
readNextEvent()
override;
31 std::unique_ptr<artdaq::detail::RawEventHeader>
getEventHeader(artdaq::Fragment::sequence_id_t
const& seqID)
override;
34 std::unique_ptr<HighFive::File> file_;
36 HighFive::DataSetCreateProps fragmentCProps_;
37 HighFive::DataSetAccessProps fragmentAProps_;
39 void writeFragment_(HighFive::Group& group, artdaq::Fragment
const& frag);
40 artdaq::FragmentPtr readFragment_(HighFive::DataSet
const& dataset);
45 artdaq::hdf5::HighFiveGeoCmpltPDSPSample::HighFiveGeoCmpltPDSPSample(fhicl::ParameterSet
const& ps)
46 : FragmentDataset(ps, ps.get<std::string>(
"mode",
"write")), file_(nullptr), eventIndex_(0)
48 TLOG(TLVL_DEBUG) <<
"HighFiveGeoCmpltPDSPSample CONSTRUCTOR BEGIN";
49 if (
mode_ == FragmentDatasetMode::Read)
51 file_.reset(
new HighFive::File(ps.get<std::string>(
"fileName"), HighFive::File::ReadOnly));
55 file_.reset(
new HighFive::File(ps.get<std::string>(
"fileName"), HighFive::File::OpenOrCreate | HighFive::File::Truncate));
57 TLOG(TLVL_DEBUG) <<
"HighFiveGeoCmpltPDSPSample CONSTRUCTOR END";
60 artdaq::hdf5::HighFiveGeoCmpltPDSPSample::~HighFiveGeoCmpltPDSPSample()
62 TLOG(TLVL_DEBUG) <<
"~HighFiveGeoCmpltPDSPSample Begin/End ";
66 void artdaq::hdf5::HighFiveGeoCmpltPDSPSample::insertOne(artdaq::Fragment
const& frag)
68 TLOG(TLVL_TRACE) <<
"insertOne BEGIN";
69 if (!file_->exist(std::to_string(frag.sequenceID())))
71 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for sequence ID " << frag.sequenceID();
72 file_->createGroup(std::to_string(frag.sequenceID()));
74 auto eventGroup = file_->getGroup(std::to_string(frag.sequenceID()));
78 if (frag.type() == Fragment::ContainerFragmentType)
80 TLOG(TLVL_INSERTONE) <<
"insertOne: Processing ContainerFragment";
81 ContainerFragment cf(frag);
82 if (cf.fragment_type() != 10 && (cf.block_count() > 1 || cf.fragment_type() == 9))
84 TLOG(TLVL_INSERTONE) <<
"insertOne: Getting Fragment type name";
85 auto fragPtr = cf.at(0);
86 auto typeName = nameHelper_->GetInstanceNameForFragment(*fragPtr).second;
87 if (!eventGroup.exist(typeName))
89 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
90 eventGroup.createGroup(typeName);
93 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group and setting attributes";
94 auto typeGroup = eventGroup.getGroup(typeName);
95 std::string containerName =
"Container0";
98 while (typeGroup.exist(containerName))
101 containerName =
"Container" + std::to_string(counter);
105 auto containerGroup = typeGroup.createGroup(containerName);
106 containerGroup.createAttribute(
"version", frag.version());
107 containerGroup.createAttribute(
"type", frag.type());
108 containerGroup.createAttribute(
"sequence_id", frag.sequenceID());
109 containerGroup.createAttribute(
"fragment_id", frag.fragmentID());
110 containerGroup.createAttribute(
"timestamp", frag.timestamp());
112 containerGroup.createAttribute(
"container_block_count", cf.block_count());
113 containerGroup.createAttribute(
"container_fragment_type", cf.fragment_type());
114 containerGroup.createAttribute(
"container_version", cf.metadata()->version);
115 containerGroup.createAttribute(
"container_missing_data", cf.missing_data());
117 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing Container contained Fragments";
118 for (
size_t ii = 0; ii < cf.block_count(); ++ii)
124 writeFragment_(containerGroup, *fragPtr);
127 else if (cf.block_count() == 1 || cf.fragment_type() == 10)
129 TLOG(TLVL_INSERTONE) <<
"insertOne: Getting Fragment type name";
130 auto fragPtr = cf.at(0);
131 auto typeName = nameHelper_->GetInstanceNameForFragment(*fragPtr).second;
132 if (!eventGroup.exist(typeName))
134 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
135 eventGroup.createGroup(typeName);
138 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating type group";
139 auto typeGroup = eventGroup.getGroup(typeName);
140 for (
size_t ii = 0; ii < cf.block_count(); ++ii)
146 writeFragment_(typeGroup, *fragPtr);
152 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing Empty Container Fragment as standard Fragment";
153 auto typeName = nameHelper_->GetInstanceNameForFragment(frag).second;
154 if (!eventGroup.exist(typeName))
156 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
157 eventGroup.createGroup(typeName);
159 auto typeGroup = eventGroup.getGroup(typeName);
161 writeFragment_(typeGroup, frag);
165 else if (frag.type() == 5)
167 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing Timing Fragment";
168 writeFragment_(eventGroup, frag);
172 TLOG(TLVL_INSERTONE) <<
"insertOne: Writing non-Container Fragment";
173 auto typeName = nameHelper_->GetInstanceNameForFragment(frag).second;
174 if (!eventGroup.exist(typeName))
176 TLOG(TLVL_INSERTONE) <<
"insertOne: Creating group for type " << typeName;
177 eventGroup.createGroup(typeName);
179 auto typeGroup = eventGroup.getGroup(typeName);
181 writeFragment_(typeGroup, frag);
183 TLOG(TLVL_TRACE) <<
"insertOne END";
186 void artdaq::hdf5::HighFiveGeoCmpltPDSPSample::insertMany(artdaq::Fragments
const& fs)
188 TLOG(TLVL_TRACE) <<
"insertMany BEGIN";
189 for (
auto& f : fs) insertOne(f);
190 TLOG(TLVL_TRACE) <<
"insertMany END";
193 void artdaq::hdf5::HighFiveGeoCmpltPDSPSample::insertHeader(artdaq::detail::RawEventHeader
const& hdr)
195 TLOG(TLVL_TRACE) <<
"insertHeader BEGIN";
196 if (!file_->exist(std::to_string(hdr.sequence_id)))
198 TLOG(TLVL_INSERTHEADER) <<
"insertHeader: Creating group for event " << hdr.sequence_id;
199 file_->createGroup(std::to_string(hdr.sequence_id));
201 auto eventGroup = file_->getGroup(std::to_string(hdr.sequence_id));
202 eventGroup.createAttribute(
"run_id", hdr.run_id);
203 eventGroup.createAttribute(
"subrun_id", hdr.subrun_id);
204 eventGroup.createAttribute(
"event_id", hdr.event_id);
205 eventGroup.createAttribute(
"is_complete", hdr.is_complete);
206 TLOG(TLVL_TRACE) <<
"insertHeader END";
211 TLOG(TLVL_DEBUG) <<
"readNextEvent BEGIN";
212 std::unordered_map<artdaq::Fragment::type_t, std::unique_ptr<artdaq::Fragments>> output;
214 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Finding next event group in file";
215 auto groupNames = file_->listObjectNames();
216 while (eventIndex_ < groupNames.size() && file_->getObjectType(groupNames[eventIndex_]) != HighFive::ObjectType::Group)
221 if (groupNames.size() <= eventIndex_)
223 TLOG(TLVL_INFO) <<
"readNextEvent: No more events in file!";
227 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Getting event group " << groupNames[eventIndex_];
228 auto event_group = file_->getGroup(groupNames[eventIndex_]);
229 auto fragment_type_names = event_group.listObjectNames();
231 for (
auto& fragment_type : fragment_type_names)
233 if (event_group.getObjectType(fragment_type) != HighFive::ObjectType::Group)
237 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Reading Fragment type " << fragment_type;
238 auto type_group = event_group.getGroup(fragment_type);
239 auto fragment_names = type_group.listObjectNames();
241 for (
auto& fragment_name : fragment_names)
243 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Reading Fragment " << fragment_name;
244 auto node_type = type_group.getObjectType(fragment_name);
245 if (node_type == HighFive::ObjectType::Group)
247 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Fragment " << fragment_name <<
" is a Container";
248 auto container_group = type_group.getGroup(fragment_name);
249 Fragment::type_t type;
250 container_group.getAttribute(
"type").read<Fragment::type_t>(type);
251 Fragment::sequence_id_t seqID;
252 container_group.getAttribute(
"sequence_id").read(seqID);
253 Fragment::timestamp_t timestamp;
254 container_group.getAttribute(
"timestamp").read(timestamp);
255 Fragment::fragment_id_t fragID;
256 container_group.getAttribute(
"fragment_id").read(fragID);
257 if (!output.count(type))
259 output[type].reset(
new Fragments());
261 output[type]->emplace_back(seqID, fragID);
262 output[type]->back().setTimestamp(timestamp);
263 output[type]->back().setSystemType(type);
265 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Creating ContainerFragmentLoader for reading Container Fragments";
266 ContainerFragmentLoader cfl(output[type]->back());
268 Fragment::type_t container_fragment_type;
270 container_group.getAttribute(
"container_fragment_type").read(container_fragment_type);
271 container_group.getAttribute(
"container_missing_data").read(missing_data);
273 cfl.set_fragment_type(container_fragment_type);
274 cfl.set_missing_data(missing_data);
276 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Reading ContainerFragment Fragments";
277 auto fragments = container_group.listObjectNames();
278 for (
auto& fragname : fragments)
280 if (container_group.getObjectType(fragname) != HighFive::ObjectType::Dataset)
continue;
281 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling readFragment_ BEGIN";
282 auto frag = readFragment_(container_group.getDataSet(fragname, fragmentAProps_));
283 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling readFragment_ END";
285 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling addFragment BEGIN";
286 cfl.addFragment(frag);
287 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: addFragment END";
290 else if (node_type == HighFive::ObjectType::Dataset)
292 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling readFragment_ BEGIN";
293 auto frag = readFragment_(type_group.getDataSet(fragment_name, fragmentAProps_));
294 TLOG(TLVL_READNEXTEVENT_V) <<
"readNextEvent: Calling readFragment_ END";
296 TLOG(TLVL_READNEXTEVENT) <<
"readNextEvent: Adding Fragment to output";
297 if (!output.count(frag->type()))
299 output[frag->type()].reset(
new artdaq::Fragments());
301 output[frag->type()]->push_back(*frag.release());
309 <<
"readNextEvent END output.size() = " << output.size();
315 TLOG(TLVL_TRACE) <<
"GetEventHeader BEGIN seqID=" << seqID;
316 if (!file_->exist(std::to_string(seqID)))
318 TLOG(TLVL_ERROR) <<
"Sequence ID " << seqID <<
" not found in input file!";
321 auto seqIDGroup = file_->getGroup(std::to_string(seqID));
323 uint32_t runID, subrunID, eventID;
325 seqIDGroup.getAttribute(
"run_id").read(runID);
326 seqIDGroup.getAttribute(
"subrun_id").read(subrunID);
327 seqIDGroup.getAttribute(
"event_id").read(eventID);
328 seqIDGroup.getAttribute(
"timestamp").read(timestamp);
330 TLOG(TLVL_GETEVENTHEADER) <<
"Creating EventHeader with runID " << runID <<
", subrunID " << subrunID <<
", eventID " << eventID <<
", timestamp " << timestamp <<
" (seqID " << seqID <<
")";
331 artdaq::detail::RawEventHeader hdr(runID, subrunID, eventID, seqID, timestamp);
332 seqIDGroup.getAttribute(
"is_complete").read(hdr.is_complete);
334 TLOG(TLVL_TRACE) <<
"GetEventHeader END";
335 return std::make_unique<artdaq::detail::RawEventHeader>(hdr);
338 void artdaq::hdf5::HighFiveGeoCmpltPDSPSample::writeFragment_(HighFive::Group& group, artdaq::Fragment
const& frag)
340 TLOG(TLVL_TRACE) <<
"writeFragment_ BEGIN";
342 std::string datasetNameBase =
"TimeSlice";
343 std::string datasetName =
"TimeSlice0";
348 datasetNameBase =
"APA3." + std::to_string( (
int) (frag.fragmentID() % 10) );
349 datasetName = datasetNameBase;
352 datasetNameBase =
"APA" + std::to_string( (
int) (frag.fragmentID() / 10) ) +
"." + std::to_string( -1 + (
int) (frag.fragmentID() % 10) );
353 datasetName = datasetNameBase;
356 datasetNameBase =
"Timing";
357 datasetName = datasetNameBase;
360 int apaNumber = ((int) (frag.fragmentID() / 10)) % 10;
361 if (apaNumber == 3) {apaNumber = 2;}
362 datasetNameBase =
"APA" + std::to_string(apaNumber) +
"." + std::to_string( (
int) (frag.fragmentID() % 10) );
363 datasetName = datasetNameBase;
366 const uint8_t* tmpBeginPtr = frag.dataBeginBytes();
367 const uint8_t* tmpEndPtr = frag.dataEndBytes();
368 const uint64_t* beginPtr =
reinterpret_cast<const uint64_t*
>(tmpBeginPtr);
369 const uint64_t* endPtr =
reinterpret_cast<const uint64_t*
>(tmpEndPtr);
370 TLOG(TLVL_DEBUG) <<
"Data addresses in hex: " << std::hex << tmpBeginPtr <<
", " << tmpEndPtr <<
", " << beginPtr <<
", " << endPtr << std::dec;
372 uint64_t* mdPtr =
reinterpret_cast<uint64_t*
>(
const_cast<uint8_t*
>(frag.headerBeginBytes()) + frag.headerSizeBytes());
373 TLOG(TLVL_DEBUG) <<
"Metadata address and data: " << std::hex << mdPtr <<
", " << *mdPtr << std::dec;
375 TLOG(TLVL_DEBUG) <<
"Metadata address and data: " << std::hex << mdPtr <<
", " << *mdPtr << std::dec;
377 if (frag.size() == 349397) {
378 uint64_t* dataPtr =
const_cast<uint64_t*
>(beginPtr);
380 for (
int idx = 0; idx < 20; ++idx) {
381 TLOG(TLVL_DEBUG) << std::hex << *dataPtr << std::dec;
383 double duneTime = (*dataPtr) * 0.000000020;
385 tsp.tv_sec = (time_t) duneTime;
386 tsp.tv_nsec = (long) ((duneTime - tsp.tv_sec) * 1000000000.0);
387 std::string timeString = artdaq::TimeUtils::convertUnixTimeToString(tsp);
388 TLOG(TLVL_DEBUG) <<
"Frame time is " << timeString;
393 while (dataPtr <= endPtr) {
394 TLOG(TLVL_DEBUG) << std::hex << *dataPtr << std::dec;
396 double duneTime = (*dataPtr) * 0.000000020;
398 tsp.tv_sec = (time_t) duneTime;
399 tsp.tv_nsec = (long) ((duneTime - tsp.tv_sec) * 1000000000.0);
400 std::string timeString = artdaq::TimeUtils::convertUnixTimeToString(tsp);
401 TLOG(TLVL_DEBUG) <<
"Frame time is " << timeString;
407 TLOG(TLVL_DEBUG) <<
"Skipping Dataset: " << datasetName <<
", fragment size=" << frag.size();
414 while (group.exist(datasetName))
417 datasetName = datasetNameBase + std::to_string(counter);
421 TLOG(TLVL_WRITEFRAGMENT) <<
"writeFragment_: Creating DataSpace";
422 HighFive::DataSpace fragmentSpace = HighFive::DataSpace({frag.size() - frag.headerSizeWords(), 1});
423 auto fragDset = group.createDataSet<RawDataType>(datasetName, fragmentSpace, fragmentCProps_, fragmentAProps_);
425 TLOG(TLVL_WRITEFRAGMENT) <<
"writeFragment_: Creating Attributes from Fragment Header";
426 auto fragHdr = frag.fragmentHeader();
427 fragDset.createAttribute(
"word_count", fragHdr.word_count);
428 fragDset.createAttribute(
"fragment_data_size", frag.size() - frag.headerSizeWords());
429 fragDset.createAttribute(
"version", fragHdr.version);
430 fragDset.createAttribute(
"type", fragHdr.type);
431 fragDset.createAttribute(
"metadata_word_count", fragHdr.metadata_word_count);
433 fragDset.createAttribute(
"sequence_id", fragHdr.sequence_id);
434 fragDset.createAttribute(
"fragment_id", fragHdr.fragment_id);
436 fragDset.createAttribute(
"timestamp", fragHdr.timestamp);
438 fragDset.createAttribute(
"valid", fragHdr.valid);
439 fragDset.createAttribute(
"complete", fragHdr.complete);
443 double duneTime = fragHdr.timestamp * 0.000000020;
445 tsp.tv_sec = (time_t) duneTime;
446 tsp.tv_nsec = (long) ((duneTime - tsp.tv_sec) * 1000000000.0);
447 std::string timeString = artdaq::TimeUtils::convertUnixTimeToString(tsp);
448 TLOG(TLVL_DEBUG) <<
"Trigger time is " << timeString <<
" for Dataset: " << datasetName;
449 fragDset.createAttribute(
"time_string", timeString);
451 TLOG(TLVL_WRITEFRAGMENT_V) <<
"writeFragment_: Writing Fragment payload START";
452 fragDset.write(frag.headerBegin() + frag.headerSizeWords());
453 TLOG(TLVL_WRITEFRAGMENT_V) <<
"writeFragment_: Writing Fragment payload DONE";
454 TLOG(TLVL_TRACE) <<
"writeFragment_ END";
457 artdaq::FragmentPtr artdaq::hdf5::HighFiveGeoCmpltPDSPSample::readFragment_(HighFive::DataSet
const& dataset)
459 TLOG(TLVL_TRACE) <<
"readFragment_ BEGIN";
461 dataset.getAttribute(
"fragment_data_size").read(fragSize);
462 TLOG(TLVL_READFRAGMENT) <<
"readFragment_: Fragment size " << fragSize <<
", dataset size " << dataset.getDimensions()[0];
464 artdaq::FragmentPtr frag(
new Fragment(fragSize));
466 artdaq::Fragment::type_t type;
467 size_t metadata_size;
468 artdaq::Fragment::sequence_id_t seqID;
469 artdaq::Fragment::fragment_id_t fragID;
470 artdaq::Fragment::timestamp_t timestamp;
471 int valid, complete, atime_ns, atime_s;
473 TLOG(TLVL_READFRAGMENT) <<
"readFragment_: Reading Fragment header fields from dataset attributes";
474 dataset.getAttribute(
"type").read(type);
475 dataset.getAttribute(
"metadata_word_count").read(metadata_size);
477 dataset.getAttribute(
"sequence_id").read(seqID);
478 dataset.getAttribute(
"fragment_id").read(fragID);
480 dataset.getAttribute(
"timestamp").read(timestamp);
482 dataset.getAttribute(
"valid").read(valid);
483 dataset.getAttribute(
"complete").read(complete);
484 dataset.getAttribute(
"atime_ns").read(atime_ns);
485 dataset.getAttribute(
"atime_s").read(atime_s);
487 auto fragHdr = frag->fragmentHeader();
489 fragHdr.metadata_word_count = metadata_size;
491 fragHdr.sequence_id = seqID;
492 fragHdr.fragment_id = fragID;
494 fragHdr.timestamp = timestamp;
496 fragHdr.valid = valid;
497 fragHdr.complete = complete;
498 fragHdr.atime_ns = atime_ns;
499 fragHdr.atime_s = atime_s;
501 TLOG(TLVL_READFRAGMENT) <<
"readFragment_: Copying header into Fragment";
502 memcpy(frag->headerAddress(), &fragHdr,
sizeof(fragHdr));
504 TLOG(TLVL_READFRAGMENT_V) <<
"readFragment_: Reading payload data into Fragment BEGIN";
505 dataset.read(frag->headerAddress() + frag->headerSizeWords());
506 TLOG(TLVL_READFRAGMENT_V) <<
"readFragment_: Reading payload data into Fragment END";
508 TLOG(TLVL_TRACE) <<
"readFragment_ END";
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...
std::unordered_map< artdaq::Fragment::type_t, std::unique_ptr< artdaq::Fragments > > readNextEvent() override
Read the next event from the Dataset (HDF5 file)
std::unique_ptr< artdaq::detail::RawEventHeader > getEventHeader(artdaq::Fragment::sequence_id_t const &seqID) override
Read a RawEventHeader from the Dataset (HDF5 file)