From 6a6c78dc8aeeb08dd49a71b63ca4b3f2917d1ea8 Mon Sep 17 00:00:00 2001 From: "Thomas G. Close" Date: Mon, 16 Mar 2026 09:05:21 +1100 Subject: [PATCH 1/3] cleaned up file type errors in unittests --- .../analyses/tests/test_diffusion_metrics.py | 68 ++++++++----------- 1 file changed, 30 insertions(+), 38 deletions(-) diff --git a/phantomkit/analyses/tests/test_diffusion_metrics.py b/phantomkit/analyses/tests/test_diffusion_metrics.py index fb7604a..d5c3e45 100644 --- a/phantomkit/analyses/tests/test_diffusion_metrics.py +++ b/phantomkit/analyses/tests/test_diffusion_metrics.py @@ -6,6 +6,7 @@ import numpy as np import pytest +from fileformats.text import TextFile from fileformats.medimage import NiftiGz, Bval, Bvec from fileformats.vendor.mrtrix3.medimage import ImageFormat as Mif @@ -91,7 +92,6 @@ def acqparams_file(tmp_path: Path) -> Path: # ============================================================================ -@pytest.mark.xfail def test_prepare_output_dirs_creates_all_dirs(tmp_path: Path) -> None: session_dir = tmp_path / "session01" session_dir.mkdir() @@ -119,7 +119,6 @@ def test_prepare_output_dirs_creates_all_dirs(tmp_path: Path) -> None: assert Path(getattr(out, attr)).exists(), f"{attr} not created" -@pytest.mark.xfail def test_prepare_output_dirs_default_base(tmp_path: Path, monkeypatch) -> None: monkeypatch.chdir(tmp_path) session_dir = tmp_path / "sess" @@ -373,15 +372,14 @@ def test_write_eddy_files_acqparams_ap_only( # ============================================================================ -@pytest.mark.xfail def test_unpack_grad_fsl_separates_tuple() -> None: bvec = Bvec.sample() bval = Bval.sample() out = _UnpackGradFsl(grad_fsl=(bvec, bval))() - assert Path(out.bvecs_file) == bvec - assert Path(out.bvals_file) == bval + assert out.bvecs_file != bvec + assert out.bvecs_file.hash() == bvec.hash() # ============================================================================ @@ -614,7 +612,6 @@ def _dummy_file(tmp_path: Path, name: str = "dummy.nii.gz") -> Path: return p -@pytest.mark.xfail def test_create_phantom_mask_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import CreatePhantomMask @@ -622,7 +619,6 @@ def test_create_phantom_mask_build(tmp_path: Path) -> None: assert wf is not None -@pytest.mark.xfail def test_prepare_topup_data_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import PrepareTopupData @@ -634,21 +630,19 @@ def test_prepare_topup_data_build(tmp_path: Path) -> None: assert wf is not None -@pytest.mark.xfail def test_apply_topup_to_dwi_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import ApplyTopupToDwi wf = ApplyTopupToDwi( dwi_mif=Mif.sample(), - topup_fieldcoef=_dummy_file(tmp_path, "fieldcoef.nii.gz"), - topup_movpar=_dummy_file(tmp_path, "movpar.txt"), - acqparams_file=_dummy_file(tmp_path, "acqparams.txt"), + topup_fieldcoef=NiftiGz.sample(), + topup_movpar=TextFile.sample(), + acqparams_file=TextFile.sample(), topup_dir=tmp_path, ) assert wf is not None -@pytest.mark.xfail def test_filter_bvalue_shells_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import FilterBvalueShells @@ -656,38 +650,37 @@ def test_filter_bvalue_shells_build(tmp_path: Path) -> None: assert wf is not None -@pytest.mark.xfail def test_prepare_eddy_inputs_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import PrepareEddyInputs wf = PrepareEddyInputs( dwi_mif=Mif.sample(), - topup_acqparams=_dummy_file(tmp_path, "acqparams.txt"), + topup_acqparams=TextFile.sample(), eddy_dir=tmp_path, ) assert wf is not None -@pytest.mark.xfail def test_convert_eddy_output_to_mif_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import ConvertEddyOutputToMif + bvecs = Bvec.sample() + wf = ConvertEddyOutputToMif( - eddy_nii=_dummy_file(tmp_path, "eddy.nii.gz"), - rotated_bvecs=_dummy_file(tmp_path, "bvecs"), - bvals_file=_dummy_file(tmp_path, "bvals"), + eddy_nii=NiftiGz.sample(), + rotated_bvecs=Path(bvecs), + bvals_file=bvecs.b_values_file, output_mif=tmp_path / "out.mif", ) assert wf is not None -@pytest.mark.xfail def test_compute_adc_maps_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import ComputeAdcMaps wf = ComputeAdcMaps( dwi_mif=Mif.sample(), - phantom_mask=_dummy_file(tmp_path, "mask.nii.gz"), + phantom_mask=NiftiGz.sample(), output_dir=tmp_path, label="test", shells=[1000.0, 2000.0], @@ -695,7 +688,6 @@ def test_compute_adc_maps_build(tmp_path: Path) -> None: assert wf is not None -@pytest.mark.xfail def test_topup_correction_step_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import TopupCorrectionStep @@ -707,22 +699,20 @@ def test_topup_correction_step_build(tmp_path: Path) -> None: assert wf is not None -@pytest.mark.xfail def test_eddy_correction_step_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import EddyCorrectionStep wf = EddyCorrectionStep( dwi_mif=Mif.sample(), - phantom_mask=_dummy_file(tmp_path, "mask.nii.gz"), - topup_fieldcoef=_dummy_file(tmp_path, "fieldcoef.nii.gz"), - topup_movpar=_dummy_file(tmp_path, "movpar.txt"), - topup_acqparams=_dummy_file(tmp_path, "acqparams.txt"), + phantom_mask=Mif.sample(seed=0), + topup_fieldcoef=Mif.sample(seed=1), + topup_movpar=TextFile.sample(), + topup_acqparams=TextFile.sample(), eddy_dir=tmp_path, ) assert wf is not None -@pytest.mark.xfail def test_cumulative_pipeline_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import CumulativeDwiPipeline @@ -730,17 +720,18 @@ def test_cumulative_pipeline_build(tmp_path: Path) -> None: session_dir.mkdir() image = NiftiGz.sample(dest_dir=session_dir, stem="dwi") + bvecs = Bvec.sample() + wf = CumulativeDwiPipeline( input_image=image, - bvals_file=_dummy_file(tmp_path, "bvals"), - bvecs_file=_dummy_file(tmp_path, "bvecs"), + bvecs_file=Path(bvecs), + bvals_file=bvecs.b_values_file, pa_ref_dir=tmp_path, output_base_dir=tmp_path / "output", ) assert wf is not None -@pytest.mark.xfail def test_isolated_pipeline_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import IsolatedDwiPipeline @@ -748,18 +739,19 @@ def test_isolated_pipeline_build(tmp_path: Path) -> None: session_dir.mkdir() image = NiftiGz.sample(dest_dir=session_dir, stem="dwi") + bvecs = Bvec.sample() + wf = IsolatedDwiPipeline( input_image=image, - bvals_file=_dummy_file(tmp_path, "bvals"), - bvecs_file=_dummy_file(tmp_path, "bvecs"), + bvecs_file=Path(bvecs), + bvals_file=bvecs.b_values_file, pa_ref_dir=tmp_path, - phantom_mask=_dummy_file(tmp_path, "mask.nii.gz"), + phantom_mask=Mif.sample(), output_base_dir=tmp_path / "output", ) assert wf is not None -@pytest.mark.xfail def test_diffusion_metrics_analysis_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import DiffusionMetricsAnalysis @@ -767,17 +759,18 @@ def test_diffusion_metrics_analysis_build(tmp_path: Path) -> None: session_dir.mkdir() image = NiftiGz.sample(dest_dir=session_dir, stem="dwi") + bvecs = Bvec.sample() + wf = DiffusionMetricsAnalysis( input_image=image, - bvals_file=_dummy_file(tmp_path, "bvals"), - bvecs_file=_dummy_file(tmp_path, "bvecs"), + bvecs_file=Path(bvecs), + bvals_file=bvecs.b_values_file, pa_ref_dir=tmp_path, output_base_dir=tmp_path / "output", ) assert wf is not None -@pytest.mark.xfail def test_diffusion_metrics_analysis_batch_build(tmp_path: Path) -> None: from phantomkit.analyses.diffusion_metrics import DiffusionMetricsAnalysisBatch @@ -795,7 +788,6 @@ def test_diffusion_metrics_analysis_batch_build(tmp_path: Path) -> None: assert wf is not None -@pytest.mark.xfail def test_compute_adc_maps_varying_shells_build(tmp_path: Path) -> None: """ComputeAdcMaps builds successfully with different shell counts.""" from phantomkit.analyses.diffusion_metrics import ComputeAdcMaps From fd329402edf715dc10da94014beebdc20593d73a Mon Sep 17 00:00:00 2001 From: "Thomas G. Close" Date: Tue, 24 Mar 2026 14:56:14 +1100 Subject: [PATCH 2/3] added mrtrix3 to tests CI --- .github/workflows/ci-cd.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 769666d..d5d9d37 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -36,6 +36,12 @@ jobs: run: git fetch --prune --unshallow - name: Disable etelemetry run: echo "NO_ET=TRUE" >> $GITHUB_ENV + - name: Install MRtrix via Conda + run: | + alias shview='ls' + alias mrview='ls' + conda install -c mrtrix3 mrtrix3 + mrconvert --version - name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }} uses: actions/setup-python@v2 with: From 7d8e3dc30962496d40184732bab8b84e23681a79 Mon Sep 17 00:00:00 2001 From: "Thomas G. Close" Date: Tue, 24 Mar 2026 18:25:25 +1100 Subject: [PATCH 3/3] installing mrtrix3 in ci via neurocommand --- .github/workflows/ci-cd.yml | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index d5d9d37..81714ee 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -25,6 +25,7 @@ jobs: shell: bash -l {0} env: PIP_BREAK_SYSTEM_PACKAGES: 1 + MRTRIX3_VERSION: "3.0.4" steps: - name: Checkout uses: actions/checkout@v2 @@ -36,12 +37,21 @@ jobs: run: git fetch --prune --unshallow - name: Disable etelemetry run: echo "NO_ET=TRUE" >> $GITHUB_ENV - - name: Install MRtrix via Conda + - name: Install Neurocommand run: | - alias shview='ls' - alias mrview='ls' - conda install -c mrtrix3 mrtrix3 - mrconvert --version + git clone https://github.com/NeuroDesk/neurocommand.git + pushd neurocommand + pip3 install -r neurodesk/requirements.txt --user + bash build.sh --cli + echo "APPTAINER_BINDPATH=`pwd -P`" >> $GITHUB_ENV + + source /etc/profile.d/lmod.sh + ./containers.sh "mrtrix3" | grep -E "^\s*\|\s*mrtrix3\s*\|\s*${{ env.MRTRIX3_VERSION }}\s*\|" | awk -F '|' '{gsub(/ /,"",$4); print $4}' + SCIGET_BUILDVERSION=$(./containers.sh "mrtrix3" | grep -E "^\s*\|\s*mrtrix3\s*\|\s*${{ env.MRTRIX3_VERSION }}\s*\|" | awk -F '|' '{gsub(/ /,"",$4); print $4}') + + ./local/fetch_containers.sh mrtrix3 ${{ env.MRTRIX3_VERSION }} $SCIGET_BUILDVERSION + echo "SCIGET_BUILDVERSION=$SCIGET_BUILDVERSION" >> $GITHUB_ENV + popd - name: Set up Python ${{ matrix.python-version }} on ${{ matrix.os }} uses: actions/setup-python@v2 with: