-
Notifications
You must be signed in to change notification settings - Fork 9
[WIP] openalea configuration #54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 18 commits
2c35c25
37d3282
7b5315c
73d4c67
542175d
2c3e8e1
f60d764
2b5091d
9d61cae
6bbde94
f355e7d
d14b987
486ac6b
eaae10c
b551247
59273ee
8a5899e
bb66dc6
dc55b88
ba618be
c343804
44a3063
1b81681
454023a
b7a7562
6db511e
032b4bc
5eefc99
8f0460b
ea24456
5d4c27f
1522c19
8dd9c4a
4d53bbd
14d3e88
6e94dba
2d92d10
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -45,6 +45,7 @@ dependencies = [ | |
| "configobj", | ||
| "six", | ||
| "setuptools", | ||
| "pyyaml", | ||
| ] | ||
|
|
||
| [tool.setuptools.dynamic] | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,184 @@ | ||
| # -*- python -*- | ||
| # | ||
| # OpenAlea.Core | ||
| # | ||
| # Copyright 2006-2026 CIRAD - INRAE - inria | ||
| # | ||
| # File author(s): Leticia Napolitano | ||
| # Christophe Pradal <christophe.prada@cirad.fr> | ||
| # Fabrice Bauget <fabrice.bauget@cirad.fr> | ||
| # | ||
| # Distributed under the Cecill-C License. | ||
| # See accompanying file LICENSE.txt or copy at | ||
| # http://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html | ||
| # | ||
| # OpenAlea WebSite : http://openalea.gforge.inria.fr | ||
| # | ||
| ############################################################################## | ||
| """Configuration of OpenAlea models""" | ||
|
|
||
| __license__ = "Cecill-C" | ||
|
|
||
| import yaml | ||
| import json | ||
| from openalea.core.singleton import Singleton | ||
| from openalea.core.observer import Observed | ||
| from pathlib import Path | ||
|
|
||
| def _load_json(filename: str): | ||
| """Load configuration from a JSON file.""" | ||
|
|
||
| file = Path(filename) | ||
| with file.open() as f: | ||
| data = json.load(f) | ||
| return data | ||
|
|
||
| def _load_yml(filename: str): | ||
| """Load configuration from a YAML file.""" | ||
|
|
||
| file = Path(filename) | ||
| with file.open() as f: | ||
| data = yaml.load(f, Loader=yaml.SafeLoader) | ||
| return data | ||
|
|
||
| def _dump_yml(data, filename: str, sort_keys=False): | ||
| """Dump configuration to a YAML file.""" | ||
|
|
||
| file = Path(filename) | ||
| with file.open("w") as f: | ||
| yaml.dump(data, f, sort_keys=sort_keys) | ||
|
|
||
| def _dump_json(data, filename: str): | ||
| """Dump configuration to a JSON file.""" | ||
|
|
||
| file = Path(filename) | ||
| with file.open("w") as f: | ||
| json.dump(data, f, indent=4) | ||
|
|
||
|
|
||
| class Parameter: | ||
| def __init__(self, name, value=None, unit=None, param_type=None, description="", uid=None, uri=None): | ||
| self.name = name | ||
| self.value = value | ||
| self.unit = unit | ||
| self.param_type = param_type | ||
| self.description = description | ||
| self.uid = uid | ||
| self.uri = uri | ||
|
|
||
| def to_dict(self): | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is also directly managed by dataclass |
||
| return { | ||
| self.name: { | ||
| "value": self.value, | ||
| "unit": self.unit, | ||
| "description": self.description, | ||
| "type": self.param_type, | ||
| "uid": self.uid, | ||
| "uri": self.uri | ||
| } | ||
| } | ||
|
|
||
| def __str__(self): | ||
| return f"name={self.name}, value={self.value}, unit={self.unit}, param_type={self.param_type}, description={self.description}, uid={self.uid}, uri={self.uri}" | ||
|
|
||
| class MyModelUnit: | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The My in MyModel is just for tutos. Like ModelUnitConfig
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can also inherit from dict, no? |
||
| def __init__(self, name, parameters: list): | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. name: str |
||
| self.name = name | ||
| self.parameters=parameters | ||
|
|
||
| def to_dict(self): | ||
| params = {k : v for param in self.parameters for k, v in param.to_dict().items()} | ||
| return { | ||
| self.name : params | ||
| } | ||
|
|
||
| def __str__(self): | ||
| return f"name={self.name}, parameters={self.to_dict()}" | ||
|
|
||
|
|
||
| class Config: | ||
| """Configuration of OpenAlea models | ||
|
|
||
| TODO : Documentation to write | ||
| """ | ||
| def __init__(self, model_unit_configs: list): | ||
| """Initialize the configuration with a list of unit configurations.""" | ||
| self.model_unit_configs = model_unit_configs | ||
|
|
||
| def to_dict(self): | ||
| dict = {} | ||
| for unit in self.model_unit_configs: | ||
| dict.update(unit.to_dict()) | ||
| return dict | ||
|
|
||
| def __len__(self): | ||
| return len(self.model_unit_configs) | ||
|
|
||
| def __getitem__(self, key): | ||
| return self.to_dict()[key] | ||
|
|
||
| def __str__(self): | ||
| return f"{self.model_unit_configs}" | ||
|
|
||
|
|
||
| def add_section(self, unit): | ||
| self.model_unit_configs.append(unit) | ||
|
|
||
| #@staticmethod | ||
| def load(self, filename: str): | ||
| """Load configuration from a file. | ||
|
|
||
| Dispatch method based on file extension (YAML, JSON, etc.). | ||
| """ | ||
|
|
||
| extension = filename.split(".")[-1] | ||
|
|
||
| if extension in ("yml", "yaml"): | ||
| data = _load_yml(filename) | ||
|
|
||
| elif extension == "json": | ||
| data = _load_json(filename) | ||
|
|
||
| units = [] | ||
|
|
||
| ''' | ||
| for unit_name, params in data.items(): | ||
| parameters = [Parameter(name=k, value=v) for k, v in params.items()] | ||
| unit = MyModelUnit(unit_name, parameters) | ||
| units.append(unit) | ||
| ''' | ||
| for unit_name, params in data.items(): | ||
| parameters = [ | ||
| Parameter( | ||
| name=name, | ||
| value=params[name]["value"], | ||
| unit=params[name].get("unit"), | ||
| description=params[name].get("description"), | ||
| param_type=params[name].get("type"), | ||
| uid=params[name].get("uid"), | ||
| uri=params[name].get("uri") | ||
| ) | ||
| for name in params | ||
| ] | ||
|
|
||
| unit = MyModelUnit(unit_name, parameters) | ||
| units.append(unit) | ||
|
|
||
|
|
||
| #print(data) | ||
|
|
||
| return Config(units) | ||
|
|
||
| def dump(self, filename: str): | ||
| """Dump configuration to a file.""" | ||
|
|
||
| extension = filename.split(".")[-1] | ||
| data = self.to_dict() | ||
|
|
||
| if extension in ("yml", "yaml"): | ||
| _dump_yml(data, filename) | ||
|
|
||
| elif extension == "json": | ||
| _dump_json(data, filename) | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For Parameter, I would use a Data Class.
Look at it