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
83 groomdef._prereqOrder[:] = list(dict.fromkeys(groomdef._prereqOrder) )
84
85 return groomdef
86
87
88def aliasToInputDef(alias, parentjetdef=None, canBeConstit=True):
89 """convert a string alias to a full config object, either a JetInputConstitSeq or a JetInputExternal according to the alias.
90
91 This also recursively translate all aliases which are dependencies of this alias. All these dependencies are
92 collected into the 'parentjetdef' (JetDefinition ).
93
94 if canBeConstit==false, the alias is not searched amongst known JetInputConstitSeq (in stdConstitDic),
95 """
96 parentjetdef = parentjetdef or _dummyJetDef()
97 # ----------------
98 # support the cases where alias is not a string but directly a config object
99 if isinstance(alias, JetInputConstit):
100 solveConstitDependencies(alias, parentjetdef, inplace=True)
101 return alias
102 if isinstance(alias, JetInputExternal):
103 solveInputExternalDependencies(alias, parentjetdef, inplace=True)
104 return alias
105
106 # else assume it's a string
107
108 # import the known dictionnary in which we'll look up for the alias
109 from .StandardJetConstits import stdConstitDic, stdInputExtDic
110
111 if canBeConstit and alias in stdConstitDic:
112 # it is a JetInputConstit or JetInputConstitSeq instance :
113 return solveConstitDependencies(stdConstitDic[alias], parentjetdef)
114 elif alias in stdInputExtDic :
115 # it is a JetInputExternal instance :
116 return solveInputExternalDependencies(stdInputExtDic[alias], parentjetdef)
117
118 raise Exception(f"Could not match a known jet input definition for '{alias}' ")
119
120def solveConstitDependencies(constitseq, parentjetdef, inplace=False):
121 """Recursively translate all aliases appearing in the prereqs of constitseq into proper config objects.
122 All are collected into the parentjetdef for which this JetInputConstitSeq is being configured.
123 Then instantiates all aliases for JetConstitModifier
124 """
125
126 if not inplace:
127 constitseq = constitseq.clone()
128
129 from .StandardJetConstits import stdInputExtDic, stdContitModifDic
130 # we technically need a JetInputExternal for constitseq.inputname : conveniently declare it if not existing :
131 stdInputExtDic.setdefault( constitseq.inputname, JetInputExternal( constitseq.inputname, constitseq.basetype) )
132
133 # bellow, we'll use 'solveInputExternalDependencies()' to instantiate the prereqs
134 # so make sure our inputname is part of prereqs. Here, internally, use 'extinput' rather 'input' to mark
135 # the prereq is necessarily a JetInputExternal (and thus avoid issues when the same alias appears in stdInputExtDic and stdConstitDic)
136 if callable(constitseq.inputname):
137 constitseq.prereqs += ['ext'+constitseq.inputname(parentjetdef)]
138 else:
139 constitseq.prereqs += ['extinput:'+constitseq.inputname]
140
141 if isinstance( constitseq, JetInputConstitSeq):
142 # instantiate the JetConstitModifier and add their dependencies to the actual constit sequence
143 for mod in constitseq.modifiers:
144 modInstance = stdContitModifDic[ mod ].clone()
145 parentjetdef._prereqDic[f'cmod:{mod}'] = modInstance
146 solveInputExternalDependencies( modInstance, parentjetdef, inplace=True)
147 # the rest of dependencies are handled similarly as JetInputExternal :
148 solveInputExternalDependencies( constitseq, parentjetdef)
149
150 return constitseq
151
152def solveInputExternalDependencies(jetinputext, parentjetdef, inplace=False):
153 """Recursively translate all aliases appearing in the prereqs of jetinputext into proper config objects.
154 All are collected into the parentjetdef for which this JetInputConstitSeq is being configured.
155 """
156 if not inplace:
157 jetinputext = jetinputext.clone()
158
159 # Prerequisite definitions may contain context-dependent functions instead of plain string.
160 # solve the context dependencence by calling these functions now :
161 if callable(jetinputext.prereqs):
162 # it's a function : call it to get the context-dependent list of prerequisites
163 jetinputext.prereqs = jetinputext.prereqs(parentjetdef)
164 # build the final list by building context-dependent prereq if needed :
165 jetinputext.prereqs = [ prereq(parentjetdef) if callable(prereq)
166 else prereq
167 for prereq in jetinputext.prereqs ]
168
169 # at this point, jetinputext.prereqs contains only strings representing the final prerequisites
170 for prereq in jetinputext.prereqs :
171 reqInstance = parentjetdef._prereqDic.get( prereq, None)
172 if reqInstance is None:
173 reqType , inputkey = prereq.split(':') #
174 reqInstance = aliasToInputDef(inputkey, parentjetdef,
175 canBeConstit = (reqType != "extinput") )
176 parentjetdef._prereqDic[prereq] = reqInstance
177 parentjetdef._prereqOrder.append(prereq)
178
179 return jetinputext
180
181
182
183
184def prereqToDef(prereq, parentjetdef):
185 """translate a prereq string in the form 'type:alias' into a known config object.
186 """
187 str_prereq = prereq(parentjetdef) if callable(prereq) else prereq
188 reqtype, reqkey = str_prereq.split(':',1)
189 if reqtype=='mod':
190 reqInstance = aliasToModDef(reqkey, parentjetdef)
191 else:
192 reqInstance = aliasToInputDef(reqkey, parentjetdef)
193 return reqInstance
194
195def aliasToModDef(alias, parentjetdef ):
196 """return a JetModifier config object corresponding to alias, also recursively translating all aliases in the dependencies of this JetModifier."""
197 if isinstance(alias, JetModifier):
198 return alias
199 # else assume it's a string
200
201 # split it, to extract the optional specifiers
202 modL = alias.split(":")
203 modkey = modL[0]
204 modspec = ':'.join(modL[1:])
205
206 # retrieve an instance from the known modifiers in StandardJetMods :
207 from .StandardJetMods import stdJetModifiers
208 moddef = stdJetModifiers[modkey].clone( modspec = modspec)
209
210
211 if callable(moddef.prereqs):
212 moddef.prereqs = moddef.prereqs( modspec, parentjetdef )
213
214 for prereq in moddef.prereqs:
215 str_prereq = prereq(parentjetdef) if callable(prereq) else prereq
216 reqInstance = parentjetdef._prereqDic.get( str_prereq, None)
217 if reqInstance is None:
218 reqInstance = prereqToDef(str_prereq, parentjetdef)
219
220 if str_prereq.startswith('ghost:'):
221 # then it is also an input : register this requirement also as an input
222 prereqN = str_prereq.split(':')[1]
223 parentjetdef._prereqOrder.append('input:'+prereqN)
224 parentjetdef._prereqDic['input:'+prereqN] = reqInstance # the input config instance is identical for input and ghost (only the PseudoJet will differ)
225
226 parentjetdef._prereqOrder.append(str_prereq)
227 parentjetdef._prereqDic[str_prereq] = reqInstance
228
229 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)