All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DiscriminatePMTwaveforms_module.cc
Go to the documentation of this file.
1 /**
2  * @file DiscriminatePMTwaveforms_module.cc
3  * @brief Module producing discriminated waveforms.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date December 4, 2019
6  */
7 
8 
9 // ICARUS libraries
13 #include "icaruscode/PMT/Algorithms/OpDetWaveformMetaUtils.h" // OpDetWaveformMetaMaker
18 #include "icarusalg/Utilities/FHiCLutils.h" // util::fhicl::getOptionalValue()
19 
20 // LArSoft libraries
23 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
25 #include "lardataalg/Utilities/quantities_fhicl.h" // for ADCCounts_t parameters
27 #include "larcorealg/CoreUtils/values.h" // util::const_values()
30 #include "larcorealg/CoreUtils/StdUtils.h" // util::to_string()
31 
32 // framework libraries
33 #include "art/Framework/Core/ModuleMacros.h"
34 #include "art/Framework/Core/EDProducer.h"
35 #include "art/Framework/Principal/Event.h"
36 #include "art/Framework/Principal/Handle.h"
37 #include "art/Persistency/Common/PtrMaker.h"
38 #include "art/Utilities/make_tool.h"
39 #include "canvas/Persistency/Common/Assns.h"
40 #include "canvas/Persistency/Common/Ptr.h"
41 #include "canvas/Utilities/InputTag.h"
42 #include "cetlib_except/exception.h"
43 #include "messagefacility/MessageLogger/MessageLogger.h"
44 #include "fhiclcpp/types/OptionalSequence.h"
45 #include "fhiclcpp/types/OptionalAtom.h"
46 #include "fhiclcpp/types/Atom.h"
47 #include "fhiclcpp/types/DelegatedParameter.h"
48 #include "fhiclcpp/ParameterSet.h"
49 
50 // C/C++ standard libraries
51 #include <map>
52 #include <vector>
53 #include <string>
54 #include <cassert>
55 
56 
57 //------------------------------------------------------------------------------
58 namespace icarus::trigger { class DiscriminatePMTwaveforms; }
59 
60 /**
61  * @brief Produces discriminated optical waveforms.
62  *
63  * This module produces a "discriminated waveform" for each optical detector
64  * channel and for each configured threshold, via an algorithm of the class of
65  * `icarus::trigger::TriggerGateBuilder` (`TriggerGateBuilder` configuration
66  * parameter).
67  *
68  * Thresholds are ultimately chosen by the tool in charge of actually run the
69  * discrimination algorithm. Out of the thresholds that this algorithm produces,
70  * it is possible to choose only a subset of them (`SelectThresholds`).
71  *
72  *
73  * Output data products
74  * =====================
75  *
76  * * `std::vector<sbn::OpDetWaveformMeta>` parallel to the input optical
77  * detector waveforms, if `SavePMTcoverage` parameter is set; each entry in
78  * the collection is matched with the corresponding one in the input waveform
79  * collection; an association
80  * `art::Assns<sbn::OpDetWaveformMeta, raw::OpDetWaveform>` is also produced.
81  * * for each threshold _thr_ (in ADC counts), data products are created with
82  * an instance name equivalent to the threshold (e.g. for a threshold of 70
83  * ADC counts, the data product instance name will be `"70"`):
84  * * a data product of type
85  * `std::vector<icarus::trigger::OpticalTriggerGate::GateData_t>`,
86  * with one entry per optical channel, including _all_ optical channels
87  * (even when no signal above threshold is ever present); each gate object
88  * has as index in the vector the number of the optical channel;
89  * * an _art_ association, one trigger gate data to many optical waveforms,
90  * of each trigger gate data (as above) with all the optical waveforms
91  * which contributed to it; the order of the association pairs is the same
92  * as the one of the trigger gate data, i.e. by channel, and some trigger
93  * gate data entries may be not associated to any waveform and therefore
94  * they can not be listed in the association; association pairs within
95  * the same optical channel are sorted by optical waveform timestamp;
96  * the type of the association is
97  * `art::Assns<icarus::trigger::OpticalTriggerGate::GateData_t, raw::OpDetWaveform>`;
98  * similarly, if `SavePMTcoverage` parameter was set, also an association
99  * `art::Assns<icarus::trigger::OpticalTriggerGate::GateData_t, sbn::OpDetWaveformMeta>`
100  * is produced.
101  *
102  * Input data products
103  * ====================
104  *
105  * * `std::vector<raw::OpDetWaveform>`: a single waveform for each recorded
106  * optical detector activity; the activity belongs to a single channel, but
107  * there may be multiple waveforms on the same channel. The time stamp is
108  * expected to be from the
109  * @ref DetectorClocksElectronicsTime "electronics time scale"
110  * and therefore expressed in microseconds.
111  *
112  *
113  * Service requirements
114  * ---------------------
115  *
116  * The following services are _required_:
117  *
118  * * an implementation of `detinfo::DetectorClocksService`
119  * * _art_ message facility
120  *
121  *
122  * Configuration parameters
123  * =========================
124  *
125  * A terse description of the parameters is printed by running
126  * `lar --print-description DiscriminatePMTwaveforms`.
127  *
128  * * `OpticalWaveforms` (input tag): the data product containing all optical
129  * detector waveforms
130  * * `Baselines` (input tag): the data product containing one baseline per
131  * waveform in data product (from `OpticalWaveforms`)
132  * * `TriggerGateBuilder` (tool configuration): configuration of the _art_ tool
133  * used to discriminate the optional waveforms; the tool interface is
134  * `icarus::trigger::TriggerGateBuilder`.
135  * * `SavePMTcoverage` (flag, default: `true`): also produces a collection of
136  * `sbn::OpDetWaveformMeta` representing each of the input waveforms; trigger
137  * tools can use this information in place for the more space-hungry waveforms
138  * for further processing.
139  * * `OutputCategory` (string, default: `"DiscriminatePMTwaveforms"`): label
140  * for the category of messages in the console output; this is the label
141  * that can be used for filtering messages via MessageFacility service
142  * configuration.
143  * * `SelectThresholds` (sequence of ADC thresholds): if specified, only the
144  * waveforms discriminated with the thresholds in this list will be saved
145  * by the module; if not specified, all the thresholds produced by the
146  * algorithm will be saved. @note If a requested threshold is not eventually
147  * produced by the algorithm, an exception will be thrown by the module.
148  *
149  *
150  */
151 class icarus::trigger::DiscriminatePMTwaveforms: public art::EDProducer {
152 
153  public:
154 
155  /// The type of data produced for a single channel.
157 
158 
159  // --- BEGIN Configuration ---------------------------------------------------
160  struct Config {
161 
162  using Name = fhicl::Name;
163  using Comment = fhicl::Comment;
164 
165  fhicl::Atom<art::InputTag> OpticalWaveforms{
166  Name("OpticalWaveforms"),
167  Comment("label of input digitized optical waveform data product"),
168  "opdaq" // tradition demands
169  };
170 
171  fhicl::OptionalAtom<art::InputTag> Baselines {
172  Name("Baselines"),
173  Comment("label of input waveform baselines (parallel to the waveforms)")
174  };
175 
176  fhicl::OptionalAtom<float> Baseline {
177  Name("Baseline"),
178  Comment("constant baseline for all waveforms, in ADC counts")
179  };
180 
181  fhicl::DelegatedParameter TriggerGateBuilder_ {
182  Name("TriggerGateBuilder"),
183  Comment
184  ("parameters for generating trigger gates from optical channel output")
185  };
186 
187  fhicl::OptionalAtom<unsigned int> NChannels {
188  Name("NChannels"),
189  Comment("minimum number of channels to provide (default: all)")
190  };
191 
192  fhicl::Atom<bool> SavePMTcoverage {
193  Name("SavePMTcoverage"),
194  Comment("write also a sbn::OpDetWaveformMeta collection"),
195  true
196  };
197 
198  fhicl::Atom<std::string> OutputCategory {
199  Name("OutputCategory"),
200  Comment("tag of the module output to console via message facility"),
201  "DiscriminatePMTwaveforms"
202  };
203 
204  fhicl::OptionalSequence<raw::ADC_Count_t> SelectThresholds {
205  Name("SelectThresholds"),
206  Comment("thresholds to save (default: all those produced by algorithm)")
207  };
208 
209  }; // struct Config
210 
211  using Parameters = art::EDProducer::Table<Config>;
212  // --- END Configuration -----------------------------------------------------
213 
214 
215  // --- BEGIN Constructors ----------------------------------------------------
216  explicit DiscriminatePMTwaveforms(Parameters const& config);
217 
218  // Plugins should not be copied or assigned.
223 
224  // --- END Constructors ------------------------------------------------------
225 
226 
227  // --- BEGIN Framework hooks -------------------------------------------------
228 
229  /// Creates the data products.
230  virtual void produce(art::Event& event) override;
231 
232  // --- END Framework hooks ---------------------------------------------------
233 
234 
235  private:
236 
237  // --- BEGIN Configuration variables -----------------------------------------
238 
239  art::InputTag const fOpDetWaveformTag; ///< Input optical waveform tag.
240 
241  ///< Input waveform baseline tag.
242  std::optional<art::InputTag> const fBaselineTag;
243 
244  std::optional<float> const fBaseline; ///< A constant baseline level.
245 
246  unsigned int const fNOpDetChannels; ///< Number of optical detector channels.
247 
248  /// Thresholds selected for saving, and their instance name.
249  std::map<icarus::trigger::ADCCounts_t, std::string> fSelectedThresholds;
250 
251  bool const fSavePMTcoverage; ///< Whether to save also `sbn::OpDetWaveformMeta`.
252 
253  std::string const fLogCategory; ///< Category name for the console output stream.
254 
255  // --- END Configuration variables -------------------------------------------
256 
257 
258  // --- BEGIN Service variables -----------------------------------------------
259 
260  // --- END Service variables -------------------------------------------------
261 
262 
263  // --- BEGIN Algorithms ------------------------------------------------------
264 
265  /// Algorithms to simulate trigger gates out of optical channel output.
266  std::unique_ptr<icarus::trigger::TriggerGateBuilder> fTriggerGateBuilder;
267 
268  // --- END Algorithms --------------------------------------------------------
269 
270 
271  /**
272  * @brief Creates a collection with one gate per channel and no gaps.
273  * @param gates the trigger gates to be put in the collection
274  * @return a collection with with one gate per channel and no gaps
275  *
276  * The returned collection includes one gate per channel, and at least
277  * `fNOpDetChannels` channels (more if there are channels with higher number
278  * than that).
279  * For each channel, a gate is set in the item of the collection with index
280  * the channel ID (i.e. the first gate in the collection will be the one for
281  * channel `0`, the next the one for channel `1` and so on). It is assumed
282  * that there is only at most one gate per channel.
283  * The `gates` specified in the argument are _moved_ to the proper item in the
284  * returned collection. The other gates are assigned the proper channel number
285  * but are closed gates and associated with no waveform.
286  */
289 
290  /// Fetches the optical detector count from geometry unless in `param`.
291  static unsigned int getNOpDetChannels
292  (fhicl::OptionalAtom<unsigned int> const& param);
293 
294 }; // icarus::trigger::DiscriminatePMTwaveforms
295 
296 
297 
298 //------------------------------------------------------------------------------
299 //--- Implementation
300 //------------------------------------------------------------------------------
301 //--- icarus::trigger::DiscriminatePMTwaveforms
302 //------------------------------------------------------------------------------
304  (Parameters const& config)
305  : art::EDProducer(config)
306  // configuration
307  , fOpDetWaveformTag(config().OpticalWaveforms())
308  , fBaselineTag(util::fhicl::getOptionalValue(config().Baselines))
309  , fBaseline(util::fhicl::getOptionalValue(config().Baseline))
310  , fNOpDetChannels(getNOpDetChannels(config().NChannels))
311  , fSavePMTcoverage(config().SavePMTcoverage())
312  , fLogCategory(config().OutputCategory())
313  , fTriggerGateBuilder
314  (
315  art::make_tool<icarus::trigger::TriggerGateBuilder>
316  (config().TriggerGateBuilder_.get<fhicl::ParameterSet>())
317  )
318 {
319  //
320  // optional configuration parameters
321  //
322  if (fBaseline && fBaselineTag) {
323  throw art::Exception(art::errors::Configuration)
324  << "Both `Baselines` ('" << fBaselineTag->encode()
325  << "') and `Baseline` (" << *fBaseline
326  << ") parameters specified, but they are exclusive!\n";
327  }
328  if (!fBaseline && !fBaselineTag) {
329  throw art::Exception(art::errors::Configuration)
330  << "Either `Baselines` or `Baseline` parameters is required.\n";
331  }
332 
333  std::vector<raw::ADC_Count_t> selectedThresholds;
334  if (!config().SelectThresholds(selectedThresholds)) {
335  std::vector<ADCCounts_t> const& allThresholds
336  = fTriggerGateBuilder->channelThresholds();
337 
338  if (allThresholds.empty()) {
339  throw art::Exception(art::errors::Configuration)
340  << "Trigger building algorithm reports no threshold!\n"
341  << "Check the configuration of `TriggerGateBuilder` tool.\n";
342  }
344  allThresholds.begin(), allThresholds.end(),
345  std::back_inserter(selectedThresholds),
347  );
348 
349  }
350  else if (selectedThresholds.empty()) {
351  throw art::Exception(art::errors::Configuration)
352  << "Configured to save no thresholds!\n"
353  << "Add values to the `SelectThresholds` configuration parameter.\n";
354  }
355 
356  for (auto const& threshold: selectedThresholds) {
357  fSelectedThresholds[icarus::trigger::ADCCounts_t{threshold}]
358  = util::to_string(threshold);
359  }
360 
361  {
362  mf::LogInfo log(fLogCategory);
363  log << "Selected thresholds:";
364  for (auto const& [ threshold, instance ]: fSelectedThresholds)
365  log << " " << threshold << " (\"" << instance << "\")";
366  } // nameless block
367 
368  //
369  // declaration of input
370  //
371  consumes<std::vector<raw::OpDetWaveform>>(fOpDetWaveformTag);
372 
373  //
374  // declaration of output
375  //
376 
377  if (fSavePMTcoverage) {
378  produces<std::vector<sbn::OpDetWaveformMeta>>();
379  produces<art::Assns<raw::OpDetWaveform, sbn::OpDetWaveformMeta>>();
380  }
381  for (std::string const& instanceName: util::const_values(fSelectedThresholds))
382  {
383  produces<std::vector<TriggerGateData_t>>(instanceName);
384  produces<art::Assns<TriggerGateData_t, raw::OpDetWaveform>>(instanceName);
385  if (fSavePMTcoverage) {
386  produces<art::Assns<sbn::OpDetWaveformMeta, TriggerGateData_t>>
387  (instanceName);
388  }
389  } // for
390 
391 } // icarus::trigger::DiscriminatePMTwaveforms::DiscriminatePMTwaveforms()
392 
393 
394 //------------------------------------------------------------------------------
396 
397  //
398  // set up the algorithm to create the trigger gates
399  //
401  art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event)
402  };
404 
405  //
406  // fetch input
407  //
408  auto const& waveformHandle
409  = event.getValidHandle<std::vector<raw::OpDetWaveform>>(fOpDetWaveformTag);
410  auto const& waveforms = *waveformHandle;
411 
412  // map address of waveform to art pointer to that waveform
413  auto const& opDetWavePtrs
414  = util::mapDataProductPointers(event, waveformHandle);
415 
416  //
417  // retrieve the baseline information
418  //
419  std::vector<icarus::WaveformBaseline> fixedBaselines;
420  std::vector<icarus::WaveformBaseline> const* baselines = nullptr;
421  if (fBaselineTag) {
422  baselines =
423  &(event.getProduct<std::vector<icarus::WaveformBaseline>>(*fBaselineTag));
424  }
425  else {
426  fixedBaselines.resize
427  (waveforms.size(), icarus::WaveformBaseline{ *fBaseline });
428  baselines = &fixedBaselines;
429  }
430 
431  //
432  // provide each waveform with additional information: baseline
433  //
434  if (baselines->size() != waveforms.size()) {
435  assert(fBaselineTag);
436  throw cet::exception("DiscriminatePMTwaveforms")
437  << "Incompatible baseline information for the waveforms: "
438  << waveforms.size() << " waveforms (" << fOpDetWaveformTag.encode()
439  << ") for " << baselines->size() << " baselines ("
440  << fBaselineTag->encode() << ")!\n";
441  }
442  std::vector<icarus::trigger::WaveformWithBaseline> waveformInfo;
443  waveformInfo.reserve(waveforms.size());
444  for (auto const& [ waveform, baseline ]: util::zip(waveforms, *baselines))
445  waveformInfo.emplace_back(&waveform, &baseline);
446 
447  {
448  mf::LogDebug log { fLogCategory };
449  log << "Discrimination of " << waveforms.size() << " PMT waveforms from '"
450  << fOpDetWaveformTag.encode() << "'";
451  if (fBaselineTag)
452  log << " with baselines from '" << fBaselineTag->encode() << "'";
453  }
454 
455 
456  //
457  // define channel-level trigger gate openings as function on threshold
458  //
459 
460  // this is a collection where each entry (of type `TriggerGates`) contains
461  // the complete set of trigger gates for an event.
462  std::vector<icarus::trigger::TriggerGateBuilder::TriggerGates> const&
463  triggerGatesByThreshold = fTriggerGateBuilder->build(waveformInfo);
464 
465  { // nameless block
466  mf::LogTrace log(fLogCategory);
467  log << "Trigger gates from " << triggerGatesByThreshold.size()
468  << " thresholds:\n";
469  for (auto const& triggerGates: triggerGatesByThreshold)
470  triggerGates.dump(log);
471 
472  } // nameless block
473 
474 
475  //
476  // prepare output
477  //
478  std::optional<art::PtrMaker<sbn::OpDetWaveformMeta>> const makePMTinfoPtr
480  ? std::optional<art::PtrMaker<sbn::OpDetWaveformMeta>>(event)
481  : std::nullopt
482  ;
483 
485  : triggerGatesByThreshold
486  ) {
487 
488  ADCCounts_t const thr = gates.threshold();
489 
490  //
491  // find the threshold and its label, if we care of it
492  //
493  auto iThr = fSelectedThresholds.find(thr);
494  if (iThr == fSelectedThresholds.end()) continue; // not interested
495 
496  std::string const& instanceName = iThr->second;
497  art::PtrMaker<TriggerGateData_t> const makeGatePtr(event, instanceName);
498 
499  //
500  // reformat the results for the threshold
501  //
502  auto [ discrGates, waveGateAssns ]
504  (fillChannelGaps(std::move(gates).gates()), makeGatePtr, opDetWavePtrs)
505  ;
506 
507  if (fSavePMTcoverage) {
508  // replica of discriminated gate-waveform association replacing the latter
509  // with the PMT coverage with the same index as the waveform
510  assert(makePMTinfoPtr);
511  art::Assns<sbn::OpDetWaveformMeta, TriggerGateData_t> assns;
512  for (auto [ gatePtr, wavePtr ]: waveGateAssns)
513  assns.addSingle((*makePMTinfoPtr)(wavePtr.key()), gatePtr);
514  event.put(
515  std::make_unique<art::Assns<sbn::OpDetWaveformMeta, TriggerGateData_t>>
516  (std::move(assns)),
517  instanceName
518  );
519  } // if save PMT coverage
520 
521  //
522  // move the reformatted data into the event
523  //
524  event.put(
525  std::make_unique<std::vector<TriggerGateData_t>>(std::move(discrGates)),
526  instanceName
527  );
528  event.put(
529  std::make_unique<art::Assns<TriggerGateData_t, raw::OpDetWaveform>>
530  (std::move(waveGateAssns)),
531  instanceName
532  );
533 
534  } // for all extracted thresholds
535 
536 
537  // add a simple one-to-one PMT coverage - waveform association just in case
538  if (fSavePMTcoverage) {
539  assert(makePMTinfoPtr);
540 
541  sbn::OpDetWaveformMetaMaker const makePMTinfo { detTimings };
542 
543  std::vector<sbn::OpDetWaveformMeta> PMTinfo;
544  art::Assns<raw::OpDetWaveform, sbn::OpDetWaveformMeta> assns;
545  art::PtrMaker<raw::OpDetWaveform> const makeWavePtr
546  { event, waveformHandle.id() };
547 
548  for (auto const& [ iWaveform, waveform ]: util::enumerate(waveforms)) {
549 
550  PMTinfo.push_back(makePMTinfo(waveform));
551 
552  assns.addSingle(makeWavePtr(iWaveform), (*makePMTinfoPtr)(iWaveform));
553 
554  } // for
555 
556  event.put
557  (std::make_unique<std::vector<sbn::OpDetWaveformMeta>>(std::move(PMTinfo)));
558  event.put(
559  std::make_unique<art::Assns<raw::OpDetWaveform, sbn::OpDetWaveformMeta>>
560  (std::move(assns))
561  );
562 
563  } // if save PMT coverage
564 
565 
566 } // icarus::trigger::DiscriminatePMTwaveforms::produce()
567 
568 
569 //------------------------------------------------------------------------------
573 {
574 
575  using GateDataColl_t
577  using Gate_t = GateDataColl_t::value_type; // TrackedOpticalTriggerGate
578 
579  //
580  // fill a map channel -> gate (missing channels have a nullptr gate)
581  //
582  std::vector<Gate_t const*> gateMap(fNOpDetChannels, nullptr);
583  for (Gate_t const& gate: gates) {
584  assert(!gate.channels().empty());
585 
586  auto const channel = gate.channels().front();
587  if (static_cast<std::size_t>(channel) >= gateMap.size())
588  gateMap.resize(channel + 1U, nullptr);
589  assert(gateMap[channel] == nullptr);
590  gateMap[channel] = &gate;
591 
592  } // for all gates
593 
594  //
595  // fill
596  //
597  GateDataColl_t allGates;
598  allGates.reserve(gateMap.size());
599  for (auto const& [ channelNo, gate ]: util::enumerate(gateMap)) {
600 
601  if (gate) {
602  assert(gate->channels().front() == channelNo);
603  allGates.push_back(std::move(*gate));
604  }
605  else {
606  allGates.emplace_back(
608  );
609  }
610 
611  } // for
612 
613  return allGates;
614 } // icarus::trigger::DiscriminatePMTwaveforms::fillChannelGaps()
615 
616 
617 //------------------------------------------------------------------------------
619  (fhicl::OptionalAtom<unsigned int> const& param)
620 {
621  unsigned int nChannels;
622  return
623  param(nChannels)? nChannels: lar::providerFrom<geo::Geometry>()->NOpDets();
624 } // icarus::trigger::DiscriminatePMTwaveforms::getNOpDetChannels()
625 
626 
627 //------------------------------------------------------------------------------
629 
630 
631 //------------------------------------------------------------------------------
Produces discriminated optical waveforms.
Definition of util::zip().
Utilities related to art service access.
Writes a collection of sbn::OpDetWaveformMeta from PMT waveforms.
unsigned int const fNOpDetChannels
Number of optical detector channels.
Utilities for the conversion of trigger gate data formats.
std::optional< typename Optional::value_type > getOptionalValue(Optional const &parameter)
Returns the value of an optional parameter as std::optional.
Definition: FHiCLutils.h:188
static constexpr Sample_t transform(Sample_t sample)
std::optional< float > const fBaseline
A constant baseline level.
Definition of util::enumerate().
Algorithm to produce trigger gates out of optical readout waveforms.
std::unique_ptr< icarus::trigger::TriggerGateBuilder > fTriggerGateBuilder
Algorithms to simulate trigger gates out of optical channel output.
bool const fSavePMTcoverage
Whether to save also sbn::OpDetWaveformMeta.
Derivative information from raw::OpDetWaveform data.
std::vector< icarus::trigger::OpticalTriggerGateData_t > transformIntoOpticalTriggerGate(Gates &&gates)
Returns the trigger gates in serializable format.
decltype(auto) const_values(Coll &&coll)
Range-for loop helper iterating across the constant values of the specified collection.
const std::string instance
constexpr value_t value() const
Returns the value of the quantity.
Definition: quantities.h:609
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
Interface to detinfo::DetectorClocks.
std::string const fLogCategory
Category name for the console output stream.
fhicl::OptionalSequence< raw::ADC_Count_t > SelectThresholds
fDetProps &fDetProps fDetProps &fDetProps fLogCategory
icarus::trigger::TriggerGateBuilder::TriggerGates::GateData_t fillChannelGaps(icarus::trigger::TriggerGateBuilder::TriggerGates::GateData_t gates) const
Creates a collection with one gate per channel and no gaps.
Container of logical gates for all triggering channels for a threshold.
Logical multi-level gate associated to one or more readout channels.
art::InputTag const fOpDetWaveformTag
Input optical waveform tag.
Utilities to read and write quantities in FHiCL configuration.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
A value measured in the specified unit.
Definition: quantities.h:566
Simple type definitions for trigger algorithms.
A trigger gate data object for optical detector electronics.
BEGIN_PROLOG baseline
static unsigned int getNOpDetChannels(fhicl::OptionalAtom< unsigned int > const &param)
Fetches the optical detector count from geometry unless in param.
BEGIN_PROLOG vertical distance to the surface Name
physics producers discrimopdaq OpticalWaveforms
Converter from raw::OpDetWaveform into sbn::OpDetWaveformMeta.
virtual void produce(art::Event &event) override
Creates the data products.
A class exposing an upgraded interface of detinfo::DetectorClocksData.
Functions pulling in STL customization if available.
Class containing a waveform baseline value.
DataProductPointerMap_t< ArtHandleData_t< Handle > > mapDataProductPointers(art::Event const &event, Handle const &handle)
Creates a map from address of data product element to art pointer to it.
std::map< icarus::trigger::ADCCounts_t, std::string > fSelectedThresholds
Thresholds selected for saving, and their instance name.
Simple helper functions to deal with FHiCL.
Sample_t fBaseline
Waveform baseline [ADC counts].
auto zip(Iterables &&...iterables)
Range-for loop helper iterating across many collections at the same time.
Definition: zip.h:295
fDetProps &fDetProps fDetProps &fDetProps detTimings
Definition of util::values() and util::const_values().
DiscriminatePMTwaveforms & operator=(DiscriminatePMTwaveforms const &)=delete
OpticalTriggerGateData_t GateData_t
Type for gate data access.
art framework interface to geometry description
Utilities to map data pointer elements to their art::Ptr.