All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SlidingWindowTriggerEfficiencyPlots_module.cc
Go to the documentation of this file.
1 /**
2  * @file SlidingWindowTriggerEfficiencyPlots_module.cc
3  * @brief Plots of efficiency for triggers based on PMT channel sliding window.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date January 9, 2020
6  * @see icaruscode/PMT/Trigger/TriggerEfficiencyPlotsBase.h
7  */
8 
9 
10 // ICARUS libraries
13 #include "icaruscode/PMT/Trigger/Algorithms/WindowTopologyAlg.h" // WindowTopologyManager
19 #include "icarusalg/Utilities/ROOTutils.h" // util::ROOT
20 #include "icarusalg/Utilities/sortBy.h" // also icarus::util::sortCollBy()
21 
22 // LArSoft libraries
24 #include "lardata/Utilities/TensorIndices.h" // util::MatrixIndices
25 #include "lardataalg/DetectorInfo/DetectorTimingTypes.h" // optical_time_ticks..
27 #include "larcorealg/Geometry/geo_vectors_utils.h" // MiddlePointAccumulator
30 #include "larcorealg/CoreUtils/StdUtils.h" // util::to_string()
31 
32 // framework libraries
33 #include "art/Framework/Core/EDAnalyzer.h"
34 #include "art/Framework/Core/ModuleMacros.h"
35 #include "art/Framework/Principal/Event.h"
36 #include "canvas/Utilities/Exception.h"
37 #include "messagefacility/MessageLogger/MessageLogger.h"
38 #include "fhiclcpp/types/TableAs.h"
39 #include "fhiclcpp/types/Table.h"
40 #include "fhiclcpp/types/Sequence.h"
41 
42 // ROOT libraries
43 #include "TTree.h"
44 #include "TH2F.h"
45 
46 // C/C++ standard libraries
47 #include <algorithm> // std::sort(), std::transform(), ...
48 #include <vector>
49 #include <array>
50 #include <memory> // std::unique_ptr
51 #include <utility> // std::pair<>, std::move()
52 #include <limits> // std::numeric_limits<>
53 #include <type_traits> // std::is_pointer_v, ...
54 #include <cstddef> // std::size_t
55 #include <cassert>
56 
57 
58 //------------------------------------------------------------------------------
59 namespace {
60 
61  /// Moves all elements of `src` at the end of `dest`.
62  template <typename DestColl, typename SrcColl>
63  DestColl& appendCollection(DestColl& dest, SrcColl&& src);
64 
65 } // local namespace
66 
67 
68 //------------------------------------------------------------------------------
69 
70 // --- BEGIN -- ROOT tree helpers ----------------------------------------------
71 /**
72  * @brief Class managing the serialization of trigger responses in a simple ROOT
73  * tree.
74  *
75  * The tree is supplied by the caller.
76  * This object will create the proper branches into the tree and assign
77  * addresses to them. Then it will assume they will stay assigned.
78  *
79  * On `assignResponse()`, the proper branch address is assigned the specified
80  * trigger response (`true` or `false`).
81  *
82  * The branch structure is: a `RespTxxSxx/O` branch for each threshold and
83  * settings label, with a single branch per element.
84  *
85  */
87 
88  // `std::vector<bool>` is too special for us. Let's pack it to go.
90  std::unique_ptr<bool[]> RespTxxSxx;
91 
92 
93  /**
94  * @brief Constructor: accommodates that many thresholds and trigger settings.
95  * @tparam Thresholds an iterable type yielding objects convertible to numbers
96  * @tparam Settings an iterable type yielding objects convertible to string
97  * @param tree the ROOT tree to add branches to (managed elsewhere)
98  * @param thresholds collection of thresholds to be included
99  * @param settings collection of trigger settings to be included
100  *
101  * The `thresholds` must be convertible to ADC counts (i.e. numbers), while
102  * the `settings` elements must support conversion to string via `to_string()`
103  * function call (more precisely, `util::to_string()` from
104  * `larcorealg/CoreUtils/StdUtils.h`).
105  */
106  template <typename Thresholds, typename Settings>
108  (TTree& tree, Thresholds const& thresholds, Settings const& settings);
109 
110  /// Assigns the response for the specified trigger.
111  void assignResponse(std::size_t iThr, std::size_t iSettings, bool resp);
112 
113 }; // struct ResponseTree
114 
115 
116 // --- END -- ROOT tree helpers ------------------------------------------------
117 
118 
119 //------------------------------------------------------------------------------
120 namespace icarus::trigger { class SlidingWindowTriggerEfficiencyPlots; }
121 /**
122  * @brief Produces plots about trigger simulation and trigger efficiency.
123  *
124  * This module is an implementation of `TriggerEfficiencyPlotsBase`
125  * for a trigger defined as a pattern of sliding windows.
126  *
127  * Note that the multi-level logical waveforms from the sliding windows are
128  * expected to be provided as input.
129  *
130  * The single sliding window with the highest activity is picked as a reference.
131  * A requirement on the number of trigger primitives "on" in that window is
132  * imposed. Additional requirements may be imposed on three other sliding
133  * windows: the upstream one (if any), the downstream one (if any) and the
134  * opposite one in the same cryostat.
135  *
136  * As usual for `TriggerEfficiencyPlotsBase` based modules, this happens for
137  * every configured PMT discrimination threshold.
138  *
139  *
140  * Trigger logic algorithm
141  * ========================
142  *
143  * @anchor SlidingWindowTriggerEfficiencyPlots_Algorithm
144  *
145  * This section describes the trigger logic algorithm used in
146  * `icarus::trigger::SlidingWindowTriggerEfficiencyPlots` and its assumptions.
147  *
148  * The module receives as input a multi-level trigger gate for each of the
149  * windows to be considered.
150  * On the first input (i.e. the first event), that input is parsed to learn
151  * the windows and their relative position from the input trigger gates
152  * (`initializeTopologicalMaps()`). This topology will be used to apply the
153  * configured patterns. On the following events, their input is checked to
154  * confirm the compatibility of the composition of its windows with the one from
155  * that first event (`verifyTopologicalMap()`).
156  *
157  * All multi-level gates are set in coincidence with the beam gate by
158  * multiplying the multi-level and the beam gates. Beacuse of this, trigger
159  * gates are suppressed everywhere except than during the beam gate.
160  * The beam gate opens at a time configured in `DetectorClocks` service provider
161  * (`detinfo::DetectorClocks::BeamGateTime()`) and has a duration configured
162  * in this module (`BeamGateDuration`).
163  *
164  * The algorithm handles independently multiple trigger patterns.
165  * On each input, each configured pattern is applied based on the window
166  * topology. Each pattern describes a minimum level of the trigger
167  * gate in the window, that usually means the number of LVDS signals in
168  * coincidence at any given time ("majority"). A pattern may have requirements
169  * on the neighbouring windows in addition to the main one. The pattern is
170  * satisfied if all involved windows pass their specific requirements at the
171  * same time (coincidence between windows).
172  * Each pattern is applied in turn to each of the windows (which is the "main"
173  * window). The neighborhood described in the pattern is applied with respect to
174  * that main window. The method `applyWindowPattern()` performs this
175  * combination.
176  * The trigger fires if one or more of the windows satisfy the pattern, and the
177  * trigger time is the one of the earliest satisfied pattern (more precisely,
178  * the earliest tick when the coincidence required by that pattern is
179  * satisfied).
180  *
181  * All windows in the detector are considered independently, but the supported
182  * patterns may only include components in the same cryostat. Therefore,
183  * triggers are effectively on a single cryostat.
184  *
185  * Eventually, for each event there are as many different trigger responses as
186  * how many different patterns are configured (`Patterns` configuration
187  * parameter), _times_ how many ADC thresholds are provided in input,
188  * configured in `Thresholds`.
189  *
190  * While there _is_ a parameter describing the time resolution of the trigger
191  * (`TriggerTimeResolution`), this is currently only used for aesthetic purposes
192  * to choose the binning of some plots: the resolution is _not_ superimposed
193  * to the gates (yet).
194  *
195  * The set of plots and their organization are described in the documentation of
196  * `icarus::trigger::TriggerEfficiencyPlotsBase`.
197  * In the following documentation only the additions are described.
198  *
199  *
200  * Output plots
201  * -------------
202  *
203  * A generic "setting" of `icarus::trigger::TriggerEfficiencyPlotsBase` is
204  * in this module represented by a tag encoding the characteristics of the
205  * pattern (see `WindowPattern::tag()`). The folders and plots will
206  * identify each requirement with tags like `M8` or `M5O2`.
207  *
208  * There are different "types" of plots. Some
209  * @ref SlidingWindowTriggerEfficiencyPlots_SelectionPlots "do not depend on triggering at all",
210  * like the deposited energy distribution. Others
211  * @ref SlidingWindowTriggerEfficiencyPlots_MultiTriggerPlots "cross different trigger definitions",
212  * like the trigger efficiency as function of trigger requirement. Others still
213  * @ref SlidingWindowTriggerEfficiencyPlots_SingleTriggerPlots "assume a single trigger definition":
214  * this is the case of trigger efficiency plots versus energy. Finally, there are
215  * @ref SlidingWindowTriggerEfficiencyPlots_SingleTriggerResponsePlots "plots that depend on a specific trigger definition and outcome":
216  * this is the case of all the plots including only triggering or non-triggering
217  * events.
218  *
219  * There are a few plots that are produced by this module in addition to the
220  * ones in `TriggerEfficiencyPlotsBase`. They are described below.
221  *
222  * All the plots are always relative to a specific optical detector channel
223  * threshold (ADC) and a broad event category.
224  *
225  *
226  * ### Plots independent of the triggers (selection plots)
227  *
228  * @anchor SlidingWindowTriggerEfficiencyPlots_SelectionPlots
229  *
230  * Only @ref TriggerEfficiencyPlotsBase_SelectionPlots "the standard plots"
231  * from `TriggerEfficiencyPlotsBase` are produced in this category.
232  *
233  *
234  * ### Plots including different trigger requirements
235  *
236  * @anchor SlidingWindowTriggerEfficiencyPlots_MultiTriggerPlots
237  *
238  * In addition to @ref TriggerEfficiencyPlotsBase_MultiTriggerPlots "the plots"
239  * from `TriggerEfficiencyPlotsBase`, the following plots are also produced:
240  *
241  * * `Eff`: trigger efficiency defined as number of triggered events over the
242  * total number of events, as function of the pattern (as encoded above);
243  * uncertainties are managed by `TEfficiency`.
244  * * `Triggers`: trigger count as function of the pattern (as encoded above).
245  * * `TriggerTick`: distribution of the time of the earliest trigger for the
246  * event, as function of the pattern (as in `Eff`). Each event appears at most
247  * once for each trigger pattern.
248  *
249  *
250  * ### Plots depending on a specific trigger definition
251  *
252  * @anchor SlidingWindowTriggerEfficiencyPlots_SingleTriggerPlots
253  *
254  * Only @ref TriggerEfficiencyPlotsBase_SingleTriggerPlots "the standard plots"
255  * from `TriggerEfficiencyPlotsBase` are produced in this category.
256  *
257  *
258  * ### Plots depending on a specific trigger definition and response
259  *
260  * @anchor SlidingWindowTriggerEfficiencyPlots_SingleTriggerResponsePlots
261  *
262  * Only @ref TriggerEfficiencyPlotsBase_SingleTriggerResponsePlots "the standard plots"
263  * from `TriggerEfficiencyPlotsBase` are produced in this category.
264  *
265  *
266  * Configuration parameters
267  * =========================
268  *
269  * @anchor SlidingWindowTriggerEfficiencyPlots_Configuration
270  *
271  * In addition to
272  * @ref TriggerEfficiencyPlotsBase_Configuration "all the configuration parameters"
273  * from `TriggerEfficiencyPlotsBase`, the following one is also present:
274  *
275  * * `Patterns` (list of pattern specifications, _mandatory_): a list of
276  * alternative pattern requirements for the definition of a trigger; each
277  * value is a table on its own, with the following elements:
278  * * `inMainWindow` (integer, mandatory): the minimum number of primitives
279  * to be fired in the central ("main") window of the pattern
280  * * `inDownstreamWindow` (integer, default: `0`): the minimum number of
281  * primitives to be fired in the window downstream of the main one
282  * (downstream is farther from the face beam neutrinos enter the
283  * detector through, i.e. larger _z_)
284  * * `inUpstreamWindow` (integer, default: `0`): the minimum number of
285  * primitives to be fired in the window upstream of the main one
286  * (upstream is closer to the face beam neutrinos enter the
287  * detector through, i.e. smaller _z_)
288  * * `inOppositeWindow` (integer, default: `0`): the minimum number of
289  * primitives to be fired in the window opposite to the main one
290  * * `requireDownstreamWindow` (flag, default: `false`): if set, this
291  * pattern is applied only on main windows that have a window downstream
292  * of them, i.e. farther from the face of the detector the beam enters
293  * through (larger _z_ coordinate); if set to `false`, if a main window
294  * has no downstream window, the downstream window requirement is always
295  * considered passed
296  * * `requireUpstreamWindow` (flag, default: `false`): if set, this pattern
297  * is applied only on main windows that have a window upstream of them,
298  * in the same way as for the `requireDownstreamWindow` setting
299  * described above
300  *
301  * An example job configuration is provided as
302  * `makeslidingwindowtriggerplots_icarus.fcl`.
303  *
304  *
305  * Technical description of the module
306  * ====================================
307  *
308  * This module class is derived from
309  * `icarus::trigger::TriggerEfficiencyPlotsBase`, which provides a backbone to
310  * perform the simulation of triggers and plotting of their efficiency.
311  *
312  * There is no superior design involved in this separation, but rather the goal
313  * to share most code possible between different modules which simulate
314  * different trigger patterns and as a consequence might have specific plots to
315  * fill.
316  *
317  * This module redefines:
318  *
319  * * `initializePlotSet()` to define the
320  * @ref SlidingWindowTriggerEfficiencyPlots_MultiTriggerPlots "few additional plots"
321  * needed;
322  * * `simulateAndPlot()`, which must always be defined, and which connects
323  * the simulation pieces and the plotting.
324  *
325  * It does not redefine `initializeEfficiencyPerTriggerPlots()` nor
326  * `initializeEventPlots()` because there are no additional plots of the types
327  * these functions deal with.
328  *
329  * The event categories are from the default list (`DefaultPlotCategories`) too.
330  *
331  */
333  : public art::EDAnalyzer
335 {
336 
337  public:
338 
339  // --- BEGIN Configuration ---------------------------------------------------
341 
342  using Name = fhicl::Name;
343  using Comment = fhicl::Comment;
344 
346  Name("Patterns"),
347  Comment("sliding window pattern requirements")
348  };
349 
350  }; // struct Config
351 
352  using Parameters = art::EDAnalyzer::Table<Config>;
353  // --- END Configuration -----------------------------------------------------
354 
355 
356  // --- BEGIN Constructors ----------------------------------------------------
357 
358  explicit SlidingWindowTriggerEfficiencyPlots(Parameters const& config);
359 
360  // --- END Constructors ------------------------------------------------------
361 
362 
363  // --- BEGIN Framework hooks -------------------------------------------------
364 
365  /// Initializes the plots.
366  virtual void beginJob() override;
367 
368  /// Fills the plots. Also extracts the information to fill them with.
369  virtual void analyze(art::Event const& event) override;
370 
371  /// Prints end-of-job summaries.
372  virtual void endJob() override;
373 
374  // --- END Framework hooks ---------------------------------------------------
375 
376 
377  private:
378 
379  /// List of configured patterns.
381 
382  using TriggerInfo_t = details::TriggerInfo_t; // type alias
383 
384  /// Data structure to communicate internally a trigger response.
385  using WindowTriggerInfo_t
387 
388  // --- BEGIN Configuration variables -----------------------------------------
389 
390  /// Configured sliding window requirement patterns.
392 
393  // --- END Configuration variables -------------------------------------------
394 
395 
396  // --- BEGIN Internal variables ----------------------------------------------
397 
398  /// Mapping of each sliding window with location and topological information.
399  // mutable = not thread-safe; optional to allow delayed construction
401 
402  /// All algorithm instances, one per pattern.
403  std::vector<icarus::trigger::SlidingWindowPatternAlg> fPatternAlgs;
404 
405  std::unique_ptr<ResponseTree> fResponseTree; ///< Handler of ROOT tree output.
406 
407  // --- END Internal variables ------------------------------------------------
408 
409 
410  // @{
411  /// Access to the helper.
412  SlidingWindowTriggerEfficiencyPlots const& helper() const { return *this; }
414  // @}
415 
416 
417  // --- BEGIN Derived class methods -------------------------------------------
418  /**
419  * @brief Initializes full set of plots for (ADC threshold + category).
420  *
421  * This customization of `TriggerEfficiencyPlotsBase::initializePlotSet()`
422  * adds some trigger-definition specific plots and some overview plots
423  * across different trigger definitions.
424  */
425  virtual void initializePlotSet
426  (PlotSandbox& plots, std::vector<SettingsInfo_t> const& settings) const
427  override;
428 
429  /**
430  * @brief Simulates all trigger minimum requirements plots the results.
431  * @param thresholdIndex the index of the PMT threshold of input primitives
432  * @param gates the trigger primitives used to simulate the trigger response
433  * @param eventInfo general information about the event being simulated
434  * @param selectedPlots list of boxes containing plots to be filled
435  *
436  * This method is expected to perform the following steps for each trigger
437  * primitive requirement in `MinimumPrimitives`:
438  *
439  * 1. combine the trigger primitives: `combineTriggerPrimitives()`;
440  * 2. apply the beam gate: `applyBeamGateToAll()` on the combined primitives;
441  * 3. generate the trigger response: in `plotResponse()`;
442  * 4. fill all plots: also in in `plotResponse()`.
443  *
444  * Details are in the documentation of the relevant methods.
445  *
446  * This method is invoked once per PMT threshold.
447  */
448  virtual void simulateAndPlot(
449  std::size_t const thresholdIndex,
450  TriggerGatesPerCryostat_t const& gates,
451  EventInfo_t const& eventInfo,
452  detinfo::DetectorClocksData const& clockData,
453  PlotSandboxRefs_t const& selectedPlots
454  ) override;
455 
456  // --- END Derived class methods ---------------------------------------------
457 
458  /**
459  * @brief Fills plots with the specified trigger response.
460  * @param iThr index of PMT threshold (used in tree output)
461  * @param threshold PMT threshold tag (for printing)
462  * @param iPattern index of the pattern being plotted
463  * @param pattern the pattern being plotted
464  * @param plotSets set of plot boxes to fill (from `initializePlotSet()`)
465  * @param eventInfo event information for plotting
466  * @param triggerInfo the information about the response of this trigger
467  *
468  * This method fills all the relevant plots for the specified trigger pattern
469  * and threshold. The trigger response is passed as a parameter.
470  */
471  void plotResponse(
472  std::size_t iThr, std::string const& threshold,
473  std::size_t iPattern, WindowPattern const& pattern,
474  PlotSandboxRefs_t const& plotSets,
475  EventInfo_t const& eventInfo,
476  PMTInfo_t const& PMTinfo,
477  WindowTriggerInfo_t const& triggerInfo
478  ) const;
479 
480  /// Constructs all the pattern algorithms.
481  /// Must be called after setting the window topology.
483 
484  /// Fills all event plots with data from `eventInfo` as in `fillEventPlots()`.
485  void fillAllEventPlots
486  (PlotSandboxRefs_t const& plotSets, EventInfo_t const& eventInfo) const;
487 
488  /// Fills all PMY plots with data from `PMTinfo` as in `fillPMTplots()`.
489  void fillAllPMTplots
490  (PlotSandboxRefs_t const& plotSets, PMTInfo_t const& PMTinfo) const;
491 
492 }; // icarus::trigger::SlidingWindowTriggerEfficiencyPlots
493 
494 
495 
496 //------------------------------------------------------------------------------
497 //--- Implementation
498 //------------------------------------------------------------------------------
499 //--- Local namespace
500 //------------------------------------------------------------------------------
501 namespace {
502  template <typename DestColl, typename SrcColl>
503  DestColl& appendCollection(DestColl& dest, SrcColl&& src) {
504  dest.insert(
505  dest.end(), std::move_iterator(src.begin()), std::move_iterator(src.end())
506  );
507  return dest;
508  } // appendCollection()
509 } // local namespace
510 
511 
512 //------------------------------------------------------------------------------
513 //--- ResponseTree
514 //------------------------------------------------------------------------------
515 template <typename Thresholds, typename Settings>
517  (TTree& tree, Thresholds const& thresholds, Settings const& settings)
518  : TreeHolder(tree)
519  , indices(std::size(thresholds), std::size(settings))
520  , RespTxxSxx{ std::make_unique<bool[]>(indices.size()) }
521 {
522 
523  for (auto [ iThr, thresholdTag]: util::enumerate(thresholds)) {
524 
525  for (auto [ iSetting, setting ]: util::enumerate(settings)) {
526 
527  std::string const branchName
528  = "RespT" + thresholdTag + "S" + util::to_string(setting);
529 
530  this->tree().Branch
531  (branchName.c_str(), &(RespTxxSxx[indices(iThr, iSetting)]));
532 
533  } // for all requirements
534 
535  } // for all thresholds
536 
537 } // ResponseTree::ResponseTree()
538 
539 
540 //------------------------------------------------------------------------------
542  (std::size_t iThr, std::size_t iSettings, bool resp)
543 {
544  RespTxxSxx[indices(iThr, iSettings)] = resp;
545 } // ResponseTree::assignResponse()
546 
547 
548 //------------------------------------------------------------------------------
549 //--- icarus::trigger::SlidingWindowTriggerEfficiencyPlots
550 //------------------------------------------------------------------------------
552  (Parameters const& config)
553  : art::EDAnalyzer (config)
555  // configuration
556  , fPatterns(config().Patterns())
557  // internal variables
558  , fWindowMapMan{
559  helper().geometry(),
560  helper().logCategory() + "_WindowMapManager"
561  }
562 {
563 
564  if (fPatterns.empty()) {
565  throw art::Exception(art::errors::Configuration)
566  << "At least one 'MinimumPrimitives' requirement... required.";
567  }
568 
569  std::size_t iPattern [[maybe_unused]] = 0U; // NOTE: incremented only in DEBUG
570  for (auto const& pattern: fPatterns) {
571  std::size_t const index [[maybe_unused]]
572  = createCountersForPattern(pattern.tag());
573  assert(index == iPattern++);
574 
575  } // for patterns
576 
577  //
578  // more complex parameter parsing
579  //
580  if (helper().eventTree()) {
581 
582  fResponseTree = std::make_unique<ResponseTree>
583  (*(helper().eventTree()), helper().ADCthresholds(), fPatterns);
584 
585  } // if make tree
586 
587  {
588  mf::LogInfo log(helper().logCategory());
589 
590  log
591  << "Requirement of sliding window patterns ("
592  << fPatterns.size() << "):";
593  for (auto const& pattern: fPatterns)
594  log << "\n [" << pattern.tag() << "] " << pattern.description();
595 
596  }
597 
598 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::SlidingWindowTriggerEfficiencyPlots()
599 
600 
601 //------------------------------------------------------------------------------
603 
604  // hook helper and framework;
605  // actual action is in the (overridden) virtual functions `initializeXxx()`.
606 
607  // NOTE this action can't happen in constructor because relies on polymorphism
608  std::vector<SettingsInfo_t> settings;
609  for (auto const& [ iPattern, pattern ]: util::enumerate(fPatterns)) {
610  settings.emplace_back(
611  iPattern, // index
612  pattern.tag(), // tag
613  pattern.description() // description
614  );
615  } // for
616 
617  // we use the default plot categories defined in
618  // `TriggerEfficiencyPlotsBase::DefaultPlotCategories`
619  helper().initializePlots(settings);
620 
621 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::beginJob()
622 
623 
624 //------------------------------------------------------------------------------
626  (art::Event const& event)
627 {
628 
629  // hook helper and framework;
630  // actual action is in the (overridden) virtual function `plotResponse()`
631  // and `fillXxxPlots()`.
632  helper().process(event);
633 
634 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::analyze()
635 
636 
637 //------------------------------------------------------------------------------
639 
640  helper().deleteEmptyPlots(); // don't keep plots with no entries
641 
642  // hook helper and framework
643  helper().printSummary();
644 
645 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::endJob()
646 
647 
648 //------------------------------------------------------------------------------
650  (PlotSandbox& plots, std::vector<SettingsInfo_t> const& settings) const
651 {
652 
653  //
654  // Selection-related plots
655  //
656 
657  // (inherited)
658  helper().TriggerEfficiencyPlotsBase::initializePlotSet(plots, settings);
659 
660  //
661  // overview plots with different settings
662  //
663 
664  std::vector<std::string> patternLabels; // each pattern has tag as label
666  fPatterns.cbegin(), fPatterns.cend(), back_inserter(patternLabels),
667  std::mem_fn(&WindowPattern::tag)
668  );
669 
670  //
671  // Triggering efficiency vs. requirements.
672  //
673  auto const [ detTimings, beamGate, preSpillWindow ] = makeGatePack();
674  detinfo::timescales::optical_time_ticks const triggerResolutionTicks
675  { detTimings.toOpticalTicks(helper().triggerTimeResolution()) };
676 
677  auto const& beamGateOpt = beamGate.asOptTickRange();
678 
679  auto* TrigTime = plots.make<TH2F>(
680  "TriggerTick",
681  "Trigger time tick"
682  ";window pattern"
683  ";optical time tick [ /" + util::to_string(triggerResolutionTicks) + " ]",
684  fPatterns.size(), 0.0, double(fPatterns.size()),
685  beamGateOpt.duration() / triggerResolutionTicks,
686  beamGateOpt.first.value(), beamGateOpt.second.value()
687  );
688 
689  util::ROOT::applyAxisLabels(TrigTime->GetXaxis(), patternLabels);
690 
691  auto* Triggers = plots.make<TH1F>(
692  "Triggers",
693  "Triggered events"
694  ";window pattern"
695  ";triggered events",
696  fPatterns.size(), 0.0, double(fPatterns.size())
697  );
698 
699  util::ROOT::applyAxisLabels(Triggers->GetXaxis(), patternLabels);
700 
701  auto* Eff = plots.make<TEfficiency>(
702  "Eff",
703  "Efficiency of triggering"
704  ";window pattern"
705  ";trigger efficiency",
706  fPatterns.size(), 0.0, double(fPatterns.size())
707 // fMinimumPrimitives.back(), 0, fMinimumPrimitives.back() + 1
708  );
709 
710  // people are said to have earned hell for things like this;
711  // but TEfficiency really does not expose the interface to assign labels to
712  // its axes, which supposedly could be done had we chosen to create it by
713  // histograms instead of directly as recommended.
714  // Also need to guess which is the relevant histogram.
716  (const_cast<TH1*>(Eff->GetTotalHistogram())->GetXaxis(), patternLabels);
718  (const_cast<TH1*>(Eff->GetPassedHistogram())->GetXaxis(), patternLabels);
719 
720 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::initializePlotSet()
721 
722 
723 //------------------------------------------------------------------------------
725  std::size_t const thresholdIndex,
726  TriggerGatesPerCryostat_t const& gates,
727  EventInfo_t const& eventInfo,
728  detinfo::DetectorClocksData const& clockData,
729  PlotSandboxRefs_t const& selectedPlots
730 ) {
731 
732  auto const threshold = helper().ADCthresholdTag(thresholdIndex);
733 
734  /*
735  * 0. initialize or verify the topology of the input
736  * 1. apply the beam gate to each input gate
737  * 2. for each pattern: apply the pattern, plot the trigger outcome
738  * 3. fill all trigger-independent plots
739  * 4. fill all PMT plots (threshold-dependent)
740  */
741 
742  //
743  // 0. initialize or verify the topology of the input
744  //
745 
746  // throws exception on verification failure;
747  // pattern algorithms are constructed here because they require window mapping
748  if (fWindowMapMan(gates)) initializePatternAlgorithms();
749 
750 
751  auto const& beamGate = helper().makeMyBeamGate(clockData);
752 
753  //
754  // 1. apply the beam gate to each input gate
755  // (it's ok to lose provenance information since we have the map)
756  //
757  TriggerGates_t inBeamGates;
758  for (auto const& cryoGates: gates)
759  appendCollection(inBeamGates, beamGate.applyToAll(cryoGates));
760 
761  // --- BEGIN DEBUG -----------------------------------------------------------
762  {
763  mf::LogTrace log(helper().logCategory());
764  log << "Input for threshold " << threshold << ": " << inBeamGates.size()
765  << " primitives. After beam gate:";
766  unsigned int nOpen = 0U;
768  for (auto const& [ iWindow, gate ]: util::enumerate(gatesIn(inBeamGates))) {
769  auto const maxTick = gate.findMaxOpen();
770  if (maxTick == gate.MinTick) continue;
771  ++nOpen;
772  log << "\n window #" << iWindow << ": maximum "
773  << gate.openingCount(maxTick) << " at tick " << maxTick;
774  } // for
775  if (!nOpen) log << " nothing.";
776  }
777  // --- END DEBUG -------------------------------------------------------------
778 
779  // get which gates are active during the beam gate
780  PMTInfo_t const PMTinfo
781  { threshold, helper().extractActiveChannels(gates) };
782 
783  //
784  // 2. for each pattern:
785  //
786  for (auto const& [ iPattern, pattern ]: util::enumerate(fPatterns)) {
787 
788  auto& patternAlg = fPatternAlgs[iPattern];
789 
790  WindowTriggerInfo_t const triggerInfo
791  = patternAlg.simulateResponse(inBeamGates);
792 
793  registerTriggerResult(thresholdIndex, iPattern, triggerInfo.info);
794 
795  plotResponse(
796  thresholdIndex, threshold,
797  iPattern, pattern,
798  selectedPlots,
799  eventInfo, PMTinfo, triggerInfo
800  );
801 
802  } // for window patterns
803 
804  //
805  // 3. fill all trigger-independent plots (one copy per threshold... meh)
806  //
807  fillAllEventPlots(selectedPlots, eventInfo);
808 
809  //
810  // 4. fill all PMT plots (threshold-dependent)
811  //
812  fillAllPMTplots(selectedPlots, PMTinfo);
813 
814 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::simulateAndPlot()
815 
816 
817 //------------------------------------------------------------------------------
818 void
820  ()
821 {
822  fPatternAlgs.clear();
823  for (auto const& pattern: fPatterns)
824  fPatternAlgs.emplace_back(*fWindowMapMan, pattern, helper().logCategory());
825 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::initializePatternAlgorithms()
826 
827 
828 //------------------------------------------------------------------------------
830  (PlotSandboxRefs_t const& plotSets, EventInfo_t const& eventInfo) const
831 {
832  /*
833  * Now fill the plots independent of the trigger response:
834  * the same value is plotted in all plot sets.
835  * (again for all pertinent event categories, e.g. charged currents, etc.)
836  */
837  for (PlotSandbox const& plotSet: plotSets) {
838 
839  //
840  // general plots, independent of trigger definition details
841  //
842  fillEventPlots(eventInfo, plotSet);
843 
844  } // for
845 
846 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::fillAllEventPlots()
847 
848 
849 
850 //------------------------------------------------------------------------------
852  (PlotSandboxRefs_t const& plotSets, PMTInfo_t const& PMTinfo) const
853 {
854  /*
855  * Now fill the plots independent of the trigger response:
856  * the same value is plotted in all plot sets.
857  * (again for all pertinent event categories, e.g. charged currents, etc.)
858  */
859  for (PlotSandbox const& plotSet: plotSets) {
860 
861  //
862  // general plots, independent of trigger definition but dependent on
863  // threshold
864  //
865  fillPMTplots(PMTinfo, plotSet);
866 
867  } // for
868 
869 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::fillAllPMTplots()
870 
871 
873  std::size_t iThr, std::string const& threshold,
874  std::size_t iPattern, WindowPattern const& pattern,
875  PlotSandboxRefs_t const& plotSets,
876  EventInfo_t const& eventInfo,
877  PMTInfo_t const& PMTinfo,
878  WindowTriggerInfo_t const& triggerInfo
879 ) const {
880 
881  using namespace std::string_literals;
882 
883  bool const fired = triggerInfo.info.fired();
884 
885  if (fResponseTree) fResponseTree->assignResponse(iThr, iPattern, fired);
886 
887 
888  std::string const patternTag { pattern.tag() };
889 
890  // go through all the plot categories this event qualifies for
891  // (for example: charged currents, muon neutrinos, ...)
892  for (icarus::trigger::PlotSandbox const& plotSet: plotSets) {
893 
894  //
895  // overview plots from different thresholds
896  //
897 
898  HistGetter const get { plotSet };
899 
900  // simple efficiency
901  get.Eff("Eff"s).Fill(fired, iPattern);
902 
903  // simple count
904  if (fired) get.Hist("Triggers"s).Fill(iPattern);
905 
906  // trigger time (if any)
907  if (fired) {
908  get.Hist2D("TriggerTick"s).Fill
909  (iPattern, triggerInfo.info.atTick().value());
910  }
911 
912  //
913  // plots depending on the trigger response
914  // (but not caring of the trigger definition details)
915  //
916 
917  // efficiency plots
918  // (including event plots in the triggered or non-triggered category)
919  helper().fillAllEfficiencyPlots
920  (eventInfo, PMTinfo, triggerInfo.info, plotSet.demandSandbox(patternTag));
921 
922  //
923  // add here further trigger-specific plots
924  //
925 
926  } // for all qualifying plot categories
927 
928 } // icarus::trigger::SlidingWindowTriggerEfficiencyPlots::plotResponse()
929 
930 
931 //------------------------------------------------------------------------------
933 
934 
935 //------------------------------------------------------------------------------
BEGIN_PROLOG BeamGateDuration pmtthr physics producers trigtilewindowORS Thresholds
bool fired() const
Returns whether the trigger fired.
Obj * make(std::string const &name, std::string const &title, Args &&...args)
Creates a new ROOT object with the specified name and title.
Definition: PlotSandbox.h:701
Helper class to produce plots about trigger simulation and trigger efficiency.
Assembles the topology of trigger windows.
Class to extract and verify a window topology from trigger gates.
static constexpr Sample_t transform(Sample_t sample)
virtual void analyze(art::Event const &event) override
Fills the plots. Also extracts the information to fill them with.
::fhicl::Sequence< ::fhicl::TableAs< icarus::trigger::WindowPattern, WindowPatternConfig > > WindowPatternSequence
Configuration element for any number of trigger windows.
Definition of util::enumerate().
void plotResponse(std::size_t iThr, std::string const &threshold, std::size_t iPattern, WindowPattern const &pattern, PlotSandboxRefs_t const &plotSets, EventInfo_t const &eventInfo, PMTInfo_t const &PMTinfo, WindowTriggerInfo_t const &triggerInfo) const
Fills plots with the specified trigger response.
Class managing the serialization of trigger responses in a simple ROOT tree.
ResponseTree(TTree &tree, Thresholds const &thresholds, Requirements const &minReqs)
Constructor: accommodates that many thresholds and requirements.
void assignResponse(std::size_t iThr, std::size_t iReq, bool resp)
Assigns the response for the specified trigger.
auto gatesIn(TrackingGateColl &trackingGates)
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
void applyAxisLabels(TAxis *pAxis, std::vector< std::string > const &labels, int first=1)
Sets all the labels starting with the bin first (1 by default).
Definition: ROOTutils.h:175
TensorIndices class to flatten multi-dimension indices into linear.
Produces plots about trigger simulation and trigger efficiency.
Helper data structure to store transient trigger result.
Definition: TriggerInfo_t.h:50
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
timescale_traits< OpticalTimeCategory >::tick_interval_t optical_time_ticks
Specification of the requirement of sliding window firing pattern.
Definition: WindowPattern.h:51
std::vector< icarus::trigger::SlidingWindowPatternAlg > fPatternAlgs
All algorithm instances, one per pattern.
icarus::trigger::WindowPatterns_t WindowPatterns_t
List of configured patterns.
Access the description of detector geometry.
Information about the event.
void fillAllEventPlots(PlotSandboxRefs_t const &plotSets, EventInfo_t const &eventInfo) const
Fills all event plots with data from eventInfo as in fillEventPlots().
Converts a tensor element specification into a linear index.
Definition: TensorIndices.h:46
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
icarus::trigger::WindowTopologyManager fWindowMapMan
Mapping of each sliding window with location and topological information.
Defines a (sliding) window trigger pattern.
WindowPatterns_t const fPatterns
Configured sliding window requirement patterns.
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
Utilities to extend the interface of geometry vectors.
A bunch of diverse utilities and futilities related to ROOT.
geo::GeometryCore const & geometry() const
Returns the detector geometry service provider.
std::vector< PlotDef > plots
Definition: demo.h:54
Utilities for the conversion of trigger gate data formats.
BEGIN_PROLOG vertical distance to the surface Name
Helper data structure to store PMT activity information in the event.
Definition: PMTInfo_t.h:25
Test of util::counter and support utilities.
Simple class holding a tree.
Definition: TreeHolder.h:24
FHiCL configuration structure for icarus::trigger::WindowPattern.
Base class for _art_modules plotting trigger efficiencies.
virtual void simulateAndPlot(std::size_t const thresholdIndex, TriggerGatesPerCryostat_t const &gates, EventInfo_t const &eventInfo, detinfo::DetectorClocksData const &clockData, PlotSandboxRefs_t const &selectedPlots) override
Simulates all trigger minimum requirements plots the results.
SlidingWindowTriggerEfficiencyPlots const & helper() const
Access to the helper.
A wrapper to trigger gate objects tracking the contributions.
optical_tick atTick() const
Returns the time of the trigger (undefined if !fired()).
std::string tag() const
Returns a tag summarizing the pattern.
Contains all timing reference information for the detector.
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
Data types for detinfo::DetectorTimings.
Functions pulling in STL customization if available.
icarus::trigger::SlidingWindowPatternAlg::AllTriggerInfo_t WindowTriggerInfo_t
Data structure to communicate internally a trigger response.
Selected information about the event.
Definition: EventInfo_t.h:45
std::vector< std::reference_wrapper< PlotSandbox const >> PlotSandboxRefs_t
List of references to plot sandboxes.
fDetProps &fDetProps fDetProps &fDetProps detTimings
virtual void initializePlots(PlotCategories_t categories, std::vector< SettingsInfo_t > const &settings)
Initializes all the plot sets, one per PMT threshold.
std::vector< TriggerGates_t > TriggerGatesPerCryostat_t
Type of lists of gates, one list per cryostat (outer index: cryostat no).
std::vector< WindowPattern > WindowPatterns_t
A list of window patterns.
Definition: WindowPattern.h:25
void fillAllPMTplots(PlotSandboxRefs_t const &plotSets, PMTInfo_t const &PMTinfo) const
Fills all PMY plots with data from PMTinfo as in fillPMTplots().
Complete information from this algorithm, standard + non-standard (extra).
std::unique_ptr< ResponseTree > fResponseTree
Handler of ROOT tree output.
Applies sliding window trigger patterns.
virtual void initializePlotSet(PlotSandbox &plots, std::vector< SettingsInfo_t > const &settings) const override
Initializes full set of plots for (ADC threshold + category).
Provides sortBy() class of utilities.
A helper to manage ROOT objects in a art::TFileDirectory.
std::vector< InputTriggerGate_t > TriggerGates_t
A list of trigger gates from input.
fDetProps &fDetProps fDetProps &fDetProps consumesCollector())
A helper to manage ROOT objects with consistent naming.
Definition: PlotSandbox.h:95