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