All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DetectorActivityRatePlots.cpp
Go to the documentation of this file.
1 /**
2  * @file DetectorActivityRatePlots.cpp
3  * @brief Draws some plots of detector activity with time. For simulation.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date October 13, 2020
6  *
7  * The configuration requires:
8  *
9  * * `services` table with `Geometry`, `LArPropertiesService`,
10  * `DetectorClocksService` and `DetectorPropertiesService`
11  * * `analysis` table configuring the job
12  *
13  */
14 
15 // local libraries
16 #include "Binner.h"
17 
18 // SBN code
19 #include "icarusalg/Utilities/ROOTutils.h" // util::ROOT::TDirectoryChanger
21 
22 // LArSoft
23 // - data products
27 
28 // - DetectorProperties
32 // - DetectorClocks
37 // - LArProperties
40 // - Geometry
44 
45 // - configuration
47 // - utilities
49 #include "lardataalg/DetectorInfo/DetectorTimingTypes.h" // simulation_time, ...
51 #include "lardataalg/Utilities/intervals_fhicl.h" // microseconds from FHiCL
52 #include "lardataalg/Utilities/quantities/energy.h" // megaelectronvolt
53 #include "lardataalg/Utilities/quantities/electronics.h" // tick, ticks
54 #include "lardataalg/Utilities/quantities/spacetime.h" // microseconds, ...
56 
57 // gallery/canvas
58 #include "gallery/Event.h"
59 #include "canvas/Utilities/InputTag.h"
60 #include "messagefacility/MessageLogger/MessageLogger.h"
61 #include "fhiclcpp/types/Table.h"
62 #include "fhiclcpp/types/Atom.h"
63 #include "fhiclcpp/ParameterSet.h"
64 
65 // ROOT
66 #include "TFile.h"
67 #include "TDirectory.h"
68 #include "TProfile.h"
69 
70 // C/C++ standard libraries
71 // #include <string>
72 #include <algorithm> // std::accumulate()
73 #include <vector>
74 #include <array>
75 #include <memory> // std::make_unique()
76 #include <iostream> // std::cerr, std::endl
77 #include <limits>
78 #include <cmath> // std::ceil(), std::floor()
79 
80 
81 // #if !defined(__CLING__)
82 // // these are needed in the main() function
83 #include <algorithm> // std::copy()
84 #include <iterator> // std::back_inserter()
85 // #include <iostream> // std::cerr
86 // #endif // !__CLING__
87 
88 // -----------------------------------------------------------------------------
89 // --- Utilities
90 // -----------------------------------------------------------------------------
91 namespace {
92 
93  template <typename Time>
94  using timetraitsOf_t
96 
97  template <typename Time>
98  constexpr std::string timeScaleName() { return timetraitsOf_t<Time>::name(); }
99 
100  template <typename DestTime, typename Stream, typename Time>
101  void printConvertedTimeRange(
102  Stream&& out, Time start, Time stop,
104  ) {
105  out << timeScaleName<DestTime>() << ": "
106  << detTimings.toTimeScale<DestTime>(start) << " -- "
107  << detTimings.toTimeScale<DestTime>(stop)
108  ;
109  } // printConvertedTimeRange()
110 
111  template <typename DestTick, typename Stream, typename Time>
112  void printConvertedTickRange(
113  Stream&& out, Time start, Time stop,
115  ) {
116  out << timeScaleName<DestTick>()
117  << " ticks: " << detTimings.toTick<DestTick>(start)
118  << " -- " << detTimings.toTick<DestTick>(stop)
119  ;
120  } // printConvertedTickRange()
121 
122 } // local namespace
123 
124 
125 // -----------------------------------------------------------------------------
126 // --- algorithm classes
127 // -----------------------------------------------------------------------------
128 
129 /**
130  * @brief Produces plots. Aaah!
131  *
132  * Algorithm workflow:
133  *
134  * 1. construction
135  * 2. `setup()`
136  * 3. `prepare()`
137  * 4. for each event:
138  * 1. `setupEvent()`
139  * 2. `plotEvent()`
140  * 5. `finish()`
141  *
142  */
144 
146 
147  /// Time scale used for plotting of generation and particle level simulation.
150 
151  using simulation_time = simulation_time_scale::time_point_t;
154 
155  /// Unit the energy depositions are stored in (LArSoft convention).
157 
158 
159  /// Data structure with all the configuration.
161  template <typename Point>
162  struct BinConfig {
163  using Point_t = Point;
168  };
169 
170  art::InputTag edepTag { "largeant", "TPCActive" };
171  art::InputTag chanTag { "largeant" };
172  art::InputTag photTag { "largeant" };
173 
177 
178  }; // AlgorithmConfiguration
179 
180 
181  // --- BEGIN -- Data members -------------------------------------------------
182 
183  // ----- BEGIN -- Configuration ----------------------------------------------
184 
185  /// Complete configuration of the algorithm.
187 
191 
192  // ----- END -- Configuration ------------------------------------------------
193 
194  // ----- BEGIN -- Setup ------------------------------------------------------
195  /// ROOT directory where to write the plots.
196  TDirectory* fDestDir = nullptr;
197 
198  std::optional<detinfo::DetectorTimings> fDetTimings;
199  std::optional<detinfo::DetectorPropertiesData> fDetPropsData;
200  // ----- END -- Setup --------------------------------------------------------
201 
202 
203  // ----- BEGIN -- Plots ------------------------------------------------------
204  /// Average amount of deposited energy per time [GeV].
205  std::unique_ptr<TProfile> fEDepDistrib;
206 
207  /// Average amount of ionization collected per time.
208  std::unique_ptr<TProfile> fTPCchargeDistrib;
209 
210  /// Average number of photon per time.
211  std::unique_ptr<TProfile> fPhotonDistrib;
212  // ----- END -- Plots --------------------------------------------------------
213 
214  /// Statistics of the total energy per event.
216 
217  /// Statistics of the total charge (electron count) per event.
219 
220  /// Statistics of the total light (photoelectron count) per event.
222 
223 
224  // --- END -- Data members ---------------------------------------------------
225 
226  public:
227 
228  /// Name of the recommended configuration table for this algorithm.
229  static std::string const ConfigurationKey;
230 
231  struct FHiCLconfig {
232 
233  using Name = fhicl::Name;
234  using Comment = fhicl::Comment;
235 
240 
241  template <typename Point, typename Interval>
242  struct BinningConfig {
243  fhicl::Atom<Point> Start {
244  Name{ "Start" },
245  Comment{ "start of the range" }
246  };
247  fhicl::Atom<Point> Stop {
248  Name{ "Stop" },
249  Comment{ "end of the range" }
250  };
251  fhicl::Atom<Interval> Step {
252  Name{ "Step" },
253  Comment{ "duration of steps in the range" }
254  };
255  }; // BinningConfig
256 
257 
258  fhicl::Atom<art::InputTag> Deposits {
259  Name{ "Deposits" },
260  Comment{ "input tag for energy deposit data product" },
261  art::InputTag{ "largeant", "TPCActive" }
262  };
263  fhicl::Atom<art::InputTag> TPCchannels {
264  Name{ "TPCchannels" },
265  Comment{ "input tag for simulated TPC channel data product" },
266  "largeant"
267  };
268  fhicl::Atom<art::InputTag> OpDetChannels {
269  Name{ "OpDetChannels" },
270  Comment{ "input tag for simulated optical detector channel data product" },
271  "largeant"
272  };
273 
274  fhicl::Table<BinningConfig<millisecond, milliseconds>> SimBinning {
275  Name{ "SimulationBinning" },
276  Comment{ "range and binning for simulation times (simulation time) [ms]" }
277  };
278 
279  fhicl::Table<BinningConfig<tick, ticks>> TPCBinning {
280  Name{ "TPCBinning" },
281  Comment{ "range and binning for TPC readout [electronics ticks]" }
282  };
283 
284  fhicl::Table<BinningConfig<millisecond, milliseconds>> OpDetBinning {
285  Name{ "OpDetBinning" },
286  Comment{ "range and binning for optical detector simulation (beam gate time)" }
287  };
288 
289  }; // FHiCLconfig
290 
291  using Parameters = fhicl::Table<FHiCLconfig>;
292 
293 
294  /// Constructor: reads the configuration from the specified parameters set.
295  PlotDetectorActivityRates(Parameters const& config);
296 
297 // /// Constructor: reads the configuration from the specified parameters set.
298 // PlotDetectorActivityRates(fhicl::ParameterSet const& pset);
299 
300 
301  /// Prints on `out` screen a configuration summary.
302  static void printConfigurationHelp(std::ostream& out);
303 
304 
305  /**
306  * @brief Sets the algorithm up.
307  * @param pDestDir ROOT output directory for the plots
308  * @param clocksData detector clocks information (event-independent)
309  * @param propsData detector properties information (event-independent)
310  */
311  void setup(
312  TDirectory* pDestDir,
313  detinfo::DetectorClocksData&& clocksData,
315  );
316 
317  /// Performs the initialization of the algorithm.
318  void prepare();
319 
320  /// Set up for a specific event.
321  void setupEvent(
322  detinfo::DetectorClocksData&& clocksData,
324  );
325 
326  /// Processes a single event.
327  template <typename Event>
328  void plotEvent(Event const& event);
329 
330  /// Completes and saves the plots.
331  void finish();
332 
333 
334  /// Prints the current configuration to the specified output stream.
335  template <typename Stream>
336  void printConfig(Stream&& out) const;
337 
338  /// Prints some information about configured timing.
339  template <typename Stream>
340  void printTimingSummary(Stream&& out) const;
341 
342  private:
343 
344 
345  // --- BEGIN -- Configuration ------------------------------------------------
346 
348  (fhicl::ParameterSet const& pset);
349 
351  (FHiCLconfig const& config);
352 
354  (fhicl::ParameterSet const& pset)
356 
357  template <typename ConfigOut>
358  static void parseBinning
359  (ConfigOut& binConfig, fhicl::ParameterSet const& pset);
360 
361  template <typename ConfigOut, typename ConfigIn>
362  static void parseAndValidateBinning
363  (ConfigOut& binConfig, ConfigIn const& config);
364 
365  template <typename T, typename BinConfig>
366  static util::Binner<T> makeBinning(BinConfig const& config)
367  { return { config.start, config.stop, config.step }; }
368 
369  template <typename T>
370  static void readParam
371  (fhicl::ParameterSet const& pset, std::string const& key, T& var)
372  { var = pset.get<T>(key); }
373 
374  // --- END -- Configuration --------------------------------------------------
375 
376 
377  // --- BEGIN -- Plot management ----------------------------------------------
378 
379  /// Performs the initialization of the plots filled by the algorithm.
380  void initializePlots();
381 
382  /// Performs the initialization of plots pertaining energy deposits.
384 
385  /// Performs the initialization of plots pertaining collected TPC charge.
387 
388  /// Performs the initialization of plots pertaining collected photoelectrons.
389  void initializePhotonPlots();
390 
391  /// Writes all plots into the current ROOT directory (and then deletes them).
392  void savePlots();
393 
394  /// Prints on screen some collected statistics.
395  void printStats() const;
396 
397  // --- END -- Plot initialization --------------------------------------------
398 
399 
400  // --- BEGIN -- Plots --------------------------------------------------------
401 
402  /// Plots data from energy deposits in liquid argon.
403  void plotEnergyDeposits(std::vector<sim::SimEnergyDeposit> const& energyDeps);
404 
405  /// Plots data from photoelectron collection.
406  void plotTPCionization(std::vector<sim::SimChannel> const& TPCchannels);
407 
408  /// Plots data from photoelectron collection.
409  void plotPhotons(std::vector<sim::SimPhotons> const& photonChannels);
410 
411  // --- END -- Plots ----------------------------------------------------------
412 
413 
414  /// Writes `plot` into the current ROOT directory, then deletes it.
415  template <typename Plot>
416  static void Serialize(std::unique_ptr<Plot>& plot);
417 
418 }; // PlotDetectorActivityRates
419 
420 
421 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
422 std::string const PlotDetectorActivityRates::ConfigurationKey { "plot" };
423 
424 
425 
427  (Parameters const& config)
428  : fConfig{ parseValidatedAlgorithmConfiguration(config()) }
429  , fSimBinner{ makeBinning<simulation_time>(fConfig.simBinning) }
430  , fTPCBinner{ makeBinning<electronics_tick>(fConfig.TPCBinning) }
431  , fOpDetBinner{ makeBinning<trigger_time>(fConfig.opDetBinning) }
432  {}
433 
434 
436  (fhicl::ParameterSet const& pset) -> AlgorithmConfiguration
437 {
438  AlgorithmConfiguration algConfig;
439  algConfig.edepTag = pset.get<art::InputTag>("Deposits", "largeant");
440  algConfig.chanTag = pset.get<art::InputTag>("TPCchannels", "largeant");
441  algConfig.photTag = pset.get<art::InputTag>("OpDetChannels", "largeant");
442 
443  parseBinning
444  (algConfig.simBinning, pset.get<fhicl::ParameterSet>("SimBinning"));
445  parseBinning
446  (algConfig.TPCBinning, pset.get<fhicl::ParameterSet>("TPCBinning"));
447  parseBinning
448  (algConfig.opDetBinning, pset.get<fhicl::ParameterSet>("OpDetBinning"));
449 
450  return algConfig;
451 } // PlotDetectorActivityRates::parseAlgorithmConfiguration()
452 
453 
456 {
457  AlgorithmConfiguration algConfig;
458  algConfig.edepTag = config.Deposits();
459  algConfig.chanTag = config.TPCchannels();
460  algConfig.photTag = config.OpDetChannels();
461  parseAndValidateBinning(algConfig.simBinning, config.SimBinning());
462  parseAndValidateBinning(algConfig.TPCBinning, config.TPCBinning());
463  parseAndValidateBinning(algConfig.opDetBinning, config.OpDetBinning());
464  return algConfig;
465 } // PlotDetectorActivityRates::parseValidatedAlgorithmConfiguration()
466 
467 
468 
469 
470 template <typename ConfigOut>
472  (ConfigOut& binConfig, fhicl::ParameterSet const& pset)
473 {
474  readParam(pset, "Start", binConfig.start);
475  readParam(pset, "Stop", binConfig.stop);
476  readParam(pset, "Step", binConfig.step);
477 } // PlotDetectorActivityRates::parseBinning()
478 
479 
480 template <typename ConfigOut, typename ConfigIn>
482  (ConfigOut& binConfig, ConfigIn const& config)
483 {
484  binConfig.start = config.Start();
485  binConfig.stop = config.Stop();
486  binConfig.step = config.Step();
487 } // PlotDetectorActivityRates::parseAndValidateBinning()
488 
489 
491 
492  out << "Configuration for the analysis algorithm:\n";
493  Parameters const table
495  table.print_allowed_configuration(out);
496  out << std::endl;
497 
498 } // PlotDetectorActivityRates::printConfigurationHelp()
499 
500 
502  TDirectory* pDestDir,
503  detinfo::DetectorClocksData&& clocksData,
505 ) {
506 
507  fDestDir = pDestDir;
508 
509  fDetTimings.emplace(std::move(clocksData));
510  fDetPropsData.emplace(std::move(propsData));
511 
512 } // PlotDetectorActivityRates::setup()
513 
514 
516 
517  initializePlots();
518 
519 } // PlotDetectorActivityRates::prepare()
520 
521 
523 
527 
528 } // PlotDetectorActivityRates::initializePlots()
529 
530 
532 
533  fEDepDistrib = std::make_unique<TProfile>(
534  "EnergyDepositsInTime",
535  (
536  "Energy deposited in active volume vs. time"
537  ";deposition time (simulation time scale) [ "
539  ";" + EDepUnit_t::unit_t::symbol() +" / event [ /"
540  + to_string(fSimBinner.step()) + " ]"
541  ).c_str(),
542  fSimBinner.nBins(), fSimBinner.lower().value(), fSimBinner.upper().value()
543  );
544 
545 } // PlotDetectorActivityRates::initializeEnergyDepositPlots()
546 
547 
549  assert(fDetTimings); // setup() should have taken care of these already
550  assert(fDetPropsData);
551 
552  detinfo::timescales::TPCelectronics_tick const TPCstart { 0 },
553  TPCstop { fDetPropsData->ReadOutWindowSize() };
554 
555  fTPCchargeDistrib = std::make_unique<TProfile>(
556  "TPCchargeInTime",
557  (
558  "Electrons sensed by TPC channels vs. time (readout window: "
559  + to_string(fDetTimings->toTick<electronics_tick>(TPCstart)) + " -- "
560  + to_string(fDetTimings->toTick<electronics_tick>(TPCstop)) + ")"
561  ";observation time (electronics time scale) [ TPC ticks, "
562  + to_string(fDetTimings->ClockPeriodFor<electronics_tick>()) + " ]"
563  ";ionization electrons / event [ /" + to_string(fTPCBinner.step()) + " ]"
564  ).c_str(),
565  fTPCBinner.nBins(), fTPCBinner.lower().value(), fTPCBinner.upper().value()
566  );
567 
568 } // PlotDetectorActivityRates::initializeTPCionizationPlots()
569 
570 
572 
573  fPhotonDistrib = std::make_unique<TProfile>(
574  "PhotoelectronsInTime",
575  (
576  "Photoelectrons detected vs. time"
577  ";PMT conversion time (simulation time scale) [ "
579  ";photons / event [ /" + to_string(fOpDetBinner.step()) + " ]"
580  ).c_str(),
582  fOpDetBinner.lower().value(), fOpDetBinner.upper().value()
583  );
584 
585 } // PlotDetectorActivityRates::initializePhotonPlots()
586 
587 
589  detinfo::DetectorClocksData&& clocksData,
591 ) {
592  // if multithreading were needed, this should be merged with `plotEvent()`
593  // and made constant; ROOT histograms are not thread-safe anyway.
594  fDetTimings.emplace(std::move(clocksData));
595  fDetPropsData.emplace(std::move(propsData));
596 } // PlotDetectorActivityRates::setupEvent()
597 
598 
599 template <typename Event>
600 void PlotDetectorActivityRates::plotEvent(Event const& event) {
601  assert(fDetTimings); // setupEvent() should have taken care of this
602 
603  //
604  // energy depositions
605  //
606  auto const& energyDeps
607  = *(event.template getValidHandle<std::vector<sim::SimEnergyDeposit>>
608  (fConfig.edepTag));
609 
610  plotEnergyDeposits(energyDeps);
611 
612  //
613  // TPC charge
614  //
615  auto const& TPCchannels
616  = *(event.template getValidHandle<std::vector<sim::SimChannel>>
617  (fConfig.chanTag));
618 
619  plotTPCionization(TPCchannels);
620 
621  //
622  // photons
623  //
624  auto const& photonChannels
625  = *(event.template getValidHandle<std::vector<sim::SimPhotons>>
626  (fConfig.photTag));
627 
628  plotPhotons(photonChannels);
629 
630 } // PlotDetectorActivityRates::plotEvent()
631 
632 
634 
635  savePlots();
636 
637  printStats();
638 
639 } // PlotDetectorActivityRates::finish()
640 
641 
642 template <typename Stream>
644 
645  out << "PlotDetectorActivityRates algorithm using:"
646  << "\n * simulated energy deposits: " << fConfig.edepTag.encode()
647  << "\n * simulated electrons: " << fConfig.chanTag.encode()
648  << "\n * simulated photons: " << fConfig.photTag.encode()
649  << "\n * time binning for: "
650  << "\n - simulation: " << fSimBinner
651  << "\n - TPC: " << fTPCBinner
652  << "\n - optical detectors: " << fOpDetBinner
653  << "\n"
654  ;
655 
656 } // PlotDetectorActivityRates::printConfig()
657 
658 
659 template <typename Stream>
661  assert(fDetTimings); // it should have been taken care by setup()
662  assert(fDetPropsData); // it should have been taken care by setup()
663 
664  detinfo::timescales::TPCelectronics_tick const TPCstart { 0 },
665  TPCstop { fDetPropsData->ReadOutWindowSize() };
666 
667  out << "Relevant timing settings:"
668  << "\n * TPC readout window: ";
669  printConvertedTickRange<detinfo::timescales::electronics_tick>
670  (out << "\n - ", TPCstart, TPCstop, *fDetTimings);
671  printConvertedTimeRange<detinfo::timescales::electronics_time>
672  (out << "\n - ", TPCstart, TPCstop, *fDetTimings);
673  printConvertedTimeRange<detinfo::timescales::simulation_time>
674  (out << "\n - ", TPCstart, TPCstop, *fDetTimings);
675  out << "\n";
676 
677 } // PlotDetectorActivityRates::printConfig()
678 
679 
681  (std::vector<sim::SimEnergyDeposit> const& energyDeps)
682 {
683  // funny fact: this method modifies the plot content but does not modify the
684  // plot object pointer, so we can declare it const.
685 
686  // shifted by 1 ([0] is underflow, ROOT standard)
687  std::vector<EDepUnit_t> counters(fSimBinner.nBins() + 2U, EDepUnit_t{ 0.0 });
688 
689  // all channels are aggregated together
690  for (sim::SimEnergyDeposit const& edep: energyDeps) {
691 
692  simulation_time const time { edep.Time() };
693 
694  int const timeBin = fSimBinner.cappedBinWithOverflows(time);
695  assert(timeBin + 1 < counters.size());
696 
697  EDepUnit_t const energy { edep.Energy() }; // explicit with the unit
698 
699  counters[timeBin + 1] += energy;
700 
701  } // for channels
702 
703  for (auto const [ iCount, count ]: util::enumerate(counters))
704  fEDepDistrib->Fill(fSimBinner.binCenter(iCount - 1).value(), count.value());
705 
706 
707  EDepUnit_t const totalE
708  = std::accumulate(counters.cbegin(), counters.cend(), EDepUnit_t{ 0.0 });
709  fEDepStats.add(totalE.value());
710 
711  mf::LogVerbatim("PlotDetectorActivityRates")
712  << "Collected " << totalE << " in " << energyDeps.size() << " deposits.";
713 
714 } // PlotDetectorActivityRates::plotEnergyDeposits()
715 
716 
718  (std::vector<sim::SimChannel> const& TPCchannels)
719 {
720  // funny fact: this method modifies the plot content but does not modify the
721  // plot object pointer, so we can declare it const.
722 
723  // shifted by 1 ([0] is underflow, ROOT standard)
724  std::vector<double> counters(fTPCBinner.nBins() + 2U, 0U);
725 
726  // all channels are aggregated together
727  for (sim::SimChannel const& channel: TPCchannels) {
728 
729  for (auto const& [ TDC, IDEs ]: channel.TDCIDEMap()) {
730 
731  // the TDC is filled by `LArVoxelReadout` with
732  // clockData.TPCClock().Ticks(clockData.G4ToElecTime(time))
733  electronics_tick const tick { TDC };
734 
735  int const tickBin = fTPCBinner.cappedBinWithOverflows(tick);
736  assert(tickBin + 1 < counters.size());
737 
738  counters[tickBin + 1] += channel.Charge(TDC);
739 
740  } // for all TDC
741 
742  } // for channels
743 
744  for (auto const [ iCount, count ]: util::enumerate(counters))
745  fTPCchargeDistrib->Fill(fTPCBinner.binCenter(iCount - 1).value(), count);
746 
747  double const totalElectrons
748  = std::accumulate(counters.cbegin(), counters.cend(), 0.0);
749  fTPCchargeStats.add(totalElectrons);
750  mf::LogVerbatim("PlotDetectorActivityRates")
751  << "Detected " << totalElectrons
752  << " electrons in " << TPCchannels.size() << " channels (all planes)."
753  ;
754 
755 } // PlotDetectorActivityRates::plotTPCionization()
756 
757 
759  (std::vector<sim::SimPhotons> const& photonChannels)
760 {
761  // funny fact: this method modifies the plot content but does not modify the
762  // plot object pointer, so we can declare it const.
763 
764  // shifted by 1 ([0] is underflow, ROOT standard)
765  std::vector<unsigned int> counters(fOpDetBinner.nBins() + 2U, 0U);
766 
767  // all channels are aggregated together
768  for (sim::SimPhotons const& photons: photonChannels) {
769 
770  for (sim::OnePhoton const& photon: photons) {
771 
772  simulation_time const time { photon.Time };
773 
774  int const timeBin
775  = fOpDetBinner.cappedBinWithOverflows(fDetTimings->toTriggerTime(time));
776  assert(timeBin + 1 < counters.size());
777 
778  ++counters[timeBin + 1];
779 
780  } // for photons in channel
781 
782  } // for channels
783 
784  for (auto const [ iCount, count ]: util::enumerate(counters))
785  fPhotonDistrib->Fill(fOpDetBinner.binCenter(iCount - 1).value(), count);
786 
787  unsigned int const totalPhotons
788  = std::accumulate(counters.cbegin(), counters.cend(), 0U);
789  fPhotonStats.add(totalPhotons);
790 
791  mf::LogVerbatim("PlotDetectorActivityRates")
792  << "Collected " << totalPhotons
793  << " photoelectrons in " << photonChannels.size() << " channels."
794  ;
795 
796 } // PlotDetectorActivityRates::plotPhotons()
797 
798 
800 
801  if (!fDestDir) return;
802 
804 
808 
809 
810 } // PlotDetectorActivityRates::savePlots()
811 
812 
814 
815  mf::LogVerbatim("PlotDetectorActivityRates")
816  << "Statistics, on average per event (" << fEDepStats.N() << " events):"
817  << "\n * )" << fEDepStats.Average() << " +/- " << fEDepStats.RMS()
818  << ") " << EDepUnit_t::unitSymbol() << " of deposited energy"
819  << "\n * (" << fTPCchargeStats.Average() << " +/- " << fTPCchargeStats.RMS()
820  << ") ionization electrons (all planes)"
821  << "\n * " << fPhotonStats.Average() << " +/- " << fPhotonStats.RMS()
822  << ") photoelectrons"
823  ;
824 
825 } // PlotDetectorActivityRates::printStats()
826 
827 
828 template <typename Plot>
829 void PlotDetectorActivityRates::Serialize(std::unique_ptr<Plot>& plot) {
830  if (!plot) return;
831  plot->Write();
832  plot.reset();
833 } // PlotDetectorActivityRates::Serialize()
834 
835 
836 // -----------------------------------------------------------------------------
837 
838 
839 /**
840  * @brief Runs the analysis macro.
841  * @param configFile path to the FHiCL configuration to be used for the services
842  * @param inputFiles vector of path of file names
843  * @return an integer as exit code (0 means success)
844  */
845 int makePlots
846  (std::string const& configFile, std::vector<std::string> const& inputFiles)
847 {
848  /*
849  * the "test" environment configuration
850  */
851  // read FHiCL configuration from a configuration file:
852  fhicl::ParameterSet config = lar::standalone::ParseConfiguration(configFile);
853 
854  // set up message facility (always picked from "services.message")
856 
857  // ***************************************************************************
858  // *** SERVICE PROVIDER SETUP BEGIN ****************************************
859  // ***************************************************************************
860  //
861  // Uncomment the things you need
862  // (and make sure the corresponding headers are also uncommented)
863  //
864  // geometry setup (it's special)
865  auto geom = lar::standalone::SetupGeometry<icarus::ICARUSChannelMapAlg>
866  (config.get<fhicl::ParameterSet>("services.Geometry"));
867 
868  // LArProperties setup
869  auto larProp = testing::setupProvider<detinfo::LArPropertiesStandard>
870  (config.get<fhicl::ParameterSet>("services.LArPropertiesService"));
871 
872  // DetectorClocks setup
873  auto detClocks = testing::setupProvider<detinfo::DetectorClocksStandard>
874  (config.get<fhicl::ParameterSet>("services.DetectorClocksService"));
875 
876  // DetectorProperties setup
877  auto detProps = testing::setupProvider<detinfo::DetectorPropertiesStandard>(
878  config.get<fhicl::ParameterSet>("services.DetectorPropertiesService"),
880 // { geom.get(), larProp.get() } // FIXME try this simpler version
881  );
882 
883  // ***************************************************************************
884  // *** SERVICE PROVIDER SETUP END ****************************************
885  // ***************************************************************************
886 
887  auto const& analysisConfig = config.get<fhicl::ParameterSet>("analysis");
888 
889  // event loop options
890  constexpr auto NoLimits = std::numeric_limits<unsigned int>::max();
891  unsigned int nSkip = analysisConfig.get("skipEvents", 0U);
892  unsigned int const maxEvents = analysisConfig.get("maxEvents", NoLimits);
893 
894  /*
895  * the preparation of input file list
896  */
897  if (inputFiles.size() != 1) {
898  throw std::runtime_error("Support for multiple input files not implemented yet!");
899  }
900  std::vector<std::string> const allInputFiles = expandInputFiles(inputFiles);
901 
902  /*
903  * other parameters
904  */
905 
906  /*
907  * preparation of histogram output file
908  */
909  std::unique_ptr<TFile> pHistFile;
910  if (analysisConfig.has_key("histogramFile")) {
911  std::string fileName = analysisConfig.get<std::string>("histogramFile");
912  mf::LogVerbatim("makePlots")
913  << "Creating output file: '" << fileName << "'" << std::endl;
914  pHistFile = std::make_unique<TFile>(fileName.c_str(), "RECREATE");
915  }
916 
917  /*
918  * preparation of the algorithm class
919  */
920 
921  // configuration from `ConfigurationKey` table of configuration file:
922  PlotDetectorActivityRates plotAlg {
923  analysisConfig.get<fhicl::ParameterSet>
925  };
926 
927  plotAlg.printConfig(mf::LogVerbatim{"makePlots"});
928 
929  {
930  auto clocksData = detClocks->DataForJob();
931  plotAlg.setup
932  (pHistFile.get(), std::move(clocksData), detProps->DataFor(clocksData));
933  }
934  plotAlg.printTimingSummary(mf::LogVerbatim{"makePlots"});
935 
936  plotAlg.prepare();
937 
938  /*
939  auto const clock_data = detclk->DataForJob();
940  auto const det_prop_data = detp->DataFor(clock_data);
941  */
942 
943  unsigned int numEvents { 0U };
944 
945  /*
946  * the event loop
947  */
948  for (gallery::Event event(allInputFiles); !event.atEnd(); event.next()) {
949 
950  if (nSkip > 0) { --nSkip; continue; }
951  if (numEvents >= maxEvents) {
952  mf::LogVerbatim("makePlots") << "Maximum number of events reached.";
953  break;
954  }
955 
956  // *************************************************************************
957  // *** SINGLE EVENT PROCESSING BEGIN *************************************
958  // *************************************************************************
959 
960  ++numEvents;
961  {
962  mf::LogVerbatim log("makePlots");
963  log << "This is event " << event.fileEntry() << "-" << event.eventEntry()
964  << " (" << numEvents;
965  if (maxEvents < NoLimits) log << "/" << maxEvents;
966  log << ")";
967  }
968 
969  {
970  auto clocksData
971  = detinfo::detectorClocksStandardDataFor(*detClocks, event);
972  plotAlg.setupEvent(std::move(clocksData), detProps->DataFor(clocksData));
973  }
974 
975  plotAlg.plotEvent(event);
976 
977 
978  // *************************************************************************
979  // *** SINGLE EVENT PROCESSING END *************************************
980  // *************************************************************************
981 
982  } // for
983 
984  plotAlg.finish();
985  plotAlg.printTimingSummary(mf::LogVerbatim{"makePlots"} << "Once again:\n");
986 
987  return 0;
988 } // makePlots()
989 
990 
991 /// Version with a single input file.
992 int makePlots(std::string const& configFile, std::string filename)
993  { return makePlots(configFile, std::vector<std::string>{ filename }); }
994 
995 #if !defined(__CLING__)
996 int main(int argc, char** argv) {
997 
998  char **pParam = argv + 1, **pend = argv + argc;
999  if (pParam == pend) {
1000  std::cerr << "Usage: " << argv[0] << " configFile [inputFile ...]"
1001  << std::endl;
1003  return 1;
1004  }
1005  std::string const configFile = *(pParam++);
1006  std::vector<std::string> fileNames;
1007  std::copy(pParam, pend, std::back_inserter(fileNames));
1008 
1009  return makePlots(configFile, fileNames);
1010 } // main()
1011 
1012 #endif // !__CLING__
std::optional< detinfo::DetectorPropertiesData > fDetPropsData
fDetProps &fDetProps detProps
void savePlots()
Writes all plots into the current ROOT directory (and then deletes them).
static void readParam(fhicl::ParameterSet const &pset, std::string const &key, T &var)
process_name can override from command line with o or output photon
Definition: runPID.fcl:28
timescale_traits< ElectronicsTimeCategory >::tick_t electronics_tick
A point on the electronics time scale expressed in its ticks.
Channel mapping algorithms for ICARUS detector.
std::optional< detinfo::DetectorTimings > fDetTimings
Energy deposited on a readout channel by simulated tracks.
Definition: SimChannel.h:145
void initializePlots()
Performs the initialization of the plots filled by the algorithm.
Utilities for one-line geometry initialization.
Service provider with utility LAr functions.
BEGIN_PROLOG could also be cerr
Definition of util::enumerate().
Data structure with all the configuration.
simulation_time_scale::time_point_t simulation_time
Helper functions for support of LArPropertiesService in LArSoft tests.
AlgorithmConfiguration parseValidatedAlgorithmConfiguration(FHiCLconfig const &config)
detinfo::timescales::electronics_tick electronics_tick
BEGIN_PROLOG could also be dds filename
All information of a photon entering the sensitive optical detector volume.
Definition: SimPhotons.h:64
lar::util::StatCollector< double > fEDepStats
Statistics of the total energy per event.
void initializeTPCionizationPlots()
Performs the initialization of plots pertaining collected TPC charge.
void plotEnergyDeposits(std::vector< sim::SimEnergyDeposit > const &energyDeps)
Plots data from energy deposits in liquid argon.
Provider const * get() const
Returns the provider with the specified type.
Definition: ProviderPack.h:193
static void parseBinning(ConfigOut &binConfig, fhicl::ParameterSet const &pset)
A collection of traits for a time scale.
constexpr value_t value() const
Returns the value of the quantity.
Definition: quantities.h:609
source drop raw::ubdaqSoftwareTriggerData_ *_ *_ * maxEvents
Definition: frame-shunt.fcl:6
Classes gathering simple statistics.
std::unique_ptr< TProfile > fTPCchargeDistrib
Average amount of ionization collected per time.
process_name plot
void printStats() const
Prints on screen some collected statistics.
Weight_t RMS() const
Returns the root mean square.
static void printConfigurationHelp(std::ostream &out)
Prints on out screen a configuration summary.
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
void setup(TDirectory *pDestDir, detinfo::DetectorClocksData &&clocksData, detinfo::DetectorPropertiesData &&propsData)
Sets the algorithm up.
static auto unitSymbol()
Returns the symbol of the unit, in a string-like object.
Definition: quantities.h:754
Weight_t Average() const
Returns the value average.
Interface to detinfo::DetectorClocks.
static std::string const ConfigurationKey
Name of the recommended configuration table for this algorithm.
Helper functions for support of DetectorClocksService in LArSoft tests.
lar::util::StatCollector< unsigned int > fPhotonStats
Statistics of the total light (photoelectron count) per event.
void prepare()
Performs the initialization of the algorithm.
Access the description of detector geometry.
void SetupMessageFacility(fhicl::ParameterSet const &pset, std::string applName="standalone")
Sets up the message facility service.
Simulation objects for optical detectors.
Collection of functions for quick setup of basic facilities.
static util::Binner< T > makeBinning(BinConfig const &config)
std::vector< std::string > expandInputFiles(std::vector< std::string > const &filePaths)
Expands all input files into a vector of file paths.
PlotDetectorActivityRates(Parameters const &config)
Constructor: reads the configuration from the specified parameters set.
TDirectory * fDestDir
ROOT directory where to write the plots.
void plotPhotons(std::vector< sim::SimPhotons > const &photonChannels)
Plots data from photoelectron collection.
void printConfig(Stream &&out) const
Prints the current configuration to the specified output stream.
lar::util::StatCollector< double > fTPCchargeStats
Statistics of the total charge (electron count) per event.
int N() const
Returns the number of entries added.
timescale_traits< SimulationTimeCategory >::time_point_t simulation_time
A point in time on the simulation time scale.
static void Serialize(std::unique_ptr< Plot > &plot)
Writes plot into the current ROOT directory, then deletes it.
void initializePhotonPlots()
Performs the initialization of plots pertaining collected photoelectrons.
std::tuple< double, double, const reco::ClusterHit3D * > Point
Definitions used by the VoronoiDiagram algorithm.
Definition: DCEL.h:44
A value measured in the specified unit.
Definition: quantities.h:566
megaelectronvolt_as<> megaelectronvolt
Type of energy stored in megaelectronvolt, in double precision.
Definition: energy.h:119
A bunch of diverse utilities and futilities related to ROOT.
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
BEGIN_PROLOG vertical distance to the surface Name
int makePlots(std::string const &configFile, std::vector< std::string > const &inputFiles)
Runs the analysis macro.
void plotTPCionization(std::vector< sim::SimChannel > const &TPCchannels)
Plots data from photoelectron collection.
Helpers for support of DetectorPropertiesService in LArSoft tests.
An interval (duration, length, distance) between two quantity points.
Definition: intervals.h:114
std::unique_ptr< TProfile > fPhotonDistrib
Average number of photon per time.
detinfo::DetectorClocksData detectorClocksStandardDataFor(detinfo::DetectorClocksStandard const &detClocks, Event const &event)
Returns DetectorClocksData tuned on the specified event.
AlgorithmConfiguration const fConfig
Complete configuration of the algorithm.
nanoseconds_as<> nanoseconds
Type of time interval stored in nanoseconds, in double precision.
Definition: spacetime.h:270
milliseconds_as<> milliseconds
Type of time interval stored in milliseconds, in double precision.
Definition: spacetime.h:248
fhicl::Table< BinningConfig< tick, ticks > > TPCBinning
Utilities to read interval and point quantity FHiCL configuration.
millisecond_as<> millisecond
Type of time point stored in milliseconds, in double precision.
Definition: spacetime.h:317
Dimensioned variables related to electronics.
fhicl::Table< BinningConfig< millisecond, milliseconds > > OpDetBinning
Collection of photons which recorded on one channel.
Definition: SimPhotons.h:136
util::Binner< simulation_time > fSimBinner
std::unique_ptr< TProfile > fEDepDistrib
Average amount of deposited energy per time [GeV].
void setupEvent(detinfo::DetectorClocksData &&clocksData, detinfo::DetectorPropertiesData &&propsData)
Set up for a specific event.
TargetTime toTimeScale(FromTime time) const
Returns a time point in a different time scale.
Dimensioned variables representing energy.
TargetTick toTick(FromTime time) const
Returns a time point as a tick on a different time scale.
Contains all timing reference information for the detector.
AlgorithmConfiguration parseAlgorithmConfiguration(fhicl::ParameterSet const &pset)
std::string to_string(WindowPattern const &pattern)
Dimensioned variables representing space or time quantities.
contains information for a single step in the detector simulation
Data_t upper() const
Returns the upper limit of the range.
Definition: Binner.h:104
Container for a list of pointers to providers.
Definition: ProviderPack.h:114
A class exposing an upgraded interface of detinfo::DetectorClocksData.
Data types for detinfo::DetectorTimings.
Energy deposition in the active material.
object containing MC truth information necessary for making RawDigits and doing back tracking ...
Step_t step() const
Returns the step size.
Definition: Binner.h:107
ticks_as<> ticks
A tick interval based on std::ptrdiff_t.
Definition: electronics.h:187
T copy(T const &v)
Data_t lower() const
Definition: Binner.h:101
tick_as<> tick
A tick value based on std::ptrdiff_t.
Definition: electronics.h:212
then echo fcl name
util::Binner< electronics_tick > fTPCBinner
fhicl::Table< FHiCLconfig > Parameters
fDetProps &fDetProps fDetProps &fDetProps detTimings
A class restoring the previous TDirectory on destruction.
Definition: ROOTutils.h:54
void plotEvent(Event const &event)
Processes a single event.
std::size_t count(Cont const &cont)
Helper to get clocks data from detinfo::DetectorClocksStandard.
fhicl::ParameterSet ParseConfiguration(std::string configPath, cet::filepath_maker &lookupPolicy)
Parses a FHiCL configuration file.
int main(int argc, char **argv)
decltype(std::declval< Data_t >()-std::declval< Data_t >()) Step_t
Type of difference between binning axis values.
Definition: Binner.h:78
Helper object to describing a binned axis.
fhicl::Table< BinningConfig< millisecond, milliseconds > > SimBinning
timescale_traits< TPCelectronicsTimeCategory >::tick_t TPCelectronics_tick
A point on the TPC electronics time scale expressed in its ticks.
void printTimingSummary(Stream &&out) const
Prints some information about configured timing.
static void parseAndValidateBinning(ConfigOut &binConfig, ConfigIn const &config)
void initializeEnergyDepositPlots()
Performs the initialization of plots pertaining energy deposits.
bnb BNB Stream
unsigned int nBins() const
Returns the number of bins in the range.
Definition: Binner.h:110
util::Binner< trigger_time > fOpDetBinner
detinfo::timescales::simulation_time trigger_time
void finish()
Completes and saves the plots.