96 """A helper function to create output algorithm"""
97 alg = config.createAlgorithm(
'CP::AsgxAODNTupleMakerAlg', name)
98 alg.TreeName = self.treeName
99 alg.RootStreamName = self.streamName
100 alg.NonContainers = list(self.nonContainers)
101 branchList = list(vars)
103 branchList_nosys = [branch
for branch
in branchList
if "%SYS%" not in branch]
104 branchList_sys = [branch
for branch
in branchList
if "%SYS%" in branch]
105 alg.Branches = branchList_nosys + branchList_sys
106 if self.defaultBasketSize
is not None:
107 alg.DefaultBasketSize = self.defaultBasketSize
112 log = logging.getLogger(
'OutputAnalysisConfig')
124 keys_message = [repr(key)
for key
in overlapping_keys]
125 raise KeyError(f
"containersFullMET would overwrite the following container keys: {', '.join(keys_message)}")
130 if config.dataType()
is not DataType.Data:
138 keys_message = [repr(key)
for key
in overlapping_keys]
139 raise KeyError(f
"containersOnlyForMC would overwrite the following container keys: {', '.join(keys_message)}")
148 log.warning(
"Skipping unrecognised container prefix '%s' for DSID-filtering in OutputAnalysisConfig...", container)
150 if not filter_dsids (dsid_filters, config):
152 log.info(
"Skipping container prefix '%s' due to DSID filtering...", container)
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)
161 var_container = var.split(
'.')[0].
replace(
'_NOSYS',
'').
replace(
'_%SYS%',
'')
162 if var_container == self.
containers[container]:
164 log.info(
"Skipping MET branch definition '%s' for excluded container %s...", var, var_container)
167 var_container = var.split(
'.')[0].
replace(
'_NOSYS',
'').
replace(
'_%SYS%',
'')
168 if var_container == self.
containers[container]:
170 log.info(
"Skipping truth MET branch definition '%s' for excluded container %s...", var, var_container)
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)
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
193 outputConfig.enabled =
True
194 outputConfigs[prefix + outputName] = outputConfig
197 for dsid, dsid_commands
in self.commandsOnlyForDSIDs.items():
198 if filter_dsids([dsid], config):
201 outputConfigsRename = {}
203 words = command.split (
' ')
204 if len (words) == 0 :
205 raise ValueError (
'received empty command for "commands" option')
206 optional = words[0] ==
'optional'
209 if words[0] ==
'enable' :
210 if len (words) != 2 :
211 raise ValueError (
'enable takes exactly one argument: ' + command)
213 for name
in outputConfigs :
214 if re.match (words[1], name) :
215 outputConfigs[name].enabled =
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)
223 for name
in outputConfigs :
224 if re.match (words[1], name) :
225 outputConfigs[name].enabled =
False
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)
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
239 if not used
and not optional
and config.dataType()
is not DataType.Data:
240 raise KeyError (
'unknown branch pattern for rename: ' + words[1])
242 raise KeyError (
'unknown command for "commands" option: ' + words[0])
245 outputConfigs.update(outputConfigsRename)
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
259 if outputConfig.noSys :
260 outputConfig.outputContainerName = outputConfig.outputContainerName.replace (
'%SYS%',
'NOSYS')
261 outputConfig.variableName = outputConfig.variableName.replace (
'%SYS%',
'NOSYS')
263 outputName +=
"_NOSYS"
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}"
273 branchDecl += f
" metTerm={self.metTermName}"
274 myVars.add(branchDecl)
278 allBranches |= self.
vars
279 allBranches |= autoVars
285 allBranches |= userMetVars
286 allBranches |= autoMetVars
288 userTruthMetVars =
set()
289 if config.dataType()
is not DataType.Data:
293 allBranches |= userTruthMetVars
294 allBranches |= autoTruthMetVars
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)
304 branchList = list(allBranches)
306 alg.Branches = branchList
311 treeMaker = config.createAlgorithm(
'CP::TreeMakerAlg',
'TreeMaker' )
312 treeMaker.TreeName = self.treeName
313 treeMaker.RootStreamName = self.streamName
317 if self.
vars or autoVars:
320 if self.
metVars or autoMetVars:
323 if config.dataType()
is not DataType.Data
and (self.
truthMetVars or autoTruthMetVars):
324 self.
createOutputAlgs(config,
'TruthMetNTupleMaker', userTruthMetVars | autoTruthMetVars)
326 treeFiller = config.createAlgorithm(
'CP::TreeFillerAlg',
'TreeFiller' )
327 treeFiller.TreeName = self.treeName
328 treeFiller.RootStreamName = self.streamName
334 For each container and for each selection, create a single pass variable in output NTuple,
335 which aggregates all the selections flag of the given selection. For example, this can include
336 pT, eta selections, some object ID selection, overlap removal, etc.
337 The goal is to have only one flag per object and working point in the output NTuple.
339 originalContainersSeen = []
342 containerName = config.getOutputContainerOrigin(outputContainerName)
343 if containerName
in originalContainersSeen:
346 originalContainersSeen.append(containerName)
349 if containerName ==
'EventInfo':
354 selectionNames = config.getSelectionNames(containerName, excludeFrom={
'ftag'})
355 for selectionName
in selectionNames:
357 if selectionName ==
'':
360 if self.skipRedundantSelectionFlags
and "outputSelect" in selectionName:
366 Schedule an algorithm to pick up all cut flags for a given selectionName.
367 The summary selection flag is written to output as selectionFlagPrefix_selectionName.
369 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
370 f
'ObjectSelectionSummary_{containerName}_{selectionName}')
371 selectionDecoration = f
'baselineSelection_{selectionName}_%SYS%'
372 alg.selectionDecoration = f
'{selectionDecoration},as_char'
373 alg.particles = config.readName (containerName)
374 alg.preselection = config.getFullSelection (containerName, selectionName)
375 config.addOutputVar (containerName, selectionDecoration, self.selectionFlagPrefix +
'_' + selectionName)