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