Configuring the backend#
Visisipy performs all optical simulations in a backend, which uses existing optical simulation software to perform the calculations. Multiple backends are available:
OpticStudio: commercial ray tracing software. Visisipy uses ZOSPy[^zospy] to connect with OpticStudio.
Optiland: an open-source Python library for optical simulations.
Backends are ‘stateful’: they keep track of the current state of the optical system, including the current field and wavelength. This allows for efficient calculations and reduces the need to repeatedly set up the optical system. Various optical system properties, for example the fields and wavelengths, are also stored in the backend.
Tip
As a rule of thumb, settings that would be configured in OpticStudio’s System Explorer should be configured in the backend.
Warning
Backends may give different results for the same optical system. Always check if results are consistent with the expected behavior of the optical system. See Comparison between the OpticStudio and Optiland backends for a comparison of the backends.
Setting the backend#
The preferred backend can be selected using visisipy.set_backend:
import visisipy
visisipy.set_backend("optiland") # or "opticstudio"
Updating settings#
Settings can be updated using visisipy.update_settings.
Supported parameters are specified by visisipy.backend.BackendSettings.
Furthermore, some parameters are backend-specific.
For example, the OpticStudio backend allows to configure Ray Aiming, which is not available in Optiland.
These OpticStudio-specific parameters are specified in visisipy.opticstudio.backend.OpticStudioSettings.
visisipy.update_settings(
field_type="angle",
fields=[(0, 0), (0, 30)],
wavelengths=[0.400, 0.500, 0.600],
aperture_type="entrance_pupil_diameter",
aperture_value=1.348,
)
Running Visisipy and OpticStudio side-by-side#
OpticStudio has two connection modes, standalone and extension.
By default, Visisipy connects to OpticStudio in standalone mode, which launches an invisible instance of OpticStudio that is entirely controlled by Visisipy.
In extension mode, Visisipy connects to an already running instance of OpticStudio.
This mode can be activated by setting the mode parameter to extension when initializing the OpticStudio backend:
visisipy.set_backend("opticstudio", mode="extension")
You can read more about OpticStudio’s connection modes in the ZOSPy documentation.
Performing ray tracing on a GPU#
Optiland allows to configure the backend for numerical computations.
This backend is also managed through the Optiland backend settings.
By default, all computations are performed using numpy.
To use GPU acceleration, the torch computation backend can be selected:
visisipy.update_settings(
computation_backend="torch",
torch_device="cuda", # or "cpu"
)
Getting the backend#
In some advanced cases, it may be necessary to access the backend directly.
The backend can be accessed using visisipy.get_backend.
Note that this function will initialize the default backend if no backend is set.
More information about backend objects
A backend is a class that implements visisipy.backend.BaseBackend.
However, backend classes are not intended to be instantiated.
Instead, all state is managed on the class object itself.
The main reason why the backend is a class, is to ensure all backends implement the visisipy.backend.BaseBackend interface.
backend = visisipy.get_backend()
print("Field type:", backend.get_setting("field_type")) # Get the field type
Field type: angle
Getting the optical system#
It may also be necessary to access the optical system directly, for example to put a camera or a lens in front of the eye model. Visisipy provides various functions to access the optical system, depending on the backend:
When using OpticStudio, the optical system can be accessed using
visisipy.get_oss.When using Optiland, the optical system can be accessed using
visisipy.get_optic.
You can read more about this in Interacting with the backend directly.
# Create an eye model and draw it
model = visisipy.EyeModel()
model.build()
visisipy.backend.get_optic().draw()