All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TriggerDataUtils.h
Go to the documentation of this file.
1 /**
2  * @file icaruscode/PMT/Trigger/Utilities/TriggerDataUtils.h
3  * @brief Utilities for the conversion of trigger gate data formats.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  */
6 
7 #ifndef ICARUSCODE_PMT_TRIGGER_UTILITIES_TRIGGERDATAUTILS_H
8 #define ICARUSCODE_PMT_TRIGGER_UTILITIES_TRIGGERDATAUTILS_H
9 
10 
11 // ICARUS libraries
16 
17 // LArSoft libraries
20 
21 // framework libraries
22 #include "art/Persistency/Common/PtrMaker.h"
23 #include "canvas/Persistency/Common/Assns.h"
24 #include "canvas/Persistency/Common/Ptr.h"
25 #include "canvas/Utilities/InputTag.h"
26 #include "cetlib_except/exception.h"
27 
28 // C/C++ standard libraries
29 #include <map>
30 #include <vector>
31 #include <tuple>
32 #include <string> // std::to_string()
33 #include <stdexcept> // std::out_of_range
34 #include <utility> // std::move()
35 #include <type_traits> // std::enable_if_t()
36 
37 
38 //------------------------------------------------------------------------------
39 namespace icarus::trigger {
40 
41  // ---------------------------------------------------------------------------
42 
43  /// Map `util::DataProductPointerMap_t` for `raw::OpDetWaveform` objects.
46 
47  /// Map `util::DataProductPointerMap_t` for `sbn::OpDetWaveformMeta` objects.
50 
51  // ---------------------------------------------------------------------------
52  /**
53  * @brief Returns the trigger gates in serializable format.
54  * @tparam Gates type of the source of trigger gate data
55  * @param gates the data to be reformatted (*data will be stolen!*)
56  * @return gate data product
57  *
58  * This function transfers the data from the original structured `gates` into
59  * a data collection suitable for serialization with _art_, but
60  * *not including the association of each gate with all its contributing
61  * waveforms*.
62  * It must be stressed that this causes information loss, because the trigger
63  * gates will not be associated any more to the contributing waveforms.
64  *
65  * The return value is a collection of trigger gate data
66  * (`icarus::trigger::OpticalTriggerGateData_t`), with data _stolen_
67  * from `gates`.
68  *
69  * The trigger gates are processed in the same order as they are in `gates`.
70  *
71  * After the function returns, `gates` will have been depleted of all the gate
72  * data; any tracking information will be still associated to each gate, whose
73  * gate data will be in an invalid state anyway, only good for destruction.
74  *
75  * The object `gates` is a iterable collection of gate objects: types derived
76  * from `icarus::trigger::ReadoutTriggerGate` and from
77  * `TrackedOpticalTriggerGate` are supported.
78  *
79  * In the following example, we start with trigger gates already serialized
80  * in a _art_ event. The serialization splits a trigger gate object in two
81  * components: the gate levels, and the associated waveforms.
82  * In the first part of the example we recover the information from the event
83  * and we assemble it into the standard trigger gate objects (of type
84  * `icarus::trigger::TrackedOpticalTriggerGate<sbn::OpDetWaveformMeta>`).
85  * After some unspecified and optional processing, `gates` are disassembled
86  * to be saved into the event: this is achieved by a call to
87  * `transformIntoOpticalTriggerGate()` which produces the trigger gate data
88  * and their associations to the waveforms.
89  * In the last part, these components are both stored into the event.
90  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
91  * //
92  * // somehow get/build a collection of trigger gates;
93  * // here we use `FillTriggerGates()` to read existing data from the event
94  * //
95  * std::vector<icarus::trigger::TrackedOpticalTriggerGate<>> gates
96  * = icarus::trigger::ReadTriggerGates(event, "orig");
97  *
98  * // ...
99  *
100  * //
101  * // use the created vector and associations (e.g. put them into art event)
102  * //
103  * event.put(std::make_unique<std::vector<icarus::trigger::OpticalTriggerGateData_t>>
104  * (icarus::trigger::transformIntoOpticalTriggerGate(std::move(gates))));
105  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
106  * Also note that in the omitted processing part the trigger gates might have
107  * been combined into a different type of gates instead.
108  * To serialize that collection, the exact same procedure would be used.
109  * Note that in this example the association to the source waveform metadata
110  * is not serialised (and presumably lost). Another version of
111  * `transformIntoOpticalTriggerGate()` also provides support for the
112  * association to waveform sources.
113  */
114  template <typename Gates>
115  std::vector<icarus::trigger::OpticalTriggerGateData_t>
116  transformIntoOpticalTriggerGate(Gates&& gates);
117 
118 
119  // ---------------------------------------------------------------------------
120  /**
121  * @brief Returns the trigger gates in serializable format.
122  * @tparam OpDetInfo type of the associated waveforms
123  * @param gates the data to be reformatted (*data will be stolen!*)
124  * @param makeGatePtr _art_ pointer maker for the gate data
125  * @param opDetInfoPtrs map of art pointers to optical waveform information
126  * @return a pair: gate data product and associations to `OpDetInfo`
127  *
128  * This function transfers the data from the original structured `gates` into
129  * a data collection suitable for serialization with _art_, including the
130  * association of each gate with all its contributing waveforms.
131  *
132  * The return value is a tuple of two elements:
133  * * `0`: collection of trigger gate data
134  * (`icarus::trigger::OpticalTriggerGateData_t`), with data _stolen_
135  * from `gates`;
136  * * `1`: association between trigger gate data and their optical waveform
137  * information, as reported by `opDetInfoPtrs`.
138  *
139  * The trigger gates are processed in the same order as they are in `gates`,
140  * and the associations to the waveform information are set gate by gate,
141  * in the same order as they are reported by the tracking information of the
142  * input gate.
143  *
144  * After the function returns, `gates` will have been depleted of all the data
145  * and left in an unspecified state only good for destruction.
146  *
147  * The object `gates` is a sequence of
148  * `icarus::trigger::TrackedOpticalTriggerGate` objects, each of them
149  * containing a trigger gate object
150  * (`icarus::trigger::OpticalTriggerGateData_t`) and a list of tracked sources
151  * in the form of `OpDetInfo` objects.
152  *
153  *
154  * In the following example, we start with trigger gates already serialized
155  * in a _art_ event. The serialization splits a trigger gate object in two
156  * components: the gate levels, and the associated waveform information.
157  * In the first part of the example we recover the information from the event
158  * and we assemble it into the standard trigger gate objects (of type
159  * `icarus::trigger::OpticalTriggerGateData_t`).
160  * After some unspecified and optional processing, `gates` are disassembled
161  * to be saved into the event: this is achieved by a call to
162  * `transformIntoOpticalTriggerGate()` which produces the trigger gate data
163  * and their associations to the waveform information.
164  * In the last part, these components are both stored into the event.
165  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
166  * using icarus::trigger::OpticalTriggerGateData_t; // for convenience
167  *
168  * //
169  * // somehow get/build a collection of trigger gates;
170  * // here we use `FillTriggerGates()` to read existing data from the event
171  * //
172  * std::vector<icarus::trigger::TrackedOpticalTriggerGate<sbn::OpDetWaveformMeta>> gates
173  * = icarus::trigger::FillTriggerGates<sbn::OpDetWaveformMeta>
174  * (
175  * event.getProduct<std::vector<OpticalTriggerGateData_t>>("orig"),
176  * event.getProduct<art::Assns<OpticalTriggerGateData_t, sbn::OpDetWaveformMeta>>("orig")
177  * );
178  *
179  *
180  * // ...
181  *
182  * //
183  * // optical waveform information to pointer map is required to create
184  * // associations between the trigger gates and their waveforms
185  * //
186  * auto const& opDetInfoPtrs = util::mapDataProductPointers
187  * (event, event.getValidHandle<std::vector<raw::OpDetWaveformMeta>>("opdaq"));
188  * // transform the data; after this line, `gates` is not usable any more
189  * auto thresholdData = icarus::trigger::transformIntoOpticalTriggerGate
190  * (std::move(gates), makeGatePtr, opDetInfoPtrs);
191  *
192  * //
193  * // use the created vector and associations (e.g. put them into art event)
194  * //
195  * event.put(
196  * std::make_unique<std::vector<OpticalTriggerGateData_t>>
197  * (std::move(std::get<0U>(thresholdData)))
198  * );
199  * event.put(
200  * std::make_unique<art::Assns<OpticalTriggerGateData_t, sbn::OpDetWaveformInfo>>
201  * (std::move(std::get<1U>(thresholdData)))
202  * );
203  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
204  * In this example the most convenient waveform information is used,
205  * `sbn::OpDetWaveformMeta`; the same syntax would hold for using the more
206  * traditional, but encumbering, `raw::OpDetWaveform`.
207  */
208  template <typename OpDetInfo = sbn::OpDetWaveformMeta>
209  std::tuple<
210  std::vector<icarus::trigger::OpticalTriggerGateData_t>,
211  art::Assns<icarus::trigger::OpticalTriggerGateData_t, OpDetInfo>
212  >
215  art::PtrMaker<icarus::trigger::OpticalTriggerGateData_t> const& makeGatePtr,
216  util::DataProductPointerMap_t<OpDetInfo> const& opDetInfoPtrs
217  );
218 
219 
220  // ---------------------------------------------------------------------------
221  /**
222  * @brief Creates a gate object out of trigger gate data products.
223  * @tparam OpDetInfo type of the associated waveforms
224  * @param gates collection of data from all the gates
225  * @param gateToWaveformInfo association between each gate and its waveforms
226  * @return a STL vector of `TrackedOpticalTriggerGate` with copy of data from
227  * `gates`
228  *
229  * Objects like `icarus::trigger::TrackedOpticalTriggerGate` include the gate
230  * level information plus the connections to the source objects (waveforms).
231  * This structure is complicate enoug that they are not saved directly into an
232  * _art_ event. Rather, they are diced into pieces and the pieces are stored.
233  *
234  * This function stitches the pieces and returns back an object like
235  * `icarus::trigger::TrackedOpticalTriggerGate`.
236  *
237  * Example:
238  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
239  * std::vector<icarus::trigger::TrackedOpticalTriggerGate<sbn::OpDetWaveformMeta>>
240  * readTriggerGates(art::Event const& event, art::InputTag const& dataTag)
241  * {
242  *
243  * auto const& gates
244  * = event.getProduct<std::vector<TriggerGateData_t>>(dataTag);
245  * auto const& gateToWaveforms
246  * = event.getProduct<art::Assns<TriggerGateData_t, sbn::OpDetWaveformMeta>>
247  * (dataTag);
248  * return icarus::trigger::FillTriggerGates<sbn::OpDetWaveformMeta>
249  * (gates, gateToWaveforms);
250  *
251  * } // readTriggerGates()
252  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
253  * will read the information from `dateTag` data products in an _art_ `event`
254  * and return a collection of `icarus::trigger::TrackedOpticalTriggerGate`
255  * objects, each one with a _copy_ of the data of the original data product
256  * and a pointer to each of the associated waveform metadata.
257  * Note that this specific functionality is now wrapped into
258  * `icarus::trigger::ReadTriggerGates()`.
259  *
260  *
261  * Return value
262  * -------------
263  *
264  * The returned collection contains one element for each
265  * `OpticalTriggerGateData_t` object in `gates`, in the same order.
266  * Each of these elements is of type
267  * `icarus::trigger::TrackedOpticalTriggerGate<OpDetInfo>`, contains a copy
268  * of the data of the corresponding gate, and a list of optical waveform
269  * information pointers (`OpDetInfo` objects) it is associated to.
270  *
271  *
272  * Requirements
273  * -------------
274  *
275  * The requirements bind the gates to their association to waveforms:
276  * * each gate must be associated to at least one waveform
277  * * the associations must be grouped so that all the association pairs
278  * pertaining a gate are contiguous
279  * * within each of these groups, which is made of at least one waveform,
280  * the waveforms must be ordered by increasing timestamp
281  * * the groups must be in the same order as their associated gates
282  * This constitutes the requirement of
283  * @ref LArSoftProxyDefinitionOneToManySeqAssn "one-to-many sequential association"
284  * with the addition that each element in `gates` must have at least one
285  * associated waveform.
286  *
287  */
288  template <typename OpDetInfo>
289  std::vector<icarus::trigger::TrackedOpticalTriggerGate<OpDetInfo>>
291  std::vector<icarus::trigger::OpticalTriggerGateData_t> const& gates,
292  art::Assns<icarus::trigger::OpticalTriggerGateData_t, OpDetInfo> const& gateToWaveformInfo
293  );
294 
295 
296  // ---------------------------------------------------------------------------
297  template <typename OpDetInfo = sbn::OpDetWaveformMeta>
298  class TriggerGateReader; // documentation is at definition
299 
300  // ---------------------------------------------------------------------------
301  /**
302  * @brief Assembles and returns trigger gates from serialized data.
303  * @tparam OpDetInfo type of object associated to the gates
304  * @tparam Event type of object to read the needed information from
305  * @param event object to read all the needed information from
306  * @param dataTag tag of the data to read from the `event`
307  * @return a collection of "tracking" trigger gates
308  * @throw cet::exception wrapping any `cet::exception` thrown internally
309  * (typically a data product not found)
310  * @see `icarus::trigger::TriggerGateReader`, `icarus::trigger::FillTriggerGates()`
311  *
312  * This function returns "tracking" trigger gates from data read from the data
313  * read from `event`.
314  * It is a one-shot replacement for `TriggerGateReader` to be used when
315  * data to be consumed needn't or can't be declared, or when that declaration
316  * is performed separately.
317  */
318  template <typename OpDetInfo = sbn::OpDetWaveformMeta, typename Event>
319  std::vector<icarus::trigger::TrackedOpticalTriggerGate<OpDetInfo>>
320  ReadTriggerGates(Event const& event, art::InputTag const& dataTag);
321 
322 
323  // ---------------------------------------------------------------------------
324  /// Associates each optical detector channel to a gate.
325  template <typename GateObject>
326  class TriggerGateIndex {
327 
328  public:
329 
330  using TriggerGate_t = GateObject; ///< Type of gate the index lists.
331 
332  /// Constructs an empty index expecting to be filled by `expectedChannels`
333  /// registered channels.
334  TriggerGateIndex(std::size_t expectedChannels = 0U);
335 
336  /// Initializes the index from all the `gates` in the specified collection.
337  TriggerGateIndex(std::vector<TriggerGate_t> const& gates);
338 
339  /// Adds a new gate to the index.
340  /// @throws cet::exception (`"TriggerGateIndex"`) if it conflicts with a
341  /// gate already added
342  void add(TriggerGate_t const& gate);
343 
344  /// Returns the total number of registered channels.
345  unsigned int nChannels() const;
346 
347  /// Returns the gate corresponding to the specified `channel`.
348  TriggerGate_t const* find(raw::Channel_t const channel) const;
349 
350  /// Returns the gate corresponding to the specified `channel`.
351  /// @throws std::out_of_range if the channel is not registered
352  TriggerGate_t const& operator[](raw::Channel_t const channel) const;
353 
354  private:
355 
356  /// Index of gates by channel number (the same gate may appear many times).
357  std::vector<TriggerGate_t const*> fGates;
358 
359  /// Extends internal map with `nullptr` to hold at least `chIndex`.
360  /// @return whether an extension was performed
361  bool expandToHold(std::size_t chIndex);
362 
363  /// Converts a channel number into an index.
364  static std::size_t channelIndex(raw::Channel_t channel);
365 
366  }; // class TriggerGateIndex
367 
368 
369  // ---------------------------------------------------------------------------
370 
371 } // namespace icarus::trigger
372 
373 
374 // -----------------------------------------------------------------------------
375 /**
376  * @brief Assembles and returns trigger gates from serialized data.
377  * @tparam OpDetInfo type of object associated to the gates
378  * @tparam Event type of object to read the needed information from
379  * @param event object to read all the needed information from
380  * @param dataTag tag of the data to read from the `event`
381  * @return a collection of "tracking" trigger gates
382  * @throw cet::exception wrapping any `cet::exception` thrown internally
383  * (typically a data product not found)
384  * @see `icarus::trigger::FillTriggerGates()`
385  *
386  * This class manages reading from a data source trigger gates
387  * (vector of `icarus::trigger::OpticalTriggerGateData_t` elements) and their
388  * associations to a tracking information (`OpDetInfo`: `sbn::OpDetWaveformMeta`
389  * by default, but it may also be e.g. `raw::OpDetWaveform`).
390  *
391  * All this information is merged into the "tracking" trigger gates, which
392  * wrap _ a copy_ of the trigger gates and a reference to the tracked
393  * information (by simple C pointer).
394  *
395  * This class is a framework interface to `FillTriggerGates()`;
396  * interaction with the data source and the framework is driven by the
397  * `Event` object in the `read()` method, which is expected to expose an
398  * `interface similar to _art_'s `art::Event`, and in particular:
399  * * `Event::getProduct<T>(art::InputTag)` to read and return directly
400  * a reference to the persistent, framework-owned data products of type `T`.
401  *
402  * In addition, this class provides a shortcut to declare the consumed data
403  * products, again in a _art_-like interface.
404  * A full usage example in a module includes:
405  *
406  * 1. a reader data member in the module class reading the data:
407  *
408  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
409  * icarus::trigger::TriggerGateReader<> const fGateReader;
410  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
411  *
412  * 2. construction in the module constructor initializer list from a configured
413  * input tag representing the data to be read:
414  *
415  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
416  * , fGateReader{ config().TriggerGateTag() }
417  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
418  *
419  * 3. also in the module constructor body, declaration of what is going to be
420  * read:
421  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
422  * fGateReader.declareConsumes(consumesCollector());
423  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
424  *
425  * 4. actual reading in a context where the current `event` is known:
426  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
427  * std::vector<icarus::trigger::TrackedOpticalTriggerGate<sbn::OpDetWaveformMeta>>
428  * gates = fGateReader(event);
429  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
430  *
431  * In a context where the consume declaration is not relevant/desired, the first
432  * three steps can be omitted and the reading can happen with a temporary
433  * `TriggerGateReader` object; or the shortcut function
434  * `icarus::trigger::ReadTriggerGates()` can be used instead:
435  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
436  * std::vector<icarus::trigger::TrackedOpticalTriggerGate<sbn::OpDetWaveformMeta>>
437  * gates = icarus::trigger::ReadTriggerGates<sbn::OpDetWaveformMeta>(event, dataTag);
438  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
439  * is equivalent to the last step above. Note that it is still possible to use
440  * temporaries also for the consume declaration: for example, a program using
441  * `icarus::trigger::ReadTriggerGates()` may in the proper place (e.g. a module
442  * constructor) call explicitly the consume declaration:
443  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
444  * icarus::trigger::TriggerGateReader<>{ config().TriggerGateTag() }
445  * .declareConsumes(consumesCollector());
446  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
447  * is equivalent to the three steps above. The only advantage of the approach
448  * in multiple steps of the first example is that consistency of declaration
449  * and use is guaranteed by construction.
450  *
451  */
452 template <typename OpDetInfo /* = sbn::OpDetWaveformMeta */>
454 
455  art::InputTag fDataTag; ///< Data tag of the data products being read.
456 
457  public:
458 
459  using OpDetWaveformMeta_t = OpDetInfo; ///< Type of associated information.
460 
461  /// Type of data objects returned.
462  using TriggerGates_t
464 
465 
466  /// Constructor: configure to read the data with the specified tag.
467  TriggerGateReader(art::InputTag dataTag): fDataTag(std::move(dataTag)) {}
468 
469  /// Declares to the `collector` the data products that are going to be read.
470  template <typename ConsumesCollector>
471  void declareConsumes(ConsumesCollector& collector) const;
472 
473  /// Returns the input tag the data is read from.
474  art::InputTag const& inputTag() const { return fDataTag; }
475 
476  // @{
477  /// Reads the configured data product from the specified `event`.
478  template <typename Event>
479  std::vector<TriggerGates_t> read(Event const& event) const;
480  template <typename Event>
481  std::vector<TriggerGates_t> operator() (Event const& event) const
482  { return read(event); }
483  // @}
484 
485 
486 }; // class icarus::trigger::TriggerGateReader
487 
488 
489 
490 // -----------------------------------------------------------------------------
491 // --- template implementation
492 // -----------------------------------------------------------------------------
493 template <typename Gates>
494 std::vector<icarus::trigger::OpticalTriggerGateData_t>
496 
497  using TriggerGateData_t = icarus::trigger::OpticalTriggerGateData_t;
498 
499  std::vector<TriggerGateData_t> gateData;
500 
501  for (TriggerGateData_t& gate: icarus::trigger::gatesIn(gates))
502  gateData.push_back(std::move(gate));
503 
504  return gateData;
505 
506 } // icarus::trigger::transformIntoOpticalTriggerGate(Gates)
507 
508 
509 // -----------------------------------------------------------------------------
510 template <typename OpDetInfo /* = sbn::OpDetWaveformMeta */>
511 std::tuple<
512  std::vector<icarus::trigger::OpticalTriggerGateData_t>,
513  art::Assns<icarus::trigger::OpticalTriggerGateData_t, OpDetInfo>
514  >
517  art::PtrMaker<icarus::trigger::OpticalTriggerGateData_t> const& makeGatePtr,
518  util::DataProductPointerMap_t<OpDetInfo> const& opDetInfoPtrs
519 ) {
520  using TriggerGateData_t = icarus::trigger::OpticalTriggerGateData_t;
521 
522  // note that we rely on the fact that `gates` still contains trigger gates,
523  // and those trigger gates still know about the associated waveforms;
524  // attempting to access their levels, though, would be an error
525  // (if really needed, we can still find them in `gateData`)
526  art::Assns<TriggerGateData_t, OpDetInfo> gateToWaveforms;
527 
528  for (auto const& [ iGate, gate ]: util::enumerate(gates)) {
529 
530  if (!gate.tracking().hasTracked()) continue;
531 
532  //
533  // produce the associations
534  //
535 
536  // pointer to the gate data we have just added:
537  art::Ptr<TriggerGateData_t> const& gatePtr = makeGatePtr(iGate);
538  for (OpDetInfo const* waveform: gate.tracking().getTracked()) {
539 
540  gateToWaveforms.addSingle(gatePtr, opDetInfoPtrs.at(waveform));
541 
542  } // for all waveform info
543 
544  } // for all gates
545 
546  //
547  // create objects for the data products
548  //
549  std::vector<TriggerGateData_t> gateData
551 
552  return { std::move(gateData), std::move(gateToWaveforms) };
553 
554 } // icarus::trigger::transformIntoOpticalTriggerGate()
555 
556 
557 // -----------------------------------------------------------------------------
558 template <typename OpDetInfo>
559 std::vector<icarus::trigger::TrackedOpticalTriggerGate<OpDetInfo>>
561  std::vector<icarus::trigger::OpticalTriggerGateData_t> const& gates,
562  art::Assns<icarus::trigger::OpticalTriggerGateData_t, OpDetInfo> const& gateToWaveformInfo
563 ) {
564 
565  std::vector<icarus::trigger::TrackedOpticalTriggerGate<OpDetInfo>>
566  allGates; // the output
567 
568  auto iGateToWaveform = gateToWaveformInfo.begin();
569  auto const gwend = gateToWaveformInfo.end();
570 
571  for (auto const& [ iGate, gate ]: util::enumerate(gates)) {
572 
574 
575  //
576  // find the relevant waveforms for this gate;
577  // match by index of the element in the data product collection
578  //
579  while (iGateToWaveform != gwend) {
580  if (iGateToWaveform->first.key() == iGate) break;
581  ++iGateToWaveform;
582  } // while
583 
584  while (iGateToWaveform != gwend) {
585  if (iGateToWaveform->first.key() != iGate) break;
586 
587  OpDetInfo const& wfInfo = *(iGateToWaveform->second);
588 
589  // add the associated information to the gate:
590  trackedGate.gate().addChannel(wfInfo.ChannelNumber());
591  trackedGate.tracking().add(&wfInfo);
592 
593  ++iGateToWaveform;
594  } // while
595 
596  allGates.push_back(std::move(trackedGate));
597 
598  } // for gates
599 
600  return allGates;
601 } // icarus::trigger::FillTriggerGates()
602 
603 
604 // -----------------------------------------------------------------------------
605 // --- icarus::trigger::TriggerGateReader
606 // -----------------------------------------------------------------------------
607 template <typename OpDetInfo /* = sbd::OpDetWaveformMeta */>
608 template <typename ConsumesCollector>
610  (ConsumesCollector& collector) const
611 {
612 
613  using icarus::trigger::OpticalTriggerGateData_t; // for convenience
614 
615  collector.template consumes<std::vector<OpticalTriggerGateData_t>>(fDataTag);
616  collector.template consumes<art::Assns<OpticalTriggerGateData_t, OpDetInfo>>
617  (fDataTag);
618 
619 } // icarus::trigger::TriggerGateReader::declareConsumes()
620 
621 
622 // -----------------------------------------------------------------------------
623 template <typename OpDetInfo /* = sbd::OpDetWaveformMeta */>
624 template <typename Event>
625 std::vector<icarus::trigger::TrackedOpticalTriggerGate<OpDetInfo>>
627 
628  using icarus::trigger::OpticalTriggerGateData_t; // for convenience
629 
630  // currently the associations are a waste of time memory...
631  auto const& gates
632  = event.template getProduct<std::vector<OpticalTriggerGateData_t>>(fDataTag);
633  auto const& gateToWaveforms = event.template getProduct
634  <art::Assns<OpticalTriggerGateData_t, OpDetInfo>>(fDataTag);
635 
636  try {
637  return icarus::trigger::FillTriggerGates(gates, gateToWaveforms);
638  }
639  catch (cet::exception const& e) {
640  throw cet::exception("readTriggerGates", "", e)
641  << "readTriggerGates() encountered an error while reading data products from '"
642  << fDataTag.encode() << "'\n";
643  }
644 
645 } // icarus::trigger::TriggerGateReader::read()
646 
647 
648 // -----------------------------------------------------------------------------
649 template <typename OpDetInfo /* = sbd::OpDetWaveformMeta */, typename Event>
650 std::vector<icarus::trigger::TrackedOpticalTriggerGate<OpDetInfo>>
652  (Event const& event, art::InputTag const& dataTag)
653 {
654  return TriggerGateReader<OpDetInfo>{ dataTag }.read(event);
655 } // icarus::trigger::TriggerSimulationOnGates::ReadTriggerGates()
656 
657 
658 // -----------------------------------------------------------------------------
659 // --- icarus::trigger::TriggerGateIndex
660 // -----------------------------------------------------------------------------
661 template <typename GateObject>
663  (std::size_t expectedChannels /* = 0U */)
664 {
665  if (expectedChannels > 0) fGates.reserve(expectedChannels);
666 } // icarus::trigger::TriggerGateIndex::TriggerGateIndex(size_t)
667 
668 // -----------------------------------------------------------------------------
669 template <typename GateObject>
671  (std::vector<TriggerGate_t> const& gates)
672 {
673  for (TriggerGate_t const& gate: gates) add(gate);
674 } // icarus::trigger::TriggerGateIndex::TriggerGateIndex(gates)
675 
676 
677 // -----------------------------------------------------------------------------
678 template <typename GateObject>
680  (TriggerGate_t const& gate)
681 {
682 
683  for (raw::Channel_t const channel: gate.channels()) {
684  auto const chIndex = static_cast<std::size_t>(channel);
685 
686  if (expandToHold(chIndex) || !fGates[chIndex]) {
687  fGates[chIndex] = &gate;
688  }
689  else if (fGates[chIndex] != &gate) {
690  throw cet::exception("TriggerGateIndex") << "TriggerGateIndex::add(): "
691  << "A gate was already present for channel " << channel << ".\n";
692  }
693 
694  } // for
695 
696 } // icarus::trigger::TriggerGateIndex::add()
697 
698 
699 // -----------------------------------------------------------------------------
700 template <typename GateObject>
702  { return static_cast<unsigned int>(fGates.size()); }
703 
704 
705 // -----------------------------------------------------------------------------
706 template <typename GateObject>
708  (raw::Channel_t const channel) const -> TriggerGate_t const*
709 {
710  auto const chIndex = channelIndex(channel);
711  return (chIndex < nChannels())? fGates[chIndex]: nullptr;
712 } // icarus::trigger::TriggerGateIndex::find()
713 
714 
715 // -----------------------------------------------------------------------------
716 template <typename GateObject>
718  (raw::Channel_t const channel) const -> TriggerGate_t const&
719 {
720  auto const gate = find(channel);
721  if (gate) return *gate;
722  throw std::out_of_range(std::to_string(channel));
723 } // icarus::trigger::TriggerGateIndex::operator[]()
724 
725 
726 // -----------------------------------------------------------------------------
727 template <typename GateObject>
729  (std::size_t chIndex)
730 {
731 
732  if (chIndex < fGates.size()) return false;
733 
734  fGates.resize(chIndex + 1U, nullptr);
735  return true;
736 
737 } // icarus::trigger::TriggerGateIndex::expandToHold()
738 
739 
740 // -----------------------------------------------------------------------------
741 template <typename GateObject>
743  (raw::Channel_t channel)
744  { return static_cast<std::size_t>(channel); }
745 
746 
747 // -----------------------------------------------------------------------------
748 
749 #endif // ICARUSCODE_PMT_TRIGGER_UTILITIES_TRIGGERDATAUTILS_H
static std::size_t channelIndex(raw::Channel_t channel)
Converts a channel number into an index.
TriggerGateIndex(std::size_t expectedChannels=0U)
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
Definition: UtilFunc.cxx:42
std::vector< TriggerGates_t > operator()(Event const &event) const
Definition of util::enumerate().
A wrapper to trigger gate objects tracking the input of operations.
auto gatesIn(TrackingGateColl &trackingGates)
Derivative information from raw::OpDetWaveform data.
TriggerGate_t const * find(raw::Channel_t const channel) const
Returns the gate corresponding to the specified channel.
std::vector< icarus::trigger::OpticalTriggerGateData_t > transformIntoOpticalTriggerGate(Gates &&gates)
Returns the trigger gates in serializable format.
void declareConsumes(ConsumesCollector &collector) const
Declares to the collector the data products that are going to be read.
Assembles and returns trigger gates from serialized data.
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
std::vector< TriggerGate_t const * > fGates
Index of gates by channel number (the same gate may appear many times).
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
art::InputTag fDataTag
Data tag of the data products being read.
OpDetInfo OpDetWaveformMeta_t
Type of associated information.
A trigger gate data object for optical detector electronics.
icarus::trigger::ReadoutTriggerGate< TriggerGateTick_t, TriggerGateTicks_t, raw::Channel_t > OpticalTriggerGateData_t
Type of trigger gate data serialized into art data products.
art::InputTag const & inputTag() const
Returns the input tag the data is read from.
bool expandToHold(std::size_t chIndex)
GateObject TriggerGate_t
Type of gate the index lists.
TriggerGate_t const & operator[](raw::Channel_t const channel) const
TriggerGate_t const & gate() const &
Returns the enclosed gate.
std::vector< TriggerGates_t > read(Event const &event) const
Reads the configured data product from the specified event.
std::string to_string(WindowPattern const &pattern)
do i e
Associates each optical detector channel to a gate.
A simple alias for a most commonly used TrackedTriggerGate type.
std::vector< icarus::trigger::TrackedOpticalTriggerGate< OpDetInfo > > FillTriggerGates(std::vector< icarus::trigger::OpticalTriggerGateData_t > const &gates, art::Assns< icarus::trigger::OpticalTriggerGateData_t, OpDetInfo > const &gateToWaveformInfo)
Creates a gate object out of trigger gate data products.
unsigned int nChannels() const
Returns the total number of registered channels.
TriggerGateReader(art::InputTag dataTag)
Constructor: configure to read the data with the specified tag.
void add(TriggerGate_t const &gate)
std::vector< icarus::trigger::TrackedOpticalTriggerGate< OpDetInfo > > ReadTriggerGates(Event const &event, art::InputTag const &dataTag)
Assembles and returns trigger gates from serialized data.
util::DataProductPointerMap_t< sbn::OpDetWaveformMeta > OpDetWaveformMetaDataProductMap_t
Map util::DataProductPointerMap_t for sbn::OpDetWaveformMeta objects.
details::DataProductPointerMap_t< T > DataProductPointerMap_t
Type of map for data product pointers to art pointers.
Utilities to map data pointer elements to their art::Ptr.
util::DataProductPointerMap_t< raw::OpDetWaveform > OpDetWaveformDataProductMap_t
Map util::DataProductPointerMap_t for raw::OpDetWaveform objects.