Source code for nondefaced_detector.preprocessing.conform

"""Conforming input data."""

from pathlib import Path
from tempfile import mkdtemp
from scipy.ndimage import map_coordinates

import numpy as np
import nibabel as nb


[docs]def conform_data( in_file, out_file=None, out_size=(256, 256, 256), out_zooms=(1.0, 1.0, 1.0), order=3 ): """Conform the input dataset to the canonical orientation. Parameters ---------- in_file: str - Path Path to the input MRI volume to conform. out_file: str - Path, default=None Path to save the conformed volume. By default the volume is saved as /tmp/conformed.nii.gz out_size: tuple of size 3, optional, default=(256, 256, 256) The shape to conform the 3D volume to. out_zooms: tuple of size 3, optional, default=(1.0, 1.0, 1.0) Factors to normalize voxel size to. order: int, optional, default=3 Order of the spline interpolation. The order has to be in the range 0-5. Returns ------- str - Path The path to where the conformed volume is saved. """ if isinstance(in_file, (str, Path)): in_file = nb.load(in_file) # Drop axes with just 1 sample (typically, a 3D file stored as 4D) in_file = nb.squeeze_image(in_file) dtype = in_file.header.get_data_dtype() # Reorient to closest canonical in_file = nb.as_closest_canonical(in_file) data = np.asanyarray(in_file.dataobj) # Calculate the factors to normalize voxel size to out_zooms normed = np.array(out_zooms) / np.array(in_file.header.get_zooms()[:3]) # Calculate the new indexes, sampling at 1mm^3 with out_size sizes. # center_ijk = 0.5 * (np.array(in_file.shape) - 1) new_ijk = normed[:, np.newaxis] * np.array( np.meshgrid( np.arange(out_size[0]), np.arange(out_size[1]), np.arange(out_size[2]), indexing="ij", ) ).reshape((3, -1)) offset = 0.5 * (np.max(new_ijk, axis=1) - np.array(in_file.shape)) # Align the centers of the two sampling extents new_ijk -= offset[:, np.newaxis] # Resample data in the new grid resampled = map_coordinates( data, new_ijk, output=dtype, order=order, mode="constant", cval=0, prefilter=True, ).reshape(out_size) resampled[resampled < 0] = 0 # Create a new x-form affine, aligned with cardinal axes, 1mm3 and centered. newaffine = np.eye(4) newaffine[:3, 3] = -0.5 * (np.array(out_size) - 1) nii = nb.Nifti1Image(resampled, newaffine, None) if out_file is None: out_file = Path(mkdtemp()) / "conformed.nii.gz" out_file = Path(out_file).absolute() nii.to_filename(out_file) return out_file