ATLAS Offline Software
JetChainConfiguration.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2 
3 import re
4 from AthenaCommon.Logging import logging
5 logging.getLogger().info("Importing %s",__name__)
6 log = logging.getLogger(__name__)
7 
8 from ..Config.ChainConfigurationBase import ChainConfigurationBase
9 
10 from .JetRecoSequencesConfig import JetRecoDataDeps
11 
12 from .JetMenuSequencesConfig import (
13  jetCaloHypoMenuSequenceGenCfg,
14  jetRoITrackJetTagHypoMenuSequenceGenCfg,
15  jetFSTrackingHypoMenuSequenceGenCfg,
16  jetCaloRecoMenuSequenceGenCfg,
17  jetCaloPreselMenuSequenceGenCfg,
18  jetHICaloHypoMenuSequenceGenCfg,
19 )
20 from .ExoticJetSequencesConfig import jetEJsMenuSequenceGenCfg, jetCRVARMenuSequenceGenCfg,jetCRMenuSequenceGenCfg
21 
22 from . import JetRecoCommon
23 from . import JetPresel
24 
25 from TrigEDMConfig.TriggerEDM import recordable
26 
27 import copy
28 
29 #----------------------------------------------------------------
30 # Class to configure chain
31 #----------------------------------------------------------------
33 
34  def __init__(self, chainDict):
35  # we deliberately don't call base class constructore, since this assumes a single chain part
36  # which is not the case for jets
37 
38  self.dict = copy.deepcopy(chainDict)
39 
40  self.chainName = self.dict['chainName']
41  self.chainL1Item = self.dict['L1item']
42 
43  self.chainPart = self.dict['chainParts']
44  self.L1Threshold = ''
45  self.mult = 1 # from the framework point of view I think the multiplicity is 1, internally the jet hypo has to figure out what to actually do
46 
47  # these properties are in the base class, but I don't think we need them for jets
48  #self.chainPartName = ''
49  #self.chainPartNameNoMult = ''
50  #self.chainPartNameNoMultwL1 = ''
51 
52  # expect that the L1 seed is the same for all jet parts, otherwise we have a problem
53  jChainParts = JetRecoCommon.jetChainParts(self.chainPart)
54  # Register if this is a performance chain, in which case the HLT should be exactly j0_perf
55  self.isPerf = False
56  # Exotic hypo (emerging-jets, trackless jets)
57  self.exotHypo = ''
58  # Check if we intend to preselect events with calo jets in step 1
59  self.trkpresel = "nopresel"
60 
61  for ip,p in enumerate(jChainParts):
62  # Check if there is exactly one exotic hypothesis defined
63  if len(p['exotHypo']) > 1:
64  raise RuntimeError('emerging chains currently not configurable with more than one emerging selection!')
65  if p['exotHypo']:
66  self.exotHypo = p['exotHypo'][0]
67 
68  if 'perf' in p['addInfo']:
69  # Need to ensure a few conditions to ensure there is no selection bias:
70  # No preselection, no special hypo
71  # Only one chainPart is permitted
72  verify_null_str = [ p[k]!='' for k in ['jvt','momCuts','timing','bsel','bTag', 'tausel']]
73  verify_null_list = [ p[k]!=[] for k in ['prefilters','exotHypo'] ]
74  if (
75  p['trkpresel']!='nopresel' or p['hypoScenario']!='simple'
76  or any(verify_null_str) or any(verify_null_list)
77  or p['smc']!='nosmc'
78  or ip>0
79  ):
80  raise RuntimeError(f'Invalid jet \'perf\' chain "{self.chainName}": No additional selection is permitted!')
81  self.isPerf = True
82  l1th = p['L1threshold']
83  if self.L1Threshold != '' and self.L1Threshold != l1th:
84  raise RuntimeError('Cannot configure a jet chain with different L1 thresholds')
85  self.L1Threshold = l1th
86  # Verify that the preselection is defined only once
87  if p["trkpresel"]!="nopresel" and ip+1!=len(jChainParts): # Last jet chainPart, presel should go here
88  log.error("Likely inconsistency encountered in preselection specification for %s",self.chainName)
89  raise RuntimeError("Preselection %s specified earlier than in the last chainPart!",p["trkpresel"])
90 
91  self.trkpresel = JetPresel.extractPreselection(self.dict)
92  self.trkpresel_parsed_reco = {key:p[key] for key in ['recoAlg']} #Storing here the reco options from last chain part that we want to propagate to preselection (e.g. jet radius)
93 
94  self.recoDict = JetRecoCommon.extractRecoDict(jChainParts)
95  self.jetName = None
96  self.jetDefDict = None
97 
98 
99  # ----------------------
100  # Precompute the data dependencies i.e. jet collections to generate
101  # ----------------------
102  def prepareDataDependencies(self, flags):
103  self.jetDefDict = JetRecoDataDeps(flags, **self.recoDict)
104  jetsOut, jetDef = self.jetDefDict['final']
105  self.jetName = recordable(jetDef.fullname())
106 
107 
108  # ----------------------
109  # Assemble the chain depending on information from chainName
110  # ----------------------
111  def assembleChainImpl(self, flags):
112  log.debug("Assembling chain %s", self.chainName)
113 
114  # --------------------
115  # define here the names of the steps and obtain the chainStep configuration
116  # --------------------
117  chainSteps = []
118  if self.recoDict["ionopt"]=="ion":
119  jetHICaloHypoStep = self.getJetHICaloHypoChainStep(flags)
120  chainSteps.append( jetHICaloHypoStep )
121  elif self.recoDict["trkopt"]=="roiftf":
122  # Can't work w/o calo presel jets to seed RoIs
123  if self.trkpresel=="nopresel":
124  raise RuntimeError("RoI FTF jet tracking requested with no jet preselection to provide RoIs")
125  # Set up calo preselection step first
126  preselJetDef, jetPreselStep = self.getJetCaloPreselChainStep(flags)
127  chainSteps.append( jetPreselStep )
128  # Standard tracking step, configure the tracking instance differently
129 
130  jetRoITrackJetTagHypoStep = self.getJetRoITrackJetTagHypoChainStep(flags, preselJetDef)
131  chainSteps.append( jetRoITrackJetTagHypoStep )
132  elif self.recoDict["trkopt"]=="ftf":
133  if self.trkpresel=="nopresel":
134  # Passthrough calo reco -- only for prescaled chains due to CPU cost
135  caloRecoStep = self.getJetCaloRecoChainStep(flags)
136  chainSteps.append( caloRecoStep )
137  #Add empty step to align with preselection step
138  roitrkPreselStep = self.getEmptyStep(2, 'RoIFTFEmptyStep')
139  else:
140  # Add calo preselection step
141  preselJetDef, jetPreselStep = self.getJetCaloPreselChainStep(flags)
142  chainSteps.append( jetPreselStep )
143 
144  if re.match(r'.*(b\d\d|bg\d\d|bgtwo\d\d)|.*Z|.*gntau', self.trkpresel):
145  # Preselection with super-RoI tracking for b-tagging, tau-tagging or pileup tagging
146  roitrkPreselStep = self.getJetRoITrackJetTagPreselChainStep(flags, preselJetDef)
147  else:
148  # Empty step for alignment if no roiftf preselection defined
149  roitrkPreselStep=self.getEmptyStep(2, 'RoIFTFEmptyStep')
150 
151  chainSteps.append(roitrkPreselStep)
152  # Final selection with FS tracking
153  jetFSTrackingHypoStep = self.getJetFSTrackingHypoChainStep(flags)
154  chainSteps.append( jetFSTrackingHypoStep )
155  else:
156  # No special options, just EMTopo jet reconstruction going straight to final rejection
157  jetCaloHypoStep = self.getJetCaloHypoChainStep(flags)
158  chainSteps.append( jetCaloHypoStep )
159 
160  # Add exotic jets hypo
161  if self.exotHypo != '' and ("emerging" in self.exotHypo or "trackless" in self.exotHypo):
162  EJsStep = self.getJetEJsChainStep(flags, self.jetName, self.exotHypo)
163  chainSteps+= [EJsStep]
164  elif self.exotHypo != '' and ("calratiovar" in self.exotHypo):
165  CRVARStep = self.getJetCRVARChainStep(flags, self.jetName, self.exotHypo)
166  chainSteps+= [ CRVARStep]
167  elif self.exotHypo != '' and ("calratio" in self.exotHypo):
168  CRStep = self.getJetCRChainStep(flags, self.jetName, self.exotHypo)
169  chainSteps+= [self.getEmptyStep(2, 'RoIFTFEmptyStep'), CRStep]
170 
171  myChain = self.buildChain(chainSteps)
172 
173  return myChain
174 
175 
176  # --------------------
177  # Configuration of steps
178  # --------------------
179 
180  # These ChainStep generators all pass information between steps
181  def getJetCaloHypoChainStep(self, flags):
182  stepName = f"MainStep_jet_{self.recoDict['jetDefStr']}"
183 
184  if self.isPerf:
185  stepName += '_perf'
186 
187  jetStep = self.getStep(flags, stepName, [jetCaloHypoMenuSequenceGenCfg], isPerf=self.isPerf, **self.jetDefDict)
188  return jetStep
189 
190  def getJetHICaloHypoChainStep(self, flags):
191  stepName = "MainStep_HIjet"
192  if self.isPerf:
193  stepName += '_perf'
194 
195  jetStep = self.getStep(
196  flags, stepName, [jetHICaloHypoMenuSequenceGenCfg],
197  isPerf=self.isPerf, **self.recoDict,
198  )
199  return jetStep
200 
202  stepName = "MainStep_jet_"+self.recoDict['jetDefStr']
203  if self.isPerf:
204  stepName += '_perf'
205 
206  jetStep = self.getStep(
207  flags, stepName, [jetFSTrackingHypoMenuSequenceGenCfg],
208  isPerf=self.isPerf,
209  **self.jetDefDict
210  )
211  return jetStep
212 
213  def getJetCaloRecoChainStep(self, flags):
214  clusterCalib = self.recoDict["clusterCalib"]
215  stepName = "CaloRecoPTStep_jet_"+clusterCalib
216 
217  return self.getStep(flags, stepName, [jetCaloRecoMenuSequenceGenCfg], clusterCalib=clusterCalib)
218 
219  def getJetCaloPreselChainStep(self, flags):
220 
221  #Find if a a4 or a10 calo jet needs to be used in the pre-selection from the last chain dict
222  assert 'recoAlg' in self.trkpresel_parsed_reco.keys(), "Impossible to find \'recoAlg\' key in last chain dictionary for preselection"
223  #Want to match now only a4 and a10 in the original reco algorithm. We don't want to use a10sd or a10t in the preselection
224  matched_reco = re.match(r'^a\d?\d?', self.trkpresel_parsed_reco['recoAlg'])
225  assert matched_reco is not None, "Impossible to get matched reco algorithm for jet trigger preselection The reco expression {0} seems to be impossible to be parsed.".format(self.trkpresel_parsed_reco['recoAlg'])
226 
227  #Getting the outcome of the regex reco option (it should correspond to a4 or a10 depending by which chain you are configuring)
228  preselRecoDict = JetPresel.getPreselRecoDict(matched_reco.group())
229 
230  preselJetDefDict = JetRecoDataDeps(flags, **preselRecoDict)
231  preselJetsOut, preselJetDef = preselJetDefDict["final"]
232 
233  stepName = "PreselStep_jet_"+preselRecoDict['jetDefStr']
234  jetStep = self.getStep(flags, stepName, [jetCaloPreselMenuSequenceGenCfg], **preselJetDefDict)
235 
236  return preselJetDef, jetStep
237 
238  # From here, only return ChainStep, no passing around of data dependencies
239  def getJetRoITrackJetTagHypoChainStep(self, flags, preselJetDef):
240  stepName = "RoIFTFStep_jet_sel_"+self.recoDict['jetDefStr']
241  return self.getStep(flags, stepName, [jetRoITrackJetTagHypoMenuSequenceGenCfg], jetDef=preselJetDef, isPresel=False)
242 
243  def getJetRoITrackJetTagPreselChainStep(self, flags, jetDef):
244 
245  #Find if a a4 or a10 calo jet needs to be used in the pre-selection from the last chain dict
246  assert 'recoAlg' in self.trkpresel_parsed_reco.keys(), "Impossible to find \'recoAlg\' key in last chain dictionary for preselection"
247  #Want to match now only a4 and a10 in the original reco algorithm. We don't want to use a10sd or a10t in the preselection
248  matched_reco = re.match(
249  r'^a\d?\d?', self.trkpresel_parsed_reco['recoAlg'])
250  assert matched_reco is not None, "Impossible to get matched reco algorithm for jet trigger preselection The reco expression {0} seems to be impossible to be parsed.".format(
251  self.trkpresel_parsed_reco['recoAlg'])
252 
253  #Getting the outcome of the regex reco option (it should correspond to a4 or a10 depending by which chain you are configuring)
254  preselRecoDict = JetPresel.getPreselRecoDict(matched_reco.group(),roiftf=True)
255 
256  assert preselRecoDict['trkopt'] == 'roiftf', 'getJetRoITrackJetTagPreselChainStep: you requested a RoI tracking preselection but the reco dictionary has \'trkopt\' set to {0}'.format(preselRecoDict['trkopt'])
257 
258  stepName = "RoIFTFStep_jet_"+self.recoDict['jetDefStr']
259  return self.getStep(flags, stepName, [jetRoITrackJetTagHypoMenuSequenceGenCfg], jetDef=jetDef, isPresel=True)
260 
261  def getJetEJsChainStep(self, flags, jetCollectionName, exotdictstring):
262 
263  # Must be configured similar to : emergingPTF0p0dR1p2 or tracklessdR1p2
264  if 'emerging' in exotdictstring and ('dR' not in exotdictstring \
265  or 'PTF' not in exotdictstring):
266  log.error('Misconfiguration of exotic jet chain - need dR and PTF options')
267  exit(1)
268  if 'trackless' in exotdictstring and 'dR' not in exotdictstring:
269  log.error('Misconfiguration of trackless exotic jet chain - need dR option')
270  exit(1)
271 
272  trackless = int(0)
273  if 'emerging' in exotdictstring:
274  ptf = float(exotdictstring.split('PTF')[1].split('dR')[0].replace('p', '.'))
275  dr = float(exotdictstring.split('dR')[1].split('_')[0].replace('p', '.'))
276  elif 'trackless' in exotdictstring:
277  trackless = int(1)
278  ptf = 0.0
279  dr = float(exotdictstring.split('dR')[1].split('_')[0].replace('p', '.'))
280  else:
281  log.error('Misconfiguration of trackless exotic jet chain - need emerging or trackless selection')
282  exit(1)
283 
284  log.debug("Running exotic jets with ptf: " + str(ptf) + "\tdR: " + str(dr) + "\ttrackless: " + str(trackless) + "\thypo: " + exotdictstring)
285 
286  stepName = "EJsStep"
287 
288  return self.getStep(flags, stepName, [jetEJsMenuSequenceGenCfg], jetsIn=jetCollectionName)
289 
290  def getJetCRVARChainStep(self, flags, jetCollectionName, exotdictstring):
291 
292  if 'calratiovar' in exotdictstring:
293  MinjetlogR = 1.2
294  if 'calratiovarrmbib' in exotdictstring:
295  doBIBremoval = int(1)
296  else:
297  doBIBremoval = int(0)
298  else:
299  log.error('Misconfiguration of trackless exotic jet chain - need calratiovar selection')
300  exit(1)
301 
302  log.debug("Running exotic jets with MinjetlogR: " + str(MinjetlogR) + "\t BIB rm " + str(doBIBremoval) + "\thypo: " + exotdictstring)
303 
304  return self.getStep(flags, "CRVARStep", [jetCRVARMenuSequenceGenCfg], jetsIn=jetCollectionName)
305 
306  def getJetCRChainStep(self, flags, jetCollectionName, exotdictstring):
307 
308  if 'calratio' in exotdictstring and ('calratiovar' not in exotdictstring):
309  MinjetlogR = 1.2
310  if 'calratiormbib' in exotdictstring:
311  doBIBremoval = int(1)
312  else:
313  doBIBremoval = int(0)
314  else:
315  log.error('Misconfiguration of trackless exotic jet chain - need calratio selection')
316  exit(1)
317 
318  log.debug("Running exotic jets with MinjetlogR: " + str(MinjetlogR) + "\t BIB rm " + str(doBIBremoval) + "\thypo: " + exotdictstring)
319 
320  return self.getStep(flags, "CRStep", [jetCRMenuSequenceGenCfg], jetsIn=jetCollectionName)
grepfile.info
info
Definition: grepfile.py:38
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.trkpresel
trkpresel
Definition: JetChainConfiguration.py:59
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
vtune_athena.format
format
Definition: vtune_athena.py:14
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.recoDict
recoDict
Definition: JetChainConfiguration.py:94
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.L1Threshold
L1Threshold
Definition: JetChainConfiguration.py:44
CaloCellPos2Ntuple.int
int
Definition: CaloCellPos2Ntuple.py:24
ChainConfigurationBase
Definition: ChainConfigurationBase.py:1
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetEJsChainStep
def getJetEJsChainStep(self, flags, jetCollectionName, exotdictstring)
Definition: JetChainConfiguration.py:261
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.jetDefDict
jetDefDict
Definition: JetChainConfiguration.py:96
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetCaloPreselChainStep
def getJetCaloPreselChainStep(self, flags)
Definition: JetChainConfiguration.py:219
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration
Definition: JetChainConfiguration.py:32
python.HLT.Jet.JetRecoSequencesConfig.JetRecoDataDeps
def JetRecoDataDeps(flags, **jetRecoDict)
Data dependency generation for the stages of jet reconstruction This is used to precompute the collec...
Definition: JetRecoSequencesConfig.py:56
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetHICaloHypoChainStep
def getJetHICaloHypoChainStep(self, flags)
Definition: JetChainConfiguration.py:190
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.__init__
def __init__(self, chainDict)
Definition: JetChainConfiguration.py:34
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.chainPart
chainPart
Definition: JetChainConfiguration.py:43
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.chainL1Item
chainL1Item
Definition: JetChainConfiguration.py:41
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.exotHypo
exotHypo
Definition: JetChainConfiguration.py:57
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetFSTrackingHypoChainStep
def getJetFSTrackingHypoChainStep(self, flags)
Definition: JetChainConfiguration.py:201
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.jetName
jetName
Definition: JetChainConfiguration.py:95
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.dict
dict
Definition: JetChainConfiguration.py:38
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetRoITrackJetTagHypoChainStep
def getJetRoITrackJetTagHypoChainStep(self, flags, preselJetDef)
Definition: JetChainConfiguration.py:239
calibdata.exit
exit
Definition: calibdata.py:236
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.mult
mult
Definition: JetChainConfiguration.py:45
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetRoITrackJetTagPreselChainStep
def getJetRoITrackJetTagPreselChainStep(self, flags, jetDef)
Definition: JetChainConfiguration.py:243
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetCaloRecoChainStep
def getJetCaloRecoChainStep(self, flags)
Definition: JetChainConfiguration.py:213
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.isPerf
isPerf
Definition: JetChainConfiguration.py:55
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.assembleChainImpl
def assembleChainImpl(self, flags)
Definition: JetChainConfiguration.py:111
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.trkpresel_parsed_reco
trkpresel_parsed_reco
Definition: JetChainConfiguration.py:92
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetCRChainStep
def getJetCRChainStep(self, flags, jetCollectionName, exotdictstring)
Definition: JetChainConfiguration.py:306
python.TriggerEDM.recordable
def recordable(arg, runVersion=3)
Definition: TriggerEDM.py:30
str
Definition: BTagTrackIpAccessor.cxx:11
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:790
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.chainName
chainName
Definition: JetChainConfiguration.py:40
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.prepareDataDependencies
def prepareDataDependencies(self, flags)
Definition: JetChainConfiguration.py:102
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetCRVARChainStep
def getJetCRVARChainStep(self, flags, jetCollectionName, exotdictstring)
Definition: JetChainConfiguration.py:290
readCCLHist.float
float
Definition: readCCLHist.py:83
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.HLT.Jet.JetChainConfiguration.JetChainConfiguration.getJetCaloHypoChainStep
def getJetCaloHypoChainStep(self, flags)
Definition: JetChainConfiguration.py:181