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)
177 outputDict = config.getOutputVars (containerName)
178 for outputName
in outputDict :
179 outputConfig = copy.deepcopy (outputDict[outputName])
180 if containerName != outputConfig.origContainerName
or config.checkOutputContainer(containerName):
181 outputConfig.outputContainerName = containerName +
'_%SYS%'
183 outputConfig.outputContainerName = config.readName(containerName)
184 outputConfig.prefix = prefix
188 outputConfig.enabled =
True
189 outputConfigs[prefix + outputName] = outputConfig
192 for dsid, dsid_commands
in self.commandsOnlyForDSIDs.items():
193 if filter_dsids([dsid], config):
196 outputConfigsRename = {}
198 words = command.split (
' ')
199 if len (words) == 0 :
200 raise ValueError (
'received empty command for "commands" option')
201 optional = words[0] ==
'optional'
204 if words[0] ==
'enable' :
205 if len (words) != 2 :
206 raise ValueError (
'enable takes exactly one argument: ' + command)
208 for name
in outputConfigs :
209 if re.match (words[1], name) :
210 outputConfigs[name].enabled =
True
212 if not used
and not optional
and config.dataType()
is not DataType.Data:
213 raise KeyError (
'unknown branch pattern for enable: ' + words[1])
214 elif words[0] ==
'disable' :
215 if len (words) != 2 :
216 raise ValueError (
'disable takes exactly one argument: ' + command)
218 for name
in outputConfigs :
219 if re.match (words[1], name) :
220 outputConfigs[name].enabled =
False
222 if not used
and not optional
and config.dataType()
is not DataType.Data:
223 raise KeyError (
'unknown branch pattern for disable: ' + words[1])
224 elif words[0] ==
'rename' :
225 if len (words) != 3 :
226 raise ValueError (
'rename takes exactly two arguments: ' + command)
228 for name
in outputConfigs :
229 if re.match (words[1], name) :
230 new_name = re.sub (words[1], words[2], name)
231 outputConfigsRename[new_name] = copy.deepcopy(outputConfigs[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 rename: ' + words[1])
237 raise KeyError (
'unknown command for "commands" option: ' + words[0])
240 outputConfigs.update(outputConfigsRename)
244 autoTruthMetVars =
set()
245 for outputName, outputConfig
in outputConfigs.items():
246 if outputConfig.enabled :
247 if config.isMetContainer (outputConfig.origContainerName)
and outputConfig.prefix
not in self.
containersFullMET:
248 if "Truth" in outputConfig.origContainerName:
249 myVars = autoTruthMetVars
254 if outputConfig.noSys :
255 outputConfig.outputContainerName = outputConfig.outputContainerName.replace (
'%SYS%',
'NOSYS')
256 outputConfig.variableName = outputConfig.variableName.replace (
'%SYS%',
'NOSYS')
258 outputName +=
"_NOSYS"
260 outputName +=
'_%SYS%'
261 branchDecl = f
"{outputConfig.outputContainerName}.{outputConfig.variableName} -> {outputName}"
262 if outputConfig.auxType
is not None :
263 branchDecl += f
" type={outputConfig.auxType}"
264 if config.isMetContainer (outputConfig.origContainerName)
and outputConfig.prefix
not in self.
containersFullMET:
265 if "Truth" in outputConfig.origContainerName:
266 branchDecl += f
" metTerm={self.truthMetTermName}"
268 branchDecl += f
" metTerm={self.metTermName}"
269 myVars.add(branchDecl)
272 treeMaker = config.createAlgorithm(
'CP::TreeMakerAlg',
'TreeMaker' )
273 treeMaker.TreeName = self.treeName
274 treeMaker.RootStreamName = self.streamName
278 if self.
vars or autoVars:
281 if self.
metVars or autoMetVars:
288 if config.dataType()
is not DataType.Data
and (self.
truthMetVars or autoTruthMetVars):
289 userTruthMetVars = set ()
293 self.
createOutputAlgs(config,
'TruthMetNTupleMaker', userTruthMetVars | autoTruthMetVars)
295 treeFiller = config.createAlgorithm(
'CP::TreeFillerAlg',
'TreeFiller' )
296 treeFiller.TreeName = self.treeName
297 treeFiller.RootStreamName = self.streamName
303 For each container and for each selection, create a single pass variable in output NTuple,
304 which aggregates all the selections flag of the given selection. For example, this can include
305 pT, eta selections, some object ID selection, overlap removal, etc.
306 The goal is to have only one flag per object and working point in the output NTuple.
308 originalContainersSeen = []
311 containerName = config.getOutputContainerOrigin(outputContainerName)
312 if containerName
in originalContainersSeen:
315 originalContainersSeen.append(containerName)
318 if containerName ==
'EventInfo':
321 selectionNames = config.getSelectionNames(containerName)
322 for selectionName
in selectionNames:
324 if selectionName ==
'':
327 if self.skipRedundantSelectionFlags
and "outputSelect" in selectionName:
333 Schedule an algorithm to pick up all cut flags for a given selectionName.
334 The summary selection flag is written to output as selectionFlagPrefix_selectionName.
336 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
337 f
'ObjectSelectionSummary_{containerName}_{selectionName}')
338 selectionDecoration = f
'baselineSelection_{selectionName}_%SYS%'
339 alg.selectionDecoration = f
'{selectionDecoration},as_char'
340 alg.particles = config.readName (containerName)
341 alg.preselection = config.getFullSelection (containerName, selectionName)
342 config.addOutputVar (containerName, selectionDecoration, self.selectionFlagPrefix +
'_' + selectionName)