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.
Link 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.
Cast Link Accessors¶
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.