File size: 3,232 Bytes
aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a 3c4c67b aef1f5a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
"""Tests for the data adapter."""
from __future__ import annotations
from typing import TYPE_CHECKING
from stroke_deepisles_demo.data.adapter import (
LocalDataset,
build_local_dataset,
parse_subject_id,
)
if TYPE_CHECKING:
from pathlib import Path
def test_parse_subject_id_extracts_correctly() -> None:
"""Test extracting subject ID from BIDS filename."""
# Valid cases
assert parse_subject_id("sub-stroke0005_ses-02_dwi.nii.gz") == "sub-stroke0005"
assert parse_subject_id("sub-stroke0149_ses-02_adc.nii.gz") == "sub-stroke0149"
assert parse_subject_id("sub-stroke1234_ses-02_lesion-msk.nii.gz") == "sub-stroke1234"
# Invalid cases
assert parse_subject_id("random_file.nii.gz") is None
assert parse_subject_id("sub-strokeABC_ses-02_dwi.nii.gz") is None # Non-digit ID
def test_build_local_dataset_matches_files(synthetic_isles_dir: Path) -> None:
"""Test that files are correctly matched by subject ID."""
dataset = build_local_dataset(synthetic_isles_dir)
assert isinstance(dataset, LocalDataset)
assert len(dataset) == 2 # synthetic_isles_dir creates 2 subjects
assert dataset.list_case_ids() == ["sub-stroke0001", "sub-stroke0002"]
# Verify matching logic
case1 = dataset.get_case("sub-stroke0001")
assert case1["dwi"].name == "sub-stroke0001_ses-02_dwi.nii.gz"
assert case1["adc"].name == "sub-stroke0001_ses-02_adc.nii.gz"
assert case1["ground_truth"] is not None
assert case1["ground_truth"].name == "sub-stroke0001_ses-02_lesion-msk.nii.gz"
def test_get_case_returns_case_files(synthetic_isles_dir: Path) -> None:
"""Test retrieval of cases by ID and index."""
dataset = build_local_dataset(synthetic_isles_dir)
# By ID
case_by_id = dataset.get_case("sub-stroke0001")
assert isinstance(case_by_id, dict)
assert "dwi" in case_by_id
assert "adc" in case_by_id
# By Index
case_by_idx = dataset.get_case(0)
assert isinstance(case_by_idx, dict)
assert case_by_id == case_by_idx # Should be the same case
def test_build_local_dataset_skips_incomplete(
synthetic_isles_dir: Path,
) -> None:
"""Test that incomplete cases (missing ADC) are skipped."""
# Delete ADC for subject 2
adc_file = synthetic_isles_dir / "Images-ADC" / "sub-stroke0002_ses-02_adc.nii.gz"
adc_file.unlink()
dataset = build_local_dataset(synthetic_isles_dir)
# Subject 2 should be gone
assert len(dataset) == 1
assert dataset.list_case_ids() == ["sub-stroke0001"]
def test_build_local_dataset_handles_missing_mask(
synthetic_isles_dir: Path,
) -> None:
"""Test that missing mask results in ground_truth=None (if allowed)."""
# NOTE: Adapter currently allows missing mask?
# Spec says: "ground_truth=mask_file if mask_file.exists() else None"
# So yes, it should load but with None.
# Delete Mask for subject 2
mask_file = synthetic_isles_dir / "Masks" / "sub-stroke0002_ses-02_lesion-msk.nii.gz"
mask_file.unlink()
dataset = build_local_dataset(synthetic_isles_dir)
# Subject 2 should still exist
assert len(dataset) == 2
case2 = dataset.get_case("sub-stroke0002")
assert case2.get("ground_truth") is None
|