Zernike#

class deeptrack.aberrations.Zernike(n: PropertyLike[int | list[int]], m: PropertyLike[int | list[int]], coefficient: PropertyLike[float | list[float]] = 1, **kwargs: dict[str, Any])#

Bases: Aberration

Introduces a Zernike phase aberration.

This class applies Zernike polynomial-based phase aberrations to an input pupil function. The Zernike polynomials are used to model various optical aberrations such as defocus, astigmatism, and coma.

The Zernike polynomial is defined by the radial index n and the azimuthal index m. The phase contribution is weighted by a specified coefficient. When multiple values are provided for n, m, and coefficient, the corresponding Zernike polynomials are summed and applied to the pupil phase.

Parameters#

n: PropertyLike[int or list of ints]

The radial index or indices of the Zernike polynomials.

m: PropertyLike[int or list of ints]

The azimuthal index or indices of the Zernike polynomials.

coefficient: PropertyLike[float or list of floats]

The scaling coefficient(s) for the Zernike polynomials.

Attributes#

n: PropertyLike[int or list of ints]

The radial index or indices of the Zernike polynomials.

m: PropertyLike[int or list of ints]

The azimuthal index or indices of the Zernike polynomials.

coefficient: PropertyLike[float or list of floats]

The scaling coefficient(s) for the Zernike polynomials.

Methods#

get(pupil: np.ndarray, rho: np.ndarray, theta: np.ndarray, n: int | list[int], m: int | list[int], coefficient: float | list[float], **kwargs: dict[str, Any]) -> np.ndarray

Applies the Zernike phase aberration to the input pupil function.

Notes#

The Zernike polynomials are normalized to ensure orthogonality. The phase aberration is added in the form of a complex exponential.

Examples#

Apply Zernike polynomial-based phase aberrations to a simulated fluorescence image:

>>> import deeptrack as dt
>>> particle = dt.PointParticle(z = 1 * dt.units.micrometer)
>>> aberrated_optics = dt.Fluorescence(
>>>     pupil=dt.Zernike(
>>>         n=[0, 1], 
>>>         m = [1, 2], 
>>>        coefficient=[1, 1]
>>>     )
>>> )
>>> aberrated_particle = aberrated_optics(particle)
>>> aberrated_particle.plot(cmap="gray")

Methods Summary

get(pupil, rho, theta, n, m, coefficient, ...)

Applies the Zernike phase aberration to the input pupil function.

Methods Documentation

get(pupil: np.ndarray, rho: np.ndarray, theta: np.ndarray, n: int | list[int], m: int | list[int], coefficient: float | list[float], **kwargs: dict[str, Any]) np.ndarray#

Applies the Zernike phase aberration to the input pupil function.

The method calculates Zernike polynomials for the specified indices n and m, scales them by coefficient, and adds the resulting phase to the input pupil function. Multiple polynomials are summed if n, m, and coefficient are provided as lists.

Parameters#

pupil: np.ndarray

A 2D array representing the input pupil function. The values should represent the amplitude and phase across the aperture.

rho: np.ndarray

A 2D array of radial coordinates normalized to the pupil aperture. The values should range from 0 to 1 within the aperture.

theta: np.ndarray

A 2D array of angular coordinates in radians. These define the azimuthal positions for the pupil.

n: int or list of ints

The radial indices of the Zernike polynomials.

m: int or list of ints

The azimuthal indices of the Zernike polynomials.

coefficient: float or list of floats

The coefficients for the Zernike polynomials, controlling their relative contributions to the phase.

**kwargs: dict, optional

Additional parameters for compatibility with other features or inherited methods.

Returns#

np.ndarray

The modified pupil function with the applied Zernike phase aberration.

Raises#

AssertionError

If the lengths of n, m, and coefficient lists do not match.

Notes#

  • The method first calculates the Zernike polynomials for each

combination of n and m and scales them by the corresponding coefficient. - The resulting polynomials are summed and converted into a phase factor, which is applied to the pupil.

Examples#

>>> import deeptrack as dt
>>> import numpy as np
>>> import matplotlib.pyplot as plt
>>> pupil = np.ones((128, 128), dtype=complex)
>>> x = np.linspace(-1, 1, 128)
>>> y = np.linspace(-1, 1, 128)
>>> X, Y = np.meshgrid(x, y)
>>> rho = np.sqrt(X**2 + Y**2)  
>>> theta = np.arctan2(Y, X) 
>>> pupil[rho > 1] = 0 
>>> n = [2, 3]
>>> m = [0, 1]
>>> coefficient = [0.5, 0.3]
>>> zernike = dt.Zernike(n=n, m=m, coefficient=coefficient)
>>> modified_pupil = zernike.get(pupil, rho, theta, n, m, coefficient)
>>> fig, axes = plt.subplots(1, 2, figsize=(12, 6))
>>> axes[0].imshow(np.abs(modified_pupil), cmap="gray")
>>> axes[0].set_title("Modified Pupil Magnitude")
>>> axes[1].imshow(np.angle(modified_pupil), cmap="hsv")
>>> axes[1].set_title("Modified Pupil Phase")
>>> plt.show()