diff --git a/darwin/importer/formats/nifti.py b/darwin/importer/formats/nifti.py index a86a70d89..3d6a32d17 100644 --- a/darwin/importer/formats/nifti.py +++ b/darwin/importer/formats/nifti.py @@ -103,7 +103,7 @@ def _parse_nifti( is_mpr: bool, legacy: bool = False, ) -> dt.AnnotationFile: - img, pixdims = process_nifti(nib.load(nifti_path), legacy=legacy) + img, pixdims = process_nifti(nib.load(nifti_path)) processed_class_map = process_class_map(class_map) video_annotations = [] @@ -513,11 +513,10 @@ def correct_nifti_header_if_necessary(img_nii): def process_nifti( input_data: nib.nifti1.Nifti1Image, ornt: Optional[List[List[float]]] = [[0.0, -1.0], [1.0, -1.0], [2.0, -1.0]], - legacy: bool = False, ) -> Tuple[np.ndarray, Tuple[float]]: """ - Function that converts a nifti object to RAS orientation (if legacy), then converts to the passed ornt orientation. - The default ornt is for LPI. + Function that converts a nifti object to the RAS orientation, then converts to the passed ornt orientation. + The default ornt is LPI. Args: input_data: nibabel nifti object. @@ -530,8 +529,7 @@ def process_nifti( pixdims: tuple of nifti header zoom values. """ img = correct_nifti_header_if_necessary(input_data) - if legacy: - img = nib.funcs.as_closest_canonical(img) + img = nib.funcs.as_closest_canonical(img) data_array = nib.orientations.apply_orientation(img.get_fdata(), ornt) pixdims = img.header.get_zooms() return data_array, pixdims diff --git a/tests/darwin/importer/formats/import_nifti_test.py b/tests/darwin/importer/formats/import_nifti_test.py index d59b2c9a9..f7045d55c 100644 --- a/tests/darwin/importer/formats/import_nifti_test.py +++ b/tests/darwin/importer/formats/import_nifti_test.py @@ -9,6 +9,7 @@ import numpy as np import pytest from scipy import ndimage +import nibabel as nib from darwin.datatypes import ( Annotation, @@ -17,7 +18,7 @@ SubAnnotation, VideoAnnotation, ) -from darwin.importer.formats.nifti import get_new_axial_size, parse_path +from darwin.importer.formats.nifti import get_new_axial_size, parse_path, process_nifti from tests.fixtures import * from darwin.utils.utils import parse_darwin_json @@ -239,6 +240,70 @@ def test_get_new_axial_size_with_isotropic(): assert new_size == (20, 10) +def test_process_nifti_orientation_ras_to_lpi(team_slug_darwin_json_v2): + """ + Test that an input NifTI annotation file in the RAS orientation is correctly + transformed to the LPI orientation. + + Do this by emulating the `process_nifti` function, which: + - 1: Transforms the input file into the RAS orientation + - 2: Transforms the transformed RAS file into the LPI orientation + """ + with tempfile.TemporaryDirectory() as tmpdir: + with ZipFile("tests/data.zip") as zfile: + zfile.extractall(tmpdir) + filepath = ( + Path(tmpdir) + / team_slug_darwin_json_v2 + / "nifti" + / "releases" + / "latest" + / "annotations" + / "vol0_brain.nii.gz" + ) + lpi_ornt = [[0.0, -1.0], [1.0, -1.0], [2.0, -1.0]] + ras_file = nib.load(filepath) + ras_transformed_file = nib.funcs.as_closest_canonical(ras_file) + lpi_transformed_file = nib.orientations.apply_orientation( + ras_transformed_file.get_fdata(), lpi_ornt + ) + processed_file, _ = process_nifti(input_data=ras_file) + assert not np.array_equal(processed_file, ras_file._dataobj) + assert np.array_equal(processed_file, lpi_transformed_file) + + +def test_process_nifti_orientation_las_to_lpi(team_slug_darwin_json_v2): + """ + Test that an input NifTI annotation file in the LAS orientation is correctly + transformed to the LPI orientation. + + Do this by emulating the `process_nifti` function, which: + - 1: Transforms the input file into the RAS orientation + - 2: Transforms the transformed RAS file into the LPI orientation + """ + with tempfile.TemporaryDirectory() as tmpdir: + with ZipFile("tests/data.zip") as zfile: + zfile.extractall(tmpdir) + filepath = ( + Path(tmpdir) + / team_slug_darwin_json_v2 + / "nifti" + / "releases" + / "latest" + / "annotations" + / "BRAINIX_NIFTI_ROI.nii.gz" + ) + lpi_ornt = [[0.0, -1.0], [1.0, -1.0], [2.0, -1.0]] + las_file = nib.load(filepath) + ras_transformed_file = nib.funcs.as_closest_canonical(las_file) + lpi_transformed_file = nib.orientations.apply_orientation( + ras_transformed_file.get_fdata(), lpi_ornt + ) + processed_file, _ = process_nifti(input_data=las_file) + assert not np.array_equal(processed_file, las_file._dataobj) + assert np.array_equal(processed_file, lpi_transformed_file) + + def serialise_annotation_file( annotation_file: AnnotationFile, as_dict ) -> Union[str, dict]: diff --git a/tests/data.zip b/tests/data.zip index fda8c0e0b..b38cedda1 100644 Binary files a/tests/data.zip and b/tests/data.zip differ