AssociationUtil.h
Go to the documentation of this file.
1 /**
2  * @file AssociationUtil.h
3  * @author brebel@fnal.gov
4  * @brief Utility object to perform functions of association
5  *
6  * @attention Please considering using the lightweight utility `art::PtrMaker`
7  * instead.
8  *
9  * This library provides a number of util::CreateAssn() functions;
10  * for convenience, the ones supported as of January 2015 are listed here:
11  *
12  * -# `CreateAssn(art::Event&, std::vector<T> const&, art::Ptr<U> const&b, art::Assns<U,T> &, std::string, size_t)`
13  * one-to-one association, between a element of a vector (future data product)
14  * and a art-pointed object; allows for a instance name for the vector
15  * -# `CreateAssn(art::Event&, std::vector<T> const&, art::Ptr<U> const&b, art::Assns<U,T> &, size_t)`
16  * one-to-one association, between a element of a vector (future data product)
17  * and a art-pointed object
18  * -# `CreateAssn(art::Event&, art::Ptr<T> const&, art::Ptr<U> const&, art::Assns<U,T>&)`
19  * one-to-one association, between two art-pointed objects
20  * -# `CreateAssn(art::Event&, std::vector<T> const&, art::PtrVector<U> const&, art::Assns<T,U>&, size_t)`
21  * one-to-many association, between a element of a vector (future data
22  * product) and a list of art-pointed objects in a art::PtrVector list
23  * -# `CreateAssn(art::Event&, art::Ptr<T> const&, std::vector<art::Ptr<U>> const&, art::Assns<T,U>&)`
24  * one-to-many association, between an art-pointed object and all the elements
25  * in a std::vector of art-pointed objects
26  * -# `CreateAssn(art::Event&, std::vector<T> const&, std::vector<art::Ptr<U>>&, art::Assns<T,U>&, size_t)`
27  * one-to-many association, between an element of a vector (future data
28  * product) and all the elements in a std::vector of art-pointed objects
29  * -# `CreateAssn(art::Event&, std::vector<T> const&, std::vector<U> const&, art::Assns<T,U>&, size_t, size_t, size_t)`
30  * one-to-many association, between an element of a vector (future data
31  * product) and the elements in a subrange of a std::vector (also future data
32  * product)
33  * -# `CreateAssn(art::Event&, art::Assns<T,U>&, size_t, Iter, Iter)`
34  * one-to-many association, between an element of a collection and the
35  * elements of another collection, whose indices are specified by the values
36  * in a subrange of a third collection (of indices)
37  * -# @code CreateAssnD(art::Event&, art::Assns<T,U>&, size_t, size_t, typename art::Assns<T,U,D>::data_t const&) @endcode,
38  * @code CreateAssnD(art::Event&, art::Assns<T,U>&, size_t, size_t, typename art::Assns<T,U,D>::data_t&&) @endcode
39  * one-to-one association, between an element of a collection and the element
40  * of another collection, both specified by index, with additional data
41  *
42  * For all the associated objects, either side, that are not specified by
43  * `art::Ptr`, the index of the object in its collection must be (or stay) the
44  * same as the index in the final data product collection.
45  *
46  *
47  * One-to-one associations
48  * ------------------------
49  *
50  * the one (T) | the other one (U) | special notes | function
51  * :--------------------: | :---------------: | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------
52  * element of std::vector | art pointer | allows instance name for T | CreateAssn(art::Event &, std::vector< T > const &, art::Ptr< U > const &, art::Assns< U, T > &, std::string, size_t)
53  * element of std::vector | art pointer | | CreateAssn(art::Event&, std::vector<T> const&, art::Ptr<U> const&, art::Assns<U,T> &, size_t)
54  * art pointer | art pointer | | CreateAssn(art::Event&, art::Ptr<T> const&, art::Ptr<U> const&, art::Assns<U,T>&)
55  * element by index | element by index | associates data too | CreateAssnD(art::Event&, art::Ptr<T> const&, art::Ptr<U> const&, art::Assns<U,T,D>&, size_t, size_t, typename art::Assns<T,U,D>::data_t const&)
56  * element by index | element by index | associates data too (moved) | CreateAssnD(art::Event&, art::Ptr<T> const&, art::Ptr<U> const&, art::Assns<U,T,D>&, size_t, size_t, typename art::Assns<T,U,D>::data_t&&)
57  *
58  *
59  * One-to-many associations
60  * -------------------------
61  *
62  * the one (T) | the many (U) | special notes | function
63  * :--------------------: | :----------------------: | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------
64  * element of std::vector | art::PtrVector | | CreateAssn(art::Event&, std::vector<T> const&, art::PtrVector<U> const&, art::Assns<T,U>&, size_t)
65  * art pointer | std::vector<art::Ptr<U>> | | CreateAssn(art::Event&, art::Ptr<T> const&, std::vector<art::Ptr<U>> const&, art::Assns<T,U>&)
66  * element of std::vector | std::vector<art::Ptr<U>> | | CreateAssn(art::Event&, std::vector<T> const&, std::vector<art::Ptr<U>>&, art::Assns<T,U>&, size_t)
67  * element of std::vector | std::vector<U> | | CreateAssn(art::Event&, std::vector<T> const&, std::vector<U> const&, art::Assns<T,U>&, size_t, size_t, size_t)
68  * element by index | range of indices | does not need object lists | CreateAssn(art::Event&, art::Assns<T,U>&, size_t, Iter, Iter)
69  *
70  */
71 
72 #ifndef ASSOCIATIONUTIL_H
73 #define ASSOCIATIONUTIL_H
74 
75 // C/C++ standard libraries
76 #include <string>
77 #include <utility> // std::move()
78 #include <vector>
79 
80 // framework libraries
84 #include "canvas/Persistency/Common/FindMany.h"
85 #include "canvas/Persistency/Common/FindManyP.h"
86 #include "canvas/Persistency/Common/FindOne.h"
87 #include "canvas/Persistency/Common/FindOneP.h"
91 
92 namespace util {
93 
94  // see https://cdcvs.fnal.gov/redmine/projects/art/wiki/Inter-Product_References
95  // for information about using art::Assns
96 
97  /**
98  * @brief Creates a single one-to-one association
99  * @tparam T type of the new object to associate
100  * @tparam U type of the object already in the data product or art::Ptr
101  * @param evt reference to the current event
102  * @param a vector of data products that are in, or will be put into, evt
103  * @param b art::Ptr to the (new) object to be associated to the one in a
104  * @param assn reference to association object where the new one will be put
105  * @param a_instance name of the instance that will be used for a in evt
106  * @param index index of the element in a to be associated with b (default: the last element)
107  * @return whether the operation was successful (can it ever fail??)
108  *
109  * As example of usage: create a wire/raw digit association.
110  * This code should live in the art::EDProduce::produce() method.
111  * The raw::RawDigit product was created already by a DigitModuleLabel module.
112  * The code is supposed to produce one recob::Wire for each existing
113  * raw::RawDigit, and contextually associate the new wire to the source digit.
114  * We are also assuming that there might be different RawDigit sets produced
115  * by the same producer: we identify the one we care of by the string
116  * spill_name and we create wires and associations with the same label
117  * for convenience.
118  *
119  * // this is the original list of digits, thawed from the event
120  * art::Handle< std::vector<raw::RawDigit>> digitVecHandle;
121  * evt.getByLabel(DigitModuleLabel, spill_name, digitVecHandle);
122  *
123  * // the collection of wires that will be written as data product
124  * std::unique_ptr<std::vector<recob::Wire>> wirecol(new std::vector<recob::Wire>);
125  * // ... and an association set
126  * std::unique_ptr<art::Assns<raw::RawDigit,recob::Wire>> WireDigitAssn
127  * (new art::Assns<raw::RawDigit,recob::Wire>);
128  *
129  * for(size_t iDigit = 0; iDigit < digitVecHandle->size(); ++iDigit) {
130  * // turn the digit into a art::Ptr:
131  * art::Ptr<raw::RawDigit> digit_ptr(digitVecHandle, iDigit);
132  *
133  * // store the wire in its final position in the data product;
134  * // the new wire is currently the last of the list
135  * wirecol->push_back(std::move(wire));
136  *
137  * // add an association between the last object in wirecol
138  * // (that we just inserted) and digit_ptr
139  * if (!util::CreateAssn(*this, evt, *wirecol, digit_ptr, *WireDigitAssn, spill_name)) {
140  * throw art::Exception(art::errors::ProductRegistrationFailure)
141  * << "Can't associate wire #" << (wirecol->size() - 1)
142  * << " with raw digit #" << digit_ptr.key();
143  * } // if failed to add association
144  *
145  * } // for digits
146  *
147  * evt.put(std::move(wirecol), spill_name);
148  * evt.put(std::move(WireDigitAssn), spill_name);
149  *
150  */
151  // MARK CreateAssn_01
152  template<class T, class U>
153  bool CreateAssn(art::Event &evt,
154  std::vector<T> const&a,
155  art::Ptr<U> const&b,
156  art::Assns<U,T> &assn,
157  std::string a_instance,
158  size_t index=UINT_MAX
159  );
160 
161  /**
162  * @brief Creates a single one-to-one association
163  * @tparam T type of the new object to associate
164  * @tparam U type of the object already in the data product or art::Ptr
165  * @param evt reference to the current event
166  * @param a vector of data products that are in, or will be put into, evt
167  * @param b art::Ptr to the (new) object to be associated to the one in a
168  * @param assn reference to association object where the new one will be put
169  * @param index index of the element in a to be associated with b (default: the last element)
170  * @return whether the operation was successful (can it ever fail??)
171  *
172  * The instance name of the product a will be in is assumed empty.
173  * Example of usage:
174  *
175  * // this is the original list of digits, thawed from the event
176  * art::Handle< std::vector<raw::RawDigit>> digitVecHandle;
177  * evt.getByLabel(DigitModuleLabel, digitVecHandle);
178  *
179  * // the collection of wires that will be written as data product
180  * std::unique_ptr<std::vector<recob::Wire>> wirecol(new std::vector<recob::Wire>);
181  * // ... and an association set
182  * std::unique_ptr<art::Assns<raw::RawDigit,recob::Wire>> WireDigitAssn
183  * (new art::Assns<raw::RawDigit,recob::Wire>);
184  *
185  * for(size_t iDigit = 0; iDigit < digitVecHandle->size(); ++iDigit) {
186  * // turn the digit into a art::Ptr:
187  * art::Ptr<raw::RawDigit> digit_ptr(digitVecHandle, iDigit);
188  *
189  * // store the wire in its final position in the data product;
190  * // the new wire is currently the last of the list
191  * wirecol->push_back(std::move(wire));
192  *
193  * // add an association between the last object in wirecol
194  * // (that we just inserted) and digit_ptr
195  * if (!util::CreateAssn(*this, evt, *wirecol, digit_ptr, *WireDigitAssn)) {
196  * throw art::Exception(art::errors::ProductRegistrationFailure)
197  * << "Can't associate wire #" << (wirecol->size() - 1)
198  * << " with raw digit #" << digit_ptr.key();
199  * } // if failed to add association
200  *
201  * } // for digits
202  *
203  * evt.put(std::move(wirecol));
204  * evt.put(std::move(WireDigitAssn));
205  *
206  */
207  // MARK CreateAssn_02
208  template<class T, class U>
209  inline bool CreateAssn(art::Event &evt,
210  std::vector<T> const&a,
211  art::Ptr<U> const&b,
212  art::Assns<U,T> &assn,
213  size_t index=UINT_MAX)
214  { return CreateAssn(evt, a, b, assn, std::string(), index); }
215 
216 
217  /**
218  * @brief Creates a single one-to-one association
219  * @tparam T type of one object to associate
220  * @tparam U type of the other object to associate
221  * @param evt reference to the current event
222  * @param a art::Ptr to the first object in the association
223  * @param b art::Ptr to the object to be associated to the one in a
224  * @param assn reference to association object where the new one will be put
225  * @return whether the operation was successful (can it ever fail??)
226  *
227  * This is the simplest way ever.
228  * Neither the event not the producer references are used.
229  */
230  // MARK CreateAssn_03
231  template<class T, class U>
232  bool CreateAssn(
233  art::Event & evt,
234  art::Ptr<T> const& a,
235  art::Ptr<U> const& b,
236  art::Assns<U,T> & assn
237  );
238 
239  /**
240  * @brief Creates a single one-to-many association
241  * @tparam T type of the new object to associate
242  * @tparam U type of the many objects already in the data product or art::Ptr
243  * @param evt reference to the current event
244  * @param a vector of data products that are in, or will be put into, evt
245  * @param b art::PtrVector to the (new) objects to be associated to the one in a
246  * @param assn reference to association object where the new one will be put
247  * @param index index of the element in a to be associated with all the ones
248  * in b (default: the last element)
249  * @return whether the operation was successful (can it ever fail??)
250  *
251  * A "one-to-many" association is actually a number of one-to-one
252  * associations. If you want to keep the information of the order of the many,
253  * you may have to use an association with a data member (the third template
254  * parameter that we pretent not to exist).
255  */
256  // MARK CreateAssn_04
257  template<class T, class U>
258  bool CreateAssn(
259  art::Event & evt,
260  std::vector<T> const& a,
261  art::PtrVector<U> const& b,
262  art::Assns<T,U> & assn,
263  size_t index = UINT_MAX
264  );
265 
266  /**
267  * @brief Creates a single one-to-many association
268  * @tparam T type of the new object to associate
269  * @tparam U type of the many objects already in the data product or art::Ptr
270  * @param evt reference to the current event
271  * @param a art::Ptr to the item to be associated with many
272  * @param b vector to art::Ptr to the (new) objects to be associated to a
273  * @param assn reference to association object where the new one will be put
274  * @return whether the operation was successful (can it ever fail??)
275  *
276  * A "one-to-many" association is actually a number of one-to-one
277  * associations. If you want to keep the information of the order of the many,
278  * you may have to use an association with a data member (the third template
279  * parameter that we pretent not to exist).
280  */
281  // method to create a 1 to many association, with the many being of type U
282  // index is the location in the input std::vector<T> of the object you wish to
283  // associate with the art::PtrVector<U>
284  // MARK CreateAssn_05
285  template<class T, class U>
286  bool CreateAssn(
287  art::Event & evt,
288  art::Ptr<T> const& a,
289  std::vector<art::Ptr<U>> const& b,
290  art::Assns<T,U> & assn
291  );
292 
293  /**
294  * @brief Creates a single one-to-many association
295  * @tparam T type of the new object to associate
296  * @tparam U type of the many objects already in the data product or art::Ptr
297  * @param evt reference to the current event
298  * @param a vector of data products that are in, or will be put into, evt
299  * @param b vector to art::Ptr to the (new) objects to be associated to the one in a
300  * @param assn reference to association object where the new one will be put
301  * @param index index of the element in a to be associated with all the ones
302  * in b (default: the last element)
303  * @return whether the operation was successful (can it ever fail??)
304  *
305  * A "one-to-many" association is actually a number of one-to-one
306  * associations. If you want to keep the information of the order of the many,
307  * you may have to use an association with a data member (the third template
308  * parameter that we pretent not to exist).
309  */
310  // MARK CreateAssn_06
311  template<class T, class U>
312  bool CreateAssn(
313  art::Event & evt,
314  std::vector<T> const& a,
315  std::vector<art::Ptr<U>> const& b,
316  art::Assns<T,U> & assn,
317  size_t index = UINT_MAX
318  );
319 
320  /**
321  * @brief Creates a single one-to-many association
322  * @tparam T type of the new object to associate
323  * @tparam U type of the many objects already in the data product or art::Ptr
324  * @param evt reference to the current event
325  * @param a vector of data products that are in, or will be put into, evt
326  * @param b vector of the (new) objects to be associated to the one in a
327  * @param assn reference to association object where the new one will be put
328  * @param startU index in b of the first element to be associated to the one in a
329  * @param endU index in b after the last element to be associated to the one in a
330  * @param index index of the element in a to be associated with all the ones
331  * in b (default: the last element)
332  * @return whether the operation was successful (can it ever fail??)
333  *
334  * Use this when the objects in b are not yet stored in the event and are in a
335  * std::vector collection instead.
336  *
337  * The method gets the product id for those as well as for the element in a.
338  * Also specify the range of entries to use from the std::vector collection of
339  * U objects.
340  *
341  * A "one-to-many" association is actually a number of one-to-one
342  * associations. If you want to keep the information of the order of the many,
343  * you may have to use an association with a data member (the third template
344  * parameter that we pretent not to exist).
345  */
346  // MARK CreateAssn_07
347  template<class T, class U>
348  bool CreateAssn(
349  art::Event & evt,
350  std::vector<T> const& a,
351  std::vector<U> const& b,
352  art::Assns<T,U> & assn,
353  size_t startU,
354  size_t endU,
355  size_t index = UINT_MAX
356  );
357 
358  /**
359  * @brief Creates a single one-to-many association
360  * @tparam T type of the new object to associate
361  * @tparam U type of the many objects already in the data product or art::Ptr
362  * @param evt reference to the current event
363  * @param a vector of data products that are in, or will be put into, evt
364  * @param b vector of the (new) objects to be associated to the one in a
365  * @param assn reference to association object where the new one will be put
366  * @param indices indices of the elements in b to be associated to the one in a
367  * @param index index of the element in a to be associated with all the ones
368  * in b (default: the last element)
369  * @return whether the operation was successful (can it ever fail??)
370  *
371  * Use this when the objects in b are not yet stored in the event and are in a
372  * std::vector collection instead.
373  *
374  * The method gets the product id for those as well as for the element in a.
375  * Also specify the entries to use from the std::vector collection of
376  * U objects.
377  *
378  * A "one-to-many" association is actually a number of one-to-one
379  * associations. If you want to keep the information of the order of the many,
380  * you may have to use an association with a data member (the third template
381  * parameter that we pretent not to exist).
382  */
383  // MARK CreateAssn_07a
384  template<class T, class U>
385  bool CreateAssn(
386  art::Event & evt,
387  std::vector<T> const& a,
388  std::vector<U> const& b,
389  art::Assns<T,U> & assn,
390  std::vector<size_t> const& indices,
391  size_t index = UINT_MAX
392  );
393 
394  /**
395  * @brief Creates a single one-to-many association
396  * @tparam T type of the new object to associate
397  * @tparam U type of the many objects already in the data product or art::Ptr
398  * @tparam Iter iterator to size_t-compatible elements
399  * @param evt reference to the current event
400  * @param assn reference to association object where the new one will be put
401  * @param first_index index of the object of type T to be associated to all
402  * the others
403  * @param from_second_index iterator pointing to the first of the indices
404  * of U type objects to be associated to the one of the first type
405  * @param to_second_index iterator pointing after the last of the indices
406  * of U type objects to be associated to the one of the first type
407  * @return whether the operation was successful (can it ever fail??)
408  *
409  * A "one-to-many" association is actually a number of one-to-one
410  * associations. If you want to keep the information of the order of the many,
411  * you may have to use an association with a data member (the third template
412  * parameter that we pretent not to exist).
413  *
414  * Use this if the objects that have to be associated to the one of type T are
415  * sparse, spread across a to-be-data-product, but you have a list of the
416  * indices in the data product of the elements to associate to the one of type
417  * T.
418  * In other words, given that you have a data product "a" of type
419  * `std::vector<T>` and a data product "b" of type `std::vector<U>`, this
420  * `method creates an association between `a[first_index]` and
421  * `b[*(from_second_index)], another between `a[first_index]` and
422  * `b[*(from_second_index + 1)]`, etc.
423  *
424  * The surprising concept here is that you don't need to specify neither of
425  * the collections of T or U elements. The data product is uniquely defined
426  * by its type, producer, process and product label.
427  * Here we assume that the type of the products are `std::vector<T>` and
428  * `std::vector<U>`, and that the products have empty product labels,
429  * and that the producer is prod for both of them.
430  */
431  // MARK CreateAssn_08
432  template <typename T, typename U, typename Iter>
433  bool CreateAssn(
434  art::Event & evt,
435  art::Assns<T,U> & assn,
436  size_t first_index,
437  Iter from_second_index,
438  Iter to_second_index
439  );
440 
441  //@{
442  /**
443  * @brief Creates a single one-to-one association with associated data
444  * @tparam T type of the new object to associate
445  * @tparam U type of the many objects already in the data product or art::Ptr
446  * @tparam D type of the "metadata" coupled to this pair association
447  * @param evt reference to the current event
448  * @param assn reference to association object where the new one will be put
449  * @param first_index index of the object of type T to be associated
450  * @param second_index index of the object of type U to be associated
451  * @param data "metadata" to be store in this association
452  * @return whether the operation was successful (can it ever fail??)
453  *
454  * Use this if you want some metadata to travel together with the association.
455  * An example may be the order of the second element within a list:
456  *
457  * size_t a_index = 2;
458  * std::vector<size_t> b_indices{ 6, 9, 18, 12 };
459  * for (size_t i = 0; i < b_indices.size(); ++i)
460  * CreateAssn(prod, evt, assn, a_index, b_index[i], i);
461  *
462  * In this way, the association between the element #2 of "a" (a vector that
463  * is not specified -- nor needed -- in this snippet of code) and the element
464  * #18 will be remembered as being the third (metadata value of 2).
465  * In this example metadata is of type `size_t` the association would be
466  * declared as `art::Assn<A, B, size_t>`.
467  * A FindMany query of that association might look like:
468  *
469  * art::Handle<std::vector<A>> a_list; // read this from the event
470  *
471  * art::FindMany<B, size_t> Query(a_list, event, ModuleLabel);
472  *
473  * // search for the last of the objects associated to the third element:
474  * size_t a_index = 2; // this means third element
475  *
476  * std::vector<size_t const*> const& metadata = Query.data(a_index);
477  * size_t largest_index = 0, last_item = 0;
478  * for (size_t iB = 0; iB < metadata.size(); ++iB) {
479  * if (largest_index >= *(metadata[iB])) continue;
480  * largest_index = *(metadata[iB]);
481  * last_item = iB;
482  * } // for iB
483  * B const& lastB = Query.at(last_item);
484  *
485  * In alternative, the elements and their metadata can be fetched
486  * simultaneously with:
487  *
488  * std::vector<art::Ptr<B>> const& Bs;
489  * std::vector<size_t const*> const& metadata;
490  *
491  * size_t a_index = 2; // this means third element
492  * size_t nMatches = Query.get(a_index, Bs, metadata);
493  *
494  */
495  // MARK CreateAssnD_01
496  // MARK CreateAssnD_01a
497  template <typename T, typename U, typename D>
498  bool CreateAssnD(
499  art::Event & evt,
500  art::Assns<T,U,D> & assn,
501  size_t first_index,
502  size_t second_index,
504  );
505  // MARK CreateAssnD_01b
506  template <typename T, typename U, typename D>
507  bool CreateAssnD(
508  art::Event & evt,
509  art::Assns<T,U,D> & assn,
510  size_t first_index,
511  size_t second_index,
512  typename art::Assns<T,U,D>::data_t const& data
513  );
514  //@}
515 
516 
517  // method to return all objects of type U that are not associated to
518  // objects of type T. Label is the module label that would have produced
519  // the associations and likely the objects of type T
520  // this method assumes there is a one to many relationship between T and U
521  // for example if you want to get all recob::Hits
522  // that are not associated to recob::Clusters
523  // std::vector<const recob::Hit*> hits = FindUNotAssociatedToU<recob::Cluster>(art::Handle<recob::Hit>, ...);
524  template<class T, class U>
525  std::vector<const U*>
527  art::Event const& evt,
528  std::string const& label);
529 
530  // method to return all objects of type U that are not associated to
531  // objects of type T. Label is the module label that would have produced
532  // the associations and likely the objects of type T
533  // this method assumes there is a one to many relationship between T and U
534  // for example if you want to get all recob::Hits
535  // that are not associated to recob::Clusters
536  // std::vector< art::Ptr<recob::Hit> > hits = FindUNotAssociatedToTP<recob::Cluster>(art::Handle<recob::Hit>, ...);
537  template<class T, class U>
538  std::vector< art::Ptr<U> >
540  art::Event const& evt,
541  std::string const& label);
542 
543  // Methods make getting simple ART-independent association information.
544  // --- GetAssociatedVectorOneI takes in a handle to an association, and a handle to a product on the event.
545  // The ouput is a vector of with the same number of entries as the handle to the product, containing an index
546  // to the location of one associated product in that product's collection.
547  // --- GetAssociatedVectorOneP takes in a handle to an association, and a handle to a product on the event.
548  // The ouput is a vector of with the same number of entries as the handle to the product, containing a pointer
549  // to one associated product.
550  // --- GetAssociatedVectorManyI takes in a handle to an association, and a handle to a product on the event.
551  // The ouput is a vector of with the same number of entries as the handle to the product, containing a vector
552  // of indices that give the locations of all associated products in those products' collection.
553  // --- GetAssociatedVectorManyP takes in a handle to an association, and a handle to a product on the event.
554  // The ouput is a vector of with the same number of entries as the handle to the product, containing a vector
555  // of pointers to all associated products.
556 
557  template<class T,class U>
558  std::vector<size_t>
560  art::Handle< std::vector<T> > index_p);
561  template<class T,class U>
562  std::vector<const U*>
564  art::Handle< std::vector<T> > index_p);
565 
566  template<class T,class U>
567  std::vector< std::vector<size_t> >
569  art::Handle< std::vector<T> > index_p);
570  template<class T,class U>
571  std::vector< std::vector<const U*> >
573  art::Handle< std::vector<T> > index_p);
574 
575 
576 }// end namespace
577 
578 //----------------------------------------------------------------------
579 // MARK CreateAssn_01
580 template<class T, class U>
582  art::Event & evt,
583  std::vector<T> const& a,
584  art::Ptr<U> const& b,
585  art::Assns<U,T> & assn,
586  std::string a_instance,
587  size_t index /* = UINT_MAX */
588  )
589 {
590  if (index == UINT_MAX) index = a.size()-1;
591 
592  try{
593  assn.addSingle(b, art::PtrMaker<T>{evt, a_instance}(index));
594  return true;
595  }
596  catch(cet::exception &e){
597  mf::LogWarning("AssociationUtil")
598  << "unable to create requested art:Assns, exception thrown: " << e;
599  return false;
600  }
601 
602 } // util::CreateAssn() [01]
603 
604 
605 //----------------------------------------------------------------------
606 // MARK CreateAssn_03
607 template<class T, class U>
609  art::Event &,
610  art::Ptr<T> const& a,
611  art::Ptr<U> const& b,
612  art::Assns<U,T> & assn
613 ) {
614 
615  try{
616  assn.addSingle(b, a);
617  }
618  catch(cet::exception &e){
619  mf::LogWarning("AssociationUtil")
620  << "unable to create requested art:Assns, exception thrown: " << e;
621  return false;
622  }
623 
624  return true;
625 } // util::CreateAssn() [03]
626 
627 
628 //----------------------------------------------------------------------
629 // MARK CreateAssn_04
630 template<class T, class U>
632  art::Event & evt,
633  std::vector<T> const& a,
634  art::PtrVector<U> const& b,
635  art::Assns<T,U> & assn,
636  size_t index /* = UINT_MAX */
637 ) {
638  if(index == UINT_MAX) index = a.size() - 1;
639 
640  try{
641  auto const aptr = art::PtrMaker<T>{evt}(index);
642  for(art::Ptr<U> const& b_item: b) assn.addSingle(aptr, b_item);
643  }
644  catch(cet::exception &e){
645  mf::LogWarning("AssociationUtil")
646  << "unable to create requested art:Assns, exception thrown: " << e;
647  return false;
648  }
649 
650  return true;
651 } // util::CreateAssn() [04]
652 
653 //----------------------------------------------------------------------
654 // MARK CreateAssn_05
655 template<class T, class U>
657  art::Event &,
658  art::Ptr<T> const& a,
659  std::vector<art::Ptr<U>> const& b,
660  art::Assns<T,U> & assn
661 ) {
662 
663  try{
664  for (art::Ptr<U> const& b_item: b) assn.addSingle(a, b_item);
665  }
666  catch(cet::exception const& e){
667  mf::LogWarning("AssociationUtil")
668  << "unable to create requested art:Assns, exception thrown: " << e;
669  return false;
670  }
671 
672  return true;
673 } // util::CreateAssn() [05]
674 
675 //----------------------------------------------------------------------
676 // MARK CreateAssn_06
677 template<class T, class U>
679  art::Event & evt,
680  std::vector<T> const& a,
681  std::vector<art::Ptr<U>> const& b,
682  art::Assns<T,U> & assn,
683  size_t index /* = UINT_MAX */
684 ) {
685 
686  if (index == UINT_MAX) index = a.size() - 1;
687 
688  try{
689  auto const aptr = art::PtrMaker<T>{evt}(index);
690  for (art::Ptr<U> const& b_item: b) assn.addSingle(aptr, b_item);
691  }
692  catch(cet::exception &e){
693  mf::LogWarning("AssociationUtil")
694  << "unable to create requested art:Assns, exception thrown: " << e;
695  return false;
696  }
697 
698  return true;
699 } // util::CreateAssn() [06]
700 
701 //----------------------------------------------------------------------
702 // MARK CreateAssn_07
703 template<class T, class U>
705  art::Event & evt,
706  std::vector<T> const& a,
707  std::vector<U> const& /* b */,
708  art::Assns<T,U> & assn,
709  size_t startU,
710  size_t endU,
711  size_t index /* = UINT_MAX */
712 ) {
713 
714  if(index == UINT_MAX) index = a.size() - 1;
715 
716  try{
717  auto const aptr = art::PtrMaker<T>{evt}(index);
718  art::PtrMaker<U> const make_bptr{evt};
719  for(size_t i = startU; i < endU; ++i){
720  assn.addSingle(aptr, make_bptr(i));
721  }
722  }
723  catch(cet::exception &e){
724  mf::LogWarning("AssociationUtil")
725  << "unable to create requested art:Assns, exception thrown: " << e;
726  return false;
727  }
728 
729  return true;
730 } // util::CreateAssn() [07]
731 
732 //----------------------------------------------------------------------
733 // MARK CreateAssn_07a
734 template<class T, class U>
736  art::Event & evt,
737  std::vector<T> const& a,
738  std::vector<U> const& /* b */,
739  art::Assns<T,U> & assn,
740  std::vector<size_t> const& indices,
741  size_t index /* = UINT_MAX */
742 ) {
743 
744  if(index == UINT_MAX) index = a.size() - 1;
745 
746  try{
747  auto const aptr = art::PtrMaker<T>{evt}(index);
748  art::PtrMaker<U> const make_bptr{evt};
749  for(size_t index: indices){
750  assn.addSingle(aptr, make_bptr(index));
751  }
752  }
753  catch(cet::exception &e){
754  mf::LogWarning("AssociationUtil")
755  << "unable to create requested art:Assns, exception thrown: " << e;
756  return false;
757  }
758 
759  return true;
760 } // util::CreateAssn() [07a]
761 
762 //----------------------------------------------------------------------
763 // MARK CreateAssn_08
764 template <typename T, typename U, typename Iter>
766  art::Event & evt,
767  art::Assns<T,U> & assn,
768  size_t first_index,
769  Iter from_second_index,
770  Iter to_second_index
771 ) {
772 
773  try{
774  // we declare here that we want to associate the element first_index of the
775  // (only) data product of type std::vector<T> with other objects.
776  // This is the pointer to that element:
777  auto const first_ptr = art::PtrMaker<T>{evt}(first_index);
778 
779  // we are going to associate that element in a with a number of elements
780  // of the only data product of type std::vector<U>
781  art::PtrMaker<U> const make_second_ptr{evt};
782  for (; from_second_index != to_second_index; ++from_second_index) {
783  assn.addSingle(first_ptr, make_second_ptr(*from_second_index));
784  } // while
785  }
786  catch(cet::exception &e){
787  mf::LogWarning("AssociationUtil")
788  << "unable to create requested art:Assns, exception thrown: " << e;
789  return false;
790  }
791 
792  return true;
793 } // util::CreateAssn() [08]
794 
795 
796 //----------------------------------------------------------------------
797 // MARK CreateAssnD_01a
798 template <typename T, typename U, typename D>
800  art::Event & evt,
801  art::Assns<T,U,D> & assn,
802  size_t first_index,
803  size_t second_index,
805 ) {
806 
807  try{
808  // we declare here that we want to associate the element first_index of the
809  // (only) data product of type std::vector<T> with the other object
810  auto const first_ptr = art::PtrMaker<T>{evt}(first_index);
811 
812  // the same to associate the element second_index of the (only)
813  // data product of type std::vector<U> with the first object.
814  auto const second_ptr = art::PtrMaker<U>{evt}(second_index);
815 
816  assn.addSingle(first_ptr, second_ptr, std::move(data));
817  }
818  catch(cet::exception &e){
819  mf::LogWarning("AssociationUtil")
820  << "unable to create requested art:Assns, exception thrown: " << e;
821  return false;
822  }
823 
824  return true;
825 } // util::CreateAssnD() [01a]
826 
827 template <typename T, typename U, typename D>
829  art::Event & evt,
830  art::Assns<T,U,D> & assn,
831  size_t first_index,
832  size_t second_index,
833  typename art::Assns<T,U,D>::data_t const& data
834 ) {
835 
836  try{
837  // we declare here that we want to associate the element first_index of the
838  // (only) data product of type std::vector<T> with the other object
839  auto const first_ptr = art::PtrMaker<T>{evt}(first_index);
840 
841  // the same to associate the element second_index of the (only)
842  // data product of type std::vector<U> with the first object.
843  auto const second_ptr = art::PtrMaker<U>{evt}(second_index);
844 
845  assn.addSingle(first_ptr, second_ptr, data);
846  }
847  catch(cet::exception &e){
848  mf::LogWarning("AssociationUtil")
849  << "unable to create requested art:Assns, exception thrown: " << e;
850  return false;
851  }
852 
853  return true;
854 } // util::CreateAssnD() [01b]
855 
856 //----------------------------------------------------------------------
857 template<class T, class U>
858 inline std::vector<const U*>
860  art::Event const& evt,
861  std::string const& label)
862 {
863  // Do a FindOne for type T for each object of type U
864  // If the FindOne returns an invalid maybe ref, add the pointer
865  // of object type U to the return vector
866 
867  std::vector<const U*> notAssociated;
868 
869  art::FindOne<T> const fa(b, evt, label);
870 
871  for(size_t u = 0; u < b->size(); ++u){
872  cet::maybe_ref<T const> t(fa.at(u));
873  if( !t.isValid() ){
874  art::Ptr<U> ptr(b, u);
875  notAssociated.push_back(ptr.get());
876  }
877  }
878 
879  return notAssociated;
880 }
881 
882 //----------------------------------------------------------------------
883 template<class T, class U>
884 inline std::vector< art::Ptr<U> >
886  art::Event const& evt,
887  std::string const& label)
888 {
889  // Do a FindOneP for type T for each object of type U
890  // If the FindOne returns an invalid maybe ref, add the pointer
891  // of object type U to the return vector
892 
893  std::vector< art::Ptr<U> > notAssociated;
894 
895  art::FindOneP<T> const fa(b, evt, label);
896 
897  for(size_t u = 0; u < b->size(); ++u){
898  cet::maybe_ref<T const> t(fa.at(u));
899  if( !t.isValid() ){
900  notAssociated.emplace_back(b, u);
901  }
902  }
903 
904  return notAssociated;
905 }
906 
907 
908 
909 template<class T,class U>
910 inline std::vector<size_t>
912  art::Handle< std::vector<T> > index_p)
913 {
914  std::vector<size_t> associated_index(index_p->size());
915  for(auto const& pair : *h)
916  associated_index.at(pair.first.key()) = pair.second.key();
917  return associated_index;
918 }
919 
920 template<class T,class U>
921 inline std::vector<const U*>
923  art::Handle< std::vector<T> > index_p)
924 {
925  std::vector<const U*> associated_pointer(index_p->size());
926  for(auto const& pair : *h)
927  associated_pointer.at(pair.first.key()) = &(*(pair.second));
928  return associated_pointer;
929 }
930 
931 template<class T,class U>
932 inline std::vector< std::vector<size_t> >
934  art::Handle< std::vector<T> > index_p)
935 {
936  std::vector< std::vector<size_t> > associated_indices(index_p->size());
937  for(auto const& pair : *h)
938  associated_indices.at(pair.first.key()).push_back(pair.second.key());
939  return associated_indices;
940 }
941 
942 template<class T,class U>
943 inline std::vector< std::vector<const U*> >
945  art::Handle< std::vector<T> > index_p)
946 {
947  std::vector< std::vector<const U*> > associated_pointers(index_p->size());
948  for(auto const& pair : *h)
949  associated_pointers.at(pair.first.key()).push_back( &(*(pair.second)) );
950  return associated_pointers;
951 }
952 
953 //--------------------------------------------------------------------
954 // Functions to support unnecessary leading producer argument
955 //
956 // These are legacy function signatures that accept a reference to a
957 // producer module. Although the signatures are still supported,
958 // they should not be encouraged. They, along with the other
959 // CreateAssn(D) functions above, will be marked as [[deprecated]]
960 // once art supports Assns::addMany (expected in art 3.04).
961 //--------------------------------------------------------------------
962 
964 
965 namespace util {
966  template <typename Producer, typename... Args>
967  std::enable_if_t<std::is_base_of_v<art::EDProducer, Producer>, bool>
968  CreateAssn(Producer const&, Args&&... args) {
969  return CreateAssn(std::forward<Args>(args)...);
970  }
971 
972  template <typename Producer, typename... Args>
973  std::enable_if_t<std::is_base_of_v<art::EDProducer, Producer>, bool>
974  CreateAssnD(Producer const&, Args&&... args) {
975  return CreateAssnD(std::forward<Args>(args)...);
976  }
977 }
978 
979 #endif //ASSOCIATIONUTIL_H
Namespace for general, non-LArSoft-specific utilities.
std::string string
Definition: nybbler.cc:12
struct vector vector
std::vector< const U * > GetAssociatedVectorOneP(art::Handle< art::Assns< T, U > > h, art::Handle< std::vector< T > > index_p)
static QCString args
Definition: declinfo.cpp:674
fInnerVessel push_back(Point(-578.400000, 0.000000, 0.000000))
const double e
std::vector< size_t > GetAssociatedVectorOneI(art::Handle< art::Assns< T, U > > h, art::Handle< std::vector< T > > index_p)
const double a
bool CreateAssnD(PRODUCER const &prod, art::Event &evt, art::Assns< T, U, D > &assn, size_t first_index, size_t second_index, typename art::Assns< T, U, D >::data_t &&data)
Creates a single one-to-one association with associated data.
def move(depos, offset)
Definition: depos.py:107
constexpr std::array< std::size_t, geo::vect::dimension< Vector >)> indices()
Returns a sequence of indices valid for a vector of the specified type.
bool CreateAssn(PRODUCER const &prod, art::Event &evt, std::vector< T > const &a, art::Ptr< U > const &b, art::Assns< U, T > &assn, std::string a_instance, size_t indx=UINT_MAX)
Creates a single one-to-one association.
std::vector< art::Ptr< U > > FindUNotAssociatedToTP(art::Handle< U > b, art::Event const &evt, std::string const &label)
std::vector< std::vector< size_t > > GetAssociatedVectorManyI(art::Handle< art::Assns< T, U > > h, art::Handle< std::vector< T > > index_p)
void addSingle(Ptr< left_t > const &left, Ptr< right_t > const &right, data_t const &data)
Definition: Assns.h:546
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< const U * > FindUNotAssociatedToT(art::Handle< U > b, art::Event const &evt, std::string const &label)
static bool * b
Definition: config.cpp:1043
TCEvent evt
Definition: DataStructs.cxx:7
T const * get() const
Definition: Ptr.h:149
Definition: fwd.h:31
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
std::vector< std::vector< const U * > > GetAssociatedVectorManyP(art::Handle< art::Assns< T, U > > h, art::Handle< std::vector< T > > index_p)