EUDAQ
 All Classes Namespaces Files Functions Variables Pages
CMSPixelHelper.hh
1 #include "api.h"
2 #include "dictionaries.h"
3 #include "constants.h"
4 #include "datasource_evt.h"
5 
6 #if USE_LCIO
7 #include "IMPL/LCEventImpl.h"
8 #include "IMPL/TrackerRawDataImpl.h"
9 #include "IMPL/TrackerDataImpl.h"
10 #include "IMPL/LCCollectionVec.h"
11 #include "IMPL/LCGenericObjectImpl.h"
12 #include "UTIL/CellIDEncoder.h"
13 #include "lcio.h"
14 #endif
15 
16 #if USE_EUTELESCOPE
17 #include "EUTELESCOPE.h"
18 #include "EUTelEventImpl.h"
19 #include "EUTelTrackerDataInterfacerImpl.h"
20 #include "EUTelGenericSparsePixel.h"
21 #include "EUTelRunHeaderImpl.h"
22 
23 using eutelescope::EUTELESCOPE;
24 #endif
25 
26 using namespace pxar;
27 
28 namespace eudaq {
29 
31  public:
32  CMSPixelHelper(std::string event_type) : m_event_type(event_type){};
33 
34  void Initialize(const Event &bore, const Configuration &cnf) {
35  DeviceDictionary *devDict;
36  std::string roctype = bore.GetTag("ROCTYPE", "");
37  std::string tbmtype = bore.GetTag("TBMTYPE", "notbm");
38 
39  m_detector = bore.GetTag("DETECTOR", "");
40  std::string pcbtype = bore.GetTag("PCBTYPE", "");
41  m_rotated_pcb =
42  (pcbtype.find("-rot") != std::string::npos ? true : false);
43 
44  // Get the number of planes:
45  m_nplanes = bore.GetTag("PLANES", 1);
46 
47  m_roctype = devDict->getInstance()->getDevCode(roctype);
48  m_tbmtype = devDict->getInstance()->getDevCode(tbmtype);
49 
50  if (m_roctype == 0x0) {
51  EUDAQ_THROW("Data contains invalid ROC type: " + roctype);
52  }
53  if(m_tbmtype == 0x0) {
54  EUDAQ_THROW("Data contains invalid TBM type: " + tbmtype);
55  }
56 
57  std::cout << "CMSPixel Converter initialized with detector " << m_detector
58  << ", Event Type " << m_event_type << ", TBM type " << tbmtype
59  << " (" << static_cast<int>(m_tbmtype) << ")"
60  << ", ROC type " << roctype << " ("
61  << static_cast<int>(m_roctype) << ")" << std::endl;
62 
63  if (m_detector == "TRP") {
64  m_planeid = 6;
65  } // TRP
66  else if (m_detector == "DUT") {
67  m_planeid = 7;
68  } // DUT
69  else if (m_detector == "REF") {
70  m_planeid = 8;
71  } // REF
72  else {
73  m_planeid = 9;
74  } // QUAD
75 
76  // Set decoder to reasonable verbosity (still informing about problems:
77  pxar::Log::ReportingLevel() = pxar::Log::FromString("WARNING");
78  //pxar::Log::ReportingLevel() = pxar::Log::FromString("DEBUGPIPES");
79 
80  // Connect the data source and set up the pipe:
81  src = evtSource(0, m_nplanes, 0, m_tbmtype, m_roctype, FLAG_DISABLE_EVENTID_CHECK);
82  src >> splitter >> decoder >> Eventpump;
83  }
84 
85  bool GetStandardSubEvent(StandardEvent &out, const Event &in) const {
86 
87  // If we receive the EORE print the collected statistics:
88  if (in.IsEORE()) {
89  // Set decoder to INFO level for statistics printout:
90  std::cout << "Decoding statistics for detector " << m_detector
91  << std::endl;
92  pxar::Log::ReportingLevel() = pxar::Log::FromString("INFO");
93  decoder.getStatistics().dump();
94  return true;
95  }
96  // Check if we have BORE:
97  else if (in.IsBORE()) {
98  return true;
99  }
100 
101  const RawDataEvent &in_raw = dynamic_cast<const RawDataEvent &>(in);
102  // Check of we have more than one data block:
103  if (in_raw.NumBlocks() > 1) {
104  EUDAQ_ERROR("Only one data block is expected!");
105  return false;
106  }
107 
108  // Transform from EUDAQ data, add it to the datasource:
109  src.AddData(TransformRawData(in_raw.GetBlock(0)));
110  // ...and pull it out at the other end:
111  pxar::Event *evt = Eventpump.Get();
112 
113  // If we have no TBM or a TBM Emulator, assume this is
114  // some sort of multi-plane telescope:
115  if (m_tbmtype <= TBM_EMU)
116  GetMultiPlanes(out, m_planeid, evt);
117  // If we have a real TBM attached, this is probably
118  // a module with just one sensor plane:
119  else
120  GetSinglePlane(out, m_planeid, evt);
121  }
122 
123 #if USE_LCIO && USE_EUTELESCOPE
124  virtual void GetLCIORunHeader(lcio::LCRunHeader &header,
125  eudaq::Event const & /*bore*/,
126  eudaq::Configuration const &conf) const {
127  eutelescope::EUTelRunHeaderImpl runHeader(&header);
128  // Type of data: real.
129  runHeader.setDAQHWName(EUTELESCOPE::DAQDATA);
130  }
131 
132  virtual bool GetLCIOSubEvent(lcio::LCEvent &result,
133  const Event &source) const {
134 
135  if (source.IsBORE()) {
136  std::cout << "CMSPixelConverterPlugin::GetLCIOSubEvent BORE " << source
137  << std::endl;
138  return true;
139  } else if (source.IsEORE()) {
140  std::cout << "CMSPixelConverterPlugin::GetLCIOSubEvent EORE " << source
141  << std::endl;
142  return true;
143  }
144 
145  // Set event type Data Event (kDE):
146  result.parameters().setValue(eutelescope::EUTELESCOPE::EVENTTYPE,
147  eutelescope::kDE);
148 
149  // Prepare the data collection and check for its existence:
150  LCCollectionVec *zsDataCollection;
151  bool zsDataCollectionExists = false;
152  try {
153  zsDataCollection =
154  static_cast<LCCollectionVec *>(result.getCollection(m_event_type));
155  zsDataCollectionExists = true;
156  } catch (lcio::DataNotAvailableException &e) {
157  zsDataCollection = new LCCollectionVec(lcio::LCIO::TRACKERDATA);
158  }
159 
160  // Set the proper cell encoder
161  CellIDEncoder<TrackerDataImpl> zsDataEncoder(
162  eutelescope::EUTELESCOPE::ZSDATADEFAULTENCODING, zsDataCollection);
163 
164  // Decode the raw data and retrieve the eudaq StandardEvent:
165  StandardEvent tmp_evt;
166  GetStandardSubEvent(tmp_evt, source);
167 
168  // Loop over all planes available in the data stream:
169  for (size_t iPlane = 0; iPlane < tmp_evt.NumPlanes(); ++iPlane) {
170  StandardPlane plane =
171  static_cast<StandardPlane>(tmp_evt.GetPlane(iPlane));
172 
173  zsDataEncoder["sensorID"] = plane.ID();
174  zsDataEncoder["sparsePixelType"] =
175  eutelescope::kEUTelGenericSparsePixel;
176 
177  // Get the total number of pixels
178  size_t nPixel = plane.HitPixels();
179 
180  // Prepare a new TrackerData for the ZS data
181  std::auto_ptr<lcio::TrackerDataImpl> zsFrame(new lcio::TrackerDataImpl);
182  zsDataEncoder.setCellID(zsFrame.get());
183 
184  // This is the structure that will host the sparse pixels
185  std::auto_ptr<eutelescope::EUTelTrackerDataInterfacerImpl<
186  eutelescope::EUTelGenericSparsePixel>>
187  sparseFrame(new eutelescope::EUTelTrackerDataInterfacerImpl<
188  eutelescope::EUTelGenericSparsePixel>(zsFrame.get()));
189 
190  // Prepare a sparse pixel to be added to the sparse data:
191  std::auto_ptr<eutelescope::EUTelGenericSparsePixel> sparsePixel(
192  new eutelescope::EUTelGenericSparsePixel);
193  for (size_t iPixel = 0; iPixel < nPixel; ++iPixel) {
194 
195  // Fill the sparse pixel coordinates with decoded data:
196  sparsePixel->setXCoord((size_t)plane.GetX(iPixel));
197  sparsePixel->setYCoord((size_t)plane.GetY(iPixel));
198  // Fill the pixel charge:
199  sparsePixel->setSignal((int32_t)plane.GetPixel(iPixel));
200 
201  // Add the pixel to the readout frame:
202  sparseFrame->addSparsePixel(sparsePixel.get());
203  }
204 
205  // Now add the TrackerData to the collection
206  zsDataCollection->push_back(zsFrame.release());
207 
208  } // loop over all planes
209 
210  // Add the collection to the event only if not empty and not yet there
211  if (!zsDataCollectionExists) {
212  if (zsDataCollection->size() != 0) {
213  result.addCollection(zsDataCollection, m_event_type);
214  } else {
215  delete zsDataCollection; // clean up if not storing the collection
216  // here
217  }
218  }
219 
220  return true;
221  }
222 #endif
223 
224  private:
225  uint8_t m_roctype, m_tbmtype;
226  size_t m_planeid;
227  size_t m_nplanes;
228  std::string m_detector;
229  bool m_rotated_pcb;
230  std::string m_event_type;
231  // The pipeworks:
232  mutable evtSource src;
233  mutable passthroughSplitter splitter;
234  mutable dtbEventDecoder decoder;
235  mutable dataSink<pxar::Event *> Eventpump;
236 
237  void GetMultiPlanes(StandardEvent &out, unsigned plane_id,
238  pxar::Event *evt) const {
239  // Iterate over all planes and check for pixel hits:
240  for (size_t roc = 0; roc < m_nplanes; roc++) {
241 
242  // Create a new StandardPlane object:
243  StandardPlane plane(plane_id + roc, m_event_type, m_detector);
244 
245  // Initialize the plane size (zero suppressed), set the number of pixels
246  // Check which carrier PCB has been used and book planes accordingly:
247  if (m_rotated_pcb) {
248  plane.SetSizeZS(ROC_NUMROWS, ROC_NUMCOLS, 0);
249  } else {
250  plane.SetSizeZS(ROC_NUMCOLS, ROC_NUMROWS, 0);
251  }
252  plane.SetTLUEvent(0);
253 
254  // Store all decoded pixels belonging to this plane:
255  for (std::vector<pxar::pixel>::iterator it = evt->pixels.begin();
256  it != evt->pixels.end(); ++it) {
257  // Check if current pixel belongs on this plane:
258  if (it->roc() == roc) {
259  if (m_rotated_pcb) {
260  plane.PushPixel(it->row(), it->column(), it->value());
261  } else {
262  plane.PushPixel(it->column(), it->row(), it->value());
263  }
264  }
265  }
266 
267  // Add plane to the output event:
268  out.AddPlane(plane);
269  }
270  };
271 
272  void GetSinglePlane(StandardEvent &out, unsigned plane_id,
273  pxar::Event *evt) const {
274 
275  // Create a new StandardPlane object:
276  StandardPlane plane(plane_id, m_event_type, m_detector);
277 
278  // More than 16 ROCs on one module?! Impossible!
279  if (m_nplanes > 16)
280  return;
281 
282  // Initialize the plane size (zero suppressed), set the number of pixels
283  // Check which carrier PCB has been used and book planes accordingly:
284  if (m_rotated_pcb) {
285  plane.SetSizeZS(2 * ROC_NUMROWS, 8 * ROC_NUMCOLS, 0);
286  } else {
287  plane.SetSizeZS(8 * ROC_NUMCOLS, 2 * ROC_NUMROWS, 0);
288  }
289  plane.SetTLUEvent(0);
290 
291  // Iterate over all pixels and place them in the module plane:
292  for (std::vector<pxar::pixel>::iterator it = evt->pixels.begin();
293  it != evt->pixels.end(); ++it) {
294 
295  if (m_rotated_pcb) {
296  plane.PushPixel(roc_to_mod_row(it->roc(), it->row()),
297  roc_to_mod_col(it->roc(), it->column()), it->value());
298  } else {
299  plane.PushPixel(roc_to_mod_col(it->roc(), it->column()),
300  roc_to_mod_row(it->roc(), it->row()), it->value());
301  }
302  }
303 
304  // Add plane to the output event:
305  out.AddPlane(plane);
306  };
307 
308  static inline uint16_t roc_to_mod_row(uint8_t roc, uint16_t row) {
309  if (roc < 8)
310  return row;
311  else
312  return (2 * ROC_NUMROWS - row - 1);
313  };
314 
315  static inline uint16_t roc_to_mod_col(uint8_t roc, uint16_t col) {
316  if (roc < 8)
317  return (col + roc * ROC_NUMCOLS);
318  else
319  return ((16 - roc) * ROC_NUMCOLS - col - 1);
320  };
321 
322  static std::vector<uint16_t>
323  TransformRawData(const std::vector<unsigned char> &block) {
324 
325  // Transform data of form char* to vector<int16_t>
326  std::vector<uint16_t> rawData;
327 
328  int size = block.size();
329  if (size < 2) {
330  return rawData;
331  }
332 
333  int i = 0;
334  while (i < size - 1) {
335  uint16_t temp = ((uint16_t)block.data()[i + 1] << 8) | block.data()[i];
336  rawData.push_back(temp);
337  i += 2;
338  }
339  return rawData;
340  }
341  };
342 }
size_t NumBlocks() const
Return the number of data blocks in the RawDataEvent.
Definition: RawDataEvent.hh:80
Definition: Configuration.hh:12
Definition: StandardEvent.hh:10
Definition: StandardEvent.hh:128
Definition: RawDataEvent.hh:14
Definition: Event.hh:38
const data_t & GetBlock(size_t i) const
Definition: RawDataEvent.cc:34
Definition: CMSPixelHelper.hh:30