Optics API Reference
The deeplens.optics module is the core of DeepLens. It provides differentiable
lens models, optical surface primitives, light representations, and image
simulation utilities. All components are PyTorch-based and support gradient
backpropagation for end-to-end optimization.
Lens Models
All lens types inherit from Lens and share a common PSF/rendering API.
The table below summarises the available models and their intended use cases.
| Lens Type | Description | Use Case |
|---|---|---|
| GeoLens | Differentiable refractive ray tracing | High-accuracy simulation; automated lens design |
| HybridLens | Ray tracing + wave optics (DOE) | Hybrid refractive-diffractive systems |
| DiffractiveLens | Pure wave-optics propagation | DOEs and metasurfaces (no geometric aberrations) |
| PSFNetLens | Neural PSF surrogate | Fast inference; depth/field-varying PSF |
| ParaxialLens | Circle-of-Confusion thin lens | Quick defocus simulation, no aberrations |
Lens (base)
Base class inherited by every lens type. Defines the public API for PSF computation, image rendering, and sensor configuration.
deeplens.optics.lens.Lens
Bases: DeepObj
Initialize a lens class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dtype
|
dtype
|
Data type. Defaults to torch.float32. |
float32
|
device
|
str
|
Device to run the lens. Defaults to None. |
None
|
set_sensor
Set sensor size and resolution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sensor_size
|
tuple
|
Sensor size (w, h) in [mm]. |
required |
sensor_res
|
tuple
|
Sensor resolution (W, H) in [pixels]. |
required |
set_sensor_res
Set sensor resolution (and aspect ratio) while keeping sensor radius unchanged.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sensor_res
|
tuple
|
Sensor resolution (W, H) in [pixels]. |
required |
calc_fov
Compute FoV (radian) of the lens.
Reference
[1] https://en.wikipedia.org/wiki/Angle_of_view_(photography)
psf
Compute the monochromatic PSF for one or more point sources.
Subclasses must override this method with a differentiable implementation. Three computation models are common in practice: geometric ray binning, coherent ray-wave, and Huygens spherical-wave integration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
Point source coordinates, shape |
required |
wvln
|
float
|
Wavelength in micrometers. Defaults to
|
DEFAULT_WAVE
|
ks
|
int
|
Output PSF kernel size in pixels. Defaults
to |
PSF_KS
|
**kwargs
|
Additional keyword arguments forwarded to the underlying
PSF computation (e.g. |
{}
|
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: PSF intensity map, shape |
|
|
point or |
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
This base implementation must be overridden. |
Notes
The method is differentiable with respect to all optimisable lens parameters so it can be used directly inside a training loop.
Example
point = torch.tensor([0.0, 0.0, -10000.0]) psf = lens.psf(points=point, ks=64, model="geometric") print(psf.shape) # torch.Size([64, 64])
psf_rgb
Compute the RGB (tri-chromatic) PSF by stacking three wavelength calls.
Calls :meth:psf three times for the RGB primary wavelengths defined
in WAVE_RGB and stacks the results along the channel axis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
Point source coordinates, shape |
required |
ks
|
int
|
PSF kernel size. Defaults to |
PSF_KS
|
**kwargs
|
Forwarded to :meth: |
{}
|
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: RGB PSF, shape |
|
|
or |
point_source_grid
Generate point source grid for PSF calculation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
float
|
Depth of the point source. |
required |
grid
|
tuple
|
Grid size (grid_w, grid_h). Defaults to (9, 9), meaning 9x9 grid. |
(9, 9)
|
normalized
|
bool
|
Return normalized object source coordinates. Defaults to True, meaning object sources xy coordinates range from [-1, 1]. |
True
|
quater
|
bool
|
Use quater of the sensor plane to save memory. Defaults to False. |
False
|
center
|
bool
|
Use center of each patch. Defaults to True. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
point_source |
Normalized object source coordinates. Shape of [grid_h, grid_w, 3], [-1, 1], [-1, 1], [-Inf, 0]. |
psf_map
Compute monochrome PSF map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grid
|
tuple
|
Grid size (grid_w, grid_h). Defaults to (5, 5), meaning 5x5 grid. |
(5, 5)
|
wvln
|
float
|
Wavelength. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
depth
|
float
|
Depth of the object. Defaults to DEPTH. |
DEPTH
|
ks
|
int
|
Kernel size. Defaults to PSF_KS. |
PSF_KS
|
Returns:
| Name | Type | Description |
|---|---|---|
psf_map |
Shape of [grid_h, grid_w, 3, ks, ks]. |
psf_map_rgb
Compute RGB PSF map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grid
|
tuple
|
Grid size (grid_w, grid_h). Defaults to (5, 5), meaning 5x5 grid. |
(5, 5)
|
ks
|
int
|
Kernel size. Defaults to PSF_KS, meaning PSF_KS x PSF_KS kernel size. |
PSF_KS
|
depth
|
float
|
Depth of the object. Defaults to DEPTH. |
DEPTH
|
**kwargs
|
Additional arguments for psf_map(). |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
psf_map |
Shape of [grid_h, grid_w, 3, ks, ks]. |
draw_psf_map
draw_psf_map(grid=(7, 7), ks=PSF_KS, depth=DEPTH, log_scale=False, save_name='./psf_map.png', show=False)
Draw RGB PSF map of the lens.
point_source_radial
Compute point radial [0, 1] in the object space to compute PSF grid.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grid
|
int
|
Grid size. Defaults to 9. |
9
|
Returns:
| Name | Type | Description |
|---|---|---|
point_source |
Shape of [grid, 3]. |
draw_psf_radial
Draw radial PSF (45 deg). Will draw M PSFs, each of size ks x ks.
render
Differentiable image simulation for a 2D (flat) scene.
Performs only the optical component of image simulation and is fully
differentiable. Sensor noise is handled separately by the
:class:~deeplens.camera.Camera class.
For incoherent imaging the intensity PSF is convolved with the object-space image. For coherent imaging the complex PSF is convolved with the complex object image before squaring for intensity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img_obj
|
Tensor
|
Input image in linear (raw) space,
shape |
required |
depth
|
float
|
Object depth in mm (negative value).
Defaults to |
DEPTH
|
method
|
str
|
Rendering method. One of:
|
'psf_patch'
|
**kwargs
|
Method-specific keyword arguments:
|
{}
|
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Rendered image, shape |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If method is |
Exception
|
If method is not recognised. |
References
[1] "Optical Aberration Correction in Postprocessing using Imaging Simulation", TOG 2021. [2] "Efficient depth- and spatially-varying image simulation for defocus deblur", ICCVW 2025.
Example
img_rendered = lens.render(img, depth=-10000.0, method="psf_patch", ... patch_center=(0.3, 0.0), psf_ks=64)
render_psf
Render image patch using PSF convolution. Better not use this function to avoid confusion.
render_psf_patch
Render an image patch using PSF convolution, and return positional encoding channel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img_obj
|
tensor
|
Input image object in raw space. Shape of [B, C, H, W]. |
required |
depth
|
float
|
Depth of the object. |
DEPTH
|
patch_center
|
tensor
|
Center of the image patch. Shape of [2] or [B, 2]. |
(0, 0)
|
psf_ks
|
int
|
PSF kernel size. Defaults to PSF_KS. |
PSF_KS
|
Returns:
| Name | Type | Description |
|---|---|---|
img_render |
Rendered image. Shape of [B, C, H, W]. |
render_psf_map
Render image using PSF block convolution.
Note
Larger psf_grid and psf_ks are typically better for more accurate rendering, but slower.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img_obj
|
tensor
|
Input image object in raw space. Shape of [B, C, H, W]. |
required |
depth
|
float
|
Depth of the object. |
DEPTH
|
psf_grid
|
int
|
PSF grid size. |
7
|
psf_ks
|
int
|
PSF kernel size. Defaults to PSF_KS. |
PSF_KS
|
Returns:
| Name | Type | Description |
|---|---|---|
img_render |
Rendered image. Shape of [B, C, H, W]. |
_sample_depth_layers
Sample depth layers centered on the focal plane in disparity space.
If the lens has a calc_focal_plane method, samples are split around the
focal plane so that it is always an explicit sample point. Otherwise falls
back to uniform disparity sampling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth_min
|
float
|
Minimum (nearest) depth in mm (positive). |
required |
depth_max
|
float
|
Maximum (farthest) depth in mm (positive). |
required |
num_layers
|
int
|
Number of depth layers to sample. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
(disp_ref, depths_ref) where disp_ref has shape (num_layers,) in disparity space and depths_ref = -1/disp_ref (negative, for PSF). |
render_rgbd
Render RGBD image.
TODO: add obstruction-aware image simulation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img_obj
|
tensor
|
Object image. Shape of [B, C, H, W]. |
required |
depth_map
|
tensor
|
Depth map [mm]. Shape of [B, 1, H, W]. Values should be positive. |
required |
method
|
str
|
Image simulation method. Defaults to "psf_patch". |
'psf_patch'
|
**kwargs
|
Additional arguments for different methods. - interp_mode (str): "depth" or "disparity". Defaults to "depth". |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
img_render |
Rendered image. Shape of [B, C, H, W]. |
Reference
[1] "Aberration-Aware Depth-from-Focus", TPAMI 2023. [2] "Efficient Depth- and Spatially-Varying Image Simulation for Defocus Deblur", ICCVW 2025.
get_optimizer_params
Get optimizer parameters for different lens parameters.
GeoLens
The primary differentiable lens model. Uses vectorised PyTorch ray tracing through multi-element refractive surfaces.
from deeplens import GeoLens
lens = GeoLens(filename='./datasets/lenses/camera/ef50mm_f1.8.json', device='cuda')
# PSF at a point
import torch
psf = lens.psf(points=torch.tensor([0.0, 0.0, -10000.0]), ks=64, spp=4096)
# Image rendering
img_rendered = lens.render(img, depth=-10000.0, method='psf_map', psf_grid=(7, 7))
# Gradient-based optimisation
optimizer = lens.get_optimizer(lrs=[1e-3, 1e-4, 0, 0], decay=0.01)
Note
Parenthesised keys like "(d)" in JSON lens files mark optimisable parameters.
deeplens.optics.geolens.GeoLens
Bases: Lens, GeoLensEval, GeoLensOptim, GeoLensVis, GeoLensIO, GeoLensTolerance, GeoLensVis3D
Differentiable geometric lens using vectorised ray tracing.
The primary lens model in DeepLens. Supports multi-element refractive
(and partially reflective) systems loaded from JSON, Zemax .zmx, or
Code V .seq files. Accuracy is aligned with Zemax OpticStudio.
Uses a mixin architecture – six specialised mixin classes are composed at class definition time to keep each concern isolated:
- :class:
~deeplens.optics.geolens_pkg.eval.GeoLensEval– optical performance evaluation (spot, MTF, distortion, vignetting). - :class:
~deeplens.optics.geolens_pkg.optim.GeoLensOptim– loss functions and gradient-based optimisation. - :class:
~deeplens.optics.geolens_pkg.vis.GeoLensVis– 2-D layout and ray visualisation. - :class:
~deeplens.optics.geolens_pkg.io.GeoLensIO– read/write JSON, Zemax.zmx. - :class:
~deeplens.optics.geolens_pkg.tolerance.GeoLensTolerance– manufacturing tolerance analysis. - :class:
~deeplens.optics.geolens_pkg.view_3d.GeoLensVis3D– 3-D mesh visualisation.
Key differentiability trick: Ray-surface intersection
(:meth:~deeplens.optics.geometric_surface.base.Surface.newtons_method)
uses a non-differentiable Newton loop followed by one differentiable
Newton step to enable gradient flow.
Attributes:
| Name | Type | Description |
|---|---|---|
surfaces |
list[Surface]
|
Ordered list of optical surfaces. |
materials |
list[Material]
|
Optical materials between surfaces. |
d_sensor |
Tensor
|
Back focal distance [mm]. |
foclen |
float
|
Effective focal length [mm]. |
fnum |
float
|
F-number. |
rfov |
float
|
Half-diagonal field of view [radians]. |
sensor_size |
tuple
|
Physical sensor size (W, H) [mm]. |
sensor_res |
tuple
|
Sensor resolution (W, H) [pixels]. |
pixel_size |
float
|
Pixel pitch [mm]. |
References
Xinge Yang et al., "Curriculum learning for ab initio deep learned refractive optics," Nature Communications 2024.
Initialize a refractive lens.
There are two ways to initialize a GeoLens
- Read a lens from .json/.zmx/.seq file
- Initialize a lens with no lens file, then manually add surfaces and materials
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to lens file (.json, .zmx, or .seq). Defaults to None. |
None
|
device
|
device
|
Device for tensor computations. Defaults to None. |
None
|
dtype
|
dtype
|
Data type for computations. Defaults to torch.float32. |
float32
|
read_lens
Read a GeoLens from a file.
Supported file formats
- .json: DeepLens native JSON format
- .zmx: Zemax lens file format
- .seq: CODE V sequence file format
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to the lens file. |
required |
Note
Sensor size and resolution will usually be overwritten by values from the file.
post_computation
Compute derived optical properties after loading or modifying lens.
Calculates and caches
- Effective focal length (EFL)
- Entrance and exit pupil positions and radii
- Field of view (FoV) in horizontal, vertical, and diagonal directions
- F-number
Note
This method should be called after any changes to the lens geometry.
__call__
Trace rays through the lens system.
Makes the GeoLens callable, allowing ray tracing with function call syntax.
sample_grid_rays
sample_grid_rays(depth=float('inf'), num_grid=(11, 11), num_rays=SPP_PSF, wvln=DEFAULT_WAVE, uniform_fov=True, sample_more_off_axis=False, scale_pupil=1.0)
Sample grid rays from object space. (1) If depth is infinite, sample parallel rays at different field angles. (2) If depth is finite, sample point source rays from the object plane.
This function is usually used for (1) PSF map, (2) RMS error map, and (3) spot diagram calculation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
float
|
sampling depth. Defaults to float("inf"). |
float('inf')
|
num_grid
|
tuple
|
number of grid points. Defaults to [11, 11]. |
(11, 11)
|
num_rays
|
int
|
number of rays. Defaults to SPP_PSF. |
SPP_PSF
|
wvln
|
float
|
ray wvln. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
uniform_fov
|
bool
|
If True, sample uniform FoV angles. |
True
|
sample_more_off_axis
|
bool
|
If True, sample more off-axis rays. |
False
|
scale_pupil
|
float
|
Scale factor for pupil radius. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
ray |
Ray object
|
Ray object. Shape [num_grid[1], num_grid[0], num_rays, 3] |
sample_radial_rays
Sample radial (meridional, y direction) rays at different field angles.
This function is usually used for (1) PSF radial map, and (2) RMS error radial map calculation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_field
|
int
|
number of field angles. Defaults to 5. |
5
|
depth
|
float
|
sampling depth. Defaults to float("inf"). |
float('inf')
|
num_rays
|
int
|
number of rays. Defaults to SPP_PSF. |
SPP_PSF
|
wvln
|
float
|
ray wvln. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
Returns:
| Name | Type | Description |
|---|---|---|
ray |
Ray object
|
Ray object. Shape [num_field, num_rays, 3] |
sample_from_points
sample_from_points(points=[[0.0, 0.0, -10000.0]], num_rays=SPP_PSF, wvln=DEFAULT_WAVE, scale_pupil=1.0)
Sample rays from point sources in object space (absolute physical coordinates).
Used for PSF and chief ray calculation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
list or Tensor
|
Ray origins in shape [3], [N, 3], or [Nx, Ny, 3]. |
[[0.0, 0.0, -10000.0]]
|
num_rays
|
int
|
Number of rays per point. Default: SPP_PSF. |
SPP_PSF
|
wvln
|
float
|
Wavelength of rays. Default: DEFAULT_WAVE. |
DEFAULT_WAVE
|
scale_pupil
|
float
|
Scale factor for pupil radius. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
Ray |
Sampled rays with shape |
sample_parallel
sample_parallel(fov_x=[0.0], fov_y=[0.0], num_rays=SPP_CALC, wvln=DEFAULT_WAVE, entrance_pupil=True, depth=-1.0, scale_pupil=1.0)
Sample parallel rays in object space for geometric optics calculations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fov_x
|
float or list
|
Field angle(s) in the xz plane (degrees). Default: [0.0]. |
[0.0]
|
fov_y
|
float or list
|
Field angle(s) in the yz plane (degrees). Default: [0.0]. |
[0.0]
|
num_rays
|
int
|
Number of rays per field point. Default: SPP_CALC. |
SPP_CALC
|
wvln
|
float
|
Wavelength of rays. Default: DEFAULT_WAVE. |
DEFAULT_WAVE
|
entrance_pupil
|
bool
|
If True, sample origins on entrance pupil; otherwise, on surface 0. Default: True. |
True
|
depth
|
float
|
Propagation depth in z. Default: -1.0. |
-1.0
|
scale_pupil
|
float
|
Scale factor for pupil radius. Default: 1.0. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
Ray |
Rays with shape [..., num_rays, 3], where leading dims are: - both fov_x and fov_y scalars: [num_rays, 3] - fov_x scalar: [len(fov_y), num_rays, 3] - fov_y scalar: [len(fov_x), num_rays, 3] - both lists: [len(fov_y), len(fov_x), num_rays, 3] Ordered as (u, v). |
sample_point_source
sample_point_source(fov_x=[0.0], fov_y=[0.0], depth=DEPTH, num_rays=SPP_PSF, wvln=DEFAULT_WAVE, entrance_pupil=True, scale_pupil=1.0)
Sample point source rays from object space with given field angles.
Used for (1) spot/rms/magnification calculation, (2) distortion/sensor sampling.
This function is equivalent to self.point_source_grid() + self.sample_from_points().
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fov_x
|
float or list
|
field angle in x0z plane. |
[0.0]
|
fov_y
|
float or list
|
field angle in y0z plane. |
[0.0]
|
depth
|
float
|
sample plane z position. Defaults to -10.0. |
DEPTH
|
num_rays
|
int
|
number of rays sampled from each grid point. Defaults to 16. |
SPP_PSF
|
entrance_pupil
|
bool
|
whether to use entrance pupil. Defaults to False. |
True
|
wvln
|
float
|
ray wvln. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
Returns:
| Name | Type | Description |
|---|---|---|
ray |
Ray object
|
Ray object. Shape [len(fov_y), len(fov_x), num_rays, 3], arranged in uv order. |
sample_sensor
Sample rays from sensor pixels (backward rays). Used for ray tracing rendering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
spp
|
int
|
sample per pixel. Defaults to 64. |
64
|
pupil
|
bool
|
whether to use pupil. Defaults to True. |
required |
wvln
|
float
|
ray wvln. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
sub_pixel
|
bool
|
whether to sample multiple points inside the pixel. Defaults to False. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
ray |
Ray object
|
Ray object. Shape [H, W, spp, 3] |
sample_circle
Sample points inside a circle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
r
|
float
|
Radius of the circle. |
required |
z
|
float
|
Z-coordinate for all sampled points. |
required |
shape
|
list
|
Shape of the output tensor. |
[16, 16, 512]
|
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Sampled points, shape |
trace
Trace rays through the lens.
Forward or backward tracing is automatically determined by the ray direction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray object
|
Ray object. |
required |
surf_range
|
list
|
Surface index range. |
None
|
record
|
bool
|
record ray path or not. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
ray_final |
Ray object
|
ray after optical system. |
ray_o_rec |
list
|
list of intersection points. |
trace2obj
Traces rays backwards through all lens surfaces from sensor side to object side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
Ray object to trace backwards. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Ray |
Ray object after backward propagation through the lens. |
trace2sensor
Forward trace rays through the lens to sensor plane.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray object
|
Ray object. |
required |
record
|
bool
|
record ray path or not. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
ray_out |
Ray object
|
ray after optical system. |
ray_o_record |
list
|
list of intersection points. |
trace2exit_pupil
Forward trace rays through the lens to exit pupil plane.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
Ray object to trace. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Ray |
Ray object propagated to the exit pupil plane. |
forward_tracing
Forward traces rays through each surface in the specified range from object side to image side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
Ray object to trace. |
required |
surf_range
|
range
|
Range of surface indices to trace through. |
required |
record
|
bool
|
If True, record ray positions at each surface. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
(ray_out, ray_o_record) where: - ray_out (Ray): Ray after propagation through all surfaces. - ray_o_record (list or None): List of ray positions at each surface, or None if record is False. |
backward_tracing
Backward traces rays through each surface in reverse order from image side to object side.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
Ray object to trace. |
required |
surf_range
|
range
|
Range of surface indices to trace through. |
required |
record
|
bool
|
If True, record ray positions at each surface. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
(ray_out, ray_o_record) where: - ray_out (Ray): Ray after backward propagation through all surfaces. - ray_o_record (list or None): List of ray positions at each surface, or None if record is False. |
render
Differentiable image simulation.
Image simulation methods
[1] PSF map block convolution. [2] PSF patch convolution. [3] Ray tracing rendering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img_obj
|
Tensor
|
Input image object in raw space. Shape of [N, C, H, W]. |
required |
depth
|
float
|
Depth of the object. Defaults to DEPTH. |
DEPTH
|
method
|
str
|
Image simulation method. One of 'psf_map', 'psf_patch', or 'ray_tracing'. Defaults to 'ray_tracing'. |
'ray_tracing'
|
**kwargs
|
Additional arguments for different methods: - psf_grid (tuple): Grid size for PSF map method. Defaults to (10, 10). - psf_ks (int): Kernel size for PSF methods. Defaults to PSF_KS. - patch_center (tuple): Center position for PSF patch method. - spp (int): Samples per pixel for ray tracing. Defaults to SPP_RENDER. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
Tensor |
Rendered image tensor. Shape of [N, C, H, W]. |
render_raytracing
Render RGB image using ray tracing rendering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
tensor
|
RGB image tensor. Shape of [N, 3, H, W]. |
required |
depth
|
float
|
Depth of the object. Defaults to DEPTH. |
DEPTH
|
spp
|
int
|
Sample per pixel. Defaults to 64. |
SPP_RENDER
|
vignetting
|
bool
|
whether to consider vignetting effect. Defaults to False. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
img_render |
tensor
|
Rendered RGB image tensor. Shape of [N, 3, H, W]. |
render_raytracing_mono
Render monochrome image using ray tracing rendering.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
tensor
|
Monochrome image tensor. Shape of [N, 1, H, W] or [N, H, W]. |
required |
wvln
|
float
|
Wavelength of the light. |
required |
depth
|
float
|
Depth of the object. Defaults to DEPTH. |
DEPTH
|
spp
|
int
|
Sample per pixel. Defaults to 64. |
64
|
Returns:
| Name | Type | Description |
|---|---|---|
img_mono |
tensor
|
Rendered monochrome image tensor. Shape of [N, 1, H, W] or [N, H, W]. |
render_compute_image
Computes the intersection points between rays and the object image plane, then generates the rendered image following rendering equation.
Back-propagation gradient flow: image -> w_i -> u -> p -> ray -> surface
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
tensor
|
[N, C, H, W] or [N, H, W] shape image tensor. |
required |
depth
|
float
|
depth of the object. |
required |
scale
|
float
|
scale factor. |
required |
ray
|
Ray object
|
Ray object. Shape [H, W, spp, 3]. |
required |
vignetting
|
bool
|
whether to consider vignetting effect. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
image |
tensor
|
[N, C, H, W] or [N, H, W] shape rendered image tensor. |
unwarp
Unwarp rendered images using distortion map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
tensor
|
Rendered image tensor. Shape of [N, C, H, W]. |
required |
depth
|
float
|
Depth of the object. Defaults to DEPTH. |
DEPTH
|
grid_size
|
int
|
Grid size. Defaults to 256. |
required |
crop
|
bool
|
Whether to crop the image. Defaults to True. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
img_unwarpped |
tensor
|
Unwarped image tensor. Shape of [N, C, H, W]. |
analysis_rendering
analysis_rendering(img_org, save_name=None, depth=DEPTH, spp=SPP_RENDER, unwarp=False, noise=0.0, method='ray_tracing', show=False)
Render a single image for visualization and analysis.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img_org
|
Tensor
|
Original image with shape [H, W, 3]. |
required |
save_name
|
str
|
Path prefix for saving rendered images. Defaults to None. |
None
|
depth
|
float
|
Depth of object image. Defaults to DEPTH. |
DEPTH
|
spp
|
int
|
Sample per pixel. Defaults to SPP_RENDER. |
SPP_RENDER
|
unwarp
|
bool
|
If True, unwarp the image to correct distortion. Defaults to False. |
False
|
noise
|
float
|
Gaussian noise standard deviation. Defaults to 0.0. |
0.0
|
method
|
str
|
Rendering method ('ray_tracing', etc.). Defaults to 'ray_tracing'. |
'ray_tracing'
|
show
|
bool
|
If True, display the rendered image. Defaults to False. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
Tensor |
Rendered image tensor with shape [1, 3, H, W]. |
psf
Calculate Point Spread Function (PSF) for given point sources.
Supports multiple PSF calculation models
- geometric: Incoherent intensity ray tracing (fast, differentiable)
- coherent: Coherent ray tracing with free-space propagation (accurate, differentiable)
- huygens: Huygens-Fresnel integration (accurate, not differentiable)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
Point source positions. Shape [N, 3] with x, y in [-1, 1] and z in [-Inf, 0]. Normalized coordinates. |
required |
ks
|
int
|
Output kernel size in pixels. Defaults to PSF_KS. |
PSF_KS
|
wvln
|
float
|
Wavelength in [um]. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
spp
|
int
|
Samples per pixel. If None, uses model-specific default. |
None
|
recenter
|
bool
|
If True, center PSF using chief ray. Defaults to True. |
True
|
model
|
str
|
PSF model type. One of 'geometric', 'coherent', 'huygens'. Defaults to 'geometric'. |
'geometric'
|
Returns:
| Name | Type | Description |
|---|---|---|
Tensor |
PSF normalized to sum to 1. Shape [ks, ks] or [N, ks, ks]. |
psf_geometric
Single wavelength geometric PSF calculation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
Normalized point source position. Shape of [N, 3], x, y in range [-1, 1], z in range [-Inf, 0]. |
required |
ks
|
int
|
Output kernel size. |
PSF_KS
|
wvln
|
float
|
Wavelength. |
DEFAULT_WAVE
|
spp
|
int
|
Sample per pixel. |
SPP_PSF
|
recenter
|
bool
|
Recenter PSF using chief ray. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
psf |
Shape of [ks, ks] or [N, ks, ks]. |
References
[1] https://optics.ansys.com/hc/en-us/articles/42661723066515-What-is-a-Point-Spread-Function
psf_coherent
Alias for psf_pupil_prop. Calculates PSF by coherent ray tracing to exit pupil followed by Angular Spectrum Method (ASM) propagation.
psf_pupil_prop
Single point monochromatic PSF using exit-pupil diffraction model. This function is differentiable.
Steps
1, Calculate complex wavefield at exit-pupil plane by coherent ray tracing. 2, Free-space propagation to sensor plane and calculate intensity PSF.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
[x, y, z] coordinates of the point source. Defaults to torch.Tensor([0,0,-10000]). |
required |
ks
|
int
|
size of the PSF patch. Defaults to PSF_KS. |
PSF_KS
|
wvln
|
float
|
wvln. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
spp
|
int
|
number of rays to sample. Defaults to SPP_COHERENT. |
SPP_COHERENT
|
recenter
|
bool
|
Recenter PSF using chief ray. Defaults to True. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
psf_out |
Tensor
|
PSF patch. Normalized to sum to 1. Shape [ks, ks] |
Reference
[1] "End-to-End Hybrid Refractive-Diffractive Lens Design with Differentiable Ray-Wave Model", SIGGRAPH Asia 2024.
Note
[1] This function is similar to ZEMAX FFT_PSF but implement free-space propagation with Angular Spectrum Method (ASM) rather than FFT transform. Free-space propagation using ASM is more accurate than doing FFT, because FFT (as used in ZEMAX) assumes far-field condition (e.g., chief ray perpendicular to image plane).
pupil_field
Compute complex wavefront at exit pupil plane by coherent ray tracing.
The wavefront is flipped for subsequent PSF calculation and has the same size as the image sensor. This function is differentiable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor or list
|
Single point source position. Shape [3] or [1, 3], with x, y in [-1, 1] and z in [-Inf, 0]. |
required |
wvln
|
float
|
Wavelength in [um]. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
spp
|
int
|
Number of rays to sample. Must be >= 1,000,000 for accurate coherent simulation. Defaults to SPP_COHERENT. |
SPP_COHERENT
|
recenter
|
bool
|
If True, center using chief ray. Defaults to True. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
(wavefront, psf_center) where: - wavefront (Tensor): Complex wavefront at exit pupil. Shape [H, H]. - psf_center (list): Normalized PSF center coordinates [x, y] in [-1, 1]. |
Note
Default dtype must be torch.float64 for accurate phase calculation.
psf_huygens
Single wavelength Huygens PSF calculation.
This function is not differentiable due to its heavy computational cost.
Steps
1, Trace coherent rays to exit-pupil plane. 2, Treat every ray as a secondary point source emitting a spherical wave.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
Normalized point source position. Shape of [N, 3], x, y in range [-1, 1], z in range [-Inf, 0]. |
required |
ks
|
int
|
Output kernel size. |
PSF_KS
|
wvln
|
float
|
Wavelength. |
DEFAULT_WAVE
|
spp
|
int
|
Sample per pixel. |
SPP_COHERENT
|
recenter
|
bool
|
Recenter PSF using chief ray. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
psf |
Shape of [ks, ks] or [N, ks, ks]. |
References
[1] "Optical Aberrations Correction in Postprocessing Using Imaging Simulation", TOG 2021
Note
This is different from ZEMAX Huygens PSF, which traces rays to image plane and do plane wave integration.
psf_map
Compute the geometric PSF map at given depth.
Overrides the base method in Lens class to improve efficiency by parallel ray tracing over different field points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
float
|
Depth of the object plane. Defaults to DEPTH. |
DEPTH
|
grid
|
(int, tuple)
|
Grid size (grid_w, grid_h). Defaults to 7. |
(7, 7)
|
ks
|
int
|
Kernel size. Defaults to PSF_KS. |
PSF_KS
|
spp
|
int
|
Sample per pixel. Defaults to SPP_PSF. |
SPP_PSF
|
recenter
|
bool
|
Recenter PSF using chief ray. Defaults to True. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
psf_map |
PSF map. Shape of [grid_h, grid_w, 1, ks, ks]. |
psf_center
Compute reference PSF center (flipped to match the original point) for given point source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points_obj
|
[..., 3] un-normalized point in object plane. [-Inf, Inf] * [-Inf, Inf] * [-Inf, 0] |
required | |
method
|
"chief_ray" or "pinhole". Defaults to "chief_ray". |
'chief_ray'
|
Returns:
| Name | Type | Description |
|---|---|---|
psf_center |
[..., 2] un-normalized psf center in sensor plane. |
analysis_spot
Compute sensor plane ray spot RMS error and radius.
Analyzes spot sizes across the field of view for multiple wavelengths (red, green, blue) and reports statistics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_field
|
int
|
Number of field positions to analyze along the radial direction. Defaults to 3. |
3
|
depth
|
float
|
Depth of the point source. Use float('inf') for collimated light. Defaults to float('inf'). |
float('inf')
|
Returns:
| Name | Type | Description |
|---|---|---|
dict |
Spot analysis results keyed by field position (e.g., 'fov0.0', 'fov0.5'). Each entry contains 'rms' (RMS radius in um) and 'radius' (geometric radius in um). |
find_diff_surf
Get differentiable/optimizable surface indices.
Returns a list of surface indices that can be optimized during lens design. Excludes the aperture surface from optimization.
Returns:
| Type | Description |
|---|---|
|
list or range: Surface indices excluding the aperture. |
calc_foclen
Compute effective focal length (EFL).
Traces a paraxial chief ray and computes the image height, then uses the image height to compute the EFL.
Updates
self.efl: Effective focal length. self.foclen: Alias for effective focal length. self.bfl: Back focal length (distance from last surface to sensor).
Reference
[1] https://wp.optics.arizona.edu/optomech/wp-content/uploads/sites/53/2016/10/Tutorial_MorelSophie.pdf [2] https://rafcamera.com/info/imaging-theory/back-focal-length
calc_numerical_aperture
Compute numerical aperture (NA).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n
|
float
|
Refractive index. Defaults to 1.0. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
NA |
float
|
Numerical aperture. |
Reference
[1] https://en.wikipedia.org/wiki/Numerical_aperture
calc_focal_plane
Compute the focus distance in the object space. Ray starts from sensor center and traces to the object space.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wvln
|
float
|
Wavelength. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
Returns:
| Name | Type | Description |
|---|---|---|
focal_plane |
float
|
Focal plane in the object space. |
calc_sensor_plane
Calculate in-focus sensor plane.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
float
|
Depth of the object plane. Defaults to float("inf"). |
float('inf')
|
Returns:
| Name | Type | Description |
|---|---|---|
d_sensor |
Tensor
|
Sensor plane in the image space. |
calc_fov
Compute FoV (radian) of the lens.
We implement two types of FoV calculation
- Perspective projection from focal length and sensor size.
- Ray tracing to compute output ray angle.
Reference
[1] https://en.wikipedia.org/wiki/Angle_of_view_(photography)
calc_scale
Calculate the scale factor (object height / image height).
Uses the pinhole camera model to compute magnification.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
float
|
Object distance from the lens (negative z direction). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
float |
Scale factor relating object height to image height. |
calc_pupil
Compute entrance and exit pupil positions and radii.
The entrance and exit pupils must be recalculated whenever
- First-order parameters change (e.g., field of view, object height, image height),
- Lens geometry or materials change (e.g., surface curvatures, refractive indices, thicknesses),
- Or generally, any time the lens configuration is modified.
Updates
self.aper_idx: Index of the aperture surface. self.exit_pupilz, self.exit_pupilr: Exit pupil position and radius. self.entr_pupilz, self.entr_pupilr: Entrance pupil position and radius. self.exit_pupilz_parax, self.exit_pupilr_parax: Paraxial exit pupil. self.entr_pupilz_parax, self.entr_pupilr_parax: Paraxial entrance pupil. self.fnum: F-number calculated from focal length and entrance pupil.
get_entrance_pupil
Get entrance pupil location and radius.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
paraxial
|
bool
|
If True, return paraxial approximation values. If False, return real ray-traced values. Defaults to False. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
(z_position, radius) of the entrance pupil in [mm]. |
get_exit_pupil
Get exit pupil location and radius.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
paraxial
|
bool
|
If True, return paraxial approximation values. If False, return real ray-traced values. Defaults to False. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
(z_position, radius) of the exit pupil in [mm]. |
calc_exit_pupil
Calculate exit pupil location and radius.
Paraxial mode
Rays are emitted from near the center of the aperture stop and are close to the optical axis. This mode estimates the exit pupil position and radius under ideal (first-order) optical assumptions. It is fast and stable.
Non-paraxial mode
Rays are emitted from the edge of the aperture stop in large quantities. The exit pupil position and radius are determined based on the intersection points of these rays. This mode is slower and affected by aperture-related aberrations.
Use paraxial mode unless precise ray aiming is required.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
paraxial
|
bool
|
center (True) or edge (False). |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
avg_pupilz |
float
|
z coordinate of exit pupil. |
avg_pupilr |
float
|
radius of exit pupil. |
Reference
[1] Exit pupil: how many rays can come from sensor to object space. [2] https://en.wikipedia.org/wiki/Exit_pupil
calc_entrance_pupil
Calculate entrance pupil of the lens.
The entrance pupil is the optical image of the physical aperture stop, as seen through the optical elements in front of the stop. We sample backward rays from the aperture stop and trace them to the first surface, then find the intersection points of the reverse extension of the rays. The average of the intersection points defines the entrance pupil position and radius.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
paraxial
|
bool
|
Ray sampling mode. If |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
(z_position, radius) of entrance pupil. |
Note
[1] Use paraxial mode unless precise ray aiming is required. [2] This function only works for object at a far distance. For microscopes, this function usually returns a negative entrance pupil.
References
[1] Entrance pupil: how many rays can come from object space to sensor. [2] https://en.wikipedia.org/wiki/Entrance_pupil: "In an optical system, the entrance pupil is the optical image of the physical aperture stop, as 'seen' through the optical elements in front of the stop." [3] Zemax LLC, OpticStudio User Manual, Version 19.4, Document No. 2311, 2019.
compute_intersection_points_2d
staticmethod
Compute the intersection points of 2D lines.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
origins
|
Tensor
|
Origins of the lines. Shape: [N, 2] |
required |
directions
|
Tensor
|
Directions of the lines. Shape: [N, 2] |
required |
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Intersection points. Shape: [N*(N-1)/2, 2] |
refocus
Refocus the lens to a depth distance by changing sensor position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
foc_dist
|
float
|
focal distance. |
float('inf')
|
Note
In DSLR, phase detection autofocus (PDAF) is a popular and efficient method. But here we simplify the problem by calculating the in-focus position of green light.
set_fnum
Set F-number and aperture radius using binary search.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fnum
|
float
|
target F-number. |
required |
set_target_fov_fnum
Set FoV, ImgH and F number, only use this function to assign design targets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rfov
|
float
|
half diagonal-FoV in radian. |
required |
fnum
|
float
|
F number. |
required |
set_fov
Set FoV. This function is used to assign design targets.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rfov
|
float
|
half diagonal-FoV in radian. |
required |
prune_surf
Prune surfaces to allow all valid rays to go through.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
expand_factor
|
float
|
height expansion factor. - For cellphone lens, we usually expand by 5% - For camera lens, we usually expand by 20%. |
None
|
correct_shape
Correct wrong lens shape during lens design optimization.
Applies correction rules to ensure valid lens geometry
- Move the first surface to z = 0.0
- Fix aperture distance if aperture is at the front
- Prune all surfaces to allow valid rays through
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
expand_factor
|
float
|
Height expansion factor for surface pruning. If None, auto-selects based on lens type. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
bool |
True if any shape corrections were made, False otherwise. |
match_materials
Match lens materials to a glass catalog.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mat_table
|
str
|
Glass catalog name. Common options include 'CDGM', 'SCHOTT', 'OHARA'. Defaults to 'CDGM'. |
'CDGM'
|
analysis
analysis(save_name='./lens', depth=float('inf'), render=False, render_unwarp=False, lens_title=None, show=False)
Analyze the optical lens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_name
|
str
|
save name. |
'./lens'
|
depth
|
float
|
object depth distance. |
float('inf')
|
render
|
bool
|
whether render an image. |
False
|
render_unwarp
|
bool
|
whether unwarp the rendered image. |
False
|
lens_title
|
str
|
lens title |
None
|
show
|
bool
|
whether to show the rendered image. |
False
|
get_optimizer_params
get_optimizer_params(lrs=[0.0001, 0.0001, 0.01, 0.0001], decay=0.01, optim_mat=False, optim_surf_range=None)
Get optimizer parameters for different lens surface.
Recommendation
For cellphone lens: [d, c, k, a], [1e-4, 1e-4, 1e-1, 1e-4] For camera lens: [d, c, 0, 0], [1e-3, 1e-4, 0, 0]
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lrs
|
list
|
learning rate for different parameters. |
[0.0001, 0.0001, 0.01, 0.0001]
|
decay
|
float
|
decay rate for higher order a. Defaults to 0.01. |
0.01
|
optim_mat
|
bool
|
whether to optimize material. Defaults to False. |
False
|
optim_surf_range
|
list
|
surface indices to be optimized. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
list |
optimizer parameters |
get_optimizer
get_optimizer(lrs=[0.0001, 0.0001, 0.1, 0.0001], decay=0.01, optim_surf_range=None, optim_mat=False)
Get optimizers and schedulers for different lens parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lrs
|
list
|
learning rate for different parameters [c, d, k, a]. Defaults to [1e-4, 1e-4, 0, 1e-4]. |
[0.0001, 0.0001, 0.1, 0.0001]
|
decay
|
float
|
decay rate for higher order a. Defaults to 0.2. |
0.01
|
optim_surf_range
|
list
|
surface indices to be optimized. Defaults to None. |
None
|
optim_mat
|
bool
|
whether to optimize material. Defaults to False. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
list |
optimizer parameters |
read_lens_json
Read the lens from a JSON file.
Loads lens configuration including surfaces, materials, and optical properties from the DeepLens native JSON format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to the JSON lens file. Defaults to './test.json'. |
'./test.json'
|
Note
After loading, the lens is moved to self.device and post_computation is called to calculate derived properties.
write_lens_json
Write the lens to a JSON file.
Saves the complete lens configuration including all surfaces, materials, focal length, F-number, and sensor properties to the DeepLens JSON format.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path for the output JSON file. Defaults to './test.json'. |
'./test.json'
|
HybridLens
Couples a GeoLens with a diffractive optical element (DOE). Uses a
differentiable ray–wave pipeline: coherent ray tracing → DOE phase modulation →
Angular Spectrum Method propagation to sensor.
import torch
from deeplens.optics import HybridLens
torch.set_default_dtype(torch.float64) # required for wave optics
lens = HybridLens(filename='./datasets/lenses/hybrid/example.json', device='cuda')
lens.double()
# Access refractive and diffractive parts separately
print(lens.geolens.foclen)
print(type(lens.doe)) # Binary2 / Pixel2D / Fresnel / Zernike
Note
Operates in torch.float64 by default for numerical stability.
deeplens.optics.hybridlens.HybridLens
Bases: Lens
Hybrid refractive-diffractive lens using a differentiable ray–wave model.
Combines a :class:~deeplens.optics.geolens.GeoLens (refractive module)
with a diffractive optical element (DOE) placed behind it. The pipeline
is:
- Coherent ray tracing through the embedded
GeoLensto obtain a complex wavefront at the DOE plane (including all geometric aberrations). - DOE phase modulation applied to the wavefront.
- Angular Spectrum Method (ASM) propagation from the DOE to the sensor plane to produce the final intensity PSF.
This enables end-to-end gradient flow from image quality metrics back to both refractive surface parameters and the DOE phase profile.
Attributes:
| Name | Type | Description |
|---|---|---|
geolens |
GeoLens
|
Embedded refractive module. |
doe |
Diffractive optical element (one of |
Notes
Operates in torch.float64 by default for numerical stability of
the wave-propagation step.
References
Xinge Yang et al., "End-to-End Hybrid Refractive-Diffractive Lens Design with Differentiable Ray-Wave Model," SIGGRAPH Asia 2024.
Initialize a hybrid refractive-diffractive lens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to the lens configuration JSON file. Defaults to None. |
None
|
device
|
str
|
Computation device ('cpu' or 'cuda'). Defaults to None. |
None
|
dtype
|
dtype
|
Data type for computations. Defaults to torch.float64. |
float64
|
read_lens_json
Read the lens configuration from a JSON file.
Loads a GeoLens and associated DOE from the specified file. Supported DOE types: binary2, pixel2d, fresnel, zernike, grating.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to the JSON configuration file. |
required |
write_lens_json
Write the lens configuration to a JSON file.
Saves the GeoLens and DOE configurations to a JSON file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lens_path
|
str
|
Path for the output JSON file. |
required |
analysis
Perform lens analysis and save visualizations.
Draws the lens layout and DOE phase map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_name
|
str
|
Base path for saving analysis images. Defaults to './test.png'. |
'./test.png'
|
refocus
Refocus the HybridLens to a given depth.
Adjusts the GeoLens focus distance. The DOE is not moved because it is installed with the geolens as described in the Siggraph Asia 2024 paper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
foc_dist
|
float
|
Target focus distance. |
required |
calc_scale
Calculate the scale factor for object-to-image mapping.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
float
|
Object depth distance. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
float |
Scale factor (object height / image height). |
doe_field
Compute the complex wave field at DOE plane using coherent ray tracing. This function re-implements geolens.pupil_field() by changing the computation position from pupil plane to the last surface (DOE). The wavefront stores information of all diffraction orders.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
point
|
Tensor
|
Tensor of shape (3,) representing the point source position. Defaults to torch.tensor([0.0, 0.0, -10000.0]). |
required |
wvln
|
float
|
Wavelength. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
spp
|
int
|
Samples per pixel. Must be >= 1,000,000 for accurate simulation. Defaults to SPP_COHERENT. |
SPP_COHERENT
|
Returns:
| Name | Type | Description |
|---|---|---|
wavefront |
Tensor of shape [H, W] representing the complex wavefront. |
|
psf_center |
List containing the PSF center coordinates [x, y]. |
psf
Single point monochromatic PSF using ray-wave model. The PSF contains all diffraction orders with correct diffraction efficiencies.
Steps
1, Calculate complex wavefield at DOE plane by coherent ray tracing. 2, Apply DOE phase modulation to the wavefield. 3, Propagate the wavefield to sensor plane, calculate intensity PSF, crop the valid region and normalize the intensity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
[x, y, z] coordinates of the point source. Defaults to torch.Tensor([0,0,-10000]). |
[0.0, 0.0, -10000.0]
|
ks
|
int
|
size of the PSF patch. Defaults to PSF_KS. |
PSF_KS
|
wvln
|
float
|
wvln. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
spp
|
int
|
number of rays to sample. Defaults to SPP_COHERENT. |
SPP_COHERENT
|
Returns:
| Name | Type | Description |
|---|---|---|
psf_out |
Tensor
|
PSF patch. Normalized to sum to 1. Shape [ks, ks] |
draw_layout
Draw HybridLens layout with ray-tracing and wave-propagation visualization.
Shows the lens geometry with ray paths through the refractive elements and wave propagation arcs from the DOE to the sensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_name
|
str
|
Path to save the figure. Defaults to './DOELens.png'. |
'./DOELens.png'
|
depth
|
float
|
Object depth for ray tracing. Defaults to -10000.0. |
-10000.0
|
ax
|
Axes
|
Existing axes to draw on. Defaults to None. |
None
|
fig
|
Figure
|
Existing figure to use. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
(ax, fig) if ax was provided, otherwise saves the figure. |
get_optimizer
Get optimizer for lens and DOE parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doe_lr
|
float
|
Learning rate for DOE parameters. Defaults to 1e-4. |
0.0001
|
lens_lr
|
list
|
Learning rates for lens parameters [d, c, k, a]. Defaults to [1e-4, 1e-4, 1e-2, 1e-5]. |
[0.0001, 0.0001, 0.01, 1e-05]
|
lr_decay
|
float
|
Decay rate for higher-order coefficients. Defaults to 0.01. |
0.01
|
Returns:
| Type | Description |
|---|---|
|
torch.optim.Adam: Configured optimizer for all trainable parameters. |
DiffractiveLens
Pure wave-optics lens where every element is a phase surface. Propagation uses scalar diffraction theory (ASM / Fresnel / Fraunhofer).
from deeplens.optics import DiffractiveLens
lens = DiffractiveLens(filename='./datasets/lenses/doe/doe_example.json', device='cuda')
# Or load a built-in example:
lens = DiffractiveLens.load_example1()
deeplens.optics.diffraclens.DiffractiveLens
Bases: Lens
Paraxial diffractive lens in which each element is modelled as a phase surface.
Every optical element (converging lens, DOE, metasurface, …) is represented by a phase function applied to an incoming complex wavefront. Propagation between surfaces uses the Angular Spectrum Method (ASM). This model is simple and fast, but accurate only in the paraxial regime (it does not account for higher-order geometric aberrations).
Attributes:
| Name | Type | Description |
|---|---|---|
surfaces |
list
|
Ordered list of diffractive/phase surfaces. |
d_sensor |
Tensor
|
Distance from the last surface to the sensor plane [mm]. |
Notes
Operates in torch.float64 by default for numerical stability of
the wave-propagation step.
Initialize a diffractive lens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to the lens configuration JSON file. If provided, loads the lens configuration from file. Defaults to None. |
None
|
device
|
str
|
Computation device ('cpu' or 'cuda'). Defaults to 'cpu'. |
None
|
load_example1
classmethod
Create an example diffractive lens with a single Fresnel DOE.
Returns:
| Name | Type | Description |
|---|---|---|
DiffractiveLens |
A configured diffractive lens with a Fresnel surface at f=50mm, 4mm size, and 4000 resolution. |
load_example2
classmethod
Create an example diffractive lens with a thin lens and binary DOE combination.
Returns:
| Name | Type | Description |
|---|---|---|
DiffractiveLens |
A configured diffractive lens with a ThinLens (f=50mm) and a Binary2 DOE, both at 4mm size and 4000 resolution. |
read_lens_json
Load the lens configuration from a JSON file.
Reads lens parameters including sensor configuration and diffractive surfaces from the specified JSON file. If sensor_size or sensor_res are not provided, defaults of 8mm x 8mm and 2000x2000 pixels will be used.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to the JSON configuration file. |
required |
write_lens_json
Write the lens configuration to a JSON file.
Saves all lens parameters including sensor configuration and diffractive surface data to the specified file.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Output path for the JSON file. |
required |
forward
Propagate a wave through the diffractive lens system to the sensor.
Sequentially applies phase modulation from each diffractive surface, then propagates the wave to the sensor plane using wave optics.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wave
|
ComplexWave
|
Input wave field entering the lens system. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ComplexWave |
Output wave field at the sensor plane. |
render_mono
Simulate monochromatic lens blur by convolving an image with the point spread function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
Tensor
|
Input image. Shape: (B, 1, H, W) |
required |
wvln
|
float
|
Wavelength. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
ks
|
int
|
PSF kernel size. Defaults to PSF_KS. |
PSF_KS
|
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Rendered image after applying lens blur with shape (B, 1, H, W). |
psf
Calculate monochromatic point PSF by wave propagation approach.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
float
|
Depth of the point source. Defaults to float('inf'). |
float('inf')
|
wvln
|
float
|
Wavelength in micrometers. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
ks
|
int
|
PSF kernel size. Defaults to PSF_KS. |
PSF_KS
|
upsample_factor
|
int
|
Upsampling factor to meet Nyquist sampling constraint. Defaults to 1. |
1
|
Returns:
| Name | Type | Description |
|---|---|---|
psf_out |
tensor
|
PSF. shape [ks, ks] |
Note
[1] Usually we only consider the on-axis PSF because paraxial approximation is implicitly applied for wave optical model. For the shifted phase issue, refer to "Modeling off-axis diffraction with the least-sampling angular spectrum method".
draw_layout
Draw the lens layout diagram.
Visualizes the DOE and sensor positions in a 2D layout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_name
|
str
|
Path to save the figure. Defaults to './doelens.png'. |
'./doelens.png'
|
draw_psf
Draw on-axis RGB PSF.
Computes and saves a visualization of the RGB PSF for a given depth.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
float
|
Depth of the point source. Defaults to DEPTH. |
DEPTH
|
ks
|
int
|
Size of the PSF kernel in pixels. Defaults to PSF_KS. |
PSF_KS
|
save_name
|
str
|
Path to save the PSF image. Defaults to './psf_doelens.png'. |
'./psf_doelens.png'
|
log_scale
|
bool
|
If True, display PSF in log scale. Defaults to True. |
True
|
eps
|
float
|
Small value for log scale to avoid log(0). Defaults to 1e-4. |
0.0001
|
ParaxialLens
Thin-lens / ABCD-matrix model for fast defocus (circle-of-confusion) simulation. Does not model higher-order aberrations.
from deeplens.optics import ParaxialLens
lens = ParaxialLens(
foclen=50.0, # focal length [mm]
fnum=1.8, # F-number
sensor_size=(36.0, 24.0),
sensor_res=(2000, 2000),
device='cuda'
)
lens.refocus(foc_dist=-1000.0)
img_blurred = lens.render(img, depth=-2000.0)
deeplens.optics.paraxiallens.ParaxialLens
Bases: Lens
Thin-lens / ABCD-matrix model for fast defocus simulation.
Models the circle of confusion (CoC) caused by defocus but not higher-order optical aberrations. Useful as a fast baseline renderer for depth-of-field effects, as commonly used in Blender and similar tools.
Attributes:
| Name | Type | Description |
|---|---|---|
foclen |
float
|
Focal length [mm]. |
fnum |
float
|
F-number. |
sensor_size |
tuple
|
Physical sensor size (W, H) [mm]. |
sensor_res |
tuple
|
Pixel resolution (W, H). |
pixel_size |
float
|
Pixel pitch [mm]. |
Initialize a paraxial lens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
foclen
|
float
|
Focal length in [mm]. |
required |
fnum
|
float
|
F-number. |
required |
sensor_size
|
tuple
|
Physical sensor size as (W, H) in [mm]. Defaults to (8.0, 8.0). |
None
|
sensor_res
|
tuple
|
Sensor resolution as (W, H) in pixels. Defaults to (2000, 2000). |
None
|
device
|
str
|
Computation device. Defaults to "cpu". |
'cpu'
|
psf
PSF is modeled as a 2D uniform circular disk with diameter CoC.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
Points of the object. Shape [N, 3] or [3]. |
required |
ks
|
int
|
Kernel size. |
PSF_KS
|
psf_type
|
str
|
PSF type. "gaussian" or "pillbox". |
'gaussian'
|
**kwargs
|
Additional arguments for psf(). Currently not used. |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
psf |
Tensor
|
PSF kernels. Shape [ks, ks] or [N, ks, ks]. |
coc
Calculate circle of confusion (CoC) [mm].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
Tensor
|
Depth of the object. Shape [B]. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
coc |
Tensor
|
Circle of confusion. Shape [B]. |
Reference
[1] https://en.wikipedia.org/wiki/Circle_of_confusion
dof
Calculate depth of field [mm].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
Tensor
|
Depth of the object. Shape [B]. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
dof |
Tensor
|
Depth of field. Shape [B]. |
Reference
[1] https://en.wikipedia.org/wiki/Depth_of_field
psf_dp
Generate dual-pixel PSF for left and right sub-apertures.
This function generates separate PSFs for left and right sub-apertures of a dual pixel sensor, which enables depth estimation and improved autofocus capabilities.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Tensor
|
Input tensor with shape [N, 3], where columns are [x, y, z] coordinates. |
required |
ks
|
int
|
Kernel size for PSF generation. |
PSF_KS
|
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
(left_psf, right_psf) where each PSF tensor has shape [N, ks, ks]. |
render_rgbd
Occlusion-aware RGBD rendering for paraxial lens.
Uses back-to-front layered compositing to prevent color bleeding at depth
discontinuities. Since paraxial lenses have no spatially varying
aberrations, all methods (psf_patch, psf_map, psf_pixel) produce
identical results; the method parameter is accepted for API
compatibility but ignored.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img_obj
|
tensor
|
Object image. Shape [B, C, H, W]. |
required |
depth_map
|
tensor
|
Depth map [mm]. Shape [B, 1, H, W]. Values should be positive. |
required |
method
|
str
|
Ignored (no spatial variation). Defaults to "psf_patch". |
'psf_patch'
|
**kwargs
|
Additional keyword arguments: - psf_ks (int): PSF kernel size. Defaults to PSF_KS. - num_layers (int): Number of depth layers. Defaults to 16. - depth_min (float): Minimum depth. Defaults to depth_map.min(). - depth_max (float): Maximum depth. Defaults to depth_map.max(). |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
img_render |
tensor
|
Rendered image. Shape [B, C, H, W]. |
Reference
[1] "Dr.Bokeh: DiffeRentiable Occlusion-aware Bokeh Rendering", CVPR 2024.
PSFNetLens
Neural surrogate wrapping a GeoLens with an MLP that predicts PSFs directly
from (fov, depth, focus_distance). Provides ~100× speedup after a one-time
training phase.
from deeplens import PSFNetLens
lens = PSFNetLens(
lens_path='./datasets/lenses/camera/ef50mm_f1.8.json',
in_chan=3, psf_chan=3, model_name='mlp_conv', kernel_size=64
)
lens.train_psfnet(iters=100000, spp=16384) # one-time training
lens.load_net('./ckpts/psfnet/PSFNet_ef50mm.pth')
psf_rgb = lens.psf_rgb(points=torch.tensor([[0.0, 0.0, -10000.0]]), ks=64)
deeplens.optics.psfnetlens.PSFNetLens
Bases: Lens
Neural surrogate lens that predicts PSFs via a small MLP/MLPConv network.
Wraps a :class:~deeplens.optics.geolens.GeoLens with a neural network
trained to predict RGB PSFs from (fov, depth, focus_distance) inputs.
After training, PSF prediction is ~100× faster than ray tracing, making
it suitable for real-time applications and large-scale optimisation.
Attributes:
| Name | Type | Description |
|---|---|---|
lens |
GeoLens
|
The underlying refractive lens (used for training data generation and for sensor metadata). |
psfnet |
Module
|
Neural network for PSF prediction. |
pixel_size |
float
|
Pixel pitch [mm] (copied from the embedded lens). |
rfov |
float
|
Half-diagonal field of view [radians]. |
Notes
Use :meth:train_psfnet to train the surrogate from ray-traced PSF
samples. Use :meth:load_net to load pre-trained weights.
Initialize a PSF network lens.
In the default settings, the PSF network takes (fov, depth, foc_dist) as input and outputs RGB PSF on y-axis at (fov, depth, foc_dist).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lens_path
|
str
|
Path to the lens file. |
required |
in_chan
|
int
|
Number of input channels. |
3
|
psf_chan
|
int
|
Number of output channels. |
3
|
model_name
|
str
|
Name of the model. |
'mlp_conv'
|
kernel_size
|
int
|
Kernel size. |
64
|
psfnet
instance-attribute
psfnet = init_net(in_chan=in_chan, psf_chan=psf_chan, kernel_size=kernel_size, model_name=model_name)
set_sensor_res
Set sensor resolution for both PSFNetLens and the embedded GeoLens.
init_net
Initialize a PSF network.
PSF network
Input: [B, 3], (fov, depth, foc_dist). fov from [0, pi/2], depth from [-20000, -100], foc_dist from [-20000, -500] Output: psf kernel [B, 3, ks, ks]
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
in_chan
|
int
|
number of input channels |
2
|
psf_chan
|
int
|
number of output channels |
3
|
kernel_size
|
int
|
kernel size |
64
|
model_name
|
str
|
name of the network architecture |
'mlpconv'
|
Returns:
| Name | Type | Description |
|---|---|---|
psfnet |
Module
|
network |
load_net
Load pretrained network.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
net_path
|
str
|
path to load the network |
required |
save_psfnet
Save the PSF network.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psfnet_path
|
str
|
path to save the PSF network |
required |
train_psfnet
train_psfnet(iters=100000, bs=128, lr=5e-05, evaluate_every=500, spp=16384, concentration_factor=2.0, result_dir='./results/psfnet')
Train the PSF surrogate network.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
iters
|
int
|
number of training iterations |
100000
|
bs
|
int
|
batch size |
128
|
lr
|
float
|
learning rate |
5e-05
|
evaluate_every
|
int
|
evaluate every how many iterations |
500
|
spp
|
int
|
number of samples per pixel |
16384
|
concentration_factor
|
float
|
concentration factor for training data sampling |
2.0
|
result_dir
|
str
|
directory to save the results |
'./results/psfnet'
|
sample_training_data
Sample training data for PSF surrogate network.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_points
|
int
|
number of training points |
512
|
concentration_factor
|
float
|
concentration factor for training data sampling |
2.0
|
Returns:
| Name | Type | Description |
|---|---|---|
sample_input |
tensor
|
[B, 3] tensor, (fov, depth, foc_dist). - fov from [0, rfov] on 0y-axis, [radians] - depth from [d_far, d_close], [mm] - foc_dist from [foc_d_far, foc_d_close], [mm] - We use absolute fov and depth. |
sample_psf |
tensor
|
[B, 3, ks, ks] tensor |
points2input
Convert points to input tensor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
tensor
|
[N, 3] tensor, [-1, 1] * [-1, 1] * [depth_min, depth_max] |
required |
Returns:
| Name | Type | Description |
|---|---|---|
input |
tensor
|
[N, 3] tensor, (fov, depth, foc_dist). - fov from [0, rfov] on y-axis, [radians] - depth/1000.0 from [d_far, d_close], [mm] - foc_dist/1000.0 from [foc_d_far, foc_d_close], [mm] |
psf_rgb
Calculate RGB PSF using the PSF network.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
tensor
|
[N, 3] tensor, [-1, 1] * [-1, 1] * [depth_min, depth_max] |
required |
foc_dist
|
float
|
focus distance |
required |
Returns:
| Name | Type | Description |
|---|---|---|
psf |
tensor
|
[N, 3, ks, ks] tensor |
psf_map_rgb
Compute monochrome PSF map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
grid
|
tuple
|
Grid size. Defaults to (11, 11), meaning 11x11 grid. |
(11, 11)
|
wvln
|
float
|
Wavelength. Defaults to DEFAULT_WAVE. |
required |
depth
|
float
|
Depth of the object. Defaults to DEPTH. |
DEPTH
|
ks
|
int
|
Kernel size. Defaults to PSF_KS, meaning PSF_KS x PSF_KS kernel size. |
PSF_KS
|
Returns:
| Name | Type | Description |
|---|---|---|
psf_map |
Shape of [grid, grid, 3, ks, ks]. |
render_rgbd
Render image with aif image and depth map. Receive [N, C, H, W] image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
tensor
|
[1, C, H, W] |
required |
depth
|
tensor
|
[1, H, W], depth map, unit in mm, range from [-20000, -200] |
required |
foc_dist
|
tensor
|
[1], unit in mm, range from [-20000, -200] |
required |
ks
|
int
|
kernel size |
64
|
high_res
|
bool
|
whether to use high resolution rendering |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
render |
tensor
|
[1, C, H, W] |
GeoLens Mixins
GeoLens inherits from six mixin classes, each handling one aspect of its
functionality.
GeoLensEval — Evaluation
Spot diagrams, MTF curves, vignetting maps, distortion grids.
deeplens.optics.geolens_pkg.eval.GeoLensEval
Mixin providing classical optical performance evaluation for GeoLens.
Provides spot diagrams, RMS error maps, MTF curves, distortion analysis, vignetting, and field curvature — results are accuracy-aligned with Zemax OpticStudio.
This class is not instantiated directly; it is mixed into
:class:~deeplens.optics.geolens.GeoLens.
draw_spot_radial
draw_spot_radial(save_name='./lens_spot_radial.png', num_fov=5, depth=float('inf'), num_rays=SPP_PSF, wvln_list=WAVE_RGB, show=False)
Draw spot diagram of the lens at different field angles along meridional (y) direction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_name
|
string
|
filename to save. Defaults to "./lens_spot_radial.png". |
'./lens_spot_radial.png'
|
num_fov
|
int
|
field of view number. Defaults to 4. |
5
|
depth
|
float
|
depth of the point source. Defaults to float("inf"). |
float('inf')
|
num_rays
|
int
|
number of rays to sample. Defaults to SPP_PSF. |
SPP_PSF
|
wvln_list
|
list
|
wavelength list to render. |
WAVE_RGB
|
show
|
bool
|
whether to show the plot. Defaults to False. |
False
|
draw_spot_map
draw_spot_map(save_name='./lens_spot_map.png', num_grid=5, depth=DEPTH, num_rays=SPP_PSF, wvln_list=WAVE_RGB, show=False)
Draw spot diagram of the lens at different field angles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_name
|
string
|
filename to save. Defaults to "./lens_spot_map.png". |
'./lens_spot_map.png'
|
num_grid
|
int
|
number of grid points. Defaults to 5. |
5
|
depth
|
float
|
depth of the point source. Defaults to DEPTH. |
DEPTH
|
num_rays
|
int
|
number of rays to sample. Defaults to SPP_PSF. |
SPP_PSF
|
wvln_list
|
list
|
wavelength list to render. Defaults to WAVE_RGB. |
WAVE_RGB
|
show
|
bool
|
whether to show the plot. Defaults to False. |
False
|
rms_map_rgb
Calculate the RMS spot error map across RGB wavelengths. Reference to the centroid of green rays.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_grid
|
int
|
Number of grid points. Defaults to 64. |
32
|
depth
|
float
|
Depth of the point source. Defaults to DEPTH. |
DEPTH
|
Returns:
| Name | Type | Description |
|---|---|---|
rms_map |
Tensor
|
RMS map for RGB channels. Shape [3, num_grid, num_grid]. |
rms_map
Calculate the RMS spot error map for a specific wavelength.
Currently this function is not used, but it can be used as the weight mask during optimization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_grid
|
int
|
Resolution of the grid used for sampling fields/points. Defaults to 64. |
32
|
depth
|
float
|
Depth of the point source. Defaults to DEPTH. |
DEPTH
|
wvln
|
float
|
Wavelength of the ray. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
Returns:
| Name | Type | Description |
|---|---|---|
rms_map |
Tensor
|
RMS map for the specified wavelength. Shape [num_grid, num_grid]. |
calc_distortion_2D
Calculate distortion at a specific field angle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rfov
|
float
|
view angle (degree) |
required |
wvln
|
float
|
wavelength |
DEFAULT_WAVE
|
plane
|
str
|
meridional or sagittal |
'meridional'
|
ray_aiming
|
bool
|
whether the chief ray through the center of the stop. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
distortion |
float
|
distortion at the specific field angle |
draw_distortion_radial
draw_distortion_radial(rfov, save_name=None, num_points=GEO_GRID, wvln=DEFAULT_WAVE, plane='meridional', ray_aiming=True, show=False)
Draw distortion. zemax format(default): ray_aiming = False.
Note: this function is provided by a community contributor.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rfov
|
view angle (degrees) |
required | |
save_name
|
Save filename. Defaults to None. |
None
|
|
num_points
|
Number of points. Defaults to GEO_GRID. |
GEO_GRID
|
|
plane
|
Meridional or sagittal. Defaults to meridional. |
'meridional'
|
|
ray_aiming
|
Whether to use ray aiming. Defaults to False. |
True
|
distortion_map
Compute distortion map at a given depth.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_grid
|
int
|
number of grid points. |
16
|
depth
|
float
|
depth of the point source. |
DEPTH
|
wvln
|
float
|
wavelength. |
DEFAULT_WAVE
|
Returns:
| Name | Type | Description |
|---|---|---|
distortion_grid |
Tensor
|
distortion map. shape (grid_size, grid_size, 2) |
distortion_center
Calculate the distortion center for given normalized points.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
Normalized point source positions. Shape [N, 3] or [..., 3]. x, y in [-1, 1], z (depth) in [-Inf, 0]. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
distortion_center |
Normalized distortion center positions. Shape [N, 2] or [..., 2]. x, y in [-1, 1]. |
draw_distortion
Draw distortion map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_name
|
str
|
filename to save. Defaults to None. |
None
|
num_grid
|
int
|
number of grid points. Defaults to 16. |
16
|
depth
|
float
|
depth of the point source. Defaults to DEPTH. |
DEPTH
|
wvln
|
float
|
wavelength. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
show
|
bool
|
whether to show the plot. Defaults to False. |
False
|
psf2mtf
staticmethod
Calculate MTF from PSF.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
psf
|
tensor
|
2D PSF tensor (e.g., ks x ks). Assumes standard orientation where the array's y-axis corresponds to the tangential/meridional direction and the x-axis to the sagittal direction. |
required |
pixel_size
|
float
|
Pixel size in mm. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
freq |
ndarray
|
Frequency axis (cycles/mm). |
tangential_mtf |
ndarray
|
Tangential MTF. |
sagittal_mtf |
ndarray
|
Sagittal MTF. |
Reference
[1] https://en.wikipedia.org/wiki/Optical_transfer_function [2] https://www.edmundoptics.com/knowledge-center/application-notes/optics/introduction-to-modulation-transfer-function/?srsltid=AfmBOoq09vVDVlh_uuwWnFoMTg18JVgh18lFSw8Ci4Sdlry-AmwGkfDd
draw_mtf
draw_mtf(save_name='./lens_mtf.png', relative_fov_list=[0.0, 0.7, 1.0], depth_list=[DEPTH], psf_ks=128, show=False)
Draw a grid of MTF curves. Each subplot in the grid corresponds to a specific (depth, FOV) combination. Each subplot displays MTF curves for R, G, B wavelengths.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
relative_fov_list
|
list
|
List of relative field of view values. Defaults to [0.0, 0.7, 1.0]. |
[0.0, 0.7, 1.0]
|
depth_list
|
list
|
List of depth values. Defaults to [DEPTH]. |
[DEPTH]
|
save_name
|
str
|
Filename to save the plot. Defaults to "./mtf_grid.png". |
'./lens_mtf.png'
|
psf_ks
|
int
|
Kernel size for intermediate PSF calculation. Defaults to 256. |
128
|
show
|
bool
|
whether to show the plot. Defaults to False. |
False
|
draw_field_curvature
draw_field_curvature(save_name=None, num_points=32, z_span=1.0, z_steps=1001, wvln_list=WAVE_RGB, spp=SPP_CALC, show=False)
Draw field curvature: best-focus defocus Δz (mm) vs field angle (deg), RGB overlaid.
- Tangential (meridional) curves are solid lines (y-axis spread minimized).
draw_vignetting
Draw vignetting.
calc_chief_ray
Compute chief ray for an incident angle.
If chief ray is only used to determine the ideal image height, we can warp this function into the image height calculation function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fov
|
float
|
incident angle in degree. |
required |
plane
|
str
|
"sagittal" or "meridional". |
'sagittal'
|
Returns:
| Name | Type | Description |
|---|---|---|
chief_ray_o |
Tensor
|
origin of chief ray. |
chief_ray_d |
Tensor
|
direction of chief ray. |
Note
It is 2D ray tracing, for 3D chief ray, we can shrink the pupil, trace rays, calculate the centroid as the chief ray.
calc_chief_ray_infinite
calc_chief_ray_infinite(rfov, depth=0.0, wvln=DEFAULT_WAVE, plane='meridional', num_rays=SPP_CALC, ray_aiming=True)
Compute chief ray for an incident angle.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
rfov
|
float
|
incident angle in degree. |
required |
depth
|
float
|
depth of the object. |
0.0
|
wvln
|
float
|
wavelength of the light. |
DEFAULT_WAVE
|
plane
|
str
|
"sagittal" or "meridional". |
'meridional'
|
num_rays
|
int
|
number of rays. |
SPP_CALC
|
ray_aiming
|
bool
|
whether the chief ray through the center of the stop. |
True
|
GeoLensOptim — Optimization
Loss functions (RMS spot, wavefront error), physical constraints, optimizer helpers.
# RMS-based optimisation loop
optimizer = lens.get_optimizer(lrs=[1e-3, 1e-4, 1e-1, 1e-4], decay=0.01)
for epoch in range(1000):
optimizer.zero_grad()
loss = lens.loss_rms(num_grid=9, depth=-10000.0, num_rays=2048)
loss_reg, _ = lens.loss_reg()
(loss + 0.05 * loss_reg).backward()
optimizer.step()
deeplens.optics.geolens_pkg.optim.GeoLensOptim
Mixin providing differentiable optimisation for GeoLens.
Implements gradient-based lens design using PyTorch autograd:
- Loss functions – RMS spot error, focus, surface regularity, gap constraints, material validity.
- Constraint initialisation – edge-thickness and self-intersection guards.
- Optimizer helpers – parameter groups with per-type learning rates and cosine annealing schedules.
- High-level
optimize()– curriculum-learning training loop.
This class is not instantiated directly; it is mixed into
:class:~deeplens.optics.geolens.GeoLens.
References
Xinge Yang et al., "Curriculum learning for ab initio deep learned refractive optics," Nature Communications 2024.
init_constraints
Initialize constraints for the lens design.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
constraint_params
|
dict
|
Constraint parameters. |
None
|
loss_reg
Regularization loss for lens design.
loss_infocus
Sample parallel rays and compute RMS loss on the sensor plane, minimize focus loss.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
float
|
target of RMS loss. Defaults to 0.005 [mm]. |
0.005
|
loss_surface
Penalize surface shape: 1. Penalize maximum sag 2. Penalize diameter to thickness ratio 3. Penalize thick_max to thick_min ratio 4. Penalize diameter to thickness ratio 5. Penalize maximum to minimum thickness ratio
loss_intersec
Loss function to avoid self-intersection.
This function penalizes when surfaces are too close to each other, which could cause self-intersection or manufacturing issues.
loss_gap
Loss function to penalize too large air gap and thickness.
This function penalizes when air gaps or lens thicknesses are too large, which could make the lens system impractically large.
loss_rms
Loss function to compute RGB spot error RMS.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_grid
|
int
|
Number of grid points. Defaults to GEO_GRID. |
GEO_GRID
|
depth
|
float
|
Depth of the lens. Defaults to DEPTH. |
DEPTH
|
num_rays
|
int
|
Number of rays. Defaults to SPP_CALC. |
SPP_PSF
|
sample_more_off_axis
|
bool
|
Whether to sample more off-axis rays. Defaults to False. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
avg_rms_error |
Tensor
|
RMS error averaged over wavelengths and grid points. |
sample_ring_arm_rays
sample_ring_arm_rays(num_ring=8, num_arm=8, spp=2048, depth=DEPTH, wvln=DEFAULT_WAVE, scale_pupil=1.0, sample_more_off_axis=True)
Sample rays from object space using a ring-arm pattern.
This method distributes sampling points (origins of ray bundles) on a polar grid in the object plane,
defined by field of view. This is useful for capturing lens performance across the full field.
The points include the center and num_ring rings with num_arm points on each.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
num_ring
|
int
|
Number of rings to sample in the field of view. |
8
|
num_arm
|
int
|
Number of arms (spokes) to sample for each ring. |
8
|
spp
|
int
|
Total number of rays to be sampled, distributed among field points. |
2048
|
depth
|
float
|
Depth of the object plane. |
DEPTH
|
wvln
|
float
|
Wavelength of the rays. |
DEFAULT_WAVE
|
scale_pupil
|
float
|
Scale factor for the pupil size. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
Ray |
A Ray object containing the sampled rays. |
optimize
optimize(lrs=[0.001, 0.0001, 0.1, 0.0001], decay=0.01, iterations=5000, test_per_iter=100, centroid=False, optim_mat=False, shape_control=True, result_dir=None)
Optimize the lens by minimizing rms errors.
Debug hints
1, Slowly optimize with small learning rate 2, FOV and thickness should match well 3, Reasonable parameter range 4, Aspheric order higher is better but also more sensitive 5, More iterations with larger ray sampling
GeoLensIO — File I/O
Read/write JSON and Zemax .zmx lens files.
lens = GeoLens(filename='lens.json') # load JSON
lens = GeoLens(filename='lens.zmx') # load Zemax
lens.write_lens_json('optimized.json') # save
deeplens.optics.geolens_pkg.io.GeoLensIO
Mixin providing file I/O for GeoLens.
Supports reading and writing lens prescriptions in three formats:
- JSON (primary): human-readable, supports parenthesised optimisable
parameters, e.g.
"(d)": 5.0. - Zemax .zmx: industry-standard sequential lens file.
- Code V .seq: Code V sequential format (read-only).
This class is not instantiated directly; it is mixed into
:class:~deeplens.optics.geolens.GeoLens.
GeoLensTolerance — Tolerance Analysis
Monte-Carlo and sensitivity tolerance analysis.
deeplens.optics.geolens_pkg.tolerance.GeoLensTolerance
Mixin providing tolerance analysis for GeoLens.
Implements two complementary approaches:
- Sensitivity analysis – first-order gradient-based estimation of how each manufacturing error affects optical performance.
- Monte-Carlo analysis – statistical sampling of random manufacturing errors to predict yield and worst-case performance.
This class is not instantiated directly; it is mixed into
:class:~deeplens.optics.geolens.GeoLens.
References
Jun Dai et al., "Tolerance-Aware Deep Optics," arXiv:2502.04719, 2025.
tolerancing_sensitivity
Use sensitivity analysis (1st order gradient) to compute the tolerance score.
References
[1] Page 10 from: https://wp.optics.arizona.edu/optomech/wp-content/uploads/sites/53/2016/08/8-Tolerancing-1.pdf [2] Fast sensitivity control method with differentiable optics. Optics Express 2025. [3] Optical Design Tolerancing. CODE V.
tolerancing_monte_carlo
Use Monte Carlo simulation to compute the tolerance.
Note: we can multiplex sampled rays to improve the speed.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
trials
|
int
|
Number of Monte Carlo trials |
1000
|
tolerance_params
|
dict
|
Tolerance parameters |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
dict |
Monte Carlo tolerance analysis results |
References
[1] https://optics.ansys.com/hc/en-us/articles/43071088477587-How-to-analyze-your-tolerance-results [2] Optical Design Tolerancing. CODE V.
tolerancing_wavefront
Use wavefront differential method to compute the tolerance.
Wavefront differential method is proposed in [1], while the detailed implementation remains unknown. I (Xinge Yang) assume a symbolic differentiation is used to compute the gradient/Jacobian of the wavefront error. With AutoDiff, we can easily calculate Jacobian with gradient backpropagation, therefore I leave the implementation of this method as future work.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tolerance_params
|
dict
|
Tolerance parameters |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
dict |
Wavefront tolerance analysis results |
References
[1] Optical Design Tolerancing. CODE V.
GeoLensVis — 2D Visualization
2D lens layout and ray path diagrams.
lens.draw_layout(filename='layout.png', depth=-10000.0)
lens.draw_spot_radial(save_name='spot.png', depth=-10000.0)
lens.draw_mtf(save_name='mtf.png', depth_list=[-10000.0])
lens.draw_psf_map(grid=(7, 7), ks=64, depth=-10000.0, save_name='psf_map.png')
deeplens.optics.geolens_pkg.vis.GeoLensVis
Mixin providing 2-D lens layout and ray visualisation for GeoLens.
Generates publication-quality cross-section plots showing lens surfaces and traced ray bundles in either the meridional or sagittal plane.
This class is not instantiated directly; it is mixed into
:class:~deeplens.optics.geolens.GeoLens.
sample_parallel_2D
sample_parallel_2D(fov=0.0, num_rays=7, wvln=DEFAULT_WAVE, plane='meridional', entrance_pupil=True, depth=0.0)
Sample parallel rays (2D) in object space.
Used for (1) drawing lens setup, (2) 2D geometric optics calculation, for example, refocusing to infinity
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fov
|
float
|
incident angle (in degree). Defaults to 0.0. |
0.0
|
depth
|
float
|
sampling depth. Defaults to 0.0. |
0.0
|
num_rays
|
int
|
ray number. Defaults to 7. |
7
|
wvln
|
float
|
ray wvln. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
plane
|
str
|
sampling plane. Defaults to "meridional" (y-z plane). |
'meridional'
|
entrance_pupil
|
bool
|
whether to use entrance pupil. Defaults to True. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
ray |
Ray object
|
Ray object. Shape [num_rays, 3] |
sample_point_source_2D
Sample point source rays (2D) in object space.
Used for (1) drawing lens setup.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
fov
|
float
|
incident angle (in degree). Defaults to 0.0. |
0.0
|
depth
|
float
|
sampling depth. Defaults to DEPTH. |
DEPTH
|
num_rays
|
int
|
ray number. Defaults to 7. |
7
|
wvln
|
float
|
ray wvln. Defaults to DEFAULT_WAVE. |
DEFAULT_WAVE
|
entrance_pupil
|
bool
|
whether to use entrance pupil. Defaults to False. |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
ray |
Ray object
|
Ray object. Shape [num_rays, 3] |
draw_layout
draw_layout(filename, depth=float('inf'), zmx_format=True, multi_plot=False, lens_title=None, show=False)
Plot 2D lens layout with ray tracing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
Output filename |
required | |
depth
|
Depth for ray tracing |
float('inf')
|
|
entrance_pupil
|
Whether to use entrance pupil |
required | |
zmx_format
|
Whether to use ZMX format |
True
|
|
multi_plot
|
Whether to create multiple plots |
False
|
|
lens_title
|
Title for the lens plot |
None
|
|
show
|
Whether to show the plot |
False
|
draw_lens_2d
Draw lens layout in a 2D plot.
draw_ray_2d
Plot ray paths.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray_o_record
|
list
|
list of intersection points. |
required |
ax
|
Axes
|
matplotlib axes. |
required |
fig
|
Figure
|
matplotlib figure. |
required |
draw_layout_3d
Draw 3D layout of the lens system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to save the figure. Defaults to None. |
None
|
view_angle
|
int
|
Viewing angle for the 3D plot |
30
|
show
|
bool
|
Whether to display the figure |
False
|
Returns:
| Type | Description |
|---|---|
|
fig, ax: Matplotlib figure and axis objects |
create_barrier
Create a 3D barrier for the lens system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
Path to save the figure |
required | |
barrier_thickness
|
Thickness of the barrier |
1.0
|
|
ring_height
|
Height of the annular ring |
0.5
|
|
ring_size
|
Size of the annular ring |
1.0
|
GeoLensVis3D — 3D Visualization
3D mesh visualization via PyVista.
deeplens.optics.geolens_pkg.view_3d.GeoLensVis3D
Mixin providing 3-D mesh visualisation for GeoLens.
Creates lens surface, aperture, barrier, sensor, and ray-path meshes as
polygon data and optionally renders them with PyVista. All geometry is
expressed in millimetres and stored as :class:CrossPoly (vertex/face)
objects that can be saved to .obj files for external renderers.
This class is not instantiated directly; it is mixed into
:class:~deeplens.optics.geolens.GeoLens.
create_mesh
Create all lens/bridge/sensor/aperture meshes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lens
|
GeoLens
|
The lens object. |
required |
mesh_rings
|
int
|
The number of rings in the mesh. |
32
|
mesh_arms
|
int
|
The number of arms in the mesh. |
128
|
is_wrap
|
bool
|
Whether to wrap the lens bridge around the lens as cylinder. |
False
|
Returns: surf_meshes (List[Surface]): Lens surfaces meshes. bridge_meshes (List[FaceMesh]): Lens bridges meshes. (NOT support wrap around for now) sensor_mesh (RectangleMesh): Sensor meshes. (only support rectangular sensor for now)
draw_lens_3d
draw_lens_3d(plotter=None, save_dir: Optional[str] = None, mesh_rings: int = 32, mesh_arms: int = 128, surface_color: List[float] = [0.06, 0.3, 0.6], draw_rays: bool = True, fovs: List[float] = [0.0], fov_phis: List[float] = [0.0], ray_rings: int = 6, ray_arms: int = 8, is_wrap: bool = False)
Draw lens 3D layout with rays using pyvista.
Note: PyVista is imported lazily only when this method is called.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
plotter
|
pv.Plotter. Optional pyvista Plotter instance. If None, a new one is created. |
None
|
|
save_dir
|
str
|
The directory to save the image. |
None
|
mesh_rings
|
int
|
The number of rings in the mesh. |
32
|
mesh_arms
|
int
|
The number of arms in the mesh. |
128
|
surface_color
|
List[float]
|
The color of the surfaces. |
[0.06, 0.3, 0.6]
|
draw_rays
|
bool
|
Whether to show the rays. |
True
|
fovs
|
List[float]
|
The FoV angles to be sampled, unit: degree. |
[0.0]
|
fov_phis
|
List[float]
|
The FoV azimuthal angles to be sampled, unit: degree. |
[0.0]
|
ray_rings
|
int
|
The number of pupil rings to be sampled. |
6
|
ray_arms
|
int
|
The number of pupil arms to be sampled. |
8
|
is_wrap
|
bool
|
Whether to wrap the lens bridge around the lens as cylinder. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
plotter |
pv.Plotter. The pyvista Plotter instance. |
save_lens_obj
save_lens_obj(save_dir: str, mesh_rings: int = 64, mesh_arms: int = 128, save_rays: bool = False, fovs: List[float] = [0.0], fov_phis: List[float] = [0.0], ray_rings: int = 6, ray_arms: int = 8, is_wrap: bool = False, save_elements: bool = True)
Save lens geometry and rays as .obj files using pyvista.
Note: use #F2F7FFFF as the color for lens when rendering in Blender.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lens
|
GeoLens
|
The lens object. |
required |
save_dir
|
str
|
The directory to save the image. |
required |
mesh_rings
|
int
|
The number of rings in the mesh. (default: 128) |
64
|
mesh_arms
|
int
|
The number of arms in the mesh. (default: 256) |
128
|
save_rays
|
bool
|
Whether to save the rays. |
False
|
fovs
|
List[float]
|
The FoV angles to be sampled, unit: degree. |
[0.0]
|
fov_phis
|
List[float]
|
The FoV azimuthal angles to be sampled, unit: degree. |
[0.0]
|
ray_rings
|
int
|
The number of pupil rings to be sampled. (default: 6) |
6
|
ray_arms
|
int
|
The number of pupil arms to be sampled. (default: 8) |
8
|
is_wrap
|
bool
|
Whether to wrap the lens bridge around the lens as cylinder. |
False
|
save_elements
|
bool
|
Whether to save the elements. |
True
|
Optical Elements
Base Classes
deeplens.optics.base.DeepObj
Base class for all differentiable optical objects in DeepLens.
Provides device management, dtype conversion, and deep-copy support via
automatic introspection over instance tensors and nested DeepObj
sub-objects. All lens, surface, material, ray, and wave objects inherit
from this class.
Attributes:
| Name | Type | Description |
|---|---|---|
dtype |
dtype
|
Current floating-point dtype of all owned tensors. |
device |
dtype
|
Current compute device (set by :meth: |
to
Move all tensors and nested objects to device.
Recursively walks over every instance attribute and moves tensors,
nn.Module sub-objects, and nested DeepObj objects to the
requested device.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
device
|
Target device, e.g. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
DeepObj |
|
Example
lens = GeoLens(filename="lens.json") lens.to("cuda") # move all tensors to GPU
astype
Convert all floating-point tensors to dtype.
Also calls torch.set_default_dtype(dtype) so that subsequent
tensor creation uses the same precision.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dtype
|
dtype
|
Target floating-point dtype. Must be one of
|
required |
Returns:
| Name | Type | Description |
|---|---|---|
DeepObj |
|
Raises:
| Type | Description |
|---|---|
AssertionError
|
If dtype is not a recognised floating-point dtype. |
Example
lens = GeoLens(filename="lens.json") lens.astype(torch.float64) # switch to double precision
deeplens.optics.geometric_surface.base.Surface
Bases: DeepObj
Base class for all geometric optical surfaces.
A surface sits at axial position d (mm) in the global coordinate
system, has an aperture radius r (mm), and separates two optical
media. Subclasses override :meth:_sag and :meth:_dfdxy to define
their shape.
Ray–surface interaction is handled by three stages, implemented in
:meth:ray_reaction:
- Coordinate transform – ray is brought into the local surface frame.
- Intersection – solved via Newton's method (:meth:
newtons_method), using a non-differentiable iteration loop followed by a single differentiable Newton step to enable gradient flow. - Refraction / reflection – vector Snell's law (:meth:
refract) or specular reflection (:meth:reflect).
Attributes:
| Name | Type | Description |
|---|---|---|
d |
Tensor
|
Axial position of the surface vertex [mm]. |
r |
float
|
Aperture radius [mm]. |
mat2 |
Material
|
Optical material on the transmission side. |
is_square |
bool
|
If |
tolerancing |
bool
|
When |
Initialize a generic optical surface.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
r
|
float
|
Aperture radius [mm]. |
required |
d
|
float
|
Axial position of the surface vertex [mm]. |
required |
mat2
|
str or Material
|
Material on the transmission side
(e.g. |
required |
pos_xy
|
list[float]
|
Lateral offset |
[0.0, 0.0]
|
vec_local
|
list[float]
|
Local normal direction.
Defaults to |
[0.0, 0.0, 1.0]
|
is_square
|
bool
|
Use a square aperture.
Defaults to |
False
|
device
|
str
|
Compute device. Defaults to |
'cpu'
|
ray_reaction
Compute the output ray after intersection and refraction/reflection.
Transforms the ray to the local surface frame, solves the intersection via Newton's method, applies vector Snell's law (or specular reflection), then transforms back to global coordinates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
Incident ray bundle. |
required |
n1
|
float
|
Refractive index of the incident medium. |
required |
n2
|
float
|
Refractive index of the transmission medium. |
required |
refraction
|
bool
|
If |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
Ray |
Updated ray bundle after the surface interaction. |
intersect
Solve ray-surface intersection in local coordinate system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
input ray. |
required |
n
|
float
|
refractive index. Defaults to 1.0. |
1.0
|
newtons_method
Solve intersection by Newton's method in local coordinate system.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
input ray. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
t |
tensor
|
intersection time. |
valid |
tensor
|
valid mask. |
refract
Calculate refracted ray according to Snell's law in local coordinate system.
Normal vector points from the surface toward the side where the light is coming from. d is already normalized if both n and ray.d are normalized.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
incident ray. |
required |
eta
|
float
|
ratio of indices of refraction, eta = n_i / n_t |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ray |
Ray
|
refracted ray. |
References
[1] https://registry.khronos.org/OpenGL-Refpages/gl4/html/refract.xhtml [2] https://en.wikipedia.org/wiki/Snell%27s_law, "Vector form" section.
reflect
Calculate reflected ray in local coordinate system.
Normal vector points from the surface toward the side where the light is coming from.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
incident ray. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
ray |
Ray
|
reflected ray. |
References
[1] https://registry.khronos.org/OpenGL-Refpages/gl4/html/reflect.xhtml [2] https://en.wikipedia.org/wiki/Snell%27s_law, "Vector form" section.
normal_vec
Calculate surface normal vector at the intersection point in local coordinate system.
Normal vector points from the surface toward the side where the light is coming from.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
input ray. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
n_vec |
tensor
|
surface normal vector. |
to_local_coord
to_global_coord
_get_rotation_matrix
Calculate rotation matrix to rotate vec_from to vec_to.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vec_from
|
tensor
|
source direction vector [3] |
required |
vec_to
|
tensor
|
target direction vector [3] |
required |
Returns:
| Name | Type | Description |
|---|---|---|
R |
tensor
|
rotation matrix [3, 3] |
_apply_rotation
Apply rotation matrix to vectors.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
vectors
|
tensor
|
input vectors [..., 3] |
required |
R
|
tensor
|
rotation matrix [3, 3] |
required |
Returns:
| Name | Type | Description |
|---|---|---|
rotated_vectors |
tensor
|
rotated vectors [..., 3] |
sag
Calculate sag (z) of the surface: z = f(x, y).
Valid term is used to avoid NaN when x, y exceed the data range, which happens in spherical and aspherical surfaces.
Calculating r = sqrt(x2, y2) may cause an NaN error during back-propagation. Because dr/dx = x / sqrt(x2 + y2), NaN will occur when x=y=0.
_sag
Calculate sag (z) of the surface: z = f(x, y).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
tensor
|
x coordinate |
required |
y
|
tensor
|
y coordinate |
required |
valid
|
tensor
|
valid mask |
required |
Return
z (tensor): z = sag(x, y)
dfdxyz
Compute derivatives of surface function. Surface function: f(x, y, z): sag(x, y) - z = 0. This function is used in Newton's method and normal vector calculation.
There are several methods to compute derivatives of surfaces
[1] Analytical derivatives: The current implementation is based on this method. But the implementation only works for surfaces which can be written as z = sag(x, y). For implicit surfaces, we need to compute derivatives (df/dx, df/dy, df/dz). [2] Numerical derivatives: Use finite difference method to compute derivatives. This can be used for those very complex surfaces, for example, NURBS. But it may suffer from numerical instability when the surface is very steep. [3] Automatic differentiation: Use torch.autograd to compute derivatives. This can work for almost all the surfaces and is accurate, but it requires an extra backward pass to compute the derivatives of the surface function.
_dfdxy
Compute derivatives of sag to x and y. (dfdx, dfdy, dfdz) = (f'x, f'y, f'z).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
tensor
|
x coordinate |
required |
y
|
tensor
|
y coordinate |
required |
Return
dfdx (tensor): df / dx dfdy (tensor): df / dy
d2fdxyz2
Compute second-order partial derivatives of the surface function f(x, y, z): sag(x, y) - z = 0. This function is currently only used for surfaces constraints.
_d2fdxy
Compute second-order derivatives of sag to x and y. (d2fdx2, d2fdxdy, d2fdy2) = (f''xx, f''xy, f''yy).
Currently, we use finite difference method to compute the second-order derivatives. And the second-order derivatives are only used for surface constraints.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
tensor
|
x coordinate |
required |
y
|
tensor
|
y coordinate |
required |
Return
d2fdx2 (tensor): d2f / dx2 d2fdxdy (tensor): d2f / dxdy d2fdy2 (tensor): d2f / dy2
is_within_data_range
Valid points inside the data region of the sag function.
surface_with_offset
Calculate z coordinate of the surface at (x, y).
This function is used in lens setup plotting and lens self-intersection detection.
surface_sag
Calculate sag of the surface at (x, y).
This function is currently not used.
get_optimizer_params
Get optimizer parameters for different parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lrs
|
list
|
learning rates for different parameters. |
[0.0001]
|
optim_mat
|
bool
|
whether to optimize material. Defaults to False. |
False
|
init_tolerance
Initialize tolerance parameters for the surface.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tolerance_params
|
dict or None
|
Tolerance for surface parameters. Supported keys (all optional, default values shown): .. code-block:: python |
None
|
References
[1] https://www.edmundoptics.com/knowledge-center/application-notes/optics/understanding-optical-specifications/?srsltid=AfmBOorBa-0zaOcOhdQpUjmytthZc07oFlmPW_2AgaiNHHQwobcAzWII [2] https://wp.optics.arizona.edu/optomech/wp-content/uploads/sites/53/2016/08/8-Tolerancing-1.pdf [3] https://wp.optics.arizona.edu/jsasian/wp-content/uploads/sites/33/2016/03/L17_OPTI517_Lens-_Tolerancing.pdf
sensitivity_score
Tolerance squared sum.
Reference
[1] Page 10 from: https://wp.optics.arizona.edu/optomech/wp-content/uploads/sites/53/2016/08/8-Tolerancing-1.pdf
draw_widget
Draw widget for the surface on the 2D plot.
create_mesh
Create triangulated surface mesh.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_rings
|
int
|
Number of concentric rings for sampling. |
32
|
n_arms
|
int
|
Number of angular divisions. |
128
|
color
|
List[float]
|
The color of the mesh. |
[0.06, 0.3, 0.6]
|
Returns:
| Name | Type | Description |
|---|---|---|
self |
The surface with mesh data. |
_create_vertices
Create vertices in radial pattern. Vertices will be used to plot the surface in PyVista.
_create_faces
Create triangular faces. Faces will be used to plot the surface in PyVista.
_create_rim
Create rim (outer edge) vertices. Rims will be used to bridge two surfaces.
get_polydata
Get PyVista PolyData object from previously generated vertices and faces.
PolyData object will be used to draw the surface and export as .obj file.
Geometric Surfaces
Spheric
Standard spherical surface. Most common refractive element.
from deeplens.optics import Spheric
surface = Spheric(c=1/50.0, r=5.0, d=5.0, mat2="N-BK7", device='cuda')
deeplens.optics.geometric_surface.Spheric
Bases: Surface
Spherical refractive surface parameterized by curvature.
The sag function is:
.. math::
z(x, y) = \frac{c \rho^2}{1 + \sqrt{1 - c^2 \rho^2}}, \quad
\rho^2 = x^2 + y^2
Attributes:
| Name | Type | Description |
|---|---|---|
c |
Tensor
|
Surface curvature |
Initialize a spherical surface.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
c
|
float
|
Surface curvature |
required |
r
|
float
|
Aperture radius [mm]. |
required |
d
|
float
|
Axial vertex position [mm]. |
required |
mat2
|
str or Material
|
Material on the transmission side. |
required |
pos_xy
|
list[float]
|
Lateral offset |
[0.0, 0.0]
|
vec_local
|
list[float]
|
Local normal direction.
Defaults to |
[0.0, 0.0, 1.0]
|
is_square
|
bool
|
Square aperture flag. Defaults to
|
False
|
device
|
str
|
Compute device. Defaults to |
'cpu'
|
_d2fdxy
Compute second-order derivatives of the surface sag z = sag(x, y).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x
|
tensor
|
x coordinate |
required |
y
|
tensor
|
y coordinate |
required |
Returns:
| Name | Type | Description |
|---|---|---|
d2f_dx2 |
tensor
|
∂²f / ∂x² |
d2f_dxdy |
tensor
|
∂²f / ∂x∂y |
d2f_dy2 |
tensor
|
∂²f / ∂y² |
intersect
Solve ray-surface intersection in local coordinate system using analytical method.
Sphere equation: (x)^2 + (y)^2 + (z - R)^2 = R^2, where R = 1/c Ray equation: p(t) = o + t*d Solve quadratic equation for intersection parameter t.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
input ray. |
required |
n
|
float
|
refractive index. Defaults to 1.0. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
ray |
Ray
|
ray with updated position and opl. |
init_tolerance
Initialize tolerance parameters for the surface.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tolerance_params
|
dict
|
Tolerance for surface parameters. |
None
|
sample_tolerance
Randomly perturb surface parameters to simulate manufacturing errors.
get_optimizer_params
Activate gradient computation for c and d and return optimizer parameters.
Aspheric
Even-order aspheric surface for aberration correction.
Conic constant k: 0 = sphere, -1 = parabola, < -1 = hyperbola, (-1,0) = ellipse, > 0 = oblate ellipsoid.
from deeplens.optics import Aspheric
surface = Aspheric(r=50.0, d=5.0, k=0.0, ai=[0, 0, 1e-5, 0, -1e-7], device='cuda')
deeplens.optics.geometric_surface.Aspheric
Aspheric(r, d, c, k, ai, mat2, pos_xy=[0.0, 0.0], vec_local=[0.0, 0.0, 1.0], is_square=False, device='cpu')
Bases: Surface
Even-order aspheric surface.
The sag function is:
.. math::
z(\rho) = \frac{c\,\rho^2}{1 + \sqrt{1-(1+k)c^2\rho^2}}
+ \sum_{i=1}^{n} a_{2i}\,\rho^{2i},
\quad \rho^2 = x^2 + y^2
All coefficients c, k, and ai are differentiable torch
tensors so they can be optimised with gradient descent.
Attributes:
| Name | Type | Description |
|---|---|---|
c |
Tensor
|
Base curvature [1/mm]. |
k |
Tensor
|
Conic constant. |
ai |
Tensor
|
Even-order aspheric coefficients
|
Initialize an aspheric surface.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
r
|
float
|
Aperture radius [mm]. |
required |
d
|
float
|
Axial vertex position [mm]. |
required |
c
|
float
|
Base curvature |
required |
k
|
float
|
Conic constant ( |
required |
ai
|
list[float] or None
|
Even-order aspheric coefficients
|
required |
mat2
|
str or Material
|
Material on the transmission side. |
required |
pos_xy
|
list[float]
|
Lateral offset |
[0.0, 0.0]
|
vec_local
|
list[float]
|
Local normal direction.
Defaults to |
[0.0, 0.0, 1.0]
|
is_square
|
bool
|
Square aperture flag.
Defaults to |
False
|
device
|
str
|
Compute device. Defaults to |
'cpu'
|
_sag
Compute surface sag (height) z = sag(x, y).
The aspheric surface is defined as
z = r²c / (1 + sqrt(1 - (1+k)r²c²)) + Σ ai_{2i} * r^{2i}
where r² = x² + y², c is curvature, k is conic constant, and ai are the aspheric coefficients (ai2, ai4, ai6, ...).
_dfdxy
Compute first-order height derivatives df/dx and df/dy.
For the aspheric polynomial Σ ai_{2i} * r^{2i}, the derivative w.r.t. r² is Σ i * ai_{2i} * r^{2(i-1)}, i.e.: ai2 + 2ai4r² + 3ai6r⁴ + ...
get_optimizer_params
Get optimizer parameters for different parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lrs
|
list
|
learning rates for d, c, k, ai2, (ai4, ai6, ai8, ai10, ai12). |
[0.0001, 0.0001, 0.01, 0.0001]
|
optim_mat
|
bool
|
whether to optimize material. Defaults to False. |
False
|
init_tolerance
Perturb the surface with some tolerance.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tolerance_params
|
dict
|
Tolerance for surface parameters. |
None
|
References
[1] https://www.edmundoptics.com/capabilities/precision-optics/capabilities/aspheric-lenses/ [2] https://www.edmundoptics.com/knowledge-center/application-notes/optics/all-about-aspheric-lenses/?srsltid=AfmBOoon8AUXVALojol2s5K20gQk7W1qUisc6cE4WzZp3ATFY5T1pK8q
sample_tolerance
Randomly perturb surface parameters to simulate manufacturing errors.
Plane
deeplens.optics.geometric_surface.Plane
Bases: Surface
Plane surface.
Examples:
- IR filter.
- Lens cover glass.
- DOE base.
The following surfaces inherit from Plane
- Aperture.
- Mirror.
- ThinLens.
intersect
Solve ray-surface intersection in local coordinate system and update ray data.
normal_vec
Calculate surface normal vector at intersection points in local coordinate system.
Normal vector points from the surface toward the side where the light is coming from.
get_optimizer_params
Activate gradient computation for d and return optimizer parameters.
Aperture
Controls F-number, vignetting, and depth of field.
deeplens.optics.geometric_surface.Aperture
Bases: Plane
Aperture surface.
ray_reaction
Compute output ray after intersection and refraction.
create_mesh
Create triangulated surface mesh.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_rings
|
int
|
Number of concentric rings for sampling. |
32
|
n_arms
|
int
|
Number of angular divisions. |
128
|
color
|
List[float]
|
The color of the mesh. |
[0.0, 0.0, 0.0]
|
Returns:
| Name | Type | Description |
|---|---|---|
self |
The surface with mesh data. |
_create_vertices
Generate vertices for two-ring aperture (inner and outer rings).
_create_faces
Generate triangular faces connecting inner and outer rings.
get_optimizer_params
Activate gradient computation for d and return optimizer parameters.
Cubic
Cubic phase plate for extended depth of field (wavefront coding).
deeplens.optics.geometric_surface.Cubic
Bases: Surface
get_optimizer_params
Return parameters for optimizer.
Mirror
deeplens.optics.geometric_surface.Mirror
Mirror(r, d, mat2='air', pos_xy=[0.0, 0.0], vec_local=[0.0, 0.0, 1.0], is_square=True, device='cpu')
Bases: Plane
Mirror surface.
Diffractive Surfaces
Fresnel
from deeplens.optics.diffractive_surface import Fresnel
surface = Fresnel(foclen=50.0, d=0.001, zone_num=100, wavelength=0.550, device='cuda')
deeplens.optics.diffractive_surface.Fresnel
Fresnel(d, f0=None, wvln0=0.55, res=(2000, 2000), mat='fused_silica', fab_ps=0.001, fab_step=16, device='cpu')
Bases: DiffractiveSurface
Initialize Fresnel DOE. A diffractive Fresnel lens shows inverse dispersion property compared to refractive lens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
f0
|
float
|
Initial focal length. [mm] |
None
|
d
|
float
|
Distance of the DOE surface. [mm] |
required |
res
|
tuple or int
|
Resolution of the DOE, [w, h]. [pixel] |
(2000, 2000)
|
wvln0
|
float
|
Design wavelength. [um] |
0.55
|
mat
|
str
|
Material of the DOE. |
'fused_silica'
|
fab_ps
|
float
|
Fabrication pixel size. [mm] |
0.001
|
fab_step
|
int
|
Fabrication step. |
16
|
device
|
str
|
Device to run the DOE. |
'cpu'
|
Binary2
from deeplens.optics.diffractive_surface import Binary2
surface = Binary2(phase_pattern=torch.rand(512, 512) > 0.5, d=0.001, wavelength=0.550, device='cuda')
deeplens.optics.diffractive_surface.Binary2
Binary2(d, res=(2000, 2000), mat='fused_silica', wvln0=0.55, fab_ps=0.001, fab_step=16, device='cpu')
Bases: DiffractiveSurface
Initialize Binary DOE.
get_optimizer_params
Get parameters for optimization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lr
|
float
|
Base learning rate for alpha2. Learning rates for higher-order parameters will be scaled progressively (10x, 100x, 1000x, 10000x). |
0.001
|
Pixel2D
High-resolution pixelated metasurface with a learnable height map.
from deeplens.optics.diffractive_surface import Pixel2D
surface = Pixel2D(
height_map=torch.rand(1024, 1024) * 0.5,
pixel_size=0.5, d=0.001, n_material=1.5, wavelength=0.550, device='cuda'
)
deeplens.optics.diffractive_surface.Pixel2D
Pixel2D(d, phase_map_path=None, res=(2000, 2000), mat='fused_silica', wvln0=0.55, fab_ps=0.001, fab_step=16, device='cpu')
Bases: DiffractiveSurface
Pixel2D DOE parameterization - direct phase map representation.
Initialize Pixel2D DOE, where each pixel is independent parameter.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
float
|
Distance of the DOE surface. [mm] |
required |
size
|
tuple or int
|
Size of the DOE, [w, h]. [mm] |
required |
res
|
tuple or int
|
Resolution of the DOE, [w, h]. [pixel] |
(2000, 2000)
|
mat
|
str
|
Material of the DOE. |
'fused_silica'
|
fab_ps
|
float
|
Fabrication pixel size. [mm] |
0.001
|
fab_step
|
int
|
Fabrication step. |
16
|
device
|
str
|
Device to run the DOE. |
'cpu'
|
Zernike
Phase surface defined by Zernike polynomials. Common terms: indices 0–2 piston/tilt, 3 defocus, 4–5 astigmatism, 6–8 coma/trefoil, 9 spherical aberration.
from deeplens.optics.diffractive_surface import Zernike
surface = Zernike(
coefficients=[0, 0, 1, 0.5, 0, 0], d=0.001,
aperture_radius=10.0, wavelength=0.550, device='cuda'
)
deeplens.optics.diffractive_surface.Zernike
Zernike(d, z_coeff=None, zernike_order=37, res=(2000, 2000), mat='fused_silica', fab_ps=0.001, fab_step=16, wvln0=0.55, device='cpu')
Bases: DiffractiveSurface
DOE parameterized by Zernike polynomials.
Initialize Zernike DOE.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
DOE position |
required | |
res
|
DOE resolution |
(2000, 2000)
|
|
z_coeff
|
Zernike coefficients |
None
|
|
zernike_order
|
Number of Zernike coefficients to use |
37
|
|
fab_ps
|
Fabrication pixel size |
0.001
|
|
fab_step
|
Fabrication step |
16
|
|
device
|
Computation device |
'cpu'
|
Grating
deeplens.optics.diffractive_surface.Grating
Grating(d, res=(2000, 2000), mat='fused_silica', wvln0=0.55, fab_ps=0.001, fab_step=16, theta=0.0, alpha=0.0, device='cpu')
Bases: DiffractiveSurface
Grating diffractive optical element.
where
- theta: angle from y-axis to grating vector
- alpha: slope of the grating (phase gradient strength)
- norm_radii: normalization radius
Initialize Grating DOE.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
d
|
float
|
Distance of the DOE surface. [mm] |
required |
res
|
tuple or int
|
Resolution of the DOE, [w, h]. [pixel] |
(2000, 2000)
|
mat
|
str
|
Material of the DOE. |
'fused_silica'
|
wvln0
|
float
|
Design wavelength. [um] |
0.55
|
fab_ps
|
float
|
Fabrication pixel size. [mm] |
0.001
|
fab_step
|
int
|
Fabrication step. |
16
|
theta
|
float
|
Angle from y-axis to grating vector. [rad] |
0.0
|
alpha
|
float
|
Slope of the grating (phase gradient strength). |
0.0
|
device
|
str
|
Device to run the DOE. |
'cpu'
|
init_from_dict
classmethod
Initialize Grating DOE from a dict.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doe_dict
|
dict
|
Dictionary containing DOE parameters. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Grating |
Initialized Grating DOE object. |
phase_func
Get the phase map at design wavelength.
Returns:
| Name | Type | Description |
|---|---|---|
phase |
tensor
|
Phase map at design wavelength. |
get_optimizer_params
Get parameters for optimization.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lr
|
float
|
Learning rate for grating parameters. |
0.001
|
Returns:
| Name | Type | Description |
|---|---|---|
list |
List of parameter groups for optimizer. |
surf_dict
Return a dict of surface parameters.
Returns:
| Name | Type | Description |
|---|---|---|
dict |
Dictionary containing surface parameters. |
save_ckpt
Save grating DOE parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_path
|
str
|
Path to save the checkpoint. |
'./grating_doe.pth'
|
Phase Surfaces
deeplens.optics.phase_surface.Phase
Bases: DeepObj
Base phase profile for diffractive surfaces (metasurface or DOE).
This is the base class that provides common functionality for all phase parameterizations. Specific parameterizations should inherit from this class.
Reference
[1] https://support.zemax.com/hc/en-us/articles/1500005489061-How-diffractive-surfaces-are-modeled-in-OpticStudio [2] https://optics.ansys.com/hc/en-us/articles/360042097313-Small-Scale-Metalens-Field-Propagation [3] https://optics.ansys.com/hc/en-us/articles/18254409091987-Large-Scale-Metalens-Ray-Propagation
init_param_model
Initialize parameterization parameters. Must be implemented by subclasses.
get_optimizer_params
Generate optimizer parameters. Must be implemented by subclasses.
activate_diffraction
Activate diffraction of DOE in ray tracing.
intersect
Solve ray-plane intersection in local coordinate system and update ray data.
diffract
Diffraction of DOE surface. 1, The phase φ in radians adds to the optical path length of the ray 2, The gradient of the phase profile (phase slope) change the direction of rays.
Reference
[1] https://support.zemax.com/hc/en-us/articles/1500005489061-How-diffractive-surfaces-are-modeled-in-OpticStudio [2] Light propagation with phase discontinuities: generalized laws of reflection and refraction. Science 2011.
refract
normal_vec
Calculate surface normal vector at intersection points.
Normal vector points from the surface toward the side where the light is coming from.
to_local_coord
to_global_coord
_get_rotation_matrix
Calculate rotation matrix to rotate vec_from to vec_to.
surface_with_offset
Surface sag with offset, only used in layout drawing.
get_optimizer
Generate optimizer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lrs
|
list or float
|
Learning rates for different parameters. |
required |
draw_phase_map
Draw phase map. Range from [0, 2*pi].
Material
DeepLens includes the SCHOTT, CDGM, and PLASTIC glass catalogues.
from deeplens.optics import Material
glass = Material('N-BK7')
n = glass.n(wavelength=550) # refractive index at 550 nm
# Custom glass via Sellmeier equation
custom = Material(name='MyGlass', catalog='CUSTOM',
sellmeier_coef=[1.040, 0.232, 1.010, 0.006, 0.020, 103.6])
Sellmeier equation:
| Name | Type | n (550 nm) |
|---|---|---|
| N-BK7 | Crown glass | 1.519 |
| N-SF11 | Flint glass | 1.785 |
| PMMA | Plastic | 1.492 |
| Fused Silica | Glass | 1.460 |
deeplens.optics.material.Material
Bases: DeepObj
Optical material defined by its wavelength-dependent refractive index.
Materials are looked up by name in the bundled CDGM, SCHOTT, or MISC AGF
catalogs, in a custom JSON catalog, or specified inline as "n/V"
(Cauchy approximation from Abbe number V).
Supported dispersion models: "sellmeier", "cauchy", "schott",
and "interp" (lookup table).
Attributes:
| Name | Type | Description |
|---|---|---|
name |
str
|
Lowercase material name. |
dispersion |
str
|
Dispersion model used ( |
n |
float
|
Refractive index at the d-line (587 nm). |
V |
float
|
Abbe number. |
Initialize an optical material.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str or None
|
Material name (case-insensitive). Accepted forms:
Defaults to |
None
|
device
|
str
|
Compute device. Defaults to |
'cpu'
|
Raises:
| Type | Description |
|---|---|
NotImplementedError
|
If name is not found in any catalog. |
Example
mat = Material("N-BK7") n_green = mat.get_ri(0.587) # refractive index at 587 nm
set_material_param_agf
Set the material parameters and dispersion equation from AGF file.
set_sellmeier_param
Manually set sellmeier parameters k1, l1, k2, l2, k3, l3.
This function is used when we want to manually set the sellmeier parameters for a custom material.
nV_to_AB
staticmethod
Convert (n ,V) paramters to (A, B) parameters to find the material.
match_material
Find the closest material in the CDGM common glasses database.
Light
Ray
Holds ray origins o, directions d, wavelength, validity mask, energy,
and optical path length (OPL for coherent tracing).
from deeplens.optics import Ray
ray = Ray(
o=torch.zeros(N, 3), # origins [mm]
d=torch.zeros(N, 3), # unit direction vectors
wavelength=0.550, # wavelength [μm]
device='cuda'
)
# Trace through a surface
ray_out = surface.ray_reaction(ray, n1=1.0, n2=1.5, wavelength=0.550)
deeplens.optics.light.Ray
Bases: DeepObj
Batched ray bundle for optical simulation.
Stores ray origins, directions, wavelength, validity mask, energy, obliquity,
and (in coherent mode) optical path length. All tensor attributes share the
same batch shape (*batch_size, num_rays).
Attributes:
| Name | Type | Description |
|---|---|---|
o |
Tensor
|
Ray origins, shape |
d |
Tensor
|
Unit ray directions, shape |
wvln |
Tensor
|
Wavelength scalar [µm]. |
is_valid |
Tensor
|
Binary validity mask, shape |
en |
Tensor
|
Energy weight, shape |
obliq |
Tensor
|
Obliquity factor, shape |
opl |
Tensor
|
Optical path length (coherent mode only),
shape |
coherent |
bool
|
Whether OPL tracking is enabled. |
Initialize a ray object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
o
|
Tensor
|
Ray origin, shape |
required |
d
|
Tensor
|
Ray direction, shape |
required |
wvln
|
float
|
Ray wavelength [µm]. |
DEFAULT_WAVE
|
coherent
|
bool
|
Enable optical path length tracking for coherent
tracing. Defaults to |
False
|
device
|
str
|
Compute device. Defaults to |
'cpu'
|
prop_to
Ray propagates to a given depth plane.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
z
|
float
|
depth. |
required |
n
|
float
|
refractive index. Defaults to 1. |
1.0
|
centroid
Calculate the centroid of the ray, shape (..., num_rays, 3)
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Centroid of the ray, shape (..., 3) |
rms_error
Calculate the RMS error of the ray.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
center_ref
|
Tensor
|
Reference center of the ray, shape (..., 3). If None, use the centroid of the ray as reference. |
None
|
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: average RMS error of the ray |
flip_xy
Flip the x and y coordinates of the ray.
This function is used when calculating point spread function and wavefront distribution.
clone
Clone the ray.
Can spercify which device we want to clone. Sometimes we want to store all rays in CPU, and when using it, we move it to GPU.
squeeze
Squeeze the ray.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dim
|
int
|
dimension to squeeze. Defaults to None. |
None
|
ComplexWave
Complex field with ASM / Fresnel / Fraunhofer propagation via torch.fft.
deeplens.optics.light.ComplexWave
Bases: DeepObj
Complex scalar wave field for diffraction simulation.
Represents a monochromatic, coherent complex amplitude on a uniform
rectangular grid. Propagation methods (ASM, Fresnel, Fraunhofer) are
implemented as member functions and use torch.fft for efficiency.
Attributes:
| Name | Type | Description |
|---|---|---|
u |
Tensor
|
Complex amplitude, shape |
wvln |
float
|
Wavelength [µm]. |
k |
float
|
Wave number |
phy_size |
tuple
|
Physical aperture size (W, H) [mm]. |
ps |
float
|
Pixel pitch [mm] (must be square). |
res |
tuple
|
Grid resolution (H, W) in pixels. |
z |
float
|
Current axial position [mm]. |
Initialize a complex wave field.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
u
|
Tensor or None
|
Initial complex amplitude.
Accepted shapes: |
None
|
wvln
|
float
|
Wavelength [µm]. Defaults to |
0.55
|
z
|
float
|
Initial axial position [mm]. Defaults to
|
0.0
|
phy_size
|
tuple
|
Physical aperture (W, H) [mm].
Defaults to |
(4.0, 4.0)
|
res
|
tuple
|
Grid resolution (H, W) [pixels]. Only
used when u is |
(2000, 2000)
|
Raises:
| Type | Description |
|---|---|
AssertionError
|
If the pixel pitch is not square or the
wavelength is outside the range |
point_wave
classmethod
point_wave(point=(0, 0, -1000.0), wvln=0.55, z=0.0, phy_size=(4.0, 4.0), res=(2000, 2000), valid_r=None)
Create a spherical wave field on x0y plane originating from a point source.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
point
|
tuple
|
Point source position in object space. [mm]. Defaults to (0, 0, -1000.0). |
(0, 0, -1000.0)
|
wvln
|
float
|
Wavelength. [um]. Defaults to 0.55. |
0.55
|
z
|
float
|
Field z position. [mm]. Defaults to 0.0. |
0.0
|
phy_size
|
tuple
|
Valid plane on x0y plane. [mm]. Defaults to (2, 2). |
(4.0, 4.0)
|
res
|
tuple
|
Valid plane resoltution. Defaults to (1000, 1000). |
(2000, 2000)
|
valid_r
|
float
|
Valid circle radius. [mm]. Defaults to None. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
field |
ComplexWave
|
Complex field on x0y plane. |
plane_wave
classmethod
Create a planar wave field on x0y plane.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wvln
|
float
|
Wavelength. [um]. |
0.55
|
z
|
float
|
Field z position. [mm]. |
0.0
|
phy_size
|
tuple
|
Physical size of the field. [mm]. |
(4.0, 4.0)
|
res
|
tuple
|
Resolution. |
(2000, 2000)
|
valid_r
|
float
|
Valid circle radius. [mm]. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
field |
ComplexWave
|
Complex field. |
image_wave
classmethod
Initialize a complex wave field from an image.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
Tensor
|
Input image with shape [H, W] or [B, C, H, W]. Data range is [0, 1]. |
required |
wvln
|
float
|
Wavelength. [um]. |
0.55
|
z
|
float
|
Field z position. [mm]. |
0.0
|
phy_size
|
tuple
|
Physical size of the field. [mm]. |
(4.0, 4.0)
|
Returns:
| Name | Type | Description |
|---|---|---|
field |
ComplexWave
|
Complex field. |
prop
Propagate the field by distance z. Can only propagate planar wave.
Reference
[1] Modeling and propagation of near-field diffraction patterns: A more complete approach. Table 1. [2] https://github.com/kaanaksit/odak/blob/master/odak/wave/classical.py [3] https://spie.org/samples/PM103.pdf [4] "Non-approximated Rayleigh Sommerfeld diffraction integral: advantages and disadvantages in the propagation of complex wave fields"
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prop_dist
|
float
|
propagation distance, unit [mm]. |
required |
n
|
float
|
refractive index. |
1.0
|
Returns:
| Name | Type | Description |
|---|---|---|
self |
propagated complex wave field. |
prop_to
Propagate the field to plane z.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
z
|
float
|
destination plane z coordinate. |
required |
pad
Pad the input field by (Hpad, Hpad, Wpad, Wpad). This step will also expand physical size of the field.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
Hpad
|
int
|
Number of pixels to pad on the top and bottom. |
required |
Wpad
|
int
|
Number of pixels to pad on the left and right. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
self |
Padded complex wave field. |
AngularSpectrumMethod
from deeplens.optics import AngularSpectrumMethod
asm = AngularSpectrumMethod(device='cuda')
field_out = asm.forward(field_in, distance=10.0, wavelength=0.550, pixel_size=0.01)
deeplens.optics.light.AngularSpectrumMethod
Angular spectrum method.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
u
|
tesor
|
complex field, shape [H, W] or [B, 1, H, W] |
required |
z
|
float
|
propagation distance in [mm] |
required |
wvln
|
float
|
wavelength in [um] |
required |
ps
|
float
|
pixel size in [mm] |
required |
n
|
float
|
refractive index |
1.0
|
padding
|
bool
|
padding or not |
True
|
Returns:
| Name | Type | Description |
|---|---|---|
u |
complex field, shape [H, W] or [B, 1, H, W] |
Reference
[1] https://github.com/kaanaksit/odak/blob/master/odak/wave/classical.py#L293 [2] https://blog.csdn.net/zhenpixiaoyang/article/details/111569495
Image Simulation
Monte-Carlo PSF Integration
Bins ray hits into PSF grids via index_put_ with accumulate=True.
Coherent mode uses OPL for complex amplitude accumulation.
deeplens.optics.imgsim.forward_integral
Differentiable Monte-Carlo integral over a ray bundle onto a pixel grid.
Bins ray hit positions into a ks × ks grid centred on pointc (or the
ray centroid if pointc is None). In coherent mode the complex
amplitude is accumulated instead of intensity, allowing PSF and wavefront
computation.
The implementation uses index_put_ with accumulate=True for
differentiability. A loop over the N field points is used because
index_put_ cannot independently accumulate to separate batch slices;
this is acceptable because N is typically small (1–10) while spp
is large.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ray
|
Ray
|
Traced ray bundle with origin |
required |
ps
|
float
|
Pixel size [mm]. |
required |
ks
|
int
|
Output grid size in pixels (square). |
required |
pointc
|
Tensor or None
|
Reference centre for each
field point, shape |
None
|
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Accumulated field, shape |
|
|
complex if |
PSF Convolution
deeplens.optics.imgsim.conv_psf
Convolve an image batch with a single spatially-uniform PSF.
Applies a per-channel 2-D convolution using reflect boundary padding
so that the output has the same spatial dimensions as the input. The PSF
is internally flipped to convert the cross-correlation implemented by
F.conv2d into a true convolution.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
Tensor
|
Input image batch, shape |
required |
psf
|
Tensor
|
PSF kernel, shape |
required |
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Rendered image, shape |
Example
psf = lens.psf_rgb(points=torch.tensor([0.0, 0.0, -10000.0])) img_blur = conv_psf(img, psf)
deeplens.optics.imgsim.conv_psf_map
Convolve an image batch with a spatially-varying PSF map.
Divides the image into grid_h × grid_w non-overlapping patches and
convolves each patch with its corresponding PSF kernel. The results are
assembled back into a full-resolution output via a weighted blending step.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
Tensor
|
Input image batch, shape |
required |
psf_map
|
Tensor
|
PSF map, shape |
required |
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Rendered image, shape |
deeplens.optics.imgsim.conv_psf_depth_interp
Depth-interpolated PSF convolution for a spatially-uniform but depth-varying blur.
Pre-convolves the image with PSFs at each reference depth, then blends the results using per-pixel linear interpolation weights derived from depth. This approximates defocus blur for a single field position across a depth range without computing a separate PSF per pixel.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
Tensor
|
Image batch, shape |
required |
depth
|
Tensor
|
Depth map, shape |
required |
psf_kernels
|
Tensor
|
PSF stack at reference depths, shape
|
required |
psf_depths
|
Tensor
|
Depth of each PSF layer, shape
|
required |
interp_mode
|
str
|
Interpolation space. |
'depth'
|
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Blurred image, shape |
Raises:
| Type | Description |
|---|---|
AssertionError
|
If depth or psf_depths contain non-negative values,
or if interp_mode is not |
deeplens.optics.imgsim.conv_psf_map_depth_interp
Convolve an image with a PSF map. Within each image patch, do interpolation with a depth map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
(B, 3, H, W), [0, 1] |
required | |
depth
|
(B, 1, H, W), (-inf, 0) |
required | |
psf_map
|
(grid_h, grid_w, num_depth, 3, ks, ks) |
required | |
psf_depths
|
(num_depth). (-inf, 0). Used to interpolate psf_map. |
required | |
interp_mode
|
"depth" or "disparity". If "disparity", weights are calculated based on disparity (1/depth). |
'depth'
|
Returns:
| Name | Type | Description |
|---|---|---|
img_render |
(B, 3, H, W), [0, 1] |
deeplens.optics.imgsim.conv_psf_pixel
Convolve an image batch with pixel-wise PSF.
Use the different PSF kernel for different pixels (folding approach). Application example: Blurs image with dynamic Gaussian blur.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
img
|
Tensor
|
The image to be blurred (B, C, H, W). |
required |
psf
|
Tensor
|
Per pixel local PSFs (H, W, C, ks, ks). ks can be odd or even. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
img_render |
Tensor
|
Rendered image (B, C, H, W). |