All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DataProductPointerMap.h
Go to the documentation of this file.
1 /**
2  * @file icaruscode/Utilities/DataProductPointerMap.h
3  * @brief Utilities to map data pointer elements to their `art::Ptr`.
4  * @author Gianluca Petrillo (petrillo@slac.stanford.edu)
5  * @date December 13, 2019
6  *
7  * This library is header only.
8  */
9 
10 #ifndef ICARUSCODE_UTILITIES_DATAPRODUCTPOINTERMAP_H
11 #define ICARUSCODE_UTILITIES_DATAPRODUCTPOINTERMAP_H
12 
13 
14 // LArSoft libraries
16 
17 // framework libraries
18 #include "art/Framework/Principal/Event.h"
19 #include "art/Persistency/Common/PtrMaker.h"
20 #include "canvas/Persistency/Common/Ptr.h"
21 
22 // C/C++ standard libraries
23 #include <map>
24 #include <vector>
25 #include <type_traits> // std::is_same_v
26 
27 
28 namespace util {
29 
30  // ---------------------------------------------------------------------------
31  namespace details {
32 
33  // this is just to stress that the fact this is a STL map may change.
34  template <typename T>
35  using DataProductPointerMap_t = std::map<T const*, art::Ptr<T>>;
36 
37  } // namespace details
38 
39  // ---------------------------------------------------------------------------
40  /// Type of data in a _art_ handle to vector data product.
41  template <typename Handle>
42  using ArtHandleData_t = typename Handle::element_type::value_type;
43 
44  /// Type of map for data product pointers to _art_ pointers.
45  template <typename T>
47 
48 
49  // ---------------------------------------------------------------------------
50  /**
51  * @brief Creates a map from address of data product element to _art_ pointer
52  * to it.
53  * @tparam Handle type of handle to data product (e.g. `art::ValidHandle`)
54  * @param handle _art_ handle to the data product
55  * @param event the _art_ event the data product belongs to
56  * @return a map from data product element pointer to _art_ pointer
57  *
58  * Returns a map from the address of any of the objects in the data product
59  * in `event` pointed by `handle` and the _art_ pointer to those objects.
60  * Provided that the type in the data product is `T`, the returned map is an
61  * object guaranteed to have:
62  * * standard mobility (copy and move constructors and assignment operators)
63  * * an unckecked access operator `operator[] (T const*) const` returning
64  * some form of `art::Ptr<T>` (`art::Ptr<T>`, `art::Ptr<T> const&`...);
65  * * a checked access operator `at(T const*) const` similar to `operator[]`
66  * but throwing an exception derived from `std::out_of_range` if the
67  * element is not found;
68  * * an `empty()`, a `size()` and a `clear()` method.
69  *
70  * Example: with `event` a `art::Event` object and `waveformHandle` an handle
71  * to a `std::vector<raw::OpDetWaveform>` data product in `event`:
72  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
73  * DataProductPointerMap_t<raw::OpDetWaveform> const& opDetWavePtrs
74  * = util::mapDataProductPointers(event, waveformHandle);
75  *
76  * for (raw::OpDetWaveform const& waveform: *waveformHandle) {
77  *
78  * art::Ptr<raw::OpDetWaveform> const& ptr = opDetWavePtrs.at(&waveform);
79  *
80  * // ...
81  *
82  * } // for
83  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
84  * in the loop the `art::Ptr` of each `waveform` is tracked without carrying
85  * around the index of the waveform in the original data product.
86  *
87  * There are alternative approaches to this: one can rely on the contiguous
88  * memory model of `std::vector` and carry around the address of the first
89  * waveform, `&(waveformHandle->front())`, and a properly initialized
90  * `art::PtrMaker` which can then invoked as
91  * `ptrMaker(&waveform - waveform0ptr)`; or work directly with `art::Ptr`.
92  * This approach is more factorised than the first alternative (knowledge
93  * of the event is not required any more during the iteration) and arguably
94  * faster than the second, where _art_ pointer dereferencing always has
95  * a small overhead, but it uses more memory.
96  *
97  * @note The returned object is currently a C++ STL data container.
98  * Optimizations are possible using a different data structure
99  * (for example, a vector-based container with index based on the
100  * difference described in the example above) and they may in future
101  * be implemented. Because of this reason, it is recommended that the
102  * produced map is stored in variables declared with an `auto const&`
103  * type or as a `DataProductPointerMap_t` instance, rather than with
104  * the currently underlying data type.
105  */
106  template <typename Handle>
108  (art::Event const& event, Handle const& handle);
109 
110  // ---------------------------------------------------------------------------
111 
112 } // namespace util
113 
114 
115 // -----------------------------------------------------------------------------
116 // --- template implementation
117 // -----------------------------------------------------------------------------
118 //------------------------------------------------------------------------------
119 template <typename Handle>
120 auto util::mapDataProductPointers(art::Event const& event, Handle const& handle)
121  -> DataProductPointerMap_t<ArtHandleData_t<Handle>>
122 {
123  using Data_t = ArtHandleData_t<Handle>;
124  using Map_t = DataProductPointerMap_t<Data_t>;
125 
126  static_assert(
127  std::is_same_v<std::vector<Data_t>, typename Handle::element_type>,
128  "mapDataProductPointers() requires handles to STL vectors of data"
129  );
130 
131  Map_t map;
132  art::PtrMaker<Data_t> makePtr { event, handle.id() };
133  for (auto const& [ i, item ]: util::enumerate(*handle))
134  map[&item] = makePtr(i);
135  return map;
136 } // util::mapDataProductPointers()
137 
138 
139 // -----------------------------------------------------------------------------
140 
141 #endif // ICARUSCODE_UTILITIES_DATAPRODUCTPOINTERMAP_H
Definition of util::enumerate().
std::map< T const *, art::Ptr< T >> DataProductPointerMap_t
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
Definition: enumerate.h:69
typename Handle::element_type::value_type ArtHandleData_t
Type of data in a art handle to vector data product.
DataProductPointerMap_t< ArtHandleData_t< Handle > > mapDataProductPointers(art::Event const &event, Handle const &handle)
Creates a map from address of data product element to art pointer to it.
details::DataProductPointerMap_t< T > DataProductPointerMap_t
Type of map for data product pointers to art pointers.