ATLAS Offline Software
Loading...
Searching...
No Matches
PhotonAnalysisConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2
3# AnaAlgorithm import(s):
4from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
5from AthenaCommon.SystemOfUnits import GeV
6from AthenaConfiguration.Enums import LHCPeriod
7from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
8from AthenaCommon.Logging import logging
9
10import ROOT
11
12# E/gamma import(s).
13from xAODEgamma.xAODEgammaParameters import xAOD
14
16
17class PhotonCalibrationConfig (ConfigBlock) :
18 """the ConfigBlock for the photon four-momentum correction"""
19
20 def __init__ (self) :
21 super (PhotonCalibrationConfig, self).__init__ ()
22 self.setBlockName('Photons')
23 self.addOption ('containerName', '', type=str,
24 noneAction='error',
25 info="the name of the output container after calibration.")
26 self.addOption ('ESModel', '', type=str,
27 info="flag for EGamma calibration. If left empty, uses the current recommendations.")
28 self.addOption ('decorrelationModel', '1NP_v1', type=str,
29 info="decorrelation model for the EGamma energy scale. Supported choices are: `FULL_v1`, `1NP_v1`.")
30 self.addOption ('postfix', '', type=str,
31 info="a postfix to apply to decorations and algorithm names. "
32 "Typically not needed here since the calibration is common to "
33 "all photons.")
34 self.addOption ('crackVeto', False, type=bool,
35 info=r"whether to perform LAr crack veto based on the cluster $\eta$, "
36 r"i.e. remove photons within $1.37<\vert\eta\vert<1.52$.")
37 self.addOption ('enableCleaning', True, type=bool,
38 info="whether to enable photon cleaning (`DFCommonPhotonsCleaning`).")
39 self.addOption ('cleaningAllowLate', False, type=bool,
40 info="whether to ignore timing information in cleaning "
41 "(`DFCommonPhotonsCleaningNoTime`).")
42 self.addOption ('recomputeIsEM', False, type=bool,
43 info="whether to recompute the photon shower shape fudge "
44 "corrections (sets up an instance of `CP::PhotonShowerShapeFudgeAlg`) or rely on derivation flags.")
45 self.addOption ('recalibratePhyslite', True, type=bool,
46 info="whether to run the `CP::EgammaCalibrationAndSmearingAlg` on "
47 "PHYSLITE derivations.")
48 self.addOption ('minPt', 10*GeV, type=float,
49 info=r"the minimum $p_\mathrm{T}$ cut to apply to calibrated photons.")
50 self.addOption ('maxEta', 2.37, type=float,
51 info=r"maximum photon $\vert\eta\vert$.")
52 self.addOption ('forceFullSimConfigForP4', False, type=bool,
53 info="whether to force the tool to use the configuration meant for "
54 "full simulation samples for 4-vector corrections. Only for testing purposes.")
55 self.addOption ('forceFullSimConfigForIso', False, type=bool,
56 info="whether to force the tool to use the configuration meant for "
57 "full simulation samples for isolation corrections. Only for testing purposes.")
58 self.addOption ('applyIsolationCorrection', True, type=bool,
59 info="whether to apply the isolation corrections.")
60 self.addOption ('splitCalibrationAndSmearing', False, type=bool,
61 info="EXPERIMENTAL: This splits the `EgammaCalibrationAndSmearingTool` "
62 " into two steps. The first step applies a baseline calibration that "
63 "is not affected by systematics. The second step then applies the "
64 "systematics dependent corrections. The net effect is that the "
65 "slower first step only has to be run once, while the second is run "
66 "once per systematic. ATLASG-2358.",
67 expertMode=True)
68 self.addOption ('decorateTruth', False, type=bool,
69 info="decorate the truth particle information on the reconstructed one.")
70 self.addOption ('decorateCaloClusterEta', False, type=bool,
71 info=r"decorate the calo-cluster $\eta$.")
72 self.addOption ('decorateEmva', False, type=bool,
73 info="decorate `E_mva_only` on the photons (needed for columnar tools/PHYSLITE).")
74
75 def instanceName (self) :
76 """Return the instance name for this block"""
77 return self.containerName + self.postfix
78
79
80 def makeCalibrationAndSmearingAlg (self, config, name) :
81 """Create the calibration and smearing algorithm
82
83 Factoring this out into its own function, as we want to
84 instantiate it in multiple places"""
85 log = logging.getLogger('PhotonCalibrationConfig')
86
87 # Set up the calibration and smearing algorithm:
88 alg = config.createAlgorithm( 'CP::EgammaCalibrationAndSmearingAlg', name )
89 config.addPrivateTool( 'calibrationAndSmearingTool',
90 'CP::EgammaCalibrationAndSmearingTool' )
91 # Set default ESModel per period
92 if self.ESModel:
93 alg.calibrationAndSmearingTool.ESModel = self.ESModel
94 else:
95 if config.geometry() is LHCPeriod.Run2:
96 alg.calibrationAndSmearingTool.ESModel = 'es2023_R22_Run2_v1'
97 elif config.geometry() is LHCPeriod.Run3:
98 alg.calibrationAndSmearingTool.ESModel = 'es2024_Run3_v0'
99 elif config.geometry() is LHCPeriod.Run4:
100 log.warning("No ESModel set for Run4, using Run3 model")
101 alg.calibrationAndSmearingTool.ESModel = 'es2024_Run3_v0'
102 else:
103 raise ValueError (f"Can't set up the ElectronCalibrationConfig with {config.geometry().value}, "
104 "there must be something wrong!")
105
106 alg.calibrationAndSmearingTool.decorrelationModel = self.decorrelationModel
107 alg.calibrationAndSmearingTool.useFastSim = (
109 else int( config.dataType() is DataType.FastSim ))
110 alg.calibrationAndSmearingTool.decorateEmva = self.decorateEmva
111 alg.egammas = config.readName (self.containerName)
112 alg.egammasOut = config.copyName (self.containerName)
113 alg.preselection = config.getPreselection (self.containerName, '')
114 return alg
115
116
117 def makeAlgs (self, config) :
118
119 log = logging.getLogger('PhotonCalibrationConfig')
120
121 postfix = self.postfix
122 if postfix != '' and postfix[0] != '_' :
123 postfix = '_' + postfix
124
126 log.warning("You are running PhotonCalibrationConfig forcing full sim config for P4 corrections")
127 log.warning("This is only intended to be used for testing purposes")
128
129 if config.isPhyslite() :
130 config.setSourceName (self.containerName, "AnalysisPhotons")
131 else :
132 config.setSourceName (self.containerName, "Photons")
133
134 cleaningWP = 'NoTime' if self.cleaningAllowLate else ''
135
136 # Decorate calo cluster eta if required
138 alg = config.createAlgorithm( 'CP::EgammaCaloClusterEtaAlg',
139 'ElectronEgammaCaloClusterEtaAlg',
140 reentrant=True )
141 alg.particles = config.readName(self.containerName)
142 config.addOutputVar (self.containerName, 'caloEta2', 'caloEta2', noSys=True)
143
144 # Set up a shallow copy to decorate
145 if config.wantCopy (self.containerName) :
146 alg = config.createAlgorithm( 'CP::AsgShallowCopyAlg', 'PhotonShallowCopyAlg' )
147 alg.input = config.readName (self.containerName)
148 alg.output = config.copyName (self.containerName)
149
150 # Set up the eta-cut on all photons prior to everything else
151 alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'PhotonEtaCutAlg' )
152 alg.selectionDecoration = 'selectEta' + postfix + ',as_bits'
153 config.addPrivateTool( 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
154 alg.selectionTool.maxEta = self.maxEta
155 if self.crackVeto:
156 alg.selectionTool.etaGapLow = 1.37
157 alg.selectionTool.etaGapHigh = 1.52
158 alg.selectionTool.useClusterEta = True
159 alg.particles = config.readName (self.containerName)
160 alg.preselection = config.getPreselection (self.containerName, '')
161 config.addSelection (self.containerName, '', alg.selectionDecoration)
162
163 # Setup shower shape fudge
164 if self.recomputeIsEM and config.dataType() is DataType.FullSim:
165 alg = config.createAlgorithm( 'CP::PhotonShowerShapeFudgeAlg',
166 'PhotonShowerShapeFudgeAlg' )
167 config.addPrivateTool( 'showerShapeFudgeTool',
168 'ElectronPhotonVariableCorrectionTool' )
169 if config.geometry is LHCPeriod.Run2:
170 alg.showerShapeFudgeTool.ConfigFile = \
171 'EGammaVariableCorrection/TUNE25/ElPhVariableNominalCorrection.conf'
172 if config.geometry is LHCPeriod.Run3:
173 alg.showerShapeFudgeTool.ConfigFile = \
174 'EGammaVariableCorrection/TUNE23/ElPhVariableNominalCorrection.conf'
175 alg.photons = config.readName (self.containerName)
176 alg.photonsOut = config.copyName (self.containerName)
177 alg.preselection = config.getPreselection (self.containerName, '')
178
179 # Select photons only with good object quality.
180 alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'PhotonObjectQualityAlg' )
181 alg.selectionDecoration = 'goodOQ,as_bits'
182 config.addPrivateTool( 'selectionTool', 'CP::EgammaIsGoodOQSelectionTool' )
183 alg.selectionTool.Mask = xAOD.EgammaParameters.BADCLUSPHOTON
184 alg.particles = config.readName (self.containerName)
185 alg.preselection = config.getPreselection (self.containerName, '')
186 config.addSelection (self.containerName, '', alg.selectionDecoration)
187
188 # Select clean photons
190 alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'PhotonCleaningAlg' )
191 config.addPrivateTool( 'selectionTool', 'CP::AsgFlagSelectionTool' )
192 alg.selectionDecoration = 'isClean,as_bits'
193 alg.selectionTool.selectionFlags = ['DFCommonPhotonsCleaning' + cleaningWP]
194 alg.particles = config.readName (self.containerName)
195 alg.preselection = config.getPreselection (self.containerName, '')
196 config.addSelection (self.containerName, '', alg.selectionDecoration)
197
198 # Change the origin of Photons from (0,0,0) to (0,0,z)
199 # where z comes from the position of a vertex
200 # Default the one tagged as Primary
201 alg = config.createAlgorithm( 'CP::PhotonOriginCorrectionAlg',
202 'PhotonOriginCorrectionAlg',
203 reentrant=True )
204 alg.photons = config.readName (self.containerName)
205 alg.photonsOut = config.copyName (self.containerName)
206 alg.preselection = config.getPreselection (self.containerName, '')
207
209 # Set up the calibration and smearing algorithm:
210 alg = self.makeCalibrationAndSmearingAlg (config, 'PhotonCalibrationAndSmearingAlg')
211 if config.isPhyslite() and not self.recalibratePhyslite :
212 alg.skipNominal = True
213 else:
214 # This splits the EgammaCalibrationAndSmearingTool into two
215 # steps. The first step applies a baseline calibration that
216 # is not affected by systematics. The second step then
217 # applies the systematics dependent corrections. The net
218 # effect is that the slower first step only has to be run
219 # once, while the second is run once per systematic.
220 #
221 # For now (22 May 24) this has to happen in the same job, as
222 # the output of the first step is not part of PHYSLITE, and
223 # even for the nominal the output of the first and second
224 # step are different. In the future the plan is to put both
225 # the output of the first and second step into PHYSLITE,
226 # allowing to skip the first step when running on PHYSLITE.
227 #
228 # WARNING: All of this is experimental, see: ATLASG-2358
229
230 # Set up the calibration algorithm:
231 alg = self.makeCalibrationAndSmearingAlg (config, 'PhotonBaseCalibrationAlg')
232 # turn off systematics for the calibration step
233 alg.noToolSystematics = True
234 # turn off smearing for the calibration step
235 alg.calibrationAndSmearingTool.doSmearing = False
236
237 # Set up the smearing algorithm:
238 alg = self.makeCalibrationAndSmearingAlg (config, 'PhotonCalibrationSystematicsAlg')
239 # turn off scale corrections for the smearing step
240 alg.calibrationAndSmearingTool.doScaleCorrection = False
241 alg.calibrationAndSmearingTool.useMVACalibration = False
242 alg.calibrationAndSmearingTool.decorateEmva = False
243
245 log.warning("You are not applying the isolation corrections")
246 log.warning("This is only intended to be used for testing purposes")
247
248 if self.minPt > 0:
249
250 # Set up the the pt selection
251 alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'PhotonPtCutAlg' )
252 alg.selectionDecoration = 'selectPt' + postfix + ',as_bits'
253 config.addPrivateTool( 'selectionTool', 'CP::AsgPtEtaSelectionTool' )
254 alg.selectionTool.minPt = self.minPt
255 alg.particles = config.readName (self.containerName)
256 alg.preselection = config.getPreselection (self.containerName, '')
257 config.addSelection (self.containerName, '', alg.selectionDecoration,
258 preselection=True)
259
260 # Set up the isolation correction algorithm.
262
264 log.warning("You are running PhotonCalibrationConfig forcing full sim config for isolation corrections")
265 log.warning("This is only intended to be used for testing purposes")
266
267 alg = config.createAlgorithm( 'CP::EgammaIsolationCorrectionAlg',
268 'PhotonIsolationCorrectionAlg' )
269 config.addPrivateTool( 'isolationCorrectionTool',
270 'CP::IsolationCorrectionTool' )
271 alg.isolationCorrectionTool.IsMC = config.dataType() is not DataType.Data
272 alg.isolationCorrectionTool.AFII_corr = (
274 else config.dataType() is DataType.FastSim)
275 alg.isolationCorrectionTool.FixTimingIssueInCore = True
276 alg.egammas = config.readName (self.containerName)
277 alg.egammasOut = config.copyName (self.containerName)
278 alg.preselection = config.getPreselection (self.containerName, '')
279
280 # Additional decorations
281 alg = config.createAlgorithm( 'CP::AsgEnergyDecoratorAlg', 'EnergyDecorator' )
282 alg.particles = config.readName (self.containerName)
283
284 config.addOutputVar (self.containerName, 'pt', 'pt')
285 config.addOutputVar (self.containerName, 'eta', 'eta', noSys=True)
286 config.addOutputVar (self.containerName, 'phi', 'phi', noSys=True)
287 config.addOutputVar (self.containerName, 'e_%SYS%', 'e')
288 config.addOutputVar (self.containerName, 'caloClusterEnergyReso_%SYS%', 'caloClusterEnergyReso', noSys=True)
289
290 # decorate truth information on the reconstructed object:
291 if self.decorateTruth and config.dataType() is not DataType.Data:
292 config.addOutputVar (self.containerName, "truthType", "truth_type", noSys=True)
293 config.addOutputVar (self.containerName, "truthOrigin", "truth_origin", noSys=True)
294
295
296class PhotonWorkingPointConfig (ConfigBlock) :
297 """the ConfigBlock for the photon working point
298
299 This may at some point be split into multiple blocks (29 Aug 22)."""
300
301 def __init__ (self) :
302 super (PhotonWorkingPointConfig, self).__init__ ()
303 self.addOption ('containerName', '', type=str,
304 noneAction='error',
305 info="the name of the input container.")
306 self.addOption ('selectionName', '', type=str,
307 noneAction='error',
308 info="the name of the photon selection to define (e.g. `tight` or "
309 "`loose`).")
310 self.addOption ('postfix', None, type=str,
311 info="a postfix to apply to decorations and algorithm names. "
312 "Typically not needed here as selectionName is used internally.")
313 self.addOption ('qualityWP', None, type=str,
314 info="the ID WP to use. Supported ID WPs: `Tight`, `Medium`, `Loose`.")
315 self.addOption ('isolationWP', None, type=str,
316 info="the isolation WP to use. Supported isolation WPs: "
317 "`FixedCutLoose`, `FixedCutTight`, `TightCaloOnly`, `NonIso`.")
318 self.addOption ('addSelectionToPreselection', True, type=bool,
319 info="whether to retain only photons satisfying the working point "
320 "requirements.")
321 self.addOption ('closeByCorrection', False, type=bool,
322 info="whether to use close-by-corrected isolation working points.")
323 self.addOption ('recomputeIsEM', False, type=bool,
324 info="whether to rerun the cut-based selection, or rely on derivation flags.")
325 self.addOption ('doFSRSelection', False, type=bool,
326 info="whether to accept additional photons close to muons for the "
327 "purpose of FSR corrections to these muons. Expert feature "
328 "requested by the H4l analysis running on PHYSLITE.",
329 expertMode=True)
330 self.addOption ('noEffSFForID', False, type=bool,
331 info="disables the calculation of ID efficiencies and scale factors. "
332 "Experimental! only useful to test a new WP for which scale "
333 "factors are not available.",
334 expertMode=True)
335 self.addOption ('noEffSFForIso', False, type=bool,
336 info="disables the calculation of isolation efficiencies and scale factors. "
337 "Experimental! only useful to test a new WP for which scale "
338 "factors are not available.",
339 expertMode=True)
340 self.addOption ('saveDetailedSF', True, type=bool,
341 info="save all the independent detailed object scale factors.")
342 self.addOption ('saveCombinedSF', False, type=bool,
343 info="save the combined object scale factor.")
344 self.addOption ('forceFullSimConfigForID', False, type=bool,
345 info="whether to force the ID tool to use the configuration meant "
346 "for full simulation samples. Only for testing purposes.")
347 self.addOption ('forceFullSimConfigForIso', False, type=bool,
348 info="whether to force the isolation tool to use the configuration meant "
349 "for full simulation samples. Only for testing purposes.")
350
351 def instanceName (self) :
352 """Return the instance name for this block"""
353 if self.postfix is not None :
354 return self.containerName + '_' + self.selectionName + self.postfix
355 return self.containerName + '_' + self.selectionName
356
357 def makeAlgs (self, config) :
358
359 log = logging.getLogger('PhotonWorkingPointConfig')
360
361 # The setup below is inappropriate for Run 1
362 if config.geometry() is LHCPeriod.Run1:
363 raise ValueError ("Can't set up the PhotonWorkingPointConfig with %s, there must be something wrong!" % config.geometry().value)
364
366 log.warning("You are running PhotonWorkingPointConfig forcing full sim config for ID")
367 log.warning("This is only intended to be used for testing purposes")
368
370 log.warning("You are running PhotonWorkingPointConfig forcing full sim config for Iso")
371 log.warning("This is only intended to be used for testing purposes")
372
373 postfix = self.postfix
374 if postfix is None :
375 postfix = self.selectionName
376 if postfix != '' and postfix[0] != '_' :
377 postfix = '_' + postfix
378
379 if self.qualityWP == 'Tight' :
380 quality = ROOT.egammaPID.PhotonTight
381 elif self.qualityWP == 'Medium' :
382 quality = ROOT.egammaPID.PhotonMedium
383 elif self.qualityWP == 'Loose' :
384 quality = ROOT.egammaPID.PhotonLoose
385 else :
386 raise Exception ('unknown photon quality working point "' + self.qualityWP + '" should be Tight, Medium or Loose')
387
388 # Set up the photon selection algorithm:
389 alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'PhotonIsEMSelectorAlg' )
390 alg.selectionDecoration = 'selectEM' + postfix + ',as_char'
392 # Rerun the cut-based ID
393 config.addPrivateTool( 'selectionTool', 'AsgPhotonIsEMSelector' )
394 alg.selectionTool.isEMMask = quality
395 if config.geometry() is LHCPeriod.Run2:
396 if self.qualityWP == 'Tight':
397 alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/mc20_20240510/PhotonIsEMTightSelectorCutDefs_pTdep_mc20_smooth.conf'
398 elif self.qualityWP == 'Loose':
399 alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/mc15_20150712/PhotonIsEMLooseSelectorCutDefs.conf'
400 elif self.qualityWP == 'Medium':
401 alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/mc20_20240510/PhotonIsEMMediumSelectorCutDefs_pTdep_smooth.conf'
402 if config.geometry() is LHCPeriod.Run3:
403 if self.qualityWP == 'Tight':
404 alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/20180825/PhotonIsEMTightSelectorCutDefs.conf'
405 elif self.qualityWP == 'Loose':
406 alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/mc15_20150712/PhotonIsEMLooseSelectorCutDefs.conf'
407 elif self.qualityWP == 'Medium':
408 raise ValueError('No Medium menu available for Run-3. Please get in contact with egamma')
409 else:
410 # Select from Derivation Framework flags
411 config.addPrivateTool( 'selectionTool', 'CP::AsgFlagSelectionTool' )
412 dfFlag = 'DFCommonPhotonsIsEM' + self.qualityWP
413 alg.selectionTool.selectionFlags = [ dfFlag ]
414 alg.particles = config.readName (self.containerName)
415 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
416 config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
417 preselection=self.addSelectionToPreselection)
418
419 # Set up the FSR selection
421 # save the flag set for the WP
422 wpFlag = alg.selectionDecoration.split(",")[0]
423 alg = config.createAlgorithm( 'CP::EgammaFSRForMuonsCollectorAlg', 'EgammaFSRForMuonsCollectorAlg')
424 alg.selectionDecoration = wpFlag
425 alg.ElectronOrPhotonContKey = config.readName (self.containerName)
426
427 # Set up the isolation selection algorithm:
428 if self.isolationWP != 'NonIso' :
429 alg = config.createAlgorithm( 'CP::EgammaIsolationSelectionAlg',
430 'PhotonIsolationSelectionAlg' )
431 alg.selectionDecoration = 'isolated' + postfix + ',as_char'
432 config.addPrivateTool( 'selectionTool', 'CP::IsolationSelectionTool' )
433 alg.selectionTool.PhotonWP = self.isolationWP
435 alg.selectionTool.IsoDecSuffix = "CloseByCorr"
436 alg.isPhoton = True
437 alg.egammas = config.readName (self.containerName)
438 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
439 config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
440 preselection=self.addSelectionToPreselection)
441
442 sfList = []
443 # Set up the ID/reco photon efficiency correction algorithm:
444 if config.dataType() is not DataType.Data and not self.noEffSFForID:
445 alg = config.createAlgorithm( 'CP::PhotonEfficiencyCorrectionAlg',
446 'PhotonEfficiencyCorrectionAlgID' )
447 config.addPrivateTool( 'efficiencyCorrectionTool',
448 'AsgPhotonEfficiencyCorrectionTool' )
449 alg.scaleFactorDecoration = 'ph_id_effSF' + postfix + '_%SYS%'
450 if config.dataType() is DataType.FastSim:
451 alg.efficiencyCorrectionTool.ForceDataType = (
452 PATCore.ParticleDataType.Full if self.forceFullSimConfigForID else
453 PATCore.ParticleDataType.Fast)
454 elif config.dataType() is DataType.FullSim:
455 alg.efficiencyCorrectionTool.ForceDataType = \
456 PATCore.ParticleDataType.Full
457 if config.geometry() >= LHCPeriod.Run2:
458 alg.efficiencyCorrectionTool.MapFilePath = 'PhotonEfficiencyCorrection/2015_2025/rel22.2/2024_FinalRun2_Recommendation_v1/map1.txt'
459 alg.outOfValidity = 2 #silent
460 alg.outOfValidityDeco = 'ph_id_bad_eff' + postfix
461 alg.photons = config.readName (self.containerName)
462 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
464 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
465 'id_effSF' + postfix)
466 sfList += [alg.scaleFactorDecoration]
467
468 # Set up the ISO photon efficiency correction algorithm:
469 if config.dataType() is not DataType.Data and self.isolationWP != 'NonIso' and not self.noEffSFForIso:
470 alg = config.createAlgorithm( 'CP::PhotonEfficiencyCorrectionAlg',
471 'PhotonEfficiencyCorrectionAlgIsol' )
472 config.addPrivateTool( 'efficiencyCorrectionTool',
473 'AsgPhotonEfficiencyCorrectionTool' )
474 alg.scaleFactorDecoration = 'ph_isol_effSF' + postfix + '_%SYS%'
475 if config.dataType() is DataType.FastSim:
476 alg.efficiencyCorrectionTool.ForceDataType = (
477 PATCore.ParticleDataType.Full if self.forceFullSimConfigForIso else
478 PATCore.ParticleDataType.Fast)
479 elif config.dataType() is DataType.FullSim:
480 alg.efficiencyCorrectionTool.ForceDataType = \
481 PATCore.ParticleDataType.Full
482 alg.efficiencyCorrectionTool.IsoKey = self.isolationWP.replace("FixedCut","")
483 if config.geometry() >= LHCPeriod.Run2:
484 alg.efficiencyCorrectionTool.MapFilePath = 'PhotonEfficiencyCorrection/2015_2025/rel22.2/2022_Summer_Prerecom_v1/map1.txt'
485 alg.outOfValidity = 2 #silent
486 alg.outOfValidityDeco = 'ph_isol_bad_eff' + postfix
487 alg.photons = config.readName (self.containerName)
488 alg.preselection = config.getPreselection (self.containerName, self.selectionName)
489 if self.saveDetailedSF:
490 config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
491 'isol_effSF' + postfix)
492 sfList += [alg.scaleFactorDecoration]
493
494 doCombEffSF = not self.noEffSFForID or not self.noEffSFForIso
495 if config.dataType() is not DataType.Data and doCombEffSF and self.saveCombinedSF:
496 alg = config.createAlgorithm( 'CP::AsgObjectScaleFactorAlg',
497 'PhotonCombinedEfficiencyScaleFactorAlg' )
498 alg.particles = config.readName (self.containerName)
499 alg.inScaleFactors = sfList
500 alg.outScaleFactor = 'effSF' + postfix + '_%SYS%'
501 config.addOutputVar (self.containerName, alg.outScaleFactor, 'effSF' + postfix)
502
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition hcg.cxx:310