From b9b549e6ef3100301aa307ccd5c8879f55087226 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Wed, 2 Oct 2024 17:55:28 -0400 Subject: [PATCH] FIX: Avoid cluttering directories with test files --- nibabies/conftest.py | 48 ++++++++----------- .../data/sub-01_run-01_echo-1_bold.nii.gz | 0 .../data/sub-01_run-01_echo-2_bold.nii.gz | 0 .../data/sub-01_run-01_echo-3_bold.nii.gz | 0 nibabies/interfaces/conftest.py | 29 +++++++++-- nibabies/interfaces/tests/data/__init__.py | 0 nibabies/interfaces/workbench.py | 38 +++++++-------- nibabies/workflows/bold/alignment.py | 6 +-- 8 files changed, 67 insertions(+), 54 deletions(-) delete mode 100644 nibabies/data/sub-01_run-01_echo-1_bold.nii.gz delete mode 100644 nibabies/data/sub-01_run-01_echo-2_bold.nii.gz delete mode 100644 nibabies/data/sub-01_run-01_echo-3_bold.nii.gz delete mode 100644 nibabies/interfaces/tests/data/__init__.py diff --git a/nibabies/conftest.py b/nibabies/conftest.py index 2a24dc2f..a76fb074 100644 --- a/nibabies/conftest.py +++ b/nibabies/conftest.py @@ -2,7 +2,7 @@ import json from pathlib import Path -from tempfile import TemporaryDirectory +from shutil import copytree import nibabel as nb import numpy as np @@ -10,36 +10,28 @@ from nibabies.data import load as load_data -FILES = ( - 'functional.nii', - 'anatomical.nii', - 'func.dlabel.nii', - 'func.dtseries.nii', - 'epi.nii', - 'T1w.nii', - 'func_to_struct.mat', - 'atlas.nii', - 'label_list.txt', - 'sub-01_run-01_echo-1_bold.nii.gz', - 'sub-01_run-01_echo-2_bold.nii.gz', - 'sub-01_run-01_echo-3_bold.nii.gz', -) - - -@pytest.fixture(scope='package') -def data_dir(): - with TemporaryDirectory() as tmpdir: - tmp_path = Path(tmpdir) - for fname in FILES: - Path.touch(tmp_path / fname) - yield tmp_path +try: + from importlib.resources import files as ir_files +except ImportError: # PY<3.9 + from importlib_resources import files as ir_files + + +def copytree_or_skip(source, target): + data_dir = ir_files('nibabies') / source + if not data_dir.exists(): + pytest.skip(f'Cannot chdir into {data_dir!r}. Probably in a zipped distribution.') + + try: + copytree(data_dir, target / data_dir.name) + except Exception: # noqa: BLE001 + pytest.skip(f'Cannot copy {data_dir!r} into {target / data_dir.name}. Probably in a zip.') @pytest.fixture(autouse=True) -def _populate_namespace(doctest_namespace, data_dir): - doctest_namespace['data_dir'] = data_dir - doctest_namespace['test_data'] = load_data.cached('../tests/data') - doctest_namespace['Path'] = Path +def _populate_namespace(doctest_namespace, tmp_path): + doctest_namespace['copytree_or_skip'] = copytree_or_skip + doctest_namespace['testdir'] = tmp_path + doctest_namespace['datadir'] = load_data() @pytest.fixture diff --git a/nibabies/data/sub-01_run-01_echo-1_bold.nii.gz b/nibabies/data/sub-01_run-01_echo-1_bold.nii.gz deleted file mode 100644 index e69de29b..00000000 diff --git a/nibabies/data/sub-01_run-01_echo-2_bold.nii.gz b/nibabies/data/sub-01_run-01_echo-2_bold.nii.gz deleted file mode 100644 index e69de29b..00000000 diff --git a/nibabies/data/sub-01_run-01_echo-3_bold.nii.gz b/nibabies/data/sub-01_run-01_echo-3_bold.nii.gz deleted file mode 100644 index e69de29b..00000000 diff --git a/nibabies/interfaces/conftest.py b/nibabies/interfaces/conftest.py index a8511d04..a0decec4 100644 --- a/nibabies/interfaces/conftest.py +++ b/nibabies/interfaces/conftest.py @@ -1,5 +1,6 @@ from pathlib import Path from shutil import copytree +from tempfile import TemporaryDirectory import pytest @@ -19,17 +20,37 @@ def _chdir(path): os.chdir(cwd) -@pytest.fixture(scope='module') +DATA_FILES = ( + 'functional.nii', + 'anatomical.nii', + 'func.dlabel.nii', + 'func.dtseries.nii', + 'epi.nii', + 'T1w.nii', + 'func_to_struct.mat', + 'atlas.nii', + 'label_list.txt', + 'sub-01_run-01_echo-1_bold.nii.gz', + 'sub-01_run-01_echo-2_bold.nii.gz', + 'sub-01_run-01_echo-3_bold.nii.gz', +) + + +@pytest.fixture(scope='package') def data_dir(): - return Path(__file__).parent / 'tests' / 'data' + with TemporaryDirectory() as tmpdir: + tmp_path = Path(tmpdir) + for fname in DATA_FILES: + Path.touch(tmp_path / fname) + yield tmp_path @pytest.fixture(autouse=True) -def _docdir(request, tmp_path): +def _docdir(data_dir, request, tmp_path): # Trigger ONLY for the doctests. doctest_plugin = request.config.pluginmanager.getplugin('doctest') if isinstance(request.node, doctest_plugin.DoctestItem): - copytree(Path(__file__).parent / 'tests' / 'data', tmp_path, dirs_exist_ok=True) + copytree(data_dir, tmp_path, dirs_exist_ok=True) # Chdir only for the duration of the test. with _chdir(tmp_path): diff --git a/nibabies/interfaces/tests/data/__init__.py b/nibabies/interfaces/tests/data/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/nibabies/interfaces/workbench.py b/nibabies/interfaces/workbench.py index 77bfe68f..3481d519 100644 --- a/nibabies/interfaces/workbench.py +++ b/nibabies/interfaces/workbench.py @@ -164,7 +164,7 @@ class CiftiCreateDenseFromTemplate(WBCommand): >>> from nibabies.interfaces import workbench as wb >>> frmtpl = wb.CiftiCreateDenseFromTemplate() - >>> frmtpl.inputs.in_file = data_dir / "func.dtseries.nii" + >>> frmtpl.inputs.in_file = testdir / "func.dtseries.nii" >>> frmtpl.inputs.series = True >>> frmtpl.inputs.series_step = 0.8 >>> frmtpl.inputs.series_start = 0 @@ -172,8 +172,8 @@ class CiftiCreateDenseFromTemplate(WBCommand): 'wb_command -cifti-create-dense-from-template .../func.dtseries.nii \ template_func.dtseries.nii -series 0.8 0.0' - >>> frmtpl.inputs.volume = [("OTHER", data_dir / 'functional.nii', True), \ - ("PUTAMEN_LEFT", data_dir / 'functional.nii')] + >>> frmtpl.inputs.volume = [("OTHER", testdir / 'functional.nii', True), \ + ("PUTAMEN_LEFT", testdir / 'functional.nii')] >>> frmtpl.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -cifti-create-dense-from-template .../func.dtseries.nii \ template_func.dtseries.nii -series 0.8 0.0 \ @@ -330,8 +330,8 @@ class CiftiCreateDenseTimeseries(WBCommand): >>> from nibabies.interfaces.workbench import CiftiCreateDenseTimeseries >>> createdts = CiftiCreateDenseTimeseries() - >>> createdts.inputs.volume_data = data_dir /'functional.nii' - >>> createdts.inputs.volume_structure_labels = data_dir / 'atlas.nii' + >>> createdts.inputs.volume_data = testdir /'functional.nii' + >>> createdts.inputs.volume_structure_labels = testdir / 'atlas.nii' >>> createdts.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -cifti-create-dense-timeseries out.dtseries.nii \ -volume .../functional.nii .../atlas.nii' @@ -467,8 +467,8 @@ class CiftiCreateLabel(WBCommand): >>> from nibabies.interfaces import workbench as wb >>> lab = wb.CiftiCreateLabel() - >>> lab.inputs.volume_label = data_dir / "functional.nii" - >>> lab.inputs.structure_label_volume = data_dir / "functional.nii" + >>> lab.inputs.volume_label = testdir / "functional.nii" + >>> lab.inputs.structure_label_volume = testdir / "functional.nii" >>> lab.cmdline # doctest: +ELLIPSIS 'wb_command -cifti-create-label out.dlabel.nii -volume .../functional.nii .../functional.nii' """ @@ -940,9 +940,9 @@ class CiftiResample(WBCommand): >>> from nibabies.interfaces import workbench as wb >>> res = wb.CiftiResample() - >>> res.inputs.in_file = data_dir / "func.dtseries.nii" + >>> res.inputs.in_file = testdir / "func.dtseries.nii" >>> res.inputs.direction = "COLUMN" - >>> res.inputs.template = data_dir / "func.dlabel.nii" + >>> res.inputs.template = testdir / "func.dlabel.nii" >>> res.inputs.template_direction = "COLUMN" >>> res.inputs.surface_method = "ADAP_BARY_AREA" >>> res.inputs.volume_method = "CUBIC" @@ -1051,7 +1051,7 @@ class CiftiSeparate(WBCommand): dimension, columns for .dtseries. >>> separate = CiftiSeparate() - >>> separate.inputs.in_file = data_dir / "func.dtseries.nii" + >>> separate.inputs.in_file = testdir / "func.dtseries.nii" >>> separate.inputs.direction = "COLUMN" >>> separate.inputs.volume_all_file = "volume_all.nii.gz" >>> separate.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE @@ -1216,10 +1216,10 @@ class VolumeAffineResample(WBCommand): >>> from nibabies.interfaces.workbench import VolumeAffineResample >>> resample = VolumeAffineResample() - >>> resample.inputs.in_file = data_dir /'functional.nii' - >>> resample.inputs.volume_space = data_dir /'anatomical.nii' + >>> resample.inputs.in_file = testdir /'functional.nii' + >>> resample.inputs.volume_space = testdir /'anatomical.nii' >>> resample.inputs.method = 'CUBIC' - >>> resample.inputs.affine = data_dir / 'func_to_struct.mat' + >>> resample.inputs.affine = testdir / 'func_to_struct.mat' >>> resample.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -volume-resample .../functional.nii .../anatomical.nii CUBIC \ resampled_functional.nii.gz -affine .../func_to_struct.mat' @@ -1237,8 +1237,8 @@ class VolumeAffineResample(WBCommand): However, if other volumes were used to calculate the affine, they can be provided: - >>> resample.inputs.flirt_source_volume = data_dir / 'epi.nii' - >>> resample.inputs.flirt_target_volume = data_dir /'T1w.nii' + >>> resample.inputs.flirt_source_volume = testdir / 'epi.nii' + >>> resample.inputs.flirt_target_volume = testdir /'T1w.nii' >>> resample.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -volume-resample .../functional.nii .../anatomical.nii CUBIC \ resampled_functional.nii.gz -affine .../func_to_struct.mat \ @@ -1297,7 +1297,7 @@ class VolumeAllLabelsToROIs(WBCommand): >>> from nibabies.interfaces.workbench import VolumeAllLabelsToROIs >>> rois = VolumeAllLabelsToROIs() - >>> rois.inputs.in_file = data_dir / 'atlas.nii' + >>> rois.inputs.in_file = testdir / 'atlas.nii' >>> rois.inputs.label_map = 1 >>> rois.cmdline # doctest: +ELLIPSIS 'wb_command -volume-all-labels-to-rois .../atlas.nii 1 atlas_rois.nii.gz' @@ -1346,7 +1346,7 @@ class VolumeLabelExportTable(WBCommand): >>> from nibabies.interfaces.workbench import VolumeLabelExportTable >>> label_export = VolumeLabelExportTable() - >>> label_export.inputs.in_file = data_dir / 'atlas.nii' + >>> label_export.inputs.in_file = testdir / 'atlas.nii' >>> label_export.inputs.label_map = 1 >>> label_export.cmdline # doctest: +ELLIPSIS 'wb_command -volume-label-export-table .../atlas.nii 1 atlas_labels.txt' @@ -1434,8 +1434,8 @@ class VolumeLabelImport(WBCommand): >>> from nibabies.interfaces.workbench import VolumeLabelImport >>> label_import = VolumeLabelImport() - >>> label_import.inputs.in_file = data_dir / 'atlas.nii' - >>> label_import.inputs.label_list_file = data_dir / 'label_list.txt' + >>> label_import.inputs.in_file = testdir / 'atlas.nii' + >>> label_import.inputs.label_list_file = testdir / 'label_list.txt' >>> label_import.cmdline # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE 'wb_command -volume-label-import .../atlas.nii .../label_list.txt \ atlas_labels.nii.gz' diff --git a/nibabies/workflows/bold/alignment.py b/nibabies/workflows/bold/alignment.py index eda6ab82..5f4ee3a6 100644 --- a/nibabies/workflows/bold/alignment.py +++ b/nibabies/workflows/bold/alignment.py @@ -321,11 +321,11 @@ def parse_roi_labels(label_file: str): Return a list of structure names and label keys. - >>> structs, ids = parse_roi_labels(test_data / "labelfile.txt") + >>> structs, ids = parse_roi_labels(datadir / "FreeSurferSubcorticalLabelTableLut.txt") >>> structs - ['CEREBELLUM_LEFT', 'THALAMUS_LEFT', 'CAUDATE_LEFT'] + ['ACCUMBENS_LEFT', 'ACCUMBENS_RIGHT', 'AMYGDALA_LEFT', ...] >>> ids - [8, 10, 11] + [26, 58, 18, ...] """ with open(label_file) as fp: