From b30f89c87d431822e0fbe70e9309f535cf9096a4 Mon Sep 17 00:00:00 2001 From: Tom Close Date: Wed, 21 Feb 2024 15:50:51 +1100 Subject: [PATCH 1/3] update to match changes in fileformats base --- extras/fileformats/extras/medimage/dicom.py | 29 ++++++++++--------- extras/fileformats/extras/medimage/nifti.py | 22 ++++++++------ .../medimage/tests/test_dicom_metadata.py | 8 ++--- fileformats/medimage/dicom.py | 2 +- fileformats/medimage/tests/test_dicom.py | 4 +-- 5 files changed, 35 insertions(+), 30 deletions(-) diff --git a/extras/fileformats/extras/medimage/dicom.py b/extras/fileformats/extras/medimage/dicom.py index 2bc3055..108404e 100644 --- a/extras/fileformats/extras/medimage/dicom.py +++ b/extras/fileformats/extras/medimage/dicom.py @@ -5,7 +5,7 @@ import pydicom import numpy as np from fileformats.core import FileSet -from fileformats.core.utils import gen_filename +from fileformats.core.utils import SampleFileGenerator from fileformats.medimage import MedicalImage, DicomCollection, DicomDir, DicomSeries import medimages4tests.dummy.dicom.mri.t1w.siemens.skyra.syngo_d13c @@ -42,15 +42,13 @@ def dicom_series_number(collection: DicomCollection) -> str: @FileSet.generate_sample_data.register -def dicom_dir_generate_sample_data(dcmdir: DicomDir, dest_dir: Path, seed: ty.Union[int, Random] = 0, stem: ty.Optional[str] = None) -> ty.Iterable[Path]: +def dicom_dir_generate_sample_data( + dcmdir: DicomDir, + generator: SampleFileGenerator, +) -> ty.Iterable[Path]: dcm_dir = medimages4tests.dummy.dicom.mri.t1w.siemens.skyra.syngo_d13c.get_image() - # Set series number to random value to make it different - if isinstance(seed, Random): - rng = seed - else: - rng = Random(seed) - series_number = rng.randint(1, SERIES_NUMBER_RANGE) - dest = Path(dest_dir) / gen_filename(seed_or_rng=seed, stem=stem) + series_number = generator.rng.randint(1, SERIES_NUMBER_RANGE) + dest = generator.generate_fspath(DicomDir) dest.mkdir() for dcm_file in dcm_dir.iterdir(): dcm = pydicom.dcmread(dcm_file) @@ -60,13 +58,16 @@ def dicom_dir_generate_sample_data(dcmdir: DicomDir, dest_dir: Path, seed: ty.Un @FileSet.generate_sample_data.register -def dicom_series_generate_sample_data(dcm_series: DicomSeries, dest_dir: Path, seed: ty.Union[int, Random] = 0, stem: ty.Optional[str] = None) -> ty.Iterable[Path]: - rng = Random(seed) - dicom_dir = dicom_dir_generate_sample_data(dcm_series, dest_dir=mkdtemp(), seed=rng, stem=None)[0] - stem = gen_filename(rng, stem=stem) +def dicom_series_generate_sample_data( + dcm_series: DicomSeries, + generator: SampleFileGenerator, +) -> ty.Iterable[Path]: + dicom_dir: Path = dicom_dir_generate_sample_data(dcm_series, generator=generator)[0] + stem = generator.generate_fspath().stem fspaths = [] for i, dicom_file in enumerate(dicom_dir.iterdir(), start=1): - fspaths.append(dicom_file.rename(dest_dir / f"{stem}-{i}.dcm")) + fspaths.append(dicom_file.rename(generator.dest_dir / f"{stem}-{i}.dcm")) + dicom_dir.rmdir() return fspaths diff --git a/extras/fileformats/extras/medimage/nifti.py b/extras/fileformats/extras/medimage/nifti.py index bb40982..433b296 100644 --- a/extras/fileformats/extras/medimage/nifti.py +++ b/extras/fileformats/extras/medimage/nifti.py @@ -4,7 +4,7 @@ import nibabel import numpy as np from fileformats.core import FileSet -from fileformats.core.utils import gen_filename +from fileformats.core.utils import SampleFileGenerator from fileformats.medimage import MedicalImage, Nifti, NiftiGz, Nifti1, NiftiGzX, NiftiX import medimages4tests.dummy.nifti @@ -33,33 +33,37 @@ def nifti_dims(nifti: Nifti) -> ty.Tuple[int, int, int]: @FileSet.generate_sample_data.register def nifti_generate_sample_data( - nifti: Nifti1, dest_dir: Path, seed: ty.Union[int, Random] = 0, stem: ty.Optional[str] = None + nifti: Nifti1, + generator: SampleFileGenerator, ) -> ty.Iterable[Path]: return medimages4tests.dummy.nifti.get_image( - out_file=dest_dir / gen_filename(seed, file_type=Nifti1, stem=stem) + out_file=generator.generate_fspath(file_type=Nifti1) ) @FileSet.generate_sample_data.register def nifti_gz_generate_sample_data( - nifti: NiftiGz, dest_dir: Path, seed: ty.Union[int, Random] = 0, stem: ty.Optional[str] = None + nifti: NiftiGz, + generator: SampleFileGenerator, ) -> ty.Iterable[Path]: return medimages4tests.dummy.nifti.get_image( - out_file=dest_dir / gen_filename(seed, file_type=NiftiGz, stem=stem), + out_file=generator.generate_fspath(file_type=NiftiGz), compressed=True, ) @FileSet.generate_sample_data.register def nifti_gz_x_generate_sample_data( - nifti: NiftiGzX, dest_dir: Path, seed: ty.Union[int, Random] = 0, stem: ty.Optional[str] = None + nifti: NiftiGzX, + generator: SampleFileGenerator, ) -> ty.Iterable[Path]: - return medimages4tests.mri.neuro.t1w.get_image() + return medimages4tests.mri.neuro.t1w.get_image(out_dir=generator.dest_dir) @FileSet.generate_sample_data.register def nifti_x_generate_sample_data( - nifti: NiftiX, dest_dir: Path, seed: ty.Union[int, Random] = 0, stem: ty.Optional[str] = None + nifti: NiftiX, + generator: SampleFileGenerator, ) -> ty.Iterable[Path]: - nifti_gz_x = NiftiGzX(medimages4tests.mri.neuro.t1w.get_image()) + nifti_gz_x = NiftiGzX(medimages4tests.mri.neuro.t1w.get_image(out_dir=generator.dest_dir)) return NiftiX.convert(nifti_gz_x) diff --git a/extras/fileformats/extras/medimage/tests/test_dicom_metadata.py b/extras/fileformats/extras/medimage/tests/test_dicom_metadata.py index 538f5d4..ef2a0ee 100644 --- a/extras/fileformats/extras/medimage/tests/test_dicom_metadata.py +++ b/extras/fileformats/extras/medimage/tests/test_dicom_metadata.py @@ -5,15 +5,15 @@ def test_dicom_series_metadata(tmp_path): series = DicomSeries.sample(tmp_path) # Check series number is not a list - assert not isinstance(series["SeriesNumber"], list) + assert not isinstance(series.metadata["SeriesNumber"], list) # check the SOP Instance ID has been converted into a list - assert isinstance(series["SOPInstanceUID"], list) + assert isinstance(series.metadata["SOPInstanceUID"], list) def test_dicom_dir_metadata(tmp_path): series = DicomDir.sample(tmp_path) # Check series number is not a list - assert not isinstance(series["SeriesNumber"], list) + assert not isinstance(series.metadata["SeriesNumber"], list) # check the SOP Instance ID has been converted into a list - assert isinstance(series["SOPInstanceUID"], list) + assert isinstance(series.metadata["SOPInstanceUID"], list) diff --git a/fileformats/medimage/dicom.py b/fileformats/medimage/dicom.py index 8c465cf..28698e9 100644 --- a/fileformats/medimage/dicom.py +++ b/fileformats/medimage/dicom.py @@ -67,7 +67,7 @@ def from_paths( for dicom in dicoms: dicom.select_metadata(selected_keys) series_dict[ - (str(dicom["StudyInstanceUID"]), str(dicom["SeriesNumber"])) + (str(dicom.metadata["StudyInstanceUID"]), str(dicom.metadata["SeriesNumber"])) ].append(dicom) return set([cls(s) for s in series_dict.values()]), remaining diff --git a/fileformats/medimage/tests/test_dicom.py b/fileformats/medimage/tests/test_dicom.py index 15f197e..de721f9 100644 --- a/fileformats/medimage/tests/test_dicom.py +++ b/fileformats/medimage/tests/test_dicom.py @@ -34,6 +34,6 @@ def test_dicom_series_metadata(tmp_path): series = DicomSeries.sample(tmp_path) # Check series number is not a list - assert not isinstance(series["SeriesNumber"], list) + assert not isinstance(series.metadata["SeriesNumber"], list) # check the SOP Instance ID has been converted into a list - assert isinstance(series["SOPInstanceUID"], list) + assert isinstance(series.metadata["SOPInstanceUID"], list) From c4583e930a1363a55471313b193691b7e6a7dcd9 Mon Sep 17 00:00:00 2001 From: Tom Close Date: Thu, 22 Feb 2024 12:33:45 +1100 Subject: [PATCH 2/3] mark xfail when using old pydra-mrtrix3 package --- conftest.py | 6 ++++++ .../extras/medimage/tests/test_dicom_metadata.py | 4 ++++ .../extras/medimage/tests/test_neuro_converters.py | 7 +++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/conftest.py b/conftest.py index fa2afb0..6ad838c 100644 --- a/conftest.py +++ b/conftest.py @@ -11,6 +11,12 @@ set_input_validator(True) from fileformats.medimage.dicom import DicomDir +try: + import pydra.tasks.mrtrix3.v3_0 +except ImportError: + OLD_MRTRIX_VERSION = True +else: + OLD_MRTRIX_VERSION = False # Set DEBUG logging for unittests diff --git a/extras/fileformats/extras/medimage/tests/test_dicom_metadata.py b/extras/fileformats/extras/medimage/tests/test_dicom_metadata.py index ef2a0ee..25c306e 100644 --- a/extras/fileformats/extras/medimage/tests/test_dicom_metadata.py +++ b/extras/fileformats/extras/medimage/tests/test_dicom_metadata.py @@ -1,6 +1,9 @@ +import pytest from fileformats.medimage import DicomSeries, DicomDir +from conftest import OLD_MRTRIX_VERSION +@pytest.mark.xfail(condition=OLD_MRTRIX_VERSION, reason="Old MRtrix version") def test_dicom_series_metadata(tmp_path): series = DicomSeries.sample(tmp_path) @@ -10,6 +13,7 @@ def test_dicom_series_metadata(tmp_path): assert isinstance(series.metadata["SOPInstanceUID"], list) +@pytest.mark.xfail(condition=OLD_MRTRIX_VERSION, reason="Old MRtrix version") def test_dicom_dir_metadata(tmp_path): series = DicomDir.sample(tmp_path) diff --git a/extras/fileformats/extras/medimage/tests/test_neuro_converters.py b/extras/fileformats/extras/medimage/tests/test_neuro_converters.py index 862f8f2..b1517cc 100644 --- a/extras/fileformats/extras/medimage/tests/test_neuro_converters.py +++ b/extras/fileformats/extras/medimage/tests/test_neuro_converters.py @@ -2,10 +2,10 @@ from fileformats.medimage import ( NiftiGzX, NiftiGzXBvec, - NiftiBvec, Analyze, ) from logging import getLogger +from conftest import OLD_MRTRIX_VERSION logger = getLogger("fileformats") @@ -27,6 +27,7 @@ def test_dicom_to_nifti_select_echo(dummy_magfmap_dicom): assert nifti_gz_x_e2.metadata["EchoNumber"] == 2 +@pytest.mark.xfail(condition=OLD_MRTRIX_VERSION, reason="Old MRtrix version") def test_dicom_to_nifti_select_suffix(dummy_mixedfmap_dicom): nifti_gz_x_ph = NiftiGzX.convert(dummy_mixedfmap_dicom, file_postfix="_ph") @@ -57,6 +58,7 @@ def test_dicom_to_nifti_with_jq_edit(dummy_t1w_dicom): assert nifti_gz_x.metadata["EchoTime"] == 2.07 +@pytest.mark.xfail(condition=OLD_MRTRIX_VERSION, reason="Old MRtrix version") def test_dicom_to_niftix_with_fslgrad(dummy_dwi_dicom): logger.debug("Performing FSL grad conversion") @@ -74,12 +76,13 @@ def test_dicom_to_niftix_with_fslgrad(dummy_dwi_dicom): assert all(abs(1 - m) < 1e5 for m in bvec_mags) -# @pytest.mark.skip("Mrtrix isn't installed in test environment yet") +@pytest.mark.xfail(condition=OLD_MRTRIX_VERSION, reason="Old MRtrix version") def test_dicom_to_nifti_as_4d(dummy_t1w_dicom): nifti_gz_x_e1 = NiftiGzX.convert(dummy_t1w_dicom, to_4d=True) assert nifti_gz_x_e1.metadata["dim"][0] == 4 +@pytest.mark.xfail(condition=OLD_MRTRIX_VERSION, reason="Old MRtrix version") def test_dicom_to_analyze(dummy_t1w_dicom): Analyze.convert(dummy_t1w_dicom) From 169ed140eda9d5c6d921f9e8e1492beefe513ee2 Mon Sep 17 00:00:00 2001 From: Tom Close Date: Thu, 22 Feb 2024 12:37:10 +1100 Subject: [PATCH 3/3] mark another test as xfail when using old mrtrix3 --- .../fileformats/extras/medimage/tests/test_neuro_converters.py | 1 + 1 file changed, 1 insertion(+) diff --git a/extras/fileformats/extras/medimage/tests/test_neuro_converters.py b/extras/fileformats/extras/medimage/tests/test_neuro_converters.py index b1517cc..cc4d3ca 100644 --- a/extras/fileformats/extras/medimage/tests/test_neuro_converters.py +++ b/extras/fileformats/extras/medimage/tests/test_neuro_converters.py @@ -43,6 +43,7 @@ def test_dicom_to_nifti_select_suffix(dummy_mixedfmap_dicom): assert list(nifti_gz_x_real.dims()) == [256, 256, 60] +@pytest.mark.xfail(condition=OLD_MRTRIX_VERSION, reason="Old MRtrix version") def test_dicom_to_nifti_with_extract_volume(dummy_dwi_dicom): nifti_gz_x_e1 = NiftiGzX.convert(dummy_dwi_dicom, extract_volume=30)