Skip to content

Commit d13b8a1

Browse files
committed
Add tests for DCM pyramid selection
1 parent 8f9c048 commit d13b8a1

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

tests/aignostics/application/service_test.py

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
"""Tests to verify the service functionality of the application module."""
22

3+
from collections.abc import Callable
34
from datetime import UTC, datetime, timedelta
5+
from pathlib import Path
46
from unittest.mock import MagicMock, patch
57

8+
import pydicom
69
import pytest
710
from typer.testing import CliRunner
811

@@ -439,3 +442,112 @@ def test_application_run_update_item_custom_metadata_not_found(mock_get_client:
439442

440443
with pytest.raises(NotFoundException, match="not found"):
441444
service.application_run_update_item_custom_metadata("run-123", "invalid-item-id", {"key": "value"})
445+
446+
447+
@pytest.fixture
448+
def create_dicom() -> Callable[..., pydicom.Dataset]:
449+
"""Fixture that returns a function to create minimal but valid DICOM datasets."""
450+
451+
def _create_dicom(series_uid: str, rows: int, cols: int) -> pydicom.Dataset:
452+
"""Create a minimal but valid DICOM dataset.
453+
454+
Args:
455+
series_uid: The series instance UID
456+
rows: Number of rows (height)
457+
cols: Number of columns (width)
458+
459+
Returns:
460+
A valid pydicom Dataset
461+
"""
462+
ds = pydicom.Dataset()
463+
464+
# File Meta Information
465+
ds.file_meta = pydicom.Dataset()
466+
ds.file_meta.TransferSyntaxUID = pydicom.uid.ImplicitVRLittleEndian
467+
ds.file_meta.MediaStorageSOPClassUID = "1.2.840.10008.5.1.4.1.1.77.1.6" # VL Whole Slide Microscopy
468+
ds.file_meta.MediaStorageSOPInstanceUID = pydicom.uid.generate_uid()
469+
470+
# Required DICOM attributes
471+
ds.SeriesInstanceUID = series_uid
472+
ds.SOPInstanceUID = pydicom.uid.generate_uid()
473+
ds.SOPClassUID = ds.file_meta.MediaStorageSOPClassUID
474+
ds.StudyInstanceUID = pydicom.uid.generate_uid()
475+
ds.Modality = "SM"
476+
ds.Rows = rows
477+
ds.Columns = cols
478+
479+
return ds
480+
481+
return _create_dicom
482+
483+
484+
@pytest.mark.unit
485+
def test_filter_dicom_series_files_single_file(
486+
tmp_path: Path,
487+
create_dicom: Callable[..., pydicom.Dataset],
488+
) -> None:
489+
"""Test that single DICOM files are not filtered."""
490+
ds = create_dicom("1.2.3.4.5", 1024, 1024)
491+
dcm_file = tmp_path / "test.dcm"
492+
ds.save_as(dcm_file, write_like_original=False)
493+
494+
excluded = ApplicationService._filter_dicom_series_files(tmp_path)
495+
assert len(excluded) == 0
496+
497+
498+
@pytest.mark.unit
499+
def test_filter_dicom_series_files_pyramid(tmp_path: Path, create_dicom: Callable[..., pydicom.Dataset]) -> None:
500+
"""Test that for multi-file DICOM series, only the highest resolution file is kept."""
501+
series_uid = "1.2.3.4.5"
502+
503+
# Create low resolution DICOM file
504+
ds_low = create_dicom(series_uid, 512, 512)
505+
dcm_file_low = tmp_path / "test_low.dcm"
506+
ds_low.save_as(dcm_file_low, write_like_original=False)
507+
508+
# Create medium resolution DICOM file
509+
ds_med = create_dicom(series_uid, 1024, 1024)
510+
dcm_file_med = tmp_path / "test_med.dcm"
511+
ds_med.save_as(dcm_file_med, write_like_original=False)
512+
513+
# Create high resolution DICOM file
514+
ds_high = create_dicom(series_uid, 2048, 2048)
515+
dcm_file_high = tmp_path / "test_high.dcm"
516+
ds_high.save_as(dcm_file_high, write_like_original=False)
517+
518+
# Filter the series
519+
excluded = ApplicationService._filter_dicom_series_files(tmp_path)
520+
521+
# Should exclude 2 files (low and medium), keeping only the highest resolution
522+
assert len(excluded) == 2
523+
assert dcm_file_low in excluded
524+
assert dcm_file_med in excluded
525+
assert dcm_file_high not in excluded
526+
527+
528+
@pytest.mark.unit
529+
def test_filter_dicom_series_files_multiple_series(
530+
tmp_path: Path, create_dicom: Callable[..., pydicom.Dataset]
531+
) -> None:
532+
"""Test that files from different series are not filtered against each other."""
533+
# Series 1 - two files
534+
ds1_low = create_dicom("1.2.3.4.5", 512, 512)
535+
dcm_file1_low = tmp_path / "series1_low.dcm"
536+
ds1_low.save_as(dcm_file1_low, write_like_original=False)
537+
538+
ds1_high = create_dicom("1.2.3.4.5", 1024, 1024)
539+
dcm_file1_high = tmp_path / "series1_high.dcm"
540+
ds1_high.save_as(dcm_file1_high, write_like_original=False)
541+
542+
# Series 2 - single file (should not be filtered)
543+
ds2 = create_dicom("6.7.8.9.0", 512, 512)
544+
dcm_file2 = tmp_path / "series2.dcm"
545+
ds2.save_as(dcm_file2, write_like_original=False)
546+
547+
excluded = ApplicationService._filter_dicom_series_files(tmp_path)
548+
549+
# Should exclude only the low-res file from series 1
550+
assert len(excluded) == 1
551+
assert dcm_file1_low in excluded
552+
assert dcm_file1_high not in excluded
553+
assert dcm_file2 not in excluded

0 commit comments

Comments
 (0)