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]:
163 raise ValueError(f
"Unkown block {blockName} in yaml file")
166 configSeq = ConfigSequence()
167 for blockName
in self._order[self.ROOTNAME]:
168 if blockName ==
"AddConfigBlocks":
171 assert blockName
in self._algs
175 blockConfig = self.
_config[blockName]
176 alg = self._algs[blockName]
184 algName, defaults=None, pos=None, superBlocks=None):
186 Load <functionName> from <modulePath>
189 module = importlib.import_module(modulePath)
190 fxn = getattr(module, functionName)
191 except ModuleNotFoundError
as e:
192 raise ModuleNotFoundError(f
"{e}\nFailed to load {functionName} from {modulePath}")
194 sys.modules[functionName] = fxn
196 self.addAlgConfigBlock(algName=algName, alg=fxn,
198 superBlocks=superBlocks,
203 def _configureAlg(self, block, blockConfig, configSeq=None, containerName=None):
204 if not isinstance(blockConfig, list):
205 blockConfig = [blockConfig]
207 for options
in blockConfig:
209 if 'containerName' in options:
210 containerName = options[
'containerName']
211 elif containerName
is not None and 'containerName' not in options:
212 options[
'containerName'] = containerName
214 logCPAlgTextCfg.info(f
"Configuring {block.algName}")
215 seq, funcOpts = block.makeConfig(options)
218 algOpts = seq.setOptions(options)
219 if configSeq
is not None:
223 algOpts = [i[
'name']
for i
in algOpts]
224 expectedOptions =
set(funcOpts)
225 expectedOptions |=
set(algOpts)
226 expectedOptions |=
set(block.subAlgs)
228 difference =
set(options.keys()) - expectedOptions
230 difference =
"\n".
join(difference)
231 raise ValueError(f
"There are options set that are not used for "
232 f
"{block.algName}:\n{difference}\n"
233 "Please check your configuration.")
236 for alg
in self._order.
get(block.algName, []):
238 subAlg = block.subAlgs[alg]
239 self.
_configureAlg(subAlg, options[alg], configSeq, containerName)
243 def makeSequence(configPath, dataType, algSeq, geometry=None, autoconfigFromFlags=None,
244 isPhyslite=False, noPhysliteBroken=False, noSystematics=None):
248 from AnalysisAlgorithmsConfig.ConfigAccumulator
import ConfigAccumulator
252 logCPAlgTextCfg.info(
"Configuration file read in:")
255 logCPAlgTextCfg.info(
"Default algorithms:")
256 config.printAlgs(printOpts=
True)
258 logCPAlgTextCfg.info(
"Configuring algorithms based on YAML file:")
259 configSeq = config.configure()
262 logCPAlgTextCfg.info(
"Configuration used:")
266 configAccumulator = ConfigAccumulator(algSeq, dataType, isPhyslite=isPhyslite, geometry=geometry, autoconfigFromFlags=autoconfigFromFlags, noSystematics=noSystematics)
267 configSeq.fullConfigure(configAccumulator)
270 logCPAlgTextCfg.info(
"ConfigBlocks and their configuration:")
271 configSeq.printOptions()
273 from AnaAlgorithm.DualUseConfig
import isAthena, useComponentAccumulator
274 if isAthena
and useComponentAccumulator:
275 return configAccumulator.CA
287 if isinstance(local, dict):
288 to_combine = local.values()
289 elif isinstance(local, list):
295 for sub
in to_combine:
299 if fragment_key
not in local:
303 pathlib.Path(local[fragment_key]),
306 with open(fragment_path)
as fragment_file:
311 if fragment_path.suffix ==
'.json':
312 fragment = json.load(fragment_file)
314 fragment = yaml.safe_load(fragment_file)
320 fragment_path.parent,
321 fragment_key=fragment_key
328 del local[fragment_key]
334 config_path / fragment_path,
335 *[x / fragment_path
for x
in os.environ[
"DATAPATH"].
split(
":")]
337 for path
in paths_to_check:
341 raise FileNotFoundError(fragment_path)
346 if isinstance(local, list):
351 if isinstance(local, dict):
352 for key, value
in fragment.items():