From 23d3e0175d6530d25b05a34d54c9d8a0ae747a7f Mon Sep 17 00:00:00 2001 From: Tom Close Date: Tue, 26 Jul 2022 18:21:52 +1000 Subject: [PATCH 1/5] properly handles gzip extensions (only adding them to out_file when compress is 'y' or 'i' or 'o', and handles echo numbers via 'echo' input --- .pre-commit-config.yaml | 2 +- pydra/tasks/dcm2niix/utils.py | 48 ++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c429bfa..9d53ff2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,6 +9,6 @@ repos: - id: check-yaml - id: check-added-large-files - repo: https://github.com/psf/black - rev: 19.3b0 + rev: 22.6.0 hooks: - id: black diff --git a/pydra/tasks/dcm2niix/utils.py b/pydra/tasks/dcm2niix/utils.py index 5cbe616..1be68fd 100644 --- a/pydra/tasks/dcm2niix/utils.py +++ b/pydra/tasks/dcm2niix/utils.py @@ -1,8 +1,34 @@ -import typing as ty +import os.path from pydra import ShellCommandTask from pydra.engine.specs import ShellSpec, ShellOutSpec, File, Directory, SpecInfo +def dcm2niix_out_file(out_dir, filename, echo, compress): + # Append echo number of NIfTI echo to select is provided + if echo: + echo_suffix = f"_e{echo}" + else: + echo_suffix = "" + + out_file = f"{out_dir}/{filename}{echo_suffix}.nii" + + # If compressed, append the zip extension + if compress in ("y", "o", "i"): + out_file += ".gz" + + return os.path.abspath(out_file) + + +def dcm2niix_out_json(out_dir, filename, echo): + # Append echo number of NIfTI echo to select is provided + if echo: + echo_suffix = f"_e{echo}" + else: + echo_suffix = "" + + return os.path.abspath(f"{out_dir}/{filename}{echo_suffix}.json") + + input_fields = [ ( "in_dir", @@ -16,7 +42,7 @@ ), ( "out_dir", - str, + Directory, { "argstr": "-o '{out_dir}'", "help_string": "output directory", @@ -29,6 +55,18 @@ "out_file", {"argstr": "-f '{filename}'", "help_string": "The output name for the file"}, ), + ( + "echo", + int, + { + "argstr": "", + "help_string": ( + "The echo number to extract from the DICOM dataset. When multiple " + "echoes are discovered in the dataset then dcm2niix will create " + "separate files for each echo with the suffix '_e.nii'" + ), + }, + ), ( "compress", str, @@ -279,7 +317,8 @@ File, { "help_string": "output NIfTI image", - "output_file_template": "{out_dir}/{filename}.nii.gz", + "callable": dcm2niix_out_file, + "mandatory": True, }, ), ( @@ -287,7 +326,8 @@ File, { "help_string": "output BIDS side-car JSON", - "output_file_template": "{out_dir}/{filename}.json", + # "requires": [("bids", 'y')], FIXME: should be either 'y' or 'o' + "callable": dcm2niix_out_json, }, ), ( From 9f2d5b512b6b15955012990a732b62d4c77358b4 Mon Sep 17 00:00:00 2001 From: Tom Close Date: Wed, 27 Jul 2022 09:24:03 +1000 Subject: [PATCH 2/5] fixed up doctest to point to existing out directory --- pydra/tasks/dcm2niix/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pydra/tasks/dcm2niix/utils.py b/pydra/tasks/dcm2niix/utils.py index 1be68fd..4a44bf2 100644 --- a/pydra/tasks/dcm2niix/utils.py +++ b/pydra/tasks/dcm2niix/utils.py @@ -359,10 +359,10 @@ class Dcm2Niix(ShellCommandTask): ------- >>> task = Dcm2Niix() >>> task.inputs.in_dir = "test-data/test_dicoms" - >>> task.inputs.out_dir = "test-data/output" + >>> task.inputs.out_dir = "test-data" >>> task.inputs.compress = "y" >>> task.cmdline - "dcm2niix -o 'test-data/output' -f 'out_file' -z y 'test-data/test_dicoms'" + "dcm2niix -o 'test-data' -f 'out_file' -z y 'test-data/test_dicoms'" """ input_spec = Dcm2NiixInputSpec From 30f29a0de441f05b912c7c8972463a76da2759e0 Mon Sep 17 00:00:00 2001 From: Tom Close Date: Wed, 27 Jul 2022 10:23:05 +1000 Subject: [PATCH 3/5] updated pydra dependency to 0.19 --- .gitignore | 4 ++++ pydra/tasks/dcm2niix/tests/test_utils.py | 12 ++++++++++++ setup.cfg | 2 +- 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 pydra/tasks/dcm2niix/tests/test_utils.py diff --git a/.gitignore b/.gitignore index 846dc44..67e5eb4 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,7 @@ dmypy.json # Pycharm .idea + + +# VSCode +.vscode diff --git a/pydra/tasks/dcm2niix/tests/test_utils.py b/pydra/tasks/dcm2niix/tests/test_utils.py new file mode 100644 index 0000000..b6213e3 --- /dev/null +++ b/pydra/tasks/dcm2niix/tests/test_utils.py @@ -0,0 +1,12 @@ +from pydra.tasks.dcm2niix.utils import Dcm2Niix + + +def test_dcm2niix(): + task = Dcm2Niix() + task.inputs.in_dir = "test-data/test_dicoms" + task.inputs.out_dir = "test-data" + task.inputs.compress = "y" + assert ( + task.cmdline + == "dcm2niix -o 'test-data' -f 'out_file' -z y 'test-data/test_dicoms'" + ) diff --git a/setup.cfg b/setup.cfg index 8245b24..9eef945 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,7 +23,7 @@ classifiers = [options] python_requires = >=3.7 install_requires = - pydra >= 0.6.2 + pydra >= 0.19 packages = find_namespace: [options.packages.find] From 8f620824c49ba76c4619d0336fb4552f2c161798 Mon Sep 17 00:00:00 2001 From: Tom Close Date: Wed, 27 Jul 2022 11:00:18 +1000 Subject: [PATCH 4/5] fixed up doctest and started to add pytest framework --- conftest.py | 14 ++++++++++++++ pydra/tasks/dcm2niix/tests/test_utils.py | 3 +-- pydra/tasks/dcm2niix/utils.py | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 conftest.py diff --git a/conftest.py b/conftest.py new file mode 100644 index 0000000..7d742bb --- /dev/null +++ b/conftest.py @@ -0,0 +1,14 @@ +import os +import pytest + +# For debugging in IDE's don't catch raised exceptions and let the IDE +# break at it +if os.getenv("_PYTEST_RAISE", "0") != "0": + + @pytest.hookimpl(tryfirst=True) + def pytest_exception_interact(call): + raise call.excinfo.value + + @pytest.hookimpl(tryfirst=True) + def pytest_internalerror(excinfo): + raise excinfo.value diff --git a/pydra/tasks/dcm2niix/tests/test_utils.py b/pydra/tasks/dcm2niix/tests/test_utils.py index b6213e3..abe9ca1 100644 --- a/pydra/tasks/dcm2niix/tests/test_utils.py +++ b/pydra/tasks/dcm2niix/tests/test_utils.py @@ -7,6 +7,5 @@ def test_dcm2niix(): task.inputs.out_dir = "test-data" task.inputs.compress = "y" assert ( - task.cmdline - == "dcm2niix -o 'test-data' -f 'out_file' -z y 'test-data/test_dicoms'" + task.cmdline == "dcm2niix -o test-data -f out_file -z y test-data/test_dicoms" ) diff --git a/pydra/tasks/dcm2niix/utils.py b/pydra/tasks/dcm2niix/utils.py index 4a44bf2..ab72907 100644 --- a/pydra/tasks/dcm2niix/utils.py +++ b/pydra/tasks/dcm2niix/utils.py @@ -362,7 +362,7 @@ class Dcm2Niix(ShellCommandTask): >>> task.inputs.out_dir = "test-data" >>> task.inputs.compress = "y" >>> task.cmdline - "dcm2niix -o 'test-data' -f 'out_file' -z y 'test-data/test_dicoms'" + "dcm2niix -o test-data -f out_file -z y test-data/test_dicoms" """ input_spec = Dcm2NiixInputSpec From 3ee3557bc8e04999075d26ae5a7c2f671441fc9b Mon Sep 17 00:00:00 2001 From: Tom Close Date: Wed, 27 Jul 2022 11:04:19 +1000 Subject: [PATCH 5/5] changed quotes for doctest output --- pydra/tasks/dcm2niix/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pydra/tasks/dcm2niix/utils.py b/pydra/tasks/dcm2niix/utils.py index ab72907..c643b33 100644 --- a/pydra/tasks/dcm2niix/utils.py +++ b/pydra/tasks/dcm2niix/utils.py @@ -362,7 +362,7 @@ class Dcm2Niix(ShellCommandTask): >>> task.inputs.out_dir = "test-data" >>> task.inputs.compress = "y" >>> task.cmdline - "dcm2niix -o test-data -f out_file -z y test-data/test_dicoms" + 'dcm2niix -o test-data -f out_file -z y test-data/test_dicoms' """ input_spec = Dcm2NiixInputSpec