110 def makeAlgs (self, config) :
111
112 log = logging.getLogger('OutputAnalysisConfig')
113
114 self.containers = dict(self.containers)
115 self.vars =
set(self.vars)
116 self.varsOnlyForMC =
set(self.varsOnlyForMC)
117 self.metVars =
set(self.metVars)
118 self.truthMetVars =
set(self.truthMetVars)
119
120
121 overlapping_keys =
set(self.containers.keys()).
intersection(self.containersFullMET.keys())
122 if overlapping_keys:
123
124 keys_message = [repr(key) for key in overlapping_keys]
125 raise KeyError(f"containersFullMET would overwrite the following container keys: {', '.join(keys_message)}")
126
127 self.containers.update(self.containersFullMET)
128
129
130 if config.dataType() is not DataType.Data:
131 self.vars |= self.varsOnlyForMC
132
133
134
135 overlapping_keys =
set(self.containers.keys()).
intersection(self.containersOnlyForMC.keys())
136 if overlapping_keys:
137
138 keys_message = [repr(key) for key in overlapping_keys]
139 raise KeyError(f"containersOnlyForMC would overwrite the following container keys: {', '.join(keys_message)}")
140
141
142 self.containers.update(self.containersOnlyForMC)
143
144
145 if self.containersOnlyForDSIDs:
146 for container, dsid_filters in self.containersOnlyForDSIDs.items():
147 if container not in self.containers:
148 log.warning("Skipping unrecognised container prefix '%s' for DSID-filtering in OutputAnalysisConfig...", container)
149 continue
150 if not filter_dsids (dsid_filters, config):
151
152 log.info("Skipping container prefix '%s' due to DSID filtering...", container)
153
154 for var
in set(self.vars):
155 var_container = var.split(
'.')[0].
replace(
'_NOSYS',
'').
replace(
'_%SYS%',
'')
156 if var_container == self.containers[container]:
157 self.vars.remove(var)
158 log.info("Skipping branch definition '%s' for excluded container %s...", var, var_container)
159
160 for var
in set(self.metVars):
161 var_container = var.split(
'.')[0].
replace(
'_NOSYS',
'').
replace(
'_%SYS%',
'')
162 if var_container == self.containers[container]:
163 self.metVars.remove(var)
164 log.info("Skipping MET branch definition '%s' for excluded container %s...", var, var_container)
165
166 for var
in set(self.truthMetVars):
167 var_container = var.split(
'.')[0].
replace(
'_NOSYS',
'').
replace(
'_%SYS%',
'')
168 if var_container == self.containers[container]:
169 self.truthMetVars.remove(var)
170 log.info("Skipping truth MET branch definition '%s' for excluded container %s...", var, var_container)
171
172 self.containers.pop (container)
173
174 for prefix, container in self.containers.items():
175 origName = config.getOutputContainerOrigin(container)
176 if config.getContainerMeta(origName, "nonContainer", False):
177 self.nonContainers.append(origName)
178
179 if self.storeSelectionFlags:
180 self.createSelectionFlagBranches(config)
181
182 outputConfigs = {}
183 for prefix in self.containers.keys() :
184 containerName = self.containers[prefix]
185 outputDict = config.getOutputVars (containerName)
186 for outputName in outputDict :
187 outputConfig = copy.deepcopy (outputDict[outputName])
188 outputConfig.outputContainerName = config.readName(containerName)
189 outputConfig.prefix = prefix
190
191
192 if prefix in self.containersFullMET and outputConfig.variableName == 'name':
193 outputConfig.enabled = True
194 outputConfigs[prefix + outputName] = outputConfig
195
196
197 for dsid, dsid_commands in self.commandsOnlyForDSIDs.items():
198 if filter_dsids([dsid], config):
199 self.commands += dsid_commands
200
201 outputConfigsRename = {}
202 for command in self.commands :
203 words = command.split (' ')
204 if len (words) == 0 :
205 raise ValueError ('received empty command for "commands" option')
206 optional = words[0] == 'optional'
207 if optional :
208 words = words[1:]
209 if words[0] == 'enable' :
210 if len (words) != 2 :
211 raise ValueError ('enable takes exactly one argument: ' + command)
212 used = False
213 for name in outputConfigs :
214 if re.match (words[1], name) :
215 outputConfigs[name].enabled = True
216 used = True
217 if not used and not optional and config.dataType() is not DataType.Data:
218 raise KeyError ('unknown branch pattern for enable: ' + words[1])
219 elif words[0] == 'disable' :
220 if len (words) != 2 :
221 raise ValueError ('disable takes exactly one argument: ' + command)
222 used = False
223 for name in outputConfigs :
224 if re.match (words[1], name) :
225 outputConfigs[name].enabled = False
226 used = True
227 if not used and not optional and config.dataType() is not DataType.Data:
228 raise KeyError ('unknown branch pattern for disable: ' + words[1])
229 elif words[0] == 'rename' :
230 if len (words) != 3 :
231 raise ValueError ('rename takes exactly two arguments: ' + command)
232 used = False
233 for name in outputConfigs :
234 if re.match (words[1], name) :
235 new_name = re.sub (words[1], words[2], name)
236 outputConfigsRename[new_name] = copy.deepcopy(outputConfigs[name])
237 outputConfigs[name].enabled = False
238 used = True
239 if not used and not optional and config.dataType() is not DataType.Data:
240 raise KeyError ('unknown branch pattern for rename: ' + words[1])
241 else :
242 raise KeyError ('unknown command for "commands" option: ' + words[0])
243
244
245 outputConfigs.update(outputConfigsRename)
246
249 autoTruthMetVars =
set()
250 for outputName, outputConfig in outputConfigs.items():
251 if outputConfig.enabled :
252 if config.isMetContainer (outputConfig.origContainerName) and outputConfig.prefix not in self.containersFullMET:
253 if "Truth" in outputConfig.origContainerName:
254 myVars = autoTruthMetVars
255 else:
256 myVars = autoMetVars
257 else :
258 myVars = autoVars
259 if outputConfig.noSys :
260 outputConfig.outputContainerName = outputConfig.outputContainerName.replace ('%SYS%', 'NOSYS')
261 outputConfig.variableName = outputConfig.variableName.replace ('%SYS%', 'NOSYS')
262 if self.alwaysAddNosys :
263 outputName += "_NOSYS"
264 else :
265 outputName += '_%SYS%'
266 branchDecl = f"{outputConfig.outputContainerName}.{outputConfig.variableName} -> {outputName}"
267 if outputConfig.auxType is not None :
268 branchDecl += f" type={outputConfig.auxType}"
269 if config.isMetContainer (outputConfig.origContainerName) and outputConfig.prefix not in self.containersFullMET:
270 if "Truth" in outputConfig.origContainerName:
271 branchDecl += f" metTerm={self.truthMetTermName}"
272 else:
273 branchDecl += f" metTerm={self.metTermName}"
274 myVars.add(branchDecl)
275
276
278 allBranches |= self.vars
279 allBranches |= autoVars
280
282 if self.metVars:
283 for var in self.metVars:
284 userMetVars.add(var + " metTerm=" + self.metTermName)
285 allBranches |= userMetVars
286 allBranches |= autoMetVars
287
288 userTruthMetVars =
set()
289 if config.dataType() is not DataType.Data:
290 if self.truthMetVars:
291 for var in self.truthMetVars:
292 userTruthMetVars.add(var + " metTerm=" + self.truthMetTermName)
293 allBranches |= userTruthMetVars
294 allBranches |= autoTruthMetVars
295
296
297 if self.outputFormat == 'RNTuple':
298 alg = config.createAlgorithm('CP::RNtupleTreeMakerAlg', 'RNtupleMaker')
299 alg.TreeName = self.treeName
300 alg.RootStreamName = self.streamName
301 alg.OutputStreamName = self.streamName
302 alg.NonContainers = list(self.nonContainers)
303
304 branchList = list(allBranches)
305 branchList.sort(key=self.branchSortOrder)
306 alg.Branches = branchList
307
308 return
309
310
311 treeMaker = config.createAlgorithm( 'CP::TreeMakerAlg', 'TreeMaker' )
312 treeMaker.TreeName = self.treeName
313 treeMaker.RootStreamName = self.streamName
314
315
316
317 if self.vars or autoVars:
318 self.createOutputAlgs(config, 'NTupleMaker', self.vars | autoVars)
319
320 if self.metVars or autoMetVars:
321 self.createOutputAlgs(config, 'MetNTupleMaker', userMetVars | autoMetVars)
322
323 if config.dataType() is not DataType.Data and (self.truthMetVars or autoTruthMetVars):
324 self.createOutputAlgs(config, 'TruthMetNTupleMaker', userTruthMetVars | autoTruthMetVars)
325
326 treeFiller = config.createAlgorithm( 'CP::TreeFillerAlg', 'TreeFiller' )
327 treeFiller.TreeName = self.treeName
328 treeFiller.RootStreamName = self.streamName
329
330
331
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
std::string replace(std::string s, const std::string &s2, const std::string &s3)