ATLAS Offline Software
JetCalibToolsConfig.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
2 
3 
13 from AthenaConfiguration.Enums import LHCPeriod
14 from JetRecConfig.StandardJetConstits import inputsFromContext
15 
16 from AthenaCommon import Logging
17 jetcaliblog = Logging.logging.getLogger('JetCalibToolsConfig')
18 
19 all = ['getJetCalibTool']
20 
21 # These context definitions could be placed in another package and made
22 # more robust with a small python class to hold the info.
23 # The convention is: config file, calibarea, default calibration sequence
24 pflowcontexts = {
25  "T0":("JES_MC15cRecommendation_PFlow_Aug2016_rel21.config","00-04-77","JetArea_Residual_EtaJES"),
26  # Omit smearing, to avoid any efficiency loss
27  "AnalysisLatest":("PreRec_R22_PFlow_ResPU_EtaJES_GSC_February23_230215.config","00-04-82","JetArea_Residual_EtaJES_GSC_Insitu"),
28  "TrigLS2":("JES_MC16Recommendation_Consolidated_PFlow_Apr2019_Rel21_Trigger.config","00-04-82","JetArea_Residual_EtaJES_GSC_Insitu"),
29  "Trigger":("JES_MC16Recommendation_Consolidated_PFlow_30May2022_Rel22_Trigger.config","00-04-82","JetArea_Residual_EtaJES_GSC_Insitu"),
30  "TrigR22Prerec":("PreRec_R22_PFlow_ResPU_EtaJES_GSC_February23_230215.config", "00-04-82", "JetArea_Residual_EtaJES_GSC_Insitu"),
31  "TrigHIUPC" : ("JES_MC16Recommendation_LowMu1718_MCJES_GSC_nTrkOn_PFlow_Sep2023_Rel21.config", "00-04-82", "EtaJES_GSC"),
32 }
33 
34 topocontexts = {
35  "T0":("JES_MC15cRecommendation_May2016_rel21.config","00-04-77","JetArea_Residual_EtaJES"),
36  # Omit smearing, to avoid any efficiency loss
37  "AnalysisLatest":("JES_MC16Recommendation_Consolidated_EMTopo_Apr2019_Rel21.config","00-04-82","JetArea_Residual_EtaJES_GSC_Insitu"),
38  "TrigRun2":("JES_MC15cRecommendation_May2016_Trigger.config","00-04-77","JetArea_EtaJES_GSC_Insitu"),
39  "TrigRun2GSC":("JES_data2016_data2015_Recommendation_Dec2016_rel21.config","00-04-77","JetArea_EtaJES_GSC_Insitu"),
40  "TrigLS2":("JES_MC16Recommendation_Consolidated_EMTopo_Apr2019_Rel21_Trigger.config","00-04-82","JetArea_Residual_EtaJES_GSC_Insitu"),
41  "Trigger":("JES_MC16Recommendation_Consolidated_EMTopo_Apr2019_Rel21_Trigger.config","00-04-82","JetArea_Residual_EtaJES_GSC_Insitu"),
42  "HLLHC":("HLLHC/JES_MC16_HLLHC_Aug2021_rel21.config","00-04-82","JetArea_Residual_EtaJES"),
43 }
44 
45 ufocontexts = {
46  "T0":("Consolidated_R22_CSSKUFO_ResPU_EtaJES_GNNC_20231103.config", "00-04-83", "Residual_EtaJES_GNNC"),
47 }
48 
49 rscanlc2 = {
50  "RScanLatest":("JES_MC16Recommendation_Rscan2LC_22Feb2018_rel21.config","00-04-81","JetArea_Residual_EtaJES_GSC_Insitu")
51 }
52 
53 rscanlc6 = {
54  "RScanLatest":("JES_MC16Recommendation_Rscan6LC_22Feb2018_rel21.config","00-04-81","JetArea_Residual_EtaJES_GSC_Insitu")
55 }
56 
57 fatjetcontexts = {
58  "CombinedMass": ("JES_MC16recommendation_FatJet_Trimmed_JMS_comb_17Oct2018.config","00-04-82","EtaJES_JMS"),
59  "CaloMass": ("JES_MC16recommendation_FatJet_Trimmed_JMS_calo_12Oct2018.config","00-04-82","EtaJES_JMS"),
60  "TAMass": ("JES_MC16recommendation_FatJet_Trimmed_JMS_TA_12Oct2018.config","00-04-82","EtaJES_JMS"),
61  "SoftDrop": ("JES_MC20PreRecommendation_R10_UFO_CSSK_SoftDrop_JMS_R21Insitu_10Mar2023.config","00-04-82","EtaJES_JMS"),
62  "TrigUngroomed": ("JES_Full2012dataset_Rscan_June2014.config","00-04-77","JetArea_EtaJES"),
63  "TrigTrimmed": ("JES_MC15recommendation_FatJet_June2015_PtFrac4.config","00-04-82","EtaJES_JMS"),
64  "TrigSoftDrop": ("JES_MC16recommendation_R10_UFO_CSSK_SoftDrop_JMS_01April2020.config","00-04-82","EtaJES_JMS"),
65  "TrigHLTSoftDrop":("JES_JMS_MC21_R10_PFlow_CSSK_SoftDrop_Dec2023_Trigger.config", "00-04-83","EtaJES_JMS"),
66  "LargeRDNN": ("JES_JMS_MC20dnnc_R10_UFO_CSSK_SoftDrop_Jun2023.config","00-04-83","LargeRDNN"),
67 }
68 
69 # List AFII config files separately, to avoid needing to specify a different context
70 af2configs = {
71  "AntiKt4EMPFlow": "JES_MC16Recommendation_AFII_PFlow_Apr2019_Rel21.config",
72  "AntiKt4GPFlow": "JES_MC16Recommendation_AFII_PFlow_Apr2019_Rel21.config",
73  "AntiKt4EMTopo": "JES_MC16Recommendation_AFII_EMTopo_Apr2019_Rel21.config",
74  "AntiKt4LCTopo": "JES_MC16Recommendation_AFII_EMTopo_Apr2019_Rel21.config",
75 }
76 
77 calibcontexts = {
78  # Standard AntiKt4
79  "AntiKt4EMPFlow":pflowcontexts,
80  "AntiKt4EMPFlow_noElectrons":pflowcontexts,
81  "AntiKt4EMPFlow_noMuons":pflowcontexts,
82  "AntiKt4EMPFlow_noLeptons":pflowcontexts,
83  "AntiKt4EMPFlowByVertex":pflowcontexts,
84  "AntiKt4GPFlow":pflowcontexts,
85  "AntiKt4UFOCSSK":ufocontexts,
86  "AntiKt4EMTopo":topocontexts,
87  "AntiKt4LCTopo":topocontexts,
88  "AntiKt10LCTopo":fatjetcontexts,
89  # Standard trimmed
90  "AntiKt10LCTopoTrimmedPtFrac5SmallR20":fatjetcontexts,
91  "AntiKt10LCTopoTrimmedPtFrac4SmallR20":fatjetcontexts,
92  # Standard UFO CS+SK jets
93  "AntiKt10UFOCSSKSoftDropBeta100Zcut10":fatjetcontexts,
94  # UFO CS+SK jets with leptons removed
95  "AntiKt10UFOCSSK_noElectronsSoftDropBeta100Zcut10":fatjetcontexts,
96  "AntiKt10UFOCSSK_noMuonsSoftDropBeta100Zcut10":fatjetcontexts,
97  "AntiKt10UFOCSSK_noLeptonsSoftDropBeta100Zcut10":fatjetcontexts,
98  # Large-R PFlow Soft Drop CSSK
99  "AntiKt10EMPFlowCSSKSoftDropBeta100Zcut10":fatjetcontexts,
100  # R-Scan
101  "AntiKt2LCTopo":rscanlc2,
102  "AntiKt6LCTopo":rscanlc6,
103 
104 }
105 
106 hasInSitu = ["AntiKt4LCTopo", "AntiKt4EMTopo", "AntiKt4EMPFlow", "AntiKt4EMPFlow_noElectrons", "AntiKt4EMPFlow_noMuons", "AntiKt4EMPFlow_noLeptons", "TrigAntiKt4EMTopo"]
107 
108 # This method extracts the relevant configuration, does some consistency checks,
109 # then forwards the configuration to defineJetCalibTool, returning the output.
110 # At present the interface allows for the calibseq to be chosen freely, other
111 # than checking that the data source is data for the in situ correction.
112 def getJetCalibTool(jetdef, context, data_type, calibseq = "", rhoname = "", pvname = "PrimaryVertices", gscdepth = "auto"):
113 
114  jetcollection = jetdef.basename
115 
116  # In principle we could autoconfigure
117  if data_type not in ['data','mc','afii']:
118  jetcaliblog.error("JetCalibConfig accepts data_type values: 'data', 'mc', 'afii'")
119  raise ValueError("Unsupported data_type provided: '{0}".format(data_type))
120 
121  if jetcollection.endswith("Jets"):
122  jetcaliblog.error("Jet collection '{0}'should be specified w/o 'Jets' in the name.".format(jetcollection))
123  raise ValueError("Bad jet collection formatting in getJetCalibTool.")
124 
125  jetcaliblog.debug("Preparing calibration for {0}, in context {1} on sample type {2}".format(jetcollection,context,data_type))
126 
127  jetcontexts = calibcontexts[jetcollection]
128 
129  if jetcollection == "AntiKt4EMTopo" and context == "T0":
130  if jetdef._cflags.GeoModel.Run >= LHCPeriod.Run4:
131  context = "HLLHC"
132 
133  try:
134  configfile, calibarea, calibseq_def = jetcontexts[context]
135  _calibseq = calibseq if calibseq else calibseq_def
136 
137  # Check that the calib sequence requests something sensible for the in situ calibration
138  # Leave other checks for the tool code.
139  # Might need to specialise if we decide MC trigger jets should also have in situ.
140  if _calibseq.endswith("Insitu"):
141  if data_type == 'data':
142  if jetcollection not in hasInSitu:
143  raise ValueError("In situ calibration does not exist for {0}, context {1}".format(jetcollection,context))
144  else:
145  raise ValueError("In situ calibration requested for MC on {0}, context {1}".format(jetcollection,context))
146  _configfile = configfile
147  if data_type == "afii" and jetcollection in af2configs.keys():
148  _configfile = af2configs[jetcollection]
149  _data_type = data_type
150  # Most likely an oversight, but R20/21 JetRecCalibrationFinder did not set the data flag
151  # This affects the residual correction by scaling mu.
152  # We should revert this later on, set up now for validation purposes
153  if context == "T0":
154  _data_type = "data"
155  _pvname = ""
156  if "Residual" in _calibseq or "GSC" in _calibseq and gscdepth!="EM3" or "LargeRDNN" in _calibseq:
157  _pvname = pvname
158  # HACK: For Trigger HI UPC who want to do pflow but avoid track-GSC
159  if context == "TrigHIUPC":
160  _pvname = pvname
161  # HACK: For testing while we don't have finalised calibrations for trigger PF jets
162  _jetcollection = jetcollection
163  if "PFlow" in jetcollection and (context=="TrigSoftDrop" or context=="TrigHLTSoftDrop"):
164  _jetcollection = jetcollection.replace("EMPFlow","UFO")
165  if "_noElectrons" in jetcollection :
166  _jetcollection = _jetcollection.replace("_noElectrons","")
167  if "_noMuons" in jetcollection :
168  _jetcollection = _jetcollection.replace("_noMuons","")
169  if "_noLeptons" in jetcollection :
170  _jetcollection = _jetcollection.replace("_noLeptons","")
171 
172  if "ByVertex" in jetcollection:
173  _jetcollection = jetcollection.replace("ByVertex","")
174  return defineJetCalibTool(_jetcollection, context, _configfile, calibarea, _calibseq, _data_type, rhoname, _pvname, gscdepth)
175  except KeyError as e:
176  jetcaliblog.error("Context '{0}' not found for jet collection '{1}'".format(context,jetcollection))
177  jetcaliblog.error("Options are '{0}".format(','.join(jetcontexts.keys())))
178  raise e
179  return None
180 
181 # This method actually sets up the tool
182 def defineJetCalibTool(jetcollection, context, configfile, calibarea, calibseq, data_type, rhoname, pvname, gscdepth):
183  # Abbreviate the calib sequence
184  calibseqshort = ''.join([ step[0] for step in calibseq.split('_') ])
185  toolname = "jetcalib_{0}_{1}_{2}".format(jetcollection,calibseqshort,context)
186  #
187  from AthenaConfiguration.ComponentFactory import CompFactory
188  jct = CompFactory.JetCalibrationTool(toolname,
189  JetCollection = jetcollection,
190  ConfigFile = configfile,
191  CalibArea = calibarea,
192  CalibSequence = calibseq,
193  IsData = (data_type == "data"),
194  RhoKey = rhoname,
195  PrimaryVerticesContainerName = pvname,
196  GSCDepth = gscdepth
197  )
198  return jct
199 
200 # This method extends the basic config getter to specify the requisite jet
201 # moments or other inputs
202 def getJetCalibToolPrereqs(modspec,jetdef):
203  calibcontext, data_type, calibseq, rhoname, pvname, gscdepth = getCalibSpecsFromString(jetdef, modspec)
204  if calibseq=="":
205  cfg, calibarea, calibseq = calibcontexts[jetdef.basename][calibcontext]
206 
207  # For now, only dependent on calibseq -- can ignore Insitu, which is
208  # added when getting the concrete tool
209  prereqs = []
210  prereqs.append("mod:ConstitFourMom")
211  if "JetArea" in calibseq: # Will not insert a prefix here
212  if calibcontext.startswith("Trig"): prereqs.append("input:HLT_EventDensity")
213  elif pvname != "PrimaryVertices": prereqs.append("input:EventDensityCustomVtx")
214  else: prereqs.append(inputsFromContext("EventDensity")(jetdef))
215  if "GSC" in calibseq:
216  prereqs += ["mod:CaloEnergies"]
217  if calibcontext != "TrigRun2": # No track/MS GSC for trigger w/o FTK
218  prereqs += ["mod:TrackMoments",
219  "ghost:MuonSegment"]
220  if "GNNC" in calibseq:
221  prereqs += ["mod:CaloQuality","mod:TrackMoments"]
222  if "CombinedMass" in calibcontext:
223  prereqs += ["mod:TrackSumMoments"]
224  if "LargeRDNN" in calibseq:
225  prereqs += ["mod:CaloEnergiesLargeR","mod:ConstitFrac","mod:groomMRatio","mod:Width",
226  "mod:nsubjettiness","mod:nsubjettinessR","mod:ktsplitter","mod:ecorr",
227  "mod:ecorrR","mod:qw"]
228  jetcaliblog.debug("Prereqs for calibseq '{0}': {1}".format(calibseq,str(prereqs)))
229  return prereqs
230 
231 # This method translates the mod specification string into calibration specifications
232 def getCalibSpecsFromString(jetdef, modspec):
233  calibseq = ""
234  # for the LCTopo EleRM context used for EleRM taus, we need alternative EventShape container
235  rhoname = "EleRM_Kt4LCTopoOriginEventShape" if jetdef.context == "EleRM" else "auto"
236  pvname = "PrimaryVertices"
237  gscdepth = "auto"
238  calibspecs = modspec.split(':')
239  # Probably want data_type to come from elsewhere
240  calibcontext, data_type = calibspecs[:2]
241  if len(calibspecs)>2: calibseq = calibspecs[2]
242  if len(calibspecs)>3: rhoname = calibspecs[3]
243  if len(calibspecs)>4: pvname = calibspecs[4]
244  if len(calibspecs)>5: gscdepth = calibspecs[5]
245 
246  return calibcontext, data_type, calibseq, rhoname, pvname, gscdepth
247 
248 # This method instantiates the JetCalibTool given the input mod specification
249 def getJetCalibToolFromString(jetdef, modspec):
250  calibcontext, data_type, calibseq, rhoname, pvname, gscdepth = getCalibSpecsFromString(jetdef, modspec)
251  return getJetCalibTool(jetdef,calibcontext,data_type,calibseq,rhoname,pvname,gscdepth)
JetCalibToolsConfig.defineJetCalibTool
def defineJetCalibTool(jetcollection, context, configfile, calibarea, calibseq, data_type, rhoname, pvname, gscdepth)
Definition: JetCalibToolsConfig.py:182
vtune_athena.format
format
Definition: vtune_athena.py:14
JetCalibToolsConfig.getCalibSpecsFromString
def getCalibSpecsFromString(jetdef, modspec)
Definition: JetCalibToolsConfig.py:232
JetCalibToolsConfig.getJetCalibToolPrereqs
def getJetCalibToolPrereqs(modspec, jetdef)
Definition: JetCalibToolsConfig.py:202
JetCalibToolsConfig.getJetCalibTool
def getJetCalibTool(jetdef, context, data_type, calibseq="", rhoname="", pvname="PrimaryVertices", gscdepth="auto")
Definition: JetCalibToolsConfig.py:112
python.StandardJetContext.inputsFromContext
def inputsFromContext(inputKey, prefix="", suffix="")
Definition: StandardJetContext.py:106
JetCalibToolsConfig.getJetCalibToolFromString
def getJetCalibToolFromString(jetdef, modspec)
Definition: JetCalibToolsConfig.py:249
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
str
Definition: BTagTrackIpAccessor.cxx:11