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