diff --git a/darwin/dataset/remote_dataset_v2.py b/darwin/dataset/remote_dataset_v2.py index 306b7b4c9..8956a8a3a 100644 --- a/darwin/dataset/remote_dataset_v2.py +++ b/darwin/dataset/remote_dataset_v2.py @@ -11,7 +11,7 @@ Tuple, Union, ) - +import numpy as np from pydantic import ValidationError from requests.models import Response @@ -873,10 +873,15 @@ def register_multi_slotted( print(f"Reistration complete. Check your items in the dataset: {self.slug}") return results - def _get_remote_files_that_require_legacy_scaling(self) -> List[Path]: + def _get_remote_files_that_require_legacy_scaling( + self, + ) -> Dict[str, Dict[str, Any]]: """ Get all remote files that have been scaled upon upload. These files require that - NifTI annotations are similarly scaled during import + NifTI annotations are similarly scaled during import. + + The in-platform affines are returned for each legacy file, as this is required + to properly re-orient the annotations during import. Parameters ---------- @@ -885,21 +890,31 @@ def _get_remote_files_that_require_legacy_scaling(self) -> List[Path]: Returns ------- - List[Path] - A list of full remote paths of dataset items that require NifTI annotations to be scaled + Dict[str, Dict[str, Any]] + A dictionary of remote file full paths to their slot affine maps """ - remote_files_that_require_legacy_scaling = [] + remote_files_that_require_legacy_scaling = {} remote_files = self.fetch_remote_files( filters={"statuses": ["new", "annotate", "review", "complete", "archived"]} ) for remote_file in remote_files: + if not remote_file.slots[0].get("metadata", {}).get("medical", {}): + continue if not ( remote_file.slots[0] .get("metadata", {}) .get("medical", {}) .get("handler") ): - remote_files_that_require_legacy_scaling.append(remote_file.full_path) + slot_affine_map = {} + for slot in remote_file.slots: + slot_affine_map[slot["slot_name"]] = np.array( + slot["metadata"]["medical"]["affine"], + dtype=np.float64, + ) + remote_files_that_require_legacy_scaling[ + Path(remote_file.full_path) + ] = slot_affine_map return remote_files_that_require_legacy_scaling diff --git a/darwin/exporter/formats/nifti.py b/darwin/exporter/formats/nifti.py index 6d2eeaf02..011b1e4e8 100644 --- a/darwin/exporter/formats/nifti.py +++ b/darwin/exporter/formats/nifti.py @@ -25,7 +25,6 @@ def _console_theme() -> Theme: console = Console(theme=_console_theme()) try: import nibabel as nib - from nibabel.orientations import io_orientation, ornt_transform except ImportError: import_fail_string = r""" You must install darwin-py with pip install darwin-py\[medical] @@ -128,7 +127,11 @@ def export( polygon_annotations, slot_map, output_volumes, legacy=legacy ) write_output_volume_to_disk( - output_volumes, image_id=image_id, output_dir=output_dir, legacy=legacy + output_volumes, + image_id=image_id, + output_dir=output_dir, + legacy=legacy, + filename=video_annotation.filename, ) # Need to map raster layers to SeriesInstanceUIDs if mask_present: @@ -161,6 +164,7 @@ def export( image_id=image_id, output_dir=output_dir, legacy=legacy, + filename=video_annotation.filename, ) @@ -456,6 +460,7 @@ def write_output_volume_to_disk( image_id: str, output_dir: Union[str, Path], legacy: bool = False, + filename: str = None, ) -> None: """Writes the given output volumes to disk. @@ -470,6 +475,8 @@ def write_output_volume_to_disk( legacy : bool, default=False If ``True``, the exporter will use the legacy calculation. If ``False``, the exporter will use the new calculation by dividing with pixdims. + filename: str + The filename of the dataset item Returns ------- @@ -489,18 +496,10 @@ def unnest_dict_to_list(d: Dict) -> List: volumes = unnest_dict_to_list(output_volumes) for volume in volumes: img = nib.Nifti1Image( - dataobj=np.flip(volume.pixel_array, (0, 1, 2)).astype(np.int16), + dataobj=volume.pixel_array.astype(np.int16), affine=volume.affine, ) - if legacy and volume.original_affine is not None: - orig_ornt = io_orientation( - volume.original_affine - ) # Get orientation of current affine - img_ornt = io_orientation(volume.affine) # Get orientation of RAS affine - from_canonical = ornt_transform( - img_ornt, orig_ornt - ) # Get transform from RAS to current affine - img = img.as_reoriented(from_canonical) + img = _get_reoriented_nifti_image(img, volume, legacy, filename) if volume.from_raster_layer: output_path = Path(output_dir) / f"{image_id}_{volume.class_name}_m.nii.gz" else: @@ -510,6 +509,46 @@ def unnest_dict_to_list(d: Dict) -> List: nib.save(img=img, filename=output_path) +def _get_reoriented_nifti_image( + img: nib.Nifti1Image, volume: Dict, legacy: bool, filename: str +) -> nib.Nifti1Image: + """ + Reorients the given NIfTI image based on the affine of the originally uploaded file. + + Files that were uploaded before the `MED_2D_VIEWER` feature are `legacy`. Non-legacy + files are uploaded and re-oriented to the `LPI` orientation. Legacy NifTI + files were treated differently. These files were re-oriented to `LPI`, but their + affine was stored as `RAS`, which is the opposite orientation. We therefore need to + flip the axes of these images to ensure alignment. + + Parameters + ---------- + img: nib.Nifti1Image + The NIfTI image to be reoriented + volume: Dict + The volume containing the affine and original affine + legacy: bool + If ``True``, the exporter will flip all axes of the image if the dataset item + is not a DICOM + If ``False``, the exporter will not flip the axes + filename: str + The filename of the dataset item + """ + if volume.original_affine is not None: + img_ax_codes = nib.orientations.aff2axcodes(volume.affine) + orig_ax_codes = nib.orientations.aff2axcodes(volume.original_affine) + img_ornt = nib.orientations.axcodes2ornt(img_ax_codes) + orig_ornt = nib.orientations.axcodes2ornt(orig_ax_codes) + transform = nib.orientations.ornt_transform(img_ornt, orig_ornt) + img = img.as_reoriented(transform) + is_dicom = filename.lower().endswith(".dcm") + if legacy and not is_dicom: + img = nib.Nifti1Image( + np.flip(img.get_fdata(), (0, 1, 2)).astype(np.int16), img.affine + ) + return img + + def shift_polygon_coords( polygon: List[Dict], pixdim: List[Number], legacy: bool = False ) -> List: diff --git a/darwin/importer/formats/nifti.py b/darwin/importer/formats/nifti.py index 103b599af..cb6f748a7 100644 --- a/darwin/importer/formats/nifti.py +++ b/darwin/importer/formats/nifti.py @@ -3,7 +3,7 @@ import warnings from collections import OrderedDict, defaultdict from pathlib import Path -from typing import Dict, List, Optional, Tuple +from typing import Dict, List, Optional, Tuple, Any from rich.console import Console @@ -31,8 +31,7 @@ def parse_path( path: Path, - legacy: bool = False, - remote_files_that_require_legacy_scaling: Optional[List] = [], + remote_files_that_require_legacy_scaling: Dict[Path, Dict[str, Any]] = {}, ) -> Optional[List[dt.AnnotationFile]]: """ Parses the given ``nifti`` file and returns a ``List[dt.AnnotationFile]`` with the parsed @@ -42,9 +41,8 @@ def parse_path( ---------- path : Path The ``Path`` to the ``nifti`` file. - legacy : bool, default: False - If ``True``, the function will not attempt to resize the annotations to isotropic pixel dimensions. - If ``False``, the function will resize the annotations to isotropic pixel dimensions. + remote_files_that_require_legacy_scaling : Optional[Dict[Path, Dict[str, Any]]] + A dictionary of remote file full paths to their slot affine maps Returns ------- @@ -78,16 +76,20 @@ def parse_path( return None annotation_files = [] for nifti_annotation in nifti_annotations: - legacy = nifti_annotation["image"] in remote_files_that_require_legacy_scaling + remote_file_path = Path(nifti_annotation["image"]) + if not str(remote_file_path).startswith("/"): + remote_file_path = Path("/" + str(remote_file_path)) + annotation_file = _parse_nifti( Path(nifti_annotation["label"]), - nifti_annotation["image"], + Path(nifti_annotation["image"]), path, class_map=nifti_annotation.get("class_map"), mode=nifti_annotation.get("mode", "image"), slot_names=nifti_annotation.get("slot_names", []), is_mpr=nifti_annotation.get("is_mpr", False), - legacy=legacy, + remote_file_path=remote_file_path, + remote_files_that_require_legacy_scaling=remote_files_that_require_legacy_scaling, ) annotation_files.append(annotation_file) return annotation_files @@ -101,10 +103,16 @@ def _parse_nifti( mode: str, slot_names: List[str], is_mpr: bool, - legacy: bool = False, + remote_file_path: Path, + remote_files_that_require_legacy_scaling: Dict[Path, Dict[str, Any]] = {}, ) -> dt.AnnotationFile: - img, pixdims = process_nifti(nib.load(nifti_path)) + img, pixdims = process_nifti( + nib.load(nifti_path), + remote_file_path=remote_file_path, + remote_files_that_require_legacy_scaling=remote_files_that_require_legacy_scaling, + ) + legacy = remote_file_path in remote_files_that_require_legacy_scaling processed_class_map = process_class_map(class_map) video_annotations = [] if mode == "instances": # For each instance produce a video annotation @@ -159,11 +167,12 @@ def _parse_nifti( dt.AnnotationClass(class_name, "mask", "mask") for class_name in class_map.values() } - + remote_path = "/" if filename.parent == "." else filename.parent + filename = Path(filename.name) return dt.AnnotationFile( path=json_path, filename=str(filename), - remote_path="/", + remote_path=str(remote_path), annotation_classes=annotation_classes, annotations=video_annotations, slots=[ @@ -353,7 +362,7 @@ def nifti_to_video_polygon_annotation( if len(all_frame_ids) == 1: segments = [[all_frame_ids[0], all_frame_ids[0] + 1]] elif len(all_frame_ids) > 1: - segments = [[min(all_frame_ids), max(all_frame_ids)]] + segments = [[min(all_frame_ids), max(all_frame_ids) + 1]] video_annotation = dt.make_video_annotation( frame_annotations, keyframes={f_id: True for f_id in all_frame_ids}, @@ -513,16 +522,33 @@ 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]], + remote_file_path: Path = Path("/"), + remote_files_that_require_legacy_scaling: Dict[Path, Dict[str, Any]] = {}, ) -> Tuple[np.ndarray, Tuple[float]]: """ - Converts a nifti object of any orientation to the passed ornt orientation. + Converts a NifTI object of any orientation to the passed ornt orientation. The default ornt is LPI. + Files that were uploaded before the `MED_2D_VIEWER` feature are `legacy`. Non-legacy + files are uploaded and re-oriented to the `LPI` orientation. Legacy files + files were treated differently: + - Legacy NifTI files were re-oriented to `LPI`, but their + affine was stored as `RAS`, which is the opposite orientation. However, because + their pixel data is stored in `LPI`, we can treat them the same way as non-legacy + files. + - Legacy DICOM files were not always re-oriented to `LPI`. We therefore use the + affine of the dataset item from `slot_affine_map` to re-orient the NifTI file to + be imported + Args: - input_data: nibabel nifti object. - ornt: (n,2) orientation array. It defines a transformation from RAS. + input_data: nibabel NifTI object. + ornt: (n,2) orientation array. It defines a transformation to LPI ornt[N,1] is a flip of axis N of the array, where 1 means no flip and -1 means flip. ornt[:,0] is the transpose that needs to be done to the implied array, as in arr.transpose(ornt[:,0]). + remote_file_path: Path + The full path of the remote file + remote_files_that_require_legacy_scaling: Dict[Path, Dict[str, Any]] + A dictionary of remote file full paths to their slot affine maps Returns: data_array: pixel array with orientation ornt. @@ -531,9 +557,14 @@ def process_nifti( img = correct_nifti_header_if_necessary(input_data) orig_ax_codes = nib.orientations.aff2axcodes(img.affine) orig_ornt = nib.orientations.axcodes2ornt(orig_ax_codes) + is_dicom = remote_file_path.suffix.lower() == ".dcm" + if remote_file_path in remote_files_that_require_legacy_scaling and is_dicom: + slot_affine_map = remote_files_that_require_legacy_scaling[remote_file_path] + affine = slot_affine_map[next(iter(slot_affine_map))] # Take the 1st slot + ax_codes = nib.orientations.aff2axcodes(affine) + ornt = nib.orientations.axcodes2ornt(ax_codes) transform = nib.orientations.ornt_transform(orig_ornt, ornt) reoriented_img = img.as_reoriented(transform) - data_array = reoriented_img.get_fdata() pixdims = reoriented_img.header.get_zooms() diff --git a/tests/darwin/data/nifti/legacy/sample_nifti.nii.json b/tests/darwin/data/nifti/legacy/sample_nifti.nii.json new file mode 100644 index 000000000..abb0cf524 --- /dev/null +++ b/tests/darwin/data/nifti/legacy/sample_nifti.nii.json @@ -0,0 +1,2148 @@ +{ + "version": "2.0", + "schema_ref": "https://darwin-public.s3.eu-west-1.amazonaws.com/darwin_json/2.0/schema.json", + "item": { + "name": "2044737.fat.nii.gz", + "path": "/", + "source_info": { + "item_id": "0192eee1-7767-3bcc-1b02-7bd3a435b59d", + "team": { + "name": "V7 John", + "slug": "v7-john" + }, + "dataset": { + "name": "MED_2D_VIEWER_OFF", + "slug": "med_2d_viewer_off", + "dataset_management_url": "https://darwin.v7labs.com/datasets/1354682/dataset-management" + }, + "workview_url": "https://darwin.v7labs.com/workview?dataset=1354682&item=0192eee1-7767-3bcc-1b02-7bd3a435b59d" + }, + "slots": [ + { + "type": "dicom", + "slot_name": "0", + "width": 224, + "height": 174, + "fps": null, + "thumbnail_url": "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/thumbnail", + "source_files": [ + { + "file_name": "2044737.fat.nii.gz", + "url": "https://darwin.v7labs.com/api/v2/teams/v7-john/uploads/e760518f-563b-467a-be4d-e85eee725e45" + } + ], + "frame_count": 17, + "frame_urls": [ + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/0", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/1", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/2", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/3", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/4", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/5", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/6", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/7", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/8", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/9", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/10", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/11", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/12", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/13", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/14", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/15", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/8c754a67-b65a-4aad-aff1-2fdcb36a1669/sections/16" + ], + "metadata": { + "handler": null, + "shape": [ + 1, + 224, + 174, + 17 + ], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.89599582585125995121795967413768680340", + "affine": "[[2.232142925262451, 0.0, 0.0, -247.7678723335266], [0.0, 2.232142925262451, 0.0, -191.96429443359375], [0.0, 0.0, 3.0, -21.0], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + [ + "-2.232142925262451", + "-0.0", + "0.0", + "250.0" + ], + [ + "-0.0", + "2.232142925262451", + "-0.0", + "-191.96429443359375" + ], + [ + "0.0", + "0.0", + "3.0", + "-21.0" + ], + [ + "0.0", + "0.0", + "0.0", + "1.0" + ] + ], + "pixdim": "(2.232143, 2.232143, 3.0)" + } + } + ] + }, + "annotations": [ + { + "frames": { + "1": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "2": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "3": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "4": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "5": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "6": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "7": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "8": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "9": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "10": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "11": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "12": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "13": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "14": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "15": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + }, + "16": { + "bounding_box": { + "h": 18.0, + "w": 27.0, + "x": 52.0, + "y": 74.0 + }, + "keyframe": true, + "polygon": { + "paths": [ + [ + { + "x": 52.0, + "y": 91.0 + }, + { + "x": 65.0, + "y": 91.0 + }, + { + "x": 66.0, + "y": 91.0 + }, + { + "x": 67.0, + "y": 92.0 + }, + { + "x": 78.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 92.0 + }, + { + "x": 79.0, + "y": 91.0 + }, + { + "x": 79.0, + "y": 90.0 + }, + { + "x": 78.0, + "y": 89.0 + }, + { + "x": 77.0, + "y": 88.0 + }, + { + "x": 77.0, + "y": 87.0 + }, + { + "x": 76.0, + "y": 86.0 + }, + { + "x": 75.0, + "y": 85.0 + }, + { + "x": 75.0, + "y": 84.0 + }, + { + "x": 74.0, + "y": 83.0 + }, + { + "x": 73.0, + "y": 82.0 + }, + { + "x": 73.0, + "y": 81.0 + }, + { + "x": 72.0, + "y": 80.0 + }, + { + "x": 71.0, + "y": 79.0 + }, + { + "x": 71.0, + "y": 78.0 + }, + { + "x": 70.0, + "y": 77.0 + }, + { + "x": 69.0, + "y": 76.0 + }, + { + "x": 69.0, + "y": 75.0 + }, + { + "x": 68.0, + "y": 74.0 + }, + { + "x": 61.0, + "y": 81.0 + }, + { + "x": 60.0, + "y": 82.0 + }, + { + "x": 60.0, + "y": 83.0 + }, + { + "x": 52.0, + "y": 91.0 + } + ] + ] + } + } + }, + "hidden_areas": [], + "id": "d75a7a42-9600-4299-9b66-d27809b5db64", + "name": "Reference_sBAT", + "properties": [], + "ranges": [ + [ + 1, + 17 + ] + ], + "slot_names": [ + "0" + ] + } + ], + "properties": [] +} \ No newline at end of file diff --git a/tests/darwin/data/nifti/nifti.json b/tests/darwin/data/nifti/nifti.json index becf8807e..ccf69a692 100644 --- a/tests/darwin/data/nifti/nifti.json +++ b/tests/darwin/data/nifti/nifti.json @@ -1,7 +1,7 @@ { "data": [ { - "image": "BRAINIX_NIFTI_ROI.nii.gz", + "image": "2044737.fat.nii.gz", "label": "/Users/john/Documents/code/development/darwin-py/tests/darwin/data/nifti/BRAINIX_NIFTI_ROI.nii.gz", "class_map": { "1": "Reference_sBAT" diff --git a/tests/darwin/data/nifti/sample_nifti.nii b/tests/darwin/data/nifti/sample_nifti.nii new file mode 100644 index 000000000..4a2593743 Binary files /dev/null and b/tests/darwin/data/nifti/sample_nifti.nii differ diff --git a/tests/darwin/dataset/remote_dataset_test.py b/tests/darwin/dataset/remote_dataset_test.py index 07881d7e8..0fb12d703 100644 --- a/tests/darwin/dataset/remote_dataset_test.py +++ b/tests/darwin/dataset/remote_dataset_test.py @@ -6,6 +6,7 @@ from pathlib import Path from typing import Any, Dict from unittest.mock import MagicMock, patch +import numpy as np import orjson as json import pytest @@ -1906,7 +1907,14 @@ def mock_remote_files(self): seq=1, current_workflow_id=None, path="/path/to/file", - slots=[{"metadata": {"medical": {"handler": "MONAI"}}}], + slots=[ + { + "slot_name": "0", + "metadata": { + "medical": {"handler": "MONAI", "affine": [1, 0, 0, 0]} + }, + } + ], layout={}, current_workflow=None, ), @@ -1921,7 +1929,21 @@ def mock_remote_files(self): seq=2, current_workflow_id=None, path="/path/to/file", - slots=[{"metadata": {"medical": {}}}], + slots=[ + { + "slot_name": "0", + "metadata": { + "medical": { + "affine": [ + [-1, 0, 0, 0], + [0, -1, 0, 0], + [0, 0, -1, 0], + [0, 0, 0, 1], + ] + } + }, + } + ], layout={}, current_workflow=None, ), @@ -1941,6 +1963,7 @@ def test_get_remote_files_that_require_legacy_scaling( ) result = remote_dataset._get_remote_files_that_require_legacy_scaling() - - assert len(result) == 1 - assert result[0] == "/path/to/file/filename" + assert Path("/path/to/file/filename") in result + np.testing.assert_array_equal( + result[Path("/path/to/file/filename")]["0"], np.array([[-1, 0, 0, 0], [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, 1]]) # type: ignore + ) diff --git a/tests/darwin/importer/formats/import_nifti_test.py b/tests/darwin/importer/formats/import_nifti_test.py index 902819a13..62104c916 100644 --- a/tests/darwin/importer/formats/import_nifti_test.py +++ b/tests/darwin/importer/formats/import_nifti_test.py @@ -168,12 +168,12 @@ def test_image_annotation_nifti_import_single_slot_to_mask_legacy( / "releases" / "latest" / "annotations" - / "vol0_brain.nii.gz" + / "sample_nifti.nii" ) input_dict = { "data": [ { - "image": "vol0 (1).nii", + "image": "2044737.fat.nii", "label": str(label_path), "class_map": {"1": "brain"}, "mode": "mask", @@ -190,7 +190,18 @@ def test_image_annotation_nifti_import_single_slot_to_mask_legacy( with patch("darwin.importer.formats.nifti.zoom") as mock_zoom: mock_zoom.side_effect = ndimage.zoom - remote_files_that_require_legacy_scaling = ["vol0 (1).nii"] + remote_files_that_require_legacy_scaling = { + Path("/2044737.fat.nii"): { + "0": np.array( + [ + [2.23214293, 0, 0, -247.76787233], + [0, 2.23214293, 0, -191.96429443], + [0, 0, 3, -21], + [0, 0, 0, 1], + ] + ) + } + } annotation_files = parse_path( path=upload_json, remote_files_that_require_legacy_scaling=remote_files_that_require_legacy_scaling, @@ -204,7 +215,7 @@ def test_image_annotation_nifti_import_single_slot_to_mask_legacy( Path(tmpdir) / team_slug_darwin_json_v2 / "nifti" - / "vol0_annotation_file_to_mask.json", + / "sample_nifti.nii.json", "r", ) ) @@ -216,17 +227,18 @@ def test_image_annotation_nifti_import_single_slot_to_mask_legacy( ] [ frame.get("raster_layer", {}).pop("mask_annotation_ids_mapping") - for frame in expected_json_string["annotations"][0][ + for frame in expected_json_string["annotations"][1][ "frames" ].values() ] - assert mock_zoom.call_count == len( - expected_json_string["annotations"][0]["frames"] + assert ( + mock_zoom.call_count + == expected_json_string["item"]["slots"][0]["frame_count"] ) assert ( output_json_string["annotations"][0]["frames"] - == expected_json_string["annotations"][0]["frames"] + == expected_json_string["annotations"][1]["frames"] ) @@ -504,19 +516,28 @@ def test_parse_path_nifti_with_legacy_scaling(): nifti_annotation_filepath = ( Path(__file__).parents[2] / "data" / "nifti" / "nifti.json" ) - nifti_filepath = ( - Path(__file__).parents[2] / "data" / "nifti" / "BRAINIX_NIFTI_ROI.nii.gz" - ) + nifti_filepath = Path(__file__).parents[2] / "data" / "nifti" / "sample_nifti.nii" expected_annotations_filepath = ( Path(__file__).parents[2] / "data" / "nifti" / "legacy" - / "BRAINIX_NIFTI_ROI.nii.json" + / "sample_nifti.nii.json" ) adjust_nifti_label_filepath(nifti_annotation_filepath, nifti_filepath) expected_annotations = parse_darwin_json(expected_annotations_filepath) - remote_files_that_require_legacy_scaling = ["BRAINIX_NIFTI_ROI.nii.gz"] + remote_files_that_require_legacy_scaling = { + Path("/2044737.fat.nii.gz"): { + "0": np.array( + [ + [2.23214293, 0, 0, -247.76787233], + [0, 2.23214293, 0, -191.96429443], + [0, 0, 3, -21], + [0, 0, 0, 1], + ] + ) + } + } parsed_annotations = parse_path( nifti_annotation_filepath, remote_files_that_require_legacy_scaling=remote_files_that_require_legacy_scaling, @@ -551,9 +572,13 @@ def test_parse_path_nifti_without_legacy_scaling(): / "no-legacy" / "BRAINIX_NIFTI_ROI.nii.json" ) + remote_files_that_require_legacy_scaling = {} adjust_nifti_label_filepath(nifti_annotation_filepath, nifti_filepath) expected_annotations = parse_darwin_json(expected_annotations_filepath) - parsed_annotations = parse_path(nifti_annotation_filepath, legacy=False) + parsed_annotations = parse_path( + nifti_annotation_filepath, + remote_files_that_require_legacy_scaling=remote_files_that_require_legacy_scaling, + ) for frame_idx in expected_annotations.annotations[0].frames: expected_annotation = ( expected_annotations.annotations[0].frames[frame_idx].data["paths"] diff --git a/tests/data.zip b/tests/data.zip index b38cedda1..cd5a2f149 100644 Binary files a/tests/data.zip and b/tests/data.zip differ