33 #include "art/Framework/Core/ModuleMacros.h" 
   34 #include "art/Framework/Core/EDProducer.h" 
   35 #include "art/Framework/Principal/Event.h" 
   36 #include "art/Framework/Principal/Handle.h" 
   37 #include "art/Persistency/Common/PtrMaker.h" 
   38 #include "art/Utilities/make_tool.h" 
   39 #include "canvas/Persistency/Common/Assns.h" 
   40 #include "canvas/Persistency/Common/Ptr.h" 
   41 #include "canvas/Utilities/InputTag.h" 
   42 #include "cetlib_except/exception.h" 
   43 #include "messagefacility/MessageLogger/MessageLogger.h" 
   44 #include "fhiclcpp/types/OptionalSequence.h" 
   45 #include "fhiclcpp/types/OptionalAtom.h" 
   46 #include "fhiclcpp/types/Atom.h" 
   47 #include "fhiclcpp/types/DelegatedParameter.h" 
   48 #include "fhiclcpp/ParameterSet.h" 
   58 namespace icarus::trigger { 
class DiscriminatePMTwaveforms; }
 
  166       Name(
"OpticalWaveforms"),
 
  167       Comment(
"label of input digitized optical waveform data product"),
 
  173       Comment(
"label of input waveform baselines (parallel to the waveforms)")
 
  178       Comment(
"constant baseline for all waveforms, in ADC counts")
 
  182       Name(
"TriggerGateBuilder"),
 
  184         (
"parameters for generating trigger gates from optical channel output")
 
  189       Comment(
"minimum number of channels to provide (default: all)")
 
  193       Name(
"SavePMTcoverage"),
 
  194       Comment(
"write also a sbn::OpDetWaveformMeta collection"),
 
  199       Name(
"OutputCategory"),
 
  200       Comment(
"tag of the module output to console via message facility"),
 
  201       "DiscriminatePMTwaveforms" 
  205       Name(
"SelectThresholds"),
 
  206       Comment(
"thresholds to save (default: all those produced by algorithm)")
 
  230   virtual void produce(art::Event& event) 
override;
 
  292     (fhicl::OptionalAtom<unsigned int> 
const& param);
 
  305   : art::EDProducer(config)
 
  310   , fNOpDetChannels(getNOpDetChannels(config().
NChannels))
 
  311   , fSavePMTcoverage(config().SavePMTcoverage())
 
  313   , fTriggerGateBuilder
 
  315       art::make_tool<icarus::trigger::TriggerGateBuilder>
 
  316         (config().TriggerGateBuilder_.get<fhicl::ParameterSet>())
 
  323     throw art::Exception(art::errors::Configuration)
 
  324       << 
"Both `Baselines` ('" << fBaselineTag->encode()
 
  326       << 
") parameters specified, but they are exclusive!\n";
 
  329     throw art::Exception(art::errors::Configuration)
 
  330       << 
