Pottu
DetectorEventGenerator.hpp
Go to the documentation of this file.
1 
7 #ifndef H_POTTU_DETECTOREVENTGENERATOR
8 #define H_POTTU_DETECTOREVENTGENERATOR
9 
10 
12 
13 #include "dataitem.hpp"
14 #include "DetectorEvent.hpp"
16 
17 #include <fmt/base.h>
18 
19 #include <deque>
20 #include <vector>
21 #include <algorithm>
22 
23 
24 
25 namespace pottu {
26 
27 
32  public:
34  : _ctxh( ContextBase::getActive().createHandle("DetectorEventGenerator") )
35  {
36  auto branch = createSubTree( results, "detector_event_generator" );
37  _h_rectypes = createHistogram1DPow2( branch, "rectypes", 2, 2 );
38  _h_infocodes = createHistogram1DPow2( branch, "infocodes", 4, 4 );
39 
40  _h_ch_data = createHistogram1DPow2( branch, "ch_data", 12, 12 );
41  // Data which is ignored due to timeorder errors or data before fulltime
42  _h_ch_dataIgnored = createHistogram1DPow2( branch, "ch_dataIgnored", 12, 12 );
43  _h_ch_trace = createHistogram1DPow2( branch, "ch_trace", 12, 12 );
44 
45  _h_ch_pileup = createHistogram1DPow2( branch, "ch_pileup", 12, 12 );
46  _h_ch_overrange = createHistogram1DPow2( branch, "ch_overrange", 12, 12 );
47  _h_ch_underrange = createHistogram1DPow2( branch, "ch_underrange", 12, 12 );
48  _h_ch_overflow = createHistogram1DPow2( branch, "ch_overflow", 12, 12 );
49  _h_ch_underflow = createHistogram1DPow2( branch, "ch_underflow", 12, 12 );
50 
51  _h_ch_pileup_marked = createHistogram1DPow2( branch, "ch_pileup_marked", 12, 12 );
52  _h_ch_overrange_marked = createHistogram1DPow2( branch, "ch_overrange_marked", 12, 12 );
53  _h_ch_underrange_marked = createHistogram1DPow2( branch, "ch_underrange_marked", 12, 12 );
54  _h_ch_overflow_marked = createHistogram1DPow2( branch, "ch_overflow_marked", 12, 12 );
55  _h_ch_underflow_marked = createHistogram1DPow2( branch, "ch_underflow_marked", 12, 12 );
56 
57  _h_ch_fail = createHistogram1DPow2( branch, "ch_fail", 12, 12 );
58  _h_ch_veto = createHistogram1DPow2( branch, "ch_veto", 12, 12 );
59 
60  _h_ch_adcbit14 = createHistogram1DPow2( branch, "ch_adcbit14", 12, 12 );
61  _h_ch_adcbit15 = createHistogram1DPow2( branch, "ch_adcbit15", 12, 12 );
62  }
63 
64 
71  //TO BE REMOVED: template <class ContInput, class ContOutput>
72  void process( const std::vector<dataitem_ts_t> &input, std::vector<DetectorEvent> &output ) {
73  /* TO BE REMOVED:
74  static_assert( std::is_same<typename ContInput::value_type,dataitem_ts_t>::value,
75  "DetectorEventGenerator requires dataitem_ts_t as a input::value_type" );
76  static_assert( std::is_same<typename ContOutput::value_type,DetectorEvent>::value,
77  "DetectorEventGenerator requires DetectorEvent as a output::value_type" );
78  */
79  auto proci = _ctxh->processInstance();
80 
81  output.clear();
82  size_t counter{0};
83 
84 #if POTTU_ENABLE_TRACES==1
85  std::vector<uint16_t> traceData;
86  uint16_t traceCh{0};
87  int64_t traceTime{0};
88  std::size_t tracePos{0} ;
89 #endif
90 
91  for( const dataitem_ts_t &di : input ) {
92  //_h_rectypes->fillNoRangeTesting( di.item.type.itemtype );
93  fillInteger( _h_rectypes, di.item.type.itemtype );
94 
95  if( di.ts < _tsPrev ) {
96  _ctxh->logWarning( fmt::format( "TimeOrder error: {} -> {}, {} s.\n input.size()={}, output.size()={}, counter={}",
97  _tsPrev, di.ts, (di.ts-_tsPrev)*1e-8 ,
98  input.size(), output.size(), counter ) );
99 
100  ++_timeOrderErrorCounter;
101  // Moving all the events out (no any
102  // pileup... markings over the timestamp error
103  // boundary)
104  std::move( _itemqueue.begin(), _itemqueue.end(), std::back_inserter(output) );
105  _itemqueue.clear();
106  }
107 
108 
109  switch( di.item.getType() ) {
110  case itemtype_e::tracedata:
111  // Actual tracedata
112 #if POTTU_ENABLE_TRACES==1
113  if( tracePos + 4 <= traceData.size() ) {
114  traceData[ tracePos++ ] = di.item.tracedata.sample0;
115  traceData[ tracePos++ ] = di.item.tracedata.sample1;
116  traceData[ tracePos++ ] = di.item.tracedata.sample2;
117  traceData[ tracePos++ ] = di.item.tracedata.sample3;
118  }
119  if( tracePos>0 && tracePos == traceData.size() ) {
120  // Trace is now collected. Checking if it can be assigned to the previous detector event
121  if( _itemqueue.size() && _itemqueue.back().ch == traceCh && _itemqueue.back().time == traceTime ) {
122  _itemqueue.back().trace = std::move( traceData );
123  //fmt::print( "Trace found and assigned for {}\n", traceCh );
124  tracePos = 0;
125  } else {
126  fmt::print( "No dataitem found for trace {}\n", traceCh );
127  }
128  tracePos = 0;
129  traceCh = 0;
130  }
131 #endif
132  break;
133  case itemtype_e::tracehead:
134  {
135  // New trace is starting here
136 #if POTTU_ENABLE_TRACES==1
137  traceData.resize( di.item.tracehead.samplelength, 0 );
138  traceCh = di.item.tracehead.chi;
139  traceTime = di.ts;
140  tracePos = 0;
141 #endif
142 
143  fillInteger( _h_ch_trace, di.item.tracehead.chi );
144  break;
145  }
146  case itemtype_e::info:
147  {
148  //_h_infocodes->fillNoRangeTesting( di.item.info.code );
149  fillInteger( _h_infocodes, di.item.info.code );
150 
151  switch( di.item.info.getCode() ) {
152  case infocode_e::pileup: {
153  const auto ch = di.item.info.getChannelIdent();
154  //_h_ch_pileup->fill( ch );
155  fillInteger( _h_ch_pileup, ch );
156 
157  // Trying to find the actual data event
158  for( auto rit = _itemqueue.rbegin(); rit != _itemqueue.rend(); ++rit ) {
159  const auto tdiff = di.ts - rit->time;
160  if( tdiff > _pileupSearchtime )
161  break;
162  if( rit->ch == ch ) {
163  rit->markPileup();
164  fillInteger( _h_ch_pileup_marked, ch );
165  break;
166  }
167  }
168 
169  break;
170  }
171  case infocode_e::adc_overrange:
172  {
173  const auto ch = di.item.info.getChannelIdent();
174  fillInteger( _h_ch_overrange, ch );
175 
176  // Trying to find the actual data event
177  for( auto rit = _itemqueue.rbegin(); rit != _itemqueue.rend(); ++rit ) {
178  const auto tdiff = di.ts - rit->time;
179  if( tdiff > _overrangeSearchtime )
180  break;
181  if( rit->ch == ch ) {
182  rit->markOverrange();
183  fillInteger( _h_ch_overrange_marked, ch );
184  break;
185  }
186  }
187 
188  break;
189  }
190  case infocode_e::adc_underrange:
191  {
192  const auto ch = di.item.info.getChannelIdent();
193  fillInteger( _h_ch_underrange, ch );
194 
195  // Trying to find the actual data event
196  for( auto rit = _itemqueue.rbegin(); rit != _itemqueue.rend(); ++rit ) {
197  const auto tdiff = di.ts - rit->time;
198  if( tdiff > _underrangeSearchtime )
199  break;
200  if( rit->ch == ch ) {
201  rit->markUnderrange();
202  fillInteger( _h_ch_underrange_marked, ch );
203  break;
204  }
205  }
206 
207  break;
208  }
209  case infocode_e::adc_overflow:
210  {
211  const auto ch = di.item.info.getChannelIdent();
212  fillInteger( _h_ch_overflow, ch );
213 
214  // Trying to find the actual data event
215  for( auto rit = _itemqueue.rbegin(); rit != _itemqueue.rend(); ++rit ) {
216  const auto tdiff = di.ts - rit->time;
217  if( tdiff > _overflowSearchtime )
218  break;
219  if( rit->ch == ch ) {
220  rit->markOverflow();
221  fillInteger( _h_ch_overflow_marked, ch );
222  break;
223  }
224  }
225 
226  break;
227  }
228  case infocode_e::adc_underflow:
229  {
230  const auto ch = di.item.info.getChannelIdent();
231  fillInteger( _h_ch_underflow, ch );
232 
233  // Trying to find the actual data event
234  for( auto rit = _itemqueue.rbegin(); rit != _itemqueue.rend(); ++rit ) {
235  const auto tdiff = di.ts - rit->time;
236  if( tdiff > _underflowSearchtime )
237  break;
238  if( rit->ch == ch ) {
239  rit->markUnderflow();
240  fillInteger( _h_ch_underflow_marked, ch );
241  break;
242  }
243  }
244 
245  break;
246  }
247  default:
248  break;
249  }
250 
251  break;
252  }
253 
254  case itemtype_e::data:
255  {
256  fillInteger( _h_ch_data, di.item.data.chi );
257  if( di.item.data.veto )
258  fillInteger( _h_ch_veto, di.item.data.chi );
259  if( di.item.data.fail )
260  fillInteger( _h_ch_fail, di.item.data.chi );
261  if( di.item.data.adc >> 14 & 0x1 )
262  fillInteger( _h_ch_adcbit14, di.item.data.chi );
263  if( di.item.data.adc >> 15 & 0x1 )
264  fillInteger( _h_ch_adcbit15, di.item.data.chi );
265 
266  // Putting data always to the queue.
267  DetectorEvent det;
268  det.time = di.ts;
269  det.ch = di.item.data.chi;
270  det.adc = di.item.data.adc;
271  det.flags = 0;
272  det.group = 0;
273  det.e = 0;
274 
275 #if POTTU_ENABLE_TRACES
276  if( traceData.size() && traceCh==det.ch && traceTime==det.time ) {
277  // Trace assigned to a data event
278  det.trace = std::move( traceData );
279  fmt::print( "Trace found and assigned for {}\n", det.ch );
280  tracePos = 0;
281  }
282 #endif
283 
284  _itemqueue.push_back( std::move(det) );
285  break;
286  }
287  }
288 
289  _tsPrev = di.ts;
290  ++counter;
291  }
292 
294  if( _itemqueue.size() ) {
295  const int64_t lastTSForPop = _itemqueue.back().time - _queue_minlength;
296 
297  auto it_last = std::upper_bound( _itemqueue.begin(), _itemqueue.end(), lastTSForPop,
298  [](const int64_t &value, const DetectorEvent &e ){
299  return value < e.time; } );
300  std::move( _itemqueue.begin(), it_last, std::back_inserter(output) );
301  _itemqueue.erase( _itemqueue.begin(), it_last );
302  }
303 
304 
305  }
306 
307 
308 
309  ContextHandle *_ctxh;
310 
311 
312  int64_t _queue_minlength{10000};
313  int64_t _pileupSearchtime{1000};
314  int64_t _underrangeSearchtime{1000};
315  int64_t _overrangeSearchtime{1000};
316  int64_t _underflowSearchtime{1000};
317  int64_t _overflowSearchtime{1000};
318 
319  int64_t _tsPrev{0};
320  std::deque<DetectorEvent> _itemqueue;
321 
322  // Number of timeorder errors in full time stamps.
323  uint64_t _timeOrderErrorCounter{0};
324 
325  // Histograms
326  _histogram_1d_pow2_type *_h_rectypes;
327  _histogram_1d_pow2_type *_h_infocodes;
328 
329  _histogram_1d_pow2_type *_h_ch_data;
330  _histogram_1d_pow2_type *_h_ch_dataIgnored;
331  _histogram_1d_pow2_type *_h_ch_trace;
332 
333  _histogram_1d_pow2_type *_h_ch_pileup;
334  _histogram_1d_pow2_type *_h_ch_overrange;
335  _histogram_1d_pow2_type *_h_ch_underrange;
336  _histogram_1d_pow2_type *_h_ch_overflow;
337  _histogram_1d_pow2_type *_h_ch_underflow;
338 
339  _histogram_1d_pow2_type *_h_ch_pileup_marked;
340  _histogram_1d_pow2_type *_h_ch_overrange_marked;
341  _histogram_1d_pow2_type *_h_ch_underrange_marked;
342  _histogram_1d_pow2_type *_h_ch_overflow_marked;
343  _histogram_1d_pow2_type *_h_ch_underflow_marked;
344 
345  _histogram_1d_pow2_type *_h_ch_fail;
346  _histogram_1d_pow2_type *_h_ch_veto;
347 
348  _histogram_1d_pow2_type *_h_ch_adcbit14;
349  _histogram_1d_pow2_type *_h_ch_adcbit15;
350  };
351 
352 
353 };
354 
355 
356 
357 #endif
Handle to context used by specific class.
Definition: ContextBase.hpp:188
Class to process raw timestamped dataitems to DetectorEvents.
Definition: DetectorEventGenerator.hpp:31
void process(const std::vector< dataitem_ts_t > &input, std::vector< DetectorEvent > &output)
Feeds raw data in and gets processed detector events out.
Definition: DetectorEventGenerator.hpp:72
Event containing event information of one daq channel.
Definition: DetectorEvent.hpp:47
flags
Flag values used in the bitmask field flags.
Definition: DetectorEvent.hpp:94
Class holding tree of histograms and subtrees.
Definition: ObjectTree.hpp:44
Abstract baseclass for all stages which creates detector events.
Definition: StageStampedRawToDetectorEvent.hpp:19
Defines the raw low level dataitems used in tdr datastreams and files.
Definition: mainpage.dox:6
static ContextBase & getActive() noexcept
Returns active Context.
Definition: ContextBase.hpp:80
Raw dataitem with full timestamp.
Definition: dataitem.hpp:419