CFEL - ASG Software Suite  2.5.0
CASS
sacla_online_input.cpp
Go to the documentation of this file.
1 // Copyright (C) 2015 Lutz Foucar
2 
3 /**
4  * @file sacla_online_input.cpp contains input that uses sacla as interface
5  *
6  * @author Lutz Foucar
7  */
8 
9 #include <iostream>
10 #include <tr1/functional>
11 
12 #ifdef _OPENMP
13 #include <omp.h>
14 #endif
15 
16 #include "sacla_online_input.h"
17 
18 #include <OnlineUserAPI.h>
19 
20 #include "cass_settings.h"
21 #include "log.h"
22 #include "sacla_converter.h"
23 #include "pixeldetector.hpp"
24 #include "machine_device.hpp"
25 #include "cass_exceptions.hpp"
26 
27 using namespace cass;
28 using namespace std;
29 using tr1::bind;
30 using tr1::placeholders::_1;
31 
32 namespace cass
33 {
34 
35 /** A Tile of a Detector
36  *
37  * @author Lutz Foucar
38  */
40 {
41  /** constructor
42  *
43  * connects to the right socket and retrieves all non changing parameters
44  *
45  * @param name The name of the detector tile
46  */
47  DetectorTile(const string &name)
48  : name(name),
49  gain(0.f),
50  xsize(0),
51  ysize(0),
52  datasize(0),
53  normalizeID(-1),
54  relativeGain(1.f)
55  {
56  int funcstatus(0);
57  /** get the socketID of the requested detector */
58  funcstatus = ol_connect(&_sockID, name.c_str());
59  if (funcstatus < 0)
60  throw runtime_error("DetectorTile: could not retrieve socket id of '" +
61  name + "' ErrorCode is '" + toString(funcstatus) +
62  "'");
63 
64  /** get the size of the data and the needed worksize */
65  int datasize = 0, worksize = 0;
66  funcstatus = ol_get_data_size(&datasize, &worksize, _sockID);
67  if (funcstatus < 0)
68  throw runtime_error("DetectorTile: could not retrieve datasize'" +
69  name + "' ErrorCode is '" + toString(funcstatus) +
70  "'");
71  _databuffer.resize(datasize,0);
72  _workbuffer.resize(worksize,0);
73 
74  /** retrieve detector data once to retrieve all non changing parameters */
75  retrieveData();
76 
77  /** read the width and height of the detector */
78  funcstatus = ol_read_det_xsize(&xsize, &(_databuffer.front()), 0);
79  if (funcstatus < 0)
80  throw runtime_error("DetectorTile: could not extract xsize of tile '" +
81  name + "' ErrorCode is '" + toString(funcstatus) + "'");
82 
83  funcstatus = ol_read_det_ysize(&ysize, &_databuffer.front(), 0);
84  if (funcstatus < 0)
85  throw runtime_error("DetectorTile: could not extract ysize of tile '" +
86  name + "' ErrorCode is '" + toString(funcstatus) + "'");
87 
88  /** read the gain of the detector tile */
89  funcstatus = ol_read_abs_gain(&gain, &_databuffer.front(), 0);
90  if (funcstatus < 0)
91  throw runtime_error("DetectorTile: could not extract gain of tile '" +
92  name + "' ErrorCode is '" + toString(funcstatus) +
93  "'");
94  }
95 
96  /** read the data
97  *
98  * defaulty read the latest tag (tag == -1). If tag is given, it will read
99  * data associated with the requested tag.
100  *
101  * @throws TagOutdated when the funcstatus is indicating an outdated tag
102  * @throws runtime_error when the funcstatus is an error other than outdated
103  * tag
104  *
105  * @return the funcstatus when it says outdated tag or no error
106  * @param tag the tag that the data should be read for
107  */
108  void retrieveData(int tag=OL_NEWESTTAGDATA)
109  {
110  int outputTag(0);
111  int funcstatus = ol_collect_det_data(&_databuffer.front(),
112  &_workbuffer.front(),
113  &outputTag,
114  _sockID,
115  tag,
116  _databuffer.size(),
117  _workbuffer.size());
118  if (funcstatus == OL_ERR_TAGDATAGONE)
119  throw TagOutdated("DetectorTile: tile '" + name + "': tag '" + toString(tag) +
120  "' on socket '" + toString(_sockID) +
121  "' isn't available anymore");
122  if (funcstatus < 0)
123  throw runtime_error("DetectorTile: could not retrieve data of tile '" +
124  name + "' for tag '" + toString(tag) +
125  "' using socket '" + toString(_sockID) +
126  "'. ErrorCode is '" + toString(funcstatus) + "'");
127  }
128 
129  /** copy the tile data to the frame
130  *
131  * Collect the data from the server to the buffer and copy the tile's data
132  * to the frame.
133  *
134  * @param tag the tag for which to copy the tile data.
135  */
136  void copyData(int tag)
137  {
138  /** reset the datasize */
139  datasize = 0;
140 
141  /** if the data for the tag has not been retrieved, retrieve it at this point */
142  if (this->tag() != tag)
143  retrieveData(tag);
144 
145  /** retrieve pointer to the tile data from the databuffer */
146  float *data_org(0);
147  int funcstatus = ol_read_det_data(&data_org, &_databuffer.front(), 0);
148  if (funcstatus < 0 || !data_org)
149  {
150  Log::add(Log::ERROR,"SACLAOnlineInput: could not extract data of detector '" +
151  name + "' ErrorCode is '" + toString(funcstatus) + "'");
152  return;
153  }
154 
155  /** if tile should be normalized, use transform to copy the data, otherwise
156  * just copy the tile data to the frame
157  */
158  if (normalizeID != -1)
159  transform(data_org, data_org+xsize*ysize, start,
160  bind1st(multiplies<float>(),relativeGain));
161  else
162  copy(data_org, data_org+xsize*ysize, start);
163 
164  /** set the datasize to the right size */
165  datasize = xsize * ysize * sizeof(uint16_t);
166  }
167 
168  /** the current Tag read from the current databuffer
169  *
170  * @return the current Tag
171  */
172  int tag()
173  {
174  int tag(0);
175  int funcstatus = ol_read_tag_num(&tag, &_databuffer.front(), 0);
176  if (funcstatus < 0)
177  Log::add(Log::ERROR,"DetectorTile::latestTag could not extract the tag from '" +
178  name + "' ErrorCode is '" + toString(funcstatus) + "'");
179  return tag;
180  }
181 
182  /** the current Run Number read from the current databuffer
183  *
184  * @return latest run number
185  */
186  int runNumber()
187  {
188  int run(0);
189  int funcstatus = ol_read_run_num(&run, &_databuffer.front(), 0);
190  if (funcstatus < 0)
191  Log::add(Log::ERROR,"DetectorTile::latestRun could not extract the run from '" +
192  name + "' ErrorCode is '" + toString(funcstatus) + "'");
193  return run;
194  }
195 
196  /** the name of the detector tile */
197  std::string name;
198 
199  /** the gain of the tile */
200  float gain;
201 
202  /** the width of the tile */
203  int xsize;
204 
205  /** the height of the tile */
206  int ysize;
207 
208  /** the size of the retrieved data */
209  uint64_t datasize;
210 
211  /** start position of the tile within the frame */
212  pixeldetector::Detector::frame_t::iterator start;
213 
214  /** id of tile to normalize to */
216 
217  /** the relative gain to normalize for */
219 
220 private:
221  /** the socket ID to connect to the online API */
222  int _sockID;
223 
224  /** the buffer with the detector data */
225  vector<char> _databuffer;
226 
227  /** buffer needed for the retrieval function to work */
228  vector<char> _workbuffer;
229 };// end class DetectorTile
230 
231 
232 /** An Octal Detector
233  *
234  * A detector with a user chosen amount of equal tiles
235  *
236  * @author Lutz Foucar
237  */
239 {
240  /** get the latest Tag
241  *
242  * if the last Tag is set return the next tag that should be there
243  * otherwise retrieve the latest tag and return it
244  * @note this hack is needed as trying to retrieve the latest tag
245  * is currently very slow. Once this issue is fixed one can
246  * think of just using the function to retrieve the latest tag.
247  *
248  * @return the latest available tag
249  * @param lastTag the last tag that was valid. If 0 the latest tag will
250  * retrieved otherwise this number will be increased
251  * by tagAdvance
252  */
253  int latestTag(int lastTag)
254  {
255  if (lastTag)
256  return lastTag + tagAdvance;
257  else
258  {
259  tiles.front().retrieveData();
260  return tiles.front().tag();
261  }
262  }
263 
264  /** get the latest Run Number
265  *
266  * get the latest runnumber for the first tile
267  *
268  * @return the latest runnumber
269  */
270  int runNumber()
271  {
272  return tiles.front().runNumber();
273  }
274 
275  /** copy data associtated with the tag to the device of the cassevent
276  *
277  * @return size of the data that has been retrieved in bytes
278  * @param dev reference to the pixeldetector device in the cassevent
279  * @param tag the Tag for which the data should be copied
280  */
281  uint64_t copyData(pixeldetector::Device &dev, int tag)
282  {
283  /** retrieve the right detector from the cassevent and reset it */
284  pixeldetector::Detector &det(dev.dets()[CASSID]);
285  det.frame().clear();
286  det.columns() = 0;
287  det.rows() = 0;
288  det.id() = tag;
289 
290  /** resize the frame to fit all tiles into it */
291  for (size_t i(0); i < tiles.size(); ++i)
292  {
293  det.frame().resize(det.frame().size() +
294  tiles[i].xsize*tiles[i].ysize);
295  det.columns() = tiles[i].xsize;
296  det.rows() += tiles[i].ysize;
297  }
298 
299  /** set where the individual tiles will start and end within the frame */
300  size_t currentsize(0);
301  for (size_t i(0); i < tiles.size(); ++i)
302  {
303  tiles[i].start = det.frame().begin() + currentsize;
304  const size_t npixels(tiles[i].xsize*tiles[i].ysize);
305  currentsize += npixels;
306  }
307 
308  /** copy the data in the tile to the frame
309  * @note need to use openmp to parallelize since, the tiles vector is too
310  * small to be parallelized automatically by __gnu_parallelize
311  * @note when compiling with openmp one needs to take special care with the
312  * exceptions. They need to be catched within the thread they have been
313  * thrown. To work around this a global exception exists that will be
314  * filled with the exception thrown. After the execution of the
315  * threads it will be checked if the global exeption has been set and
316  * if so, it will be thrown in the main thread. To be catched at a
317  * convenient time.
318  * @note All variables that are declared within the
319  * 'pragma omp parallel for' statement are local to the specific
320  * thread, therefore one has to use the 'shared(error)' statement
321  * to tell openmp that 'error' is global to all threads. The
322  * 'pragma omp critical' defines a section that will only be executed
323  * by one thread at a time. Since its the part that where the
324  * exception will be handled it should only be exectued by the
325  * thread that is throwing the exception.
326  */
327 // for_each(tiles.begin(), tiles.end(), bind(&DetectorTile::copyData,_1,tag));
328 #ifdef _OPENMP
329  TagOutdated error("",false);
330  #pragma omp parallel for shared(error) num_threads(tiles.size())
331 #endif
332  for (size_t i = 0; i < tiles.size(); ++i)
333  {
334 #ifdef _OPENMP
335 // string out("loop is running with " + toString(omp_get_num_threads()) +
336 // " threads");
337 // cout << out <<endl;
338  try
339  {
340 #endif
341  tiles[i].copyData(tag);
342 #ifdef _OPENMP
343  }
344  catch (const TagOutdated &err)
345  {
346  #pragma omp critical
347  error = err;
348  }
349 #endif
350  }
351 #ifdef _OPENMP
352  if (error)
353  throw error;
354 #endif
355 
356  /** gather the size of the copied data */
357  uint64_t datasize(0);
358  for (size_t i(0); i < tiles.size(); ++i)
359  datasize += tiles[i].datasize;
360 
361  return datasize;
362  }
363 
364  /** vector containing the tiles of the detector */
365  vector<DetectorTile> tiles;
366 
367  /** the id that the detector should have within the pixeldetector part of
368  * the CASSEvent
369  */
370  int CASSID;
371 
372  /** how much the last tag should be advanced */
374 
375 }; // end struct octal detector
376 
377 
378 ///** a Machine value
379 // *
380 // * @author Lutz Foucar
381 // */
382 //struct MachineValue
383 //{
384 // /** constructor
385 // *
386 // * retrieve the hightag with the offline version of the API using the
387 // * provided runnumber
388 // *
389 // * @param name The name of this Machine Value
390 // * @param runNbr The run number with which we can retrieve the high tag
391 // * @param blNbr The beamline number used to retrieve the right high tag number
392 // */
393 // MachineValue(const string &name, int runNbr, int blNbr)
394 // : cassname(name),
395 // name(name),
396 // _highTagNbr(0)
397 // {
398 // int funcstatus,startTagNbr = 0;
399 // funcstatus = ReadStartTagNumber(_highTagNbr,startTagNbr,blNbr,runNbr);
400 // if (funcstatus)
401 // Log::add(Log::ERROR,"MachineValue: could not retrieve hight tag of run '" +
402 // toString(runNbr) + "' at beamline '" + toString(blNbr) +
403 // "' Errorcode is '" + toString(funcstatus) + "'");
404 // }
405 //
406 // /** copy the data corresponding data to the machine device
407 // *
408 // * The machine data can only be retrieved using the offline api
409 // *
410 // * @return the size of the data that has been copied
411 // * @param md reference to the machine data devices
412 // * @param tag the tag for which the data should be retrieved
413 // */
414 // uint64_t copyData(MachineData::Device &md, int tag)
415 // {
416 // /** retrieve the machinevalue and check if it was retrieved ok */
417 // vector<string> machineValueStringList;
418 // vector<int> tagList(1,tag);
419 // int funcstatus = ReadSyncDataList(&machineValueStringList,
420 // const_cast<char*>(name.c_str()),
421 // _highTagNbr,tagList);
422 // if (funcstatus)
423 // {
424 // Log::add(Log::ERROR,"MachineValue::copyData could not extract machine values of '" +
425 // name + "' ErrorCode is '" + toString(funcstatus) + "'");
426 // return 0;
427 // }
428 // if (machineValueStringList.size() != tagList.size())
429 // {
430 // Log::add(Log::ERROR,"MachineValue:copyData '" +
431 // name + "' did not return the right size");
432 // return 0;
433 // }
434 //
435 // /** check if retrieved value can be converted to double, and if so add it
436 // * to the machine data, otherwise issue an error and continue
437 // * @note the retrieved values might contain the unit of the value in the
438 // * string, therefore one has to remove all characters from the string
439 // */
440 // QString machineValueQString(QString::fromStdString(machineValueStringList.back()));
441 // machineValueQString.remove(QRegExp("V|C|pulse|a\\.u\\."));
442 // bool isDouble(false);
443 // double machineValue(machineValueQString.toDouble(&isDouble));
444 // if (isDouble)
445 // md.BeamlineData()[cassname] = machineValue;
446 // else
447 // {
448 // Log::add(Log::ERROR,"MachineValue::copyData '" + name + "' for tag '" +
449 // toString(tag) + "': String '" + machineValueStringList.back() +
450 // "' which is altered to '" + machineValueQString.toStdString() +
451 // "' to remove units, cannot be converted to double");
452 // return 0;
453 // }
454 // return sizeof(double);
455 // }
456 //
457 // /** the name of the machine value within the cassevent */
458 // string cassname;
459 //
460 // /** the name of the Machine value */
461 // string name;
462 //
463 //private:
464 // /** the high tag number */
465 // int _highTagNbr;
466 //
467 //};//end struct MachineValue
468 
469 } //end namespace cass
470 
471 
472 
473 
475  Ratemeter &ratemeter,
476  Ratemeter &loadmeter,
477  QObject *parent)
478 {
479  if(_instance)
480  throw logic_error("SACLAOnlineInput::instance(): The instance of the base class is already initialized");
481  _instance = shared_pointer(new SACLAOnlineInput(buffer,ratemeter,loadmeter,parent));
482 }
483 
485  Ratemeter &ratemeter,
486  Ratemeter &loadmeter,
487  QObject *parent)
488  : InputBase(ringbuffer,ratemeter,loadmeter,parent),
489  _evtCounter(0),
490  _skippedEvtCounter(0)
491 {
492  Log::add(Log::VERBOSEINFO, "SACLAOnlineInput:: constructed");
493 }
494 
496 {
497  /** load settings from the ini file */
498  CASSSettings s;
499  s.beginGroup("SACLAOnlineInput");
500 
501  /** load requested octal detectors */
502  vector<OctalDetector> octalDetectors;
503  int size = s.beginReadArray("OctalPixelDetectors");
504  for (int i = 0; i < size; ++i)
505  {
506  s.setArrayIndex(i);
507  int cassid(s.value("CASSID",-1).toInt());
508  /** skip if the detector cass id has not been set */
509  if (cassid == -1)
510  continue;
511  /** load the infos for the detector */
512  octalDetectors.push_back(OctalDetector());
513  OctalDetector &det(octalDetectors.back());
514  det.CASSID = cassid;
515  det.tagAdvance = s.value("NextTagNumberAdvancedBy",2).toInt();
516  Log::add(Log::INFO, "SACLAOnlineInput: Setting up octal detector with cassid '" +
517  toString(cassid) + "'. The next tag number is guessed by " +
518  "advancing the current one by '" + toString(det.tagAdvance) + "'");
519  /** setup the individual tiles of the detector */
520  int nTiles = s.beginReadArray("Tiles");
521  for (int j(0); j<nTiles; ++j)
522  {
523  s.setArrayIndex(j);
524  const string tilename(s.value("TileName","Invalid").toString().toStdString());
525  octalDetectors.back().tiles.push_back(DetectorTile(tilename));
526  DetectorTile &tile(octalDetectors.back().tiles.back());
527  /** @note in online mode one gets the raw tile shape therefore one needs
528  * to remove the last 6 lines, which are used for calibration.
529  * Allow the user to choose how many rows need to be removed to
530  * prevent the necessity to recompile when the API changes with that
531  * respect.
532  */
533  tile.ysize -= s.value("NbrCalibrationRows",6).toUInt();
534  tile.normalizeID = s.value("NormalizeTo",0).toInt()-1;
535  }
536  for (size_t j(0); j<det.tiles.size(); ++j)
537  {
538  DetectorTile &tile(det.tiles[j]);
539  if (tile.normalizeID != -1)
540  tile.relativeGain = tile.gain / det.tiles[tile.normalizeID].gain;
541  Log::add(Log::INFO, "SACLAOnlineInput: Octal detector with cassid '"+
542  toString(cassid) + "' has tile '" + tile.name +
543  (tile.normalizeID == -1 ?"":" The tile will be normalized to tile '" +
544  toString(tile.normalizeID + 1) + " (" +
545  det.tiles[tile.normalizeID].name + ")'" +
546  " with relative gain '" +
547  toString(tile.relativeGain)) +
548  "'; Tile shape '" + toString(tile.xsize) + "x" + toString(tile.ysize) +
549  "'; Tile Gain '" + toString(tile.gain) + "'");
550  }
551  s.endArray();
552  }
553  s.endArray();
554 
555  /** quit if not at least one octal detector has been defined */
556  if (octalDetectors.empty())
557  throw invalid_argument("SACLAOnlineInput: Need to have at least one octal detector defined");
558 
559  /** generate a counter to enable the user to reset to the latest event after
560  * so and so many events
561  */
562  size_t counter(0);
563  size_t maxGuessedEvents(s.value("MaxGuessedEvents",60).toUInt());
564 
565  /** load the beamline number of the beamline we're running on
566  * (needed to retieve database values)
567  */
568  int BeamlineNbr = s.value("BeamlineNumber",3).toInt();
569  Log::add(Log::INFO, "SACLAOnlineInput: Using BeamlineNumber '" +
570  toString(BeamlineNbr) + "'");
571 
572 
573 // /** load the requested database values */
574 // size = s.beginReadArray("DatabaseValues");
575 // vector<MachineValue> machineValues;
576 // for (int i = 0; i < size; ++i)
577 // {
578 // s.setArrayIndex(i);
579 // string machineValName(s.value("ValueName","Invalid").toString().toStdString());
580 // string cassValName(s.value("CASSName","Invalid").toString().toStdString());
581 // /** skip if the value name has not been set and not at least one octal detector exitst
582 // * @note the octal detector is needed in order to get the run number with
583 // * which one can get the high tag number, needed to retrieve the
584 // * machine data. Since the machine data needs to be retrieved using
585 // * the offline api.
586 // */
587 // if (machineValName == "Invalid")
588 // continue;
589 // /** add the machine value */
590 // machineValues.push_back(MachineValue(machineValName,
591 // octalDetectors.back().runNumber(),
592 // BeamlineNbr));
593 // /** if the cass name is set then overwrite it withing the machinevalue */
594 // if (cassValName != "Invalid")
595 // machineValues.back().cassname = cassValName;
596 // Log::add(Log::INFO, "SACLAOnlineInput: Setting up Database value '" +
597 // machineValues.back().name + "' with CASSName '" +
598 // machineValues.back().cassname + "'");
599 // }
600 // s.endArray();
601 
602  s.endGroup();
603 
604 #ifdef _OPENMP
605  Log::add(Log::INFO, "SACLAOnlineInput: Running with up to '" +
606  toString(omp_get_max_threads()) + "' input threads");
607 #endif
608  /** run until the thread is told to quit */
609  Log::add(Log::DEBUG0,"SACLAOnlineInput::run(): starting loop");
610  int lastTag(0);
611  while(!shouldQuit())
612  {
613  /** here we can safely pause the execution */
614  pausePoint();
615 
616  /** retrieve a new element from the ringbuffer, continue with next iteration
617  * in case the retrieved element is the iterator to the last element of the
618  * buffer.
619  */
620  rbItem_t rbItem(getNextFillable());
621  if (rbItem == _ringbuffer.end())
622  continue;
623  CASSEvent &evt(*rbItem->element);
624 
625  /** generate and set variable to keep the size of the retrieved data */
626  uint64_t datasize(0);
627 
628  /** use try...catch to get notified when the requested tag data is not
629  * available anymore
630  */
631  try
632  {
633  /** get the part where the detector will be store in from the event */
634  CASSEvent::devices_t &devices(evt.devices());
635  CASSEvent::devices_t::iterator devIt(devices.find(CASSEvent::PixelDetectors));
636  if(devIt == devices.end())
637  throw runtime_error("SACLAOnlineInput: CASSEvent does not contains a pixeldetector device");
638  pixeldetector::Device &dev (dynamic_cast<pixeldetector::Device&>(*(devIt->second)));
639 
640  /** get the latest tag from the first defined octal detector */
641  int latestTag(octalDetectors.front().latestTag(lastTag));
642 
643  /** only do something when the tag has advanced
644  * @note currently this not really necessary as the tag will always be
645  * advanced by the latestTag call. But this might be needed in
646  * future when it is possible to use the API function to retrieve
647  * the latest tag.
648  */
649  if (latestTag > lastTag)
650  {
651  /** set the event id */
652  evt.id() = latestTag;
653 
654  /** copy octal detector data to cassevent and
655  * add the size in bytes copied to the total size retrieved
656  */
657  vector<OctalDetector>::iterator octIter(octalDetectors.begin());
658  vector<OctalDetector>::iterator octEnd(octalDetectors.end());
659  for(; octIter != octEnd; ++octIter)
660  {
661  datasize += octIter->copyData(dev,latestTag);
662  }
663 
664 
665 // /** get refrence to the machine device of the CASSEvent */
666 // CASSEvent::devices_t::iterator mdIt (devices.find(CASSEvent::MachineData));
667 // if (mdIt == devices.end())
668 // throw runtime_error("SACLAOnlineInput():The CASSEvent does not contain a Machine Data Device");
669 // MachineData::Device &md(dynamic_cast<MachineData::Device&>(*(mdIt->second)));
670 //
671 // /** retrieve requested machinedata, copy it to the CASSEvent and add
672 // * the size in bytes to the total size retrieved
673 // */
674 // vector<MachineValue>::iterator machIter(machineValues.begin());
675 // vector<MachineValue>::iterator machEnd(machineValues.end());
676 // for(; machIter != machEnd; ++machIter)
677 // {
678 // datasize += machIter->copyData(md,latestTag);
679 // }
680 
681 
682  /** remember the latest tag, but reset it every user given event,
683  * to ensure that always gets the latest data.
684  */
685  if (counter < maxGuessedEvents)
686  {
687  lastTag = latestTag;
688  ++counter;
689  }
690  else
691  {
692  counter = 0;
693  lastTag = 0;
694  }
695  }
696  }
697  /** if the data for the tag wasn't available, reset the last tag and the datasize */
698  catch (const TagOutdated &error)
699  {
700  Log::add(Log::ERROR,error.what());
701  datasize = 0;
702  lastTag = 0;
703  }
704 
705  /** let the ratemeter know that we're done with this event with size
706  * datasize and return the element to the ringbuffer, telling it whether it contains
707  * valuable information (datasize is non zero)
708  */
709  if (!datasize)
710  {
711  Log::add(Log::WARNING,"SACLAOnlineInput: Event with id '"+
712  toString(rbItem->element->id()) + "' is bad: skipping Event");
714  }
715  else
716  ++_evtCounter;
717  newEventAdded(datasize);
718  _ringbuffer.doneFilling(rbItem, datasize);
719  }
720  Log::add(Log::DEBUG0,"SACLAOnlineInput::run(): quitting loop");
721 }
setArrayIndex(int i)
Event to store all LCLS Data.
Definition: cass_event.h:32
vector< char > _databuffer
the buffer with the detector data
int normalizeID
id of tile to normalize to
RingBuffer< CASSEvent >::iter_type rbItem_t
define an item in the ringbuffer
Definition: input_base.h:109
contains input that uses the sacla online interface
uint64_t _evtCounter
a counter for the events so far
class calculating a rate in Hz.
Definition: ratemeter.h:28
std::string name
the name of the detector tile
pixeldetector::Detector::frame_t::iterator start
start position of the tile within the frame
Settings for CASS.
Definition: cass_settings.h:30
detectors_t & dets()
instrument setter
int tagAdvance
how much the last tag should be advanced
Exception thrown when SACLA tag is outdated.
Input base class.
Definition: input_base.h:31
STL namespace.
int runNumber()
the current Run Number read from the current databuffer
uint64_t copyData(pixeldetector::Device &dev, int tag)
copy data associtated with the tag to the device of the cassevent
things written only at end of run H5Dump ProcessorSummary size
SACLAOnlineInput(RingBuffer< CASSEvent > &buffer, Ratemeter &ratemeter, Ratemeter &loadmeter, QObject *parent=0)
constructor
vector< char > _workbuffer
buffer needed for the retrieval function to work
file contains custom exceptions used in cass
vector< DetectorTile > tiles
vector containing the tiles of the detector
int xsize
the width of the tile
uint64_t datasize
the size of the retrieved data
Online Input to be used at SACLA.
An Octal Detector.
static void add(Level level, const std::string &line)
add a string to the log
Definition: log.cpp:31
beginReadArray(const QString &prefix)
int runNumber()
get the latest Run Number
A Ringbuffer, handles communication between Input and Worker Threads.
Definition: ringbuffer.hpp:52
front pnCCD LCLSPixelDetectors CASSID
devices_t & devices()
setters
Definition: cass_event.h:66
int _sockID
the socket ID to connect to the online API
bool shouldQuit() const
query whether this thread is told to quit
void retrieveData(int tag=OL_NEWESTTAGDATA)
read the data
id_t & id()
setters
Definition: cass_event.h:64
int CASSID
the id that the detector should have within the pixeldetector part of the CASSEvent ...
std::string toString(const Type &t)
convert any type to a string
Definition: cass.h:63
static shared_pointer instance()
get the signelton instance
Definition: input_base.cpp:20
value(const QString &key, const QVariant &defaultValue=QVariant()
DetectorTile(const string &name)
constructor
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
int tag()
the current Tag read from the current databuffer
contains container for simple pixel detector data
definitions of a machine device
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
the device containing pixel detector data
A Tile of a Detector.
int ysize
the height of the tile
Detector containing a ccd camera image.
uint64_t _skippedEvtCounter
a counter for the skipped events so far
void pausePoint()
point where the thread will be paused
rbItem_t getNextFillable(unsigned timeout=500)
retrieve an iterator to the next fillable event
Definition: input_base.cpp:48
void runthis()
starts the thread
contains a logger for cass
float gain
the gain of the tile
void newEventAdded(const size_t eventsize)
increment the numer of events received in the ratemeter
Definition: input_base.cpp:37
contains class to convert sacla data to cassevent
void copyData(int tag)
copy the tile data to the frame
beginGroup(const QString &prefix)
int latestTag(int lastTag)
get the latest Tag
float relativeGain
the relative gain to normalize for