Skip to content

Commit

Permalink
Merge pull request #17 from samuelstjean/maint
Browse files Browse the repository at this point in the history
Maint
  • Loading branch information
samuelstjean authored Nov 4, 2022
2 parents 85c17d3 + ca11042 commit 026490a
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 43 deletions.
7 changes: 3 additions & 4 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,19 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.6", "3.7", "3.8", "3.9", "3.10"]
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
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: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pythonpublish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 0 additions & 2 deletions autodmri/blocks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import division

import numpy as np
import numbers

Expand Down
14 changes: 6 additions & 8 deletions autodmri/estimator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import division

import numpy as np

from scipy.ndimage.interpolation import zoom
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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]))
Expand Down Expand Up @@ -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
Expand Down
6 changes: 2 additions & 4 deletions autodmri/gamma.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import division

import numpy as np

from scipy.special import digamma, polygamma
Expand Down Expand Up @@ -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)

Expand All @@ -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

Expand Down
10 changes: 5 additions & 5 deletions example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
[build-system]
requires = ["setuptools"]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
22 changes: 10 additions & 12 deletions scripts/get_distribution → scripts/autodmri_get_distribution
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#!/usr/bin/env python

from __future__ import division

import numpy as np
import nibabel as nib

Expand Down Expand Up @@ -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)
Expand All @@ -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:
Expand All @@ -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,
Expand All @@ -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)
Expand Down
7 changes: 3 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
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(
name='autodmri',
version='0.2.5',
version='0.2.6',
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".',
Expand Down

0 comments on commit 026490a

Please sign in to comment.