Skip to content

Cross-link nominal and systematic variations objects to build union containers

Teng Jian Khoo requested to merge khoo/athena:systematic-object-links into main

This is an alternative approach to CP::AsgUnionSelectionAlg, which flags all objects in a container with its systematic variations for which any variation passes some selection criteria. The concept is that:

  • At some point when we still have access to an unfiltered container, we apply the SystObjectLinkerAlg. It should happen when all systematic variations affecting this container are already known. This applies two sets of decorations, as follows:
    • Each object in the nominal container receives a systLinkVar_%SYS% decoration for every variation.
    • Each object in a variation container receives a nominalObjectLink decoration.
  • Downstream of this, the user applies some selection, building VIEW_ELEMENTS containers that pass their analysis selection. In event selection algorithms and observable computations, they need only loop over the objects in these filtered containers. This filtering should be done in a systematics-aware way preserving the usual ContainerName_%SYS% convention (e.g. with SysWriteHandles).
  • Before writing to an output file, the corresponding CP::Syst[Object]UnioniserAlg is run on the filtered container. It builds a set containing all selected nominal objects, and then adds to this any other systematic variation objects that were not already selected. This forms the union of all selected objects. It then loops over the nominal union set, recording this to a new VIEW_ELEMENTS container and uses the links to populate corresponding variation output containers.

It is important that the linker runs early on, hence I have put it in the makeBlahAnalysisSequences functions with the option to toggle it on. If we run this on prefiltered selections we can run into this issue:

ENTRY | TAU | NOSYS | TAUS_TRUEHADTAU_SME_TES_INSITUFIT__1down | TAUS_TRUEHADTAU_SME_TES_INSITUFIT__1up
------------------------------------------------------------
    0 |   0 |   126 |    126 |    126
    1 |   0 |  60.1 |     -- |   60.3
    2 |   0 |  69.4 |   69.4 |   69.4

One variation in the 2nd event has no selected object (pt is 59.9 GeV with a cut at 60 GeV), so we are unable ever to access it. While we can go from a non-empty filtered collection back to the full one, nothing can be done about an empty collection.

Another caveat: It is possible to cause objects to depend on more systematic variations than existed at the time that the calibration sequences ran. In this case, one needs to defer the selection from the existing sequence and run the linker when these correlations are known. We might also need a modified procedure to handle something like overlap removal, which doesn't multiply the object copies, but does generate extra containers for systematics that were not initially affecting the input containers.

For a more explicit statement of the motivation thanks to @gwilliam:

We want to be able to write out just the sys varied pt for an object so we need to take the union of nominal + sys variations to avoid getting out of sync with the other variables e.g. eta. Now, this can be done with selection flags following the examples but this is a bit of a pain if one also wants to do event selection / filtering on these as you have to pass around not only the container but also the selection.

For example, in the bbtautau case we were thinking of applying a loose preselection that requires 1 e/mu and 1 tau or 2 taus + 2 bjets. We would do this for nominal + each syst and keep events in the ntuple that pass at least one, labelling with an event flag in the ntuple which they passed. As part of this we also have to calculate the tautau mass based on the MMC to which we also need to pass the containers.

It seems this would be easier for particularly new grad students to understand if we could just apply the selections as normal and then when writing deal with taking the union behind the scenes rather than keeping track of selection flags everywhere

TODO:

  • Implement in the ConfigBlock version of the CP algs as well

Implementation details

I had to template the SystObjectUnioniserAlg. Originally I intended to work with IParticleContainer only, but this is incompatible with AsgxAODNTupleMakerAlg because IParticleContainer does not provide a collection proxy -- only the derived containers do. Two template parameters are needed, one for the object type and one for the container type. The latter is explicitly needed because DataVector<xAOD::Blah_v1> does not have a classID -- only its versionless typedef BlahContainer does. The templated algs are then subclassed for the types that were obviously necessary, because otherwise genConf generates a long explicit name for the python class, even if one makes a compact typedef.

Edited by Teng Jian Khoo

Merge request reports