IcebergDataInterface_tool.cc
Go to the documentation of this file.
1 // IcebergDataInterface_tool.cc
2 
3 #include "IcebergDataInterface.h"
4 #include "TMath.h"
5 #include "TString.h"
6 #include <iostream>
7 #include <set>
8 
10 
11 // artdaq and dune-raw-data includes
17 #include "dam/HeaderFragmentUnpack.hh"
18 #include "dam/DataFragmentUnpack.hh"
19 #include "dam/TpcFragmentUnpack.hh"
20 #include "dam/TpcStreamUnpack.hh"
21 #include "dam/access/WibFrame.hh"
22 #include "dam/access/Headers.hh"
23 #include "dam/access/TpcStream.hh"
24 #include "dam/access/TpcRanges.hh"
25 #include "dam/access/TpcToc.hh"
26 #include "dam/access/TpcPacket.hh"
27 #include "dam/RceFragmentUnpack.hh"
28 
30 {
31  _input_labels_by_apa[1] = p.get< std::vector<std::string> >("APA1InputLabels");
32  _input_labels_by_apa[2] = p.get< std::vector<std::string> >("APA2InputLabels");
33  _input_labels_by_apa[3] = p.get< std::vector<std::string> >("APA3InputLabels");
34  _input_labels_by_apa[4] = p.get< std::vector<std::string> >("APA4InputLabels");
35  _input_labels_by_apa[5] = p.get< std::vector<std::string> >("APA5InputLabels");
36  _input_labels_by_apa[6] = p.get< std::vector<std::string> >("APA6InputLabels");
37  _input_labels_by_apa[7] = p.get< std::vector<std::string> >("APA7InputLabels");
38  _input_labels_by_apa[8] = p.get< std::vector<std::string> >("APA8InputLabels");
39  _input_labels_by_apa[-1] = p.get< std::vector<std::string> >("MISCAPAInputLabels");
40 
41  _default_crate_if_unexpected = p.get<unsigned int>("DefaultCrateIfUnexpected",3);
42 
43  _min_offline_channel = p.get<long int>("MinOfflineChannel",-1);
44  _max_offline_channel = p.get<long int>("MaxOfflineChannel",-1);
45 
46  _drop_small_rce_frags = p.get<bool>("RCEDropSmallFrags",true);
47  _rce_frag_small_size = p.get<unsigned int>("RCESmallFragSize",10000);
48  _rce_drop_frags_with_badsf = p.get<bool>("RCEDropFragsWithBadSF",true);
49  _rce_drop_frags_with_badc = p.get<bool>("RCEDropFragsWithBadC",true);
50  _rce_hex_dump = p.get<bool>("RCEHexDump",false);
51  _rce_save_frags_to_files = p.get<bool>("RCESaveFragsToFiles",false);
52  _rce_check_buffer_size = p.get<bool>("RCECheckBufferSize",true);
53  _rce_buffer_size_checklimit = p.get<unsigned int>("RCEBufferSizeCheckLimit",10000000);
54 
55  _felix_drop_frags_with_badsf = p.get<bool>("FELIXDropFragsWithBadSF",true);
56  _felix_drop_frags_with_badc = p.get<bool>("FELIXDropFragsWithBadC",true);
57  _felix_hex_dump = p.get<bool>("FELIXHexDump",false);
58  _drop_small_felix_frags = p.get<bool>("FELIXDropSmallFrags",true);
59  _felix_frag_small_size = p.get<unsigned int>("FELIXSmallFragSize",10000);
60  _felix_check_buffer_size = p.get<bool>("FELIXCheckBufferSize",true);
61  _felix_buffer_size_checklimit = p.get<unsigned int>("FELIXBufferSizeCheckLimit",10000000);
62 
63  _enforce_same_tick_count = p.get<bool>("EnforceSameTickCount",false);
64  _enforce_median_tick_count = p.get<bool>("EnforceMedianTickCount",false);
65  _enforce_full_tick_count = p.get<bool>("EnforceFullTickCount",false);
66  _full_tick_count = p.get<unsigned int>("FullTickCount",6000);
67  _enforce_error_free = p.get<bool>("EnforceErrorFree",false);
68  _enforce_no_duplicate_channels = p.get<bool>("EnforceNoDuplicateChannels", true);
69 }
70 
71 // wrapper for backward compatibility. Return data for all APA's represented in the fragments on these labels
72 
74  std::string inputLabel,
75  std::vector<raw::RawDigit> &raw_digits,
76  std::vector<raw::RDTimeStamp> &rd_timestamps,
77  std::vector<raw::RDStatus> &rdstatuses)
78 {
79  std::vector<int> apalist;
80  apalist.push_back(-1);
81  int retcode = retrieveDataAPAListWithLabels(evt, inputLabel, raw_digits, rd_timestamps, rdstatuses, apalist );
82  _collectRDStatus(rdstatuses);
83  return retcode;
84 }
85 
86 // get data for specified APAs. Loop over labels specified in the fcl configuration looking for the data so the caller doesn't have to
87 // keep track of all the branch labels an APA's data might be on.
88 
90  std::vector<raw::RawDigit> &raw_digits,
91  std::vector<raw::RDTimeStamp> &rd_timestamps,
92  std::vector<raw::RDStatus> &rdstatuses,
93  std::vector<int> &apalist)
94 {
95  int totretcode = 0;
96 
97  for (size_t i=0; i<apalist.size(); ++i)
98  {
99  auto lli = _input_labels_by_apa.find(apalist.at(i));
100  if (lli == _input_labels_by_apa.end())
101  {
102  MF_LOG_WARNING("IcebergDataInterface:") << " No list of input labels known for APA " << apalist.at(i) << " Returning no data.";
103  }
104  for (size_t j=0; j<lli->second.size(); ++j)
105  {
106  int retcode = retrieveDataAPAListWithLabels(evt, lli->second.at(j), raw_digits, rd_timestamps, rdstatuses, apalist );
107  if (retcode > totretcode) totretcode = retcode; // take most severe retcode of everything
108  }
109  }
110  _collectRDStatus(rdstatuses);
111  return totretcode;
112 }
113 
114 // get data for a specific label, but only return those raw digits that correspond to APA's on the list
115 
117  std::string inputLabel,
118  std::vector<raw::RawDigit> &raw_digits,
119  std::vector<raw::RDTimeStamp> &rd_timestamps,
120  std::vector<raw::RDStatus> &rdstatuses,
121  std::vector<int> &apalist)
122 {
123 
125 
127  _DiscardedCorruptData = false; // can be set to true if we drop some of the event's data
128  _KeptCorruptData = false; // true if we identify a corruption candidate but are skipping the test to drop it
129 
130  if (inputLabel.find("TPC") != std::string::npos)
131  {
132  _processRCE(evt, inputLabel, raw_digits, rd_timestamps, apalist);
133  }
134  else if ( (inputLabel.find("FELIX") != std::string::npos) ||
135  (inputLabel.find("FRAME14") != std::string::npos) )
136  {
137  _processFELIX(evt, inputLabel, raw_digits, rd_timestamps, apalist);
138  }
139  else
140  {
141  throw cet::exception("IcebergInterface_tool") << "ununderstood fragment branch label: \"" << inputLabel << "\"";
142  }
143 
144  bool flagged_duplicate = false;
145 
147  {
148  std::set<unsigned int> channels_seen;
149 
150  for (const auto& rd : raw_digits)
151  {
152  unsigned int ichan = rd.Channel();
153  if (channels_seen.find(ichan) == channels_seen.end())
154  {
155  channels_seen.insert(ichan);
156  }
157  else
158  {
159  MF_LOG_WARNING("IcebergDataInterface:") << " Duplicate channel detected: " << ichan << " Discarding TPC data for this chunk: " << inputLabel;
160  raw_digits.clear();
161  rd_timestamps.clear();
162  flagged_duplicate = true;
163  break;
164  }
165  }
166  }
167 
169  {
170 
171  // 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,
172  // allowing it to have up to 10% missing ticks.
173 
174  std::vector<size_t> ticklist;
175  for (size_t i=0; i<raw_digits.size(); ++i)
176  {
177  ticklist.push_back(raw_digits.at(i).Samples());
178  }
179  size_t tls = ticklist.size();
180  size_t tickmed = 0;
181  if (tls != 0)
182  {
183  tickmed = TMath::Median(tls,ticklist.data());
184  }
185  size_t tickexample=0;
186  std::vector<size_t> dlist;
187  for (size_t i=0; i<raw_digits.size(); ++i)
188  {
189  if (ticklist.at(i) != tickmed)
190  {
191  unsigned int channel = raw_digits.at(i).Channel();
192  unsigned int crate = cmap->APAFromOfflineChannel(channel);
193  unsigned int slot = cmap->WIBFromOfflineChannel(channel);
194  unsigned int fiber = cmap->FEMBFromOfflineChannel(channel);
195  //std::cout << "tick not at median: " << channel << " " << crate << " " << slot << " " << fiber << " " << ticklist.at(i) << " " << tickmed << std::endl;
196  if ( (crate == 3) && (slot == 3) && (fiber == 2) && ( ticklist.at(i) > 0.9*tickmed && ticklist.at(i) < tickmed ) ) continue; // FEMB 302
197  dlist.push_back(i);
198  tickexample = ticklist.at(i);
199  }
200  }
201 
202  if (dlist.size() != 0)
203  {
204  //std::cout << "IcebergDataInterface_tool: Discarding data with n_ticks not at the median. Example invalid ticks: " << tickexample << std::endl;
205  MF_LOG_WARNING("IcebergDataInterface_tool:") << " Discarding data with n_ticks not at the median. Example invalid ticks: " << tickexample;
206  for (size_t i=dlist.size(); i>0; --i)
207  {
208  raw_digits.erase(raw_digits.begin() + dlist.at(i-1));
209  rd_timestamps.erase(rd_timestamps.begin() + dlist.at(i-1));
210  }
211  }
212  }
213 
214  unsigned int statword=0;
215  if (_DiscardedCorruptData) statword |= 1;
216  if (_KeptCorruptData) statword |= 2;
217  rdstatuses.emplace_back(_DiscardedCorruptData,_KeptCorruptData,statword);
218  if (flagged_duplicate) statword = 4; // a flag to the caller indicating that the entire event's worth of raw digits is to be dropped
219  _collectRDStatus(rdstatuses);
220  return statword;
221 }
222 
223 
224 void IcebergDataInterface::_collectRDStatus(std::vector<raw::RDStatus> &rdstatuses)
225 {
226  if (rdstatuses.size() < 2) return;
227  unsigned int statword=0;
228  bool dcflag = false;
229  bool kcflag = false;
230  for (size_t i=0; i<rdstatuses.size(); ++i)
231  {
232  statword |= rdstatuses.at(i).GetStatWord();
233  dcflag |= rdstatuses.at(i).GetCorruptDataDroppedFlag();
234  kcflag |= rdstatuses.at(i).GetCorruptDataKeptFlag();
235  }
236  rdstatuses.clear();
237  rdstatuses.emplace_back(dcflag,kcflag,statword);
238 }
239 
240 
242  std::string inputLabel,
243  RawDigits& raw_digits,
244  RDTimeStamps &timestamps,
245  std::vector<int> &apalist)
246 {
247  size_t n_rce_frags = 0;
248  bool have_data=false;
249  bool have_data_nc=false;
250 
251  if (inputLabel.find("Container") != std::string::npos)
252  {
253  auto cont_frags = evt.getHandle<artdaq::Fragments>(inputLabel);
254  if (cont_frags)
255  {
256  have_data = true;
257  if (! _rceProcContNCFrags(cont_frags, n_rce_frags, true, evt, raw_digits, timestamps, apalist))
258  {
259  return false;
260  }
261  }
262  }
263  else
264  {
265  auto frags = evt.getHandle<artdaq::Fragments>(inputLabel);
266  if (frags)
267  {
268  have_data_nc = true;
269  if (! _rceProcContNCFrags(frags, n_rce_frags, false, evt, raw_digits, timestamps, apalist))
270  {
271  return false;
272  }
273  }
274  }
275 
276  // returns true if we want to add to the number of fragments processed.
277 
278  return have_data || have_data_nc;
279 }
280 
282  size_t &n_rce_frags,
283  bool is_container,
284  art::Event &evt,
285  RawDigits& raw_digits,
286  RDTimeStamps &timestamps,
287  std::vector<int> &apalist)
288 {
289 
290  for (auto const& frag : *frags)
291  {
292  //std::cout << "RCE fragment size bytes: " << frag.sizeBytes() << std::endl;
293 
294  bool process_flag = true;
295  if (frag.sizeBytes() < _rce_frag_small_size)
296  {
297  if ( _drop_small_rce_frags )
298  {
299  MF_LOG_WARNING("_process_RCE:") << " Small RCE fragment size: " << frag.sizeBytes() << " Discarding just this fragment on request.";
300  _DiscardedCorruptData = true;
301  process_flag = false;
302  }
303  else
304  {
305  _KeptCorruptData = true;
306  }
307  }
308  if (process_flag)
309  {
310  if (is_container)
311  {
312  artdaq::ContainerFragment cont_frag(frag);
313  for (size_t ii = 0; ii < cont_frag.block_count(); ++ii)
314  {
315  if (_process_RCE_AUX(evt,*cont_frag[ii], raw_digits, timestamps, apalist)) ++n_rce_frags;
316  }
317  }
318  else
319  {
320  if (_process_RCE_AUX(evt,frag, raw_digits, timestamps, apalist)) ++n_rce_frags;
321  }
322  }
323  }
324  evt.removeCachedProduct(frags); // do this always, even if we need to re-read a TBranch
325  return true;
326 }
327 
328 
330  art::Event &evt,
331  const artdaq::Fragment& frag,
332  RawDigits& raw_digits,
333  RDTimeStamps &timestamps,
334  std::vector<int> &apalist
335  )
336 {
337 
338  if (_rce_hex_dump)
339  {
340  std::ios oldState(nullptr);
341  oldState.copyfmt(std::cout);
342 
343  std::cout << "RCE Fragment: all numbers in hex " << std::hex
344  << " SequenceID = " << frag.sequenceID()
345  << " fragmentID = " << frag.fragmentID()
346  << " fragmentType = " << (unsigned)frag.type()
347  << " Timestamp = " << frag.timestamp() << std::endl;
348  std::cout << "Offset Data";
349  artdaq::Fragment fragloc(frag);
350  unsigned char *dbegin = reinterpret_cast<unsigned char *>(fragloc.dataAddress());
351  size_t dsize = fragloc.dataSizeBytes();
352  size_t offcounter=0;
353  for (size_t bcounter=0; bcounter<dsize;++bcounter)
354  {
355  if ( (offcounter % 8) == 0 )
356  {
357  std::cout << std::endl << std::hex << std::setfill('0') << std::setw(8) << offcounter << " ";
358  }
359  std::cout << std::hex << std::setfill('0') << std::setw(2) << (int) *dbegin << " ";
360  dbegin++;
361  offcounter++;
362  }
363  std::cout << std::endl;
364  std::cout.copyfmt(oldState);
365  }
366 
367  //MF_LOG_INFO("_Process_RCE_AUX")
368  //<< " SequenceID = " << frag.sequenceID()
369  //<< " fragmentID = " << frag.fragmentID()
370  //<< " fragmentType = " << (unsigned)frag.type()
371  //<< " Timestamp = " << frag.timestamp();
373 
374  artdaq::Fragment cfragloc(frag);
375  size_t cdsize = cfragloc.dataSizeBytes();
376  const uint64_t* cdptr = (uint64_t const*) (cfragloc.dataBeginBytes() + 12); // see dune-raw-data/Overlays/RceFragment.cc
377  HeaderFragmentUnpack const cdheader(cdptr);
378  //bool isOkay = RceFragmentUnpack::isOkay(cdptr,cdsize+sizeof(cdheader));
379  if (cdsize>16) cdsize -= 16;
380  bool isOkay = RceFragmentUnpack::isOkay(cdptr,cdsize);
381  if (!isOkay)
382  {
383  MF_LOG_WARNING("_process_RCE_AUX:") << "RCE Fragment isOkay failed: " << cdsize << " Discarding this fragment";
384  _DiscardedCorruptData = true;
385  return false;
386  }
387 
388  //DataFragmentUnpack df(cdptr);
389  //std::cout << "isTPpcNormal: " << df.isTpcNormal() << " isTpcDamaged: " << df.isTpcDamaged() << " isTpcEmpty: " << df.isTpcEmpty() << std::endl;
390 
391  dune::RceFragment rce(frag);
393  {
394  TString outfilename="rce_";
395  outfilename += evt.run();
396  outfilename += "_";
397  outfilename += frag.sequenceID();
398  outfilename += "_";
399  outfilename += frag.fragmentID();
400  outfilename+=".fragment";
401  rce.save(outfilename.Data());
402  std::cout << "Saved an RCE fragment with " << rce.size() << " streams: " << outfilename << std::endl;
403  }
404 
405  uint32_t ch_counter = 0;
406  for (int i = 0; i < rce.size(); ++i)
407  {
408  auto const * rce_stream = rce.get_stream(i);
409  size_t n_ch = rce_stream->getNChannels();
410  size_t n_ticks = rce_stream->getNTicks();
411  if (n_ticks == 0) continue; // on David Adams's request.
412  auto const identifier = rce_stream->getIdentifier();
413  uint32_t crateNumber = identifier.getCrate();
414  // always use crate #3 for iceberg to fool the ProtoDUNE data prep into thinking it should
415  // have the low-numbered channels
416  crateNumber = 3;
417  uint32_t slotNumber = identifier.getSlot();
418  uint32_t fiberNumber = identifier.getFiber();
419 
420  // only take this rce stream if it has data from an APA we are interested in
421  bool foundapainlist = false;
422  for (size_t ialist=0; ialist < apalist.size(); ++ ialist)
423  {
424  if ( ( (apalist[ialist] == -1) && (!_rce_drop_frags_with_badc || (crateNumber >0 && crateNumber < 7)) ) ||
425  (apalist[ialist] == (int) crateNumber) ||
426  (apalist[ialist] == 7 && (crateNumber == 0 || crateNumber > 6)) )
427  {
428  foundapainlist = true;
429  break;
430  }
431  }
432  if (!foundapainlist) continue;
433 
434  //std::cout << "Processing an RCE Stream: " << crateNumber << " " << slotNumber << " " << fiberNumber << " " << n_ticks << " " << n_ch << std::endl;
435 
436  //------------------------------------------------------------------------------------------
437  // Handle run-dependent re-cabling of the detector
438  //------------------------------------------------------------------------------------------
439 
440  uint32_t runNumber = evt.run();
441 
442  // inverted ordering on back side, Run 2c (=Run 3)
443  // note Shekhar's FEMB number is fiber-1, and WIB is slot+1
444 
445  if (runNumber > 2572)
446  {
447  auto oldfiber = fiberNumber;
448  auto oldslot = slotNumber;
449 
450  if (oldslot == 0 && oldfiber == 4)
451  {
452  slotNumber = 1;
453  fiberNumber = 3;
454  }
455  if (oldslot == 1 && oldfiber == 4)
456  {
457  slotNumber = 0;
458  fiberNumber = 3;
459  }
460  if (oldslot == 1 && oldfiber == 3)
461  {
462  slotNumber = 0;
463  fiberNumber = 4;
464  }
465  if (oldslot == 0 && oldfiber == 3)
466  {
467  slotNumber = 1;
468  fiberNumber = 4;
469  }
470  }
471 
472  // two cable swaps on June 20, 2019, and go back to the original on Jan 22, 2020
473 
474  if (runNumber > 1530 && runNumber < 2572)
475  {
476  auto oldfiber = fiberNumber;
477  auto oldslot = slotNumber;
478 
479  // second swap, June 21, 2019 -- see Slack
480 
481  if (oldslot == 2 && oldfiber == 1)
482  {
483  slotNumber = 2;
484  fiberNumber = 3;
485  }
486  if (oldslot == 1 && oldfiber == 1)
487  {
488  slotNumber = 1;
489  fiberNumber = 3;
490  }
491  if (oldslot == 2 && oldfiber == 3)
492  {
493  slotNumber = 2;
494  fiberNumber = 1;
495  }
496  if (oldslot == 1 && oldfiber == 3)
497  {
498  slotNumber = 1;
499  fiberNumber = 1;
500  }
501 
502  oldfiber = fiberNumber;
503  oldslot = slotNumber;
504 
505  if (oldslot == 0 && oldfiber == 4)
506  {
507  slotNumber = 1;
508  fiberNumber = 3;
509  }
510  if (oldslot == 1 && oldfiber == 4)
511  {
512  slotNumber = 0;
513  fiberNumber = 3;
514  }
515  if (oldslot == 0 && oldfiber == 3)
516  {
517  slotNumber = 1;
518  fiberNumber = 4;
519  }
520  if (oldslot == 1 && oldfiber == 3)
521  {
522  slotNumber = 0;
523  fiberNumber = 4;
524  }
525  }
526 
527  // skip the fake TPC data
528 
529  if ( slotNumber == 1 && fiberNumber == 1 )
530  {
531  continue;
532  }
533 
534  if ( slotNumber == 2 && fiberNumber == 1 )
535  {
536  continue;
537  }
538 
539  //std::cout << " After cable swap : WIB: " << slotNumber+1 << " FEMB: " << fiberNumber-1 << std::endl;
540 
541  //------------------------------------------------------------------------------------------
542  // End of handling of run-dependent re-cabling of the detector
543  //------------------------------------------------------------------------------------------
544 
545  if (slotNumber > 4 || fiberNumber == 0 || fiberNumber > 4)
546  {
548  {
549  MF_LOG_WARNING("_process_RCE:") << "Bad crate, slot, fiber number, discarding fragment on request: "
550  << crateNumber << " " << slotNumber << " " << fiberNumber;
551  _DiscardedCorruptData = true;
552  return false;
553  }
554  _KeptCorruptData = true;
555  }
556 
557  if (n_ticks != _full_tick_count)
558  {
560  {
561  MF_LOG_WARNING("_process_RCE_AUX:") << "Nticks not the required value: " << n_ticks << " "
562  << _full_tick_count << " Discarding Data";
563  _DiscardedCorruptData = true;
564  return false;
565  }
566  _KeptCorruptData = true;
567  }
568 
570  {
572  _tick_count_this_event = n_ticks;
573  }
574  else
575  {
576  if (n_ticks != _tick_count_this_event)
577  {
579  {
580  MF_LOG_WARNING("_process_RCE_AUX:") << "Nticks different for two channel streams: " << n_ticks
581  << " vs " << _tick_count_this_event << " Discarding Data";
582  _DiscardedCorruptData = true;
583  return false;
584  }
585  }
586  _KeptCorruptData = true;
587  }
588 
589 
590  //MF_LOG_INFO("_Process_RCE_AUX")
591  //<< "RceFragment timestamp: " << rce_stream->getTimeStamp()
592  //<< ", NChannels: " << n_ch
593  //<< ", NTicks: " << n_ticks;
594 
595  // TODO -- speed this up!! Remove one buffer copy
596 
597  size_t buffer_size = n_ch * n_ticks;
598 
599  if (buffer_size > _rce_buffer_size_checklimit)
600  {
602  {
603  MF_LOG_WARNING("_process_RCE_AUX:") << "n_ch*nticks too large: " << n_ch << " * " << n_ticks << " = " <<
604  buffer_size << " larger than: " << _rce_buffer_size_checklimit << ". Discarding this fragment";
605  _DiscardedCorruptData = true;
606  return false;
607  }
608  else
609  {
610  _KeptCorruptData = true;
611  }
612  }
613 
614  std::vector<int16_t> _buffer(buffer_size);
615 
616  int16_t* adcs = _buffer.data();
617  bool sgmcdretcode = rce_stream->getMultiChannelData(adcs);
618  if (!sgmcdretcode)
619  {
621  {
622  MF_LOG_WARNING("_process_RCE_AUX:") << "getMutliChannelData returns error flag: "
623  << " c:s:f:ich: " << crateNumber << " " << slotNumber << " " << fiberNumber << " Discarding Data";
624  _DiscardedCorruptData = true;
625  return false;
626  }
627  _KeptCorruptData = true;
628  }
629 
630  //std::cout << "RCE raw decoder trj: " << crateNumber << " " << slotNumber << " " << fiberNumber << std::endl;
631 
632  // David Adams's request for channels to start at zero for coldbox test data
633  unsigned int crateloc = crateNumber;
634  //if (crateNumber == 0 || crateNumber > 6) crateloc = _default_crate_if_unexpected;
635  crateloc = 1; // always use crate 1 for Iceberg
636 
638  for (size_t i_ch = 0; i_ch < n_ch; i_ch++)
639  {
640  unsigned int offlineChannel = channelMap->GetOfflineNumberFromDetectorElements(crateloc, slotNumber, fiberNumber, i_ch, dune::IcebergChannelMapService::kRCE);
641 
643  (offlineChannel < (size_t) _min_offline_channel || offlineChannel > (size_t) _max_offline_channel) ) continue;
644 
645  v_adc.clear();
646 
647  for (size_t i_tick = 0; i_tick < n_ticks; i_tick++)
648  {
649  v_adc.push_back(adcs[i_tick]);
650  }
651 
652  adcs += n_ticks;
653 
654  ch_counter++;
655 
656  float median=0;
657  float sigma=0;
658  computeMedianSigma(v_adc,median,sigma);
659 
660  /// FEMB 302 IS crate 3, slot 3, fiber 2
661 
662  auto uncompressed_nticks = v_adc.size(); // can be different from n_ticks due to padding of FEMB 302
663 
665  // here n_ticks is the uncompressed size as required by the constructor
666  raw::RawDigit raw_digit(offlineChannel, uncompressed_nticks, v_adc, cflag);
667  raw_digit.SetPedestal(median,sigma);
668  raw_digits.push_back(raw_digit);
669 
670  raw::RDTimeStamp rdtimestamp(rce_stream->getTimeStamp(),offlineChannel);
671  timestamps.push_back(rdtimestamp);
672 
673  } // end loop over channels
674  } // end loop over RCE streams (1 per FEMB)
675  // end processing one RCE fragment
676  return true;
677 }
678 
679 
680 
682  std::string inputLabel,
683  RawDigits& raw_digits,
684  RDTimeStamps &timestamps,
685  std::vector<int> &apalist)
686 {
687  size_t n_felix_frags = 0;
688  bool have_data=false;
689  bool have_data_nc=false;
690 
691  if (inputLabel.find("Container") != std::string::npos)
692  {
693  auto cont_frags = evt.getHandle<artdaq::Fragments>(inputLabel);
694  if (cont_frags)
695  {
696  have_data = true;
697  if (! _felixProcContNCFrags(cont_frags, n_felix_frags, true, evt, raw_digits, timestamps, apalist, inputLabel))
698  {
699  return false;
700  }
701  }
702  }
703  else
704  {
705  auto frags = evt.getHandle<artdaq::Fragments>(inputLabel);
706 
707  if (frags)
708  {
709  have_data_nc = true;
710  if (! _felixProcContNCFrags(frags, n_felix_frags, false, evt, raw_digits, timestamps, apalist, inputLabel))
711  {
712  return false;
713  }
714  }
715  }
716 
717  // returns true if we want to add to the number of fragments processed.
718 
719  return have_data || have_data_nc;
720 }
721 
723  size_t &n_felix_frags,
724  bool is_container,
725  art::Event &evt,
726  RawDigits& raw_digits,
727  RDTimeStamps &timestamps,
728  std::vector<int> &apalist,
729  std::string inputLabel)
730 {
731  uint32_t runNumber = evt.run();
732 
733  for (auto const& frag : *frags)
734  {
735  //std::cout << "FELIX fragment size bytes: " << frag.sizeBytes() << std::endl;
736 
737  bool process_flag = true;
738  if (frag.sizeBytes() < _felix_frag_small_size)
739  {
741  {
742  MF_LOG_WARNING("_process_FELIX:") << " Small FELIX fragment size: " << frag.sizeBytes() << " Discarding just this fragment on request.";
743  _DiscardedCorruptData = true;
744  process_flag = false;
745  }
746  else
747  {
748  _KeptCorruptData = true;
749  }
750  }
751  if (process_flag)
752  {
753  if (is_container)
754  {
755  artdaq::ContainerFragment cont_frag(frag);
756  for (size_t ii = 0; ii < cont_frag.block_count(); ++ii)
757  {
758  if (_process_FELIX_AUX(evt,*cont_frag[ii], raw_digits, timestamps, apalist, runNumber, inputLabel)) ++n_felix_frags;
759  }
760  }
761  else
762  {
763  if (_process_FELIX_AUX(evt,frag, raw_digits, timestamps, apalist, runNumber, inputLabel)) ++n_felix_frags;
764  }
765  }
766  }
767  evt.removeCachedProduct(frags);
768  return true;
769 }
770 
771 
773  const artdaq::Fragment& frag, RawDigits& raw_digits,
774  RDTimeStamps &timestamps,
775  std::vector<int> &apalist,
776  uint32_t runNumber,
777  std::string inputLabel)
778 {
779 
780  //std::cout
781  //<< " SequenceID = " << frag.sequenceID()
782  //<< " fragmentID = " << frag.fragmentID()
783  //<< " fragmentType = " << (unsigned)frag.type()
784  //<< " Timestamp = " << frag.timestamp() << std::endl;
785 
786  if (_felix_hex_dump)
787  {
788  std::ios oldState(nullptr);
789  oldState.copyfmt(std::cout);
790 
791  std::cout << "FELIX Fragment: all numbers in hex " << std::hex
792  << " SequenceID = " << frag.sequenceID()
793  << " fragmentID = " << frag.fragmentID()
794  << " fragmentType = " << (unsigned)frag.type()
795  << " Timestamp = " << frag.timestamp() << std::endl;
796  std::cout << "Offset Data";
797  artdaq::Fragment fragloc(frag);
798  unsigned char *dbegin = reinterpret_cast<unsigned char *>(fragloc.dataAddress());
799  size_t dsize = fragloc.dataSizeBytes();
800  size_t offcounter=0;
801  for (size_t bcounter=0; bcounter<dsize;++bcounter)
802  {
803  if ( (offcounter % 8) == 0 )
804  {
805  std::cout << std::endl << std::hex << std::setfill('0') << std::setw(8) << offcounter << " ";
806  }
807  std::cout << std::hex << std::setfill('0') << std::setw(2) << (int) *dbegin << " ";
808  dbegin++;
809  offcounter++;
810  }
811  std::cout << std::endl;
812  std::cout.copyfmt(oldState);
813  }
814 
816 
817  // Load overlay class. Either a felix or a frame14 overlay, depending on the
818  // input instance name
819 
820  bool is14 = (inputLabel.find("FRAME14") != std::string::npos);
821  std::unique_ptr<dune::FelixFragment> felixptr;
822  std::unique_ptr<dune::Frame14FragmentUnordered> frame14ptr;
823  if (is14)
824  {
825  std::unique_ptr<dune::Frame14FragmentUnordered> ftmp(new dune::Frame14FragmentUnordered(frag));
826  frame14ptr = std::move(ftmp);
827  }
828  else
829  {
830  std::unique_ptr<dune::FelixFragment> ftmp(new dune::FelixFragment(frag));
831  felixptr = std::move(ftmp);
832  }
833 
834  //Get detector element numbers from the fragment
835 
836  uint8_t crate = 0;
837  uint8_t slot = 0;
838  uint8_t fiber = 0;
839 
840  if (is14)
841  {
842  crate = frame14ptr->crate_no(0);
843  slot = frame14ptr->slot_no(0);
844  fiber = frame14ptr->fiber_no(0); // decode this one later
845  int frame_version = frame14ptr->frame_version(0);
846  //std::cout << "ICEBERG frame_version, crate, slot, fiber, fragID: " << frame_version << " "
847  // << (int) crate << " " << (int) slot << " " << (int) fiber << " " << (int) frag.fragmentID() << std::endl;
848  if (frame_version == 0)
849  {
850  std::cout << "ICEBERG frame_version = 0; skipping this fragment" << std::endl;
851  return false;
852  }
853  fiber ++; // read in 0 to 1, go from 1 to 2
854  crate = 1; // ignored anyway for Iceberg -- just one crate.
855  }
856  else
857  {
858  crate = felixptr->crate_no(0);
859  slot = felixptr->slot_no(0);
860  fiber = felixptr->fiber_no(0); // decode this one later
861  }
862 
863  if (slot > 4)
864  {
866  {
867  _DiscardedCorruptData = true;
868  MF_LOG_WARNING("_process_FELIX_AUX:") << "Invalid crate or slot: c=" << (int) crate << " s=" << (int) slot << " discarding FELIX data.";
869  return false;
870  }
871  _KeptCorruptData = true;
872  }
873 
874  // only take this felix fragment if it has data from an APA we are interested in
875  bool foundapainlist = false;
876  for (size_t ialist=0; ialist < apalist.size(); ++ ialist)
877  {
878  if ( ( (apalist[ialist] == -1) && (!_rce_drop_frags_with_badc || (crate >0 && crate < 7)) ) ||
879  (apalist[ialist] == (int) crate) ||
880  (apalist[ialist] == 7 && (crate == 0 || crate > 6)) )
881  {
882  foundapainlist = true;
883  break;
884  }
885  }
886  if (!foundapainlist) return true;
887 
888  //std::cout << "FELIX raw decoder trj: " << (int) crate << " " << (int) slot << " " << (int) fiber << std::endl;
889 
890  // One frame contains 25 felix (20 ns-long) ticks. A "frame" is an offline tick
891  unsigned n_frames = 0;
892  if (is14)
893  {
894  n_frames = frame14ptr->total_frames();
895  }
896  else
897  {
898  n_frames = felixptr->total_frames();
899  }
900 
901 
902  //std::cout<<" Nframes = "<<n_frames<<std::endl;
903  //_h_nframes->Fill(n_frames);
904  if (n_frames ==0) return true;
905 
906  const unsigned n_channels = dune::FelixFrame::num_ch_per_frame;// should be 256
907 
908 
909  if (n_frames*n_channels > _felix_buffer_size_checklimit)
910  {
912  {
913  MF_LOG_WARNING("_process_FELIX_AUX:") << "n_channels*n_frames too large: " << n_channels << " * " << n_frames << " = " <<
914  n_frames*n_channels << " larger than: " << _felix_buffer_size_checklimit << ". Discarding this fragment";
915  _DiscardedCorruptData = true;
916  return false;
917  }
918  else
919  {
920  _KeptCorruptData = true;
921  }
922  }
923 
924  // this test does not yet exist for Frame14
925 
926  if (!is14)
927  {
928  for (unsigned int iframe=0; iframe<n_frames; ++iframe)
929  {
930  if ( felixptr->wib_errors(iframe) != 0)
931  {
932  if (_enforce_error_free )
933  {
934  _DiscardedCorruptData = true;
935  MF_LOG_WARNING("_process_FELIX_AUX:") << "WIB Errors on frame: " << iframe << " : " << felixptr->wib_errors(iframe)
936  << " Discarding Data";
937  // drop just this fragment
938  //_discard_data = true;
939  return true;
940  }
941  _KeptCorruptData = true;
942  }
943  }
944  }
945 
946  // check optimization of this -- size not reserved
947 
949  //v_adc.reserve(n_frames*n_channels);
950  // Fill the adc vector.
951 
952  for(unsigned ch = 0; ch < n_channels; ++ch) {
953 
954  // handle 256 channels on two fibers -- use the channel map that assumes 128 chans per fiber (=FEMB)
955 
956  unsigned int fiberloc = 0;
957  if (fiber == 1)
958  {
959  fiberloc = 1;
960  }
961  else if (fiber == 2)
962  {
963  fiberloc = 3;
964  }
965  else
966  {
967  MF_LOG_WARNING("_process_FELIX_AUX:") << " Fiber number " << (int) fiber << " is expected to be 1 or 2 -- revisit logic";
968  fiberloc = 1;
970  {
971  MF_LOG_WARNING("_process_FELIX_AUX:") << " Dropping FELIX Data";
972  return false;
973  }
974  }
975 
976  unsigned int chloc = ch;
977  if (chloc > 127)
978  {
979  chloc -= 128;
980  fiberloc++;
981  }
982  unsigned int crateloc = crate;
983  // David Adams's request for channels to start at zero for coldbox test data
984  if (crateloc == 0 || crateloc > 6) crateloc = _default_crate_if_unexpected;
985  // conversion of Run 7 slot and fibers to Run 5
986 
987  if (runNumber > 9745)
988  {
989  auto slotloc3 = slot;
990  auto fiberloc3 = fiberloc;
991 
992  // conversion map
993  // run 7 slot, run 7 fiber, run 5 slot, run 5 fiber
994  unsigned int sfmap[10][4] =
995  {
996  {4, 1, 0, 4},
997  {3, 4, 1, 4},
998  {3, 3, 2, 4},
999  {3, 2, 0, 3},
1000  {3, 1, 1, 3},
1001  {0, 1, 0, 1},
1002  {0, 2, 2, 2},
1003  {0, 3, 1, 2},
1004  {0, 4, 0, 2},
1005  {1, 1, 2, 3}
1006  };
1007  bool found = false;
1008  for (size_t imap = 0; imap<10; ++imap)
1009  {
1010  if (slot == sfmap[imap][0] && fiberloc == sfmap[imap][1])
1011  {
1012  slotloc3 = sfmap[imap][2];
1013  fiberloc3 = sfmap[imap][3];
1014  found = true;
1015  break;
1016  }
1017  if (!found)
1018  {
1019  std::cout << "Slot, fiber not understood in mapping from Run 7 to Run 5: " << (int) slot << " " << (int) fiberloc << std::endl;
1020  slotloc3 = 0;
1021  fiberloc3 = 4;
1022  }
1023  }
1024  slot = slotloc3;
1025  fiberloc = fiberloc3;
1026  }
1027 
1028 
1029  // inverted ordering on back side, Run 2c (=Run 3)
1030  // note Shekhar's FEMB number is fiber-1, and WIB is slot+1
1031 
1032  auto slotloc2 = slot;
1033  auto fiberloc2 = fiberloc;
1034 
1035  if (runNumber > 2572)
1036  {
1037 
1038  if (slot == 0 && fiberloc == 4)
1039  {
1040  slotloc2 = 1;
1041  fiberloc2 = 3;
1042  }
1043  if (slot == 1 && fiberloc == 4)
1044  {
1045  slotloc2 = 0;
1046  fiberloc2 = 3;
1047  }
1048  if (slot == 1 && fiberloc == 3)
1049  {
1050  slotloc2 = 0;
1051  fiberloc2 = 4;
1052  }
1053  if (slot == 0 && fiberloc == 3)
1054  {
1055  slotloc2 = 1;
1056  fiberloc2 = 4;
1057  }
1058  }
1059 
1060  // skip the fake TPC data
1061 
1062  if ( slotloc2 == 1 && fiberloc2 == 1 )
1063  {
1064  continue;
1065  }
1066 
1067  if ( slotloc2 == 2 && fiberloc2 == 1 )
1068  {
1069  continue;
1070  }
1071 
1072 
1073  unsigned int offlineChannel = channelMap->GetOfflineNumberFromDetectorElements(crateloc, slotloc2, fiberloc2, chloc, dune::IcebergChannelMapService::kFELIX);
1074 
1075  // skip this channel if we are asked to.
1076 
1078  (offlineChannel < (size_t) _min_offline_channel || offlineChannel > (size_t) _max_offline_channel) ) continue;
1079 
1080  v_adc.clear();
1081  std::vector<dune::adc_t> waveform( is14 ?
1082  frame14ptr->get_ADCs_by_channel(ch) :
1083  felixptr->get_ADCs_by_channel(ch) );
1084 
1085  for(unsigned int nframe=0;nframe<waveform.size();nframe++){
1086  v_adc.push_back(waveform.at(nframe));
1087  }
1088 
1089  if ( v_adc.size() != _full_tick_count)
1090  {
1092  {
1093  MF_LOG_WARNING("_process_FELIX_AUX:") << "Nticks not the required value: " << v_adc.size() << " "
1094  << _full_tick_count << " Discarding Data";
1095  _DiscardedCorruptData = true;
1096  return true;
1097  }
1098  _KeptCorruptData = true;
1099  }
1100 
1102  {
1104  _tick_count_this_event = v_adc.size();
1105  }
1106  else
1107  {
1109  {
1110  if (v_adc.size() != _tick_count_this_event)
1111  {
1112  MF_LOG_WARNING("_process_FELIX_AUX:") << "Nticks different for two channel streams: " << v_adc.size()
1113  << " vs " << _tick_count_this_event << " Discarding Data";
1114  _DiscardedCorruptData = true;
1115  return true;
1116  }
1117  _KeptCorruptData = true;
1118  }
1119  }
1120 
1121  float median=0;
1122  float sigma=0;
1123  computeMedianSigma(v_adc,median,sigma);
1124 
1125  auto n_ticks = v_adc.size();
1127  raw::RawDigit raw_digit(offlineChannel, n_ticks, v_adc, cflag);
1128  raw_digit.SetPedestal(median,sigma);
1129  raw_digits.push_back(raw_digit);
1130 
1131  raw::RDTimeStamp rdtimestamp( is14 ? frame14ptr->timestamp() : felixptr->timestamp(),offlineChannel);
1132  timestamps.push_back(rdtimestamp);
1133  }
1134 
1135  return true;
1136 }
1137 
1138 
1139 // compute median and sigma.
1140 
1142 {
1143  size_t asiz = v_adc.size();
1144  int imed=0;
1145  if (asiz == 0)
1146  {
1147  median = 0;
1148  sigma = 0;
1149  }
1150  else
1151  {
1152  // the RMS includes tails from bad samples and signals and may not be the best RMS calc.
1153 
1154  imed = TMath::Median(asiz,v_adc.data()) + 0.01; // add an offset to make sure the floor gets the right integer
1155  median = imed;
1156  sigma = TMath::RMS(asiz,v_adc.data());
1157 
1158  // add in a correction suggested by David Adams, May 6, 2019
1159 
1160  size_t s1 = 0;
1161  size_t sm = 0;
1162  for (size_t i=0; i<asiz; ++i)
1163  {
1164  if (v_adc[i] < imed) s1++;
1165  if (v_adc[i] == imed) sm++;
1166  }
1167  if (sm > 0)
1168  {
1169  float mcorr = (-0.5 + (0.5*(float) asiz - (float) s1)/ ((float) sm) );
1170  //if (std::abs(mcorr)>1.0) std::cout << "mcorr: " << mcorr << std::endl;
1171  median += mcorr;
1172  }
1173  }
1174 }
1175 
static constexpr size_t num_ch_per_frame
Definition: FelixFormat.hh:298
size_t total_frames() const
enum raw::_compress Compress_t
#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
uint8_t slot_no(const unsigned &frame_ID=0) const
uint8_t fiber_no(const unsigned &frame_ID=0) const
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
bool _process_RCE_AUX(art::Event &evt, const artdaq::Fragment &frag, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist)
unsigned int _tick_count_this_event
unsigned int _default_crate_if_unexpected
std::vector< short > ADCvector_t
Type representing a (compressed) vector of ADC counts.
Definition: RawDigit.h:73
QTextStream & hex(QTextStream &s)
uint8_t channel
Definition: CRTFragment.hh:201
int size() const
Definition: RceFragment.hh:25
no compression
Definition: RawTypes.h:9
bool _processRCE(art::Event &evt, std::string inputLabel, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist)
unsigned int GetOfflineNumberFromDetectorElements(unsigned int crate, unsigned int slot, unsigned int fiber, unsigned int fembchannel, FelixOrRCE frswitch)
std::vector< raw::RawDigit > RawDigits
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, std::string inputLabel)
struct dune::tde::crate crate
IcebergDataInterface(fhicl::ParameterSet const &ps)
def move(depos, offset)
Definition: depos.py:107
T get(std::string const &key) const
Definition: ParameterSet.h:271
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)
uint64_t timestamp(const unsigned &frame_ID=0) const
p
Definition: test.py:223
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 APAFromOfflineChannel(unsigned int offlineChannel) const
Returns APA/crate.
RunNumber_t run() const
Definition: DataViewImpl.cc:71
bool removeCachedProduct(Handle< PROD > &) const
Definition: DataViewImpl.h:927
bool _processFELIX(art::Event &evt, std::string inputLabel, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist)
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
uint8_t frame_version(const unsigned &frame_ID=0) const
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)
uint16_t wib_errors(const unsigned &frame_ID=0) const
uint8_t crate_no(const unsigned &frame_ID=0) const
bool _process_FELIX_AUX(art::Event &evt, const artdaq::Fragment &frag, RawDigits &raw_digits, RDTimeStamps &timestamps, std::vector< int > &apalist, uint32_t runNumber, std::string inputLabel)
void SetPedestal(float ped, float sigma=1.)
Set pedestal and its RMS (the latter is 0 by default)
Definition: RawDigit.cxx:68
adc_v get_ADCs_by_channel(const uint8_t block_ID, const uint8_t channel_ID) const
void computeMedianSigma(raw::RawDigit::ADCvector_t &v_adc, float &median, float &sigma)
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)
TCEvent evt
Definition: DataStructs.cxx:7
#define MF_LOG_WARNING(category)
std::vector< raw::RDTimeStamp > RDTimeStamps
unsigned int WIBFromOfflineChannel(unsigned int offlineChannel) const
Returns WIB/slot.
Q_EXPORT QTSManip setfill(int f)
Definition: qtextstream.h:337
unsigned int FEMBFromOfflineChannel(unsigned int offlineChannel) const
Returns FEMB/fiber.
std::vector< Fragment > Fragments
Definition: HDF5Utils.h:57
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
void _collectRDStatus(std::vector< raw::RDStatus > &rdstatuses)
QTextStream & endl(QTextStream &s)
uint64_t timestamp(const unsigned &frame_ID=0) const