ATLAS Offline Software
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):
4 from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
5 from AthenaCommon.SystemOfUnits import GeV
6 from AthenaConfiguration.Enums import LHCPeriod
7 from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
8 from AthenaCommon.Logging import logging
9 
10 import ROOT
11 
12 # E/gamma import(s).
13 from xAODEgamma.xAODEgammaParameters import xAOD
14 
16 
17 class 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 = (
116  0 if self.forceFullSimConfigForP4
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 
133  if self.forceFullSimConfigForP4:
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
145  if self.decorateCaloClusterEta:
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
197  if self.enableCleaning:
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 
216  if not self.splitCalibrationAndSmearing :
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 
252  if not self.applyIsolationCorrection:
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.
269  if self.applyIsolationCorrection:
270 
271  if self.forceFullSimConfigForIso:
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 = (
281  0 if self.forceFullSimConfigForIso
282  else config.dataType() is DataType.FastSim)
283  alg.egammas = config.readName (self.containerName)
284  alg.egammasOut = config.copyName (self.containerName)
285  alg.preselection = config.getPreselection (self.containerName, '')
286 
287  # Additional decorations
288  alg = config.createAlgorithm( 'CP::AsgEnergyDecoratorAlg', 'EnergyDecorator' )
289  alg.particles = config.readName (self.containerName)
290 
291  config.addOutputVar (self.containerName, 'pt', 'pt')
292  config.addOutputVar (self.containerName, 'eta', 'eta', noSys=True)
293  config.addOutputVar (self.containerName, 'phi', 'phi', noSys=True)
294  config.addOutputVar (self.containerName, 'e_%SYS%', 'e')
295 
296  # decorate truth information on the reconstructed object:
297  if self.decorateTruth and config.dataType() is not DataType.Data:
298  config.addOutputVar (self.containerName, "truthType", "truth_type", noSys=True)
299  config.addOutputVar (self.containerName, "truthOrigin", "truth_origin", noSys=True)
300 
301 
302 class PhotonWorkingPointConfig (ConfigBlock) :
303  """the ConfigBlock for the photon working point
304 
305  This may at some point be split into multiple blocks (29 Aug 22)."""
306 
307  def __init__ (self) :
308  super (PhotonWorkingPointConfig, self).__init__ ()
309  self.addOption ('containerName', '', type=str,
310  noneAction='error',
311  info="the name of the input container.")
312  self.addOption ('selectionName', '', type=str,
313  noneAction='error',
314  info="the name of the photon selection to define (e.g. tight or "
315  "loose).")
316  self.addOption ('postfix', None, type=str,
317  info="a postfix to apply to decorations and algorithm names. "
318  "Typically not needed here as selectionName is used internally.")
319  self.addOption ('qualityWP', None, type=str,
320  info="the ID WP (string) to use. Supported ID WPs: Tight, Medium and Loose.")
321  self.addOption ('isolationWP', None, type=str,
322  info="the ID WP (string) to use. Supported isolation WPs: "
323  "FixedCutLoose, FixedCutTight, TightCaloOnly, NonIso.")
324  self.addOption ('addSelectionToPreselection', True, type=bool,
325  info="whether to retain only photons satisfying the working point "
326  "requirements. The default is True.")
327  self.addOption ('closeByCorrection', False, type=bool,
328  info="whether to use close-by-corrected isolation working points")
329  self.addOption ('recomputeIsEM', False, type=bool,
330  info="whether to rerun the cut-based selection. The default is "
331  "False, i.e. to use derivation flags.")
332  self.addOption ('doFSRSelection', False, type=bool,
333  info="whether to accept additional photons close to muons for the "
334  "purpose of FSR corrections to these muons. Expert feature "
335  "requested by the H4l analysis running on PHYSLITE. "
336  "The default is False.",
337  expertMode=True)
338  self.addOption ('noEffSFForID', False, type=bool,
339  info="disables the calculation of ID efficiencies and scale factors. "
340  "Experimental! only useful to test a new WP for which scale "
341  "factors are not available. The default is False.",
342  expertMode=True)
343  self.addOption ('noEffSFForIso', False, type=bool,
344  info="disables the calculation of Iso efficiencies and scale factors. "
345  "Experimental! only useful to test a new WP for which scale "
346  "factors are not available. The default is False.",
347  expertMode=True)
348  self.addOption ('saveDetailedSF', True, type=bool,
349  info="save all the independent detailed object scale factors. "
350  "The default is True.")
351  self.addOption ('saveCombinedSF', False, type=bool,
352  info="save the combined object scale factor. "
353  "The default is False.")
354  self.addOption ('forceFullSimConfigForID', False, type=bool,
355  info="whether to force the ID tool to use the configuration meant "
356  "for full simulation samples. Only for testing purposes. "
357  "The default is False.")
358  self.addOption ('forceFullSimConfigForIso', False, type=bool,
359  info="whether to force the Iso tool to use the configuration meant "
360  "for full simulation samples. Only for testing purposes. "
361  "The default is False.")
362 
363  def instanceName (self) :
364  """Return the instance name for this block"""
365  if self.postfix is not None :
366  return self.containerName + '_' + self.selectionName + self.postfix
367  return self.containerName + '_' + self.selectionName
368 
369  def makeAlgs (self, config) :
370 
371  log = logging.getLogger('PhotonWorkingPointConfig')
372 
373  # The setup below is inappropriate for Run 1
374  if config.geometry() is LHCPeriod.Run1:
375  raise ValueError ("Can't set up the PhotonWorkingPointConfig with %s, there must be something wrong!" % config.geometry().value)
376 
377  if self.forceFullSimConfigForID:
378  log.warning("You are running PhotonWorkingPointConfig forcing full sim config for ID")
379  log.warning("This is only intended to be used for testing purposes")
380 
381  if self.forceFullSimConfigForIso:
382  log.warning("You are running PhotonWorkingPointConfig forcing full sim config for Iso")
383  log.warning("This is only intended to be used for testing purposes")
384 
385  postfix = self.postfix
386  if postfix is None :
387  postfix = self.selectionName
388  if postfix != '' and postfix[0] != '_' :
389  postfix = '_' + postfix
390 
391  if self.qualityWP == 'Tight' :
392  quality = ROOT.egammaPID.PhotonTight
393  elif self.qualityWP == 'Medium' :
394  quality = ROOT.egammaPID.PhotonMedium
395  elif self.qualityWP == 'Loose' :
396  quality = ROOT.egammaPID.PhotonLoose
397  else :
398  raise Exception ('unknown photon quality working point "' + self.qualityWP + '" should be Tight, Medium or Loose')
399 
400  # Set up the photon selection algorithm:
401  alg = config.createAlgorithm( 'CP::AsgSelectionAlg', 'PhotonIsEMSelectorAlg' )
402  alg.selectionDecoration = 'selectEM' + postfix + ',as_char'
403  if self.recomputeIsEM:
404  # Rerun the cut-based ID
405  config.addPrivateTool( 'selectionTool', 'AsgPhotonIsEMSelector' )
406  alg.selectionTool.isEMMask = quality
407  if config.geometry() is LHCPeriod.Run2:
408  if self.qualityWP == 'Tight':
409  alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/mc20_20240510/PhotonIsEMTightSelectorCutDefs_pTdep_mc20_smooth.conf'
410  elif self.qualityWP == 'Loose':
411  alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/mc15_20150712/PhotonIsEMLooseSelectorCutDefs.conf'
412  elif self.qualityWP == 'Medium':
413  alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/mc20_20240510/PhotonIsEMMediumSelectorCutDefs_pTdep_smooth.conf'
414  if config.geometry() is LHCPeriod.Run3:
415  if self.qualityWP == 'Tight':
416  alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/20180825/PhotonIsEMTightSelectorCutDefs.conf'
417  elif self.qualityWP == 'Loose':
418  alg.selectionTool.ConfigFile = 'ElectronPhotonSelectorTools/offline/mc15_20150712/PhotonIsEMLooseSelectorCutDefs.conf'
419  elif self.qualityWP == 'Medium':
420  raise ValueError('No Medium menu available for Run-3. Please get in contact with egamma')
421  else:
422  # Select from Derivation Framework flags
423  config.addPrivateTool( 'selectionTool', 'CP::AsgFlagSelectionTool' )
424  dfFlag = 'DFCommonPhotonsIsEM' + self.qualityWP
425  alg.selectionTool.selectionFlags = [ dfFlag ]
426  alg.particles = config.readName (self.containerName)
427  alg.preselection = config.getPreselection (self.containerName, self.selectionName)
428  config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
429  preselection=self.addSelectionToPreselection)
430 
431  # Set up the FSR selection
432  if self.doFSRSelection :
433  # save the flag set for the WP
434  wpFlag = alg.selectionDecoration.split(",")[0]
435  alg = config.createAlgorithm( 'CP::EgammaFSRForMuonsCollectorAlg', 'EgammaFSRForMuonsCollectorAlg')
436  alg.selectionDecoration = wpFlag
437  alg.ElectronOrPhotonContKey = config.readName (self.containerName)
438 
439  # Set up the isolation selection algorithm:
440  if self.isolationWP != 'NonIso' :
441  alg = config.createAlgorithm( 'CP::EgammaIsolationSelectionAlg',
442  'PhotonIsolationSelectionAlg' )
443  alg.selectionDecoration = 'isolated' + postfix + ',as_char'
444  config.addPrivateTool( 'selectionTool', 'CP::IsolationSelectionTool' )
445  alg.selectionTool.PhotonWP = self.isolationWP
446  if self.closeByCorrection:
447  alg.selectionTool.IsoDecSuffix = "CloseByCorr"
448  alg.isPhoton = True
449  alg.egammas = config.readName (self.containerName)
450  alg.preselection = config.getPreselection (self.containerName, self.selectionName)
451  config.addSelection (self.containerName, self.selectionName, alg.selectionDecoration,
452  preselection=self.addSelectionToPreselection)
453 
454  sfList = []
455  # Set up the ID/reco photon efficiency correction algorithm:
456  if config.dataType() is not DataType.Data and not self.noEffSFForID:
457  alg = config.createAlgorithm( 'CP::PhotonEfficiencyCorrectionAlg',
458  'PhotonEfficiencyCorrectionAlgID' )
459  config.addPrivateTool( 'efficiencyCorrectionTool',
460  'AsgPhotonEfficiencyCorrectionTool' )
461  alg.scaleFactorDecoration = 'ph_id_effSF' + postfix + '_%SYS%'
462  if config.dataType() is DataType.FastSim:
463  alg.efficiencyCorrectionTool.ForceDataType = (
464  PATCore.ParticleDataType.Full if self.forceFullSimConfigForID else
465  PATCore.ParticleDataType.Fast)
466  elif config.dataType() is DataType.FullSim:
467  alg.efficiencyCorrectionTool.ForceDataType = \
468  PATCore.ParticleDataType.Full
469  if config.geometry() >= LHCPeriod.Run2:
470  alg.efficiencyCorrectionTool.MapFilePath = 'PhotonEfficiencyCorrection/2015_2025/rel22.2/2024_FinalRun2_Recommendation_v1/map1.txt'
471  alg.outOfValidity = 2 #silent
472  alg.outOfValidityDeco = 'ph_id_bad_eff' + postfix
473  alg.photons = config.readName (self.containerName)
474  alg.preselection = config.getPreselection (self.containerName, self.selectionName)
475  if self.saveDetailedSF:
476  config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
477  'id_effSF' + postfix)
478  sfList += [alg.scaleFactorDecoration]
479 
480  # Set up the ISO photon efficiency correction algorithm:
481  if config.dataType() is not DataType.Data and self.isolationWP != 'NonIso' and not self.noEffSFForIso:
482  alg = config.createAlgorithm( 'CP::PhotonEfficiencyCorrectionAlg',
483  'PhotonEfficiencyCorrectionAlgIsol' )
484  config.addPrivateTool( 'efficiencyCorrectionTool',
485  'AsgPhotonEfficiencyCorrectionTool' )
486  alg.scaleFactorDecoration = 'ph_isol_effSF' + postfix + '_%SYS%'
487  if config.dataType() is DataType.FastSim:
488  alg.efficiencyCorrectionTool.ForceDataType = (
489  PATCore.ParticleDataType.Full if self.forceFullSimConfigForIso else
490  PATCore.ParticleDataType.Fast)
491  elif config.dataType() is DataType.FullSim:
492  alg.efficiencyCorrectionTool.ForceDataType = \
493  PATCore.ParticleDataType.Full
494  alg.efficiencyCorrectionTool.IsoKey = self.isolationWP.replace("FixedCut","")
495  if config.geometry() >= LHCPeriod.Run2:
496  alg.efficiencyCorrectionTool.MapFilePath = 'PhotonEfficiencyCorrection/2015_2025/rel22.2/2022_Summer_Prerecom_v1/map1.txt'
497  alg.outOfValidity = 2 #silent
498  alg.outOfValidityDeco = 'ph_isol_bad_eff' + postfix
499  alg.photons = config.readName (self.containerName)
500  alg.preselection = config.getPreselection (self.containerName, self.selectionName)
501  if self.saveDetailedSF:
502  config.addOutputVar (self.containerName, alg.scaleFactorDecoration,
503  'isol_effSF' + postfix)
504  sfList += [alg.scaleFactorDecoration]
505 
506  doCombEffSF = not self.noEffSFForID or not self.noEffSFForIso
507  if config.dataType() is not DataType.Data and doCombEffSF and self.saveCombinedSF:
508  alg = config.createAlgorithm( 'CP::AsgObjectScaleFactorAlg',
509  'PhotonCombinedEfficiencyScaleFactorAlg' )
510  alg.particles = config.readName (self.containerName)
511  alg.inScaleFactors = sfList
512  alg.outScaleFactor = 'effSF' + postfix + '_%SYS%'
513  config.addOutputVar (self.containerName, alg.outScaleFactor, 'effSF' + postfix)
514 
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
python.PhotonAnalysisConfig.PhotonWorkingPointConfig.__init__
def __init__(self)
Definition: PhotonAnalysisConfig.py:307
SystemOfUnits
PATCore::ParticleDataType
Definition: PATCoreEnums.h:21
python.PhotonAnalysisConfig.PhotonCalibrationConfig.__init__
def __init__(self)
Definition: PhotonAnalysisConfig.py:20
python.PhotonAnalysisConfig.PhotonWorkingPointConfig
Definition: PhotonAnalysisConfig.py:302
python.PhotonAnalysisConfig.PhotonCalibrationConfig.makeAlgs
def makeAlgs(self, config)
Definition: PhotonAnalysisConfig.py:125
python.PhotonAnalysisConfig.PhotonWorkingPointConfig.makeAlgs
def makeAlgs(self, config)
Definition: PhotonAnalysisConfig.py:369
python.PhotonAnalysisConfig.PhotonCalibrationConfig.instanceName
def instanceName(self)
Definition: PhotonAnalysisConfig.py:83
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
python.PhotonAnalysisConfig.PhotonWorkingPointConfig.instanceName
def instanceName(self)
Definition: PhotonAnalysisConfig.py:363
python.PhotonAnalysisConfig.PhotonCalibrationConfig
Definition: PhotonAnalysisConfig.py:17
python.PhotonAnalysisConfig.PhotonWorkingPointConfig.qualityWP
qualityWP
Definition: PhotonAnalysisConfig.py:391
python.PhotonAnalysisConfig.PhotonCalibrationConfig.makeCalibrationAndSmearingAlg
def makeCalibrationAndSmearingAlg(self, config, name)
Definition: PhotonAnalysisConfig.py:88