All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TriggerEfficiencyPlotsBase.h
Go to the documentation of this file.
1 /**
2  * @file icaruscode/PMT/Trigger/TriggerEfficiencyPlotsBase.h
3  * @brief Base class for _art_modules plotting trigger efficiencies.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date March 30, 2020
6  */
7 
8 #ifndef ICARUSCODE_PMT_TRIGGER_TRIGGEREFFICIENCYPLOTSBASE_H
9 #define ICARUSCODE_PMT_TRIGGER_TRIGGEREFFICIENCYPLOTSBASE_H
10 
11 
12 // ICARUS libraries
25 #include "icaruscode/Utilities/DetectorClocksHelpers.h" // makeDetClockData()
27 #include "icarusalg/Utilities/ChangeMonitor.h" // ThreadSafeChangeMonitor
29 
30 // LArSoft libraries
32 #include "lardataalg/DetectorInfo/DetectorTimingTypes.h" // simulation_time, ...
34 #include "lardataalg/Utilities/quantities/spacetime.h" // microseconds, ...
35 #include "lardataalg/Utilities/quantities/energy.h" // gigaelectronvolt, ...
36 #include "lardataalg/Utilities/intervals_fhicl.h" // microseconds from FHiCL
41 #include "larcoreobj/SimpleTypesAndConstants/geo_types.h" // geo::CryostatID
42 
43 // framework libraries
44 #include "art_root_io/TFileDirectory.h"
45 #include "art/Framework/Core/ConsumesCollector.h"
46 #include "art/Framework/Principal/Event.h"
47 #include "canvas/Persistency/Provenance/EventID.h"
48 #include "canvas/Utilities/InputTag.h"
49 #include "fhiclcpp/types/Sequence.h"
50 #include "fhiclcpp/types/Atom.h"
51 #include "fhiclcpp/types/OptionalAtom.h"
52 
53 // ROOT libraries
54 #include "TTree.h"
55 #include "TH1.h"
56 #include "TH2.h"
57 #include "TEfficiency.h"
58 
59 // C/C++ standard libraries
60 #include <iosfwd> // std::ostream
61 #include <algorithm> // std::transform
62 #include <atomic>
63 #include <unordered_map>
64 #include <map>
65 #include <vector>
66 #include <array>
67 #include <string>
68 #include <optional>
69 #include <functional> // std::function<>, std::reference_wrapper<>
70 #include <memory> // std::unique_ptr
71 #include <utility> // std::forward(), std::pair<>, std::move()
72 #include <limits> // std::numeric_limits
73 #include <cstddef> // std::size_t
74 
75 
76 //------------------------------------------------------------------------------
77 namespace icarus::trigger {
78 
79  using namespace util::quantities::time_literals; // ""_ns ...
80 
81  class TriggerEfficiencyPlotsBase;
82 
83 } // icarus::trigger
84 
85 
86 //------------------------------------------------------------------------------
87 namespace icarus::trigger::details {
88 
89  struct PlotInfoTree;
90 
91  class TriggerPassCounters;
92  std::ostream& operator<<
93  (std::ostream& out, TriggerPassCounters const& counters);
94 
95 } // namespace icarus::trigger::details
96 
97 
98 //------------------------------------------------------------------------------
99 /// Tracks pass rate by discrimination threshold and trigger pattern name.
101 
102  public:
103  using Threshold_t = std::string;
104 
105  /// Type used as counter for a specific trigger.
107 
108  using IndexPair_t = std::pair<std::size_t, std::size_t>;
109 
110  /// Represents the index of a threshold or pattern that is not registered.
111  static constexpr std::size_t NoIndex
112  = std::numeric_limits<std::size_t>::max();
113 
114  /**
115  * @brief Creates and returns a new counter.
116  * @return the specified counter
117  *
118  * If the counter already exists, it is returned.
119  */
120  IndexPair_t create
121  (Threshold_t const& threshold, std::string const& patternName);
122 
123 
124  // @{
125  /// Returns the counter for the specified threshold and pattern.
126  /// @throw std::out_of_range if not registered.
127 
128  Counter_t const& counter
129  (Threshold_t const& threshold, std::string const& patternName) const;
130  Counter_t const& counter
131  (std::size_t threshold, std::string const& patternName) const;
132  Counter_t const& counter
133  (Threshold_t const& threshold, std::size_t patternName) const;
134  Counter_t const& counter
135  (std::size_t threshold, std::size_t patternName) const;
136  Counter_t const& counter(IndexPair_t indices) const;
137 
138  Counter_t const& operator()
139  (Threshold_t const& threshold, std::string const& patternName) const
140  { return counter(threshold, patternName); }
141  Counter_t const& operator()
142  (std::size_t threshold, std::string const& patternName) const
143  { return counter(threshold, patternName); }
144  Counter_t const& operator()
145  (Threshold_t const& threshold, std::size_t patternName) const
146  { return counter(threshold, patternName); }
147  Counter_t const& operator()
148  (std::size_t threshold, std::size_t patternName) const
149  { return counter(threshold, patternName); }
150  Counter_t const& operator() (IndexPair_t indices) const
151  { return counter(indices); }
152 
153  Counter_t& counter
154  (Threshold_t const& threshold, std::string const& patternName);
155  Counter_t& counter(std::size_t threshold, std::string const& patternName);
156  Counter_t& counter(Threshold_t const& threshold, std::size_t patternName);
157  Counter_t& counter(std::size_t threshold, std::size_t patternName);
158  Counter_t& counter(IndexPair_t indices);
159 
160  Counter_t& operator()
161  (Threshold_t const& threshold, std::string const& patternName)
162  { return counter(threshold, patternName); }
163  Counter_t& operator() (std::size_t threshold, std::string const& patternName)
164  { return counter(threshold, patternName); }
165  Counter_t& operator() (Threshold_t const& threshold, std::size_t patternName)
166  { return counter(threshold, patternName); }
167  Counter_t& operator() (std::size_t threshold, std::size_t patternName)
168  { return counter(threshold, patternName); }
169  Counter_t& operator() (IndexPair_t indices) { return counter(indices); }
170 
171  // @}
172 
173  // @{
174  /// Returns whether the specified threshold is registered.
175  bool hasThreshold(Threshold_t const& threshold) const;
176  bool hasThreshold(std::size_t index) const;
177  // @}
178 
179  //@{
180  /// Returns whether the specified pattern is registered.
181  bool hasPattern(std::string const& patternName) const;
182  bool hasPattern(std::size_t patternIndex) const;
183  //@}
184 
185  /// Returns the index of the specified threshold (`max()` if not registered).
186  std::size_t thresholdIndex(Threshold_t const& threshold) const;
187 
188  /// Returns the index of the specified pattern (`max()` if not registered).
189  std::size_t patternIndex(std::string const& patternName) const;
190 
191  /// Returns the value of the threshold with the specified `index`.
192  /// @throw std::out_of_range if the index is not available
193  Threshold_t const& threshold(std::size_t index) const;
194 
195  /// Returns the name of the pattern with the specified `index`.
196  /// @throw std::out_of_range if the index is not available
197  std::string const& patternName(std::size_t index) const;
198 
199  /// Returns the number of thresholds currently registered.
200  std::size_t nThresholds() const;
201 
202  /// Returns the number of patterns currently registered.
203  std::size_t nPatterns() const;
204 
205  /// Dump all the counters on the specified stream.
206  void dump(std::ostream& out) const;
207 
208  private:
209 
210  /// All counters; indices: [threshold][pattern]
211  std::vector<std::vector<Counter_t>> fCounters;
212 
213  /// Map: threshold -> threshold index.
214  std::unordered_map<Threshold_t, std::size_t> fThresholdIndex;
215 
216  /// Map: pattern name -> pattern index.
217  std::unordered_map<std::string, std::size_t> fPatternIndex;
218 
219  /// Registers a new threshold in the index and returns its index (unchecked).
220  std::size_t registerThreshold(Threshold_t const& threshold);
221 
222  /// Registers a new pattern in the index and returns its index (unchecked).
223  std::size_t registerPattern(std::string const& name);
224 
225 }; // icarus::trigger::details::TriggerPassCounters
226 
227 
228 // --- BEGIN -- ROOT tree helpers ----------------------------------------------
229 /**
230  * @brief Class managing the serialization of plot information in a simple ROOT
231  * tree.
232  *
233  * The tree is supplied by the caller.
234  * This object will create the proper branches into the tree and assign
235  * addresses to them. Then it will assume they will stay assigned.
236  *
237  * On `assign()`, the branch addresses are assigned the values from the
238  * arguments. The tree is not `Fill()`-ed.
239  *
240  * The tree structure is:
241  * `InPlots/O`,
242  * with a single branch per element.
243  *
244  * Branches:
245  * * `InPlots` (bool): the event was _not_ filtered out before plotting
246  * (it may still belong to no category and eventually appear in no plot)
247  *
248  */
250 
251  /// Creates the required branches and assigns addresses to them.
252  PlotInfoTree(TTree& tree);
253 
254  /**
255  * @brief Fills the information of the specified event.
256  * @param inPlots whether this event is plotted (as opposed to filtered out)
257  */
258  void assign(bool inPlots);
259 
260  Bool_t fInPlots;
261 
262 }; // struct icarus::trigger::details::PlotInfoTree
263 
264 
265 // --- END -- ROOT tree helpers ------------------------------------------------
266 
267 
268 //------------------------------------------------------------------------------
269 /**
270  * @brief Helper class to produce plots about trigger simulation and trigger
271  * efficiency.
272  * @see icarus::trigger::MajorityTriggerEfficiencyPlots
273  *
274  * This helper class provides the foundation for writing a module producing sets
275  * of plots based on trigger primitives given in input.
276  *
277  * The following documentation mainly deals with the most standard configuration
278  * and operations in ICARUS. Modules made with this helper and the modules
279  * upstream of them in data processing have quite some knobs that can be
280  * manipulated to test unorthodox configurations.
281  *
282  * An example of module implemented with this class is
283  * `icarus::trigger::MajorityTriggerEfficiencyPlots`.
284  *
285  *
286  * Overview of trigger simulation steps
287  * =====================================
288  *
289  * This simulation only trigger primitives derived from the optical detector
290  * via hardware (V1730B boards).
291  * The trigger simulation branches from the standard simulation of optical
292  * detector waveforms (`icarus::SimPMTIcarus` module).
293  * From there, multiple steps are needed.
294  *
295  * 1. Produce single-PMT-channel discriminated waveforms: the discrimination
296  * threshold can be chosen ("ADC threshold" or just "threshold" in the
297  * following), and the result is one binary discriminated waveform that
298  * has value `0` when the waveform is under threshold and `1` when it's
299  * above threshold, with the same time discretization as the PMT waveform.
300  * Each discriminated waveform spans the whole event readout time and
301  * therefore it may merge information from multiple readout waveforms
302  * (`raw::OpDetWaveform`), but all from the same optical detector channel.
303  * This step can be performed with the module
304  * `icarus::trigger::DiscriminatePMTwaveforms`.
305  * 2. Combine the discriminated waveforms in pairs, in the same fashion as the
306  * V1730B readout board does to produce LVDS output. The output of this step
307  * is roughly half as many discriminated outputs as there were from the
308  * previous step (some channels are not paired). This output will be called
309  * _trigger primitives_ because it is what the trigger logics is based on.
310  * We say that a trigger primitive is "on" when its level is `1`.
311  * This step can be performed with the module `icarus::trigger::LVDSgates`.
312  * 3. Simulate the trigger logic based on the trigger primitives _(see below)_.
313  * This usually includes the requirement of coincidence with the beam gate.
314  *
315  * Trigger logic may be complex, being implemented in a FPGA.
316  * Many options are available, including:
317  *
318  * * coincidence of a minimum number of trigger primitives: the event is trigger
319  * if at least _N_ trigger primitives are on at the same time;
320  * * sliding window: primitives are grouped depending on their location, and
321  * there is a requirement on the minimum number of primitives in "on" level
322  * within one or more of these groups. For example, any sliding window of 30
323  * channels (corresponding to 16 trigger primitives in standard ICARUS PMT
324  * readout installation) has to contain at least 10 trigger primitives "on"
325  * at the same time; or there must be two sliding windows with that condition;
326  * etc. Sliding windows can be obtained from further processing of the LVDS
327  * trigger primitives, for example with the module
328  * `icarus::trigger::SlidingWindowTrigger`.
329  *
330  * This class is expected to support modules implementing different trigger
331  * logics.
332  *
333  *
334  * Data objects for discriminated waveforms
335  * -----------------------------------------
336  *
337  * @anchor TriggerEfficiencyPlotsBase_Data
338  *
339  * A discriminated waveform is the information whether the level of a waveform
340  * is beyond threshold, as function of time.
341  * A discriminated waveform may be binary, i.e. with only levels `0` and `1`
342  * based on a single threshold, or with multiple levels.
343  * Also the numerical _addition_ of two binary discriminated waveforms
344  * yields a multi-level waveform (in fact, three levels -- `0`, `1` and `2`).
345  *
346  * We represent this data in the forms of "events": an event is a change of
347  * level happening at a certain time. The class holding this information,
348  * `icarus::trigger::TriggerGateData`, covers the whole time, starting with a
349  * ground level `0`. The next event will be a "opening" that increases the
350  * level, usually to `1`. Other changing events may follow, and typically the
351  * last one will bring the level back to `0`.
352  *
353  * This information is joined by a list of _channel numbers_ in order to
354  * represent a discriminated waveform e.g. from the optical detector.
355  * There may be one or more channels associated to a discriminated waveform,
356  * but for us there should always be at least one.
357  * The discriminated waveforms from PMT readout (`raw::OpDetWaveform`) are
358  * associated to a single channel, while LVDS trigger primitives are most often
359  * associated to two channels (some channels are not paired and will have only
360  * one channel). A sliding window will have as many channels as the PMT it
361  * covers. The global trigger should have _all_ channels, while in ICARUS each
362  * of the two discriminated wabeforms from a cryostat should have half the
363  * channels.
364  * This information is represented in the class
365  * `icarus::trigger::ReadoutTriggerGate`, which inherits from
366  * `icarus::trigger::TriggerGateData`.
367  * This class is generic and can hold any representation for the time of the
368  * level changing events, for the levels, and for the identifiers of the
369  * channels. ICARUS specifies a data type for each of these quantities, and
370  * the resulting `icarus::trigger::ReadoutTriggerGate` class instance is called
371  * `icarus::trigger::OpticalTriggerGateData_t`.
372  *
373  * @note The class `icarus::trigger::OpticalTriggerGateData_t` is the one that
374  * gets written to disk in the _art_ ROOT files.
375  * That is not a class by itself, but rather an alias of
376  * `icarus::trigger::ReadoutTriggerGate`, and many coding tools will call
377  * it in the latter way.
378  *
379  * It is often convenient to track for each trigger gate object which input
380  * contributed to it, both in terms of channels and of single waveforms.
381  * The list of channels is embedded in `icarus::trigger::ReadoutTriggerGate`,
382  * while the list of source waveforms is not. An additional wrapper object,
383  * `icarus::trigger::TrackedOpticalTriggerGate`, contains a trigger gate proper
384  * (`icarus::trigger::ReadoutTriggerGate`) and a list of pointers to the source
385  * waveforms. In most of the code the source is represented by metadata
386  * (`sbn::OpDetWaveformMeta`) rather than the full waveforms
387  * (`raw::OpDetWaveform`) so that the bulk of the data is not necessary for the
388  * vast majority of the uses, and it can be dropped.
389  *
390  * Utilities are available to manage the serialization of
391  * `icarus::trigger::TrackedOpticalTriggerGate` objects
392  * (`icaruscode/PMT/Trigger/Utilities/TriggerDataUtils.h`), which is implemented
393  * as a trigger gate collection and a association object
394  *
395  * There are utilities available in
396  * `icaruscode/PMT/Trigger/Utilities/TriggerDataUtils.h` that can convert them
397  * into a collection of `icarus::trigger::OpticalTriggerGateData_t` objects
398  * plus a collection of _art_ associations (for writing), and the other way
399  * around (for reading). Additional utilities allow to bridge between
400  * the waveform metadata and their original waveforms
401  * (`icaruscode/PMT/Trigger/Utilities/OpDetWaveformMetaMatcher.h`), which is
402  * needed when a producer utilising the metadata and combining trigger gates
403  * wants to save associations not only of the gates with the metadata,
404  * but also with the original waveforms. The module `icarus::trigger::LVDSgates`
405  * uses all of them and can be used as an illustration of the functionality.
406  *
407  * A module is provided, called `icarus::trigger::DumpTriggerGateData`, which
408  * dumps on screen or on text file the information from a collection of
409  * discriminated waveforms in a (sort-of) human readable format.
410  * An example configuration for this module is provided in `icaruscode`, called
411  * `dump_triggergatedata_icarus.fcl`.
412  *
413  * The main functions to manipulate the trigger gates are defined in the very
414  * base class, `icarus::trigger::TriggerGateData`: these allow e.g. to find
415  * events and query the level at a given time.
416  * Another important set of features is also present in
417  * `icarus::trigger::TriggerGateData` and replicated in the higher levels:
418  * the combination of trigger gates by sum (`OR`), multiplication (_AND_),
419  * minimum and maximum value.
420  *
421  * @note Combining a multi-level gate via `Min()` with a binary gate results
422  * into a binary gate which is logic AND of the two gates.
423  *
424  *
425  * On the terminology
426  * -------------------
427  *
428  * In this documentation, the "discriminated waveforms" are sometimes called
429  * "trigger gates" and sometimes "trigger primitives".
430  * Although these concepts are, strictly, different, usually the difference
431  * does not affect the meaning and they end up being exchanged carelessly.
432  *
433  *
434  * Trigger logic algorithm
435  * ========================
436  *
437  * @anchor TriggerEfficiencyPlotsBase_Algorithm
438  *
439  * The trigger logic algorithm is completely absent from this helper, and it is
440  * entirely delegated to the derived classes (`simulateAndPlot()`). There are
441  * nevertheless a lot of functions that may help to process the input trigger
442  * primitives and fill some standard plots. Many of them are listed in the
443  * documentation of `simulateAndPlot()`.
444  *
445  *
446  * Event categories
447  * =================
448  *
449  * Each event is assigned to a set of categories, and its information
450  * contributes to the plots of all those categories.
451  * The categories are passed to the helper in the `initializePlots()` call to
452  * create all the plots to be filled later.
453  * A default list of categories is provided as `DefaultPlotCategories`.
454  *
455  *
456  * Module usage
457  * =============
458  *
459  * The following aspects are common to all modules based on this helper.
460  *
461  *
462  * Input data products
463  * --------------------
464  *
465  * This module uses the following data products as input:
466  *
467  * * trigger primitives:
468  * * `std::vector<icarus::trigger::OpticalTriggerGateData_t>` (labels out of
469  * `TriggerGatesTag` and `Thresholds`): full sets of discriminated
470  * waveforms, each waveform possibly covering multiple optical channels,
471  * and their associations to optical waveforms. One set per threshold;
472  * note that these are converted into `InputTriggerGate_t` data type for
473  * internal use;
474  * * associations with `raw::OpDetWaveform` (currently superfluous);
475  * * event characterization:
476  * * `std::vector<simb::MCTruth>`: generator information (from
477  * `GeneratorTags`; multiple generators are allowed at the same time);
478  * it is used mostly to categorize the type of event (background,
479  * weak charged current, electron neutrino, etc.);
480  * * `std::vector<simb::MCParticle>`: particles propagating in the detector
481  * (from `PropagatedParticles`); currently not used;
482  * * `std::vector<sim::SimEnergyDeposit>`: energy deposited in the active
483  * liquid argon volume (from `EnergyDepositTags`); it is used to
484  * quantify the energy available to be detected in the event.
485  *
486  *
487  * Output plots
488  * -------------
489  *
490  * @anchor TriggerEfficiencyPlotsBase_Plots
491  *
492  * The module produces a standard set of plots for each configured ADC threshold
493  * and for each event category.
494  * The plots are saved via _art_ service `TFileService` in a ROOT file and they
495  * are organized in nested ROOT directories under the module label directory
496  * which is assigned by _art_:
497  *
498  * * `Thr###` (outer level) describes the ADC threshold on the discriminated
499  * waveforms: the threshold is `###` from the baseline;
500  * * `<Category>` (inner level) describes the category of events included in
501  * the plots (e.g. `All`, `NuCC`; see `PlotCategories`).
502  *
503  * Each of the inner ROOT directories contains a full set of plots, whose name
504  * is the standard plot name followed by its event category and threshold
505  * (e.g. `Eff_NuCC_Thr15` for the trigger efficiency plot on neutrino charged
506  * current events with 15 ADC counts as PMT threshold).
507  *
508  * Each set of plots, defined in
509  * `icarus::trigger::TriggerEfficiencyPlots::initializePlotSet()`
510  * (and, within, `initializeEventPlots()`
511  * and `initializeEfficiencyPerTriggerPlots()`), is contributed only by the
512  * events in the set category.
513  *
514  * There are different "types" of plots. Some
515  * @ref TriggerEfficiencyPlotsBase_SelectionPlots "do not depend on triggering at all",
516  * like the deposited energy distribution. Others
517  * @ref TriggerEfficiencyPlotsBase_MultiTriggerPlots "cross different trigger definitions",
518  * like the trigger efficiency as function of trigger requirement. Others still
519  * @ref TriggerEfficiencyPlotsBase_SingleTriggerPlots "assume a single trigger definition":
520  * this is the case of trigger efficiency plots versus energy. Finally, there are
521  * @ref TriggerEfficiencyPlotsBase_SingleTriggerResponsePlots "plots that depend on a specific trigger definition and outcome":
522  * this is the case of all the plots including only triggering or non-triggering
523  * events.
524  *
525  * A list of plots follows for each plot type.
526  * All the plots are always relative to a specific optical detector channel
527  * threshold (ADC) and a broad event category.
528  *
529  *
530  * ### Plots independent of the triggers (including selection plots)
531  *
532  * @anchor TriggerEfficiencyPlotsBase_SelectionPlots
533  *
534  * These plots are stored directly in a threshold/category folder:
535  *
536  * * `EnergyInSpill`: total energy deposited in the detector during the time the
537  * beam gate is open. It is proportional to the amount of scintillation light
538  * in the event;
539  * * `EnergyInSpillActive`: energy deposited in the active volume of the
540  * detector during the time the beam gate is open; the active volume is
541  * defined as the union of all TPC drift voulmes;
542  * * plots specific to neutrino interactions (if the event is not a neutrino
543  * interaction, it will not contribute to them); if not otherwise specified,
544  * only the first neutrino interaction in the event is considered:
545  * * `InteractionType`: code of the interaction type, as in
546  * `sim::TruthInteractionTypeName`;
547  * * `NeutrinoEnergy`: generated energy of the interacting neutrino;
548  * * `LeptonEnergy`: generated energy of the lepton out of the _first_
549  * neutrino interaction;
550  * * `InteractionVertexYZ`: coordinates of the location of all interactions
551  * in the event, in world coordinates, projected on the anode plane.
552  * * `ActivePMT`: the channels contributing to the trigger; a channel is added
553  * to this plot if it belongs to a gate (LVDS output) which during the beam
554  * gate it is beyond threshold at least once (note that in case of LVDS OR
555  * combination, a channel will appear in this plot even if it is not beyond
556  * threshold if the one paired with it is beyond threshold);
557  * this plot depends on the discrimination threshold.
558  *
559  *
560  * @note In fact, these plots _usually_ do not even depend on the ADC threshold
561  * of the optical detector channels. Nevertheless, they are stored in the
562  * folders under specific thresholds, and they are duplicate.
563  *
564  *
565  * ### Plots including different trigger requirements
566  *
567  * @anchor TriggerEfficiencyPlotsBase_MultiTriggerPlots
568  *
569  * These plots collect information from scenarios with different trigger
570  * requirements, but still with the same underlying optical detector channel
571  * ADC threshold.
572  * No plots are provided in this category by `TriggerEfficiencyPlotsBase` at
573  * the moment. Implementing modules can add plots by overriding the method
574  * `initializePlotSet()`:
575  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
576  * void MyTriggerEfficiencyPlots::initializePlotSet
577  * (PlotSandbox& plots, std::vector<SettingsInfo_t> const& settings) const
578  * {
579  * // (inherited)
580  * helper().TriggerEfficiencyPlotsBase::initializePlotSet(plots, settings);
581  *
582  * // ... add more plot definitions, e.g.
583  * plots.make<TEfficiency>(
584  * "Eff",
585  * "Efficiency of triggering;requested primitives;trigger efficiency",
586  * settings.size(), 0, settings.size()
587  * );
588  *
589  * } // MyTriggerEfficiencyPlots::initializePlotSet()
590  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
591  *
592  *
593  * ### Plots depending on a specific trigger definition
594  *
595  * @anchor TriggerEfficiencyPlotsBase_SingleTriggerPlots
596  *
597  * The following plots depend on the full definition of the trigger, including
598  * PMT thresholds _and_ other requirements.
599  * They are hosted each in a subfolder of the threshold/category folder, with
600  * a name encoding the requirement: `ReqXX` for trigger with minimum required
601  * primitives `XX`.
602  *
603  * * `EffVsEnergyInSpill`: trigger efficiency as function of the total energy
604  * deposited during the beam gate.
605  * * `EffVsEnergyInSpillActive`: trigger efficiency as function of the energy
606  * deposited in the TPC active volumes during the beam gate.
607  * * `EffVsNeutrinoEnergy`, `EffVsLeptonEnergy`: trigger efficiency as function
608  * of the true energy of the first interacting neutrino, and of the outgoing
609  * lepton in the final state of the interaction, respectively.
610  * * `TriggerTick`: time of the earliest trigger, in ticks. Only triggering
611  * events contribute.
612  * * `TriggerTime`: the time (relative to the nominal beam gate opening) of the
613  * "main" trigger (the earliest in the triggering window). Only triggering
614  * events contribute.
615  * * `OpeningTimes`: the time (relative to the nominal beam gate opening) of
616  * all the times the trigger requirements were satisfied (limited to the
617  * time interval where the trigger emulation is performed). Only triggering
618  * events contribute.
619  *
620  * The parameters are defined in the same way as in the
621  * @ref TriggerEfficiencyPlotsBase_SelectionPlots "selection plots", unless stated
622  * otherwise.
623  *
624  *
625  * ### Plots depending on a specific trigger definition and response
626  *
627  * @anchor TriggerEfficiencyPlotsBase_SingleTriggerResponsePlots
628  *
629  * These plots depend on the trigger definition, as the ones in the previous
630  * type, and on the actual trigger response.
631  * They are hosted each in a subfolder of the threshold/category/requirement
632  * folder, with a name encoding the response: `triggering` for triggering
633  * events, `nontriggering` for the others.
634  *
635  * Their event pool is filtered to include only the events in the current
636  * category which also pass, or do not pass, the trigger requirement.
637  *
638  * The plots are:
639  * * `EnergyInSpill`, `EnergyInSpillActive`, `InteractionType`,
640  * `NeutrinoEnergy`,`LeptonEnergy`, `InteractionVertexYZ`:
641  * these are defined in the same way as the
642  * @ref TriggerEfficiencyPlotsBase_SelectionPlots "selection plots"
643  *
644  *
645  * Configuration parameters
646  * =========================
647  *
648  * @anchor TriggerEfficiencyPlotsBase_Configuration
649  *
650  * A terse description of the parameters is printed by running
651  * `lar --print-description TriggerEfficiencyPlots`.
652  *
653  * * `TriggerGatesTag` (string, mandatory): name of the module
654  * instance which produced the trigger primitives to be used as input;
655  * it must not include any instance name, as the instance names will be
656  * automatically added from `Thresholds` parameter.
657  * The typical trigger primitives used as input may be LVDS discriminated
658  * output (e.g. from `icarus::trigger::LVDSgates` module) or combinations
659  * of them (e.g. from `icarus::trigger::SlidingWindowTrigger` module).
660  * * `Thresholds` (list of tags, mandatory): list of the discrimination
661  * thresholds to consider. A data product containing a
662  * digital signal is read for each one of the thresholds, and the tag of the
663  * data product is expected to be the module label `TriggerGatesTag` with as
664  * instance name the value of the threshold (e.g. for a threshold of `"60"`
665  * ADC counts the data product tag might be `LVDSgates:60`).
666  * * `GeneratorTags` (list of input tags, default: `[ generator ]`): a list of
667  * data products containing the particles generated by event generators;
668  * if empty, plots or categories requiring truth information will be
669  * omitted;
670  * * `DetectorParticleTag` (input tag, default: `largeant`): data product
671  * containing the list of particles going through the argon in the detector;
672  * * `EnergyDepositTags`
673  * (list of input tags, default: `[ "largeant:TPCActive" ]`): a list of
674  * data products with energy depositions; if empty, plots or categories
675  * requiring energy deposition information will be omitted; in alternative,
676  * `EnergyDepositSummaryTag` can be specified with the same purpose;
677  * * `EnergyDepositSummaryTag` (input tags, optional): if specified, overrides
678  * `EnergyDepositTags` and uses for the energy deposition the information
679  * from the summary in the specified data product; such summary may be
680  * created for example by `ExtractEnergyDepositionSummary` module;
681  * * `BeamGateDuration` (time, _mandatory_): the duration of the beam
682  * gate; _the time requires the unit to be explicitly specified_: use
683  * `"1.6 us"` for BNB, `9.5 us` for NuMI (also available as
684  * `BNB_settings.spill_duration` and `NuMI_settings.spill_duration` in
685  * `trigger_icarus.fcl`);
686  * * `BeamGateStart` (time, default: `0_us`): how long after the
687  * * @ref DetectorClocksBeamGateOpening "nominal beam gate opening time"
688  * the actual beam gate opens at;
689  * * `PreSpillWindow` (time, default: `10_us`): a pre-spill window is defined
690  * to observe the activity before the beam gate that might leak into the
691  * latter; this parameter regulates how long that window last; its position
692  * can be tweaked with the `PreSpillWindowGap` parameter;
693  * * `PreSpillWindowGap` (time, default: `0_us`): the delay from the _end_ of
694  * the pre-spill window and the start of the beam gate (`BeamGateStart`);
695  * by default, the pre-spill window immediately precedes the beam gate;
696  * negative values of the gap allow the pre-spill window to overlap
697  * (or to be after) the beam gate; the duration of the pre-spill window is
698  * set via `PreSpillWindow` parameter;
699  * * `TriggerTimeResolution` (time, default: `8 ns`): time resolution for the
700  * trigger primitives;
701  * * `EventTreeName` (optional string): if specified, a simple ROOT tree is
702  * created with the information from each event (see `EventInfoTree` for
703  * its structure);
704  * * `EventDetailsLogCategory` (optional string): if specified, information for
705  * each single event is output into the specified stream category; if
706  * the string is specified empty, the default module stream is used, as
707  * determined by `LogCategory` parameter;
708  * * `PlotOnlyActiveVolume` (flag, default: `true`): if set, only events within
709  * TPC active volume are plot; the check is performed on the generated
710  * location of the neutrino interactions (if any); events with no neutrino
711  * interactions are always plotted;
712  * * `LogCategory` (string, default `TriggerEfficiencyPlots`): name of category
713  * used to stream messages from this module into message facility.
714  *
715  * An example job configuration is provided as `maketriggerplots_icarus.fcl`.
716  *
717  *
718  * Technical description of the module
719  * ====================================
720  *
721  * The modules based on this helper read
722  * @ref TriggerEfficiencyPlotsBase_Data "trigger gate data products" from
723  * different ADC thresholds, and for each threshold they combine the data into a
724  * trigger response depending on a ADC threshold.
725  * Then they apply different trigger settings and for each one they fill plots.
726  *
727  * All the input sets (each with its own ADC treshold) are treated independently
728  * from each other.
729  *
730  * Each event is assigned to event categories. These categories do not depend on
731  * trigger definition nor primitives. For example, a electron neutrino neutral
732  * current interaction event would be assigned to the neutral current neutrino
733  * interaction category, to the electron neutrino category, and so on.
734  * A set of plot is produced at once for each of the event categories.
735  *
736  * This module is designed as follows:
737  *
738  * * each _art_ event is treated independently from the others (this is the
739  * norm; method: `process()`, to be called in module's `analyze()`);
740  * * information for the plots which do not depend on the trigger primitives
741  * are extracted once per event (method: `extractEventInfo()`);
742  * * the event is assigned its categories (method: `selectedPlotCategories()`,
743  * with the categories defined at the time of `initializePlots()` call);
744  * * for each input primitive set (i.e. for each ADC threshold):
745  * * trigger logic is applied, the beam gate is imposed, a trigger result
746  * is extracted and plots are filled; all is done in the method
747  * `simulateAndPlot()` provided by the derived module.
748  *
749  * Note that the plots depending on the response may require multiple fillings.
750  * For example, a trigger efficiency plot as function of the trigger settings
751  * is a single plot in the plot set which requires a filling for every
752  * trigger setting.
753  * In a similar fashion, the plot of trigger time requires one filling for
754  * each requirement level that is met.
755  *
756  *
757  * Organization of the plots
758  * --------------------------
759  *
760  * @anchor TriggerEfficiencyPlotsBase_OrganizationOfPlots
761  *
762  * Plots are written on disk via the standard _art_ service `TFileService`,
763  * which puts them in a ROOT subdirectory named as the instance of this module
764  * being run.
765  *
766  * As described above, there are two "dimensions" for the plot sets: there is
767  * one plot set for each ADC threshold and for each event category, the total
768  * number of plot sets being the product of the options in the two dimensions.
769  *
770  * The code is structured to work by threshold by threshold, because the trigger
771  * response depends on the threshold but not by the event category: the response
772  * is computed once per threshold, then all the plots related to that response
773  * (including all the event categories) are filled.
774  *
775  * The structure in the file reflects this logic, and there are two levels of
776  * ROOT directories inside the one assigned by _art_ to this module:
777  * * the outer level pins down the ADC threshold of the plots inside it;
778  * the name of the directory follows the pattern `Thr###` (### being the ADC
779  * threshold), which is the "threshold tag";
780  * * the inner level is the category of events included in the plots, and the
781  * name of the directories reflect the name of the category as defined in
782  * the corresponding `PlotCategory` object (`PlotCategory::name()`); this
783  * defines the "category tag".
784  *
785  * In each inner directory, a complete set of plots is contained.
786  * The name of each plot is a base name for that plot (e.g. `Eff` for the
787  * efficiency plot) with the event category tag and the threshold tag appended
788  * (separated by an underscore character, `"_"`). The title of the plot is also
789  * modified to include the description of the plot category (as defined in
790  * `PlotCategory::description()`) and the ADC threshold.
791  * Therefore, within the same module directory, all plot names are different.
792  *
793  *
794  * Adding a plot
795  * --------------
796  *
797  * When adding a plot, two actions are necessary:
798  *
799  * 1. initialize the new plot
800  * 2. fill the new plot
801  *
802  * The initialization happens in
803  * `icarus::trigger::TriggerEfficiencyPlots::initializePlotSet()` method.
804  * A request must be issued to the
805  * @ref TriggerEfficiencyPlotsBase_PlotSandboxes "plot sandbox" to "make" the
806  * plot.
807  * In general it can be expected that all the arguments `args` in a call
808  * `plots.make<PlotType>(args)` are forwarded to the constructor of `PlotType`,
809  * so that to make a new `PlotType` object one has to consult only the
810  * constructor of that class. Be aware though that the library expects the first
811  * argument to be the ROOT name of the new object and the second to be its ROOT
812  * title.
813  * It is possible to work around this requirement with additional coding.
814  *
815  * The method performing the plotting is `simulateAndPlot()`.
816  * The plots should be filled inside loops going through all plot sets.
817  * The existing code already does that in two loops, one for the plots
818  * depending on the trigger response requirement, and the other for the plots
819  * _not_ depending on it.
820  *
821  *
822  * ### About plot sandboxes
823  *
824  * @anchor TriggerEfficiencyPlotsBase_PlotSandboxes
825  *
826  * For the sake of this module, a plot sandbox is an object similar to a ROOT
827  * `TDirectory`, which can mangle the objects it contains to change ("process")
828  * their name and title, and that interacts properly with `art::TFileDirectory`
829  * so make `TFileService` happy.
830  * The processing of the name and title is used to add the category and
831  * threshold tags to the plot ROOT name and the corresponding annotations to
832  * the plot title, as described
833  * @ref TriggerEfficiencyPlotsBase_OrganizationOfPlots "above".
834  *
835  *
836  * Adding an event category
837  * -------------------------
838  *
839  * @anchor TriggerEfficiencyPlotsBase_AddingCategory
840  *
841  * Event categories are specified to `initializePlots()` call: each category is
842  * described by a simple object `PlotCategory` which contains a name (used in
843  * ROOT directories, plot name tags and to univocally identify the category),
844  * a description (used in plot titles) and a condition for the event to fulfill
845  * in order to qualify for the category. The condition is a function object
846  * that accepts an `EventInfo_t` object with the relevant event information,
847  * and returns its decision (`true` if the event belongs to this category).
848  *
849  * To add a category, it is enough to add an entry in the collection of plot
850  * categories passed to `initializePlots()`. The `DefaultPlotCategories` list
851  * can be used as a starting point.
852  *
853  * The condition function adjudicates based on the information in `EventInfo_t`.
854  * It is likely though that if a new category is needed, the information
855  * currently available in `EventInfo_t` is not enough to decide the response.
856  * In that case, `EventInfo_t` must be extended to hold the newly required
857  * information. In addition, the method `extractEventInfo()` must be modified
858  * to set the new information. The documentation of that method expands on this
859  * topic.
860  *
861  *
862  * Usage of the helper
863  * ====================
864  *
865  * An example of how to turn this helper class in a full blown _art_ module is
866  * `icarus::trigger::MajorityTriggerEfficiencyPlots`.
867  *
868  *
869  * Changing the trigger logic
870  * ---------------------------
871  *
872  * The trigger logic is required to be coded in `simulateAndPlot()` of the
873  * derived class. Some details on implementing it can be found in the
874  * documentation of the method itself.
875  *
876  * To implement a trigger logic, several components need to be coordinated:
877  *
878  * 1. combination of trigger primitives;
879  * 2. the data structure the combination is stored in;
880  * 3. interpretation of that data structure in terms of trigger firing
881  * (which we call here "trigger settings");
882  * 4. configuration of the trigger logic from user parameters.
883  *
884  * A module may simulate a trigger which counts the number of primitives that
885  * are "on" and imposing a required minimum on that number for the trigger to
886  * fire. This is a possible implementation including those elements:
887  *
888  * 1. combination of trigger primitives: primitives are summed into a single
889  * multilevel gate (with beam gate on top);
890  * 2. the data structure the combination is stored in: a
891  * @ref TriggerEfficiencyPlotsBase_Data "trigger gate object";
892  * 3. interpretation of that data structure in terms of trigger firing:
893  * the logic requires a minimum number of primitives being on at the same
894  * time; the interpretation uses the level of the combined trigger gate as
895  * the number of primitives on at every time, and decides that the first
896  * time this number meets the requirement, the trigger fires;
897  * 4. configuration of the trigger logic from user parameters:
898  * it's a parameter of the module itself (`MinimumPrimitives`).
899  *
900  * An example of how a different trigger logic could be implemented following
901  * a similar model: let's assume we want a trigger based on two sliding windows.
902  * A window is a group of LVDS signals from neighboring channels. We can split
903  * the whole optical detector channels into many windows, and we can make the
904  * windows overlap: for example, a window includes the first 30 channels behind
905  * one anode plane, the second window includes 30 channels starting from the
906  * fifteenth, the third window includes 30 channels starting from the thirtieth,
907  * and so on. In ICARUS, 30 channels are served in 16 LVDS discriminated
908  * waveforms, i.e. 16 trigger primitives. We may require as a loose trigger
909  * that any window contains at least 10 primitives on at the same time (that is
910  * about 20 PMT channels beyond ADC threshold), and as a tighter trigger that
911  * there is a window with at least 8 trigger primitives on, _and_ the
912  * corresponding window in the opposite TPC has at least 6 primitives on
913  * at the same time. Note that a splitting 7/7 won't do: one of the two windows
914  * must have 8 or more primitives on.
915  * The input primitives from the point of view of the module now become the
916  * "sliding window" combination of the LVDS trigger primitives, as produced e.g.
917  * by `icarus::trigger::SlidingWindowTrigger` module.
918  * How this can be implemented following the pattern of this module:
919  *
920  * 1. combination of trigger primitives: we prepare two primitives:
921  * one describes the maximum level among all the windows, and the other
922  * describes the level of the window opposite to the maximum (the way to
923  * achieve this is quite complicate);
924  * 2. the data structure the combination is stored in: two
925  * @ref TriggerEfficiencyPlotsBase_Data "trigger gate objects";
926  * 3. interpretation of that data structure in terms of trigger firing:
927  * for the loose trigger, we look for the first time the maximum window level
928  * reaches the designated threshold; for the tighter trigger, some
929  * additional logic is required, discriminating the maximum window level
930  * primitive to the higher threshold, the opposite window level on the lower
931  * threshold, and setting them in coincidence; then the time the resulting
932  * gate opens, if any, is the trigger time;
933  * 4. configuration of trigger logic parameters: the two requirements (single
934  * window, double window with their minimum number of LVDS primitives)
935  * are read from the module FHiCL configuration; for computing efficiency,
936  * either in the constructor or in a `beginJob()` method we may also prepare
937  * the associations (pairing) between opposite windows or just channels;
938  *
939  * @todo add ability to discriminate a trigger gate object?
940  * discrimination on level _N_ (>=N -> 1, <N -> 0) can be obtained with
941  * adding a _-N_ uniform level, flooring on level 0 and (if needed) maxing
942  * on level 1.
943  *
944  *
945  * Code style: quantities with units
946  * ==================================
947  *
948  * To avoid issues with missing or wrong conversions, this code often uses
949  * LArSoft quantities library. A variable with a `Quantity` type is represented
950  * with a specific unit (e.g. microseconds) and can undergo only limited
951  * manipulation. The allowed manipulation should guarantee that the unit of
952  * the quantity is correctly preserved. For example, it is not possible to
953  * add to a `microseconds` interval a pure number (e.g. `9.0`), but rather
954  * it is only possible to add time quantities (e.g. another `microseconds`
955  * variable, or a `nanoseconds` variable, or a literal value with unit, like
956  * `9.0_ns`), and those quantities are properly converted, with the caveat that
957  * rounding errors may happen that a more careful explicit handling could avoid.
958  * Also, there are two types of variables that can feature the same unit,
959  * intervals and points. A point can't be scaled (e.g. you can't "double" the
960  * time the beam gate opens, while you can double the beam gate _duration_)
961  * and it can't be added to another point (the difference between two points
962  * is an interval).
963  *
964  * To avoid mistakes in the conversion between different time scales, the
965  * LArSoft utility library `detinfo::DetectorTimings` is used, which is a
966  * wrapper of `DetectorClocks` service provider that makes the interface to
967  * convert times easier and uniform. Here we use it to convert time points
968  * from the simulation (which are expressed in nanoseconds and are starting
969  * at trigger time) into optical detector readout ticks, and vice versa.
970  * The values returned by this library have encoded in them which time scale
971  * they belong to, and in which unit they are measured.
972  *
973  */
975 
976  // no serviceable part for anyone except derived classes
977 
978  protected:
979 
982 
983  // --- BEGIN Configuration ---------------------------------------------------
984  struct Config {
985 
986  using Name = fhicl::Name;
987  using Comment = fhicl::Comment;
988 
989  fhicl::Sequence<art::InputTag> GeneratorTags {
990  Name("GeneratorTags"),
991  Comment("labels of the event generators"),
992  std::vector<art::InputTag>{ "generator" }
993  };
994 
995  fhicl::Atom<art::InputTag> DetectorParticleTag {
996  Name("DetectorParticleTag"),
997  Comment("label of simulated particles through the detector"),
998  "largeant" // tradition demands
999  };
1000 
1001  fhicl::Sequence<art::InputTag> EnergyDepositTags {
1002  Name("EnergyDeposits"),
1003  Comment("label of energy deposition data product(s) in the detector"),
1004  std::vector<art::InputTag>{ "largeant:TPCActive" }
1005  };
1006 
1007  fhicl::OptionalAtom<art::InputTag> EnergyDepositSummaryTag {
1008  Name("EnergyDepositSummaryTag"),
1009  Comment("label of energy deposition summary data product")
1010  };
1011 
1012  fhicl::Atom<std::string> TriggerGatesTag {
1013  Name("TriggerGatesTag"),
1014  Comment("label of the input trigger gate data product (no instance name)")
1015  };
1016 
1017  fhicl::Sequence<std::string> Thresholds {
1018  Name("Thresholds"),
1019  Comment("thresholds to consider (as tags)")
1020  };
1021 
1022  fhicl::Atom<microseconds> BeamGateDuration {
1023  Name("BeamGateDuration"),
1024  Comment("length of time interval when optical triggers are accepted")
1025  };
1026 
1027  fhicl::Atom<microseconds> BeamGateStart {
1028  Name("BeamGateStart"),
1029  Comment("open the beam gate this long after the nominal beam gate time"),
1030  microseconds{ 0.0 }
1031  };
1032 
1033  fhicl::Atom<microseconds> PreSpillWindow {
1034  Name("PreSpillWindow"),
1035  Comment("duration of the pre-spill window"),
1036  microseconds{ 10.0 }
1037  };
1038 
1039  fhicl::Atom<microseconds> PreSpillWindowGap {
1040  Name("PreSpillWindowGap"),
1041  Comment("gap from the end of pre-spill window to the start of beam gate"),
1042  microseconds{ 0.0 }
1043  };
1044 
1045  fhicl::Atom<nanoseconds> TriggerTimeResolution {
1046  Name("TriggerTimeResolution"),
1047  Comment("resolution of trigger in time"),
1048  8_ns
1049  };
1050 
1051  fhicl::Atom<bool> PlotOnlyActiveVolume {
1052  Name("PlotOnlyActiveVolume"),
1053  Comment
1054  ("only events within TPC active volume are plot (if that makes sense)"),
1055  true
1056  };
1057 
1058  fhicl::Sequence<std::string> OnlyPlotCategories {
1059  Name("OnlyPlotCategories"),
1060  Comment
1061  ("if specified, plot categories not in this list are not considered"),
1062  std::vector<std::string>{}
1063  };
1064 
1065  fhicl::OptionalAtom<std::string> EventTreeName {
1066  Name("EventTreeName"),
1067  Comment("name of a ROOT tree where to store event-by-event information")
1068  };
1069 
1070  fhicl::OptionalAtom<std::string> EventDetailsLogCategory {
1071  Name("EventDetailsLogCategory"),
1072  Comment("name of the category used for event information output")
1073  };
1074 
1075  fhicl::Atom<std::string> LogCategory {
1076  Name("LogCategory"),
1077  Comment("name of the category used for the output"),
1078  "SlidingWindowTrigger" // default
1079  };
1080 
1081  }; // struct Config
1082 
1083  // --- END Configuration -----------------------------------------------------
1084 
1085 
1086  using EventInfo_t = details::EventInfo_t; // type alias
1087  using PMTInfo_t = details::PMTInfo_t; // type alias
1088  using TriggerInfo_t = details::TriggerInfo_t; // type alias
1089 
1090 
1091  // --- BEGIN Constructors ----------------------------------------------------
1092 
1093  /// Constructor; requires a configuration and module's `consumesCollector()`.
1095  (Config const& config, art::ConsumesCollector& consumer);
1096 
1097  // --- END Constructors ------------------------------------------------------
1098 
1099 
1100  // --- BEGIN Framework hooks -------------------------------------------------
1101 
1102  /// Fills the plots. Also extracts the information to fill them with.
1103  void process(art::Event const& event);
1104 
1105  /// Prints end-of-job summaries.
1106  void printSummary() const;
1107 
1108  // --- END Framework hooks ---------------------------------------------------
1109 
1110 
1111  // --- BEGIN Helper interface ------------------------------------------------
1112  //
1113  // Mediated access to private stuff.
1114  //
1115 
1116  /// Returns the name of the log category.
1117  std::string const& logCategory() const { return fLogCategory; }
1118 
1119  /// Returns a pointer to the tree where event information is written.
1120  TTree* eventTree() { return fIDTree? &(fIDTree->tree()): nullptr; }
1121 
1122  /// Returns whether we are using and filling generator information.
1123  bool useGen() const { return fEventInfoExtractorMaker.hasGenerated(); }
1124 
1125  /// Returns whether we are using and filling energy deposition information.
1126  bool useEDep() const { return fEventInfoExtractorMaker.hasEDep(); }
1127 
1128  /// Returns the number of configured PMT thresholds.
1129  std::size_t nADCthresholds() const { return fADCthresholds.size(); }
1130 
1131  /// Returns a iterable sequence of all configured PMT thresholds.
1132  auto ADCthresholds() const { return util::get_elements<0U>(fADCthresholds); }
1133 
1134  /// Returns the ADC threshold tag value for PMT threshold index `iThr`.
1135  /// @throws std::out_of_range if `iThr` is not a valid threshold index
1136  /// @see `nADCthresholds()`
1137  std::string const& ADCthresholdTag(std::size_t iThr) const
1138  { return next(fADCthresholds.begin(), iThr)->first; }
1139 
1140  /// Returns the detector geometry service provider.
1141  geo::GeometryCore const& geometry() const { return fGeom; }
1142 
1143  /// Returns the resolution of trigger timing clock [ns]
1144  nanoseconds triggerTimeResolution() const { return fTriggerTimeResolution; }
1145 
1146  // --- END Helper interface --------------------------------------------------
1147 
1148 
1149  using PlotSandbox = icarus::trigger::PlotSandbox; ///< Import type.
1150 
1151  /// List of references to plot sandboxes.
1152  using PlotSandboxRefs_t
1153  = std::vector<std::reference_wrapper<PlotSandbox const>>;
1154 
1155 
1156  //----------------------------------------------------------------------------
1158 
1159  public:
1160 
1161  /// Type of test function.
1162  using QualifyFunc_t = std::function<bool(EventInfo_t const&)>;
1163 
1164 
1165  /// Constructor from category name and test function.
1167  std::string name, std::string descr = {},
1168  QualifyFunc_t&& test = [](EventInfo_t const&){ return true; }
1169  )
1170  : fName(std::move(name)), fDescr(std::move(descr)), fTest(std::move(test))
1171  {}
1172 
1173  /// Returns the name of the category.
1174  std::string const& name() const { return fName; }
1175 
1176  /// Returns the description of the category.
1177  std::string const& description() const { return fDescr; }
1178 
1179  /// Returns whether the event belong to this category.
1180  bool test(EventInfo_t const& info) const { return fTest(info); }
1181 
1182  operator std::string() const { return name(); }
1183  bool operator() (EventInfo_t const& info) const { return test(info); }
1184 
1185  private:
1186 
1187  std::string fName;
1188  std::string fDescr;
1190 
1191  }; // class PlotCategory
1192  using PlotCategories_t = std::vector<PlotCategory>;
1193 
1194 
1195  //----------------------------------------------------------------------------
1196 
1197  class HistGetter { // helper, since this seems "popular"
1199 
1200  public:
1201  HistGetter(PlotSandbox const& plots): plots(plots) {}
1202 
1203  PlotSandbox const& box() const { return plots; }
1204 
1205  TH1& Hist(std::string const& name) const { return plots.demand<TH1>(name); }
1206  TH2& Hist2D(std::string const& name) const { return plots.demand<TH2>(name); }
1207  TEfficiency& Eff(std::string const& name) const
1208  { return plots.demand<TEfficiency>(name); }
1209 
1210  }; // class HistGetter
1211 
1212  //----------------------------------------------------------------------------
1213 
1214  /// Generic description of trigger settings.
1216 
1217  std::size_t index; ///< Settings unique index.
1218  std::string tag; ///< A tag of the settings (for object names).
1219  std::string description; ///< A description of the settings (for plots).
1220 
1221  SettingsInfo_t() = default;
1222  SettingsInfo_t(std::size_t index, std::string tag, std::string descr)
1223  : index(index), tag(tag), description(descr) {}
1224 
1225  }; // SettingsInfo_t
1226 
1227  /// Type of trigger gate extracted from the input event.
1228  using InputTriggerGate_t
1230 
1231  /// A list of trigger gates from input.
1232  using TriggerGates_t = std::vector<InputTriggerGate_t>;
1233 
1234  /// Type of lists of gates, one list per cryostat (outer index: cryostat no).
1235  using TriggerGatesPerCryostat_t = std::vector<TriggerGates_t>;
1236 
1237  /// Type representing the unique identifier of a optical detector channel.
1239 
1240 
1241  /// A collection of useful beam gates. Make one with `makeGatePack()`.
1242  struct GatePack_t {
1246  }; // GatePack_t
1247 
1248  // --- BEGIN Customization interface -----------------------------------------
1249 
1250  /// Initializes all the plot sets, one per PMT threshold.
1251  virtual void initializePlots
1252  (PlotCategories_t categories, std::vector<SettingsInfo_t> const& settings);
1253 
1254  /// Initializes sets of default plots, one per PMT threshold.
1255  void initializePlots(std::vector<SettingsInfo_t> const& settings)
1256  { initializePlots(DefaultPlotCategories, settings); }
1257 
1258  /// Initializes full set of plots for (ADC threshold + category) into `plots`.
1259  virtual void initializePlotSet
1260  (PlotSandbox& plots, std::vector<SettingsInfo_t> const& settings) const;
1261 
1262  /// Initializes set of plots per complete trigger definition into `plots`.
1263  virtual void initializeEfficiencyPerTriggerPlots(PlotSandbox& plots) const;
1264 
1265  /// Initializes a single, trigger-independent plot set into `plots`.
1266  virtual void initializeEventPlots(PlotSandbox& plots) const;
1267 
1268  /// Initializes a single, trigger-independent, threshold-dependent plot set
1269  /// into `plots`.
1270  virtual void initializePMTplots(PlotSandbox& plots) const;
1271 
1272  /// Returns whether an event with the specified information should be included
1273  /// in the plots at all (it's a filter).
1274  virtual bool shouldPlotEvent(EventInfo_t const& eventInfo) const;
1275 
1276  /**
1277  * @brief Simulates all triggers for a trigger setting and plots the results.
1278  * @param thresholdIndex the index of the PMT threshold of input primitives
1279  * @param gates the trigger primitives used to simulate the trigger response
1280  * @param eventInfo general information about the event being simulated
1281  * @param selectedPlots list of boxes containing plots to be filled
1282  *
1283  * This pure virtual function is the core of the customization of this class.
1284  * The `simulateAndPlot()` method is expected to:
1285  *
1286  * 1. combine the trigger primitives
1287  * 2. apply the beam gate
1288  * 3. generate the trigger response
1289  * 4. fill all plots
1290  *
1291  * **for each trigger setting**.
1292  * Note that this helper class has no knowledge of those settings: how many
1293  * they are, what they mean, which are their parameters. It is
1294  * `simulateAndPlot()` task to properly process all of them _at once_, i.e.
1295  * within a single call.
1296  *
1297  * Big deal! The second and fourth step (application of beam gate and plots
1298  * filling) have some helpers in this same class:
1299  *
1300  * * `ApplyBeamGateClass::applyToAll()` can easily apply the beam gate at the
1301  * right time (the right time is chosen by the implementation of
1302  * `simulateAndPlot()`); an `ApplyBeamGateClass` object is obtained with
1303  * `makeMyBeamGate()`;
1304  * * filling of standard plots is performed with `fillAllEfficiencyPlots()`,
1305  * `fillEfficiencyPlots()` and `fillEventPlots()`, which can be used as such
1306  * or be customized for more plots.
1307  *
1308  * Combination of primitive can be helped with
1309  * `icarus::trigger::TriggerGateData`
1310  *
1311  * All plots must have already been initialized via `initializePlots()` and
1312  * its helpers.
1313  *
1314  * The method is required to perform the simulation of the trigger primitives
1315  * specified in input. These primitives are provided in `gates` as many
1316  * collections, one per cryostat. While this interface splits the primitives
1317  * by cryostat, the trigger simulation gets to choose how to handle that
1318  * information, e.g. performing an independent simulation per cryostat and
1319  * then combining them all, or just merging back the two collections and
1320  * treating the two cryostats as a single entity.
1321  *
1322  * The input trigger primitives are extracted from PMT waveforms with a
1323  * certain PMT threshold, which is documented by its index `thresholdIndex`;
1324  * the threshold value can be obtained from `ADCthreshold(thresholdIndex)`,
1325  * and in the future more information may become available as well.
1326  *
1327  * Plots will need information from the event being simulated: that
1328  * information is precooked, extracted from the event and stored in
1329  * `eventInfo`. If more information is needed, `EventInfo_t` needs to be
1330  * updated in this helper, as no way is provided to perform that customization
1331  * in the derived class.
1332  *
1333  * It is expected that all PMT thresholds settings identified by the specified
1334  * index. This helper class does not know the definition of any trigger, and
1335  * it is expected that settings are tracked by the derived classes and each
1336  * is associated to an index.
1337  *
1338  */
1339  virtual void simulateAndPlot(
1340  std::size_t const thresholdIndex,
1341  TriggerGatesPerCryostat_t const& gates,
1342  EventInfo_t const& eventInfo,
1343  detinfo::DetectorClocksData const& clockData,
1344  PlotSandboxRefs_t const& selectedPlots
1345  ) = 0;
1346 
1347 
1348  /// Fills the plots (`initializeEventPlots()`) with info from `eventInfo`.
1349  virtual void fillEventPlots
1350  (EventInfo_t const& eventInfo, PlotSandbox const& plots) const;
1351 
1352  /// Fill the plots (`initializePMTplots()`) with info from `PMTinfo`.
1353  virtual void fillPMTplots
1354  (PMTInfo_t const& PMTinfo, PlotSandbox const& plots) const;
1355 
1356  /// Fills the plots (`initializeEfficiencyPerTriggerPlots()`) with info from
1357  /// `eventInfo` and `triggerInfo`.
1358  virtual void fillEfficiencyPlots(
1359  EventInfo_t const& eventInfo,
1360  TriggerInfo_t const& triggerInfo,
1361  PlotSandbox const& plots
1362  ) const;
1363 
1364  /// Fills the plots as `fillEfficiencyPlots()` and also as `fillEventPlots()`
1365  /// for the proper category: triggered or not triggered.
1366  virtual void fillAllEfficiencyPlots(
1367  EventInfo_t const& eventInfo,
1368  PMTInfo_t const& PMTinfo,
1369  TriggerInfo_t const& triggerInfo,
1370  PlotSandbox const& plots
1371  ) const;
1372 
1373  // --- END Customization interface -------------------------------------------
1374 
1375 
1376  // --- BEGIN Additional helper utilities -------------------------------------
1377 
1378  /// Deletes plots with no entries, and directories which became empty.
1379  void deleteEmptyPlots();
1380 
1381  /**
1382  * @brief Creates counters for all the thresholds of the specified trigger.
1383  * @param patternName an identified for the pattern
1384  * @return the index of the pattern in the counter list
1385  */
1386  std::size_t createCountersForPattern(std::string const& patternName);
1387 
1388 
1389  //@{
1390  /// Registers the outcome of the specified trigger.
1391  void registerTriggerResult
1392  (std::size_t threshold, std::size_t pattern, bool fired);
1393  void registerTriggerResult(
1394  std::size_t threshold, std::size_t pattern,
1395  TriggerInfo_t const& triggerInfo
1396  );
1397  //@}
1398 
1399  /**
1400  * @brief Creates a `GatePack_t` from the specified event
1401  * @param event the event to extract beam for (if `nullptr`, uses job info)
1402  * @return a set of relevant gates
1403  *
1404  * Use it C++17-fancy!
1405  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
1406  * auto const [ detTimings, beamGate, preSpillWindow ] = makeGatePack(&event);
1407  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1408  * (the arguments are mapped to the `GatePack_t` members by position).
1409  */
1410  GatePack_t makeGatePack(art::Event const* event = nullptr) const;
1411 
1412  //@{
1413  /// Shortcut to create an `ApplyBeamGate` with the current configuration.
1415  (detinfo::DetectorClocksData const& clockData) const
1416  {
1417  return makeApplyBeamGate
1418  (fBeamGateDuration, fBeamGateStart, clockData, fLogCategory);
1419  }
1421  (art::Event const* event = nullptr) const
1422  { return makeMyBeamGate(icarus::ns::util::makeDetClockData(event)); }
1424  (art::Event const& event) const { return makeMyBeamGate(&event); }
1425  //@}
1426 
1427 
1428  // documentation at definition:
1430 
1431 
1432  /**
1433  * @brief Returns all channels contributing to the trigger gates.
1434  * @param cryoGates all trigger gates
1435  * @return a list of ID of "active" channels
1436  *
1437  * A channels is considered "active" when it is contributing to a trigger gate
1438  * which is open at least one. Conversely, all channels belonging to gates
1439  * which have no opening are excluded.
1440  */
1441  static std::vector<ChannelID_t> extractActiveChannels
1442  (TriggerGatesPerCryostat_t const& cryoGates);
1443 
1444 
1445  // --- END Additional helper utilities ---------------------------------------
1446 
1447 
1448  private:
1449 
1450  // --- BEGIN Configuration variables -----------------------------------------
1451 
1452  art::InputTag fDetectorParticleTag; ///< Input simulated particles.
1453 
1454  /// ADC threshold tags to read, and the input tag connected to their data.
1455  std::map<std::string, art::InputTag> fADCthresholds;
1456 
1457  /// Duration of the gate during with global optical triggers are accepted.
1459 
1460  /// Start of the beam gate with respect to `BeamGate()`.
1462 
1463  microseconds fPreSpillWindow; ///< Duration of the pre-spill gate.
1464 
1465  microseconds fPreSpillStart; ///< Start of the pre-spill gate.
1466 
1467  nanoseconds fTriggerTimeResolution; ///< Trigger resolution in time.
1468 
1469  bool fPlotOnlyActiveVolume; ///< Plot only events in active volume.
1470 
1471  ///< Only apply these categories (empty applies all).
1472  std::vector<std::string> fOnlyPlotCategories;
1473 
1474  /// Message facility stream category for output.
1475  std::string const fLogCategory;
1476 
1477  std::string fLogEventDetails; ///< Steam where to print event info.
1478 
1479  /// Plot categories (via `initializePlots()`).
1481 
1482  // --- END Configuration variables -------------------------------------------
1483 
1484 
1485  // --- BEGIN Service variables -----------------------------------------------
1486 
1488 
1489  /// ROOT directory where all the plots are written.
1490  art::TFileDirectory fOutputDir;
1491 
1492  // --- END Service variables -------------------------------------------------
1493 
1494 
1495  // --- BEGIN Internal variables ----------------------------------------------
1496 
1497  /// Helper to extract information from the event.
1499 
1500  /// ID of cryostat where each optical detector channel (vector index) is.
1501  std::vector<geo::CryostatID> const fChannelCryostat;
1502 
1503  /// All plots, one set per ADC threshold.
1504  std::vector<PlotSandbox> fThresholdPlots;
1505 
1506  /// Handler of ROOT tree output.
1507  std::unique_ptr<details::EventIDTree> fIDTree;
1508  std::unique_ptr<details::PlotInfoTree> fPlotTree; ///< Handler of ROOT tree output.
1509  std::unique_ptr<details::EventInfoTree> fEventTree; ///< Handler of ROOT tree output.
1510 
1511 
1512  std::atomic<unsigned int> nEvents { 0U }; ///< Count of seen events.
1513  std::atomic<unsigned int> nPlottedEvents { 0U }; ///< Count of plotted events.
1514 
1515  /// Functor returning whether a gate has changed.
1518 
1519  details::TriggerPassCounters fPassCounters; ///< Counters for all triggers.
1520 
1521  // --- END Internal variables ------------------------------------------------
1522 
1523 
1524  /// Returns the names of the plot categories event qualifies for.
1525  std::vector<std::string> selectPlotCategories
1526  (EventInfo_t const& info, PlotCategories_t const& categories) const;
1527 
1528  /// Returns the TPC `point` is within, `nullptr` if none.
1529  geo::TPCGeo const* pointInTPC(geo::Point_t const& point) const;
1530 
1531  /// Returns in which TPC `point` is within the _active volume_ of;
1532  /// `nullptr` if none.
1533  geo::TPCGeo const* pointInActiveTPC(geo::Point_t const& point) const;
1534 
1535  /// Reads a set of input gates from the `event`
1536  /// @return trigger gates, converted into `InputTriggerGate_t`
1537  TriggerGates_t readTriggerGates
1538  (art::Event const& event, art::InputTag const& dataTag) const;
1539 
1540  /// Moves the data in `gates` in a collection of gates by cryostat.
1541  TriggerGatesPerCryostat_t splitByCryostat(TriggerGates_t&& gates) const;
1542 
1543  /// Deletes from `plots` sandbox all plots and subboxes with no entries.
1544  /// @return whether `plots` is now empty
1545  bool deleteEmptyPlots(PlotSandbox& plots) const;
1546 
1547 
1548  /// Fills and returns a map of cryostat ID for each optical detector channel.
1549  static std::vector<geo::CryostatID> makeChannelCryostatMap
1550  (geo::GeometryCore const& geom);
1551 
1552  static std::string thrAndCatName
1553  (std::string const& boxName, std::string const& category)
1554  { return boxName + "_" + category; }
1555  static std::string thrAndCatName
1556  (PlotSandbox const& box, std::string const& category)
1557  { return thrAndCatName(box.name(), category); }
1558 
1559  /// Creates a `EDepTags_t` out of the module configuration.
1561  fhicl::Sequence<art::InputTag> const& EnergyDepositTags,
1562  fhicl::OptionalAtom<art::InputTag> const& EnergyDepositSummaryTag
1563  );
1564 
1565 }; // icarus::trigger::TriggerEfficiencyPlotsBase
1566 
1567 
1568 //------------------------------------------------------------------------------
1569 
1570 
1571 #endif // ICARUSCODE_PMT_TRIGGER_TRIGGEREFFICIENCYPLOTSBASE_H
BEGIN_PROLOG BeamGateDuration pmtthr physics producers trigtilewindowORS Thresholds
std::pair< std::size_t, std::size_t > IndexPair_t
Class managing the serialization of plot information in a simple ROOT tree.
std::string const & ADCthresholdTag(std::size_t iThr) const
Helper class to produce plots about trigger simulation and trigger efficiency.
microseconds fPreSpillWindow
Duration of the pre-spill gate.
std::string fLogEventDetails
Steam where to print event info.
ApplyBeamGateClass makeApplyBeamGate(util::quantities::intervals::microseconds duration, util::quantities::intervals::microseconds delay, detinfo::DetectorClocksData const &clockData, std::string const &logCategory="ApplyBeamGateClass")
Returns a new ApplyBeamGateClass object with the specified gate.
An object representing a time gate, with a start and and end.
Tracks pass rate by discrimination threshold and trigger pattern name.
Definition of util::get_elements() and util::get_const_elements().
static PlotCategories_t const DefaultPlotCategories
List of event categories.
A wrapper to trigger gate objects tracking the input of operations.
bool useGen() const
Returns whether we are using and filling generator information.
microseconds_as<> microseconds
Type of time interval stored in microseconds, in double precision.
Definition: spacetime.h:259
std::vector< geo::CryostatID > const fChannelCryostat
ID of cryostat where each optical detector channel (vector index) is.
A collection of useful beam gates. Make one with makeGatePack().
std::vector< std::vector< Counter_t > > fCounters
All counters; indices: [threshold][pattern].
std::string const & logCategory() const
Returns the name of the log category.
std::unordered_map< Threshold_t, std::size_t > fThresholdIndex
Map: threshold -&gt; threshold index.
Geometry information for a single TPC.
Definition: TPCGeo.h:38
std::unordered_map< std::string, std::size_t > fPatternIndex
Map: pattern name -&gt; pattern index.
TTree * eventTree()
Returns a pointer to the tree where event information is written.
PlotCategories_t fPlotCategories
Plot categories (via initializePlots()).
Derivative information from raw::OpDetWaveform data.
std::string const fLogCategory
Message facility stream category for output.
Helper to manage a beam gate.
std::string const & name() const
Returns the name of the category.
std::string const & name() const
Returns the sandbox name.
Definition: PlotSandbox.h:196
std::variant< std::vector< art::InputTag >, SimEnergyDepositSummaryInputTag, SimChannelsInputTag > EDepTags_t
Type to specify the source of energy deposition information, if any.
Helper applying a beam gate to any gate.
Definition: ApplyBeamGate.h:85
Helper to check if an object has changed. Thread-safe.
Class to keep count of a pass/fail result.
pure virtual base interface for detector clocks
microseconds fBeamGateDuration
Duration of the gate during with global optical triggers are accepted.
Helper data structure to store transient trigger result.
Definition: TriggerInfo_t.h:50
std::string const & description() const
Returns the description of the category.
Interface to detinfo::DetectorClocks.
fDetProps &fDetProps fDetProps &fDetProps fLogCategory
nanoseconds triggerTimeResolution() const
Returns the resolution of trigger timing clock [ns].
Access the description of detector geometry.
Information about the event.
std::unique_ptr< details::EventInfoTree > fEventTree
Handler of ROOT tree output.
art::TFileDirectory fOutputDir
ROOT directory where all the plots are written.
details::EventInfoExtractorMaker const fEventInfoExtractorMaker
Helper to extract information from the event.
Class holding a ROOT tree, to be shared by other classes.
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
Definition: counter.h:285
details::TriggerPassCounters fPassCounters
Counters for all triggers.
Definitions of geometry vector data types.
Simple functions to streamline the creation of DetectorClocksData.
Simple type definitions for trigger algorithms.
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
auto ADCthresholds() const
Returns a iterable sequence of all configured PMT thresholds.
geo::GeometryCore const & geometry() const
Returns the detector geometry service provider.
std::vector< PlotDef > plots
Definition: demo.h:54
Class managing the serialization of plot information in a simple ROOT tree.
BEGIN_PROLOG vertical distance to the surface Name
Helper data structure to store PMT activity information in the event.
Definition: PMTInfo_t.h:25
art::InputTag fDetectorParticleTag
Input simulated particles.
bool test(EventInfo_t const &info) const
Returns whether the event belong to this category.
Simple class holding a tree.
Definition: TreeHolder.h:24
Description of geometry of one entire detector.
An interval (duration, length, distance) between two quantity points.
Definition: intervals.h:114
Functions dealing with icarus::trigger::details::EventInfo_t.
Definition of data types for geometry description.
void initializePlots(std::vector< SettingsInfo_t > const &settings)
Initializes sets of default plots, one per PMT threshold.
InputTriggerGate_t::TriggerGate_t::ChannelID_t ChannelID_t
Type representing the unique identifier of a optical detector channel.
nanoseconds_as<> nanoseconds
Type of time interval stored in nanoseconds, in double precision.
Definition: spacetime.h:270
std::map< std::string, art::InputTag > fADCthresholds
ADC threshold tags to read, and the input tag connected to their data.
Utilities to read interval and point quantity FHiCL configuration.
Object representing a time gate, with a start and and end.
std::string description
A description of the settings (for plots).
Class writing event information into a ROOT tree.
Classes to detect the change of object values.
A helper class creating a EventInfoExtractor with a specific setup.
Dimensioned variables representing energy.
Contains all timing reference information for the detector.
Class hosting selected information about the event.
PlotCategory(std::string name, std::string descr={}, QualifyFunc_t &&test=[](EventInfo_t const &){return true;})
Constructor from category name and test function.
std::unique_ptr< details::PlotInfoTree > fPlotTree
Handler of ROOT tree output.
Dimensioned variables representing space or time quantities.
Helper class to store transient trigger result.
A class exposing an upgraded interface of detinfo::DetectorClocksData.
Data types for detinfo::DetectorTimings.
std::string tag
A tag of the settings (for object names).
std::function< bool(EventInfo_t const &)> QualifyFunc_t
Type of test function.
A simple alias for a most commonly used TrackedTriggerGate type.
Selected information about the event.
Definition: EventInfo_t.h:45
std::size_t nADCthresholds() const
Returns the number of configured PMT thresholds.
then echo fcl name
microseconds fPreSpillStart
Start of the pre-spill gate.
std::vector< std::reference_wrapper< PlotSandbox const >> PlotSandboxRefs_t
List of references to plot sandboxes.
std::unique_ptr< details::EventIDTree > fIDTree
Handler of ROOT tree output.
BEGIN_PROLOG hitmakerfive clustermakerfour pfparticlemakerthree showermakertwo END_PROLOG hitmakerfive clustermakerfour pfparticlemakerthree sequence::inline_paths sequence::inline_paths sequence::inline_paths showermakers test
Helper class to store discriminated PMT information.
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
std::vector< PlotSandbox > fThresholdPlots
All plots, one set per ADC threshold.
SettingsInfo_t(std::size_t index, std::string tag, std::string descr)
Class hosting selected information about the event.
nanoseconds fTriggerTimeResolution
Trigger resolution in time.
std::vector< TriggerGates_t > TriggerGatesPerCryostat_t
Type of lists of gates, one list per cryostat (outer index: cryostat no).
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
detinfo::DetectorClocksData makeDetClockData(art::Event const *event)
Returns a detinfo::DetectorClocksData from DetectorClocksService.
Class counting pass/fail events.
Definition: PassCounter.h:15
bool fPlotOnlyActiveVolume
Plot only events in active volume.
A helper to manage ROOT objects in a art::TFileDirectory.
std::vector< InputTriggerGate_t > TriggerGates_t
A list of trigger gates from input.
Encapsulate the construction of a single detector plane.
bool useEDep() const
Returns whether we are using and filling energy deposition information.
microseconds fBeamGateStart
Start of the beam gate with respect to BeamGate().
icarus::ns::util::ThreadSafeChangeMonitor< icarus::trigger::BeamGateStruct > fBeamGateChangeCheck
Functor returning whether a gate has changed.
A helper to manage ROOT objects with consistent naming.
Definition: PlotSandbox.h:95