Source code for at.load.json

"""
Handling of JSON files
"""

from __future__ import annotations

__all__ = ["save_json", "load_json"]

from os.path import abspath
import json
from typing import Optional, Any

import numpy as np

from .allfiles import register_format
from .utils import keep_elements, keep_attributes
from ..lattice import Element, Lattice, Particle


class _AtEncoder(json.JSONEncoder):
    """JSON encoder for specific AT types"""

    def default(self, obj):
        if isinstance(obj, Element):
            return obj.to_dict()
        elif isinstance(obj, np.ndarray):
            return obj.tolist()
        elif isinstance(obj, Particle):
            return obj.to_dict()
        else:
            return super().default(obj)


[docs] def save_json( ring: Lattice, filename: Optional[str] = None, compact: bool = False ) -> None: """Save a :py:class:`.Lattice` as a JSON file Parameters: ring: Lattice description filename: Name of the JSON file. Default: outputs on :py:obj:`sys.stdout` compact: If :py:obj:`False` (default), the JSON file is pretty-printed with line feeds and indentation. Otherwise, the output is a single line. See Also: :py:func:`.save_lattice` for a generic lattice-saving function. :py:meth:`.Lattice.save` for a generic lattice-saving method. """ indent = None if compact else 2 data = dict( atjson=1, elements=list(keep_elements(ring)), properties=keep_attributes(ring) ) if filename is None: print(json.dumps(data, cls=_AtEncoder, indent=indent)) else: with open(filename, "wt") as jsonfile: json.dump(data, jsonfile, cls=_AtEncoder, indent=indent)
[docs] def load_json(filename: str, **kwargs) -> Lattice: """Create a :py:class:`.Lattice` from a JSON file Parameters: filename: Name of a JSON file Keyword Args: *: All keywords update the lattice properties Returns: lattice (Lattice): New :py:class:`.Lattice` object See Also: :py:meth:`.Lattice.load` for a generic lattice-loading method. """ def json_generator(params: dict[str, Any], fn): with open(params.setdefault("in_file", fn), "rt") as jsonfile: data = json.load(jsonfile) # Check the file signature - For later use try: atjson = data["atjson"] # noqa F841 except KeyError: atjson = 1 # noqa F841 # Get elements elements = data["elements"] # Get lattice properties try: properties = data["properties"] except KeyError: properties = {} particle_dict = properties.pop("particle", {}) params.setdefault("particle", Particle(**particle_dict)) for k, v in properties.items(): params.setdefault(k, v) for idx, elem_dict in enumerate(elements): yield Element.from_dict(elem_dict, index=idx, check=False) return Lattice(abspath(filename), iterator=json_generator, **kwargs)
register_format( ".json", load_json, save_json, descr="JSON representation of a python AT Lattice. See :py:func:`.load_json`.", )