CFEL - ASG Software Suite  2.5.0
CASS
lcls_converter.cpp
Go to the documentation of this file.
1 // Copyright (C) 2009, 2010, 2011 Lutz Foucar
2 
3 /**
4  * @file lcls_converter.cpp contains the converters to convert ccd and pnccd data
5  * to CASSEvent
6  *
7  * @author Lutz Foucar
8  */
9 
10 #include <iostream>
11 #include <stdexcept>
12 #include <algorithm>
13 
14 #include "pdsdata/xtc/Xtc.hh"
15 #include "pdsdata/xtc/TypeId.hh"
16 #include "pdsdata/xtc/DetInfo.hh"
17 #include "pdsdata/pnCCD/ConfigV1.hh"
18 #include "pdsdata/pnCCD/ConfigV2.hh"
19 #include "pdsdata/pnCCD/FrameV1.hh"
20 #include "pdsdata/camera/FrameV1.hh"
21 #include "pdsdata/cspad/ConfigV1.hh"
22 #include "pdsdata/cspad/ConfigV2.hh"
23 #include "pdsdata/cspad/ConfigV3.hh"
24 #include "pdsdata/cspad/ConfigV4.hh"
25 #include "pdsdata/cspad/ConfigV5.hh"
26 #include "pdsdata/cspad/ElementHeader.hh"
27 #include "pdsdata/cspad/ElementIterator.hh"
28 #include "pdsdata/cspad2x2/ConfigV1.hh"
29 #include "pdsdata/cspad2x2/ConfigV2.hh"
30 #include "pdsdata/cspad2x2/ElementHeader.hh"
31 #include "pdsdata/psddl/epix.ddl.h"
32 
33 #include "lcls_converter.h"
34 
35 #include "cass_settings.h"
36 #include "cass_event.h"
37 #include "pixeldetector.hpp"
38 #include "log.h"
39 #include "lcls_key.hpp"
40 
41 using namespace cass;
42 using namespace pixeldetector;
43 using namespace lclsid;
44 using namespace std;
45 using std::tr1::shared_ptr;
46 using namespace Pds;
47 
48 namespace cass
49 {
50 namespace pixeldetector
51 {
52 
53 /** extract the right detector from the CASSEvent
54  *
55  * check whether the device that contains the detector is present in the CASSevent
56  * if not throw a runtime error
57  *
58  * @return reference to the requested detector
59  * @param evt the cassvent containing the detector
60  * @param key key of the detector within the map of the device holding the devices
61  *
62  * @author Lutz Foucar
63  */
64 Detector& retrieveDet(CASSEvent& evt, const Device::detectors_t::key_type& key)
65 {
66  CASSEvent::devices_t &devices(evt.devices());
67  CASSEvent::devices_t::iterator devIt(devices.find(CASSEvent::PixelDetectors));
68  if(devIt == devices.end())
69  {
70  throw runtime_error("pixeldetector::retrieveDet: There is no pixeldetector device within the CASSEvent");
71  }
72  Device &dev (dynamic_cast<Device&>(*(devIt->second)));
73  return (dev.dets()[key]);
74 }
75 
76 /** copy payload of xtc into a bytearray
77  *
78  * create a byte array of the right size and copy the payload of the xtc to it.
79  *
80  * @return vector containing the payload of the xtc
81  * @param xtc the xtc whos payload should be copied.
82  *
83  * @author Lutz Foucar
84  */
85 vector<uint8_t> extractPayload(const Pds::Xtc* xtc)
86 {
87  vector<uint8_t> payload(xtc->sizeofPayload());
88  copy(xtc->payload(),xtc->payload()+xtc->sizeofPayload(),payload.begin());
89 
90  return payload;
91 }
92 
93 /** copy additional info about the pnCCD
94  *
95  * No info is available, just set default values.
96  *
97  * @param cfg unused
98  * @param det reference to the detector that the info will be copied to
99  * @param rowsOfSegment the number of rows in each segment
100  * @param columnsOfSegment the number of columns in each segment
101  *
102  * @author Lutz Foucar
103  */
104 void copyAdditionalPnccdInfo(const Pds::PNCCD::ConfigV1& /*cfg*/, Detector &det,
105  size_t & rowsOfSegment, size_t &columnsOfSegment)
106 {
107  det.rows() = det.columns() = 1024;
108  rowsOfSegment = 512;
109  columnsOfSegment = 512;
110 }
111 
112 /** copy additional info about the pnCCD
113  *
114  * Copy all info that one can get from version 2.
115  *
116  * @param cfg reference to the configuration
117  * @param det reference to the detector that the info will be copied to
118  * @param rowsOfSegment the number of rows in each segment
119  * @param columnsOfSegment the number of columns in each segment
120  *
121  * @author Lutz Foucar
122  */
123 void copyAdditionalPnccdInfo(const Pds::PNCCD::ConfigV2& cfg, Detector &det,
124  size_t & rowsOfSegment, size_t &columnsOfSegment)
125 {
126  det.rows() = cfg.numRows();
127  det.columns() = cfg.numChannels();
128  det.info().assign(cfg.info());
129  det.timingFilename().assign(cfg.timingFName());
130  det.camaxMagic() = cfg.camexMagic();
131  rowsOfSegment = cfg.numSubmoduleRows();
132  columnsOfSegment = cfg.numSubmoduleChannels();
133  if(det.rows()>1024||det.columns()>1024||rowsOfSegment>512||columnsOfSegment>512)
134  {
135  Log::add(Log::ERROR,"pnCCDConverter::DataXTC: rows:" + toString(det.rows()));
136  Log::add(Log::ERROR,"pnCCDConverter::DataXTC: cols:" + toString(det.columns()));
137  Log::add(Log::ERROR,"pnCCDConverter::DataXTC: info:" + det.info());
138  Log::add(Log::ERROR,"pnCCDConverter::DataXTC: tfileName:" + det.timingFilename());
139  Log::add(Log::ERROR,"pnCCDConverter::DataXTC: camaxMagic:" + toString(det.camaxMagic()));
140  Log::add(Log::ERROR,"pnCCDConverter::DataXTC: SegRows:" + toString(rowsOfSegment));
141  Log::add(Log::ERROR,"pnCCDConverter::DataXTC: SegCols:" + toString(columnsOfSegment));
142  }
143 }
144 
145 /** copy the pnCCD frame into the detector
146  *
147  * @tparam ConfigType the type of configuration
148  * @param xtc the raw data of the detector
149  * @param cfg the configuration that tells what is where in the configuration
150  * @param det the place where the frame data should be copied to
151  *
152  * @author Lutz Foucar
153  */
154 template <typename ConfigType>
155 void copyPnCCDFrame(const Pds::Xtc* xtc, const ConfigType& cfg, Detector& det)
156 {
157  const PNCCD::FrameV1* frameSegment
158  (reinterpret_cast<const Pds::PNCCD::FrameV1*>(xtc->payload()));
159 
160  size_t rowsOfSegment(0);
161  size_t columnsOfSegment(0);
162 
163  copyAdditionalPnccdInfo(cfg,det,rowsOfSegment,columnsOfSegment);
164 
165  const size_t sizeOfOneSegment = frameSegment->sizeofData(cfg);
166  if (sizeOfOneSegment != rowsOfSegment*columnsOfSegment)
167  {
168  throw runtime_error("copyPnCCDFrame: size of one segment '" +
169  toString(sizeOfOneSegment) +
170  "' is inconsistent with number of rows '" +
171  toString(rowsOfSegment) + "' colums '" +
172  toString(columnsOfSegment) + "' of the segments");
173  }
174  const size_t NbrOfSegments = cfg.numLinks();
175  const size_t FrameSize = sizeOfOneSegment * NbrOfSegments;
176  det.frame().resize(FrameSize);
177 
178  vector<const uint16_t*> xtcSegmentPointers(NbrOfSegments,0);
179  for (size_t i=0; i<NbrOfSegments ;++i)
180  {
181  //pointer to first data element of segment//
182  xtcSegmentPointers[i] = frameSegment->data();
183  frameSegment = frameSegment->next(cfg);
184  }
185  const uint16_t * tileA = xtcSegmentPointers[0];
186  const uint16_t * tileB = xtcSegmentPointers[3];
187  const uint16_t * tileC = xtcSegmentPointers[1]+sizeOfOneSegment-1;
188  const uint16_t * tileD = xtcSegmentPointers[2]+sizeOfOneSegment-1;
189 
190  Detector::frame_t::iterator pixel = det.frame().begin();
191 
192  for (size_t iRow=0; iRow<rowsOfSegment ;++iRow)
193  {
194  for (size_t iCol=0; iCol<columnsOfSegment ;++iCol)
195  *pixel++ = *tileA++ & 0x3fff;
196  for (size_t iCol=0; iCol<columnsOfSegment ;++iCol)
197  *pixel++ = *tileB++ & 0x3fff;
198  }
199  for (size_t iRow=0; iRow<rowsOfSegment ;++iRow)
200  {
201  for (size_t iCol=0; iCol<columnsOfSegment ;++iCol)
202  *pixel++ = *tileC-- & 0x3fff;
203  for (size_t iCol=0; iCol<columnsOfSegment ;++iCol)
204  *pixel++ = *tileD-- & 0x3fff;
205  }
206 }
207 
208 /** copy the cspad frame to the detector
209  *
210  * @tparam ConfigType the type of configuration
211  * @param xtc the raw data of the detector
212  * @param cfg the configuration that tells what is where in the configuration
213  * @param det the place where the frame data should be copied to
214  *
215  * @author Lutz Foucar
216  */
217 template <typename ConfigType>
218 void copyCsPadFrame(const Pds::Xtc* xtc, const ConfigType& cfg, Detector& det)
219 {
220  //Get the frame from the xtc
221  const int asic_nx(Pds::CsPad::MaxRowsPerASIC);
222  const int asic_ny(Pds::CsPad::ColumnsPerASIC);
223  Pds::CsPad::ElementIterator iter(cfg, *xtc);
224  const Pds::CsPad::ElementHeader* element;
225  /** 2 asics per segment. 8 segments per quadrant. */
226  const int pixelsPerQuadrant(2*asic_nx*8*asic_ny);
227  const int pixelsPerSegment(2*asic_nx*asic_ny);
228  /** 4 quadrants */
229  const int FrameSize(4*pixelsPerQuadrant);
230  det.frame().resize(FrameSize);
231  // loop over quadrants (elements)
232  while( (element=iter.next() ))
233  {
234  const size_t quad(element->quad());
235  Detector::pixel_t* rawframe((&det.frame().front()) + quad * pixelsPerQuadrant);
236  const Pds::CsPad::Section* section;
237  unsigned int section_id;
238  while(( section=iter.next(section_id) ))
239  {
240  const uint16_t* pixels = section->pixel[0];
241  for (int ii=0; ii<pixelsPerSegment; ++ii)
242  {
243  *rawframe = *pixels;
244  ++rawframe;
245  ++pixels;
246  }
247  }
248  }
249  /** all sections above each other */
250  det.columns() = 2 * 194;
251  det.rows() = 4 * 8 * 185;
252 }
253 
254 
255 
256 /** copy the epix frame to the detector
257  *
258  * @tparam ConfigType the type of configuration
259  * @param element the epix element that contains the raw data
260  * @param cfg the configuration that tells what is where in the configuration
261  * @param det the place where the frame data should be copied to
262  *
263  * @author Lutz Foucar
264  */
265 template <typename ConfigType>
266 void copyEpixFrame(const Pds::Epix::ElementV3& element, const ConfigType& cfg, Detector& det)
267 {
268  //Get the frame from the element
269  det.columns() = cfg.numberOfColumns();
270  det.rows() = cfg.numberOfReadableRows();
271  const char* pData(reinterpret_cast<const char*>(&element)+32);
272  const uint16_t* data(reinterpret_cast<const uint16_t*>(pData));
273  // copy the data to the detector frame
274  const size_t framesize(det.columns()*det.rows());
275  det.frame().resize(framesize);
276  copy(data, data+framesize, det.frame().begin());
277 }
278 
279 
280 }//end namepsace pixeldetector
281 }//end namespace cass
282 
283 // =================define static members =================
286 
288 {
289  QMutexLocker locker(&_mutex);
290  if(!_instance)
291  {
292  _instance = ConversionBackend::shared_pointer(new Converter());
293  }
294  return _instance;
295 }
296 // ========================================================
297 
298 
300 {
301  _pdsTypeList.push_back(TypeId::Id_pnCCDconfig);
302  _pdsTypeList.push_back(TypeId::Id_pnCCDframe);
303  _pdsTypeList.push_back(TypeId::Id_Frame);
304  _pdsTypeList.push_back(TypeId::Id_CspadConfig);
305  _pdsTypeList.push_back(TypeId::Id_CspadElement);
306  _pdsTypeList.push_back(TypeId::Id_Cspad2x2Element);
307  _pdsTypeList.push_back(TypeId::Id_EpixConfig);
308  _pdsTypeList.push_back(TypeId::Id_Epix10kConfig);
309  _pdsTypeList.push_back(TypeId::Id_Epix100aConfig);
310  _pdsTypeList.push_back(TypeId::Id_EpixSConfig);
311  _pdsTypeList.push_back(TypeId::Id_Epix10kaConfig);
312  _pdsTypeList.push_back(TypeId::Id_EpixElement);
313 
314 
315  CASSSettings s;
316  s.beginGroup("Converter");
317 
318  int size = s.beginReadArray("LCLSPixelDetectors");
319  for (int i = 0; i < size; ++i)
320  {
321  s.setArrayIndex(i);
322  string type(s.value("TypeName","Invalid").toString().toStdString());
323  TypeId::Type typeID(TypeId::NumberOf);
324  for (int i(0); i < TypeId::NumberOf; ++i)
325  if (TypeId::name(static_cast<TypeId::Type>(i)) == type)
326  {
327  typeID = static_cast<TypeId::Type>(i);
328  break;
329  }
330 
331  uint32_t detID(s.value("DetectorID",0).toUInt());
332  string detname(s.value("DetectorName","Invalid").toString().toStdString());
333  DetInfo::Detector detnameID(DetInfo::NumDetector);
334  for (int i(0); i < DetInfo::NumDetector; ++i)
335  if (DetInfo::name(static_cast<DetInfo::Detector>(i)) == detname)
336  {
337  detnameID = static_cast<DetInfo::Detector>(i);
338  break;
339  }
340 
341  uint32_t devID(s.value("DeviceID",0).toUInt());
342  string devname(s.value("DeviceName","Invalid").toString().toStdString());
343  DetInfo::Device devnameID(DetInfo::NumDevice);
344  for (int i(0); i < DetInfo::NumDevice; ++i)
345  if (DetInfo::name(static_cast<DetInfo::Device>(i)) == devname)
346  {
347  devnameID = static_cast<DetInfo::Device>(i);
348  break;
349  }
350 
351  /** skip if the either name has not been set or not correctly set */
352  if (typeID == TypeId::NumberOf ||
353  detnameID == DetInfo::NumDetector ||
354  devnameID == DetInfo::NumDevice)
355  continue;
356 
357  Key key(typeID, detnameID, detID, devnameID, devID);
358  _LCLSToCASSId[key] = s.value("CASSID",0).toInt();
359  }
360  s.endArray();
361 }
362 
363 void Converter::operator()(const Pds::Xtc* xtc, CASSEvent* evt)
364 {
365  Log::add(Log::DEBUG4, string("XTC: '") +
366  TypeId::name(xtc->contains.id()) + "'(" + toString(xtc->contains.id()) +
367  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->detector()) +
368  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->detId()) +
369  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->device()) +
370  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->devId()) +
371  ")");
372 
373  /** skip if there is no corresponding cass key for that xtc */
374  idmap_t::key_type lclskey(xtc->contains.id(), xtc->src.phy());
375  idmap_t::iterator lclsmapIt(_LCLSToCASSId.find(lclskey));
376  if (lclsmapIt == _LCLSToCASSId.end())
377  {
378  Log::add(Log::DEBUG0, string("pixeldetector::Converter::operator(): There is no corresponding cass key for : '") +
379  TypeId::name(xtc->contains.id()) + "'(" + toString(xtc->contains.id()) +
380  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->detector()) +
381  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->detId()) +
382  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->device()) +
383  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->devId()) +
384  ")");
385  return;
386  }
387  const idmap_t::mapped_type &casskey(lclsmapIt->second);
388 
389 
390  switch( xtc->contains.id() )
391  {
392 
393  case (Pds::TypeId::Id_CspadConfig) :
394  case (Pds::TypeId::Id_Cspad2x2Config) :
395  case (Pds::TypeId::Id_pnCCDconfig) :
396  case (Pds::TypeId::Id_EpixConfig):
397  case (Pds::TypeId::Id_Epix10kConfig):
398  case (Pds::TypeId::Id_Epix100aConfig):
399  case (Pds::TypeId::Id_EpixSConfig):
400  case (Pds::TypeId::Id_Epix10kaConfig):
401  {
402  if (xtc->contains.id() == Pds::TypeId::Id_pnCCDconfig && 2 < xtc->contains.version())
403  throw runtime_error("pixeldetector::Converter::operator: pnCCD Config version" +
404  toString(xtc->contains.version()) + "is not supported");
405  else
406  {
407  switch (xtc->contains.version())
408  {
409  case 2:
410  {
411  const Pds::PNCCD::ConfigV2 &cfg
412  (reinterpret_cast<const Pds::PNCCD::ConfigV2&>(*(xtc->payload())));
413  string out(string("pixeldetector::Converter::operator(): ")
414  + TypeId::name(xtc->contains.id()) + "'(" + toString(xtc->contains.id())
415  + "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->detector())
416  + "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->detId())
417  + "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->device())
418  + "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->devId())
419  + "): CASSID '"+toString(casskey)+"'"
420  + "', rows'" + toString(cfg.numRows())
421  + "', cols'" + toString(cfg.numChannels())
422  + "', info'" + cfg.info()
423  + "', tfileName'" + cfg.timingFName()
424  + "', camaxMagic'" + toString(cfg.camexMagic())
425  + "', SegRows'" + toString(cfg.numSubmoduleRows())
426  + "', SegCols'" + toString(cfg.numSubmoduleChannels())
427  + "'");
428  Log::add(Log::INFO,out);
429  }
430  break;
431 
432  default:
433  break;
434  }
435  }
436  if (xtc->contains.id() == Pds::TypeId::Id_CspadConfig && 5 < xtc->contains.version())
437  throw runtime_error("pixeldetector::Converter::operator: csPad Config version" +
438  toString(xtc->contains.version()) + "is not supported");
439  if (xtc->contains.id() == Pds::TypeId::Id_Cspad2x2Config && 2 < xtc->contains.version())
440  throw runtime_error("pixeldetector::Converter::operator: csPad2x2 Config version" +
441  toString(xtc->contains.version()) + "is not supported");
442  if (xtc->contains.id() == Pds::TypeId::Id_EpixConfig && 1 < xtc->contains.version())
443  throw runtime_error("pixeldetector::Converter::operator: Epix Config version" +
444  toString(xtc->contains.version()) + "is not supported");
445  if (xtc->contains.id() == Pds::TypeId::Id_Epix10kConfig && 1 < xtc->contains.version())
446  throw runtime_error("pixeldetector::Converter::operator: Epix10k Config version" +
447  toString(xtc->contains.version()) + "is not supported");
448  if (xtc->contains.id() == Pds::TypeId::Id_Epix100aConfig && 2 < xtc->contains.version())
449  throw runtime_error("pixeldetector::Converter::operator: Epix100a Config version" +
450  toString(xtc->contains.version()) + "is not supported");
451  if (xtc->contains.id() == Pds::TypeId::Id_EpixSConfig && 1 < xtc->contains.version())
452  throw runtime_error("pixeldetector::Converter::operator: EpixS Config version" +
453  toString(xtc->contains.version()) + "is not supported");
454  if (xtc->contains.id() == Pds::TypeId::Id_Epix10kaConfig && 1 < xtc->contains.version())
455  throw runtime_error("pixeldetector::Converter::operator: EpixS Config version" +
456  toString(xtc->contains.version()) + "is not supported");
457  _configStore[casskey] = make_pair(xtc->contains.value(),extractPayload(xtc));
458  }
459  break;
460 
461 
462  case (Pds::TypeId::Id_EpixElement) :
463  {
464  /** get the epix element from the xtc */
465  if (xtc->contains.version() != 3)
466  {
467  Log::add(Log::ERROR, string("pixeldetector::Converter::operator(): ") +
468  "Version '" + toString(xtc->contains.version()) +
469  "' of EpixElement is not yet supported");
470  break;
471  }
472  const Pds::Epix::ElementV3& element
473  (reinterpret_cast<const Pds::Epix::ElementV3&>(*(xtc->payload())));
474 
475  /** get the corrsponding config for the epix element */
476  configStore_t::const_iterator storeIt(_configStore.find(casskey));
477  if(storeIt == _configStore.end())
478  {
479  Log::add(Log::ERROR, string("pixeldetector::Converter::operator(): No configuration to read the data of '") +
480  TypeId::name(xtc->contains.id()) + "'(" + toString(xtc->contains.id()) +
481  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->detector()) +
482  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->detId()) +
483  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->device()) +
484  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->devId()) +
485  ")");
486  break;
487  }
488  const config_t config(storeIt->second);
489  const TypeId& configId(reinterpret_cast<const TypeId&>(config.first));
490  if (configId.value() != config.first)
491  throw logic_error("we've to implment the conversion from value to typeid differntly");
492  Detector &det(retrieveDet(*evt,casskey));
493  det.id() = evt->id();
494  /** @todo need to implement all configurtion types of the epix data type */
495  switch (configId.id())
496  {
497  case (TypeId::Id_EpixConfig):
498  {
499  const Pds::Epix::ConfigV1 &cfg
500  (reinterpret_cast<const Pds::Epix::ConfigV1&>(config.second.front()));
501  //copyEpixFrame(element,cfg,det);
502  }
503  break;
504 
505  case (TypeId::Id_Epix100aConfig):
506  {
507  switch (configId.version())
508  {
509  case 1:
510  {
511  const Pds::Epix::Config100aV1 &cfg
512  (reinterpret_cast<const Pds::Epix::Config100aV1&>(config.second.front()));
513  copyEpixFrame(element,cfg,det);
514  }
515  break;
516 
517  case 2:
518  {
519  const Pds::Epix::Config100aV2 &cfg
520  (reinterpret_cast<const Pds::Epix::Config100aV2&>(config.second.front()));
521  copyEpixFrame(element,cfg,det);
522  }
523  break;
524 
525  default:
526  throw runtime_error("LCLSConverter: Unknown epix100aconfig version '" +
527  toString(configId.version()) + "'");
528  }
529  }
530  break;
531 
532 
533  default:
534  throw runtime_error("LCLSConverter: Unknown epix configuration typeid '" +
535  toString(configId.id()) + "'");
536  }
537  }
538  break;
539 
540  case (Pds::TypeId::Id_pnCCDframe) :
541  {
542  configStore_t::const_iterator storeIt(_configStore.find(casskey));
543  if(storeIt == _configStore.end())
544  {
545  Log::add(Log::ERROR, string("pixeldetector::Converter::operator(): No configuration to read the data of '") +
546  TypeId::name(xtc->contains.id()) + "'(" + toString(xtc->contains.id()) +
547  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->detector()) +
548  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->detId()) +
549  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->device()) +
550  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->devId()) +
551  ")");
552  break;
553  }
554  const config_t config(storeIt->second);
555  const TypeId& configId(reinterpret_cast<const TypeId&>(config.first));
556  Detector &det(retrieveDet(*evt,casskey));
557  det.id() = evt->id();
558  switch (configId.version())
559  {
560  case 1:
561  {
562  const Pds::PNCCD::ConfigV1 &cfg
563  (reinterpret_cast<const Pds::PNCCD::ConfigV1&>(config.second.front()));
564  copyPnCCDFrame(xtc,cfg,det);
565  }
566  break;
567 
568  case 2:
569  {
570  const Pds::PNCCD::ConfigV2 &cfg
571  (reinterpret_cast<const Pds::PNCCD::ConfigV2&>(config.second.front()));
572  copyPnCCDFrame(xtc,cfg,det);
573  }
574  break;
575 
576  default:
577  throw runtime_error("LCLSConverter: Unknown PnCCD Version '" +
578  toString(config.first) + "'");
579  }
580  }
581  break;
582 
583  case (Pds::TypeId::Id_CspadElement) :
584  {
585  /** get the configuration for this element and return when there is no config */
586  configStore_t::const_iterator storeIt(_configStore.find(casskey));
587  if(storeIt == _configStore.end())
588  {
589  Log::add(Log::ERROR, string("pixeldetector::Converter::operator(): No configuration to read the data of '") +
590  TypeId::name(xtc->contains.id()) + "'(" + toString(xtc->contains.id()) +
591  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->detector()) +
592  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->detId()) +
593  "), '" + DetInfo::name(reinterpret_cast<const DetInfo*>(&xtc->src)->device()) +
594  "'(" + toString(reinterpret_cast<const DetInfo*>(&xtc->src)->devId()) +
595  ")");
596  break;
597  }
598  const config_t config(storeIt->second);
599  const TypeId& configId(reinterpret_cast<const TypeId&>(config.first));
600  Detector &det(retrieveDet(*evt,casskey));
601  det.id() = evt->id();
602  switch (configId.version())
603  {
604  case 1:
605  {
606  const Pds::CsPad::ConfigV1 &cfg
607  (reinterpret_cast<const Pds::CsPad::ConfigV1&>(config.second.front()));
608  copyCsPadFrame(xtc,cfg,det);
609  }
610  break;
611 
612  case 2:
613  {
614  const Pds::CsPad::ConfigV2 &cfg
615  (reinterpret_cast<const Pds::CsPad::ConfigV2&>(config.second.front()));
616  copyCsPadFrame(xtc,cfg,det);
617  }
618  break;
619 
620  case 3:
621  {
622  const Pds::CsPad::ConfigV3 &cfg
623  (reinterpret_cast<const Pds::CsPad::ConfigV3&>(config.second.front()));
624  copyCsPadFrame(xtc,cfg,det);
625  }
626  break;
627 
628  case 4:
629  {
630  const Pds::CsPad::ConfigV4 &cfg
631  (reinterpret_cast<const Pds::CsPad::ConfigV4&>(config.second.front()));
632  copyCsPadFrame(xtc,cfg,det);
633  }
634  break;
635 
636  case 5:
637  {
638  const Pds::CsPad::ConfigV5 &cfg
639  (reinterpret_cast<const Pds::CsPad::ConfigV5&>(config.second.front()));
640  copyCsPadFrame(xtc,cfg,det);
641  }
642  break;
643 
644  default:
645  throw runtime_error("LCLSConverter: Unknown CsPad Configuration Version '" +
646  toString(config.first) + "'");
647  }
648 
649 
650  }
651  break;
652 
653  case (Pds::TypeId::Id_Cspad2x2Element):
654  {
655  Detector &det(retrieveDet(*evt,casskey));
656  det.id() = evt->id();
657  const int asic_nx(Pds::CsPad::MaxRowsPerASIC);
658  const int asic_ny(Pds::CsPad::ColumnsPerASIC);
659  Pds::CsPad2x2::ElementHeader* head
660  (reinterpret_cast<Pds::CsPad2x2::ElementHeader*>(xtc->payload()));
661  const int pixelsPerSegment(2*asic_nx*asic_ny);
662  const int framesize(2*pixelsPerSegment);
663  det.frame().resize(framesize);
664  uint16_t* data = reinterpret_cast<uint16_t*>(head+1);
665  uint16_t* End = data + framesize;
666  Detector::frame_t::iterator firstSegment(det.frame().begin());
667  Detector::frame_t::iterator secondSegment(det.frame().begin() + pixelsPerSegment);
668  while (data != End)
669  {
670  *firstSegment++ = *data++;
671  *secondSegment++ = *data++;
672  }
673  det.columns() = 2 * 194;
674  det.rows() = 2 * 185;
675  }
676  break;
677 
678  case (Pds::TypeId::Id_Frame) :
679  {
680  Detector &det(retrieveDet(*evt,casskey));
681  det.id() = evt->id();
682  const Camera::FrameV1 &frame
683  (*reinterpret_cast<const Camera::FrameV1*>(xtc->payload()));
684  det.columns() = frame.width();
685  det.rows() = frame.height();
686  const uint16_t* framedata (reinterpret_cast<const uint16_t*>(frame.data()));
687  const size_t framesize(frame.width()*frame.height());
688  det.frame().resize(framesize);
689  transform(framedata,framedata + framesize,
690  det.frame().begin(),
691  bind2nd(minus<float>(),static_cast<float>(frame.offset())));
692  fill(det.frame().begin(),det.frame().begin()+8,*(det.frame().begin()+9));
693  }
694  break;
695 
696  default:
697  break;
698  }
699 }
setArrayIndex(int i)
definition of front detector[PixelDetectors] FrontPnCCD Detector
Event to store all LCLS Data.
Definition: cass_event.h:32
std::pair< uint32_t, std::vector< uint8_t > > config_t
pair the typeid of the config with a shared pointer of the config
contains the lcls keys
std::string & info()
setter
file contains declaration of the CASSEvent
Settings for CASS.
Definition: cass_settings.h:30
detectors_t & dets()
instrument setter
void copyCsPadFrame(const Pds::Xtc *xtc, const ConfigType &cfg, Detector &det)
copy the cspad frame to the detector
void copyPnCCDFrame(const Pds::Xtc *xtc, const ConfigType &cfg, Detector &det)
copy the pnCCD frame into the detector
STL namespace.
things written only at end of run H5Dump ProcessorSummary size
Detector & retrieveDet(CASSEvent &evt, const Device::detectors_t::key_type &key)
extract the right detector from the CASSEvent
static void add(Level level, const std::string &line)
add a string to the log
Definition: log.cpp:31
float pixel_t
define a pixel of the pixel detector
static QMutex _mutex
singleton locker for mutithreaded requests
void copyEpixFrame(const Pds::Epix::ElementV3 &element, const ConfigType &cfg, Detector &det)
copy the epix frame to the detector
beginReadArray(const QString &prefix)
vector< uint8_t > extractPayload(const Pds::Xtc *xtc)
copy payload of xtc into a bytearray
void operator()(const Pds::Xtc *xtc, cass::CASSEvent *evt)
operator to convert the LCLS Data to CASSEvent
devices_t & devices()
setters
Definition: cass_event.h:66
std::string & timingFilename()
setter
static ConversionBackend::shared_pointer _instance
the singleton container
id_t & id()
setters
Definition: cass_event.h:64
void copyAdditionalPnccdInfo(const Pds::PNCCD::ConfigV1 &, Detector &det, size_t &rowsOfSegment, size_t &columnsOfSegment)
copy additional info about the pnCCD
std::string toString(const Type &t)
convert any type to a string
Definition: cass.h:63
uint32_t & camaxMagic()
setter
auxiliary data[Processor]
std::tr1::shared_ptr< ConversionBackend > shared_pointer
typedef
value(const QString &key, const QVariant &defaultValue=QVariant()
std::map< Device, DeviceBackend::shared_pointer > devices_t
mapping from device type to handler instance
Definition: cass_event.h:46
Converter for pnCCD, CsPad and commercial CCD Data.
contains container for simple pixel detector data
file contains specialized class that do the settings for cass
the device containing pixel detector data
Detector containing a ccd camera image.
static ConversionBackend::shared_pointer instance()
create singleton if doesnt exist already
contains the converters to convert ccd and pnccd data to CASSEvent
contains a logger for cass
int16_t pixel
define a pixel
Definition: hlltypes.hpp:27
beginGroup(const QString &prefix)