From 148d2a0dcea649962142fe25b5750a2db7e1207f Mon Sep 17 00:00:00 2001 From: Jo-Byr Date: Fri, 11 Jul 2025 09:03:33 +0200 Subject: [PATCH 1/5] e2e test for nifti multi-segment conversion --- e2e_tests/cli/test_convert.py | 5 + .../from/axial_RPI_pixdim_1.0_1.0_1.0.json | 259 ++++++++++++++++++ .../from/coronal_LAS_pixdim_0.1_0.2_0.5.json | 259 ++++++++++++++++++ .../from/sagittal_LPI_pixdim_0.1_0.2_0.5.json | 259 ++++++++++++++++++ ...ial_RPI_pixdim_1.0_1.0_1_Segments_m.nii.gz | Bin 0 -> 2510 bytes .../axial_RPI_pixdim_1.0_1.0_1_mask1_m.nii.gz | Bin 0 -> 2469 bytes .../axial_RPI_pixdim_1.0_1.0_1_mask2_m.nii.gz | Bin 0 -> 2467 bytes ...nal_LAS_pixdim_0.1_0.2_0_Segments_m.nii.gz | Bin 0 -> 2472 bytes ...oronal_LAS_pixdim_0.1_0.2_0_mask1_m.nii.gz | Bin 0 -> 2447 bytes ...oronal_LAS_pixdim_0.1_0.2_0_mask2_m.nii.gz | Bin 0 -> 2447 bytes ...tal_LPI_pixdim_0.1_0.2_0_Segments_m.nii.gz | Bin 0 -> 2535 bytes ...gittal_LPI_pixdim_0.1_0.2_0_mask1_m.nii.gz | Bin 0 -> 2491 bytes ...gittal_LPI_pixdim_0.1_0.2_0_mask2_m.nii.gz | Bin 0 -> 2489 bytes 13 files changed, 782 insertions(+) create mode 100644 e2e_tests/data/convert/nifti-multi-segment/from/axial_RPI_pixdim_1.0_1.0_1.0.json create mode 100644 e2e_tests/data/convert/nifti-multi-segment/from/coronal_LAS_pixdim_0.1_0.2_0.5.json create mode 100644 e2e_tests/data/convert/nifti-multi-segment/from/sagittal_LPI_pixdim_0.1_0.2_0.5.json create mode 100644 e2e_tests/data/convert/nifti-multi-segment/to/axial_RPI_pixdim_1.0_1.0_1.0/0/axial_RPI_pixdim_1.0_1.0_1_Segments_m.nii.gz create mode 100644 e2e_tests/data/convert/nifti-multi-segment/to/axial_RPI_pixdim_1.0_1.0_1.0/0/axial_RPI_pixdim_1.0_1.0_1_mask1_m.nii.gz create mode 100644 e2e_tests/data/convert/nifti-multi-segment/to/axial_RPI_pixdim_1.0_1.0_1.0/0/axial_RPI_pixdim_1.0_1.0_1_mask2_m.nii.gz create mode 100644 e2e_tests/data/convert/nifti-multi-segment/to/coronal_LAS_pixdim_0.1_0.2_0.5/0/coronal_LAS_pixdim_0.1_0.2_0_Segments_m.nii.gz create mode 100644 e2e_tests/data/convert/nifti-multi-segment/to/coronal_LAS_pixdim_0.1_0.2_0.5/0/coronal_LAS_pixdim_0.1_0.2_0_mask1_m.nii.gz create mode 100644 e2e_tests/data/convert/nifti-multi-segment/to/coronal_LAS_pixdim_0.1_0.2_0.5/0/coronal_LAS_pixdim_0.1_0.2_0_mask2_m.nii.gz create mode 100644 e2e_tests/data/convert/nifti-multi-segment/to/sagittal_LPI_pixdim_0.1_0.2_0.5/0/sagittal_LPI_pixdim_0.1_0.2_0_Segments_m.nii.gz create mode 100644 e2e_tests/data/convert/nifti-multi-segment/to/sagittal_LPI_pixdim_0.1_0.2_0.5/0/sagittal_LPI_pixdim_0.1_0.2_0_mask1_m.nii.gz create mode 100644 e2e_tests/data/convert/nifti-multi-segment/to/sagittal_LPI_pixdim_0.1_0.2_0.5/0/sagittal_LPI_pixdim_0.1_0.2_0_mask2_m.nii.gz diff --git a/e2e_tests/cli/test_convert.py b/e2e_tests/cli/test_convert.py index 863b6c0cc..456af1544 100644 --- a/e2e_tests/cli/test_convert.py +++ b/e2e_tests/cli/test_convert.py @@ -70,6 +70,11 @@ def compare_directories(self, path: Path, expected_path: Path) -> None: data_path / "nifti-multislot/from", data_path / "nifti-multislot/to", ), + ( + "nifti", + data_path / "nifti-multi-segment/from", + data_path / "nifti-multi-segment/to", + ), ( "instance_mask", data_path / "instance_mask/from", diff --git a/e2e_tests/data/convert/nifti-multi-segment/from/axial_RPI_pixdim_1.0_1.0_1.0.json b/e2e_tests/data/convert/nifti-multi-segment/from/axial_RPI_pixdim_1.0_1.0_1.0.json new file mode 100644 index 000000000..7c64e0c0b --- /dev/null +++ b/e2e_tests/data/convert/nifti-multi-segment/from/axial_RPI_pixdim_1.0_1.0_1.0.json @@ -0,0 +1,259 @@ +{ + "version": "2.0", + "schema_ref": "https://darwin-public.s3.eu-west-1.amazonaws.com/darwin_json/2.0/schema.json", + "item": { + "name": "axial_RPI_pixdim_1.0_1.0_1.0.dcm", + "path": "/", + "source_info": { + "item_id": "0197ee1d-591e-a61b-82e2-e6f1e5c30cf2", + "dataset": { + "name": "dicom_test_data_new", + "slug": "dicom_test_data_new", + "dataset_management_url": "https://darwin.v7labs.com/datasets/1856922/dataset-management" + }, + "team": { + "name": "V7 John", + "slug": "v7-john" + }, + "workview_url": "https://darwin.v7labs.com/workview?dataset=1856922&item=0197ee1d-591e-a61b-82e2-e6f1e5c30cf2" + }, + "slots": [ + { + "type": "dicom", + "slot_name": "0", + "width": 128, + "height": 128, + "fps": null, + "thumbnail_url": "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/thumbnail?token=590de404-3490-4dde-90f9-d13136b0d14f", + "source_files": [ + { + "file_name": "axial_RPI_pixdim_1.0_1.0_1.0.dcm", + "url": "https://darwin.v7labs.com/api/v2/teams/v7-john/uploads/d4f4e7cd-e8a8-407f-9ff3-0a1f3298c84c?token=590de404-3490-4dde-90f9-d13136b0d14f" + } + ], + "frame_count": 16, + "frame_urls": [ + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/0?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/1?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/2?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/3?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/4?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/5?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/6?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/7?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/8?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/9?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/10?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/11?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/12?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/13?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/14?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/15?token=590de404-3490-4dde-90f9-d13136b0d14f" + ], + "metadata": { + "handler": "MONAI", + "shape": [ + 1, + 128, + 128, + 16 + ], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.37180825650614764423282910493086149224", + "affine": "[[-1.0, 0.0, 0.0, 127.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, -1.0, 15.0], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + [ + "1.0", + "0.0", + "0.0", + "0.0" + ], + [ + "0.0", + "-1.0", + "0.0", + "0.0" + ], + [ + "0.0", + "0.0", + "1.0", + "0.0" + ], + [ + "0.0", + "0.0", + "0.0", + "1.0" + ] + ], + "pixdim": "(1.0, 1.0, 1.0)", + "plane_map": { + "0": "AXIAL" + }, + "primary_plane": "AXIAL" + } + } + ] + }, + "annotations": [ + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "02c693fa-97f5-4a3c-9c45-e1d9eebb0731", + "interpolate_algorithm": "linear-1.1", + "name": "mask1", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "d212f8a6-8e09-4901-a44b-77745626edc9", + "interpolate_algorithm": "linear-1.1", + "name": "mask2", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "raster_layer": { + "dense_rle": [ + 0, + 2104, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 11816 + ], + "mask_annotation_ids_mapping": { + "02c693fa-97f5-4a3c-9c45-e1d9eebb0731": 1, + "d212f8a6-8e09-4901-a44b-77745626edc9": 2 + }, + "total_pixels": 16384 + } + } + }, + "id": "a15c3b3e-89af-4733-b6c7-10f01e2c0b57", + "name": "__raster_layer__", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 0, + 16 + ] + ], + "slot_names": [ + "0" + ] + } + ], + "properties": [] +} \ No newline at end of file diff --git a/e2e_tests/data/convert/nifti-multi-segment/from/coronal_LAS_pixdim_0.1_0.2_0.5.json b/e2e_tests/data/convert/nifti-multi-segment/from/coronal_LAS_pixdim_0.1_0.2_0.5.json new file mode 100644 index 000000000..e42e9e8d3 --- /dev/null +++ b/e2e_tests/data/convert/nifti-multi-segment/from/coronal_LAS_pixdim_0.1_0.2_0.5.json @@ -0,0 +1,259 @@ +{ + "version": "2.0", + "schema_ref": "https://darwin-public.s3.eu-west-1.amazonaws.com/darwin_json/2.0/schema.json", + "item": { + "name": "coronal_LAS_pixdim_0.1_0.2_0.5.dcm", + "path": "/", + "source_info": { + "item_id": "0197ee1d-591e-7d19-bb01-65d27fb0bcdd", + "dataset": { + "name": "dicom_test_data_new", + "slug": "dicom_test_data_new", + "dataset_management_url": "https://darwin.v7labs.com/datasets/1856922/dataset-management" + }, + "team": { + "name": "V7 John", + "slug": "v7-john" + }, + "workview_url": "https://darwin.v7labs.com/workview?dataset=1856922&item=0197ee1d-591e-7d19-bb01-65d27fb0bcdd" + }, + "slots": [ + { + "type": "dicom", + "slot_name": "0", + "width": 128, + "height": 128, + "fps": null, + "thumbnail_url": "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/thumbnail?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "source_files": [ + { + "file_name": "coronal_LAS_pixdim_0.1_0.2_0.5.dcm", + "url": "https://darwin.v7labs.com/api/v2/teams/v7-john/uploads/bbf2147d-e328-4a93-a624-90f9c474a071?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f" + } + ], + "frame_count": 16, + "frame_urls": [ + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/0?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/1?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/2?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/3?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/4?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/5?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/6?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/7?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/8?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/9?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/10?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/11?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/12?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/13?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/14?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/15?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f" + ], + "metadata": { + "handler": "MONAI", + "shape": [ + 1, + 128, + 16, + 128 + ], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.10392093638286046303269310577715221690", + "affine": "[[-0.1, 0.0, 0.0, 0.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, -0.25, 31.75], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + [ + "-0.1", + "0.0", + "0.0", + "0.0" + ], + [ + "0.0", + "0.0", + "-1.0", + "0.0" + ], + [ + "0.0", + "0.25", + "0.0", + "0.0" + ], + [ + "0.0", + "0.0", + "0.0", + "1.0" + ] + ], + "pixdim": "(0.1, 1.0, 0.25)", + "plane_map": { + "0": "CORONAL" + }, + "primary_plane": "CORONAL" + } + } + ] + }, + "annotations": [ + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "0a8b3cfb-d6ff-427a-8b3e-a31410f10331", + "interpolate_algorithm": "linear-1.1", + "name": "mask1", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "0e845870-995b-4cb7-982e-741c1e54109e", + "interpolate_algorithm": "linear-1.1", + "name": "mask2", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "raster_layer": { + "dense_rle": [ + 0, + 6184, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 7736 + ], + "mask_annotation_ids_mapping": { + "0a8b3cfb-d6ff-427a-8b3e-a31410f10331": 1, + "0e845870-995b-4cb7-982e-741c1e54109e": 2 + }, + "total_pixels": 16384 + } + } + }, + "id": "1af4d613-c4c4-41cd-a53a-2e8905f90b95", + "name": "__raster_layer__", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 0, + 16 + ] + ], + "slot_names": [ + "0" + ] + } + ], + "properties": [] +} \ No newline at end of file diff --git a/e2e_tests/data/convert/nifti-multi-segment/from/sagittal_LPI_pixdim_0.1_0.2_0.5.json b/e2e_tests/data/convert/nifti-multi-segment/from/sagittal_LPI_pixdim_0.1_0.2_0.5.json new file mode 100644 index 000000000..b757dee96 --- /dev/null +++ b/e2e_tests/data/convert/nifti-multi-segment/from/sagittal_LPI_pixdim_0.1_0.2_0.5.json @@ -0,0 +1,259 @@ +{ + "version": "2.0", + "schema_ref": "https://darwin-public.s3.eu-west-1.amazonaws.com/darwin_json/2.0/schema.json", + "item": { + "name": "sagittal_LPI_pixdim_0.1_0.2_0.5.dcm", + "path": "/", + "source_info": { + "item_id": "0197ee1d-5920-c9f8-017f-987b38e38f5f", + "dataset": { + "name": "dicom_test_data_new", + "slug": "dicom_test_data_new", + "dataset_management_url": "https://darwin.v7labs.com/datasets/1856922/dataset-management" + }, + "team": { + "name": "V7 John", + "slug": "v7-john" + }, + "workview_url": "https://darwin.v7labs.com/workview?dataset=1856922&item=0197ee1d-5920-c9f8-017f-987b38e38f5f" + }, + "slots": [ + { + "type": "dicom", + "slot_name": "0", + "width": 128, + "height": 128, + "fps": null, + "thumbnail_url": "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/thumbnail?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "source_files": [ + { + "file_name": "sagittal_LPI_pixdim_0.1_0.2_0.5.dcm", + "url": "https://darwin.v7labs.com/api/v2/teams/v7-john/uploads/54adbf48-0129-44ea-978c-313aeb35627b?token=4ca42b77-ad16-42ce-82e1-e9c762085012" + } + ], + "frame_count": 16, + "frame_urls": [ + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/0?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/1?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/2?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/3?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/4?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/5?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/6?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/7?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/8?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/9?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/10?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/11?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/12?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/13?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/14?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/15?token=4ca42b77-ad16-42ce-82e1-e9c762085012" + ], + "metadata": { + "handler": "MONAI", + "shape": [ + 1, + 16, + 128, + 128 + ], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.16951377570626244557338024182864652772", + "affine": "[[-1.0, 0.0, 0.0, 15.0], [0.0, -0.1, 0.0, 0.0], [0.0, 0.0, -0.25, 0.0], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + [ + "0.0", + "0.0", + "1.0", + "0.0" + ], + [ + "-0.1", + "0.0", + "0.0", + "0.0" + ], + [ + "0.0", + "-0.25", + "0.0", + "0.0" + ], + [ + "0.0", + "0.0", + "0.0", + "1.0" + ] + ], + "pixdim": "(1.0, 0.1, 0.25)", + "plane_map": { + "0": "SAGITTAL" + }, + "primary_plane": "SAGITTAL" + } + } + ] + }, + "annotations": [ + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "2d12dc2e-5cc5-4bb7-89ce-5f010fc0f184", + "interpolate_algorithm": "linear-1.1", + "name": "mask1", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "97117be2-ae2e-4431-bcd3-5dd724121489", + "interpolate_algorithm": "linear-1.1", + "name": "mask2", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "raster_layer": { + "dense_rle": [ + 0, + 2088, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 11832 + ], + "mask_annotation_ids_mapping": { + "2d12dc2e-5cc5-4bb7-89ce-5f010fc0f184": 1, + "97117be2-ae2e-4431-bcd3-5dd724121489": 2 + }, + "total_pixels": 16384 + } + } + }, + "id": "c41d3017-793b-41f8-b9be-fa95d2e505ef", + "name": "__raster_layer__", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 0, + 16 + ] + ], + "slot_names": [ + "0" + ] + } + ], + "properties": [] +} \ No newline at end of file diff --git a/e2e_tests/data/convert/nifti-multi-segment/to/axial_RPI_pixdim_1.0_1.0_1.0/0/axial_RPI_pixdim_1.0_1.0_1_Segments_m.nii.gz b/e2e_tests/data/convert/nifti-multi-segment/to/axial_RPI_pixdim_1.0_1.0_1.0/0/axial_RPI_pixdim_1.0_1.0_1_Segments_m.nii.gz new file mode 100644 index 0000000000000000000000000000000000000000..3feaf827d5155849b4aaaaf0397a8882b1a76067 GIT binary patch literal 2510 zcmb2|=3oE;mj7>WUi3X|Ai$Qe-GHI`!x0vn4Q$2+&hAOfVcAMM+QS^J=C)dR&tH7P zEBW;IdcR*6_RV)&W!rPQ%%=D9`9kZLg}XOzKYhJy-@m%LeYN*@&;45;{(SGVwf7d6 zefc@>{XW@V>BoPrv%bpS#Y?@qWv<$7 z^?2-f^^W2C!Yv`06BplFE|zJtVwUwY)4pk1x|>mU~uJv59LhZ1@;OX5*Rrc02Ri5 As{jB1 literal 0 HcmV?d00001 diff --git a/e2e_tests/data/convert/nifti-multi-segment/to/axial_RPI_pixdim_1.0_1.0_1.0/0/axial_RPI_pixdim_1.0_1.0_1_mask1_m.nii.gz b/e2e_tests/data/convert/nifti-multi-segment/to/axial_RPI_pixdim_1.0_1.0_1.0/0/axial_RPI_pixdim_1.0_1.0_1_mask1_m.nii.gz new file mode 100644 index 0000000000000000000000000000000000000000..8a3ec61ae1ae99edf39aaf783a124b4649d7346f GIT binary patch literal 2469 zcmb2|=3oE;mj7>W?BzY=z{7UoaXQ1d1xZX?*Am#$5>(6*OobY|7bryL6@1j|^7G7@ zyFdKdF3FW!rN6(l>N)#7%IxiO{m;AXm;e6ryDsM5{b_gqSKm5k?EiV)+O6M<_r2d5 zW`68##V@@tJ`D_vOe`D%3Jy?)2j`Lh(_hWAT2dHjTK>hfZ<>^DQONfzioM;db}n9D zxaCU5#KpUo^JT__oRzKZUA)w-Tjr{5smJ3*S?^wC%jlX$Jz4Q?rL&ZHXt8_z;|w=t wn7MEZMj6P#JsKLLp@EhIN0Y>8k{C@Aqq$%-7YxE&kl84nvU^EX0wV_l0ONFBLI3~& literal 0 HcmV?d00001 diff --git a/e2e_tests/data/convert/nifti-multi-segment/to/axial_RPI_pixdim_1.0_1.0_1.0/0/axial_RPI_pixdim_1.0_1.0_1_mask2_m.nii.gz b/e2e_tests/data/convert/nifti-multi-segment/to/axial_RPI_pixdim_1.0_1.0_1.0/0/axial_RPI_pixdim_1.0_1.0_1_mask2_m.nii.gz new file mode 100644 index 0000000000000000000000000000000000000000..6952c3979256732ffa3470a301f2569d8976f640 GIT binary patch literal 2467 zcmb2|=3oE;mj7>W?&Uq?z{7UoaXQ1d1xZX?*Am#$5>(6*OobY`3nomEPI(zCGWXFD z_4@T^D^2U7W*5#~cQ<11y6?;0eo2eF{<}ne|NZTkKi{qX{(s)J&u1?0@y=dp_xyK^ z_x;|&oAP${Uwj%E7@1f&1QZ-F848?7{%?OZk1r=|#k0PBX@!?}OkBKcIrD7MRXZ22 zkGx}&_hiMpmj}{Xv);YP7Blaawp>+hwIOohEbCvhj`}`!>qFAo>y2srs0h|j9}Sk# lV8N9mN7Ke=+89k6qq$%-7Ysx$Xq?X~x8!X(djcZ|0|2foU^oB( literal 0 HcmV?d00001 diff --git a/e2e_tests/data/convert/nifti-multi-segment/to/coronal_LAS_pixdim_0.1_0.2_0.5/0/coronal_LAS_pixdim_0.1_0.2_0_Segments_m.nii.gz b/e2e_tests/data/convert/nifti-multi-segment/to/coronal_LAS_pixdim_0.1_0.2_0.5/0/coronal_LAS_pixdim_0.1_0.2_0_Segments_m.nii.gz new file mode 100644 index 0000000000000000000000000000000000000000..cf9b81479922cd6fced1e65ca2351a32d6aaba93 GIT binary patch literal 2472 zcmb2|=3oE;mj7?B?&UpXAix%&Zop6-5E#J3nr*;roT4J;pu=!^1H&_SB@V77+7G6r zpYEEh(e=JIY*Xf`@Z6AHx73$be!1R$?CZI$rR|qL?pSd=Rd)6FjnVhl@3s58d-Jz% zuRd4o+tv5aDoghFzn{hTWUD?$J%7G!?m4^r1ydOqnOHak6dW2x8KZ$Pni58H!DucR z%>|>mU^EvDl3c(nnBl!9J-sXRewx1hjD5d0=QI4aS5x?ZhiT)N+W$q% literal 0 HcmV?d00001 diff --git a/e2e_tests/data/convert/nifti-multi-segment/to/coronal_LAS_pixdim_0.1_0.2_0.5/0/coronal_LAS_pixdim_0.1_0.2_0_mask1_m.nii.gz b/e2e_tests/data/convert/nifti-multi-segment/to/coronal_LAS_pixdim_0.1_0.2_0.5/0/coronal_LAS_pixdim_0.1_0.2_0_mask1_m.nii.gz new file mode 100644 index 0000000000000000000000000000000000000000..062d845334ac95c2818584f5563a631b1f0d2c4a GIT binary patch literal 2447 zcmb2|=3oE;mj7?Bp5<*akYKnFCV9Ztrt-rInV7?pa~dbc9N56%_n1k{R8Wb1vfP$m zw@kjM^Zvbe{eWHD_ER<{EA^aeu6$gkwf4)>%=59^JkPteaUl1QZ+^7#NvG8KZ$Pni58H!DucR%>|>m zU^EvDzFhEtoi*vi>ZOyPxXOF;+Z+FWr2m&`$Nx&EPx0Fv;=a}XKXtC|$M65~FMk%- Uk=~m5(90BV;8DLNfsum&06qj%X#fBK literal 0 HcmV?d00001 diff --git a/e2e_tests/data/convert/nifti-multi-segment/to/coronal_LAS_pixdim_0.1_0.2_0.5/0/coronal_LAS_pixdim_0.1_0.2_0_mask2_m.nii.gz b/e2e_tests/data/convert/nifti-multi-segment/to/coronal_LAS_pixdim_0.1_0.2_0.5/0/coronal_LAS_pixdim_0.1_0.2_0_mask2_m.nii.gz new file mode 100644 index 0000000000000000000000000000000000000000..69127b8eb09f32ff08fb506473a5016eb7f5ca62 GIT binary patch literal 2447 zcmb2|=3oE;mj7?Bp5<*akYKnFCV9Ztrt-rInV7?pa~dbc9N56%_n1k{R8Wb1vYf}^ z?8_JCn|!H`XMQg6PwVxCCA&C31|OfjYRjeR%l4MvRkZD2d3FEWs;cw7<>$?#_Qw5P z@vZcJ+jEb?J8h5i_h+*I6?tB=GpGDAcN(XFfW9t>nM6k&V7AeJCMPlv(wMw@BG;b|_+S_E7f+|^YxDlZn?DM7`1<3(S+{ZwdOKCiO6;?2}E!U_%z42(=H90E{=Q{%Va zr(a0q&0AnGYxi1j0mGb)PbFjzpA{ByFWz3tsnn*sO=fZOj>@J-8Sl2~IUdI7?oa1AzoZt2 zJiGM!&-02?fAwttTQ=^?={prub^pJNf8=z8Ti}iwWgthCJ literal 0 HcmV?d00001 diff --git a/e2e_tests/data/convert/nifti-multi-segment/to/sagittal_LPI_pixdim_0.1_0.2_0.5/0/sagittal_LPI_pixdim_0.1_0.2_0_mask1_m.nii.gz b/e2e_tests/data/convert/nifti-multi-segment/to/sagittal_LPI_pixdim_0.1_0.2_0.5/0/sagittal_LPI_pixdim_0.1_0.2_0_mask1_m.nii.gz new file mode 100644 index 0000000000000000000000000000000000000000..c0dda9437b0c32c2515aa124079d09876b0c25a1 GIT binary patch literal 2491 zcmb2|=3oE;mj7>W9Q0*&#-e@6S2Huu=GZcSJaFKYzz3EHY z)}k_<^XKZ1+q^wCf8FVgXMb0{+4uhO!qqn;uYdcn@&5g@Rr~Aa+w1qYZ+-mofA#K& z`E~Qp+q@2seXoA~l;N>6U#l+7SbzKW&s&L4e?I%Rd|D|J3x|M$LjwaNl;NNy@PB_u z_O8n2G}H1krX4fn42#I+zUV+R9B#`f13An`Lt`{FMsvz&E*Q-Pqq$%-7YyQD@F2X= Nf5*vVs}dMF7yyU?YRv!u literal 0 HcmV?d00001 diff --git a/e2e_tests/data/convert/nifti-multi-segment/to/sagittal_LPI_pixdim_0.1_0.2_0.5/0/sagittal_LPI_pixdim_0.1_0.2_0_mask2_m.nii.gz b/e2e_tests/data/convert/nifti-multi-segment/to/sagittal_LPI_pixdim_0.1_0.2_0.5/0/sagittal_LPI_pixdim_0.1_0.2_0_mask2_m.nii.gz new file mode 100644 index 0000000000000000000000000000000000000000..c9c482017c37e54887b112070266ca26eed79d1b GIT binary patch literal 2489 zcmb2|=3oE;mj7>Wp7mvR#-e@6S2Huu=GZb$G2`Ns{KXK{y z)l;99{hw7|w|RSP{=Cy0&wj6Zv+w@nWvh2?p7-`)^8Wp^zt;7h-#`8M;ai2@|DV;n z=D+`Z{=KiO*Zn-Xxv0mmc<;QNGcUiD?JJ9@+_&>@=4mTNCKe6>1&0O(Oh%(f$N&4Q zO!>2{Ry^z5w`}9*TN4*YeO|DvIqThvY$@yYvX;b3#?HoKJf?-CB3R>LG+0K11y>#& gO&gE4y=7P~&K>J* Date: Fri, 25 Jul 2025 14:19:09 +0200 Subject: [PATCH 2/5] Add a full cycle nifti e2e test --- e2e_tests/cli/test_full_cycle.py | 103 ++++++- .../axial_RPI_pixdim_1.0_1.0_1.0.json | 259 ++++++++++++++++++ .../coronal_LAS_pixdim_0.1_0.2_0.5.json | 259 ++++++++++++++++++ .../sagittal_LPI_pixdim_0.1_0.2_0.5.json | 259 ++++++++++++++++++ e2e_tests/helpers.py | 2 +- e2e_tests/objects.py | 119 ++++++++ 6 files changed, 999 insertions(+), 2 deletions(-) create mode 100644 e2e_tests/data/import/nifti_multi_segment/axial_RPI_pixdim_1.0_1.0_1.0.json create mode 100644 e2e_tests/data/import/nifti_multi_segment/coronal_LAS_pixdim_0.1_0.2_0.5.json create mode 100644 e2e_tests/data/import/nifti_multi_segment/sagittal_LPI_pixdim_0.1_0.2_0.5.json diff --git a/e2e_tests/cli/test_full_cycle.py b/e2e_tests/cli/test_full_cycle.py index 09cad16c9..c8105255a 100644 --- a/e2e_tests/cli/test_full_cycle.py +++ b/e2e_tests/cli/test_full_cycle.py @@ -1,8 +1,9 @@ import os import shutil +import time from pathlib import Path -from e2e_tests.helpers import assert_cli, run_cli_command, export_release +from e2e_tests.helpers import SERVER_WAIT_TIME, assert_cli, run_cli_command, export_release from e2e_tests.objects import E2EDataset, ConfigValues from e2e_tests.cli.test_import import compare_annotations_export from e2e_tests.cli.test_push import extract_and_push @@ -125,6 +126,106 @@ def test_full_cycle_images( ) +def test_full_cycle_nifti( + local_dataset: E2EDataset, + config_values: ConfigValues, +): + """ + This test performs the following steps: + - 1: Registers a set of DICOM files from external storage to a dataset + - 2: Imports mask annotations + - 3: Creates and pulls a release of the dataset + - 4: Deletes all items from the dataset + - 5: Pushes and imports the pulled files & annotations to the dataset + - 6: Deletes locally pulled copies of the dataset files + - 7: Creates and pulls a new release of the dataset + - 8: Assert that the pulled data is as expected + + It is designed to catch errors that may arise from changes to exported Darwin JSON + """ + item_type = "multi_segment_nifti" + annotation_format = "darwin" + first_release_name = "first_release" + second_release_name = "second_release" + pull_dir = Path( + f"{Path.home()}/.darwin/datasets/{config_values.team_slug}/{local_dataset.slug}" + ) + annotations_import_dir = ( + Path(__file__).parents[1] + / "data" + / "import" + / "nifti_multi_segment" + ) + + expected_filepaths = [ + f"{pull_dir}/images/axial_RPI_pixdim_1.0_1.0_1.0.dcm", + f"{pull_dir}/images/coronal_LAS_pixdim_0.1_0.2_0.5.dcm", + f"{pull_dir}/images/sagittal_LPI_pixdim_0.1_0.2_0.5.dcm", + ] + + # Populate the dataset with items and annotations + local_dataset.register_read_only_items(config_values, item_type) + time.sleep(SERVER_WAIT_TIME) + + result = run_cli_command( + f"darwin dataset import {local_dataset.name} {annotation_format} {annotations_import_dir} --yes" + ) + assert_cli(result, 0) + + # Pull a first release of the dataset + original_release = export_release( + annotation_format, local_dataset, config_values, release_name=first_release_name + ) + result = run_cli_command( + f"darwin dataset pull {local_dataset.name}:{original_release.name}" + ) + assert_cli(result, 0) + + # Delete all items in the dataset + local_dataset.delete_items(config_values) + + # Push and import the pulled files and annotations to the dataset + result = run_cli_command( + f"darwin dataset push {local_dataset.name} {pull_dir}/images --preserve-folders" + ) + assert_cli(result, 0) + # we are uploading 3 DICOM images which need to be extracted asynchronously + time.sleep(SERVER_WAIT_TIME * 3) + + result = run_cli_command( + f"darwin dataset import {local_dataset.name} {annotation_format} {pull_dir}/releases/{first_release_name}/annotations --yes" + ) + assert_cli(result, 0) + + # Delete local copies of the dataset files for the dataset + shutil.rmtree(f"{pull_dir}/images") + + # Pull a second release of the dataset + new_release = export_release( + annotation_format, + local_dataset, + config_values, + release_name=second_release_name, + ) + result = run_cli_command( + f"darwin dataset pull {local_dataset.name}:{new_release.name}" + ) + assert_cli(result, 0) + + # Check that all expected files have been downloaded + all_filepaths = list(pull_dir.rglob("*")) + for expected_file in expected_filepaths: + assert Path(expected_file) in all_filepaths + + # Check that all downloaded annotations are as expected + compare_annotations_export( + Path(f"{pull_dir}/releases/{first_release_name}/annotations"), + Path(f"{pull_dir}/releases/{second_release_name}/annotations"), + item_type, + unzip=False, + ) + + def test_full_cycle_video( local_dataset: E2EDataset, config_values: ConfigValues, diff --git a/e2e_tests/data/import/nifti_multi_segment/axial_RPI_pixdim_1.0_1.0_1.0.json b/e2e_tests/data/import/nifti_multi_segment/axial_RPI_pixdim_1.0_1.0_1.0.json new file mode 100644 index 000000000..7c64e0c0b --- /dev/null +++ b/e2e_tests/data/import/nifti_multi_segment/axial_RPI_pixdim_1.0_1.0_1.0.json @@ -0,0 +1,259 @@ +{ + "version": "2.0", + "schema_ref": "https://darwin-public.s3.eu-west-1.amazonaws.com/darwin_json/2.0/schema.json", + "item": { + "name": "axial_RPI_pixdim_1.0_1.0_1.0.dcm", + "path": "/", + "source_info": { + "item_id": "0197ee1d-591e-a61b-82e2-e6f1e5c30cf2", + "dataset": { + "name": "dicom_test_data_new", + "slug": "dicom_test_data_new", + "dataset_management_url": "https://darwin.v7labs.com/datasets/1856922/dataset-management" + }, + "team": { + "name": "V7 John", + "slug": "v7-john" + }, + "workview_url": "https://darwin.v7labs.com/workview?dataset=1856922&item=0197ee1d-591e-a61b-82e2-e6f1e5c30cf2" + }, + "slots": [ + { + "type": "dicom", + "slot_name": "0", + "width": 128, + "height": 128, + "fps": null, + "thumbnail_url": "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/thumbnail?token=590de404-3490-4dde-90f9-d13136b0d14f", + "source_files": [ + { + "file_name": "axial_RPI_pixdim_1.0_1.0_1.0.dcm", + "url": "https://darwin.v7labs.com/api/v2/teams/v7-john/uploads/d4f4e7cd-e8a8-407f-9ff3-0a1f3298c84c?token=590de404-3490-4dde-90f9-d13136b0d14f" + } + ], + "frame_count": 16, + "frame_urls": [ + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/0?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/1?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/2?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/3?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/4?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/5?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/6?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/7?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/8?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/9?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/10?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/11?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/12?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/13?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/14?token=590de404-3490-4dde-90f9-d13136b0d14f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/243d7c36-d767-4e3c-adb0-44324ebd14fe/sections/15?token=590de404-3490-4dde-90f9-d13136b0d14f" + ], + "metadata": { + "handler": "MONAI", + "shape": [ + 1, + 128, + 128, + 16 + ], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.37180825650614764423282910493086149224", + "affine": "[[-1.0, 0.0, 0.0, 127.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, -1.0, 15.0], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + [ + "1.0", + "0.0", + "0.0", + "0.0" + ], + [ + "0.0", + "-1.0", + "0.0", + "0.0" + ], + [ + "0.0", + "0.0", + "1.0", + "0.0" + ], + [ + "0.0", + "0.0", + "0.0", + "1.0" + ] + ], + "pixdim": "(1.0, 1.0, 1.0)", + "plane_map": { + "0": "AXIAL" + }, + "primary_plane": "AXIAL" + } + } + ] + }, + "annotations": [ + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "02c693fa-97f5-4a3c-9c45-e1d9eebb0731", + "interpolate_algorithm": "linear-1.1", + "name": "mask1", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "d212f8a6-8e09-4901-a44b-77745626edc9", + "interpolate_algorithm": "linear-1.1", + "name": "mask2", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "raster_layer": { + "dense_rle": [ + 0, + 2104, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 11816 + ], + "mask_annotation_ids_mapping": { + "02c693fa-97f5-4a3c-9c45-e1d9eebb0731": 1, + "d212f8a6-8e09-4901-a44b-77745626edc9": 2 + }, + "total_pixels": 16384 + } + } + }, + "id": "a15c3b3e-89af-4733-b6c7-10f01e2c0b57", + "name": "__raster_layer__", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 0, + 16 + ] + ], + "slot_names": [ + "0" + ] + } + ], + "properties": [] +} \ No newline at end of file diff --git a/e2e_tests/data/import/nifti_multi_segment/coronal_LAS_pixdim_0.1_0.2_0.5.json b/e2e_tests/data/import/nifti_multi_segment/coronal_LAS_pixdim_0.1_0.2_0.5.json new file mode 100644 index 000000000..e42e9e8d3 --- /dev/null +++ b/e2e_tests/data/import/nifti_multi_segment/coronal_LAS_pixdim_0.1_0.2_0.5.json @@ -0,0 +1,259 @@ +{ + "version": "2.0", + "schema_ref": "https://darwin-public.s3.eu-west-1.amazonaws.com/darwin_json/2.0/schema.json", + "item": { + "name": "coronal_LAS_pixdim_0.1_0.2_0.5.dcm", + "path": "/", + "source_info": { + "item_id": "0197ee1d-591e-7d19-bb01-65d27fb0bcdd", + "dataset": { + "name": "dicom_test_data_new", + "slug": "dicom_test_data_new", + "dataset_management_url": "https://darwin.v7labs.com/datasets/1856922/dataset-management" + }, + "team": { + "name": "V7 John", + "slug": "v7-john" + }, + "workview_url": "https://darwin.v7labs.com/workview?dataset=1856922&item=0197ee1d-591e-7d19-bb01-65d27fb0bcdd" + }, + "slots": [ + { + "type": "dicom", + "slot_name": "0", + "width": 128, + "height": 128, + "fps": null, + "thumbnail_url": "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/thumbnail?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "source_files": [ + { + "file_name": "coronal_LAS_pixdim_0.1_0.2_0.5.dcm", + "url": "https://darwin.v7labs.com/api/v2/teams/v7-john/uploads/bbf2147d-e328-4a93-a624-90f9c474a071?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f" + } + ], + "frame_count": 16, + "frame_urls": [ + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/0?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/1?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/2?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/3?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/4?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/5?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/6?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/7?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/8?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/9?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/10?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/11?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/12?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/13?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/14?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/b33547f6-c281-4766-97cf-1623f00353f5/sections/15?token=971b08d7-a0d7-4d95-a22f-f1f7429b207f" + ], + "metadata": { + "handler": "MONAI", + "shape": [ + 1, + 128, + 16, + 128 + ], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.10392093638286046303269310577715221690", + "affine": "[[-0.1, 0.0, 0.0, 0.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, -0.25, 31.75], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + [ + "-0.1", + "0.0", + "0.0", + "0.0" + ], + [ + "0.0", + "0.0", + "-1.0", + "0.0" + ], + [ + "0.0", + "0.25", + "0.0", + "0.0" + ], + [ + "0.0", + "0.0", + "0.0", + "1.0" + ] + ], + "pixdim": "(0.1, 1.0, 0.25)", + "plane_map": { + "0": "CORONAL" + }, + "primary_plane": "CORONAL" + } + } + ] + }, + "annotations": [ + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "0a8b3cfb-d6ff-427a-8b3e-a31410f10331", + "interpolate_algorithm": "linear-1.1", + "name": "mask1", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "0e845870-995b-4cb7-982e-741c1e54109e", + "interpolate_algorithm": "linear-1.1", + "name": "mask2", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "raster_layer": { + "dense_rle": [ + 0, + 6184, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 7736 + ], + "mask_annotation_ids_mapping": { + "0a8b3cfb-d6ff-427a-8b3e-a31410f10331": 1, + "0e845870-995b-4cb7-982e-741c1e54109e": 2 + }, + "total_pixels": 16384 + } + } + }, + "id": "1af4d613-c4c4-41cd-a53a-2e8905f90b95", + "name": "__raster_layer__", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 0, + 16 + ] + ], + "slot_names": [ + "0" + ] + } + ], + "properties": [] +} \ No newline at end of file diff --git a/e2e_tests/data/import/nifti_multi_segment/sagittal_LPI_pixdim_0.1_0.2_0.5.json b/e2e_tests/data/import/nifti_multi_segment/sagittal_LPI_pixdim_0.1_0.2_0.5.json new file mode 100644 index 000000000..b757dee96 --- /dev/null +++ b/e2e_tests/data/import/nifti_multi_segment/sagittal_LPI_pixdim_0.1_0.2_0.5.json @@ -0,0 +1,259 @@ +{ + "version": "2.0", + "schema_ref": "https://darwin-public.s3.eu-west-1.amazonaws.com/darwin_json/2.0/schema.json", + "item": { + "name": "sagittal_LPI_pixdim_0.1_0.2_0.5.dcm", + "path": "/", + "source_info": { + "item_id": "0197ee1d-5920-c9f8-017f-987b38e38f5f", + "dataset": { + "name": "dicom_test_data_new", + "slug": "dicom_test_data_new", + "dataset_management_url": "https://darwin.v7labs.com/datasets/1856922/dataset-management" + }, + "team": { + "name": "V7 John", + "slug": "v7-john" + }, + "workview_url": "https://darwin.v7labs.com/workview?dataset=1856922&item=0197ee1d-5920-c9f8-017f-987b38e38f5f" + }, + "slots": [ + { + "type": "dicom", + "slot_name": "0", + "width": 128, + "height": 128, + "fps": null, + "thumbnail_url": "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/thumbnail?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "source_files": [ + { + "file_name": "sagittal_LPI_pixdim_0.1_0.2_0.5.dcm", + "url": "https://darwin.v7labs.com/api/v2/teams/v7-john/uploads/54adbf48-0129-44ea-978c-313aeb35627b?token=4ca42b77-ad16-42ce-82e1-e9c762085012" + } + ], + "frame_count": 16, + "frame_urls": [ + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/0?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/1?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/2?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/3?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/4?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/5?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/6?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/7?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/8?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/9?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/10?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/11?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/12?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/13?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/14?token=4ca42b77-ad16-42ce-82e1-e9c762085012", + "https://darwin.v7labs.com/api/v2/teams/v7-john/files/c160652a-9d74-4a27-91f5-158bd68eab2c/sections/15?token=4ca42b77-ad16-42ce-82e1-e9c762085012" + ], + "metadata": { + "handler": "MONAI", + "shape": [ + 1, + 16, + 128, + 128 + ], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.16951377570626244557338024182864652772", + "affine": "[[-1.0, 0.0, 0.0, 15.0], [0.0, -0.1, 0.0, 0.0], [0.0, 0.0, -0.25, 0.0], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + [ + "0.0", + "0.0", + "1.0", + "0.0" + ], + [ + "-0.1", + "0.0", + "0.0", + "0.0" + ], + [ + "0.0", + "-0.25", + "0.0", + "0.0" + ], + [ + "0.0", + "0.0", + "0.0", + "1.0" + ] + ], + "pixdim": "(1.0, 0.1, 0.25)", + "plane_map": { + "0": "SAGITTAL" + }, + "primary_plane": "SAGITTAL" + } + } + ] + }, + "annotations": [ + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "2d12dc2e-5cc5-4bb7-89ce-5f010fc0f184", + "interpolate_algorithm": "linear-1.1", + "name": "mask1", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "mask": {} + } + }, + "global_sub_types": {}, + "id": "97117be2-ae2e-4431-bcd3-5dd724121489", + "interpolate_algorithm": "linear-1.1", + "name": "mask2", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 15, + 16 + ] + ], + "slot_names": [ + "0" + ] + }, + { + "frames": { + "15": { + "keyframe": true, + "raster_layer": { + "dense_rle": [ + 0, + 2088, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 1, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 96, + 2, + 32, + 0, + 11832 + ], + "mask_annotation_ids_mapping": { + "2d12dc2e-5cc5-4bb7-89ce-5f010fc0f184": 1, + "97117be2-ae2e-4431-bcd3-5dd724121489": 2 + }, + "total_pixels": 16384 + } + } + }, + "id": "c41d3017-793b-41f8-b9be-fa95d2e505ef", + "name": "__raster_layer__", + "only_keyframes": true, + "properties": [], + "ranges": [ + [ + 0, + 16 + ] + ], + "slot_names": [ + "0" + ] + } + ], + "properties": [] +} \ No newline at end of file diff --git a/e2e_tests/helpers.py b/e2e_tests/helpers.py index 4346339a7..31d6ef186 100644 --- a/e2e_tests/helpers.py +++ b/e2e_tests/helpers.py @@ -170,7 +170,7 @@ def wait_until_items_processed( Waits until all items in a dataset have finished processing before attempting to upload annotations. Raises a `TimeoutError` if the process takes longer than the specified timeout. """ - sleep_duration = 10 + sleep_duration = SERVER_WAIT_TIME api_key = config_values.api_key team_slug = config_values.team_slug base_url = config_values.server diff --git a/e2e_tests/objects.py b/e2e_tests/objects.py index ab405af60..6d1877473 100644 --- a/e2e_tests/objects.py +++ b/e2e_tests/objects.py @@ -467,6 +467,125 @@ def get_read_only_registration_payload( "name": "multi_slotted_dicom_item", }, ], + "multi_segment_nifti": [ + { + "path": path or "/", + "name": "axial_RPI_pixdim_1.0_1.0_1.0.dcm", + "slots": [ + { + "slot_name": "0", + "type": "dicom", + "storage_key": "darwin-py/dicoms/axial_RPI_pixdim_1.0_1.0_1.0.dcm", + "storage_thumbnail_key": "data/darwin-py/dicoms/axial_RPI_pixdim_1.0_1.0_1.0.dcm/uploads/a176ce30-4a3e-48db-a33a-01af311726ee/thumbnails/000000000.jpg", + "file_name": "axial_RPI_pixdim_1.0_1.0_1.0.dcm", + "sections": [ + { + "section_index": i + 1, + "height": 128, + "width": 128, + "storage_hq_key": f"data/darwin-py/dicoms/axial_RPI_pixdim_1.0_1.0_1.0.dcm/uploads/a176ce30-4a3e-48db-a33a-01af311726ee/hq_sections/{i:09}.png", + "storage_lq_key": f"data/darwin-py/dicoms/axial_RPI_pixdim_1.0_1.0_1.0.dcm/uploads/a176ce30-4a3e-48db-a33a-01af311726ee/lq_sections/{i:09}.png", + } + for i in range(16) + ], + "metadata": { + "handler": "MONAI", + "shape": [1, 128, 128, 16], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.37180825650614764423282910493086149224", + "affine": "[[-1.0, 0.0, 0.0, 127.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, -1.0, 15.0], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + ["1.0", "0.0", "0.0", "0.0"], + ["0.0", "-1.0", "0.0", "0.0"], + ["0.0", "0.0", "1.0", "0.0"], + ["0.0", "0.0", "0.0", "1.0"], + ], + "pixdim": "(1.0, 1.0, 1.0)", + "plane_map": {"0": "AXIAL"}, + "primary_plane": "AXIAL", + }, + }, + ], + }, + { + "path": path or "/", + "name": "coronal_LAS_pixdim_0.1_0.2_0.5.dcm", + "slots": [ + { + "slot_name": "0", + "type": "dicom", + "storage_key": "darwin-py/dicoms/coronal_LAS_pixdim_0.1_0.2_0.5.dcm", + "storage_thumbnail_key": "data/darwin-py/dicoms/coronal_LAS_pixdim_0.1_0.2_0.5.dcm/uploads/120c999b-230e-4bdd-a833-93fe6b3a3a30/thumbnails/000000000.jpg", + "file_name": "coronal_LAS_pixdim_0.1_0.2_0.5.dcm", + "sections": [ + { + "section_index": i + 1, + "height": 128, + "width": 128, + "storage_hq_key": f"data/darwin-py/dicoms/coronal_LAS_pixdim_0.1_0.2_0.5.dcm/uploads/120c999b-230e-4bdd-a833-93fe6b3a3a30/hq_sections/{i:09}.png", + "storage_lq_key": f"data/darwin-py/dicoms/coronal_LAS_pixdim_0.1_0.2_0.5.dcm/uploads/120c999b-230e-4bdd-a833-93fe6b3a3a30/lq_sections/{i:09}.png", + } + for i in range(16) + ], + "metadata": { + "handler": "MONAI", + "shape": [1, 128, 16, 128], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.10392093638286046303269310577715221690", + "affine": "[[-0.1, 0.0, 0.0, 0.0], [0.0, -1.0, 0.0, 0.0], [0.0, 0.0, -0.25, 31.75], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + ["-0.1", "0.0", "0.0", "0.0"], + ["0.0", "0.0", "-1.0", "0.0"], + ["0.0", "0.25", "0.0", "0.0"], + ["0.0", "0.0", "0.0", "1.0"], + ], + "pixdim": "(0.1, 1.0, 0.25)", + "plane_map": {"0": "CORONAL"}, + "primary_plane": "CORONAL", + }, + }, + ], + }, + { + "path": path or "/", + "name": "sagittal_LPI_pixdim_0.1_0.2_0.5.dcm", + "slots": [ + { + "slot_name": "0", + "type": "dicom", + "storage_key": "darwin-py/dicoms/sagittal_LPI_pixdim_0.1_0.2_0.5.dcm", + "storage_thumbnail_key": "data/darwin-py/dicoms/sagittal_LPI_pixdim_0.1_0.2_0.5.dcm/uploads/8d69ef65-db0f-45ab-827e-23faa4871519/thumbnails/000000000.jpg", + "file_name": "sagittal_LPI_pixdim_0.1_0.2_0.5.dcm", + "sections": [ + { + "section_index": i + 1, + "height": 128, + "width": 128, + "storage_hq_key": f"data/darwin-py/dicoms/sagittal_LPI_pixdim_0.1_0.2_0.5.dcm/uploads/8d69ef65-db0f-45ab-827e-23faa4871519/hq_sections/{i:09}.png", + "storage_lq_key": f"data/darwin-py/dicoms/sagittal_LPI_pixdim_0.1_0.2_0.5.dcm/uploads/8d69ef65-db0f-45ab-827e-23faa4871519/lq_sections/{i:09}.png", + } + for i in range(16) + ], + "metadata": { + "handler": "MONAI", + "shape": [1, 16, 128, 128], + "SeriesInstanceUID": "1.2.826.0.1.3680043.8.498.16951377570626244557338024182864652772", + "affine": "[[-1.0, 0.0, 0.0, 15.0], [0.0, -0.1, 0.0, 0.0], [0.0, 0.0, -0.25, 0.0], [0.0, 0.0, 0.0, 1.0]]", + "colorspace": "RG16", + "original_affine": [ + ["0.0", "0.0", "1.0", "0.0"], + ["-0.1", "0.0", "0.0", "0.0"], + ["0.0", "-0.25", "0.0", "0.0"], + ["0.0", "0.0", "0.0", "1.0"], + ], + "pixdim": "(1.0, 0.1, 0.25)", + "plane_map": {"0": "SAGITTAL"}, + "primary_plane": "SAGITTAL", + }, + }, + ], + }, + ], } return { "items": items[item_type], # type: ignore From dff6a300b72eaf4be99b5da1812247c662f7819c Mon Sep 17 00:00:00 2001 From: Valentin Vikhorev Date: Fri, 25 Jul 2025 14:24:39 +0200 Subject: [PATCH 3/5] black formatting --- e2e_tests/cli/test_full_cycle.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/e2e_tests/cli/test_full_cycle.py b/e2e_tests/cli/test_full_cycle.py index c8105255a..268e737db 100644 --- a/e2e_tests/cli/test_full_cycle.py +++ b/e2e_tests/cli/test_full_cycle.py @@ -3,7 +3,12 @@ import time from pathlib import Path -from e2e_tests.helpers import SERVER_WAIT_TIME, assert_cli, run_cli_command, export_release +from e2e_tests.helpers import ( + SERVER_WAIT_TIME, + assert_cli, + run_cli_command, + export_release, +) from e2e_tests.objects import E2EDataset, ConfigValues from e2e_tests.cli.test_import import compare_annotations_export from e2e_tests.cli.test_push import extract_and_push @@ -151,10 +156,7 @@ def test_full_cycle_nifti( f"{Path.home()}/.darwin/datasets/{config_values.team_slug}/{local_dataset.slug}" ) annotations_import_dir = ( - Path(__file__).parents[1] - / "data" - / "import" - / "nifti_multi_segment" + Path(__file__).parents[1] / "data" / "import" / "nifti_multi_segment" ) expected_filepaths = [ From 45a8b2658a7173bf1c8eb8f24b89d546071993fb Mon Sep 17 00:00:00 2001 From: Valentin Vikhorev Date: Fri, 25 Jul 2025 17:19:16 +0200 Subject: [PATCH 4/5] Include conversion to nifti in the full cycle e2e test --- darwin/cli_functions.py | 4 +- darwin/exporter/formats/nifti.py | 2 +- e2e_tests/cli/test_convert.py | 35 +------------- e2e_tests/cli/test_full_cycle.py | 50 +++++++++++++------- e2e_tests/data/push/multi_segment_nifti.zip | Bin 0 -> 30019 bytes e2e_tests/helpers.py | 33 +++++++++++++ 6 files changed, 71 insertions(+), 53 deletions(-) create mode 100644 e2e_tests/data/push/multi_segment_nifti.zip diff --git a/darwin/cli_functions.py b/darwin/cli_functions.py index 95b1daf3f..5f04c2ab8 100644 --- a/darwin/cli_functions.py +++ b/darwin/cli_functions.py @@ -1185,7 +1185,9 @@ def dataset_convert( output_dir = Path(output_dir) output_dir.mkdir(parents=True, exist_ok=True) - export_annotations(parser, [annotations_path], output_dir) + export_annotations( + parser, [annotations_path], output_dir, split_sequences=(format != "nifti") + ) except ExporterNotFoundError: _error( f"Unsupported export format: {format}, currently supported: {export_formats}" diff --git a/darwin/exporter/formats/nifti.py b/darwin/exporter/formats/nifti.py index 396f49743..4b9b89ca1 100644 --- a/darwin/exporter/formats/nifti.py +++ b/darwin/exporter/formats/nifti.py @@ -93,7 +93,7 @@ def export( try: medical_metadata = slot.metadata legacy = not medical_metadata.get("handler") == "MONAI" # type: ignore - plane_map = medical_metadata.get("plane_map", {slot_name: "AXIAL"}) + plane_map = medical_metadata.get("plane_map") or {slot_name: "AXIAL"} primary_plane = medical_metadata.get( "primary_plane", plane_map.get(slot_name, "AXIAL") ) diff --git a/e2e_tests/cli/test_convert.py b/e2e_tests/cli/test_convert.py index 456af1544..2cfe32e5b 100644 --- a/e2e_tests/cli/test_convert.py +++ b/e2e_tests/cli/test_convert.py @@ -6,7 +6,7 @@ import pytest import xml.etree.ElementTree as ET -from e2e_tests.helpers import assert_cli, run_cli_command +from e2e_tests.helpers import assert_cli, compare_directories, run_cli_command class TestExportCli: @@ -17,37 +17,6 @@ class TestExportCli: def config(self) -> None: assert self.data_path.exists(), "Data path does not exist, tests cannot run" - def compare_directories(self, path: Path, expected_path: Path) -> None: - """ - Compare two directories recursively - """ - assert path.exists() and expected_path.exists() - assert path.is_dir() and expected_path.is_dir() - - for file in path.iterdir(): - if file.is_dir(): - # Recursively compare directories - self.compare_directories(file, expected_path / file.name) - else: - if file.name.startswith("."): - # Ignore hidden files - continue - - # Compare files - with file.open("rb") as f: - content = f.read() - - with Path(expected_path / file.name).open("rb") as f: - expected_content = f.read() - - if content != expected_content: - print(f"Expected file: {expected_path / file.name}") - print(f"Expected Content: \n{expected_content}") - print("---------------------") - print(f"Actual file: {file}") - print(f"Actual Content: \n{content}") - assert False, f"File {file} does not match expected file" - @pytest.mark.parametrize( "format, input_path, expectation_path", [ @@ -117,7 +86,7 @@ def test_darwin_convert( ) self.patch_format(format, tmp_path) assert_cli(result, 0) - self.compare_directories(expectation_path, tmp_path) + compare_directories(expectation_path, tmp_path) def patch_format(self, format: str, path: Path) -> None: """ diff --git a/e2e_tests/cli/test_full_cycle.py b/e2e_tests/cli/test_full_cycle.py index 268e737db..278fdcfcc 100644 --- a/e2e_tests/cli/test_full_cycle.py +++ b/e2e_tests/cli/test_full_cycle.py @@ -6,6 +6,7 @@ from e2e_tests.helpers import ( SERVER_WAIT_TIME, assert_cli, + compare_directories, run_cli_command, export_release, ) @@ -148,8 +149,8 @@ def test_full_cycle_nifti( It is designed to catch errors that may arise from changes to exported Darwin JSON """ - item_type = "multi_segment_nifti" - annotation_format = "darwin" + expected_push_dir = "multi_segment_nifti" + annotation_format = "nifti" first_release_name = "first_release" second_release_name = "second_release" pull_dir = Path( @@ -158,30 +159,37 @@ def test_full_cycle_nifti( annotations_import_dir = ( Path(__file__).parents[1] / "data" / "import" / "nifti_multi_segment" ) - - expected_filepaths = [ - f"{pull_dir}/images/axial_RPI_pixdim_1.0_1.0_1.0.dcm", - f"{pull_dir}/images/coronal_LAS_pixdim_0.1_0.2_0.5.dcm", - f"{pull_dir}/images/sagittal_LPI_pixdim_0.1_0.2_0.5.dcm", + source_files = [ + "axial_RPI_pixdim_1.0_1.0_1.0", + "coronal_LAS_pixdim_0.1_0.2_0.5", + "sagittal_LPI_pixdim_0.1_0.2_0.5", ] + expected_filepaths = [f"{pull_dir}/images/{file}.dcm" for file in source_files] + # Populate the dataset with items and annotations - local_dataset.register_read_only_items(config_values, item_type) - time.sleep(SERVER_WAIT_TIME) + push_dir = Path(__file__).parents[1] / "data" / "push" / f"{expected_push_dir}.zip" + items = extract_and_push(push_dir, local_dataset, config_values, expected_push_dir) + assert len(items) == 3 + time.sleep(SERVER_WAIT_TIME * 3) result = run_cli_command( - f"darwin dataset import {local_dataset.name} {annotation_format} {annotations_import_dir} --yes" + f"darwin dataset import {local_dataset.name} darwin {annotations_import_dir}" ) assert_cli(result, 0) # Pull a first release of the dataset original_release = export_release( - annotation_format, local_dataset, config_values, release_name=first_release_name + "darwin", local_dataset, config_values, release_name=first_release_name ) result = run_cli_command( f"darwin dataset pull {local_dataset.name}:{original_release.name}" ) assert_cli(result, 0) + result = run_cli_command( + f"darwin dataset convert {local_dataset.name}:{original_release.name} {annotation_format}" + ) + assert_cli(result, 0) # Delete all items in the dataset local_dataset.delete_items(config_values) @@ -195,7 +203,7 @@ def test_full_cycle_nifti( time.sleep(SERVER_WAIT_TIME * 3) result = run_cli_command( - f"darwin dataset import {local_dataset.name} {annotation_format} {pull_dir}/releases/{first_release_name}/annotations --yes" + f"darwin dataset import {local_dataset.name} darwin {pull_dir}/releases/{first_release_name}/annotations" ) assert_cli(result, 0) @@ -204,7 +212,7 @@ def test_full_cycle_nifti( # Pull a second release of the dataset new_release = export_release( - annotation_format, + "darwin", local_dataset, config_values, release_name=second_release_name, @@ -213,6 +221,10 @@ def test_full_cycle_nifti( f"darwin dataset pull {local_dataset.name}:{new_release.name}" ) assert_cli(result, 0) + result = run_cli_command( + f"darwin dataset convert {local_dataset.name}:{new_release.name} {annotation_format}" + ) + assert_cli(result, 0) # Check that all expected files have been downloaded all_filepaths = list(pull_dir.rglob("*")) @@ -220,11 +232,13 @@ def test_full_cycle_nifti( assert Path(expected_file) in all_filepaths # Check that all downloaded annotations are as expected - compare_annotations_export( - Path(f"{pull_dir}/releases/{first_release_name}/annotations"), - Path(f"{pull_dir}/releases/{second_release_name}/annotations"), - item_type, - unzip=False, + compare_directories( + Path( + f"{pull_dir}/releases/{first_release_name}/other_formats/{annotation_format}" + ), + Path( + f"{pull_dir}/releases/{second_release_name}/other_formats/{annotation_format}" + ), ) diff --git a/e2e_tests/data/push/multi_segment_nifti.zip b/e2e_tests/data/push/multi_segment_nifti.zip new file mode 100644 index 0000000000000000000000000000000000000000..5ec5f39648562e3bf01a0816e19a36622532b6ba GIT binary patch literal 30019 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 A0ssI2 literal 0 HcmV?d00001 diff --git a/e2e_tests/helpers.py b/e2e_tests/helpers.py index 31d6ef186..493e957b7 100644 --- a/e2e_tests/helpers.py +++ b/e2e_tests/helpers.py @@ -1,3 +1,4 @@ +from pathlib import Path from subprocess import run from time import sleep from typing import Optional, Union, Sequence @@ -295,3 +296,35 @@ def exclude_annotations_of_type( for annotation in annotations if annotation.annotation_class.annotation_type != annotation_type ] + + +def compare_directories(path: Path, expected_path: Path) -> None: + """ + Compare two directories recursively + """ + assert path.exists() and expected_path.exists() + assert path.is_dir() and expected_path.is_dir() + + for file in path.iterdir(): + if file.is_dir(): + # Recursively compare directories + compare_directories(file, expected_path / file.name) + else: + if file.name.startswith("."): + # Ignore hidden files + continue + + # Compare files + with file.open("rb") as f: + content = f.read() + + with Path(expected_path / file.name).open("rb") as f: + expected_content = f.read() + + if content != expected_content: + print(f"Expected file: {expected_path / file.name}") + print(f"Expected Content: \n{expected_content}") + print("---------------------") + print(f"Actual file: {file}") + print(f"Actual Content: \n{content}") + assert False, f"File {file} does not match expected file" From 1933f1d3675dea59fcaf99ae8466dce8c28a55b6 Mon Sep 17 00:00:00 2001 From: Valentin Vikhorev Date: Thu, 31 Jul 2025 16:51:37 +0200 Subject: [PATCH 5/5] Remove convert step from full cycle nifti e2e --- e2e_tests/cli/test_full_cycle.py | 39 +++++++++++--------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/e2e_tests/cli/test_full_cycle.py b/e2e_tests/cli/test_full_cycle.py index 278fdcfcc..089a1f99a 100644 --- a/e2e_tests/cli/test_full_cycle.py +++ b/e2e_tests/cli/test_full_cycle.py @@ -6,7 +6,6 @@ from e2e_tests.helpers import ( SERVER_WAIT_TIME, assert_cli, - compare_directories, run_cli_command, export_release, ) @@ -149,8 +148,8 @@ def test_full_cycle_nifti( It is designed to catch errors that may arise from changes to exported Darwin JSON """ - expected_push_dir = "multi_segment_nifti" - annotation_format = "nifti" + item_type = "multi_segment_nifti" + annotation_format = "darwin" first_release_name = "first_release" second_release_name = "second_release" pull_dir = Path( @@ -168,28 +167,22 @@ def test_full_cycle_nifti( expected_filepaths = [f"{pull_dir}/images/{file}.dcm" for file in source_files] # Populate the dataset with items and annotations - push_dir = Path(__file__).parents[1] / "data" / "push" / f"{expected_push_dir}.zip" - items = extract_and_push(push_dir, local_dataset, config_values, expected_push_dir) - assert len(items) == 3 - time.sleep(SERVER_WAIT_TIME * 3) + local_dataset.register_read_only_items(config_values, item_type) + time.sleep(SERVER_WAIT_TIME) result = run_cli_command( - f"darwin dataset import {local_dataset.name} darwin {annotations_import_dir}" + f"darwin dataset import {local_dataset.name} {annotation_format} {annotations_import_dir}" ) assert_cli(result, 0) # Pull a first release of the dataset original_release = export_release( - "darwin", local_dataset, config_values, release_name=first_release_name + annotation_format, local_dataset, config_values, release_name=first_release_name ) result = run_cli_command( f"darwin dataset pull {local_dataset.name}:{original_release.name}" ) assert_cli(result, 0) - result = run_cli_command( - f"darwin dataset convert {local_dataset.name}:{original_release.name} {annotation_format}" - ) - assert_cli(result, 0) # Delete all items in the dataset local_dataset.delete_items(config_values) @@ -203,7 +196,7 @@ def test_full_cycle_nifti( time.sleep(SERVER_WAIT_TIME * 3) result = run_cli_command( - f"darwin dataset import {local_dataset.name} darwin {pull_dir}/releases/{first_release_name}/annotations" + f"darwin dataset import {local_dataset.name} {annotation_format} {pull_dir}/releases/{first_release_name}/annotations" ) assert_cli(result, 0) @@ -212,7 +205,7 @@ def test_full_cycle_nifti( # Pull a second release of the dataset new_release = export_release( - "darwin", + annotation_format, local_dataset, config_values, release_name=second_release_name, @@ -221,10 +214,6 @@ def test_full_cycle_nifti( f"darwin dataset pull {local_dataset.name}:{new_release.name}" ) assert_cli(result, 0) - result = run_cli_command( - f"darwin dataset convert {local_dataset.name}:{new_release.name} {annotation_format}" - ) - assert_cli(result, 0) # Check that all expected files have been downloaded all_filepaths = list(pull_dir.rglob("*")) @@ -232,13 +221,11 @@ def test_full_cycle_nifti( assert Path(expected_file) in all_filepaths # Check that all downloaded annotations are as expected - compare_directories( - Path( - f"{pull_dir}/releases/{first_release_name}/other_formats/{annotation_format}" - ), - Path( - f"{pull_dir}/releases/{second_release_name}/other_formats/{annotation_format}" - ), + compare_annotations_export( + Path(f"{pull_dir}/releases/{first_release_name}/annotations"), + Path(f"{pull_dir}/releases/{second_release_name}/annotations"), + item_type, + unzip=False, )