Defining eye models#
Eye models provide a backend-independent specification of the optical eye model.
They can be created using the visisipy.models.EyeModel class:
import visisipy
model = visisipy.EyeModel()
Eye models consist of two parts: the geometry of the eye and the material model. By default, Visisipy uses the geometry and material properties from the Navarro wide-angle schematic eye (Escudero-Sanz and Navarro, 1999).
Eye geometry#
Geometries are defined in visisipy.models.geometry.
Apart from base classes that can be used to define your own geometry, this module also provides a number of predefined
geometries, such as the NavarroGeometry.
Geometry objects contain surface definitions for all surfaces in the eye model.
A fully customized geometry can be specified like this:
from visisipy.models.geometry import StandardSurface, Stop
custom_geometry = visisipy.EyeGeometry(
cornea_front=StandardSurface(radius=7.72, asphericity=-0.26, thickness=0.55),
cornea_back=StandardSurface(radius=6.50, asphericity=0, thickness=3.05),
pupil=Stop(semi_diameter=1.348, is_stop=True),
lens_front=StandardSurface(radius=10.2, asphericity=-3.1316, thickness=4.0),
lens_back=StandardSurface(radius=-6.0, asphericity=-1, thickness=16.3203),
retina=StandardSurface(radius=-12.0, asphericity=0),
)
It is also possible to modify the predefined geometries. Complete surfaces can be replaced via the model constructor, or single parameters can be modified after creating the model.
Note
When modifying the geometry using the constructor, only complete surfaces can be modified.
default_navarro_geometry = visisipy.NavarroGeometry()
# Change the thickness of the cornea front surface
default_navarro_geometry.cornea_front.thickness = 1
# Alternatively, specify a new cornea front surface upon model creation
modified_navarro_geometry = visisipy.NavarroGeometry(
cornea_front=StandardSurface(radius=7.72, asphericity=-0.26, thickness=1),
)
Easy geometry customization with create_geometry#
The easiest way to create a custom geometry is to use the create_geometry function.
Using this function, you can specify the geometry using a set of clinically relevant parameters, such as the cornea radius, lens thickness, and axial length.
Parameters that are not specified will be taken from a standard geometry, which is the Navarro geometry by default.
The base geometry can be changed using the base parameter of create_geometry.
As an example, a custom geometry based on the Navarro geometry can be created like this:
myopic_geometry = visisipy.create_geometry(axial_length=26, cornea_front_radius=8.0, lens_thickness=4.0)
Convenience properties#
EyeGeometry objects provide some convenience properties to access clinically relevant parameters.
Note that these properties are calculated from the surface definitions and can therefore not be set directly.
print(f"""
Cornea thickness : {default_navarro_geometry.cornea_thickness} mm,
Anterior chamber depth : {default_navarro_geometry.anterior_chamber_depth} mm,
Lens thickness : {default_navarro_geometry.lens_thickness} mm,
Vitreous chamber depth : {default_navarro_geometry.vitreous_thickness} mm,
Axial length : {default_navarro_geometry.axial_length} mm,
""")
Cornea thickness : 1 mm,
Anterior chamber depth : 3.05 mm,
Lens thickness : 4.0 mm,
Vitreous chamber depth : 16.3203 mm,
Axial length : 24.3703 mm,
Definitions of anatomical distances#
The anatomical definitions of the convenience properties and create_geometry are defined as follows:
axial_length: Distance from the anterior cornea surface to the retina, along the optical axis.cornea_thickness: Central corneal thickness, defined as the distance between the anterior and posterior surfaces of the cornea.anterior_chamber_depth: Distance from the posterior surface of the cornea to the anterior surface of the lens.pupil_lens_distance: Distance from the pupil to the anterior surface of the lens.lens_thickness: Thickness of the crystalline lens, defined as the distance from the anterior to the posterior surface of the lens.vitreous_thickness: Distance from the posterior surface of the lens to the retina.
Eye materials#
The material properties of the different parts of the eye can be specified using EyeMaterials.
This class bundles the material properties of the cornea, aqueous humour, lens, and vitreous humour.
For each of these structures, the material can either be a MaterialModel or a string.
If a string is used, it should be a valid material name in the selected backend.
MaterialModels allow to specify the refractive index, Abbe number, and partial dispersion of the material.
The partial dispersion is only used in the OpticStudio backend and is ignored in other backends.
Predefined material models#
Visisipy provides a number of predefined material models.
Most importantly, the NavarroMaterials class provides the material properties of the Navarro eye model.
This model has been fitted to the refractive indices reported by Escudero-Sanz and Navarro (1999) and works well for all visible wavelengths.
The model accuracy is slightly lower than the specific models for each wavelength, but it is still a good approximation.
Furthermore, material models are provided for all separate wavelengths as reported by Escudero-Sanz and Navarro (1999):
NavarroMaterials458: 458 nmNavarroMaterials543: 543 nmNavarroMaterials589: 589.3 nmNavarroMaterials633: 632.8 nm
Attention
The models for specific wavelengths have a constant refractive index. It is possible to use them with different wavelengths, but this will result in inaccurate results.
Custom material models#
It is also possible to use the EyeMaterials class to create custom material models.
These models can then be supplied to the EyeModel constructor.
from visisipy.models.materials import MaterialModel
custom_materials = visisipy.EyeMaterials(
cornea=MaterialModel(refractive_index=1.376, abbe_number=0, partial_dispersion=0),
aqueous=MaterialModel(refractive_index=1.336, abbe_number=0, partial_dispersion=0),
lens=MaterialModel(refractive_index=1.406, abbe_number=0, partial_dispersion=0),
vitreous=MaterialModel(refractive_index=1.336, abbe_number=0, partial_dispersion=0),
)
Building the model#
Let’s bring it all together!
After defining the eye model in terms of its geometry and materials, the model can be built in the backend using its build method.
final_model = visisipy.EyeModel(
geometry=default_navarro_geometry, materials=visisipy.models.materials.NavarroMaterials458()
)
final_model.build()
<visisipy.optiland.models.OptilandEye at 0x70d2b6139400>
If a backend has not yet been initialized, the default backend will be initialized and used to build the model. You can read more about that in the next chapter.
You can also pass a custom geometry or materials to the model constructor:
model_custom_materials = visisipy.EyeModel(
geometry=visisipy.create_geometry(axial_length=26, cornea_front_radius=8.0, lens_thickness=4),
materials=custom_materials,
)
Using predefined eye models#
Finally, it is also possible to start with a predefined model and adjust it by modifying its properties.
model_custom = visisipy.EyeModel()
# Change the lens thickness to 5 mm
model_custom.geometry.lens_front.thickness = 5
# Change the cornea's refractive index to 1.38
model_custom.materials.cornea.refractive_index = 1.38
Attention
It is not possible to modify the geometry through the convenience properties; these are read-only. Instead, you must directly change the properties of the optical surfaces, as demonstrated above.
Visisipy provides a number of predefined eye models in the visisipy.models.catalog module.
These include:
The Navarro eye model. This is the default model used by Visisipy, and it is what you get when you create an
EyeModelwithout any parameters.The Gullstrand-LeGrand eye model, which can be created using the
GullstrandLeGrandEyeModelclass.The Bennett-Rabbetts eye model, which can be created using the
BennettRabbettsEyeModelclass.
The predefined EyeModel classes are convenience wrappers around the respective geometry and material classes.
For example, the GullstrandLeGrandEyeModel class creates a GullstrandLeGrandGeometry and the appropriate material model based on the accommodation state, so the two examples below are equivalent:
gullstrand_model = visisipy.EyeModel(
geometry=visisipy.models.GullstrandLeGrandGeometry(accommodation="unaccommodated"),
materials=visisipy.models.materials.GullstrandLeGrandUnaccommodatedMaterials(),
)
gullstrand_model_2 = visisipy.models.GullstrandLeGrandEyeModel(accommodation="unaccommodated")