HybridLens
Combines a GeoLens with a diffractive optical element (DOE).
HybridLens performs coherent ray tracing to the DOE plane, then Angular
Spectrum Method (ASM) propagation to the sensor — a hybrid ray–wave model for
refractive lenses with DOE or metasurface phase elements.
deeplens.HybridLens
HybridLens(filename=None, device=None, dtype=torch.float64, primary_wvln=DEFAULT_WAVE, wvln_rgb=WAVE_RGB, obj_depth=DEPTH)
Bases: Lens
Hybrid refractive-diffractive lens using a differentiable ray–wave model.
Combines a 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
|
primary_wvln
|
float
|
Primary design wavelength [µm].
Used as fallback when a method is called without an explicit
|
DEFAULT_WAVE
|
wvln_rgb
|
sequence of float
|
Three wavelengths used
for RGB computations, ordered |
WAVE_RGB
|
obj_depth
|
float
|
Default object depth [mm], used
when a method is called without an explicit |
DEPTH
|
Source code in deeplens-src/deeplens/hybridlens.py
read_lens_json
Read the lens configuration from a JSON file.
Loads a GeoLens and associated DOE from the specified file.
A Plane surface is appended to the GeoLens surface list as a
placeholder for the DOE plane.
Supported DOE types: binary2, pixel2d, fresnel,
zernike, grating.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
Path to the JSON configuration file. Must
contain a |
required |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the DOE type in the file is not supported. |
Source code in deeplens-src/deeplens/hybridlens.py
write_lens_json
Write the lens configuration to a JSON file.
Serialises the GeoLens surfaces (excluding the DOE placeholder)
and the DOE configuration into a single JSON file that can be
reloaded with read_lens_json.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lens_path
|
str
|
Output file path. |
required |
Source code in deeplens-src/deeplens/hybridlens.py
analysis
Run a quick visual analysis of the hybrid lens.
Generates two figures: the 2D lens layout (saved to save_name) and
the DOE phase map (saved to <save_name>_doe.png).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_name
|
str
|
Base file path for the layout image.
The DOE phase-map image is derived by appending |
'./test.png'
|
Source code in deeplens-src/deeplens/hybridlens.py
double
Convert the GeoLens and DOE to float64 precision.
Double precision is required for numerically stable phase
accumulation during coherent ray tracing and ASM propagation.
Called automatically by __init__.
Source code in deeplens-src/deeplens/hybridlens.py
refocus
Refocus the hybrid lens to a given object distance.
Only the GeoLens sensor-to-last-surface spacing is adjusted; the
DOE remains fixed relative to the refractive group (it is physically
cemented to the lens barrel).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
foc_dist
|
float
|
Target focus distance in [mm] (negative, towards the object). |
required |
Source code in deeplens-src/deeplens/hybridlens.py
calc_scale
Calculate the object-to-image magnification scale factor.
Delegates to the embedded GeoLens.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
depth
|
float
|
Object distance in [mm] (negative, towards the object). |
required |
Returns:
| Name | Type | Description |
|---|---|---|
float |
Scale factor mapping normalised sensor coordinates
|
Source code in deeplens-src/deeplens/hybridlens.py
doe_field
Compute the complex wave field at the DOE plane via coherent ray tracing.
Similar to GeoLens.pupil_field(), but evaluates the field at the
last surface (DOE plane) instead of the exit pupil. The returned
wavefront encodes amplitude, phase, and all diffraction-order
information needed for subsequent DOE modulation and ASM propagation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
point
|
Tensor
|
Point source position, shape |
required |
wvln
|
float
|
Wavelength in µm. When |
None
|
spp
|
int
|
Number of rays to sample. Must be
|
SPP_COHERENT
|
Returns:
| Name | Type | Description |
|---|---|---|
tuple |
|
Raises:
| Type | Description |
|---|---|
AssertionError
|
If spp < 1,000,000 or the default dtype is not
|
Source code in deeplens-src/deeplens/hybridlens.py
279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 | |
psf
Compute a single-point monochromatic PSF using the ray-wave model.
The returned PSF includes all diffraction orders with physically correct diffraction efficiencies. The pipeline is:
- Coherent ray tracing through the
GeoLensto obtain the complex wavefront at the DOE plane. - DOE phase modulation applied to the wavefront.
- ASM propagation to the sensor, intensity calculation, cropping, and normalisation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
points
|
list or Tensor
|
|
[0.0, 0.0, -10000.0]
|
ks
|
int or None
|
Output PSF patch size. If |
PSF_KS
|
wvln
|
float
|
Wavelength in µm. When |
None
|
spp
|
int
|
Number of coherent rays to sample. Defaults
to |
SPP_COHERENT
|
Returns:
| Type | Description |
|---|---|
|
torch.Tensor: Normalised PSF patch (sums to 1), shape
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If the default dtype is not |
Source code in deeplens-src/deeplens/hybridlens.py
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 | |
draw_layout
Draw the hybrid-lens layout with ray paths and wave-propagation arcs.
Renders the refractive elements via GeoLens.draw_lens_2d(), traces
rays at three field angles (on-axis, 0.707x, 0.99x full field), and
overlays concentric arcs between the DOE and sensor to illustrate the
wave-propagation region.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_name
|
str
|
File path to save the figure (used only
when ax is |
'./DOELens.png'
|
depth
|
float
|
Object depth [mm] for the traced rays.
Defaults to |
-10000.0
|
ax
|
Axes
|
Pre-existing axes to draw
into. If |
None
|
fig
|
Figure
|
Pre-existing figure. Required when ax is provided. |
None
|
dpi
|
int
|
Resolution used when saving a new figure. Defaults to 600. |
600
|
Returns:
| Type | Description |
|---|---|
|
tuple or None: |
Source code in deeplens-src/deeplens/hybridlens.py
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 | |
get_optimizer
Build an Adam optimiser for joint lens + DOE design.
Collects trainable parameters from both the GeoLens (surface
thicknesses, curvatures, conic constants, aspheric coefficients) and
the DOE phase profile into a single optimiser with per-group learning
rates.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doe_lr
|
float
|
Learning rate for DOE phase parameters.
Defaults to |
0.0001
|
lens_lr
|
list[float]
|
Per-parameter-group learning
rates for the GeoLens, ordered as
|
[0.0001, 0.0001, 0.01, 1e-05]
|
Returns:
| Type | Description |
|---|---|
|
torch.optim.Adam: Configured optimiser over all trainable parameters. |
Source code in deeplens-src/deeplens/hybridlens.py
DOE Models
The diffractive element is configured by the DOE block in the lens JSON; its
type field selects one of the phase parameterizations below. All subclass
DiffractiveSurface, which defines the shared phase / propagation interface.
deeplens.diffractive_surface.DiffractiveSurface
DiffractiveSurface(d, res, fab_ps=0.001, fab_step=16, wvln0=0.55, mat='fused_silica', design_ps=None, is_square=True, device='cpu')
Bases: DeepObj
Diffractive (multi-layer diffractive) surface class. Optical properties of diffractive surfaces are simulated with wave optics.
By default the DOE is designed for 0.55um, which means it will have the highest 1st-order diffraction efficiency for 0.55um.
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] |
required |
fab_ps
|
float
|
Fabrication pixel size. [mm] |
0.001
|
fab_step
|
int
|
Fabrication step. Default is 16. |
16
|
wvln0
|
float
|
Design wavelength. [um] |
0.55
|
mat
|
str
|
Material of the DOE. |
'fused_silica'
|
design_ps
|
float
|
Design pixel size. [mm] |
None
|
device
|
str
|
Device to run the DOE. |
'cpu'
|
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
init_from_dict
classmethod
phase_func
Calculate raw phase function (no wrapping, no quantization) at design wavelength.
Returns:
| Name | Type | Description |
|---|---|---|
phase |
tensor
|
raw phase function at design wavelength. |
get_phase_map0
Calculate phase map at design wavelength with phase wrapping and quantization.
In this function, we are actually processing height map. The maximum height is 2pi for design wavelength.
Returns:
| Name | Type | Description |
|---|---|---|
phase0 |
tensor
|
phase map at design wavelength, range [0, 2pi]. |
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
get_phase_map
Calculate phase map at the given wavelength.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wvln
|
float
|
Wavelength. [um]. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
phase_map |
tensor
|
Phase map. [1, 1, H, W], range [0, 2pi]. |
Note
First we should calculate the phase map at 0.55um, then calculate the phase map for the given other wavelength.
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
forward
Propagate wave field to the DOE and apply phase modulation. Input wave field can have different pixel size and physical size with the DOE.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wave
|
Wave
|
Input complex wave field. Shape of [B, 1, H, W]. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
wave |
Wave
|
Output complex wave field. Shape of [B, 1, H, W]. |
Reference
[1] https://github.com/vsitzmann/deepoptics function phaseshifts_from_height_map
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
__call__
Forward function.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
wave
|
Wave
|
Input complex wave field. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
wave |
Wave
|
Output complex wave field. |
pmap_quantize
Quantize phase map to bits levels.
pmap_fab
Convert to fabricate phase map and save it. This function is used to output DOE_fab file, and it will not change the DOE object itself.
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
activate_grad
get_optimizer
Generate optimizer for DOE.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lr
|
float
|
Learning rate. Defaults to 1e-3. |
None
|
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
loss_quantization
DOE quantization errors.
Reference: Quantization-aware Deep Optics for Diffractive Snapshot Hyperspectral Imaging
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
draw_phase_map
Draw phase map. Range from [0, 2pi].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bits
|
int
|
Number of quantization bits. If provided, quantizes the phase map. |
None
|
save_name
|
str
|
Path to save the image. |
'./DOE_phase_map.png'
|
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
draw_phase_map3d
Draw 3D phase map.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
bits
|
int
|
Number of quantization bits. If provided, quantizes the phase map. |
None
|
save_name
|
str
|
Path to save the image. |
'./DOE_phase_map3d.png'
|
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
draw_phase_map_fab
Draw phase map. Range from [0, 2pi].
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
draw_cross_section
Draw cross section of the phase map.
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
draw_widget
Draw a 2D Fresnel-style widget for the DOE in a layout plot.
Plots the cross-section along the x-axis at y=0. For a square aperture
the half-extent is the half-side (w/2); for a circular aperture it
is the full radius r (= half-diagonal).
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
surf_dict
Return a dict of surface.
Source code in deeplens-src/deeplens/diffractive_surface/diffractive.py
Polynomial (Binary-2) rotationally-symmetric phase profile.
deeplens.diffractive_surface.Binary2
Binary2(d, res=(2000, 2000), mat='fused_silica', wvln0=0.55, fab_ps=0.001, fab_step=16, is_square=True, device='cpu')
Bases: DiffractiveSurface
Initialize Binary DOE.
Source code in deeplens-src/deeplens/diffractive_surface/binary2.py
init_from_dict
classmethod
Initialize Binary DOE from a dict.
Source code in deeplens-src/deeplens/diffractive_surface/binary2.py
phase_func
Get the phase map at design wavelength.
Source code in deeplens-src/deeplens/diffractive_surface/binary2.py
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
|
Source code in deeplens-src/deeplens/diffractive_surface/binary2.py
surf_dict
Return a dict of surface.
Source code in deeplens-src/deeplens/diffractive_surface/binary2.py
Free-form, per-pixel phase map.
deeplens.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'
|
Source code in deeplens-src/deeplens/diffractive_surface/pixel2d.py
init_from_dict
classmethod
Initialize Pixel2D DOE from a dict.
Source code in deeplens-src/deeplens/diffractive_surface/pixel2d.py
phase_func
get_optimizer_params
Get parameters for optimization.
surf_dict
Return a dict of surface.
Source code in deeplens-src/deeplens/diffractive_surface/pixel2d.py
Fresnel-lens (quadratic) phase profile.
deeplens.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'
|
Source code in deeplens-src/deeplens/diffractive_surface/fresnel.py
init_from_dict
classmethod
Initialize Fresnel DOE from a dict.
Source code in deeplens-src/deeplens/diffractive_surface/fresnel.py
phase_func
Get the phase map at design wavelength.
Source code in deeplens-src/deeplens/diffractive_surface/fresnel.py
get_optimizer_params
Get parameters for optimization.
Phase parameterized by Zernike polynomials.
deeplens.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'
|
Source code in deeplens-src/deeplens/diffractive_surface/zernike.py
init_from_dict
classmethod
Initialize Zernike DOE from a dict.
Source code in deeplens-src/deeplens/diffractive_surface/zernike.py
phase_func
get_optimizer_params
Get parameters for optimization.
surf_dict
Return a dict of surface.
Linear / blazed grating phase.
deeplens.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'
|
Source code in deeplens-src/deeplens/diffractive_surface/grating.py
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. |
Source code in deeplens-src/deeplens/diffractive_surface/grating.py
phase_func
Get the phase map at design wavelength.
Returns:
| Name | Type | Description |
|---|---|---|
phase |
tensor
|
Phase map at design wavelength. |
Source code in deeplens-src/deeplens/diffractive_surface/grating.py
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. |
Source code in deeplens-src/deeplens/diffractive_surface/grating.py
surf_dict
Return a dict of surface parameters.
Returns:
| Name | Type | Description |
|---|---|---|
dict |
Dictionary containing surface parameters. |
Source code in deeplens-src/deeplens/diffractive_surface/grating.py
save_ckpt
Save grating DOE parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
save_path
|
str
|
Path to save the checkpoint. |
'./grating_doe.pth'
|
Source code in deeplens-src/deeplens/diffractive_surface/grating.py
load_ckpt
Load grating DOE parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
load_path
|
str
|
Path to load the checkpoint from. |
'./grating_doe.pth'
|