PDSPTPCDataInterface_tool.cc
Go to the documentation of this file.
1 // PDSPTPCDataInterface_tool.cc
2 
3 #include "PDSPTPCDataInterface.h"
4 #include "TMath.h"
5 #include "TString.h"
6 #include <iostream>
7 #include <set>
8 
10 
11 // artdaq and dune-raw-data includes
16 #include "dam/HeaderFragmentUnpack.hh"
17 #include "dam/DataFragmentUnpack.hh"
18 #include "dam/TpcFragmentUnpack.hh"
19 #include "dam/TpcStreamUnpack.hh"
20 #include "dam/access/WibFrame.hh"
21 #include "dam/access/Headers.hh"
22 #include "dam/access/TpcStream.hh"
23 #include "dam/access/TpcRanges.hh"
24 #include "dam/access/TpcToc.hh"
25 #include "dam/access/TpcPacket.hh"
26 #include "dam/RceFragmentUnpack.hh"
27 
29 {
30  _input_labels_by_apa[1] = p.get< std::vector<std::string> >("APA1InputLabels");
31  _input_labels_by_apa[2] = p.get< std::vector<std::string> >("APA2InputLabels");
32  _input_labels_by_apa[3] = p.get< std::vector<std::string> >("APA3InputLabels");
33  _input_labels_by_apa[4] = p.get< std::vector<std::string> >("APA4InputLabels");
34  _input_labels_by_apa[5] = p.get< std::vector<std::string> >("APA5InputLabels");
35  _input_labels_by_apa[6] = p.get< std::vector<std::string> >("APA6InputLabels");
36  _input_labels_by_apa[7] = p.get< std::vector<std::string> >("APA7InputLabels");
37  _input_labels_by_apa[8] = p.get< std::vector<std::string> >("APA8InputLabels");
38  _input_labels_by_apa[-1] = p.get< std::vector<std::string> >("MISCAPAInputLabels");
39 
40  _default_crate_if_unexpected = p.get<unsigned int>("DefaultCrateIfUnexpected",3);
41 
42  _min_offline_channel = p.get<long int>("MinOfflineChannel",-1);
43  _max_offline_channel = p.get<long int>("MaxOfflineChannel",-1);
44 
45  _drop_small_rce_frags = p.get<bool>("RCEDropSmallFrags",true);
46  _rce_frag_small_size = p.get<unsigned int>("RCESmallFragSize",10000);
47  _rce_drop_frags_with_badsf = p.get<bool>("RCEDropFragsWithBadSF",true);
48  _rce_drop_frags_with_badc = p.get<bool>("RCEDropFragsWithBadC",true);
49  _rce_hex_dump = p.get<bool>("RCEHexDump",false);
50  _rce_save_frags_to_files = p.get<bool>("RCESaveFragsToFiles",false);
51  _rce_check_buffer_size = p.get<bool>("RCECheckBufferSize",true);
52  _rce_buffer_size_checklimit = p.get<unsigned int>("RCEBufferSizeCheckLimit",10000000);
53 
54  // parameters to steer the FEMB 110 band-aid
55 
56  _rce_fix110 = p.get<bool>("RCEFIX110",true);
57  _rce_fix110_nticks = p.get<unsigned int>("RCEFIX110NTICKS",18);
58 
59  _felix_drop_frags_with_badsf = p.get<bool>("FELIXDropFragsWithBadSF",true);
60  _felix_drop_frags_with_badc = p.get<bool>("FELIXDropFragsWithBadC",true);
61  _felix_hex_dump = p.get<bool>("FELIXHexDump",false);
62  _drop_small_felix_frags = p.get<bool>("FELIXDropSmallFrags",true);
63  _felix_frag_small_size = p.get<unsigned int>("FELIXSmallFragSize",10000);
64  _felix_check_buffer_size = p.get<bool>("FELIXCheckBufferSize",true);
65  _felix_buffer_size_checklimit = p.get<unsigned int>("FELIXBufferSizeCheckLimit",10000000);
66 
67  _enforce_same_tick_count = p.get<bool>("EnforceSameTickCount",false);
68  _enforce_median_tick_count = p.get<bool>("EnforceMedianTickCount",false);
69  _enforce_full_tick_count = p.get<bool>("EnforceFullTickCount",false);
70  _full_tick_count = p.get<unsigned int>("FullTickCount",6000);
71  _enforce_error_free = p.get<bool>("EnforceErrorFree",false);
72  _enforce_no_duplicate_channels = p.get<bool>("EnforceNoDuplicateChannels", true);
73 }
74 
75 // wrapper for backward compatibility. Return data for all APA's represented in the fragments on these labels
76 
78  std::string inputLabel,
79  std::vector<raw::RawDigit> &raw_digits,
80  std::vector<raw::RDTimeStamp> &rd_timestamps,
81  std::vector<raw::RDStatus> &rdstatuses)
82 {
83  std::vector<int> apalist;
84  apalist.push_back(-1);
85  int retcode = retrieveDataAPAListWithLabels(evt, inputLabel, raw_digits, rd_timestamps, rdstatuses, apalist );
86  _collectRDStatus(rdstatuses);
87  return retcode;
88 }
89 
90 // get data for specified APAs. Loop over labels specified in the fcl configuration looking for the data so the caller doesn't have to
91 // keep track of all the branch labels an APA's data might be on.
92 
94  std::vector<raw::RawDigit> &raw_digits,
95  std::vector<raw::RDTimeStamp> &rd_timestamps,
96  std::vector<raw::RDStatus> &rdstatuses,
97  std::vector<int> &apalist)
98 {
99  int totretcode = 0;
100 
101  for (size_t i=0; i<apalist.size(); ++i)
102  {
103  auto lli = _input_labels_by_apa.find(apalist.at(i));
104  if (lli == _input_labels_by_apa.end())
105  {
106  MF_LOG_WARNING("PDSPTPCDataInterface:") << " No list of input labels known for APA " << apalist.at(i) << " Returning no data.";
107  }
108  for (size_t j=0; j<lli->second.size(); ++j)
109  {
110  int retcode = retrieveDataAPAListWithLabels(evt, lli->second.at(j), raw_digits, rd_timestamps, rdstatuses, apalist );
111  if (retcode > totretcode) totretcode = retcode; // take most severe retcode of everything
112  }
113  }
114  _collectRDStatus(rdstatuses);
115  return totretcode;
116 }
117 
118 // get data for a specific label, but only return those raw digits that correspond to APA's on the list
119 
121  std::string inputLabel,
122  std::vector<raw::RawDigit> &raw_digits,
123  std::vector<raw::RDTimeStamp> &rd_timestamps,
124  std::vector<raw::RDStatus> &rdstatuses,
125  std::vector<int> &apalist)
126 {
127 
129 
131  _DiscardedCorruptData = false; // can be set to true if we drop some of the event's data
132  _KeptCorruptData = false; // true if we identify a corruption candidate but are skipping the test to drop it
133 
134  if (inputLabel.find("TPC") != std::string::npos)
135  {
136  _processRCE(evt, inputLabel, raw_digits, rd_timestamps, apalist);
137  }
138  else if (inputLabel.find("FELIX") != std::string::npos)
139  {
140  _processFELIX(evt, inputLabel, raw_digits, rd_timestamps, apalist);
141  }
142  else
143  {
144  throw cet::exception("PDSPTPCInterface_tool") << "ununderstood fragment branch label: \"" << inputLabel << "\"";
145  }
146 
147  bool flagged_duplicate = false;
148 
150  {
151  std::set<unsigned int> channels_seen;
152 
153  for (const auto& rd : raw_digits)
154  {
155  unsigned int ichan = rd.Channel();
156  if (channels_seen.find(ichan) == channels_seen.end())
157  {
158  channels_seen.insert(ichan);
159  }
160  else
161  {
162  MF_LOG_WARNING("PDSPTPCDataInterface:") << " Duplicate channel detected: " << ichan << " Discarding TPC data for this chunk: " << inputLabel;
163  raw_digits.clear();
164  rd_timestamps.clear();
165  flagged_duplicate = true;
166  break;
167  }
168  }
169  }
170 
172  {
173 
174  // find the median tick count and if a channel has a different tick count from median, remove it from the list. Special dispensation for FEMB302,
175  // allowing it to have up to 10% missing ticks.
176 
177  std::vector<size_t> ticklist;
178  for (size_t i=0; i<raw_digits.size(); ++i)
179  {
180  ticklist.push_back(raw_digits.at(i).Samples());
181  }
182  size_t tls = ticklist.size();
183  size_t tickmed = 0;
184  if (tls != 0)
185  {
186  tickmed = TMath::Median(tls,ticklist.data());
187  }
188  size_t tickexample=0;
189  std::vector<size_t> dlist;
190  for (size_t i=0; i<raw_digits.size(); ++i)
191  {
192  if (ticklist.at(i) != tickmed)
193  {
194  unsigned int channel = raw_digits.at(i).Channel();
195  unsigned int crate = cmap->InstalledAPAFromOfflineChannel(channel);
196  unsigned int slot = cmap->WIBFromOfflineChannel(channel);
197  unsigned int fiber = cmap->FEMBFromOfflineChannel(channel);
198  //std::cout << "tick not at median: " << channel << " " << crate << " " << slot << " " << fiber << " " << ticklist.at(i) << " " << tickmed << std::endl;
199  if ( (crate == 3) && (slot == 3) && (fiber == 2) && ( ticklist.at(i) > 0.9*tickmed && ticklist.at(i) < tickmed ) ) continue; // FEMB 302
200  dlist.push_back(i);
201  tickexample = ticklist.at(i);
202  }
203  }
204 
205  if (dlist.size() != 0)
206  {
207  //std::cout << "PDSPTPCDataInterface_tool: Discarding data with n_ticks not at the median. Example invalid ticks: " << tickexample << std::endl;
208  MF_LOG_WARNING("PDSPTPCDataInterface_tool:") << " Discarding data with n_ticks not at the median. Example invalid ticks: " << tickexample;
209  for (size_t i=dlist.size(); i>0; --i)
210  {
211  raw_digits.erase(raw_digits.begin() + dlist.at(i-1));
212  rd_timestamps.erase(rd_timestamps.begin() + dlist.at(i-1));
213  }
214  }
215  }
216 
217  unsigned int statword=0;
218  if (_DiscardedCorruptData) statword |= 1;
219  if (_KeptCorruptData) statword |= 2;
220  rdstatuses.emplace_back(_DiscardedCorruptData,_KeptCorruptData,statword);
221  if (flagged_duplicate) statword = 4; // a flag to the caller indicating that the entire event's worth of raw digits is to be dropped
222  _collectRDStatus(rdstatuses);
223  return statword;
224 }
225 
226 
227 void PDSPTPCDataInterface::_collectRDStatus(std::vector<raw::RDStatus> &rdstatuses)
228 {
229  if (rdstatuses.size() < 2) return;
230  unsigned int statword=0;
231  bool dcflag = false;
232  bool kcflag = false;
233  for (size_t i=0; i<rdstatuses.size(); ++i)
234  {
235  statword |= rdstatuses.at(i).GetStatWord();
236  dcflag |= rdstatuses.at(i).GetCorruptDataDroppedFlag();
237  kcflag |= rdstatuses.at(i).GetCorruptDataKeptFlag();
238  }
239  rdstatuses.clear();
240  rdstatuses.emplace_back(dcflag,kcflag,statword);
241 }
242 
243 
245  std::string inputLabel,
246  RawDigits& raw_digits,
247  RDTimeStamps &timestamps,
248  std::vector<int> &apalist)
249 {
250  size_t n_rce_frags = 0;
251  bool have_data=false;
252  bool have_data_nc=false;
253 
254  if (inputLabel.find("Container") != std::string::npos)
255  {
256  auto cont_frags= evt.getHandle<artdaq::Fragments>(inputLabel);
257  if (cont_frags)
258  {
259  have_data = true;
260  if (! _rceProcContNCFrags(cont_frags, n_rce_frags, true, evt, raw_digits, timestamps, apalist))
261  {
262  return false;
263  }
264  }
265  }
266  else
267  {
268  auto frags = evt.getHandle<artdaq::Fragments>(inputLabel);
269  if (frags)
270  {
271  have_data_nc = true;
272  if (! _rceProcContNCFrags(frags, n_rce_frags, false, evt, raw_digits, timestamps, apalist))
273  {
274  return false;
275  }
276  }
277  }
278 
279  // returns true if we want to add to the number of fragments processed.
280 
281  return have_data || have_data_nc;
282 }
283 
285  size_t &n_rce_frags,
286  bool is_container,
287  art::Event &evt,
288  RawDigits& raw_digits,
289  RDTimeStamps &timestamps,
290  std::vector<int> &apalist)
291 {
292 
293  for (auto const& frag : *frags)
294  {
295  //std::cout << "RCE fragment size bytes: " << frag.sizeBytes() << std::endl;
296 
297  bool process_flag = true;
298  if (frag.sizeBytes() < _rce_frag_small_size)
299  {
300  if ( _drop_small_rce_frags )
301  {
302  MF_LOG_WARNING("_process_RCE:") << " Small RCE fragment size: " << frag.sizeBytes() << " Discarding just this fragment on request.";
303  _DiscardedCorruptData = true;
304  process_flag = false;
305  }
306  else
307  {
308  _KeptCorruptData = true;
309  }
310  }
311  if (process_flag)
312  {
313  if (is_container)
314  {
315  artdaq::ContainerFragment cont_frag(frag);
316  for (size_t ii = 0; ii < cont_frag.block_count(); ++ii)
317  {
318  if (_process_RCE_AUX(evt,*cont_frag[ii], raw_digits, timestamps, apalist)) ++n_rce_frags;
319  }
320  }
321  else
322  {
323  if (_process_RCE_AUX(evt,frag, raw_digits, timestamps, apalist)) ++n_rce_frags;
324  }
325  }
326  }
327  evt.removeCachedProduct(frags); // do this always, even if we need to re-read a TBranch
328  return true;
329 }
330 
331 
333  art::Event &evt,
334  const artdaq::Fragment& frag,
335  RawDigits& raw_digits,
336  RDTimeStamps &timestamps,
337  std::vector<int> &apalist
338  )
339 {
340 
341  if (_rce_hex_dump)
342  {
343  std::ios oldState(nullptr);
344  oldState.copyfmt(std::cout);
345 
346  std::cout << "RCE Fragment: all numbers in hex " << std::hex
347  << " SequenceID = " << frag.sequenceID()
348  << " fragmentID = " << frag.fragmentID()
349  << " fragmentType = " << (unsigned)frag.type()
350  << " Timestamp = " << frag.timestamp() << std::endl;
351  std::cout << "Offset Data";
352  artdaq::Fragment fragloc(frag);
353  unsigned char *dbegin = reinterpret_cast<unsigned char *>(fragloc.dataAddress());
354  size_t dsize = fragloc.dataSizeBytes();
355  size_t offcounter=0;
356  for (size_t bcounter=0; bcounter<dsize;++bcounter)
357  {
358  if ( (offcounter % 8) == 0 )
359  {
360  std::cout << std::endl << std::hex << std::setfill('0') << std::setw(8) << offcounter << " ";
361  }
362  std::cout << std::hex << std::setfill('0') << std::setw(2) << (int) *dbegin << " ";
363  dbegin++;
364  offcounter++;
365  }
366  std::cout << std::endl;
367  std::cout.copyfmt(oldState);
368  }
369 
370  //MF_LOG_INFO("_Process_RCE_AUX")
371  //<< " SequenceID = " << frag.sequenceID()
372  //<< " fragmentID = " << frag.fragmentID()
373  //<< " fragmentType = " << (unsigned)frag.type()
374  //<< " Timestamp = " << frag.timestamp();
376  dune::RceFragment rce(frag);
377 
379  {
380  TString outfilename="rce_";
381  outfilename += evt.run();
382  outfilename += "_";
383  outfilename += frag.sequenceID();
384  outfilename += "_";
385  outfilename += frag.fragmentID();
386  outfilename+=".fragment";
387  rce.save(outfilename.Data());
388  std::cout << "Saved an RCE fragment with " << rce.size() << " streams: " << outfilename << std::endl;
389  }
390 
391 
392  artdaq::Fragment cfragloc(frag);
393  size_t cdsize = cfragloc.dataSizeBytes();
394  const uint64_t* cdptr = (uint64_t const*) (cfragloc.dataBeginBytes() + 12); // see dune-raw-data/Overlays/RceFragment.cc
395  HeaderFragmentUnpack const cdheader(cdptr);
396  //bool isOkay = RceFragmentUnpack::isOkay(cdptr,cdsize+sizeof(cdheader));
397  if (cdsize>16) cdsize -= 16;
398  bool isOkay = RceFragmentUnpack::isOkay(cdptr,cdsize);
399  if (!isOkay)
400  {
401  MF_LOG_WARNING("_process_RCE_AUX:") << "RCE Fragment isOkay failed: " << cdsize << " Discarding this fragment";
402  _DiscardedCorruptData = true;
403  return false;
404  }
405 
406  //DataFragmentUnpack df(cdptr);
407  //std::cout << "isTPpcNormal: " << df.isTpcNormal() << " isTpcDamaged: " << df.isTpcDamaged() << " isTpcEmpty: " << df.isTpcEmpty() << std::endl;
408 
409 
410  uint32_t ch_counter = 0;
411  for (int i = 0; i < rce.size(); ++i)
412  {
413  auto const * rce_stream = rce.get_stream(i);
414  size_t n_ch = rce_stream->getNChannels();
415  size_t n_ticks = rce_stream->getNTicks();
416  if (n_ticks == 0) continue; // on David Adams's request.
417  auto const identifier = rce_stream->getIdentifier();
418  uint32_t crateNumber = identifier.getCrate();
419  uint32_t slotNumber = identifier.getSlot();
420  uint32_t fiberNumber = identifier.getFiber();
421 
422  // only take this rce stream if it has data from an APA we are interested in
423  bool foundapainlist = false;
424  for (size_t ialist=0; ialist < apalist.size(); ++ ialist)
425  {
426  if ( ( (apalist[ialist] == -1) && (!_rce_drop_frags_with_badc || (crateNumber >0 && crateNumber < 7)) ) ||
427  (apalist[ialist] == (int) crateNumber) ||
428  (apalist[ialist] == 7 && (crateNumber == 0 || crateNumber > 6)) )
429  {
430  foundapainlist = true;
431  break;
432  }
433  }
434  if (!foundapainlist) continue;
435 
436  //std::cout << "Processing an RCE Stream: " << crateNumber << " " << slotNumber << " " << fiberNumber << " " << n_ticks << " " << n_ch << std::endl;
437 
438  if (slotNumber > 4 || fiberNumber == 0 || fiberNumber > 4)
439  {
441  {
442  MF_LOG_WARNING("_process_RCE:") << "Bad crate, slot, fiber number, discarding fragment on request: "
443  << crateNumber << " " << slotNumber << " " << fiberNumber;
444  _DiscardedCorruptData = true;
445  return false;
446  }
447  _KeptCorruptData = true;
448  }
449 
450  if (n_ticks != _full_tick_count)
451  {
453  {
454  MF_LOG_WARNING("_process_RCE_AUX:") << "Nticks not the required value: " << n_ticks << " "
455  << _full_tick_count << " Discarding Data";
456  _DiscardedCorruptData = true;
457  return false;
458  }
459  _KeptCorruptData = true;
460  }
461 
463  {
465  _tick_count_this_event = n_ticks;
466  }
467  else
468  {
469  if (n_ticks != _tick_count_this_event)
470  {
472  {
473  MF_LOG_WARNING("_process_RCE_AUX:") << "Nticks different for two channel streams: " << n_ticks
474  << " vs " << _tick_count_this_event << " Discarding Data";
475  _DiscardedCorruptData = true;
476  return false;
477  }
478  }
479  _KeptCorruptData = true;
480  }
481 
482 
483  //MF_LOG_INFO("_Process_RCE_AUX")
484  //<< "RceFragment timestamp: " << rce_stream->getTimeStamp()
485  //<< ", NChannels: " << n_ch
486  //<< ", NTicks: " << n_ticks;
487 
488  // TODO -- speed this up!! Remove one buffer copy
489 
490  size_t buffer_size = n_ch * n_ticks;
491 
492  if (buffer_size > _rce_buffer_size_checklimit)
493  {
495  {
496  MF_LOG_WARNING("_process_RCE_AUX:") << "n_ch*nticks too large: " << n_ch << " * " << n_ticks << " = " <<
497  buffer_size << " larger than: " << _rce_buffer_size_checklimit << ". Discarding this fragment";
498  _DiscardedCorruptData = true;
499  return false;
500  }
501  else
502  {
503  _KeptCorruptData = true;
504  }
505  }
506 
507  std::vector<int16_t> _buffer(buffer_size);
508 
509  int16_t* adcs = _buffer.data();
510  bool sgmcdretcode = rce_stream->getMultiChannelData(adcs);
511  if (!sgmcdretcode)
512  {
514  {
515  MF_LOG_WARNING("_process_RCE_AUX:") << "getMutliChannelData returns error flag: "
516  << " c:s:f:ich: " << crateNumber << " " << slotNumber << " " << fiberNumber << " Discarding Data";
517  _DiscardedCorruptData = true;
518  return false;
519  }
520  _KeptCorruptData = true;
521  }
522 
523  //std::cout << "RCE raw decoder trj: " << crateNumber << " " << slotNumber << " " << fiberNumber << std::endl;
524 
525  // David Adams's request for channels to start at zero for coldbox test data
526  unsigned int crateloc = crateNumber;
527  if (crateNumber == 0 || crateNumber > 6) crateloc = _default_crate_if_unexpected;
528 
530  for (size_t i_ch = 0; i_ch < n_ch; i_ch++)
531  {
532  unsigned int offlineChannel = channelMap->GetOfflineNumberFromDetectorElements(crateloc, slotNumber, fiberNumber, i_ch, dune::PdspChannelMapService::kRCE);
533 
535  (offlineChannel < (size_t) _min_offline_channel || offlineChannel > (size_t) _max_offline_channel) ) continue;
536 
537  v_adc.clear();
538 
539  if (_rce_fix110 && crateNumber == 1 && slotNumber == 0 && fiberNumber == 1 && channelMap->ChipFromOfflineChannel(offlineChannel) == 4 && n_ticks > _rce_fix110_nticks)
540  {
541  for (size_t i_tick = 0; i_tick < n_ticks-_rce_fix110_nticks; i_tick++)
542  {
543  v_adc.push_back(adcs[i_tick+_rce_fix110_nticks]);
544  }
545  for (size_t i_tick=0; i_tick<_rce_fix110_nticks; ++i_tick)
546  {
547  v_adc.push_back(v_adc.back());
548  }
549 
550  }
551  else
552  {
553  for (size_t i_tick = 0; i_tick < n_ticks; i_tick++)
554  {
555  v_adc.push_back(adcs[i_tick]);
556  }
557  }
558  adcs += n_ticks;
559 
560  ch_counter++;
561 
562  float median=0;
563  float sigma=0;
564  computeMedianSigma(v_adc,median,sigma);
565 
566  /// FEMB 302 IS crate 3, slot 3, fiber 2
567 
568  auto uncompressed_nticks = v_adc.size(); // can be different from n_ticks due to padding of FEMB 302
569 
571  // here n_ticks is the uncompressed size as required by the constructor
572  raw::RawDigit raw_digit(offlineChannel, uncompressed_nticks, v_adc, cflag);
573  raw_digit.SetPedestal(median,sigma);
574  raw_digits.push_back(raw_digit);
575 
576  raw::RDTimeStamp rdtimestamp(rce_stream->getTimeStamp(),offlineChannel);
577  timestamps.push_back(rdtimestamp);
578 
579  } // end loop over channels
580  } // end loop over RCE streams (1 per FEMB)
581  // end processing one RCE fragment
582  return true;
583 }
584 
585 
586 
588  std::string inputLabel,
589  RawDigits& raw_digits,
590  RDTimeStamps &timestamps,
591  std::vector<int> &apalist)
592 {
593  size_t n_felix_frags = 0;
594  bool have_data=false;
595  bool have_data_nc=false;
596 
597  if (inputLabel.find("Container") != std::string::npos)
598  {
599  auto cont_frags = evt.getHandle<artdaq::Fragments>(inputLabel);
600  if (cont_frags)
601  {
602  have_data = true;
603  if (! _felixProcContNCFrags(cont_frags, n_felix_frags, true, evt, raw_digits, timestamps, apalist))
604  {
605  return false;
606  }
607  }
608  }
609  else
610  {
611  auto frags = evt.getHandle<artdaq::Fragments>(inputLabel);
612  if (frags)
613  {
614  have_data_nc = true;
615  if (! _felixProcContNCFrags(frags, n_felix_frags, false, evt, raw_digits, timestamps, apalist))
616  {
617  return false;
618  }
619  }
620  }
621 
622  // returns true if we want to add to the number of fragments processed.
623 
624  return have_data || have_data_nc;
625 }
626 
628  size_t &n_felix_frags,
629  bool is_container,
630  art::Event &evt,
631  RawDigits& raw_digits,
632  RDTimeStamps &timestamps,
633  std::vector<int> &apalist)
634 {
635  for (auto const& frag : *frags)
636  {
637  //std::cout << "FELIX fragment size bytes: " << frag.sizeBytes() << std::endl;
638 
639  bool process_flag = true;
640  if (frag.sizeBytes() < _felix_frag_small_size)
641  {
643  {
644  MF_LOG_WARNING("_process_FELIX:") << " Small FELIX fragment size: " << frag.sizeBytes() << " Discarding just this fragment on request.";
645  _DiscardedCorruptData = true;
646  process_flag = false;
647  }
648  else
649  {
650  _KeptCorruptData = true;
651  }
652  }
653  if (process_flag)
654  {
655  if (is_container)
656  {
657  artdaq::ContainerFragment cont_frag(frag);
658  for (size_t ii = 0; ii < cont_frag.block_count(); ++ii)
659  {
660  if (_process_FELIX_AUX(evt,*cont_frag[ii], raw_digits, timestamps, apalist)) ++n_felix_frags;
661  }
662  }
663  else
664  {
665  if (_process_FELIX_AUX(evt,frag, raw_digits, timestamps, apalist)) ++n_felix_frags;
666  }
667  }
668  }
669  evt.removeCachedProduct(frags);
670  return true;
671 }
672 
673 
675  const artdaq::Fragment& frag, RawDigits& raw_digits,
676  RDTimeStamps &timestamps,
677  std::vector<int> &apalist)
678 {
679 
680  //std::cout
681  //<< " SequenceID = " << frag.sequenceID()
682  //<< " fragmentID = " << frag.fragmentID()
683  //<< " fragmentType = " << (unsigned)frag.type()
684  //<< " Timestamp = " << frag.timestamp() << std::endl;
685 
686  if (_felix_hex_dump)
687  {
688  std::ios oldState(nullptr);
689  oldState.copyfmt(std::cout);
690 
691  std::cout << "FELIX Fragment: all numbers in hex " << std::hex
692  << " SequenceID = " << frag.sequenceID()
693  << " fragmentID = " << frag.fragmentID()
694  << " fragmentType = " << (unsigned)frag.type()
695  << " Timestamp = " << frag.timestamp() << std::endl;
696  std::cout << "Offset Data";
697  artdaq::Fragment fragloc(frag);
698  unsigned char *dbegin = reinterpret_cast<unsigned char *>(fragloc.dataAddress());
699  size_t dsize = fragloc.dataSizeBytes();
700  size_t offcounter=0;
701  for (size_t bcounter=0; bcounter<dsize;++bcounter)
702  {
703  if ( (offcounter % 8) == 0 )
704  {
705  std::cout << std::endl << std::hex << std::setfill('0') << std::setw(8) << offcounter << " ";
706  }
707  std::cout << std::hex << std::setfill('0') << std::setw(2) << (int) *dbegin << " ";
708  dbegin++;
709  offcounter++;
710  }
711  std::cout << std::endl;
712  std::cout.copyfmt(oldState);
713  }
714 
716 
717  //Load overlay class.
718  dune::FelixFragment felix(frag);
719 
720  //Get detector element numbers from the fragment
721 
722  uint8_t crate = felix.crate_no(0);
723  uint8_t slot = felix.slot_no(0);
724  uint8_t fiber = felix.fiber_no(0); // decode this one later
725 
726  if (slot > 4)
727  {
729  {
730  _DiscardedCorruptData = true;
731  MF_LOG_WARNING("_process_FELIX_AUX:") << "Invalid crate or slot: c=" << (int) crate << " s=" << (int) slot << " discarding FELIX data.";
732  return false;
733  }
734  _KeptCorruptData = true;
735  }
736 
737  // only take this felix fragment if it has data from an APA we are interested in
738  bool foundapainlist = false;
739  for (size_t ialist=0; ialist < apalist.size(); ++ ialist)
740  {
741  if ( ( (apalist[ialist] == -1) && (!_rce_drop_frags_with_badc || (crate >0 && crate < 7)) ) ||
742  (apalist[ialist] == (int) crate) ||
743  (apalist[ialist] == 7 && (crate == 0 || crate > 6)) )
744  {
745  foundapainlist = true;
746  break;
747  }
748  }
749  if (!foundapainlist) return true;
750 
751  //std::cout << "FELIX raw decoder trj: " << (int) crate << " " << (int) slot << " " << (int) fiber << std::endl;
752 
753  const unsigned n_frames = felix.total_frames(); // One frame contains 25 felix (20 ns-long) ticks. A "frame" is an offline tick
754  //std::cout<<" Nframes = "<<n_frames<<std::endl;
755  //_h_nframes->Fill(n_frames);
756  if (n_frames ==0) return true;
757 
758  const unsigned n_channels = dune::FelixFrame::num_ch_per_frame;// should be 256
759 
760 
761  if (n_frames*n_channels > _felix_buffer_size_checklimit)
762  {
764  {
765  MF_LOG_WARNING("_process_FELIX_AUX:") << "n_channels*n_frames too large: " << n_channels << " * " << n_frames << " = " <<
766  n_frames*n_channels << " larger than: " << _felix_buffer_size_checklimit << ". Discarding this fragment";
767  _DiscardedCorruptData = true;
768  return false;
769  }
770  else
771  {
772  _KeptCorruptData = true;
773  }
774  }
775 
776  for (unsigned int iframe=0; iframe<n_frames; ++iframe)
777  {
778  if ( felix.wib_errors(iframe) != 0)
779  {
780  if (_enforce_error_free )
781  {
782  _DiscardedCorruptData = true;
783  MF_LOG_WARNING("_process_FELIX_AUX:") << "WIB Errors on frame: " << iframe << " : " << felix.wib_errors(iframe)
784  << " Discarding Data";
785  // drop just this fragment
786  return true;
787  }
788  _KeptCorruptData = true;
789  }
790  }
791 
792  // check optimization of this -- size not reserved
793 
795  //v_adc.reserve(n_frames*n_channels);
796  // Fill the adc vector.
797 
798  for(unsigned ch = 0; ch < n_channels; ++ch) {
799 
800  // handle 256 channels on two fibers -- use the channel map that assumes 128 chans per fiber (=FEMB)
801 
802  unsigned int fiberloc = 0;
803  if (fiber == 1)
804  {
805  fiberloc = 1;
806  }
807  else if (fiber == 2)
808  {
809  fiberloc = 3;
810  }
811  else
812  {
813  MF_LOG_WARNING("_process_FELIX_AUX:") << " Fiber number " << (int) fiber << " is expected to be 1 or 2 -- revisit logic";
814  fiberloc = 1;
816  {
817  MF_LOG_WARNING("_process_FELIX_AUX:") << " Dropping FELIX Data";
818  return false;
819  }
820  }
821 
822  unsigned int chloc = ch;
823  if (chloc > 127)
824  {
825  chloc -= 128;
826  fiberloc++;
827  }
828  unsigned int crateloc = crate;
829  // David Adams's request for channels to start at zero for coldbox test data
830  if (crateloc == 0 || crateloc > 6) crateloc = _default_crate_if_unexpected;
831 
832  unsigned int offlineChannel = channelMap->GetOfflineNumberFromDetectorElements(crateloc, slot, fiberloc, chloc, dune::PdspChannelMapService::kFELIX);
833 
834  // skip this channel if we are asked to.
835 
837  (offlineChannel < (size_t) _min_offline_channel || offlineChannel > (size_t) _max_offline_channel) ) continue;
838 
839  v_adc.clear();
840  std::vector<dune::adc_t> waveform( felix.get_ADCs_by_channel(ch) );
841  for(unsigned int nframe=0;nframe<waveform.size();nframe++){
842  v_adc.push_back(waveform.at(nframe));
843  }
844 
845  if ( v_adc.size() != _full_tick_count)
846  {
848  {
849  MF_LOG_WARNING("_process_FELIX_AUX:") << "Nticks not the required value: " << v_adc.size() << " "
850  << _full_tick_count << " Discarding Data";
851  _DiscardedCorruptData = true;
852  return true;
853  }
854  _KeptCorruptData = true;
855  }
856 
858  {
860  _tick_count_this_event = v_adc.size();
861  }
862  else
863  {
865  {
866  if (v_adc.size() != _tick_count_this_event)
867  {
868  MF_LOG_WARNING("_process_FELIX_AUX:") << "Nticks different for two channel streams: " << v_adc.size()
869  << " vs " << _tick_count_this_event << " Discarding Data";
870  _DiscardedCorruptData = true;
871  return true;
872  }
873  _KeptCorruptData = true;
874  }
875  }
876 
877  float median=0;
878  float sigma=0;
879  computeMedianSigma(v_adc,median,sigma);
880 
881  auto n_ticks = v_adc.size();
883  raw::RawDigit raw_digit(offlineChannel, n_ticks, v_adc, cflag);
884  raw_digit.SetPedestal(median,sigma);
885  raw_digits.push_back(raw_digit);
886 
887  raw::RDTimeStamp rdtimestamp(felix.timestamp(),offlineChannel);
888  timestamps.push_back(rdtimestamp);
889  }
890 
891  return true;
892 }
893 
894 
895 // compute median and sigma.
896 
898 {
899  size_t asiz = v_adc.size();
900  int imed=0;
901  if (asiz == 0)
902  {
903  median = 0;
904  sigma = 0;
905  }
906  else
907  {
908  // the RMS includes tails from bad samples and signals and may not be the best RMS calc.
909 
910  imed = TMath::Median(asiz,v_adc.data()) + 0.01; // add an offset to make sure the floor gets the right integer
911  median = imed;
912  sigma = TMath::RMS(asiz,v_adc.data());
913 
914  // add in a correction suggested by David Adams, May 6, 2019
915 
916  size_t s1 = 0;
917  size_t sm = 0;
918  for (size_t i=0; i<asiz; ++i)
919  {
920  if (v_adc[i] < imed) s1++;
921  if (v_adc[i] == imed) sm++;
922  }
923  if (sm > 0)
924  {
925  float mcorr = (-0.5 + (0.5*(float) asiz - (float) s1)/ ((float) sm) );
926  //if (std::abs(mcorr)>1.0) std::cout << "mcorr: " << mcorr << std::endl;
927  median += mcorr;
928  }
929  }
930 }
931 
bool _processFELIX(art::Event &evt, std::string inputLabel, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist)
int retrieveData(art::Event &evt, std::string inputlabel, std::vector< raw::RawDigit > &raw_digits, std::vector< raw::RDTimeStamp > &rd_timestamps, std::vector< raw::RDStatus > &rdstatuses)
static constexpr size_t num_ch_per_frame
Definition: FelixFormat.hh:298
int retrieveDataForSpecifiedAPAs(art::Event &evt, std::vector< raw::RawDigit > &raw_digits, std::vector< raw::RDTimeStamp > &rd_timestamps, std::vector< raw::RDStatus > &rdstatuses, std::vector< int > &apalist)
size_t total_frames() const
enum raw::_compress Compress_t
unsigned int InstalledAPAFromOfflineChannel(unsigned int offlineChannel) const
Returns APA/crate in installation notation.
#define DEFINE_ART_CLASS_TOOL(tool)
Definition: ToolMacros.h:42
Collection of charge vs time digitized from a single readout channel.
Definition: RawDigit.h:69
TpcStreamUnpack const * get_stream(int i) const
Definition: RceFragment.cc:48
uint8_t slot_no(const unsigned &frame_ID=0) const
void computeMedianSigma(raw::RawDigit::ADCvector_t &v_adc, float &median, float &sigma)
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
uint8_t crate_no(const unsigned &frame_ID=0) const
unsigned int _default_crate_if_unexpected
unsigned int _tick_count_this_event
std::vector< short > ADCvector_t
Type representing a (compressed) vector of ADC counts.
Definition: RawDigit.h:73
bool _processRCE(art::Event &evt, std::string inputLabel, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist)
QTextStream & hex(QTextStream &s)
uint8_t channel
Definition: CRTFragment.hh:201
bool _process_FELIX_AUX(art::Event &evt, const artdaq::Fragment &frag, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist)
int size() const
Definition: RceFragment.hh:25
no compression
Definition: RawTypes.h:9
unsigned int GetOfflineNumberFromDetectorElements(unsigned int crate, unsigned int slot, unsigned int fiber, unsigned int fembchannel, FelixOrRCE frswitch)
std::vector< raw::RawDigit > RawDigits
struct dune::tde::crate crate
T get(std::string const &key) const
Definition: ParameterSet.h:271
bool _felixProcContNCFrags(art::Handle< artdaq::Fragments > frags, size_t &n_felix_frags, bool is_container, art::Event &evt, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist)
p
Definition: test.py:223
void _collectRDStatus(std::vector< raw::RDStatus > &rdstatuses)
RunNumber_t run() const
Definition: DataViewImpl.cc:71
bool removeCachedProduct(Handle< PROD > &) const
Definition: DataViewImpl.h:927
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
void save(const std::string &filepath) const
Definition: RceFragment.cc:63
uint8_t fiber_no(const unsigned &frame_ID=0) const
adc_v get_ADCs_by_channel(const uint8_t channel_ID) const
unsigned int WIBFromOfflineChannel(unsigned int offlineChannel) const
Returns WIB/slot.
uint16_t wib_errors(const unsigned &frame_ID=0) const
std::vector< raw::RDTimeStamp > RDTimeStamps
int retrieveDataAPAListWithLabels(art::Event &evt, std::string inputlabel, std::vector< raw::RawDigit > &raw_digits, std::vector< raw::RDTimeStamp > &rd_timestamps, std::vector< raw::RDStatus > &rdstatuses, std::vector< int > &apalist)
void SetPedestal(float ped, float sigma=1.)
Set pedestal and its RMS (the latter is 0 by default)
Definition: RawDigit.cxx:68
bool _rceProcContNCFrags(art::Handle< artdaq::Fragments > frags, size_t &n_rce_frags, bool is_container, art::Event &evt, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist)
std::map< int, std::vector< std::string > > _input_labels_by_apa
unsigned int FEMBFromOfflineChannel(unsigned int offlineChannel) const
Returns FEMB/fiber.
bool _process_RCE_AUX(art::Event &evt, const artdaq::Fragment &frag, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist)
TCEvent evt
Definition: DataStructs.cxx:7
#define MF_LOG_WARNING(category)
PDSPTPCDataInterface(fhicl::ParameterSet const &ps)
Q_EXPORT QTSManip setfill(int f)
Definition: qtextstream.h:337
std::vector< Fragment > Fragments
Definition: HDF5Utils.h:57
unsigned int ChipFromOfflineChannel(unsigned int offlineChannel) const
Returns chip number.
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
double median(sqlite3 *db, std::string const &table_name, std::string const &column_name)
Definition: statistics.cc:26
QTextStream & endl(QTextStream &s)
uint64_t timestamp(const unsigned &frame_ID=0) const