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