13.6. openwfs.utilities

class Transform(transform=None, source_origin=None, destination_origin=None)[source]

Bases: object

Represents a transformation from one 2-d coordinate system to another.

Transform objects are used to specify any combination of shift, (anisotropic) scaling, rotation and shear. The transform matrix, as well as the source and destination origins, can be specified with astropy units attached.

Note that a Transform object does not contain any information about the extent and pixel size of the source or destination image, it only specifies the coordinate transformation itself. When a Transform object is used to transform image data (see project() and place()), the pixel_size information should be specified separately.

apply(vector)[source]

Applies the transformation to a column vector.

If vector is a 2-D array, applies the transformation to each column of vector individually.

compose(other)[source]

Compose two transformations.

Parameters:

other (Transform) – the transformation to apply first

Returns:

Transform – the composition of the two transformations

cv2_matrix(source_shape, source_pixel_size, destination_shape, destination_pixel_size)[source]

Returns the transformation matrix in the format used by cv2.warpAffine.

This matrix is 2x3, with the last column corresponding to the translation vector.

Note: OpenCV uses the (x,y) convention, so the matrix is transposed compared to the numpy matrix. Note: OpenCV uses the _center_ of the top-left corner as the origin, whereas OpenWFS uses the centerso the origin is corrected.

of the image as the origin. The difference of half the image size minus half the pixel size is corrected in the transformation matrix.

destination_unit(src_unit)[source]

Computes the unit of the output of the transformation, given the unit of the input.

Raises:

ValueError – If src_unit does not match the unit of the source_origin (if specified) or if dst_unit does not match the unit of the destination_origin (if specified).

classmethod identity()[source]
inverse()[source]

Compute the inverse transformation, such that the composition of the transformation and its inverse is the identity.

opencl_matrix()[source]

Returns the transformation matrix (including translation) in the format used by OpenCL.

The returned matrix is a 3x4 matrix that includes the transformation matrix and the translation vector. The last two columns are for padding only.

to_matrix(source_pixel_size, destination_pixel_size)[source]

Returns a homogeneous transformation matrix that transforms (y,x,1) coordinates to (y’, x’, 1).

static zoom(scale)[source]

Returns a transform that just zooms in the image.

coordinate_range(shape, extent, offset=None)[source]

Returns coordinate vectors for the two coordinates (y and x).

Given a range from -extent/2 to +extent/2, uniformly divided into shape pixels, the returned coordinates correspond to the centers of these coordinates.

Parameters:
  • shape (ShapeType) – size of the full grid (y, x) in pixels

  • extent (ExtentType) – extent of the coordinate range

  • offset (Optional[CoordinateType]) – offset to be added to the coordinates (optional)

Returns:

Tuple[Quantity, Quantity] – coordinate vectors for the two coordinates (y and x)

disk(shape, radius=1, extent=(2.0, 2.0), offset=None)[source]

Constructs an image of a centered (ellipsoid) disk.

(x / rx)^2 + (y / ry)^2 <= 1.0

Parameters:
  • shape (Union[int, Sequence[int]]) – number of pixels of the returned pattern.

  • extent (Union[float, Sequence[float], ndarray, Quantity]) – extent of the return pattern. This value is used to compute the coordinates of each pixel of the image. Scaling both the extent and radius by the same factor does not change the returned pattern, but changing their ratio does.

  • radius (ScalarType) – radius of the disk, should have the same unit as extent.

  • offset (Union[Sequence[float], ndarray, Quantity, None]) – offsets the centre of the disk by offset

Returns:

An array of the same shape as the input shape, containing the values of the disk pattern. The values are 1 inside the disk and 0 outside the disk.

gaussian(shape, waist, extent=(2.0, 2.0), truncation_radius=None, offset=None)[source]

Constructs an image of a centered Gaussian

waist, extent and the optional truncation_radius should all have the same unit.

Parameters:
  • shape (Union[int, Sequence[int]]) – Number of pixels of the returned pattern.

  • extent (Union[float, Sequence[float], ndarray, Quantity]) – Extent of the return pattern. This value is used to compute the coordinates for the Gaussian profile. Changing the ratio of extent and waist changes the returned pattern, but scaling both by the same factor does not change the returned pattern.

  • waist (Union[float, ndarray, Quantity]) – location of the beam waist (1/e value) relative to half of the size of the pattern (i.e. relative to the radius of the square)

  • truncation_radius (Union[float, ndarray, Quantity]) – when not None, specifies the radius of a disk that is used to truncate the Gaussian. All values outside the disk are set to 0.

  • offset (Union[Sequence[float], ndarray, Quantity, None]) – offsets the centre of the Gaussian. The centre of the disk is also offsetted by this amount.

get_extent(data)[source]

Extracts the extent from the data array. The extent is always equal to shape * pixel_size.

get_pixel_size(data)[source]

Extracts the pixel size metadata from the data array.

Parameters:

data (np.ndarray) – The input data array or Quantity.

Returns:

OptionalQuantity] – The pixel size metadata, or None if no pixel size metadata is present.

Usage: >>> import astropy.units as u >>> import numpy as np >>> data = set_pixel_size(((1, 2), (3, 4)), 5 * u.um) >>> pixel_size = get_pixel_size(data)

