From f01cee13425aba2542fee85011453c039477650d Mon Sep 17 00:00:00 2001 From: Oscar Esteban Date: Tue, 2 May 2023 09:28:57 +0200 Subject: [PATCH] Apply suggestions from code review Co-authored-by: Mathias Goncalves Co-authored-by: Chris Markiewicz --- sdcflows/utils/tools.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/sdcflows/utils/tools.py b/sdcflows/utils/tools.py index 1e4c95fd49..99200504e0 100644 --- a/sdcflows/utils/tools.py +++ b/sdcflows/utils/tools.py @@ -21,9 +21,16 @@ # https://www.nipreps.org/community/licensing/ # """Image processing tools.""" +import nibabel as nb -def deoblique_and_zooms(in_reference, oblique, factor=4, padding=1): +def deoblique_and_zooms( + in_reference: nb.spatialimages.SpatialImage, + oblique: nb.spatialimages.SpatialImage, + factor: int = 4, + padding: int = 1, + factor_tol: float = 1e-4, +): """ Generate a sampling reference aligned with in_reference fully covering oblique. @@ -39,6 +46,8 @@ def deoblique_and_zooms(in_reference, oblique, factor=4, padding=1): padding : :obj:`int` Number of additional voxels around the most extreme positions of the projection of oblique on to the reference. + factor_tol : :obj:`float` + Absolute tolerance to determine whether factor is one. """ from itertools import product @@ -54,11 +63,10 @@ def deoblique_and_zooms(in_reference, oblique, factor=4, padding=1): _, qcode = in_reference.get_qform(coded=True) # Calculate the 8 most extreme coordinates of oblique in in_reference space - extent = apply_affine( - oblique.affine, - np.array(list(product((0, 1), repeat=3))) * (np.array(oblique.shape[:3]) - 1), + corners = np.array(list(product((0, 1), repeat=3))) * ( + np.array(oblique.shape[:3]) - 1 ) - extent_ijk = apply_affine(np.linalg.inv(affine), extent) + extent_ijk = apply_affine(np.linalg.inv(affine) @ oblique.affine, corners) underflow = np.clip(extent_ijk.min(0) - padding, None, 0).astype(int) overflow = np.ceil( @@ -66,12 +74,12 @@ def deoblique_and_zooms(in_reference, oblique, factor=4, padding=1): ).astype(int) if np.any(underflow < 0) or np.any(overflow > 0): # Add under/overflow voxels - ref_shape += np.abs(underflow) + overflow + ref_shape += overflow - underflow # Consistently update origin affine[:-1, -1] = apply_affine(affine, underflow) # Make grid denser - if abs(1.0 - factor) > 1e-4: + if abs(1.0 - factor) > factor_tol: new_shape = np.rint(ref_shape * factor) affine = rescale_affine(affine, ref_shape, ref_zooms / factor, new_shape) ref_shape = new_shape @@ -81,7 +89,7 @@ def deoblique_and_zooms(in_reference, oblique, factor=4, padding=1): hdr.set_qform(affine, qcode) return in_reference.__class__( - np.zeros(ref_shape.astype(int), dtype=hdr.get_data_dtype()), + nb.fileslice.strided_scalar(ref_shape.astype(int)), affine, hdr, )