All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MakeTriggerSimulationTree_module.cc
Go to the documentation of this file.
1 /**
2  * @file MakeTriggerSimulationTree_module.cc
3  * @brief Creates a ROOT tree with trigger information.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date May 15, 2020
6  */
7 
8 // ICARUS libraries
20 #include "icaruscode/Utilities/DetectorClocksHelpers.h" // makeDetTimings()...
22 #include "icarusalg/Utilities/FHiCLutils.h" // util::fhicl::getOptionalValue()
23 #include "icarusalg/Utilities/ChangeMonitor.h" // ThreadSafeChangeMonitor
27 
28 // LArSoft libraries
31 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
33 #include "lardataalg/DetectorInfo/DetectorTimingTypes.h" // simulation_time, ...
34 #include "lardataalg/Utilities/intervals_fhicl.h" // microseconds from FHiCL
35 #include "lardataalg/Utilities/quantities_fhicl.h" // for ADCCounts_t parameters
36 #include "larcorealg/Geometry/geo_vectors_utils.h" // MiddlePointAccumulator
39 #include "larcorealg/CoreUtils/values.h" // util::const_values()
41 
42 // framework libraries
43 #include "art_root_io/TFileService.h"
44 #include "art/Framework/Services/Registry/ServiceHandle.h"
45 #include "art/Framework/Core/EDAnalyzer.h"
46 #include "art/Framework/Core/ModuleMacros.h"
47 #include "art/Framework/Principal/Event.h"
48 #include "canvas/Utilities/Exception.h"
49 #include "messagefacility/MessageLogger/MessageLogger.h"
50 #include "fhiclcpp/types/OptionalSequence.h"
51 #include "fhiclcpp/types/Sequence.h"
52 #include "fhiclcpp/types/OptionalAtom.h"
53 #include "fhiclcpp/types/Atom.h"
54 
55 // ROOT libraries
56 #include "TTree.h"
57 
58 // C/C++ standard libraries
59 #include <memory> // std::unique_ptr<>
60 #include <string>
61 #include <optional>
62 #include <utility> // std::pair<>
63 #include <limits> // std::numeric_limits<>
64 
65 
66 //------------------------------------------------------------------------------
68 
69 // --- BEGIN -- Trigger information --------------------------------------------
70 
71 /// All information from the trigger gates.
73 
74  /// Information from a single trigger gate.
75  struct TriggerGateInfo {
76 
77  /// Middle point of the center of all contributing channels.
79 
80  /// Number of times the gate was "open".
81  unsigned int nOpenings = 0U;
82 
83  /// The time of the first opening on the channel, in simulation time [ns]
84  simulation_time firstOpenTime = std::numeric_limits<simulation_time>::max();
85 
86  }; // struct TriggerGateInfo
87 
88  /// Collection of all available trigger gates.
89  std::vector<TriggerGateInfo> TriggerGates;
90 
91 }; // struct TriggerGatesInfo
92 
93 std::ostream& operator<<
94  (std::ostream& out, TriggerGatesInfo::TriggerGateInfo const& info);
95 std::ostream& operator<< (std::ostream& out, TriggerGatesInfo const& info);
96 
97 // --- END -- Trigger information ----------------------------------------------
98 
99 
100 // --- BEGIN -- ROOT tree helpers ----------------------------------------------
101 /**
102  * @brief Class managing the serialization of trigger gates in a simple ROOT
103  * tree.
104  *
105  * The tree is supplied by the caller.
106  * This object will create the proper branches into the tree and assign
107  * addresses to them. Then it will assume they will stay assigned.
108  * Information may be loaded into the tree via `assignTriggerGatesInfo()`
109  * method, which sets each branch according to a value of the data structure
110  * `TriggerGatesInfo`, as described below.
111  *
112  * The branch structure is:
113  * `NChannels/i:OpDetPos_[]/D:NOpenings[]/i:OpeningTime[]/D`
114  *
115  * * `NChannels` (from the size of `TriggerGatesInfo::info`): number of
116  * channels in this event;
117  * * `OpDetPos` (one 3D point per channel, from `TriggerGateInfo::center`):
118  * the location of the centroid of the optical detectors contributing to the
119  * channel, in world coordinates [cm]; it's a vector of GenVector 3D points
120  * (can access coordinates as `OpDetPos.X()` or `OpDetPos.fCoordinates.fX`);
121  * * `NOpenings` (one count per channel, from `TriggerGateInfo::nOpenings`):
122  * the number of times the gate opened;
123  * * `OpeningTime` (one time per channel, based on
124  * `TriggerGateInfo::firstOpenTime`): first time that channel opened, or
125  * very large number (`std::numeric_limits<double>::max()`)
126  * if no opening happened at all (note that in this case the value in
127  * `TriggerGateInfo::firstOpenTime` is ignored).
128  *
129  * All branches come from a variable size vector with size the number of
130  * available trigger gates.
131  */
133 
134  /// Constructor.
135  TriggerGateTree(TTree& tree);
136 
137  /// Copies the information from the `info` record into the ROOT tree buffers.
139 
140  private:
141 
142  UInt_t fNChannels; ///< Number of channels.
143 
144  std::vector<geo::Point_t> fOpDetPos; ///< Coordinates of the optical detector.
145  std::vector<UInt_t> fNOpenings; ///< Number of openings (`0` if never opens).
146  std::vector<Double_t> fOpeningTime; ///< Time of first opening.
147 
148  /// Internal check: all branch buffers have the same size.
149  void checkSizes() const;
150 
151 }; // struct TriggerGateTree
152 
153 
154 // --- END -- ROOT tree helpers ------------------------------------------------
155 
156 
157 //------------------------------------------------------------------------------
158 namespace icarus::trigger { class MakeTriggerSimulationTree; }
159 /**
160  * @brief Make ROOT tree with information about event and trigger input.
161  *
162  * This module produces a ROOT tree with information about the event and about
163  * the trigger input.
164  *
165  * Trigger simulation logic is applied in a time interval that we call "beam
166  * gate", although it would more precisely dubbed as "trigger gate".
167  * The reference time of this gate is the ("real") beam gate opening time as
168  * reported by `detinfo::DetectorClocksData::BeamGateTime()`, whose absolute
169  * value may vary event by event (see note below).
170  * The configuration of this module allows to shift pre-beam and beam gates
171  * with respect to that time.
172  *
173  *
174  * _Note_: detector data and simulated data have intrinsically different time
175  * references. In LArSoft, the TPC waveform time reference is the most static
176  * and less flexible. Since the detector pins the TPC timing to the trigger
177  * time, TPC waveforms are written referring to that time, and then the whole
178  * event is also written in that frame. In simulated data, instead, a trigger
179  * is not known until after the (PMT) waveforms are produced, and it is
180  * therefore more convenient to refer to a time that is less dependent on data
181  * itself: the beam gate opening. In detector data, the value of beam gate
182  * opening time will appear to change event by event, as trigger(s) time do
183  * in simulated data. For this reason, all the analysis should be performed on
184  * relative times (e.g. relative to the trigger, which is the "native" LArSoft
185  * reference), i.e. in the @ref DetectorClocksTriggerTime "trigger timescale"
186  * or, equivalently, subtracting `detinfo::DetectorClocksData::TriggerTime()`
187  * from the times.
188  *
189  *
190  * Input
191  * ======
192  *
193  * The following data products are required in input:
194  *
195  * * `std::vector<simb::MCTruth>` (tag: configured in `GeneratorTags`):
196  * any number of truth information records;
197  * * `std::vector<sim::SimEnergyDeposits>` (tag: configured in
198  * `EnergyDepositTags`): energy depositions to be counted in the event
199  * information;
200  * * `std::vector<icarus::trigger::OpticalTriggerGateData_t>` (tag: configured
201  * in `TriggerGatesTag`): list of trigger gate outputs to be put into the
202  * tree.
203  *
204  *
205  * Output
206  * =======
207  *
208  * The output tree is written via `TFileService` in the ROOT directory assigned
209  * to this module.
210  *
211  * The tree contains three "sections":
212  *
213  * * event identification: see `icarus::trigger::details::EventIDTree`
214  * for the details;
215  * * event information: see `icarus::trigger::details::EventInfoTree`
216  * for the details;
217  * * information on the trigger gates (data product configured via
218  * `TriggerGatesTag` parameter): information on the state of each trigger
219  * gate _during the beam gate_ is extracted, including the number of times
220  * the gate is opened and when; see `TriggerGateTree` for details on the
221  * structure of the tree, and `extractTriggerInfo()` for the details of how
222  * each value is computed.
223  *
224  *
225  * Configuration parameters
226  * =========================
227  *
228  * * `GeneratorTags` (list of input tags, default: `[ generator ]`): a list of
229  * data products containing the particles generated by event generators.
230  * * `EnergyDepositTags`
231  * (list of input tags, default: `[ "largeant:TPCActive" ]`): a list of
232  * data products with energy depositions.
233  * * `EnergyDepositSummaryTag` (input tag): alternative to `EnergyDepositTags`,
234  * uses energy deposition information from a summary data product instead
235  * of extracting the information.
236  * * `TriggerGatesTag` (string, mandatory): name of the module
237  * instance which produced the trigger primitives to be used as input.
238  * The typical trigger primitives used as input may be LVDS discriminated
239  * output (e.g. from `icarus::trigger::LVDSgates` module) or combinations
240  * of them (e.g. from `icarus::trigger::SlidingWindowTrigger` module).
241  * * `BeamGateDuration` (time, _mandatory_): the duration of the beam
242  * gate; _the time requires the unit to be explicitly specified_: use
243  * `"1.6 us"` for BNB, `9.5 us` for NuMI (also available as
244  * `BNB_settings.spill_duration` and `NuMI_settings.spill_duration` in
245  * `trigger_icarus.fcl`).
246  * * `BeamGateStart` (time, default: 0 &micro;s): open the beam gate this long
247  * after the formal beam gate time.
248  * * `PreSpillWindow` (time, default: 10 &micro;s): duration of the pre-spill
249  * window;
250  * * `PreSpillWindowGap` (time, default: 0 &micro;s): gap from the end of
251  * pre-spill window to the start of beam gate;
252  * * `EventTreeName` (string, default: "Treegger"): the name of the ROOT tree
253  * being written on disk;
254  * * `LogCategory` (string, default `MakeTriggerSimulationTree`): name of
255  * category used to stream messages from this module into message facility.
256  *
257  *
258  * Technical description of the module
259  * ====================================
260  *
261  *
262  */
263 class icarus::trigger::MakeTriggerSimulationTree: public art::EDAnalyzer {
264 
265  public:
266 
268 
269  // --- BEGIN Configuration ---------------------------------------------------
270  struct Config {
271 
272  using Name = fhicl::Name;
273  using Comment = fhicl::Comment;
274 
275  fhicl::Sequence<art::InputTag> GeneratorTags {
276  Name("GeneratorTags"),
277  Comment("labels of the event generators"),
278  std::vector<art::InputTag>{ "generator" }
279  };
280 
281  fhicl::OptionalSequence<art::InputTag> EnergyDepositTags {
282  Name("EnergyDepositTags"),
283  Comment("label of energy deposition data product(s) in the detector")
284  };
285 
286  fhicl::OptionalAtom<art::InputTag> EnergyDepositSummaryTag {
287  Name("EnergyDepositSummaryTag"),
288  Comment("label of energy deposition summary data product")
289  };
290 
291  fhicl::Atom<std::string> TriggerGatesTag {
292  Name("TriggerGatesTag"),
293  Comment("label of the input trigger gate data product (no instance name)")
294  };
295 
296  fhicl::Atom<microseconds> BeamGateDuration {
297  Name("BeamGateDuration"),
298  Comment("length of time interval when optical triggers are accepted")
299  };
300 
301  fhicl::Atom<microseconds> BeamGateStart {
302  Name("BeamGateStart"),
303  Comment("open the beam gate this long after the nominal beam gate time"),
304  microseconds{ 0.0 }
305  };
306 
307  fhicl::Atom<microseconds> PreSpillWindow {
308  Name("PreSpillWindow"),
309  Comment("duration of the pre-spill window"),
310  microseconds{ 10.0 }
311  };
312 
313  fhicl::Atom<microseconds> PreSpillWindowGap {
314  Name("PreSpillWindowGap"),
315  Comment("gap from the end of pre-spill window to the start of beam gate"),
316  microseconds{ 0.0 }
317  };
318 
319  fhicl::Atom<std::string> EventTreeName {
320  Name("EventTreeName"),
321  Comment("name of the ROOT tree"),
322  "Treegger" // default
323  };
324 
325  fhicl::Atom<std::string> LogCategory {
326  Name("LogCategory"),
327  Comment("name of the category used for the output"),
328  "MakeTriggerSimulationTree" // default
329  };
330 
331  }; // struct Config
332 
333  using Parameters = art::EDAnalyzer::Table<Config>;
334  // --- END Configuration -----------------------------------------------------
335 
336 
337  // --- BEGIN Constructors ----------------------------------------------------
338  explicit MakeTriggerSimulationTree(Parameters const& config);
339 
340  // Plugins should not be copied or assigned.
345 
346  // --- END Constructors ------------------------------------------------------
347 
348 
349  // --- BEGIN Framework hooks -------------------------------------------------
350 
351  /// Fills the plots. Also extracts the information to fill them with.
352  virtual void analyze(art::Event const& event) override;
353 
354  // --- END Framework hooks ---------------------------------------------------
355 
356 
357  private:
358 
359  // --- BEGIN Configuration variables -----------------------------------------
360 
361  /// Duration of the gate during with global optical triggers are accepted.
363 
364  /// Start of the beam gate with respect to `BeamGate()`.
366 
367  microseconds const fPreSpillWindow; ///< Duration of the pre-spill gate.
368 
369  microseconds const fPreSpillStart; ///< Start of the pre-spill gate.
370 
371  /// Tag for optical trigger gate data product.
372  art::InputTag const fTriggerGatesTag;
373 
374  /// Name of output stream for message facility.
375  std::string const fLogCategory;
376 
377  // --- END Configuration variables -------------------------------------------
378 
379 
380  // --- BEGIN Setup variables -------------------------------------------------
381 
383 
384  // --- END Setup variables ---------------------------------------------------
385 
386 
387  // --- BEGIN Internal variables ----------------------------------------------
388 
389  /// Main ROOT tree: event ID.
391 
392  // these trees are "optional" so that in the future they can be disabled;
393  // but currently (v08_52_00) no option for disabling them is implemented
394 
395  /// ROOT tree: event information.
396  std::optional<details::EventInfoTree> fEventTree;
397 
398  /// ROOT tree: trigger gates.
399  std::optional<TriggerGateTree> fTriggerGateTree;
400 
401  /// Helper to fill a `EventInfo_t` from an _art_ event.
403 
404  /// Functor returning whether a gate has changed.
407 
408  // --- END Internal variables ------------------------------------------------
409 
410 
411  /**
412  * @brief Returns a `TriggerGatesInfo` with trigger information for the tree.
413  * @param event the _art_ event where to find the trigger gates
414  * @param detTimings detector timings updated for this event
415  * @return a `TriggerGatesInfo` with trigger information for the tree
416  *
417  * Information from the trigger gates configured in the module is extracted
418  * and stored into a `TriggerGatesInfo` object, which is returned.
419  * The data fields are defined as follows:
420  *
421  * * a `TriggerGateInfo` element is stored in `TriggerGatesInfo::info` for
422  * each and every trigger gate in the input, in the same order as the
423  * input data product;
424  * * for each gate:
425  * * `TriggerGateInfo::center`: for each channel associated to the
426  * trigger gate, the geometric center of the optical detector connected
427  * to that channel is taken; `center` is set to the middle point
428  * (unweighted 3D centroid) of all those points; the center is in world
429  * coordinates and in centimeters;it is assumed that the trigger gate
430  * is associated to at least one channel, otherwise behavior is
431  * undefined;
432  * * `TriggerGateInfo::nOpenings`: the number of times in coincidence
433  * with the beam gate, when the gate changes state from closed (opening
434  * level `0`) to open (opening level `1` or larger);
435  * * `TriggerGateInfo::firstOpenTime`: the time the first of the openings
436  * (as defined in `nOpenings`) happens; the time is in
437  * @ref DetectorClocksSimulationTime "simulation time scale"; if there
438  * was no opening during the beam gate (`nOpenings` zero), the value
439  * is undefined;
440  * * 'TriggerGateInfo::Amplitude': the amplitude of the PMT
441  *
442  */
444  (art::Event const& event, detinfo::DetectorTimings const& detTimings) const;
445 
446 
447  /// Returns the centroid (middle point) of all the centers of optical detectors
448  /// contributing to the specified `gate`, in world coordinates [cm]
450  (icarus::trigger::OpticalTriggerGateData_t const& gate) const;
451 
452 
453  /// Creates a `EDepTags_t` from two optional parameters.
455  fhicl::OptionalSequence<art::InputTag> const& EnergyDepositTags,
456  fhicl::OptionalAtom<art::InputTag> const& EnergyDepositSummaryTag
457  );
458 
459 }; // icarus::trigger::MakeTriggerSimulationTree
460 
461 
462 
463 //------------------------------------------------------------------------------
464 //--- Implementation
465 //------------------------------------------------------------------------------
466 //--- TriggerGatesInfo
467 //------------------------------------------------------------------------------
468 std::ostream& operator<<
469  (std::ostream& out, TriggerGatesInfo::TriggerGateInfo const& info)
470 {
471  out << "center at " << info.center;
472  if (info.nOpenings == 0) out << " never opened";
473  else {
474  out << " opened " << info.nOpenings << " times, first at "
475  << info.firstOpenTime;
476  }
477  return out;
478 } // operator<< (TriggerGatesInfo::TriggerGateInfo const&)
479 
480 
481 //------------------------------------------------------------------------------
482 std::ostream& operator<< (std::ostream& out, TriggerGatesInfo const& info) {
483  out << size(info.TriggerGates) << " gates:";
484  for (auto const& [ iGate, gate ]: util::enumerate(info.TriggerGates))
485  out << "\n [" << iGate << "] " << gate;
486  out << "\n";
487  return out;
488 } // operator<< (TriggerGatesInfo const&)
489 
490 
491 
492 //------------------------------------------------------------------------------
493 //--- TriggerGateTree
494 //------------------------------------------------------------------------------
496  : TreeHolder(tree)
497 {
498 
499  this->tree().Branch("NChannels", &fNChannels);
500  this->tree().Branch("OpDetPos", &fOpDetPos);
501  this->tree().Branch("NOpenings", &fNOpenings);
502  this->tree().Branch("OpeningTime", &fOpeningTime);
503 
504 } // TriggerGateTree::TriggerGateTree()
505 
506 
507 //------------------------------------------------------------------------------
509 
510  auto checkSize = [this](auto const& v){ return v.size() == fNChannels; };
511 
512  if (!checkSize(fOpDetPos)) {
513  throw cet::exception("TriggerGateTree") << __func__
514  << ": Internal error: unexpected buffer size (" << fOpDetPos.size()
515  << ") : fOpDetPos\n";
516  }
517  if (!checkSize(fNOpenings)) {
518  throw cet::exception("TriggerGateTree") << __func__
519  << ": Internal error: unexpected buffer size (" << fNOpenings.size()
520  << ") : fNOpenings\n";
521  }
522  if (!checkSize(fOpeningTime)) {
523  throw cet::exception("TriggerGateTree") << __func__
524  << ": Internal error: unexpected buffer size (" << fOpeningTime.size()
525  << ") : fOpeningTime\n";
526  }
527 
528 } // TriggerGateTree::checkSizes()
529 
530 
531 //------------------------------------------------------------------------------
533 
534  fNChannels = info.TriggerGates.size();
535  fOpDetPos.clear();
536  fNOpenings.clear();
537  fOpeningTime.clear();
538  for
539  (auto const& [ iChannel, channelInfo ]: util::enumerate(info.TriggerGates))
540  {
541 
542  fOpDetPos.push_back(channelInfo.center);
543  fNOpenings.push_back(channelInfo.nOpenings);
544 
545  // accepting the fallback value when there is no interaction
546  // (that is `max()`)
547  fOpeningTime.push_back(channelInfo.firstOpenTime.value());
548  // fAmplitude.push_back(channelInfo.Amplitude);
549  } // for
550 
551  checkSizes();
552 
553 } // TriggerGateTree::assignTriggerGatesInfo()
554 
555 
556 //------------------------------------------------------------------------------
557 //--- icarus::trigger::MakeTriggerSimulationTree
558 //------------------------------------------------------------------------------
560  (Parameters const& config)
561  : art::EDAnalyzer(config)
562  // persistent configuration
563  , fBeamGateDuration (config().BeamGateDuration())
564  , fBeamGateStart (config().BeamGateStart())
565  , fPreSpillWindow (config().PreSpillWindow())
566  , fPreSpillStart
567  (fBeamGateStart - config().PreSpillWindowGap() - fPreSpillWindow)
568  , fTriggerGatesTag(config().TriggerGatesTag())
569  , fLogCategory(config().LogCategory())
570  // setup
571  , fGeom(*lar::providerFrom<geo::Geometry>())
572  // other data
573  , fIDTree(*(art::ServiceHandle<art::TFileService>()
574  ->make<TTree>(config().EventTreeName().c_str(), "Event information")
575  ))
576  , fEventTree(fIDTree.tree())
577  , fTriggerGateTree(fIDTree.tree())
578  , fEventInfoExtractorMaker(
579  config().GeneratorTags(), // truthTags
580  makeEdepTag(config().EnergyDepositTags, config().EnergyDepositSummaryTag),
581  // edepTags
582  fGeom, // geom
583  nullptr, // detProps
584  nullptr, // detTimings
585  fLogCategory, // logCategory
586  consumesCollector() // consumesCollector
587  )
588 {
589 
590  //
591  // declaration of further input (more is by `fEventInfoExtractorMaker`)
592  //
593 
594  // none so far
595 
596 } // icarus::trigger::MakeTriggerSimulationTree::MakeTriggerSimulationTree()
597 
598 
599 //------------------------------------------------------------------------------
601  (art::Event const& event)
602 {
603 
604  // we need to convert the two relevant gates with the proper parameters
607 
608  auto const beamGate = icarus::trigger::makeBeamGateStruct
609  (detTimings, fBeamGateDuration, fBeamGateStart);
610 
611  if (auto oldGate = fBeamGateChangeCheck(beamGate); oldGate) {
612  MF_LOG_DEBUG(fLogCategory)
613  << "Beam gate has changed from " << oldGate->asOptTickRange()
614  << " to " << beamGate.asOptTickRange() << " (optical tick)!";
615  }
616 
617  details::EventInfo_t const eventInfo = fEventInfoExtractorMaker(
618  beamGate.asSimulationRange(),
620  (detTimings, fPreSpillStart, fPreSpillStart + fPreSpillWindow)
622  )(event);
623 
624  TriggerGatesInfo const triggerInfo = extractTriggerInfo(event, detTimings);
625 
626  mf::LogDebug(fLogCategory) << event.id() << " trigger info: " << triggerInfo;
627 
628  fIDTree.assignID(event.id());
629  if (fEventTree) fEventTree->assignEvent(eventInfo);
630  if (fTriggerGateTree) fTriggerGateTree->assignTriggerGatesInfo(triggerInfo);
631 
632  fIDTree.tree().Fill();
633 
634 } // icarus::trigger::MakeTriggerSimulationTree::analyze()
635 
636 
637 //------------------------------------------------------------------------------
639  (art::Event const& event, detinfo::DetectorTimings const& detTimings) const
640 {
641  /*
642  * 1. get the data product from the event
643  * 2. fill one "channel" of `TriggerGateInfo` per entry in the data product
644  * 1. get centroid of associated detectors
645  * 2. find and convert to `simulation_time` the first opening
646  * 3. find the number of openings
647  * 4. find the amplitude
648  * 4. fill the information
649  *
650  */
651 
654 
655  //
656  // 0. construct the beam gate for this event
657  //
658  auto const beamGate = icarus::trigger::BeamGateMaker{ detTimings }
659  .make(fBeamGateDuration, fBeamGateStart);
660 
661  //
662  // 1. get the data product from the event
663  //
664  auto const& gates
665  = event.getProduct<std::vector<OpticalTriggerGateData_t>>(fTriggerGatesTag);
666 
667  //
668  // 2. fill one "channel" of `TriggerGateInfo` per entry in the data product
669  //
671 
672  unsigned int nOpenChannels = 0U; // count for debugging message
673  for (OpticalTriggerGateData_t const& gate: gates) {
674 
675  // the gate, in coincidence with the beam gate:
676  auto const beamAndGate = OpticalTriggerGateData_t::Mul(gate, beamGate);
677 
678  //
679  // 2.2. find and convert to `simulation_time` the first opening
680  //
681  OpticalTriggerGateData_t::ClockTick_t const firstOpenTick
682  = beamAndGate.findOpen();
683 
684  //
685  // 2.3. find the number of openings
686  //
687  unsigned int nOpenings = 0U;
688  OpticalTriggerGateData_t::ClockTick_t openTick = firstOpenTick;
689  while (openTick != OpticalTriggerGateData_t::MaxTick) {
690  ++nOpenings;
691  // move out of this open region, then find the next one
692  openTick = beamAndGate.findClose(1U, openTick);
693  openTick = beamAndGate.findOpen(1U, openTick);
694  } // while
695  if (nOpenings > 0) ++nOpenChannels;
696 
697  //
698  // 2.4. fill the information
699  //
700  info.TriggerGates.push_back({
701  gateChannelCentroid(gate), // 2.1. get centroid of associated detectors
702  nOpenings,
703  // users should ignore this if `nOpenings == 0`:
704  (nOpenings == 0U)
705  ? std::numeric_limits<simulation_time>::max() //std::numeric_limits<T>::max Returns the maximum finite value representable by the
706  //numeric type T. Meaningful for all bounded types.
707  : detTimings.toSimulationTime
708  (detinfo::timescales::optical_tick{ firstOpenTick })
709  //,amplitude
710  });
711 
712  } // for all gates
713 
714  mf::LogTrace(fLogCategory)
715  << "Information from '" << fTriggerGatesTag.encode() << "' ("
716  << gates.size() << " trigger gates, " << nOpenChannels
717  << " channels) written to tree."
718  ;
719 
720  return info;
721 } // icarus::trigger::MakeTriggerSimulationTree::extractTriggerInfo()
722 
723 
724 //------------------------------------------------------------------------------
727 {
728 
730 
731  for (auto const channel: gate.channels()) {
732 
733  try {
734  centroid.add(fGeom.OpDetGeoFromOpChannel(channel).GetCenter());
735  }
736  catch (cet::exception const& e) {
737  throw cet::exception("MakeTriggerSimulationTree", "", e)
738  << "Error while accessing position of optical detector with channel "
739  << channel << "\n";
740  }
741 
742  } // for
743 
744  return centroid.middlePoint();
745 
746 } // icarus::trigger::MakeTriggerSimulationTree::gateChannelCentroid()
747 
748 
749 //------------------------------------------------------------------------------
752  fhicl::OptionalSequence<art::InputTag> const& EnergyDepositTags,
753  fhicl::OptionalAtom<art::InputTag> const& EnergyDepositSummaryTag
754 ) {
755 
756  if (EnergyDepositSummaryTag.hasValue()) {
757  if (EnergyDepositTags.hasValue()) {
758  throw art::Exception(art::errors::Configuration)
759  << "MakeTriggerSimulationTree: "
760  << "both EnergyDepositTags and EnergyDepositSummaryTag "
761  << "have been specified, but they are exclusive: @erase one.\n";
762  }
763 
764  art::InputTag tag;
765  EnergyDepositSummaryTag(tag);
766  return {
768  { tag }
769  };
770  }
771  else {
772 
773  std::vector<art::InputTag> tags;
774  if (!EnergyDepositTags(tags)) tags.push_back("largeant:TPCActive");
775  return { std::move(tags) };
776 
777  }
778 
779 } // icarus::trigger::MakeTriggerSimulationTree::makeEdepTag()
780 
781 
782 //------------------------------------------------------------------------------
784 
785 
786 //------------------------------------------------------------------------------
decltype(auto) channels() const
Returns the channels associated to the gate data.
std::vector< Double_t > fOpeningTime
Time of first opening.
std::optional< details::EventInfoTree > fEventTree
ROOT tree: event information.
art::InputTag const fTriggerGatesTag
Tag for optical trigger gate data product.
Utilities related to art service access.
Utilities for the conversion of trigger gate data formats.
An object representing a time gate, with a start and and end.
TriggerGatesInfo extractTriggerInfo(art::Event const &event, detinfo::DetectorTimings const &detTimings) const
Returns a TriggerGatesInfo with trigger information for the tree.
Definition of util::enumerate().
Algorithm to produce trigger gates out of optical readout waveforms.
microseconds_as<> microseconds
Type of time interval stored in microseconds, in double precision.
Definition: spacetime.h:259
Information from a single trigger gate.
Helper class to compute the middle point in a point set.
UInt_t fNChannels
Number of channels.
std::size_t size(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:561
std::variant< std::vector< art::InputTag >, SimEnergyDepositSummaryInputTag, SimChannelsInputTag > EDepTags_t
Type to specify the source of energy deposition information, if any.
Helper to check if an object has changed. Thread-safe.
void add(Point const &p)
Accumulates a point.
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
Interface to detinfo::DetectorClocks.
geo::Point_t gateChannelCentroid(icarus::trigger::OpticalTriggerGateData_t const &gate) const
fDetProps &fDetProps fDetProps &fDetProps fLogCategory
Access the description of detector geometry.
std::optional< TriggerGateTree > fTriggerGateTree
ROOT tree: trigger gates.
Class holding a ROOT tree, to be shared by other classes.
Logical multi-level gate associated to one or more readout channels.
details::EventInfoExtractorMaker const fEventInfoExtractorMaker
Helper to fill a EventInfo_t from an art event.
TimeRange< simulation_time > const & asSimulationRange() const
Returns the gate as start/stop pair in simulation time scale.
Utilities to read and write quantities in FHiCL configuration.
timescale_traits< SimulationTimeCategory >::time_point_t simulation_time
A point in time on the simulation time scale.
Simple functions to streamline the creation of DetectorClocksData.
A logical multilevel gate for triggering.
microseconds const fPreSpillStart
Start of the pre-spill gate.
static icarus::trigger::details::EventInfoExtractor::EDepTags_t makeEdepTag(fhicl::OptionalSequence< art::InputTag > const &EnergyDepositTags, fhicl::OptionalAtom< art::InputTag > const &EnergyDepositSummaryTag)
Creates a EDepTags_t from two optional parameters.
Simple type definitions for trigger algorithms.
microseconds const fPreSpillWindow
Duration of the pre-spill gate.
virtual void analyze(art::Event const &event) override
Fills the plots. Also extracts the information to fill them with.
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.
details::EventIDTree fIDTree
Main ROOT tree: event ID.
simulation_time toSimulationTime(FromTime time) const
Converts a time point into simulation time scale.
Utilities to extend the interface of geometry vectors.
Class managing the serialization of trigger gates in a simple ROOT tree.
Class managing the serialization of event ID in a simple ROOT tree.
Definition: EventIDTree.h:37
BEGIN_PROLOG vertical distance to the surface Name
TriggerGateTree(TTree &tree)
Constructor.
Simple class holding a tree.
Definition: TreeHolder.h:24
All information from the trigger gates.
Description of geometry of one entire detector.
An interval (duration, length, distance) between two quantity points.
Definition: intervals.h:114
Functions dealing with icarus::trigger::details::EventInfo_t.
microseconds const fBeamGateDuration
Duration of the gate during with global optical triggers are accepted.
geo::Point_t center
Middle point of the center of all contributing channels.
std::vector< UInt_t > fNOpenings
Number of openings (0 if never opens).
Utilities to read interval and point quantity FHiCL configuration.
Class writing event information into a ROOT tree.
timescale_traits< OpticalTimeCategory >::tick_t optical_tick
Classes to detect the change of object values.
A helper class creating a EventInfoExtractor with a specific setup.
Class hosting selected information about the event.
BeamGateStruct makeBeamGateStruct(detinfo::DetectorTimings const &detTimings, util::quantities::intervals::microseconds duration, util::quantities::intervals::microseconds delay=util::quantities::intervals::microseconds{0.0})
Creates a BeamGateStruct object of specified duration and start.
MakeTriggerSimulationTree & operator=(MakeTriggerSimulationTree const &)=delete
A class exposing an upgraded interface of detinfo::DetectorClocksData.
Data types for detinfo::DetectorTimings.
Class to create an object representing a beam gate.
do i e
void checkSizes() const
Internal check: all branch buffers have the same size.
icarus::ns::util::ThreadSafeChangeMonitor< icarus::trigger::BeamGateStruct > fBeamGateChangeCheck
Functor returning whether a gate has changed.
A simple alias for a most commonly used TrackedTriggerGate type.
simulation_time firstOpenTime
The time of the first opening on the channel, in simulation time [ns].
Simple utility to generate gates around beam time.
Definition: BeamGateMaker.h:49
Selected information about the event.
Definition: EventInfo_t.h:45
unsigned int nOpenings
Number of times the gate was &quot;open&quot;.
Simple helper functions to deal with FHiCL.
fDetProps &fDetProps fDetProps &fDetProps detTimings
Definition of util::values() and util::const_values().
std::string const fLogCategory
Name of output stream for message facility.
Utility tag to identify a parameter as a specific type of tag.
Class hosting selected information about the event.
microseconds const fBeamGateStart
Start of the beam gate with respect to BeamGate().
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
void assignTriggerGatesInfo(TriggerGatesInfo const &info)
Copies the information from the info record into the ROOT tree buffers.
std::ostream & operator<<(std::ostream &out, lar::example::CheatTrack const &track)
Definition: CheatTrack.h:153
art framework interface to geometry description
std::vector< TriggerGateInfo > TriggerGates
Collection of all available trigger gates.
detinfo::DetectorTimings makeDetTimings(art::Event const *event)
Returns a detinfo::DetectorTimings from DetectorClocksService.
fDetProps &fDetProps fDetProps &fDetProps consumesCollector())
std::vector< geo::Point_t > fOpDetPos
Coordinates of the optical detector.
Make ROOT tree with information about event and trigger input.
Utilities to map data pointer elements to their art::Ptr.