Skip to content

Variant Link and Object Access

The general assumption in the columnar infrastructure is that when you have an object you know exactly which container it belongs to. And for the most part that works very well and is sufficient. However, sometimes that simply doesn't work, you may have a link that can point to objects in multiple containers, or may need to have uniform handling of objects from multiple containers. In analogy to std::variant we use the name variant for this access.

While this is by now pretty well supported and it is what you may be used to from the xAOD world (where that is integrated into all EDM objects), please only use it where actually necessary, e.g. for variant links that already exist in PHYSLITE or if otherwise you'd need to implement variant-like behavior yourself. In particular you don't need this if the same tool may be run on different containers in the same job. Each instance of the tool (or even each call to the tool) can operate on a different container without using variant code.

To use variants in your code, you first need to define a variant container, which could look like:

using MyTrackDef = VariantContainerId<ContainerId::track0,ContainerId::track0,ContainerId::track1>;
This lists all the containers that your new track definition can be associated with. Note that ContainerId::track0 is listed here twice, with the first instance being used solely to determine the type the variant should have in xAOD mode, i.e. it must correspond to an xAOD type that is base to all other types. So if you used a variant over muons and electrons, you could put ContainerId::particle there (for xAOD::IParticle), even if you don't use a particle container.

You can then use that like a regular container as a template argument for many of the columnar infrastructure template classes, e.g. ObjectId, OptObjectId, ColumnAccessor. One notable exception for that is the momentum accessor which currently doesn't support them, but could have support added in the future.

For variant links we will typically use an ObjectLink not an OptObjectId column. The ObjectLink is a bit more raw (think ElementLink vs xAOD::IParticle*), and has some options for inspection and converting to OptObjectId and ObjectId either for the variant or individual containers.

Note that the ObjectLink was where the original variant support started, essentially as a way to read the object links for METAssociation in the columnar METMaker. As we seem to be adding more and more complete support for variants we may take another look at the ObjectLink and potentially phase it out, either completely or relegate it to special cases in which it is actually beneficial.

Variant Accessors

You can also declare a column accessor for a variant:

ColumnAccessor<MyTrackDef,float> phiAcc {*this, "phi"};
This will then be able to take not just ObjectId<MyTrackDef> but also other compatible object ids.

However, please keep in mind that it is very easy to overdeclare the numberĀ of input columns you request. Instead of just declaring a single input column, it requires to declare one column per container in the variant. Sometimes that is exactly what you want, but other times you may just need or want it for one of them.