ATLAS Offline Software
Loading...
Searching...
No Matches
python.OutputAnalysisConfig.OutputAnalysisConfig Class Reference
Inheritance diagram for python.OutputAnalysisConfig.OutputAnalysisConfig:
Collaboration diagram for python.OutputAnalysisConfig.OutputAnalysisConfig:

Public Member Functions

 __init__ (self)
 instanceName (self)
 createOutputAlgs (self, config, name, vars)
 makeAlgs (self, config)
 createSelectionFlagBranches (self, config)
 makeSelectionSummaryAlg (self, config, containerName, selectionName)

Static Public Member Functions

 branchSortOrder (rule)

Public Attributes

bool validated = False
 containers = dict(self.containers)
 vars = set(self.vars)
 varsOnlyForMC = set(self.varsOnlyForMC)
 metVars = set(self.metVars)
 truthMetVars = set(self.truthMetVars)
 containersFullMET
 containersOnlyForMC
 containersOnlyForDSIDs
 storeSelectionFlags
 commands
 alwaysAddNosys
 metTermName
 truthMetTermName

Detailed Description

the ConfigBlock for the MET configuration

Definition at line 10 of file OutputAnalysisConfig.py.

Constructor & Destructor Documentation

◆ __init__()

python.OutputAnalysisConfig.OutputAnalysisConfig.__init__ ( self)

Definition at line 13 of file OutputAnalysisConfig.py.

13 def __init__ (self) :
14 super (OutputAnalysisConfig, self).__init__ ()
15 self.addOption ('postfix', '', type=str,
16 info="a postfix to apply to decorations and algorithm names. "
17 "Typically not needed here.")
18 self.addOption ('vars', [], type=None,
19 info="a list of mappings (list of strings) between containers and "
20 "decorations to output branches.")
21 self.addOption ('varsOnlyForMC', [], type=None,
22 info="same as `vars`, but for MC-only variables so as to avoid a "
23 "crash when running on data.")
24 self.addOption ('metVars', [], type=None,
25 info="a list of mappings (list of strings) between containers "
26 "and decorations to output branches. Specficially for MET "
27 "variables, where only the final MET term is retained.")
28 self.addOption ('truthMetVars', [], type=None,
29 info="a list of mappings (list of strings) between containers "
30 "and decorations to output branches for truth MET.")
31 self.addOption ('containers', {}, type=None,
32 info="a dictionary mapping prefixes (key) to container names "
33 "(values) to be used when saving to the output tree. Branches "
34 "are then of the form `prefix_decoration`.")
35 self.addOption ('containersFullMET', {}, type=None,
36 info="same as `containers`, but for MET containers that should be "
37 "saved with all terms (as opposed to just the final term). This "
38 "is useful for special studies. A container can appear both here and "
39 "in containers (with different prefixes).")
40 self.addOption ('containersOnlyForMC', {}, type=None,
41 info="same as `containers`, but for MC-only containers so as to avoid "
42 "a crash when running on data.")
43 self.addOption ('containersOnlyForDSIDs', {}, type=None,
44 info="specify which DSIDs are allowed to produce a given container. "
45 "This works like `onlyForDSIDs`: pass a list of DSIDs or regexps.")
46 self.addOption ('nonContainers', ['EventInfo'], type=None,
47 info="a list of container names that are not actual containers but should be treated as non-containers.")
48 self.addOption ('treeName', 'analysis', type=str,
49 info="name of the output TTree to save.")
50 self.addOption ('streamName', 'ANALYSIS', type=str,
51 info="name of the output stream to save the tree in.")
52 self.addOption ('metTermName', 'Final', type=str,
53 info="the name of the MET term to save, turning the MET "
54 "container into a single object.")
55 self.addOption ('truthMetTermName', 'NonInt', type=str,
56 info="the name of the truth MET term to save, turning the MET "
57 "container into a single object.")
58 self.addOption ('storeSelectionFlags', True, type=bool,
59 info="whether to store one branch for each object selection.")
60 self.addOption ('selectionFlagPrefix', 'select', type=str,
61 info="the prefix used when naming selection branches")
62 self.addOption ('commands', [], type=None,
63 info="a list of strings containing commands (regexp strings "
64 "prefaced by the keywords `enable` or `disable`) to turn on/off the "
65 "writing of branches to the output ntuple. If left empty, do not modify "
66 "the scheduled output branches.")
67 self.addOption ('commandsOnlyForDSIDs', {}, type=None,
68 info="a dictionary with individual DSIDs as keys, and a list of strings "
69 "like for the `commands` option as items. These `commands` will only be run "
70 "for the corresponding DSID.")
71 self.addOption ('alwaysAddNosys', False, type=bool,
72 info="If set to `True`, all branches will be given a systematics suffix, "
73 "even if they have no systematics (beyond the nominal).")
74 self.addOption ('skipRedundantSelectionFlags', True, type=bool,
75 info="remove the redundant `outputSelect` branches created by the `Thinning` step. "
76 "These could however be used to simplify downstream workflows, as in Easyjet.")
77 self.addOption ('defaultBasketSize', None, type=int,
78 info="default basket size for all branches in the output tree. "
79 "If not set (the default), no basket size is configured and ROOT's "
80 "default will be used.")
81 # helper to protect for second pass
82 self.validated = False
83

