All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DumpOpDetWaveforms_module.cc
Go to the documentation of this file.
1 /**
2  * @file DumpOpDetWaveforms_module.cc
3  * @brief Dumps on screen the content of the raw optical detector waveforms.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date March 8th, 2017
6  */
7 
8 // LArSoft includes
13 
14 // art libraries
15 #include "art/Framework/Core/EDAnalyzer.h"
16 #include "art/Framework/Core/ModuleMacros.h"
17 #include "art/Framework/Principal/Event.h"
18 #include "art/Framework/Principal/Handle.h"
19 #include "canvas/Utilities/InputTag.h"
20 
21 // support libraries
22 #include "fhiclcpp/types/Atom.h"
23 #include "fhiclcpp/types/Comment.h"
24 #include "fhiclcpp/types/Name.h"
25 #include "messagefacility/MessageLogger/MessageLogger.h"
26 
27 // C//C++ standard libraries
28 #include <algorithm> // std::sort()
29 #include <string>
30 #include <vector>
31 
32 namespace detsim {
33 
34  /**
35  * @brief Prints the content of all optical detector waveforms on screen.
36  *
37  * This analyser prints the content of all the raw digits into the
38  * LogInfo/LogVerbatim stream.
39  *
40  * Configuration parameters
41  * -------------------------
42  *
43  * - *OpDetWaveformsTag* (string, default: `daq`): input tag of the
44  * raw::OpDetWaveform collection to be dumped
45  * - *OutputCategory* (string, default: `DumpOpDetWaveforms`): the category
46  * used for the output (useful for filtering)
47  * - *DigitsPerLine* (integer, default: `20`): the dump of ADC readings
48  * will put this many of them for each line
49  * - *Pedestal* (integer, default: `0`): ADC readings are written relative
50  * to this number
51  * - *TickLabel* (string, default: `"tick"`): a preamble to each line of the
52  * dumped waveform digits, chosen among:
53  * - `"tick"`: the tick number of the waveform is printed (starts at `0`)
54  * - `"time"`: timestamp (&micro;s) of the first tick in the row
55  * - `"none"`: no preamble written at all
56  *
57  */
58  class DumpOpDetWaveforms : public art::EDAnalyzer {
59  public:
60  struct Config {
61 
62  using Name = fhicl::Name;
63  using Comment = fhicl::Comment;
64 
65  fhicl::Atom<art::InputTag> OpDetWaveformsTag{
66  Name("OpDetWaveformsTag"),
67  Comment("input tag of the raw::OpDetWaveform collection to be dumped")};
68 
69  fhicl::Atom<std::string> OutputCategory{Name("OutputCategory"),
70  Comment("name of the category used for the output"),
71  "DumpOpDetWaveforms"};
72 
73  fhicl::Atom<unsigned int> DigitsPerLine{
74  Name("DigitsPerLine"),
75  Comment("the dump of ADC readings will put this many of them for each line"),
76  20U};
77 
78  fhicl::Atom<raw::ADC_Count_t> Pedestal{
79  Name("Pedestal"),
80  Comment("ADC readings are written relative to this number"),
81  0};
82 
83  fhicl::Atom<bool> SortByChannelAndTime{
84  Name("SortByChannelAndTime"),
85  Comment
86  ("waveforms are dumped in channel number order, and then timestamp"),
87  true};
88 
89  fhicl::Atom<std::string> TickLabel{
90  Name("TickLabel"),
91  Comment("write an index in front of each digit dump line; choose between:"
92  " \"tick\" (waveform tick number)"
93  ", \"timestamp\" (electronics clock time in microseconds)"
94  ", \"none\" (no tick label)"),
95  "tick"};
96 
97  }; // struct Config
98 
99  using Parameters = art::EDAnalyzer::Table<Config>;
100 
101  explicit DumpOpDetWaveforms(Parameters const& config);
102 
103  /// Does the printing.
104  void analyze(const art::Event& evt);
105 
106  private:
107 
108  enum class sortMode {
109  DataProductOrder, ///< Unsorted: same order as the input data product.
110  ChannelAndTime ///< Sort by PMT channel number, then timestamp.
111  }; // sortMode
112 
113  /// Base functor for printing time according to tick number.
115  double tickDuration; // should this me `util::quantities::microsecond`?
116 
117  /// Constructor: specify the duration of optical clock tick [&micro;s].
118  TimestampLabelMaker(double tickDuration) : tickDuration(tickDuration) {}
119 
120  /// Returns the electronics time of the specified waveform tick.
121  virtual std::string
122  label(raw::OpDetWaveform const& waveform, unsigned int tick) const override
123  {
124  return std::to_string(waveform.TimeStamp() + tick * tickDuration);
125  }
126 
127  }; // struct TimestampLabelMaker
128 
129  art::InputTag fOpDetWaveformsTag; ///< Input tag of data product to dump.
130  std::string fOutputCategory; ///< Category for `mf::LogInfo` output.
131  unsigned int fDigitsPerLine; ///< ADC readings per line in the output.
132  raw::ADC_Count_t fPedestal; ///< ADC pedestal (subtracted from readings).
133  sortMode fSortByChannelAndTime; ///< How to sort the waveforms in the dump.
134 
135 
136  /// The object used to print tick labels.
137  std::unique_ptr<dump::raw::OpDetWaveformDumper::TimeLabelMaker> fTimeLabel;
138 
139  /// Returns pointers to all waveforms in a vector with channel as index.
140  static std::vector<std::vector<raw::OpDetWaveform const*>> groupByChannel(
141  std::vector<raw::OpDetWaveform> const& waveforms);
142 
143  /// Sorts all the waveforms in the vector by growing timestamp.
144  static void sortByTimestamp(std::vector<raw::OpDetWaveform const*>& waveforms);
145 
146  }; // class DumpOpDetWaveforms
147 
148 } // namespace detsim
149 
150 namespace detsim {
151 
152  //-------------------------------------------------
154  : EDAnalyzer(config)
155  , fOpDetWaveformsTag(config().OpDetWaveformsTag())
156  , fOutputCategory(config().OutputCategory())
157  , fDigitsPerLine(config().DigitsPerLine())
158  , fPedestal(config().Pedestal())
159  , fSortByChannelAndTime(config().SortByChannelAndTime()
160  ? sortMode::ChannelAndTime: sortMode::DataProductOrder
161  )
162  {
163  std::string const tickLabelStr = config().TickLabel();
164  if (tickLabelStr == "none") {
165  fTimeLabel.reset(); // not very useful, but let's be explicit
166  }
167  else if (tickLabelStr == "tick") {
168  fTimeLabel = std::make_unique<dump::raw::OpDetWaveformDumper::TickLabelMaker>();
169  }
170  else if (tickLabelStr == "time") {
171  auto const clock_data =
172  art::ServiceHandle<detinfo::DetectorClocksService const>()->DataForJob();
173  fTimeLabel = std::make_unique<TimestampLabelMaker>(clock_data.OpticalClock().TickPeriod());
174  }
175  else {
176  throw art::Exception(art::errors::Configuration)
177  << "Invalid choice '" << tickLabelStr << "' for time label.\n";
178  }
179 
180  } // DumpOpDetWaveforms::DumpOpDetWaveforms()
181 
182  //-------------------------------------------------
183  void
184  DumpOpDetWaveforms::analyze(const art::Event& event)
185  {
186 
187  // fetch the data to be dumped on screen
188  auto const& Waveforms
189  = event.getProduct<std::vector<raw::OpDetWaveform>>(fOpDetWaveformsTag);
190 
192  dump.setTimeLabelMaker(fTimeLabel.get());
193 
194  mf::LogVerbatim(fOutputCategory) << "The event " << event.id() << " contains data for "
195  << Waveforms.size() << " optical detector channels";
196  if (fPedestal != 0) {
197  mf::LogVerbatim(fOutputCategory)
198  << "A pedestal of " << fPedestal << " counts will be subtracted from all ADC readings.";
199  } // if pedestal
200 
201  switch (fSortByChannelAndTime) {
203  {
204  dump.setIndent(" ");
205  for (raw::OpDetWaveform const& waveform : Waveforms) {
206  mf::LogVerbatim log(fOutputCategory);
207  dump(log, waveform);
208  } // for waveforms on channel
209  }
210  break; // sortMode::DataProductOrder
212  {
213  dump.setIndent(" ");
214 
215  auto groupedWaveforms = groupByChannel(Waveforms);
216  for (auto& channelWaveforms : groupedWaveforms) {
217  if (channelWaveforms.empty()) continue;
218 
219  sortByTimestamp(channelWaveforms);
220  auto const channel = channelWaveforms.front()->ChannelNumber();
221 
222  mf::LogVerbatim(fOutputCategory)
223  << " optical detector channel #" << channel << " has "
224  << channelWaveforms.size() << " waveforms:";
225 
226  for (raw::OpDetWaveform const* pWaveform : channelWaveforms) {
227  mf::LogVerbatim log(fOutputCategory);
228  dump(log, *pWaveform);
229  } // for waveforms on channel
230 
231  } // for all channels
232  }
233  break; // sortMode::ChannelAndTime
234  } // switch (fSortMode)
235 
236  } // DumpOpDetWaveforms::analyze()
237 
238  //----------------------------------------------------------------------------
239  std::vector<std::vector<raw::OpDetWaveform const*>>
240  DumpOpDetWaveforms::groupByChannel(std::vector<raw::OpDetWaveform> const& waveforms)
241  {
242  std::vector<std::vector<raw::OpDetWaveform const*>> groups;
243  for (auto const& waveform : waveforms) {
244  auto const channel = waveform.ChannelNumber();
245  if (groups.size() <= channel) groups.resize(channel + 1);
246  groups[channel].push_back(&waveform);
247  } // for
248  return groups;
249  } // DumpOpDetWaveforms::groupByChannel()
250 
251  //----------------------------------------------------------------------------
252  void
253  DumpOpDetWaveforms::sortByTimestamp(std::vector<raw::OpDetWaveform const*>& waveforms)
254  {
255 
256  struct ChannelSorter {
257 
258  static bool
259  sort(raw::OpDetWaveform const& a, raw::OpDetWaveform const& b)
260  {
261  if (a.ChannelNumber() < b.ChannelNumber()) return true;
262  if (a.ChannelNumber() > b.ChannelNumber()) return false;
263 
264  return (a.TimeStamp() < b.TimeStamp());
265  }
266 
267  bool
268  operator()(raw::OpDetWaveform const& a, raw::OpDetWaveform const& b) const
269  {
270  return sort(a, b);
271  }
272 
273  bool
274  operator()(raw::OpDetWaveform const* a, raw::OpDetWaveform const* b) const
275  {
276  return sort(*a, *b);
277  }
278 
279  }; // struct ChannelSorter
280  std::sort(waveforms.begin(), waveforms.end(), ChannelSorter());
281 
282  } // DumpOpDetWaveforms::sortByTimestamp()
283 
284  //----------------------------------------------------------------------------
285  DEFINE_ART_MODULE(DumpOpDetWaveforms)
286 
287  //----------------------------------------------------------------------------
288 
289 } // namespace detsim
fhicl::Atom< raw::ADC_Count_t > Pedestal
DumpOpDetWaveforms(Parameters const &config)
std::string fOutputCategory
Category for mf::LogInfo output.
Utilities to dump raw::OpDetWaveform objects on screen.
Prints the content of all optical detector waveforms on screen.
std::unique_ptr< dump::raw::OpDetWaveformDumper::TimeLabelMaker > fTimeLabel
The object used to print tick labels.
pure virtual base interface for detector clocks
process_name gaushit a
static std::vector< std::vector< raw::OpDetWaveform const * > > groupByChannel(std::vector< raw::OpDetWaveform > const &waveforms)
Returns pointers to all waveforms in a vector with channel as index.
fhicl::Atom< art::InputTag > OpDetWaveformsTag
Base functor for printing time according to tick number.
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
BEGIN_PROLOG vertical distance to the surface Name
TimestampLabelMaker(double tickDuration)
Constructor: specify the duration of optical clock tick [s].
raw::ADC_Count_t fPedestal
ADC pedestal (subtracted from readings).
Unsorted: same order as the input data product.
Prints the content of optical detector waveforms on screen.
static void sortByTimestamp(std::vector< raw::OpDetWaveform const * > &waveforms)
Sorts all the waveforms in the vector by growing timestamp.
std::string to_string(WindowPattern const &pattern)
art::EDAnalyzer::Table< Config > Parameters
void analyze(const art::Event &evt)
Does the printing.
sortMode fSortByChannelAndTime
How to sort the waveforms in the dump.
art::InputTag fOpDetWaveformsTag
Input tag of data product to dump.
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int fDigitsPerLine
ADC readings per line in the output.
Base functor for printing time according to tick number.
Sort by PMT channel number, then timestamp.
virtual std::string label(raw::OpDetWaveform const &waveform, unsigned int tick) const override
Returns the electronics time of the specified waveform tick.