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 if containerName != outputConfig.origContainerName
or config.checkOutputContainer(containerName):
189 outputConfig.outputContainerName = containerName +
'_%SYS%'
191 outputConfig.outputContainerName = config.readName(containerName)
192 outputConfig.prefix = prefix
196 outputConfig.enabled =
True
197 outputConfigs[prefix + outputName] = outputConfig
200 for dsid, dsid_commands
in self.commandsOnlyForDSIDs.items():
201 if filter_dsids([dsid], config):
204 outputConfigsRename = {}
206 words = command.split (
' ')
207 if len (words) == 0 :
208 raise ValueError (
'received empty command for "commands" option')
209 optional = words[0] ==
'optional'
212 if words[0] ==
'enable' :
213 if len (words) != 2 :
214 raise ValueError (
'enable takes exactly one argument: ' + command)
216 for name
in outputConfigs :
217 if re.match (words[1], name) :
218 outputConfigs[name].enabled =
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)
226 for name
in outputConfigs :
227 if re.match (words[1], name) :
228 outputConfigs[name].enabled =
False
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)
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
242 if not used
and not optional
and config.dataType()
is not DataType.Data:
243 raise KeyError (
'unknown branch pattern for rename: ' + words[1])
245 raise KeyError (
'unknown command for "commands" option: ' + words[0])
248 outputConfigs.update(outputConfigsRename)
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
262 if outputConfig.noSys :
263 outputConfig.outputContainerName = outputConfig.outputContainerName.replace (
'%SYS%',
'NOSYS')
264 outputConfig.variableName = outputConfig.variableName.replace (
'%SYS%',
'NOSYS')
266 outputName +=
"_NOSYS"
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}"
276 branchDecl += f
" metTerm={self.metTermName}"
277 myVars.add(branchDecl)
281 allBranches |= self.
vars
282 allBranches |= autoVars
288 allBranches |= userMetVars
289 allBranches |= autoMetVars
291 userTruthMetVars =
set()
292 if config.dataType()
is not DataType.Data:
296 allBranches |= userTruthMetVars
297 allBranches |= autoTruthMetVars
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)
307 branchList = list(allBranches)
309 alg.Branches = branchList
314 treeMaker = config.createAlgorithm(
'CP::TreeMakerAlg',
'TreeMaker' )
315 treeMaker.TreeName = self.treeName
316 treeMaker.RootStreamName = self.streamName
320 if self.
vars or autoVars:
323 if self.
metVars or autoMetVars:
326 if config.dataType()
is not DataType.Data
and (self.
truthMetVars or autoTruthMetVars):
327 self.
createOutputAlgs(config,
'TruthMetNTupleMaker', userTruthMetVars | autoTruthMetVars)
329 treeFiller = config.createAlgorithm(
'CP::TreeFillerAlg',
'TreeFiller' )
330 treeFiller.TreeName = self.treeName
331 treeFiller.RootStreamName = self.streamName
337 For each container and for each selection, create a single pass variable in output NTuple,
338 which aggregates all the selections flag of the given selection. For example, this can include
339 pT, eta selections, some object ID selection, overlap removal, etc.
340 The goal is to have only one flag per object and working point in the output NTuple.
342 originalContainersSeen = []
345 containerName = config.getOutputContainerOrigin(outputContainerName)
346 if containerName
in originalContainersSeen:
349 originalContainersSeen.append(containerName)
352 if containerName ==
'EventInfo':
357 selectionNames = config.getSelectionNames(containerName, excludeFrom={
'ftag'})
358 for selectionName
in selectionNames:
360 if selectionName ==
'':
363 if self.skipRedundantSelectionFlags
and "outputSelect" in selectionName:
369 Schedule an algorithm to pick up all cut flags for a given selectionName.
370 The summary selection flag is written to output as selectionFlagPrefix_selectionName.
372 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
373 f
'ObjectSelectionSummary_{containerName}_{selectionName}')
374 selectionDecoration = f
'baselineSelection_{selectionName}_%SYS%'
375 alg.selectionDecoration = f
'{selectionDecoration},as_char'
376 alg.particles = config.readName (containerName)
377 alg.preselection = config.getFullSelection (containerName, selectionName)
378 config.addOutputVar (containerName, selectionDecoration, self.selectionFlagPrefix +
'_' + selectionName)