Skip to content

Commit

Permalink
Merge pull request #44 from eilidhmacnicol/enh/brain_extraction_optim…
Browse files Browse the repository at this point in the history
…ization

ENH: improved brain extraction parameters
  • Loading branch information
eilidhmacnicol authored Mar 16, 2021
2 parents 8fcd626 + 93d250d commit 4bf4dc9
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 31 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ ENV PATH=/usr/local/miniconda/bin:$PATH \
RUN conda install -y python=3.7.1 \
mkl=2018.0.3 \
mkl-service \
numpy=1.15.4 \
numpy>=1.16.5 \
scipy=1.1.0 \
scikit-learn=0.19.1 \
scikit-learn>=0.20 \
matplotlib=2.2.2 \
pandas=0.23.4 \
libxml2=2.9.8 \
Expand Down
11 changes: 0 additions & 11 deletions nirodents/cli/brainextraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,16 +122,6 @@ def get_parser():
default=(0, 4, 4),
help="Specify ants-ai Search Grid parameter",
)

parser.add_argument(
"--slice-direction",
dest="slice_direction",
action="store",
type=int,
default=1,
choices=[0, 1, 2],
help="Specify slice direction: 0 = Sagittal (R-L), 1 = Coronal (A-P), 2 = Axial (S-I)",
)
return parser


Expand All @@ -148,7 +138,6 @@ def main():
arc=opts.antsai_arcfrac,
step=opts.antsai_step,
grid=tuple(opts.antsai_grid),
slice_direction=opts.slice_direction,
debug=opts.debug,
mri_scheme=opts.mri_scheme,
omp_nthreads=opts.omp_nthreads,
Expand Down
2 changes: 1 addition & 1 deletion nirodents/data/artsBrainExtraction_precise_T2w.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"metric_weight": [
1,
1,
[0.5, 0.5]
[0.4, 0.6]
],
"number_of_iterations": [
[1000, 500, 250, 100],
Expand Down
33 changes: 16 additions & 17 deletions nirodents/workflows/brainextraction.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ def init_rodent_brain_extraction_wf(
arc=0.12,
step=4,
grid=(0, 4, 4),
slice_direction=1,
debug=False,
interim_checkpoints=True,
mem_gb=3.0,
Expand Down Expand Up @@ -128,7 +127,7 @@ def init_rodent_brain_extraction_wf(
norm_lap_tmpl = pe.Node(niu.Function(function=_trunc), name="norm_lap_tmpl")
norm_lap_tmpl.inputs.out_max = 1.0
norm_lap_tmpl.inputs.percentiles = (1, 99.99)
norm_lap_tmpl.inputs.clip_max = None
norm_lap_tmpl.inputs.clip_max = 99.9
target_sigma = pe.Node(niu.Function(function=_lap_sigma),
name="target_sigma", run_without_submitting=True)
lap_target = pe.Node(
Expand All @@ -137,7 +136,7 @@ def init_rodent_brain_extraction_wf(
norm_lap_target = pe.Node(niu.Function(function=_trunc), name="norm_lap_target")
norm_lap_target.inputs.out_max = 1.0
norm_lap_target.inputs.percentiles = (1, 99.99)
norm_lap_target.inputs.clip_max = None
norm_lap_target.inputs.clip_max = 99.9

# Set up initial spatial normalization
ants_params = "testing" if debug else "precise"
Expand Down Expand Up @@ -167,8 +166,7 @@ def init_rodent_brain_extraction_wf(
clip_tmpl.inputs.percentiles = (35.0, 90.0)

# set INU bspline grid based on voxel size
init_bspline_grid = pe.Node(niu.Function(function=_bspline_distance), name="init_bspline_grid")
init_bspline_grid.inputs.slice_dir = slice_direction
bspline_grid = pe.Node(niu.Function(function=_bspline_grid), name="bspline_grid")

# INU correction of the target image
init_n4 = pe.Node(
Expand Down Expand Up @@ -200,8 +198,8 @@ def init_rodent_brain_extraction_wf(
wf.connect([
# Target image massaging
(inputnode, clip_target, [(("in_files", _pop), "in_file")]),
(inputnode, init_bspline_grid, [(("in_files", _pop), "in_file")]),
(init_bspline_grid, init_n4, [("out", "args")]),
(inputnode, bspline_grid, [(("in_files", _pop), "in_file")]),
(bspline_grid, init_n4, [("out", "args")]),
(clip_target, denoise, [("out", "input_image")]),
(denoise, init_n4, [("output_image", "input_image")]),
(init_n4, clip_inu, [("output_image", "in_file")]),
Expand Down Expand Up @@ -274,6 +272,7 @@ def init_rodent_brain_extraction_wf(
# fmt: off
wf.connect([
(inputnode, map_brainmask, [(("in_files", _pop), "reference_image")]),
(bspline_grid, final_n4, [("out", "args")]),
(denoise, final_n4, [("output_image", "input_image")]),
# Project template's brainmask into subject space
(norm, map_brainmask, [("reverse_transforms", "transforms"),
Expand Down Expand Up @@ -453,18 +452,18 @@ def _pop(in_files):
return in_files


def _bspline_distance(in_file, spacings=(8, 10, 8), slice_dir=1):
import numpy as np
def _bspline_grid(in_file):
import nibabel as nb
import numpy as np

img = nb.load(in_file)
zooms = img.header.get_zooms()[:3]
zooms_round = [round(x, 3) for x in zooms]
extent = (np.array(img.shape[:3]) - 1) * zooms
if zooms_round.count(zooms_round[0]) != 3 and np.argmax(zooms) != slice_dir:
extent[np.argmax(zooms)], extent[slice_dir] = extent[slice_dir], extent[np.argmax(zooms)]
retval = [f"{v}" for v in np.ceil(extent / np.array(spacings)).astype(int)]
return f"-b [{'x'.join(retval)}]"
slices = img.header.get_data_shape()
# get slice ratio
ratio = [s / slices[np.argmax(slices)] for s in slices]
ratio_factor = ratio[np.argmax(ratio)] / ratio[np.argmin(ratio)]
# turn into integer resolution
mesh_res = [f"{round(i * ratio_factor)}" for i in ratio]
return f"-b [{'x'.join(mesh_res)}]"


def _lap_sigma(in_file):
Expand All @@ -474,4 +473,4 @@ def _lap_sigma(in_file):

img = nb.load(in_file)
min_vox = np.amin(img.header.get_zooms())
return str(0.3508 * math.exp(1.4652 * min_vox))
return str(1.5 * min_vox ** 0.75)
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ install_requires =
nipype ~= 1.5.1
niworkflows >= 1.3.2
templateflow ~= 0.7.1
svgutils == 0.3.1

test_requires =
coverage < 5
pytest >= 4.4
Expand Down

0 comments on commit 4bf4dc9

Please sign in to comment.