4 from AnalysisAlgorithmsConfig.ConfigBlock
import ConfigBlock
5 from AnalysisAlgorithmsConfig.ConfigAccumulator
import DataType
9 """the ConfigBlock for the MET configuration"""
12 super (OutputAnalysisConfig, self).__init__ ()
13 self.addOption (
'postfix',
'', type=str,
14 info=
"a postfix to apply to decorations and algorithm names. "
15 "Typically not needed here.")
16 self.addOption (
'vars', [], type=
None,
17 info=
"a list of mappings (list of strings) between containers and "
18 "decorations to output branches. The default is [] (empty list).")
19 self.addOption (
'varsOnlyForMC', [], type=
None,
20 info=
"same as vars, but for MC-only variables so as to avoid a "
21 "crash when running on data. The default is [] (empty list).")
22 self.addOption (
'metVars', [], type=
None,
23 info=
"a list of mappings (list of strings) between containers "
24 "and decorations to output branches. Specficially for MET "
25 "variables, where only the final MET term is retained. "
26 "The default is [] (empty list).")
27 self.addOption (
'containers', {}, type=
None,
28 info=
"a dictionary mapping prefixes (key) to container names "
29 "(values) to be used when saving to the output tree. Branches "
30 "are then of the form prefix_decoration.")
32 self.addOption (
'containersOnlyForMC', [], type=
None,
34 self.addOption (
'treeName',
'analysis', type=str,
35 info=
"name of the output TTree to save. The default is analysis.")
36 self.addOption (
'metTermName',
'Final', type=str,
37 info=
"the name (string) of the MET term to save, turning the MET "
38 "container into a single object. The default is 'Final'.")
40 self.addOption (
'storeSelectionFlags',
True, type=bool,
43 self.addOption (
'selectionFlagPrefix',
'select', type=str,
45 self.addOption (
'commands', [], type=
None,
46 info=
"a list of strings containing commands (regexp strings "
47 "prefaced by the keywords enable or disable) to turn on/off the "
48 "writing of branches to the output ntuple. The default is None "
49 "(no modification to the scheduled output branches).")
50 self.addOption (
'alwaysAddNosys',
False, type=bool,
51 info=
"If set to True, all branches will be given a systematics suffix, "
52 "even if they have no systematics (beyond the nominal).")
60 if config.dataType()
is not DataType.Data:
62 self.containers.
update(self.containersOnlyForMC)
64 if self.storeSelectionFlags:
68 for prefix
in self.containers.
keys() :
69 containerName = self.containers[prefix]
70 outputDict = config.getOutputVars (containerName)
71 for outputName
in outputDict :
72 outputConfig = copy.deepcopy (outputDict[outputName])
73 if containerName ==
'EventInfo' :
74 outputConfig.outputContainerName = outputConfig.origContainerName
75 elif outputConfig.outputContainerName != outputConfig.origContainerName :
76 outputConfig.outputContainerName = containerName +
'_%SYS%'
78 outputConfig.outputContainerName = config.readName (containerName)
79 outputConfigs[prefix + outputName] = outputConfig
81 for command
in self.commands :
82 words = command.split (
' ')
84 raise ValueError (
'received empty command for "commands" option')
85 if words[0] ==
'enable' :
87 raise ValueError (
'enable takes exactly one argument: ' + command)
89 for name
in outputConfigs :
90 if re.match (words[1], name) :
91 outputConfigs[name].enabled =
True
93 if not used
and config.dataType()
is not DataType.Data:
94 raise KeyError (
'unknown branch pattern for enable: ' + words[1])
95 elif words[0] ==
'disable' :
97 raise ValueError (
'disable takes exactly one argument: ' + command)
99 for name
in outputConfigs :
100 if re.match (words[1], name) :
101 outputConfigs[name].enabled =
False
103 if not used
and config.dataType()
is not DataType.Data:
104 raise KeyError (
'unknown branch pattern for disable: ' + words[1])
106 raise KeyError (
'unknown command for "commands" option: ' + words[0])
110 for outputName
in outputConfigs :
111 outputConfig = outputConfigs[outputName]
112 if outputConfig.enabled :
113 if config.isMetContainer (outputConfig.origContainerName) :
117 if outputConfig.noSys :
118 outputConfig.outputContainerName = outputConfig.outputContainerName.replace (
'%SYS%',
'NOSYS')
119 outputConfig.variableName = outputConfig.variableName.replace (
'%SYS%',
'NOSYS')
120 if self.alwaysAddNosys :
121 outputName +=
"_NOSYS"
123 outputName +=
'_%SYS%'
124 myVars += [outputConfig.outputContainerName +
'.' + outputConfig.variableName +
' -> ' + outputName]
126 postfix = self.postfix
129 treeMaker = config.createAlgorithm(
'CP::TreeMakerAlg',
'TreeMaker' + postfix )
130 treeMaker.TreeName = self.treeName
134 if len (self.
vars) + len (autoVars) :
135 ntupleMaker = config.createAlgorithm(
'CP::AsgxAODNTupleMakerAlg',
'NTupleMaker' + postfix )
136 ntupleMaker.TreeName = self.treeName
139 branchList_nosys = [branch
for branch
in branchList
if "%SYS%" not in branch]
140 branchList_sys = [branch
for branch
in branchList
if "%SYS%" in branch]
141 ntupleMaker.Branches = branchList_nosys + branchList_sys
144 if len (self.metVars) + len (autoMetVars) > 0:
145 ntupleMaker = config.createAlgorithm(
'CP::AsgxAODMetNTupleMakerAlg',
'MetNTupleMaker' + postfix )
146 ntupleMaker.TreeName = self.treeName
147 branchList = self.metVars + autoMetVars
149 branchList_nosys = [branch
for branch
in branchList
if "%SYS%" not in branch]
150 branchList_sys = [branch
for branch
in branchList
if "%SYS%" in branch]
151 ntupleMaker.Branches = branchList_nosys + branchList_sys
152 ntupleMaker.termName = self.metTermName
155 treeFiller = config.createAlgorithm(
'CP::TreeFillerAlg',
'TreeFiller' + postfix )
156 treeFiller.TreeName = self.treeName
161 For each container and for each selection, create a single pass variable in output NTuple,
162 which aggregates all the selections flag of the given selection. For example, this can include
163 pT, eta selections, some object ID selection, overlap removal, etc.
164 The goal is to have only one flag per object and working point in the output NTuple.
166 for prefix
in self.containers.
keys() :
167 outputContainerName = self.containers[prefix]
168 containerName = config.getOutputContainerOrigin(outputContainerName)
171 if containerName ==
'EventInfo':
174 selectionNames = config.getSelectionNames(containerName)
175 for selectionName
in selectionNames:
177 if selectionName ==
'':
183 Schedule an algorithm to pick up all cut flags for a given selectionName.
184 The summary selection flag is written to output as selectionFlagPrefix_selectionName.
186 alg = config.createAlgorithm(
'CP::AsgSelectionAlg',
187 f
'ObjectSelectionSummary_{containerName}_{selectionName}')
188 selectionDecoration = f
'baselineSelection_{selectionName}_%SYS%'
189 alg.selectionDecoration = f
'{selectionDecoration},as_char'
190 alg.particles = config.readName (containerName)
191 alg.preselection = config.getFullSelection (containerName, selectionName)
192 config.addOutputVar (containerName, selectionDecoration, self.selectionFlagPrefix +
'_' + selectionName)