ATLAS Offline Software
Public Member Functions | Private Member Functions | Private Attributes | List of all members
python.ConfigText.TextConfig Class Reference
Inheritance diagram for python.ConfigText.TextConfig:
Collaboration diagram for python.ConfigText.TextConfig:

Public Member Functions

def __init__ (self, yamlPath=None, *config=None, addDefaultBlocks=True)
 
def setConfig (self, config)
 
def preprocessConfig (self, config, algs)
 
def cleanupPlaceholders (self, config)
 
def loadConfig (self, yamlPath=None, *configDict=None)
 
def printConfig (self, sort=False, jsonFormat=False)
 
def saveYaml (self, filePath='config.yaml', default_flow_style=False, **kwargs)
 
def addBlock (self, name, **kwargs)
 
def setOptions (self, **kwargs)
 
def configure (self)
 

Private Member Functions

def _addNewConfigBlocks (self, modulePath, functionName, algName, defaults=None, pos=None, superBlocks=None)
 
def _configureAlg (self, block, blockConfig, configSeq=None, containerName=None, extraOptions=None)
 

Private Attributes

 _config
 
 __loadedYaml
 
 _last
 

Detailed Description

Definition at line 38 of file ConfigText.py.

Constructor & Destructor Documentation

◆ __init__()

def python.ConfigText.TextConfig.__init__ (   self,
  yamlPath = None,
config = None,
  addDefaultBlocks = True 
)

Definition at line 39 of file ConfigText.py.

39  def __init__(self, yamlPath=None, *, config=None, addDefaultBlocks=True):
40  super().__init__(addDefaultBlocks=False)
41 
42  if yamlPath and config:
43  raise ValueError("Cannot specify both yamlPath and config. Use one or the other.")
44 
45  # Block to add new blocks to this object
46  self.addAlgConfigBlock(algName="AddConfigBlocks", alg=self._addNewConfigBlocks,
47  defaults={'self': self})
48  # add default blocks
49  if addDefaultBlocks:
50  self.addDefaultAlgs()
51  # load yaml
52  self._config = {}
53  # do not allow for loading multiple yaml files
54  self.__loadedYaml = False
55  if yamlPath is not None or config is not None:
56  self.loadConfig(yamlPath, configDict=config)
57  # last is used for setOptionValue when using addBlock
58  self._last = None
59 
60 

Member Function Documentation

◆ _addNewConfigBlocks()

def python.ConfigText.TextConfig._addNewConfigBlocks (   self,
  modulePath,
  functionName,
  algName,
  defaults = None,
  pos = None,
  superBlocks = None 
)
private
Load <functionName> from <modulePath>

Definition at line 240 of file ConfigText.py.

240  def _addNewConfigBlocks(self, modulePath, functionName,
241  algName, defaults=None, pos=None, superBlocks=None):
242  """
243  Load <functionName> from <modulePath>
244  """
245  try:
246  module = importlib.import_module(modulePath)
247  fxn = getattr(module, functionName)
248  except ModuleNotFoundError as e:
249  raise ModuleNotFoundError(f"{e}\nFailed to load {functionName} from {modulePath}")
250  else:
251  sys.modules[functionName] = fxn
252  # add new algorithm to available algorithms
253  self.addAlgConfigBlock(algName=algName, alg=fxn,
254  defaults=defaults,
255  superBlocks=superBlocks,
256  pos=pos)
257  return
258 
259 

◆ _configureAlg()

def python.ConfigText.TextConfig._configureAlg (   self,
  block,
  blockConfig,
  configSeq = None,
  containerName = None,
  extraOptions = None 
)
private

Definition at line 260 of file ConfigText.py.

