Skip to content
Snippets Groups Projects
Commit b0f43ceb authored by Nils Krumnack's avatar Nils Krumnack
Browse files

add a configuration block for electrons

This is mostly a transcribing of the electron sequence in the style of
the muon configuration block.
parent ff26d244
No related branches found
No related tags found
19 merge requests!59674InDetPerformanceMonitoring with LumiBlock selection,!59383cppcheck in trigger code: Prefer prefix ++/-- operators for non-primitive types.,!58990Draft:Fixing bug in FTF config when running with Reco_tf,!58835DataQualityConfigurations: Modify L1Calo config for web display,!58791DataQualityConfigurations: Modify L1Calo config for web display,!58373Modification of V2.3 processing to work well with all clients,!58289New NVSI calibration,!58286New NVSI calibration,!58106Update NVSI example algorithm,!57937Draft: New nighlty test for trigger with a Run 4 single muon RDO,!57841Edits to ZDC signal processing in preparation for analysis of data from LHCf run,!57590Fixing LAr DT dumper,!57584Draft: LAr DB fixes,!57316ATR-26311 and ATR-25754 moving one dimuon and few egamma chains from dev to phys or MC,!57090ATLASRECTS-7305: fixes for large cluster building,!56828Draft: [trigEGam] Integration beteween mongroups and TrigEgammaMonitoring,!56523Draft: Proposal for CA-Based AODFix,!56355introduce CP configuration blocks for the remaining leptons, photons and jets,!55609Add Athena TEvent-based file access
...@@ -15,6 +15,8 @@ triggerChains = [ ...@@ -15,6 +15,8 @@ triggerChains = [
'HLT_2e17_lhvloose_nod0' 'HLT_2e17_lhvloose_nod0'
] ]
electronMinPt = 10e3
electronMaxEta = None
muonMinPt = None muonMinPt = None
muonMaxEta = None muonMaxEta = None
...@@ -141,11 +143,12 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) : ...@@ -141,11 +143,12 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
electronSequence.configure( inputName = 'Electrons', electronSequence.configure( inputName = 'Electrons',
outputName = 'AnaElectrons_%SYS%' ) outputName = 'AnaElectrons_%SYS%' )
algSeq += electronSequence algSeq += electronSequence
if not forCompare : vars += [ 'OutElectrons_%SYS%.pt -> el_pt_%SYS%',
vars += [ 'OutElectrons_%SYS%.pt -> el_pt_%SYS%', 'OutElectrons_NOSYS.phi -> el_phi',
'OutElectrons_NOSYS.phi -> el_phi', 'OutElectrons_NOSYS.eta -> el_eta',
'OutElectrons_NOSYS.eta -> el_eta', 'OutElectrons_%SYS%.baselineSelection_loose -> el_select_loose_%SYS%', ]
'OutElectrons_%SYS%.baselineSelection_loose -> el_select_loose_%SYS%', ] if dataType != 'data':
vars += [ 'OutElectrons_%SYS%.effSF_loose_%SYS% -> el_effSF_loose_%SYS%', ]
# Include, and then set up the photon analysis sequence: # Include, and then set up the photon analysis sequence:
...@@ -195,8 +198,10 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) : ...@@ -195,8 +198,10 @@ def makeSequenceOld (dataType, algSeq, vars, forCompare) :
selalg = createAlgorithm( 'CP::AsgSelectionAlg', 'UserElectronsSelectionAlg' ) selalg = createAlgorithm( 'CP::AsgSelectionAlg', 'UserElectronsSelectionAlg' )
addPrivateTool( selalg, 'selectionTool', 'CP::AsgPtEtaSelectionTool' ) addPrivateTool( selalg, 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
selalg.selectionTool.minPt = 10e3 if electronMinPt :
#selalg.selectionTool.maxEta = 2.47 selalg.selectionTool.minPt = electronMinPt
if electronMaxEta :
selalg.selectionTool.maxEta = electronMaxEta
selalg.selectionDecoration = 'selectPtEta' selalg.selectionDecoration = 'selectPtEta'
selalg.particles = 'AnaElectrons_%SYS%' selalg.particles = 'AnaElectrons_%SYS%'
algSeq += selalg algSeq += selalg
...@@ -407,11 +412,32 @@ def makeSequenceBlocks (dataType, algSeq, vars, forCompare) : ...@@ -407,11 +412,32 @@ def makeSequenceBlocks (dataType, algSeq, vars, forCompare) :
'EventInfo.eventNumber -> eventNumber', ] 'EventInfo.eventNumber -> eventNumber', ]
configSeq = ConfigSequence ()
# Include, and then set up the electron analysis algorithm sequence:
from EgammaAnalysisAlgorithms.ElectronAnalysisConfig import makeElectronCalibrationConfig, makeElectronWorkingPointConfig
likelihood = True
recomputeLikelihood=False
if likelihood:
workingpoint = 'LooseLHElectron.Loose_VarRad'
else:
workingpoint = 'LooseDNNElectron.Loose_VarRad'
makeElectronCalibrationConfig (configSeq, 'AnaElectrons')
makeElectronWorkingPointConfig (configSeq, 'AnaElectrons', workingpoint, postfix = 'loose',
recomputeLikelihood=recomputeLikelihood)
vars += [ 'OutElectrons_NOSYS.eta -> el_eta',
'OutElectrons_NOSYS.phi -> el_phi',
'OutElectrons_%SYS%.pt -> el_pt_%SYS%',
'OutElectrons_%SYS%.baselineSelection_loose -> el_select_loose_%SYS%', ]
if dataType != 'data':
vars += [ 'OutElectrons_%SYS%.effSF_loose_%SYS% -> el_effSF_loose_%SYS%', ]
# Include, and then set up the muon analysis algorithm sequence: # Include, and then set up the muon analysis algorithm sequence:
from MuonAnalysisAlgorithms.MuonAnalysisConfig import makeMuonCalibrationConfig, makeMuonWorkingPointConfig from MuonAnalysisAlgorithms.MuonAnalysisConfig import makeMuonCalibrationConfig, makeMuonWorkingPointConfig
configSeq = ConfigSequence ()
makeMuonCalibrationConfig (configSeq, 'AnaMuons') makeMuonCalibrationConfig (configSeq, 'AnaMuons')
makeMuonWorkingPointConfig (configSeq, 'AnaMuons', workingPoint='Medium.Iso', postfix='medium') makeMuonWorkingPointConfig (configSeq, 'AnaMuons', workingPoint='Medium.Iso', postfix='medium')
makeMuonWorkingPointConfig (configSeq, 'AnaMuons', workingPoint='Tight.Iso', postfix='tight') makeMuonWorkingPointConfig (configSeq, 'AnaMuons', workingPoint='Tight.Iso', postfix='tight')
...@@ -427,6 +453,17 @@ def makeSequenceBlocks (dataType, algSeq, vars, forCompare) : ...@@ -427,6 +453,17 @@ def makeSequenceBlocks (dataType, algSeq, vars, forCompare) :
configAccumulator = ConfigAccumulator (dataType, algSeq) configAccumulator = ConfigAccumulator (dataType, algSeq)
configSeq.fullConfigure (configAccumulator) configSeq.fullConfigure (configAccumulator)
selalg = createAlgorithm( 'CP::AsgSelectionAlg', 'UserElectronsSelectionAlg' )
addPrivateTool( selalg, 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
if electronMinPt :
selalg.selectionTool.minPt = electronMinPt
if electronMaxEta :
selalg.selectionTool.maxEta = electronMaxEta
selalg.selectionDecoration = 'selectPtEta'
selalg.particles = 'AnaElectrons_%SYS%'
algSeq += selalg
addOutputCopyAlgorithms (algSeq, 'Electrons', 'AnaElectrons_%SYS%', 'OutElectrons_%SYS%',
'selectPtEta&&baselineSelection_loose,as_char')
selalg = createAlgorithm( 'CP::AsgSelectionAlg', 'UserMuonsSelectionAlg' ) selalg = createAlgorithm( 'CP::AsgSelectionAlg', 'UserMuonsSelectionAlg' )
addPrivateTool( selalg, 'selectionTool', 'CP::AsgPtEtaSelectionTool' ) addPrivateTool( selalg, 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
......
# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
# AnaAlgorithm import(s):
from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
# E/gamma import(s).
from xAODEgamma.xAODEgammaParameters import xAOD
import PATCore.ParticleDataType
class ElectronCalibrationConfig (ConfigBlock) :
"""the ConfigBlock for the electron four-momentum correction"""
def __init__ (self, containerName, postfix) :
super (ElectronCalibrationConfig, self).__init__ ()
self.containerName = containerName
self.postfix = postfix
self.crackVeto = False
self.ptSelectionOutput = False
self.isolationCorrection = False
def makeAlgs (self, config) :
# Set up a shallow copy to decorate
if config.wantCopy (self.containerName, 'Electrons') :
alg = config.createAlgorithm( 'CP::AsgShallowCopyAlg', 'ElectronShallowCopyAlg' + self.postfix )
alg.input = config.readName (self.containerName)
alg.output = config.copyName (self.containerName)
# Set up the eta-cut on all electrons prior to everything else
alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronEtaCutAlg' + self.postfix )
alg.selectionDecoration = 'selectEta' + self.postfix + ',as_bits'
config.addPrivateTool( 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
alg.selectionTool.maxEta = 2.47
if self.crackVeto:
alg.selectionTool.etaGapLow = 1.37
alg.selectionTool.etaGapHigh = 1.52
alg.selectionTool.useClusterEta = True
alg.particles = config.readName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, '')
config.addSelection (self.containerName, '', alg.selectionDecoration,
bits=(5 if self.crackVeto else 4))
# Set up the track selection algorithm:
alg = config.createAlgorithm( 'CP::AsgLeptonTrackSelectionAlg',
'ElectronTrackSelectionAlg' + self.postfix )
alg.selectionDecoration = 'trackSelection' + self.postfix + ',as_bits'
alg.maxD0Significance = 5
alg.maxDeltaZ0SinTheta = 0.5
alg.particles = config.readName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, '')
config.addSelection (self.containerName, '', alg.selectionDecoration,
bits=3)
# Select electrons only with good object quality.
alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronObjectQualityAlg' + self.postfix )
alg.selectionDecoration = 'goodOQ' + self.postfix + ',as_bits'
config.addPrivateTool( 'selectionTool', 'CP::EgammaIsGoodOQSelectionTool' )
alg.selectionTool.Mask = xAOD.EgammaParameters.BADCLUSELECTRON
alg.particles = config.readName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, '')
config.addSelection (self.containerName, '', alg.selectionDecoration,
bits=1)
# Set up the calibration and smearing algorithm:
alg = config.createAlgorithm( 'CP::EgammaCalibrationAndSmearingAlg',
'ElectronCalibrationAndSmearingAlg' + self.postfix )
config.addPrivateTool( 'calibrationAndSmearingTool',
'CP::EgammaCalibrationAndSmearingTool' )
alg.calibrationAndSmearingTool.ESModel = 'es2022_R22_PRE'
alg.calibrationAndSmearingTool.decorrelationModel = '1NP_v1'
if config.dataType() == 'afii':
alg.calibrationAndSmearingTool.useAFII = 1
else:
alg.calibrationAndSmearingTool.useAFII = 0
alg.egammas = config.readName (self.containerName)
alg.egammasOut = config.copyName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, '')
# Set up the the pt selection
alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronPtCutAlg' + self.postfix )
alg.selectionDecoration = 'selectPt' + self.postfix + ',as_bits'
config.addPrivateTool( 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
alg.selectionTool.minPt = 4.5e3
alg.particles = config.readName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, '')
config.addSelection (self.containerName, '', alg.selectionDecoration,
bits=2, preselection=self.ptSelectionOutput)
# Set up the isolation correction algorithm:
if self.isolationCorrection:
alg = config.createAlgorithm( 'CP::EgammaIsolationCorrectionAlg',
'ElectronIsolationCorrectionAlg' + self.postfix )
config.addPrivateTool( 'isolationCorrectionTool',
'CP::IsolationCorrectionTool' )
if config.dataType() == 'data':
alg.isolationCorrectionTool.IsMC = 0
else:
alg.isolationCorrectionTool.IsMC = 1
alg.egammas = config.readName (self.containerName)
alg.egammasOut = config.readName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, '')
class ElectronWorkingPointConfig (ConfigBlock) :
"""the ConfigBlock for the electron working point
This may at some point be split into multiple blocks (29 Aug 22)."""
def __init__ (self, containerName, postfix, likelihoodWP, isolationWP) :
super (ElectronWorkingPointConfig, self).__init__ ()
self.containerName = containerName
self.selectionName = postfix
self.postfix = postfix
if self.postfix != '' and self.postfix[0] != '_' :
self.postfix = '_' + self.postfix
self.likelihoodWP = likelihoodWP
self.isolationWP = isolationWP
self.recomputeLikelihood = False
self.chargeIDSelection = False
def makeAlgs (self, config) :
if 'LH' in self.likelihoodWP:
# Set up the likelihood ID selection algorithm
# It is safe to do this before calibration, as the cluster E is used
alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronLikelihoodAlg' + self.postfix )
alg.selectionDecoration = 'selectLikelihood' + self.postfix + ',as_bits'
if self.recomputeLikelihood:
# Rerun the likelihood ID
config.addPrivateTool( 'selectionTool', 'AsgElectronLikelihoodTool' )
alg.selectionTool.primaryVertexContainer = 'PrimaryVertices'
alg.selectionTool.WorkingPoint = self.likelihoodWP
algDecorCount = 7
else:
# Select from Derivation Framework flags
config.addPrivateTool( 'selectionTool', 'CP::AsgFlagSelectionTool' )
dfFlag = "DFCommonElectronsLH" + self.likelihoodWP.split('LH')[0]
alg.selectionTool.selectionFlags = [dfFlag]
algDecorCount = 1
else:
# Set up the DNN ID selection algorithm
alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'ElectronDNNAlg' + self.postfix )
alg.selectionDecoration = 'selectDNN' + self.postfix + ',as_bits'
if self.recomputeLikelihood:
# Rerun the DNN ID
config.addPrivateTool( 'selectionTool', 'AsgElectronSelectorTool' )
alg.selectionTool.WorkingPoint = self.likelihoodWP
algDecorCount = 6
else:
# Select from Derivation Framework flags
raise ValueError ( "DNN working points are not available in derivations yet.")
alg.particles = config.readName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, self.selectionName)
config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
bits=algDecorCount)
# Set up the isolation selection algorithm:
if self.isolationWP != 'NonIso' :
alg = config.createAlgorithm( 'CP::EgammaIsolationSelectionAlg',
'ElectronIsolationSelectionAlg' + self.postfix )
alg.selectionDecoration = 'isolated' + self.postfix + ',as_bits'
config.addPrivateTool( 'selectionTool', 'CP::IsolationSelectionTool' )
alg.selectionTool.ElectronWP = self.isolationWP
alg.egammas = config.readName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, self.selectionName)
config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
bits=1)
# Select electrons only if they don't appear to have flipped their charge.
if self.chargeIDSelection:
alg = config.createAlgorithm( 'CP::AsgSelectionAlg',
'ElectronChargeIDSelectionAlg' + self.postfix )
alg.selectionDecoration = 'chargeID' + self.postfix + ',as_bits'
config.addPrivateTool( 'selectionTool',
'AsgElectronChargeIDSelectorTool' )
alg.selectionTool.TrainingFile = \
'ElectronPhotonSelectorTools/ChargeID/ECIDS_20180731rel21Summer2018.root'
alg.selectionTool.WorkingPoint = 'Loose'
alg.selectionTool.CutOnBDT = -0.337671 # Loose 97%
alg.particles = config.readName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, self.selectionName)
config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
bits=1)
# Set up an algorithm used for decorating baseline electron selection:
alg = config.createAlgorithm( 'CP::AsgSelectionAlg',
'ElectronSelectionSummary' + self.postfix )
alg.selectionDecoration = 'baselineSelection' + self.postfix + ',as_char'
alg.particles = config.readName (self.containerName)
alg.preselection = config.getFullSelection (self.containerName, self.selectionName)
# Set up the electron efficiency correction algorithm:
if config.dataType() != 'data':
alg = config.createAlgorithm( 'CP::ElectronEfficiencyCorrectionAlg',
'ElectronEfficiencyCorrectionAlg' + self.postfix )
config.addPrivateTool( 'efficiencyCorrectionTool',
'AsgElectronEfficiencyCorrectionTool' )
alg.scaleFactorDecoration = 'effSF' + self.postfix + '_%SYS%'
alg.efficiencyCorrectionTool.RecoKey = "Reconstruction"
alg.efficiencyCorrectionTool.CorrelationModel = "TOTAL"
if config.dataType() == 'afii':
alg.efficiencyCorrectionTool.ForceDataType = \
PATCore.ParticleDataType.Fast
elif config.dataType() == 'mc':
alg.efficiencyCorrectionTool.ForceDataType = \
PATCore.ParticleDataType.Full
alg.outOfValidity = 2 #silent
alg.outOfValidityDeco = 'bad_eff' + self.postfix
alg.electrons = config.readName (self.containerName)
alg.preselection = config.getPreselection (self.containerName, self.selectionName)
def makeElectronCalibrationConfig( seq, containerName, postfix = '',
crackVeto = False,
ptSelectionOutput = False,
isolationCorrection = False):
"""Create electron calibration configuration blocks
This makes all the algorithms that need to be run first befor
all working point specific algorithms and that can be shared
between the working points.
Keyword arguments:
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.
isolationCorrection -- Whether or not to perform isolation correction
ptSelectionOutput -- Whether or not to apply pt selection when creating
output containers.
"""
config = ElectronCalibrationConfig (containerName, postfix)
config.crackVeto = crackVeto
config.ptSelectionOutput = ptSelectionOutput
config.isolationCorrection = isolationCorrection
seq.append (config)
def makeElectronWorkingPointConfig( seq, containerName, workingPoint,
postfix = '',
recomputeLikelihood = False,
chargeIDSelection = False ):
"""Create electron analysis configuration blocks
Keyword arguments:
workingPoint -- The working point to use
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.
recomputeLikelihood -- Whether to rerun the LH. If not, use derivation flags
chargeIDSelection -- Whether or not to perform charge ID/flip selection
"""
splitWP = workingPoint.split ('.')
if len (splitWP) != 2 :
raise ValueError ('working point should be of format "likelihood.isolation", not ' + workingPoint)
config = ElectronWorkingPointConfig (containerName, postfix, splitWP[0], splitWP[1])
config.recomputeLikelihood = False
config.chargeIDSelection = False
seq.append (config)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment