Common CP Algorithms Example Sequence

Last update: 05 Jul 2023 [History] [Edit]

As a first exercise let us get set up to implement our CP algorithms, we suggest creating a new algorithm like we did in the beginner’s tutorial. As it was mentioned earlier, there are example/test jobs for all object types, but for this tutorial we’ll focus mostly on the muons.

The idea of the common CP algorithms is to use a ready made selection sequence for each object that would be used in an analysis. This means consistency between analysis frameworks and also using ‘good’ objects. However, the sequence can be configured differently for tests and the needs of the analysis.

For example, a snippet of the muon analysis sequence is shown below, take your time to read each part and figure out what is happening. The full file can be found HERE

# Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration

# AnaAlgorithm import(s):
from AnaAlgorithm.AnaAlgSequence import AnaAlgSequence
from AnaAlgorithm.DualUseConfig import createAlgorithm, addPrivateTool
import ROOT

def makeMuonAnalysisSequence( dataType, workingPoint,
                              deepCopyOutput = False,
                              shallowViewOutput = True,
                              postfix = '',
                              ptSelectionOutput = False ):
    """Create a muon analysis algorithm sequence

    Keyword arguments:
      dataType -- The data type to run on ("data", "mc" or "afii")
      workingPoint -- The working point to use
      deepCopyOutput -- If set to 'True', the output containers will be
                        standalone, deep copies (slower, but needed for xAOD
                        output writing)
      shallowViewOutput -- Create a view container if required
      postfix -- a postfix to apply to decorations and algorithm
                 names.  this is mostly used/needed when using this
                 sequence with multiple working points to ensure all
                 names are unique.
      ptSelectionOutput -- Whether or not to apply pt selection when creating
                           output containers.
    """

    if not dataType in ["data", "mc", "afii"] :
        raise ValueError ("invalid data type: " + dataType)

    if postfix != '' :
        postfix = '_' + postfix
        pass

    # Make sure selection options make sense
    if deepCopyOutput and shallowViewOutput:
        raise ValueError ("deepCopyOutput and shallowViewOutput can't both be true!")

    splitWP = workingPoint.split ('.')
    if len (splitWP) != 2 :
        raise ValueError ('working point should be of format "quality.isolation", not ' + workingPoint)

    sfWorkingPoint = splitWP[0]
    if splitWP[0] == 'Tight' :
        quality = ROOT.xAOD.Muon.Tight
        pass
    elif splitWP[0] == 'Medium' :
        quality = ROOT.xAOD.Muon.Medium        
        pass
    elif splitWP[0] == 'Loose' :
        quality = ROOT.xAOD.Muon.Loose        
        pass
    elif splitWP[0] == 'VeryLoose' :
        quality = ROOT.xAOD.Muon.VeryLoose        
        pass
    elif splitWP[0] == 'HighPt' :
        quality = 4
        pass
    elif splitWP[0] == 'LowPtEfficiency' :
        quality = 5
        pass
    else :
        raise ValueError ("invalid muon quality: \"" + splitWP[0] +
                          "\", allowed values are Tight, Medium, Loose, " +
                          "VeryLoose, HighPt, LowPtEfficiency")

    if not splitWP[1] in ["Iso", "NonIso"] :
        raise ValueError ('invalid muon isolation \"' + splitWP[1] +
                          '\", allowed values are Iso, NonIso')

    # Create the analysis algorithm sequence object:
    seq = AnaAlgSequence( "MuonAnalysisSequence" + postfix )

    # Variables keeping track of the selections being applied.
    selectionDecorNames = []
    selectionDecorCount = []

    # Set up the eta-cut on all muons prior to everything else
    alg = createAlgorithm( 'CP::AsgSelectionAlg',
                           'MuonEtaCutAlg' + postfix )
    alg.preselection = "&&".join (selectionDecorNames)
    addPrivateTool( alg, 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
    alg.selectionTool.maxEta = 2.5
    alg.selectionDecoration = 'selectEta' + postfix + ',as_bits'
    seq.append( alg, inputPropName = 'particles',
                outputPropName = 'particlesOut',
                stageName = 'selection' )
    selectionDecorNames.append( alg.selectionDecoration )
    selectionDecorCount.append( 2 )

    # Set up the track selection algorithm:
    alg = createAlgorithm( 'CP::AsgLeptonTrackSelectionAlg',
                           'MuonTrackSelectionAlg' + postfix )
    alg.preselection = "&&".join (selectionDecorNames)
    alg.selectionDecoration = 'trackSelection' + postfix + ',as_bits'
    alg.maxD0Significance = 3
    alg.maxDeltaZ0SinTheta = 0.5
    seq.append( alg, inputPropName = 'particles',
                stageName = 'selection' )
    selectionDecorNames.append( alg.selectionDecoration )
    selectionDecorCount.append( 3 )

    ...

    # Set up the the pt selection
    ptSelectionDecoration = 'selectPt' + postfix + ',as_bits'
    alg = createAlgorithm( 'CP::AsgSelectionAlg', 'MuonPtCutAlg' + postfix )
    alg.preselection = "&&".join (selectionDecorNames)
    alg.selectionDecoration = ptSelectionDecoration
    addPrivateTool( alg, 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
    alg.selectionTool.minPt = 3e3
    seq.append( alg, inputPropName = 'particles',
                stageName = 'selection' )
    selectionDecorNames.append( alg.selectionDecoration )
    selectionDecorCount.append( 2 )

    ...

    ...

    # Set up an algorithm dumping the properties of the muons, for debugging:
    alg = createAlgorithm( 'CP::KinematicHistAlg',
                           'MuonKinematicDumperAlg' + postfix )
    alg.histPattern = 'muon' + postfix + '_%VAR%_%SYS%'
    seq.append( alg, inputPropName = 'input',
                stageName = 'selection' )

    ...

    # Return the sequence:
    return seq

Do not worry if this is a little confusing; even though we are implementing a very simple example of the common CP algorithms, some things may appear complicated for a beginner. Hopefully they become clearer as you go along.

Some things to note here:

  • This file is designed to describe the algorithm chain all muons in your analysis should follow.

  • The algorithm itself can be configured later with the workingPoint and postfix string to make sure different configurations are unique.

  • Some parts of this algorithm setup are just examples of good practice and aren’t strictly necessary (but you should still follow)