CFEL - ASG Software Suite  2.5.0
CASS
machine_converter.cpp
Go to the documentation of this file.
1 // Copyright (C) 2009 - 2014 Lutz Foucar
2 
3 /**
4  * @file machine_converter.cpp contains xtc converter for machine data
5  *
6  * @author Lutz Foucar
7  */
8 
9 
10 #include <sstream>
11 #include <iostream>
12 
13 #include "machine_converter.h"
14 
15 #include "pdsdata/xtc/Xtc.hh"
16 #include "pdsdata/xtc/BldInfo.hh"
17 #include "pdsdata/bld/bldData.hh"
18 #include "pdsdata/epics/EpicsPvData.hh"
19 #include "pdsdata/evr/DataV3.hh"
20 #include "pdsdata/ipimb/DataV2.hh"
21 #include "pdsdata/xtc/DetInfo.hh"
22 #include "pdsdata/lusi/IpmFexV1.hh"
23 #include "pdsdata/lusi/IpmFexConfigV2.hh"
24 #include "pdsdata/control/ConfigV1.hh"
25 #include "pdsdata/control/PVControl.hh"
26 #include "pdsdata/psddl/usdusb.ddl.h"
27 
28 #include "cass_event.h"
29 #include "log.h"
30 #include "machine_device.hpp"
31 
32 using namespace cass::MachineData;
33 using namespace std;
34 
35 // =================define static members =================
38 
40 {
41  QMutexLocker locker(&_mutex);
42  if(!_instance)
43  {
45  }
46  return _instance;
47 }
48 // ========================================================
49 
50 
51 namespace cass
52 {
53 namespace MachineData
54 {
55 /** convert epics variable to double
56  *
57  * convert the value contained in the Epics variable to a double and fill it
58  * into the map. One has to define beforehand where to add it and pass the right
59  * iterator to the function
60  *
61  * @tparam valtype the value type of the epics variable
62  * @param epicsData the object that contains the epics data
63  * @param first iterator to the first entry in the map that needs to be filled
64  *
65  * @author Lutz Foucar
66  */
67 template <int valtype>
68 void convertEpicsToDouble(const Pds::EpicsPvHeader& epicsData,
69  Device::epicsDataMap_t::iterator first)
70 {
71  const Pds::EpicsPvTime<valtype> &p
72  (reinterpret_cast<const Pds::EpicsPvTime<valtype>&>(epicsData));
73  const typename Pds::EpicsDbrTools::DbrTypeFromInt<valtype>::TDbr* value(&p.value);
74  for(int i=0; i<epicsData.iNumElements; ++i)
75  first++->second = *value++;
76 }
77 
78 /** convert epics variable to double and fill store and cassevent
79  *
80  * convert the value contained in the Epics variable to a double and fill it
81  * into the map. One has to define beforehand where to add it and pass the right
82  * iterator to the function
83  *
84  * @tparam valtype the value type of the epics variable
85  * @param epicsData the object that contains the epics data
86  * @param storefirst iterator to the first entry in the epics part of store
87  * @param cassfirst iterator to the first entry in the epics part of cassevent
88  *
89  * @author Lutz Foucar
90  */
91 template <int valtype>
92 void epicsValToCassVal(const Pds::EpicsPvHeader& epicsData,
93  Device::epicsDataMap_t::iterator storefirst,
94  Device::epicsDataMap_t::iterator cassfirst)
95 {
96  const Pds::EpicsPvTime<valtype> &p
97  (reinterpret_cast<const Pds::EpicsPvTime<valtype>&>(epicsData));
98  const typename Pds::EpicsDbrTools::DbrTypeFromInt<valtype>::TDbr* value(&p.value);
99  for(int i=0; i<epicsData.iNumElements; ++i)
100  {
101  const double val(*value++);
102  storefirst++->second = val;
103  cassfirst++->second = val;
104  }
105 }
106 
107 /** convert epics variable to nothing
108  *
109  * don't do anything. This function is needed, because string types can't be
110  * converted, therefore this is used as dummy for epics string types.
111  *
112  * @tparam valtype the value type of the epics variable
113  * @param epicsData the object that contains the epics data
114  * @param storefirst iterator to the first entry in the epics part of store
115  * @param cassfirst iterator to the first entry in the epics part of cassevent
116  *
117  * @author Lutz Foucar
118  */
119 void epicsValToNothing(const Pds::EpicsPvHeader& /*epicsData*/,
120  Device::epicsDataMap_t::iterator /*storefirst*/,
121  Device::epicsDataMap_t::iterator /*cassfirst*/)
122 
123 {
124 
125 }
126 
127 /** Key for the xtc data lookup map
128  *
129  * Key for mapping Epics index and list to a specific name
130  *
131  * @author Lutz Foucar
132  */
134 {
135 public:
136  /** constructor
137  *
138  * @param src the info about the source of the xtc data
139  * @param index the index of the the xtc data in the list
140  */
141  XTCDataKey(const Pds::Src &src, uint32_t index)
142  : _key(((static_cast<uint64_t>(src.phy())&0xffffffff)<<32) | (index&0xffffffff))
143  {}
144 
145  /** check whether this is less than other
146  *
147  * @return true when this is smaller than other
148  * @param other the other key that one compares this key to
149  */
150  bool operator <(const XTCDataKey& other) const
151  {
152  return _key < other._key;
153  }
154 
155 private:
156  /** the combined key */
157  uint64_t _key;
158 
159 };
160 }//end namespace MachineData
161 }//end namespace cass
162 
164 {
165  _pdsTypeList.push_back(Pds::TypeId::Id_Epics);
166  _pdsTypeList.push_back(Pds::TypeId::Id_FEEGasDetEnergy);
167  _pdsTypeList.push_back(Pds::TypeId::Id_EBeam);
168  _pdsTypeList.push_back(Pds::TypeId::Id_PhaseCavity);
169  _pdsTypeList.push_back(Pds::TypeId::Id_EvrData);
170  _pdsTypeList.push_back(Pds::TypeId::Id_IpimbData);
171  _pdsTypeList.push_back(Pds::TypeId::Id_IpmFex);
172  _pdsTypeList.push_back(Pds::TypeId::Id_ControlConfig);
173  _pdsTypeList.push_back(Pds::TypeId::Id_Spectrometer);
174  _pdsTypeList.push_back(Pds::TypeId::Id_UsdUsbFexConfig);
175  _pdsTypeList.push_back(Pds::TypeId::Id_UsdUsbFexData);
176 
177  _epicsType2convFunc[DBR_TIME_SHORT] = &epicsValToCassVal<DBR_SHORT>;
178  _epicsType2convFunc[DBR_TIME_FLOAT] = &epicsValToCassVal<DBR_FLOAT>;
179  _epicsType2convFunc[DBR_TIME_ENUM] = &epicsValToCassVal<DBR_ENUM>;
180  _epicsType2convFunc[DBR_TIME_LONG] = &epicsValToCassVal<DBR_LONG>;
181  _epicsType2convFunc[DBR_TIME_DOUBLE] = &epicsValToCassVal<DBR_DOUBLE>;
182  _epicsType2convFunc[DBR_TIME_STRING] = &epicsValToNothing;
183 }
184 
185 void cass::MachineData::Converter::operator()(const Pds::Xtc* xtc, cass::CASSEvent* cassevent)
186 {
187 
188  switch (xtc->contains.id())
189  {
190 
191 
192  case(Pds::TypeId::Id_FEEGasDetEnergy):
193  {
194  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
195  uint32_t version (xtc->contains.version());
196  const Pds::BldDataFEEGasDetEnergy &gasdet =
197  *reinterpret_cast<const Pds::BldDataFEEGasDetEnergy*>(xtc->payload());
198  switch (version)
199  {
200  case(1):
201  md.BeamlineData()["f_63_ENRC"] = gasdet.f_63_ENRC;
202  md.BeamlineData()["f_64_ENRC"] = gasdet.f_64_ENRC;
203  case(0):
204  md.BeamlineData()["f_11_ENRC"] = gasdet.f_11_ENRC;
205  md.BeamlineData()["f_12_ENRC"] = gasdet.f_12_ENRC;
206  md.BeamlineData()["f_21_ENRC"] = gasdet.f_21_ENRC;
207  md.BeamlineData()["f_22_ENRC"] = gasdet.f_22_ENRC;
208  break;
209  default:
210  Log::add(Log::ERROR,"Unknown FEEGasDet version");
211  break;
212  }
213  }
214 
215 
216  case(Pds::TypeId::Id_EBeam):
217  {
218  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
219  uint32_t version (xtc->contains.version());
220  const Pds::BldDataEBeam &beam =
221  *reinterpret_cast<const Pds::BldDataEBeam*>(xtc->payload());
222  switch (version)
223  {
224  default:
225  Log::add(Log::WARNING,"Unknown BLD version '" + toString(version) +
226  "' using latest known version '7'");
227  /** BldDataEBeamV7 is the same as BldDataEBeamV6.
228  * A sign-error error was discovered in the calculation of the photon
229  * energy that goes into the ebeam bld. This is fixed on the accelerator
230  * side, but we will increment the ebeam bld version number to V7 so the
231  * data is clearly marked as changed.
232  */
233  case (7):
234  case (6):
235  {
236  if(!(Pds::BldDataEBeam::EbeamPhotonEnergyDamage & beam.uDamageMask))
237  md.BeamlineData()["EbeamPhotonEnergy"]= beam.fEbeamPhotonEnergy;
238  else
239  Log::add(Log::VERBOSEINFO,"'EbeamPhotonEnergy' is damaged");
240 
241 // if(!(Pds::BldDataEBeam::EbeamXTCAVPhaseDamage & beam.uDamageMask))
242  md.BeamlineData()["fEbeamLTU250"]= beam.fEbeamLTU250;
243 // else
244 // Log::add(Log::VERBOSEINFO,"'EbeamXTCAVPhase' is damaged");
245 
246 // if(!(Pds::BldDataEBeam::EbeamDumpChargeDamage & beam.uDamageMask))
247  md.BeamlineData()["EbeamLTU450"]= beam.fEbeamLTU450;
248 // else
249 // Log::add(Log::VERBOSEINFO,"'EbeamDumpCharge' is damaged");
250 
251  }
252  case (5):
253  {
254  if(!(Pds::BldDataEBeam::EbeamXTCAVAmplDamage & beam.uDamageMask))
255  md.BeamlineData()["EbeamXTCAVAmpl"]= beam.fEbeamXTCAVAmpl;
256  else
257  Log::add(Log::VERBOSEINFO,"'EbeamXTCAVAmpl' is damaged");
258 
259  if(!(Pds::BldDataEBeam::EbeamXTCAVPhaseDamage & beam.uDamageMask))
260  md.BeamlineData()["EbeamXTCAVPhase"]= beam.fEbeamXTCAVPhase;
261  else
262  Log::add(Log::VERBOSEINFO,"'EbeamXTCAVPhase' is damaged");
263 
264  if(!(Pds::BldDataEBeam::EbeamDumpChargeDamage & beam.uDamageMask))
265  md.BeamlineData()["EbeamDumpCharge"]= beam.fEbeamDumpCharge;
266  else
267  Log::add(Log::VERBOSEINFO,"'EbeamDumpCharge' is damaged");
268  }
269  case (4):
270  {
271  if(!(Pds::BldDataEBeam::EbeamUndPosXDamage & beam.uDamageMask))
272  md.BeamlineData()["EbeamUndPosX"]= beam.fEbeamUndPosX;
273  else
274  Log::add(Log::VERBOSEINFO,"'EbeamUndPosX' is damaged");
275 
276  if(!(Pds::BldDataEBeam::EbeamUndPosYDamage & beam.uDamageMask))
277  md.BeamlineData()["EbeamUndPosY"]= beam.fEbeamUndPosY;
278  else
279  Log::add(Log::VERBOSEINFO,"'EbeamUndPosY' is damaged");
280 
281  if(!(Pds::BldDataEBeam::EbeamUndAngXDamage & beam.uDamageMask))
282  md.BeamlineData()["EbeamUndAngX"]= beam.fEbeamUndAngX;
283  else
284  Log::add(Log::VERBOSEINFO,"'EbeamUndPosX' is damaged");
285 
286  if(!(Pds::BldDataEBeam::EbeamUndAngYDamage & beam.uDamageMask))
287  md.BeamlineData()["EbeamUndAngY"]= beam.fEbeamUndAngY;
288  else
289  Log::add(Log::VERBOSEINFO,"'EbeamUndPosY' is damaged");
290  }
291  case (3):
292  {
293  if(!(Pds::BldDataEBeam::EbeamPkCurrBC1Damage & beam.uDamageMask))
294  md.BeamlineData()["EbeamPkCurrBC1"]= beam.fEbeamPkCurrBC1;
295  else
296  Log::add(Log::VERBOSEINFO,"'EbeamPkCurrBC1' is damaged");
297 
298  if(!(Pds::BldDataEBeam::EbeamEnergyBC1Damage & beam.uDamageMask))
299  md.BeamlineData()["fEbeamEnergyBC1"]= beam.fEbeamEnergyBC1;
300  else
301  Log::add(Log::VERBOSEINFO,"'fEbeamEnergyBC1' is damaged");
302  }
303  case (2):
304  {
305  if(!(Pds::BldDataEBeam::EbeamEnergyBC2Damage & beam.uDamageMask))
306  md.BeamlineData()["EbeamEnergyBC2"]= beam.fEbeamEnergyBC2;
307  else
308  Log::add(Log::VERBOSEINFO,"'EbeamEnergyBC2' is damaged");
309  }
310  case (1):
311  {
312  if(!(Pds::BldDataEBeam::EbeamPkCurrBC2Damage & beam.uDamageMask))
313  md.BeamlineData()["EbeamPkCurrBC2"]= beam.fEbeamPkCurrBC2;
314  else
315  Log::add(Log::VERBOSEINFO,"'EbeamPkCurrBC2' is damaged");
316  }
317  case (0):
318  {
319  if(!(Pds::BldDataEBeam::EbeamChargeDamage & beam.uDamageMask))
320  md.BeamlineData()["EbeamCharge"] = beam.fEbeamCharge;
321  else
322  Log::add(Log::VERBOSEINFO,"'EbeamCharge' is damaged");
323 
324  if(!(Pds::BldDataEBeam::EbeamL3EnergyDamage & beam.uDamageMask))
325  md.BeamlineData()["EbeamL3Energy"] = beam.fEbeamL3Energy;
326  else
327  Log::add(Log::VERBOSEINFO,"'EbeamL3Energy' is damaged");
328 
329  if(!(Pds::BldDataEBeam::EbeamLTUAngXDamage & beam.uDamageMask))
330  md.BeamlineData()["EbeamLTUAngX"] = beam.fEbeamLTUAngX;
331  else
332  Log::add(Log::VERBOSEINFO,"'EbeamLTUAngX' is damaged");
333 
334  if(!(Pds::BldDataEBeam::EbeamLTUAngYDamage & beam.uDamageMask))
335  md.BeamlineData()["EbeamLTUAngY"] = beam.fEbeamLTUAngY;
336  else
337  Log::add(Log::VERBOSEINFO,"'EbeamLTUAngY' is damaged");
338 
339  if(!(Pds::BldDataEBeam::EbeamLTUPosXDamage & beam.uDamageMask))
340  md.BeamlineData()["EbeamLTUPosX"] = beam.fEbeamLTUPosX;
341  else
342  Log::add(Log::VERBOSEINFO,"'EbeamLTUPosX' is damaged");
343 
344  if(!(Pds::BldDataEBeam::EbeamLTUPosYDamage & beam.uDamageMask))
345  md.BeamlineData()["EbeamLTUPosY"] = beam.fEbeamLTUPosY;
346  else
347  Log::add(Log::VERBOSEINFO,"'EbeamLTUPosY' is damaged");
348  break;
349  }
350  }
351  break;
352  }
353 
354 
355  case(Pds::TypeId::Id_PhaseCavity):
356  {
357  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
358  const Pds::BldDataPhaseCavity &cavity =
359  *reinterpret_cast<const Pds::BldDataPhaseCavity*>(xtc->payload());
360  md.BeamlineData()["Charge1"] = cavity.fCharge1;
361  md.BeamlineData()["Charge2"] = cavity.fCharge2;
362  md.BeamlineData()["FitTime1"] = cavity.fFitTime1;
363  md.BeamlineData()["FitTime2"] = cavity.fFitTime2;
364  break;
365  }
366 
367 
368  case(Pds::TypeId::Id_Epics):
369  {
370  /** need to lock this operation as it involves the store used by all */
371  QMutexLocker lock(&_mutex);
372 
373  /** get the epics header and the epics id for this epics variable */
374  const Pds::EpicsPvHeader& epicsData =
375  *reinterpret_cast<const Pds::EpicsPvHeader*>(xtc->payload());
376  XTCDataKey key(xtc->src,epicsData.iPvId);
377 
378  /** cntrl is a configuration type and will only be send with a configure
379  * transition
380  */
381  if ( dbr_type_is_CTRL(epicsData.iDbrType) )
382  {
383  const Pds::EpicsPvCtrlHeader& ctrl =
384  static_cast<const Pds::EpicsPvCtrlHeader&>(epicsData);
385  /** create a key for the epics list and index. If this is an additional
386  * list, prepend the detInfo to the epics variable name
387  */
388  string epicsVariableName(ctrl.sPvName);
389  _index2name[key] = epicsVariableName;
390  /** now we need to create the map which we will fill later with real values
391  * if this epics variable is an array we want an entry in the map for each entry in the array
392  */
393  if (ctrl.iNumElements > 1)
394  {
395  /** go through all entries of the array
396  * create an entry in the map with the the index in brackets
397  * and initialize it with 0
398  */
399  for (int i=0;i<ctrl.iNumElements;++i)
400  {
401  std::stringstream entryname;
402  entryname << epicsVariableName << "[" << i << "]";
403  _store.EpicsData()[entryname.str()] = 0.;
404  Log::add(Log::INFO,"MachineData::Converter: '" + entryname.str() +
405  "' is available in Epics Data");;
406  }
407  }
408  /** otherwise we just add the name to the map and initialze it with 0 */
409  else
410  {
411  _store.EpicsData()[epicsVariableName] = 0.;
412  Log::add(Log::INFO,"MachineData::Converter: '" + epicsVariableName +
413  "' is available in Epics Data");
414  }
415  }
416  /** time is the actual data, that will be send down the xtc with 1 Hz */
417  else if(dbr_type_is_TIME(epicsData.iDbrType))
418  {
419  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
420 
421  /** now we need to find the variable name in the map, therefore we look up
422  * the name in the indexmap
423  */
424  KeyMap_t::const_iterator eIt(_index2name.find(key));
425  if (eIt == _index2name.end())
426  Log::add(Log::ERROR, "MachineData::Converter: Epics variable with id '" +
427  toString(epicsData.iPvId) + "' was not defined");
428  else
429  {
430  string epicsVariableName(eIt->second);
431 
432  /** if it is an array go through all entries of the array create an entry
433  * in the map with the the index in brackets and initialize it with 0
434  */
435  if (epicsData.iNumElements > 1)
436  epicsVariableName.append("[0]");
437 
438  /** try to find the the name in the map
439  * this returns an iterator to the first entry we found
440  * if it was an array we can then use the iterator to the next values
441  */
442  Device::epicsDataMap_t::iterator storeIt =
443  _store.EpicsData().find(epicsVariableName);
444  Device::epicsDataMap_t::iterator cassIt =
445  md.EpicsData().find(epicsVariableName);
446  /** if the name is not in the map, ouput error message */
447  if (storeIt == _store.EpicsData().end() || cassIt == md.EpicsData().end())
448  Log::add(Log::ERROR, "MachineData::Converter: Epics variable with id '" +
449  toString(epicsData.iPvId) + "' was not found in store or cassevent");
450  /** otherwise extract the epicsData and write it into the map */
451  else
452  {
453  _epicsType2convFunc[epicsData.iDbrType](epicsData,storeIt,cassIt);
454  }
455  /** set the variable that the epics store was filled */
456  md.epicsFilled() = true;
457  }
458  }
459  break;
460  }
461 
462 
463  case(Pds::TypeId::Id_EvrData):
464  {
465  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
466  /** clear the status bytes of the event code */
467  std::fill(md.EvrData().begin(),md.EvrData().end(),false);
468  /** get the evr data */
469  const Pds::EvrData::DataV3 &evrData =
470  *reinterpret_cast<const Pds::EvrData::DataV3*>(xtc->payload());
471  /** how many events have happened between the last event and now */
472  const uint32_t nbrFifoEvents = evrData.numFifoEvents();
473  /** go through all events and extract the eventcode from them */
474  for (size_t i=0;i<nbrFifoEvents;++i)
475  {
476  const Pds::EvrData::DataV3::FIFOEvent& fifoEvent = evrData.fifoEvent(i);
477  uint32_t eventcode = fifoEvent.EventCode;
478  /** check if the array is big enough to hold the recorded eventcode */
479  if (md.EvrData().size() < eventcode )
480  md.EvrData().resize(eventcode+1,false);
481  md.EvrData()[eventcode]=true;
482  }
483  break;
484  }
485 
486 
487  case(Pds::TypeId::Id_IpimbData):
488  {
489  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
490  const Pds::DetInfo& info = *(Pds::DetInfo*)(&xtc->src);
491  string detector(Pds::DetInfo::name(info.detector()));
492  const Pds::Ipimb::DataV2& ipimbData =
493  *reinterpret_cast<const Pds::Ipimb::DataV2*>(xtc->payload());
494  md.BeamlineData()[detector + "_Channel0"] = ipimbData.channel0Volts();
495  md.BeamlineData()[detector + "_Channel1"] = ipimbData.channel1Volts();
496  md.BeamlineData()[detector + "_Channel2"] = ipimbData.channel2Volts();
497  md.BeamlineData()[detector + "_Channel3"] = ipimbData.channel3Volts();
498  }
499  break;
500 
501 
502  case(Pds::TypeId::Id_IpmFex):
503  {
504  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
505  const Pds::DetInfo& info = *(Pds::DetInfo*)(&xtc->src);
506  string detector(Pds::DetInfo::name(info.detector()));
507  const Pds::Lusi::IpmFexV1& ipmfex =
508  *reinterpret_cast<const Pds::Lusi::IpmFexV1*>(xtc->payload());
509  for(size_t i=0; i<Pds::Lusi::IpmFexConfigV2::NCHANNELS; i++)
510  {
511  stringstream ss;
512  ss << detector << "_CorrectChannel" << i;
513  md.BeamlineData()[ss.str()] = ipmfex.channel[i];
514  }
515  md.BeamlineData()[detector + "_sum"] = ipmfex.sum;
516  md.BeamlineData()[detector + "_xPos"] = ipmfex.xpos;
517  md.BeamlineData()[detector + "_yPos"] = ipmfex.ypos;
518  break;
519  }
520 
521 
522  case(Pds::TypeId::Id_ControlConfig):
523  {
524  QMutexLocker lock(&_mutex);
525  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
526  /** add variables to store, cassevent and to log */
527  const Pds::ControlData::ConfigV1& config = *reinterpret_cast<const Pds::ControlData::ConfigV1*>(xtc->payload());
528  string log("MachineData::Converter: Calibcylce: [" +
529  toString(config.npvControls())+ " values]: ");
530  for (unsigned int i = 0; i < config.npvControls(); i++)
531  {
532  const Pds::ControlData::PVControl &pvControlCur = config.pvControl(i);
533  _store.BeamlineData()[pvControlCur.name()] = pvControlCur.value();
534  if(cassevent)
535  md.BeamlineData()[pvControlCur.name()] = pvControlCur.value();
536  log += string(pvControlCur.name()) + " = " + toString(pvControlCur.value()) + "; ";
537  }
538  Log::add(Log::INFO,log);
539  break;
540  }
541 
542 
543  case(Pds::TypeId::Id_Spectrometer):
544  {
545  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
546  uint32_t version(xtc->contains.version());
547  string specname
548  (Pds::BldInfo::name(reinterpret_cast<const Pds::BldInfo&>(xtc->src)));
549  Device::spectrometer_t::mapped_type &horiz
550  (md.spectrometers()[specname +"_horiz"]);
551  Device::spectrometer_t::mapped_type &vert
552  (md.spectrometers()[specname +"_vert"]);
553  switch (version)
554  {
555  case (0):
556  {
557  const Pds::BldDataSpectrometerV0 &spec
558  (*reinterpret_cast<const Pds::BldDataSpectrometerV0*>(xtc->payload()));
559  horiz.assign(spec._hproj,spec._hproj+1024);
560  vert.assign(spec._vproj,spec._vproj+256);
561  break;
562  }
563  case (1):
564  {
565  const Pds::BldDataSpectrometerV1 *spec
566  (reinterpret_cast<const Pds::BldDataSpectrometerV1*>(xtc->payload()));
567  const uint32_t* first(reinterpret_cast<const uint32_t*>(reinterpret_cast<const char*>(spec)+48));
568  const uint32_t* last(first + spec->_width);
569  horiz.assign(first,last);
570  break;
571  }
572  default:
573  Log::add(Log::ERROR,"Unknown Spectrometer Version '" + toString(version) +
574  "'. Skipping reading of Spectrometer data.");
575  break;
576  }
577  break;
578  }
579 
580 
581  case(Pds::TypeId::Id_EOrbits):
582  {
583  Device &md(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])));
584  uint32_t version(xtc->contains.version());
585  switch (version)
586  {
587  case (0):
588  {
589  const Pds::BldDataEOrbitsV0 *data
590  (reinterpret_cast<const Pds::BldDataEOrbitsV0*>(xtc->payload()));
591  /** BPM X values (mm) */
592  ptrdiff_t offset(4);
593  const double* x_first(reinterpret_cast<const double*>(reinterpret_cast<const char*>(data)+offset));
594  const double* x_last(x_first + data->_nBPMS);
595  /** BPM Y values (mm) */
596  offset = 4+(8*(data->_nBPMS));
597  const double* y_first(reinterpret_cast<const double*>(reinterpret_cast<const char*>(data)+offset));
598  const double* y_last(y_first + data->_nBPMS);
599  /** BPM TMIT values (Nel) */
600  offset = (4+(8*(data->_nBPMS)))+(8*(data->_nBPMS));
601  const double* tmit_first(reinterpret_cast<const double*>(reinterpret_cast<const char*>(data)+offset));
602  const double* tmit_last(tmit_first + data->_nBPMS);
603  break;
604  }
605  default:
606  Log::add(Log::ERROR,"Unknown EOrbits Version '" + toString(version) +
607  "'. Skipping reading of EOrbits data.");
608  break;
609  }
610  break;
611  }
612 
613  case(Pds::TypeId::Id_UsdUsbFexConfig):
614  {
615  switch(xtc->contains.version())
616  {
617  default:
618  {
619  Log::add(Log::WARNING,"Unknown USDUBS config version '" +
620  toString(xtc->contains.version()) + "' ignoring data");
621  break;
622  }
623 
624  case(1):
625  {
626  const Pds::UsdUsb::FexConfigV1& usbcfg =
627  *reinterpret_cast<const Pds::UsdUsb::FexConfigV1*>(xtc->payload());
628  for (int i(0); i<(Pds::UsdUsb::FexConfigV1::NCHANNELS); ++i)
629  {
630  string name(Pds::DetInfo::name(reinterpret_cast<const Pds::DetInfo&>(xtc->src)));
631  name += ":" + toString(i) + ":";
632  name += usbcfg._name[i];
633  _index2name[XTCDataKey(xtc->src,i)] = name;
634  Log::add(Log::INFO,"MachineData::Converter: '" + name +
635  "' is available in Beamline Data");
636  }
637  }
638  }
639  break;
640  }
641 
642  case(Pds::TypeId::Id_UsdUsbFexData):
643  {
644  if (cassevent)
645  {
646  Device::bldMap_t& bld(dynamic_cast<Device&>(*(cassevent->devices()[cass::CASSEvent::MachineData])).BeamlineData());
647  switch(xtc->contains.version())
648  {
649  default:
650  {
651  Log::add(Log::WARNING,"Unknown USDUSB data version '" +
652  toString(xtc->contains.version()) + "' ignoring data");
653  break;
654  }
655 
656  case(1):
657  {
658  const Pds::UsdUsb::FexDataV1& usbdata =
659  *reinterpret_cast<const Pds::UsdUsb::FexDataV1*>(xtc->payload());
660  for (int i(0); i<(Pds::UsdUsb::FexDataV1::Encoder_Inputs); ++i)
661  {
662  KeyMap_t::const_iterator it(_index2name.find(XTCDataKey(xtc->src,i)));
663  if (it == _index2name.end())
664  {
665  Log::add(Log::ERROR, string("MachineData::Converter: USDUSB variable from '") +
666  Pds::DetInfo::name(reinterpret_cast<const Pds::DetInfo&>(xtc->src)) +
667  "' with encoder '" + toString(i) + "' was not defined");
668  }
669  else
670  {
671  //cout <<it->second<<" " << usbdata._encoder_value[i]<<endl;
672  bld[it->second] = usbdata._encoder_value[i];
673  }
674  }
675  break;
676  }
677  }
678  }
679  break;
680  }
681 
682  default: break;
683  }//end switch
684 }
685 
687 {
688  /** clear the beamline data by setting every value to 0
689  * and reset the filled flag
690  *
691  * @note clearing is needed to be done at this point, because the map will
692  * be updated multiple times during the conversion process and
693  * therefore clearing it during the conversion will erase variables
694  * that have already been set.
695  */
696  if (evt)
697  {
698  QMutexLocker lock(&_mutex);
699  Device &md(dynamic_cast<Device&>(*(evt->devices()[cass::CASSEvent::MachineData])));
700  Device::bldMap_t::iterator bi (md.BeamlineData().begin());
701  Device::bldMap_t::const_iterator bEnd (md.BeamlineData().end());
702  for (; bi != bEnd ;++bi)
703  bi->second = 0;
704  md.epicsFilled() = false;
705  /** copy values in the store to the event */
706  md.EpicsData() = _store.EpicsData();
707  /** @note we want to add the addional values that are in the store to
708  * the beamline data of the event therefore we should not use the
709  * assignment operator here
710  */
711  Device::bldMap_t::const_iterator it (_store.BeamlineData().begin());
712  Device::bldMap_t::const_iterator End (_store.BeamlineData().end());
713  for(; it != End; ++it)
714  md.BeamlineData()[it->first] = it->second;
715  md.spectrometers().clear();
716  }
717 }
718 
720 {
721 }
contains xtc converter for machine data
Event to store all LCLS Data.
Definition: cass_event.h:32
uint64_t _key
the combined key
void epicsValToNothing(const Pds::EpicsPvHeader &, Device::epicsDataMap_t::iterator, Device::epicsDataMap_t::iterator)
convert epics variable to nothing
static ConversionBackend::shared_pointer _instance
the singleton container
file contains declaration of the CASSEvent
STL namespace.
bool operator<(const pp240::indexf_t &lhs, const pp240::indexf_t::first_type rhs)
operates less of an indices to a scalar
Definition: imaging.cpp:87
additional info
static void add(Level level, const std::string &line)
add a string to the log
Definition: log.cpp:31
Container for all Machine related Data.
bool epicsFilled() const
getter
devices_t & devices()
setters
Definition: cass_event.h:66
void convertEpicsToDouble(const Pds::EpicsPvHeader &epicsData, Device::epicsDataMap_t::iterator first)
convert epics variable to double
std::string toString(const Type &t)
convert any type to a string
Definition: cass.h:63
auxiliary data[Processor]
std::tr1::shared_ptr< ConversionBackend > shared_pointer
typedef
Key for the xtc data lookup map.
std::map< std::string, double > bldMap_t
define the beamline data container
void operator()(const Pds::Xtc *xtc, cass::CASSEvent *evt)
called for appropriate xtc part.
void epicsValToCassVal(const Pds::EpicsPvHeader &epicsData, Device::epicsDataMap_t::iterator storefirst, Device::epicsDataMap_t::iterator cassfirst)
convert epics variable to double and fill store and cassevent
const evrStatus_t & EvrData() const
getter
definitions of a machine device
static QMutex _mutex
singleton locker for mutithreaded requests
XTCDataKey(const Pds::Src &src, uint32_t index)
constructor
static ConversionBackend::shared_pointer instance()
create singleton if doesnt exist already
offset
void prepare(CASSEvent *evt)
called before the conversion
Electron detector
Definition: hdf5-input.ini:62
Converter for Beamline-, Cavity-, Epics- and EVR Data.
contains a logger for cass
void finalize(CASSEvent *evt)
called at the end of the conversion
check if there is some light in the chamber based upon the GMD value
const bldMap_t & BeamlineData() const
getter