Skip to content

Commit

Permalink
Update nibabel to latest version, fix int error and add scaled thresh…
Browse files Browse the repository at this point in the history
…old when masking
  • Loading branch information
po09i committed Aug 28, 2023
1 parent 98d1fa0 commit f1df9ac
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 27 deletions.
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -41,7 +41,7 @@
'importlib-metadata ~= 4.0 ; python_version < "3.8"',
"numpy>=1.21",
"phantominator~=0.6.4",
"nibabel~=3.2.1",
"nibabel>=3.2.1",
"requests",
"scipy>=1.7",
"tqdm",
Expand Down
24 changes: 14 additions & 10 deletions shimmingtoolbox/cli/mask.py
@@ -1,13 +1,13 @@
#!/usr/bin/env python3

import click
import logging
import nibabel as nib
import numpy as np
import os
import logging

import shimmingtoolbox.masking.threshold
from shimmingtoolbox.masking.shapes import shape_square, shape_cube, shape_sphere
import shimmingtoolbox.masking.threshold
from shimmingtoolbox.utils import run_subprocess, create_output_dir, set_all_loggers

CONTEXT_SETTINGS = dict(help_option_names=['-h', '--help'])
Expand Down Expand Up @@ -55,7 +55,7 @@ def box(fname_input, output, size, center, verbose):
if len(data.shape) == 3:
mask_cb = shape_cube(data, size[0], size[1], size[2], center[0], center[1], center[2]) # creation
# of the box mask
mask_cb = mask_cb.astype(int)
mask_cb = mask_cb.astype(np.int32)
nii_img = nib.Nifti1Image(mask_cb, nii.affine)
nib.save(nii_img, output)
click.echo(f"The filename for the output mask is: {os.path.abspath(output)}")
Expand Down Expand Up @@ -114,7 +114,7 @@ def rect(fname_input, output, size, center, verbose):
# on each slice (2D)
mask_sqr[:, :, z] = mask_slice # addition of each masked slice to form a 3D array

mask_sqr = mask_sqr.astype(int)
mask_sqr = mask_sqr.astype(np.int32)
nii_img = nib.Nifti1Image(mask_sqr, nii.affine)
nib.save(nii_img, output)
click.echo(f"The filename for the output mask is: {os.path.abspath(output)}")
Expand Down Expand Up @@ -151,7 +151,7 @@ def sphere(fname_input, fname_output, radius, center, verbose):
# API for sphere mask
mask = shape_sphere(nii.get_fdata(), radius, center[0], center[1], center[2])

nii_mask = nib.Nifti1Image(mask.astype(int), affine=nii.affine, header=nii.header)
nii_mask = nib.Nifti1Image(mask.astype(np.int32), affine=nii.affine, header=nii.header)
nib.save(nii_mask, fname_output)


Expand All @@ -165,10 +165,14 @@ def sphere(fname_input, fname_output, radius, center, verbose):
@click.option('-o', '--output', type=click.Path(), default=os.path.join(os.curdir, 'mask.nii.gz'), show_default=True,
help="Name of output mask. Supported extensions are .nii or .nii.gz. (default: "
"(os.curdir, 'mask.nii.gz'))")
@click.option('--thr', default=30, help="Value to threshold the data: voxels will be set to zero if their "
"value is equal or less than this threshold. (default: 30)")
@click.option('--thr', type=click.FLOAT, default=30.0, show_default=True,
help="Value to threshold the data: voxels will be set to zero if their value is equal or less than this"
" threshold.")
@click.option('--scaled-thr', is_flag=True, default=False, show_default=True,
help="Indicate whether the --thr option is scaled from 0 to 1 (True) or according to the values within "
"the input (False). Default: False")
@click.option('-v', '--verbose', type=click.Choice(['info', 'debug']), default='info', help="Be more verbose")
def threshold(fname_input, output, thr, verbose):
def threshold(fname_input, output, thr, scaled_thr, verbose):

# Set all loggers
set_all_loggers(verbose)
Expand All @@ -179,8 +183,8 @@ def threshold(fname_input, output, thr, verbose):
nii = nib.load(fname_input)
data = nii.get_fdata() # convert nifti file to numpy array

