pyzernike.cartesian_to_elliptic_annulus#

pyzernike.cartesian_to_elliptic_annulus(x: ndarray, y: ndarray, Rx: Real = 1.0, Ry: Real = 1.0, x0: Real = 0.0, y0: Real = 0.0, alpha: Real = 0.0, h: Real = 0.0, x_derivative: array | Sequence[Integral] | None = None, y_derivative: array | Sequence[Integral] | None = None) Tuple[List[ndarray], List[ndarray]][source]#

Transform Cartesian coordinates \((x, y)\) to elliptic annulus domain polar coordinates \((\rho_{eq}, \theta_{eq})\).

See also

Lets consider the extended elliptic annulus domain defined by the following parameters:

../_images/elliptic_annulus_domain.png

The parameters to define the extended domain of the Zernike polynomial.#

The parameters are:

  • \(R_x\) and \(R_y\) are the lengths of the semi-axis of the ellipse.

  • \(x_0\) and \(y_0\) are the coordinates of the center of the ellipse.

  • \(\alpha\) is the rotation angle of the ellipse in radians.

  • \(h=\frac{a}{R_x}=\frac{b}{R_y}\) defining the inner boundary of the ellipse.

The methods allow to compute the polar coordinates \((\rho_{eq}, \theta_{eq})\) and their derivatives with respect to the Cartesian coordinates \((x, y)\).

  • x and y are expected to be numpy arrays of the same shape.

  • x_derivative and y_derivative must be sequences of non-negative integers of the same length.

The output is a tuple of two lists with lengths equal to the length of x_derivative and y_derivative:

  • The first list contains the equivalent polar radius \(\rho_{eq}\) and its derivatives with respect to the given orders.

  • The second list contains the equivalent polar angle \(\theta_{eq}\) and its derivatives with respect to the given orders.

Note

If the input x or y are not floating point numpy arrays, it is converted to one with numpy.float64 dtype. If the input x or y are floating point numpy arrays (ex: numpy.float32), the computation will be done in numpy.float32. If the input x and y are not of the same dtype, they are both converted to numpy.float64.

The derivatives for orders higher than 2 are computed using symbolic differentiation with sympy library (high computational cost). For orders 0, 1 and 2, the derivatives are computed using the analytical expressions derived from the chain rule.

Parameters:
  • x (numpy.ndarray) – The x coordinates in Cartesian system with shape (…,).

  • y (numpy.ndarray) – The y coordinates in Cartesian system with shape (…,).

  • Rx (Real, optional) – The length of the semi-axis of the ellipse along x axis. Must be strictly positive. The default is 1.0, which corresponds to the unit circle.

  • Ry (Real, optional) – The length of the semi-axis of the ellipse along y axis. Must be strictly positive. The default is 1.0, which corresponds to the unit circle.

  • x0 (Real, optional) – The x coordinate of the center of the ellipse. Can be any real number. The default is 0.0, which corresponds to an ellipse centered at the origin.

  • y0 (Real, optional) – The y coordinate of the center of the ellipse. Can be any real number. The default is 0.0, which corresponds to an ellipse centered at the origin.

  • alpha (Real, optional) – The rotation angle of the ellipse in radians. Can be any real number. The default is 0.0, such as \(x\) and \(y\) axis are aligned with the ellipse axes.

  • h (Real, optional) – The ratio of the inner semi-axis to the outer semi-axis. Must be in the range [0, 1). The default is 0.0, which corresponds to a filled ellipse.

  • x_derivative (Optional[Union[Sequence[Integral], numpy.array]], optional) – A sequence (List, Tuple) or 1D numpy array of the order(s) of the x derivative(s) to compute. Must be non-negative integers. If None, is it assumed that x_derivative is 0 for all polynomials.

  • y_derivative (Optional[Union[Sequence[Integral], numpy.array]], optional) – A sequence (List, Tuple) or 1D numpy array of the order(s) of the y derivative(s) to compute. Must be non-negative integers. If None, is it assumed that y_derivative is 0 for all polynomials.

Returns:

The polar coordinates (\(\rho_{eq}, \theta_{eq}\)) and their derivatives with respect to the Cartesian coordinates \((x, y)\) as two lists of numpy arrays with shape (…,) and dtype matching the input arrays. output[0][i] is the derivative with respect to x of order x_derivative[i] and with respect to y of order y_derivative[i] of \(\rho_{eq}\). output[1][i] is the derivative with respect to x of order x_derivative[i] and with respect to y of order y_derivative[i] of \(\theta_{eq}\).

Return type:

Tuple[List[numpy.ndarray], List[numpy.ndarray]]

Examples

Lets compute Zernike polynomial \(Z_2^0\) on an extended circle of radius 2 centered at (1,1).

First, we convert a grid of Cartesian coordinates to elliptic annulus polar coordinates using pyzernike.cartesian_to_elliptic_annulus():

import numpy
from pyzernike import cartesian_to_elliptic_annulus

# Define the elliptic annulus domain parameters
Rx = 2.0  # Semi-axis along x
Ry = 2.0  # Semi-axis along y
x0 = 1.0  # Center x
y0 = 1.0  # Center y

# Create a grid of Cartesian coordinates
x = np.linspace(-1, 3, 100)
y = np.linspace(-1, 3, 100)
X, Y = np.meshgrid(x, y)

# Convert to elliptic annulus polar coordinates
list_rho_eq, list_theta_eq = cartesian_to_elliptic_annulus(X, Y, Rx, Ry, x0, y0)

# Extract the polar coordinates (0th order derivatives)
rho_eq = list_rho_eq[0]
theta_eq = list_theta_eq[0]

Then the variables rho_eq and theta_eq can be directly used to compute Zernike polynomials on the elliptic annulus domain using pyzernike.zernike_polynomial(). Note that the complete process can be done in one step using pyzernike.xy_zernike_polynomial().

from pyzernike import zernike_polynomial

# Compute the Zernike polynomial Z_2^0 on the elliptic annulus domain
Z20 = zernike_polynomial(rho_eq, theta_eq, n=2, m=0)[0]

If you also want to extract rho_eq and theta_eq and their first derivatives with respect to x and y, you can specify the derivative orders:

# Define the derivative orders
x_derivative = [0, 1, 0]  # 0th and 1st derivative with respect to x
y_derivative = [0, 0, 1]  # 0th and 1st derivative with respect to y

# Convert to elliptic annulus polar coordinates and compute derivatives
list_rho_eq, list_theta_eq = cartesian_to_elliptic_annulus(X, Y, Rx, Ry, x0, y0, x_derivative=x_derivative, y_derivative=y_derivative)

# Extract the polar coordinates and their derivatives
rho_eq = list_rho_eq[0]          # 0th order derivative of rho_eq
drho_eq_dx = list_rho_eq[1]      # 1st order derivative of rho_eq with respect to x
drho_eq_dy = list_rho_eq[2]      # 1st order derivative of rho_eq with respect to y

theta_eq = list_theta_eq[0]      # 0th order derivative of theta_eq
dtheta_eq_dx = list_theta_eq[1]  # 1st order derivative of theta_eq with respect to x
dtheta_eq_dy = list_theta_eq[2]  # 1st order derivative of theta_eq with respect to y

These derivatives can be useful for computing gradients or Jacobians of Zernike polynomials on the elliptic annulus domain, see pyzernike.xy_zernike_polynomial() for more details.