ATLAS Offline Software
JetUncertaintiesConfig.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 
4 
5 # AnaAlgorithm import(s):
6 from AnalysisAlgorithmsConfig.ConfigBlock import ConfigBlock
7 from AnalysisAlgorithmsConfig.ConfigAccumulator import DataType
8 from AthenaConfiguration.Enums import LHCPeriod
9 from AthenaCommon.Logging import logging
10 import re
11 
12 
13 class JetUncertaintiesConfig (ConfigBlock) :
14  """the ConfigBlock for the common preprocessing of jet uncertainties"""
15 
16  def __init__ (self) :
17  super (JetUncertaintiesConfig, self).__init__ ()
18  self.setBlockName('Uncertainties')
19  self.addDependency('OverlapRemoval', required=False)
20  self.addOption ('containerName', '', type=str,
21  noneAction='error',
22  info="the name of the output container after calibration.")
23  self.addOption ('jetInput', '', type=str,
24  noneAction='error',
25  info="")
26  self.addOption('analysisJetSelection', '', type=str,
27  info="the jet selection to use to calculate N jets for an analysis specific "
28  "jet flavor composition uncertainty. Of the form jvt_selection,as_char&&passesOR,as_char...")
29  self.addOption('analysisFile', '', type=str,
30  info="the file containing gluon fraction histograms needed to calculate an analysis specific "
31  "jet flavor composition uncertainty.")
32  self.addOption ('largeRMass', "Comb", type=str,
33  info="")
34  self.addOption ('systematicsModelJES', "Category", type=str,
35  info="the NP reduction scheme to use for JES: All, Global, Category, "
36  "Scenario. The default is Category.")
37  self.addOption ('systematicsModelJER', "Full", type=str,
38  info="the NP reduction scheme to use for JER: All, Full, Simple. The "
39  "default is Full.")
40  self.addOption ('systematicsModelJMS', "Full", type=str)
41  self.addOption ('systematicsModelJMR', "Full", type=str,
42  info="the NP reduction scheme to use for JMR: Full, Simple. The default is Full.")
43  self.addOption ('runJERsystematicsOnData', False, type=bool,
44  info="whether to run the All/Full JER model variations also on data samples. Expert option!")
45  # Uncertainties tool options
46  self.addOption ('uncertToolConfigPath', None, type=str,
47  info="name (str) of the config file to use for the jet uncertainty "
48  "tool. Expert option to override JetETmiss recommendations. The "
49  "default is None.")
50  self.addOption ('uncertToolCalibArea', None, type=str,
51  info="name (str) of the CVMFS area to use for the jet uncertainty "
52  "tool. Expert option to override JetETmiss recommendations. The "
53  "default is None.")
54  self.addOption ('uncertToolMCType', None, type=str,
55  info="data type (str) to use for the jet uncertainty tool (e.g. "
56  "'AF3' or 'MC16'). Expert option to override JetETmiss "
57  "recommendations. The default is None.")
58 
59  def instanceName (self) :
60  """Return the instance name for this block"""
61  return self.containerName
62 
64 
65  # Retrieve appropriate JES/JER recommendations for the JetUncertaintiesTool.
66  # We do this separately from the tool declaration, as we may need to set uo
67  # two such tools, but they have to be private.
68 
69  # Config file:
70  config_file = None
71  if self.systematicsModelJES == "All" and self.systematicsModelJER == "All":
72  config_file = "R4_AllNuisanceParameters_AllJERNP.config"
73  elif "Scenario" in self.systematicsModelJES:
74  if self.systematicsModelJER != "Simple":
75  raise ValueError(
76  "Invalid uncertainty configuration - Scenario* systematicsModelJESs can "
77  "only be used together with the Simple systematicsModelJER")
78  config_file = "R4_{0}_SimpleJER.config".format(self.systematicsModelJES)
79  elif self.systematicsModelJES in ["Global", "Category"] and self.systematicsModelJER in ["Simple", "Full"]:
80  config_file = "R4_{0}Reduction_{1}JER.config".format(self.systematicsModelJES, self.systematicsModelJER)
81  else:
82  raise ValueError(
83  "Invalid combination of systematicsModelJES and systematicsModelJER settings: "
84  "systematicsModelJES: {0}, systematicsModelJER: {1}".format(self.systematicsModelJES, self.systematicsModelJER) )
85 
86  # Calibration area:
87  calib_area = None
88  if self.uncertToolCalibArea is not None:
89  calib_area = self.uncertToolCalibArea
90 
91  # Expert override for config path:
92  if self.uncertToolConfigPath is not None:
93  config_file = self.uncertToolConfigPath
94  else:
95  if config.geometry() is LHCPeriod.Run2:
96  if config.dataType() is DataType.FastSim:
97  config_file = "rel22/Fall2024_PreRec/" + config_file
98  else:
99  if self.jetInput == "HI":
100  config_file = "HIJetUncertainties/Spring2023/HI" + config_file
101  else:
102  config_file = "rel22/Summer2023_PreRec/" + config_file
103  else:
104  if config.dataType() is DataType.FastSim:
105  config_file = "rel22/Winter2025_AF3_PreRec/" + config_file
106  else:
107  if self.jetInput == "HI":
108  config_file = "HIJetUncertainties/Spring2023/HI" + config_file
109  else:
110  config_file = "rel22/Winter2025_PreRec/" + config_file
111 
112  # MC type:
113  mc_type = None
114  if self.uncertToolMCType is not None:
115  mc_type = self.uncertToolMCType
116  else:
117  if config.geometry() is LHCPeriod.Run2:
118  if config.dataType() is DataType.FastSim:
119  mc_type = "AF3"
120  else:
121  mc_type = "MC20"
122  else:
123  if config.dataType() is DataType.FastSim:
124  mc_type = "MC23AF3"
125  else:
126  if self.jetInput == "HI":
127  mc_type = "MC16"
128  else:
129  mc_type = "MC23"
130 
131  return config_file, calib_area, mc_type
132 
133 
134  def createUncertaintyToolSmallRJets(self, jetUncertaintiesAlg, config, jetCollectionName, doPseudoData=False):
135 
136  # Create an instance of JetUncertaintiesTool, following JetETmiss recommendations.
137  # To run Jet Energy Resolution (JER) uncertainties in the "Full" or "All" schemes,
138  # we need two sets of tools: one configured as normal (MC), the other with the
139  # exact same settings but pretending to run on data (pseudo-data).
140  # This is achieved by passing "isPseudoData=True" to the arguments.
141 
142  # Retrieve the common configuration settings
143  configFile, calibArea, mcType = self.getUncertaintyToolSettingsSmallRJets(config)
144 
145  # The main tool for all JES+JER combinations
146  config.addPrivateTool( 'uncertaintiesTool', 'JetUncertaintiesTool' )
147  jetUncertaintiesAlg.uncertaintiesTool.JetDefinition = jetCollectionName[:-4]
148  jetUncertaintiesAlg.uncertaintiesTool.ConfigFile = configFile
149  if calibArea is not None:
150  jetUncertaintiesAlg.uncertaintiesTool.CalibArea = calibArea
151  jetUncertaintiesAlg.uncertaintiesTool.MCType = mcType
152  jetUncertaintiesAlg.uncertaintiesTool.IsData = (config.dataType() is DataType.Data)
153  jetUncertaintiesAlg.uncertaintiesTool.PseudoDataJERsmearingMode = False
154 
155  if config.dataType() is DataType.Data and not (doPseudoData and self.runJERsystematicsOnData):
156  # we don't want any systematics on data if we're not using the right JER model!
157  jetUncertaintiesAlg.affectingSystematicsFilter = '.*'
158  if config.dataType() is not DataType.Data and doPseudoData and not self.runJERsystematicsOnData:
159  # The secondary tool for pseudo-data JER smearing
160  config.addPrivateTool( 'uncertaintiesToolPD', 'JetUncertaintiesTool' )
161  jetUncertaintiesAlg.uncertaintiesToolPD.JetDefinition = jetCollectionName[:-4]
162  jetUncertaintiesAlg.uncertaintiesToolPD.ConfigFile = configFile
163  if calibArea is not None:
164  jetUncertaintiesAlg.uncertaintiesToolPD.CalibArea = calibArea
165  jetUncertaintiesAlg.uncertaintiesToolPD.MCType = mcType
166 
167  # This is the part that is different!
168  jetUncertaintiesAlg.uncertaintiesToolPD.IsData = True
169  jetUncertaintiesAlg.uncertaintiesToolPD.PseudoDataJERsmearingMode = True
170 
172  # Retrieve appropriate JES/JER recommendations for the JetUncertaintiesTool.
173  # We do this separately from the tool declaration, as we may need to set uo
174  # two such tools, but they have to be private.
175 
176  log = logging.getLogger('LargeRJetAnalysisConfig')
177 
178  # Config file:
179  config_file = None
180  if self.systematicsModelJER in ["Simple", "Full"] and self.systematicsModelJMS in ["Simple", "Full"]:
181  config_file = "R10_CategoryJES_{0}JER_{1}JMS.config".format(self.systematicsModelJER, self.systematicsModelJMS)
182  else:
183  raise ValueError(
184  "Invalid request for systematicsModelJER/JMS settings: "
185  "systematicsModelJER = '{0}', "
186  "systematicsModelJMS = '{1}'".format(self.systematicsModelJER, self.systematicsModelJMS) )
187  if self.uncertToolConfigPath is not None:
188  # Expert override
189  config_file = self.uncertToolConfigPath
190  else:
191  if config.geometry() in [LHCPeriod.Run2, LHCPeriod.Run3]:
192  config_file = "rel22/Summer2025_PreRec/" + config_file
193  else:
194  log.warning("Uncertainties for UFO jets are not for Run 4!")
195 
196  # Calibration area:
197  calib_area = None
198  if self.uncertToolCalibArea is not None:
199  calib_area = self.uncertToolCalibArea
200 
201  # MC type:
202  if self.uncertToolMCType is not None:
203  mc_type = self.uncertToolMCType
204  else:
205  if config.dataType() is DataType.FastSim:
206  if config.geometry() is LHCPeriod.Run2:
207  mc_type = "MC20AF3"
208  else:
209  mc_type = "MC23AF3"
210  else:
211  if config.geometry() is LHCPeriod.Run2:
212  mc_type = "MC20"
213  else:
214  mc_type = "MC23"
215 
216  return config_file, calib_area, mc_type
217 
218  def createUncertaintyToolLargeRJets(self, jetUncertaintiesAlg, config, jetCollectionName, doPseudoData=False):
219  '''
220  Create instance(s) of JetUncertaintiesTool following JetETmiss recommendations.
221 
222  JER uncertainties under the "Full" scheme must be run on MC samples twice:
223  1. Normal (MC) mode,
224  2. Pseudodata (PD) mode, as if the events are Data.
225  '''
226 
227  # Retrieve the common configuration settings
228  configFile, calibArea, mcType = self.getUncertaintyToolSettingsLargeRJets(config)
229 
230  # The main tool for all JER combinations
231  config.addPrivateTool( 'uncertaintiesTool', 'JetUncertaintiesTool' )
232  jetUncertaintiesAlg.uncertaintiesTool.JetDefinition = jetCollectionName[:-4]
233  jetUncertaintiesAlg.uncertaintiesTool.ConfigFile = configFile
234  from PathResolver import PathResolver
235  if self.analysisFile is not None:
236  jetUncertaintiesAlg.uncertaintiesTool.AnalysisFile = PathResolver.FindCalibFile(self.analysisFile)
237  if calibArea is not None:
238  jetUncertaintiesAlg.uncertaintiesTool.CalibArea = calibArea
239  jetUncertaintiesAlg.uncertaintiesTool.MCType = mcType
240  jetUncertaintiesAlg.uncertaintiesTool.IsData = (config.dataType() is DataType.Data)
241  jetUncertaintiesAlg.uncertaintiesTool.PseudoDataJERsmearingMode = False
242  jetUncertaintiesAlg.uncertaintiesTool.NJetAccessorName = "Njet_NOSYS"
243 
244  # JER smearing on data
245  if config.dataType() is DataType.Data and not (config.isPhyslite() and doPseudoData and self.runJERsystematicsOnData):
246  # we don't want any systematics on data if we're not using the right JER model!
247  jetUncertaintiesAlg.affectingSystematicsFilter = '.*'
248 
249  if config.dataType() is not (DataType.Data and config.isPhyslite()) and doPseudoData and not self.runJERsystematicsOnData:
250  # The secondary tool for pseudo-data JER smearing
251  config.addPrivateTool( 'uncertaintiesToolPD', 'JetUncertaintiesTool' )
252  jetUncertaintiesAlg.uncertaintiesToolPD.JetDefinition = jetCollectionName[:-4]
253  jetUncertaintiesAlg.uncertaintiesToolPD.ConfigFile = configFile
254  if calibArea is not None:
255  jetUncertaintiesAlg.uncertaintiesToolPD.CalibArea = calibArea
256  jetUncertaintiesAlg.uncertaintiesToolPD.MCType = mcType
257  jetUncertaintiesAlg.uncertaintiesToolPD.IsData = True
258  jetUncertaintiesAlg.uncertaintiesToolPD.PseudoDataJERsmearingMode = True
259 
260  def makeAlgs (self, config) :
261 
262  jetCollectionName=config.originalName(self.containerName)
263  if(config.originalName(self.containerName)=="AnalysisJets") :
264  jetCollectionName="AntiKt4EMPFlowJets"
265  if(config.originalName(self.containerName)=="AnalysisLargeRJets") :
266  jetCollectionName="AntiKt10UFOCSSKSoftDropBeta100Zcut10Jets"
267 
268  # interpret the jet collection
269  collection_pattern = re.compile(
270  r"AntiKt(\d+)(EMTopo|EMPFlow|LCTopo|TrackCaloCluster|UFO|Track|HI)(TrimmedPtFrac5SmallR20|CSSKSoftDropBeta100Zcut10)?Jets")
271  match = collection_pattern.match(jetCollectionName)
272  if not match:
273  raise ValueError(
274  "Jet collection {0} does not match expected pattern!".format(jetCollectionName) )
275  radius = int(match.group(1) )
276  if radius not in [2, 4, 6, 10]:
277  raise ValueError("Jet collection has an unsupported radius '{0}'!".format(radius) )
278 
279  if (self.analysisJetSelection!= ''):
280  alg = config.createAlgorithm( 'CP::NJetDecoratorAlg', 'NJetDecoratorAlg' )
281  alg.jets = config.readName(self.containerName)
282  alg.jetSelection = self.analysisJetSelection
283  config.addOutputVar('EventInfo', 'Njet_%SYS%', 'Njet')
284 
285  # Jet uncertainties
286  if (radius == 4):
287  alg = config.createAlgorithm( 'CP::JetUncertaintiesAlg', 'JetUncertaintiesAlg' )
288  self.createUncertaintyToolSmallRJets(alg, config, jetCollectionName, doPseudoData=( self.systematicsModelJER in ["Full","All"] ))
289  alg.jets = config.readName (self.containerName)
290  alg.jetsOut = config.copyName (self.containerName)
291  alg.preselection = config.getPreselection (self.containerName, '')
292 
293  elif (radius == 10):
294  if self.jetInput == "UFO" and config.dataType() in [DataType.FullSim, DataType.FastSim]:
295  alg = config.createAlgorithm( 'CP::JetUncertaintiesAlg', 'JetUncertaintiesAlg' )
296  self.createUncertaintyToolLargeRJets(alg, config, jetCollectionName, doPseudoData=( self.systematicsModelJER in ["Full","All"] ))
297 
298  alg.uncertaintiesTool.JetDefinition = jetCollectionName[:-4]
299 
300  # R=1.0 jets have a validity range
301  alg.outOfValidity = 2 # SILENT
302  alg.outOfValidityDeco = 'outOfValidity'
303 
304  alg.jets = config.readName (self.containerName)
305  alg.jetsOut = config.copyName (self.containerName)
306  alg.preselection = config.getPreselection (self.containerName, '')
307 
308  if self.jetInput != "UFO":
309  alg = config.createAlgorithm( 'CP::JetUncertaintiesAlg', 'JetUncertaintiesAlg' )
310 
311  # R=1.0 jets have a validity range
312  alg.outOfValidity = 2 # SILENT
313  alg.outOfValidityDeco = 'outOfValidity'
314  config.addPrivateTool( 'uncertaintiesTool', 'JetUncertaintiesTool' )
315 
316  alg.uncertaintiesTool.JetDefinition = jetCollectionName[:-4]
317  alg.uncertaintiesTool.ConfigFile = \
318  "rel21/Moriond2018/R10_{0}Mass_all.config".format(self.largeRMass)
319  alg.uncertaintiesTool.MCType = "MC16a"
320  alg.uncertaintiesTool.IsData = (config.dataType() is DataType.Data)
321 
322  alg.jets = config.readName (self.containerName)
323  alg.jetsOut = config.copyName (self.containerName)
324  alg.preselection = config.getPreselection (self.containerName, '')
325  config.addSelection (self.containerName, '', 'outOfValidity')
PathResolver::FindCalibFile
static std::string FindCalibFile(const std::string &logical_file_name)
Definition: PathResolver.h:63
vtune_athena.format
format
Definition: vtune_athena.py:14
python.JetUncertaintiesConfig.JetUncertaintiesConfig.createUncertaintyToolLargeRJets
def createUncertaintyToolLargeRJets(self, jetUncertaintiesAlg, config, jetCollectionName, doPseudoData=False)
Definition: JetUncertaintiesConfig.py:218
python.JetUncertaintiesConfig.JetUncertaintiesConfig.__init__
def __init__(self)
Definition: JetUncertaintiesConfig.py:16
python.JetUncertaintiesConfig.JetUncertaintiesConfig.systematicsModelJER
systematicsModelJER
Definition: JetUncertaintiesConfig.py:71
python.JetUncertaintiesConfig.JetUncertaintiesConfig.systematicsModelJES
systematicsModelJES
Definition: JetUncertaintiesConfig.py:71
python.JetUncertaintiesConfig.JetUncertaintiesConfig.getUncertaintyToolSettingsSmallRJets
def getUncertaintyToolSettingsSmallRJets(self, config)
Definition: JetUncertaintiesConfig.py:63
python.JetUncertaintiesConfig.JetUncertaintiesConfig
Definition: JetUncertaintiesConfig.py:13
python.JetUncertaintiesConfig.JetUncertaintiesConfig.createUncertaintyToolSmallRJets
def createUncertaintyToolSmallRJets(self, jetUncertaintiesAlg, config, jetCollectionName, doPseudoData=False)
Definition: JetUncertaintiesConfig.py:134
python.CaloAddPedShiftConfig.int
int
Definition: CaloAddPedShiftConfig.py:45
python.JetUncertaintiesConfig.JetUncertaintiesConfig.instanceName
def instanceName(self)
Definition: JetUncertaintiesConfig.py:59
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
python.JetUncertaintiesConfig.JetUncertaintiesConfig.jetInput
jetInput
Definition: JetUncertaintiesConfig.py:99
python.JetUncertaintiesConfig.JetUncertaintiesConfig.makeAlgs
def makeAlgs(self, config)
Definition: JetUncertaintiesConfig.py:260
python.JetUncertaintiesConfig.JetUncertaintiesConfig.getUncertaintyToolSettingsLargeRJets
def getUncertaintyToolSettingsLargeRJets(self, config)
Definition: JetUncertaintiesConfig.py:171