withParallelData.h
Go to the documentation of this file.
1 /**
2  * @file lardata/RecoBaseProxy/ProxyBase/withParallelData.h
3  * @brief Interface to add auxiliary data from parallel collections to a proxy.
4  * @author Gianluca Petrillo (petrillo@fnal.gov)
5  * @date July 27, 2017
6  * @see lardata/RecoBaseProxy/ProxyBase.h
7  *
8  * This library is header-only.
9  */
10 
11 #ifndef LARDATA_RECOBASEPROXY_PROXYBASE_WITHPARALLELDATA_H
12 #define LARDATA_RECOBASEPROXY_PROXYBASE_WITHPARALLELDATA_H
13 
14 // LArSoft libraries
17 #include "larcorealg/CoreUtils/ContainerMeta.h" // util::collection_value_t, ...
18 
19 // C/C++ standard
20 #include <tuple>
21 #include <utility> // std::forward(), std::move()
22 
23 
24 namespace proxy {
25 
26 
27  //----------------------------------------------------------------------------
28  namespace details {
29 
30  template <typename Aux, typename ArgTuple, typename AuxTag = Aux>
31  using WithParallelCollectionStruct = WithAssociatedStructBase<
32  Aux,
33  void, // no metadata concept for parallel collections
34  ArgTuple,
35  ParallelDataProxyMakerWrapper<Aux, AuxTag>::template maker_t,
36  AuxTag
37  >;
38 
39 
40  template
41  <typename Aux, typename ArgTuple, typename AuxColl, typename AuxTag = Aux>
43  Aux,
44  void, // no metadata concept for parallel collections
45  ArgTuple,
47  AuxTag
48  >;
49 
50  } // namespace details
51 
52 
53  // --- BEGIN Parallel data collections ---------------------------------------
54  /**
55  * @name Parallel data collections
56  *
57  * These functions allow to merge into a data collection proxy some auxiliary
58  * data from other collections fulfilling the
59  * @ref LArSoftProxyDefinitionParallelData "parallel data product requirement".
60  *
61  * Two categories of functions are available depending on the data source:
62  * * `proxy::withParallelData()` reads the relevant data product from an
63  * event
64  * * `proxy::wrapParallelData()` uses an existing collection
65  *
66  * Also, variants are available to customize the tag class.
67  *
68  * The implementation of this feature is documented in
69  * @ref LArSoftProxiesParallelData "its own doxygen module".
70  *
71  * @{
72  */
73 
74  //----------------------------------------------------------------------------
75  /**
76  * @brief Helper function to merge an auxiliary data product into the proxy.
77  * @tparam Aux type of parallel data product requested
78  * @tparam AuxTag the tag type to refer this auxiliary data as
79  * @tparam Args types of constructor arguments for parallel data proxy
80  * @param args constructor arguments for the parallel data collection proxy
81  * @return a temporary object that `getCollection()` knows to handle
82  * @ingroup LArSoftProxyBase
83  * @see `proxy::withParallelData()`
84  *
85  * This function is meant to convey to `getCollection()` function the request
86  * for merging a auxiliary data structured as a
87  * @ref LArSoftProxyDefinitionParallelData "collection parallel" into the
88  * collection proxy.
89  *
90  * It is functionally equivalent to `withParallelData()`, with the difference
91  * that here the auxiliary data tag must be specified. `withParallelData()`
92  * documentation also contains examples on how to use this function and the
93  * proxy resulting from that.
94  */
95  template <typename Aux, typename AuxTag, typename... Args>
96  auto withParallelDataAs(Args&&... args) {
97  using ArgTuple_t = std::tuple<Args&&...>;
98  ArgTuple_t argsTuple(std::forward<Args>(args)...);
100  (std::move(argsTuple));
101  } // withParallelDataAs()
102 
103  //----------------------------------------------------------------------------
104  /**
105  * @brief Helper function to merge an auxiliary data product into the proxy.
106  * @tparam Aux type of parallel data product requested
107  * @tparam Args types of constructor arguments for parallel data proxy
108  * @param args constructor arguments for the parallel data collection proxy
109  * @return a temporary object that `getCollection()` knows to handle
110  * @ingroup LArSoftProxyBase
111  *
112  * This function is meant to convey to `getCollection()` function the request
113  * to merge auxiliary data structured as a
114  * @ref LArSoftProxyDefinitionParallelData "collection parallel" into the
115  * collection proxy.
116  *
117  * This data will be tagged with the type `Aux`. To use a different type as
118  * tag, use `withParallelDataAs()` instead, specifying the tag as second
119  * template argument, e.g.:
120  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
121  * struct MCS {};
122  * auto tracks = proxy::getCollection<proxy::Tracks>(event, trackTag,
123  * withParallelData<recob::TrackMomentum>(defaultMomTag),
124  * withParallelDataAs<recob::TrackMomentum, MCS>(MCSmomTag)
125  * );
126  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
127  * The first momentum association (`"defaultMomTag"`) will be accessed by
128  * using the type `recob::TrackMomentum` as tag, while the second one will
129  * be accessed by the `MCS` tag (which is better not be defined in a local
130  * scope):
131  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
132  * for (auto&& track: tracks) {
133  * decltype(auto) trackMom = track.get<recob::TrackMomentum>();
134  * decltype(auto) trackMCSmom = track.get<MCS>();
135  * // ...
136  * }
137  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
138  *
139  * The default implementation of parallel data proxy returns for each element
140  * query an object with the same interface as the element of the parallel data
141  * collection. In the previous examples, that would be a constant reference to
142  * an object with `recob::TrackMomentum` interface.
143  *
144  *
145  * Customization of the parallel data proxy
146  * =========================================
147  *
148  * To have a call like:
149  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
150  * auto tracks = getCollection<SpecialTracks>
151  * (event, tag, withParallelData<recob::TrackMomentum>(momTag, "special"));
152  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
153  * to create something different than the standard parallel data proxy,
154  * one needs to specialize `proxy::ParallelDataProxyMaker`, e.g.:
155  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
156  * namespace proxy {
157  * template <>
158  * struct ParallelDataProxyMaker<recob::Track, recob::TrackMomentum, SpecialTracks>
159  * : public ParallelDataProxyMakerBase<recob::Track, std::vector<recob::TrackMomentum>, recob::TrackMomentum>
160  * {
161  *
162  * template<typename Event, typename MainArgs>
163  * static auto make(
164  * Event const& event,
165  * MainArgs const&,
166  * art::InputTag assnTag,
167  * std::string quality = "default"
168  * )
169  * {
170  * ::SpecialTrackHitsProxy myAuxProxy;
171  * // ... make it, and make it right
172  * return myAuxProxy;
173  * }
174  *
175  * }; // struct ParallelDataProxyMaker<recob::Track, recob::TrackMomentum, SpecialTracks>
176  *
177  * } // namespace proxy
178  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
179  *
180  */
181  template <typename Aux, typename... Args>
182  auto withParallelData(Args&&... args)
183  { return withParallelDataAs<Aux, Aux>(std::forward<Args>(args)...); }
184 
185 
186  //----------------------------------------------------------------------------
187  /**
188  * @brief Uses a collection as auxiliary data for a collection proxy.
189  * @tparam AuxTag the tag type to refer this auxiliary data as
190  * @tparam AuxColl type of the auxiliary data collection
191  * @param auxColl the data collection to be used as auxiliary data
192  * @return an object making `getCollection()` add such auxiliary data
193  * @ingroup LArSoftProxyBase
194  * @see `withParallelDataAs()`, `wrapParallelData()`
195  *
196  * The specified collection is used directly as auxiliary data in a collection
197  * proxy. It is required to fulfil the
198  * @ref LArSoftProxyDefinitionParallelData "parallel data product"
199  * requirements, but it does not have to actually be a data product (that is,
200  * it does not have to be a collection read from _art_).
201  *
202  * The usage of the resulting proxy is the same as the ones created using
203  * `proxy::withParallelDataAs()`, but the object `auxColl` must remain valid
204  * as long as that proxy is being used.
205  * Example of usage:
206  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
207  * struct MCS {};
208  *
209  * void checkMomenta(
210  * std::vector<recob::TrackMomentum> const& mom,
211  * std::vector<recob::TrackMomentum> const& MCSmom
212  * ) {
213  * auto tracks = proxy::getCollection<proxy::Tracks>(event, trackTag,
214  * wrapParallelData<recob::TrackMomentum>(defaultMomTag),
215  * wrapParallelDataAs<recob::TrackMomentum, MCS>(MCSmomTag)
216  * );
217  * for (auto const& track: tracks) {
218  * auto const& trackMom = track.get<recob::TrackMomentum>();
219  * auto const& trackMCSmom = track.get<MCS>();
220  *
221  * // ...
222  *
223  * } // for tracks
224  *
225  * } // checkMomenta()
226  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
227  * The first momentum (`mom`) will be accessed by using the type
228  * `recob::TrackMomentum` as tag, while the second one (`MCSmom`) will be
229  * accessed by the `MCS` tag (which is better not be defined in a local
230  * scope).
231  */
232  template <typename AuxTag, typename AuxColl>
233  auto wrapParallelDataAs(AuxColl const& auxColl) {
234  std::tuple<AuxColl const&> args = { auxColl };
236  <util::collection_value_t<AuxColl>, decltype(args), AuxColl, AuxTag>
237  (std::move(args));
238  } // wrapParallelDataAs()
239 
240 
241  /**
242  * @brief Uses a collection as auxiliary data for a collection proxy.
243  * @tparam AuxColl type of the auxiliary data collection
244  * @param auxColl the data collection to be used as auxiliary data
245  * @return an object making `getCollection()` add such auxiliary data
246  * @ingroup LArSoftProxyBase
247  * @see `proxy::withParallelData()`, `proxy::wrapParallelDataAs()`
248  *
249  * This function is meant to convey to `getCollection()` function the request
250  * for merging an existing auxiliary data collection structured as a
251  * @ref LArSoftProxyDefinitionParallelData "collection parallel" into the
252  * collection proxy.
253  *
254  * It is functionally equivalent to `wrapParallelDataAs()`, with the
255  * difference that here the auxiliary data tag is automatically defined after
256  * the type of the data in the container. `withParallelDataAs()`
257  * documentation also contains examples on how to use this function and the
258  * proxy resulting from that.
259  */
260  template <typename AuxColl>
261  auto wrapParallelData(AuxColl const& auxColl)
262  { return wrapParallelDataAs<util::collection_value_t<AuxColl>>(auxColl); }
263 
264 
265  /// @}
266  // --- END Parallel data collections -----------------------------------------
267 
268 } // namespace proxy
269 
270 
271 #endif // LARDATA_RECOBASEPROXY_PROXYBASE_WITHPARALLELDATA_H
auto wrapParallelData(AuxColl const &auxColl)
Uses a collection as auxiliary data for a collection proxy.
Helper to create associated data proxy.
static QCString args
Definition: declinfo.cpp:674
auto withParallelData(Args &&...args)
Helper function to merge an auxiliary data product into the proxy.
def move(depos, offset)
Definition: depos.py:107
auto withParallelDataAs(Args &&...args)
Helper function to merge an auxiliary data product into the proxy.
Infrastructure for the addition of parallel data to a proxy.
auto wrapParallelDataAs(AuxColl const &auxColl)
Uses a collection as auxiliary data for a collection proxy.
WithAssociatedStructBase< Aux, void, ArgTuple, ParallelDataProxyMakerWrapper< Aux, AuxTag >::template maker_t, AuxTag > WithParallelCollectionStruct
typename collection_value_type< Coll >::type collection_value_t
Type contained in the collection Coll.
Definition: ContainerMeta.h:65
C++ metaprogramming utilities for dealing with containers.
Template class to declare addition of associated data to a proxy.