mask_thr = shimmingtoolbox.masking.threshold.threshold(data, thr) # creation of the threshold mask
mask_thr = mask_thr.astype(int)
mask_thr = shimmingtoolbox.masking.threshold.threshold(data, thr, scaled_thr) # creation of the threshold mask
mask_thr = mask_thr.astype(np.int32)
nii_img = nib.Nifti1Image(mask_thr, nii.affine)
nib.save(nii_img, output)
click.echo(f"The filename for the output mask is: {os.path.abspath(output)}")
Expand Down
4 changes: 2 additions & 2 deletions test/cli/test_cli_b0shim.py
Expand Up @@ -56,7 +56,7 @@ def _define_inputs(fmap_dim):
center_dim2=int(ny / 2),
len_dim1=10, len_dim2=10, len_dim3=nz - 10)

nii_mask = nib.Nifti1Image(mask.astype(int), nii_anat.affine)
nii_mask = nib.Nifti1Image(mask.astype(np.uint8), nii_anat.affine)

return nii_fmap, nii_anat, nii_mask, fm_data, anat_data

Expand Down Expand Up @@ -1087,7 +1087,7 @@ def test_b0_max_intensity():
center_dim1=32,
center_dim2=36,
len_dim1=10, len_dim2=10, len_dim3=nz)
nii_mask = nib.Nifti1Image(mask.astype(int), nii.affine)
nii_mask = nib.Nifti1Image(mask.astype(np.uint8), nii.affine)
nib.save(nii_mask, fname_mask)

runner = CliRunner()
Expand Down
4 changes: 2 additions & 2 deletions test/cli/test_cli_image.py
Expand Up @@ -55,8 +55,8 @@ def test_cli_concat_pixdim(self):
class TestImageLogicalAnd(object):
def setup_method(self):
affine_1 = np.eye(4)
self.nii1 = nib.Nifti1Image(np.array([[[1, 1], [1, 1]], [[0, 0], [0, 0]]]), affine=affine_1)
self.nii2 = nib.Nifti1Image(np.array([[[0, 0], [1, 1]], [[1, 1], [0, 0]]]), affine=affine_1)
self.nii1 = nib.Nifti1Image(np.array([[[1, 1], [1, 1]], [[0, 0], [0, 0]]], dtype=np.uint8), affine=affine_1)
self.nii2 = nib.Nifti1Image(np.array([[[0, 0], [1, 1]], [[1, 1], [0, 0]]], dtype=np.uint8), affine=affine_1)

mask_3 = np.ones([8, 8])
mask_3[0, 0] = 0
Expand Down
26 changes: 25 additions & 1 deletion test/cli/test_cli_mask.py
Expand Up @@ -88,7 +88,31 @@ def test_cli_mask_threshold():

out = os.path.join(tmp, 'mask.nii.gz')
thr = 780
result = runner.invoke(mask_cli, ['threshold', '--input', inp, '--output', out, '--thr', thr])
result = runner.invoke(mask_cli, ['threshold', '--input', inp, '--output', out, '--thr', thr],
catch_exceptions=False)

# With a threshold value of 780, the expected mask for the positions [58:62, 28:31, 7:9] is :
expected = np.array([[[1.0, 1.0], [0.0, 1.0], [0.0, 0.0]],
[[1.0, 1.0], [0.0, 1.0], [0.0, 0.0]],
[[0.0, 1.0], [0.0, 0.0], [0.0, 0.0]],
[[0.0, 1.0], [0.0, 0.0], [0.0, 0.0]]])

nii = nib.load(out)
mask = nii.get_fdata()

assert result.exit_code == 0
assert np.all(mask[58:62, 28:31, 7:9] == expected)


def test_cli_mask_threshold_scaled():
with tempfile.TemporaryDirectory(prefix='st_' + pathlib.Path(__file__).stem) as tmp:
runner = CliRunner()

out = os.path.join(tmp, 'mask.nii.gz')
thr = 0.412
result = runner.invoke(mask_cli, ['threshold', '--input', inp, '--output', out, '--thr', thr,
'--scaled-thr'],
catch_exceptions=False)

