For the common CP algorithms we developed a set of data handles to take care of handling data access and managing systematics. If you haven’t already, please work through the CP algorithm tutorial first.
The systematics handles are similar in concept to the data handles in AthenaMT, so if you are familiar with those you may recognize some of the concepts, but if not don’t worry, the information below should be enough to get you going.
Generally the systematics handles do three things:
They take care of the actual read/write access to the event store (TEvent, TStore or StoreGate), meaning you don’t directly talk to the event store anymore, but call the systematics handle instead.
They do the actual systematics management, i.e. they know what object in the event store to access for which systematic. One implication of this is that if the input to your algorithm is affected by systematics, then you need to use systematics handles even if your algorithm itself isn’t directly affected by systematics.
They add all the properties to the algorithm that are needed to configure their behavior. The default values of those properties are usually passed in as constructor arguments to the handle. There are actually special configuration helpers to take care of setting these properties correctly, and it is usually advisable to rely on those instead of setting them directly. They are still described here, but that is (mostly) meant for experts.
All the systematics handles are defined in the package
SystematicsHandles
. The way they are written assumes that you rely
on C++11 in-class initialization of all handles (as illustrated
below). They also try to rely on other modern C++ techniques as
appropriate.
For the naming of systematics-varied containers, the handles usually
employ a string like MyMuon_%SYS%
, in which %SYS%
gets replaced
with the name of the systematic (NOSYS
for nominal). It is
generally fine to specify a name without %SYS%
, but the implication
is that there are no systematics variations on the container.
Technically it also doesn’t have to be a container, though it normally
is.
Note that we only ever tested systematics handles with AnaAlgorithm
,
it should probably work with other athena algorithms, but probably not
with tools. Overall, you probably have the best experience if you
stick with AnaAlgorithm
.
SysListHandle
: List of SystematicsThe SysListHandle
takes care of the actual list of systematics to
process, and to filter it for the list of systematics actually
affecting this algorithm. As such every systematics-aware algorithm
needs this handle, and every other systematics handle needs to connect
to it (which is also the reason we currently (14 Jan 19) don’t support
systematics handles on tools).
The full list of systematics is placed into the event store by the
SysListLoaderAlg
, as such that algorithm has to run before any other
systematics-aware algorithm. For now (14 Jan 19) it is putting that
information into the event store on every execute, but at some point
we may change it to put the information into the meta-data store
instead.
The declaration in the class header is usually very straightforward:
CP::SysListHandle m_systematicsList {this};
However, you will then have to do some initialization work in the
initialize
function:
// if you have a systematics data handle, register it here
ANA_CHECK (m_sysDataHandle.initialize (m_systematicsList));
// if you have an ISystematicsTool, retrieve and register it
ANA_CHECK (m_systematicsTool.retrieve());
ANA_CHECK (m_systematicsList.addSystematics (m_systematicsTool));
// initialize the systematics list
ANA_CHECK (m_systematicsList.initialize());
Retrieving the tool and adding the list of affecting systematics does three things:
Then in the execute
you need to add a loop over all systematics.
This uses a C++11 lambda function, but apart from that it ought to be
very straight-forward:
StatusCode MyAlgorithm ::
execute ()
{
return m_systematicsList.foreach ([&] (const CP::SystematicSet& sys) -> StatusCode {
// if you have an ISystematicsTool, set the systematic we use
ANA_CHECK (m_systematicsTool->applySystematicVariation (sys));
// do actual algorithm work
return StatusCode::SUCCESS;
});
}
The handle defines two properties:
systematics
: The name of the systematics list in the event store.
The name can be changed through a constructor parameter, but there
is generally no need for that.systematicsRegex
: The regular expression describing the list of
systematics that affect this algorithm directly (as opposed to
affecting it only indirectly through its inputs). This name is
derived from the name of the main property.You may have noticed that we set the list of affecting systematics
twice, once in initialize
based on what the tool reports and then
again as a property from the configuration side. There are two
reasons for that:
It allows us to double-check that the configuration really knows which systematics affect this algorithm. Should the configured expression not match all the systematics reported by the tool it will be considered an error.
It allows us to configure the algorithm to run for more systematics than strictly needed, which could e.g. be used to optimize away some shallow copies which may otherwise be necessary.
This configured list of regular expressions is combined with the systematics affecting any of the inputs, so generally it is neither necessary nor advised to include a systematic just because it affects the input. However, it doesn’t hurt either.
There is a pending feature request to allow not reading the list of
systematics from the event store, but instead assuming we only want to
process the nominal systematics. This is mostly meant for running CP
algorithms the derivations, where we don’t care about systematics and
don’t want to run the SysListLoaderAlg
. However, that hasn’t been
implemented yet (14 Jan 19).
There has also been some discussion to put the systematics list into the meta-data store instead of the event store, as the list of systematics shouldn’t really change event-by-event. Besides some possibly efficiency improvements this would also allow to store the list of systematics in the output file. However, that hasn’t been implemented yet (14 Jan 19) and there could also be potential problems with such a design.
SysReadHandle
: Reading ObjectsThe SysReadHandle
takes care of reading objects from the event store
that you intent to neither modify nor decorate. If you want to do
that, see the SysCopyHandle
below. As such it only allows const
access to the object retrieved.
The declaration in the class header is usually very straightforward:
CP::SysReadHandle<xAOD::MuonContainer> m_inputHandle {
this, "propertyName", "defaultPropertyValue", "property description"};
In the initialize
function, it then needs to be added to the
SysListHandle
(see above):
m_systematicsList.addHandle (m_inputHandle);
And then in the systematics loop it can be accessed similar to how you
would call retrieve
on the event store:
const xAOD::MuonContainer *input = nullptr;
ANA_CHECK (m_inputHandle.retrieve (input, sys));
The handle defines two properties:
propertyName
: The name of the input container.
propertyNameRegex
: The regular expression describing the list of
systematics that affect the input container.
Note that there is no check that the regular expression specified is correct. If it is too loose there will be an error because the corresponding container can’t be found. If it is too tight, systematic variations will be silently dropped. So, if you configure this manually, you better get it right.
Just as for the global systematics list, there has also been some thoughts whether the systematics affecting a container could be stored as meta-data, but nothing has come of it yet (14 Jan 19).
SysReadHandleArray
: Reading Multiple ContainersThere is an array version of the read handle, that allows to read a
user configured number of containers at once. This was meant for MET
or Overlap Removal to take as input just a list of
IParticleContainer
objects instead of having a separate property for
each object type. However, currently (14 Jan 19) none of the common
CP algorithms is using this.
It mostly works like the regular SysReadHandle
, except there is a
size()
member to check the number of objects to read, and the
retrieve
method has an extra argument to indicate the index of the
object to be read. And on the configuration side the properties are
changed from strings to arrays of strings.
Note that despite the name this is not an array of SysReadHandle
objects, and the two classes are not related.
SysCopyHandle
: Modifying/Copying ContainersThe goal of SysCopyHandle
is to allow you to retrieve a container
and modify/decorate it. As such it tends to be the more common for CP
algorithms than read or write handles, as most CP algorithms just take
a single input container and do something with/to it.
When dealing with systematics it is quite common that you want to operate on a copy of the input container, instead of modifying the input container itself. Basically if you want to apply multiple systematic variations to the same input container you need to make multiple copies so that those variations don’t overwrite one another. As such, the handle can be configured to make a (shallow) copy of its input container (or not to do so).
The declaration in the class header is usually very straightforward:
CP::SysCopyHandle<xAOD::MuonContainer> m_copyHandle {
this, "propertyName", "defaultPropertyValue", "property description"};
In the initialize
function, it then needs to be added to the
SysListHandle
(see above):
m_systematicsList.addHandle (m_copyHandle);
And then in the systematics loop it can be accessed similar to how you
would call retrieve
on the event store:
xAOD::MuonContainer *container = nullptr;
ANA_CHECK (m_copyHandle.getCopy (container, sys));
The handle defines three properties:
propertyName
: The name of the input container.
propertyNameRegex
: The regular expression describing the list of
systematics that affect the input container.
propertyNameOut
: The name under which to store copies of the
container, or the empty string to perform no copies.
All the caveats for SysReadHandle
also apply for SysCopyHandle
.
SysWriteHandle
: Writing New ContainersThe goal of SysWriteHandle
is to allow you to retrieve a newly
created container. As such it doesn’t get used a lot, as in most
situations you have some input container that you want to
modify/decorate instead.
Due to the nature of the xAOD container, the SysWriteHandle
has a
second (optional) template argument. This is the associated aux-store
for your object. Those generally go together and if you want to add
an xAOD container to the store, you need to add the aux-store at the
same time. If your object doesn’t have an associated aux-store object
you can just omit the second template argument.
The declaration in the class header is usually very straightforward:
SysWriteHandle<xAOD::MissingETContainer,xAOD::MissingETAuxContainer> m_writeHandle {
this, "propertyName", "defaultPropertyValue", "property description"};
In the initialize
function, it then needs to be added to the
SysListHandle
(see above):
m_systematicsList.addHandle (m_writeHandle);
And then in the systematics loop it can be accessed similar to how you
would call record
on the event store, except you do one record
call instead of two:
auto met = std::make_unique<xAOD::MissingETContainer> ();
auto aux = std::make_unique<xAOD::MissingETAuxContainer> ();
met->setStore (aux.get());
ANA_CHECK (m_writeHandle.record (std::move (met), std::move (aux), sys));
The handle defines three properties:
propertyName
: The name of the output container.Note that in this case we do not need to configure the list of systematics (and there is no property for it), as that list depends solely on the list of systematics the algorithm ran on, i.e. there is exactly one copy per systematic.
There are a couple of helper algorithms that are specifically designed to help with systematics handling and associated tasks.
SysListLoaderAlg
: Load List of SystematicsThis algorithm is needed in any systematics-aware job to load the list of systematics into the event-store, so that subsequent algorithms can pick it up and use it. As such it has to be loaded before all other systematics-aware algorithms.
The default way of using this algorithm is to pick up the list of systematics from the systematics registry. As CP tools get created they register their systematics into the registry, making it very easy to retrieve the complete list of systematics and run on all of them:
sysLoader = createAlgorithm ('CP::SysListLoaderAlg', 'SysLoaderAlg')
sysLoader.sigmaRecommended = 1
Or to run all the 2-sigma variations instead of the 1-sigma variation you can just change the associated property:
sysLoader.sigmaRecommended = 2
While this is fine in some situations, you may want either more
control over which systematics are run, or may simply want to have the
certainty that the list of systematics doesn’t change as you
reconfigure your tools or algorithms. In that case you can specify
the list of systematics directly (and leave out sigmaRecommended
):
sysLoader.systematicsList = [...]
This algorithm will also print out the list of systematics that are contained in the systematics registry on job startup, so if you quickly want to check the list of systematics that’s one place you can take it from.