47 #include "art_root_io/TFileService.h"
48 #include "art_root_io/TFileDirectory.h"
49 #include "art/Framework/Services/Registry/ServiceHandle.h"
50 #include "art/Framework/Core/EDProducer.h"
51 #include "art/Framework/Core/ModuleMacros.h"
52 #include "art/Framework/Principal/Event.h"
53 #include "canvas/Utilities/InputTag.h"
54 #include "canvas/Utilities/Exception.h"
55 #include "messagefacility/MessageLogger/MessageLogger.h"
56 #include "fhiclcpp/types/Sequence.h"
57 #include "fhiclcpp/types/Atom.h"
60 #include "TEfficiency.h"
73 #ifdef __cpp_lib_source_location
74 # include <source_location>
75 #endif // __cpp_lib_source_location
83 using namespace util::quantities::time_literals;
89 namespace icarus::trigger {
class MajorityTriggerCombiner; }
99 (std::string
const& logCategory =
"MajorityTriggerCombiner")
103 template <
typename GateObj>
104 GateObj
combine(std::vector<GateObj>
const& gates)
const
114 namespace icarus::trigger {
class CryostatTriggerCombiner; }
124 (std::string
const& logCategory =
"CryostatTriggerCombiner")
128 template <
typename GateObj>
129 GateObj
combine(std::vector<GateObj>
const& cryoGates)
const
138 namespace icarus::trigger {
class GeometryChannelSplitter; }
150 std::string
const& logCategory =
"GeometryChannelSplitter"
154 template <
typename GateObj>
155 std::vector<std::vector<GateObj>> byCryostat
156 (std::vector<GateObj>&& gates)
const;
167 static std::vector<geo::CryostatID> makeChannelCryostatMap
176 std::string
const& logCategory
178 : icarus::ns::util::mfLoggingClass(logCategory)
179 , fNCryostats(geom.Ncryostats())
180 , fChannelCryostat(makeChannelCryostatMap(geom))
185 template <
typename GateObj>
186 std::vector<std::vector<GateObj>>
188 (std::vector<GateObj>&& gates)
const
190 std::vector<std::vector<GateObj>> gatesPerCryostat{ fNCryostats };
192 for (
auto& gate: gates) {
193 gatesPerCryostat[fChannelCryostat.at(gate.channels().front()).Cryostat]
194 .push_back(std::move(gate));
197 return gatesPerCryostat;
208 std::vector<geo::CryostatID> channelCryostatMap(nOpChannels);
212 channelCryostatMap.at(opChannel)
216 return channelCryostatMap;
343 :
public art::EDProducer
359 fhicl::Atom<std::string> TriggerGatesTag {
360 Name(
"TriggerGatesTag"),
361 Comment(
"label of the input trigger gate data product (no instance name)")
366 Comment(
"thresholds to consider [ADC counts]")
369 fhicl::Atom<unsigned int> MinimumPrimitives {
370 Name(
"MinimumPrimitives"),
371 Comment(
"minimum required number of trigger primitives for the trigger")
374 fhicl::Atom<microseconds> BeamGateDuration {
375 Name(
"BeamGateDuration"),
376 Comment(
"length of time interval when optical triggers are accepted")
379 fhicl::Atom<std::uint32_t> BeamBits {
381 Comment(
"bits to be set in the trigger object as beam identified")
384 fhicl::Atom<nanoseconds> TriggerTimeResolution {
385 Name(
"TriggerTimeResolution"),
386 Comment(
"resolution of trigger in time"),
390 fhicl::Atom<std::string> LogCategory {
392 Comment(
"name of the category used for the output"),
393 "SlidingWindowTrigger"
417 virtual void beginJob()
override;
420 virtual void produce(art::Event& event)
override;
423 virtual void endJob()
override;
482 std::atomic<unsigned int> fTotalEvents { 0U };
497 void initializePlots();
573 void plotTriggerResponse
578 void printSummary()
const;
584 (art::Event
const* event =
nullptr)
const
593 (art::Event
const& event)
const {
return makeMyBeamGate(&event); }
606 : art::EDProducer (config)
608 , fMinimumPrimitives (config().MinimumPrimitives())
609 , fBeamGateDuration (config().BeamGateDuration())
610 , fTriggerTimeResolution(config().TriggerTimeResolution())
611 , fBeamBits (config().BeamBits())
614 ,
fGeom (*lar::providerFrom<geo::Geometry>())
615 , fOutputDir (*art::ServiceHandle<art::TFileService>())
620 fOutputDir,
"",
"minimum primitives: " +
std::to_string(fMinimumPrimitives)
627 std::string
const discrModuleLabel = config().TriggerGatesTag();
634 fTriggerCount = std::vector<std::atomic<unsigned int>>(fADCthresholds.size());
635 std::fill(fTriggerCount.begin(), fTriggerCount.end(), 0U);
645 consumes<std::vector<OpticalTriggerGateData_t>>(inputDataTag);
646 consumes<art::Assns<OpticalTriggerGateData_t, raw::OpDetWaveform>>
654 produces<std::vector<raw::Trigger>>(inputDataTag.instance());
658 <<
"Requirement of minimum " << fMinimumPrimitives <<
" primitives.";
676 log <<
"Event " <<
event.id() <<
":";
679 = art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event);
681 auto const beamGate = makeMyBeamGate(event);
683 if (
auto oldGate = fGateChangeCheck(beamGate); oldGate) {
685 <<
"Beam gate has changed from " << *oldGate <<
" to " << beamGate <<
"!";
689 for (
auto const [ iThr, thr ]
695 log <<
"\n * threshold " << thr <<
": ";
696 if (triggerInfo) log <<
"trigger at " << triggerInfo.
atTick();
697 else log <<
"not triggered";
721 std::vector<std::string> thresholdLabels;
722 thresholdLabels.reserve(
size(fADCthresholds));
724 thresholdLabels.push_back(inputDataTag.instance());
726 auto const beamGate = makeMyBeamGate();
727 fGateChangeCheck(beamGate);
729 <<
"Beam gate for plots: " << beamGate.asSimulationTime()
730 <<
" (simulation time), " << beamGate.tickRange()
731 <<
" (optical ticks)"
737 auto* NTriggers = fPlots.make<TH1F>(
739 "Number of triggering events"
740 ";PMT discrimination threshold [ ADC counts ]"
742 thresholdLabels.size(), 0.0, double(thresholdLabels.size())
746 auto* Eff = fPlots.make<TEfficiency>(
748 "Efficiency of triggering"
749 ";PMT discrimination threshold [ ADC counts ]"
750 ";trigger efficiency",
751 thresholdLabels.size(), 0.0, double(thresholdLabels.size())
758 (const_cast<TH1*>(Eff->GetTotalHistogram())->GetXaxis(), thresholdLabels);
764 auto const& beamGateTicks = beamGate.tickRange();
765 auto* TrigTime = fPlots.make<TH2F>(
768 ";optical time tick [ /" +
util::to_string(triggerResolutionTicks) +
" ]"
769 ";PMT discrimination threshold [ ADC counts ]"
771 static_cast<int>(std::ceil(beamGate.lengthTicks()/triggerResolutionTicks)),
772 beamGateTicks.start().value(),
774 (beamGateTicks.start() + beamGate.lengthTicks(), triggerResolutionTicks)
776 thresholdLabels.size(), 0.0, double(thresholdLabels.size())
795 art::InputTag
const dataTag = fADCthresholds.at(thr);
802 if (triggerInfo) ++fTriggerCount[iThr];
807 plotTriggerResponse(iThr, triggerInfo);
812 auto triggers = std::make_unique<std::vector<raw::Trigger>>();
813 if (triggerInfo.
fired()) {
815 (triggerInfoToTriggerData(
detTimings, fTriggerCount[iThr], triggerInfo));
817 event.put(std::move(triggers), dataTag.instance());
837 auto const& cryoGates = fChannelSplitter.byCryostat(
TriggerGates_t{ gates });
843 (simulateCryostat(beamGate, iCryo, gatesInCryo));
869 auto const combinedCount = beamGate.
apply(fCombiner.combine(gates));
873 { combinedCount, fMinimumPrimitives };
875 while (extractOpeningInfo) {
876 auto info = extractOpeningInfo();
890 fPlots.demand<TEfficiency>(
"Eff").Fill(triggerInfo.
fired(), iThr);
892 if (triggerInfo.
fired()) {
893 fPlots.demand<TH1>(
"NTriggers").Fill(iThr);
894 fPlots.demand<TH2>(
"TriggerTick").Fill(triggerInfo.
atTick().value(), iThr);
908 <<
"Summary of triggers requiring " << fMinimumPrimitives
909 <<
"+ primitives for " << fTriggerCount.size() <<
" ADC thresholds:"
911 for (
auto const& [
count, thr ]
912 :
util::zip(fTriggerCount, util::get_elements<0U>(fADCthresholds)))
914 log <<
"\n ADC threshold " << thr
915 <<
": " <<
count <<
" events triggered";
916 if (fTotalEvents > 0U)
917 log <<
" (" << (double(count) / fTotalEvents * 100.0) <<
"%)";
929 assert(info.
fired());
bool addAndReplaceIfEarlier(TriggerInfo_t const &other)
If other has fired, and at an earlier tick, set a new main().
BEGIN_PROLOG BeamGateDuration pmtthr physics producers trigtilewindowORS Thresholds
bool fired() const
Returns whether the trigger fired.
std::vector< std::atomic< unsigned int > > fTriggerCount
TriggerInfo_t simulateCryostat(ApplyBeamGateClass const &beamGate, std::size_t iCryo, TriggerGates_t const &gates) const
Simulates the trigger response within a single cryostat.
electronics_time BeamGateTime() const
auto maxGates(GateColl const &gates)
Computes the gate with the maximum opening of gates from collection.
An empty class that can't be copied nor moved.
TriggerInfo_t simulate(ApplyBeamGateClass const &clockData, TriggerGates_t const &gates) const
Performs the simulation of the configured trigger on gates input.
geo::GeometryCore const & fGeom
Utilities related to art service access.
Utilities for the conversion of trigger gate data formats.
std::string const fLogCategory
Message facility stream category for output.
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.
void sortOpenings()
Sorts all openings by time.
constexpr T roundup(T const value, U const quantum, T const offset=T{})
Returns the value, rounded up.
Definition of util::get_elements() and util::get_const_elements().
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.
Defines classes that can't be copied nor moved.
art::TFileDirectory fOutputDir
ROOT directory where all the plots are written.
std::map< icarus::trigger::ADCCounts_t, art::InputTag > fADCthresholds
ADC thresholds to read, and the input tag connected to their data.
GeometryChannelSplitter(geo::GeometryCore const &geom, std::string const &logCategory="GeometryChannelSplitter")
Base class facilitating logging to message facility.
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.
std::size_t size(FixedBins< T, C > const &) noexcept
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).
Helper applying a beam gate to any gate.
Helper to check if an object has changed. Thread-safe.
unsigned int NOpChannels() const
Number of electronics channels for all the optical detectors.
pure virtual base interface for detector clocks
Helper for logging classes.
Helper data structure to store transient trigger result.
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
unsigned int const fMinimumPrimitives
Minimum number of trigger primitives for a trigger to happen.
Combines a group of trigger gates for majority trigger. Glorified Sum().
timescale_traits< OpticalTimeCategory >::tick_interval_t optical_time_ticks
Interface to detinfo::DetectorClocks.
Access the description of detector geometry.
std::vector< geo::CryostatID > const fChannelCryostat
Map: optical channel ID -> number of the cryostat with that channel.
raw::Trigger triggerInfoToTriggerData(detinfo::DetectorTimings const &detTimings, unsigned int triggerNumber, TriggerInfo_t const &info) const
Converts the trigger information into a raw::Trigger object.
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
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.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
GateObj combine(std::vector< GateObj > const &gates) const
Combines all the gates (by cryostat) in a single majority gate.
Simple functions to streamline the creation of DetectorClocksData.
A value measured in the specified unit.
Simple type definitions for trigger algorithms.
std::vector< std::vector< GateObj > > byCryostat(std::vector< GateObj > &&gates) const
Splits the gates by cryostat.
art::EDProducer::Table< Config > Parameters
void plotTriggerResponse(std::size_t iThr, TriggerInfo_t const &triggerInfo) const
Fills the plots for threshold index iThr with trigger information.
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.
std::uint32_t fBeamBits
Bits for the beam gate being simulated.
unsigned int const fNCryostats
Number of cryostats in the detector.
virtual void endJob() override
Prints end-of-job summaries.
icarus::ns::util::ThreadSafeChangeMonitor< icarus::trigger::ApplyBeamGateClass > fGateChangeCheck
Functor returning whether a gate has changed.
Utilities for the conversion of trigger gate data formats.
void fill(const art::PtrVector< recob::Hit > &hits, int only_plane)
BEGIN_PROLOG vertical distance to the surface Name
void initializePlots()
Initializes the full set of plots (all ADC thresholds).
Test of util::counter and support utilities.
Simulates a "majority" trigger.
Description of geometry of one entire detector.
static std::vector< geo::CryostatID > makeChannelCryostatMap(geo::GeometryCore const &geom)
Creates a map like fChannelCryostat from the geometry information.
An interval (duration, length, distance) between two quantity points.
Definition of data types for geometry description.
auto sumGates(GateColl const &gates)
Sums all the gates in a collection.
GeometryChannelSplitter fChannelSplitter
Algorithm to sort trigger gates by cryostat or TPC.
nanoseconds_as<> nanoseconds
Type of time interval stored in nanoseconds, in double precision.
std::vector< InputTriggerGate_t > TriggerGates_t
A list of trigger gates from input.
Utilities to read interval and point quantity FHiCL configuration.
Gate apply(Gate gate) const
Returns a copy of gate in AND with this beam gate.
timescale_traits< OpticalTimeCategory >::tick_t optical_tick
Classes to detect the change of object values.
optical_tick atTick() const
Returns the time of the trigger (undefined if !fired()).
virtual void produce(art::Event &event) override
Runs the simulation and saves the results into the art event.
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.
Data types for detinfo::DetectorTimings.
Functions pulling in STL customization if available.
Class to create an object representing a beam gate.
GateObj combine(std::vector< GateObj > const &cryoGates) const
Combines all the gates (by cryostat) in a single majority gate.
MajorityTriggerSimulation(Parameters const &config)
void printSummary() const
Prints the summary of fired triggers on screen.
A simple alias for a most commonly used TrackedTriggerGate type.
microseconds fBeamGateDuration
Duration of the gate during with global optical triggers are accepted.
geo::OpDetID const & ID() const
Returns the geometry ID of this optical detector.
auto zip(Iterables &&...iterables)
Range-for loop helper iterating across many collections at the same time.
Definition of util::values() and util::const_values().
std::size_t count(Cont const &cont)
MajorityTriggerCombiner const fCombiner
Algorithm to combine primitives.
Combines cryostat triggers via OR. Glorified Max().
std::vector< icarus::trigger::TrackedOpticalTriggerGate< OpDetInfo > > ReadTriggerGates(Event const &event, art::InputTag const &dataTag)
Assembles and returns trigger gates from serialized data.
detinfo::DetectorClocksData makeDetClockData(art::Event const *event)
Returns a detinfo::DetectorClocksData from DetectorClocksService.
TriggerInfo_t produceForThreshold(art::Event &event, detinfo::DetectorTimings const &detTimings, ApplyBeamGateClass const &beamGate, std::size_t const iThr, icarus::trigger::ADCCounts_t const thr)
Performs the simulation for the specified ADC threshold.
OpDetGeo const & OpDetGeoFromOpChannel(unsigned int OpChannel) const
Returns the geo::OpDetGeo object for the given channel number.
nanoseconds fTriggerTimeResolution
Trigger resolution in time.
bool IsValidOpChannel(int opChannel) const
Is this a valid OpChannel number?
void add(OpeningInfo_t info)
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.
Combines cryostat triggers via OR. Glorified Max().
icarus::trigger::PlotSandbox fPlots
All plots in one practical sandbox.
A helper to manage ROOT objects with consistent naming.