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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, art::Event&, art::Assns<T,U>&, size_t, size_t, typename art::Assns<T,U,D>::data_t const&) @endcode,
38  * @code CreateAssnD(PRODUCER const&, 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(PRODUCER const &, 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(PRODUCER const&, art::Event&, std::vector<T> const&, art::Ptr<U> const&, art::Assns<U,T> &, size_t)
54  * art pointer | art pointer | | CreateAssn(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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(PRODUCER const&, 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 <vector>
77 #include <string>
78 #include <utility> // std::move()
79 
80 // framework libraries
88 #include "canvas/Persistency/Common/FindMany.h"
89 #include "canvas/Persistency/Common/FindManyP.h"
90 #include "canvas/Persistency/Common/FindOneP.h"
91 #include "canvas/Persistency/Common/FindOne.h"
92 
93 namespace util {
94 
95  // see https://cdcvs.fnal.gov/redmine/projects/art/wiki/Inter-Product_References
96  // for information about using art::Assns
97 
98  /**
99  * @brief Creates a single one-to-one association
100  * @tparam T type of the new object to associate
101  * @tparam U type of the object already in the data product or art::Ptr
102  * @param prod reference to the producer that will write the vector a
103  * @param evt reference to the current event
104  * @param a vector of data products that are in, or will be put into, evt
105  * @param b art::Ptr to the (new) object to be associated to the one in a
106  * @param assn reference to association object where the new one will be put
107  * @param a_instance name of the instance that will be used for a in evt
108  * @param indx index of the element in a to be associated with b (default: the last element)
109  * @return whether the operation was successful (can it ever fail??)
110  *
111  * As example of usage: create a wire/raw digit association.
112  * This code should live in the art::EDProduce::produce() method.
113  * The raw::RawDigit product was created already by a DigitModuleLabel module.
114  * The code is supposed to produce one recob::Wire for each existing
115  * raw::RawDigit, and contextually associate the new wire to the source digit.
116  * We are also assuming that there might be different RawDigit sets produced
117  * by the same producer: we identify the one we care of by the string
118  * spill_name and we create wires and associations with the same label
119  * for convenience.
120  *
121  * // this is the original list of digits, thawed from the event
122  * art::InputTag itag(DigitModuleLabel, spill_name);
123  * auto digitVecHandle = evt.getHandle< std::vector<raw::RawDigit>>(itag);
124  * // the collection of wires that will be written as data product
125  * std::unique_ptr<std::vector<recob::Wire>> wirecol(new std::vector<recob::Wire>);
126  * // ... and an association set
127  * std::unique_ptr<art::Assns<raw::RawDigit,recob::Wire>> WireDigitAssn
128  * (new art::Assns<raw::RawDigit,recob::Wire>);
129  *
130  * for(size_t iDigit = 0; iDigit < digitVecHandle->size(); ++iDigit) {
131  * // turn the digit into a art::Ptr:
132  * art::Ptr<raw::RawDigit> digit_ptr(digitVecHandle, iDigit);
133  *
134  * // store the wire in its final position in the data product;
135  * // the new wire is currently the last of the list
136  * wirecol->push_back(std::move(wire));
137  *
138  * // add an association between the last object in wirecol
139  * // (that we just inserted) and digit_ptr
140  * if (!util::CreateAssn(*this, evt, *wirecol, digit_ptr, *WireDigitAssn, spill_name)) {
141  * throw art::Exception(art::errors::ProductRegistrationFailure)
142  * << "Can't associate wire #" << (wirecol->size() - 1)
143  * << " with raw digit #" << digit_ptr.key();
144  * } // if failed to add association
145  *
146  * } // for digits
147  *
148  * evt.put(std::move(wirecol), spill_name);
149  * evt.put(std::move(WireDigitAssn), spill_name);
150  *
151  */
152  // MARK CreateAssn_01
153  template<class PRODUCER, class T, class U>
154  bool CreateAssn(PRODUCER const& prod,
155  art::Event &evt,
156  std::vector<T> const&a,
157  art::Ptr<U> const&b,
158  art::Assns<U,T> &assn,
159  std::string a_instance,
160  size_t indx=UINT_MAX
161  );
162 
163  /**
164  * @brief Creates a single one-to-one association
165  * @tparam T type of the new object to associate
166  * @tparam U type of the object already in the data product or art::Ptr
167  * @param prod reference to the producer that will write the vector a
168  * @param evt reference to the current event
169  * @param a vector of data products that are in, or will be put into, evt
170  * @param b art::Ptr to the (new) object to be associated to the one in a
171  * @param assn reference to association object where the new one will be put
172  * @param indx index of the element in a to be associated with b (default: the last element)
173  * @return whether the operation was successful (can it ever fail??)
174  *
175  * The instance name of the product a will be in is assumed empty.
176  * Example of usage:
177  *
178  * // this is the original list of digits, thawed from the event
179  * auto digitVecHandle = evt.getHandle< std::vector<raw::RawDigit>>(DigitModuleLabel);
180  *
181  * // the collection of wires that will be written as data product
182  * std::unique_ptr<std::vector<recob::Wire>> wirecol(new std::vector<recob::Wire>);
183  * // ... and an association set
184  * std::unique_ptr<art::Assns<raw::RawDigit,recob::Wire>> WireDigitAssn
185  * (new art::Assns<raw::RawDigit,recob::Wire>);
186  *
187  * for(size_t iDigit = 0; iDigit < digitVecHandle->size(); ++iDigit) {
188  * // turn the digit into a art::Ptr:
189  * art::Ptr<raw::RawDigit> digit_ptr(digitVecHandle, iDigit);
190  *
191  * // store the wire in its final position in the data product;
192  * // the new wire is currently the last of the list
193  * wirecol->push_back(std::move(wire));
194  *
195  * // add an association between the last object in wirecol
196  * // (that we just inserted) and digit_ptr
197  * if (!util::CreateAssn(*this, evt, *wirecol, digit_ptr, *WireDigitAssn)) {
198  * throw art::Exception(art::errors::ProductRegistrationFailure)
199  * << "Can't associate wire #" << (wirecol->size() - 1)
200  * << " with raw digit #" << digit_ptr.key();
201  * } // if failed to add association
202  *
203  * } // for digits
204  *
205  * evt.put(std::move(wirecol));
206  * evt.put(std::move(WireDigitAssn));
207  *
208  */
209  // MARK CreateAssn_02
210  template<class PRODUCER, class T, class U>
211  inline bool CreateAssn(PRODUCER const& prod,
212  art::Event &evt,
213  std::vector<T> const&a,
214  art::Ptr<U> const&b,
215  art::Assns<U,T> &assn,
216  size_t indx=UINT_MAX)
217  { return CreateAssn(prod, evt, a, b, assn, std::string(), indx); }
218 
219 
220  /**
221  * @brief Creates a single one-to-one association
222  * @tparam T type of one object to associate
223  * @tparam U type of the other object to associate
224  * @param prod reference to the producer that will write the vector a
225  * @param evt reference to the current event
226  * @param a art::Ptr to the first object in the association
227  * @param b art::Ptr to the object to be associated to the one in a
228  * @param assn reference to association object where the new one will be put
229  * @return whether the operation was successful (can it ever fail??)
230  *
231  * This is the simplest way ever.
232  * Neither the event not the producer references are used.
233  */
234  // MARK CreateAssn_03
235  template<class PRODUCER, class T, class U>
236  bool CreateAssn(
237  PRODUCER const& prod,
238  art::Event & evt,
239  art::Ptr<T> const& a,
240  art::Ptr<U> const& b,
241  art::Assns<U,T> & assn
242  );
243 
244  /**
245  * @brief Creates a single one-to-many association
246  * @tparam T type of the new object to associate
247  * @tparam U type of the many objects already in the data product or art::Ptr
248  * @param prod reference to the producer that will write the vector a
249  * @param evt reference to the current event
250  * @param a vector of data products that are in, or will be put into, evt
251  * @param b art::PtrVector to the (new) objects to be associated to the one in a
252  * @param assn reference to association object where the new one will be put
253  * @param indx index of the element in a to be associated with all the ones
254  * in b (default: the last element)
255  * @return whether the operation was successful (can it ever fail??)
256  *
257  * A "one-to-many" association is actually a number of one-to-one
258  * associations. If you want to keep the information of the order of the many,
259  * you may have to use an association with a data member (the third template
260  * parameter that we pretent not to exist).
261  */
262  // MARK CreateAssn_04
263  template<class PRODUCER, class T, class U>
264  bool CreateAssn(
265  PRODUCER const& prod,
266  art::Event & evt,
267  std::vector<T> const& a,
268  art::PtrVector<U> const& b,
269  art::Assns<T,U> & assn,
270  size_t indx = UINT_MAX
271  );
272 
273  /**
274  * @brief Creates a single one-to-many association
275  * @tparam T type of the new object to associate
276  * @tparam U type of the many objects already in the data product or art::Ptr
277  * @param prod reference to the producer that will write the vector a
278  * @param evt reference to the current event
279  * @param a art::Ptr to the item to be associated with many
280  * @param b vector to art::Ptr to the (new) objects to be associated to a
281  * @param assn reference to association object where the new one will be put
282  * @return whether the operation was successful (can it ever fail??)
283  *
284  * A "one-to-many" association is actually a number of one-to-one
285  * associations. If you want to keep the information of the order of the many,
286  * you may have to use an association with a data member (the third template
287  * parameter that we pretent not to exist).
288  */
289  // method to create a 1 to many association, with the many being of type U
290  // indx is the location in the input std::vector<T> of the object you wish to
291  // associate with the art::PtrVector<U>
292  // MARK CreateAssn_05
293  template<class PRODUCER, class T, class U>
294  bool CreateAssn(
295  PRODUCER const& prod,
296  art::Event & evt,
297  art::Ptr<T> const& a,
298  std::vector<art::Ptr<U>> const& b,
299  art::Assns<T,U> & assn
300  );
301 
302  /**
303  * @brief Creates a single one-to-many association
304  * @tparam T type of the new object to associate
305  * @tparam U type of the many objects already in the data product or art::Ptr
306  * @param prod reference to the producer that will write the vector a
307  * @param evt reference to the current event
308  * @param a vector of data products that are in, or will be put into, evt
309  * @param b vector to art::Ptr to the (new) objects to be associated to the one in a
310  * @param assn reference to association object where the new one will be put
311  * @param indx index of the element in a to be associated with all the ones
312  * in b (default: the last element)
313  * @return whether the operation was successful (can it ever fail??)
314  *
315  * A "one-to-many" association is actually a number of one-to-one
316  * associations. If you want to keep the information of the order of the many,
317  * you may have to use an association with a data member (the third template
318  * parameter that we pretent not to exist).
319  */
320  // MARK CreateAssn_06
321  template<class PRODUCER, class T, class U>
322  bool CreateAssn(
323  PRODUCER const& prod,
324  art::Event & evt,
325  std::vector<T> const& a,
326  std::vector<art::Ptr<U>> const& b,
327  art::Assns<T,U> & assn,
328  size_t indx = UINT_MAX
329  );
330 
331  /**
332  * @brief Creates a single one-to-many association
333  * @tparam T type of the new object to associate
334  * @tparam U type of the many objects already in the data product or art::Ptr
335  * @param prod reference to the producer that will write the vector a
336  * @param evt reference to the current event
337  * @param a vector of data products that are in, or will be put into, evt
338  * @param b vector of the (new) objects to be associated to the one in a
339  * @param assn reference to association object where the new one will be put
340  * @param startU index in b of the first element to be associated to the one in a
341  * @param endU index in b after the last element to be associated to the one in a
342  * @param indx index of the element in a to be associated with all the ones
343  * in b (default: the last element)
344  * @return whether the operation was successful (can it ever fail??)
345  *
346  * Use this when the objects in b are not yet stored in the event and are in a
347  * std::vector collection instead.
348  *
349  * The method gets the product id for those as well as for the element in a.
350  * Also specify the range of entries to use from the std::vector collection of
351  * U objects.
352  *
353  * A "one-to-many" association is actually a number of one-to-one
354  * associations. If you want to keep the information of the order of the many,
355  * you may have to use an association with a data member (the third template
356  * parameter that we pretent not to exist).
357  */
358  // MARK CreateAssn_07
359  template<class PRODUCER, class T, class U>
360  bool CreateAssn(
361  PRODUCER const& prod,
362  art::Event & evt,
363  std::vector<T> const& a,
364  std::vector<U> const& b,
365  art::Assns<T,U> & assn,
366  size_t startU,
367  size_t endU,
368  size_t indx = UINT_MAX
369  );
370 
371  /**
372  * @brief Creates a single one-to-many association
373  * @tparam T type of the new object to associate
374  * @tparam U type of the many objects already in the data product or art::Ptr
375  * @param prod reference to the producer that will write the vector a
376  * @param evt reference to the current event
377  * @param a vector of data products that are in, or will be put into, evt
378  * @param b vector of the (new) objects to be associated to the one in a
379  * @param assn reference to association object where the new one will be put
380  * @param indices indices of the elements in b to be associated to the one in a
381  * @param indx index of the element in a to be associated with all the ones
382  * in b (default: the last element)
383  * @return whether the operation was successful (can it ever fail??)
384  *
385  * Use this when the objects in b are not yet stored in the event and are in a
386  * std::vector collection instead.
387  *
388  * The method gets the product id for those as well as for the element in a.
389  * Also specify the entries to use from the std::vector collection of
390  * U objects.
391  *
392  * A "one-to-many" association is actually a number of one-to-one
393  * associations. If you want to keep the information of the order of the many,
394  * you may have to use an association with a data member (the third template
395  * parameter that we pretent not to exist).
396  */
397  // MARK CreateAssn_07a
398  template<class PRODUCER, class T, class U>
399  bool CreateAssn(
400  PRODUCER const& prod,
401  art::Event & evt,
402  std::vector<T> const& a,
403  std::vector<U> const& b,
404  art::Assns<T,U> & assn,
405  std::vector<size_t> const& indices,
406  size_t indx = UINT_MAX
407  );
408 
409  /**
410  * @brief Creates a single one-to-many association
411  * @tparam T type of the new object to associate
412  * @tparam U type of the many objects already in the data product or art::Ptr
413  * @tparam Iter iterator to size_t-compatible elements
414  * @param prod reference to the producer that will write the vector a
415  * @param evt reference to the current event
416  * @param assn reference to association object where the new one will be put
417  * @param first_index index of the object of type T to be associated to all
418  * the others
419  * @param from_second_index iterator pointing to the first of the indices
420  * of U type objects to be associated to the one of the first type
421  * @param to_second_index iterator pointing after the last of the indices
422  * of U type objects to be associated to the one of the first type
423  * @return whether the operation was successful (can it ever fail??)
424  *
425  * A "one-to-many" association is actually a number of one-to-one
426  * associations. If you want to keep the information of the order of the many,
427  * you may have to use an association with a data member (the third template
428  * parameter that we pretent not to exist).
429  *
430  * Use this if the objects that have to be associated to the one of type T are
431  * sparse, spread across a to-be-data-product, but you have a list of the
432  * indices in the data product of the elements to associate to the one of type
433  * T.
434  * In other words, given that you have a data product "a" of type
435  * `std::vector<T>` and a data product "b" of type `std::vector<U>`, this
436  * `method creates an association between `a[first_index]` and
437  * `b[*(from_second_index)], another between `a[first_index]` and
438  * `b[*(from_second_index + 1)]`, etc.
439  *
440  * The surprising concept here is that you don't need to specify neither of
441  * the collections of T or U elements. The data product is uniquely defined
442  * by its type, producer, process and product label.
443  * Here we assume that the type of the products are `std::vector<T>` and
444  * `std::vector<U>`, and that the products have empty product labels,
445  * and that the producer is prod for both of them.
446  */
447  // MARK CreateAssn_08
448  template <typename PRODUCER, typename T, typename U, typename Iter>
449  bool CreateAssn(
450  PRODUCER const& prod,
451  art::Event & evt,
452  art::Assns<T,U> & assn,
453  size_t first_index,
454  Iter from_second_index,
455  Iter to_second_index
456  );
457 
458  //@{
459  /**
460  * @brief Creates a single one-to-one association with associated data
461  * @tparam T type of the new object to associate
462  * @tparam U type of the many objects already in the data product or art::Ptr
463  * @tparam D type of the "metadata" coupled to this pair association
464  * @param prod reference to the producer that will write the vector a
465  * @param evt reference to the current event
466  * @param assn reference to association object where the new one will be put
467  * @param first_index index of the object of type T to be associated
468  * @param second_index index of the object of type U to be associated
469  * @param data "metadata" to be store in this association
470  * @return whether the operation was successful (can it ever fail??)
471  *
472  * Use this if you want some metadata to travel together with the association.
473  * An example may be the order of the second element within a list:
474  *
475  * size_t a_index = 2;
476  * std::vector<size_t> b_indices{ 6, 9, 18, 12 };
477  * for (size_t i = 0; i < b_indices.size(); ++i)
478  * CreateAssn(prod, evt, assn, a_index, b_index[i], i);
479  *
480  * In this way, the association between the element #2 of "a" (a vector that
481  * is not specified -- nor needed -- in this snippet of code) and the element
482  * #18 will be remembered as being the third (metadata value of 2).
483  * In this example metadata is of type `size_t` the association would be
484  * declared as `art::Assn<A, B, size_t>`.
485  * A FindMany query of that association might look like:
486  *
487  * art::Handle<std::vector<A>> a_list; // read this from the event
488  *
489  * art::FindMany<B, size_t> Query(a_list, event, ModuleLabel);
490  *
491  * // search for the last of the objects associated to the third element:
492  * size_t a_index = 2; // this means third element
493  *
494  * std::vector<size_t const*> const& metadata = Query.data(a_index);
495  * size_t largest_index = 0, last_item = 0;
496  * for (size_t iB = 0; iB < metadata.size(); ++iB) {
497  * if (largest_index >= *(metadata[iB])) continue;
498  * largest_index = *(metadata[iB]);
499  * last_item = iB;
500  * } // for iB
501  * B const& lastB = Query.at(last_item);
502  *
503  * In alternative, the elements and their metadata can be fetched
504  * simultaneously with:
505  *
506  * std::vector<art::Ptr<B>> const& Bs;
507  * std::vector<size_t const*> const& metadata;
508  *
509  * size_t a_index = 2; // this means third element
510  * size_t nMatches = Query.get(a_index, Bs, metadata);
511  *
512  */
513  // MARK CreateAssnD_01
514  // MARK CreateAssnD_01a
515  template <typename PRODUCER, typename T, typename U, typename D>
516  bool CreateAssnD(
517  PRODUCER const& prod,
518  art::Event & evt,
519  art::Assns<T,U,D> & assn,
520  size_t first_index,
521  size_t second_index,
523  );
524  // MARK CreateAssnD_01b
525  template <typename PRODUCER, typename T, typename U, typename D>
526  bool CreateAssnD(
527  PRODUCER const& prod,
528  art::Event & evt,
529  art::Assns<T,U,D> & assn,
530  size_t first_index,
531  size_t second_index,
532  typename art::Assns<T,U,D>::data_t const& data
533  );
534  //@}
535 
536 
537  // MARK CreateAssnD_02
538  template <typename PRODUCER, typename T, typename U, typename D>
539  bool CreateAssnD(PRODUCER const& prod,
540  art::Event& evt,
541  std::vector<T> const& a,
542  art::Ptr<U> const& b,
543  typename art::Assns<U,T,D>::data_t const& data,
544  art::Assns<U,T,D>& assn,
545  size_t indx=UINT_MAX
546  );
547 
548 
549  // method to return all objects of type U that are not associated to
550  // objects of type T. Label is the module label that would have produced
551  // the associations and likely the objects of type T
552  // this method assumes there is a one to many relationship between T and U
553  // for example if you want to get all recob::Hits
554  // that are not associated to recob::Clusters
555  // std::vector<const recob::Hit*> hits = FindUNotAssociatedToU<recob::Cluster>(art::Handle<recob::Hit>, ...);
556  template<class T, class U> std::vector<const U*> FindUNotAssociatedToT(art::Handle<U> b,
557  art::Event const& evt,
558  std::string const& label);
559 
560  // method to return all objects of type U that are not associated to
561  // objects of type T. Label is the module label that would have produced
562  // the associations and likely the objects of type T
563  // this method assumes there is a one to many relationship between T and U
564  // for example if you want to get all recob::Hits
565  // that are not associated to recob::Clusters
566  // std::vector< art::Ptr<recob::Hit> > hits = FindUNotAssociatedToTP<recob::Cluster>(art::Handle<recob::Hit>, ...);
567  template<class T, class U> std::vector< art::Ptr<U> > FindUNotAssociatedToTP(art::Handle<U> b,
568  art::Event const& evt,
569  std::string const& label);
570 
571  // Methods make getting simple ART-independent association information.
572  // --- GetAssociatedVectorOneI takes in a handle to an association, and a handle to a product on the event.
573  // The ouput is a vector of with the same number of entries as the handle to the product, containing an index
574  // to the location of one associated product in that product's collection.
575  // --- GetAssociatedVectorOneP takes in a handle to an association, and a handle to a product on the event.
576  // The ouput is a vector of with the same number of entries as the handle to the product, containing a pointer
577  // to one associated product.
578  // --- GetAssociatedVectorManyI takes in a handle to an association, and a handle to a product on the event.
579  // The ouput is a vector of with the same number of entries as the handle to the product, containing a vector
580  // of indices that give the locations of all associated products in those products' collection.
581  // --- GetAssociatedVectorManyP takes in a handle to an association, and a handle to a product on the event.
582  // The ouput is a vector of with the same number of entries as the handle to the product, containing a vector
583  // of pointers to all associated products.
584 
585  template<class T,class U> std::vector<size_t> GetAssociatedVectorOneI(art::Handle< art::Assns<T,U> > h,
586  art::Handle< std::vector<T> > index_p);
587  template<class T,class U> std::vector<const U*> GetAssociatedVectorOneP(art::Handle< art::Assns<T,U> > h,
588  art::Handle< std::vector<T> > index_p);
589 
590  template<class T,class U> std::vector< std::vector<size_t> > GetAssociatedVectorManyI(art::Handle< art::Assns<T,U> > h,
591  art::Handle< std::vector<T> > index_p);
592  template<class T,class U> std::vector< std::vector<const U*> > GetAssociatedVectorManyP(art::Handle< art::Assns<T,U> > h,
593  art::Handle< std::vector<T> > index_p);
594 
595 
596 }// end namespace
597 
598 //----------------------------------------------------------------------
599 // MARK CreateAssn_01
600 template<class PRODUCER, class T, class U>
602  PRODUCER const& /* prod */,
603  art::Event & evt,
604  std::vector<T> const& a,
605  art::Ptr<U> const& b,
606  art::Assns<U,T> & assn,
607  std::string a_instance,
608  size_t indx /* = UINT_MAX */
609  )
610 {
611  if (indx == UINT_MAX) indx = a.size()-1;
612 
613  try{
614  //art::ProductID aid = prod.template evt.getProductID< std::vector<T > >( a_instance);
615  art::ProductID aid = evt.getProductID< std::vector<T > >( a_instance);
616  art::Ptr<T> aptr(aid, indx, evt.productGetter(aid));
617  //std::cout << "In assoc util: " << aptr << " " << b << " " << indx << std::endl;
618  assn.addSingle(b, aptr);
619  return true;
620  }
621  catch(cet::exception &e){
622  mf::LogWarning("AssociationUtil")
623  << "unable to create requested art:Assns, exception thrown: " << e;
624  return false;
625  }
626 
627 } // util::CreateAssn() [01]
628 
629 
630 //----------------------------------------------------------------------
631 // MARK CreateAssn_03
632 template<class PRODUCER, class T, class U>
634  PRODUCER const& /* prod */,
635  art::Event & /* evt */,
636  art::Ptr<T> const& a,
637  art::Ptr<U> const& b,
638  art::Assns<U,T> & assn
639 ) {
640 
641  try{
642  assn.addSingle(b, a);
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() [03]
652 
653 
654 //----------------------------------------------------------------------
655 // MARK CreateAssn_04
656 template<class PRODUCER, class T, class U>
658  PRODUCER const& prod,
659  art::Event & evt,
660  std::vector<T> const& a,
661  art::PtrVector<U> const& b,
662  art::Assns<T,U> & assn,
663  size_t indx /* = UINT_MAX */
664 ) {
665  if(indx == UINT_MAX) indx = a.size() - 1;
666 
667  try{
668  art::ProductID aid = prod.template getProductID< std::vector<T> >();
669  art::Ptr<T> aptr(aid, indx, evt.productGetter(aid));
670  for(art::Ptr<U> const& b_item: b) assn.addSingle(aptr, b_item);
671  }
672  catch(cet::exception &e){
673  mf::LogWarning("AssociationUtil")
674  << "unable to create requested art:Assns, exception thrown: " << e;
675  return false;
676  }
677 
678  return true;
679 } // util::CreateAssn() [04]
680 
681 //----------------------------------------------------------------------
682 // MARK CreateAssn_05
683 template<class PRODUCER, class T, class U>
685  PRODUCER const& /* prod */,
686  art::Event & /* evt */,
687  art::Ptr<T> const& a,
688  std::vector<art::Ptr<U>> const& b,
689  art::Assns<T,U> & assn
690 ) {
691 
692  try{
693  for (art::Ptr<U> const& b_item: b) assn.addSingle(a, b_item);
694  }
695  catch(cet::exception const& e){
696  mf::LogWarning("AssociationUtil")
697  << "unable to create requested art:Assns, exception thrown: " << e;
698  return false;
699  }
700 
701  return true;
702 } // util::CreateAssn() [05]
703 
704 //----------------------------------------------------------------------
705 // MARK CreateAssn_06
706 template<class PRODUCER, class T, class U>
708  PRODUCER const& prod,
709  art::Event & evt,
710  std::vector<T> const& a,
711  std::vector<art::Ptr<U>> const& b,
712  art::Assns<T,U> & assn,
713  size_t indx /* = UINT_MAX */
714 ) {
715 
716  if (indx == UINT_MAX) indx = a.size() - 1;
717 
718  try{
719  art::ProductID aid = prod.template getProductID< std::vector<T> >();
720  art::Ptr<T> aptr(aid, indx, evt.productGetter(aid));
721  for (art::Ptr<U> const& b_item: b) assn.addSingle(aptr, b_item);
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() [06]
731 
732 //----------------------------------------------------------------------
733 // MARK CreateAssn_07
734 template<class PRODUCER, class T, class U>
736  PRODUCER const& /* prod */,
737  art::Event & evt,
738  std::vector<T> const& a,
739  std::vector<U> const& /* b */,
740  art::Assns<T,U> & assn,
741  size_t startU,
742  size_t endU,
743  size_t indx /* = UINT_MAX */
744 ) {
745 
746  if(indx == UINT_MAX) indx = a.size() - 1;
747 
748  try{
749  //art::ProductID aid = prod.template getProductID< std::vector<T> >();
750  //art::ProductID bid = prod.template getProductID< std::vector<U> >();
751  art::ProductID aid = evt.getProductID< std::vector<T> >();
752  art::ProductID bid = evt.getProductID< std::vector<U> >();
753  art::Ptr<T> aptr(aid, indx, evt.productGetter(aid));
754  auto const* getter = evt.productGetter(bid); // I don't want to know what it is
755  for(size_t i = startU; i < endU; ++i){
756  art::Ptr<U> bptr(bid, i, getter);
757  assn.addSingle(aptr, bptr);
758  }
759  }
760  catch(cet::exception &e){
761  mf::LogWarning("AssociationUtil")
762  << "unable to create requested art:Assns, exception thrown: " << e;
763  return false;
764  }
765 
766  return true;
767 } // util::CreateAssn() [07]
768 
769 //----------------------------------------------------------------------
770 // MARK CreateAssn_07a
771 template<class PRODUCER, class T, class U>
773  PRODUCER const& prod,
774  art::Event & evt,
775  std::vector<T> const& a,
776  std::vector<U> const& /* b */,
777  art::Assns<T,U> & assn,
778  std::vector<size_t> const& indices,
779  size_t indx /* = UINT_MAX */
780 ) {
781 
782  if(indx == UINT_MAX) indx = a.size() - 1;
783 
784  try{
785  art::ProductID aid = prod.template getProductID< std::vector<T> >();
786  art::ProductID bid = prod.template getProductID< std::vector<U> >();
787  art::Ptr<T> aptr(aid, indx, evt.productGetter(aid));
788  auto const* getter = evt.productGetter(bid); // I don't want to know what it is
789  for(size_t index: indices){
790  art::Ptr<U> bptr(bid, index, getter);
791  assn.addSingle(aptr, bptr);
792  }
793  }
794  catch(cet::exception &e){
795  mf::LogWarning("AssociationUtil")
796  << "unable to create requested art:Assns, exception thrown: " << e;
797  return false;
798  }
799 
800  return true;
801 } // util::CreateAssn() [07a]
802 
803 //----------------------------------------------------------------------
804 // MARK CreateAssn_08
805 template <typename PRODUCER, typename T, typename U, typename Iter>
807  PRODUCER const& prod,
808  art::Event & evt,
809  art::Assns<T,U> & assn,
810  size_t first_index,
811  Iter from_second_index,
812  Iter to_second_index
813 ) {
814 
815  try{
816  // We need the "product ID" of what is going to become a data product.
817  // The data product ID is unique for the combination of process, producer,
818  // data type and product (instance) label.
819  //
820  art::ProductID first_id = prod.template getProductID< std::vector<T> >();
821  art::ProductID second_id = prod.template getProductID< std::vector<U> >();
822 
823  // we declare here that we want to associate the element first_index of the
824  // (only) data product of type std::vector<T> with other objects.
825  // This is the pointer to that element:
826  art::Ptr<T> first_ptr(first_id, first_index, evt.productGetter(first_id));
827 
828  // we are going to associate that element in a with a number of elements
829  // of the only data product of type std::vector<U>
830  auto const* getter = evt.productGetter(second_id); // auto, spare me the details
831  while (from_second_index != to_second_index) {
832  art::Ptr<U> second_ptr(second_id, *from_second_index, getter);
833  assn.addSingle(first_ptr, second_ptr);
834  ++from_second_index;
835  } // while
836  }
837  catch(cet::exception &e){
838  mf::LogWarning("AssociationUtil")
839  << "unable to create requested art:Assns, exception thrown: " << e;
840  return false;
841  }
842 
843  return true;
844 } // util::CreateAssn() [08]
845 
846 
847 //----------------------------------------------------------------------
848 // MARK CreateAssnD_01a
849 template <typename PRODUCER, typename T, typename U, typename D>
851  PRODUCER const& prod,
852  art::Event & evt,
853  art::Assns<T,U,D> & assn,
854  size_t first_index,
855  size_t second_index,
857 ) {
858 
859  try{
860  // We need the "product ID" of what is going to become a data product.
861  // The data product ID is unique for the combination of process, producer,
862  // data type and product (instance) label.
863  //
864  // we declare here that we want to associate the element first_index of the
865  // (only) data product of type std::vector<T> with the other object
866  art::ProductID first_id = prod.template getProductID< std::vector<T> >();
867  art::Ptr<T> first_ptr(first_id, first_index, evt.productGetter(first_id));
868 
869  // the same to associate the element second_index of the (only)
870  // data product of type std::vector<U> with the first object.
871  art::ProductID second_id = prod.template getProductID< std::vector<U> >();
872  art::Ptr<U> second_ptr
873  (second_id, second_index, evt.productGetter(second_id));
874 
875  assn.addSingle(first_ptr, second_ptr, std::move(data));
876  }
877  catch(cet::exception &e){
878  mf::LogWarning("AssociationUtil")
879  << "unable to create requested art:Assns, exception thrown: " << e;
880  return false;
881  }
882 
883  return true;
884 } // util::CreateAssnD() [01a]
885 
886 template <typename PRODUCER, typename T, typename U, typename D>
888  PRODUCER const& prod,
889  art::Event & evt,
890  art::Assns<T,U,D> & assn,
891  size_t first_index,
892  size_t second_index,
893  typename art::Assns<T,U,D>::data_t const& data
894 ) {
895 
896  try{
897  // We need the "product ID" of what is going to become a data product.
898  // The data product ID is unique for the combination of process, producer,
899  // data type and product (instance) label.
900  //
901  // we declare here that we want to associate the element first_index of the
902  // (only) data product of type std::vector<T> with the other object
903  art::ProductID first_id = prod.template getProductID< std::vector<T> >();
904  art::Ptr<T> first_ptr(first_id, first_index, evt.productGetter(first_id));
905 
906  // the same to associate the element second_index of the (only)
907  // data product of type std::vector<U> with the first object.
908  art::ProductID second_id = prod.template getProductID< std::vector<U> >();
909  art::Ptr<U> second_ptr
910  (second_id, second_index, evt.productGetter(second_id));
911 
912  assn.addSingle(first_ptr, second_ptr, data);
913  }
914  catch(cet::exception &e){
915  mf::LogWarning("AssociationUtil")
916  << "unable to create requested art:Assns, exception thrown: " << e;
917  return false;
918  }
919 
920  return true;
921 } // util::CreateAssnD() [01b]
922 
923 //----------------------------------------------------------------------
924 // MARK CreateAssnD_02
925 template <typename PRODUCER, typename T, typename U, typename D>
926 bool util::CreateAssnD(PRODUCER const& /*prod*/,
927  art::Event& evt,
928  std::vector<T> const& a,
929  art::Ptr<U> const& b,
930  typename art::Assns<U,T,D>::data_t const& data,
931  art::Assns<U,T,D> &assn,
932  size_t indx /*=UINT_MAX*/)
933 {
934  if (indx == UINT_MAX) indx = a.size()-1;
935 
936  try{
937  art::ProductID aid = evt.getProductID< std::vector<T > >();
938  art::Ptr<T> aptr(aid, indx, evt.productGetter(aid));
939  //std::cout << "In assoc util: " << aptr << " " << b << " " << indx << std::endl;
940  assn.addSingle(b, aptr, data);
941  return true;
942  }
943  catch(cet::exception &e){
944  mf::LogWarning("AssociationUtil")
945  << "unable to create requested art:Assns, exception thrown: " << e;
946  return false;
947  }
948 
949 
950 }
951 
952 //----------------------------------------------------------------------
953 template<class T, class U> inline std::vector<const U*> util::FindUNotAssociatedToT(art::Handle<U> b,
954  art::Event const& evt,
955  std::string const& label)
956 {
957 
958  // Do a FindOne for type T for each object of type U
959  // If the FindOne returns an invalid maybe ref, add the pointer
960  // of object type U to the return vector
961 
962  std::vector<const U*> notAssociated;
963 
964  art::FindOne<T> fa(b, evt, label);
965 
966  for(size_t u = 0; u < b->size(); ++u){
967  cet::maybe_ref<T const> t(fa.at(u));
968  if( !t.isValid() ){
969  art::Ptr<U> ptr(b, u);
970  notAssociated.push_back(ptr.get());
971  }
972  }
973 //
974  return notAssociated;
975 }
976 
977 //----------------------------------------------------------------------
978 template<class T, class U> inline std::vector< art::Ptr<U> > util::FindUNotAssociatedToTP(art::Handle<U> b,
979  art::Event const& evt,
980  std::string const& label)
981 {
982 
983  // Do a FindOneP for type T for each object of type U
984  // If the FindOne returns an invalid maybe ref, add the pointer
985  // of object type U to the return vector
986 
987  std::vector< art::Ptr<U> > notAssociated;
988 
989  art::FindOneP<T> fa(b, evt, label);
990 
991  for(size_t u = 0; u < b->size(); ++u){
992  cet::maybe_ref<T const> t(fa.at(u));
993  if( !t.isValid() ){
994  art::Ptr<U> ptr(b, u);
995  notAssociated.push_back(ptr);
996  }
997  }
998 
999  return notAssociated;
1000 }
1001 
1002 
1003 
1004 template<class T,class U> inline std::vector<size_t> util::GetAssociatedVectorOneI(art::Handle< art::Assns<T,U> > h,
1005  art::Handle< std::vector<T> > index_p)
1006 {
1007  std::vector<size_t> associated_index(index_p->size());
1008  for(auto const& pair : *h)
1009  associated_index.at(pair.first.key()) = pair.second.key();
1010  return associated_index;
1011 }
1012 
1013 template<class T,class U> inline std::vector<const U*> util::GetAssociatedVectorOneP(art::Handle< art::Assns<T,U> > h,
1014  art::Handle< std::vector<T> > index_p)
1015 {
1016  std::vector<const U*> associated_pointer(index_p->size());
1017  for(auto const& pair : *h)
1018  associated_pointer.at(pair.first.key()) = &(*(pair.second));
1019  return associated_pointer;
1020 }
1021 
1022 template<class T,class U> inline std::vector< std::vector<size_t> > util::GetAssociatedVectorManyI(art::Handle< art::Assns<T,U> > h,
1023  art::Handle< std::vector<T> > index_p)
1024 {
1025  std::vector< std::vector<size_t> > associated_indices(index_p->size());
1026  for(auto const& pair : *h)
1027  associated_indices.at(pair.first.key()).push_back(pair.second.key());
1028  return associated_indices;
1029 }
1030 
1031 template<class T,class U> inline std::vector< std::vector<const U*> > util::GetAssociatedVectorManyP(art::Handle< art::Assns<T,U> > h,
1032  art::Handle< std::vector<T> > index_p)
1033 {
1034  std::vector< std::vector<const U*> > associated_pointers(index_p->size());
1035  for(auto const& pair : *h)
1036  associated_pointers.at(pair.first.key()).push_back( &(*(pair.second)) );
1037  return associated_pointers;
1038 }
1039 
1040 
1041 #endif //ASSOCIATIONUTIL_H
Namespace for general, non-LArSoft-specific utilities.
ProductID getProductID(std::string const &instance_name="") const
Definition: DataViewImpl.h:338
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)
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
EDProductGetter const * productGetter(ProductID const pid) const
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)