diff --git a/findoutlie/__init__.py b/findoutlie/__init__.py index e69de29..2306795 100644 --- a/findoutlie/__init__.py +++ b/findoutlie/__init__.py @@ -0,0 +1,4 @@ +""" Init for findoutlie module +""" + +__version__ = '0.1a0' diff --git a/findoutlie/metrics.py b/findoutlie/metrics.py new file mode 100644 index 0000000..08ba844 --- /dev/null +++ b/findoutlie/metrics.py @@ -0,0 +1,32 @@ +""" Scan outlier metrics +""" + +# Any imports you need +# +++your code here+++ + + +def dvars(img): + """ Calculate dvars metric on Nibabel image `img` + + The dvars calculation between two volumes is defined as the square root of + (the mean of the (voxel differences squared)). + + Parameters + ---------- + img : nibabel image + + Returns + ------- + dvals : 1D array + One-dimensional array with n-1 elements, where n is the number of + volumes in `img`. + """ + # Hint: remember 'axis='. For example: + # In [2]: arr = np.array([[2, 3, 4], [5, 6, 7]]) + # In [3]: np.mean(arr, axis=1) + # Out[2]: array([3., 6.]) + # + # You may be be able to solve this in four lines, without a loop. + # But solve it any way you can. + # This is a placeholder, replace it to write your solution. + raise NotImplementedError('Code up this function') diff --git a/findoutlie/tests/test_dvars.py b/findoutlie/tests/test_dvars.py new file mode 100644 index 0000000..27e60c7 --- /dev/null +++ b/findoutlie/tests/test_dvars.py @@ -0,0 +1,35 @@ +""" Test dvars implementation + +You can run the tests from the root directory (containing ``README.md``) with:: + + python3 -m pytest . +""" + +import numpy as np + +import nibabel as nib + +import nipraxis as npx + +from findoutlie.metrics import dvars + + +TEST_FNAME = npx.fetch_file('ds114_sub009_t2r1.nii') + + +def test_dvars(): + img = nib.load(TEST_FNAME) + n_trs = img.shape[-1] + n_voxels = np.prod(img.shape[:-1]) + dvals = dvars(img) + assert len(dvals) == n_trs - 1 + # Calculate the values the long way round + data = img.get_fdata() + prev_vol = data[..., 0] + long_dvals = [] + for i in range(1, n_trs): + this_vol = data[..., i] + d = this_vol - prev_vol + long_dvals.append(np.sqrt(np.sum(d ** 2) / n_voxels)) + prev_vol = this_vol + assert np.allclose(dvals, long_dvals) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..1e834f4 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,20 @@ +[build-system] +requires = ["flit_core >=2,<4"] +build-backend = "flit_core.buildapi" + +[tool.flit.metadata] +module = "findoutlie" +author = "The team" +author-email = "team@email" +home-page = "https://github.com/nipraxis-fall-2022/diagnostics-example" +classifiers = ["License :: OSI Approved :: BSD License", + "Programming Language :: Python :: 3"] +description-file="README.md" +# Check against requirements.txt +requires = [ + 'nibabel', + 'numpy', + 'scipy', + 'matplotlib', +] +requires-python=">=3.6" diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..63b4d70 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = --ignore-glob=solutions/* diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d1f283a --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +nibabel +numpy +scipy +matplotlib +nipraxis diff --git a/solutions/.solutions.toml b/solutions/.solutions.toml index 8c38f62..24c16f5 100644 --- a/solutions/.solutions.toml +++ b/solutions/.solutions.toml @@ -1,5 +1,8 @@ # Where the exercises etc go, given the solutions +[solution.metrics] +out_path = '{one_down}/findoutlie/metrics.py' + [solution.validate_data] out_path = '{one_down}/scripts/validate_data.py' diff --git a/solutions/.write_dvars.sh b/solutions/.write_dvars.sh new file mode 100755 index 0000000..73f7619 --- /dev/null +++ b/solutions/.write_dvars.sh @@ -0,0 +1,4 @@ +#!/bin/bash +nxt-proc-solutions write-solutions +pytest findoutlie +nxt-proc-solutions write diff --git a/solutions/metrics.py b/solutions/metrics.py new file mode 100644 index 0000000..994986b --- /dev/null +++ b/solutions/metrics.py @@ -0,0 +1,43 @@ +""" Scan outlier metrics +""" + +# Any imports you need +# LAB(begin solution) +import numpy as np +# LAB(replace solution) +# +++your code here+++ +# LAB(end solution) + + +def dvars(img): + """ Calculate dvars metric on Nibabel image `img` + + The dvars calculation between two volumes is defined as the square root of + (the mean of the (voxel differences squared)). + + Parameters + ---------- + img : nibabel image + + Returns + ------- + dvals : 1D array + One-dimensional array with n-1 elements, where n is the number of + volumes in `img`. + """ + # Hint: remember 'axis='. For example: + # In [2]: arr = np.array([[2, 3, 4], [5, 6, 7]]) + # In [3]: np.mean(arr, axis=1) + # Out[2]: array([3., 6.]) + # + # You may be be able to solve this in four lines, without a loop. + # But solve it any way you can. + # LAB(begin solution) + data = img.get_fdata() + vx_by_time = np.reshape(data, (-1, data.shape[-1])) + time_diffs = np.diff(vx_by_time, axis=1) + return np.sqrt(np.mean(time_diffs ** 2, axis=0)) + # LAB(replace solution) + # This is a placeholder, replace it to write your solution. + raise NotImplementedError('Code up this function') + # LAB(end solution) diff --git a/test_requirements.txt b/test_requirements.txt new file mode 100644 index 0000000..e4766f7 --- /dev/null +++ b/test_requirements.txt @@ -0,0 +1,3 @@ +# Test requirements +-r requirements.txt +pytest