ATLAS Offline Software
Loading...
Searching...
No Matches
ItemListSemantics.py
Go to the documentation of this file.
1# Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
2
3from GaudiConfig2.semantics import getSemanticsFor, SequenceSemantics
4from collections import defaultdict
5
6from AthenaCommon.Logging import logging
7msg = logging.getLogger("OutputStreamItemListAuxCheck")
8
9
10class OutputStreamItemListSemantics(SequenceSemantics):
11 __handled_types__ = ( "OutputStreamItemList", )
12 __AUX_ext__ = "Aux."
13 __AUX_len__ = len(__AUX_ext__)
14
15 def __init__(self, cpp_type):
16 valueSem = getSemanticsFor("std::string") if cpp_type in self.__handled_types__ else None
17 super(OutputStreamItemListSemantics, self).__init__(cpp_type, valueSem=valueSem)
18
19 def merge(self, bb, aa):
20 for b in bb:
21 if b not in aa:
22 aa.append(b)
23 scrubbed = self.checkAuxAttributes( aa )
24 aa.clear()
25 aa.extend( scrubbed )
26 return aa
27
28 def checkAuxAttributes(self, itemList):
29 """
30 Checks dynamic Aux attribute selection in the ItemList for duplicates and conflicts
31
32 From Event/xAOD/xAODCore/Root/AuxSelection.cxx
33 The formalism for attribute selection is the following:
34 - An empty set, or a set containing "*" will select all the dynamic
35 attributes passed to the object.
36 - A single "-" attribute will not select any of the dynamic attributes.
37 - A set of variables (without "-" as the first character of the
38 variable names) will select just the variables listed.
39 - A set of variable names, each prefixed by "-", will select all
40 variables but the ones listed.
41 """
42 newitemlist=[]
43 auxitems = defaultdict(set)
44 for item in itemList:
45 auxpos = item.find(self.__AUX_ext__)
46 if auxpos > 0:
47 # Aux store item
48 itemname = item[ : auxpos+self.__AUX_len__]
49 selection = item[auxpos+self.__AUX_len__ : ]
50 # collect attributes selection for this item in a set
51 # empty selection means 'everything'
52 auxitems[itemname].add( selection )
53 else:
54 newitemlist.append(item)
55
56 newauxlist=[]
57 for k,sel in auxitems.items():
58 allsel = set() # gather all selection items in this set
59 negsel = set() # set of negative ("-") selections
60 for line in sel:
61 if ".." in line or line.startswith(".") or line.endswith('.'):
62 raise ValueError(f"ItemList AuxAttribute selection syntax error for {k} - extra dot in '{line}'")
63 newsel = set(line.split('.'))
64 newneg = {s for s in newsel if s[:1]=='-'}
65 if newneg:
66 if not negsel:
67 negsel = newneg
68 else:
69 # if they are the same it's OK, but different negative selections are ambiguous
70 if newneg != negsel:
71 raise ValueError(f"Multiple (different) negative selection are not supported: for {k} : {str(sel)}")
72 allsel.update( newsel )
73 if negsel and len(negsel) != len(allsel):
74 raise ValueError(f"Mixing up negative and positive Aux selections is not supported: {k} : {str(sel)}")
75 if len(sel) == 1:
76 # single selection, just pass it on
77 newauxlist.append( k + next(iter(sel)) )
78 continue
79 # multiple selections fun
80 if '' in sel or '*' in allsel:
81 if len(allsel) > 1:
82 msg.info(f"Multiple Aux attribute selections for {k} - will write all attributes." +
83 f" Original selection was: {str(sel)}")
84 newauxlist.append( k + '*')
85 continue
86 # 2 or more positive selections - merge them into one
87 newitem = k + ".".join(sorted(allsel))
88 newauxlist.append(newitem)
89 msg.info(f"Multiple attribute selections for {k} - will write combined selection. Found {len(sel)} selections: {str(sel)}")
90 msg.info(f" New selection: {newitem}")
91
92 return newitemlist + newauxlist
93
94
STL class.
bool add(const std::string &hname, TKey *tobj)
Definition fastadd.cxx:55
Definition merge.py:1