# With a threshold value of 780, the expected mask for the positions [58:62, 28:31, 7:9] is :
expected = np.array([[[1.0, 1.0], [0.0, 1.0], [0.0, 0.0]],
Expand Down
10 changes: 6 additions & 4 deletions test/cli/test_cli_realtime_shim.py
@@ -1,11 +1,13 @@
#!usr/bin/env python3
# coding: utf-8

import json
import numpy as np
import os
import pathlib
import pytest
import tempfile
import nibabel as nib
import pytest
import json

from click.testing import CliRunner
from shimmingtoolbox.cli.realtime_shim import gradient_realtime
Expand Down Expand Up @@ -40,7 +42,7 @@ def test_cli_realtime_shim():
center_dim2=int(ny / 2),
len_dim1=30, len_dim2=30, len_dim3=nz)

nii_mask_static = nib.Nifti1Image(mask.astype(int), nii_anat.affine)
nii_mask_static = nib.Nifti1Image(mask.astype(np.int16), nii_anat.affine)
fname_mask_static = os.path.join(tmp, 'mask.nii.gz')
nib.save(nii_mask_static, fname_mask_static)

Expand All @@ -50,7 +52,7 @@ def test_cli_realtime_shim():
center_dim2=int(ny / 2),
len_dim1=20, len_dim2=20, len_dim3=nz)

nii_mask_riro = nib.Nifti1Image(mask.astype(int), nii_anat.affine)
nii_mask_riro = nib.Nifti1Image(mask.astype(np.uint8), nii_anat.affine)
fname_mask_riro = os.path.join(tmp, 'mask.nii.gz')
nib.save(nii_mask_riro, fname_mask_riro)

Expand Down
4 changes: 2 additions & 2 deletions test/shim/test_sequencer.py
Expand Up @@ -693,7 +693,7 @@ def save_nii(nii_fieldmap, coil, opt, nii_mask):
nib.save(nii_coil, fname_coil_res)


array = np.array([[1, 2], [3, 4]])
array = np.array([[1, 2], [3, 4]], dtype=np.uint8)
array = np.repeat(array, 4, 1)
array = np.repeat(array[..., np.newaxis], 1, 2)
array = np.repeat(array[..., np.newaxis], 5, 3)
Expand Down Expand Up @@ -836,7 +836,7 @@ def setup_method(self):
center_dim1=32,
center_dim2=36,
len_dim1=10, len_dim2=10, len_dim3=nz)
self.nii_mask = nib.Nifti1Image(mask.astype(int), self.nii_input.affine)
self.nii_mask = nib.Nifti1Image(mask.astype(np.uint8), self.nii_input.affine)

def test_default_max_intensity(self):
output = shim_max_intensity(self.nii_input, self.nii_mask)
Expand Down
10 changes: 5 additions & 5 deletions test/test_load_nifti.py
Expand Up @@ -18,13 +18,13 @@
class TestCore(object):
_data = np.array([[[1, 2, 3], [4, 5, 6], [7, 8, 9]],
[[10, 11, 12], [13, 14, 15], [16, 17, 18]],
[[19, 20, 21], [22, 23, 24], [25, 26, 27]]])
[[19, 20, 21], [22, 23, 24], [25, 26, 27]]], dtype=np.uint8)
_data_volume = np.array([[[[1, 1], [2, 2], [3, 3]], [[4, 4], [5, 5], [6, 6]], [[7, 7], [8, 8], [9, 9]]],
[[[10, 10], [11, 11], [12, 12]], [[13, 13], [14, 14], [15, 15]],
[[16, 16], [17, 17], [18, 18]]],
[[[19, 19], [20, 20], [21, 21]], [[22, 22], [23, 23], [24, 24]],
[[25, 25], [26, 26], [27, 27]]]])
_aff = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]])
[[25, 25], [26, 26], [27, 27]]]], dtype=np.uint8)
_aff = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]], dtype=np.uint8)
_json_phase = {"Modality": "MR",
"ImageComments": "phase",
"MagneticFieldStrength": 3,
Expand Down Expand Up @@ -151,8 +151,8 @@ def setup_method(self):
self.data_path_2.mkdir(exist_ok=True)
self.data_path_volume.mkdir(exist_ok=True)

dummy_data = nib.nifti1.Nifti1Image(dataobj=self._data, affine=self._aff)
dummy_data_volume = nib.nifti1.Nifti1Image(dataobj=self._data_volume, affine=self._aff)
dummy_data = nib.Nifti1Image(self._data, affine=self._aff)
dummy_data_volume = nib.Nifti1Image(self._data_volume, affine=self._aff)

nib.save(dummy_data, os.path.join(self.data_path, 'dummy.nii'))
with open(os.path.join(self.data_path, 'dummy.json'), 'w') as json_file:
Expand Down

0 comments on commit f1df9ac

Please sign in to comment.