Skip to content

Commit 75c3570

Browse files
committed
PALS Root Structure
Add a free standing `load`/`store` function. Parse the root structure. https://pals-project.readthedocs.io/en/latest/conventions.html#pals-root-object
1 parent 7ead33b commit 75c3570

File tree

4 files changed

+81
-7
lines changed

4 files changed

+81
-7
lines changed

examples/fodo.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pals import Quadrupole
44
from pals import BeamLine
55
from pals import Lattice
6+
from pals import load, store
67

78

89
def main():
@@ -51,23 +52,23 @@ def main():
5152

5253
# Serialize to YAML
5354
yaml_file = "examples_fodo.pals.yaml"
54-
lattice.to_file(yaml_file)
55+
store(yaml_file, lattice)
5556

5657
# Read YAML data from file
57-
loaded_lattice = Lattice.from_file(yaml_file)
58+
loaded_lattice = load(yaml_file)
5859

5960
# Validate loaded data
60-
assert lattice == loaded_lattice
61+
assert lattice == loaded_lattice.facility[0]
6162

6263
# Serialize to JSON
6364
json_file = "examples_fodo.pals.json"
64-
lattice.to_file(json_file)
65+
store(json_file, lattice)
6566

6667
# Read JSON data from file
67-
loaded_lattice = Lattice.from_file(json_file)
68+
loaded_lattice = load(json_file)
6869

6970
# Validate loaded data
70-
assert lattice == loaded_lattice
71+
assert lattice == loaded_lattice.facility[0]
7172

7273

7374
if __name__ == "__main__":

src/pals/PALS.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
from pydantic import BaseModel
2+
3+
from pydantic import model_validator
4+
from typing import List, Optional
5+
6+
from .kinds import Lattice
7+
from .kinds.all_elements import get_all_elements_as_annotation
8+
from .functions import load_file_to_dict, store_dict_to_file
9+
10+
11+
Facility = List[get_all_elements_as_annotation()]
12+
13+
14+
class PALSroot(BaseModel):
15+
"""Represent the roo PALS structure"""
16+
17+
version: Optional[str] = None
18+
19+
facility: Facility
20+
21+
@model_validator(mode="before")
22+
@classmethod
23+
def unpack_json_structure(cls, data):
24+
"""Deserialize the JSON/YAML/...-like dict for facility elements"""
25+
from pals.kinds.mixin.all_element_mixin import unpack_element_list_structure
26+
27+
return unpack_element_list_structure(data, "facility", "facility")
28+
29+
def model_dump(self, *args, **kwargs):
30+
"""Custom model dump for facility to handle element list formatting"""
31+
from pals.kinds.mixin.all_element_mixin import dump_element_list
32+
33+
data = {}
34+
data["PALS"] = {}
35+
data["PALS"]["version"] = self.version
36+
data["PALS"] = dump_element_list(self, "facility", *args, **kwargs)
37+
return data
38+
39+
@staticmethod
40+
def from_file(filename: str) -> "PALSroot":
41+
"""Load a facility from a text file"""
42+
pals_dict = load_file_to_dict(filename)
43+
return PALSroot(**pals_dict)
44+
45+
def to_file(self, filename: str):
46+
"""Save a facility to a text file"""
47+
pals_dict = self.model_dump()
48+
store_dict_to_file(filename, pals_dict)
49+
50+
51+
def load(filename: str) -> PALSroot:
52+
"""Load a facility from a text file"""
53+
pals_dict = load_file_to_dict(filename)
54+
return PALSroot(**pals_dict)
55+
56+
57+
def store(filename: str, pals_root: PALSroot | Facility | Lattice):
58+
if isinstance(pals_root, Lattice):
59+
pals_root = PALSroot(version=None, facility=[pals_root])
60+
elif isinstance(pals_root, list):
61+
pals_root = PALSroot(version=None, facility=pals_root)
62+
pals_dict = pals_root.model_dump()
63+
64+
print(pals_dict)
65+
store_dict_to_file(filename, pals_dict)

src/pals/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@
66

77
from .kinds import * # noqa
88
from .parameters import * # noqa
9+
from .PALS import PALSroot, load, store # noqa
10+
11+
12+
# Rebuild pydantic models that depend on other classes
13+
PALSroot.model_rebuild()

src/pals/kinds/mixin/all_element_mixin.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,5 +110,8 @@ def dump_element_list(self, field_name: str, *args, **kwargs) -> dict:
110110
elem_dict = elem.model_dump(**kwargs)
111111
new_list.append(elem_dict)
112112

113-
data[self.name][field_name] = new_list
113+
if hasattr(self, "name"): # all but PALSroot have a name
114+
data[self.name][field_name] = new_list
115+
else:
116+
data[field_name] = new_list
114117
return data

0 commit comments

Comments
 (0)