-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from MREYE-LUMC/crnh/doc/readme
Write README for public version
- Loading branch information
Showing
13 changed files
with
362 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,30 @@ | ||
# EyeSimulator | ||
# Visisipy: accessible vision simulations in Python | ||
|
||
This project aims to provide a standardized method to perform optical (ray tracing) simulations on eye models. `EyeSimulator` is just a working name and should preferrably be replaced with something better before releasing this library. | ||
Visisipy (pronounced `/ˌvɪsəˈsɪpi/`, like Mississippi but with a V) is a Python library for optical simulations of the eye. | ||
It provides an easy-to-use interface to define and build eye models, and to perform common ophthalmic analyses on these models. | ||
|
||
## Goals | ||
|
||
1. Provide a uniform interface to define, build and analyze various types of eye models, using abstractions that make sense in a clinical context; | ||
2. Provide an accessible interface to the most common analyses on these models; | ||
3. Decouple the model definition interface as much as possible from the simulation software, i.e. Zemax OpticStudio; | ||
4. Introduce this as a standardized method for optical simulations of the eye, that can be used by the broader physiological optics community. | ||
2. Provide a collection of ready-to-use eye models, such as the Navarro model[^navarro], that can be customized at need; | ||
3. Provide an accessible interface to clinically relevant analyses with these models. | ||
|
||
All calculations are currently performed in OpticStudio through the [ZOSPy][zospy] library[^zospy], but visisipy is designed in a modular fashion to allow for other backends in the future. | ||
|
||
## Contributing | ||
|
||
Visisipy aims to be a community-driven project and warmly accepts contributions. If you want to contribute, please email us ([email protected]) or [open a new discussion](https://github.com/MREYE-LUMC/visisipy/discussions). | ||
Visisipy aims to be a community-driven project and warmly accepts contributions. | ||
If you want to contribute, please email us ([email protected]) or [open a new discussion](https://github.com/MREYE-LUMC/visisipy/discussions). | ||
|
||
## Installation | ||
|
||
## Current implementation | ||
Visisipy can be installed through `pip`: | ||
|
||
In its current state, `EyeSimulator` provides | ||
```bash | ||
pip install git+https://github.com/MREYE-LUMC/visisipy.git | ||
``` | ||
|
||
- Classes to define models in terms of clinically relevant and measurable parameters (`EyeGeometry`); | ||
- An abstract base class `BaseEye` and a simple implementation `Eye`, which allows to build and analyze these eye models; | ||
- A `Surface` class, which acts as a bridge between the abstractions used in this library and Zemax OpticStudio. This allows for seamless integration of OpticStudio models in our `Eye` class. | ||
Visisipy will be made available through PyPI and Conda as soon as possible. | ||
|
||
## Example | ||
|
||
|
@@ -35,7 +40,11 @@ model = visisipy.EyeModel() | |
model.build() | ||
|
||
# Perform a raytrace analysis | ||
raytrace = visisipy.analysis.raytrace(coordinates=zip([0] * 5, range(0, 60, 10))) | ||
coordinates = [(0, 0), (0, 10), (0, 20), (0, 30), (0, 40)] | ||
raytrace = visisipy.analysis.raytrace(coordinates=coordinates) | ||
|
||
# Alternatively, the model can be built and analyzed in one go: | ||
# raytrace = visisipy.analysis.raytrace(model, coordinates=zip([0] * 5, range(0, 60, 10))) | ||
|
||
# Visualize the model | ||
fig, ax = plt.subplots() | ||
|
@@ -49,42 +58,91 @@ sns.lineplot(raytrace, x="z", y="y", hue="field", ax=ax) | |
plt.show() | ||
``` | ||
|
||
### Configure the backend | ||
|
||
Visisipy uses OpticStudio as a backend for calculations; this is currently the only supported backend. | ||
This backend is automatically started and managed in the background, but can also be configured manually. | ||
|
||
```python | ||
import zospy as zp | ||
from visisipy import EyeModel, NavarroGeometry | ||
from visisipy.opticstudio import OpticStudioEye | ||
import visisipy | ||
|
||
# Use OpticStudio in standalone mode (default) | ||
visisipy.set_backend("opticstudio") | ||
|
||
# Use OpticStudio in extension mode | ||
visisipy.set_backend("opticstudio", mode="extension") | ||
|
||
# Use OpticStudio in extension mode with ray aiming enabled | ||
visisipy.set_backend("opticstudio", mode="extension", ray_aiming="real") | ||
|
||
# Get the OpticStudioSystem from visisipy to interact with it manually | ||
# This only works when the backend is set to "opticstudio" | ||
# See https://zospy.readthedocs.io/en/latest/api/zospy.zpcore.OpticStudioSystem.html for documentation of this object | ||
oss = visisipy.backend.get_oss() | ||
``` | ||
|
||
# Initialize ZOSPy | ||
zos = zp.ZOS() | ||
oss = zos.connect() | ||
### Create a custom eye model from clinical parameters | ||
|
||
# Initialize an eye, using a slightly modified Navarro model | ||
eye_model = EyeModel(NavarroGeometry(iris_radius=0.5)) | ||
eye = OpticStudioEye(eye_model) | ||
An eye model in visispy consists of two parts: the geometry and the material properties. | ||
The geometry is defined by `visisipy.models.EyeGeometry`, and the material properties are defined by `visisipy.models.Materials`. | ||
They are combined in `visisipy.EyeModel` to constitute a complete eye model. | ||
|
||
# Update a parameter of one of the eye's surfaces | ||
eye.lens_front.refractive_index += 1.0 | ||
```python | ||
import visisipy | ||
|
||
geometry = visisipy.models.create_geometry( | ||
axial_length=20, | ||
cornea_thickness=0.5, | ||
anterior_chamber_depth=3, | ||
lens_thickness=4, | ||
cornea_front_radius=7, | ||
cornea_front_asphericity=0, | ||
cornea_back_radius=6, | ||
cornea_back_asphericity=0, | ||
lens_front_radius=10, | ||
lens_front_asphericity=0, | ||
lens_back_radius=-6, | ||
lens_back_asphericity=0, | ||
retina_radius=-12, | ||
retina_asphericity=0, | ||
pupil_radius=1.0, | ||
) | ||
|
||
# Use this geometry together with the refractive indices of the Navarro model | ||
model = visisipy.EyeModel(geometry=geometry, materials=visisipy.models.materials.NavarroMaterials()) | ||
|
||
# NavarroMaterials is the default, so this is equivalent: | ||
model = visisipy.EyeModel(geometry=geometry) | ||
``` | ||
|
||
# Build the eye in OpticStudio | ||
eye.build(oss) | ||
### Interact with the eye model in OpticStudio | ||
|
||
# Change the lens's refractive index back | ||
eye.lens_front.refractive_index -= 1.0 | ||
```python | ||
import visisipy | ||
|
||
# Insert a new (dummy) surface in OpticStudio | ||
oss.LDE.InsertNewSurfaceAt(1).Comment = "input beam" | ||
# Just use the default Navarro model | ||
model = visisipy.EyeModel() | ||
|
||
# Relink the surfaces of the eye, because a new surface was added | ||
eye.relink_surfaces(oss) | ||
# Build the model in OpticStudio | ||
built_model: visisipy.opticstudio.OpticStudioEye = model.build() | ||
|
||
# Check if the relinking succeeded | ||
assert eye.lens_back.radius == eye_model.geometry.lens_back_curvature | ||
# Update the lens front radius | ||
built_model.lens_front.radius = 10.5 | ||
``` | ||
|
||
## Planned functions | ||
|
||
- Generation of realistic randomized eye models using the method proposed by Rozema et al.[^rozema] | ||
|
||
## Future ideas | ||
|
||
- Provide (customizable) geometry definitions for various standard eye models, e.g. `NavarroGeometry`, `GullstrandGeometry`. | ||
- Most likely as child classes of `EyeGeometry`. The default values currently used in `EyeGeometry` will then be removed. | ||
- The same applies for the `EyeMaterials` class. | ||
- Add more implementations of `BaseEye`, e.g. `ReverseEye`, a reversed version of `Eye`. | ||
- Integrate the eye plot functions defined in [chaasjes/utilities](https://git.lumc.nl/chaasjes/utilities/-/tree/main/utilities/plots/eye) in this library for easy visualization of eye models. | ||
- Provide (customizable) geometry definitions for other standard eye models, e.g. `GullstrandGeometry`. | ||
- Add support for reversed eyes. | ||
- Add support for other (open source) ray tracing backends. | ||
|
||
[zospy]: https://zospy.readthedocs.io/ | ||
|
||
[//]: # (References) | ||
[^navarro]: Escudero-Sanz, I., & Navarro, R. (1999). Off-axis aberrations of a wide-angle schematic eye model. JOSA A, 16(8), 1881–1891. https://doi.org/10.1364/JOSAA.16.001881 | ||
[^rozema]: Rozema, J. J., Rodriguez, P., Navarro, R., & Tassignon, M.-J. (2016). SyntEyes: A Higher-Order Statistical Eye Model for Healthy Eyes. Investigative Ophthalmology & Visual Science, 57(2), 683–691. https://doi.org/10.1167/iovs.15-18067 | ||
[^zospy]: Vught, L. van, Haasjes, C., & Beenakker, J.-W. M. (2024). ZOSPy: Optical ray tracing in Python through OpticStudio. Journal of Open Source Software, 9(96), 5756. https://doi.org/10.21105/joss.05756 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.