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