All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
lardataalg/lardataalg/Dumpers/RawData/OpDetWaveform.h
Go to the documentation of this file.
1 /**
2  * @file lardataalg/Dumpers/RawData/OpDetWaveform.h
3  * @brief Utilities to dump `raw::OpDetWaveform` objects on screen.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date March 8th, 2017
6  *
7  * Currently this is a header-only library.
8  *
9  */
10 
11 #ifndef LARDATAALG_DUMPERS_RAWDATA_OPDETWAVEFORM_H
12 #define LARDATAALG_DUMPERS_RAWDATA_OPDETWAVEFORM_H
13 
14 
15 // LArSoft includes
17 #include "lardataalg/Utilities/StatCollector.h" // lar::util::MinMaxCollector
19 
20 // C//C++ standard libraries
21 #include <vector>
22 #include <algorithm> // std::min()
23 #include <ios> // std::fixed
24 #include <iomanip> // std::setprecision(), std::setw()
25 #include <utility> // std::forward(), std::swap()
26 
27 
28 namespace dump::raw {
29 
30  using namespace ::raw;
31 
32  /**
33  * @brief Prints the content of optical detector waveforms on screen.
34  *
35  * Example of usage:
36  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
37  * dump::raw::OpDetWaveformDumper dump;
38  * dump.setIndent(" ");
39  *
40  * for (raw::OpDetWaveform const& waveform: waveforms)
41  * dump(mf::LogVerbatim("dumper"), waveform);
42  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
43  *
44  */
46  public:
47 
48  /// Base functor for printing time according to tick number.
49  struct TimeLabelMaker {
50 
51  virtual ~TimeLabelMaker() = default;
52 
53  /// Returns the label to be written for the specified `tick` number.
54  virtual std::string label
55  (raw::OpDetWaveform const& waveform, unsigned int tick) const = 0;
56 
57  /// Length of padded label. For best results, it should be a constant.
58  virtual unsigned int labelWidth
59  (raw::OpDetWaveform const& waveform, unsigned int tick) const
60  { return 10U; }
61 
62  }; // struct TimeLabelMaker
63 
64 
65  /// Time label: tick number relative to the waveform.
66  struct TickLabelMaker: public TimeLabelMaker {
67 
68  /// Returns the label to be written for the specified `tick` number.
69  virtual std::string label
70  (raw::OpDetWaveform const&, unsigned int tick) const override
71  { return std::to_string(tick); }
72 
73  /// Length of padded label. For best results, it should be a constant.
74  virtual unsigned int labelWidth
75  (raw::OpDetWaveform const& waveform, unsigned int) const override
76  { return digitsOf(waveform.size()); }
77 
78  }; // struct TickLabelMaker
79 
80 
81  /**
82  * @brief Constructor: sets waveform dump parameters.
83  * @param pedestal (default: `0`) the pedestal to be automatically added to
84  * all digits
85  * @param digitsPerLine (default: `0`) how many ADC digits to print per
86  * line; `0` disables the digit printing completely
87  *
88  * Note that no indentation is set. If some is desired, set it with
89  * `setIndent()` after construction.
90  */
92  (raw::ADC_Count_t pedestal = 0, unsigned int digitsPerLine = 0U)
93  : fPedestal(pedestal), fDigitsPerLine(digitsPerLine)
94  {}
95 
96  /**
97  * @brief Chooses which time label maker to use.
98  * @param timeLabelMaker a pointer to the external time label maker
99  *
100  * A time label maker is an object derived from `TimeLabelMaker` which can
101  * convert a waveform and tick into a string representing that tick within
102  * the waveform. If never specified or if `nullptr`, no time label will be
103  * printed at all.
104  */
105  void setTimeLabelMaker(TimeLabelMaker const* timeLabelMaker)
106  { fTimeLabelMaker = timeLabelMaker; }
107 
108 
109  /**
110  * @brief Dumps the content of a waveform into the specified output stream.
111  * @tparam Stream type of stream to dump data into
112  * @param stream stream to dump data into
113  * @param waveform the object to be dumped
114  *
115  * Indentation is regulated via base class methods (see `setIndent()`).
116  */
117  template <typename Stream>
118  void dump(Stream&& stream, raw::OpDetWaveform const& waveform);
119 
120  /// An alias of `dump()`.
121  template <typename Stream>
122  void operator()(Stream&& stream, raw::OpDetWaveform const& waveform)
123  { dump(stream, waveform); }
124 
125 
126  /// Pads the specified string to the right, truncating its right if needed.
127  static std::string padRight
128  (std::string const& s, unsigned int width, std::string padding = " ");
129 
130  /// Pads the specified string to the right, truncating its right if needed.
131  static unsigned int digitsOf(unsigned int n);
132 
133  private:
134 
135  raw::ADC_Count_t fPedestal; ///< ADC pedestal (subtracted from readings).
136  unsigned int fDigitsPerLine; ///< ADC readings per line in the output.
137 
138  /// The functor to be used to extract the time label.
139  TimeLabelMaker const* fTimeLabelMaker = nullptr;
140 
141  }; // class OpDetWaveformDumper
142 
143 } // namespace dump::raw
144 
145 
146 // -----------------------------------------------------------------------------
147 // --- Template implementation
148 // -----------------------------------------------------------------------------
149 template <typename Stream>
151  (Stream&& stream, raw::OpDetWaveform const& waveform)
152 {
153  static std::string const headerSep = " | ";
154 
155  auto const& data = waveform;
156  using Count_t = raw::ADC_Count_t;
157 
158  auto out = indenter(std::forward<Stream>(stream));
159 
160  // print a header for the raw digits
161  out.start()
162  << "on channel #" << waveform.ChannelNumber() << " (time stamp: "
163  << waveform.TimeStamp() << "): " << data.size() << " time ticks";
164 
165  // print the content of the channel
166  if (fDigitsPerLine == 0) return;
167 
168  // save and change indentation
169  saveIndentSettings().set(indent() + " ");
170 
171  unsigned int repeat_count = 0U; // additional lines like the last one
172  unsigned int index = 0U;
173  unsigned int firstLineTick = 0U;
174 
175  // local function for printing and resetting the repeat count
176  auto flushRepeatCount
177  = [this, &out, &waveform, &firstLineTick](unsigned int& count)
178  -> decltype(auto)
179  {
180  if (count > 0) {
181  out.newline();
182  if (fTimeLabelMaker) {
183  out
184  << padRight("", fTimeLabelMaker->labelWidth(waveform, firstLineTick))
185  << headerSep
186  ;
187  }
188  out << " [ ... repeated " << count << " more times ]";
189  count = 0;
190  }
191  return out;
192  };
193 
194  std::vector<Count_t> DigitBuffer(fDigitsPerLine), LastBuffer;
195 
197  out.newline()
198  << "content of the channel (" << fDigitsPerLine << " ticks per line):";
199  auto iTick = data.cbegin(), tend = data.cend(); // const iterators
200  while (iTick != tend) {
201  // the next line will show at most fDigitsPerLine ticks
202  unsigned int line_size
203  = std::min(fDigitsPerLine, (unsigned int) data.size() - index);
204  if (line_size == 0) break; // no more ticks
205 
206  // fill the new buffer (iTick will move forward)
207  DigitBuffer.resize(line_size);
208  auto iBuf = DigitBuffer.begin(), bend = DigitBuffer.end();
209  while ((iBuf != bend) && (iTick != tend))
210  Extrema.add(*(iBuf++) = *(iTick++) - fPedestal);
211  firstLineTick = index;
212  index += line_size;
213 
214  // if the new buffer is the same as the old one, just mark it
215  if (DigitBuffer == LastBuffer) {
216  repeat_count += 1;
217  continue;
218  }
219 
220  // if there are previous repeats, write that on screen
221  // before the new, different line
222  flushRepeatCount(repeat_count);
223 
224  // dump the new line of ticks
225  out.newline();
226  if (fTimeLabelMaker) {
227  out << padRight(
228  fTimeLabelMaker->label(waveform, firstLineTick),
229  fTimeLabelMaker->labelWidth(waveform, firstLineTick)
230  )
231  << headerSep
232  ;
233  }
234  for (auto digit: DigitBuffer)
235  out << " " << std::setw(4) << digit;
236 
237 
238  // quick way to assign DigitBuffer to LastBuffer
239  // (we don't care we lose the former)
240  std::swap(LastBuffer, DigitBuffer);
241 
242  } // while
243  flushRepeatCount(repeat_count);
244  if (Extrema.min() != Extrema.max()) {
245  out.newline()
246  << " range of " << data.size()
247  << " samples: [" << Extrema.min() << ";" << Extrema.max() << "] (span: "
248  << (Extrema.max() - Extrema.min());
249  if (fPedestal != 0) {
250  out << ", absolute: ["
251  << (Extrema.min() + fPedestal) << ";"
252  << (Extrema.max() + fPedestal) << "]";
253  }
254  out << ")";
255  }
256 
257  restoreIndentSettings();
258 
259 } // dump::raw::OpDetWaveformDumper::dump()
260 
261 
262 //----------------------------------------------------------------------------
264  (std::string const& s, unsigned int width, std::string padding /* = " " */)
265 {
266 
267  if (s.length() > width) { // too long already?
268  // truncate on the right
269  return { s, 0U, width }; // { string, start index, character count }
270  }
271 
272  std::string padded;
273  padded.reserve(width);
274 
275  // this is how many full padding strings we need to prepend
276  unsigned int nPadding
277  = (s.length() >= width)? 0U: (width - s.length()) / padding.length();
278 
279  // if there is need for some more partial padding beyond that:
280  if (nPadding * padding.length() + s.length() < width) {
281  // immediately prepend from the rightmost part of the padding string
282  padded.append(
283  padding.end() - (width - (nPadding * padding.length() + s.length())),
284  padding.end()
285  );
286  }
287 
288  // add the rest of the padding and the string, and then we are done
289  while (nPadding-- > 0) padded += padding;
290  padded += s;
291 
292  assert(padded.length() == width);
293 
294  return padded;
295 } // dump::raw::OpDetWaveformDumper::padRight()
296 
297 
298 //----------------------------------------------------------------------------
299 unsigned int dump::raw::OpDetWaveformDumper::digitsOf(unsigned int n) {
300  unsigned int digits = 1U;
301  while (n >= 10) {
302  ++digits;
303  n /= 10;
304  }
305  return digits;
306 } // dump::raw::OpDetWaveformDumper::digitsOf()
307 
308 
309 //----------------------------------------------------------------------------
310 
311 
312 #endif // LARDATAALG_DUMPERS_RAWDATA_OPDETWAVEFORM_H
Data_t max() const
Returns the accumulated maximum, or a very small number if no values.
This_t & add(Data_t value)
Include a single value in the statistics.
OpDetWaveformDumper(raw::ADC_Count_t pedestal=0, unsigned int digitsPerLine=0U)
Constructor: sets waveform dump parameters.
void dump(Stream &&stream, raw::OpDetWaveform const &waveform)
Dumps the content of a waveform into the specified output stream.
void operator()(Stream &&stream, raw::OpDetWaveform const &waveform)
An alias of dump().
virtual unsigned int labelWidth(raw::OpDetWaveform const &waveform, unsigned int) const override
Length of padded label. For best results, it should be a constant.
static std::string padRight(std::string const &s, unsigned int width, std::string padding=" ")
Pads the specified string to the right, truncating its right if needed.
virtual unsigned int labelWidth(raw::OpDetWaveform const &waveform, unsigned int tick) const
Length of padded label. For best results, it should be a constant.
Classes gathering simple statistics.
Keeps track of the minimum and maximum value we observed.
TimeLabelMaker const * fTimeLabelMaker
The functor to be used to extract the time label.
Data_t min() const
Returns the accumulated minimum, or a very large number if no values.
Base functor for printing time according to tick number.
virtual std::string label(raw::OpDetWaveform const &, unsigned int tick) const override
Returns the label to be written for the specified tick number.
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:75
void setTimeLabelMaker(TimeLabelMaker const *timeLabelMaker)
Chooses which time label maker to use.
virtual std::string label(raw::OpDetWaveform const &waveform, unsigned int tick) const =0
Returns the label to be written for the specified tick number.
raw::ADC_Count_t fPedestal
ADC pedestal (subtracted from readings).
Prints the content of optical detector waveforms on screen.
std::string to_string(WindowPattern const &pattern)
then echo File list $list not found else cat $list while read file do echo $file sed s
Definition: file_to_url.sh:60
Base class for data dumpers.
Definition: DumperBase.h:39
std::size_t count(Cont const &cont)
unsigned int fDigitsPerLine
ADC readings per line in the output.
Helper base class for implementing data product dump algorithms.
bnb BNB Stream
static unsigned int digitsOf(unsigned int n)
Pads the specified string to the right, truncating its right if needed.