CFEL - ASG Software Suite  2.5.0
CASS
xfel_hdf5_file_input.cpp
Go to the documentation of this file.
1 // Copyright (C) 2017 Lutz Foucar
2 
3 /**
4  * @file xfel_hdf5_file_input.cpp contains class for reading xfel hdf5 data files
5  *
6  * @author Lutz Foucar
7  */
8 
9 #include <iostream>
10 #include <string>
11 #include <set>
12 #include <vector>
13 #include <stdexcept>
14 #include <tr1/functional>
15 
16 #include <QtCore/QFileInfo>
17 
18 #ifdef _OPENMP
19 #include <omp.h>
20 #endif
21 
22 #include "xfel_hdf5_file_input.h"
23 
24 #include "cass_event.h"
25 #include "cass_settings.h"
26 #include "log.h"
27 #include "hdf5_handle.hpp"
28 #include "machine_device.hpp"
29 #include "acqiris_device.hpp"
30 #include "pixeldetector.hpp"
31 
32 using namespace std;
33 using namespace std::tr1::placeholders;
34 
35 using namespace cass;
36 
37 namespace cass
38 {
39 /** a tile
40  *
41  * @author Lutz Foucar
42  */
43 struct AGIPDTile
44 {
45  /** define the type of the raw image */
46  typedef vector<uint16_t> rawImage_t;
47 
48  /** define the type of the raw image */
49  typedef vector<float> corImage_t;
50 
51  /** define the type of the mask data */
52  typedef vector<uint8_t> mask_t;
53 
54  /** define the type of the gain data */
55  typedef vector<uint8_t> gain_t;
56 
57  /** id of the tile */
58  uint32_t id;
59 
60  /** define a pointer to the handler */
61  typedef tr1::shared_ptr<hdf5::Handler> h5handle_t;
62 
63  /** handler to the file containing the tile data */
64  h5handle_t fh;
65 
66  /** container for the corrrected image data */
67  corImage_t dataCache;
68 
69  /** container for the mask data */
70  mask_t maskCache;
71 
72  /** container for the gains settings data */
73  gain_t gainCache;
74 
75  /** container for the train ids */
76  vector<uint64_t> trainIds;
77 
78  /** map the uinque id to an index within the array */
79  map<uint64_t, size_t> idToIdx;
80 
81  /** name of the data dataset in the hdf5 file */
82  std::string dataDsetName;
83 
84  /** name of the mask dataset in the hdf5 file */
85  std::string maskDsetName;
86 
87  /** name of the mask dataset in the hdf5 file */
88  std::string gainDsetName;
89 
90  /** name of the train id dataset in the hdf5 file */
91  std::string trainIdDsetName;
92 
93  /** name of the pulse id dataset in the hdf5 file */
94  std::string pulseIdDsetName;
95 
96  /** name of the cell id dataset in the hdf5 file */
97  std::string cellIdDsetName;
98 
99  /** the datasize of the data tile */
100  size_t size;
101 
102  /** the number of columns of the tile */
103  size_t nCols;
104 
105  /** the number of rows of the tile */
106  size_t nRows;
107 };
108 
109 /** a struct combining the information needed to get machine values
110  *
111  * @author Lutz Foucar
112  */
114 {
115  /** define a pointer to the handler */
116  typedef tr1::shared_ptr<hdf5::Handler> h5handle_t;
117 
118  /** handler to the file containing the tile data */
119  h5handle_t fh;
120 
121  /** name of the machine dataset in the hdf5 file */
122  std::string hdf5DsetName;
123 
124  /** name of the machineData within the CASSEvent */
125  std::string cassname;
126 
127  /** name of the train id dataset in the hdf5 file */
128  std::string trainIdDsetName;
129 
130  /** map the uinque id to an index within the array */
131  map<uint64_t, size_t> idxToTrainId;
132 
133  /** cache to store the data in */
134  vector<float> cache;
135 
136  /** shape of the cached data */
138 };
139 
140 /** get the tile from the hdf5 file and copy it to the correct position in the
141  * frame
142  *
143  * @author Lutz Foucar
144  *
145  * @param tile reference to the tile to be copied
146  * @param frame iterator to the frame where the tile data should be written to.
147  * @param imageNbr which image within the file should be retrieved
148  */
149 void tileToFrames(const AGIPDTile& tile,
150  const uint64_t &eventId,
151  pixeldetector::Detector::frame_t::iterator dframe,
152  pixeldetector::Detector::frame_t::iterator gframe,
153  pixeldetector::Detector::frame_t::iterator mframe,
154  const bool precache)
155 {
156  /** return if the tile data for the eventid id is not available */
157  map<uint64_t,size_t>::const_iterator idxIt(tile.idToIdx.find(eventId));
158  if (idxIt == tile.idToIdx.end())
159  return;
160 
161  if (precache)
162  {
163  /** @NOTE instead of reading the partial data from file, copy from the cached data
164  * to see if thats faster.
165  */
166  /** get iterators to start and end of requested image from the cache */
167  auto dTileBegin(tile.dataCache.begin());
168  advance(dTileBegin,tile.size*idxIt->second);
169  auto dTileEnd(dTileBegin);
170  advance(dTileEnd,tile.size);
171  /** now read the current images tile into the frame */
172  auto dTileInFrame(dframe+tile.id*tile.size);
173  copy(dTileBegin,dTileEnd,dTileInFrame);
174 
175  /** get iterators to start and end of requested image from the cache */
176  auto gTileBegin(tile.gainCache.begin());
177  advance(gTileBegin,tile.size*idxIt->second);
178  auto gTileEnd(gTileBegin);
179  advance(gTileEnd,tile.size);
180  /** now read the current images tile into the frame */
181  auto gTileInFrame(gframe+tile.id*tile.size);
182  copy(gTileBegin,gTileEnd,gTileInFrame);
183 
184  /** get iterators to start and end of requested image from the cache */
185  auto mTileBegin(tile.maskCache.begin());
186  advance(mTileBegin,tile.size*idxIt->second);
187  auto mTileEnd(mTileBegin);
188  advance(mTileEnd,tile.size);
189  /** now read the current images tile into the frame */
190  auto mTileInFrame(mframe+tile.id*tile.size);
191  copy(mTileBegin,mTileEnd,mTileInFrame);
192  }
193  else
194  {
195  /** create the partiality parameters for retrieving only the current images'
196  * tile from the dataset
197  */
198  hdf5::partiality_t part;
199  part.dims.push_back(1);
200  part.dims.push_back(tile.nRows);
201  part.dims.push_back(tile.nCols);
202 
203  part.offset.resize(part.dims.size(),0);
204  part.offset[0] = idxIt->second;
205 
206  part.count.assign(part.dims.begin(),part.dims.end());
207  part.block.resize(part.dims.size(),1);
208  part.stride.resize(part.dims.size(),1);
209 
210  /** get iterator to the start of the tile within the frame */
211  pixeldetector::Detector::frame_t::iterator dTileInFrame(dframe+tile.id*tile.size);
212  pixeldetector::Detector::frame_t::iterator gTileInFrame(gframe+tile.id*tile.size);
213  pixeldetector::Detector::frame_t::iterator mTileInFrame(mframe+tile.id*tile.size);
214 
215  /** now read the current images tile into the frame */
216  tile.fh->readPartialMultiDim<float>(dTileInFrame,part,tile.dataDsetName);
217  tile.fh->readPartialMultiDim<float>(gTileInFrame,part,tile.gainDsetName);
218  tile.fh->readPartialMultiDim<float>(mTileInFrame,part,tile.maskDsetName);
219  }
220 }
221 
222 }//end namespace cass
223 
224 void XFELHDF5FileInput::instance(string filelistname,
225  RingBuffer<CASSEvent> &ringbuffer,
226  Ratemeter &ratemeter, Ratemeter &loadmeter,
227  bool quitWhenDone,
228  QObject *parent)
229 {
230  if(_instance)
231  throw logic_error("HDF5FileInput::instance(): The instance of the base class is already initialized");
232  _instance = shared_pointer(new XFELHDF5FileInput(filelistname,ringbuffer,ratemeter,loadmeter,quitWhenDone,parent));
233 }
234 
235 XFELHDF5FileInput::XFELHDF5FileInput(string filelistname,
236  RingBuffer<CASSEvent> &ringbuffer,
237  Ratemeter &ratemeter, Ratemeter &loadmeter,
238  bool quitWhenDone,
239  QObject *parent)
240  : InputBase(ringbuffer,ratemeter,loadmeter,parent),
241  _quitWhenDone(quitWhenDone),
242  _filelistname(filelistname),
243  _counter(0),
244  _scounter(0),
245  _totalevents(0)
246 {
247  Log::add(Log::VERBOSEINFO, "HDF5FileInput::HDF5FileInput: constructed");
248 }
249 
251 {
252 }
253 
255 {
256  /** load the settings from the ini file */
257  CASSSettings s;
258  s.beginGroup("XFELHDF5FileInput");
259  const bool precache(s.value("PreCacheData",true).toBool());
260  const size_t maxPulseId(s.value("MaxPulseId",65).toUInt());
261  s.beginGroup("AGIPD");
262 
263  Log::add(Log::VERBOSEINFO, "XFELHDF5FileInput::runthis: setup the parameters from the ini file");
264 
265  /** get the cassids for the individual agipd images */
266  int DataCASSID(s.value("DataCASSID",30).toInt());
267  int MaskCASSID(s.value("MaskCASSID",31).toInt());
268  int GainCASSID(s.value("GainCASSID",32).toInt());
269 
270  /** get info for the individual tiles */
271  vector<AGIPDTile> agiptiles;
272  int size = s.beginReadArray("Tiles");
273  for (int i = 0; i < size; ++i)
274  {
275  s.setArrayIndex(i);
276  /** create a new tile */
277  AGIPDTile tile;
278  const int tileid(s.value("Id",-1).toInt());
279  if (tileid == -1)
280  continue;
281  //cout << tileid <<endl;
282  tile.id = tileid;
283  const string fn(s.value("HDF5FileName","Invalid").toString().toStdString());
284  if (fn == "Invalid")
285  continue;
286  //cout << fn <<endl;
287  try
288  {
289  tile.fh = AGIPDTile::h5handle_t(new hdf5::Handler());
290  if (precache)
291  {
292  tile.fh->open(fn,"r");
293  }
294  else
295  {
296  /* open the hdf5 file with an increased cache, so that partial operations should be faster*/
297  tile.fh->open(fn,"r",128);
298  }
299  }
300  catch (const std::invalid_argument & error)
301  {
302  Log::add(Log::ERROR,string(error.what()) + ": File '"+fn+"' doesn't exist; ignoring it");
303  continue;
304  }
305  tile.dataDsetName = s.value("DataHDF5Key","Invalid").toString().toStdString();
306  if (tile.dataDsetName == "Invalid")
307  continue;
308  //cout << tile.dataDsetName <<endl;
309  tile.maskDsetName = s.value("MaskHDF5Key","Invalid").toString().toStdString();
310  if (tile.maskDsetName == "Invalid")
311  continue;
312  //cout << tile.maskDsetName <<endl;
313  tile.gainDsetName = s.value("GainHDF5Key","Invalid").toString().toStdString();
314  if (tile.gainDsetName == "Invalid")
315  continue;
316  //cout << tile.gainDsetName <<endl;
317  tile.trainIdDsetName = s.value("TrainIdHDF5Key","Invalid").toString().toStdString();
318  if (tile.trainIdDsetName == "Invalid")
319  continue;
320  //cout << tile.trainIdDsetName <<endl;
321  tile.pulseIdDsetName = s.value("PulseIdHDF5Key","Invalid").toString().toStdString();
322  if (tile.pulseIdDsetName == "Invalid")
323  continue;
324  //cout << tile.pulseIdDsetName <<endl;
325  tile.cellIdDsetName = s.value("CellIdHDF5Key","Invalid").toString().toStdString();
326  if (tile.cellIdDsetName == "Invalid")
327  continue;
328  //cout << tile.cellIdDsetName <<endl;
329  tile.nRows = 512;
330  tile.nCols = 128;
331  tile.size = tile.nRows * tile.nCols;
332  Log::add(Log::INFO,"XFELHDF5FileInput: adding agipd tile '" + toString(tile.id) +
333  "' to list of tiles to be processed");
334  agiptiles.push_back(tile);
335  }
336 // if (agiptiles.size() != 16)
337 // throw invalid_argument("Wrong size of agipd tiles '" + toString(agiptiles.size()) + "'");
338  s.endArray(); // Tiles
339  s.endGroup(); // AGPID
340 
341  /** get the user defined machine values */
342  vector<MachineInfo> machinevalues;
343  size = s.beginReadArray("MachineData");
344  for (int i = 0; i < size; ++i)
345  {
346  s.setArrayIndex(i);
347  /** create a new machineInfo */
348  MachineInfo mi;
349 
350  /** the filename of the file containing the machine value */
351  const string fn(s.value("HDF5FileName","Invalid").toString().toStdString());
352  if (fn == "Invalid")
353  continue;
354  //cout << fn <<endl;
355  try
356  {
358  mi.fh->open(fn,"r");
359  }
360  catch (const std::invalid_argument & error)
361  {
362  Log::add(Log::ERROR,string(error.what()) + ": File '"+fn+"' doesn't exist; ignoring it");
363  continue;
364  }
365 
366  /** the name of the machine data within the cassevent */
367  mi.cassname = s.value("CASSName","Invalid").toString().toStdString();
368  if (mi.cassname == "Invalid")
369  continue;
370  //cout << mi.cassname << endl;
371 
372  /** the name of the machine data within the cassevent */
373  mi.hdf5DsetName = s.value("MachineHDF5Key","Invalid").toString().toStdString();
374  if (mi.hdf5DsetName == "Invalid")
375  continue;
376  //cout << mi.hdf5DsetName << endl;
377 
378  mi.trainIdDsetName = s.value("TrainIdHDF5Key","Invalid").toString().toStdString();
379  if (mi.trainIdDsetName == "Invalid")
380  continue;
381  //cout << tile.trainIdDsetName <<endl;
382 
383  machinevalues.push_back(mi);
384  }
385  s.endArray(); // MachineData
386 
387  s.endGroup(); // XFEHDF5FileInput
388 
390 
391  /** for all the tiles make a map of ids generated from the trainId and the pulseId with the
392  * corresponding index to the data
393  * Using openmp to parallelize the retrieval of the detector data. The
394  * 'pragma omp parallel for' statement says that the for loop should be
395  * parallelized. Within the loop all the declared variables are local to
396  * the thread and not shared. The 'num_threads' parameter allows to define
397  * how many threads should be used. Since the agip detector has 16 tiles,
398  * we only need 16 threads and not all that are available (which will be
399  * used if nothing is declared).
400  */
401 #ifdef _OPENMP
402  #pragma omp parallel for num_threads(agiptiles.size())
403 #endif
404 // for (auto &tile : agiptiles)
405  for (size_t i = 0; i<agiptiles.size(); ++i)
406  {
407  auto &tile(agiptiles[i]);
408  Log::add(Log::VERBOSEINFO, "XFELHDF5FileInput::runthis: create eventid map for agipd tile '"+
409  toString(tile.id) + "'");
410  hdf5::shape_t shape;
411  tile.fh->readMultiDim<uint64_t>(tile.trainIds,shape,tile.trainIdDsetName);
412  vector<uint64_t> pulseIds;
413  tile.fh->readMultiDim<uint64_t>(pulseIds,shape,tile.cellIdDsetName);
414  //tile.fh->readMultiDim<uint64_t>(pulseIds,shape,tile.pulseIdDsetName);
415  if (pulseIds.size() != tile.trainIds.size())
416  cout << "BAD!!"<<endl;
417  for (size_t i(0); i<pulseIds.size(); ++i)
418  {
419  const uint64_t trainId(tile.trainIds[i]);
420  const uint64_t pulseId(pulseIds[i]);
421  const uint64_t id(((trainId & 0x0000FFFFFFFFFFFF)<<16) +
422  (pulseId & 0x000000000000FFFF));
423  tile.idToIdx[id] = i;
424  }
425 
426  /** preload the data to check if it improves the speed of the analysis */
427  if (precache)
428  {
429  Log::add(Log::VERBOSEINFO, "XFELHDF5FileInput::runthis: precache data for agipd tile '"+
430  toString(tile.id) + "'.");
431  tile.fh->readMultiDim<AGIPDTile::corImage_t::value_type>(tile.dataCache,shape,tile.dataDsetName);
432  tile.fh->readMultiDim<AGIPDTile::mask_t::value_type>(tile.maskCache,shape,tile.maskDsetName);
433  tile.fh->readMultiDim<AGIPDTile::gain_t::value_type>(tile.gainCache,shape,tile.gainDsetName);
434  }
435  Log::add(Log::VERBOSEINFO, "XFELHDF5FileInput::runthis: done setting up agipd tile '"+
436  toString(tile.id) + "'");
437  }
438 
439  /** create a map that tells the idx for each trainids of the machine values */
440  for (auto &mv : machinevalues)
441  {
442  Log::add(Log::VERBOSEINFO, "XFELHDF5FileInput::runthis: create trainId map for machinvalue '"+
443  mv.cassname + "' and precache the data");
444  hdf5::shape_t shape;
445  vector<uint64_t> trainIds;
446  mv.fh->readMultiDim<uint64_t>(trainIds,shape,mv.trainIdDsetName);
447  for (size_t i(0); i<trainIds.size(); ++i)
448  mv.idxToTrainId[trainIds[i]] = i;
449 
450  /** pre cache the data to see whether its faster to analyze */
451  if (precache)
452  {
453  mv.fh->readMultiDim<float>(mv.cache,mv.shape,mv.hdf5DsetName);
454  }
455  }
456 
457  /** generate container list of all the unique trainIds available */
458  std::set<uint64_t> trainIds;
459  for (const auto &tile : agiptiles)
460  {
461  for (const auto &trainId : tile.trainIds)
462  {
463  trainIds.emplace(trainId);
464  }
465  }
466 
467  Log::add(Log::VERBOSEINFO, "XFELHDF5FileInput::runthis: the list of trainIds is '"+
468  toString(trainIds.size()) + "' long");
469 
470  _totalevents = trainIds.size() * 60;
471 
472  /** now go through all the trains */
473  for (const auto &trainId : trainIds)
474 // auto iTrainId(trainIds.begin());
475 // advance(iTrainId,250);
476 // for (; iTrainId != trainIds.end(); ++iTrainId)
477  {
478 // auto trainId(*iTrainId);
479  /** add break point here */
480  if (shouldQuit()) break;
481 
482  /** go through all the nominal available pulses within a train */
483  for (size_t pulseId(0); pulseId<maxPulseId; ++pulseId)
484  {
485  /** add break point here */
486  if (shouldQuit()) break;
487 
488  /** retrieve a new element from the ringbuffer. If one didn't get a
489  * an element (when the end iterator of the buffer is returned).
490  * Continue to the next iteration, where it is checked if the thread
491  * should quit.
492  */
493  bool isGood(true);
494  rbItem_t rbItem(getNextFillable());
495  if (rbItem == _ringbuffer.end())
496  continue;
497  CASSEvent& evt(*rbItem->element);
498 
499  /** generate an unique eventid from the pulse id and the trainId */
500  evt.id() = (((trainId & 0x0000FFFFFFFFFFFF)<<16) +
501  (pulseId & 0x000000000000FFFF));
502 
503  /** get reference to all devices of the CASSEvent and an iterator*/
504  CASSEvent::devices_t &devices(evt.devices());
505  CASSEvent::devices_t::iterator devIt;
506  /** retrieve the pixel detector part of the cassevent */
507  devIt = devices.find(CASSEvent::PixelDetectors);
508  if(devIt == devices.end())
509  throw runtime_error(string("xfelhdf5fileinput: CASSEvent does not") +
510  " contain a pixeldetector device");
511  pixeldetector::Device &pixdev (dynamic_cast<pixeldetector::Device&>(*(devIt->second)));
512 
513  /** retrieve the right detectors from the cassevent and reset it*/
514  const size_t nRows(512);
515  const size_t nCols(128);
516  const size_t nTiles(16);
517  /** the data frame */
518  pixeldetector::Detector &data(pixdev.dets()[DataCASSID]);
519  data.id() = evt.id();
520  data.columns() = nCols;
521  data.rows() = nRows*nTiles;
522  pixeldetector::Detector::frame_t &dataframe(data.frame());
523  dataframe.clear();
524  dataframe.resize(nRows*nCols*nTiles,0);
525  /** the mask frame */
526  pixeldetector::Detector &mask(pixdev.dets()[MaskCASSID]);
527  mask.id() = evt.id();
528  mask.columns() = nCols;
529  mask.rows() = nRows*nTiles;
530  pixeldetector::Detector::frame_t &maskframe(mask.frame());
531  maskframe.clear();
532  maskframe.resize(nRows*nCols*nTiles,0);
533  /** the gain frame */
534  pixeldetector::Detector &gain(pixdev.dets()[GainCASSID]);
535  gain.id() = evt.id();
536  gain.columns() = nCols;
537  gain.rows() = nRows*nTiles;
538  pixeldetector::Detector::frame_t &gainframe(gain.frame());
539  gainframe.clear();
540  gainframe.resize(nRows*nCols*nTiles,0);
541 
542  /** find the tiles that correspond to the the made up eventid and copy them to the right pos
543  * within the detector image
544  */
545  for_each(agiptiles.begin(),agiptiles.end(),
546  tr1::bind(tileToFrames, _1,
547  evt.id(),
548  dataframe.begin(),
549  gainframe.begin(),
550  maskframe.begin(),
551  precache));
552  /** ensure that all values in the frame are numbers */
553  for (auto &pixel : dataframe) if (!isfinite(pixel)) pixel = 0;
554 
555 
556  /** retrieve the machine detector part of the cassevent */
557  devIt = devices.find(CASSEvent::MachineData);
558  if(devIt == devices.end())
559  throw runtime_error(string("xfelhdf5fileinput: CASSEvent does not") +
560  " contain a machinedata device");
561  MachineData::Device &md (dynamic_cast<MachineData::Device&>(*(devIt->second)));
562  md.BeamlineData()["PulseId"] = pulseId;
563  md.BeamlineData()["TrainId"] = trainId;
564  /** find the additional data for the machine data */
565  for (const auto& mv : machinevalues)
566  {
567  /** skip if the tile data for the eventid id is not available */
568  map<uint64_t,size_t>::const_iterator idxIt(mv.idxToTrainId.find(trainId));
569  if (idxIt == mv.idxToTrainId.end())
570  continue;
571  if (precache)
572  {
573  auto mBegin(mv.cache.begin());
574  advance(mBegin, pulseId + idxIt->second*mv.shape[1]);
575  md.BeamlineData()[mv.cassname] = *mBegin;
576  }
577  else
578  {
579  hdf5::partiality_t part;
580  part.dims.push_back(1);
581  part.dims.push_back(1);
582 
583  part.offset.resize(part.dims.size(),0);
584  part.offset[0] = idxIt->second;
585  part.offset[1] = pulseId;
586 
587  part.count.assign(part.dims.begin(),part.dims.end());
588  part.block.resize(part.dims.size(),1);
589  part.stride.resize(part.dims.size(),1);
590 
591  vector<float> mval(1,0);
592  mv.fh->readPartialMultiDim<float>(mval.begin(), part, mv.hdf5DsetName);
593 
594  md.BeamlineData()[mv.cassname] = mval.front();
595  }
596  }
597 
598  /** tell the ringbuffer that we're done with the event */
599  newEventAdded(0);
600  ++_counter;
601  _ringbuffer.doneFilling(rbItem, isGood);
602  }
603  }
604 
605 
606 // /** now go through all set of files */
607 // for (size_t i(0); (!shouldQuit()) && (i<filesetlist.size());++i)
608 // {
609 // fileset_t& fileset(filesetlist[i]);
610 //
611 // /** get the shape from the first datafile (should be the same for all data
612 // * files). The first dimension is the number of images, so we iterate over
613 // * this number
614 // */
615 // const hdf5::shape_t shape(fileset[0].fh->shape(fileset[0].dataDsetName));
616 // const size_t nCols(shape[shape.size()-1]);
617 // const size_t nRows(shape[shape.size()-2]);
618 // const size_t nTiles(fileset.size());
619 // _totalevents = shape[0];
620 // fileset_t::iterator fsit(fileset.begin());
621 // while(fsit < fileset.end())
622 // {
623 // fsit->nCols = nCols;
624 // fsit->nRows = nRows;
625 // fsit->size = (nCols*nRows);
626 // ++fsit;
627 // }
628 // /** pre cache the data */
629 // for_each(fileset.begin(),fileset.end(),preCacheData);
630 //
631 // /** get all the trainids and the pulseids from the first datafile, they
632 // * later used to compile a unique eventid
633 // */
634 // vector<uint64_t> trainIds;
635 // size_t length;
636 // fileset[0].fh->readArray(trainIds,length,trainIdKey);
637 //
638 // vector<uint64_t> pulseIds;
639 // fileset[0].fh->readArray(pulseIds,length,pulseIdKey);
640 //
641 // vector<uint16_t> cellIds;
642 // fileset[0].fh->readArray(cellIds,length,cellIdKey);
643 //
644 // for (size_t iTrain(0); (!shouldQuit()) && (iTrain < nTrains);++iTrain)
645 // {
646 // for (size_t iImage(0); (!shouldQuit()) && (iImage < nImages);++iImage)
647 // {
648 // /** calculate the which Event in the file should be retrieved */
649 // size_t iImageInFile(iTrain*nImagesInTrainTotal + iImage*imageStride + imageOffset);
650 // /** flag that tell whether the data is good */
651 // bool isGood(true);
652 // /** retrieve a new element from the ringbuffer. If one didn't get a
653 // * an element (when the end iterator of the buffer is returned).
654 // * Continue to the next iteration, where it is checked if the thread
655 // * should quit.
656 // */
657 // rbItem_t rbItem(getNextFillable());
658 // if (rbItem == _ringbuffer.end())
659 // continue;
660 // CASSEvent& evt(*rbItem->element);
661 //
662 // /** create the event id from the trainid and the pulseid */
663 // evt.id() = ((trainIds[iImageInFile] & 0x0000FFFFFFFFFFFF)<< 16) +
664 // ((pulseIds[iImageInFile] & 0x000000000000FFFF));
665 //
666 // /** get reference to all devices of the CASSEvent and an iterator*/
667 // CASSEvent::devices_t &devices(evt.devices());
668 // CASSEvent::devices_t::iterator devIt;
669 // /** retrieve the pixel detector part of the cassevent */
670 // devIt = devices.find(CASSEvent::PixelDetectors);
671 // if(devIt == devices.end())
672 // throw runtime_error(string("xfelhdf5fileinput: CASSEvent does not") +
673 // " contain a pixeldetector device");
674 // pixeldetector::Device &pixdev (dynamic_cast<pixeldetector::Device&>(*(devIt->second)));
675 // /** retrieve the right detector from the cassevent and reset it*/
676 // pixeldetector::Detector &data(pixdev.dets()[DataCASSID]);
677 // pixeldetector::Detector::frame_t &dataframe(data.frame());
678 // dataframe.clear();
679 // dataframe.resize(nRows*nCols*nTiles);
680 // /** copy the det data to the frame */
681 // // for_each(fileset.begin(),fileset.end(),tr1::bind(copyDataTileToFrame,_1,
682 // // dataframe.begin(),iImageInFile));
683 // for_each(fileset.begin(),fileset.end(),tr1::bind(copyCorImageFromCacheToFrame,_1,
684 // dataframe.begin(),iImageInFile));
685 // /** set the detector parameters and add the event id */
686 // data.columns() = nCols;
687 // data.rows() = nRows*nTiles;
688 // data.id() = evt.id();
689 // /** retrieve the right detector from the cassevent and reset it*/
690 // pixeldetector::Detector &gain(pixdev.dets()[GainCASSID]);
691 // pixeldetector::Detector::frame_t &gainframe(gain.frame());
692 // gainframe.clear();
693 // gainframe.resize(nRows*nCols*nTiles);
694 // /** copy the det data to the frame */
695 // // for_each(fileset.begin(),fileset.end(),tr1::bind(copyGainTileToFrame,_1,
696 // // gainframe.begin(),iImageInFile));
697 // for_each(fileset.begin(),fileset.end(),tr1::bind(copyGainFromCacheToFrame,_1,
698 // gainframe.begin(),iImageInFile));
699 // /** set the detector parameters and add the event id */
700 // gain.columns() = nCols;
701 // gain.rows() = nRows*nTiles;
702 // gain.id() = evt.id();
703 // /** retrieve the right detector to hold the mask from the cassevent and reset it*/
704 // pixeldetector::Detector &mask(pixdev.dets()[MaskCASSID]);
705 // pixeldetector::Detector::frame_t &maskframe(mask.frame());
706 // maskframe.clear();
707 // maskframe.resize(nRows*nCols*nTiles);
708 // /** copy the det data to the frame */
709 // // for_each(fileset.begin(),fileset.end(),tr1::bind(copyTileToMask,_1,
710 // // maskframe.begin(),iImageInFile));
711 // for_each(fileset.begin(),fileset.end(),tr1::bind(copyMaskFromCacheToFrame,_1,
712 // maskframe.begin(),iImageInFile));
713 // /** set the detector parameters and add the event id */
714 // mask.columns() = nCols;
715 // mask.rows() = nRows*nTiles;
716 // mask.id() = evt.id();
717 //
718 // /** retrieve the machine detector part of the cassevent */
719 // devIt = devices.find(CASSEvent::MachineData);
720 // if(devIt == devices.end())
721 // throw runtime_error(string("xfelhdf5fileinput: CASSEvent does not") +
722 // " contain a machinedata device");
723 // MachineData::Device &md (dynamic_cast<MachineData::Device&>(*(devIt->second)));
724 // md.BeamlineData()["CellId"] = cellIds[iImageInFile];
725 // md.BeamlineData()["PulseId"] = pulseIds[iImageInFile];
726 // md.BeamlineData()["TrainId"] = trainIds[iImageInFile];
727 //
728 // /** tell the ringbuffer that we're done with the event */
729 // newEventAdded(0);
730 // ++_counter;
731 // _ringbuffer.doneFilling(rbItem, isGood);
732 // }
733 // }
734 // }
735 
736  /** quit the program if requested otherwise wait until the program is signalled
737  * to quit
738  */
739  Log::add(Log::INFO,"XFELHDF5FileInput::run(): Finished with all files.");
740  if(!_quitWhenDone)
741  while(!shouldQuit())
742  this->sleep(1);
743  Log::add(Log::VERBOSEINFO, "XFELHDF5FileInput::run(): closing the input");
744  Log::add(Log::INFO,"XFELHDF5FileInput::run(): Extracted '" +
745  toString(eventcounter()) + "' events.");
746 }
747 
uint64_t _totalevents
the total # of events to be handled
std::string cellIdDsetName
name of the cell id dataset in the hdf5 file
void load()
load the parameters used for the multifile input
setArrayIndex(int i)
hdf5::shape_t shape
shape of the cached data
Event to store all LCLS Data.
Definition: cass_event.h:32
RingBuffer< CASSEvent >::iter_type rbItem_t
define an item in the ringbuffer
Definition: input_base.h:109
vector< float > cache
cache to store the data in
class calculating a rate in Hz.
Definition: ratemeter.h:28
sleep(unsigned long secs)
std::vector< hsize_t > count
the count
Definition: hdf5_handle.hpp:76
vector< uint8_t > gain_t
define the type of the gain data
status_t _status
the internal status of the thread
vector< uint64_t > trainIds
container for the train ids
file contains declaration of the CASSEvent
Settings for CASS.
Definition: cass_settings.h:30
A handler for h5 files.
detectors_t & dets()
instrument setter
size_t nCols
the number of columns of the tile
std::string hdf5DsetName
name of the machine dataset in the hdf5 file
std::string pulseIdDsetName
name of the pulse id dataset in the hdf5 file
Input base class.
Definition: input_base.h:31
STL namespace.
tr1::shared_ptr< hdf5::Handler > h5handle_t
define a pointer to the handler
things written only at end of run H5Dump ProcessorSummary size
std::string gainDsetName
name of the mask dataset in the hdf5 file
std::string maskDsetName
name of the mask dataset in the hdf5 file
tr1::shared_ptr< hdf5::Handler > h5handle_t
define a pointer to the handler
uint64_t _counter
the counter for all events
bool _quitWhenDone
flag to tell the thread to quit when its done with all files
std::string trainIdDsetName
name of the train id dataset in the hdf5 file
std::string trainIdDsetName
name of the train id dataset in the hdf5 file
static void add(Level level, const std::string &line)
add a string to the log
Definition: log.cpp:31
void tileToFrames(const AGIPDTile &tile, const uint64_t &eventId, pixeldetector::Detector::frame_t::iterator dframe, pixeldetector::Detector::frame_t::iterator gframe, pixeldetector::Detector::frame_t::iterator mframe, const bool precache)
get the tile from the hdf5 file and copy it to the correct position in the frame
std::string cassname
name of the machineData within the CASSEvent
std::vector< hsize_t > offset
the offset of the partial data within the original data
Definition: hdf5_handle.hpp:59
h5handle_t fh
handler to the file containing the tile data
beginReadArray(const QString &prefix)
Container for all Machine related Data.
std::vector< hsize_t > shape_t
define the shape type
Definition: hdf5_handle.hpp:43
A Ringbuffer, handles communication between Input and Worker Threads.
Definition: ringbuffer.hpp:52
XFEL HDF5 File Input for cass.
devices_t & devices()
setters
Definition: cass_event.h:66
uint64_t eventcounter()
retrieve the number of processed events
std::vector< pixel_t > frame_t
a frame is a vector of pixels
define the partiality parameter container
Definition: hdf5_handle.hpp:49
mask_t maskCache
container for the mask data
bool shouldQuit() const
query whether this thread is told to quit
file contains the declaration of the acqiris part of the CASSEvent
a struct combining the information needed to get machine values
contains a xfel hdf5 file reader class
std::vector< hsize_t > block
the block
Definition: hdf5_handle.hpp:84
id_t & id()
setters
Definition: cass_event.h:64
std::vector< hsize_t > stride
the stride
Definition: hdf5_handle.hpp:68
std::string toString(const Type &t)
convert any type to a string
Definition: cass.h:63
auxiliary data[Processor]
size_t nRows
the number of rows of the tile
value(const QString &key, const QVariant &defaultValue=QVariant()
RingBuffer< CASSEvent > & _ringbuffer
reference to the ringbuffer
Definition: input_base.h:140
std::map< Device, DeviceBackend::shared_pointer > devices_t
mapping from device type to handler instance
Definition: cass_event.h:46
vector< float > corImage_t
define the type of the raw image
void runthis()
function with the main loop
std::vector< hsize_t > dims
the dimensions of the partial dataset
Definition: hdf5_handle.hpp:52
noise and mask[Processor]
h5handle_t fh
handler to the file containing the tile data
contains container for simple pixel detector data
definitions of a machine device
std::string dataDsetName
name of the data dataset in the hdf5 file
std::tr1::shared_ptr< InputBase > shared_pointer
shared pointer of this type
Definition: input_base.h:35
file contains specialized class that do the settings for cass
size_t size
the datasize of the data tile
the device containing pixel detector data
vector< uint8_t > mask_t
define the type of the mask data
Detector containing a ccd camera image.
map< uint64_t, size_t > idxToTrainId
map the uinque id to an index within the array
rbItem_t getNextFillable(unsigned timeout=500)
retrieve an iterator to the next fillable event
Definition: input_base.cpp:48
corImage_t dataCache
container for the corrrected image data
vector< uint16_t > rawImage_t
define the type of the raw image
contains a logger for cass
int16_t pixel
define a pixel
Definition: hlltypes.hpp:27
void newEventAdded(const size_t eventsize)
increment the numer of events received in the ratemeter
Definition: input_base.cpp:37
easier api for hdf5 file writing
gain_t gainCache
container for the gains settings data
map< uint64_t, size_t > idToIdx
map the uinque id to an index within the array
const bldMap_t & BeamlineData() const
getter
beginGroup(const QString &prefix)
uint32_t id
id of the tile