Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
TriggerEDM.py
Go to the documentation of this file.
1 # Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
2 
3 # ********************* All Tools/Functions for the TriggerEDM **********************
4 # Keeping all functions from the original TriggerEDM.py (Run 2 EDM) in this file
5 # with this name to not break backwards compatibility
6 # Where possible, functions will be adapted to also work with Run 3, they will then be moved
7 # to the Run 3 section
8 # ***********************************************************************************
9 
10 from TrigEDMConfig.TriggerEDMRun1 import TriggerL2List,TriggerEFList,TriggerResultsRun1List
11 from TrigEDMConfig.TriggerEDMRun2 import TriggerResultsList,TriggerLvl1List,TriggerIDTruth,TriggerHLTList,EDMDetails,EDMLibraries,TriggerL2EvolutionList,TriggerEFEvolutionList
12 from TrigEDMConfig.TriggerEDMRun3 import TriggerHLTListRun3,varToRemoveFromAODSLIM,EDMDetailsRun3,getSafeEDMInsertPosition
13 from TrigEDMConfig.TriggerEDMRun4 import TriggerHLTListRun4
14 from TrigEDMConfig.TriggerEDMDefs import allowTruncation
15 from CLIDComps.clidGenerator import clidGenerator
16 import re
17 from AthenaCommon.Logging import logging
18 log = logging.getLogger('TriggerEDM')
19 
20 #************************************************************
21 #
22 # For Run 3 and Run 4
23 #
24 #************************************************************
25 
26 # ------------------------------------------------------------
27 # AllowedOutputFormats
28 # ------------------------------------------------------------
29 AllowedOutputFormats = ['BS', 'ESD', 'AODFULL', 'AODSLIM', 'AODBLSSLIM' ]
30 from TrigEDMConfig import DataScoutingInfo
31 AllowedOutputFormats.extend(DataScoutingInfo.getAllDataScoutingIdentifiers())
32 
33 _allowedEDMPrefixes = ['HLT_', 'L1_', 'LVL1']
34 def recordable( arg, runVersion=3 ):
35  """
36  Verify that the name is in the list of recorded objects and conform to the name convention
37 
38  In Run 2 it was a delicate process to configure correctly what got recorded
39  as it had to be set in the algorithm that produced it as well in the TriggerEDM.py in a consistent manner.
40 
41  For Run 3 every alg input/output key can be crosschecked against the list of objects to record which is defined here.
42  I.e. in the configuration alg developer would do this:
43  from TriggerEDM.TriggerEDMRun3 import recordable
44 
45  alg.outputKey = recordable("SomeKey")
46  If the names are correct the outputKey is assigned with SomeKey, if there is a missmatch an exception is thrown.
47 
48  """
49 
50  # Allow passing DataHandle as argument - convert to string and remove store name
51  name = str(arg).replace('StoreGateSvc+','')
52 
53  if "HLTNav_" in name:
54  log.error( "Don't call recordable({0}), or add any \"HLTNav_\" collection manually to the EDM. See:collectDecisionObjects.".format( name ) )
55  pass
56  else: #negative filtering
57  if not any([name.startswith(p) for p in _allowedEDMPrefixes]):
58  raise RuntimeError( f"The collection name {name} does not start with any of the allowed prefixes: {_allowedEDMPrefixes}" )
59  if "Aux" in name and not name[-1] != ".":
60  raise RuntimeError( f"The collection name {name} is Aux but the name does not end with the '.'" )
61 
62  if runVersion >= 3:
63  for entry in TriggerHLTListRun3:
64  if entry[0].split( "#" )[1] == name:
65  return arg
66  msg = "The collection name {0} is not declared to be stored by HLT. Add it to TriggerEDMRun3.py".format( name )
67  log.error("ERROR in recordable() - see following stack trace.")
68  raise RuntimeError( msg )
69 
70 def _addExtraCollectionsToEDMList(edmList, extraList):
71  """
72  Extend edmList with extraList, keeping track whether a completely new
73  collection is being added, or a dynamic variable is added to an existing collection, or new targets are added to an existing collection.
74  The format of extraList is the same as those of TriggerHLTListRun3.
75  """
76  existing_collections = [(c[0].split("#")[1]).split(".")[0] for c in edmList]
77  insert_idx = getSafeEDMInsertPosition(edmList)
78  for item in extraList:
79  colname = (item[0].split("#")[1]).split(".")[0]
80  if colname not in existing_collections:
81  # a new collection and its Aux container are inserted in front of 'allowTruncation' items.
82  if 'Aux' in colname:
83  edmList.insert(insert_idx+1,item)
84  else:
85  edmList.insert(insert_idx,item)
86  log.info("added new item to Trigger EDM: {}".format(item))
87  else:
88  # Maybe extra dynamic variables or EDM targets are added
89  isAux = "Aux." in item[0]
90  # find the index of the existing item
91  existing_item_nr = [i for i,s in enumerate(edmList) if colname == (s[0].split("#")[1]).split(".")[0]]
92  if len(existing_item_nr) != 1:
93  log.error("Found {} existing edm items corresponding to new item {}, but it must be exactly one!".format(len(existing_item_nr), item))
94  existingItem = edmList[existing_item_nr[0]]
95  if isAux:
96  dynVars = (item[0].split("#")[1]).split(".")[1:]
97  existing_dynVars = (existingItem[0].split("#")[1]).split(".")[1:]
98  existing_dynVars.extend(dynVars)
99  dynVars = list(dict.fromkeys(existing_dynVars))
100  if '' in dynVars:
101  dynVars.remove('')
102  newVars = '.'.join(dynVars)
103  edmTargets = item[1].split(" ") if len(item) > 1 else []
104  existing_edmTargets = existingItem[1].split(" ")
105  edmTargets.extend(existing_edmTargets)
106  edmTargets = list(dict.fromkeys(edmTargets))
107  newTargets = " ".join(edmTargets)
108  typename = item[0].split("#")[0]
109  log.info("old item in Trigger EDM : {}".format(existingItem))
110  signature = existingItem[2] # NOT updated at the moment
111  tags = existingItem[3] if len(existingItem) > 3 else None # NOT updated at the moment
112  edmList.pop(existing_item_nr[0])
113  combName = typename + "#" + colname
114  if isAux:
115  combName += "." + newVars
116  if tags:
117  edmList.insert(existing_item_nr[0], (combName, newTargets, signature, tags))
118  else:
119  edmList.insert(existing_item_nr[0] , (combName, newTargets, signature))
120  log.info("updated item in Trigger EDM: {}".format(edmList[existing_item_nr[0]]))
121 
122  if testEDMList(edmList, error_on_edmdetails=False):
123  log.error("edmList contains inconsistencies!")
124 
125 def getRawTriggerEDMList(flags, runVersion=-1):
126  """
127  The static EDM list does still need some light manipulation before it can be used commonly.
128  Never import TriggerHLTListRun3 or TriggerHLTListRun4 directly, always fetch them via this function
129  """
130  if runVersion == -1:
131  runVersion = flags.Trigger.EDMVersion
132 
133  if runVersion == 3:
134  edmListCopy = TriggerHLTListRun3.copy()
135  elif runVersion == 4:
136  edm4ListCopy = TriggerHLTListRun4.copy()
137  edm3ListCopy = TriggerHLTListRun3.copy()
138  log.debug("Removing duplicated item between TriggerHLTListRun3 and TriggerHLTListRun4.")
139  for i in range(len(edm3ListCopy)-1, -1, -1): # Back iterate by index, we might be removing as we go
140  for r4item in edm4ListCopy:
141  if edm3ListCopy[i][0] == r4item[0]:
142  del edm3ListCopy[i]
143  log.debug(f"- Dupe: {r4item} is removed from TriggerHLTListRun3 to be updated by TriggerHLTListRun4")
144  break
145  lenPreMerge = len(edm3ListCopy)
146  edm4ListCopy.extend(edm3ListCopy)
147  lenPostMerge = len(edm4ListCopy)
148  edmListCopy = edm4ListCopy
149  log.info(f"Added TriggerHLTListRun4 to TriggerHLTListRun3. EDM entries {lenPreMerge} -> {lenPostMerge}")
150  if testEDMList(edmListCopy, error_on_edmdetails=False):
151  log.error("edmList contains inconsistencies!")
152  else:
153  errMsg="ERROR the getRawTriggerEDMList function supports runs 3 and 4."
154  log.error(errMsg)
155  raise RuntimeError(errMsg)
156 
157  if flags and flags.Trigger.ExtraEDMList:
158  log.info( "Adding extra collections to EDM %i: %s", runVersion, str(flags.Trigger.ExtraEDMList))
159  _addExtraCollectionsToEDMList(edmListCopy, flags.Trigger.ExtraEDMList)
160 
161  return edmListCopy
162 
163 def getTriggerEDMList(flags, key, runVersion=-1):
164  """
165  List (Literally Python dict) of trigger objects to be placed with flags:
166  flags is the CA flag container
167  key can be" 'ESD', 'AODSLIM', 'AODFULL'
168  runVersion can be: '-1 (Auto-configure)', '1 (Run1)', '2 (Run2)', '3' (Run 3), '4' (Run 4)
169  """
170  # We allow for this to be overriden as Run1 bytestream actually need to request the Run2 EDM due to it additionally undergoing a transient xAOD migration.
171  if runVersion == -1:
172  runVersion = flags.Trigger.EDMVersion
173 
174  if runVersion == 1:
175  return _getTriggerRun1Run2ObjList(key, [TriggerL2List,TriggerEFList, TriggerResultsRun1List])
176 
177  elif runVersion == 2:
178  edmList = _getTriggerRun1Run2ObjList(key, [TriggerHLTList, TriggerResultsList])
179  return _getTriggerRun2EDMSlimList(key, edmList) if 'SLIM' in key else edmList
180 
181  elif runVersion >= 3:
182  RawEDMList = getRawTriggerEDMList(flags=flags, runVersion=runVersion)
183 
184  if key not in AllowedOutputFormats: # AllowedOutputFormats is the entire list of output formats including ESD
185  log.warning('Output format: %s is not in list of allowed formats, please check!', key)
186  return _getRun3TrigObjList(key, [RawEDMList])
187 
188  # this keeps only the dynamic variables that have been specified in TriggerEDMRun3
189  Run3TrigEDM = {}
190  Run3TrigEDMSLIM = {}
191 
192  if "AODFULL" in key:
193  Run3TrigEDM.update(_getRun3TrigEDMSlimList(key, RawEDMList))
194 
195  elif "AODSLIM" in key:
196  # remove the variables that are defined in TriggerEDMRun3.varToRemoveFromAODSLIM from the containers
197 
198  # get all containers from list that are marked with AODSLIM
199  if len(varToRemoveFromAODSLIM) == 0:
200  Run3TrigEDM.update(_getRun3TrigEDMSlimList(key, RawEDMList))
201  log.info("No decorations are listed to be removed from AODSLIM")
202  else:
203  Run3TrigEDMSLIM.update(_getRun3TrigEDMSlimList(key, RawEDMList))
204  log.info("The following decorations are going to be removed from the listed collections in AODSLIM {}".format(varToRemoveFromAODSLIM))
205  # Go through all container values and remove the variables to remove
206  # Format of Run3TrigEDMSLIM is {'xAOD::Cont': ['coll1.varA.varB', 'coll2.varD',...],...}
207  for cont, values in Run3TrigEDMSLIM.items():
208  if (isinstance(values, list)):
209  newValues = []
210  for value in values:
211  newValue = value+'.'
212  coll = value.split('.')[0]
213 
214  varRemovedFlag = False
215  for myTuple in varToRemoveFromAODSLIM:
216  var = myTuple[0]
217 
218  if var in value and coll in myTuple:
219  varRemovedFlag = True
220  removeVar = '.'+var+'.'
221  newValue = newValue.replace(removeVar, '.')
222 
223  if newValue[-1:] == '.':
224  newValue = newValue[:-1]
225 
226  if varRemovedFlag is False:
227  newValues.append(value)
228  elif varRemovedFlag is True:
229  newValues.append(newValue)
230  else:
231  raise RuntimeError("Decoration removed but no new Value was available, not sure what to do...")
232 
233  # Filling the Run3TrigEDM dictionary with the new set of values for each cont
234  Run3TrigEDM[cont] = newValues
235  else:
236  raise RuntimeError("Value in Run3TrigEDM dictionary is not a list")
237 
238  else: # ESD
239  Run3TrigEDM.update(_getRun3TrigEDMSlimList(key, RawEDMList))
240 
241  log.debug('TriggerEDM for EDM set {} contains the following collections: {}'.format(key, Run3TrigEDM) )
242  return Run3TrigEDM
243 
244 
245  else:
246  raise RuntimeError("Invalid runVersion=%s supplied to getTriggerEDMList" % runVersion)
247 
248 
249 
250 def _getRun3TrigObjProducedInView(theKey, trigEDMList):
251  """
252  Run 3 only
253  Finds a given key from within the trigEDMList.
254  Returns true if this collection is produced inside EventViews
255  (Hence, has the special viewIndex Aux decoration applied by steering)
256  """
257  from TrigEDMConfig.TriggerEDMRun3 import InViews
258  import itertools
259 
260  return any(coll for coll in itertools.chain(*trigEDMList) if
261  len(coll)>3 and theKey==coll[0].split('#')[1] and
262  any(isinstance(v, InViews) for v in coll[3]))
263 
264 
265 def _handleRun3ViewContainers( el, HLTList ):
266  if 'Aux.' in el:
267  # Get equivalent non-aux string (fragile!!!)
268  keyNoAux = el.split('.')[0].replace('Aux','')
269  # Check if this interface container is produced inside a View
270  inView = _getRun3TrigObjProducedInView(keyNoAux, [HLTList])
271  if el.split('.')[1] == '':
272  # Aux lists zero dynamic vars to save ...
273  if inView:
274  # ... but it was produced in a View, so we need to add the viewIndex dynamic aux
275  return el.split('.')[0]+'.viewIndex'
276  else:
277  # ... and was not in a View, strip all dynamic
278  return el.split('.')[0]+'.-'
279  else:
280  # Aux lists one or more dynamic vars to save ...
281  if inView:
282  # ... and was produced in a View, so add the viewIndex dynamic as well
283  return el+'.viewIndex'
284  else:
285  # ... and was not produced in a View, keep user-supplied list
286  return el
287  else: # no Aux
288  return el
289 
290 
291 def getRun3BSList(flags, keys):
292  """
293  The keys should contain BS and all the identifiers used for scouting.
294  Returns list of tuples (typename#key, [keys], [properties]).
295  """
296 
297  from TrigEDMConfig.TriggerEDMRun3 import persistent
298  keys = set(keys[:])
299  collections = []
300  _HLTList = getRawTriggerEDMList(flags, 3)
301  for definition in _HLTList:
302 
303  typename,collkey = definition[0].split("#")
304  # normalise collection name and the key (decorations)
305  typename = persistent(typename)
306  collkey = _handleRun3ViewContainers( collkey, _HLTList )
307  destination = keys & set(definition[1].split())
308  if len(destination) > 0:
309  collections.append( (typename+"#"+collkey, list(destination),
310  definition[3] if len(definition)>3 else []) )
311 
312  return collections
313 
314 
315 def _getRun3TrigObjList(destination, trigEDMList):
316  """
317  Run 3 version
318  Gives back the Python dictionary with the content of ESD/AOD (dst) which can be inserted in OKS.
319  """
320  dset = set(destination.split())
321  from collections import OrderedDict
322  toadd = OrderedDict()
323  import itertools
324 
325  for item in itertools.chain(*trigEDMList):
326  if item[1] == '': # no output has been defined
327  continue
328 
329  confset = set(item[1].split())
330 
331  if dset & confset: # intersection of the sets
332  t,k = _getTypeAndKey(item[0])
333  colltype = t
334 
335  if colltype in toadd:
336  if k not in toadd[colltype]:
337  toadd[colltype] += [k]
338  else:
339  toadd[colltype] = [k]
340 
341  return toadd
342 
343 
344 def _getRun3TrigEDMSlimList(key, HLTList):
345  """
346  Run 3 version
347  Modified EDM list to remove all dynamic variables
348  Requires changing the list to have 'Aux.-'
349  """
350  _edmList = _getRun3TrigObjList(key,[HLTList])
351  from collections import OrderedDict
352  output = OrderedDict()
353  for k,v in _edmList.items():
354  newnames = []
355  for el in v:
356  newnames.append( _handleRun3ViewContainers( el, HLTList ) )
357  output[k] = newnames
358  return output
359 
360 #************************************************************
361 #
362 # For Run 1 and Run 2 (not modified (so far))
363 #
364 #************************************************************
365 def _getTriggerRun2EDMSlimList(key, edmList):
366  """
367  Run 2 version
368  Modified EDM list to remove all dynamic variables
369  Requires changing the list to have 'Aux.-'
370  """
371  output = {}
372  for k,v in edmList.items():
373  newnames = []
374  for el in v:
375  if 'Aux' in el:
376  newnames+=[el.split('.')[0]+'.-']
377  else:
378  newnames+=[el]
379  output[k] = newnames
380  return output
381 
382 def getCategory(s):
383  """ From name of object in AOD/ESD found by checkFileTrigSize.py, return category """
384 
385  """ Clean up object name """
386  s = s.strip()
387 
388  # To-do
389  # seperate the first part of the string at the first '_'
390  # search in EDMDetails for the key corresponding to the persistent value
391  # if a key is found, use this as the first part of the original string
392  # put the string back together
393 
394  if s.count('.') : s = s[:s.index('.')]
395  if s.count('::'): s = s[s.index(':')+2:]
396  if s.count('<'): s = s[s.index('<')+1:]
397  if s.count('>'): s = s[:s.index('>')]
398  if s.count('.') : s = s[:s.index('.')]
399  if s.count('Dyn') : s = s[:s.index('Dyn')]
400 
401  # containers from Run 1-2 and 3 require different preprocessing
402  # s12 is for Run 1-2, s is for Run 3
403  s12 = s
404 
405  if s12.startswith('HLT_xAOD__') or s12.startswith('HLT_Rec__') or s12.startswith('HLT_Analysis__') :
406  s12 = s12[s12.index('__')+2:]
407  s12 = s12[s12.index('_')+1:]
408  #if s12.count('.') : s12 = s12[:s12.index('.')]
409  s12 = "HLT_"+s12
410  elif s12.startswith('HLT_'):
411  #if s.count('Dyn') : s = s[:s.index('Dyn')]
412  if s12.count('_'): s12 = s12[s12.index('_')+1:]
413  if s12.count('_'): s12 = s12[s12.index('_')+1:]
414  s12 = "HLT_"+s12
415 
416  TriggerListRun1 = TriggerL2List + TriggerEFList + TriggerResultsRun1List
417  TriggerListRun2 = TriggerResultsList + TriggerLvl1List + TriggerIDTruth + TriggerHLTList
418  TriggerListRun3 = getRawTriggerEDMList(flags=None, runVersion=3)
419 
420  category = ''
421  bestMatch = ''
422 
423  """ Loop over all objects already defined in lists (and hopefully categorized!!) """
424  for item in TriggerListRun1+TriggerListRun2:
425  t,k = _getTypeAndKey(item[0])
426 
427  """ Clean up type name """
428  if t.count('::'): t = t[t.index(':')+2:]
429  if t.count('<'): t = t[t.index('<')+1:]
430  if t.count('>'): t = t[:t.index('>')]
431  if (s12.startswith(t) and s12.endswith(k)) and (len(t) > len(bestMatch)):
432  bestMatch = t
433  category = item[2]
434 
435  if k.count('.'): k = k[:k.index('.')]
436  if (s12 == k):
437  bestMatch = k
438  category = item[2]
439 
440  for item in TriggerListRun3:
441  t,k = _getTypeAndKey(item[0])
442 
443  """ Clean up type name """
444  if t.count('::'): t = t[t.index(':')+2:]
445  if t.count('<'): t = t[t.index('<')+1:]
446  if t.count('>'): t = t[:t.index('>')]
447 
448  if (s.startswith(t) and s.endswith(k)) and (len(t) > len(bestMatch)):
449  bestMatch = t
450  category = item[2]
451 
452  if k.count('.'): k = k[:k.index('.')]
453  if (s == k):
454  bestMatch = k
455  category = item[2]
456 
457  if category == '' and 'HLTNav' in s:
458  category = 'HLTNav'
459 
460  if category == '': return 'NOTFOUND'
461  return category
462 
463 
464 
466  """ From the strings containing type and key of trigger EDM extract type and key
467  """
468  return s[:s.index('#')], s[s.index('#')+1:]
469 
470 def _keyToLabel(key):
471  """ The key is usually HLT_*, this function returns second part of it or empty string
472  """
473  if '_' not in key:
474  return ''
475  else:
476  return key[key.index('_'):].lstrip('_')
477 
478 def _getTriggerRun1Run2ObjList(destination, lst):
479  """
480  Gives back the Python dictionary with the content of ESD/AOD (dst) which can be inserted in OKS.
481  """
482  dset = set(destination.split())
483 
484  toadd = {}
485  import itertools
486 
487  for item in itertools.chain(*lst):
488  if item[1] == '':
489  continue
490  confset = set(item[1].split())
491  if dset & confset: # intersection of the sets
492  t,k = _getTypeAndKey(item[0])
493  colltype = t
494  if 'collection' in EDMDetails[t]:
495  colltype = EDMDetails[t]['collection']
496  if colltype in toadd:
497  if k not in toadd[colltype]:
498  toadd[colltype] += [k]
499  else:
500  toadd[colltype] = [k]
501  return _InsertContainerNameForHLT(toadd)
502 
503 
505  """
506  Gives back the Python dictionary with the truth trigger content of ESD/AOD (dst) which can be inserted in OKS.
507  """
508  return _getTriggerRun1Run2ObjList(dst,[TriggerIDTruth])
509 
511  """
512  Gives back the Python dictionary with the lvl1 trigger result content of ESD which can be inserted in OKS.
513  """
514  return _getTriggerRun1Run2ObjList('ESD',[TriggerLvl1List])
515 
517  """
518  Gives back the Python dictionary with the lvl1 trigger result content of AOD which can be inserted in OKS.
519  """
520  return _getTriggerRun1Run2ObjList('AODFULL',[TriggerLvl1List])
521 
522 
523 
525  """
526  List (Literally Python list) of trigger objects to be preregistered i.e. this objects we want in every event for L2
527  """
528  l = []
529  for item in TriggerL2List:
530  if len (item[1]) == 0: continue
531  t,k = _getTypeAndKey(item[0])
532  if('Aux' in t):
533  continue #we don't wat to preregister Aux containers
534  l += [t+"#"+_keyToLabel(k)]
535  return l
536 
538  """
539  List (Literally Python list) of trigger objects to be preregistered i.e. this objects we want in every event for EF
540  """
541  l = []
542  for item in TriggerEFList:
543  if len (item[1]) == 0: continue
544  t,k = _getTypeAndKey(item[0])
545  if('Aux' in t):
546  continue #we don't wat to preregister Aux containers
547  l += [t+"#"+_keyToLabel(k)]
548  return l
549 
551  """
552  List (Literally Python list) of trigger objects to be preregistered i.e. this objects we want in every event for merged L2/EF in addition to default L2 and EF
553  """
554  l = []
555  for item in TriggerHLTList:
556  if len (item[1]) == 0: continue
557  t,k = _getTypeAndKey(item[0])
558  if('Aux' in t):
559  continue #we don't wat to preregister Aux containers
560  l += [t+"#"+_keyToLabel(k)]
561  return l
562 
563 
564 def getPreregistrationList(version=2, doxAODConversion=True):
565  """
566  List (Literally Python list) of trigger objects to be preregistered i.e. this objects we want for all levels
567  version can be: '1 (Run1)', '2 (Run2)'
568  """
569 
570  l=[]
571  if version==2:
573  elif version==1:
574  # remove duplicates while preserving order
576  if doxAODConversion:
578  l=list(dict.fromkeys(objs))
579  else:
580  raise RuntimeError("Invalid version=%s supplied to getPreregistrationList" % version)
581  return l
582 
583 
585  """ List of L2 types to be read from BS, used by the TP
586  """
587  l = []
588  for item in TriggerL2List:
589  t,k = _getTypeAndKey(item[0])
590  ctype = t
591  if 'collection' in EDMDetails[t]:
592  ctype = EDMDetails[t]['collection']
593  l += [ctype]
594  return l
595 
597  """ List of EF types to be read from BS, used by the TP
598  """
599  l = []
600  for item in TriggerEFList:
601  t,k = _getTypeAndKey(item[0])
602  ctype = t
603  if 'collection' in EDMDetails[t]:
604  ctype = EDMDetails[t]['collection']
605  l += [ctype]
606  return l
607 
609  """ List of HLT types to be read from BS, used by the TP
610  """
611  l = []
612  for item in TriggerHLTList:
613  t,k = _getTypeAndKey(item[0])
614  ctype = t
615  if 'collection' in EDMDetails[t]:
616  ctype = EDMDetails[t]['collection']
617  l += [ctype]
618  return l
619 
620 def getTPList(version=2):
621  """
622  Mapping of Transient objects to Peristent during serialization (BS creation)
623  version can be: '1 (Run1)', '2 (Run2)'
624  """
625  l = {}
626  if version==2:
627  bslist = _getHLTBSTypeList()
628  elif version==1:
629  bslist = list(set(_getL2BSTypeList() + _getEFBSTypeList()))
630  else:
631  raise RuntimeError("Invalid version=%s supplied to getTPList" % version)
632 
633  for t,d in EDMDetails.items():
634  colltype = t
635  if 'collection' in d:
636  colltype = EDMDetails[t]['collection']
637  if colltype in bslist:
638  l[colltype] = d['persistent']
639  return l
640 
641 
643  return EDMLibraries
644 
646  import re
647  output = {}
648  for k,v in typedict.items():
649  newnames = []
650  for el in v:
651  if el.startswith('HLT_') or el == 'HLT':
652  prefixAndLabel = el.split('_',1) #only split on first underscore
653  containername = k if 'Aux' not in k else EDMDetails[k]['parent'] #we want the type in the Aux SG key to be the parent type #104811
654  #maybe this is not needed anymore since we are now versionless with the CLIDs but it's not hurting either
655  containername = re.sub('::','__',re.sub('_v[0-9]+$','',containername))
656  newnames+=['_'.join([prefixAndLabel[0],containername]+([prefixAndLabel[1]] if len(prefixAndLabel) > 1 else []))]
657  else:
658  newnames+=[el]
659  output[k] = newnames
660  return output
661 
663  """
664  List of EF trigger objects that were written to ByteStream in Run 1
665  """
666  l = []
667  for item in TriggerEFEvolutionList:
668  if len (item[1]) == 0: continue
669  t,k = _getTypeAndKey(item[0])
670  l += [t+"#"+_keyToLabel(k)]
671  return l
672 
674  """
675  List of Run-2 containers equivalent to Run-1 EF containers
676  """
677  l = []
678  for item in TriggerEFEvolutionList:
679  if len (item[1]) == 0: continue
680  t,k = _getTypeAndKey(item[1])
681  l += [t+"#"+_keyToLabel(k)]
682  return l
683 
685  """
686  List of L2 trigger objects that were written to ByteStream in Run 1
687  """
688  l = []
689  for item in TriggerL2EvolutionList:
690  if len (item[1]) == 0: continue
691  t,k = _getTypeAndKey(item[0])
692  l += [t+"#"+_keyToLabel(k)]
693  return l
694 
696  """
697  List of Run-2 containers equivalent to Run-1 L2 containers
698  """
699  l = []
700  for item in TriggerL2EvolutionList:
701  if len (item[1]) == 0: continue
702  t,k = _getTypeAndKey(item[1])
703  l += [t+"#"+_keyToLabel(k)]
704  return l
705 
706 def isCLIDDefined(cgen,typename):
707  """
708  Checks container type name is hashable
709  """
710  c = cgen.genClidFromName(typename)
711  return (cgen.getNameFromClid(c) is not None)
712 
713 def testEDMList(edm_list, error_on_edmdetails = True):
714  """
715  Checks EDM list entries for serialization and configuration compliance.
716  """
717 
718  #xAOD types that don't expect accompanying Aux containers
719  _noAuxList = ["xAOD::" + contType for contType in ["TrigConfKeys", "BunchConfKey"]]
720 
721  cgen = clidGenerator("", False)
722  return_code = 0
723  found_allow_truncation = False
724  serializable_names = []
725  serializable_names_no_label = []
726  serializable_names_no_properties = []
727 
728  for i, edm in enumerate(edm_list):
729 
730  #check has sufficient entries
731  if len(edm) < 3:
732  log.error("EDM entry too short for " + edm[0])
733  return_code = 1
734  continue
735 
736  serializable_name = edm[0]
737  serializable_name_no_label = re.sub(r"\#.*", "", serializable_name)
738  serializable_name_no_properties = serializable_name.split('.')[0]
739 
740  serializable_names.append(serializable_name)
741  serializable_names_no_label.append(serializable_name_no_label)
742  serializable_names_no_properties.append(serializable_name_no_properties)
743 
744  #check container type name is hashable
745  if not isCLIDDefined(cgen,serializable_name_no_label):
746  log.error("no CLID for " + serializable_name)
747  return_code = 1
748 
749  #check that no '.' in entries _not_ containing 'Aux'
750  if "Aux" not in serializable_name and "." in serializable_name:
751  log.error("A '.' found in non-Aux container name " + serializable_name)
752  return_code = 1
753 
754  #check for Aux "."
755  if "Aux" in serializable_name and "Aux." not in serializable_name:
756  log.error("no final Aux. in label for " + serializable_name)
757  return_code = 1
758 
759  #check contains exactly one #
760  if serializable_name.count("#") != 1:
761  log.error("Invalid naming structure for " + serializable_name)
762  return_code = 1
763  else: # only proceed if type and name can be separated
764  #check that every interface xAOD container directly followed by matching Aux container.
765  if serializable_name.startswith("xAOD") and "Aux" not in serializable_name:
766  cont_type,cont_name = serializable_name.split("#")
767  if cont_type not in _noAuxList:
768  auxmismatch = False
769  if len(edm_list) == i+1:
770  auxmismatch = True
771  cont_to_test = "nothing"
772  else:
773  cont_to_test = edm_list[i+1][0].split(".")[0]+"."
774  cont_type_short = cont_type.replace("Container","")
775  pattern = re.compile(cont_type_short+r".*Aux.*\#"+cont_name+"Aux.")
776  if not pattern.match(cont_to_test):
777  #test if shallow container type.
778  shallow_pattern = re.compile("xAOD::ShallowAuxContainer#"+cont_name+"Aux.")
779  if not shallow_pattern.match(cont_to_test):
780  auxmismatch = True
781  if auxmismatch:
782  log.error("Expected relevant Aux container following interface container %s, but found %s instead.",serializable_name,cont_to_test)
783  return_code = 1
784  else:
785  #check that targets of interface and aux container match
786  targets = set(edm[1].split())
787  if len(edm_list[i+1]) > 1 and cont_to_test.count("#") == 1:
788  contname_to_test = cont_to_test.split("#")[1]
789  targets_to_test = set(edm_list[i+1][1].split())
790  if len(targets ^ targets_to_test) > 0:
791  log.error("Targets of %s (%s) and %s (%s) do not match",cont_name,targets,contname_to_test,targets_to_test)
792  return_code = 1
793 
794  #check that Aux always follows non-Aux (our deserialiser relies on that)
795  if i>0 and "Aux" in serializable_name and "Aux" in edm_list[i-1][0]:
796  log.error(f"Aux container {serializable_name} needs to folow the "
797  "associated interface container in the EDM list")
798  return_code = 1
799 
800  #check target types are valid. Check that target lists containing higher level targets
801  #have required low level targets (ESD for AOD targets, AODFULL for SLIM targets).
802  file_types = edm[1].split() # might return empty list, this is fine - 0 output file types allowed for an EDM entry (in case of obsolete containers)
803  for file_type in file_types:
804  if file_type not in AllowedOutputFormats:
805  log.error("unknown file type " + file_type + " for " + serializable_name)
806  return_code = 1
807  for higher_level,required_lower_level in [('AOD','ESD'), ('SLIM','AODFULL')]:
808  if higher_level in file_type and required_lower_level not in file_types:
809  log.error("Target list for %s containing '%s' must also contain lower level target '%s'.",serializable_name,file_type,required_lower_level)
810  return_code = 1
811 
812  # Check allowTuncation is only at the end
813  tags = edm[3] if len(edm) > 3 else None
814  allow_truncation_flag = False
815  if tags:
816  allow_truncation_flag = allowTruncation in tags
817  if allow_truncation_flag:
818  found_allow_truncation = True
819 
820  if found_allow_truncation and not allow_truncation_flag:
821  log.error("All instances of 'allowTruncation' need to be at the END of the EDM serialisation list")
822  return_code = 1
823 
824  #end of for loop over entries. Now do complete list checks.
825 
826  #check for duplicates:
827  #check that no two EDM entries match after stripping out characters afer '.'
828  if not len(set(serializable_names_no_properties)) == len(serializable_names_no_properties):
829  log.error("Duplicates in EDM list! Duplicates found:")
830  import collections.abc
831  for item, count in collections.Counter(serializable_names_no_properties).items():
832  if count > 1:
833  log.error(str(count) + "x: " + str(item))
834  return_code = 1
835 
836  #check EDMDetails
837  for EDMDetail in EDMDetailsRun3.keys():
838  if EDMDetail not in serializable_names_no_label:
839  msg = "EDMDetail for " + EDMDetail + " does not correspond to any name in TriggerList"
840  if error_on_edmdetails:
841  log.error(msg)
842  return_code = 1
843  else:
844  log.warning(msg)
845 
846  return return_code
python.TriggerEDM.testEDMList
def testEDMList(edm_list, error_on_edmdetails=True)
Definition: TriggerEDM.py:713
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
python.TriggerEDMRun3.persistent
def persistent(transient)
Definition: TriggerEDMRun3.py:1169
python.TriggerEDM.getRawTriggerEDMList
def getRawTriggerEDMList(flags, runVersion=-1)
Definition: TriggerEDM.py:125
vtune_athena.format
format
Definition: vtune_athena.py:14
python.TriggerEDM.getL2Run1BSList
def getL2Run1BSList()
Definition: TriggerEDM.py:684
python.TriggerEDM.isCLIDDefined
def isCLIDDefined(cgen, typename)
Definition: TriggerEDM.py:706
python.TriggerEDM._getHLTBSTypeList
def _getHLTBSTypeList()
Definition: TriggerEDM.py:608
python.TriggerEDM.getRun3BSList
def getRun3BSList(flags, keys)
Definition: TriggerEDM.py:291
python.TriggerEDM._getTriggerRun1Run2ObjList
def _getTriggerRun1Run2ObjList(destination, lst)
Definition: TriggerEDM.py:478
python.TriggerEDM._getL2BSTypeList
def _getL2BSTypeList()
Definition: TriggerEDM.py:584
python.TriggerEDM._getHLTPreregistrationList
def _getHLTPreregistrationList()
Definition: TriggerEDM.py:550
python.TriggerEDM._getEFBSTypeList
def _getEFBSTypeList()
Definition: TriggerEDM.py:596
python.TriggerEDM._getL2PreregistrationList
def _getL2PreregistrationList()
Definition: TriggerEDM.py:524
python.TriggerEDM.getTriggerEDMList
def getTriggerEDMList(flags, key, runVersion=-1)
Definition: TriggerEDM.py:163
python.TriggerEDM.getTrigIDTruthList
def getTrigIDTruthList(dst)
Definition: TriggerEDM.py:504
python.TriggerEDM.getEDMLibraries
def getEDMLibraries()
Definition: TriggerEDM.py:642
python.TriggerEDM.getEFRun1BSList
def getEFRun1BSList()
Definition: TriggerEDM.py:662
python.TriggerEDM.getTPList
def getTPList(version=2)
Definition: TriggerEDM.py:620
python.TriggerEDM.getCategory
def getCategory(s)
Definition: TriggerEDM.py:382
plotBeamSpotVxVal.range
range
Definition: plotBeamSpotVxVal.py:195
python.TriggerEDM._getRun3TrigObjProducedInView
def _getRun3TrigObjProducedInView(theKey, trigEDMList)
Definition: TriggerEDM.py:250
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
python.TriggerEDM._addExtraCollectionsToEDMList
def _addExtraCollectionsToEDMList(edmList, extraList)
Definition: TriggerEDM.py:70
python.TriggerEDM._handleRun3ViewContainers
def _handleRun3ViewContainers(el, HLTList)
Definition: TriggerEDM.py:265
python.TriggerEDM._getTypeAndKey
def _getTypeAndKey(s)
Definition: TriggerEDM.py:465
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.TriggerEDM.getL2Run2EquivalentList
def getL2Run2EquivalentList()
Definition: TriggerEDM.py:695
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
python.TriggerEDM._getEFPreregistrationList
def _getEFPreregistrationList()
Definition: TriggerEDM.py:537
python.TriggerEDM.getEFRun2EquivalentList
def getEFRun2EquivalentList()
Definition: TriggerEDM.py:673
TrigJetMonitorAlgorithm.items
items
Definition: TrigJetMonitorAlgorithm.py:71
python.TriggerEDM.getPreregistrationList
def getPreregistrationList(version=2, doxAODConversion=True)
Definition: TriggerEDM.py:564
python.TriggerEDM._getTriggerRun2EDMSlimList
def _getTriggerRun2EDMSlimList(key, edmList)
Definition: TriggerEDM.py:365
python.TriggerEDM.getLvl1ESDList
def getLvl1ESDList()
Definition: TriggerEDM.py:510
python.TriggerEDMRun3.getSafeEDMInsertPosition
def getSafeEDMInsertPosition(edm_list)
Definition: TriggerEDMRun3.py:1195
python.TriggerEDM.getLvl1AODList
def getLvl1AODList()
Definition: TriggerEDM.py:516
if
if(febId1==febId2)
Definition: LArRodBlockPhysicsV0.cxx:567
python.TriggerEDM.recordable
def recordable(arg, runVersion=3)
Definition: TriggerEDM.py:34
python.TriggerEDM._getRun3TrigObjList
def _getRun3TrigObjList(destination, trigEDMList)
Definition: TriggerEDM.py:315
str
Definition: BTagTrackIpAccessor.cxx:11
python.TriggerEDM._keyToLabel
def _keyToLabel(key)
Definition: TriggerEDM.py:470
python.TriggerEDM._InsertContainerNameForHLT
def _InsertContainerNameForHLT(typedict)
Definition: TriggerEDM.py:645
Trk::split
@ split
Definition: LayerMaterialProperties.h:38
python.TriggerEDM._getRun3TrigEDMSlimList
def _getRun3TrigEDMSlimList(key, HLTList)
Definition: TriggerEDM.py:344