12 from AnalysisAlgorithmsConfig.ConfigSequence
import ConfigSequence
13 from AnalysisAlgorithmsConfig.ConfigFactory
import ConfigFactory
15 from AnaAlgorithm.Logging
import logging
16 logCPAlgTextCfg = logging.getLogger(
'CPAlgTextCfg')
20 """Loads YAML file into a dictionary"""
21 if not os.path.isfile(yamlPath):
22 raise ValueError(f
"{yamlPath} is not a file.")
23 with open(yamlPath,
'r')
as f:
24 textConfig = yaml.safe_load(f)
29 """Prints a dictionary as YAML"""
30 print(yaml.dump(d, default_flow_style=jsonFormat, sort_keys=sort))
34 def __init__(self, yamlPath=None, *, addDefaultBlocks=True):
35 super().
__init__(addDefaultBlocks=
False)
39 defaults={
'self': self})
47 if yamlPath
is not None:
54 """Print YAML configuration file."""
56 raise ValueError(
"Configuration has already been loaded.")
63 read a YAML file. Will combine with any config blocks added using python
66 raise NotImplementedError(
"Mering multiple yaml files is not implemented.")
69 def merge(config, algs, path=''):
70 """Add to config block-by-block"""
71 if not isinstance(config, list):
76 if blocks == {}
and path:
81 for blockName
in algs:
82 if blockName
in blocks:
83 subBlocks[blockName] = blocks.pop(blockName)
88 for subName, subBlock
in subBlocks.items():
89 newPath = f
'{path}.{subName}' if path
else subName
90 merge(subBlock, algs[subName].subAlgs, newPath)
93 logCPAlgTextCfg.info(f
'loading {yamlPath}')
96 if "AddConfigBlocks" in config:
97 self.
_configureAlg(self._algs[
"AddConfigBlocks"], config[
"AddConfigBlocks"])
98 merge(config, self._algs)
103 """Print YAML configuration file."""
105 raise ValueError(
"No configuration has been loaded.")
110 def saveYaml(self, filePath='config.yaml', default_flow_style=False,
113 Convert dictionary representation to yaml and save
115 logCPAlgTextCfg.info(f
"Saving configuration to {filePath}")
117 with open(filePath,
'w')
as outfile:
118 yaml.dump(config, outfile, default_flow_style=
False, **kwargs)
124 Create entry into dictionary representing the text configuration
126 def setEntry(name, config, opts):
128 if name
not in config:
130 elif isinstance(config[name], list):
133 config[name] = [config[name], opts]
137 name, rest = name[:name.index(
'.')], name[name.index(
'.') + 1:]
138 config = config[name]
139 if isinstance(config, list):
141 setEntry(rest, config, opts)
143 setEntry(name, self.
_config, dict(kwargs))
149 Set option(s) for the lsat block that was added. If an option
150 was added previously, will update value
152 if self.
_last is None:
153 raise TypeError(
"Cannot set options before adding a block")
159 """Process YAML configuration file and confgure added algorithms."""
162 if blockName
not in self._order[self.ROOTNAME]:
165 raise ValueError(f
"Unkown block {blockName} in yaml file")
168 configSeq = ConfigSequence()
169 for blockName
in self._order[self.ROOTNAME]:
170 if blockName ==
"AddConfigBlocks":
173 assert blockName
in self._algs
177 blockConfig = self.
_config[blockName]
178 alg = self._algs[blockName]
186 algName, defaults=None, pos=None, superBlocks=None):
188 Load <functionName> from <modulePath>
191 module = importlib.import_module(modulePath)
192 fxn = getattr(module, functionName)
193 except ModuleNotFoundError
as e:
194 raise ModuleNotFoundError(f
"{e}\nFailed to load {functionName} from {modulePath}")
196 sys.modules[functionName] = fxn
198 self.addAlgConfigBlock(algName=algName, alg=fxn,
200 superBlocks=superBlocks,
205 def _configureAlg(self, block, blockConfig, configSeq=None, containerName=None):
206 if not isinstance(blockConfig, list):
207 blockConfig = [blockConfig]
209 for options
in blockConfig:
211 if 'containerName' in options:
212 containerName = options[
'containerName']
213 elif containerName
is not None and 'containerName' not in options:
214 options[
'containerName'] = containerName
216 logCPAlgTextCfg.info(f
"Configuring {block.algName}")
217 seq, funcOpts = block.makeConfig(options)
220 algOpts = seq.setOptions(options)
221 if configSeq
is not None:
225 algOpts = [i[
'name']
for i
in algOpts]
226 expectedOptions =
set(funcOpts)
227 expectedOptions |=
set(algOpts)
228 expectedOptions |=
set(block.subAlgs)
230 difference =
set(options.keys()) - expectedOptions
232 difference =
"\n".
join(difference)
233 raise ValueError(f
"There are options set that are not used for "
234 f
"{block.algName}:\n{difference}\n"
235 "Please check your configuration.")
238 for alg
in self._order.
get(block.algName, []):
240 subAlg = block.subAlgs[alg]
241 self.
_configureAlg(subAlg, options[alg], configSeq, containerName)
245 def makeSequence(configPath, dataType, algSeq, geometry=None, autoconfigFromFlags=None,
246 isPhyslite=False, noPhysliteBroken=False, noSystematics=None):
250 from AnalysisAlgorithmsConfig.ConfigAccumulator
import ConfigAccumulator
254 logCPAlgTextCfg.info(
"Configuration file read in:")
257 logCPAlgTextCfg.info(
"Default algorithms:")
258 config.printAlgs(printOpts=
True)
260 logCPAlgTextCfg.info(
"Configuring algorithms based on YAML file:")
261 configSeq = config.configure()
264 logCPAlgTextCfg.info(
"Configuration used:")
268 configAccumulator = ConfigAccumulator(algSeq, dataType, isPhyslite=isPhyslite, geometry=geometry, autoconfigFromFlags=autoconfigFromFlags, noSystematics=noSystematics)
269 configSeq.fullConfigure(configAccumulator)
272 logCPAlgTextCfg.info(
"ConfigBlocks and their configuration:")
273 configSeq.printOptions()
275 from AnaAlgorithm.DualUseConfig
import isAthena, useComponentAccumulator
276 if isAthena
and useComponentAccumulator:
277 return configAccumulator.CA
289 if isinstance(local, dict):
290 to_combine = local.values()
291 elif isinstance(local, list):
297 for sub
in to_combine:
301 if fragment_key
not in local:
305 pathlib.Path(local[fragment_key]),
308 with open(fragment_path)
as fragment_file:
313 if fragment_path.suffix ==
'.json':
314 fragment = json.load(fragment_file)
316 fragment = yaml.safe_load(fragment_file)
322 fragment_path.parent,
323 fragment_key=fragment_key
330 del local[fragment_key]
336 config_path / fragment_path,
337 *[x / fragment_path
for x
in os.environ[
"DATAPATH"].
split(
":")]
339 for path
in paths_to_check:
343 raise FileNotFoundError(fragment_path)
348 if isinstance(local, list):
353 if isinstance(local, dict):
354 for key, value
in fragment.items():