95 """A helper function to create output algorithm"""
96 alg = config.createAlgorithm(
'CP::AsgxAODNTupleMakerAlg', name)
97 alg.TreeName = self.treeName
98 alg.RootStreamName = self.streamName
99 alg.NonContainers = list(self.nonContainers)
100 branchList = list(vars)
102 branchList_nosys = [branch
for branch
in branchList
if "%SYS%" not in branch]
103 branchList_sys = [branch
for branch
in branchList
if "%SYS%" in branch]
104 alg.Branches = branchList_nosys + branchList_sys
105 if self.defaultBasketSize
is not None:
106 alg.DefaultBasketSize = self.defaultBasketSize
111 log = logging.getLogger(
'OutputAnalysisConfig')
126 keys_message = [repr(key)
for key
in overlapping_keys]
127 raise KeyError(f
"containersFullMET would overwrite the following container keys: {', '.join(keys_message)}")
132 if config.dataType()
is not DataType.Data:
140 keys_message = [repr(key)
for key
in overlapping_keys]
141 raise KeyError(f
"containersOnlyForMC would overwrite the following container keys: {', '.join(keys_message)}")
152 log.warning(
"Skipping unrecognised container prefix '%s' for DSID-filtering in OutputAnalysisConfig...", container)
154 if not filter_dsids (dsid_filters, config):
156 log.info(
"Skipping container prefix '%s' due to DSID filtering...", container)
159 var_container = var.split(
'.')[0].
replace(
'_NOSYS',
'').
replace(
'_%SYS%',
'')
160 if var_container == self.
containers[container]:
161 self.
vars.remove(var)
162 log.info(
"Skipping branch definition '%s' for excluded container %s...", var, var_container)
165 var_container = var.split(
'.')[0].
replace(
'_NOSYS',
'').
replace(
'_%SYS%',
'')
166 if var_container == self.
containers[container]:
168 log.info(
"Skipping MET branch definition '%s' for excluded container %s...", var, var_container)
171 var_container = var.split(
'.')[0].
replace(
'_NOSYS',
'').
replace(
'_%SYS%',
'')
172 if var_container == self.
containers[container]:
174 log.info(
"Skipping truth MET branch definition '%s' for excluded container %s...", var, var_container)
189 outputDict = config.getOutputVars (containerName)
190 for outputName
in outputDict :
191 outputConfig = copy.deepcopy (outputDict[outputName])
192 if containerName != outputConfig.origContainerName
or config.checkOutputContainer(containerName):
193 outputConfig.outputContainerName = containerName +
'_%SYS%'
195 outputConfig.outputContainerName = config.readName(containerName)
196 outputConfig.prefix = prefix
200 outputConfig.enabled =
True
201 outputConfigs[prefix + outputName] = outputConfig
204 for dsid, dsid_commands
in self.commandsOnlyForDSIDs.items():
205 if filter_dsids([dsid], config):
208 outputConfigsRename = {}
210 words = command.split (
' ')
211 if len (words) == 0 :
212 raise ValueError (
'received empty command for "commands" option')
213 optional = words[0] ==
'optional'
216 if words[0] ==
'enable' :
217 if len (words) != 2 :
218 raise ValueError (
'enable takes exactly one argument: ' + command)
220 for name
in outputConfigs :
221 if re.match (words[1], name) :
222 outputConfigs[name].enabled =
True
224 if not used
and not optional
and config.dataType()
is not DataType.Data:
225 raise KeyError (
'unknown branch pattern for enable: ' + words[1])
226 elif words[0] ==
'disable' :
227 if len (words) != 2 :
228 raise ValueError (
'disable takes exactly one argument: ' + command)
230 for name
in outputConfigs :
231 if re.match (words[1], name) :
232 outputConfigs[name].enabled =
False
234 if not used
and not optional
and config.dataType()
is not DataType.Data:
235 raise KeyError (
'unknown branch pattern for disable: ' + words[1])
236 elif words[0] ==
'rename' :
237 if len (words) != 3 :
238 raise ValueError (
'rename takes exactly two arguments: ' + command)
240 for name
in outputConfigs :
241 if re.match (words[1], name) :
242 new_name = re.sub (words[1], words[2], name)
243 outputConfigsRename[new_name] = copy.deepcopy(outputConfigs[name])
244 outputConfigs[name].enabled =
False
246 if not used
and not optional
and config.dataType()
is not DataType.Data:
247 raise KeyError (
'unknown branch pattern for rename: ' + words[1])
249 raise KeyError (
'unknown command for "commands" option: ' + words[0])
252 outputConfigs.update(outputConfigsRename)
256 autoTruthMetVars =
set()
257 for outputName, outputConfig
in outputConfigs.items():
258 if outputConfig.enabled :
259 if config.isMetContainer (outputConfig.origContainerName)
and outputConfig.prefix
not in self.
containersFullMET:
260 if "Truth" in outputConfig.origContainerName:
261 myVars = autoTruthMetVars
266 if outputConfig.noSys :
267 outputConfig.outputContainerName = outputConfig.outputContainerName.replace (
'%SYS%',
'NOSYS')
268 outputConfig.variableName = outputConfig.variableName.replace (
'%SYS%',
'NOSYS')
270 outputName +=
"_NOSYS"
272 outputName +=
'_%SYS%'
273 branchDecl = f
"{outputConfig.outputContainerName}.{outputConfig.variableName} -> {outputName}"
274 if outputConfig.auxType
is not None :
275 branchDecl += f
" type={outputConfig.auxType}"
276 if config.isMetContainer (outputConfig.origContainerName)
and outputConfig.prefix
not in self.
containersFullMET:
277 if "Truth" in outputConfig.origContainerName:
278 branchDecl += f
" metTerm={self.truthMetTermName}"
280 branchDecl += f
" metTerm={self.metTermName}"
281 myVars.add(branchDecl)
284 treeMaker = config.createAlgorithm(
'CP::TreeMakerAlg',
'TreeMaker' )
285 treeMaker.TreeName = self.treeName
286 treeMaker.RootStreamName = self.streamName
290 if self.
vars or autoVars:
293 if self.
metVars or autoMetVars:
300 if config.dataType()
is not DataType.Data
and (self.
truthMetVars or autoTruthMetVars):
301 userTruthMetVars = set ()
305 self.
createOutputAlgs(config,
'TruthMetNTupleMaker', userTruthMetVars | autoTruthMetVars)
307 treeFiller = config.createAlgorithm(
'CP::TreeFillerAlg',
'TreeFiller' )
308 treeFiller.TreeName = self.treeName
309 treeFiller.RootStreamName = self.streamName
315 For each container and for each selection, create a single pass variable in output NTuple,
316 which aggregates all the selections flag of the given selection. For example, this can include
317 pT, eta selections, some object ID selection, overlap removal, etc.
318 The goal is to have only one flag per object and working point in the output NTuple.
320 originalContainersSeen = []
323 containerName = config.getOutputContainerOrigin(outputContainerName)
324 if containerName
in originalContainersSeen:
327 originalContainersSeen.append(containerName)
330 if containerName ==
'EventInfo':
333 selectionNames = config.getSelectionNames(containerName)
334 for selectionName
in selectionNames:
336 if selectionName ==
'':
339 if self.skipRedundantSelectionFlags
and "outputSelect" in selectionName:
345 Schedule an algorithm to pick up all cut flags for a given selectionName.
346 The summary selection flag is written to output as selectionFlagPrefix_selectionName.
348 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
349 f
'ObjectSelectionSummary_{containerName}_{selectionName}')
350 selectionDecoration = f
'baselineSelection_{selectionName}_%SYS%'
351 alg.selectionDecoration = f
'{selectionDecoration},as_char'
352 alg.particles = config.readName (containerName)
353 alg.preselection = config.getFullSelection (containerName, selectionName)
354 config.addOutputVar (containerName, selectionDecoration, self.selectionFlagPrefix +
'_' + selectionName)