ATLAS Offline Software
Loading...
Searching...
No Matches
EventBuildingSequences.py
Go to the documentation of this file.
2# Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3#
4import functools
5from TrigEDMConfig import DataScoutingInfo
6from TrigEDMConfig.TriggerEDM import recordable
7from TriggerMenuMT.HLT.Menu import EventBuildingInfo
8from TriggerMenuMT.HLT.Config.MenuComponents import ChainStep, MenuSequence, SelectionCA, InEventRecoCA
9from TrigPartialEventBuilding.TrigPartialEventBuildingConfig import StaticPEBInfoWriterToolCfg, RoIPEBInfoWriterToolCfg
10from HLTSeeding.HLTSeedingConfig import mapThresholdToL1DecisionCollection
11from libpyeformat_helper import SourceIdentifier, SubDetector
12from AthenaConfiguration.ComponentFactory import CompFactory
13from .LATOMESourceIDs import LATOMESourceIDs
14from .FEXSourceIDs import FEXSourceIDs
15from AthenaCommon.Logging import logging
16log = logging.getLogger(__name__)
17
18
19def addEventBuildingSequence(flags, chain, eventBuildType, chainDict):
20 '''
21 Add an extra ChainStep to a Chain object with a PEBInfoWriter sequence configured for the eventBuildType
22 '''
23 if not eventBuildType:
24 log.error('No eventBuildType specified')
25 return
26 if eventBuildType not in EventBuildingInfo.getAllEventBuildingIdentifiers():
27 log.error('eventBuildType \'%s\' not found in the allowed Event Building identifiers', eventBuildType)
28 return
29
30 seq = functools.partial(pebMenuSequenceGenCfg, flags, chain=chain, eventBuildType=eventBuildType, chainDict=chainDict)
31
32 if len(chain.steps)==0:
33 # noalg PEB chain
34 step_name = 'PEBInfoWriter_{:s}'.format( eventBuildType)
35 step = ChainStep(name=step_name,
36 SequenceGens=[seq],
37 chainDicts=[chainDict])
38 else:
39 # standard PEB chain
40 prevStep = chain.steps[-1]
41 step_name = 'EventBuild_{:s}_PEBInfoWriter_{:s}'.format(prevStep.name, eventBuildType)
42 step = ChainStep(name=step_name,
43 SequenceGens=[seq for _ in range(prevStep.nLegs)],
44 chainDicts=prevStep.stepDicts)
45
46 chain.steps.append(step)
47
48def pebInfoWriterToolCfg(flags, name, eventBuildType):
49 """Create PEBInfoWriterTool configuration for the eventBuildType"""
50
51 # Main HLTResult ROB:
52 HLT_ROB = SourceIdentifier(SubDetector.TDAQ_HLT, DataScoutingInfo.getFullHLTResultID())
53
54 acc = None
55 if 'BeamSpotPEB' == eventBuildType:
56 acc = StaticPEBInfoWriterToolCfg(
57 flags, name,
58 subDets = [SubDetector.PIXEL_BARREL,
59 SubDetector.PIXEL_DISK_SIDE, # note different name in C++, ADHI-4753
60 SubDetector.PIXEL_B_LAYER,
61 SubDetector.PIXEL_IBL,
62 SubDetector.SCT_BARREL_A_SIDE,
63 SubDetector.SCT_BARREL_C_SIDE,
64 SubDetector.SCT_ENDCAP_A_SIDE,
65 SubDetector.SCT_ENDCAP_C_SIDE,
66 SubDetector.TDAQ_CTP] )
67
68 elif 'MuonTrkPEB' == eventBuildType:
69 acc = RoIPEBInfoWriterToolCfg(
70 flags, name,
71 regSelDets = ['Pixel', 'SCT', 'TRT', 'MDT', 'RPC', 'TGC', 'CSC', 'MM', 'sTGC'],
72 MaxRoIs = 99,
73 EtaWidth = 0.75, # values from run2 check later
74 PhiWidth = 0.75, # values from run2 check later
75 subDets = [SubDetector.TDAQ_CTP], # add full CTP data to the output
76 ROBs = [HLT_ROB] )
77
78 elif 'IDCalibPEB' == eventBuildType:
79 acc = RoIPEBInfoWriterToolCfg(
80 flags, name,
81 regSelDets = ['Pixel', 'SCT', 'TRT'],
82 EtaWidth = 0.1,
83 PhiWidth = 0.1,
84 subDets = [SubDetector.TDAQ_CTP] )
85
86 elif 'LArPEBCalib' == eventBuildType:
87 acc = StaticPEBInfoWriterToolCfg(
88 flags, name,
89 subDets = [SubDetector.LAR_EM_BARREL_A_SIDE,
90 SubDetector.LAR_EM_BARREL_C_SIDE,
91 SubDetector.LAR_EM_ENDCAP_A_SIDE,
92 SubDetector.LAR_EM_ENDCAP_C_SIDE,
93 SubDetector.LAR_HAD_ENDCAP_A_SIDE,
94 SubDetector.LAR_HAD_ENDCAP_C_SIDE,
95 SubDetector.LAR_FCAL_A_SIDE,
96 SubDetector.LAR_FCAL_C_SIDE,
97 SubDetector.LAR_EM_BARREL_ENDCAP_A_SIDE,
98 SubDetector.LAR_EM_BARREL_ENDCAP_C_SIDE,
99 SubDetector.LAR_EM_HAD_ENDCAP_A_SIDE,
100 SubDetector.LAR_EM_HAD_ENDCAP_C_SIDE,
101 SubDetector.TDAQ_CTP] )
102
103 elif eventBuildType in ('LArPEBHLT', 'LArPEB'):
104 acc = RoIPEBInfoWriterToolCfg(
105 flags, name,
106 regSelDets = ['Pixel', 'SCT', 'TRT', 'TTEM', 'TTHEC', 'FCALEM', 'FCALHAD'],
107 MaxRoIs = 5,
108 ROBs = [HLT_ROB] + LATOMESourceIDs, # add full-scan LATOME data
109 subDets = [SubDetector.TDAQ_CTP] )
110
111 elif 'LATOMEPEB' == eventBuildType:
112 acc = StaticPEBInfoWriterToolCfg(
113 flags, name,
114 ROBs = LATOMESourceIDs + FEXSourceIDs, # add full-scan LATOME and FEX data
115 subDets = [SubDetector.TDAQ_CTP] )
116
117 elif 'SCTPEB' == eventBuildType:
118 acc = StaticPEBInfoWriterToolCfg(
119 flags, name,
120 subDets = [SubDetector.SCT_BARREL_A_SIDE,
121 SubDetector.SCT_BARREL_C_SIDE,
122 SubDetector.SCT_ENDCAP_A_SIDE,
123 SubDetector.SCT_ENDCAP_C_SIDE,
124 SubDetector.TDAQ_CTP] )
125
126 elif 'TilePEB' == eventBuildType:
127 acc = StaticPEBInfoWriterToolCfg(
128 flags, name,
129 subDets = [SubDetector.TILECAL_LASER_CRATE,
130 SubDetector.TILECAL_BARREL_A_SIDE,
131 SubDetector.TILECAL_BARREL_C_SIDE,
132 SubDetector.TILECAL_EXT_A_SIDE,
133 SubDetector.TILECAL_EXT_C_SIDE,
134 SubDetector.TDAQ_CTP,
135 SubDetector.TDAQ_CALO_PREPROC, # = 0x71
136 SubDetector.TDAQ_CALO_CLUSTER_PROC_DAQ, # = 0x72
137 SubDetector.TDAQ_CALO_CLUSTER_PROC_ROI, # = 0x73
138 SubDetector.TDAQ_CALO_JET_PROC_DAQ, # = 0x74
139 SubDetector.TDAQ_CALO_JET_PROC_ROI # = 0x75
140 ],
141 MatchTriggerType = [0x31, 0x32, 0x34] if '_L1CALREQ' in name else [] )
142
143 elif 'LArPEBNoise' == eventBuildType:
144 acc = RoIPEBInfoWriterToolCfg(
145 flags, name,
146 regSelDets = ['Pixel', 'SCT', 'TRT', 'TTEM', 'TTHEC', 'FCALEM', 'FCALHAD'],
147 MaxRoIs = 5,
148 ROBs = [HLT_ROB] + LATOMESourceIDs,
149 subDets = [SubDetector.MUON_MMEGA_ENDCAP_A_SIDE,
150 SubDetector.MUON_MMEGA_ENDCAP_C_SIDE,
151 SubDetector.MUON_STGC_ENDCAP_A_SIDE,
152 SubDetector.MUON_STGC_ENDCAP_C_SIDE,
153 SubDetector.TDAQ_CTP] )
154
155 elif 'ZDCPEB' == eventBuildType:
156 acc = StaticPEBInfoWriterToolCfg(
157 flags, name,
158 subDets = [SubDetector.FORWARD_ZDC,
159 SubDetector.TDAQ_CTP],
160 MatchTriggerType = [0x69, 0x6a, 0x6c] if '_L1CALREQ' in name else [] )
161
162 elif 'AFPPEB' == eventBuildType:
163 acc = StaticPEBInfoWriterToolCfg(
164 flags, name,
165 subDets = [SubDetector.FORWARD_AFP,
166 SubDetector.TDAQ_CTP] )
167
168 elif 'LumiPEB' == eventBuildType:
169 acc = StaticPEBInfoWriterToolCfg(
170 flags, name,
171 ROBs = [HLT_ROB],
172 subDets = [SubDetector.PIXEL_IBL,
173 SubDetector.PIXEL_BARREL,
174 SubDetector.PIXEL_DISK_SIDE,
175 SubDetector.PIXEL_B_LAYER,
176 SubDetector.SCT_BARREL_A_SIDE,
177 SubDetector.SCT_BARREL_C_SIDE,
178 SubDetector.SCT_ENDCAP_A_SIDE,
179 SubDetector.SCT_ENDCAP_C_SIDE,
180 SubDetector.PIXEL_DBM,
181 SubDetector.TDAQ_CTP] )
182
183 elif 'Lvl1CaloPEB' == eventBuildType:
184 acc = StaticPEBInfoWriterToolCfg(
185 flags, name,
186 ROBs = [HLT_ROB],
187 MaxRoIs = 1,
188 subDets = [SubDetector.TDAQ_CALO_PREPROC,
189 SubDetector.TDAQ_CALO_CLUSTER_PROC_DAQ,
190 SubDetector.TDAQ_CALO_CLUSTER_PROC_ROI,
191 SubDetector.TDAQ_CALO_JET_PROC_DAQ,
192 SubDetector.TDAQ_CALO_JET_PROC_ROI,
193 SubDetector.TDAQ_CTP] )
194
195 elif 'DarkJetPEBTLA' == eventBuildType:
196 acc = RoIPEBInfoWriterToolCfg(
197 flags, name,
198 # Add subdetectors within a ROI for PEB
199 regSelDets = ['Pixel', 'SCT', 'TRT', 'TTEM', 'TTHEC', 'FCALEM', 'FCALHAD', 'TILE', 'MDT', 'RPC', 'TGC', 'CSC', 'MM', 'STGC'],
200 # DS HLT result
201 ROBs = [SourceIdentifier(SubDetector.TDAQ_HLT,
202 DataScoutingInfo.getDataScoutingResultID(eventBuildType))],
203 EtaWidth = 0.6, # half-width (the RoI is between etaJet-EtaWidth and etaJet+EtaWidth)
204 PhiWidth = 0.6,
205 MaxRoIs = 3 )
206
207 elif 'EgammaPEBTLA' == eventBuildType:
208 acc = RoIPEBInfoWriterToolCfg(
209 flags, name,
210 # Add subdetectors within a ROI for PEB
211 regSelDets = ['Pixel', 'SCT', 'TRT', 'TTEM', 'TTHEC', 'FCALEM', 'FCALHAD', 'TILE'],
212 # DS HLT result
213 ROBs = [SourceIdentifier(SubDetector.TDAQ_HLT,
214 DataScoutingInfo.getDataScoutingResultID(eventBuildType))],
215 EtaWidth = 0.4, # half-width (the RoI is between etaJet-EtaWidth and etaJet+EtaWidth)
216 PhiWidth = 0.4,
217 MaxRoIs = 6 )
218 elif 'FTagPEBTLA' == eventBuildType:
219 acc = RoIPEBInfoWriterToolCfg(
220 flags, name,
221 # Add subdetectors within a ROI for PEB
222 regSelDets = ['Pixel', 'SCT'],
223 # DS HLT result
224 ROBs = [SourceIdentifier(SubDetector.TDAQ_HLT,
225 DataScoutingInfo.getDataScoutingResultID(eventBuildType))],
226 EtaWidth = 0.4, # half-width (the RoI is between etaJet-EtaWidth and etaJet+EtaWidth)
227 PhiWidth = 0.4,
228 MaxRoIs = 6 )
229
230 elif eventBuildType in DataScoutingInfo.getAllDataScoutingIdentifiers():
231 # Pure DataScouting configuration
232 acc = StaticPEBInfoWriterToolCfg(
233 flags, name,
234 ROBs = [SourceIdentifier(SubDetector.TDAQ_HLT,
235 DataScoutingInfo.getDataScoutingResultID(eventBuildType))] )
236
237 # Name not matched
238 if acc is None:
239 log.error('PEBInfoWriterTool configuration is missing for event building identifier \'%s\'', eventBuildType)
240
241 return acc
242
243def getPEBBuildSuffix(chain, eventBuildType):
244 '''
245 Define suffix for unique configurations - prevents config clashes.
246 '''
247
248 suffix=''
249
250 _isFullscan = isFullScan(chain)
251 _isRoIBasedPEB = EventBuildingInfo.isRoIBasedPEB(eventBuildType)
252 _isNoalg = isNoAlg(chain)
253
254 if _isNoalg or not _isRoIBasedPEB: suffix+='_noSeed'
255 if _isFullscan and _isRoIBasedPEB: suffix+='_RoIBasedFS'
256
257 return suffix
258
259def pebInputMaker(flags, chain, eventBuildType):
260
261 suffix= getPEBBuildSuffix(chain, eventBuildType)
262
263 # Check if we are configuring a chain with at least one full-scan leg
264 isFullscan = isFullScan(chain)
265 # Check if we are configuring RoI-based PEB
266 _isRoIBasedPEB = EventBuildingInfo.isRoIBasedPEB(eventBuildType)
267 _isNoalg = isNoAlg(chain)
268
269 # Configure the InputMaker
270 maker = CompFactory.InputMakerForRoI("IMpeb_" + eventBuildType + suffix)
271 maker.RoIs = "pebInputRoI_" + eventBuildType + suffix
272 # Allow more than one feature per input RoI if we care about RoIs, and have at least one Step
273 maker.mergeUsingFeature = _isRoIBasedPEB and not _isNoalg
274
275 # Configure the InputMaker RoI tool
276 if _isNoalg or not _isRoIBasedPEB:
277 # Streamers or static PEB: use initial RoI
278 maker.RoITool = CompFactory.ViewCreatorInitialROITool()
279 elif isFullscan and _isRoIBasedPEB:
280 # Full-scan chains with RoI-based PEB: create RoI around feature IParticle
281 maker.RoITool = CompFactory.ViewCreatorCentredOnIParticleROITool()
282 maker.RoITool.RoisWriteHandleKey = recordable("HLT_Roi_" + eventBuildType)
283 else:
284 # Other chains: use previous RoI
285 maker.RoITool = CompFactory.ViewCreatorPreviousROITool()
286
287 return maker
288
289
290def pebMenuSequenceGenCfg(flags, chain, eventBuildType, chainDict):
291 '''
292 Return the MenuSequence for the PEB input maker for this chain.
293 '''
294
295 def pebInfoWriterToolGenerator(flags, chainDict):
296 return pebInfoWriterToolCfg(flags, chainDict['chainName'], eventBuildType)
297
298 suffix = getPEBBuildSuffix(chain, eventBuildType)
299
300 inputMaker = pebInputMaker(flags, chain, eventBuildType)
301 recoAcc = InEventRecoCA("pebSequence_"+eventBuildType, inputMaker=inputMaker)
302 selAcc = SelectionCA("pebMainSeq_"+eventBuildType+suffix)
303 selAcc.mergeReco(recoAcc)
304 selAcc.addHypoAlgo(CompFactory.PEBInfoWriterAlg('PEBInfoWriterAlg_' + eventBuildType+suffix))
305
306 return MenuSequence(flags,
307 selAcc,
308 HypoToolGen = pebInfoWriterToolGenerator)
309
310
311def findEventBuildingStep(chainConfig):
312 pebSteps = [s for s in chainConfig.steps if 'PEBInfoWriter' in s.name and 'EmptyPEBAlign' not in s.name]
313 if len(pebSteps) == 0:
314 return None
315 elif len(pebSteps) > 1:
316 raise RuntimeError('Multiple Event Building steps in one chain are not supported but found in chain ' + chainConfig.name)
317 return pebSteps[0]
318
319
320def alignEventBuildingSteps(chain_configs, chain_dicts):
321
322 all_peb_chain_configs = [ch for ch in chain_configs if len(chain_dicts[ch.name]['eventBuildType'])>0]
323
324 def getPebStepPosition(chainConfig):
325 pebStep = findEventBuildingStep(chainConfig)
326 return chainConfig.steps.index(pebStep) + 1
327
328 # First loop to find the maximal PEB step positions to which we need to align
329 maxPebStepPosition = {} # {eventBuildType: N}
330 for chain in all_peb_chain_configs:
331 pebStepPosition = getPebStepPosition(chain)
332 ebt = chain_dicts[chain.name]['eventBuildType']
333 if ebt not in maxPebStepPosition or pebStepPosition > maxPebStepPosition[ebt]:
334 maxPebStepPosition[ebt] = pebStepPosition
335
336 # Second loop to insert empty steps before the PEB steps where needed
337 for chain in all_peb_chain_configs:
338 pebStepPosition = getPebStepPosition(chain)
339 ebt = chain_dicts[chain.name]['eventBuildType']
340 if pebStepPosition < maxPebStepPosition[ebt]:
341 numStepsNeeded = maxPebStepPosition[ebt] - pebStepPosition
342 log.debug('Aligning PEB step for chain %s by adding %d empty steps', chain.name, numStepsNeeded)
343 chain.insertEmptySteps('EmptyPEBAlign', numStepsNeeded, pebStepPosition-1)
344 chain.numberAllSteps()
345
346
347def isFullScan(chain):
348 '''Helper function to determine if chain is full scan'''
349 # Check if we are configuring a chain with at least one full-scan leg
350 return (mapThresholdToL1DecisionCollection('FSNOSEED') in chain.L1decisions)
351
352
353def isNoAlg(chain):
354 '''Helper function to determine if chain has HLT reco'''
355 return (len(chain.steps) == 1 and "PEBInfoWriter" in chain.steps[0].name)
356
357
358# Unit test
359if __name__ == "__main__":
360 from AthenaConfiguration.TestDefaults import defaultTestFiles, defaultGeometryTags
361 from AthenaConfiguration.AllConfigFlags import initConfigFlags
362 flags = initConfigFlags()
363 flags.Input.Files = defaultTestFiles.RAW_RUN3
364 flags.GeoModel.AtlasVersion = defaultGeometryTags.RUN3
365 flags.lock()
366
367 # Ensure all DS identifiers have been added to the EB list:
368 assert( set(DataScoutingInfo.getAllDataScoutingIdentifiers()).issubset(
369 EventBuildingInfo.getAllEventBuildingIdentifiers()) )
370
371 failures = 0
372 for eb_identifier in EventBuildingInfo.getAllEventBuildingIdentifiers():
373 log.info('Checking %s event building identifier', eb_identifier)
374 tool = None
375 try:
376 cfg = pebInfoWriterToolCfg(flags, 'TestTool_'+eb_identifier, eb_identifier)
377 tool = cfg.popPrivateTools()
378 except Exception as ex:
379 failures += 1
380 log.error('Caught exception while configuring PEBInfoWriterTool for %s: %s', eb_identifier, ex)
381 continue
382
383 cfg.wasMerged()
384
385 if not tool:
386 failures += 1
387 log.error('No tool created for %s', eb_identifier)
388 continue
389
390 if not isinstance(tool, (CompFactory.StaticPEBInfoWriterTool, CompFactory.RoIPEBInfoWriterTool)):
391 failures += 1
392 log.error('Unexpected tool type for %s: %s', eb_identifier, tool.getType())
393 continue
394
395 isRoIBasedPEB = EventBuildingInfo.isRoIBasedPEB(eb_identifier)
396 if isinstance(tool, CompFactory.RoIPEBInfoWriterTool) != isRoIBasedPEB:
397 failures += 1
398 log.error('Tool type %s for %s but isRoIBasedPEB==%s',
399 tool.getType(), eb_identifier, isRoIBasedPEB)
400 continue
401
402 robs = tool.ROBList if tool.getType() == 'StaticPEBInfoWriterTool' else tool.ExtraROBs
403 dets = tool.SubDetList if tool.getType() == 'StaticPEBInfoWriterTool' else tool.ExtraSubDets
404 robs_check_passed = True
405 is_data_scouting = False
406 for rob_id in robs:
407 rob_sid = SourceIdentifier(rob_id)
408 rob_det_id = rob_sid.subdetector_id()
409 if rob_det_id == SubDetector.TDAQ_HLT and rob_sid.module_id() != DataScoutingInfo.getFullHLTResultID():
410 is_data_scouting = True
411 if int(rob_det_id) in dets:
412 robs_check_passed = False
413 log.error('Redundant configuration for %s: ROB %s added to the ROB list while full SubDetector '
414 '%s is already in the SubDets list', eb_identifier, rob_sid.human(), str(rob_det_id))
415
416 if not robs_check_passed:
417 failures += 1
418 continue
419
420 # Check for always-present fragment to avoid PEB becoming FEB (ATR-24378)
421 # DataScouting is exempt as it always comes with a dedicated HLT result
422 always_present_rob = SourceIdentifier(SubDetector.TDAQ_CTP, 0) # cannot run HLT without CTP so it is always present
423 if not is_data_scouting and \
424 always_present_rob.code() not in robs and \
425 always_present_rob.subdetector_id() not in dets:
426 log.error('Bug-prone configuration for %s: without always-present CTP data in the PEB list, the '
427 'streaming may break when all requested detectors are disabled. Add CTP data to this PEB '
428 'configuration to prevent the bug (ATR-24378).', eb_identifier)
429 failures += 1
430 continue
431
432 log.info('%s correctly configured', tool.name() if callable(tool.name) else tool.name)
433
434 import sys
435 sys.exit(failures)
STL class.
pebMenuSequenceGenCfg(flags, chain, eventBuildType, chainDict)
addEventBuildingSequence(flags, chain, eventBuildType, chainDict)