Skip to content

Special Accessors

Vector Accessors

Vector accessors need special handling because vector columns have a different memory layout in the different environments. In xAOD mode they are stored as std::vector (nested if necessary). In columnar mode the individual vector elements are all sequentially laid out with an offset map (or several) laying out the starting and end points of each stored vector in the column.

To accommodate the difference in memory layout the std::vector accessors are not returning an std::vector, but an std::span or an std::span-like object. You still specify it as std::vector<float> etc. to match how it is specified for xAOD accessors.

There are currently only read-accessors for std::vector. This is in part because all CP Tools converted so far only used read-accessors. However, there are also some issues with creating std::vector columns in columnar mode. In general we expect all output columns to be preallocated and passed into the columnar tool, avoiding the need for any memory management or memory model in the columnar infrastructure. If needed we can probably work around that and provide write accessors, but please think carefully beforehand whether you really need them, as that would be a non-trivial feature to add.

There are several headers for vector accessors, there is ColumnarCore/VectorColumn.h and ColumnarCore/VectorVectorColumn.h. That is because in columnar mode the nested vectors need a separate implementation (with two offset maps). There is the possibility we may consolidate them into one header file in the future.

String Accessors

In general we don't use strings in our EDM, with one exception: the name of the MET terms. We do support reading strings, and the std::string accessor will return an std::string_view as that is compatible with all modes. Under the hood this is handled similar to the std::vector accessors.

ElementLink decorations are widely used in PHYSLITE, linking e.g. electrons to the associated clusters. For a simple link from one container to another, this is done by accessing it as an OptObjectId, e.g.:

ElectronAccessor<OptClusterId> eleClusterAcc {*this, "cluster"};

This also works nested inside vectors, which is also very common:

ElectronAccessor<std::vector<OptClusterId>> eleClustersAcc {*this, "clusters"};

In general you will also need an ObjectColumn for the linked-to container, to declare the name of the linked container:

ClusterAccessor<ObjectColumn> clusterAcc {*this, "egammaClusters"};

You may have noticed that this only works for links to a single target container, which is intentional and preferred, as it is a lot simpler on the columnar side, essentially it is just a simple integer. If you need a link that can point to objects that can be in one of several containers, please take a look at the variant section. Note that even though it is just a simple index, there will need to be preprocessing of the ElementLink columns by the columnar framework.

To use link columns you need to include the ColumnarCore/LinkColumn.h header.

In some cases the link type in PHYSLITE is different than the type the tool needs, e.g. it is stored as a ElementLink<xAOD::IParticle> but the code needs it cast to a different type. For that there is a special accessor that integrates the cast:

JetAccessor<std::vector<LinkCastColumn<ContainerId::track,xAOD::IParticleContainer>>> ghostAcc {*this, "GhostTrack"};

This is really only needed to give you the right xAOD type in xAOD mode. As noted before, in columnar mode we really don't care what the exact type is, and you could just handle it as a OptParticleId throughout. At the same time, the columnar infrastructure absolutely does not allow casting from one container type to another, so it has to happen inside the accessor.

Overall it is likely best to avoid writing links to base types if you intend to read them as a different type. However, that is not always the case.

Momentum Accessors

There is a special momentum accessor in the ColumnarCore/MomentumAccessors.h header. For detailed documentation look at the header and the example tool. This is specifically for the case that you are using the full four-momentum (e.g. to add together multiple momenta). If all you need is e.g. the muon pt and eta, please just use regular column accessors instead.

The momentum accessors generally need to be told what kind of particle they run on, so that they configure themselves for the right layout for whatever object you are reading. If they are not configured they will default to the IParticle accessors in xAOD mode and throw in columnar mode. Note that even in xAOD mode configuring to a specific particle type will generally provide you with better performance.

Note that you can have more than one momentum accessor for a container. The main use case for that is jets, which both have a regular jet momentum and a constituent scale momentum.

This is a relatively new and also somewhat niche feature, so it is possible that there will be changes based on user feedback.

Custom Object-Specific Accessors

In general all of the xAOD classes contain code for unpacking the data from PHYSLITE, e.g. to extra etaBE2 from a calorimeter cluster. Since we don't use the xAOD classes in columnar mode, we can't use them. Instead we provide an "accessor-like" class for each, that tries to behave like an accessor, while having a custom implementation underneath.

Those are generally implemented only when needed, i.e. when a CP Tool needs to be migrated from using the xAOD function. They are also somewhat inconsistent in how they are implemented. Where possible we try to share the implementation with the xAOD function, by factoring out the code into a shared POD-function. However, such code sharing is not always possible, particularly if the implementation accesses ElementLink variables.