Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion darwin/cli_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
2 changes: 1 addition & 1 deletion darwin/exporter/formats/nifti.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
)
Expand Down
40 changes: 7 additions & 33 deletions e2e_tests/cli/test_convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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",
[
Expand All @@ -70,6 +39,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",
Expand Down Expand Up @@ -112,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:
"""
Expand Down
106 changes: 105 additions & 1 deletion e2e_tests/cli/test_full_cycle.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
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
Expand Down Expand Up @@ -125,6 +131,104 @@ 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"
)
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)

result = run_cli_command(
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(
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"
)
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,
Expand Down
Loading
Loading