All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TriggerSimulationOnGates_module.cc
Go to the documentation of this file.
1 /**
2  * @file TriggerSimulationOnGates_module.cc
3  * @brief Plots of efficiency for triggers based on PMT sliding windows.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date March 27, 2021
6  */
7 
8 
9 // ICARUS libraries
11 #include "icaruscode/PMT/Trigger/Algorithms/WindowTopologyAlg.h" // WindowTopologyManager
19 #include "icaruscode/PMT/Trigger/Utilities/TriggerDataUtils.h" // FillTriggerGates()
21 #include "icarusalg/Utilities/ROOTutils.h" // util::ROOT
23 #include "icaruscode/Utilities/DetectorClocksHelpers.h" // makeDetTimings()...
27 #include "icarusalg/Utilities/ChangeMonitor.h" // ThreadSafeChangeMonitor
28 #include "icarusalg/Utilities/rounding.h" // icarus::ns::util::roundup()
29 
30 // LArSoft libraries
33 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
36 #include "lardataalg/DetectorInfo/DetectorTimingTypes.h" // optical_tick...
37 #include "lardataalg/Utilities/quantities/spacetime.h" // microseconds, ...
38 #include "lardataalg/Utilities/intervals_fhicl.h" // microseconds from FHiCL
42 #include "larcorealg/CoreUtils/values.h" // util::const_values()
43 #include "larcorealg/CoreUtils/get_elements.h" // util::get_elements()
45 #include "larcorealg/CoreUtils/StdUtils.h" // util::to_string()
47 #include "lardataobj/RawData/TriggerData.h" // raw::Trigger
48 #include "lardataobj/RawData/OpDetWaveform.h" // raw::ADC_Count_t
49 #include "larcoreobj/SimpleTypesAndConstants/geo_types.h" // geo::CryostatID
50 
51 // framework libraries
52 #include "art_root_io/TFileService.h"
53 #include "art_root_io/TFileDirectory.h"
54 #include "art/Framework/Services/Registry/ServiceHandle.h"
55 #include "art/Framework/Core/EDProducer.h"
56 #include "art/Framework/Core/ModuleMacros.h"
57 #include "art/Framework/Principal/Event.h"
58 #include "canvas/Utilities/InputTag.h"
59 #include "canvas/Utilities/Exception.h"
60 #include "messagefacility/MessageLogger/MessageLogger.h"
61 #include "fhiclcpp/types/Sequence.h"
62 #include "fhiclcpp/types/OptionalAtom.h"
63 #include "fhiclcpp/types/Atom.h"
64 
65 // ROOT libraries
66 #include "TEfficiency.h"
67 #include "TH1F.h"
68 #include "TH2F.h"
69 #include "TGraph.h"
70 
71 // C/C++ standard libraries
72 #include <ostream>
73 #include <algorithm> // std::fill()
74 #include <map>
75 #include <vector>
76 #include <memory> // std::make_unique()
77 #include <string>
78 #include <atomic>
79 #include <optional>
80 #include <utility> // std::pair<>, std::move()
81 #include <cmath> // std::ceil()
82 #include <cstddef> // std::size_t
83 #include <cassert>
84 
85 
86 //------------------------------------------------------------------------------
87 using namespace util::quantities::time_literals;
88 
89 
90 //------------------------------------------------------------------------------
91 namespace icarus::trigger { class TriggerSimulationOnGates; }
92 /**
93  * @brief Simulates a sliding window trigger at specified gate times.
94  *
95  * This module produces `raw::Trigger` objects each representing the outcome of
96  * some trigger logic applied to discriminated optical detector input
97  * ("trigger primitives").
98  * The logic is applied to each event at multiple times, according to a list
99  * of time intervals read from each event.
100  *
101  * The main purpose of this module is to simulate the trigger logic at times of
102  * special interest, typically the times some track is believed to have crossed
103  * the detector.
104  *
105  * A trigger primitive is a two-level function of time which describes when
106  * that primitive is on and when it is off. Trigger primitives are given as
107  * input to this module and their origin may vary, but the standard source in
108  * ICARUS is @ref ICARUSPMTTriggerGlossary "single trigger request (LVDS)".
109  *
110  * This module applies a sliding window pattern to the input: the pattern
111  * consists of a requirement on the main window and optional additional
112  * requirements on the neighbouring windows. This module rebases the configured
113  * pattern on each of the available windows, evaluates the requirement of the
114  * pattern in that configuration, and decides whether those requirements are
115  * met. The general trigger is considered passed if _any_ of the rebased
116  * patterns satisfies the requirement at any time, and no special treatment is
117  * performed in case multiple windows fulfil them, except that the trigger time
118  * is driven by the earliest of the satisfied patterns.
119  *
120  * A single trigger pattern is configured for each instance of the module,
121  * while multiple input sets (e.g. with different discrimination thresholds)
122  * can be processed on the same pattern by the same module instance.
123  * Conversely, testing a different pattern requires the instantiation of a new
124  * module.
125  *
126  *
127  * Configuration
128  * ==============
129  *
130  * * `TriggerGatesTag` (string, mandatory): name of the module instance which
131  * produced the trigger primitives to be used as input; it must not include
132  * any instance name, as the instance names will be automatically added from
133  * `Thresholds` parameter.
134  * The typical trigger primitives used as input are LVDS discriminated
135  * output combined into trigger windows (e.g. from
136  * `icarus::trigger::SlidingWindowTrigger` module).
137  * * `Thresholds` (list of names, mandatory): list of the discrimination
138  * thresholds to consider. A data product containing a digital signal is
139  * read for each one of the thresholds, and the tag of the data product is
140  * expected to be the instance name in this configuration parameter for the
141  * module label set in `TriggerGatesTag` (e.g. for a threshold of
142  * `"60"`, supposedly 60 ADC counts, and with `TriggerGatesTag` set to
143  * `"TrigSlidingWindows"`, the data product tag would be
144  * `TrigSlidingWindows:60`).
145  * * `KeepThresholdName` (flag, optional): by default, output data products have
146  * each an instance name according to their threshold (from the `Threshold`
147  * parameter), unless there is only one threshold specified. If this
148  * parameter is specified as `true`, the output data product always
149  * includes the threshold instance name, even when there is only one
150  * threshold specified. If this parameter is specified as `false`, if there
151  * is only one threshold the default behaviour (of not adding an instance
152  * name) is confirmed; otherwise, it is a configuration error to have this
153  * parameter set to `false`.
154  * * `Pattern` (configuration table, mandatory): describes the sliding window
155  * pattern; the configuration format for a pattern is described under
156  * `icarus::trigger::ns::fhicl::WindowPatternConfig`.
157  * * `BeamGates` (input tag, _mandatory_): the data product with the beam gates
158  * * to run the simulation in;
159  * * `BeamBits` (bitmask as 32-bit integral number): bits to be set in the
160  * produced `raw::Trigger` objects (see also `daq::TriggerDecoder` tool).
161  * * `LogCategory` (string, default `TriggerSimulationOnGates`): name of
162  * category used to stream messages from this module into message facility.
163  *
164  * An example job configuration is provided as
165  * `simulate_sliding_window_trigger_icarus.fcl`.
166  *
167  *
168  * Input data products
169  * ====================
170  *
171  * * `TriggerGatesTag` + `Thresholds`: input gate collections.
172  * * `BeamGates` (`std::vector<sim::BeamGateInfo>`): the beam gate intervals
173  * to run the simulation on; one trigger result is produced and saved for
174  * each of the gates in this data product. The gates are interpreted
175  * following LArSoft convention for the simulation, with the times in
176  * nanoseconds and in
177  * @ref DetectorClocksSimulationTime "simulation time reference".
178  *
179  *
180  * Output data products
181  * =====================
182  *
183  * * `std::vector<raw::Trigger>` (one instance per ADC threshold):
184  * list of triggers fired according to the configured trigger definition;
185  * there is one collection (and data product) per ADC threshold, and the
186  * data product has the same instance name as the input data one, unless
187  * there is only one threshold (see `TriggerGatesTag`, `Thresholds` and
188  * `KeepThresholdName` configuration parameters);
189  * one trigger object is produced for each of the beam gates found in the
190  * input data product specified by the `BeamGates` parameter.
191  * Each trigger object has the time stamp matching the first time the trigger
192  * criteria are satisfied. All triggers feature the bits specified in
193  * `BeamBits` configuration parameter.
194  *
195  *
196  *
197  * Trigger logic algorithm
198  * ========================
199  *
200  * @anchor TriggerSimulationOnGates_Algorithm
201  *
202  * This section describes the trigger logic algorithm used in
203  * `icarus::trigger::TriggerSimulationOnGates` and its assumptions.
204  * Nevertheless, more up-to-date information can be found in
205  * `SlidingWindowTrigger` module (for the combination of the LVDS signals into
206  * window-wide gates) and in `icarus::trigger::SlidingWindowPatternAlg`,
207  * which applies the configured pattern logic to the input.
208  *
209  * The module receives as input a multi-level trigger gate for each of the
210  * windows to be considered.
211  * On the first input (i.e. the first event), that input is parsed to learn
212  * the windows and their relative position from the input trigger gates.
213  * This topology will be used to apply the configured patterns. On the following
214  * events, their input is checked to confirm the compatibility of the
215  * composition of its windows with the one from that first event (both aspects
216  * are handled by an `icarus::trigger::WindowTopologyManager` object).
217  *
218  * All multi-level gates are set in coincidence with the beam gate by
219  * multiplying the multi-level and the beam gates. Because of this, trigger
220  * gates are suppressed everywhere except than during the beam gate (see below).
221  * The reference time for the beam gates is the time configured in
222  * `DetectorClocks` service provider
223  * (`detinfo::DetectorClocks::BeamGateTime()`).
224  *
225  * The algorithm handles independently multiple trigger patterns.
226  * On each input, each configured pattern is applied based on the window
227  * topology. Each pattern describes a minimum level of the trigger
228  * gate in the window, that usually means the number of LVDS signals in
229  * coincidence at any given time ("majority"). A pattern may have requirements
230  * on the neighbouring windows in addition to the main one. The pattern is
231  * satisfied if all involved windows pass their specific requirements at the
232  * same time (coincidence between windows).
233  * Each pattern is applied in turn to each of the windows (which is the "main"
234  * window). The neighborhood described in the pattern is applied with respect to
235  * that main window. The trigger fires if one or more of the windows satisfy
236  * the pattern, and the trigger time is the one of the earliest satisfied
237  * pattern (more precisely, the earliest tick when the coincidence required
238  * by that pattern is satisfied).*
239  * All windows in the detector are considered independently, but the supported
240  * patterns may only include components in the same cryostat. Therefore,
241  * triggers are effectively on a single cryostat.
242  * An object of class `icarus::trigger::SlidingWindowPatternAlg` applies this
243  * logic: see its documentation for the most up-to-date details.
244  *
245  * Eventually, for each event there are as many different trigger responses as
246  * how many different patterns are configured (`Patterns` configuration
247  * parameter), _times_ how many ADC thresholds are provided in input,
248  * configured in `Thresholds`.
249  *
250  *
251  * Beam gates
252  * -----------
253  *
254  * A single instance of this module can perform the simulation on several beam
255  * gates. The values of these beam gates are picked from the data product
256  * specified in `BeamGates`, event by event. The specified beam gate times are
257  * on beam gate time scale, i.e. their reference time `0` is the time of the
258  * beam gate as known by `detinfo::DetectorClocks::BeamGateTime()`.
259  * In case the same beam gate is desired for all events, such data product can
260  * be produced by `icarus::trigger::WriteBeamGateInfo` module.
261  * The trigger data product collection produced by this module has the same
262  * number of entries as the beam gates in the data product, and they match
263  * one-to-one.
264  *
265  *
266  *
267  * Technical aspects of the module
268  * --------------------------------
269  *
270  * @anchor TriggerSimulationOnGates_Tech
271  *
272  * This module does not build the trigger gates of the sliding windows, but
273  * rather it takes them as input (see e.g. `SlidingWindowTrigger` module).
274  * Window topology (size of the windows and their relations) is stored in
275  * `icarus::trigger::WindowChannelMap` objects, and its construction is
276  * delegated to `icarus::trigger::WindowTopologyAlg` (under the hood of the
277  * `WindowTopologyManager` class) which learns it from the actual trigger gate
278  * input rather than on explicit configuration. Pattern definitions and
279  * configuration are defined in `icarus::trigger::WindowPattern` and
280  * `icarus::trigger::ns::fhicl::WindowPatternConfig` respectively. Trigger
281  * simulation is delegated to `icarus::trigger::SlidingWindowPatternAlg`.
282  *
283  *
284  * @todo Plots need to be thought and implemented.
285  *
286  */
288  : public art::EDProducer
290 {
291 
292  public:
293 
296 
297 
298  // --- BEGIN Configuration ---------------------------------------------------
299  struct Config {
300 
301  using Name = fhicl::Name;
302  using Comment = fhicl::Comment;
303 
304  fhicl::Atom<std::string> TriggerGatesTag {
305  Name("TriggerGatesTag"),
306  Comment("label of the input trigger gate data product (no instance name)")
307  };
308 
309  fhicl::Sequence<std::string> Thresholds {
310  Name("Thresholds"),
311  Comment("tags of the thresholds to consider")
312  };
313 
314  fhicl::OptionalAtom<bool> KeepThresholdName {
315  Name("KeepThresholdName"),
316  Comment
317  ("add threshold to output product tag even with only one threshold")
318  };
319 
321  Name("Pattern"),
322  Comment("trigger requirements as a trigger window pattern")
323  };
324 
325  fhicl::Atom<art::InputTag> BeamGates {
326  Name("BeamGates"),
327  Comment("data product with all beam gates to run simulation into")
328  };
329 
330  fhicl::Atom<std::uint32_t> BeamBits {
331  Name("BeamBits"),
332  Comment("bits to be set in the trigger object as beam identified")
333  };
334 
335  fhicl::Atom<nanoseconds> TriggerTimeResolution {
336  Name("TriggerTimeResolution"),
337  Comment("resolution of trigger in time"),
338  25_ns
339  };
340 
341  fhicl::Atom<double> EventTimeBinning {
342  Name("EventTimeBinning"),
343  Comment("binning for the trigger time plot [second]"),
344  300 // 5 minutes
345  };
346 
347  fhicl::Atom<std::string> LogCategory {
348  Name("LogCategory"),
349  Comment("name of the category used for the output"),
350  "TriggerSimulationOnGates" // default
351  };
352 
353  }; // struct Config
354 
355  using Parameters = art::EDProducer::Table<Config>;
356  // --- END Configuration -----------------------------------------------------
357 
358 
359  // --- BEGIN Constructors ----------------------------------------------------
360  explicit TriggerSimulationOnGates(Parameters const& config);
361 
362  // --- END Constructors ------------------------------------------------------
363 
364 
365  // --- BEGIN Framework hooks -------------------------------------------------
366 
367  /// Initializes the plots.
368  virtual void beginJob() override;
369 
370  /// Runs the simulation and saves the results into the _art_ event.
371  virtual void produce(art::Event& event) override;
372 
373  /// Prints end-of-job summaries.
374  virtual void endJob() override;
375 
376  // --- END Framework hooks ---------------------------------------------------
377 
378 
379  private:
380 
381  using TriggerInfo_t = details::TriggerInfo_t; ///< Type alias.
382 
383  /// Type of trigger gate extracted from the input event.
384  using InputTriggerGate_t
386 
387  /// List of trigger gates.
388  using TriggerGates_t
390 
391  /// Data structure to communicate internally a trigger response.
392  using WindowTriggerInfo_t
394 
395  /// Content for future histograms, binned.
397 
398  /// All information needed to generate plots for a specific threshold.
404  };
405 
406  /// Type of list of gates to simulate trigger into.
407  using BeamGates_t = std::vector<sim::BeamGateInfo>;
408 
409 
410  // --- BEGIN Configuration variables -----------------------------------------
411 
412  /// Name of ADC thresholds to read, and the input tag connected to their data.
413  std::map<std::string, art::InputTag> fADCthresholds;
414 
415  /// Configured sliding window requirement pattern.
417 
418  art::InputTag const fBeamGateTag; ///< Data product of beam gates to simulate.
419 
420  std::uint32_t fBeamBits; ///< Bits for the beam gate being simulated.
421 
422  nanoseconds fTriggerTimeResolution; ///< Trigger resolution in time.
423 
424  double fEventTimeBinning; ///< Trigger time plot binning [s]
425 
426  /// Message facility stream category for output.
427  std::string const fLogCategory;
428 
429  // --- END Configuration variables -------------------------------------------
430 
431 
432  // --- BEGIN Service variables -----------------------------------------------
433 
434  /// ROOT directory where all the plots are written.
435  art::TFileDirectory fOutputDir;
436 
437  // --- END Service variables -------------------------------------------------
438 
439 
440  // --- BEGIN Internal variables ----------------------------------------------
441 
442  /// Output data product instance names (same order as `fADCthresholds`).
443  std::vector<std::string> fOutputInstances;
444 
445  /// Mapping of each sliding window with location and topological information.
446  // mutable = not thread-safe
448 
449  /// Pattern algorithm.
450  std::optional<icarus::trigger::SlidingWindowPatternAlg> fPatternAlg;
451 
452  /// All plots in one practical sandbox.
454 
455  /// Proto-histogram information in a convenient packet; event-wide.
457 
458  /// Proto-histogram information in a not-so-practical array; per threshold.
459  std::vector<ThresholdPlotInfo_t> fThresholdPlots;
460 
461  ///< Count of fired triggers, per threshold.
462  std::vector<std::atomic<unsigned int>> fTriggerCount;
463  std::atomic<unsigned int> fTotalGates { 0U }; ///< Count of opened gates.
464 
465 
466  // --- END Internal variables ------------------------------------------------
467 
468 
469  // --- BEGIN --- Plot infrastructure -----------------------------------------
470 
471  /// @brief Initializes the full set of plots (all ADC thresholds).
472  void initializePlots();
473 
474  /// Creates summary plots from proto-histogram data.
475  void finalizePlots();
476 
477  /// Creates in `plots` sandbox all plots for threshold `threshold` from data
478  /// in `plotInfo`.
479  void makeThresholdPlots(
480  std::string const& threshold,
482  ThresholdPlotInfo_t const& plotInfo
483  );
484 
485  /// Creates in the main sandbox all event-wide plots.
486  void makeEventPlots();
487 
488  /// Fills event-wide plots.
489  void plotEvent(
490  art::Event const& event, detinfo::DetectorTimings const& detTimings,
491  std::vector<icarus::trigger::ApplyBeamGateClass> const& gates
492  );
493 
494  /// Fills the plots for threshold index `iThr` with trigger information.
495  void plotTriggerResponse(
496  std::size_t iThr, std::string const& thrTag,
497  WindowTriggerInfo_t const& triggerInfo,
499  );
500 
501  // --- END ----- Plot infrastructure -----------------------------------------
502 
503  /**
504  * @brief Performs the simulation for the specified ADC threshold.
505  * @param event _art_ event to read data from and put results into
506  * @param detTimings detector clocks service provider proxy
507  * @param beamGates list of all beam gates to evaluate
508  * @param iThr index of the threshold in the configuration
509  * @param thr value of the threshold (ADC counts)
510  * @param firstTriggerNumber the next unassigned trigger number
511  * @return the trigger response information
512  *
513  * For the given threshold, the simulation of the configured trigger is
514  * performed.
515  * The input data is read from the event (the source tag is from the module
516  * configuration), simulation is performed, auxiliary plots are drawn and
517  * a `raw::Trigger` collection is stored into the event.
518  *
519  * The stored collection contains either one or zero `raw::Trigger` elements.
520  *
521  * The simulation itself is performed by the `simulate()` method.
522  */
523  std::vector<WindowTriggerInfo_t> produceForThreshold(
524  art::Event& event,
526  std::vector<ApplyBeamGateClass> const& beamGates,
527  std::size_t const iThr, std::string const& thrTag,
528  unsigned int firstTriggerNumber
529  );
530 
531  /**
532  * @brief Converts the trigger information into a `raw::Trigger` object.
533  * @param triggerNumber the unique number to assign to this trigger
534  * @param info the information about the fired trigger
535  * @return a `raw::Trigger` object with all the information encoded
536  *
537  * The trigger described by `info` is encoded into a `raw::Trigger` object.
538  * The trigger _must_ have fired.
539  */
540  raw::Trigger triggerInfoToTriggerData(
542  ApplyBeamGateClass const& beamGate,
543  unsigned int triggerNumber, WindowTriggerInfo_t const& info
544  ) const;
545 
546 
547  /// Prints the summary of fired triggers on screen.
548  void printSummary() const;
549 
550  /// Creates and returns a 1D histogram filled with `binnedContent`.
551  TH1* makeHistogramFromBinnedContent(
553  std::string const& name, std::string const& title,
554  BinnedContent_t const& binnedContent
555  ) const;
556 
557  /// Shortcut to create an `ApplyBeamGate` with the specified `gate`.
560  {
561  // the input gate is assumed to be relative to the global beam gate
562  // opening (which is the implicit convention of simulation time and of
563  // sim::BeamGateInfo in my understanding - [petrillo@slac.stanford.edu])
564  // so it does not need further processing here
565  return makeApplyBeamGate(
566  nanoseconds{ gate.Width() }, nanoseconds{ gate.Start() },
567  detTimings.clockData(), fLogCategory
568  );
569  }
570 
571  //@{
572  /// Shortcut to create `ApplyBeamGate` from a list of gates.
573  std::vector<icarus::trigger::ApplyBeamGateClass> makeMyBeamGates
574  (detinfo::DetectorTimings const& detTimings, BeamGates_t const& gates) const
575  {
576  std::vector<icarus::trigger::ApplyBeamGateClass> applyGates;
577  for (sim::BeamGateInfo const& gate: gates)
578  applyGates.push_back(makeMyBeamGate(detTimings, gate));
579  return applyGates;
580  }
581  std::vector<icarus::trigger::ApplyBeamGateClass> makeMyBeamGates
582  (art::Event const* event, BeamGates_t const& gates) const
583  { return makeMyBeamGates(icarus::ns::util::makeDetTimings(event), gates); }
584  std::vector<icarus::trigger::ApplyBeamGateClass> makeMyBeamGates
585  (art::Event const& event, BeamGates_t const& gates) const
586  { return makeMyBeamGates(&event, gates); }
587  //@}
588 
589 
590  //@{
591  /// Returns the time of the event in seconds from The Epoch.
592  static double eventTimestampInSeconds(art::Timestamp const& time);
593  static double eventTimestampInSeconds(art::Event const& event);
594  //@}
595 
596 }; // icarus::trigger::TriggerSimulationOnGates
597 
598 
599 
600 //------------------------------------------------------------------------------
601 //--- Implementation
602 //------------------------------------------------------------------------------
604  (Parameters const& config)
605  : art::EDProducer (config)
606  // configuration
607  , fPattern (config().Pattern())
608  , fBeamGateTag (config().BeamGates())
609  , fBeamBits (config().BeamBits())
610  , fTriggerTimeResolution(config().TriggerTimeResolution())
611  , fEventTimeBinning (config().EventTimeBinning())
612  , fLogCategory (config().LogCategory())
613  // services
614  , fOutputDir (*art::ServiceHandle<art::TFileService>())
615  // internal and cached
616  , fWindowMapMan
617  { *lar::providerFrom<geo::Geometry>(), fLogCategory + "_WindowMapManager" }
618  , fPlots(
619  fOutputDir, "", "requirement: " + fPattern.description()
620  )
621  , fEventPlotInfo{
622  BinnedContent_t{ fEventTimeBinning } // eventTimes
623  , BinnedContent_t{ // HWtrigTimeVsBeam
624  fTriggerTimeResolution.convertInto
625  <detinfo::timescales::trigger_time::interval_t>().value()
626  }
627  , BinnedContent_t{ // triggerTimesVsHWtrig
628  fTriggerTimeResolution.convertInto
629  <detinfo::timescales::trigger_time::interval_t>().value()
630  }
631  , BinnedContent_t{ // triggerTimesVsBeam
632  fTriggerTimeResolution.convertInto
633  <detinfo::timescales::trigger_time::interval_t>().value()
634  }
635  }
636 {
637 
638  //
639  // more complex parameter parsing
640  //
641  std::string const& discrModuleLabel = config().TriggerGatesTag();
642  for (std::string const& threshold: config().Thresholds())
643  fADCthresholds[threshold] = art::InputTag{ discrModuleLabel, threshold };
644 
645  // initialization of a vector of atomic is not as trivial as it sounds...
646  fTriggerCount = std::vector<std::atomic<unsigned int>>(fADCthresholds.size());
647  std::fill(fTriggerCount.begin(), fTriggerCount.end(), 0U);
648 
649  //
650  // input data declaration
651  //
652  using icarus::trigger::OpticalTriggerGateData_t; // for convenience
653 
654  // trigger primitives
655  for (art::InputTag const& inputDataTag: util::const_values(fADCthresholds)) {
658  } // for
659 
660  //
661  // output data declaration
662  //
663  // keepThresholdName is true if we write instance name in output data products
664  bool const keepThresholdName
665  = config().KeepThresholdName().value_or(config().Thresholds().size() > 1);
666  if (!keepThresholdName && (config().Thresholds().size() > 1)) {
667  throw art::Exception(art::errors::Configuration)
668  << config().KeepThresholdName.name()
669  << " can be set to `true` only when a single threshold is specified ("
670  << config().Thresholds.name() << " has " << config().Thresholds().size()
671  << ")";
672  }
673 
674  for (auto const& inputDataTag: util::const_values(fADCthresholds)) {
675  std::string const outputInstance
676  = keepThresholdName? inputDataTag.instance(): "";
677  produces<std::vector<raw::Trigger>>(outputInstance);
678  fOutputInstances.push_back(outputInstance);
679  }
680 
681  {
682  mf::LogInfo log(fLogCategory);
683  log << "\nConfigured " << fADCthresholds.size() << " thresholds (ADC):";
684  for (auto const& [ thresholdTag, dataTag ]: fADCthresholds)
685  log << "\n * " << thresholdTag << " (from '" << dataTag.encode() << "')";
686 
687  } // local block
688 
689 
690 } // icarus::trigger::TriggerSimulationOnGates::TriggerSimulationOnGates()
691 
692 
693 //------------------------------------------------------------------------------
695 
696  initializePlots();
697 
698 } // icarus::trigger::TriggerSimulationOnGates::beginJob()
699 
700 
701 //------------------------------------------------------------------------------
703 {
704 
705  //
706  // prepare all the gates to run the simulation on
707  //
708  detinfo::DetectorTimings const detTimings {
709  art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event)
710  };
711 
712  std::vector<icarus::trigger::ApplyBeamGateClass> const beamGates {
713  makeMyBeamGates(
714  detTimings,
715  event.getProduct<std::vector<sim::BeamGateInfo>>(fBeamGateTag)
716  )
717  };
718 
719 
720  { // BEGIN local block
721  mf::LogDebug log { fLogCategory };
722  log << "Trigger simulation for " << beamGates.size() << " gates";
723  if (!beamGates.empty()) {
724  log << " ('" << fBeamGateTag.encode() << "'):";
725  for (auto const& [iGate, gate]: util::enumerate(beamGates)) {
726  log << "\n [" << iGate << "] " << gate;
727  } // for
728  } // if
729  } // END local block
730 
731 
732  //
733  // run the simulation on each threshold in turn
734  //
735  mf::LogDebug log(fLogCategory); // this will print at the end of produce()
736  log << "Event " << event.id() << ":";
737 
738  // FIXME these two operations should be atomic
739  unsigned int const firstTriggerNumber
740  = fTotalGates.fetch_add(beamGates.size());
741 
742  for (auto const& [ iThr, thrTag ]
743  : util::enumerate(util::get_elements<0U>(fADCthresholds))
744  ) {
745 
746  std::vector<WindowTriggerInfo_t> const triggers = produceForThreshold
747  (event, detTimings, beamGates, iThr, thrTag, firstTriggerNumber);
748 
749  log << "\n * threshold " << thrTag << ": ";
750  icarus::ns::util::PassCounter gateResults;
751  for (WindowTriggerInfo_t const& triggerInfo: triggers)
752  gateResults.add(triggerInfo.info.fired());
753  log << gateResults.passed() << "/" << gateResults.total()
754  << " gates triggered";
755 
756  } // for
757 
758  //
759  // event-level plots
760  //
761  plotEvent(event, detTimings, beamGates);
762 
763 } // icarus::trigger::TriggerSimulationOnGates::produce()
764 
765 
766 //------------------------------------------------------------------------------
768 
769  finalizePlots();
770 
771  printSummary();
772 
773 } // icarus::trigger::TriggerSimulationOnGates::endJob()
774 
775 
776 //------------------------------------------------------------------------------
778 
779 #if 0
780  //
781  // overview plots with different settings
782  //
783 
784  std::vector<std::string> thresholdLabels;
785  thresholdLabels.reserve(size(fADCthresholds));
786  for (std::string thr: util::get_elements<0U>(fADCthresholds))
787  thresholdLabels.push_back(std::move(thr));
788 
789  auto const beamGate = makeMyBeamGate();
790  mf::LogInfo(fLogCategory)
791  << "Beam gate for plots: " << beamGate.asSimulationTime()
792  << " (simulation time), " << beamGate.tickRange()
793  << " (optical ticks)"
794  ;
795 
796  //
797  // Triggering efficiency vs. ADC threshold.
798  //
799  auto* NTriggers = fPlots.make<TH1F>(
800  "NTriggers",
801  "Number of triggering events"
802  ";PMT discrimination threshold [ ADC counts ]"
803  ";events",
804  thresholdLabels.size(), 0.0, double(thresholdLabels.size())
805  );
806  util::ROOT::applyAxisLabels(NTriggers->GetXaxis(), thresholdLabels);
807 
808  auto* Eff = fPlots.make<TEfficiency>(
809  "Eff",
810  "Triggering pass fraction"
811  ";PMT discrimination threshold [ ADC counts ]"
812  ";trigger pass fraction",
813  thresholdLabels.size(), 0.0, double(thresholdLabels.size())
814  );
815  // people are said to have earned hell for things like this;
816  // but TEfficiency really does not expose the interface to assign labels to
817  // its axes, which supposedly could be done had we chosen to create it by
818  // histograms instead of directly as recommended.
820  (const_cast<TH1*>(Eff->GetTotalHistogram())->GetXaxis(), thresholdLabels);
821 
822  detinfo::timescales::optical_time_ticks const triggerResolutionTicks{
823  icarus::ns::util::makeDetTimings().toOpticalTicks(fTriggerTimeResolution)
824  };
825 
826  auto const& beamGateTicks = beamGate.tickRange();
827  auto* TrigTime = fPlots.make<TH2F>(
828  "TriggerTick",
829  "Trigger time tick"
830  ";optical time tick [ /" + util::to_string(triggerResolutionTicks) + " ]"
831  ";PMT discrimination threshold [ ADC counts ]"
832  ";events",
833  static_cast<int>(std::ceil(beamGate.lengthTicks()/triggerResolutionTicks)),
834  beamGateTicks.start().value(),
836  (beamGateTicks.start() + beamGate.lengthTicks(), triggerResolutionTicks)
837  .value(),
838  thresholdLabels.size(), 0.0, double(thresholdLabels.size())
839  );
840  util::ROOT::applyAxisLabels(TrigTime->GetYaxis(), thresholdLabels);
841 
842 
843  // we allow some fixed margin in the plot, just in case:
844  constexpr microseconds beamPlotPadding { 4_us };
845 
847 
848  // hardware trigger may happen at any place within the beam gate,
849  // and in this plot range I want to include the full beam gate;
850  // so I take a beam gate worth of time before the trigger time,
851  // and as much after it; since this plot is relative to the hardware trigger,
852  // the hardware trigger time itself is 0
853  icarus::ns::util::BinningSpecs const HWtrigBinning = alignBinningTo(
855  (- beamGate.length() - beamPlotPadding).value(),
856  (beamGate.length() + beamPlotPadding).value(),
857  fTriggerTimeResolution.convertInto<trigger_time::interval_t>().value()
858  },
859  0.0
860  );
861  fPlots.make<TH2F>(
862  "TriggerTimeVsHWTrig",
863  "Time of the trigger"
864  ";trigger time (relative to hardware trigger) [ #mus ]"
865  ";PMT discrimination threshold [ ADC counts ]"
866  ";triggers",
867  HWtrigBinning.nBins(), HWtrigBinning.lower(), HWtrigBinning.upper(),
868  thresholdLabels.size(), 0.0, double(thresholdLabels.size())
869  );
870 
871  icarus::ns::util::BinningSpecs const beamGateBinning = alignBinningTo(
873  (-beamPlotPadding).value(),
874  (beamGate.length() + beamPlotPadding).value(),
875  fTriggerTimeResolution.convertInto<trigger_time::interval_t>().value()
876  },
877  0.0
878  );
879  fPlots.make<TH2F>(
880  "TriggerTimeVsBeamGate",
881  "Time of the trigger"
882  ";trigger time (relative to beam gate opening) [ #mus ]"
883  ";PMT discrimination threshold [ ADC counts ]"
884  ";triggers",
885  beamGateBinning.nBins(), beamGateBinning.lower(), beamGateBinning.upper(),
886  thresholdLabels.size(), 0.0, double(thresholdLabels.size())
887  );
888 
889  //
890  // per-threshold plots; should this initialization be set into its own method?
891  //
892  for (auto const& [ thr, info ]
893  : util::zip(util::get_elements<0U>(fADCthresholds), fThresholdPlots))
894  {
896  = fPlots.addSubSandbox("Thr" + thr, "Threshold: " + thr);
897 
898  plots.make<TGraph>(
899  "TriggerTimeVsHWTrigVsBeam",
900  "Time of the trigger: emulated vs. hardware"
901  ";hardware trigger time (relative to beam gate opening) [ #mus ]"
902  ";emulated trigger time (relative to beam gate opening) [ #mus ]"
903  );
904 
905  } // for thresholds
906 
907  fThresholdPlots.resize(
908  size(fADCthresholds),
909  {
910  BinnedContent_t{ fEventTimeBinning }, // eventTimes
911  BinnedContent_t{ HWtrigBinning.binWidth() }, // HWtrigTimeVsBeam
912  BinnedContent_t{ HWtrigBinning.binWidth() }, // triggerTimesVsHWtrig
913  BinnedContent_t{ beamGateBinning.binWidth() } // triggerTimesVsBeam
914  }
915  );
916 
917 #endif // 0
918 
919 } // icarus::trigger::TriggerSimulationOnGates::initializePlots()
920 
921 
922 //------------------------------------------------------------------------------
924 
925 #if 0
926 
927  for (auto const& [ thr, info ]
928  : util::zip(util::get_elements<0U>(fADCthresholds), fThresholdPlots))
929  {
930  icarus::trigger::PlotSandbox& plots = fPlots.demandSandbox("Thr" + thr);
931  makeThresholdPlots(thr, plots, info);
932  if (plots.empty()) fPlots.deleteSubSandbox(plots.name());
933  } // for thresholds
934 
935  makeEventPlots();
936 
937 #endif // 0
938 
939 } // icarus::trigger::TriggerSimulationOnGates::finalizePlots()
940 
941 
942 //------------------------------------------------------------------------------
944  std::string const& threshold,
946  ThresholdPlotInfo_t const& plotInfo
947 ) {
948 
949 #if 0
950 
951  BinnedContent_t const* content;
952 
953  content = &(plotInfo.eventTimes);
954  makeHistogramFromBinnedContent(plots,
955  "TriggerTime",
956  "Time of the triggered events"
957  ";time"
958  ";triggered events [ / " + std::to_string(content->binWidth())
959  + "\" ]",
960  *content
961  );
962 
963  content = &(plotInfo.HWtrigTimeVsBeam);
964  makeHistogramFromBinnedContent(plots,
965  "HWTrigVsBeam",
966  "Time of the hardware trigger"
967  ";trigger time (relative to beam gate) [ #mus ]"
968  ";events [ / " + std::to_string(content->binWidth())
969  + " #mus ]",
970  *content
971  );
972 
973  content = &(plotInfo.triggerTimesVsHWtrig);
974  makeHistogramFromBinnedContent(plots,
975  "TriggerTimeVsHWTrig",
976  "Time of the trigger"
977  ";trigger time (relative to hardware trigger) [ #mus ]"
978  ";triggers [ / " + std::to_string(content->binWidth())
979  + " #mus ]",
980  *content
981  );
982 
983  content = &(plotInfo.triggerTimesVsBeam);
984  makeHistogramFromBinnedContent(plots,
985  "TriggerTimeVsBeamGate",
986  "Time of the trigger"
987  ";trigger time (relative to beam gate opening) [ #mus ]"
988  ";triggers [ / " + std::to_string(content->binWidth())
989  + " #mus ]",
990  *content
991  );
992 
993 #endif // 0
994 
995 } // icarus::trigger::TriggerSimulationOnGates::makeThresholdPlots()
996 
997 
998 
999 //------------------------------------------------------------------------------
1001 
1002 #if 0
1003 
1004  BinnedContent_t const* content;
1005 
1006  content = &(fEventPlotInfo.eventTimes);
1007  makeHistogramFromBinnedContent(fPlots,
1008  "EventTime",
1009  "Time of the events"
1010  ";time"
1011  ";events [ / " + std::to_string(content->binWidth())
1012  + "\" ]",
1013  *content
1014  );
1015 
1016  content = &(fEventPlotInfo.HWtrigTimeVsBeam);
1017  makeHistogramFromBinnedContent(fPlots,
1018  "HWTrigVsBeam",
1019  "Time of the hardware trigger"
1020  ";trigger time (relative to beam gate) [ #mus ]"
1021  ";events [ / " + std::to_string(content->binWidth())
1022  + " #mus ]",
1023  *content
1024  );
1025 
1026 #endif // 0
1027 
1028 } // icarus::trigger::TriggerSimulationOnGates::makeEventPlots()
1029 
1030 
1031 //------------------------------------------------------------------------------
1033  art::Event& event,
1034  detinfo::DetectorTimings const& detTimings,
1035  std::vector<ApplyBeamGateClass> const& beamGates,
1036  std::size_t const iThr, std::string const& thrTag,
1037  unsigned int firstTriggerNumber
1038 ) -> std::vector<WindowTriggerInfo_t> {
1039 
1040 // auto& plotInfo = fThresholdPlots[iThr];
1041 
1042  //
1043  // get the input
1044  //
1045  art::InputTag const& dataTag = fADCthresholds.at(thrTag);
1046  auto const& gates = icarus::trigger::ReadTriggerGates(event, dataTag);
1047 
1048 
1049  // extract or verify the topology of the trigger windows
1050  if (fWindowMapMan(gates))
1051  fPatternAlg.emplace(*fWindowMapMan, fPattern, fLogCategory);
1052  assert(fPatternAlg);
1053 
1054  //
1055  // simulate the trigger response on all beam gates
1056  //
1057  std::vector<WindowTriggerInfo_t> allTriggerInfo; // one per gate
1058  auto triggers = std::make_unique<std::vector<raw::Trigger>>();
1059  unsigned int triggerNumber = firstTriggerNumber;
1060  for (auto const& beamGate: beamGates) {
1061  WindowTriggerInfo_t const triggerInfo
1062  = fPatternAlg->simulateResponse(beamGate.applyToAll(gates));
1063 
1064  // FIXME what do we do with statistics and plots?
1065  if (triggerInfo) {
1066  ++fTriggerCount[iThr]; // keep the unique count
1067 // plotInfo.eventTimes.add(eventTimestampInSeconds(event));
1068  }
1069 
1070  //
1071  // fill the plots
1072  //
1073  plotTriggerResponse(iThr, thrTag, triggerInfo, detTimings);
1074 
1075  //
1076  // create and store the data product
1077  //
1078  triggers->push_back(
1079  triggerInfoToTriggerData
1080  (detTimings, beamGate, triggerNumber++, triggerInfo)
1081  );
1082  allTriggerInfo.push_back(std::move(triggerInfo));
1083 
1084  } // for beam gates
1085 
1086  event.put(std::move(triggers), fOutputInstances[iThr]);
1087 
1088  return allTriggerInfo;
1089 
1090 } // icarus::trigger::TriggerSimulationOnGates::produceForThreshold()
1091 
1092 
1093 //------------------------------------------------------------------------------
1095  art::Event const& event, detinfo::DetectorTimings const& detTimings,
1096  std::vector<icarus::trigger::ApplyBeamGateClass> const& gates
1097 ) {
1098 
1099 #if 0
1100 
1101  detinfo::timescales::trigger_time const beamGateTime
1102  { detTimings.toTriggerTime(detTimings.BeamGateTime()) };
1103 
1104  fEventPlotInfo.eventTimes.add(eventTimestampInSeconds(event));
1105  fEventPlotInfo.HWtrigTimeVsBeam.add(-beamGateTime.value());
1106 
1107  // `gates` is currently unused; it may be used e.g. to show how many gates
1108  // were tested in each event
1109 
1110 #endif // 0
1111 
1112 } // icarus::trigger::TriggerSimulationOnGates::plotEvent()
1113 
1114 
1115 //------------------------------------------------------------------------------
1117  std::size_t iThr, std::string const& thrTag,
1118  WindowTriggerInfo_t const& triggerInfo,
1119  detinfo::DetectorTimings const& detTimings
1120 ) {
1121 
1122 #if 0
1123 
1124  bool const fired = triggerInfo.info.fired();
1125 
1126  fPlots.demand<TEfficiency>("Eff").Fill(fired, iThr);
1127 
1128  if (fired) {
1129  using namespace detinfo::timescales;
1130 
1131  // time of the beam gate in hardware trigger time scale
1132  trigger_time const beamGateTime
1133  { detTimings.toTriggerTime(detTimings.BeamGateTime()) };
1134 
1135  optical_tick const thisTriggerTick { triggerInfo.info.atTick() };
1136  trigger_time const thisTriggerTimeVsHWtrig
1137  { detTimings.toTriggerTime(thisTriggerTick) };
1138  time_interval const thisTriggerTimeVsBeamGate
1139  { thisTriggerTimeVsHWtrig - beamGateTime };
1140 
1141  mf::LogTrace(fLogCategory)
1142  << "Trigger " << fPattern.tag() << " at tick " << thisTriggerTick
1143  << " (" << thisTriggerTimeVsHWtrig << " vs. HW trigger, "
1144  << thisTriggerTimeVsBeamGate << " vs. beam gate)"
1145  ;
1146 
1147  fPlots.demand<TH1>("NTriggers").Fill(iThr);
1148  fPlots.demand<TH2>("TriggerTick").Fill(thisTriggerTick.value(), iThr);
1149  fPlots.demand<TH2>("TriggerTimeVsHWTrig").Fill
1150  (thisTriggerTimeVsHWtrig.value(), iThr);
1151  fPlots.demand<TH2>("TriggerTimeVsBeamGate").Fill
1152  (thisTriggerTimeVsBeamGate.value(), iThr);
1153 
1154  icarus::trigger::PlotSandbox& plots{ fPlots.demandSandbox("Thr" + thrTag) };
1155 // plots.demand<TGraph>("TriggerTimeVsHWTrigVsBeam").AddPoint( // ROOT 6.24?
1156  TGraph& graph = plots.demand<TGraph>("TriggerTimeVsHWTrigVsBeam");
1157  graph.SetPoint(graph.GetN(),
1158  -beamGateTime.value(), thisTriggerTimeVsBeamGate.value()
1159  );
1160 
1161  ThresholdPlotInfo_t& plotInfo { fThresholdPlots[iThr] };
1162  plotInfo.HWtrigTimeVsBeam.add(-beamGateTime.value());
1163  plotInfo.triggerTimesVsHWtrig.add(thisTriggerTimeVsHWtrig.value());
1164  plotInfo.triggerTimesVsBeam.add(thisTriggerTimeVsBeamGate.value());
1165 
1166  }
1167 
1168 #endif // 0
1169 
1170 } // icarus::trigger::TriggerSimulationOnGates::plotTriggerResponse()
1171 
1172 
1173 //------------------------------------------------------------------------------
1175 
1176  //
1177  // summary from our internal counters
1178  //
1179  mf::LogInfo log(fLogCategory);
1180  log
1181  << "Summary of triggers for " << fTriggerCount.size()
1182  << " thresholds (ADC) with pattern: " << fPattern.description()
1183  ;
1184  for (auto const& [ count, thr ]
1185  : util::zip(fTriggerCount, util::get_elements<0U>(fADCthresholds)))
1186  {
1187  log << "\n threshold " << thr
1188  << ": " << count;
1189  if (fTotalGates > 0U) {
1190  log << "/" << fTotalGates
1191  << " (" << (double(count) / fTotalGates * 100.0) << "%)";
1192  }
1193  else log << " gates triggered";
1194  } // for
1195 
1196 } // icarus::trigger::TriggerSimulationOnGates::printSummary()
1197 
1198 
1199 //------------------------------------------------------------------------------
1202  detinfo::DetectorTimings const& detTimings,
1203  ApplyBeamGateClass const& beamGate,
1204  unsigned int triggerNumber, WindowTriggerInfo_t const& info
1205 ) const {
1206 
1207  return {
1208  triggerNumber, // counter
1209  info.info.fired() // trigger time
1210  ? double(detTimings.toElectronicsTime(info.info.atTick()))
1211  : std::numeric_limits<double>::lowest()
1212  ,
1213  double(detTimings.toElectronicsTime(beamGate.tickRange().start())),
1214  // beam gate in electronics time scale
1215  (info.info.fired()? fBeamBits: 0) // bits
1216  };
1217 
1218 } // icarus::trigger::TriggerSimulationOnGates::triggerInfoToTriggerData()
1219 
1220 
1221 //------------------------------------------------------------------------------
1222 TH1*
1225  std::string const& name, std::string const& title,
1226  BinnedContent_t const& binnedContent
1227 ) const {
1228 
1229  if (binnedContent.empty()) return nullptr;
1230 
1231  TH1* hist = plots.make<TH1F>(
1232  name, title,
1233  binnedContent.nBins(), binnedContent.min(), binnedContent.max()
1234  );
1235 
1236  // directly transfer the content bin by bin
1237  unsigned int total = 0U;
1238  for (auto [ iBin, count ]: util::enumerate(binnedContent)) {
1239  hist->SetBinContent(iBin + 1, count);
1240  total += count;
1241  }
1242  hist->SetEntries(static_cast<double>(total));
1243  return hist;
1244 } // icarus::trigger::TriggerSimulationOnGates::makeHistogramFromBinnedContent
1245 
1246 
1247 //------------------------------------------------------------------------------
1249  (art::Timestamp const& time)
1250 {
1251  // high value: seconds from the Epoch (Jan 1, 1970 UTC?);
1252  // low value: nanoseconds after that the start of that second
1253  return static_cast<double>(time.timeHigh())
1254  + static_cast<double>(time.timeHigh()) * 1e-9;
1255 } // icarus::trigger::TriggerSimulationOnGates::eventTimestampInSeconds()
1256 
1257 
1258 //------------------------------------------------------------------------------
1260  (art::Event const& event)
1261  { return eventTimestampInSeconds(event.time()); }
1262 
1263 
1264 //------------------------------------------------------------------------------
1266 
1267 
1268 //------------------------------------------------------------------------------
BEGIN_PROLOG BeamGateDuration pmtthr physics producers trigtilewindowORS Thresholds
bool fired() const
Returns whether the trigger fired.
std::map< std::string, art::InputTag > fADCthresholds
Name of ADC thresholds to read, and the input tag connected to their data.
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
art::InputTag const fBeamGateTag
Data product of beam gates to simulate.
electronics_time BeamGateTime() const
An empty class that can&#39;t be copied nor moved.
Simulates a sliding window trigger at specified gate times.
Utilities related to art service access.
Utilities for the conversion of trigger gate data formats.
Assembles the topology of trigger windows.
Class to extract and verify a window topology from trigger gates.
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.
constexpr T roundup(T const value, U const quantum, T const offset=T{})
Returns the value, rounded up.
Definition: rounding.h:112
Definition of util::get_elements() and util::get_const_elements().
raw::Trigger triggerInfoToTriggerData(detinfo::DetectorTimings const &detTimings, ApplyBeamGateClass const &beamGate, unsigned int triggerNumber, WindowTriggerInfo_t const &info) const
Converts the trigger information into a raw::Trigger object.
void initializePlots()
Initializes the full set of plots (all ADC thresholds).
Definition of util::enumerate().
A wrapper to trigger gate objects tracking the input of operations.
microseconds_as<> microseconds
Type of time interval stored in microseconds, in double precision.
Definition: spacetime.h:259
Defines classes that can&#39;t be copied nor moved.
Simple utility for human-friendly binning.
double fEventTimeBinning
Trigger time plot binning [s].
void plotEvent(art::Event const &event, detinfo::DetectorTimings const &detTimings, std::vector< icarus::trigger::ApplyBeamGateClass > const &gates)
Fills event-wide plots.
trigger_time toTriggerTime(FromTime time) const
Converts a time point into trigger time scale.
detinfo::DetectorClocksData const & clockData() const
Returns the detector clocks data.
Base class facilitating logging to message facility.
BinIndex_t add(Data_t value)
Increases by a unit the count at the bin including value.
Definition: FixedBins.h:338
icarus::trigger::SlidingWindowPatternAlg::TriggerGates_t TriggerGates_t
List of trigger gates.
Helper to manage a beam gate.
decltype(auto) const_values(Coll &&coll)
Range-for loop helper iterating across the constant values of the specified collection.
Utilities for numerical rounding.
void makeThresholdPlots(std::string const &threshold, icarus::trigger::PlotSandbox &plots, ThresholdPlotInfo_t const &plotInfo)
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
void declareConsumes(ConsumesCollector &collector) const
Declares to the collector the data products that are going to be read.
Data_t max() const noexcept
Definition: FixedBins.h:422
std::optional< icarus::trigger::SlidingWindowPatternAlg > fPatternAlg
Pattern algorithm.
void plotTriggerResponse(std::size_t iThr, std::string const &thrTag, WindowTriggerInfo_t const &triggerInfo, detinfo::DetectorTimings const &detTimings)
Fills the plots for threshold index iThr with trigger information.
std::string const & name() const
Returns the sandbox name.
Definition: PlotSandbox.h:196
double Start() const
Definition: BeamGateInfo.h:30
Helper applying a beam gate to any gate.
Definition: ApplyBeamGate.h:85
double lower() const
Returns the value of the lower end of the first bin.
Definition: BinningSpecs.h:187
All information needed to generate plots for a specific threshold.
Class to keep count of a pass/fail result.
auto tickRange() const
Returns the range of the beam gate as start and stop tick.
std::vector< sim::BeamGateInfo > BeamGates_t
Type of list of gates to simulate trigger into.
Count_t total() const
Returns the total number of registered events.
Definition: PassCounter.h:60
Data_t min() const noexcept
Definition: FixedBins.h:416
std::string const fLogCategory
Message facility stream category for output.
Helper data structure to store transient trigger result.
Definition: TriggerInfo_t.h:50
Assembles and returns trigger gates from serialized data.
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
BinningSpecs alignBinningTo(BinningSpecs const &binning, double boundary, bool extendCoverage=true)
Returns a binning shifted to align with the specified boundary.
timescale_traits< OpticalTimeCategory >::tick_interval_t optical_time_ticks
Interface to detinfo::DetectorClocks.
Specification of the requirement of sliding window firing pattern.
Definition: WindowPattern.h:51
fDetProps &fDetProps fDetProps &fDetProps fLogCategory
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
Access the description of detector geometry.
std::vector< ThresholdPlotInfo_t > fThresholdPlots
Proto-histogram information in a not-so-practical array; per threshold.
timescale_traits< TriggerTimeCategory >::time_point_t trigger_time
A point in time on the trigger time scale.
bool empty() const noexcept
Returns whether there is no storage at all.
Definition: FixedBins.h:360
std::vector< std::string > fOutputInstances
Output data product instance names (same order as fADCthresholds).
TH1 * makeHistogramFromBinnedContent(icarus::trigger::PlotSandbox &plots, std::string const &name, std::string const &title, BinnedContent_t const &binnedContent) const
Creates and returns a 1D histogram filled with binnedContent.
Data structure holding binning information.
Definition: BinningSpecs.h:170
double binWidth() const
Returns the width of the bins (all bins have the same width).
Definition: BinningSpecs.h:199
electronics_time toElectronicsTime(FromTime time) const
Converts a time point into electronics time scale.
Ticks toOpticalTicks(time_interval time) const
Returns the optical ticks corresponding to a time interval.
void add(bool pass)
Adds a single event, specifying whether it &quot;passes&quot; or not.
Definition: PassCounter.h:112
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
bool empty() const
Returns if the sandbox is empty (neither it nor subboxes hold objects).
void finalizePlots()
Creates summary plots from proto-histogram data.
Simple functions to streamline the creation of DetectorClocksData.
Defines a (sliding) window trigger pattern.
Simple type definitions for trigger algorithms.
A trigger gate data object for optical detector electronics.
icarus::trigger::ReadoutTriggerGate< TriggerGateTick_t, TriggerGateTicks_t, raw::Channel_t > OpticalTriggerGateData_t
Type of trigger gate data serialized into art data products.
A bunch of diverse utilities and futilities related to ROOT.
virtual void endJob() override
Prints end-of-job summaries.
std::vector< PlotDef > plots
Definition: demo.h:54
icarus::trigger::WindowTopologyManager fWindowMapMan
Mapping of each sliding window with location and topological information.
std::uint32_t fBeamBits
Bits for the beam gate being simulated.
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
void printSummary() const
Prints the summary of fired triggers on screen.
BEGIN_PROLOG vertical distance to the surface Name
Test of util::counter and support utilities.
An interval (duration, length, distance) between two quantity points.
Definition: intervals.h:114
Definition of data types for geometry description.
Class with extensible fix-sized binning.
WindowPattern const fPattern
Configured sliding window requirement pattern.
FHiCL configuration structure for icarus::trigger::WindowPattern.
std::vector< std::atomic< unsigned int > > fTriggerCount
std::size_t nBins() const noexcept
Returns how many bins currently have storage.
Definition: FixedBins.h:354
icarus::trigger::PlotSandbox fPlots
All plots in one practical sandbox.
nanoseconds_as<> nanoseconds
Type of time interval stored in nanoseconds, in double precision.
Definition: spacetime.h:270
double upper() const
Returns the value of the upper end of the last bin.
Definition: BinningSpecs.h:190
::fhicl::TableAs< icarus::trigger::WindowPattern, WindowPatternConfig > WindowPatternTable
Configuration element for a trigger window.
Utilities to read interval and point quantity FHiCL configuration.
virtual void produce(art::Event &event) override
Runs the simulation and saves the results into the art event.
timescale_traits< OpticalTimeCategory >::tick_t optical_tick
std::vector< WindowTriggerInfo_t > produceForThreshold(art::Event &event, detinfo::DetectorTimings const &detTimings, std::vector< ApplyBeamGateClass > const &beamGates, std::size_t const iThr, std::string const &thrTag, unsigned int firstTriggerNumber)
Performs the simulation for the specified ADC threshold.
Classes to detect the change of object values.
optical_tick atTick() const
Returns the time of the trigger (undefined if !fired()).
art::TFileDirectory fOutputDir
ROOT directory where all the plots are written.
std::string to_string(WindowPattern const &pattern)
virtual void beginJob() override
Initializes the plots.
Dimensioned variables representing space or time quantities.
Helper class to store transient trigger result.
A class exposing an upgraded interface of detinfo::DetectorClocksData.
double Width() const
Definition: BeamGateInfo.h:31
Data types for detinfo::DetectorTimings.
Functions pulling in STL customization if available.
Class to create an object representing a beam gate.
std::vector< InputTriggerGate_t > TriggerGates_t
A list of trigger gates from input.
ThresholdPlotInfo_t fEventPlotInfo
Proto-histogram information in a convenient packet; event-wide.
do i e
icarus::trigger::TrackedOpticalTriggerGate< sbn::OpDetWaveformMeta > InputTriggerGate_t
Type of trigger gate provided as input.
static double eventTimestampInSeconds(art::Timestamp const &time)
Returns the time of the event in seconds from The Epoch.
then echo fcl name
auto zip(Iterables &&...iterables)
Range-for loop helper iterating across many collections at the same time.
Definition: zip.h:295
temporary value
fDetProps &fDetProps fDetProps &fDetProps detTimings
Definition of util::values() and util::const_values().
BEGIN_PROLOG triggeremu_data_config_icarus settings sequence::triggeremu_data_config_icarus settings PMTADCthresholds sequence::triggeremu_data_config_icarus settings PMTADCthresholds sequence::triggeremu_data_config_icarus settings PMTADCthresholds Pattern
unsigned long nBins() const
Returns the number of bins.
Definition: BinningSpecs.h:196
std::size_t count(Cont const &cont)
Count_t passed() const
Returns the number of events which &quot;passed&quot;.
Definition: PassCounter.h:54
std::vector< icarus::trigger::TrackedOpticalTriggerGate< OpDetInfo > > ReadTriggerGates(Event const &event, art::InputTag const &dataTag)
Assembles and returns trigger gates from serialized data.
nanoseconds fTriggerTimeResolution
Trigger resolution in time.
Complete information from this algorithm, standard + non-standard (extra).
Class counting pass/fail events.
Definition: PassCounter.h:15
Applies sliding window trigger patterns.
A helper to manage ROOT objects in a art::TFileDirectory.
art framework interface to geometry description
detinfo::DetectorTimings makeDetTimings(art::Event const *event)
Returns a detinfo::DetectorTimings from DetectorClocksService.
void makeEventPlots()
Creates in the main sandbox all event-wide plots.
fDetProps &fDetProps fDetProps &fDetProps consumesCollector())
A helper to manage ROOT objects with consistent naming.
Definition: PlotSandbox.h:95
Interval_t binWidth() const noexcept
Returns the width of the bins.
Definition: FixedBins.h:366