260  def _configureAlg(self, block, blockConfig, configSeq=None, containerName=None,
261  extraOptions=None):
262  if not isinstance(blockConfig, list):
263  blockConfig = [blockConfig]
264 
265  for options in blockConfig:
266  # Special case: propogate containerName down to subAlgs
267  if 'containerName' in options:
268  containerName = options['containerName']
269  elif containerName is not None and 'containerName' not in options:
270  options['containerName'] = containerName
271  # will check which options are associated alg and not options
272  logCPAlgTextCfg.info(f"Configuring {block.algName}")
273  seq, funcOpts = block.makeConfig(options)
274  if not seq._blocks:
275  continue
276  algOpts = seq.setOptions(options)
277  # If containerName was not set explicitly, we can now retrieve
278  # its default value
279  if containerName is None:
280  for opt in algOpts:
281  if 'name' in opt and opt['name'] == 'containerName':
282  containerName = opt.get('value', None)
283  break # Exit the loop as we've found the key
284 
285  if configSeq is not None:
286  configSeq += seq
287 
288  # propagate special extra options to subalgs
289  if extraOptions is None:
290  extraOptionsList = ["skipOnData", "skipOnMC", "onlyForDSIDs"]
291  for i in algOpts:
292  if i['name'] in extraOptionsList and i['defaultValue'] != i['value']:
293  if extraOptions is None:
294  extraOptions = {}
295  extraOptions[i['name']] = i['value']
296  else:
297  algOpts = seq.setOptions(extraOptions.copy())
298 
299  # check to see if there are unused parameters
300  algOpts = [i['name'] for i in algOpts]
301  expectedOptions = set(funcOpts)
302  expectedOptions |= set(algOpts)
303  expectedOptions |= set(block.subAlgs)
304 
305  difference = set(options.keys()) - expectedOptions
306  difference.discard('__placeholder__')
307  if difference:
308  difference = "\n".join(difference)
309  raise ValueError(f"There are options set that are not used for "
310  f"{block.algName}:\n{difference}\n"
311  "Please check your configuration.")
312 
313  # check for sub-blocks and call this function recursively
314  for alg in self._order.get(block.algName, []):
315  if alg in options:
316  subAlg = block.subAlgs[alg]
317  self._configureAlg(subAlg, options[alg], configSeq, containerName, extraOptions)
318  return configSeq
319 
320 

◆ addBlock()

def python.ConfigText.TextConfig.addBlock (   self,
  name,
**  kwargs 
)
Create entry into dictionary representing the text configuration

Definition at line 177 of file ConfigText.py.

177  def addBlock(self, name, **kwargs):
178  """
179  Create entry into dictionary representing the text configuration
180  """
181  def setEntry(name, config, opts):
182  if '.' not in name:
183  if name not in config:
184  config[name] = opts
185  elif isinstance(config[name], list):
186  config[name].append(opts)
187  else:
188  config[name] = [config[name], opts]
189  # set last added block for setOptionValue
190  self._last = opts
191  else:
192  name, rest = name[:name.index('.')], name[name.index('.') + 1:]
193  config = config[name]
194  if isinstance(config, list):
195  config = config[-1]
196  setEntry(rest, config, opts)
197  return
198  setEntry(name, self._config, dict(kwargs))
199  return
200 
201 

◆ cleanupPlaceholders()

def python.ConfigText.TextConfig.cleanupPlaceholders (   self,
  config 
)
Remove placeholder markers after initialization.

Definition at line 93 of file ConfigText.py.

93  def cleanupPlaceholders(self, config):
94  """
95  Remove placeholder markers after initialization.
96  """
97  if not isinstance(config, dict):
98  return
99  if "__placeholder__" in config:
100  del config["__placeholder__"]
101  for key, value in config.items():
102  self.cleanupPlaceholders(value)
103 

◆ configure()

def python.ConfigText.TextConfig.configure (   self)
Process YAML configuration file and confgure added algorithms.

Definition at line 213 of file ConfigText.py.

213  def configure(self):
214  """Process YAML configuration file and confgure added algorithms."""
215  # make sure all blocks in yaml file are added (otherwise they would be ignored)
216  for blockName in self._config:
217  if blockName not in self._order[self.ROOTNAME]:
218  if not blockName:
219  blockName = list(self._config[blockName].keys())[0]
220  raise ValueError(f"Unkown block {blockName} in yaml file")
221 
222  # configure blocks
223  configSeq = ConfigSequence()
224  for blockName in self._order[self.ROOTNAME]:
225  if blockName == "AddConfigBlocks":
226  continue
227 
228  assert blockName in self._algs
229 
230  # order only applies to root blocks
231  if blockName in self._config:
232  blockConfig = self._config[blockName]
233  alg = self._algs[blockName]
234  self._configureAlg(alg, blockConfig, configSeq)
235  else:
236  continue
237  return configSeq
238 
239 