"Either `Baselines` or `Baseline` parameters is required.\n";
 
  333   std::vector<raw::ADC_Count_t> selectedThresholds;
 
  334   if (!config().SelectThresholds(selectedThresholds)) {
 
  335     std::vector<ADCCounts_t> 
const& allThresholds
 
  336       = fTriggerGateBuilder->channelThresholds();
 
  338     if (allThresholds.empty()) {
 
  339       throw art::Exception(art::errors::Configuration)
 
  340         << 
"Trigger building algorithm reports no threshold!\n" 
  341         << 
"Check the configuration of `TriggerGateBuilder` tool.\n";
 
  344       allThresholds.begin(), allThresholds.end(),
 
  345       std::back_inserter(selectedThresholds),
 
  350   else if (selectedThresholds.empty()) {
 
  351     throw art::Exception(art::errors::Configuration)
 
  352       << 
"Configured to save no thresholds!\n" 
  353       << 
"Add values to the `SelectThresholds` configuration parameter.\n";
 
  356   for (
auto const& threshold: selectedThresholds) {
 
  363     log << 
"Selected thresholds:";
 
  364     for (
auto const& [ threshold, 
instance ]: fSelectedThresholds)
 
  365       log << 
" " << threshold << 
" (\"" << 
instance << 
"\")";
 
  371   consumes<std::vector<raw::OpDetWaveform>>(fOpDetWaveformTag);
 
  377   if (fSavePMTcoverage) {
 
  378     produces<std::vector<sbn::OpDetWaveformMeta>>();
 
  379     produces<art::Assns<raw::OpDetWaveform, sbn::OpDetWaveformMeta>>();
 
  383     produces<std::vector<TriggerGateData_t>>(instanceName);
 
  384     produces<art::Assns<TriggerGateData_t, raw::OpDetWaveform>>(instanceName);
 
  385     if (fSavePMTcoverage) {
 
  386       produces<art::Assns<sbn::OpDetWaveformMeta, TriggerGateData_t>>
 
  401     art::ServiceHandle<detinfo::DetectorClocksService const>()->DataFor(event)
 
  408   auto const& waveformHandle
 
  410   auto const& waveforms = *waveformHandle;
 
  413   auto const& opDetWavePtrs
 
  419   std::vector<icarus::WaveformBaseline> fixedBaselines;
 
  420   std::vector<icarus::WaveformBaseline> 
const* baselines = 
nullptr;
 
  423       &(
event.getProduct<std::vector<icarus::WaveformBaseline>>(*fBaselineTag));
 
  426     fixedBaselines.resize
 
  428     baselines = &fixedBaselines;
 
  434   if (baselines->size() != waveforms.size()) {
 
  436     throw cet::exception(
"DiscriminatePMTwaveforms")
 
  437       << 
"Incompatible baseline information for the waveforms: " 
  439       << 
") for " << baselines->size() << 
" baselines (" 
  442   std::vector<icarus::trigger::WaveformWithBaseline> waveformInfo;
 
  443   waveformInfo.reserve(waveforms.size());
 
  445     waveformInfo.emplace_back(&waveform, &
baseline);
 
  449     log << 
"Discrimination of " << waveforms.size() << 
" PMT waveforms from '" 
  452       log << 
" with baselines from '" << 
fBaselineTag->encode() << 
"'";
 
  462   std::vector<icarus::trigger::TriggerGateBuilder::TriggerGates> 
const&
 
  467     log << 
"Trigger gates from " << triggerGatesByThreshold.size()
 
  469     for (
auto const& triggerGates: triggerGatesByThreshold)
 
  470       triggerGates.dump(log);
 
  478   std::optional<art::PtrMaker<sbn::OpDetWaveformMeta>> 
const makePMTinfoPtr
 
  480     ? std::optional<art::PtrMaker<sbn::OpDetWaveformMeta>>(event)
 
  485     : triggerGatesByThreshold
 
  496     std::string 
const& instanceName = iThr->second;
 
  497     art::PtrMaker<TriggerGateData_t> 
const makeGatePtr(event, instanceName);
 
  502     auto [ discrGates, waveGateAssns ]
 
  504         (
fillChannelGaps(std::move(gates).gates()), makeGatePtr, opDetWavePtrs)
 
  510       assert(makePMTinfoPtr);
 
  511       art::Assns<sbn::OpDetWaveformMeta, TriggerGateData_t> assns;
 
  512       for (
auto [ gatePtr, wavePtr ]: waveGateAssns)
 
  513         assns.addSingle((*makePMTinfoPtr)(wavePtr.key()), gatePtr);
 
  515         std::make_unique<art::Assns<sbn::OpDetWaveformMeta, TriggerGateData_t>>
 
  525       std::make_unique<std::vector<TriggerGateData_t>>(std::move(discrGates)),
 
  529       std::make_unique<art::Assns<TriggerGateData_t, raw::OpDetWaveform>>
 
  530         (std::move(waveGateAssns)),
 
  539     assert(makePMTinfoPtr);
 
  543     std::vector<sbn::OpDetWaveformMeta> PMTinfo;
 
  544     art::Assns<raw::OpDetWaveform, sbn::OpDetWaveformMeta> assns;
 
  545     art::PtrMaker<raw::OpDetWaveform> 
const makeWavePtr
 
  546       { event, waveformHandle.id() };
 
  548     for (
auto const& [ iWaveform, waveform ]: 
util::enumerate(waveforms)) {
 
  550       PMTinfo.push_back(makePMTinfo(waveform));
 
  552       assns.addSingle(makeWavePtr(iWaveform), (*makePMTinfoPtr)(iWaveform));
 
  557       (std::make_unique<std::vector<sbn::OpDetWaveformMeta>>(std::move(PMTinfo)));
 
  559       std::make_unique<art::Assns<raw::OpDetWaveform, sbn::OpDetWaveformMeta>>
 
  577   using Gate_t = GateDataColl_t::value_type; 
 
  582   std::vector<Gate_t const*> gateMap(fNOpDetChannels, 
nullptr);
 
  583   for (Gate_t 
const& gate: gates) {
 
  584     assert(!gate.channels().empty());
 
  586     auto const channel = gate.channels().front();
 
  587     if (static_cast<std::size_t>(channel) >= gateMap.size())
 
  588       gateMap.resize(channel + 1U, 
nullptr);
 
  589     assert(gateMap[channel] == 
nullptr);
 
  590     gateMap[channel] = &gate;
 
  597   GateDataColl_t allGates;
 
  598   allGates.reserve(gateMap.size());
 
  602       assert(gate->channels().front() == channelNo);
 
  603       allGates.push_back(std::move(*gate));
 
  606       allGates.emplace_back(
 
  619   (fhicl::OptionalAtom<unsigned int> 
const& param)
 
  621   unsigned int nChannels;
 
  623     param(nChannels)? nChannels: lar::providerFrom<geo::Geometry>()->
NOpDets();
 
Definition of util::zip(). 
 
Utilities related to art service access. 
 
Utilities for the conversion of trigger gate data formats. 
 
std::optional< typename Optional::value_type > getOptionalValue(Optional const ¶meter)
Returns the value of an optional parameter as std::optional. 
 
Definition of util::enumerate(). 
 
Algorithm to produce trigger gates out of optical readout waveforms. 
 
std::vector< icarus::trigger::OpticalTriggerGateData_t > transformIntoOpticalTriggerGate(Gates &&gates)
Returns the trigger gates in serializable format. 
 
decltype(auto) const_values(Coll &&coll)
Range-for loop helper iterating across the constant values of the specified collection. 
 
const std::string instance
 
constexpr value_t value() const 
Returns the value of the quantity. 
 
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration. 
 
Interface to detinfo::DetectorClocks. 
 
Container of logical gates for all triggering channels for a threshold. 
 
Logical multi-level gate associated to one or more readout channels. 
 
Utilities to read and write quantities in FHiCL configuration. 
 
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string. 
 
A value measured in the specified unit. 
 
Simple type definitions for trigger algorithms. 
 
A trigger gate data object for optical detector electronics. 
 
BEGIN_PROLOG vertical distance to the surface Name
 
physics producers discrimopdaq OpticalWaveforms
 
size_t NOpDets(int cryostat)
 
A class exposing an upgraded interface of detinfo::DetectorClocksData. 
 
Functions pulling in STL customization if available. 
 
DataProductPointerMap_t< ArtHandleData_t< Handle > > mapDataProductPointers(art::Event const &event, Handle const &handle)
Creates a map from address of data product element to art pointer to it. 
 
std::vector< triggergate_t > GateData_t
 
Simple helper functions to deal with FHiCL. 
 
auto zip(Iterables &&...iterables)
Range-for loop helper iterating across many collections at the same time. 
 
Definition of util::values() and util::const_values(). 
 
OpticalTriggerGateData_t GateData_t
Type for gate data access. 
 
art framework interface to geometry description 
 
Utilities to map data pointer elements to their art::Ptr.