Member Function Documentation

◆ branchSortOrder()

python.OutputAnalysisConfig.OutputAnalysisConfig.branchSortOrder ( rule)
static

Definition at line 91 of file OutputAnalysisConfig.py.

91 def branchSortOrder (rule):
92 return rule.split('->')[1].strip()
93

◆ createOutputAlgs()

python.OutputAnalysisConfig.OutputAnalysisConfig.createOutputAlgs ( self,
config,
name,
vars )
A helper function to create output algorithm

Definition at line 94 of file OutputAnalysisConfig.py.

94 def createOutputAlgs (self, config, name, vars):
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)
101 branchList.sort(key=self.branchSortOrder)
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
107 return alg
108

◆ createSelectionFlagBranches()

python.OutputAnalysisConfig.OutputAnalysisConfig.createSelectionFlagBranches ( self,
config )
For each container and for each selection, create a single pass variable in output NTuple,
which aggregates all the selections flag of the given selection. For example, this can include
pT, eta selections, some object ID selection, overlap removal, etc.
The goal is to have only one flag per object and working point in the output NTuple.

Definition at line 301 of file OutputAnalysisConfig.py.

301 def createSelectionFlagBranches(self, config):
302 """
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.
307 """
308 originalContainersSeen = []
309 for prefix in self.containers.keys() :
310 outputContainerName = self.containers[prefix]
311 containerName = config.getOutputContainerOrigin(outputContainerName)
312 if containerName in originalContainersSeen:
313 continue
314 else:
315 originalContainersSeen.append(containerName)
316
317 # EventInfo is one obvious example of a container that has no object selections
318 if containerName == 'EventInfo':
319 continue
320
321 selectionNames = config.getSelectionNames(containerName)
322 for selectionName in selectionNames:
323 # skip default selection
324 if selectionName == '':
325 continue
326 # skip selection coming from the Thinning block
327 if self.skipRedundantSelectionFlags and "outputSelect" in selectionName:
328 continue
329 self.makeSelectionSummaryAlg(config, containerName, selectionName)
330

◆ instanceName()

python.OutputAnalysisConfig.OutputAnalysisConfig.instanceName ( self)
Return the instance name for this block

Definition at line 84 of file OutputAnalysisConfig.py.

84 def instanceName (self) :
85 """Return the instance name for this block"""
86 if self.postfix is not None and self.postfix != '':
87 return self.postfix
88 return self.treeName
89

◆ makeAlgs()

python.OutputAnalysisConfig.OutputAnalysisConfig.makeAlgs ( self,
config )

Definition at line 109 of file OutputAnalysisConfig.py.

