HDFFileReader.cc
Go to the documentation of this file.
5 #include "artdaq-core/Utilities/TimeUtils.hh"
6 #include <boost/algorithm/string.hpp>
7 #include <regex>
8 #include <set>
9 #include <sstream>
10 
11 #include <sys/time.h>
12 #include <sys/resource.h>
13 
14 namespace dune {
15  namespace HDFFileReader {
16 
17  // *****************************************
18  // *** General-purpose data and routines ***
19  // *****************************************
20 
22  {
23  HDFFileInfoPtr hdfFileInfoPtr(new HDFFileInfo());
24  hdfFileInfoPtr->filePtr = H5Fopen(fileName.data(), H5F_ACC_RDONLY, H5P_DEFAULT);
25  hdfFileInfoPtr->bytesWritten = 0;
26  hdfFileInfoPtr->fileName = fileName;
27  hdfFileInfoPtr->runNumber = 0; // don't know it yet. Fill it when we get fragments.
28  hdfFileInfoPtr->dataFormatVersion = 0;
29 
30  hid_t grp = H5Gopen(hdfFileInfoPtr->filePtr,"/", H5P_DEFAULT);
31  if (attrExists(grp,"data_format_version"))
32  {
33  hid_t ga = H5Aopen_name(grp,"data_format_version");
34  H5Aread(ga, H5Aget_type(ga), &hdfFileInfoPtr->dataFormatVersion);
35  H5Aclose(ga);
36  }
37  H5Gclose(grp);
38  return hdfFileInfoPtr;
39  }
40 
42  {
43  H5Fclose(oldHdfFileInfoPtr->filePtr);
44  oldHdfFileInfoPtr->filePtr = 0;
45 
46  HDFFileInfoPtr newHdfFileInfoPtr(new HDFFileInfo());
47  newHdfFileInfoPtr->filePtr = H5Fopen(oldHdfFileInfoPtr->fileName.data(), H5F_ACC_RDONLY, H5P_DEFAULT);
48  newHdfFileInfoPtr->bytesWritten = 0;
49  newHdfFileInfoPtr->fileName = oldHdfFileInfoPtr->fileName;
50  newHdfFileInfoPtr->runNumber = oldHdfFileInfoPtr->runNumber; // gets overwritten but fill it anyway
51  newHdfFileInfoPtr->dataFormatVersion = oldHdfFileInfoPtr->dataFormatVersion;
52  return newHdfFileInfoPtr;
53  }
54 
55  void closeFile(HDFFileInfoPtr hdfFileInfoPtr)
56  {
57  H5Fclose(hdfFileInfoPtr->filePtr);
58  hdfFileInfoPtr->filePtr = 0;
59  }
60 
61  std::list<std::string> getTopLevelGroupNames(HDFFileInfoPtr& hdfFileInfoPtr)
62  {
63  hid_t grp = H5Gopen(hdfFileInfoPtr->filePtr,"/", H5P_DEFAULT);
64  std::list<std::string> theList = getMidLevelGroupNames(grp);
65  H5Gclose(grp);
66  return theList;
67  }
68 
69  std::list<std::string> getMidLevelGroupNames(hid_t grp)
70  {
71  std::list<std::string> theList;
72  hsize_t nobj = 0;
73  H5Gget_num_objs(grp,&nobj);
74  for (hsize_t idx = 0; idx < nobj; ++idx)
75  {
76  hsize_t len = H5Gget_objname_by_idx(grp, idx, NULL, 0 );
77  char *memb_name = new char(len+1);
78  H5Gget_objname_by_idx(grp, idx, memb_name, len+1 );
79  theList.emplace_back(memb_name);
80  delete[] memb_name;
81  }
82  return theList;
83  }
84 
85  hid_t getGroupFromPath(HDFFileInfoPtr& hdfFileInfoPtr, const std::string &path)
86  {
87  hid_t grp = H5Gopen(hdfFileInfoPtr->filePtr,path.data(),H5P_DEFAULT);
88  return grp;
89  }
90 
91  // check to see if an attribute exists -- quiet the error messages when probing
92  // using example from the HDF5 documentation
93 
94  bool attrExists(hid_t object, const std::string &attrname)
95  {
96  // Save old error handler
97  H5E_auto_t old_func;
98  void *old_client_data;
99  H5Eget_auto(H5E_DEFAULT,&old_func, &old_client_data);
100 
101  // Turn off error handling */
102  H5Eset_auto(H5E_DEFAULT,NULL, NULL);
103 
104  // Probe. On failure, retval is supposed to be negative
105 
106  hid_t retval = H5Aopen_name(object, attrname.data());
107 
108  // Restore previous error handler
109  H5Eset_auto(H5E_DEFAULT,old_func, old_client_data);
110 
111  bool result = (retval >= 0);
112  return result;
113  }
114 
115  // ************************************************
116  // *** Trigger-Record-related data and routines ***
117  // ************************************************
118 
119  // We don't know the run number until we read some fragments in, so this method modifies the run number
120  // in hdfFileInfoPtr
121 
122  FragmentListsByType getFragmentsForEvent(HDFFileInfoPtr& hdfFileInfoPtr, const std::string& topLevelGroupName)
123  {
124  FragmentListsByType fragmentMap;
125  artdaq::Fragment::fragment_id_t sampleFragmentID = 1001;
126 
127  hid_t requestedGroup = getGroupFromPath(hdfFileInfoPtr, topLevelGroupName);
128  {
129  std::list<std::string> detectorTypeNames = getMidLevelGroupNames(requestedGroup);
130  for (auto& detectorTypeName : detectorTypeNames)
131  {
132  if (detectorTypeName != "TPC") continue; // skip non-TPC fragments for now
133  std::string dtnameloc = detectorTypeName;
134  if (dtnameloc == "TPC")
135  {
136  dtnameloc = "FELIX"; // label the fragments as FELIX fragments for later consumption
137  }
138  fragmentMap[dtnameloc] = std::make_unique<artdaq::Fragments>();
139 
140  std::string subdetGroupPath = topLevelGroupName + "/" + detectorTypeName;
141  hid_t subdetGroup = getGroupFromPath(hdfFileInfoPtr, subdetGroupPath);
142 
143  // this loop doesn't make sense for TriggerRecordHeader datasets
144 
145  std::list<std::string> subdetGeoNames = getMidLevelGroupNames(subdetGroup);
146  for (auto& subdetGeoName : subdetGeoNames)
147  {
148  std::string geoGroupPath = subdetGroupPath + "/" + subdetGeoName;
149  //std::cout << " Geo path: " << geoGroupPath << std::endl;
150  hid_t geoGroup = getGroupFromPath(hdfFileInfoPtr,geoGroupPath);
151  std::list<std::string> dataSetNames = getMidLevelGroupNames(geoGroup);
152  for (auto& dataSetName : dataSetNames)
153  {
154  std::string dataSetPath = geoGroupPath + "/" + dataSetName;
155  //std::cout << "Dataset path: " << dataSetPath << std::endl;
156 
157  // read a dataset and put it in a buffer so we can extract metadata
158  // Future optimization -- just read in the first part of the dataset to extract
159  // the header, and read in the rest of it directly into the fragment.
160  // need to know header size to do that. 80 bytes for v2 TPC data.
161 
162  hid_t datasetid = H5Dopen(geoGroup,dataSetName.data(),H5P_DEFAULT);
163  hsize_t ds_size = H5Dget_storage_size(datasetid);
164  std::vector<char> ds_data(ds_size);
165  H5Dread(datasetid, H5T_STD_I8LE, H5S_ALL, H5S_ALL, H5P_DEFAULT, ds_data.data());
166  H5Dclose(datasetid);
167 
168  artdaq::FragmentPtr frag;
169  artdaq::Fragment::type_t type = artdaq::Fragment::InvalidFragmentType;
170  uint32_t payloadOffset = 0;
171  if (detectorTypeName == TPC_GROUP_NAME)
172  {
173  if (ds_size < 81) continue; // skip if there isn't even enough for a header
174  frag = artdaq::Fragment::FragmentBytes(ds_size - 80);
175  type = dune::detail::FELIX;
176  frag->setUserType(type);
177  size_t numframes = (ds_size - 80)/sizeof(dune::FelixFrame);
178 
179  //int magic_word = 0;
180  //memcpy(&magic_word,&ds_data[0],4);
181  //std::cout << " Magic word: 0x" << std::hex << magic_word << std::dec << std::endl;
182 
183  //int version = 0;
184  //memcpy(&version, &ds_data[4],4);
185  //std::cout << " Version: " << std::dec << version << std::dec << std::endl;
186 
187  //uint64_t fragsize=0;
188  //memcpy(&fragsize, &ds_data[8],8);
189  //std::cout << " Frag Size: " << std::dec << fragsize << std::dec << std::endl;
190 
191  uint64_t trignum=0;
192  memcpy(&trignum, &ds_data[16],8);
193  //std::cout << " Trig Num: " << std::dec << trignum << std::dec << std::endl;
194  frag->setSequenceID(trignum);
195 
196  uint64_t triggerTime = 0;
197  memcpy(&triggerTime, &ds_data[24],8);
198  //std::cout << " Trig Timestamp: " << std::dec << trig_timestamp << std::dec << std::endl;
199 
200  uint64_t windowStart=0;
201  memcpy(&windowStart, &ds_data[32],8);
202  //std::cout << " Window Begin: " << std::dec << windowbeg << std::dec << std::endl;
203 
204  uint64_t windowEnd=0;
205  memcpy(&windowEnd, &ds_data[40],8);
206  //std::cout << " Window End: " << std::dec << windowend << std::dec << std::endl;
207 
208  int runno=0;
209  memcpy(&runno, &ds_data[48], 4);
210  //std::cout << " Run Number: " << std::dec << runno << std::endl;
211  hdfFileInfoPtr->runNumber = runno; // keep overwriting this with each dataset
212 
213  //int errbits=0;
214  //memcpy(&errbits, &ds_data[52], 4);
215  //std::cout << " Error bits: " << std::dec << errbits << std::endl;
216 
217  //int fragtype=0;
218  //memcpy(&fragtype, &ds_data[56], 4);
219  //std::cout << " Fragment type: " << std::dec << fragtype << std::endl;
220 
221  //int fragpadding=0;
222  //memcpy(&fragtype, &ds_data[60], 4);
223  //std::cout << " Fragment padding: " << std::dec << fragpadding << std::endl;
224 
225  //int geoidversion=0;
226  //memcpy(&geoidversion, &ds_data[64], 4);
227  //std::cout << " GeoID version: " << std::dec << geoidversion << std::endl;
228 
229  //unsigned short geoidtype;
230  //memcpy(&geoidtype, &ds_data[70], 1);
231  //std::cout << " GeoID type: " << geoidtype << std::endl;
232 
233  //unsigned short geoidregion=0;
234  //memcpy(&geoidregion, &ds_data[71], 1);
235  //std::cout << " GeoID region: " << std::dec << geoidregion << std::endl;
236 
237  //int geoidelement=0;
238  //memcpy(&geoidelement, &ds_data[72], 4);
239  //std::cout << " GeoID element: " << std::dec << geoidelement << std::endl;
240 
241  //int geoidpadding=0;
242  //memcpy(&geoidpadding, &ds_data[76], 4);
243  //std::cout << " GeoID padding: " << std::dec << geoidpadding << std::endl;
244 
245  dune::FelixFragmentBase::Metadata felixMetadata;
246  felixMetadata.control_word = 0xabc;
247  felixMetadata.version = 1;
248  felixMetadata.reordered = 0;
249  felixMetadata.compressed = 0;
250  felixMetadata.offset_frames = (uint32_t) ((triggerTime - windowStart) / 25);
251  felixMetadata.window_frames = (uint32_t) ((windowEnd - windowStart) / 25);
252  felixMetadata.num_frames = numframes;
253 
254  frag->setMetadata(felixMetadata);
255  frag->setTimestamp(windowStart);
256 
257  memcpy(frag->dataBeginBytes() + payloadOffset, &ds_data[80], ds_size-80);
258  }
259 
260  uint64_t pdsPayloadHeaderWord = 0;
261  if (detectorTypeName == PDS_GROUP_NAME)
262  {
263  payloadOffset = sizeof(uint64_t);
264  frag = artdaq::Fragment::FragmentBytes(ds_size + sizeof(uint64_t));
265  type = dune::detail::PHOTON;
266 
267  // fill in the SSPFragment metadata, as much as we can
268  SSPDAQ::MillisliceHeader pdsMetadata;
269  pdsMetadata.triggerTime = 0;
270  pdsMetadata.triggerType = 0;
271 
272  if (attrExists(requestedGroup,"trigger_timestamp"))
273  {
274  uint64_t timestamp;
275  hid_t a1 = H5Aopen_name(requestedGroup,"trigger_timestamp");
276  H5Aread(a1, H5Aget_type(a1), &timestamp);
277  H5Aclose(a1);
278  pdsMetadata.triggerTime = timestamp * 3;
279  }
280 
281  if (attrExists(requestedGroup,"timeslice_start"))
282  {
283  uint64_t timestamp;
284  hid_t a1 = H5Aopen_name(requestedGroup,"timeslice_start");
285  H5Aread(a1, H5Aget_type(a1), &timestamp);
286  H5Aclose(a1);
287  pdsMetadata.startTime = timestamp * 3;
288  if (pdsMetadata.triggerTime == 0) {pdsMetadata.triggerTime = timestamp * 3;}
289  }
290  else
291  {
292  if (attrExists(datasetid,"timestamp_of_first_packet"))
293  {
294  uint64_t timestamp;
295  hid_t a1 = H5Aopen_name(datasetid,"timestamp_of_first_packet");
296  H5Aread(a1, H5Aget_type(a1), &timestamp);
297  H5Aclose(a1);
298  pdsMetadata.startTime = timestamp * 3;
299  }
300  }
301 
302 
303  if (attrExists(requestedGroup,"timeslice_end"))
304  {
305  uint64_t timestamp;
306  hid_t a1 = H5Aopen_name(requestedGroup,"timeslice_end");
307  H5Aread(a1, H5Aget_type(a1), &timestamp);
308  H5Aclose(a1);
309  pdsMetadata.endTime = timestamp * 3;
310  }
311  else
312  {
313  if (attrExists(datasetid,"timestamp_of_last_packet"))
314  {
315  uint64_t timestamp;
316  hid_t a1 = H5Aopen_name(datasetid,"timestamp_of_last_packet");
317  H5Aread(a1, H5Aget_type(a1), &timestamp);
318  H5Aclose(a1);
319  pdsMetadata.endTime = timestamp * 3;
320  }
321  }
322 
323 
324  if (attrExists(datasetid,"number_of_packets"))
325  {
326  uint32_t packetCount;
327  hid_t a1 = H5Aopen_name(datasetid,"number_of_packets");
328  H5Aread(a1, H5Aget_type(a1), &packetCount);
329  H5Aclose(a1);
330  pdsMetadata.nTriggers = packetCount;
331  }
332 
333  if (attrExists(datasetid,"size_in_bytes"))
334  {
335  uint32_t sizeBytes;
336  hid_t a1 = H5Aopen_name(datasetid,"size_in_bytes");
337  H5Aread(a1, H5Aget_type(a1), &sizeBytes);
338  H5Aclose(a1);
339  pdsMetadata.length = 9 + (sizeBytes / sizeof(uint32_t));
340  pdsPayloadHeaderWord |= ((2 + (sizeBytes / sizeof(uint32_t))) & 0xffffffff);
341  }
342  else
343  {
344  pdsMetadata.length = 9 + (ds_size / sizeof(uint32_t));
345  pdsPayloadHeaderWord |= ((2 + (ds_size / sizeof(uint32_t))) & 0xffffffff);
346  }
347 
348  frag->setMetadata(pdsMetadata);
349  pdsPayloadHeaderWord |= 0x000003e700000000; // run number always seems to be set to 999
350  }
351 
352  artdaq::Fragment::sequence_id_t seqID;
353  artdaq::Fragment::fragment_id_t fragID;
354 
355  std::stringstream seqStr(topLevelGroupName);
356  seqStr >> seqID;
357  // sequence ID in artdaq::Fragment header is only 48 bits
358  seqID &= 0xffffffffffff;
359 
360  fragID = sampleFragmentID++;
361 
362  frag->setFragmentID(fragID);
363  //frag->setUserType(type); // set this in the relevant block
364  //frag->setSequenceID(seqID); // to be read out of each fragment's header
365  //frag->setTimestamp(headerTimestamp); // to be read out of each fragment's header
366 
367  if (detectorTypeName == PDS_GROUP_NAME)
368  {
369  memcpy(frag->dataBeginBytes(), &pdsPayloadHeaderWord, sizeof(uint64_t));
370  }
371 
372  fragmentMap[dtnameloc]->emplace_back(std::move(*(frag.release())));
373 
374  }
375  }
376  H5Gclose(subdetGroup);
377  }
378  }
379 
380  H5Gclose(requestedGroup);
381 
382  //hdfFileInfoPtr->filePtr->flush(H5F_SCOPE_GLOBAL);
383  return fragmentMap;
384  }
385 
386  } // namespace HDFFileReader
387 } // namespace dune
HDFFileInfoPtr reopenFile(HDFFileInfoPtr oldHdfFileInfoPtr)
HDFFileInfoPtr openFile(const std::string &fileName)
static QCString result
std::string string
Definition: nybbler.cc:12
unsigned long startTime
Definition: anlTypes.hh:56
std::list< std::string > getTopLevelGroupNames(HDFFileInfoPtr &hdfFileInfoPtr)
std::list< std::string > getMidLevelGroupNames(hid_t grp)
fileName
Definition: dumpTree.py:9
def move(depos, offset)
Definition: depos.py:107
const std::string PDS_GROUP_NAME
unsigned long triggerTime
Definition: anlTypes.hh:58
unsigned int nTriggers
Definition: anlTypes.hh:60
FragmentListsByType getFragmentsForEvent(HDFFileInfoPtr &hdfFileInfoPtr, const std::string &topLevelGroupName)
unsigned long endTime
Definition: anlTypes.hh:57
const std::string TPC_GROUP_NAME
std::unique_ptr< HDFFileInfo > HDFFileInfoPtr
std::map< std::string, std::unique_ptr< artdaq::Fragments > > FragmentListsByType
void closeFile(HDFFileInfoPtr hdfFileInfoPtr)
hid_t getGroupFromPath(HDFFileInfoPtr &hdfFileInfoPtr, const std::string &path)
unsigned int length
Definition: anlTypes.hh:59
unsigned int triggerType
Definition: anlTypes.hh:61
bool attrExists(hid_t object, const std::string &attrname)
#define a1