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 if containerName != outputConfig.origContainerName or config.checkOutputContainer(containerName):
189 outputConfig.outputContainerName = containerName + '_%SYS%'
190 else:
191 outputConfig.outputContainerName = config.readName(containerName)
192 outputConfig.prefix = prefix
193
194
195 if prefix in self.containersFullMET and outputConfig.variableName == 'name':
196 outputConfig.enabled = True
197 outputConfigs[prefix + outputName] = outputConfig
198
199
200 for dsid, dsid_commands in self.commandsOnlyForDSIDs.items():
201 if filter_dsids([dsid], config):
202 self.commands += dsid_commands
203
204 outputConfigsRename = {}
205 for command in self.commands :
206 words = command.split (' ')
207 if len (words) == 0 :
208 raise ValueError ('received empty command for "commands" option')
209 optional = words[0] == 'optional'
210 if optional :
211 words = words[1:]
212 if words[0] == 'enable' :
213 if len (words) != 2 :
214 raise ValueError ('enable takes exactly one argument: ' + command)
215 used = False
216 for name in outputConfigs :
217 if re.match (words[1], name) :
218 outputConfigs[name].enabled = True
219 used = True
220 if not used and not optional and config.dataType() is not DataType.Data:
221 raise KeyError ('unknown branch pattern for enable: ' + words[1])
222 elif words[0] == 'disable' :
223 if len (words) != 2 :
224 raise ValueError ('disable takes exactly one argument: ' + command)
225 used = False
226 for name in outputConfigs :
227 if re.match (words[1], name) :
228 outputConfigs[name].enabled = False
229 used = True
230 if not used and not optional and config.dataType() is not DataType.Data:
231 raise KeyError ('unknown branch pattern for disable: ' + words[1])
232 elif words[0] == 'rename' :
233 if len (words) != 3 :
234 raise ValueError ('rename takes exactly two arguments: ' + command)
235 used = False
236 for name in outputConfigs :
237 if re.match (words[1], name) :
238 new_name = re.sub (words[1], words[2], name)
239 outputConfigsRename[new_name] = copy.deepcopy(outputConfigs[name])
240 outputConfigs[name].enabled = False
241 used = True
242 if not used and not optional and config.dataType() is not DataType.Data:
243 raise KeyError ('unknown branch pattern for rename: ' + words[1])
244 else :
245 raise KeyError ('unknown command for "commands" option: ' + words[0])
246
247
248 outputConfigs.update(outputConfigsRename)
249
252 autoTruthMetVars =
set()
253 for outputName, outputConfig in outputConfigs.items():
254 if outputConfig.enabled :
255 if config.isMetContainer (outputConfig.origContainerName) and outputConfig.prefix not in self.containersFullMET:
256 if "Truth" in outputConfig.origContainerName:
257 myVars = autoTruthMetVars
258 else:
259 myVars = autoMetVars
260 else :
261 myVars = autoVars
262 if outputConfig.noSys :
263 outputConfig.outputContainerName = outputConfig.outputContainerName.replace ('%SYS%', 'NOSYS')
264 outputConfig.variableName = outputConfig.variableName.replace ('%SYS%', 'NOSYS')
265 if self.alwaysAddNosys :
266 outputName += "_NOSYS"
267 else :
268 outputName += '_%SYS%'
269 branchDecl = f"{outputConfig.outputContainerName}.{outputConfig.variableName} -> {outputName}"
270 if outputConfig.auxType is not None :
271 branchDecl += f" type={outputConfig.auxType}"
272 if config.isMetContainer (outputConfig.origContainerName) and outputConfig.prefix not in self.containersFullMET:
273 if "Truth" in outputConfig.origContainerName:
274 branchDecl += f" metTerm={self.truthMetTermName}"
275 else:
276 branchDecl += f" metTerm={self.metTermName}"
277 myVars.add(branchDecl)
278
279
281 allBranches |= self.vars
282 allBranches |= autoVars
283
285 if self.metVars:
286 for var in self.metVars:
287 userMetVars.add(var + " metTerm=" + self.metTermName)
288 allBranches |= userMetVars
289 allBranches |= autoMetVars
290
291 userTruthMetVars =
set()
292 if config.dataType() is not DataType.Data:
293 if self.truthMetVars:
294 for var in self.truthMetVars:
295 userTruthMetVars.add(var + " metTerm=" + self.truthMetTermName)
296 allBranches |= userTruthMetVars
297 allBranches |= autoTruthMetVars
298
299
300 if self.outputFormat == 'RNTuple':
301 alg = config.createAlgorithm('CP::RNtupleTreeMakerAlg', 'RNtupleMaker')
302 alg.TreeName = self.treeName
303 alg.RootStreamName = self.streamName
304 alg.OutputStreamName = self.streamName
305 alg.NonContainers = list(self.nonContainers)
306
307 branchList = list(allBranches)
308 branchList.sort(key=self.branchSortOrder)
309 alg.Branches = branchList
310
311 return
312
313
314 treeMaker = config.createAlgorithm( 'CP::TreeMakerAlg', 'TreeMaker' )
315 treeMaker.TreeName = self.treeName
316 treeMaker.RootStreamName = self.streamName
317
318
319
320 if self.vars or autoVars:
321 self.createOutputAlgs(config, 'NTupleMaker', self.vars | autoVars)
322
323 if self.metVars or autoMetVars:
324 self.createOutputAlgs(config, 'MetNTupleMaker', userMetVars | autoMetVars)
325
326 if config.dataType() is not DataType.Data and (self.truthMetVars or autoTruthMetVars):
327 self.createOutputAlgs(config, 'TruthMetNTupleMaker', userTruthMetVars | autoTruthMetVars)
328
329 treeFiller = config.createAlgorithm( 'CP::TreeFillerAlg', 'TreeFiller' )
330 treeFiller.TreeName = self.treeName
331 treeFiller.RootStreamName = self.streamName
332
333
334
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)