4 from AsgAnalysisAlgorithms.AnalysisObjectSharedSequence
import makeSharedObjectSequence
5 from AnaAlgorithm.AnaAlgSequence
import AnaAlgSequence
6 from AnaAlgorithm.DualUseConfig
import createAlgorithm, addPrivateTool
9 from xAODEgamma.xAODEgammaParameters
import xAOD
14 deepCopyOutput = False,
15 shallowViewOutput = True,
17 recomputeLikelihood = False,
18 chargeIDSelection = False,
19 isolationCorrection = False,
21 ptSelectionOutput = False,
22 trackSelection = True,
23 enableCutflow = False,
24 enableKinematicHistograms = False,
25 defineSystObjectLinks = False,
26 forceFullSimConfig = False):
27 """Create an electron analysis algorithm sequence
30 dataType -- The data type to run on ("data", "mc" or "afii")
31 workingPoint -- The working point to use
32 deepCopyOutput -- If set to 'True', the output containers will be
33 standalone, deep copies (slower, but needed for xAOD
35 shallowViewOutput -- Create a view container if required
36 postfix -- a postfix to apply to decorations and algorithm
37 names. this is mostly used/needed when using this
38 sequence with multiple working points to ensure all
40 recomputeLikelihood -- Whether to rerun the LH. If not, use derivation flags
41 chargeIDSelection -- Whether or not to perform charge ID/flip selection
42 isolationCorrection -- Whether or not to perform isolation correction
43 crackVeto -- Whether or not to perform eta crack veto
44 ptSelectionOutput -- Whether or not to apply pt selection when creating
46 trackSelection -- apply selection on tracks (d0, z0, siHits, etc.)
47 enableCutflow -- Whether or not to dump the cutflow
48 enableKinematicHistograms -- Whether or not to dump the kinematic histograms
52 if dataType
not in [
'data',
'mc',
'afii' ]:
53 raise ValueError(
'Invalid data type: %s' % dataType )
56 postfix =
'_' + postfix
60 seq = AnaAlgSequence(
"ElectronAnalysisSequence" + postfix )
63 seq.addMetaConfigDefault (
"selectionDecorNames", [])
64 seq.addMetaConfigDefault (
"selectionDecorNamesOutput", [])
65 seq.addMetaConfigDefault (
"selectionDecorCount", [])
67 makeElectronCalibrationSequence (seq, dataType, postfix=postfix,
68 crackVeto = crackVeto,
69 ptSelectionOutput = ptSelectionOutput,
70 trackSelection = trackSelection,
71 isolationCorrection = isolationCorrection,
72 forceFullSimConfig = forceFullSimConfig)
73 makeElectronWorkingPointSequence (seq, dataType, workingPoint, postfix=postfix,
74 recomputeLikelihood = recomputeLikelihood,
75 chargeIDSelection = chargeIDSelection,
76 forceFullSimConfig = forceFullSimConfig)
77 makeSharedObjectSequence (seq, deepCopyOutput = deepCopyOutput,
78 shallowViewOutput = shallowViewOutput,
79 postfix =
'_Electron' + postfix,
80 enableCutflow = enableCutflow,
81 enableKinematicHistograms = enableKinematicHistograms,
82 defineSystObjectLinks = defineSystObjectLinks )
93 ptSelectionOutput = False,
94 trackSelection = False,
95 isolationCorrection = False,
96 forceFullSimConfig = False):
97 """Create electron calibration analysis algorithms
99 This makes all the algorithms that need to be run first befor
100 all working point specific algorithms and that can be shared
101 between the working points.
104 dataType -- The data type to run on ("data", "mc" or "afii")
105 workingPoint -- The working point to use
106 postfix -- a postfix to apply to decorations and algorithm
107 names. this is mostly used/needed when using this
108 sequence with multiple working points to ensure all
110 isolationCorrection -- Whether or not to perform isolation correction
111 ptSelectionOutput -- Whether or not to apply pt selection when creating
116 if dataType
not in [
'data',
'mc',
'afii' ]:
117 raise ValueError(
'Invalid data type: %s' % dataType )
119 if forceFullSimConfig:
120 print(
"WARNING! You are running makeElectronCalibrationSequence forcing full sim config")
121 print(
"WARNING! This is only intended to be used for testing purposes")
124 alg =
createAlgorithm(
'CP::AsgShallowCopyAlg',
'ElectronShallowCopyAlg' + postfix )
125 seq.append( alg, inputPropName =
'input',
126 outputPropName =
'output',
127 stageName =
'prepare')
130 alg =
createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronEtaCutAlg' + postfix )
131 alg.selectionDecoration =
'selectEta' + postfix +
',as_bits'
132 addPrivateTool( alg,
'selectionTool',
'CP::AsgPtEtaSelectionTool' )
133 alg.selectionTool.maxEta = 2.47
135 alg.selectionTool.etaGapLow = 1.37
136 alg.selectionTool.etaGapHigh = 1.52
137 alg.selectionTool.useClusterEta =
True
138 seq.append( alg, inputPropName =
'particles',
139 stageName =
'calibration',
140 metaConfig = {
'selectionDecorNames' : [alg.selectionDecoration],
141 'selectionDecorNamesOutput' : [alg.selectionDecoration],
142 'selectionDecorCount' : [5
if crackVeto
else 4]},
143 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
148 'ElectronTrackSelectionAlg' + postfix )
149 alg.selectionDecoration =
'trackSelection' + postfix +
',as_bits'
150 alg.maxD0Significance = 5
151 alg.maxDeltaZ0SinTheta = 0.5
152 seq.append( alg, inputPropName =
'particles',
153 stageName =
'selection',
154 metaConfig = {
'selectionDecorNames' : [alg.selectionDecoration],
155 'selectionDecorNamesOutput' : [alg.selectionDecoration],
156 'selectionDecorCount' : [3]},
157 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
160 alg =
createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronObjectQualityAlg' + postfix )
161 alg.selectionDecoration =
'goodOQ' + postfix +
',as_bits'
162 addPrivateTool( alg,
'selectionTool',
'CP::EgammaIsGoodOQSelectionTool' )
163 alg.selectionTool.Mask = xAOD.EgammaParameters.BADCLUSELECTRON
164 seq.append( alg, inputPropName =
'particles',
165 stageName =
'calibration',
166 metaConfig = {
'selectionDecorNames' : [alg.selectionDecoration],
167 'selectionDecorNamesOutput' : [alg.selectionDecoration],
168 'selectionDecorCount' : [1]},
169 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
173 'ElectronCalibrationAndSmearingAlg' + postfix )
175 'CP::EgammaCalibrationAndSmearingTool' )
176 alg.calibrationAndSmearingTool.ESModel =
'es2022_R22_PRE'
177 alg.calibrationAndSmearingTool.decorrelationModel =
'1NP_v1'
178 alg.calibrationAndSmearingTool.useFastSim = (0
if forceFullSimConfig
179 else int(dataType ==
'afii'))
180 seq.append( alg, inputPropName =
'egammas', outputPropName =
'egammasOut',
181 stageName =
'calibration',
182 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
185 alg =
createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronPtCutAlg' + postfix )
186 alg.selectionDecoration =
'selectPt' + postfix +
',as_bits'
187 addPrivateTool( alg,
'selectionTool',
'CP::AsgPtEtaSelectionTool' )
188 alg.selectionTool.minPt = 4.5e3
189 seq.append( alg, inputPropName =
'particles',
190 stageName =
'selection',
191 metaConfig = {
'selectionDecorNames' : [alg.selectionDecoration],
192 'selectionDecorNamesOutput' : [alg.selectionDecoration]
if ptSelectionOutput
else [],
193 'selectionDecorCount' : [2]},
194 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
197 if isolationCorrection:
199 'ElectronIsolationCorrectionAlg' + postfix )
201 'CP::IsolationCorrectionTool' )
202 alg.isolationCorrectionTool.IsMC =
int(dataType !=
'data')
203 alg.isolationCorrectionTool.AFII_corr = (0
if forceFullSimConfig
204 else dataType ==
'afii')
205 seq.append( alg, inputPropName =
'egammas', outputPropName =
'egammasOut',
206 stageName =
'calibration',
207 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
215 recomputeLikelihood = False,
216 chargeIDSelection = False,
217 forceFullSimConfig = False ):
218 """Create electron analysis algorithms for a single working point
221 dataType -- The data type to run on ("data", "mc" or "afii")
222 workingPoint -- The working point to use
223 postfix -- a postfix to apply to decorations and algorithm
224 names. this is mostly used/needed when using this
225 sequence with multiple working points to ensure all
227 recomputeLikelihood -- Whether to rerun the LH. If not, use derivation flags
228 chargeIDSelection -- Whether or not to perform charge ID/flip selection
232 if dataType
not in [
'data',
'mc',
'afii' ]:
233 raise ValueError(
'Invalid data type: %s' % dataType )
235 if forceFullSimConfig:
236 print(
"WARNING! You are running makeElectronWorkingPointSequence forcing full sim config")
237 print(
"WARNING! This is only intended to be used for testing purposes")
239 splitWP = workingPoint.split (
'.')
240 if len (splitWP) != 2 :
241 raise ValueError (
'working point should be of format "likelihood.isolation", not ' + workingPoint)
243 likelihoodWP = splitWP[0]
244 isolationWP = splitWP[1]
246 if 'LH' in likelihoodWP:
249 alg =
createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronLikelihoodAlg' + postfix )
250 alg.selectionDecoration =
'selectLikelihood' + postfix +
',as_bits'
251 if 'SiHits' in likelihoodWP:
253 addPrivateTool( alg,
'selectionTool',
'CP::AsgMaskSelectionTool' )
254 dfVar =
"DFCommonElectronsLHLooseBLIsEMValue"
255 alg.selectionTool.selectionVars = [dfVar]
256 mask =
int( 0 | 0x1 << 1 | 0x1 << 2)
257 alg.selectionTool.selectionMasks = [mask]
260 if recomputeLikelihood:
262 addPrivateTool( alg,
'selectionTool',
'AsgElectronLikelihoodTool' )
263 alg.selectionTool.primaryVertexContainer =
'PrimaryVertices'
264 alg.selectionTool.WorkingPoint = likelihoodWP
268 addPrivateTool( alg,
'selectionTool',
'CP::AsgFlagSelectionTool' )
269 dfFlag =
"DFCommonElectronsLH" + likelihoodWP.split(
'LH')[0]
270 dfFlag = dfFlag.replace(
"BLayer",
"BL")
271 alg.selectionTool.selectionFlags = [dfFlag]
275 alg =
createAlgorithm(
'CP::AsgSelectionAlg',
'ElectronDNNAlg' + postfix )
276 alg.selectionDecoration =
'selectDNN' + postfix +
',as_bits'
277 if recomputeLikelihood:
280 alg.selectionTool.WorkingPoint = likelihoodWP
284 raise ValueError (
"DNN working points are not available in derivations yet.")
285 seq.append( alg, inputPropName =
'particles',
286 stageName =
'selection',
287 metaConfig = {
'selectionDecorNames' : [alg.selectionDecoration],
288 'selectionDecorNamesOutput' : [alg.selectionDecoration],
289 'selectionDecorCount' : [algDecorCount]},
290 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
293 if isolationWP !=
'NonIso' :
295 'ElectronIsolationSelectionAlg' + postfix )
296 alg.selectionDecoration =
'isolated' + postfix +
',as_bits'
297 addPrivateTool( alg,
'selectionTool',
'CP::IsolationSelectionTool' )
298 alg.selectionTool.ElectronWP = isolationWP
299 seq.append( alg, inputPropName =
'egammas',
300 stageName =
'selection',
301 metaConfig = {
'selectionDecorNames' : [alg.selectionDecoration],
302 'selectionDecorNamesOutput' : [alg.selectionDecoration],
303 'selectionDecorCount' : [1]},
304 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
307 if chargeIDSelection:
309 'ElectronChargeIDSelectionAlg' + postfix )
310 alg.selectionDecoration =
'chargeID' + postfix +
',as_bits'
312 'AsgElectronChargeIDSelectorTool' )
313 alg.selectionTool.TrainingFile = \
314 'ElectronPhotonSelectorTools/ChargeID/ECIDS_20180731rel21Summer2018.root'
315 alg.selectionTool.WorkingPoint =
'Loose'
316 alg.selectionTool.CutOnBDT = -0.337671
317 seq.append( alg, inputPropName =
'particles',
318 stageName =
'selection',
319 metaConfig = {
'selectionDecorNames' : [alg.selectionDecoration],
320 'selectionDecorNamesOutput' : [alg.selectionDecoration],
321 'selectionDecorCount' : [1]},
322 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
327 'ElectronEfficiencyCorrectionAlg' + postfix )
329 'AsgElectronEfficiencyCorrectionTool' )
330 alg.scaleFactorDecoration =
'effSF' + postfix +
'_%SYS%'
331 alg.efficiencyCorrectionTool.RecoKey =
"Reconstruction"
332 alg.efficiencyCorrectionTool.CorrelationModel =
"TOTAL"
333 if dataType ==
'afii':
334 alg.efficiencyCorrectionTool.ForceDataType = (
335 PATCore.ParticleDataType.Full
if forceFullSimConfig
336 else PATCore.ParticleDataType.Fast)
337 elif dataType ==
'mc':
338 alg.efficiencyCorrectionTool.ForceDataType = \
339 PATCore.ParticleDataType.Full
341 alg.outOfValidity = 2
342 alg.outOfValidityDeco =
'bad_eff' + postfix
343 if dataType !=
'data':
344 seq.append( alg, inputPropName =
'electrons',
345 stageName =
'efficiency',
346 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNamesOutput"])} )
351 'ElectronSelectionSummary' + postfix )
352 alg.selectionDecoration =
'baselineSelection' + postfix +
',as_char'
353 seq.append( alg, inputPropName =
'particles',
354 stageName =
'selection',
355 dynConfig = {
'preselection' :
lambda meta :
"&&".join (meta[
"selectionDecorNames"])} )