◆ loadConfig()

def python.ConfigText.TextConfig.loadConfig (   self,
  yamlPath = None,
configDict = None 
)
read a YAML file. Will combine with any config blocks added using python

Definition at line 104 of file ConfigText.py.

104  def loadConfig(self, yamlPath=None, *, configDict=None):
105  """
106  read a YAML file. Will combine with any config blocks added using python
107  """
108  if self.__loadedYaml or isinstance(yamlPath, list):
109  raise NotImplementedError("Mering multiple yaml files is not implemented.")
110  self.__loadedYaml = True
111 
112  def merge(config, algs, path=''):
113  """Add to config block-by-block"""
114  if not isinstance(config, list):
115  config = [config]
116  # loop over list of blocks with same block name
117  for blocks in config:
118  # deal with case where empty dict is config
119  if blocks == {} and path:
120  self.addBlock(path)
121  return
122  # remove any subBlocks from block config
123  subBlocks = {}
124  for blockName in algs:
125  if blockName in blocks:
126  subBlocks[blockName] = blocks.pop(blockName)
127  # anything left should be a block and it's configuration
128  if blocks:
129  self.addBlock(path, **blocks)
130  # add in any subBlocks
131  for subName, subBlock in subBlocks.items():
132  newPath = f'{path}.{subName}' if path else subName
133  merge(subBlock, algs[subName].subAlgs, newPath)
134  return
135 
136  logCPAlgTextCfg.info(f'loading {yamlPath}')
137  if configDict is not None:
138  # if configDict is provided, use it directly
139  config = configDict
140  else:
141  config = readYaml(yamlPath)
142  # check if blocks are defined in yaml file
143  if "AddConfigBlocks" in config:
144  self._configureAlg(self._algs["AddConfigBlocks"], config["AddConfigBlocks"])
145 
146  # Preprocess the configuration dictionary (see !76767)
147  self.preprocessConfig(config, self._algs)
148 
149  merge(config, self._algs)
150 
151  # Cleanup placeholders (see !76767)
152  self.cleanupPlaceholders(config)
153 
154  return
155 
156 

◆ preprocessConfig()

def python.ConfigText.TextConfig.preprocessConfig (   self,
  config,
  algs 
)
Preprocess the configuration dictionary.
Ensure blocks with only sub-blocks are initialized with an empty dictionary.

Definition at line 69 of file ConfigText.py.

69  def preprocessConfig(self, config, algs):
70  """
71  Preprocess the configuration dictionary.
72  Ensure blocks with only sub-blocks are initialized with an empty dictionary.
73  """
74  def processNode(node, algs):
75  if not isinstance(node, dict):
76  return # Base case: not a dictionary
77  for blockName, blockContent in list(node.items()):
78  # If the block name is recognized in algs
79  if blockName in algs:
80  # If the block only defines sub-blocks, initialize it
81  if isinstance(blockContent, dict) and not any(
82  key in algs[blockName].options for key in blockContent
83  ):
84  # Ensure parent block is initialized as an empty dictionary
85  node[blockName] = {'__placeholder__': True, **blockContent}
86  # Recurse into sub-blocks
87  processNode(node[blockName], algs[blockName].subAlgs)
88 
89  # Start processing from the root of the configuration
90  processNode(config, algs)
91 

◆ printConfig()

def python.ConfigText.TextConfig.printConfig (   self,
  sort = False,
  jsonFormat = False 
)
Print YAML configuration file.

Definition at line 157 of file ConfigText.py.

157  def printConfig(self, sort=False, jsonFormat=False):
158  """Print YAML configuration file."""
159  if self._config is None:
160  raise ValueError("No configuration has been loaded.")
161  printYaml(self._config, sort, jsonFormat)
162  return
163 
164 

