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 'IDScanPEB' == eventBuildType:
184 acc = StaticPEBInfoWriterToolCfg(
185 flags, name,
186 ROBs = [HLT_ROB],
187 subDets = [SubDetector.PIXEL_IBL,
188 SubDetector.PIXEL_BARREL,
189 SubDetector.PIXEL_DISK_SIDE,
190 SubDetector.PIXEL_B_LAYER,
191 SubDetector.SCT_BARREL_A_SIDE,
192 SubDetector.SCT_BARREL_C_SIDE,
193 SubDetector.SCT_ENDCAP_A_SIDE,
194 SubDetector.SCT_ENDCAP_C_SIDE,
195 SubDetector.PIXEL_DBM,
196 SubDetector.TDAQ_CTP] )
197
198 elif 'Lvl1CaloPEB' == eventBuildType:
199 acc = StaticPEBInfoWriterToolCfg(
200 flags, name,
201 ROBs = [HLT_ROB],
202 MaxRoIs = 1,
203 subDets = [SubDetector.TDAQ_CALO_PREPROC,
204 SubDetector.TDAQ_CALO_CLUSTER_PROC_DAQ,
205 SubDetector.TDAQ_CALO_CLUSTER_PROC_ROI,
206 SubDetector.TDAQ_CALO_JET_PROC_DAQ,
207 SubDetector.TDAQ_CALO_JET_PROC_ROI,
208 SubDetector.TDAQ_CTP] )
209
210 elif 'Lvl1CaloLatomePEB' == eventBuildType:
211 acc = StaticPEBInfoWriterToolCfg(
212 flags, name,
213 ROBs = LATOMESourceIDs,
214 MaxRoIs = 1,
215 subDets = [SubDetector.TDAQ_CALO_PREPROC,
216 SubDetector.TDAQ_CTP,
217 SubDetector.TDAQ_HLT,
218 SubDetector.TDAQ_CALO_TOPO_PROC,
219 SubDetector.TDAQ_CALO_FEAT_EXTRACT_DAQ,
220 SubDetector.TDAQ_CALO_FEAT_EXTRACT_ROI] )
221
222 elif 'DarkJetPEBTLA' == eventBuildType:
223 acc = RoIPEBInfoWriterToolCfg(
224 flags, name,
225 # Add subdetectors within a ROI for PEB
226 regSelDets = ['Pixel', 'SCT', 'TRT', 'TTEM', 'TTHEC', 'FCALEM', 'FCALHAD', 'TILE', 'MDT', 'RPC', 'TGC', 'CSC', 'MM', 'STGC'],
227 # DS HLT result
228 ROBs = [SourceIdentifier(SubDetector.TDAQ_HLT,
229 DataScoutingInfo.getDataScoutingResultID(eventBuildType))],
230 EtaWidth = 0.6, # half-width (the RoI is between etaJet-EtaWidth and etaJet+EtaWidth)
231 PhiWidth = 0.6,
232 MaxRoIs = 3 )
233
234 elif 'EgammaPEBTLA' == eventBuildType:
235 acc = RoIPEBInfoWriterToolCfg(
236 flags, name,
237 # Add subdetectors within a ROI for PEB
238 regSelDets = ['Pixel', 'SCT', 'TRT', 'TTEM', 'TTHEC', 'FCALEM', 'FCALHAD', 'TILE'],
239 # DS HLT result
240 ROBs = [SourceIdentifier(SubDetector.TDAQ_HLT,
241 DataScoutingInfo.getDataScoutingResultID(eventBuildType))],
242 EtaWidth = 0.4, # half-width (the RoI is between etaJet-EtaWidth and etaJet+EtaWidth)
243 PhiWidth = 0.4,
244 MaxRoIs = 6 )
245 elif 'FTagPEBTLA' == eventBuildType:
246 acc = RoIPEBInfoWriterToolCfg(
247 flags, name,
248 # Add subdetectors within a ROI for PEB
249 regSelDets = ['Pixel', 'SCT'],
250 # DS HLT result
251 ROBs = [SourceIdentifier(SubDetector.TDAQ_HLT,
252 DataScoutingInfo.getDataScoutingResultID(eventBuildType))],
253 EtaWidth = 0.4, # half-width (the RoI is between etaJet-EtaWidth and etaJet+EtaWidth)
254 PhiWidth = 0.4,
255 MaxRoIs = 6 )
256
257 elif eventBuildType in DataScoutingInfo.getAllDataScoutingIdentifiers():
258 # Pure DataScouting configuration
259 acc = StaticPEBInfoWriterToolCfg(
260 flags, name,
261 ROBs = [SourceIdentifier(SubDetector.TDAQ_HLT,
262 DataScoutingInfo.getDataScoutingResultID(eventBuildType))] )
263
264 # Name not matched
265 if acc is None:
266 log.error('PEBInfoWriterTool configuration is missing for event building identifier \'%s\'', eventBuildType)
267
268 return acc
269
270def getPEBBuildSuffix(chain, eventBuildType):
271 '''
272 Define suffix for unique configurations - prevents config clashes.
273 '''
274
275 suffix=''
276
277 _isFullscan = isFullScan(chain)
278 _isRoIBasedPEB = EventBuildingInfo.isRoIBasedPEB(eventBuildType)
279 _isNoalg = isNoAlg(chain)
280
281 if _isNoalg or not _isRoIBasedPEB: suffix+='_noSeed'
282 if _isFullscan and _isRoIBasedPEB: suffix+='_RoIBasedFS'
283
284 return suffix
285
286def pebInputMaker(flags, chain, eventBuildType):
287
288 suffix= getPEBBuildSuffix(chain, eventBuildType)
289
290 # Check if we are configuring a chain with at least one full-scan leg
291 isFullscan = isFullScan(chain)
292 # Check if we are configuring RoI-based PEB
293 _isRoIBasedPEB = EventBuildingInfo.isRoIBasedPEB(eventBuildType)
294 _isNoalg = isNoAlg(chain)
295
296 # Configure the InputMaker
297 maker = CompFactory.InputMakerForRoI("IMpeb_" + eventBuildType + suffix)
298 maker.RoIs = "pebInputRoI_" + eventBuildType + suffix
299 # Allow more than one feature per input RoI if we care about RoIs, and have at least one Step
300 maker.mergeUsingFeature = _isRoIBasedPEB and not _isNoalg
301
302 # Configure the InputMaker RoI tool
303 if _isNoalg or not _isRoIBasedPEB:
304 # Streamers or static PEB: use initial RoI
305 maker.RoITool = CompFactory.ViewCreatorInitialROITool()
306 elif isFullscan and _isRoIBasedPEB:
307 # Full-scan chains with RoI-based PEB: create RoI around feature IParticle
308 maker.RoITool = CompFactory.ViewCreatorCentredOnIParticleROITool()
309 maker.RoITool.RoisWriteHandleKey = recordable("HLT_Roi_" + eventBuildType)
310 else:
311 # Other chains: use previous RoI
312 maker.RoITool = CompFactory.ViewCreatorPreviousROITool()
313
314 return maker
315
316
317def pebMenuSequenceGenCfg(flags, chain, eventBuildType, chainDict):
318 '''
319 Return the MenuSequence for the PEB input maker for this chain.
320 '''
321
322 def pebInfoWriterToolGenerator(flags, chainDict):
323 return pebInfoWriterToolCfg(flags, chainDict['chainName'], eventBuildType)
324
325 suffix = getPEBBuildSuffix(chain, eventBuildType)
326
327 inputMaker = pebInputMaker(flags, chain, eventBuildType)
328 recoAcc = InEventRecoCA("pebSequence_"+eventBuildType, inputMaker=inputMaker)
329 selAcc = SelectionCA("pebMainSeq_"+eventBuildType+suffix)
330 selAcc.mergeReco(recoAcc)
331 selAcc.addHypoAlgo(CompFactory.PEBInfoWriterAlg('PEBInfoWriterAlg_' + eventBuildType+suffix))
332
333 return MenuSequence(flags,
334 selAcc,
335 HypoToolGen = pebInfoWriterToolGenerator)
336
337
338def findEventBuildingStep(chainConfig):
339 pebSteps = [s for s in chainConfig.steps if 'PEBInfoWriter' in s.name and 'EmptyPEBAlign' not in s.name]
340 if len(pebSteps) == 0:
341 return None
342 elif len(pebSteps) > 1:
343 raise RuntimeError('Multiple Event Building steps in one chain are not supported but found in chain ' + chainConfig.name)
344 return pebSteps[0]
345
346
347def alignEventBuildingSteps(chain_configs, chain_dicts):
348
349 all_peb_chain_configs = [ch for ch in chain_configs if len(chain_dicts[ch.name]['eventBuildType'])>0]
350
351 def getPebStepPosition(chainConfig):
352 pebStep = findEventBuildingStep(chainConfig)
353 return chainConfig.steps.index(pebStep) + 1
354
355 # First loop to find the maximal PEB step positions to which we need to align
356 maxPebStepPosition = {} # {eventBuildType: N}
357 for chain in all_peb_chain_configs:
358 pebStepPosition = getPebStepPosition(chain)
359 ebt = chain_dicts[chain.name]['eventBuildType']
360 if ebt not in maxPebStepPosition or pebStepPosition > maxPebStepPosition[ebt]:
361 maxPebStepPosition[ebt] = pebStepPosition
362
363 # Second loop to insert empty steps before the PEB steps where needed
364 for chain in all_peb_chain_configs:
365 pebStepPosition = getPebStepPosition(chain)
366 ebt = chain_dicts[chain.name]['eventBuildType']
367 if pebStepPosition < maxPebStepPosition[ebt]:
368 numStepsNeeded = maxPebStepPosition[ebt] - pebStepPosition
369 log.debug('Aligning PEB step for chain %s by adding %d empty steps', chain.name, numStepsNeeded)
370 chain.insertEmptySteps('EmptyPEBAlign', numStepsNeeded, pebStepPosition-1)
371 chain.numberAllSteps()
372
373
374def isFullScan(chain):
375 '''Helper function to determine if chain is full scan'''
376 # Check if we are configuring a chain with at least one full-scan leg
377 return (mapThresholdToL1DecisionCollection('FSNOSEED') in chain.L1decisions)
378
379
380def isNoAlg(chain):
381 '''Helper function to determine if chain has HLT reco'''
382 return (len(chain.steps) == 1 and "PEBInfoWriter" in chain.steps[0].name)
383
384
385# Unit test
386if __name__ == "__main__":
387 from AthenaConfiguration.TestDefaults import defaultTestFiles, defaultGeometryTags
388 from AthenaConfiguration.AllConfigFlags import initConfigFlags
389 flags = initConfigFlags()
390 flags.Input.Files = defaultTestFiles.RAW_RUN3
391 flags.GeoModel.AtlasVersion = defaultGeometryTags.RUN3
392 flags.lock()
393
394 # Ensure all DS identifiers have been added to the EB list:
395 assert( set(DataScoutingInfo.getAllDataScoutingIdentifiers()).issubset(
396 EventBuildingInfo.getAllEventBuildingIdentifiers()) )
397
398 failures = 0
399 for eb_identifier in EventBuildingInfo.getAllEventBuildingIdentifiers():
400 log.info('Checking %s event building identifier', eb_identifier)
401 tool = None
402 try:
403 cfg = pebInfoWriterToolCfg(flags, 'TestTool_'+eb_identifier, eb_identifier)
404 tool = cfg.popPrivateTools()
405 except Exception as ex:
406 failures += 1
407 log.error('Caught exception while configuring PEBInfoWriterTool for %s: %s', eb_identifier, ex)
408 continue
409
410 cfg.wasMerged()
411
412 if not tool:
413 failures += 1
414 log.error('No tool created for %s', eb_identifier)
415 continue
416
417 if not isinstance(tool, (CompFactory.StaticPEBInfoWriterTool, CompFactory.RoIPEBInfoWriterTool)):
418 failures += 1
419 log.error('Unexpected tool type for %s: %s', eb_identifier, tool.getType())
420 continue
421
422 isRoIBasedPEB = EventBuildingInfo.isRoIBasedPEB(eb_identifier)
423 if isinstance(tool, CompFactory.RoIPEBInfoWriterTool) != isRoIBasedPEB:
424 failures += 1
425 log.error('Tool type %s for %s but isRoIBasedPEB==%s',
426 tool.getType(), eb_identifier, isRoIBasedPEB)
427 continue
428
429 robs = tool.ROBList if tool.getType() == 'StaticPEBInfoWriterTool' else tool.ExtraROBs
430 dets = tool.SubDetList if tool.getType() == 'StaticPEBInfoWriterTool' else tool.ExtraSubDets
431 robs_check_passed = True
432 is_data_scouting = False
433 for rob_id in robs:
434 rob_sid = SourceIdentifier(rob_id)
435 rob_det_id = rob_sid.subdetector_id()
436 if rob_det_id == SubDetector.TDAQ_HLT and rob_sid.module_id() != DataScoutingInfo.getFullHLTResultID():
437 is_data_scouting = True
438 if int(rob_det_id) in dets:
439 robs_check_passed = False
440 log.error('Redundant configuration for %s: ROB %s added to the ROB list while full SubDetector '
441 '%s is already in the SubDets list', eb_identifier, rob_sid.human(), str(rob_det_id))
442
443 if not robs_check_passed:
444 failures += 1
445 continue
446
447 # Check for always-present fragment to avoid PEB becoming FEB (ATR-24378)
448 # DataScouting is exempt as it always comes with a dedicated HLT result
449 always_present_rob = SourceIdentifier(SubDetector.TDAQ_CTP, 0) # cannot run HLT without CTP so it is always present
450 if not is_data_scouting and \
451 always_present_rob.code() not in robs and \
452 always_present_rob.subdetector_id() not in dets:
453 log.error('Bug-prone configuration for %s: without always-present CTP data in the PEB list, the '
454 'streaming may break when all requested detectors are disabled. Add CTP data to this PEB '
455 'configuration to prevent the bug (ATR-24378).', eb_identifier)
456 failures += 1
457 continue
458
459 log.info('%s correctly configured', tool.name() if callable(tool.name) else tool.name)
460
461 import sys
462 sys.exit(failures)
STL class.
pebMenuSequenceGenCfg(flags, chain, eventBuildType, chainDict)
addEventBuildingSequence(flags, chain, eventBuildType, chainDict)