DataPrepModule_module.cc
Go to the documentation of this file.
1 // DataPrepModule_module.cc
2 
3 // David Adams
4 // July 2016
5 // November 2016 - Add option to group channels.
6 //
7 // Module that reads RawData and writes Wire and their associations.
8 // It uses RawDigitPrepService to build the wires.
9 //
10 // It is possible to also write intermediate states. List the states in the fcl
11 // vector IntermediateStates. Supported values are:
12 // extracted - After pedestal subtraction
13 // mitigated - After mitigation (e.g. stuck bit interpolation)
14 // noiseRemoved - After noise removal
15 // The states are written to the containers with the same name. To save space
16 // and time, e.g. in standard production, this vector should be empty.
17 //
18 // If the flag is set set, channels are processed in groups specified by
19 // the ChannelGroupService. This can save memory because the transient ADC
20 // channel data is deleted after each group is processed.
21 //
22 // Configuration parameters:
23 // LogLevel - Usual logging level.
24 // DigitLabel - Full label for the input digit container, e.g. daq
25 // WireName - Name for the output wire container.
26 // IntermediateStates - Names of intermediate states to record.
27 // DoGroups - Process channels in groups obtained from ChannelGroupService
28 // if ChannelRanges is empty.
29 // ChannelRanges - Process channels in groups corresponding to these range names.
30 // The range for each name is obtained from the tool channelRanges.
31 // BeamEventLabel - Label for the BeamEvent data product. If blank, it is not used.
32 
50 #include "TTimeStamp.h"
54 #include <iomanip>
55 
56 using std::cout;
57 using std::endl;
58 using std::string;
59 using std::vector;
60 using std::move;
61 using std::setw;
62 using art::ServiceHandle;
63 using art::Timestamp;
64 using raw::RDStatus;
65 using recob::Wire;
66 
67 //**********************************************************************
68 
70 
71 public:
72 
73  using Index = unsigned int;
74  using Name = std::string;
75  using NameVector = std::vector<Name>;
76 
77  // Ctor.
78  explicit DataPrepModule(fhicl::ParameterSet const& pset);
79 
80  // Dtor.
82 
83  // Producer methods.
84  void produce(art::Event& evt);
85  void beginJob();
86  void endJob();
87  void reconfigure(fhicl::ParameterSet const& p);
88 
89 private:
90 
91  // Configuration parameters.
93  Name m_DecoderTool; // Name for the decoder tool
94  Name m_DigitLabel; ///< Full label for the input digit container, e.g. daq:
95  Name m_TimeStampName; // Label for the output RDTimeStamp conainer
96  Name m_OutputDigitName; // Label for the output raw::RawDigit conainer
97  Name m_WireName; ///< Second field in full label for the output wire container.
98  std::vector<std::string> m_IntermediateStates;
99  bool m_DoAssns = false;
100  bool m_DoGroups = false;
107 
108  // Split label into producer and name: PRODUCER or PRODUCER:NAME
111 
112  // Accessed services.
116 
117  // Tools.
119 
120  std::unique_ptr<PDSPTPCDataInterfaceParent> m_pDecoderTool;
121  std::unique_ptr<IndexMapTool> m_onlineChannelMapTool;
122 
123  // Processed event count.
124  unsigned int m_nproc =0;
125 
126  // Skipped event count.
127  unsigned int m_nskip =0;
128 
129 };
130 
132 
133 //**********************************************************************
134 
135 DataPrepModule::DataPrepModule(fhicl::ParameterSet const& pset) : EDProducer{pset} {
136  const Name myname = "DataPrepModule::ctor: ";
137  this->reconfigure(pset);
138  produces<std::vector<recob::Wire>>(m_WireName);
139  if ( m_DoAssns ) {
140  produces<art::Assns<raw::RawDigit, recob::Wire>>(m_WireName);
141  }
142  for ( string sname : m_IntermediateStates ) {
143  if ( m_LogLevel > 0 ) cout << myname << "Module will produce intermediate Wires with name " << sname << endl;
144  produces<std::vector<recob::Wire>>(sname);
145  }
146  //produces<std::vector<raw::RawDigit>>("dataprep");
147  if ( m_DecoderTool.size() ) {
148  if ( m_TimeStampName.size() ) {
149  if ( m_LogLevel > 0 ) {
150  cout << myname << "Module will produce RDTimeStamps with name " << m_TimeStampName << endl;
151  }
152  produces<std::vector<raw::RDTimeStamp>>(m_TimeStampName);
153  }
154  if ( m_OutputDigitName.size() ) {
155  if ( m_LogLevel > 0 ) {
156  cout << myname << "Module will produce digits with name " << m_OutputDigitName << endl;
157  }
158  produces<std::vector<raw::RawDigit>>(m_OutputDigitName);
159  }
160  //produces<std::vector<raw::RDStatus>>("dataprep");
161  }
162 }
163 
164 //**********************************************************************
165 
167 
168 //**********************************************************************
169 
171  const string myname = "DataPrepModule::reconfigure: ";
172  m_LogLevel = pset.get<int>("LogLevel");
173  m_DecoderTool = pset.get<Name>("DecoderTool");
174  m_DigitLabel = pset.get<Name>("DigitLabel", "daq");
175  m_TimeStampName = pset.get<Name>("TimeStampName");
176  m_OutputDigitName = pset.get<Name>("OutputDigitName");
177  m_WireName = pset.get<Name>("WireName", "");
178  m_DoAssns = pset.get<bool>("DoAssns");
179  m_DoGroups = pset.get<bool>("DoGroups");
180  m_ChannelRanges = pset.get<NameVector>("ChannelRanges");
181  m_BeamEventLabel = pset.get<string>("BeamEventLabel");
182  m_IntermediateStates = pset.get<vector<string>>("IntermediateStates");
183  pset.get_if_present<AdcChannel>("KeepChannelBegin", m_KeepChannelBegin);
184  pset.get_if_present<AdcChannel>("KeepChannelEnd", m_KeepChannelEnd);
185  pset.get_if_present<AdcChannelVector>("SkipChannels", m_SkipChannels);
186  pset.get_if_present<AdcChannelVector>("KeepFembs", m_KeepFembs);
187  pset.get_if_present<std::string>("OnlineChannelMapTool", m_OnlineChannelMapTool);
188 
189  size_t ipos = m_DigitLabel.find(":");
190  if ( ipos == std::string::npos ) {
192  } else {
193  m_DigitProducer = m_DigitLabel.substr(0, ipos);
194  m_DigitName = m_DigitLabel.substr(ipos + 1);
195  }
196 
198  if ( m_pChannelStatusProvider == nullptr ) {
199  cout << myname << "WARNING: Channel status provider not found." << endl;
200  }
201 
204 
205  if ( m_DecoderTool.size() ) {
208  if ( ! m_pDecoderTool ) {
209  cout << myname << "ERROR: Decoder tool not found: " << m_DecoderTool << endl;
210  }
211  }
212  if ( m_pDecoderTool ) {
213  cout << myname << "Raw digits will be obtained with decoder tool " << m_DecoderTool << endl;
214  } else {
215  cout << myname << "Raw digits will be obtained from event data store." << endl;
216  }
217 
218  if ( m_OnlineChannelMapTool.size() ) {
221  }
222 
223  if ( m_LogLevel >= 1 ) {
224  cout << myname << " LogLevel: " << m_LogLevel << endl;
225  cout << myname << " DecoderTool: " << m_DecoderTool << endl;
226  cout << myname << " DigitLabel: " << m_DigitLabel << " (" << m_DigitProducer
227  << ", " << m_DigitName << ")" << endl;
228  cout << myname << " TimeStampName: " << m_TimeStampName << endl;
229  cout << myname << " OutputDigitName: " << m_OutputDigitName << endl;
230  cout << myname << " WireName: " << m_WireName << endl;
231  cout << myname << " DoAssns: " << m_DoAssns << endl;
232  cout << myname << " DoGroups: " << m_DoGroups << endl;
233  cout << myname << " ChannelRanges: [";
234  bool first = true;
235  for ( Name rnam : m_ChannelRanges ) {
236  if ( first ) first = false;
237  else cout << ", ";
238  cout << rnam;
239  }
240  cout << "]" << endl;
241  cout << myname << " BeamEventLabel: " << m_BeamEventLabel << endl;
242  cout << myname << " IntermediateStates: [";
243  int count = 0;
244  for ( string sname : m_IntermediateStates ) cout << (count++ == 0 ? "" : " ") << sname;
245  cout << "]" << endl;
246  cout << myname << " OnlineChannelMapTool: " << m_OnlineChannelMapTool << endl;
247  cout << myname << " KeepChannelBegin: " << m_KeepChannelBegin << endl;
248  cout << myname << " KeepChannelEnd: " << m_KeepChannelEnd << endl;
249  cout << myname << " SkipChannels: " << "[";
250  first = true;
251  for ( AdcChannel ich : m_SkipChannels ) {
252  if ( first ) first = false;
253  else cout << ", ";
254  cout << ich;
255  }
256  cout << "]" << endl;
257  cout << myname << " KeepFembs: " << "[";
258  first = true;
259  for ( AdcChannel ifmb : m_KeepFembs ) {
260  if ( first ) first = false;
261  else cout << ", ";
262  cout << ifmb;
263  }
264  cout << "]" << endl;
265  }
266 }
267 
268 //**********************************************************************
269 
271  const string myname = "DataPrepModule::beginJob: ";
272  if ( m_LogLevel >= 2 ) cout << myname << "Starting job." << endl;
273  m_nproc = 0;
274  m_nskip = 0;
275 }
276 
277 //**********************************************************************
278 
280  const string myname = "DataPrepModule::endJob: ";
281  if ( m_LogLevel >= 1 ) {
282  cout << myname << "# events processed: " << m_nproc << endl;
283  cout << myname << " # events skipped: " << m_nskip << endl;
284  }
285 }
286 
287 //**********************************************************************
288 
290  const string myname = "DataPrepModule::produce: ";
291 
292  // Flag indicating that non-verbose info level messages should be logged.
293  bool logInfo = m_LogLevel >= 2;
294 
295  // Factor to convert event clock to ticks.
296  unsigned long triggerPerTick = 25;
297 
298  // Control flags.
299  bool skipAllEvents = false;
300  bool skipEventsWithCorruptDataDropped = false;
301 
302  // Decode the event time.
303  Timestamp beginTime = evt.time();
304  time_t itim = beginTime.timeHigh();
305  int itimrem = beginTime.timeLow();
306  // Older protoDUNE data has time in low field.
307  if ( itim == 0 && itimrem != 0 ) {
308  itimrem = itim;
309  itim = beginTime.timeLow();
310  }
311 
312  // Log event processing header.
313  if ( logInfo ) {
314  cout << myname << "Run " << evt.run();
315  if ( evt.subRun() ) cout << "-" << evt.subRun();
316  cout << ", event " << evt.event();
317  cout << ", nproc=" << m_nproc;
318  if ( m_nskip ) cout << ", nskip=" << m_nskip;
319  cout << endl;
320  if ( m_LogLevel >= 3 ) cout << myname << "Reading raw digits for producer, name: " << m_DigitProducer << ", " << m_DigitName << endl;
321  if ( evt.isRealData() ) {
322  TTimeStamp rtim(itim, itimrem);
323  string stim = string(rtim.AsString("s")) + " UTC";
324  cout << myname << "Real data event time: " << itim << " (" << stim << ")" << endl;
325  } else {
326  cout << myname << "Sim data event time: " << DuneTimeConverter::toString(beginTime) << endl;
327  }
328  }
329  if ( m_LogLevel >= 3 ) {
330  cout << myname << "Event time high, low: " << beginTime.timeHigh() << ", " << beginTime.timeLow() << endl;
331  }
332 
333  // Fetch the event trigger and timing clock.
334  AdcIndex trigFlag = 0;
335  AdcLongIndex timingClock = 0;
336  using TimeVector = std::vector<raw::RDTimeStamp>;
337  const TimeVector* ptims = nullptr;
338  if ( true ) {
339  art::InputTag itag1("timingrawdecoder", "daq");
340  auto htims = evt.getHandle<TimeVector>(itag1);
341  if ( htims ) {
342  ptims = &*htims;
343  if ( ptims->size() != 1 ) {
344  cout << myname << "WARNING: Unexpected timing clocks size: " << ptims->size() << endl;
345  for ( unsigned int itim=0; itim<ptims->size() && itim<50; ++itim ) {
346  cout << myname << " " << ptims->at(itim).GetTimeStamp() << endl;
347  }
348  } else {
349  const raw::RDTimeStamp& tim = ptims->at(0);
350  if ( logInfo ) cout << myname << "Timing clock: " << tim.GetTimeStamp() << endl;
351  timingClock = tim.GetTimeStamp();
352  // See https://twiki.cern.ch/twiki/bin/view/CENF/TimingSystemAdvancedOp#Reference_info
353  trigFlag = tim.GetFlags();
354  if ( m_LogLevel >= 2 ) cout << myname << "Trigger flag: " << trigFlag << " (";
355  bool isBeam = trigFlag == 0xc;
356  bool isCrt = trigFlag == 13;
357  bool isFake = trigFlag >= 0x8 && trigFlag <= 0xb;
358  if ( logInfo ) {
359  if ( isBeam ) cout << "Beam";
360  else if ( isCrt ) cout << "CRT";
361  else if ( isFake ) cout << "Fake";
362  else cout << "Unexpected";
363  cout << ")" << endl;
364  }
365  }
366  } else {
367  if ( logInfo ) {
368  cout << myname << "WARNING: Event timing clocks product not found." << endl;
369  }
370  }
371  }
372 
373  // If the decoder tool is used, use it to retrive the raw digits, their status
374  // and the channelclocks.
375  bool useDecoderTool = bool(m_pDecoderTool);
376  using StatVector = std::vector<raw::RDStatus>;
377  using DigitVector = std::vector<raw::RawDigit>;
378  std::unique_ptr<TimeVector> ptimsFromTool;
379  std::unique_ptr<StatVector> pstatsFromTool;
380  std::unique_ptr<DigitVector> pdigitsFromTool;
381  if ( useDecoderTool ) {
382  if ( useDecoderTool ) {
383  ptimsFromTool.reset(new TimeVector);
384  pstatsFromTool.reset(new StatVector);
385  pdigitsFromTool.reset(new DigitVector);
386  }
387  std::vector<int> apas = {-1};
388  if ( logInfo ) cout << myname << "Fetching digits and clocks with decoder tool." << endl;
389  int decodeStat = m_pDecoderTool->
390  retrieveDataForSpecifiedAPAs(evt, *pdigitsFromTool.get(), *ptimsFromTool.get(),
391  *pstatsFromTool.get(), apas);
392  if ( m_LogLevel >= 3 ) { // Decoder tool can return any value for success
393  cout << myname << "WARNING: Decoder tool returned " << decodeStat << endl;
394  }
395  if ( logInfo ) {
396  cout << myname << " Digit count from tool: " << pdigitsFromTool->size() << endl;
397  cout << myname << " Stats count from tool: " << pstatsFromTool->size() << endl;
398  cout << myname << " Clock count from tool: " << ptimsFromTool->size() << endl;
399  }
400  }
401 
402  // Fetch and check the channel clocks from the tool.
403  vector<AdcLongIndex> channelClocks;
404  vector<ULong64_t> tzeroClockCandidates; // Candidates for t0 = 0.
405  float trigTickOffset = -500.5;
406  if ( ptimsFromTool ) {
407  using ClockCounter = std::map<ULong64_t, AdcIndex>;
408  ClockCounter clockCounts;
409  ULong64_t chClock = 0;
410  long chClockDiff = 0;
411  float tickdiff = 0.0;
412  for ( raw::RDTimeStamp chts : *ptimsFromTool ) {
413  chClock = chts.GetTimeStamp();
414  channelClocks.push_back(chClock);
415  chClockDiff = chClock > timingClock ? (chClock - timingClock)
416  : -(timingClock - chClock);
417  bool nearTrigger = fabs(tickdiff - trigTickOffset) < 1.0;
418  tickdiff = chClockDiff/triggerPerTick;
419  if ( clockCounts.find(chClock) == clockCounts.end() ) {
420  clockCounts[chClock] = 1;
421  if ( nearTrigger ) tzeroClockCandidates.push_back(chClock);
422  } else {
423  ++clockCounts[chClock];
424  }
425  if ( ! nearTrigger ) {
426  if ( m_LogLevel >= 3 ) {
427  cout << myname << "WARNING: Channel timing difference: " << chClockDiff
428  << " (" << tickdiff << " ticks)." << endl;
429  }
430  }
431  }
432  if ( clockCounts.size() > 1 ) {
433  if ( logInfo ) {
434  cout << myname << "WARNING: Channel clocks are not consistent." << endl;
435  cout << myname << "WARNING: Clock ticks count" << endl;
436  }
437  for ( ClockCounter::value_type iclk : clockCounts ) {
438  ULong64_t chClock = iclk.first;
439  AdcIndex count = iclk.second;
440  long chClockDiff = chClock > timingClock ? (chClock - timingClock)
441  : -(timingClock - chClock);
442  float tickdiff = chClockDiff/triggerPerTick;
443  if ( logInfo ) {
444  cout << myname << "WARNING:" << setw(10) << chClockDiff << setw(10) << tickdiff
445  << setw(8) << count << endl;
446  }
447  }
448  } else {
449  if ( logInfo ) cout << myname << "Channel counts are consistent with an offset of "
450  << tickdiff << " ticks." << endl;
451  }
452  } else {
453  if ( logInfo ) cout << myname << "Channel clocks not checked for data retrieval from stroe." << endl;
454  }
455 
456  // Read the raw digit status.
457  const std::vector<raw::RDStatus>* pstats = nullptr;
458  if ( useDecoderTool ) {
459  pstats = pstatsFromTool.get();
460  } else {
462  auto hstats = evt.getHandle<std::vector<raw::RDStatus>>(itag2);
463  if ( hstats ) {
464  pstats = &*hstats;
465  } else {
466  if ( evt.isRealData() ) {
467  cout << myname << "WARNING: Raw data status product not found." << endl;
468  }
469  }
470  }
471 
472  // Check read status.
473  string srdstat;
474  bool skipEvent = skipAllEvents;
475  if ( pstats != nullptr ) {
476  if ( pstats->size() != 1 ) {
477  cout << myname << "WARNING: Unexpected raw data status size: " << pstats->size() << endl;
478  }
479  const RDStatus rdstat = pstats->at(0);
480  if ( false ) {
481  cout << myname << "Raw data status: " << rdstat.GetStatWord();
482  if ( rdstat.GetCorruptDataDroppedFlag() ) cout << " (Corrupt data was dropped.)";
483  if ( rdstat.GetCorruptDataKeptFlag() ) cout << " (Corrupt data was retained.)";
484  cout << endl;
485  }
486  cout << myname << "Raw data read status: " << std::to_string(rdstat.GetStatWord()) << endl;
487  srdstat = "rdstat=" + std::to_string(rdstat.GetStatWord());
488  skipEvent |= skipEventsWithCorruptDataDropped && rdstat.GetCorruptDataDroppedFlag();
489  }
490 
491  // Fetch beam information
492  float beamTof = 0.0; // Time of flight.
493  if ( m_BeamEventLabel.size() ) {
494  std::vector< art::Ptr<beam::ProtoDUNEBeamEvent> > beaminfo;
495  auto pdbeamHandle = evt.getHandle< std::vector<beam::ProtoDUNEBeamEvent> >(m_BeamEventLabel);
496  if ( pdbeamHandle ) {
497  art::fill_ptr_vector(beaminfo, pdbeamHandle);
498  if ( beaminfo.size() == 0 ) {
499  cout << myname << "WARNING: Beam event vector is empty." << endl;
500  } else {
501  if ( beaminfo.size() > 1 ) {
502  cout << myname << "WARNING: Beam event vector has size " << beaminfo.size() << endl;
503  }
504  AdcIndex beamTrigFlag = beaminfo[0]->GetTimingTrigger();
505  if ( beamTrigFlag != trigFlag ) {
506  if ( logInfo ) cout << myname << "Beam event and timing trigger flags differ: " << beamTrigFlag << " != " << trigFlag << endl;
507  } else if ( beamTrigFlag != 12 ) {
508  if ( logInfo ) cout << myname << "Beam event trigger is not beam: it is " << beamTrigFlag << endl;
509  //} else if ( ! beaminfo[0]->CheckIsMatched() ) {
510  // cout << myname << "Beam event is not matched." << endl;
511  } else if ( beaminfo[0]->GetTOFChan() == -1 ) {
512  if ( logInfo ) cout << myname << "Beam event index does not indicate match." << endl;
513  } else {
514  int beamChan = beaminfo[0]->GetTOFChan();
515  beamTof = beaminfo[0]->GetTOF();
516  if ( logInfo ) cout << myname << "Beam event TOF[" << beamChan << "]: " << beamTof << endl;
517  }
518  }
519  } else {
520  if ( logInfo ) cout << myname << "Beam event data product not found: " << m_BeamEventLabel << endl;
521  }
522  }
523 
524  // Read in the digits.
525  const DigitVector* pdigits = nullptr;
526  art::Handle<DigitVector> hdigits;
527  if ( useDecoderTool ) {
528  pdigits = pdigitsFromTool.get();
529  } else {
531  hdigits = evt.getHandle<DigitVector>(itag3);
532  pdigits = &*hdigits;
533  }
534  if ( m_LogLevel >= 3 ) {
535  cout << myname << "# digits read: " << pdigits->size() << endl;
536  }
537  if ( pdigits->size() == 0 ) mf::LogWarning("DataPrepModule") << "Input digit container is empty";
538 
539  // Create the container to hold the output wires.
540  std::unique_ptr<std::vector<recob::Wire>> pwires(new std::vector<recob::Wire>);
541  pwires->reserve(pdigits->size());
542 
543  // Create the association container.
544  std::unique_ptr<art::Assns<raw::RawDigit,recob::Wire>> passns(new art::Assns<raw::RawDigit,recob::Wire>);
545 
546  // If status was bad, skip this event.
547  // We store empty results to avoid exception.
548  // We have to have read digits to store those results (yech).
549  if ( skipEvent ) {
550  if ( logInfo ) cout << myname << "Skipping event with " << srdstat << endl;
551  evt.put(std::move(pwires), m_WireName);
552  if ( m_DoAssns ) evt.put(std::move(passns), m_WireName);
553  ++m_nskip;
554  return;
555  }
556 
557  // Prepare the intermediate state cache.
558  // Note that transient data is retained between groups and so most of the memory saving
559  // of groups is lost if intermediate states are recorded.
560  WiredAdcChannelDataMap* pintStates = nullptr;
561  if ( m_IntermediateStates.size() ) {
562  pintStates = new WiredAdcChannelDataMap(m_IntermediateStates, pdigits->size());
563  }
564 
565  // Create the transient data map and copy the digits there.
566  AdcChannelDataMap fulldatamap;
567  bool checkKeep = m_KeepChannelEnd > m_KeepChannelBegin;
568  unsigned int nkeep = 0;
569  unsigned int nskip = 0;
570  unsigned int ndigi = pdigits->size();
572  EventInfo* pevt = new EventInfo;
573  pevt->run = evt.run();
574  pevt->subRun = evt.subRun();
575  pevt->event = evt.event();
576  pevt->time = itim;
577  pevt->timerem = itimrem;
578  pevt->triggerClock = timingClock;
579  pevt->trigger = trigFlag;
580  AdcChannelData::EventInfoPtr pevtShared(pevt);
581  for ( unsigned int idig=0; idig<ndigi; ++idig ) {
582  const raw::RawDigit& dig = (*pdigits)[idig];
583  AdcChannel chan = dig.Channel();
584  if ( checkKeep ) {
585  if ( chan < m_KeepChannelBegin || chan >= m_KeepChannelEnd ) {
586  ++nskip;
587  continue;
588  }
589  }
590  if ( std::find(m_SkipChannels.begin(), m_SkipChannels.end(), chan) != m_SkipChannels.end() ) {
591  ++nskip;
592  continue;
593  }
594  if ( fulldatamap.find(chan) != fulldatamap.end() ) {
595  cout << myname << "WARNING: Skipping duplicate channel " << chan << "." << endl;
596  ++nskip;
597  continue;
598  }
599  // Fetch the channel status.
600  Index chanStat = AdcChannelStatusGood;
601  if ( m_pChannelStatusProvider != nullptr ) {
602  if ( m_pChannelStatusProvider->IsNoisy(chan) ) chanStat = AdcChannelStatusNoisy;
603  if ( m_pChannelStatusProvider->IsBad(chan) ) chanStat = AdcChannelStatusBad;
604  }
605  // Fetch the online ID.
607  AdcChannel fembChannel = AdcChannelData::badIndex();
608  if ( m_onlineChannelMapTool ) {
609  unsigned int ichOn = m_onlineChannelMapTool->get(chan);
610  if ( ichOn != IndexMapTool::badIndex() ) {
611  fembID = ichOn/128;
612  fembChannel = ichOn % 128;
613  }
614  }
615  if ( m_KeepFembs.size() ) {
616  if ( find(m_KeepFembs.begin(), m_KeepFembs.end(), fembID) == m_KeepFembs.end() ) {
617  continue;
618  ++nskip;
619  }
620  }
621  // Build the channel data.
622  AdcChannelData& acd = fulldatamap[chan];
623  acd.setEventInfo(pevtShared);
624  acd.setChannelInfo(chan, fembID, fembChannel, chanStat);
625  acd.digitIndex = idig;
626  acd.digit = &dig;
627  if ( channelClocks.size() > idig ) acd.channelClock = channelClocks[idig];
628  acd.metadata["ndigi"] = ndigi;
629  if ( m_BeamEventLabel.size() ) {
630  acd.metadata["beamTof"] = beamTof;
631  }
632  ++nkeep;
633  }
634 
635  // Create a vector of data maps with an entry for each group.
636  unsigned int nproc = 0;
637  vector<AdcChannelDataMap> datamaps;
638  if ( m_ChannelRanges.size() ) {
639  const IndexRangeTool* pcrt = nullptr;
640  string errmsg;
642  if ( ptm == nullptr ) {
643  errmsg = "Tool manager not found.";
644  } else {
645  pcrt = ptm->getShared<IndexRangeTool>("channelRanges");
646  if ( pcrt == nullptr ) errmsg = "Unable to find IndexRangeTool with name channelRanges.";
647  }
648  if ( pcrt == nullptr ) {
649  cout << myname << "ERROR: IndexRangeTool not found: channelRanges" << endl;
650  } else {
651  for ( Name crn : m_ChannelRanges ) {
652  IndexRange ran = pcrt->get(crn);
653  if ( ran.isValid() ) {
654  datamaps.emplace_back();
655  AdcChannelDataMap& datamap = datamaps.back();
656  for ( Index icha=ran.begin; icha<ran.end; ++icha ) {
657  if ( fulldatamap.find(icha) != fulldatamap.end() ) {
658  datamap.emplace(icha, move(fulldatamap[icha]));
659  }
660  ++nproc;
661  }
662  } else {
663  cout << myname << "WARNING: Channel range not found: " << crn << endl;
664  }
665  }
666  }
667  } else if ( m_DoGroups ) {
668  if ( m_pChannelGroupService == nullptr ) {
669  mf::LogError("DataPrepModule") << "Channel group service not found." << endl;
670  return;
671  }
672  unsigned int ngrp = m_pChannelGroupService->size();
673  for ( unsigned int igrp=0; igrp<ngrp; ++igrp ) {
674  datamaps.emplace_back();
675  AdcChannelDataMap& datamap = datamaps.back();
676  for ( AdcChannel chan : m_pChannelGroupService->channels(igrp) ) {
677  if ( fulldatamap.find(chan) != fulldatamap.end() ) {
678  datamap.emplace(chan, move(fulldatamap[chan]));
679  ++nproc;
680  }
681  }
682  }
683  } else {
684  datamaps.emplace_back(move(fulldatamap));
685  nproc = datamaps.front().size();
686  }
687  if ( logInfo ) {
688  cout << myname << " # input digits: " << ndigi << endl;
689  cout << myname << " # channels selected: " << nkeep << endl;
690  cout << myname << " # channels skipped: " << nskip << endl;
691  cout << myname << " # channels to be processed: " << nproc << endl;
692  }
693 
694  DuneEventInfo devt;
695  devt.run = evt.run();
696  devt.subRun = evt.subRun();
697  devt.event = evt.event();
698  devt.time = itim;
699  devt.timerem = itimrem;
700  devt.triggerClock = timingClock;
701  devt.triggerTick0 = timingClock/triggerPerTick;
702  int bstat = m_pRawDigitPrepService->beginEvent(devt);
703  if ( bstat ) cout << myname << "WARNING: Event initialization failed." << endl;
704 
705  auto const clockData = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(evt);
706  for ( AdcChannelDataMap& datamap : datamaps ) {
707 
708  Index nacd = datamap.size();
709  if ( nacd == 0 ) {
710  if ( m_LogLevel >= 3 ) {
711  if ( logInfo ) cout << myname << "Skipping empty data map." << endl;
712  }
713  continue;
714  }
715 
716  // Use the data preparation service to build the wires and intermediate states.
717  if ( m_LogLevel >= 3 ) {
718  cout << myname << "Preparing " << nacd << " channel" << (nacd == 1 ? "" : "s") << "." << endl;
719  }
720  int rstat = m_pRawDigitPrepService->prepare(clockData, datamap, pwires.get(), pintStates);
721  if ( rstat != 0 ) mf::LogWarning("DataPrepModule") << "Data preparation service returned error " << rstat;
722 
723  // Build associations between wires and digits.
724  if ( m_DoAssns && !useDecoderTool ) {
725  for ( const AdcChannelDataMap::value_type& iacd : datamap ) {
726  const AdcChannelData& acd = iacd.second;
727  AdcIndex idig = acd.digitIndex;
728  if ( idig == AdcChannelData::badIndex() )
729  throw art::Exception(art::errors::ProductRegistrationFailure) << "Digit index is not set.";
730  AdcIndex iwir = acd.wireIndex;
731  if ( iwir == AdcChannelData::badIndex() ) continue;
732  art::Ptr<raw::RawDigit> pdig(hdigits, idig);
733  bool success = util::CreateAssn(*this, evt, *pwires, pdig, *passns, m_WireName, iwir);
735  << "Can't associate wire " << iwir << " with raw digit " << idig;
736  }
737  }
738 
739  // Delete the entries from the current channel map.
740  // This is an easy way to clear the transient data.
741  datamap.erase(datamap.begin(), datamap.end());
742 
743  } // end loop over groups
744 
745  int estat = m_pRawDigitPrepService->endEvent(devt);
746  if ( estat ) cout << myname << "WARNING: Event finalization failed." << endl;
747 
748  if ( logInfo ) cout << myname << "Created wire count: " << pwires->size() << endl;
749  if ( pwires->size() == 0 ) mf::LogWarning("DataPrepModule") << "No wires made for this event.";
750 
751  // Record wires and associations in the event.
752  evt.put(std::move(pwires), m_WireName);
753  if ( m_DoAssns ) {
754  evt.put(std::move(passns), m_WireName);
755  }
756 
757  // Record decoder containers.
758  if ( useDecoderTool ) {
759  if ( m_TimeStampName.size() ) evt.put(std::move(ptimsFromTool), m_TimeStampName);
760  if ( m_OutputDigitName.size() ) evt.put(std::move(pdigitsFromTool), m_OutputDigitName);
761  //evt.put(std::move(pstatsFromTool), "dataprep");
762  }
763 
764  // Record intermediate state wires.
765  for ( string sname : m_IntermediateStates ) {
766  vector<Wire>* pintWires = pintStates->wires[sname];
767  if ( pintWires == nullptr ) {
768  cout << myname << "WARNING: Wires not found for state " << sname << "." << endl;
769  continue;
770  }
771  if ( logInfo ) {
772  cout << myname << "Recording intermediate state " << sname << " with "
773  << pintWires->size() << " channels." << endl;
774  }
775  if ( m_LogLevel >=3 ) {
776  for ( const Wire& wire : *pintWires ) {
777  cout << myname << " Channel " << wire.Channel() << " has "
778  << wire.SignalROI().n_ranges() << " ROI and "
779  << wire.SignalROI().count() << "/" << wire.SignalROI().size()
780  << " ticks." << endl;
781  }
782  }
783  std::unique_ptr<std::vector<recob::Wire>> pintWiresWrapped(pintWires);
784  evt.put(std::move(pintWiresWrapped), sname);
785  }
786 
787  ++m_nproc;
788  return;
789 }
virtual bool IsBad(raw::ChannelID_t channel) const =0
Returns whether the specified channel is bad in the current run.
LongIndex triggerTick0
Definition: DuneEventInfo.h:28
constexpr std::uint32_t timeLow() const
Definition: Timestamp.h:29
EventNumber_t event() const
Definition: DataViewImpl.cc:85
uint16_t GetFlags() const
Definition: RDTimeStamp.h:46
Collection of charge vs time digitized from a single readout channel.
Definition: RawDigit.h:69
virtual Index size() const =0
AdcChannelVector m_SkipChannels
const AdcIndex AdcChannelStatusNoisy
Definition: AdcTypes.h:48
static std::string toString(art::Timestamp tart)
Handle< PROD > getHandle(SelectorBase const &) const
Definition: DataViewImpl.h:382
std::string string
Definition: nybbler.cc:12
Index begin
Definition: IndexRange.h:34
virtual bool IsNoisy(raw::ChannelID_t channel) const =0
Returns whether the specified channel is noisy in the current run.
EDProducer(fhicl::ParameterSet const &pset)
Definition: EDProducer.h:20
constexpr std::uint32_t timeHigh() const
Definition: Timestamp.h:34
ChannelID_t Channel() const
DAQ channel this raw data was read from.
Definition: RawDigit.h:212
struct vector vector
std::vector< std::string > m_IntermediateStates
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
bool isValid() const
Definition: IndexRange.h:94
Index end
Definition: IndexRange.h:35
std::shared_ptr< const EventInfo > EventInfoPtr
const raw::RawDigit * digit
virtual int prepare(detinfo::DetectorClocksData const &clockData, AdcChannelDataMap &prepdigs, std::vector< recob::Wire > *pwires=nullptr, WiredAdcChannelDataMap *pwiredData=nullptr) const =0
std::vector< AdcChannel > AdcChannelVector
Definition: AdcTypes.h:51
bool GetCorruptDataDroppedFlag() const
Definition: RDStatus.h:31
void produce(art::Event &evt)
bool isRealData() const
void setChannelInfo(ChannelInfoPtr pchi)
virtual const ChannelVector & channels(Index igrp) const =0
Timestamp time() const
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:67
AdcChannelVector m_KeepFembs
Name m_DigitLabel
Full label for the input digit container, e.g. daq:
def move(depos, offset)
Definition: depos.py:107
T get(std::string const &key) const
Definition: ParameterSet.h:271
Framework includes.
void setEventInfo(EventInfoPtr pevi)
p
Definition: test.py:223
SubRunNumber_t subRun() const
Definition: DataViewImpl.cc:78
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
Definition: DataViewImpl.h:686
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
DataPrepModule(fhicl::ParameterSet const &pset)
Class providing information about the quality of channels.
RunNumber_t run() const
Definition: DataViewImpl.cc:71
unsigned int AdcIndex
Definition: AdcTypes.h:15
ULong64_t GetTimeStamp() const
Definition: RDTimeStamp.h:42
RawDigitPrepService * m_pRawDigitPrepService
Q_EXPORT QTSManip setw(int w)
Definition: qtextstream.h:331
std::map< Name, WireContainer * > wires
std::unique_ptr< PDSPTPCDataInterfaceParent > m_pDecoderTool
virtual int beginEvent(const DuneEventInfo &) const
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::unique_ptr< T > getPrivate(std::string name)
std::string m_OnlineChannelMapTool
unsigned long AdcLongIndex
Definition: AdcTypes.h:16
Name m_WireName
Second field in full label for the output wire container.
unsigned int AdcChannel
Definition: AdcTypes.h:50
static Index badIndex()
Definition: IndexMapTool.h:18
void reconfigure(fhicl::ParameterSet const &p)
std::optional< T > get_if_present(std::string const &key) const
Definition: ParameterSet.h:224
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
const AdcIndex AdcChannelStatusGood
Definition: AdcTypes.h:46
virtual int endEvent(const DuneEventInfo &) const
AdcLongIndex channelClock
Interface for experiment-specific channel quality info provider.
bool GetCorruptDataKeptFlag() const
Definition: RDStatus.h:32
Class holding the regions of interest of signal from a channel.
Definition: Wire.h:118
std::unique_ptr< IndexMapTool > m_onlineChannelMapTool
Declaration of basic channel signal object.
std::map< AdcChannel, AdcChannelData > AdcChannelDataMap
const AdcIndex AdcChannelStatusBad
Definition: AdcTypes.h:47
AdcIndex digitIndex
TCEvent evt
Definition: DataStructs.cxx:7
void fill_ptr_vector(std::vector< Ptr< T >> &ptrs, H const &h)
Definition: Ptr.h:297
Interface for experiment-specific service for channel quality info.
ChannelGroupService * m_pChannelGroupService
std::vector< Name > NameVector
AdcIndex wireIndex
if(!yymsg) yymsg
static Index badIndex()
int bool
Definition: qglobal.h:345
unsigned int GetStatWord() const
Definition: RDStatus.h:33
std::string to_string(ModuleType const mt)
Definition: ModuleType.h:34
static DuneToolManager * instance(std::string fclname="", int dbg=1)
DuneEventInfo EventInfo
std::string m_BeamEventLabel
T * getShared(std::string name)
QTextStream & endl(QTextStream &s)
LongIndex triggerClock
Definition: DuneEventInfo.h:27
const lariov::ChannelStatusProvider * m_pChannelStatusProvider
virtual IndexRange get(Name nam) const =0