diff --git a/docs/requirements.txt b/docs/requirements.txt index 32245b783f..a26c7ad188 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -11,3 +11,4 @@ sphinx_rtd_theme sphinxcontrib-apidoc ~= 0.3.0 templateflow networkx != 2.8.1 +acres diff --git a/pyproject.toml b/pyproject.toml index e8b8fbbc1f..b042c9d4b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,7 @@ classifiers = [ license = {file = "LICENSE"} requires-python = ">=3.10" dependencies = [ + "acres", "indexed_gzip >= 0.8.8", "lockfile", "looseversion", diff --git a/smriprep/cli/run.py b/smriprep/cli/run.py index 5510bcbb65..0f07a63788 100644 --- a/smriprep/cli/run.py +++ b/smriprep/cli/run.py @@ -471,7 +471,7 @@ def build_workflow(opts, retval): from niworkflows.utils.bids import collect_participants from ..__about__ import __version__ - from ..data import load_resource + from ..data import load from ..workflows.base import init_smriprep_wf logger = logging.getLogger('nipype.workflow') @@ -651,7 +651,7 @@ def build_workflow(opts, retval): boilerplate, ) - boilerplate_bib = load_resource('boilerplate.bib') + boilerplate_bib = load('boilerplate.bib') # Generate HTML file resolving citations cmd = [ diff --git a/smriprep/conftest.py b/smriprep/conftest.py index ea8e2bf743..a85ba7e066 100644 --- a/smriprep/conftest.py +++ b/smriprep/conftest.py @@ -3,7 +3,7 @@ import numpy as np import pytest -from smriprep.data import load_resource +from smriprep.data import load os.environ['NO_ET'] = '1' @@ -12,5 +12,5 @@ def _populate_namespace(doctest_namespace, tmp_path): doctest_namespace['os'] = os doctest_namespace['np'] = np - doctest_namespace['load'] = load_resource + doctest_namespace['load'] = load doctest_namespace['testdir'] = tmp_path diff --git a/smriprep/data/__init__.py b/smriprep/data/__init__.py index 5cc3f3426d..9dbc26f244 100644 --- a/smriprep/data/__init__.py +++ b/smriprep/data/__init__.py @@ -1,25 +1,3 @@ -import atexit -from contextlib import ExitStack -from pathlib import Path +from acres import Loader -try: - from functools import cache -except ImportError: # PY38 - from functools import lru_cache as cache - -try: # Prefer backport to leave consistency to dependency spec - from importlib_resources import as_file, files -except ImportError: - from importlib.resources import as_file, files - -__all__ = ['load_resource'] - -exit_stack = ExitStack() -atexit.register(exit_stack.close) - -path = files(__package__) - - -@cache -def load_resource(fname: str) -> Path: - return exit_stack.enter_context(as_file(path.joinpath(fname))) +load = Loader(__package__) diff --git a/smriprep/interfaces/tests/data/__init__.py b/smriprep/interfaces/tests/data/__init__.py new file mode 100644 index 0000000000..9dbc26f244 --- /dev/null +++ b/smriprep/interfaces/tests/data/__init__.py @@ -0,0 +1,3 @@ +from acres import Loader + +load = Loader(__package__) diff --git a/smriprep/interfaces/tests/test_surf.py b/smriprep/interfaces/tests/test_surf.py index 54335d1a1e..e1473fe128 100644 --- a/smriprep/interfaces/tests/test_surf.py +++ b/smriprep/interfaces/tests/test_surf.py @@ -2,19 +2,15 @@ import numpy as np from nipype.pipeline import engine as pe -from ...data import load_resource +from smriprep.interfaces.tests.data import load + from ..surf import MakeRibbon def test_MakeRibbon(tmp_path): - res_template = '{path}/sub-fsaverage_res-4_hemi-{hemi}_desc-cropped_{surf}dist.nii.gz' + res_template = 'sub-fsaverage_res-4_hemi-{hemi}_desc-cropped_{surf}dist.nii.gz' white, pial = ( - [ - load_resource( - res_template.format(path='../interfaces/tests/data', hemi=hemi, surf=surf) - ) - for hemi in 'LR' - ] + [load(res_template.format(hemi=hemi, surf=surf)) for hemi in 'LR'] for surf in ('wm', 'pial') ) @@ -27,9 +23,7 @@ def test_MakeRibbon(tmp_path): result = make_ribbon.run() ribbon = nb.load(result.outputs.ribbon) - expected = nb.load( - load_resource('../interfaces/tests/data/sub-fsaverage_res-4_desc-cropped_ribbon.nii.gz') - ) + expected = nb.load(load('sub-fsaverage_res-4_desc-cropped_ribbon.nii.gz')) assert ribbon.shape == expected.shape assert np.allclose(ribbon.affine, expected.affine) diff --git a/smriprep/utils/bids.py b/smriprep/utils/bids.py index 958cffa33b..5e1c679310 100644 --- a/smriprep/utils/bids.py +++ b/smriprep/utils/bids.py @@ -28,13 +28,13 @@ from bids.layout import BIDSLayout from niworkflows.data import load as nwf_load -from ..data import load_resource +from ..data import load def collect_derivatives(derivatives_dir, subject_id, std_spaces, spec=None, patterns=None): """Gather existing derivatives and compose a cache.""" if spec is None or patterns is None: - _spec, _patterns = tuple(loads(load_resource('io_spec.json').read_text()).values()) + _spec, _patterns = tuple(loads(load('io_spec.json').read_text()).values()) if spec is None: spec = _spec @@ -96,11 +96,11 @@ def write_derivative_description(bids_dir, deriv_dir): .. testsetup:: - >>> from smriprep.data import load_resource + >>> from smriprep.data import load >>> from pathlib import Path >>> from tempfile import TemporaryDirectory >>> tmpdir = TemporaryDirectory() - >>> bids_dir = load_resource('tests') + >>> bids_dir = load('tests') >>> deriv_desc = Path(tmpdir.name) / 'dataset_description.json' .. doctest:: diff --git a/smriprep/utils/tests/__init__.py b/smriprep/utils/tests/__init__.py index 84a88300dc..2978572d1e 100644 --- a/smriprep/utils/tests/__init__.py +++ b/smriprep/utils/tests/__init__.py @@ -1,4 +1,4 @@ -from niworkflows.data import Loader +from acres import Loader load_data = Loader(__package__) diff --git a/smriprep/workflows/anatomical.py b/smriprep/workflows/anatomical.py index 005cf047eb..113df4360e 100644 --- a/smriprep/workflows/anatomical.py +++ b/smriprep/workflows/anatomical.py @@ -54,7 +54,7 @@ from niworkflows.utils.misc import add_suffix from niworkflows.utils.spaces import Reference, SpatialReferences -from ..data import load_resource +from ..data import load from ..interfaces import DerivativesDataSink from ..utils.misc import apply_lut as _apply_bids_lut from ..utils.misc import fs_isRunning as _fs_isRunning @@ -1461,7 +1461,7 @@ def init_anat_template_wf( if num_files == 1: get1st = pe.Node(niu.Select(index=[0]), name='get1st') - outputnode.inputs.anat_realign_xfm = [str(load_resource('itkIdentityTransform.txt'))] + outputnode.inputs.anat_realign_xfm = [str(load('itkIdentityTransform.txt'))] # fmt:off workflow.connect([ diff --git a/smriprep/workflows/surfaces.py b/smriprep/workflows/surfaces.py index c2a43b4f73..941da71119 100644 --- a/smriprep/workflows/surfaces.py +++ b/smriprep/workflows/surfaces.py @@ -56,7 +56,7 @@ from smriprep.interfaces.surf import MakeRibbon from smriprep.interfaces.workbench import SurfaceResample -from ..data import load_resource +from ..data import load from ..interfaces.freesurfer import MakeMidthickness, ReconAll from ..interfaces.gifti import MetricMath from ..interfaces.workbench import CreateSignedDistanceVolume @@ -723,7 +723,7 @@ def init_fsLR_reg_wf(*, name='fsLR_reg_wf'): iterfield=['sphere_in', 'sphere_project_to', 'sphere_unproject_from'], name='project_unproject', ) - atlases = load_resource('atlases') + atlases = load('atlases') project_unproject.inputs.sphere_project_to = [ atlases / 'fs_L' / 'fsaverage.L.sphere.164k_fs_L.surf.gii', atlases / 'fs_R' / 'fsaverage.R.sphere.164k_fs_R.surf.gii', @@ -804,8 +804,8 @@ def init_msm_sulc_wf(*, sloppy: bool = False, name: str = 'msm_sulc_wf'): # --indata=sub-${SUB}_ses-${SES}_hemi-${HEMI)_sulc.shape.gii \ # --refdata=tpl-fsaverage_hemi-${HEMI}_den-164k_sulc.shape.gii \ # --out=${HEMI}. --verbose - atlases = load_resource('atlases') - msm_conf = load_resource(f'msm/MSMSulcStrain{"Sloppy" if sloppy else "Final"}conf') + atlases = load('atlases') + msm_conf = load(f'msm/MSMSulcStrain{"Sloppy" if sloppy else "Final"}conf') msmsulc = pe.MapNode( MSM(verbose=True, config_file=msm_conf), iterfield=['in_mesh', 'reference_mesh', 'in_data', 'reference_data', 'out_base'], @@ -1512,7 +1512,7 @@ def init_morph_grayords_wf( name='outputnode', ) - atlases = load_resource('atlases') + atlases = load('atlases') select_surfaces = pe.Node( KeySelect( fields=[ diff --git a/smriprep/workflows/tests/test_surfaces.py b/smriprep/workflows/tests/test_surfaces.py index d768328fe7..9831fb1815 100644 --- a/smriprep/workflows/tests/test_surfaces.py +++ b/smriprep/workflows/tests/test_surfaces.py @@ -7,7 +7,8 @@ import pytest from nipype.pipeline import engine as pe -from ...data import load_resource +from smriprep.interfaces.tests.data import load + from ..surfaces import init_anat_ribbon_wf, init_gifti_surfaces_wf @@ -23,9 +24,7 @@ def test_ribbon_workflow(tmp_path: Path): # Low-res file that includes the fsaverage surfaces in its bounding box # We will use it both as a template and a comparison. - test_ribbon = load_resource( - '../interfaces/tests/data/sub-fsaverage_res-4_desc-cropped_ribbon.nii.gz' - ) + test_ribbon = load('sub-fsaverage_res-4_desc-cropped_ribbon.nii.gz') gifti_surfaces_wf = init_gifti_surfaces_wf(surfaces=['white', 'pial']) anat_ribbon_wf = init_anat_ribbon_wf()