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