Project

General

Profile

Inter-Product References

Motivation and overview.

One wishes to create (and use later) a collection of associations between two types, Cluster and Track, collections of both of which are already in the event.

An example of how one might want to retrieve and use such associations is below, with respect to clusters and tracks:

Handle<Clusters> h;
e.getByLabel(h, "myClusters");
Clusters const &cl = *h;
FindOne<Track> fa(h, e, "TrackMatcher");
for (size_t i = 0; i != cl.size(); ++i) {
  // Use cl[i];
  cet::maybe_ref<Track const> track(fa.at(i)); // Returns null maybe_ref if not found.
}

And the equivalent code for one-to-many associations, with respect to tracks and hits:

Handle<Tracks> h;
e.getByLabel(h, "myTracks");
Tracks const &tk = *h;
FindMany<Hit> fb(h, e, "TrackFinder");
for (size_t i = 0; i != tk.size(); ++i) {
  // Use tk[i];
  std::vector<Hit const*> v;
  fb.get(i, v); // Appends to v.
}

Note that the FindOne and FindMany objects are not the persistent representation of the associations -- they are "smart query objects" which encapsulate the associations requested based on the provided arguments. The persistent entity is the Assns, which is envisaged to be used only during filling or for the rare case when the associations are more relevant than the associations themselves.

For an Assns declared as:

template <typename A, typename B, typename D = void>
class Assns;

We constrain the persistent representation of Assns<A, B, D> to be identical to that of Assns<B, A, D>. As a consequence of this, it becomes irrelevant whether any given creator or user of AssociationCollection specifies A followed by B or the converse when declaring the collection. Moreover, both FindOne<A, D> and FindOne<B, D> (and FindMany<A, D>, FindMany<B, D>) shall behave correctly regardless of whether the original underlying Assns specified A or B first.

The association collection: Assns

An association collection: a persist-able collection of associations between two items in other persistent collections, with an optional ancillary object containing information about the association itself.

Note that the associations may be one-to-one, one-to-many or many-to-many, and the Assns may hold associations between multiple collections of A and / or B and compatible types therewith.

An Assns need only be used directly:
  1. When being filled and put into the event; or
  2. When the emphasis is on the associations themselves (and possibly their order) rather than particularly the associated objects. When it is desired to loop over A (or B) objects and access their counterparts and/or extra data objects a FindOne or FindMany would be more suitable.

Note that the structure of the Assns template is non-trivial because there is a variant that has an extra data object attached to each association, and a variant that does not.

Notes.

  • A and B below are the types of two objects to be found in collections in the event. D where used is an arbitrary user-supplied type wherein information is stored about the association between a particular L and a particular R.
  • An Assns operates essentially as a vector of pairs of Ptr, with axuiliary methods for accessing the attached extra data object for an association, if applicable.
  • An attempt to create an Assns with a template argument D of pointer-type will result in a compile-time assertion failure.
  • Due to the bi-directionality of the Assns (See especially the lookup rules below), it is a compile-time error to attempt to specify an art::Assns<A, A> or art::Assns<A, A, D>.
  • An Assns<A, B> and an Assns<B, A>@ are represented identically in an art-format ROOT file: therefore it is an error to produce one of each in the same process from the same module with the same instance name.

Event lookup rules for Assns.

In all rules specified below, an art::Assns<A, B, D> (including where D is void) has exactly equal status with its left-right-swapped partner.

  1. If there is an Assns<A, B> in the event for a given process it will unambiguously match in preference to any Assns<A, B, D> with the same module label and instance name in the same process.
  2. If there are multiple Assns<A, B, Dn> in the event for a given process (with the same module label / instance name) and no Assns<A, B> for same, then there will be an ambiguity.
  3. If there is an Assns<A, B, D> in one process, and an Assns<A, B> in an earlier process with the same module label / instance name, the former will unambiguously match a request for an Assns<A, B> in preference to the latter unless the process name is specified to match the real Assns<A, B>.

Useful typedefs.

typedef std::pair<Ptr<A>, Ptr<B> > assn_t;

Constructors.

Assns<A, B>();
Assns<A, B, D>();

Modifiers.

void swap(Assns & other);
void addSingle(Ptr<A> const &, Ptr<B> const &); // Assns<A, B> only.
void addSingle(Ptr<A> const &, Ptr<B> const &, D const &);

Accessors.

assn_iterator begin() const; // De-referencing an assn_iterator
assn_iterator end() const;   // yields an assn_t const &.
assn_t const & operator [] (size_type i) const;
assn_t const & at(size_type i) const; // Bounds-checked.
size_type size() const;
D const & data(size_t index) const;
D const & data(assn_iterator it) const;

Examples.

FindOne / FindOneP and FindMany / FindManyP

These classes are smart query objects used as the main way of accessing associated objects.

A FindXXX object may be created using as a reference either:

  1. An art::Handle to one of the collections referred to by the associations upon which it is based.
  2. An art::View into one of said collections.
  3. An arbitrary collection of art::Ptr into one or more of said collections.

In addition, an event and input tag must be provided in order to retrieve the Assns upon which the FindXXX collection will be based.

