106 def makeAlgs (self, config) :
107
108 log = logging.getLogger('OutputAnalysisConfig')
109
110
111 if not self.validated:
112
113 self.containers = dict(self.containers)
114 self.vars =
set(self.vars)
115 self.varsOnlyForMC =
set(self.varsOnlyForMC)
116 self.metVars =
set(self.metVars)
117 self.truthMetVars =
set(self.truthMetVars)
118
119
120 overlapping_keys =
set(self.containers.keys()).
intersection(self.containersFullMET.keys())
121 if overlapping_keys:
122
123 keys_message = [repr(key) for key in overlapping_keys]
124 raise KeyError(f"containersFullMET would overwrite the following container keys: {', '.join(keys_message)}")
125
126 self.containers.update(self.containersFullMET)
127
128
129 if config.dataType() is not DataType.Data:
130 self.vars |= self.varsOnlyForMC
131
132
133
134 overlapping_keys =
set(self.containers.keys()).
intersection(self.containersOnlyForMC.keys())
135 if overlapping_keys:
136
137 keys_message = [repr(key) for key in overlapping_keys]
138 raise KeyError(f"containersOnlyForMC would overwrite the following container keys: {', '.join(keys_message)}")
139
140
141 self.containers.update(self.containersOnlyForMC)
142
143 self.containersOnlyForMC.clear()
144
145
146 if self.containersOnlyForDSIDs:
147 for container, dsid_filters in self.containersOnlyForDSIDs.items():
148 if container not in self.containers:
149 log.warning("Skipping unrecognised container prefix '%s' for DSID-filtering in OutputAnalysisConfig...", container)
150 continue
151 if not filter_dsids (dsid_filters, config):
152
153 log.info("Skipping container prefix '%s' due to DSID filtering...", container)
154
155 for var
in set(self.vars):
156 var_container = var.split(
'.')[0].
replace(
'_NOSYS',
'').
replace(
'_%SYS%',
'')
157 if var_container == self.containers[container]:
158 self.vars.remove(var)
159 log.info("Skipping branch definition '%s' for excluded container %s...", var, var_container)
160
161 self.containers.pop (container)
162
163 self.containersOnlyForDSIDs.clear()
164
165
166 self.validated = True
167
168 if self.storeSelectionFlags:
169 self.createSelectionFlagBranches(config)
170
171 outputConfigs = {}
172 for prefix in self.containers.keys() :
173 containerName = self.containers[prefix]
174 outputDict = config.getOutputVars (containerName)
175 for outputName in outputDict :
176 outputConfig = copy.deepcopy (outputDict[outputName])
177 if containerName != outputConfig.origContainerName or config.checkOutputContainer(containerName):
178 outputConfig.outputContainerName = containerName + '_%SYS%'
179 else:
180 outputConfig.outputContainerName = config.readName(containerName)
181 outputConfig.prefix = prefix
182
183
184 if prefix in self.containersFullMET and outputConfig.variableName == 'name':
185 outputConfig.enabled = True
186 outputConfigs[prefix + outputName] = outputConfig
187
188
189 for dsid, dsid_commands in self.commandsOnlyForDSIDs.items():
190 if filter_dsids([dsid], config):
191 self.commands += dsid_commands
192
193 outputConfigsRename = {}
194 for command in self.commands :
195 words = command.split (' ')
196 if len (words) == 0 :
197 raise ValueError ('received empty command for "commands" option')
198 optional = words[0] == 'optional'
199 if optional :
200 words = words[1:]
201 if words[0] == 'enable' :
202 if len (words) != 2 :
203 raise ValueError ('enable takes exactly one argument: ' + command)
204 used = False
205 for name in outputConfigs :
206 if re.match (words[1], name) :
207 outputConfigs[name].enabled = True
208 used = True
209 if not used and not optional and config.dataType() is not DataType.Data:
210 raise KeyError ('unknown branch pattern for enable: ' + words[1])
211 elif words[0] == 'disable' :
212 if len (words) != 2 :
213 raise ValueError ('disable takes exactly one argument: ' + command)
214 used = False
215 for name in outputConfigs :
216 if re.match (words[1], name) :
217 outputConfigs[name].enabled = False
218 used = True
219 if not used and not optional and config.dataType() is not DataType.Data:
220 raise KeyError ('unknown branch pattern for disable: ' + words[1])
221 elif words[0] == 'rename' :
222 if len (words) != 3 :
223 raise ValueError ('rename takes exactly two arguments: ' + command)
224 used = False
225 for name in outputConfigs :
226 if re.match (words[1], name) :
227 new_name = re.sub (words[1], words[2], name)
228 outputConfigsRename[new_name] = copy.deepcopy(outputConfigs[name])
229 outputConfigs[name].enabled = False
230 used = True
231 if not used and not optional and config.dataType() is not DataType.Data:
232 raise KeyError ('unknown branch pattern for rename: ' + words[1])
233 else :
234 raise KeyError ('unknown command for "commands" option: ' + words[0])
235
236
237 outputConfigs.update(outputConfigsRename)
238
241 autoTruthMetVars =
set()
242 for outputName, outputConfig in outputConfigs.items():
243 if outputConfig.enabled :
244 if config.isMetContainer (outputConfig.origContainerName) and outputConfig.prefix not in self.containersFullMET:
245 if "Truth" in outputConfig.origContainerName:
246 myVars = autoTruthMetVars
247 else:
248 myVars = autoMetVars
249 else :
250 myVars = autoVars
251 if outputConfig.noSys :
252 outputConfig.outputContainerName = outputConfig.outputContainerName.replace ('%SYS%', 'NOSYS')
253 outputConfig.variableName = outputConfig.variableName.replace ('%SYS%', 'NOSYS')
254 if self.alwaysAddNosys :
255 outputName += "_NOSYS"
256 else :
257 outputName += '_%SYS%'
258 myVars.add(f"{outputConfig.outputContainerName}.{outputConfig.variableName} -> {outputName}")
259
260
261 treeMaker = config.createAlgorithm( 'CP::TreeMakerAlg', 'TreeMaker' )
262 treeMaker.TreeName = self.treeName
263 treeMaker.RootStreamName = self.streamName
264
265
266
267 if self.vars or autoVars:
268 ntupleMaker = self.createOutputAlgs(config, 'NTupleMaker', self.vars | autoVars)
269
270 if self.metVars or autoMetVars:
271 ntupleMaker = self.createOutputAlgs(config, 'MetNTupleMaker', self.metVars | autoMetVars, isMet=True)
272 ntupleMaker.termName = self.metTermName
273
274 if config.dataType() is not DataType.Data and (self.truthMetVars or autoTruthMetVars):
275 ntupleMaker = self.createOutputAlgs(config, 'TruthMetNTupleMaker', self.truthMetVars | autoTruthMetVars, isMet=True)
276 ntupleMaker.termName = self.truthMetTermName
277
278 treeFiller = config.createAlgorithm( 'CP::TreeFillerAlg', 'TreeFiller' )
279 treeFiller.TreeName = self.treeName
280 treeFiller.RootStreamName = self.streamName
281
282
283
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
std::string replace(std::string s, const std::string &s2, const std::string &s3)