TODO: return 1 if no pixel size is present

place(out_shape, out_pixel_size, source, offset=None, out=None)[source]

Takes a source array and places it in an otherwise empty array of specified shape and pixel size.

The source array must have a pixel_size property (see set_pixel_size). It is scaled (using area interpolation) so that the pixel size matches that of the output. Then, the source array is placed into the output array at the position given by offset, where offset=None or offset=(0.0, 0.0) * pixel_size corresponds to centering the source image with respect to the output array. Parts of the source array that extend beyond the output are cropped, and parts of the array that are not covered by the source array are zero padded.

Note: this function currently works for 2-D inputs only

Args:

project(source, *, source_extent=None, transform=None, out=None, out_extent=None, out_shape=None, interp=cv2.INTER_NEAREST)[source]

Projects the input image onto an array with specified shape and resolution.

The input image is scaled so that the pixel sizes match those of the output, and cropped/zero-padded so that the data shape matches that of the output. Optionally, an additional Transform can be specified, e.g., to scale or translate the source image.

Parameters:
  • source (ndarray) – input image.

  • source_extent (Union[float, Sequence[float], ndarray, Quantity, None]) – extent of the source image in some physical unit. If not given (None), the extent metadata of the input image is used. see get_extent().

  • transform (Optional[Transform]) – optional transformed (rotate, translate, etc.) to appy to the source image before placing it in the output

  • out (Optional[ndarray]) – optional array where the output image is stored in.

  • out_extent (Union[float, Sequence[float], ndarray, Quantity, None]) – extent of the output image in some physical unit. If not given, the extent metadata of the out image is used.

  • out_shape (Optional[tuple[int, ...]]) – shape of the output image. This value is ignored if out is specified.

  • interp – interpolation method to use when rescaling the image. See OpenCV documentation for options.

Returns:

np.ndarray – the projected image (out if specified, otherwise a new array)

set_extent(data, extent)[source]

Sets the extent metadata for the given data array.

Parameters:
  • data (ArrayLike) – The input data array.

  • extent (ArrayLike) – The extent to be set. When a single-element extent is given, it is broadcasted to all dimensions of the data array. Passing None sets the extent metadata to None.

Returns:

np.ndarray – The modified data array with the extent metadata.

Usage: >>> data = np.array([[1, 2], [3, 4]]) >>> extent = 0.1 * u.m >>> modified_data = set_extent(data, extent)

set_pixel_size(data, pixel_size)[source]

Sets the pixel size metadata for the given data array.

Parameters:
  • data (ArrayLike) – The input data array.

  • pixel_size (Optional[Quantity]) – The pixel size to be set. When a single-element pixel size is given, it is broadcasted to all dimensions of the data array. Passing None sets the pixel size metadata to None.

Returns:

np.ndarray – The modified data array with the pixel size metadata.

Usage: >>> data = np.array([[1, 2], [3, 4]]) >>> pixel_size = 0.1 * u.m >>> modified_data = set_pixel_size(data, pixel_size)

tilt(shape, g, extent=(2.0, 2.0), phase_offset=0.0, offset=None)[source]

Constructs a linear gradient pattern φ=2g·r

Note, these are the Zernike tilt modes (modes 2 and 3 in the Noll index convention) with normalization so that \(\frac{\int_0^{2\pi} \int_0^1 |Z(\rho, \phi)|^2 \rho d\rho d\phi}{\int_0^{2\pi} \int_0^1 \rho d\rho d\phi} = 1\).

Parameters:
  • shape (Union[int, Sequence[int]]) – Number of pixels of the returned pattern.

  • extent (Union[float, Sequence[float], ndarray, Quantity]) – extent of the return pattern defined in normalised pupil coordinates, i.e. an extent of (2, 2) covers the entire back pupil plane of a microscope objective.

  • g (tuple of two floats) – gradient vector. For an extent of (2,2), the shift in the focal plane is given by (gx, gy) * -1 / π * wavelength / numerical_aperture_aperture. Where ‘numerical_aperture’ is the numerical aperture of the microscope objective, and ‘wavelength’ is the wavelength of the light. (Note: a positive x-gradient g causes the focal point to move in the _negative_ x-direction)

  • phase_offset (float) – optional additional phase offset to be added to the pattern

unitless(data)[source]

Converts an object to a numpy array. Especially useful to remove the scaling from a unitless Quantity.

Parameters:
  • data (Union[_Buffer, _SupportsArray[dtype[Any]], _NestedSequence[_SupportsArray[dtype[Any]]], complex, bytes, str, _NestedSequence[complex | bytes | str]]) – The input data.

  • Quantity (If data is a)

  • a (it is converted to)

  • is. (All other data types are just returned as)

Returns:

ArrayLike – unitless numpy array, or the input data if it is not a Quantity.

Raises:

UnitConversionError – If the data is a Quantity with a unit

Note

Do NOT use np.array(data) to convert a Quantity to a numpy array, because this will drop the unit prefix. For example, np.array(1 * u.s / u.ms) == 1. Whereas unitless(1 * u.s / u.ms) == 1000 gives the correct answer.

Usage: >>> data = np.array([1.0, 2.0, 3.0]) * u.m >>> unitless_data = unitless(data / u.mm)