Skip to content

Commit

Permalink
enh: function that calculates the new reference grid
Browse files Browse the repository at this point in the history
  • Loading branch information
oesteban committed Apr 27, 2023
1 parent 0d97d9e commit fc16f55
Showing 1 changed file with 65 additions and 0 deletions.
65 changes: 65 additions & 0 deletions sdcflows/utils/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,71 @@
"""Image processing tools."""


def deoblique_and_zooms(in_reference, oblique, factor=4, padding=1):
"""
Generate a sampling reference aligned with in_reference fully covering oblique.
Parameters
----------
in_reference : :obj:`~nibabel.spatialimages.SpatialImage`
The sampling reference.
oblique : :obj:`~nibabel.spatialimages.SpatialImage`
The rotated coordinate system whose extent should be fully covered by the
generated reference.
factor : :obj:`int`
A factor to increase the resolution of the generated reference.
padding : :obj:`int`
Number of additional voxels around the most extreme positions of the projection of
oblique on to the reference.
"""
from itertools import product
import numpy as np
from nibabel.affines import apply_affine, rescale_affine

# Reference space metadata
hdr = in_reference.header.copy()
affine = in_reference.affine
ref_shape = np.array(in_reference.shape[:3])
ref_zooms = np.array(hdr.get_zooms()[:3])
_, scode = in_reference.get_sform(coded=True)
_, 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))) * (ref_shape - 1),
)
extent_ijk = apply_affine(np.linalg.inv(affine), extent)

if isinstance(padding, int):
padding = tuple([padding] * 3)

underflow = min(extent_ijk.min(0) - padding, 0)
overflow = max(extent_ijk.max(0) + padding + 1 - ref_shape, 0)
if np.any(underflow > 0) or np.any(overflow > 0):
# Add under/overflow voxels
ref_shape += abs(underflow) + overflow
# Consistently update origin
affine[:-1, -1] = apply_affine(affine, underflow)

# Make grid denser
if abs(1.0 - factor) > 1e-5:
new_shape = np.rint(ref_shape * factor)
affine = rescale_affine(affine, ref_shape, ref_zooms / factor, new_shape)
ref_shape = new_shape

# Generate new reference
hdr.set_sform(affine, scode)
hdr.set_qform(affine, qcode)

return in_reference.__class__(
np.zeros(ref_shape.astype(int), dtype=hdr.get_data_dtype()),
affine,
hdr,
)


def resample_to_zooms(in_file, zooms, order=3, prefilter=True):
"""Resample the input data to a new grid with the requested zooms."""
from pathlib import Path
Expand Down

0 comments on commit fc16f55

Please sign in to comment.