From d1c7499e9ccc90c856c8218d228ee6a54afc5e55 Mon Sep 17 00:00:00 2001 From: Samuel <3030760+samuelstjean@users.noreply.github.com> Date: Fri, 4 Nov 2022 14:55:46 +0100 Subject: [PATCH 1/7] rename main script --- scripts/{get_distribution => autodmri_get_distribution} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename scripts/{get_distribution => autodmri_get_distribution} (100%) diff --git a/scripts/get_distribution b/scripts/autodmri_get_distribution similarity index 100% rename from scripts/get_distribution rename to scripts/autodmri_get_distribution From d0b23f32df84c8494ca83a55a79fe271c7989d4a Mon Sep 17 00:00:00 2001 From: Samuel <3030760+samuelstjean@users.noreply.github.com> Date: Fri, 4 Nov 2022 14:56:12 +0100 Subject: [PATCH 2/7] revamp gh actions --- .github/workflows/python-package.yml | 3 +-- .github/workflows/pythonpublish.yml | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 03bed86..a2b3aea 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"] + python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] os: [ubuntu-latest, macos-latest, windows-latest] steps: @@ -28,7 +28,6 @@ jobs: run: | python -m pip install --upgrade pip pip install flake8 pytest - if [ -f requirements.txt ]; then pip install -r requirements.txt; fi pip install . - name: Lint with flake8 run: | diff --git a/.github/workflows/pythonpublish.yml b/.github/workflows/pythonpublish.yml index 32cb7f3..f845042 100644 --- a/.github/workflows/pythonpublish.yml +++ b/.github/workflows/pythonpublish.yml @@ -8,9 +8,9 @@ jobs: deploy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - name: Set up Python - uses: actions/setup-python@v1 + uses: actions/setup-python@v4 with: python-version: '3.x' - name: Install dependencies From 90151dd599390e4c75e075e2c62da661aebf815e Mon Sep 17 00:00:00 2001 From: Samuel <3030760+samuelstjean@users.noreply.github.com> Date: Fri, 4 Nov 2022 14:56:48 +0100 Subject: [PATCH 3/7] fix deprecation and py2.7 stuff --- autodmri/blocks.py | 2 -- autodmri/estimator.py | 14 ++++++-------- autodmri/gamma.py | 6 ++---- scripts/autodmri_get_distribution | 22 ++++++++++------------ setup.py | 5 ++--- 5 files changed, 20 insertions(+), 29 deletions(-) diff --git a/autodmri/blocks.py b/autodmri/blocks.py index 5c10313..d0df547 100644 --- a/autodmri/blocks.py +++ b/autodmri/blocks.py @@ -1,5 +1,3 @@ -from __future__ import division - import numpy as np import numbers diff --git a/autodmri/estimator.py b/autodmri/estimator.py index 6d969a3..ff96ae4 100644 --- a/autodmri/estimator.py +++ b/autodmri/estimator.py @@ -1,5 +1,3 @@ -from __future__ import division - import numpy as np from scipy.ndimage.interpolation import zoom @@ -112,8 +110,8 @@ def get_mask(data, N_min, N_max, phi, alpha_prob=0.05): lambda_minus = lambda_cdf(N_min*K, alpha_prob/2) lambda_plus = lambda_cdf(N_max*K, 1 - alpha_prob/2) - mask_current = np.zeros(data.shape[:-1], dtype=np.bool) - mask_loop = np.zeros(data.shape[:-1], dtype=np.bool) + mask_current = np.zeros(data.shape[:-1], dtype=bool) + mask_loop = np.zeros(data.shape[:-1], dtype=bool) for sigma in phi: s = sum_data2 / (2*sigma**2) @@ -126,7 +124,7 @@ def get_mask(data, N_min, N_max, phi, alpha_prob=0.05): # Explicitly remove known artifacts if exclude_mask is None: - exclude_mask = np.zeros(data.shape[:-1], dtype=np.bool) + exclude_mask = np.zeros(data.shape[:-1], dtype=bool) # we don't know N, so guess parameters iteratively data = data.astype(np.float64) # prevent data**4 overflow @@ -201,7 +199,7 @@ def estimate_from_nmaps(data, size=5, return_mask=True, method='moments', full=F ------- sigma, N, mask (optional) ''' - m_out = np.zeros(data.shape[:-1], dtype=np.bool) + m_out = np.zeros(data.shape[:-1], dtype=bool) median = np.median(data) if median == 0: @@ -242,7 +240,7 @@ def estimate_from_nmaps(data, size=5, return_mask=True, method='moments', full=F sigma = np.zeros(reshaped_maps.shape[0], dtype=np.float32) N = np.zeros(reshaped_maps.shape[0], dtype=np.float32) - mask = np.zeros((reshaped_maps.shape[0], size**3), dtype=np.bool) + mask = np.zeros((reshaped_maps.shape[0], size**3), dtype=bool) output = Parallel(n_jobs=ncores, verbose=verbose)(delayed(proc_inner)(reshaped_maps[i], median, size, method, use_rejection) for i in range(reshaped_maps.shape[0])) @@ -280,7 +278,7 @@ def proc_inner(cur_map, median, size, method, use_rejection): else: cur_map = cur_map.reshape(size**3, 1, -1) sigma, N = get_noise_distribution(cur_map, method=method) - mask = np.ones_like(cur_map, dtype=np.bool) + mask = np.ones_like(cur_map, dtype=bool) if np.isnan(sigma) or np.isnan(N): sigma = 0 diff --git a/autodmri/gamma.py b/autodmri/gamma.py index 49c04e4..040e64f 100644 --- a/autodmri/gamma.py +++ b/autodmri/gamma.py @@ -1,5 +1,3 @@ -from __future__ import division - import numpy as np from scipy.special import digamma, polygamma @@ -39,7 +37,7 @@ def get_noise_distribution(data, method='moments'): elif method == 'maxlk': sigma = maxlk_sigma(data) else: - raise ValueError('Invalid method name {}'.format(method)) + raise ValueError(f'Invalid method name {method}') t = data**2 / (2*sigma**2) @@ -50,7 +48,7 @@ def get_noise_distribution(data, method='moments'): y = np.mean(np.log(t)) N = inv_digamma(y) else: - raise ValueError('Invalid method name {}'.format(method)) + raise ValueError(f'Invalid method name {method}') return sigma, N diff --git a/scripts/autodmri_get_distribution b/scripts/autodmri_get_distribution index 76e2d08..3d555e2 100755 --- a/scripts/autodmri_get_distribution +++ b/scripts/autodmri_get_distribution @@ -1,7 +1,5 @@ #!/usr/bin/env python -from __future__ import division - import numpy as np import nibabel as nib @@ -122,9 +120,9 @@ def main(): for f in overwritable_files: if f is not None and os.path.isfile(f): if args.overwrite: - logger.warning('Overwriting {}'.format(os.path.realpath(f))) + logger.warning(f'Overwriting {os.path.realpath(f)}') else: - parser.error('{} already exists! Use -f or --force to overwrite it.'.format(f)) + parser.error(f'{f} already exists! Use -f or --force to overwrite it.') vol = nib.load(args.data) data = vol.get_fdata(dtype=np.float32) @@ -139,23 +137,23 @@ def main(): noise_maps = args.noise_maps if args.exclude is not None: - exclude_mask = nib.load(args.exclude).get_fdata().astype(np.bool) - logger.info('Excluding voxels from file {}'.format(args.exclude)) + exclude_mask = nib.load(args.exclude).get_fdata().astype(bool) + logger.info(f'Excluding voxels from file {args.exclude}') else: exclude_mask = None - logger.info('Now estimating over file {} with method = {} and axis = {}'.format(args.data, method, axis)) + logger.info(f'Now estimating over file {args.data} with method = {method} and axis = {axis}') if noise_maps: if full: overlap = 'overlapping windows' else: - overlap = 'non overlapping windows' + overlap = 'non-overlapping windows' if data.ndim == 3: data = data[..., None] - logger.info('Estimation will be done over noise maps with a window of size {} and {}'.format(size, overlap)) + logger.info(f'Estimation will be done over noise maps with a window of size {size} and {overlap}') sigma, N, mask = estimate_from_nmaps(data, size=size, return_mask=True, method=method, full=full, ncores=ncores, use_rejection=False, verbose=args.verbose) else: @@ -165,7 +163,7 @@ def main(): if args.fast_median: logger.info('Estimation of the medians will be done over each volume, then on the median of the medians.') elif data.shape[-1] > 100: - logger.warning('Estimation of the median will be done over the whole volume, but you have {} volumes.\n'.format(data.shape[-1]) + + logger.warning(f'Estimation of the median will be done over the whole volume, but you have {data.shape[-1]} volumes.\n' + '\tConsider the option --fast_median if memory usage is high and startup time is too long.') sigma, N, mask = estimate_from_dwis(data, axis=axis, return_mask=True, exclude_mask=exclude_mask, ncores=ncores, @@ -182,13 +180,13 @@ def main(): sigma = sigma[None, None, :] N = N[None, None, :] else: - raise ValueError('axis = {} is not 0, 1 or 2, but that should never happen!'.format(axis)) + raise ValueError(f'axis = {axis} is not 0, 1 or 2, but that should never happen!') sigma = np.ones(mask.shape) * sigma N = np.ones(mask.shape) * N # Save the data - logger.info('Output files are {}, {} and {}'.format(args.sigma, args.N, args.mask)) + logger.info(f'Output files are {args.sigma}, {args.N} and {args.mask}') mask = mask.astype(np.int16) nib.Nifti1Image(sigma, aff).to_filename(args.sigma) diff --git a/setup.py b/setup.py index f680984..01aa3de 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,6 @@ -import io from setuptools import setup, find_packages -with io.open('README.md', encoding='utf-8') as f: +with open('README.md', encoding='utf-8') as f: long_description = f.read() setup( @@ -9,7 +8,7 @@ version='0.2.5', author='Samuel St-Jean', packages=find_packages(), - scripts=['scripts/get_distribution'], + scripts=['scripts/autodmri_get_distribution'], url='https://github.com/samuelstjean/autodmri', license='MIT', description='Implementation of "Automated characterization of noise distributions in diffusion MRI data".', From 6cd22dda1ff24775fc4cba0a6b0fdf67a6ec78c9 Mon Sep 17 00:00:00 2001 From: Samuel <3030760+samuelstjean@users.noreply.github.com> Date: Fri, 4 Nov 2022 14:59:09 +0100 Subject: [PATCH 4/7] changelog and update pyproject --- CHANGELOG.md | 8 +++++++- pyproject.toml | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8bcb20..6043d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,15 @@ # Changelog +## [v0.2.6] - 2022-11-04 + +- Change the main script name from **get_distribution** to **autodmri_get_distribution** for consistency with the package name. +- Remove python 2.7 support. +- Fix some deprecation warnings from numpy. + ## [v0.2.5] - 2021-03-09 - Remove nans from the output when using noise maps. -- Fix the main script regarding the noise maps to 4d conversion. +- Fix the main script regarding the noise maps to 4D conversion. - Remove Dockerfile. ## [v0.2.4] - 2021-03-09 diff --git a/pyproject.toml b/pyproject.toml index fed528d..638dd9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,3 @@ [build-system] -requires = ["setuptools"] +requires = ["setuptools>=61.0"] build-backend = "setuptools.build_meta" From 0e2f8270e0f5eee8b5c16bd73a260c47a2efc21d Mon Sep 17 00:00:00 2001 From: Samuel <3030760+samuelstjean@users.noreply.github.com> Date: Fri, 4 Nov 2022 15:02:26 +0100 Subject: [PATCH 5/7] pimp test actions --- .github/workflows/python-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index a2b3aea..32a5963 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -15,13 +15,13 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.6", "3.7", "3.8", "3.9", "3.10", "3.11"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"] os: [ubuntu-latest, macos-latest, windows-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Install dependencies From 04d472d3c141f5f35ffafe04907623fa9a85fc2b Mon Sep 17 00:00:00 2001 From: Samuel <3030760+samuelstjean@users.noreply.github.com> Date: Fri, 4 Nov 2022 15:08:59 +0100 Subject: [PATCH 6/7] pimp readme and example --- README.md | 8 ++++++++ example/README.md | 10 +++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index f461f22..4786c00 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,14 @@ pip install autodmri You can find a quick example and datasets over [here](example) and the full documentation at http://autodmri.rtfd.io/. +An example, super basic call to the script would be + +~~~bash +autodmri_get_distribution dwi.nii.gz sigma.nii.gz N.nii.gz mask.nii.gz +~~~ + +Be sure to check the options by passing `--help` to the script. + ### The manuscript and references You can read the [journal version][media] in Medical Image Analysis and the datasets are available here https://zenodo.org/record/2483105. diff --git a/example/README.md b/example/README.md index cbd6eb9..1a2e262 100644 --- a/example/README.md +++ b/example/README.md @@ -6,7 +6,7 @@ You can change things such as the number of cores for parallel processing, which the size of the window, to do a full estimation or only non overlapping windows for noise maps, etc. ~~~bash -get_distribution -h +autodmri_get_distribution -h ~~~ Further information is available from the [documentation](https://autodmri.readthedocs.io/en/stable/) as these are more advanced cases. @@ -31,7 +31,7 @@ The data looks like this 1. With equations using the moments (the default, also accessible with `-m moments`) ~~~bash -get_distribution dwi_1_8.nii.gz sigma.nii.gz N.nii.gz mask.nii.gz +autodmri_get_distribution dwi_1_8.nii.gz sigma.nii.gz N.nii.gz mask.nii.gz ~~~ And the output files looks like that. @@ -48,7 +48,7 @@ so if we look at an axial view we would only see a single value while the other 2. With equations using the maximum likelihood (with the option `-m maxlk`) ~~~bash -get_distribution dwi_1_8.nii.gz sigma_maxlk.nii.gz N_maxlk.nii.gz mask_maxlk.nii.gz -m maxlk +autodmri_get_distribution dwi_1_8.nii.gz sigma_maxlk.nii.gz N_maxlk.nii.gz mask_maxlk.nii.gz -m maxlk ~~~ ![](sigma_maxlk.png) @@ -69,7 +69,7 @@ Notice how every output is now a full fledged 3D maps. 1. With equations using the moments ~~~bash -get_distribution data_SENSE3_MB3_noisemap.nii.gz sigma_nmaps.nii.gz N_nmaps.nii.gz mask_nmaps.nii.gz --noise_maps +autodmri_get_distribution data_SENSE3_MB3_noisemap.nii.gz sigma_nmaps.nii.gz N_nmaps.nii.gz mask_nmaps.nii.gz --noise_maps ~~~ ![](sigma_nmaps.png) @@ -80,7 +80,7 @@ get_distribution data_SENSE3_MB3_noisemap.nii.gz sigma_nmaps.nii.gz N_nmaps.nii. 2. With equations using the maximum likelihood ~~~bash -get_distribution data_SENSE3_MB3_noisemap.nii.gz sigma_maxlk_nmaps.nii.gz N_maxlk_nmaps.nii.gz mask_maxlk_nmaps.nii.gz -m maxlk --noise_maps +autodmri_get_distribution data_SENSE3_MB3_noisemap.nii.gz sigma_maxlk_nmaps.nii.gz N_maxlk_nmaps.nii.gz mask_maxlk_nmaps.nii.gz -m maxlk --noise_maps ~~~ ![](sigma_maxlk_nmaps.png) From ca11042801ff59ffdbba8e15a83e18e88e7d1ba1 Mon Sep 17 00:00:00 2001 From: Samuel <3030760+samuelstjean@users.noreply.github.com> Date: Fri, 4 Nov 2022 15:11:47 +0100 Subject: [PATCH 7/7] increment version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 01aa3de..cf49a74 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name='autodmri', - version='0.2.5', + version='0.2.6', author='Samuel St-Jean', packages=find_packages(), scripts=['scripts/autodmri_get_distribution'],