Inter-Product References¶
- Table of contents
- 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.
Assns
need only be used directly:
- When being filled and put into the event; or
- 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
(orB
) objects and access their counterparts and/or extra data objects aFindOne
orFindMany
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
andB
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 particularL
and a particularR
.- An
Assns
operates essentially as a vector of pairs ofPtr
, with axuiliary methods for accessing the attached extra data object for an association, if applicable. - An attempt to create an
Assns
with a template argumentD
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 anart::Assns<A, A>
orart::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.
- If there is an
Assns<A, B>
in the event for a given process it will unambiguously match in preference to anyAssns<A, B, D>
with the same module label and instance name in the same process. - If there are multiple
Assns<A, B, Dn>
in the event for a given process (with the same module label / instance name) and noAssns<A, B> for same
, then there will be an ambiguity. - If there is an
Assns<A, B, D>
in one process, and anAssns<A, B>
in an earlier process with the same module label / instance name, the former will unambiguously match a request for anAssns<A, B>
in preference to the latter unless the process name is specified to match the realAssns<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.¶
- Construction and output: source:art/test/Integration/AssnsProducer_module.cc
- Use: source:art/test/Integration/AssnsAnalyzer_module.cc
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:
- An
art::Handle
to one of the collections referred to by the associations upon which it is based. - An
art::View
into one of said collections. - 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
andData
are the only template arguments that must be specified when constructing aFindXXX
. Any other items are deducible from arguments.- The
FindXXX
needs a source of objects of typeA
, 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 correctAssns
and provide access to theB
(and/orD
) object(s) associated with each suppliedA
object in the order in which theA
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 ofPtr
objects instead ofconst
pointer or derivative thereof.
FindOne
/ FindOneP
¶
- If the specified
A
has multiple associatedB
(orD
) then an exception will be thrown: useFindMany
instead. - If the specified
A
does not have an associatedB
orD
then an attempt to create aFindOne
with same will cause an exception to be thrown: use aFindOneP
instead (returnedPtr
will be invalid:Ptr::isNull()
returns true). - If any of the associated
B
are non-resolvable, then an attempt to create aFindOne
will fail: use aFindOneP
instead (returnedPtr<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 ofA
: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 associatedB
orD
then the vector will be empty. - If an associated
art::Ptr<B>
does not resolve, then the corresponding slot inart::FindMany
will benullptr
.
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 ofA
: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;