21 #include "art_root_io/TFileService.h"
22 #include "art_root_io/TFileDirectory.h"
23 #include "art/Framework/Core/ModuleMacros.h"
24 #include "art/Framework/Core/EDProducer.h"
25 #include "art/Framework/Principal/Event.h"
26 #include "art/Framework/Principal/Handle.h"
27 #include "art/Persistency/Common/PtrMaker.h"
28 #include "canvas/Persistency/Common/Assns.h"
29 #include "canvas/Persistency/Common/Ptr.h"
30 #include "canvas/Utilities/InputTag.h"
31 #include "cetlib_except/exception.h"
32 #include "messagefacility/MessageLogger/MessageLogger.h"
33 #include "fhiclcpp/types/Atom.h"
50 namespace icarus {
class PMTWaveformBaselines; }
127 Name(
"OpticalWaveforms"),
128 Comment(
"label of input digitized optical waveform data product")
132 Name(
"OutputCategory"),
133 Comment(
"tag of the module output to console via message facility"),
134 "PMTWaveformBaselines"
138 Name(
"PlotBaselines"),
139 Comment(
"produce plots on the extracted baseline"),
144 Name(
"BaselineTimeAverage"),
145 Comment(
"binning of the baseline profile vs. time [s]"),
168 virtual void produce(art::Event& event)
override;
171 virtual void endJob()
override;
228 template <
typename BIter,
typename EIter>
229 auto median(BIter
begin, EIter
end) {
231 using value_type =
typename BIter::value_type;
233 std::vector<value_type> data{
begin, end };
234 assert(!data.empty());
236 auto const middle = data.begin() + data.size() / 2;
237 std::nth_element(data.begin(), middle, data.end());
251 : art::EDProducer(config)
254 , fPlotBaselines(config().PlotBaselines())
255 , fBaselineTimeAverage(config().BaselineTimeAverage())
266 <<
"Using the standard (median) algorithm, waveform by waveform, on '"
267 << fOpDetWaveformTag.encode() <<
"'.";
272 consumes<std::vector<raw::OpDetWaveform>>(fOpDetWaveformTag);
277 produces<std::vector<icarus::WaveformBaseline>>();
278 produces<art::Assns<icarus::WaveformBaseline, raw::OpDetWaveform>>();
300 auto const& waveformHandle
301 =
event.getValidHandle<std::vector<raw::OpDetWaveform>>(fOpDetWaveformTag);
302 auto const& waveforms = *waveformHandle;
316 std::vector<icarus::WaveformBaseline> baselines;
317 baselines.reserve(waveforms.size());
319 std::vector<lar::util::StatCollector<double>> averages;
320 if (fHBaselines || !fBaselinesVsTime.empty())
321 averages.resize(fNPlotChannels);
323 art::Assns<icarus::WaveformBaseline, raw::OpDetWaveform> baselineToWaveforms;
325 art::PtrMaker<icarus::WaveformBaseline>
const makeBaselinePtr(event);
327 for (
auto const& [ iWaveform, waveform ]:
util::enumerate(waveforms)) {
328 assert(iWaveform == baselines.size());
332 if (!averages.empty())
333 averages[waveform.ChannelNumber()].add(
baseline.baseline());
336 baselineToWaveforms.addSingle(
337 makeBaselinePtr(iWaveform),
338 art::Ptr<raw::OpDetWaveform>(waveformHandle, iWaveform)
346 if (!averages.empty()) {
348 double const eventTime =
static_cast<double>(
event.time().timeHigh())
349 + static_cast<double>(event.time().timeHigh()) * 1
e-9;
352 if (
stat.N() == 0)
continue;
354 double const aveBaseline =
stat.Average();
356 fHBaselines->Fill(
double(channel), aveBaseline);
358 if (channel < fBaselinesVsTime.size())
359 fBaselinesVsTime[channel].emplace_back(eventTime, aveBaseline);
369 std::make_unique<std::vector<icarus::WaveformBaseline>>
370 (std::move(baselines))
373 std::make_unique<art::Assns<icarus::WaveformBaseline, raw::OpDetWaveform>>
374 (std::move(baselineToWaveforms))
384 if (fPlotBaselines) buildBaselineGraphs();
392 auto const&
tfs = *(art::ServiceHandle<art::TFileService>());
393 auto const& geom = *(lar::providerFrom<geo::Geometry const>());
395 fNPlotChannels = geom.NOpChannels();
397 fHBaselines =
tfs.make<TH2F>(
399 "PMT baseline;channel;baseline per channel [ / 8 ADC ]",
400 fNPlotChannels, 0.0, double(fNPlotChannels),
401 256, 13312.0, 15360.0
408 fBaselinesVsTime.resize(fNPlotChannels);
416 auto&
tfs = *(art::ServiceHandle<art::TFileService>());
418 art::TFileDirectory graphDir =
tfs.mkdir(
"graphs",
"Baseline vs. time");
419 art::TFileDirectory profileDir
420 =
tfs.mkdir(
"profiles",
"Baseline profiles vs. time");
422 for (
auto const channel:
util::counter(fBaselinesVsTime.size())) {
424 auto& timeAndBaselines = fBaselinesVsTime[channel];
425 if (timeAndBaselines.empty())
continue;
429 std::sort(timeAndBaselines.begin(), timeAndBaselines.end());
432 auto*
const graph = graphDir.makeAndRegister<TGraph>(
434 "PMT channel #" +
std::to_string(channel) +
": baseline vs. run time",
435 timeAndBaselines.size()
437 assert(graph->GetXaxis());
438 assert(graph->GetYaxis());
439 graph->GetXaxis()->SetTitle(
"event time");
440 graph->GetYaxis()->SetTitle(
"baseline [ ADC ]");
444 double const startTime = timeAndBaselines.front().first;
445 double const totalTime = timeAndBaselines.back().first - startTime;
446 auto const nBins = std::max(1U,
447 static_cast<unsigned int>(std::ceil(totalTime / fBaselineTimeAverage))
449 double const endTime = startTime + nBins * fBaselineTimeAverage;
451 auto*
const profile = profileDir.make<TProfile>(
453 (
"PMT channel #" +
std::to_string(channel) +
": baseline vs. run time")
455 nBins, startTime, endTime
457 assert(profile->GetXaxis());
458 assert(profile->GetYaxis());
459 profile->GetXaxis()->SetTitle(
460 (
"event time [ / " +
std::to_string(fBaselineTimeAverage) +
" s ]")
463 profile->GetYaxis()->SetTitle(
"average baseline [ ADC ]");
466 auto const [ time,
baseline ] = data;
482 { waveform.empty()? 0.0f: median(waveform.begin(), waveform.end()) };
Utilities related to art service access.
Definition of util::enumerate().
Classes gathering simple statistics.
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Access the description of detector geometry.
auto counter(T begin, T end)
Returns an object to iterate values from begin to end in a range-for loop.
auto end(FixedBins< T, C > const &) noexcept
BEGIN_PROLOG vertical distance to the surface Name
auto begin(FixedBins< T, C > const &) noexcept
physics producers discrimopdaq OpticalWaveforms
std::string to_string(WindowPattern const &pattern)
art::ServiceHandle< art::TFileService > tfs
art framework interface to geometry description