In general: given an Assns associating A with B (or B with A) (possibly with an associated data object D) and a sequence ACOLL of A objects to be found in the Assns, allow indexed access to the B and/or D objects associated with the A objects in ACOLL.

  • ProdB and Data are the only template arguments that must be specified when constructing a FindXXX. Any other items are deducible from arguments.
  • The FindXXX needs a source of objects of type A, an event and an input tag corresponding to the underlying association collection from which to create itself.
  • When constructed, the FindXXX will obtain and interrogate the correct Assns and provide access to the B (and/or D) object(s) associated with each supplied A object in the order in which the A objects were specified.
    All indexed accessors (at(), data(), get()) are bounds-checked.
  • The P variants of each query object allow for by-return or by-filled-reference retrieval of Ptr objects instead of const pointer or derivative thereof.

FindOne / FindOneP

  • If the specified A has multiple associated B (or D) then an exception will be thrown: use FindMany instead.
  • If the specified A does not have an associated B or D then an attempt to create a FindOne with same will cause an exception to be thrown: use a FindOneP instead (returned Ptr will be invalid: Ptr::isNull() returns true).
  • If any of the associated B are non-resolvable, then an attempt to create a FindOne will fail: use a FindOneP instead (returned Ptr<B> will be invalid: Ptr<B>::isNonNull() returns true, Ptr<B>::isAvailable() returns false).

Useful typedefs.

typedef ProdB assoc_t;
typedef Data data_t;
typedef typename std::vector<ProdB const *>::size_type size_type;

Constructors.

  • From Handle to collection of A:
    FindOne<ProdB>(Handle<ProdAColl> const &,
                   Event const &,
                   InputTag const &);
    FindOne<ProdB, Data>(Handle<ProdAColl> const &,
                         Event const &,
                         InputTag const &);
  • From View<A>:
    FindOne<ProdB>(View<ProdA> const &,
                   Event const &,
                   InputTag const &);
    FindOne<ProdB, Data>(View<ProdA> const &,
                         Event const &,
                         InputTag const &);
  • From arbitrary sequence of Ptr<A>:
    FindOne<ProdB>(PtrProdAColl const &,
                   Event const &,
                   InputTag const &);
    FindOne<ProdB, Data>(PtrProdAColl const &,
                         Event const &,
                         InputTag const &);

Modifiers.

None.

Accessors.

size_type size() const;
cet::maybe_ref<assoc_t const> at(size_type) const; // FindOne
art::Ptr<assoc_t> const & at(size_type) const; // FindOneP
cet::maybe_ref<data_t const> data(size_type) const;
void get(size_type,
         cet::maybe_ref<assoc_t const> &) const; // FindOne
void get(size_type,
         art::Ptr<assoc_t> const &) const; // FindOneP
void get(size_type,
         cet::maybe_ref<assoc_t const> &,
         cet::maybe_ref<data_t const> &)
  const; // *Must* be used for FindOne<ProdB, Data>.
void get(size_type,
         art::Ptr<assoc_t> &,
         cet::maybe_ref<data_t const> &)
  const; // *Must* be used for FindOneP<ProdB, Data>.

Comparison operations.

bool operator == (FindOne const & other) const;

FindMany / FindManyP

  • If the specified A does not have an associated B or D then the vector will be empty.
  • If an associated art::Ptr<B> does not resolve, then the corresponding slot in art::FindMany will be nullptr.

Useful typedefs.

typedef ProdB assoc_t;
typedef Data data_t;
typedef std::vector<assoc_t const *> value_type; // FindMany
typedef std::vector<art::Ptr<assoc_t> > value_type; // FindManyP
typedef typename std::vector<value_type>::size_type size_type;
typedef value_type const & const_reference;
typedef value_type & reference;
typedef typename std::vector<data_t const *> const & data_const_reference;
typedef typename std::vector<data_t const *> & data_reference;

Constructors.

  • From Handle to collection of A:
    FindMany<ProdB>(Handle<ProdAColl> const &,
                    Event const &,
                    InputTag const &);
    FindMany<ProdB, Data>(Handle<ProdAColl> const &,
                          Event const &,
                          InputTag const &);
  • From View<A>:
    FindMany<ProdB>(View<ProdA> const &,
                    Event const &,
                    InputTag const &);
    FindMany<ProdB, Data>(View<ProdA> const &,
                          Event const &,
                          InputTag const &);
  • From arbitrary sequence of Ptr<A>:
    FindMany<ProdB>(PtrProdAColl const &,
    Event const &,
    InputTag const &);
    FindMany<ProdB, Data>(PtrProdAColl const &,
    Event const &,
    InputTag const &);

Modifiers.

None.

Accessors.

size_type size() const;
const_reference at(size_type) const;
const_data_reference data(size_type) const;
size_type get(size_type,
              reference)
  const; // Returns number of elements appended.
size_type get(size_type,
              reference,
              data_reference)
  const; // *Must* be used for FindMany<ProdB, Data>.

Comparison operations.

bool operator == (FindMany const & other) const;

Example

source:art/test/Integration/AssnsAnalyzer_module.cc