How To Use Associations

Associations are a way to make references between two data objects stored in an art::Event. This page describes how to make associations and how to retrieve them from the art::Event.

The art::Assns can handle many-to-many relations, ie one-to-one, one-to-many, many-to-one.

A set of in-line functions is provided in the source:Utilities/AssociationUtil.h to create associations and retrieve them from the art::Event.

Creating Associations

The AssociationUtil.h provides functions to do one-to-one and one-to-many associations. Typically, one would use a one-to-many relation. An example of such a relation is a recob::Cluster to the recob::Hits it contains. In this case, use

  template<class T, class U> static bool CreateAssn(art::EDProducer const& prod,
                                                    art::Event            &evt, 
                                                    std::vector<T>        &a,
                                                    art::Ptr<U>            b,
                                                    art::Assns<U,T>       &assn,
                                                    size_t                indx=UINT_MAX);

This is a templated function, so T and U are generic class types.

The producer is the module making the art::Assns object, the art::Event is the input to the art::EDProducer module, the std::vector<T> is the collection being produced by the art::EDProducer, the art::Ptr<U> is the reference to an object that was previously stored in the art::Event and retrieved in by the current art::EDProducer, the art::Assns<U,T> is the art::Assns being produced and the size_t is the index in the srt::vector<T> of the object of type <T> that is being associated to the object of type <U>. Unless the size_t is specified (notice it has a default value), the last entry in the std::vector<T> will be associated with the art::Ptr<U>.

An example of making an art::Assns can be seen in source:MCCheater/ClusterCheater.cxx.

First, one must declare that the art::EDProducer will make the desired art::Assns, as seen in the constructor of ClusterCheater:

  ClusterCheater::ClusterCheater(fhicl::ParameterSet const& pset)

    produces< std::vector<rb::Cluster> >();
    produces< art::Assns<rb::Cluster, rb::Hit> >();

Then, in the produces method declare the auto_ptr< art::Assns<rb::Cluster, rb::Hit> > as in line 111 of ClusterCheater.cxx:

    std::auto_ptr< art::Assns<rb::Cluster, rb::Hit> > assn(new art::Assns<rb::Cluster, rb::Hit>);

After adding the cluster to the collection that is being produced, we make use of the CreateAssn method in line 143:

      if(ptrvsX.size() > 0){
                      ((*hitMapItr).first * 1000) + geo::kX*10));
    // associate the hits to this cluster
    util::CreateAssn(*this, evt, *(clustercol.get()), ptrvsX, *(assn.get()));

Finally put() the art::Assns onto the event, as in line 168:


Retrieving art::Assns from the art::Event

To get a previously created art::Assns out of the art::Event make use of the AssociationUtil::FindMany* and AssociationUtil::FindOne* methods. The versions of these methods where the "*" is replaced by "P" return art::Ptr objects. Those versions are useful when making associations that are more than one level deep, for example associated recob::Hits to recob::Tracks.

To use these methods, look at the example of FindManyP:

  template<class T, class U> static art::PtrVector<T> FindManyP(art::PtrVector<U>  b, 
                                                                art::Event  const& evt,
                                                                std::string const& label,
                                                                size_t             indx);

Let's assume we are finding the art::PtrVector<rb::Hits> associated with the rb::Clusters in an art::PtrVector<rb::Cluster>.

The art::PtrVector<U> is the art::PtrVector of objects that were previously associated, in this case the recob::Clusters. The art::Event is the argument to either a art::EDProducer or art::EDAnalyzer, the std::string is the label of the module that created the art::Assns, not the label of the module that created the collection of objects type U. The size_t is the index of the recob::Cluster object we are interested in in the art::PtrVector<U>.

An example of using this function is in lines 146-150 of source:MCCheater/TrackCheater.cxx:

    // get the hits associated with each cluster and associate those with the track
        for(size_t c = 0; c < tidClusters.size(); ++c){
          art::PtrVector<rb::Hit> hits = util::FindManyP<rb::Hit>(tidClusters, evt, fCheatedClusterLabel, c);
          util::CreateAssn(*this, evt, *(trackcol.get()), hits, *(assn.get()));

The FindMany methods can also take an art::View<U> and art::Handle<U> instead of the art::PtrVector<U>.

These "P" variant methods return art::PtrVector<T> while the others return std::vector<const T*>.