ATLAS Offline Software
Loading...
Searching...
No Matches
JetMenuSequencesConfig.py
Go to the documentation of this file.
1# Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2#
3
4from enum import Enum
5from TriggerMenuMT.HLT.Config.MenuComponents import MenuSequence, SelectionCA, InEventRecoCA
6from AthenaConfiguration.ComponentFactory import CompFactory
7from AthenaConfiguration.AccumulatorCache import AccumulatorCache
8from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
9
10from ..CommonSequences.FullScanDefs import trkFSRoI, fs_towers
11from ..Config.MenuComponents import parOR
12from .JetRecoCommon import jetDefToString, jetCalibFromJetDef
13from TrigEDMConfig.TriggerEDM import recordable
14
15# Hypo tool generators
16from TrigHLTJetHypo.TrigJetHypoToolConfig import trigJetHypoToolFromDict
17from .JetPresel import caloPreselJetHypoToolFromDict, roiPreselJetHypoToolFromDict
18from TrigCaloRec.TrigCaloRecConfig import jetmetTopoClusteringCfg, jetmetTopoClusteringCfg_LC, HICaloTowerCfg
19from AthenaConfiguration.AthConfigFlags import AthConfigFlags
20from TrigGenericAlgs.TrigGenericAlgsConfig import TrigEventInfoRecorderAlgCfg
21
22from AthenaCommon.Logging import logging
23logging.getLogger().info("Importing %s",__name__)
24log = logging.getLogger(__name__)
25
26
28
29# For step 1, starting from the basic calo reco and topoclustering
30# Used for calo-only chains and preselection for tracking
32 from TrigT2CaloCommon.CaloDef import clusterFSInputMaker
33 InputMakerAlg = clusterFSInputMaker()
34 return InputMakerAlg
35
36# For later steps, where calo reco should not be run
37# The same instance of an algorithm cannot be run in different steps
38# Used for chains that use tracking
39def getTrackingInputMaker(flags : AthConfigFlags, trkopt : str):
40 if trkopt=="ftf":
41 log.debug( "jet FS tracking: useDynamicRoiZWidth: %s", flags.Trigger.InDetTracking.fullScan.useDynamicRoiZWidth )
42
43 roiUpdater = None
44 if flags.Trigger.InDetTracking.fullScan.useDynamicRoiZWidth:
45 roiUpdater = CompFactory.RoiUpdaterTool( useBeamSpot=True )
46
47 log.info( roiUpdater )
48
49 InputMakerAlg = CompFactory.InputMakerForRoI(
50 "IM_Jet_TrackingStep",
51 mergeUsingFeature = False,
52 RoITool = CompFactory.ViewCreatorFSROITool(
53 name="RoiTool_FS",
54 RoiUpdater=roiUpdater,
55 RoisWriteHandleKey=recordable( flags.Trigger.InDetTracking.fullScan.roi )
56 ),
57 RoIs = trkFSRoI,
58 )
59 else:
60 InputMakerAlg = CompFactory.InputMakerForRoI(
61 "IM_Jet_TrackingStep",
62 mergeUsingFeature = False,
63 RoITool = CompFactory.ViewCreatorInitialROITool(),
64 RoIs = trkFSRoI,
65 )
66
67 elif trkopt=="roiftf":
68 InputMakerAlg = CompFactory.EventViewCreatorAlgorithm(
69 "IMJetRoIFTF",
70 mergeUsingFeature = False,
71 RoITool = CompFactory.ViewCreatorJetSuperROITool(
72 'ViewCreatorJetSuperRoI',
73 RoisWriteHandleKey = recordable( flags.Trigger.InDetTracking.jetSuper.roi ),
74 RoIEtaWidth = flags.Trigger.InDetTracking.jetSuper.etaHalfWidth,
75 RoIPhiWidth = flags.Trigger.InDetTracking.jetSuper.phiHalfWidth,
76 RoIZWidth = flags.Trigger.InDetTracking.jetSuper.zedHalfWidth,
77 ),
78 Views = "JetSuperRoIViews",
79 InViewRoIs = "InViewRoIs",
80 RequireParentView = False,
81 ViewFallThrough = True,
82 )
83 else:
84 raise RuntimeError(f"Unrecognised trkopt '{trkopt}' provided, choices are ['ftf','roiftf']")
85 return InputMakerAlg
86
87# The same super-RoI as the RoI FTF step, in views of its own
88def getHitZInputMaker(flags : AthConfigFlags):
89 return CompFactory.EventViewCreatorAlgorithm(
90 "IMJetRoIHitZ",
91 mergeUsingFeature = False,
92 RoITool = CompFactory.ViewCreatorJetSuperROITool(
93 'ViewCreatorJetSuperRoIHitZ',
94 RoisWriteHandleKey = recordable( 'HLT_Roi_JetSuperHitZ' ),
95 RoIEtaWidth = flags.Trigger.InDetTracking.jetSuper.etaHalfWidth,
96 RoIPhiWidth = flags.Trigger.InDetTracking.jetSuper.phiHalfWidth,
97 RoIZWidth = flags.Trigger.InDetTracking.jetSuper.zedHalfWidth,
98 ),
99 Views = "JetSuperRoIHitZViews",
100 InViewRoIs = "InViewRoIs",
101 RequireParentView = False,
102 ViewFallThrough = True,
103 )
104
105
107
108# Functions defining the MenuSequence that will be placed into ChainSteps
109# Generate a menu sequence given a set of jet sequences to schedule.
110# The hypo may be set up as a preselection hypo, in which case it will
111# record a single DecisionObject, instead of one per jet.
112# A hypo may alternatively be configured to passThrough, such that
113# the hypo will not retrieve any jets and simply pass.
114#
115# In these functions, we:
116# - First generate the data dependencies for the full jet reco sequence.
117# These come in the form of a dict of JetDefinitions, which are
118# used to define inter-step data dependencies (cluster collections etc).
119# The JetDef is accompanied by a final jet collection name, which is
120# filtered into a vew container to accelerate the hypo
121# - Then pass the JetDefinitions into the configurator functions,
122# which return ComponentAccumulator.
123# - When ChainSteps are created by JetChainConfiguration.getStep,
124# the MenuSequence generators will be wrapped in a deferred call
125# so that when constructing the full HLT menu, we don't regenerate
126# identical sequence configurations repeatedly.
127
128class JetHypoAlgType(Enum):
129 STANDARD = 0
130 CALOPRESEL = 1
131 ROIPRESEL = 2
132 PASSTHROUGH = 3
133
134def jetSelectionCfg(flags, jetDefStr, jetsIn, hypoType=JetHypoAlgType.STANDARD):
135 """constructs CA with hypo alg given arguments """
136 if hypoType==JetHypoAlgType.PASSTHROUGH:
137 hyponame = f"TrigStreamerHypoAlg_{jetDefStr}_passthrough"
138 hypo = CompFactory.TrigStreamerHypoAlg(hyponame)
139 else:
140 assert jetsIn is not None
141 if hypoType==JetHypoAlgType.CALOPRESEL:
142 hyponame = f"TrigJetHypoAlg_{jetDefStr}_calopresel"
143 hypo = CompFactory.TrigJetHypoAlg(hyponame, Jets=jetsIn, DoPresel=True)
144 elif hypoType==JetHypoAlgType.ROIPRESEL:
145 hyponame = f"TrigJetHypoAlg_{jetDefStr}_roipresel"
146 hypo = CompFactory.TrigJetHypoAlg(hyponame, Jets=jetsIn, DoPresel=True)
147 else:
148 hyponame = f"TrigJetHypoAlg_{jetDefStr}"
149 hypo = CompFactory.TrigJetHypoAlg(hyponame, Jets=jetsIn)
150 ca = ComponentAccumulator()
151 ca.addEventAlgo(hypo)
152 return ca
153
154def selName(recoSequenceName, hypoType=JetHypoAlgType.STANDARD):
155 """Construct selection (the name passed to SelectionCA) given reco sequence and hypo type"""
156 selname = recoSequenceName.replace('RecoSequence','MenuSequence')
157 if hypoType==JetHypoAlgType.PASSTHROUGH:
158 selname += "_passthrough"
159 else:
160 if hypoType==JetHypoAlgType.CALOPRESEL:
161 selname += "_calopresel"
162 elif hypoType==JetHypoAlgType.ROIPRESEL:
163 selname += "_roipresel"
164 return selname
165
166
167def hypoToolGenerator(hypoType):
168 """returns function (that in turn returns hypo tool) for menu sequence"""
169 def trigStreamerHypoTool(flags, chainDict):
170 return CompFactory.TrigStreamerHypoTool(chainDict["chainName"])
171 return {
172 JetHypoAlgType.STANDARD: trigJetHypoToolFromDict,
173 JetHypoAlgType.PASSTHROUGH: trigStreamerHypoTool,
174 JetHypoAlgType.CALOPRESEL: caloPreselJetHypoToolFromDict,
175 JetHypoAlgType.ROIPRESEL: roiPreselJetHypoToolFromDict,
176 }[hypoType]
177
178
179
180
182
183# For the preselection step before running tracking (step 1)
184# We set RoIs='' (recognised as seedless) instead of caloFSRoI (output of caloInputMater()) to
185# cut data dependency to InputMaker and allow full scan CaloCell+Clustering to be
186# shared with EGamma (ATR-24722)
187@AccumulatorCache
188def jetCaloPreselMenuSequenceGenCfg(flags, **jetDefDict):
189 jetsOut, jetDef = jetDefDict['final']
190 jetDefStr = jetDefToString(jetDef)
191 reco = InEventRecoCA(f"jetSeqCaloPresel_{jetDefStr}_RecoSequence", inputMaker=getCaloInputMaker())
192
193 if 'LC' in jetDef.inputdef.label:
194 reco.mergeReco(jetmetTopoClusteringCfg_LC(flags, RoIs=''))
195 else:
196 reco.mergeReco(jetmetTopoClusteringCfg(flags, RoIs=''))
197
198 from .JetRecoSequencesConfig import JetRecoCfg
199 jetreco = JetRecoCfg(flags, **jetDefDict)
200 reco.mergeReco(jetreco)
201
202 log.debug("Generating jet preselection menu sequence for reco %s",jetDef.fullname())
203 selAcc = SelectionCA(selName(reco.name, hypoType=JetHypoAlgType.CALOPRESEL))
204 selAcc.mergeReco(reco)
205 selAcc.mergeHypo(jetSelectionCfg(flags, jetDefStr=jetDefStr, jetsIn=jetsOut, hypoType=JetHypoAlgType.CALOPRESEL))
206
207 return MenuSequence(flags, selAcc, HypoToolGen=hypoToolGenerator(hypoType=JetHypoAlgType.CALOPRESEL))
208
209# A null preselection, which will only run the cluster making (step 1)
210# We set RoIs='' for same reason as described for jetCaloPreselMenuSequence
211@AccumulatorCache
212def jetCaloRecoMenuSequenceGenCfg(flags, clusterCalib):
213 reco = InEventRecoCA(f"jetSeqCaloReco_{clusterCalib}_RecoSequence", inputMaker=getCaloInputMaker())
214
215 if clusterCalib=='lcw':
216 reco.mergeReco(jetmetTopoClusteringCfg_LC(flags, RoIs=''))
217 else:
218 reco.mergeReco(jetmetTopoClusteringCfg(flags, RoIs=''))
219
220 selAcc = SelectionCA(selName(reco.name, hypoType=JetHypoAlgType.PASSTHROUGH))
221 selAcc.mergeReco(reco)
222 selAcc.mergeHypo(jetSelectionCfg(flags, jetDefStr="caloreco", jetsIn=None, hypoType=JetHypoAlgType.PASSTHROUGH))
223
224 return MenuSequence(flags, selAcc, HypoToolGen=hypoToolGenerator(hypoType=JetHypoAlgType.PASSTHROUGH))
225
226
227# A full hypo selecting only on calo jets (step 1)
228# Passing isPerf = True disables the hypo
229# We set RoIs='' for same reason as described for jetCaloPreselMenuSequence
230@AccumulatorCache
231def jetCaloHypoMenuSequenceGenCfg(flags, isPerf, **jetDefDict):
232 jetsOut, jetDef = jetDefDict['final']
233 jetDefStr = jetDefToString(jetDef)
234 reco = InEventRecoCA(f"jetSeqCaloHypo_{jetDefStr}{'_perf' if isPerf else ''}_RecoSequence", inputMaker=getCaloInputMaker())
235
236 if 'LC' in jetDef.inputdef.label:
237 reco.mergeReco(jetmetTopoClusteringCfg_LC(flags, RoIs=''))
238 else:
239 reco.mergeReco(jetmetTopoClusteringCfg(flags, RoIs=''))
240
241 from .JetRecoSequencesConfig import JetRecoCfg
242 jetreco = JetRecoCfg(flags, **jetDefDict)
243 reco.mergeReco(jetreco)
244 log.debug("Generating jet calo hypo menu sequence for reco %s",jetDef.fullname())
245
246 hypoType = JetHypoAlgType.PASSTHROUGH if isPerf else JetHypoAlgType.STANDARD
247 selAcc = SelectionCA(selName(reco.name, hypoType=hypoType))
248 selAcc.mergeReco(reco)
249 selAcc.mergeHypo(jetSelectionCfg(flags, jetDefStr=jetDefStr, jetsIn=jetsOut, hypoType=hypoType))
250
251 return MenuSequence(flags, selAcc, HypoToolGen=hypoToolGenerator(hypoType))
252
253
254# A full hypo selecting only on heavy ion calo jets (step 1)
255# Passing isPerf = True disables the hypo
256# We set RoIs='' for same reason as described for jetCaloPreselMenuSequence
257@AccumulatorCache
258def jetHICaloHypoMenuSequenceGenCfg(flags, isPerf, **jetRecoDict):
259 reco = InEventRecoCA(f"jetSeqHICaloHypo_{jetRecoDict['jetDefStr']}{'_perf' if isPerf else ''}_RecoSequence", inputMaker=getCaloInputMaker())
260
261 reco.mergeReco( HICaloTowerCfg(flags) )
262
263 from .JetHIConfig import jetHIRecoSequenceCA
264 jetreco, jetsOut, jetDef = jetHIRecoSequenceCA(flags, clustersKey="HLT_HICaloClustersFS",towerKey = fs_towers, **jetRecoDict)
265 reco.mergeReco(jetreco)
266 log.debug("Generating jet HI calo hypo menu sequence for reco %s",jetDef.fullname())
267 hypoType = JetHypoAlgType.PASSTHROUGH if isPerf else JetHypoAlgType.STANDARD
268 selAcc = SelectionCA(selName(reco.name, hypoType=hypoType))
269 selAcc.mergeReco(reco)
270 selAcc.mergeHypo(jetSelectionCfg(flags, jetDefStr=jetRecoDict['jetDefStr'], jetsIn=jetsOut, hypoType=hypoType))
271
272 return MenuSequence(flags, selAcc, HypoToolGen=hypoToolGenerator(hypoType))
273
274
275# A full hypo selecting on jets with FS track reco (step 2)
276# To combine either with a presel or a passthrough sequence
277@AccumulatorCache
278def jetFSTrackingHypoMenuSequenceGenCfg(flags, isPerf, **jetDefDict):
279 jetsOut, jetDef = jetDefDict['final']
280 jetDefStr = jetDefToString(jetDef)
281 trkopt = jetDef.context
282 reco = InEventRecoCA(f"jetFSTrackingHypo_{jetDefStr}{'_perf' if isPerf else ''}_RecoSequence", inputMaker=getTrackingInputMaker(flags,trkopt))
283
284 assert trkopt != "notrk"
285 from .JetTrackingConfig import JetFSTrackingCfg
286 trk_acc = JetFSTrackingCfg(flags, trkopt, trkFSRoI)
287 reco.mergeReco(trk_acc)
288
289 from .JetRecoSequencesConfig import JetRecoCfg
290 jetreco = JetRecoCfg(flags, **jetDefDict)
291 reco.mergeReco(jetreco)
292 log.debug("Generating jet tracking hypo menu sequence for reco %s",jetDef.fullname())
293
294 if 'PFlow' in jetDef.basename and jetDef.basename.startswith('AntiKt4') and 'sub' in jetCalibFromJetDef(jetDef):
295 pvKey = flags.Trigger.InDetTracking.fullScan.vertex_jet
296 trig_evt_info_key = recordable("HLT_TCEventInfo_jet")
297
298 # Can encapsulate in another CA if necessary but only this instance
299 # currently needed
300 reco.mergeReco(
301 TrigEventInfoRecorderAlgCfg(
302 flags,
303 name="TrigEventInfoRecorderAlg_jet",
304 decoratePFlowInfo=True,
305 decorateEMTopoInfo=False,
306 trigEventInfoKey=trig_evt_info_key, primaryVertexInputName=pvKey,
307 RhoKey_EMTopo='HLT_Kt4EMTopoEventShape', RhoKey_PFlow='HLT_Kt4EMPFlowEventShape'
308 )
309 )
310
311 hypoType = JetHypoAlgType.PASSTHROUGH if isPerf else JetHypoAlgType.STANDARD
312 selAcc = SelectionCA(selName(reco.name, hypoType=hypoType))
313 selAcc.mergeReco(reco)
314 selAcc.mergeHypo(jetSelectionCfg(flags, jetDefStr=jetDefStr, jetsIn=jetsOut, hypoType=hypoType))
315
316 return MenuSequence(flags, selAcc, HypoToolGen=hypoToolGenerator(hypoType))
317
318
319# A full hypo selecting on jets with RoI track reco (step 2)
320# Needs to be preceded by a presel sequence, and be provided
321# with the input jets from which to define RoIs
322# Presel jets to be reused, which makes ghost association impossible
323# Substitute DR association decorator
324@AccumulatorCache
325def jetRoITrackJetTagSelCfg(flags, preselJetDef, isPresel=True):
326 # Seems odd, but we have to combine event and view execution here
327 # where InViewRecoCA will do all in view
328 jetDefStr = jetDefToString(preselJetDef)+'_roiftf'
329 trkopt = 'roiftf'
330 reco = InEventRecoCA(
331 f"jetRoITrackJetTagHypo_{jetDefStr}_RecoSequence",
332 inputMaker=getTrackingInputMaker(flags,trkopt)
333 )
334
335 # Decorate EventInfo with online beamspot info in global context -- avoid multiple executes
336 from ..Bjet.BjetFlavourTaggingConfig import OnlineBeamspotAugmenterCfg
337 reco.mergeReco(OnlineBeamspotAugmenterCfg(flags))
338
339 # Add to top-level serial sequence to ensure it is ready for in-view reco
340 from .JetRecoSequencesConfig import (
341 FastFtaggedJetCopyAlgCfg, JetRoITrackJetTagSequenceCfg, JetViewAlgCfg, formatFilteredJetsName, JET_DEFAULT_VIEW_PT_MIN_GEV
342 )
343 ftagjet_acc, ftaggedJetDef = FastFtaggedJetCopyAlgCfg(flags,preselJetDef)
344 ftaggedJetName = recordable(ftaggedJetDef.fullname())
345 reco.mergeReco(ftagjet_acc)
346
347 track_acc = JetRoITrackJetTagSequenceCfg(
348 flags,
349 ftaggedJetName,
350 trkopt,
351 RoIs=reco.inputMaker().InViewRoIs)
352 # Explicitly add the sequence here that is to run in the super-RoI view
353 seqname = f"JetRoITrackJetTag_{trkopt}_RecoSequence"
354 reco.addSequence(parOR(seqname),primary=True)
355 verifier = CompFactory.AthViews.ViewDataVerifier("roiftf_ftag_ViewDataVerifier")
356 verifier.DataObjects = [
357 ('SG::AuxElement',f'EventInfo.{dec}')
358 for dec in ['onlineBeamPosSigmaXY','onlineBeamPosX','onlineBeamPosY','onlineBeamPosZ']
359 ]
360 reco.addEventAlgo(verifier,seqname)
361 reco.merge(track_acc,seqname)
362 reco.inputMaker().ViewNodeName = seqname
363
364 # Run the JetViewAlg sequence to filter out low pT jets
365 # Have to run it outside of JetRoITrackJetTagSequence (which runs in EventView), so that hypo recognises the filtered jets.
366 jetview_Acc = JetViewAlgCfg(flags,jetDef=ftaggedJetDef)
367 filtered_jetsIn = formatFilteredJetsName(ftaggedJetName,JET_DEFAULT_VIEW_PT_MIN_GEV)
368 reco.merge(jetview_Acc)
369
370 # Needs track-to-jet association here, maybe with dR decorator
371 hypoType = JetHypoAlgType.ROIPRESEL if isPresel else JetHypoAlgType.STANDARD
372 selAcc = SelectionCA(selName(reco.name, hypoType=hypoType))
373 selAcc.mergeReco(reco)
374 selAcc.mergeHypo(jetSelectionCfg(flags, jetDefStr=jetDefStr, jetsIn=filtered_jetsIn, hypoType=hypoType))
375 return selAcc, hypoType
376
377def jetRoITrackJetTagHypoMenuSequenceGenCfg(flags, jetDef, isPresel=True):
378 selAcc, hypoType = jetRoITrackJetTagSelCfg(flags, jetDef, isPresel)
379 return MenuSequence(flags, selAcc, HypoToolGen=hypoToolGenerator(hypoType))
380
381
382
383# HitZ on the super-RoI hits, before any tracking: returns the reco and the decorated jets
384def jetRoIHitZRecoCfg(flags, preselJetDef):
385 jetDefStr = jetDefToString(preselJetDef)+'_roihitz'
386 reco = InEventRecoCA(
387 f"jetRoIHitZHypo_{jetDefStr}_RecoSequence",
388 inputMaker=getHitZInputMaker(flags)
389 )
390
391 from .JetRecoSequencesConfig import (
392 HitZJetCopyAlgCfg, formatFilteredJetsName, JET_DEFAULT_VIEW_PT_MIN_GEV
393 )
394 from .JetRecoCommon import getDecorList
395 hitzjet_acc, hitzJetDef = HitZJetCopyAlgCfg(flags,preselJetDef)
396 hitzJetName = recordable(hitzJetDef.fullname())
397 reco.mergeReco(hitzjet_acc)
398
399 seqname = "JetRoIHitZ_RecoSequence"
400 reco.addSequence(parOR(seqname),primary=True)
401 from ..Bjet.BjetHitZConfig import hitZRoICfg
402 reco.merge(hitZRoICfg(flags, hitzJetName, RoIs=reco.inputMaker().InViewRoIs), seqname)
403 reco.inputMaker().ViewNodeName = seqname
404
405 # Not JetViewAlgCfg: its cache keys on the JetDefinition, whose hash ignores
406 # the suffix, so it would hand back the RoI FTF step's _fastftag view alg
407 filtered_jetsIn = formatFilteredJetsName(hitzJetName,JET_DEFAULT_VIEW_PT_MIN_GEV)
408 reco.addEventAlgo(CompFactory.JetViewAlg(
409 "jetview_"+filtered_jetsIn,
410 InputContainer=hitzJetName,
411 OutputContainer=filtered_jetsIn,
412 PtMin=JET_DEFAULT_VIEW_PT_MIN_GEV*1e3,
413 DecorDeps=getDecorList(hitzJetDef),
414 ))
415 return reco, filtered_jetsIn
jetHICaloHypoMenuSequenceGenCfg(flags, isPerf, **jetRecoDict)
jetCaloPreselMenuSequenceGenCfg(flags, **jetDefDict)
— Menu Sequence getters —
getTrackingInputMaker(AthConfigFlags flags, str trkopt)
jetSelectionCfg(flags, jetDefStr, jetsIn, hypoType=JetHypoAlgType.STANDARD)
jetCaloHypoMenuSequenceGenCfg(flags, isPerf, **jetDefDict)
jetFSTrackingHypoMenuSequenceGenCfg(flags, isPerf, **jetDefDict)
jetRoITrackJetTagHypoMenuSequenceGenCfg(flags, jetDef, isPresel=True)
selName(recoSequenceName, hypoType=JetHypoAlgType.STANDARD)
jetRoITrackJetTagSelCfg(flags, preselJetDef, isPresel=True)