LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
OpDetWaveform.h
Go to the documentation of this file.
1 
11 #ifndef LARDATAALG_DUMPERS_RAWDATA_OPDETWAVEFORM_H
12 #define LARDATAALG_DUMPERS_RAWDATA_OPDETWAVEFORM_H
13 
14 // LArSoft includes
16 #include "lardataalg/Utilities/StatCollector.h" // lar::util::MinMaxCollector
18 
19 // C//C++ standard libraries
20 #include <algorithm> // std::min()
21 #include <iomanip> // std::setprecision(), std::setw()
22 #include <ios> // std::fixed
23 #include <utility> // std::forward(), std::swap()
24 #include <vector>
25 
26 namespace dump::raw {
27 
28  using namespace ::raw;
29 
44  public:
46  struct TimeLabelMaker {
47 
48  virtual ~TimeLabelMaker() = default;
49 
51  virtual std::string label(raw::OpDetWaveform const& waveform, unsigned int tick) const = 0;
52 
54  virtual unsigned int labelWidth(raw::OpDetWaveform const& waveform, unsigned int tick) const
55  {
56  return 10U;
57  }
58 
59  }; // struct TimeLabelMaker
60 
62  struct TickLabelMaker : public TimeLabelMaker {
63 
65  virtual std::string label(raw::OpDetWaveform const&, unsigned int tick) const override
66  {
67  return std::to_string(tick);
68  }
69 
71  virtual unsigned int labelWidth(raw::OpDetWaveform const& waveform,
72  unsigned int) const override
73  {
74  return digitsOf(waveform.size());
75  }
76 
77  }; // struct TickLabelMaker
78 
89  OpDetWaveformDumper(raw::ADC_Count_t pedestal = 0, unsigned int digitsPerLine = 0U)
90  : fPedestal(pedestal), fDigitsPerLine(digitsPerLine)
91  {}
92 
102  void setTimeLabelMaker(TimeLabelMaker const* timeLabelMaker)
103  {
104  fTimeLabelMaker = timeLabelMaker;
105  }
106 
115  template <typename Stream>
116  void dump(Stream&& stream, raw::OpDetWaveform const& waveform);
117 
119  template <typename Stream>
120  void operator()(Stream&& stream, raw::OpDetWaveform const& waveform)
121  {
122  dump(stream, waveform);
123  }
124 
126  static std::string padRight(std::string const& s,
127  unsigned int width,
128  std::string padding = " ");
129 
131  static unsigned int digitsOf(unsigned int n);
132 
133  private:
135  unsigned int fDigitsPerLine;
136 
138  TimeLabelMaker const* fTimeLabelMaker = nullptr;
139 
140  }; // class OpDetWaveformDumper
141 
142 } // namespace dump::raw
143 
144 // -----------------------------------------------------------------------------
145 // --- Template implementation
146 // -----------------------------------------------------------------------------
147 template <typename Stream>
148 void dump::raw::OpDetWaveformDumper::dump(Stream&& stream, raw::OpDetWaveform const& waveform)
149 {
150  static std::string const headerSep = " | ";
151 
152  auto const& data = waveform;
153  using Count_t = raw::ADC_Count_t;
154 
155  auto out = indenter(std::forward<Stream>(stream));
156 
157  // print a header for the raw digits
158  out.start() << "on channel #" << waveform.ChannelNumber()
159  << " (time stamp: " << waveform.TimeStamp() << "): " << data.size() << " time ticks";
160 
161  // print the content of the channel
162  if (fDigitsPerLine == 0) return;
163 
164  // save and change indentation
165  saveIndentSettings().set(indent() + " ");
166 
167  unsigned int repeat_count = 0U; // additional lines like the last one
168  unsigned int index = 0U;
169  unsigned int firstLineTick = 0U;
170 
171  // local function for printing and resetting the repeat count
172  auto flushRepeatCount =
173  [this, &out, &waveform, &firstLineTick](unsigned int& count) -> decltype(auto) {
174  if (count > 0) {
175  out.newline();
176  if (fTimeLabelMaker) {
177  out << padRight("", fTimeLabelMaker->labelWidth(waveform, firstLineTick)) << headerSep;
178  }
179  out << " [ ... repeated " << count << " more times ]";
180  count = 0;
181  }
182  return out;
183  };
184 
185  std::vector<Count_t> DigitBuffer(fDigitsPerLine), LastBuffer;
186 
188  out.newline() << "content of the channel (" << fDigitsPerLine << " ticks per line):";
189  auto iTick = data.cbegin(), tend = data.cend(); // const iterators
190  while (iTick != tend) {
191  // the next line will show at most fDigitsPerLine ticks
192  unsigned int line_size = std::min(fDigitsPerLine, (unsigned int)data.size() - index);
193  if (line_size == 0) break; // no more ticks
194 
195  // fill the new buffer (iTick will move forward)
196  DigitBuffer.resize(line_size);
197  auto iBuf = DigitBuffer.begin(), bend = DigitBuffer.end();
198  while ((iBuf != bend) && (iTick != tend))
199  Extrema.add(*(iBuf++) = *(iTick++) - fPedestal);
200  firstLineTick = index;
201  index += line_size;
202 
203  // if the new buffer is the same as the old one, just mark it
204  if (DigitBuffer == LastBuffer) {
205  repeat_count += 1;
206  continue;
207  }
208 
209  // if there are previous repeats, write that on screen
210  // before the new, different line
211  flushRepeatCount(repeat_count);
212 
213  // dump the new line of ticks
214  out.newline();
215  if (fTimeLabelMaker) {
216  out << padRight(fTimeLabelMaker->label(waveform, firstLineTick),
217  fTimeLabelMaker->labelWidth(waveform, firstLineTick))
218  << headerSep;
219  }
220  for (auto digit : DigitBuffer)
221  out << " " << std::setw(4) << digit;
222 
223  // quick way to assign DigitBuffer to LastBuffer
224  // (we don't care we lose the former)
225  std::swap(LastBuffer, DigitBuffer);
226 
227  } // while
228  flushRepeatCount(repeat_count);
229  if (Extrema.min() != Extrema.max()) {
230  out.newline() << " range of " << data.size() << " samples: [" << Extrema.min() << ";"
231  << Extrema.max() << "] (span: " << (Extrema.max() - Extrema.min());
232  if (fPedestal != 0) {
233  out << ", absolute: [" << (Extrema.min() + fPedestal) << ";" << (Extrema.max() + fPedestal)
234  << "]";
235  }
236  out << ")";
237  }
238 
240 
241 } // dump::raw::OpDetWaveformDumper::dump()
242 
243 //----------------------------------------------------------------------------
244 std::string dump::raw::OpDetWaveformDumper::padRight(std::string const& s,
245  unsigned int width,
246  std::string padding /* = " " */)
247 {
248 
249  if (s.length() > width) { // too long already?
250  // truncate on the right
251  return {s, 0U, width}; // { string, start index, character count }
252  }
253 
254  std::string padded;
255  padded.reserve(width);
256 
257  // this is how many full padding strings we need to prepend
258  unsigned int nPadding = (s.length() >= width) ? 0U : (width - s.length()) / padding.length();
259 
260  // if there is need for some more partial padding beyond that:
261  if (nPadding * padding.length() + s.length() < width) {
262  // immediately prepend from the rightmost part of the padding string
263  padded.append(padding.end() - (width - (nPadding * padding.length() + s.length())),
264  padding.end());
265  }
266 
267  // add the rest of the padding and the string, and then we are done
268  while (nPadding-- > 0)
269  padded += padding;
270  padded += s;
271 
272  assert(padded.length() == width);
273 
274  return padded;
275 } // dump::raw::OpDetWaveformDumper::padRight()
276 
277 //----------------------------------------------------------------------------
278 unsigned int dump::raw::OpDetWaveformDumper::digitsOf(unsigned int n)
279 {
280  unsigned int digits = 1U;
281  while (n >= 10) {
282  ++digits;
283  n /= 10;
284  }
285  return digits;
286 } // dump::raw::OpDetWaveformDumper::digitsOf()
287 
288 //----------------------------------------------------------------------------
289 
290 #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.
Channel_t ChannelNumber() const
Definition: OpDetWaveform.h:52
OpDetWaveformDumper(raw::ADC_Count_t pedestal=0, unsigned int digitsPerLine=0U)
Constructor: sets waveform dump parameters.
Definition: OpDetWaveform.h:89
void dump(Stream &&stream, raw::OpDetWaveform const &waveform)
Dumps the content of a waveform into the specified output stream.
TimeStamp_t TimeStamp() const
Definition: OpDetWaveform.h:53
void operator()(Stream &&stream, raw::OpDetWaveform const &waveform)
An alias of dump().
IndentSettings & restoreIndentSettings()
Restores and returns the last saved settings.
Definition: DumperBase.h:233
void set(std::string const &newIndent, std::string const &newFirstIndent)
Definition: DumperBase.h:43
Raw data description.
Definition: RawTypes.h:6
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.
Definition: OpDetWaveform.h:54
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.
decltype(auto) constexpr to_string(T &&obj)
ADL-aware version of std::to_string.
virtual std::string label(raw::OpDetWaveform const &, unsigned int tick) const override
Returns the label to be written for the specified tick number.
Definition: OpDetWaveform.h:65
Base functor for printing time according to tick number.
Definition: OpDetWaveform.h:46
std::string const & indent() const
Returns the indentation string currently configured for all lines.
Definition: DumperBase.h:95
tick_as<> tick
Tick number, represented by std::ptrdiff_t.
Definition: electronics.h:73
decltype(auto) indenter(Stream &&out) const
Returns an Indenter object tied to this dumper and out stream.
Definition: DumperBase.h:215
void setTimeLabelMaker(TimeLabelMaker const *timeLabelMaker)
Chooses which time label maker to use.
raw::ADC_Count_t fPedestal
ADC pedestal (subtracted from readings).
Prints the content of optical detector waveforms on screen.
Definition: OpDetWaveform.h:43
IndentSettings & saveIndentSettings()
Stacks a copy of the current settings, and returns the "new" ones.
Definition: DumperBase.h:225
virtual unsigned int labelWidth(raw::OpDetWaveform const &waveform, unsigned int) const override
Length of padded label. For best results, it should be a constant.
Definition: OpDetWaveform.h:71
Char_t n[5]
virtual std::string label(raw::OpDetWaveform const &waveform, unsigned int tick) const =0
Returns the label to be written for the specified tick number.
Base class for data dumpers.
Definition: DumperBase.h:37
unsigned int fDigitsPerLine
ADC readings per line in the output.
Helper base class for implementing data product dump algorithms.
short ADC_Count_t
Definition: OpDetWaveform.h:20
static unsigned int digitsOf(unsigned int n)
Pads the specified string to the right, truncating its right if needed.
Time label: tick number relative to the waveform.
Definition: OpDetWaveform.h:62