ATLAS Offline Software
Loading...
Searching...
No Matches
DependencyHelper.py
Go to the documentation of this file.
1# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2"""
3
4Functions to solve dependencies of Jet reco components.
5
6Jet reco components are objects described by classes in JetDefinition.py (including JetDefinition, JetModifier,...)
7and the dependencies of each instance are set as (list of) string aliases refering to other components.
8
9The functions here are scanning recursively all the aliases, building the corresponding component objects and
10collecting them in a JetDefinition.
11
12"""
13from .JetDefinition import JetInputExternal, JetInputConstit, JetModifier, JetInputConstitSeq
15 def __init__(self):
16 self._prereqDic = {}
17 self._prereqOrder = []
18
19
20def solveDependencies( jetdef0, flags ):
21 """ Retrieve recursively all dependencies described by str aliases (from modifiers, ghosts, etc..) within jetdef0.
22 The aliases are converted in to proper config objects (like JetModifier, JetInputConstit,...) and are collected into
23 a cloned version of jetdef0.
24
25 The cloned version is returned and contains all the necessary information to build the actual C++ tools and algs.
26 (in particular, the _prereqDic and _prereqOrder internal members of the clone are filled).
27 The cloned version also has its member '._cflags' set to the given config flags (might be used to instantiate the dependencies).
28 If jetdef0.context=='default' than the cloned version has its context set according to flags
29 """
30
31 # create a clone onto which we can set internal variables to keep track of dependencies
32 jetdef = jetdef0.clone()
33 jetdef._cflags = flags
34 jetdef._contextDic = flags.Jet.Context[jetdef0.context]
35
36 solveConstitDependencies(jetdef.inputdef, jetdef, inplace=True)
37
38 jetdef._prereqDic['input:'+jetdef.inputdef.name] = jetdef.inputdef
39 jetdef._prereqOrder.append('input:'+jetdef.inputdef.name)
40
41 for g in jetdef.extrainputs:
42 gInstance = aliasToInputDef( g , jetdef)
43 jetdef._prereqDic['input:'+g] = gInstance
44 jetdef._prereqOrder.append('input:'+g)
45
46 for g in jetdef.ghostdefs:
47 gInstance = aliasToInputDef( g , jetdef)
48 jetdef._prereqDic['input:'+g] = gInstance
49 jetdef._prereqOrder.append('input:'+g)
50 jetdef._prereqDic['ghost:'+g] = gInstance
51 jetdef._prereqOrder.append('ghost:'+g)
52
53 for mod in jetdef.modifiers:
54 modInstance = aliasToModDef(mod, jetdef)
55 jetdef._prereqDic['mod:'+mod] = modInstance
56 jetdef._prereqOrder.append('mod:'+mod)
57
58 # Deduplicate the prereq (with python > 3.6 dict is ordered so the trick is guaranteed to work) :
59 jetdef._prereqOrder[:] = list(dict.fromkeys(jetdef._prereqOrder) )
60
61 return jetdef
62
63
64def solveGroomingDependencies( groomdef0, flags ):
65 """Retrieve all dependencies described by str aliases in groomdef0.modifiers.
66
67 The aliases are converted in to proper config objects (like JetModifier, JetInputConstit,...) and are collected into
68 a cloned version of groomdef0.
69 The cloned version is returned and contains all the necessary information to build the actual C++ tools and algs.
70 (in particular, the _prereqDic and _prereqOrder internal members of the clone are filled).
71 """
72
73 # if the context is "default", translate it into an actual context according to flags
74 groomdef = groomdef0.clone()
75 groomdef._cflags = flags
76 groomdef._contextDic = flags.Jet.Context[groomdef0.context]
77
78 for mod in groomdef.modifiers:
79 modInstance = aliasToModDef(mod, groomdef)
80 groomdef._prereqDic['mod:'+mod] = modInstance
81 groomdef._prereqOrder.append('mod:'+mod)
82 return groomdef
83
84
85def aliasToInputDef(alias, parentjetdef=None, canBeConstit=True):
86 """convert a string alias to a full config object, either a JetInputConstitSeq or a JetInputExternal according to the alias.
87
88 This also recursively translate all aliases which are dependencies of this alias. All these dependencies are
89 collected into the 'parentjetdef' (JetDefinition ).
90
91 if canBeConstit==false, the alias is not searched amongst known JetInputConstitSeq (in stdConstitDic),
92 """
93 parentjetdef = parentjetdef or _dummyJetDef()
94 # ----------------
95 # support the cases where alias is not a string but directly a config object
96 if isinstance(alias, JetInputConstit):
97 solveConstitDependencies(alias, parentjetdef, inplace=True)
98 return alias
99 if isinstance(alias, JetInputExternal):
100 solveInputExternalDependencies(alias, parentjetdef, inplace=True)
101 return alias
102
103 # else assume it's a string
104
105 # import the known dictionnary in which we'll look up for the alias
106 from .StandardJetConstits import stdConstitDic, stdInputExtDic
107
108 if canBeConstit and alias in stdConstitDic:
109 # it is a JetInputConstit or JetInputConstitSeq instance :
110 return solveConstitDependencies(stdConstitDic[alias], parentjetdef)
111 elif alias in stdInputExtDic :
112 # it is a JetInputExternal instance :
113 return solveInputExternalDependencies(stdInputExtDic[alias], parentjetdef)
114
115 raise Exception(f"Could not match a known jet input definition for '{alias}' ")
116
117def solveConstitDependencies(constitseq, parentjetdef, inplace=False):
118 """Recursively translate all aliases appearing in the prereqs of constitseq into proper config objects.
119 All are collected into the parentjetdef for which this JetInputConstitSeq is being configured.
120 Then instantiates all aliases for JetConstitModifier
121 """
122
123 if not inplace:
124 constitseq = constitseq.clone()
125
126 from .StandardJetConstits import stdInputExtDic, stdContitModifDic
127 # we technically need a JetInputExternal for constitseq.inputname : conveniently declare it if not existing :
128 stdInputExtDic.setdefault( constitseq.inputname, JetInputExternal( constitseq.inputname, constitseq.basetype) )
129
130 # bellow, we'll use 'solveInputExternalDependencies()' to instantiate the prereqs
131 # so make sure our inputname is part of prereqs. Here, internally, use 'extinput' rather 'input' to mark
132 # the prereq is necessarily a JetInputExternal (and thus avoid issues when the same alias appears in stdInputExtDic and stdConstitDic)
133 if callable(constitseq.inputname):
134 constitseq.prereqs += ['ext'+constitseq.inputname(parentjetdef)]
135 else:
136 constitseq.prereqs += ['extinput:'+constitseq.inputname]
137
138 if isinstance( constitseq, JetInputConstitSeq):
139 # instantiate the JetConstitModifier and add their dependencies to the actual constit sequence
140 for mod in constitseq.modifiers:
141 modInstance = stdContitModifDic[ mod ].clone()
142 parentjetdef._prereqDic[f'cmod:{mod}'] = modInstance
143 solveInputExternalDependencies( modInstance, parentjetdef, inplace=True)
144 # the rest of dependencies are handled similarly as JetInputExternal :
145 solveInputExternalDependencies( constitseq, parentjetdef)
146
147 return constitseq
148
149def solveInputExternalDependencies(jetinputext, parentjetdef, inplace=False):
150 """Recursively translate all aliases appearing in the prereqs of jetinputext into proper config objects.
151 All are collected into the parentjetdef for which this JetInputConstitSeq is being configured.
152 """
153 if not inplace:
154 jetinputext = jetinputext.clone()
155
156 # Prerequisite definitions may contain context-dependent functions instead of plain string.
157 # solve the context dependencence by calling these functions now :
158 if callable(jetinputext.prereqs):
159 # it's a function : call it to get the context-dependent list of prerequisites
160 jetinputext.prereqs = jetinputext.prereqs(parentjetdef)
161 # build the final list by building context-dependent prereq if needed :
162 jetinputext.prereqs = [ prereq(parentjetdef) if callable(prereq)
163 else prereq
164 for prereq in jetinputext.prereqs ]
165
166 # at this point, jetinputext.prereqs contains only strings representing the final prerequisites
167 for prereq in jetinputext.prereqs :
168 reqInstance = parentjetdef._prereqDic.get( prereq, None)
169 if reqInstance is None:
170 reqType , inputkey = prereq.split(':') #
171 reqInstance = aliasToInputDef(inputkey, parentjetdef,
172 canBeConstit = (reqType != "extinput") )
173 parentjetdef._prereqDic[prereq] = reqInstance
174 parentjetdef._prereqOrder.append(prereq)
175
176 return jetinputext
177
178
179
180
181def prereqToDef(prereq, parentjetdef):
182 """translate a prereq string in the form 'type:alias' into a known config object.
183 """
184 str_prereq = prereq(parentjetdef) if callable(prereq) else prereq
185 reqtype, reqkey = str_prereq.split(':',1)
186 if reqtype=='mod':
187 reqInstance = aliasToModDef(reqkey, parentjetdef)
188 else:
189 reqInstance = aliasToInputDef(reqkey, parentjetdef)
190 return reqInstance
191
192def aliasToModDef(alias, parentjetdef ):
193 """return a JetModifier config object corresponding to alias, also recursively translating all aliases in the dependencies of this JetModifier."""
194 if isinstance(alias, JetModifier):
195 return alias
196 # else assume it's a string
197
198 # split it, to extract the optional specifiers
199 modL = alias.split(":")
200 modkey = modL[0]
201 modspec = ':'.join(modL[1:])
202
203 # retrieve an instance from the known modifiers in StandardJetMods :
204 from .StandardJetMods import stdJetModifiers
205 moddef = stdJetModifiers[modkey].clone( modspec = modspec)
206
207
208 if callable(moddef.prereqs):
209 moddef.prereqs = moddef.prereqs( modspec, parentjetdef )
210
211 for prereq in moddef.prereqs:
212 str_prereq = prereq(parentjetdef) if callable(prereq) else prereq
213 reqInstance = parentjetdef._prereqDic.get( str_prereq, None)
214 if reqInstance is None:
215 reqInstance = prereqToDef(str_prereq, parentjetdef)
216
217 if str_prereq.startswith('ghost:'):
218 # then it is also an input : register this requirement also as an input
219 prereqN = str_prereq.split(':')[1]
220 parentjetdef._prereqOrder.append('input:'+prereqN)
221 parentjetdef._prereqDic['input:'+prereqN] = reqInstance # the input config instance is identical for input and ghost (only the PseudoJet will differ)
222
223 parentjetdef._prereqOrder.append(str_prereq)
224 parentjetdef._prereqDic[str_prereq] = reqInstance
225
226 return moddef
solveDependencies(jetdef0, flags)
solveConstitDependencies(constitseq, parentjetdef, inplace=False)
prereqToDef(prereq, parentjetdef)
aliasToModDef(alias, parentjetdef)
solveGroomingDependencies(groomdef0, flags)
aliasToInputDef(alias, parentjetdef=None, canBeConstit=True)
solveInputExternalDependencies(jetinputext, parentjetdef, inplace=False)