◆ saveYaml()

def python.ConfigText.TextConfig.saveYaml (   self,
  filePath = 'config.yaml',
  default_flow_style = False,
**  kwargs 
)
Convert dictionary representation to yaml and save

Definition at line 165 of file ConfigText.py.

165  def saveYaml(self, filePath='config.yaml', default_flow_style=False,
166  **kwargs):
167  """
168  Convert dictionary representation to yaml and save
169  """
170  logCPAlgTextCfg.info(f"Saving configuration to {filePath}")
171  config = self._config
172  with open(filePath, 'w') as outfile:
173  yaml.dump(config, outfile, default_flow_style=False, **kwargs)
174  return
175 
176 

◆ setConfig()

def python.ConfigText.TextConfig.setConfig (   self,
  config 
)
Print YAML configuration file.

Definition at line 61 of file ConfigText.py.

61  def setConfig(self, config):
62  """Print YAML configuration file."""
63  if self._config:
64  raise ValueError("Configuration has already been loaded.")
65  self._config = config
66  return
67 

◆ setOptions()

def python.ConfigText.TextConfig.setOptions (   self,
**  kwargs 
)
Set option(s) for the lsat block that was added. If an option
was added previously, will update value

Definition at line 202 of file ConfigText.py.

202  def setOptions(self, **kwargs):
203  """
204  Set option(s) for the lsat block that was added. If an option
205  was added previously, will update value
206  """
207  if self._last is None:
208  raise TypeError("Cannot set options before adding a block")
209  # points to dict with opts for last added block
210  self._last.update(**kwargs)
211 
212 

Member Data Documentation

◆ __loadedYaml

python.ConfigText.TextConfig.__loadedYaml
private

Definition at line 54 of file ConfigText.py.

◆ _config

python.ConfigText.TextConfig._config
private

Definition at line 52 of file ConfigText.py.

◆ _last

python.ConfigText.TextConfig._last
private

Definition at line 58 of file ConfigText.py.


The documentation for this class was generated from the following file:
configure
bool configure(asg::AnaToolHandle< ITrigGlobalEfficiencyCorrectionTool > &tool, ToolHandleArray< IAsgElectronEfficiencyCorrectionTool > &electronEffToolsHandles, ToolHandleArray< IAsgElectronEfficiencyCorrectionTool > &electronSFToolsHandles, ToolHandleArray< CP::IMuonTriggerScaleFactors > &muonToolsHandles, ToolHandleArray< IAsgPhotonEfficiencyCorrectionTool > &photonEffToolsHandles, ToolHandleArray< IAsgPhotonEfficiencyCorrectionTool > &photonSFToolsHandles, const std::string &triggers, const std::map< std::string, std::string > &legsPerTool, unsigned long nToys, bool debug)
Definition: TrigGlobEffCorrValidation.cxx:514
python.processes.powheg.ZZj_MiNNLO.ZZj_MiNNLO.__init__
def __init__(self, base_directory, **kwargs)
Constructor: all process options are set here.
Definition: ZZj_MiNNLO.py:18
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.ConfigText.readYaml
def readYaml(yamlPath)
Definition: ConfigText.py:21
python.ConfigText.printYaml
def printYaml(d, sort=False, jsonFormat=False)
Definition: ConfigText.py:30
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
CxxUtils::set
constexpr std::enable_if_t< is_bitmask_v< E >, E & > set(E &lhs, E rhs)
Convenience function to set bits in a class enum bitmask.
Definition: bitmask.h:232
TCS::join
std::string join(const std::vector< std::string > &v, const char c=',')
Definition: Trigger/TrigT1/L1Topo/L1TopoCommon/Root/StringUtils.cxx:10
Trk::open
@ open
Definition: BinningType.h:40
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition: hcg.cxx:127
python.utility.LHE.merge
def merge(input_file_pattern, output_file)
Merge many input LHE files into a single output file.
Definition: LHE.py:29
python.Bindings.keys
keys
Definition: Control/AthenaPython/python/Bindings.py:801
merge
Definition: merge.py:1