109 def makeAlgs (self, config) :
110
111 log = logging.getLogger('OutputAnalysisConfig')
112
113
114 if not self.validated:
115
116 self.containers = dict(self.containers)
117 self.vars =
set(self.vars)
118 self.varsOnlyForMC =
set(self.varsOnlyForMC)
119 self.metVars =
set(self.metVars)
120 self.truthMetVars =
set(self.truthMetVars)
121
122
123 overlapping_keys =
set(self.containers.keys()).
intersection(self.containersFullMET.keys())
124 if overlapping_keys:
125
126 keys_message = [repr(key) for key in overlapping_keys]
127 raise KeyError(f"containersFullMET would overwrite the following container keys: {', '.join(keys_message)}")
128
129 self.containers.update(self.containersFullMET)
130
131
132 if config.dataType() is not DataType.Data:
133 self.vars |= self.varsOnlyForMC
134
135
136
137 overlapping_keys =
set(self.containers.keys()).
intersection(self.containersOnlyForMC.keys())
138 if overlapping_keys:
139
140 keys_message = [repr(key) for key in overlapping_keys]
141 raise KeyError(f"containersOnlyForMC would overwrite the following container keys: {', '.join(keys_message)}")
142
143
144 self.containers.update(self.containersOnlyForMC)
145
146 self.containersOnlyForMC.clear()
147
148
149 if self.containersOnlyForDSIDs:
150 for container, dsid_filters in self.containersOnlyForDSIDs.items():
151 if container not in self.containers:
152 log.warning("Skipping unrecognised container prefix '%s' for DSID-filtering in OutputAnalysisConfig...", container)
153 continue
154 if not filter_dsids (dsid_filters, config):
155
156 log.info("Skipping container prefix '%s' due to DSID filtering...", container)
157
158 for var
in set(self.vars):
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)
163
164 self.containers.pop (container)
165
166 self.containersOnlyForDSIDs.clear()
167
168
169 self.validated = True
170
171 if self.storeSelectionFlags:
172 self.createSelectionFlagBranches(config)
173
174 outputConfigs = {}
175 for prefix in self.containers.keys() :
176 containerName = self.containers[prefix]
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%'
182 else:
183 outputConfig.outputContainerName = config.readName(containerName)
184 outputConfig.prefix = prefix
185
186
187 if prefix in self.containersFullMET and outputConfig.variableName == 'name':
188 outputConfig.enabled = True
189 outputConfigs[prefix + outputName] = outputConfig
190
191
192 for dsid, dsid_commands in self.commandsOnlyForDSIDs.items():
193 if filter_dsids([dsid], config):
194 self.commands += dsid_commands
195
196 outputConfigsRename = {}
197 for command in self.commands :
198 words = command.split (' ')
199 if len (words) == 0 :
200 raise ValueError ('received empty command for "commands" option')
201 optional = words[0] == 'optional'
202 if optional :
203 words = words[1:]
204 if words[0] == 'enable' :
205 if len (words) != 2 :
206 raise ValueError ('enable takes exactly one argument: ' + command)
207 used = False
208 for name in outputConfigs :
209 if re.match (words[1], name) :
210 outputConfigs[name].enabled = True
211 used = 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)
217 used = False
218 for name in outputConfigs :
219 if re.match (words[1], name) :
220 outputConfigs[name].enabled = False
221 used = True
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)
227 used = False
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
233 used = True
234 if not used and not optional and config.dataType() is not DataType.Data:
235 raise KeyError ('unknown branch pattern for rename: ' + words[1])
236 else :
237 raise KeyError ('unknown command for "commands" option: ' + words[0])
238
239
240 outputConfigs.update(outputConfigsRename)
241
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
250 else:
251 myVars = autoMetVars
252 else :
253 myVars = autoVars
254 if outputConfig.noSys :
255 outputConfig.outputContainerName = outputConfig.outputContainerName.replace ('%SYS%', 'NOSYS')
256 outputConfig.variableName = outputConfig.variableName.replace ('%SYS%', 'NOSYS')
257 if self.alwaysAddNosys :
258 outputName += "_NOSYS"
259 else :
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}"
267 else:
268 branchDecl += f" metTerm={self.metTermName}"
269 myVars.add(branchDecl)
270
271
272 treeMaker = config.createAlgorithm( 'CP::TreeMakerAlg', 'TreeMaker' )
273 treeMaker.TreeName = self.treeName
274 treeMaker.RootStreamName = self.streamName
275
276
277
278 if self.vars or autoVars:
279 self.createOutputAlgs(config, 'NTupleMaker', self.vars | autoVars)
280
281 if self.metVars or autoMetVars:
282 userMetVars = set ()
283 if self.metVars :
284 for var in self.metVars:
285 userMetVars.add(var + " metTerm=" + self.metTermName)
286 self.createOutputAlgs(config, 'MetNTupleMaker', userMetVars | autoMetVars)
287
288 if config.dataType() is not DataType.Data and (self.truthMetVars or autoTruthMetVars):
289 userTruthMetVars = set ()
290 if self.truthMetVars :
291 for var in self.truthMetVars:
292 userTruthMetVars.add(var + " metTerm=" + self.truthMetTermName)
293 self.createOutputAlgs(config, 'TruthMetNTupleMaker', userTruthMetVars | autoTruthMetVars)
294
295 treeFiller = config.createAlgorithm( 'CP::TreeFillerAlg', 'TreeFiller' )
296 treeFiller.TreeName = self.treeName
297 treeFiller.RootStreamName = self.streamName
298
299
300
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)