Backends#

Backends allows users to effortlessly switch between different array and FFT implementations and to define custom ones. Backends enable the same code to be run on CPU or GPU, and to quickly integrate novel solutions and benefit from their performance gains. Having backends makes pytme flexible and highly adaptive to available compute infrastructure.

Note

Currently flexible backends are only implemented for exhaustive template matching operations. Keep an eye on the documentation or announcements regarding extension to other parts of pytme.

Backend Manager#

Modules that support flexible backends import a global instance of BackendManager like so: from tme.backends import backend. The import is quasi-equivalent to import numpy as np, with the exception being the naming difference. Notably, backend agnostic code is written without instance specific methods such as the ones defined by np.ndarray. Instance-specific functions are wrapped instead, e.g. NumpyFFTWBackend.fill(). For additional information please refer to the class documentation below.

BackendManager()

Manager for template matching backends.

Abstract Base Backend#

MatchingBackend serves as specification for new backends. Generally the aim is to create a structure that is syntactically similar to numpy.

MatchingBackend(array_backend, float_dtype, ...)

A strategy class for template matching backends.

Schematically, each backend requires an array implementation, such as the ones provided by numpy, pytorch or mars. This backend should provide array data structures and define operations on it. Since the syntax of many backends is already similar to numpy, wrapping them is fairly straightfoward. In addition to array operations, each backend is requried to define a range of template matching specific operations.

With array and template matching specific operations defined, practically any backend can be used to perform template matching with pytme. Below is an overview of methods that are required from each backend.

Array operations#

MatchingBackend.add(arr1, arr2[, out])

Element-wise addition of arrays.

MatchingBackend.subtract(arr1, arr2[, out])

Element-wise subtraction of arrays.

MatchingBackend.multiply(arr1, arr2[, out])

Element-wise multiplication of arrays.

MatchingBackend.divide(arr1, arr2[, out])

Element-wise division of arrays.

MatchingBackend.mod(arr1, arr2[, out])

Element-wise modulus of arrays.

MatchingBackend.sum(arr[, axis])

Compute the sum of array elements.

MatchingBackend.einsum(arr1, arr2[, out])

Compute the einstein notation based summation.

MatchingBackend.mean(arr[, axis])

Compute the mean of array elements.

MatchingBackend.std(arr[, axis])

Compute the standad deviation of array elements.

MatchingBackend.max(arr[, axis])

Compute the maximum of array elements.

MatchingBackend.min(arr[, axis])

Compute the minimum of array elements.

MatchingBackend.maximum(arr1, arr2[, out])

Compute the element wise maximum of arr1 and arr2.

MatchingBackend.minimum(arr1, arr2[, out])

Compute the element wise minimum of arr1 and arr2.

MatchingBackend.sqrt(arr[, out])

Compute the square root of array elements.

MatchingBackend.square(arr[, out])

Compute the square of array elements.

MatchingBackend.abs(arr[, out])

Compute the absolute of array elements.

MatchingBackend.transpose(arr)

Compute the transpose of arr.

MatchingBackend.tobytes(arr)

Compute the bytestring representation of arr.

MatchingBackend.size(arr)

Compute the number of elements of arr.

MatchingBackend.fill(arr, value)

Fills arr in-place with a given value.

MatchingBackend.clip(arr, a_min, a_max[, out])

Clip elements of arr.

MatchingBackend.roll(*args, **kwargs)

Roll array elements along a specified axis.

MatchingBackend.stack(*args, **kwargs)

Join a sequence of objects along a new axis.

MatchingBackend.indices(*args, **kwargs)

Creates an array representing the index grid of an input.

MatchingBackend.power([arr, power, out])

Compute the n-th power of an array.

MatchingBackend.astype(dtype)

Change the datatype of arr.

MatchingBackend.concatenate(*args, **kwargs)

Join a sequence of objects along an existing axis.

MatchingBackend.repeat(*args, **kwargs)

Repeat each array element a specified number of times.

MatchingBackend.unique(arr[, return_index, ...])

Find the unique elements of an array.

MatchingBackend.topk_indices(arr, k)

Determinces the indices of largest elements.

MatchingBackend.argsort(*args, **kwargs)

Compute the indices to sort a given input array.

MatchingBackend.unravel_index(indices, shape)

Convert flat index to array indices.

MatchingBackend.tril_indices(*args, **kwargs)

Compute indices of upper triangular matrix

Array initialization#

MatchingBackend.full(shape, dtype, fill_value)

Returns an array filled with fill_value of specified shape and dtype.

MatchingBackend.zeros(shape, dtype)

Returns an aligned array of zeros with specified shape and dtype.

MatchingBackend.arange(stop[, start, step])

Arange values in evenly spaced interval.

Template matching#

MatchingBackend.build_fft(fast_shape, ...)

Build forward and inverse real fourier transform functions.

MatchingBackend.topleft_pad(arr, shape[, padval])

Returns an array that has been padded to a specified shape with a padding value at the top-left corner.

MatchingBackend.to_sharedarr(arr[, ...])

Converts an array to an object shared in memory.

MatchingBackend.from_sharedarr(shape, dtype, shm)

Returns an array of given shape and dtype from shared memory location.

MatchingBackend.extract_center(arr, newshape)

Extract the centered portion of an array based on a new shape.

MatchingBackend.rigid_transform(arr, ...[, ...])

Performs a rigid transformation.

MatchingBackend.max_filter_coordinates(...)

Identifies local maxima in score_space separated by min_distance.

MatchingBackend.compute_convolution_shapes(...)

Computes regular, optimized and fourier convolution shape.

Conversion#

MatchingBackend.to_cpu_array(arr)

Convert an array of a given backend to a CPU array of that backend.

MatchingBackend.to_numpy_array(arr)

Convert an array of given backend to a numpy array.

MatchingBackend.to_backend_array(arr)

Convert a numpy array instance to backend array type.

Auxiliary#

MatchingBackend.eps(dtype)

Returns the minimal difference representable by dtype.

MatchingBackend.free_cache()

Free cached objects allocated by backend.

MatchingBackend.datatype_bytes(dtype)

Return the number of bytes occupied by a given datatype.

MatchingBackend.get_available_memory()

Returns the available memory available for computations in bytes.

Note

Notably, autoray provides a framework that allows for writing backend agnostic python code, similar to the approach taken here. In the future, tme.backends might be deprecated in favor of autoray.

Supported Backends#

NumpyFFTWBackend([array_backend, ...])

A numpy and pyfftw-based matching backend.

PytorchBackend([device, float_dtype, ...])

A pytorch-based matching backend.

CupyBackend([float_dtype, complex_dtype, ...])

A cupy-based matching backend.

MLXBackend([device, float_dtype, ...])

A mlx-based matching backend.

JaxBackend([float_dtype, complex_dtype, ...])

A jax-based matching backend.