From 06407481b39f878dd1f182c4fc98886aa6dcb45e Mon Sep 17 00:00:00 2001 From: Yukai Xue <144064399+AlwinXue@users.noreply.github.com> Date: Mon, 30 Mar 2026 18:54:02 -0700 Subject: [PATCH] fix: copy dicom inputs before running dcm2niix Made-with: Cursor --- .../converters/dicom_to_nifti_converter.py | 5 +- .../tests/test_dicom_to_nifti_converter.py | 50 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 package/src/pyaslreport/tests/test_dicom_to_nifti_converter.py diff --git a/package/src/pyaslreport/converters/dicom_to_nifti_converter.py b/package/src/pyaslreport/converters/dicom_to_nifti_converter.py index 3b8242b9..3b5192f2 100644 --- a/package/src/pyaslreport/converters/dicom_to_nifti_converter.py +++ b/package/src/pyaslreport/converters/dicom_to_nifti_converter.py @@ -1,6 +1,7 @@ import json import os import re +import shutil import subprocess import tempfile import pydicom @@ -24,7 +25,9 @@ def convert(dcm_files, nifti_file=None, converted_files_location="/tmp/upload"): series_repetitions = {} with tempfile.TemporaryDirectory() as temp_dir: - for dcm_file in dcm_files: + for index, dcm_file in enumerate(dcm_files): + temp_file_path = os.path.join(temp_dir, f"{index}_{os.path.basename(dcm_file)}") + shutil.copy2(dcm_file, temp_file_path) ds = pydicom.dcmread(dcm_file) series_number_tag = ds.get((0x0020, 0x0011), None) diff --git a/package/src/pyaslreport/tests/test_dicom_to_nifti_converter.py b/package/src/pyaslreport/tests/test_dicom_to_nifti_converter.py new file mode 100644 index 00000000..2cb23a5a --- /dev/null +++ b/package/src/pyaslreport/tests/test_dicom_to_nifti_converter.py @@ -0,0 +1,50 @@ +import json +from pathlib import Path +from types import SimpleNamespace +from unittest.mock import patch + +from pyaslreport.converters.dicom_to_nifti_converter import DICOM2NiFTIConverter + + +def test_convert_copies_files_to_temp_dir_and_runs_dcm2niix(tmp_path): + dicom_file = tmp_path / "input1.dcm" + dicom_file.write_bytes(b"fake dicom") + output_dir = tmp_path / "converted" + observed_temp_dir = {"path": None} + + def fake_dcmread(_path): + def fake_get(tag, default=None): + if tag == (0x0020, 0x0011): + return SimpleNamespace(value=1) + if tag == (0x0029, 0x1020): + return SimpleNamespace(value=b"lRepetitions = 4") + return default + + return SimpleNamespace(get=fake_get) + + def fake_run(cmd, check, stdout, stderr): + temp_dir = Path(cmd[-1]) + observed_temp_dir["path"] = temp_dir + assert any(temp_dir.iterdir()) + + output_dir.mkdir(exist_ok=True) + (output_dir / "series.nii.gz").write_bytes(b"fake nifti") + (output_dir / "series.json").write_text(json.dumps({"SeriesNumber": 1})) + return SimpleNamespace(stdout=b"", stderr=b"") + + with patch("pyaslreport.converters.dicom_to_nifti_converter.pydicom.dcmread", side_effect=fake_dcmread), \ + patch("pyaslreport.converters.dicom_to_nifti_converter.subprocess.run", side_effect=fake_run): + converted_files, converted_filenames, nifti_file, file_format, error = DICOM2NiFTIConverter.convert( + [str(dicom_file)], + converted_files_location=str(output_dir), + ) + + assert observed_temp_dir["path"] is not None + assert converted_filenames == ["series.json"] + assert converted_files == [str(output_dir / "series.json")] + assert nifti_file == str(output_dir / "series.nii.gz") + assert file_format == "dicom" + assert error is None + + json_data = json.loads((output_dir / "series.json").read_text()) + assert json_data["lRepetitions"] == "4"