109 def makeAlgs (self, config) :
110
111 log = logging.getLogger('OutputAnalysisConfig')
112
113 # do some transformations of the options we should only do once
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 # check for overlaps between containers and containersFullMET
123 overlapping_keys = set(self.containers.keys()).intersection(self.containersFullMET.keys())
124 if overlapping_keys:
125 # convert the set of overlapping keys to a list of strings for the message (represents the empty string too!)
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 # move items in self.containersFullMET to containers
129 self.containers.update(self.containersFullMET)
130
131 # merge the MC-specific branches and containers into the main list/dictionary only if we are not running on data
132 if config.dataType() is not DataType.Data:
133 self.vars |= self.varsOnlyForMC
134
135 # protect 'containers' against being overwritten
136 # find overlapping keys
137 overlapping_keys = set(self.containers.keys()).intersection(self.containersOnlyForMC.keys())
138 if overlapping_keys:
139 # convert the set of overlapping keys to a list of strings for the message (represents the empty string too!)
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 # move items in self.containersOnlyForMC to self.containers
144 self.containers.update(self.containersOnlyForMC)
145 # clear the dictionary to avoid overlapping key error during the second pass
146 self.containersOnlyForMC.clear()
147
148 # now filter the containers depending on DSIDs
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 # if current DSID is not allowed for this container, remove it
156 log.info("Skipping container prefix '%s' due to DSID filtering...", container)
157 # filter branches for validated containers
158 for var in set(self.vars): # make a copy of the list to avoid modifying it while iterating
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 # remove the container from the list at the end
164 self.containers.pop (container)
165 # clear the dictionary to avoid warnings during the second pass
166 self.containersOnlyForDSIDs.clear()
167
168 # at this point we are OK
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 # if the container is a MET container with all terms, we
186 # also need to write out the name of each MET term
187 if prefix in self.containersFullMET and outputConfig.variableName == 'name':
188 outputConfig.enabled = True
189 outputConfigs[prefix + outputName] = outputConfig
190
191 # check for DSID-specific commands
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:] # remove the 'optional' keyword
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 # update the outputConfigs with renamed branches
240 outputConfigs.update(outputConfigsRename)
241
242 autoVars = set()
243 autoMetVars = set()
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 # Add an ntuple dumper algorithm:
272 treeMaker = config.createAlgorithm( 'CP::TreeMakerAlg', 'TreeMaker' )
273 treeMaker.TreeName = self.treeName
274 treeMaker.RootStreamName = self.streamName
275 # the auto-flush setting still needs to be figured out
276 #treeMaker.TreeAutoFlush = 0
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
STL class.
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)
Definition hcg.cxx:310

◆ makeSelectionSummaryAlg()

python.OutputAnalysisConfig.OutputAnalysisConfig.makeSelectionSummaryAlg ( self,
config,
containerName,
selectionName )
Schedule an algorithm to pick up all cut flags for a given selectionName.
The summary selection flag is written to output as selectionFlagPrefix_selectionName.

Definition at line 331 of file OutputAnalysisConfig.py.

331 def makeSelectionSummaryAlg(self, config, containerName, selectionName):
332 """
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.
335 """
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)

Member Data Documentation

◆ alwaysAddNosys

python.OutputAnalysisConfig.OutputAnalysisConfig.alwaysAddNosys

Definition at line 257 of file OutputAnalysisConfig.py.

◆ commands

python.OutputAnalysisConfig.OutputAnalysisConfig.commands

Definition at line 197 of file OutputAnalysisConfig.py.

◆ containers

python.OutputAnalysisConfig.OutputAnalysisConfig.containers = dict(self.containers)

Definition at line 116 of file OutputAnalysisConfig.py.

◆ containersFullMET

python.OutputAnalysisConfig.OutputAnalysisConfig.containersFullMET

Definition at line 129 of file OutputAnalysisConfig.py.

◆ containersOnlyForDSIDs

python.OutputAnalysisConfig.OutputAnalysisConfig.containersOnlyForDSIDs

Definition at line 149 of file OutputAnalysisConfig.py.

◆ containersOnlyForMC

python.OutputAnalysisConfig.OutputAnalysisConfig.containersOnlyForMC

Definition at line 144 of file OutputAnalysisConfig.py.

◆ metTermName

python.OutputAnalysisConfig.OutputAnalysisConfig.metTermName

Definition at line 285 of file OutputAnalysisConfig.py.

◆ metVars

python.OutputAnalysisConfig.OutputAnalysisConfig.metVars = set(self.metVars)

Definition at line 119 of file OutputAnalysisConfig.py.

◆ storeSelectionFlags

python.OutputAnalysisConfig.OutputAnalysisConfig.storeSelectionFlags

Definition at line 171 of file OutputAnalysisConfig.py.

◆ truthMetTermName

python.OutputAnalysisConfig.OutputAnalysisConfig.truthMetTermName

Definition at line 292 of file OutputAnalysisConfig.py.

◆ truthMetVars

python.OutputAnalysisConfig.OutputAnalysisConfig.truthMetVars = set(self.truthMetVars)

Definition at line 120 of file OutputAnalysisConfig.py.

◆ validated

bool python.OutputAnalysisConfig.OutputAnalysisConfig.validated = False

Definition at line 82 of file OutputAnalysisConfig.py.

◆ vars

python.OutputAnalysisConfig.OutputAnalysisConfig.vars = set(self.vars)

Definition at line 117 of file OutputAnalysisConfig.py.

◆ varsOnlyForMC

python.OutputAnalysisConfig.OutputAnalysisConfig.varsOnlyForMC = set(self.varsOnlyForMC)

Definition at line 118 of file OutputAnalysisConfig.py.


The documentation for this class was generated from the following file: