Utilities Module#

General utility functions and helpers.

Data Manipulation#

cdiutils.utils.transform_volume(data, transform_matrix, output_shape=None, voxel_size=None, method='direct', preserve_norm=False)[source]#

Apply a linear transform to a 3D volume.

Parameters:
  • data (ndarray) – complex 3D array describing the source volume.

  • transform_matrix (ndarray) – 3x3 matrix mapping source indices to target.

  • output_shape (tuple | None) – target volume shape; uses data.shape when None.

  • voxel_size (tuple | float | None) – target voxel spacing; uses unit voxels when None.

  • method (str) – transformation mode; "direct" or "fourier".

  • preserve_norm (bool) – if True, rescales result by |det(A)|**(-1/2) to approximately preserve the L2 norm for the underlying continuous field. For pure rotations (orthogonal A) this factor is 1; for general shears or scales it compensates the change of volume element.

Returns:

interpolated volume on the target grid.

Return type:

np.ndarray

cdiutils.utils.get_reciprocal_voxel_size(real_voxel_size, shape, convention=None)[source]#

Calculate reciprocal-space voxel size from real-space parameters.

Uses the generic relation

dq = factor / (N * dx)

for each axis, where N is the number of pixels and dx the corresponding real-space voxel size.

This implementation is dimension-agnostic and does not assume any particular axis ordering. real_voxel_size and shape are only required to have the same length. This makes it compatible with both CXI- and xrayutilities-style conventions as long as the ordering of real_voxel_size matches that of shape.

Parameters:
  • real_voxel_size (float | tuple | ndarray) – Real-space voxel size (scalar or sequence). If scalar, the same value is used for all axes; otherwise it must have the same length as shape.

  • shape (tuple | list | ndarray) – Array shape, e.g. (nz, ny, nx). Any dimensionality is accepted.

  • convention (str | None) – Optional convention for calculation. Currently only controls an overall 2pi factor when set to "xu" or "crystallography" or None. For other values factor=1. Defaults to None.

Returns:

Tuple of reciprocal voxel sizes (dq0, dq1, …, dq_{ndim-1}) in inverse units, with the same ordering as shape.

Return type:

tuple

cdiutils.utils.bin_along_axis(data, binning_factor, binning_method='sum', axis=0)[source]#

Bin n-dimensional data along a specified axis using the specified method (mean, sum, median, max).

Parameters:
  • data (np.ndarray | list) – n-dimensional data to be binned.

  • binning_factor (int) – the number of elements per bin.

  • binning_method (str, optional) – the binning method, either “mean”, “sum”, “median”, or “max”. Defaults to “sum”.

  • axis (int, optional) – the axis along which to perform binning. Defaults to 0.

Raises:

ValueError – if the binning_method is unknown.

Returns:

binned data.

Return type:

np.ndarray

cdiutils.utils.get_prime_factors(n)[source]#

Return the prime factors of the given integer.

cdiutils.utils.is_valid_shape(n, maxprime=13, required_dividers=(2,))[source]#

Check if n meets Pynx shape constraints.

cdiutils.utils.adjust_to_valid_shape(n, maxprime=13, required_dividers=(2,), decrease=True)[source]#

Find the nearest valid shape value.

cdiutils.utils.ensure_pynx_shape(shape, maxprime=13, required_dividers=(2,), decrease=True, verbose=False)[source]#

Ensure shape dimensions comply with Pynx constraints. This function has been adapted from the PyNX library. See: pynx.utils.math.smaller_primes.

Parameters:
  • shape (int | tuple | list | np.ndarray) – the shape to adjust.

  • maxprime (int, optional) – the maximum prime factor allowed. Defaults to 13.

  • required_dividers (tuple, optional) – the required dividers. Defaults to (4,).

  • decrease (bool, optional) – whether to decrease the shape. Defaults to True.

  • verbose (bool, optional) – whether to print messages.

Raises:

TypeError – if the shape is not an int, list, tuple, or numpy array.

Returns:

the adjusted shape.

Return type:

tuple | np.ndarray | list

cdiutils.utils.energy_to_wavelength(energy)[source]#

Find the wavelength in metre (not angstrom!) that energy (in eV) corresponds to.

Parameters:

energy (float) – the energy to convert.

Returns:

the wavelength in metre.

Return type:

float

cdiutils.utils.wavelength_to_energy(wavelength)[source]#

Find the energy in eV that wavelength in metre (not angstrom!) corresponds to.

Parameters:

wavelength (float) – the wavelength in metre to convert.

Returns:

the energy in eV.

Return type:

float

cdiutils.utils.fill_up_support(support)[source]#

Fill up the support using the convex hull of the support.

Parameters:

support (np.ndarray) – The binary support array to fill up.

Returns:

The filled support array.

Return type:

np.ndarray

cdiutils.utils.size_up_support(support)[source]#
cdiutils.utils.find_hull(volume, threshold=18, kernel_size=3, boolean_values=False, nan_value=False)[source]#

Find the convex hull of a 2D or 3D object.

Parameters:
  • volume (ndarray) – 2 or 3D np.ndarray. The volume to get the hull from.

  • threshold (float) – threshold that selects what belongs to the hull or not (int). If threshold >= 27, the returned hull will be similar to volume.

  • kernel_size (int) – the size of the kernel used to convolute (int).

  • boolean_values (bool) – whether or not to return 1 and 0 np.ndarray or the computed coordination.

Returns:

the convex hull of the shape accordingly to the given threshold (np.array).

Return type:

ndarray

cdiutils.utils.make_support(data, isosurface=0.5, nan_values=False)[source]#

Create a support using the provided isosurface value.

cdiutils.utils.unit_vector(vector)[source]#

Return a unit vector.

cdiutils.utils.angle(v1, v2)[source]#

Compute angle between two vectors.

cdiutils.utils.v1_to_v2_rotation_matrix(v1, v2)[source]#

Rotation matrix around axis v1xv2

cdiutils.utils.normalise(data, zero_centered=False)[source]#

Normalise a np.ndarray so the values are between 0 and 1.

cdiutils.utils.normalise_complex_array(array)[source]#

Normalise a array of complex numbers.

cdiutils.utils.find_max_pos(data)[source]#

Find the index coordinates of the maximum value.

cdiutils.utils.shape_for_safe_centred_cropping(data_shape, position, final_shape=None)[source]#

Utility function that finds the smallest shape that allows a safe cropping, i.e. without moving data from one side to another when using the np.roll() function.

cdiutils.utils.center(data, where='com', return_former_center=False)[source]#

Center 3D volume data such that the center of mass or max of data is at the very center of the 3D matrix. :param data: volume data (np.array). 3D numpy array which will be centered. :param com: center of mass coordinates(list, np.array). If no com is provided, com of the given data is computed (default: None). :param where: what region to place at the center (str), either com or max, or a tuple of the coordinates where to place the center at. :returns: centered 3D numpy array.

cdiutils.utils.symmetric_pad(data, output_shape, values=0)[source]#

Return padded data so it matches the provided final_shape

cdiutils.utils.crop_at_center(data, final_shape)[source]#

Crop 3D array data to match the final_shape. Center of the input data remains the center of cropped data. :param data: 3D array data to be cropped (np.array). :param final_shape: the targetted shape (list). If None, nothing happens. :returns: cropped 3D array (np.array).

cdiutils.utils.compute_distance_from_com(data, com=None)[source]#

Return a np.ndarray of the same shape of the provided data. (i, j, k) Value will correspond to the distance of the (i, j, k) voxel in data to the center of mass if that voxel is not null.

cdiutils.utils.num_to_nan(data, num=0)[source]#

Replace all occurrences of ‘num’ in the array with np.nan.

Parameters:
  • data (np.ndarray) – NumPy array.

  • num (int | float, optional) – The number to replace with np.nan Defaults to 0.

Returns:

A new NumPy array with ‘num’ replaced by np.nan.

cdiutils.utils.zero_to_nan(data, boolean_values=False)[source]#

Convert zero values to np.nan.

cdiutils.utils.nan_to_zero(data, boolean_values=False)[source]#

Convert np.nan values to 0.

cdiutils.utils.to_bool(data, nan_value=False)[source]#

Convert values to 1 (True) if not nan otherwise to 0 (False)

cdiutils.utils.nan_center_of_mass(data, return_int=False)[source]#

Compute the center of mass of a np.ndarray that may contain nan values.

cdiutils.utils.hybrid_gradient(data, *d)[source]#

Compute the gradient of a n-dim volume in each axis direction, 2nd order in the interior of the non-nan object, 1st order at the interface between the non-nan object and the surrounding nan values.

Parameters:
  • data (np.ndarray) – the n-dim volume i to be derived

  • d (list) – the spacing in each direction

Returns:

the gradients (in each direction) with the same shape as the input data

Return type:

list[np.ndarray] | np.ndarray

class cdiutils.utils.CroppingHandler[source]#

Bases: object

A class to handle data cropping. The class allows finding the requested position of the center and crop the data accordingly.

static get_position(data, method)[source]#

Get the position of the reference voxel based on the centering method.

Parameters:
  • data (ndarray) – Input data array.

  • method (str | tuple[int]) – Centering method. Can be “max” for maximum intensity, “com” for center of mass, or a tuple of coordinates representing the voxel position.

Returns:

The position of the reference voxel as a tuple of coordinates.

Return type:

tuple[int]

Raises: ValueError: If an invalid method is provided.

classmethod get_masked_data(data, roi)[source]#

Get the masked data array based on the region of interest (ROI).

Parameters:
  • data (ndarray) – Input data array.

  • roi (list[int]) – Region of interest as a list of representing the cropped region ex: [start, end, start, end].

Returns:

The masked data array with the specified ROI.

Return type:

MaskedArray

static roi_list_to_slices(roi)[source]#

Convert a ROI to a tuple of slices.

Parameters:

roi (list[int]) – Region of interest as a list of start and end values for each dimension.

Returns:

The ROI converted to a tuple of slices.

Return type:

tuple[slice, …]

classmethod get_roi(output_shape, where, input_shape=None)[source]#

Calculate the region of interest (ROI) for cropping the data based on the input shape, desired output shape, and reference voxel position.

Parameters:
  • output_shape (tuple) – Desired output shape after cropping.

  • where (tuple) – Reference voxel position as a tuple of coordinates.

  • input_shape (tuple) – Shape of the input data array.

Returns:

The region of interest as a list of start and end values for each dimension.

Return type:

list[int]

classmethod chain_centring(data, output_shape, methods, verbose=False)[source]#

Apply sequential centring methods to the input data and return the cropped and centred data along with the position of the reference voxel in the newly cropped data frame.

Parameters:
  • data (ndarray) – Input data array.

  • output_shape (tuple[int, ...]) – Desired output shape after cropping.

  • methods (list[str | tuple[int, ...]]) – list of sequential centring methods. Each method can be “max” for maximum intensity, “com” for center of mass, or a tuple of coordinates representing the voxel position.

  • verbose (bool) – (bool, optional) whether to print out messages.

Returns:

A tuple containing the cropped and centered data array, the position of the reference voxel in the original data frame, and the position of the reference voxel in the newly cropped data frame and the roi.

Raises:

ValueError – If an invalid method is provided.

Return type:

tuple[ndarray, tuple[int, …]]

classmethod force_centred_cropping(data, where='centre', output_shape=None, verbose=False)[source]#

Crop the data so the given reference position (where) is at the center of the final data frame no matter the output_shape. Therefore the real output shape might be different to output_shape.

cdiutils.utils.compute_corrected_angles(inplane_angle, outofplane_angle, detector_coordinates, detector_distance, direct_beam_position, pixel_size=5.5e-05, verbose=False)[source]#

Compute the detector corrected angles given the angles saved in the experiment data file and the position of interest in the detector frame

Parameters:
  • inplane_angle (float) – in-plane detector angle in degrees (float).

  • outofplane_angle (float) – out-of-plane detector angle in degrees (float).

  • detector_coordinates (tuple) – the detector coordinates of the point of interest (tuple or list).

  • detector_distance (float) – the sample to detector distance

  • direct_beam_position (tuple) – the direct beam position in the detector frame (tuple or list).

  • pixel_size (float) – the pixel size (float).

  • verbose – whether or not to print the corrections (bool).

Returns:

the two corrected angles.

Return type:

tuple[float, float]

cdiutils.utils.find_suitable_array_shape(support, pad=None, symmetrical=True)[source]#

Find a smaller array shape of 2 or 3D array containing a support.

cdiutils.utils.extract_reduced_shape(support, pad=None, symmetric=False)[source]#
cdiutils.utils.get_oversampling_ratios(support=None, direct_space_object=None, isosurface=0.3, plot=False)[source]#

Compute the oversampling ratio of a reconstruction. Function proposed by Ewen Bellec (ewen.bellec@esrf.fr)

Parameters:
  • support (np.ndarray, optional) – the support of the

  • None. (object. Defaults to)

  • direct_space_object (np.ndarray, optional) – the reconstructed

  • None.

  • isosurface (float, optional) – the isosurface to determine the

  • .3. (support. Defaults to)

  • plot (bool, optional) – whether to plot or not. Defaults to False.

Raises:
  • ValueError – If support is not provided, requires

  • direct_space_object and isosurface (default to 0.3) value.

Returns:

the oversampling ratio.

Return type:

np.ndarray

cdiutils.utils.oversampling_from_diffraction(data, support_threshold=0.1)[source]#

Compute the oversampling ratios from diffraction data. Autocorrelation of the intensity is calculated to generate a support using support_threshold (isosurface).

Parameters:
  • data (np.ndarray) – intensity (diffracted data)

  • support_threshold (0.1) – the threshold to build the support from a la pynx, default to 0.1.

Returns:

the oversampling ratio and a

suggestion for the rebin factors

Return type:

tuple[np.ndarray, np.ndarray]

cdiutils.utils.get_centred_slices(shape, shift=None)[source]#

Compute the slices that allows to select the centre of each axis. It returns a list of len(shape) tuples made of len(shape) slices. The shift allows to shift the centred the slices by the amount provided.

Ex:

  • if shape = (25, 48), will return:

    [(12, slice(None, None, None)), (slice(None, None, None), 24)]
    
  • if shape = (25, 48, 50), will return:

    [(12, slice(None, None, None), slice(None, None, None)),
     (slice(None, None, None), 24, slice(None, None, None)),
     (slice(None, None, None), slice(None, None, None), 25)]
    
Parameters:
  • shape (tuple | list | np.ndarray) – the shape of the np.ndarray of which you want to select the centre.

  • shift (tuple | list) – a shift in the slice selection with respect to the centre.

Returns:

the list of tuples made of slices.

Return type:

list

cdiutils.utils.hot_pixel_filter(data, threshold=100.0, kernel_size=3)[source]#

Remove hot pixels using a median filter.

Parameters:
  • data (np.ndarray) – the input data.

  • threshold (float, optional) – the threshold to determine the mask. Mask pixels that are threshold times higher than neighbouring pixels. Defaults to 1e2.

  • kernel_size (int, optional) – the size of the kernel to compute the median filter. It corresponds to the size parameter of scipy.ndimage.median_filter function. Defaults to 3.

Returns:

the cleaned data, hot pixel are

set to 0 and the mask (1 for hot pixel, 0 otherwise).

Return type:

tuple[np.ndarray, np.ndarray]

cdiutils.utils.valid_args_only(params, function)[source]#