"""Optiland File Handler
This module provides functions for loading and saving Optiland objects and
Optic instances to and from JSON files. The functions `load_obj_from_json` and
`save_obj_to_json` can be used to load and save any object that has a class
method `from_dict` and a method `to_dict`, respectively. In Optiland, this
includes most core classes, such as Optic, BaseGeometry, BaseCoating,
BaseMaterial, Aperture, FieldGroup, WavelengthGroup, etc.
Kramer Harrison, 2024
"""
from __future__ import annotations
import json
import os
from optiland.optic import Optic
[docs]
def load_obj_from_json(cls, filepath):
"""Load an object from a JSON file.
Note that this function can be used to load any object that has a class
method `from_dict` that can be used to create an instance of the class from
a dictionary. In Optiland, this includes most core classes, such as Optic,
BaseGeometry, BaseCoating, BaseMaterial, Aperture, FieldGroup,
WavelengthGroup, etc.
Args:
cls: The class of the object to load.
filepath: The path to the JSON file.
Returns:
An instance of the class
"""
if not os.path.exists(filepath):
raise FileNotFoundError(f"File '{filepath}' does not exist.")
with open(filepath) as f:
data = json.load(f)
return cls.from_dict(data)
[docs]
class OptilandEncoder(json.JSONEncoder):
"""Custom JSON encoder to handle tensor/array serialization across backends."""
[docs]
def default(self, obj):
if hasattr(obj, "tolist") and callable(obj.tolist):
return obj.tolist()
elif hasattr(obj, "item") and callable(obj.item):
return obj.item()
return super().default(obj)
[docs]
def save_obj_to_json(obj, filepath):
"""Save an object to a JSON file.
Note that this function can be used to save any object that has a method
`to_dict` that returns a dictionary representation of the object. In
Optiland, this includes most core classes, such as Optic, BaseGeometry,
BaseCoating, BaseMaterial, Aperture, FieldGroup, WavelengthGroup, etc.
Args:
obj: The object to save.
filepath: The path to the JSON file.
"""
with open(filepath, "w") as f:
json.dump(obj.to_dict(), f, indent=4, cls=OptilandEncoder)
[docs]
def load_optiland_file(filepath):
"""Load an Optiland Optic from a JSON file.
Args:
filepath: The path to the JSON file.
Returns:
An Optic instance.
"""
return load_obj_from_json(Optic, filepath)
[docs]
def save_optiland_file(obj, filepath):
"""Save an Optiland Optic to a JSON file.
Args:
obj: The Optic to save.
filepath: The path to the JSON file.
"""
save_obj_to_json(obj, filepath)