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.