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, nonContainers, streamName)
 makeAlgs (self, config)
 createSelectionFlagBranches (self, config, containers)
 makeSelectionSummaryAlg (self, config, containerName, selectionName)

Static Public Member Functions

 branchSortOrder (rule)

Public Attributes

 containersFullMET
 containersOnlyForMC
 containersOnlyForDSIDs
 varsOnlyForDSIDs
 storeSelectionFlags
 alwaysAddNosys
 metTermName
 truthMetTermName
 splitBySelection
str outputFormat = 'RNTuple':

Detailed Description

the ConfigBlock for the output ntuple 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().__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=list,
19 info="a list of mappings (list of strings) between containers and "
20 "decorations to output branches.")
21 self.addOption ('varsOnlyForMC', [], type=list,
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=list,
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=list,
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=dict,
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=dict,
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=dict,
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=dict,
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 ('varsOnlyForDSIDs', {}, type=dict,
47 info="specify which DSIDs are allowed to produce a given variable. "
48 "Pass a dictionary with the variable definition as key and a list of DSIDs/regexps as value.")
49 self.addOption ('nonContainers', [], type=list,
50 info="a list of container names that are not actual containers but should be treated as non-containers.")
51 self.addOption ('treeName', 'analysis', type=str,
52 info="name of the output TTree (or RNTuple) to save.")
53 self.addOption ('streamName', 'ANALYSIS', type=str,
54 info="name of the output stream to save the tree in.")
55 self.addOption ('splitBySelection', False, type=bool,
56 info="write one tree per `EventSelection` instead of a single tree, each in "
57 "its own stream `<streamName>_<selectionName>` (i.e. its own output file) and "
58 "filled with the events passing that selection for at least one systematic. "
59 "With a single selection nothing changes.")
60 self.addOption ('metTermName', 'Final', type=str,
61 info="the name of the MET term to save, turning the MET "
62 "container into a single object.")
63 self.addOption ('truthMetTermName', 'NonInt', type=str,
64 info="the name of the truth MET term to save, turning the MET "
65 "container into a single object.")
66 self.addOption ('storeSelectionFlags', True, type=bool,
67 info="whether to store one branch for each object selection.")
68 self.addOption ('selectionFlagPrefix', 'select', type=str,
69 info="the prefix used when naming selection branches.")
70 self.addOption ('commands', [], type=list,
71 info="a list of strings containing commands (regexp strings "
72 "prefaced by the keywords `enable` or `disable`) to turn on/off the "
73 "writing of branches to the output ntuple. If left empty, do not modify "
74 "the scheduled output branches.")
75 self.addOption ('commandsOnlyForDSIDs', {}, type=dict,
76 info="a dictionary with individual DSIDs as keys, and a list of strings "
77 "like for the `commands` option as items. These `commands` will only be run "
78 "for the corresponding DSID.")
79 self.addOption ('alwaysAddNosys', False, type=bool,
80 info="If set to `True`, all branches will be given a systematics suffix, "
81 "even if they have no systematics (beyond the nominal).")
82 self.addOption ('skipRedundantSelectionFlags', True, type=bool,
83 info="remove the redundant 'outputSelect' branches created by the Thinning step. "
84 "These could however be used to simplify downstream workflows, as in Easyjet. "
85 "The default is True.")
86 self.addOption ('outputFormat', 'TTree', type=str,
87 info="The output format, `TTree` or `RNTuple`.")
88 self.addOption ('defaultBasketSize', None, type=int,
89 info="default basket size for all branches in the output tree. "
90 "If not set (the default), no basket size is configured and ROOT's "
91 "default will be used.")
92 self.addOption ('RNTupleApproxZippedClusterSize', 0, type=int,
93 info="approximate target compressed cluster size in bytes for RNTuple output (0 = ROOT default).")
94 self.addOption ('RNTupleMaxUnzippedClusterSize', 32 * 1024 * 1024, type=int,
95 info="maximum uncompressed cluster size in bytes for RNTuple output, bounds the write buffer memory (0 = ROOT default).")
96

Member Function Documentation

◆ branchSortOrder()

python.OutputAnalysisConfig.OutputAnalysisConfig.branchSortOrder ( rule)
static

Definition at line 104 of file OutputAnalysisConfig.py.

104 def branchSortOrder (rule):
105 return rule.split('->')[1].strip()
106

◆ createOutputAlgs()

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

Definition at line 107 of file OutputAnalysisConfig.py.

107 def createOutputAlgs (self, config, name, vars, nonContainers, streamName):
108 """A helper function to create output algorithm"""
109 alg = config.createAlgorithm('CP::AsgxAODNTupleMakerAlg', name)
110 alg.TreeName = self.treeName
111 alg.RootStreamName = streamName
112 alg.NonContainers = list(nonContainers)
113 branchList = list(vars)
114 branchList.sort(key=self.branchSortOrder)
115 branchList_nosys = [branch for branch in branchList if "%SYS%" not in branch]
116 branchList_sys = [branch for branch in branchList if "%SYS%" in branch]
117 alg.Branches = branchList_nosys + branchList_sys
118 if self.defaultBasketSize is not None:
119 alg.DefaultBasketSize = self.defaultBasketSize
120 return alg
121

◆ createSelectionFlagBranches()

python.OutputAnalysisConfig.OutputAnalysisConfig.createSelectionFlagBranches ( self,
config,
containers )
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 390 of file OutputAnalysisConfig.py.

390 def createSelectionFlagBranches(self, config, containers):
391 """
392 For each container and for each selection, create a single pass variable in output NTuple,
393 which aggregates all the selections flag of the given selection. For example, this can include
394 pT, eta selections, some object ID selection, overlap removal, etc.
395 The goal is to have only one flag per object and working point in the output NTuple.
396 """
397 originalContainersSeen = []
398 for prefix in containers.keys() :
399 outputContainerName = containers[prefix]
400 containerName = config.getOutputContainerOrigin(outputContainerName)
401 if containerName in originalContainersSeen:
402 continue
403 else:
404 originalContainersSeen.append(containerName)
405
406 # EventInfo is one obvious example of a container that has no object selections
407 if containerName == 'EventInfo':
408 continue
409
410 # Get the selection names, except the systematic-dependent version of the FTAG
411 # selection flag, as it's already saved as a systematic-independent output branch
412 selectionNames = config.getSelectionNames(containerName, excludeFrom={'ftag'})
413 for selectionName in selectionNames:
414 # skip default selection
415 if selectionName == '':
416 continue
417 # skip selection coming from the Thinning block
418 if self.skipRedundantSelectionFlags and "outputSelect" in selectionName:
419 continue
420 self.makeSelectionSummaryAlg(config, containerName, selectionName)
421

◆ instanceName()

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

Definition at line 97 of file OutputAnalysisConfig.py.

97 def instanceName (self) :
98 """Return the instance name for this block"""
99 if self.postfix is not None and self.postfix != '':
100 return self.postfix
101 return self.treeName
102

◆ makeAlgs()

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

Definition at line 122 of file OutputAnalysisConfig.py.

122 def makeAlgs (self, config) :
123
124 log = logging.getLogger('OutputAnalysisConfig')
125
126 containers = dict(self.containers)
127 branchVars = set(self.vars)
128 metVars = set(self.metVars)
129 truthMetVars = set(self.truthMetVars)
130 nonContainers = list(self.nonContainers)
131 commands = list(self.commands)
132
133 # check for overlaps between containers and containersFullMET
134 overlapping_keys = set(containers.keys()).intersection(self.containersFullMET.keys())
135 if overlapping_keys:
136 # convert the set of overlapping keys to a list of strings for the message (represents the empty string too!)
137 keys_message = [repr(key) for key in overlapping_keys]
138 raise KeyError(f"containersFullMET would overwrite the following container keys: {', '.join(keys_message)}")
139 # move items in self.containersFullMET to containers
140 containers.update(self.containersFullMET)
141
142 # merge the MC-specific branches and containers into the main list/dictionary only if we are not running on data
143 if config.dataType() is not DataType.Data:
144 branchVars |= set(self.varsOnlyForMC)
145
146 # protect 'containers' against being overwritten
147 # find overlapping keys
148 overlapping_keys = set(containers.keys()).intersection(self.containersOnlyForMC.keys())
149 if overlapping_keys:
150 # convert the set of overlapping keys to a list of strings for the message (represents the empty string too!)
151 keys_message = [repr(key) for key in overlapping_keys]
152 raise KeyError(f"containersOnlyForMC would overwrite the following container keys: {', '.join(keys_message)}")
153
154 # move items in self.containersOnlyForMC to containers
155 containers.update(self.containersOnlyForMC)
156
157 # now filter the containers depending on DSIDs
158 if self.containersOnlyForDSIDs:
159 for container, dsid_filters in self.containersOnlyForDSIDs.items():
160 if container not in containers:
161 log.warning("Skipping unrecognised container prefix '%s' for DSID-filtering in OutputAnalysisConfig...", container)
162 continue
163 if not filter_dsids (dsid_filters, config):
164 # if current DSID is not allowed for this container, remove it
165 log.info("Skipping container prefix '%s' due to DSID filtering...", container)
166 # filter branches for validated containers
167 for var in set(branchVars): # make a copy of the list to avoid modifying it while iterating
168 var_container = var.split('.')[0].replace('_NOSYS', '').replace('_%SYS%', '')
169 if var_container == containers[container]:
170 branchVars.remove(var)
171 log.info("Skipping branch definition '%s' for excluded container %s...", var, var_container)
172 # filter branches for MET variables
173 for var in set(metVars): # make a copy of the list to avoid modifying it while iterating
174 var_container = var.split('.')[0].replace('_NOSYS', '').replace('_%SYS%', '')
175 if var_container == containers[container]:
176 metVars.remove(var)
177 log.info("Skipping MET branch definition '%s' for excluded container %s...", var, var_container)
178 # filter branches for truth MET variables
179 for var in set(truthMetVars): # make a copy of the list to avoid modifying it while iterating
180 var_container = var.split('.')[0].replace('_NOSYS', '').replace('_%SYS%', '')
181 if var_container == containers[container]:
182 truthMetVars.remove(var)
183 log.info("Skipping truth MET branch definition '%s' for excluded container %s...", var, var_container)
184 # remove the container from the list at the end
185 containers.pop (container)
186 # Filter individual variables depending on DSIDs
187 if self.varsOnlyForDSIDs:
188 for var_pattern, dsid_filters in self.varsOnlyForDSIDs.items():
189 if not filter_dsids(dsid_filters, config):
190 # Remove matching variables from user-defined vars collections
191 for var in set(branchVars):
192 if var_pattern in var:
193 branchVars.remove(var)
194 log.info("Skipping branch definition '%s' due to variable-level DSID filtering...", var)
195 for var in set(metVars):
196 if var_pattern in var:
197 metVars.remove(var)
198 log.info("Skipping MET branch definition '%s' due to variable-level DSID filtering...", var)
199 for var in set(truthMetVars):
200 if var_pattern in var:
201 truthMetVars.remove(var)
202 log.info("Skipping truth MET branch definition '%s' due to variable-level DSID filtering...", var)
203
204
205 for prefix, container in containers.items():
206 origName = config.getOutputContainerOrigin(container)
207 if config.getContainerMeta(origName, "nonContainer", False):
208 if origName not in nonContainers:
209 nonContainers.append(origName)
210
211 if self.storeSelectionFlags:
212 self.createSelectionFlagBranches(config, containers)
213
214 outputConfigs = {}
215 for prefix in containers.keys() :
216 containerName = containers[prefix]
217 outputDict = config.getOutputVars (containerName)
218 for outputName in outputDict :
219 outputConfig = copy.deepcopy (outputDict[outputName])
220 outputConfig.outputContainerName = config.readName(containerName)
221 outputConfig.prefix = prefix
222 # if the container is a MET container with all terms, we
223 # also need to write out the name of each MET term
224 if prefix in self.containersFullMET and outputConfig.variableName == 'name':
225 outputConfig.enabled = True
226 outputConfigs[prefix + outputName] = outputConfig
227
228 # check for DSID-specific commands
229 for dsid, dsid_commands in self.commandsOnlyForDSIDs.items():
230 if filter_dsids([dsid], config):
231 commands += dsid_commands
232
233 outputConfigsRename = {}
234 for command in commands :
235 words = command.split (' ')
236 if len (words) == 0 :
237 raise ValueError ('received empty command for "commands" option')
238 optional = words[0] == 'optional'
239 if optional :
240 words = words[1:] # remove the 'optional' keyword
241 if words[0] == 'enable' :
242 if len (words) != 2 :
243 raise ValueError ('enable takes exactly one argument: ' + command)
244 used = False
245 for name in outputConfigs :
246 if re.match (words[1], name) :
247 outputConfigs[name].enabled = True
248 used = True
249 if not used and not optional and config.dataType() is not DataType.Data:
250 raise KeyError ('unknown branch pattern for enable: ' + words[1])
251 elif words[0] == 'disable' :
252 if len (words) != 2 :
253 raise ValueError ('disable takes exactly one argument: ' + command)
254 used = False
255 for name in outputConfigs :
256 if re.match (words[1], name) :
257 outputConfigs[name].enabled = False
258 used = True
259 if not used and not optional and config.dataType() is not DataType.Data:
260 raise KeyError ('unknown branch pattern for disable: ' + words[1])
261 elif words[0] == 'rename' :
262 if len (words) != 3 :
263 raise ValueError ('rename takes exactly two arguments: ' + command)
264 used = False
265 for name in outputConfigs :
266 if re.match (words[1], name) :
267 new_name = re.sub (words[1], words[2], name)
268 outputConfigsRename[new_name] = copy.deepcopy(outputConfigs[name])
269 outputConfigs[name].enabled = False
270 used = True
271 if not used and not optional and config.dataType() is not DataType.Data:
272 raise KeyError ('unknown branch pattern for rename: ' + words[1])
273 else :
274 raise KeyError ('unknown command for "commands" option: ' + words[0])
275
276 # update the outputConfigs with renamed branches
277 outputConfigs.update(outputConfigsRename)
278
279 autoVars = set()
280 autoMetVars = set()
281 autoTruthMetVars = set()
282 for outputName, outputConfig in outputConfigs.items():
283 if outputConfig.enabled :
284 if config.isMetContainer (outputConfig.origContainerName) and outputConfig.prefix not in self.containersFullMET:
285 if "Truth" in outputConfig.origContainerName:
286 myVars = autoTruthMetVars
287 else:
288 myVars = autoMetVars
289 else :
290 myVars = autoVars
291 if outputConfig.noSys :
292 outputConfig.outputContainerName = outputConfig.outputContainerName.replace ('%SYS%', 'NOSYS')
293 outputConfig.variableName = outputConfig.variableName.replace ('%SYS%', 'NOSYS')
294 if self.alwaysAddNosys :
295 outputName += "_NOSYS"
296 else :
297 outputName += '_%SYS%'
298 branchDecl = f"{outputConfig.outputContainerName}.{outputConfig.variableName} -> {outputName}"
299 if outputConfig.auxType is not None :
300 branchDecl += f" type={outputConfig.auxType}"
301 if config.isMetContainer (outputConfig.origContainerName) and outputConfig.prefix not in self.containersFullMET:
302 if "Truth" in outputConfig.origContainerName:
303 branchDecl += f" metTerm={self.truthMetTermName}"
304 else:
305 branchDecl += f" metTerm={self.metTermName}"
306 myVars.add(branchDecl)
307
308 # Unified branch collection for all output formats
309 allBranches = set()
310 allBranches |= branchVars
311 allBranches |= autoVars
312 # Add MET branches
313 userMetVars = set()
314 if metVars:
315 for var in metVars:
316 userMetVars.add(var + " metTerm=" + self.metTermName)
317 allBranches |= userMetVars
318 allBranches |= autoMetVars
319 # Add truth MET branches (for MC)
320 userTruthMetVars = set()
321 if config.dataType() is not DataType.Data:
322 if truthMetVars:
323 for var in truthMetVars:
324 userTruthMetVars.add(var + " metTerm=" + self.truthMetTermName)
325 allBranches |= userTruthMetVars
326 allBranches |= autoTruthMetVars
327
328 selections = []
329 if self.splitBySelection:
330 # sub-selections are not regions, same as in EventSelectionMerger
331 selections = [selection for selection in config.getContainerMeta('EventInfo', 'eventSelectionNames', failOnMiss=True)
332 if not selection.startswith('pass_SUB')]
333 # one (algorithm name suffix, stream, event selection) per output tree;
334 # with a single selection, keep the single tree as without splitting
335 outputs = [('', self.streamName, '')]
336 if len(selections) > 1:
337 outputs = []
338 for selection in selections:
339 name = selection.removeprefix('pass_').removesuffix('_%SYS%')
340 outputs.append((f'_{name}', f'{self.streamName}_{name}', f'{selection},as_char'))
341 for _, streamName, _ in outputs:
342 config.requestOutputStream(streamName)
343
344 # Create the output algorithm based on outputFormat
345 if self.outputFormat == 'RNTuple':
346 branchList = list(allBranches)
347 branchList.sort(key=self.branchSortOrder)
348 branchList_nosys = [branch for branch in branchList if "%SYS%" not in branch]
349 branchList_sys = [branch for branch in branchList if "%SYS%" in branch]
350
351 for suffix, streamName, eventSelection in outputs:
352 alg = config.createAlgorithm('CP::RNtupleTreeMakerAlg', 'RNtupleMaker' + suffix)
353 alg.TreeName = self.treeName
354 alg.RootStreamName = streamName
355 alg.OutputStreamName = streamName
356 alg.NonContainers = list(nonContainers)
357 alg.ApproxZippedClusterSize = self.RNTupleApproxZippedClusterSize
358 alg.MaxUnzippedClusterSize = self.RNTupleMaxUnzippedClusterSize
359 alg.Branches = branchList_nosys + branchList_sys
360 if eventSelection:
361 alg.EventSelection = eventSelection
362
363 return
364
365 for suffix, streamName, eventSelection in outputs:
366 # Add an ntuple dumper algorithm:
367 treeMaker = config.createAlgorithm( 'CP::TreeMakerAlg', 'TreeMaker' + suffix )
368 treeMaker.TreeName = self.treeName
369 treeMaker.RootStreamName = streamName
370 # the auto-flush setting still needs to be figured out
371 #treeMaker.TreeAutoFlush = 0
372
373 if branchVars or autoVars:
374 self.createOutputAlgs(config, 'NTupleMaker' + suffix, branchVars | autoVars, nonContainers, streamName)
375
376 if metVars or autoMetVars:
377 self.createOutputAlgs(config, 'MetNTupleMaker' + suffix, userMetVars | autoMetVars, nonContainers, streamName)
378
379 if config.dataType() is not DataType.Data and (truthMetVars or autoTruthMetVars):
380 self.createOutputAlgs(config, 'TruthMetNTupleMaker' + suffix, userTruthMetVars | autoTruthMetVars, nonContainers, streamName)
381
382 treeFiller = config.createAlgorithm( 'CP::TreeFillerAlg', 'TreeFiller' + suffix )
383 treeFiller.TreeName = self.treeName
384 treeFiller.RootStreamName = streamName
385 if eventSelection:
386 treeFiller.EventSelection = eventSelection
387
388
389
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:312

◆ 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 422 of file OutputAnalysisConfig.py.

422 def makeSelectionSummaryAlg(self, config, containerName, selectionName):
423 """
424 Schedule an algorithm to pick up all cut flags for a given selectionName.
425 The summary selection flag is written to output as selectionFlagPrefix_selectionName.
426 """
427 alg = config.createAlgorithm( 'CP::AsgSelectionAlg',
428 f'ObjectSelectionSummary_{containerName}_{selectionName}')
429 selectionDecoration = f'baselineSelection_{selectionName}_%SYS%'
430 alg.selectionDecoration = f'{selectionDecoration},as_char'
431 alg.particles = config.readName (containerName)
432 alg.preselection = config.getFullSelection (containerName, selectionName)
433 config.addOutputVar (containerName, selectionDecoration, self.selectionFlagPrefix + '_' + selectionName, auxType='char')

Member Data Documentation

◆ alwaysAddNosys

python.OutputAnalysisConfig.OutputAnalysisConfig.alwaysAddNosys

Definition at line 294 of file OutputAnalysisConfig.py.

◆ containersFullMET

python.OutputAnalysisConfig.OutputAnalysisConfig.containersFullMET

Definition at line 140 of file OutputAnalysisConfig.py.

◆ containersOnlyForDSIDs

python.OutputAnalysisConfig.OutputAnalysisConfig.containersOnlyForDSIDs

Definition at line 158 of file OutputAnalysisConfig.py.

◆ containersOnlyForMC

python.OutputAnalysisConfig.OutputAnalysisConfig.containersOnlyForMC

Definition at line 155 of file OutputAnalysisConfig.py.

◆ metTermName

python.OutputAnalysisConfig.OutputAnalysisConfig.metTermName

Definition at line 316 of file OutputAnalysisConfig.py.

◆ outputFormat

str python.OutputAnalysisConfig.OutputAnalysisConfig.outputFormat = 'RNTuple':

Definition at line 345 of file OutputAnalysisConfig.py.

◆ splitBySelection

python.OutputAnalysisConfig.OutputAnalysisConfig.splitBySelection

Definition at line 329 of file OutputAnalysisConfig.py.

◆ storeSelectionFlags

python.OutputAnalysisConfig.OutputAnalysisConfig.storeSelectionFlags

Definition at line 211 of file OutputAnalysisConfig.py.

◆ truthMetTermName

python.OutputAnalysisConfig.OutputAnalysisConfig.truthMetTermName

Definition at line 324 of file OutputAnalysisConfig.py.

◆ varsOnlyForDSIDs

python.OutputAnalysisConfig.OutputAnalysisConfig.varsOnlyForDSIDs

Definition at line 187 of file OutputAnalysisConfig.py.


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