From f8ec76dbd3a7088499e9839f7ff74f6c4ae6764e Mon Sep 17 00:00:00 2001 From: esavary Date: Tue, 12 Mar 2024 14:43:20 +0100 Subject: [PATCH 01/16] maint: migrate to PEP517/518 packaging --- .circleci/config.yml | 3 +- .github/workflows/pythonpackage.yml | 11 +- .maint/update_requirements.py | 44 +++++++ MANIFEST.in | 12 -- min-requirements.txt | 10 ++ pyproject.toml | 194 ++++++++++++++++++++++++++-- requirements.txt | 10 ++ setup.cfg | 125 ------------------ setup.py | 7 - 9 files changed, 250 insertions(+), 166 deletions(-) create mode 100644 .maint/update_requirements.py delete mode 100644 MANIFEST.in create mode 100644 min-requirements.txt create mode 100644 requirements.txt delete mode 100755 setup.cfg delete mode 100644 setup.py diff --git a/.circleci/config.yml b/.circleci/config.yml index 0c171241..bf707248 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -74,8 +74,7 @@ jobs: - run: name: Initiate versioning command: | - python -m pip install -U build "setuptools >= 45" wheel "setuptools_scm >= 6.2" \ - setuptools_scm_git_archive pip twine docutils + python3 -m pip install -U build hatch hatchling pip twine docutils pip install /tmp/src/eddymotion[all] diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index b3b6a132..4ea62c34 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -39,8 +39,7 @@ jobs: run: | python -m venv /tmp/buildenv source /tmp/buildenv/bin/activate - python -m pip install -U build "setuptools >= 45" wheel "setuptools_scm >= 6.2" \ - setuptools_scm_git_archive pip twine docutils + pip install -U build hatch hatchling pip twine docutils python -m build -s -w python -m twine check dist/eddymotion-* @@ -52,7 +51,7 @@ jobs: if [[ "$GITHUB_REF" == refs/tags/* ]]; then TAG=${GITHUB_REF##*/} fi - THISVERSION=$( python -m setuptools_scm ) + THISVERSION=$( python -m hatch version | tail -n1 | xargs ) THISVERSION=${TAG:-$THISVERSION} echo "Expected VERSION: \"${THISVERSION}\"" echo "THISVERSION=${THISVERSION}" >> $GITHUB_ENV @@ -61,7 +60,7 @@ jobs: run: | python -m venv /tmp/pip source /tmp/pip/bin/activate - python -m pip install -U "setuptools >= 45" "setuptools_scm >= 6.2" "${{ matrix.pip }}" + python -m pip install -U build hatch hatchling pip twine docutils python -m pip install . INSTALLED_VERSION=$(python -c 'import eddymotion as em; print(em.__version__, end="")') echo "VERSION: \"${THISVERSION}\"" @@ -72,7 +71,7 @@ jobs: run: | python -m venv /tmp/install_sdist source /tmp/install_sdist/bin/activate - python -m pip install -U "setuptools >= 45" "${{ matrix.pip }}" + python -m pip install -U build hatch hatchling pip twine docutils python -m pip install /tmp/package/eddymotion*.tar.gz INSTALLED_VERSION=$(python -c 'import eddymotion as em; print(em.__version__, end="")') echo "VERSION: \"${THISVERSION}\"" @@ -83,7 +82,7 @@ jobs: run: | python -m venv /tmp/install_wheel source /tmp/install_wheel/bin/activate - python -m pip install -U "setuptools >= 45" "${{ matrix.pip }}" + python -m pip install -U build hatch hatchling pip twine docutils python -m pip install /tmp/package/eddymotion*.whl INSTALLED_VERSION=$(python -c 'import eddymotion as em; print(em.__version__, end="")') echo "INSTALLED: \"${INSTALLED_VERSION}\"" diff --git a/.maint/update_requirements.py b/.maint/update_requirements.py new file mode 100644 index 00000000..d8695f79 --- /dev/null +++ b/.maint/update_requirements.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +from copy import copy +from pathlib import Path +from packaging.requirements import Requirement, SpecifierSet + +try: + from tomllib import loads # Python +3.11 +except ImportError: + from pip._vendor.tomli import loads + +repo_root = Path(__file__).parent.parent +pyproject = repo_root / "pyproject.toml" +reqs = repo_root / "requirements.txt" +min_reqs = repo_root / "min-requirements.txt" + +requirements = [ + Requirement(req) + for req in loads(pyproject.read_text())["project"]["dependencies"] +] + +script_name = Path(__file__).relative_to(repo_root) + + +def to_min(req): + if req.specifier: + req = copy(req) + try: + min_spec = [spec for spec in req.specifier if spec.operator in (">=", "~=")][0] + except IndexError: + return req + min_spec._spec = ("==",) + min_spec._spec[1:] + req.specifier = SpecifierSet(str(min_spec)) + return req + + +lines = [f"# Auto-generated by {script_name}", ""] + +# Write requirements +lines[1:-1] = [str(req) for req in requirements] +reqs.write_text("\n".join(lines)) + +# Write minimum requirements +lines[1:-1] = [str(to_min(req)) for req in requirements] +min_reqs.write_text("\n".join(lines)) \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 86f118e6..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,12 +0,0 @@ -recursive-exclude .circleci/ * -recursive-exclude .docker/ * -recursive-exclude .github/ * -recursive-exclude .git/ * -recursive-exclude .maint/ * -recursive-exclude docs/ * -recursive-exclude test/ * - -exclude .* -exclude Dockerfile - -recursive-include src/eddymotion/config *.* diff --git a/min-requirements.txt b/min-requirements.txt new file mode 100644 index 00000000..e8efba90 --- /dev/null +++ b/min-requirements.txt @@ -0,0 +1,10 @@ +# Auto-generated by .maint/update_requirements.py +dipy==1.3.0 +joblib +nipype==1.5.1 +nitransforms==21.0.0 +nireports +numpy==1.17.3 +nest-asyncio==1.5.1 +scikit-image==0.14.2 +scipy==1.8.0 diff --git a/pyproject.toml b/pyproject.toml index 78a60e81..0f69adf0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,15 +1,181 @@ [build-system] -requires = [ - "setuptools >= 45", - "setuptools_scm[toml] >= 6.2", - "wheel" -] -build-backend = "setuptools.build_meta" - -[tool.setuptools_scm] -write_to = "src/eddymotion/_version.py" -write_to_template = """\ -\"\"\"Version file, automatically generated by setuptools_scm.\"\"\" -__version__ = "{version}" -""" -fallback_version = "0.0" +requires = ["hatchling", "hatch-vcs", "nipreps-versions"] +build-backend = "hatchling.build" + +[project] +name = "eddymotion" +description = "Pure python eddy-current and head-motion correction for dMRI, an extension of QSIprep's SHOREline algorithm (Cieslak, 2020) to multiple diffusion models." +readme = "README.rst" +authors = [{name = "The NiPreps Developers", email = "nipreps@gmail.com"}] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering :: Image Recognition", + "License :: OSI Approved :: Apache Software License", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", +] +license = "Apache-2.0" +requires-python = ">=3.8" +dependencies = [ + "dipy>=1.3.0", + "joblib", + "nipype>= 1.5.1, < 2.0", + "nitransforms>=21.0.0", + "nireports", + "numpy>=1.17.3", + "nest-asyncio>=1.5.1", + "scikit-image>=0.14.2", + "scipy>=1.8.0", +] +dynamic = ["version"] + +[project.urls] +Documentation = "https://www.nipreps.org/eddymotion" +Home = "https://github.com/nipreps/eddymotion" +NiPreps = "https://www.nipreps.org/" + +[project.optional-dependencies] +doc = [ + "nbsphinx", + "packaging", + "pydot >= 1.2.3", + "pydotplus", + "sphinx >= 2.1.2", + "sphinx-argparse", + "sphinx_rtd_theme", + "sphinxcontrib-apidoc ~= 0.3.0", + "sphinxcontrib-napoleon", + "sphinxcontrib-versioning" +] + +dev = [ + "black~=22.3", + "flake8~=4.0", + "isort~=5.10", + "pre-commit", + "pre-commit-hooks", +] + +plotting = ["nilearn"] + +resmon = ["psutil >=5.4"] + +popylar = ["popylar >= 0.2"] + +test = [ + "coverage", + "pytest >= 4.4", + "pytest-cov", + "pytest-env", + "pytest-xdist >= 1.28" +] + +# Aliases +docs = ["eddymotion[doc]"] +tests = ["eddymotion[test]"] +all = ["eddymotion[doc,test,dev,plotting,resmon,popylar]"] + +[project.scripts] +sdcflows-find-estimators = "sdcflows.cli.find_estimators:main" + +# +# Hatch configurations +# + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.sdist] +exclude = [".git_archival.txt"] # No longer needed in sdist + +[tool.hatch.build.targets.wheel] +packages = ["eddymotion"] +# exclude = [ +# "sdcflows/tests/data", # Large test data directory +# ] + + +[tool.hatch.version] +validate-bump = true +source = "vcs" +raw-options = { version_scheme = "nipreps-calver" } + +[tool.hatch.build.hooks.vcs] +version-file = "src/eddymotion/_version.py" + +# +# Developer tool configurations +# + +[tool.black] +line-length = 99 +target-version = ['py39'] +skip-string-normalization = true +exclude = ''' +# Directories +/( + \.eggs + | \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | venv + | _build + | build + | dist +)/ +''' + +[tool.isort] +profile = 'black' +skip_gitignore = true + +[tool.flake8] +max-line-length = 99 +doctests = false +exclude = ["*build/", "docs/"] +select = "C,E,F,W,B,B950" +ignore = "N802,N806,W503,E203" +per-file-ignores = [ + "*/__init__.py: F401", + "docs/conf.py: E265", + "/^\\s*\\.\\. _.*?: http/: E501" +] + +[tool.pytest.ini_options] +pythonpath = "src/ test/" +norecursedirs = [".*", "_*"] +addopts = "-v --doctest-modules" +doctest_optionflags = "ALLOW_UNICODE NORMALIZE_WHITESPACE" +env = "PYTHONHASHSEED=0" +filterwarnings = ["ignore::DeprecationWarning"] + + +[tool.coverage.run] +branch = true +concurrency = 'multiprocessing' +omit = [ + '*/tests/*', + '*/__init__.py', + '*/conftest.py', + 'eddymotion/_version.py' +] + +[tool.coverage.report] +# Regexes for lines to exclude from consideration +exclude_lines = [ + 'raise NotImplementedError', + 'warnings\.warn', +] + +[tool.codespell] +# nd - import scipy.ndimage as nd +# mapp, reson -- Mapp. and Reson. abbreviations in citation +ignore-words-list = 'nd,mapp,reson' +skip = """ +./.git,*.pdf,*.svg,*.min.js,*.ipynb,ORIGINAL_LICENSE,\ +./docs/source/_static/example_anatreport.html""" diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..437d9d14 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,10 @@ +# Auto-generated by .maint/update_requirements.py +dipy>=1.3.0 +joblib +nipype<2.0,>=1.5.1 +nitransforms>=21.0.0 +nireports +numpy>=1.17.3 +nest-asyncio>=1.5.1 +scikit-image>=0.14.2 +scipy>=1.8.0 diff --git a/setup.cfg b/setup.cfg deleted file mode 100755 index c75129a8..00000000 --- a/setup.cfg +++ /dev/null @@ -1,125 +0,0 @@ -[metadata] -name = eddymotion -author = Derek Pisner -author_email = nipreps@gmail.com -classifiers = - Development Status :: 3 - Alpha - Intended Audience :: Science/Research - Topic :: Scientific/Engineering :: Image Recognition - License :: OSI Approved :: Apache Software License - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 -description = Pure python eddy-current and head-motion correction for dMRI, an extension of QSIprep's SHOREline algorithm (Cieslak, 2020) to multiple diffusion models. -license = Apache License, Version 2.0 -long_description = file:README.rst -long_description_content_type = text/x-rst; charset=UTF-8 -maintainers = The NiPreps developers -maintainer_email = nipreps@gmail.com, dpysalexander@gmail.com -url = https://github.com/nipreps/eddymotion - -[options] -python_requires = >=3.8 -setup_requires = - setuptools >= 45 - setuptools_scm >= 6.2 - wheel -install_requires = - dipy>=1.3.0 - joblib - nipype>= 1.5.1, < 2.0 - nitransforms>=21.0.0 - nireports - numpy>=1.17.3 - nest-asyncio>=1.5.1 - scikit-image>=0.14.2 - scipy>=1.8.0 -test_requires = - codecov - coverage - pytest -packages = find_namespace: -package_dir= - = src -include_package_data = True -zip_safe = True - -[options.packages.find] -where = src -include = eddymotion* -exclude = - test - test.* - -[options.package_data] -eddymotion.config = - *.json - -[options.exclude_package_data] -* = test - -[options.extras_require] -doc = - nbsphinx - packaging - pydot >= 1.2.3 - pydotplus - sphinx >= 2.1.2 - sphinx-argparse - sphinx_rtd_theme - sphinxcontrib-apidoc ~= 0.3.0 - sphinxcontrib-napoleon - sphinxcontrib-versioning -docs = - %(doc)s -plotting = nilearn -resmon = psutil >=5.4 -popylar = popylar >= 0.2 -style = - flake8 >= 3.7.0 -test = - pytest >= 4.4 - pytest-xdist >= 1.28 - pytest-env - pytest-cov - coverage -tests = - %(test)s -dev = - black~=22.3 - flake8~=4.0 - isort~=5.10 - pre-commit - pre-commit-hooks - %(docs)s - %(test)s -all = - %(doc)s - %(resmon)s - %(popylar)s - %(tests)s - %(dev)s - -[flake8] -max-line-length = 99 -doctests = False -exclude= - *build/ - docs/ -select = C,E,F,W,B,B950 -ignore = N802,N806,W503,E203 -putty-ignore = - */__init__.py : +F401 - docs/conf.py : +E265 - /^\s*\.\. _.*?: http/ : +E501 - -[tool:pytest] -pythonpath = src/ test/ -norecursedirs = .* _* -addopts = -v --doctest-modules -doctest_optionflags = ALLOW_UNICODE NORMALIZE_WHITESPACE -env = - PYTHONHASHSEED=0 -filterwarnings = - ignore::DeprecationWarning diff --git a/setup.py b/setup.py deleted file mode 100644 index 5c773cf1..00000000 --- a/setup.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -"""eddymotion's PEP518 setup.py shim.""" -from setuptools import setup - -if __name__ == "__main__": - """ Install entry-point """ - setup() From afdd6f861d11ee24a8484e1e23a54cb2a658a41b Mon Sep 17 00:00:00 2001 From: esavary Date: Tue, 12 Mar 2024 16:05:48 +0100 Subject: [PATCH 02/16] fix : update docs build update and docs build PR --- .github/workflows/docs-build-pr.yml | 4 ++-- .github/workflows/docs-build-update.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs-build-pr.yml b/.github/workflows/docs-build-pr.yml index 48faa369..1681063c 100644 --- a/.github/workflows/docs-build-pr.yml +++ b/.github/workflows/docs-build-pr.yml @@ -39,10 +39,10 @@ jobs: - name: Install dependencies run: | - pip install --no-cache-dir "setuptools >= 45.0" "setuptools_scm[toml] >= 6.2" + pip install -U build hatch hatchling pip twine docutils pip install -r docs/requirements.txt + python -m hatch version | tail -n1 | xargs - name: Build docs run: | - python -m setuptools_scm # Generate _version.py file make -C docs/ SPHINXOPTS="-W" BUILDDIR="$HOME/docs" OUTDIR="${CURBRANCH:-html}" html diff --git a/.github/workflows/docs-build-update.yml b/.github/workflows/docs-build-update.yml index bf73fa7c..90c2faf3 100644 --- a/.github/workflows/docs-build-update.yml +++ b/.github/workflows/docs-build-update.yml @@ -42,12 +42,12 @@ jobs: - name: Install dependencies run: | - pip install --no-cache-dir "setuptools >= 45.0" "setuptools_scm[toml] >= 6.2" + pip install -U build hatch hatchling pip twine docutils pip install -r docs/requirements.txt + python -m hatch version | tail -n1 | xargs - name: Build docs run: | - python -m setuptools_scm # Generate _version.py file make -C docs/ SPHINXOPTS="-W" BUILDDIR="$HOME/docs" OUTDIR="${CURBRANCH:-html}" html - name: Push created tag to gh-pages From e4b5b6fb773471be0d9cfdeac9de9c34692dd512 Mon Sep 17 00:00:00 2001 From: esavary Date: Thu, 14 Mar 2024 17:30:29 +0100 Subject: [PATCH 03/16] fix: package path --- pyproject.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0f69adf0..9032f83a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,6 +2,7 @@ requires = ["hatchling", "hatch-vcs", "nipreps-versions"] build-backend = "hatchling.build" + [project] name = "eddymotion" description = "Pure python eddy-current and head-motion correction for dMRI, an extension of QSIprep's SHOREline algorithm (Cieslak, 2020) to multiple diffusion models." @@ -92,9 +93,9 @@ allow-direct-references = true exclude = [".git_archival.txt"] # No longer needed in sdist [tool.hatch.build.targets.wheel] -packages = ["eddymotion"] +packages = ["src/eddymotion"] # exclude = [ -# "sdcflows/tests/data", # Large test data directory +# "eddymotion/tests/data", # Large test data directory # ] @@ -162,7 +163,7 @@ omit = [ '*/tests/*', '*/__init__.py', '*/conftest.py', - 'eddymotion/_version.py' + 'src/eddymotion/_version.py' ] [tool.coverage.report] From 238fb09af0bee055cd468c254ea4411d1c7ac517 Mon Sep 17 00:00:00 2001 From: esavary Date: Tue, 19 Mar 2024 15:09:43 +0100 Subject: [PATCH 04/16] fix: remove unused line --- pyproject.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9032f83a..039a9e6e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -79,9 +79,6 @@ docs = ["eddymotion[doc]"] tests = ["eddymotion[test]"] all = ["eddymotion[doc,test,dev,plotting,resmon,popylar]"] -[project.scripts] -sdcflows-find-estimators = "sdcflows.cli.find_estimators:main" - # # Hatch configurations # From 4b8eb77cb5bfacf503ed88c4843b26d2632d3e57 Mon Sep 17 00:00:00 2001 From: esavary Date: Tue, 19 Mar 2024 15:57:36 +0100 Subject: [PATCH 05/16] sty: black + flake8 --- .maint/update_requirements.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.maint/update_requirements.py b/.maint/update_requirements.py index d8695f79..cd797ef3 100644 --- a/.maint/update_requirements.py +++ b/.maint/update_requirements.py @@ -25,7 +25,11 @@ def to_min(req): if req.specifier: req = copy(req) try: - min_spec = [spec for spec in req.specifier if spec.operator in (">=", "~=")][0] + min_spec = [ + spec + for spec in req.specifier + if spec.operator in (">=", "~=") + ][0] except IndexError: return req min_spec._spec = ("==",) + min_spec._spec[1:] @@ -41,4 +45,4 @@ def to_min(req): # Write minimum requirements lines[1:-1] = [str(to_min(req)) for req in requirements] -min_reqs.write_text("\n".join(lines)) \ No newline at end of file +min_reqs.write_text("\n".join(lines)) From ea1d68d56df76b2de73c12b191e9c2c847b16394 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 12:09:56 -0400 Subject: [PATCH 06/16] MNT: Remove linter/formatter pins, add flake8-pyproject --- pyproject.toml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 039a9e6e..631f94a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,9 +53,10 @@ doc = [ ] dev = [ - "black~=22.3", - "flake8~=4.0", - "isort~=5.10", + "black", + "flake8", + "flake8-pyproject", + "isort", "pre-commit", "pre-commit-hooks", ] From dd88ede56fec6a4eb82bbf4dcfe586f6254810b2 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 12:11:43 -0400 Subject: [PATCH 07/16] MNT: Rerun black/isort --- src/eddymotion/__init__.py | 4 +--- src/eddymotion/data/dmri.py | 4 +--- src/eddymotion/data/pet.py | 4 +--- src/eddymotion/data/utils.py | 4 +--- src/eddymotion/estimator.py | 18 +++++---------- src/eddymotion/model/__init__.py | 4 ++-- src/eddymotion/model/base.py | 39 ++++++++++++-------------------- src/eddymotion/viz.py | 22 ++++++++---------- 8 files changed, 35 insertions(+), 64 deletions(-) diff --git a/src/eddymotion/__init__.py b/src/eddymotion/__init__.py index 90e1b6f0..dd1f0ac7 100644 --- a/src/eddymotion/__init__.py +++ b/src/eddymotion/__init__.py @@ -27,6 +27,4 @@ __copyright__ = "Copyright 2021, The eddymotion developers" __url__ = "https://github.com/nipreps/EddyMotionCorrection" -DOWNLOAD_URL = ( - f"https://github.com/nipreps/{__packagename__}/archive/{__version__}.tar.gz" -) +DOWNLOAD_URL = f"https://github.com/nipreps/{__packagename__}/archive/{__version__}.tar.gz" diff --git a/src/eddymotion/data/dmri.py b/src/eddymotion/data/dmri.py index dfefd01a..55d634a5 100644 --- a/src/eddymotion/data/dmri.py +++ b/src/eddymotion/data/dmri.py @@ -228,9 +228,7 @@ def from_filename(cls, filename): """Read an HDF5 file from disk.""" with h5py.File(filename, "r") as in_file: root = in_file["/0"] - data = { - k: np.asanyarray(v) for k, v in root.items() if not k.startswith("_") - } + data = {k: np.asanyarray(v) for k, v in root.items() if not k.startswith("_")} return cls(**data) diff --git a/src/eddymotion/data/pet.py b/src/eddymotion/data/pet.py index 44a97b89..4591962d 100644 --- a/src/eddymotion/data/pet.py +++ b/src/eddymotion/data/pet.py @@ -132,9 +132,7 @@ def from_filename(cls, filename): """Read an HDF5 file from disk.""" with h5py.File(filename, "r") as in_file: root = in_file["/0"] - data = { - k: np.asanyarray(v) for k, v in root.items() if not k.startswith("_") - } + data = {k: np.asanyarray(v) for k, v in root.items() if not k.startswith("_")} return cls(**data) diff --git a/src/eddymotion/data/utils.py b/src/eddymotion/data/utils.py index 4d5e00d3..07cdd329 100644 --- a/src/eddymotion/data/utils.py +++ b/src/eddymotion/data/utils.py @@ -28,9 +28,7 @@ def apply_affines(nii, em_affines, output_filename=None): for ii, bvecnii in enumerate(nib.four_to_three(nii)): xfms = nt.linear.Affine(em_affines[ii]) - transformed_nii[..., ii] = np.asanyarray( - (~xfms).apply(bvecnii, reference=nii).dataobj - ) + transformed_nii[..., ii] = np.asanyarray((~xfms).apply(bvecnii, reference=nii).dataobj) nii_t_img = nii.__class__(transformed_nii, nii.affine, nii.header) diff --git a/src/eddymotion/estimator.py b/src/eddymotion/estimator.py index 7efff9d0..137b6dba 100644 --- a/src/eddymotion/estimator.py +++ b/src/eddymotion/estimator.py @@ -95,18 +95,16 @@ def fit( n_iter = len(models) for i_iter, model in enumerate(models): reg_target_type = ( - "dwi" - if model.lower() not in ("b0", "s0", "avg", "average", "mean") - else "b0" + "dwi" if model.lower() not in ("b0", "s0", "avg", "average", "mean") else "b0" ) # When downsampling these need to be set per-level bmask_img = None if dwdata.brainmask is not None: _, bmask_img = mkstemp(suffix="_bmask.nii.gz") - nb.Nifti1Image( - dwdata.brainmask.astype("uint8"), dwdata.affine, None - ).to_filename(bmask_img) + nb.Nifti1Image(dwdata.brainmask.astype("uint8"), dwdata.affine, None).to_filename( + bmask_img + ) kwargs["mask"] = dwdata.brainmask if hasattr(dwdata, "bzero") and dwdata.bzero is not None: @@ -203,9 +201,7 @@ def fit( if bmask_img: registration.inputs.fixed_image_masks = ["NULL", bmask_img] - if dwdata.em_affines is not None and np.any( - dwdata.em_affines[i, ...] - ): + if dwdata.em_affines is not None and np.any(dwdata.em_affines[i, ...]): reference = namedtuple("ImageGrid", ("shape", "affine"))( shape=dwdata.dataobj.shape[:3], affine=dwdata.affine ) @@ -243,9 +239,7 @@ def fit( return dwdata.em_affines -def _advanced_clip( - data, p_min=35, p_max=99.98, nonnegative=True, dtype="int16", invert=False -): +def _advanced_clip(data, p_min=35, p_max=99.98, nonnegative=True, dtype="int16", invert=False): """ Remove outliers at both ends of the intensity distribution and fit into a given dtype. diff --git a/src/eddymotion/model/__init__.py b/src/eddymotion/model/__init__.py index e2eb4565..7e32df8b 100644 --- a/src/eddymotion/model/__init__.py +++ b/src/eddymotion/model/__init__.py @@ -22,12 +22,12 @@ # """Data models.""" from eddymotion.model.base import ( - ModelFactory, AverageDWModel, DKIModel, DTIModel, - TrivialB0Model, + ModelFactory, PETModel, + TrivialB0Model, ) __all__ = ( diff --git a/src/eddymotion/model/base.py b/src/eddymotion/model/base.py index e0e8d2e9..fe8aca40 100644 --- a/src/eddymotion/model/base.py +++ b/src/eddymotion/model/base.py @@ -22,9 +22,10 @@ # """A factory class that adapts DIPY's dMRI models.""" import warnings -from joblib import Parallel, delayed + import numpy as np from dipy.core.gradients import gradient_table +from joblib import Parallel, delayed def _exec_fit(model, data, chunk=None): @@ -97,7 +98,11 @@ def __init__(self, gtab, S0=None, mask=None, b_max=None, **kwargs): # Setup B0 map self._S0 = None if S0 is not None: - self._S0 = np.clip(S0.astype("float32") / S0.max(), a_min=1e-5, a_max=1.0,) + self._S0 = np.clip( + S0.astype("float32") / S0.max(), + a_min=1e-5, + a_max=1.0, + ) # Setup brain mask self._mask = mask @@ -124,9 +129,7 @@ def __init__(self, gtab, S0=None, mask=None, b_max=None, **kwargs): from importlib import import_module module_name, class_name = model_str.rsplit(".", 1) - self._model = getattr( - import_module(module_name), class_name - )(_rasb2dipy(gtab), **kwargs) + self._model = getattr(import_module(module_name), class_name)(_rasb2dipy(gtab), **kwargs) def fit(self, data, n_jobs=None, **kwargs): """Fit the model chunk-by-chunk asynchronously""" @@ -136,9 +139,7 @@ def fit(self, data, n_jobs=None, **kwargs): # Select voxels within mask or just unravel 3D if no mask data = ( - data[self._mask, ...] - if self._mask is not None - else data.reshape(-1, data.shape[-1]) + data[self._mask, ...] if self._mask is not None else data.reshape(-1, data.shape[-1]) ) # One single CPU - linear execution (full model) @@ -154,8 +155,7 @@ def fit(self, data, n_jobs=None, **kwargs): # Parallelize process with joblib with Parallel(n_jobs=n_jobs) as executor: results = executor( - delayed(_exec_fit)(self._model, dchunk, i) - for i, dchunk in enumerate(data_chunks) + delayed(_exec_fit)(self._model, dchunk, i) for i, dchunk in enumerate(data_chunks) ) for submodel, index in results: self._models[index] = submodel @@ -182,10 +182,7 @@ def predict(self, gradient, **kwargs): if n_models == 1: predicted, _ = _exec_predict(self._model, gradient, S0=S0, **kwargs) else: - S0 = ( - np.array_split(S0, n_models) if S0 is not None - else [None] * n_models - ) + S0 = np.array_split(S0, n_models) if S0 is not None else [None] * n_models predicted = [None] * n_models @@ -345,10 +342,7 @@ def fit(self, data, *args, **kwargs): self._shape = data.shape[:3] # Convert data into V (voxels) x T (timepoints) - data = ( - data.reshape((-1, data.shape[-1])) - if self._mask is None else data[self._mask] - ) + data = data.reshape((-1, data.shape[-1])) if self._mask is None else data[self._mask] # A.shape = (T, K - 4); T= n. timepoints, K= n. knots (with padding) A = BSpline.design_matrix(x, self._t, k=self._order) @@ -357,17 +351,12 @@ def fit(self, data, *args, **kwargs): # One single CPU - linear execution (full model) if n_jobs == 1: - self._coeff = np.array([ - cg(ATdotA, AT @ v)[0] for v in data - ]) + self._coeff = np.array([cg(ATdotA, AT @ v)[0] for v in data]) return # Parallelize process with joblib with Parallel(n_jobs=n_jobs) as executor: - results = executor( - delayed(cg)(ATdotA, AT @ v) - for v in data - ) + results = executor(delayed(cg)(ATdotA, AT @ v) for v in data) self._coeff = np.array([r[0] for r in results]) diff --git a/src/eddymotion/viz.py b/src/eddymotion/viz.py index 38d112b0..07311c07 100644 --- a/src/eddymotion/viz.py +++ b/src/eddymotion/viz.py @@ -49,11 +49,13 @@ def plot_dwi(dataobj, affine, gradient=None, **kwargs): nb.Nifti1Image(dataobj, affine, None), vmax=vmax, cut_coords=cut_coords, - title=r"Reference $b$=0" - if gradient is None - else f"""\ + title=( + r"Reference $b$=0" + if gradient is None + else f"""\ $b$={gradient[3].astype(int)}, \ -$\\vec{{b}}$ = ({', '.join(str(v) for v in gradient[:3])})""", +$\\vec{{b}}$ = ({', '.join(str(v) for v in gradient[:3])})""" + ), **kwargs, ) @@ -328,9 +330,7 @@ def plot_carpet( nii_data_div_b0 = dw_data / bzero[..., np.newaxis] sort_inds = np.argsort( - gtab.bvals[~gtab.b0s_mask] - if sort_by_bval - else np.arange(len(gtab.bvals[~gtab.b0s_mask])) + gtab.bvals[~gtab.b0s_mask] if sort_by_bval else np.arange(len(gtab.bvals[~gtab.b0s_mask])) ) nii_data_div_b0 = nii_data_div_b0[..., sort_inds] @@ -351,9 +351,7 @@ def plot_carpet( for label in labels: indices = np.array([], dtype=int) for ii in segment_labels[label]: - indices = np.concatenate( - [indices, np.where(segmentation_masked == ii)[0]] - ) + indices = np.concatenate([indices, np.where(segmentation_masked == ii)[0]]) segments[label] = indices else: @@ -372,9 +370,7 @@ def plot_carpet( ) -def get_segment_labels( - filepath, keywords, delimiter=" ", index_position=0, label_position=1 -): +def get_segment_labels(filepath, keywords, delimiter=" ", index_position=0, label_position=1): """ Return segment labels for plot_carpet function From a6073ef061bbe184d8e9fddefab9ddfb6694a0cf Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 14:38:52 -0400 Subject: [PATCH 08/16] CI: Update flake8 test, apply fix --- .github/workflows/contrib.yml | 14 ++++++-------- test/test_estimator.py | 2 +- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/.github/workflows/contrib.yml b/.github/workflows/contrib.yml index 1f9246da..c0f1a005 100755 --- a/.github/workflows/contrib.yml +++ b/.github/workflows/contrib.yml @@ -11,15 +11,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: submodules: recursive fetch-depth: 0 - - name: Set up Python 3.9 - uses: actions/setup-python@v2 + - name: Set up Python 3 + uses: actions/setup-python@v5 with: - python-version: 3.9 - - name: Install flake8 - run: python -m pip install flake8 - - name: Check EddyMotion - run: python -m flake8 src + python-version: 3 + - name: Lint EddyMotion + run: pipx run flake8-pyproject diff --git a/test/test_estimator.py b/test/test_estimator.py index b592fe57..84a77475 100644 --- a/test/test_estimator.py +++ b/test/test_estimator.py @@ -77,4 +77,4 @@ def test_ANTs_config_b0(datadir, tmp_path, r_x, r_y, r_z, t_x, t_y, t_z): coords = xfm.reference.ndcoords.T rms = np.sqrt(((xfm.map(coords) - xform.map(coords)) ** 2).sum(1)).mean() - assert rms < 0.8 + assert rms < 0.8 From 5776011c19961b20a11bf991ef402b4b5c7921cb Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 14:41:35 -0400 Subject: [PATCH 09/16] CI: Remove unnecessary package installations, pip versions --- .github/workflows/pythonpackage.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 4ea62c34..63cf78fb 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -17,18 +17,17 @@ jobs: strategy: matrix: python-version: ["3.8", "3.9", "3.10"] - pip: ["pip==21.2", "pip~=22.0"] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Fetch all tags (for setuptools_scm to work) run: | /usr/bin/git -c protocol.version=2 fetch --tags --prune --unshallow origin - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v1 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} - - uses: actions/cache@v1 + - uses: actions/cache@v4 with: path: $HOME/.cache/pip key: pip-cache-v1 @@ -39,7 +38,7 @@ jobs: run: | python -m venv /tmp/buildenv source /tmp/buildenv/bin/activate - pip install -U build hatch hatchling pip twine docutils + pip install -U build hatch pip twine python -m build -s -w python -m twine check dist/eddymotion-* @@ -60,7 +59,7 @@ jobs: run: | python -m venv /tmp/pip source /tmp/pip/bin/activate - python -m pip install -U build hatch hatchling pip twine docutils + pip install -U pip python -m pip install . INSTALLED_VERSION=$(python -c 'import eddymotion as em; print(em.__version__, end="")') echo "VERSION: \"${THISVERSION}\"" @@ -71,7 +70,7 @@ jobs: run: | python -m venv /tmp/install_sdist source /tmp/install_sdist/bin/activate - python -m pip install -U build hatch hatchling pip twine docutils + pip install -U pip python -m pip install /tmp/package/eddymotion*.tar.gz INSTALLED_VERSION=$(python -c 'import eddymotion as em; print(em.__version__, end="")') echo "VERSION: \"${THISVERSION}\"" @@ -82,7 +81,7 @@ jobs: run: | python -m venv /tmp/install_wheel source /tmp/install_wheel/bin/activate - python -m pip install -U build hatch hatchling pip twine docutils + pip install -U pip python -m pip install /tmp/package/eddymotion*.whl INSTALLED_VERSION=$(python -c 'import eddymotion as em; print(em.__version__, end="")') echo "INSTALLED: \"${INSTALLED_VERSION}\"" From de55b626095d778d8b68643bb89b0bb87cd39813 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 14:49:20 -0400 Subject: [PATCH 10/16] Rebuild _version.py files --- .github/workflows/docs-build-pr.yml | 5 +++-- .github/workflows/docs-build-update.yml | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs-build-pr.yml b/.github/workflows/docs-build-pr.yml index 1681063c..d4e38ff9 100644 --- a/.github/workflows/docs-build-pr.yml +++ b/.github/workflows/docs-build-pr.yml @@ -39,10 +39,11 @@ jobs: - name: Install dependencies run: | - pip install -U build hatch hatchling pip twine docutils + pip install -U build hatch pip pip install -r docs/requirements.txt - python -m hatch version | tail -n1 | xargs + python -m hatch version | tail -n1 - name: Build docs run: | + python -m hatch build --hooks-only make -C docs/ SPHINXOPTS="-W" BUILDDIR="$HOME/docs" OUTDIR="${CURBRANCH:-html}" html diff --git a/.github/workflows/docs-build-update.yml b/.github/workflows/docs-build-update.yml index 90c2faf3..a3be07b4 100644 --- a/.github/workflows/docs-build-update.yml +++ b/.github/workflows/docs-build-update.yml @@ -42,12 +42,13 @@ jobs: - name: Install dependencies run: | - pip install -U build hatch hatchling pip twine docutils + pip install -U build hatch pip pip install -r docs/requirements.txt - python -m hatch version | tail -n1 | xargs + python -m hatch version | tail -n1 - name: Build docs run: | + python -m hatch build --hooks-only make -C docs/ SPHINXOPTS="-W" BUILDDIR="$HOME/docs" OUTDIR="${CURBRANCH:-html}" html - name: Push created tag to gh-pages From d27a4488c5cef989c708a7f50cca99740549faa6 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 14:49:34 -0400 Subject: [PATCH 11/16] CI: Minor cleanups, test on more Python versions --- .github/workflows/pythonpackage.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index 63cf78fb..0e583523 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -16,13 +16,13 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"] steps: - uses: actions/checkout@v4 - - name: Fetch all tags (for setuptools_scm to work) - run: | - /usr/bin/git -c protocol.version=2 fetch --tags --prune --unshallow origin + with: + submodules: recursive + fetch-depth: 0 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: @@ -44,7 +44,6 @@ jobs: python -m twine check dist/eddymotion-* mv dist /tmp/package - rm -rf eddymotion.egg-info/ # Interpolate version if [[ "$GITHUB_REF" == refs/tags/* ]]; then From a9d8a5e2ffdbd9c6490731dc78ebdd31ddbb90cc Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 14:53:10 -0400 Subject: [PATCH 12/16] CI: Build docs --- .github/workflows/docs-build-pr.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docs-build-pr.yml b/.github/workflows/docs-build-pr.yml index d4e38ff9..fc96c4e2 100644 --- a/.github/workflows/docs-build-pr.yml +++ b/.github/workflows/docs-build-pr.yml @@ -7,11 +7,11 @@ on: jobs: build: - if: "(github.repository_owner != 'nipreps') && !contains(github.event.head_commit.message, '[skip ci]')" + if: "!contains(github.event.head_commit.message, '[skip ci]')" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: fetch-depth: 0 From 82ce93e3879335e4c551983dadab450742750210 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 14:56:01 -0400 Subject: [PATCH 13/16] DOC: Update requirements --- docs/requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index e27fcc66..4d72e2b8 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,6 +1,6 @@ attrs >= 20.1.0 -furo ~= 2021.10.09 +furo >= 2024.01.29 matplotlib >= 2.2.0 packaging -sphinx ~= 4.2 +sphinx >= 4.5 sphinxcontrib-apidoc From f312b432b9804567be1d1df78156042abd834710 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 16:05:50 -0400 Subject: [PATCH 14/16] DOC: Address Sphinx warnings --- docs/conf.py | 4 ++-- docs/index.rst | 2 ++ docs/requirements.txt | 1 + src/eddymotion/viz.py | 9 +++------ 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index e3c3419b..54dd206e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -91,7 +91,7 @@ # # This is also used if you do content translation via gettext catalogs. # Usually you set "language" from the command line for these cases. -language = None +language = 'en' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -235,7 +235,7 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { "bids": ("https://bids-standard.github.io/pybids/", None), - "dipy": ("https://dipy.org/documentation/latest/", None), + "dipy": ("https://docs.dipy.org/stable/", None), "matplotlib": ("https://matplotlib.org/stable", None), "nibabel": ("https://nipy.org/nibabel/", None), "nipype": ("https://nipype.readthedocs.io/en/latest/", None), diff --git a/docs/index.rst b/docs/index.rst index 4e6dbd0b..848e3cc2 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,6 +1,8 @@ .. include:: links.rst .. include:: ../README.rst :end-line: 29 +.. include:: ../README.rst + :start-line: 34 .. image:: _static/eddymotion-flowchart.svg diff --git a/docs/requirements.txt b/docs/requirements.txt index 4d72e2b8..85f17b2c 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -4,3 +4,4 @@ matplotlib >= 2.2.0 packaging sphinx >= 4.5 sphinxcontrib-apidoc +nireports diff --git a/src/eddymotion/viz.py b/src/eddymotion/viz.py index 07311c07..eeeaee88 100644 --- a/src/eddymotion/viz.py +++ b/src/eddymotion/viz.py @@ -291,8 +291,7 @@ def plot_carpet( segment_labels=None, detrend=False, ): - """ - Return carpet plot using niworkflows carpet_plot + """Return carpet plot using niworkflows carpet_plot Parameters ---------- @@ -307,10 +306,8 @@ def plot_carpet( output_file : :obj:`string` Path to save the plot segment_labels : :obj:`dict` - Dictionary of segment labels - e.g. {'Cerebral_White_Matter': [2, 41], - 'Cerebral_Cortex': [3, 42], - 'Ventricle': [4, 14, 15, 43, 72]} + Dictionary of segment labels, mapping segment name to list of integers + e.g. {'Cerebral_White_Matter': [2, 41], ...} detrend : :obj:`bool` niworkflows plot_carpet detrend flag From ccc458648958ac6c6dcd3b1c2a7812acaf9cafa6 Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Tue, 19 Mar 2024 16:10:10 -0400 Subject: [PATCH 15/16] MNT: Update doc extra to match docs/requirements --- pyproject.toml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 631f94a0..317a96e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,11 +40,14 @@ NiPreps = "https://www.nipreps.org/" [project.optional-dependencies] doc = [ + "attrs >= 20.1.0", + "furo >= 2024.01.29", + "matplotlib >= 2.2.0", "nbsphinx", "packaging", "pydot >= 1.2.3", "pydotplus", - "sphinx >= 2.1.2", + "sphinx >= 4.5", "sphinx-argparse", "sphinx_rtd_theme", "sphinxcontrib-apidoc ~= 0.3.0", From b1ac62634391e54350f3c2c81b44852c52853d1a Mon Sep 17 00:00:00 2001 From: esavary Date: Thu, 21 Mar 2024 13:13:10 +0100 Subject: [PATCH 16/16] fix: remove unused files --- .maint/update_requirements.py | 48 ----------------------------------- min-requirements.txt | 10 -------- requirements.txt | 10 -------- 3 files changed, 68 deletions(-) delete mode 100644 .maint/update_requirements.py delete mode 100644 min-requirements.txt delete mode 100644 requirements.txt diff --git a/.maint/update_requirements.py b/.maint/update_requirements.py deleted file mode 100644 index cd797ef3..00000000 --- a/.maint/update_requirements.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python3 -from copy import copy -from pathlib import Path -from packaging.requirements import Requirement, SpecifierSet - -try: - from tomllib import loads # Python +3.11 -except ImportError: - from pip._vendor.tomli import loads - -repo_root = Path(__file__).parent.parent -pyproject = repo_root / "pyproject.toml" -reqs = repo_root / "requirements.txt" -min_reqs = repo_root / "min-requirements.txt" - -requirements = [ - Requirement(req) - for req in loads(pyproject.read_text())["project"]["dependencies"] -] - -script_name = Path(__file__).relative_to(repo_root) - - -def to_min(req): - if req.specifier: - req = copy(req) - try: - min_spec = [ - spec - for spec in req.specifier - if spec.operator in (">=", "~=") - ][0] - except IndexError: - return req - min_spec._spec = ("==",) + min_spec._spec[1:] - req.specifier = SpecifierSet(str(min_spec)) - return req - - -lines = [f"# Auto-generated by {script_name}", ""] - -# Write requirements -lines[1:-1] = [str(req) for req in requirements] -reqs.write_text("\n".join(lines)) - -# Write minimum requirements -lines[1:-1] = [str(to_min(req)) for req in requirements] -min_reqs.write_text("\n".join(lines)) diff --git a/min-requirements.txt b/min-requirements.txt deleted file mode 100644 index e8efba90..00000000 --- a/min-requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Auto-generated by .maint/update_requirements.py -dipy==1.3.0 -joblib -nipype==1.5.1 -nitransforms==21.0.0 -nireports -numpy==1.17.3 -nest-asyncio==1.5.1 -scikit-image==0.14.2 -scipy==1.8.0 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 437d9d14..00000000 --- a/requirements.txt +++ /dev/null @@ -1,10 +0,0 @@ -# Auto-generated by .maint/update_requirements.py -dipy>=1.3.0 -joblib -nipype<2.0,>=1.5.1 -nitransforms>=21.0.0 -nireports -numpy>=1.17.3 -nest-asyncio>=1.5.1 -scikit-image>=0.14.2 -scipy>=1.8.0