Saving and Loading Results#

Most of Beam Corset’s dataclass() based objects can be serialized to and from YAML to save data for later use.

Beam Corset Objects#

All objects that can be serialized to YAML implement two methods: save_yaml() and load_yaml(). The former is called on an instance of the object, taking a path to a file to write the YAML representation of the object. The latter is a class method that takes a path to a YAML file and returns an instance of the object.

[2]:
from corset import Beam

beam = Beam.from_gauss(focus=200e-3, waist=100e-6, wavelength=1064e-9)
print("original:", beam)
beam.save_yaml("beam.yaml") # save through the instance method
loaded_beam = Beam.load_yaml("beam.yaml") # load through the class method
print("reloaded:", loaded_beam)
original: Beam(beam_parameter=0.029526246744264968j, z_offset=0.2, wavelength=1.064e-06, gauss_cov=None, fit_data=None)
reloaded: Beam(beam_parameter=0.029526246744264968j, z_offset=0.2, wavelength=1.064e-06, gauss_cov=None, fit_data=None)

This also works for more complex objects like solution lists.

[3]:
from corset import ShiftingRange, SolutionList, ThinLens, mode_match

solutions = mode_match(Beam.from_gauss(0.0, 500e-6, 1064e-9), Beam.from_gauss(1.0, 100e-6, 1064e-9), [ShiftingRange(0.0, 0.8)], [ThinLens(f) for f in [100e-3, 150e-3]], 2, 2)
solutions.save_yaml("solutions.yaml") # save through the instance method
reloaded_solutions = SolutionList.load_yaml("solutions.yaml") # load through the class method
reloaded_solutions
[3]:
overlap num_elements elements positions min_sensitivity_axis min_sensitivity max_sensitivity_axis max_sensitivity min_cross_sens_pair min_cross_sens min_cross_sens_direction min_coupling_pair min_coupling sensitivities couplings const_space grad_focus grad_waist solution
0 100.0 % 2 [f=100mm, f=100mm] [472., 737.] mm 1 4.80 %/cm² 0 10.88 %/cm² (0, 1) 7.07 %/cm² [0.55 , 0.835] (0, 1) 97.9 % [[10.88, -7.07], [-7.07, 4.8 ]] %/cm² [[100. , -97.9], [-97.9, 100. ]] % [] [ 2.591, -1.557] mm/mm [ 1.588, -1.625] μm/mm ModeMatchingSolution(...)
1 100.0 % 2 [f=100mm, f=150mm] [273., 624.] mm 1 2.64 %/cm² 0 7.81 %/cm² (0, 1) 4.45 %/cm² [0.499, 0.867] (0, 1) 98.0 % [[ 7.81, -4.45], [-4.45, 2.64]] %/cm² [[100., -98.], [-98., 100.]] % [] [ 2.26 , -1.221] mm/mm [ 0.988, -1.002] μm/mm ModeMatchingSolution(...)
2 100.0 % 2 [f=150mm, f=150mm] [252., 704.] mm 1 0.22 %/cm² 0 1.51 %/cm² (0, 1) 0.09 %/cm² [0.07 , 0.998] (0, 1) 15.6 % [[ 1.51, -0.09], [-0.09, 0.22]] %/cm² [[100. , -15.6], [-15.6, 100. ]] % [] [0.949, 0.09 ] mm/mm [ 0.658, -0.649] μm/mm ModeMatchingSolution(...)

Since most Beam Corset objects also include references to the data they are computed from, saving a solution will also save the underlying ModeMatchingProblem and all its relevant members.

[4]:
print(reloaded_solutions[0].candidate.problem.setup.initial_beam)
Beam(beam_parameter=0.7381561686066243j, z_offset=0.0, wavelength=1.064e-06, gauss_cov=None, fit_data=None)

This is implemented fairly efficient since YAML allows emitting references to already serialized objects, so that the same object is not serialized multiple times.

Built-in Data Structures#

Beam Corset also supports serializing data structures containing beam corset objects, such as lists, tuples, and dictionaries. Everything that does not implement a save_yaml() or load_yaml() (and everything that does) can be serialized using the free save_yaml() and load_yaml() functions.

[5]:
from corset import load_yaml, save_yaml

my_dict = {
    "beam": beam,
    "other_data": [1, 2, 3],
}
save_yaml(my_dict, "my_dict.yaml") # save through the free function
reloaded_dict = load_yaml("my_dict.yaml") # load through the free function
reloaded_dict
[5]:
{'beam': Beam(beam_parameter=0.029526246744264968j, z_offset=0.2, wavelength=1.064e-06, gauss_cov=None, fit_data=None),
 'other_data': [1, 2, 3]}

Unlike the subclass methods for loading which only allow loading objects of the classes type. The free load_yaml() function can load any object from a YAML file, and will return the correct type of object based on the contents of the file.

PNG Files with Metadata#

All beam corset objects that have an IPython PNG representation (i.e. they implement _repr_png_) can also be saved to PNG files with the YAML representation of the object embedded in the PNG metadata. This is done through the save_png() and load_png() methods.

This makes it very convenient to save Beam Corset’s visualizations for viewing outside of Jupyter notebooks, while still preserving all underlying information for later analysis.

[6]:
from corset import ModeMatchingSolution

solutions[0].save_png("solution.png") # save through the instance method
reloaded_solution = ModeMatchingSolution.load_png("solution.png") # load through the class method
print("minimum coupling in reloaded solution:", reloaded_solution.analysis.min_coupling)
reloaded_solution
minimum coupling in reloaded solution: 0.9790679653526969
[6]:
Element Summary
element shape focal_length position clearance_left clearance_right dof sensitivity grad_focus grad_waist sensitivities couplings shifting_range
0 f=100mm | 100 mm 472 mm 472 mm 265 mm 0 10.88 %/cm² 2.591 mm/mm 1.588 μm/mm [10.88, -7.07] %/cm² [100. , -97.9] % ShiftingRange(left=0.0, right=0.8, min_element...
1 f=100mm | 100 mm 737 mm 265 mm 63 mm 1 4.80 %/cm² -1.557 mm/mm -1.625 μm/mm [-7.07, 4.8 ] %/cm² [-97.9, 100. ] % ShiftingRange(left=0.0, right=0.8, min_element...

To make things even more convenient, the HTML representation of mode matching solutions also has two buttons that appear when hovering over the solution (they are also available in this documentation). They will save the solution as a YAML file or as a PNG file with the YAML representation embedded in the metadata respectively.

This is especially useful to immediately save a chosen solution while browsing through the visualizations of all solutions in a solution list to avoid any index based selection ambiguities.