Skip to content

Commit

Permalink
simplify parameter inference in multi tissue tortuosity correction
Browse files Browse the repository at this point in the history
The corresponding tests are adapted.
  • Loading branch information
matteofrigo committed Jun 14, 2020
1 parent bc9949f commit 8065936
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 91 deletions.
45 changes: 14 additions & 31 deletions dmipy/core/modeling_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -559,8 +559,7 @@ def set_tortuous_parameter(self, lambda_perp_parameter_name,
lambda_par_parameter_name,
volume_fraction_intra_parameter_name,
volume_fraction_extra_parameter_name,
S0_intra=None,
S0_extra=None):
S0_correction=False):
"""
Allows the user to set a tortuosity constraint on the perpendicular
diffusivity of the extra-axonal compartment, which depends on the
Expand All @@ -586,12 +585,9 @@ def set_tortuous_parameter(self, lambda_perp_parameter_name,
volume_fraction_extra_parameter_name: string
name of the extra-axonal volume fraction parameter, see
self.parameter_names.
S0_intra: float,
S0 response of the tissue associated to the intra-cellular
compartment. Default: 1 .
S0_extra: float,
S0 response of the tissue associated to the extra-cellular
compartment. Default: 1.
S0_correction: bool
If True, it uses the S0 of the intra-axonal and extra-axonal
compartments to define the tortuosity constraint. Default: False.
"""
params = [lambda_perp_parameter_name, lambda_par_parameter_name,
volume_fraction_intra_parameter_name,
Expand All @@ -604,31 +600,18 @@ def set_tortuous_parameter(self, lambda_perp_parameter_name,
param)
raise ValueError(msg)

if S0_intra is None and S0_extra is None:
model, name = self._parameter_map[lambda_perp_parameter_name]
if S0_correction and self.S0_tissue_responses is not None:
s0intra_tag = volume_fraction_intra_parameter_name.split('_')[-1]
s0extra_tag = volume_fraction_extra_parameter_name.split('_')[-1]
S0_intra = self.S0_tissue_responses[int(s0intra_tag)]
S0_extra = self.S0_tissue_responses[int(s0extra_tag)]
print('Employing S0 correction of tortuosity constraint with:')
print('S0_intra: {}'.format(S0_intra))
print('S0_extra: {}'.format(S0_extra))
else:
S0_intra = 1.
S0_extra = 1.
elif S0_intra is not None and S0_extra is not None:
if self.S0_tissue_responses is None:
msg = ('The multi compartment model does not have an S0 for '
'each compartment. It is necessary in order to use the '
'tortuosity constraint with multi-tissue correction.')
raise ValueError(msg)
if S0_intra not in self.S0_tissue_responses:
msg = ('The specified S0_intra does not correspond to any S0 '
'in the multi-compartment model.')
raise ValueError(msg)
if S0_extra not in self.S0_tissue_responses:
msg = ('The specified S0_extra does not correspond to any S0 '
'in the multi-compartment model.')
raise ValueError(msg)
S0_intra = float(S0_intra)
S0_extra = float(S0_extra)
else:
raise ValueError('Only one S0 has been specified. Both S0_intra '
'and S0_extra must be passed.')

model, name = self._parameter_map[lambda_perp_parameter_name]

tortuosity = T1_tortuosity(S0_intra, S0_extra)

self.parameter_links.append([model, name, tortuosity, [
Expand Down
125 changes: 66 additions & 59 deletions dmipy/core/tests/test_multi_tissue_models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from numpy.testing import assert_almost_equal, assert_raises
from numpy.testing import assert_almost_equal, assert_

from dmipy.core import modeling_framework
from dmipy.data.saved_acquisition_schemes import (
Expand Down Expand Up @@ -84,61 +84,68 @@ def test_multi_tissue_tortuosity():
s0z = 4000.
s0b = 10000.

def only_intra_s0_in_tortuosity():
model1t = modeling_framework.MultiCompartmentModel(
models=[stick, zeppelin, ball])
model1t.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
'C1Stick_1_lambda_par',
'partial_volume_0',
'partial_volume_1',
S0_intra=s0s)

assert_raises(ValueError, only_intra_s0_in_tortuosity)

def only_extra_s0_in_tortuosity():
model = modeling_framework.MultiCompartmentModel(
models=[stick, zeppelin, ball])
model.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
'C1Stick_1_lambda_par',
'partial_volume_0',
'partial_volume_1',
S0_extra=s0z)

assert_raises(ValueError, only_extra_s0_in_tortuosity)

def one_tissue_but_two_s0_in_tortuosity():
model = modeling_framework.MultiCompartmentModel(
models=[stick, zeppelin, ball])
model.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
'C1Stick_1_lambda_par',
'partial_volume_0',
'partial_volume_1',
S0_intra=s0s,
S0_extra=s0z)

assert_raises(ValueError, one_tissue_but_two_s0_in_tortuosity)

def mismatch_s0_intra():
model = modeling_framework.MultiCompartmentModel(
models=[stick, zeppelin, ball])
model.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
'C1Stick_1_lambda_par',
'partial_volume_0',
'partial_volume_1',
S0_intra=s0s + 10.,
S0_extra=s0z)

assert_raises(ValueError, mismatch_s0_intra)

def mismatch_s0_extra():
model = modeling_framework.MultiCompartmentModel(
models=[stick, zeppelin, ball],
S0_tissue_responses=[s0s, s0z, s0b])
model.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
'C1Stick_1_lambda_par',
'partial_volume_0',
'partial_volume_1',
S0_intra=s0s,
S0_extra=s0z + 10.)

assert_raises(ValueError, mismatch_s0_extra)
model = modeling_framework.MultiCompartmentModel(
models=[stick, zeppelin, ball],
S0_tissue_responses=[s0s, s0z, s0b])
model.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
'C1Stick_1_lambda_par',
'partial_volume_0',
'partial_volume_1',
True)
tort = model.parameter_links[0][2]
s0ic, s0ec = tort.S0_intra, tort.S0_extra
assert_(s0ic == s0s and s0ec == s0z)


def test_multi_tissue_tortuosity_no_s0():
stick = cylinder_models.C1Stick()
zeppelin = gaussian_models.G2Zeppelin()
ball = gaussian_models.G1Ball()

model = modeling_framework.MultiCompartmentModel(
models=[stick, zeppelin, ball])
model.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
'C1Stick_1_lambda_par',
'partial_volume_0',
'partial_volume_1',
True)
tort = model.parameter_links[0][2]
s0ic, s0ec = tort.S0_intra, tort.S0_extra
assert_(s0ic == 1 and s0ec == 1)


def test_multi_tissue_tortuosity_no_correction():
stick = cylinder_models.C1Stick()
zeppelin = gaussian_models.G2Zeppelin()
ball = gaussian_models.G1Ball()

model = modeling_framework.MultiCompartmentModel(
models=[stick, zeppelin, ball],
S0_tissue_responses=[4000, 5000, 10000]
)
model.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
'C1Stick_1_lambda_par',
'partial_volume_0',
'partial_volume_1',
False)
tort = model.parameter_links[0][2]
s0ic, s0ec = tort.S0_intra, tort.S0_extra
assert_(s0ic == 1 and s0ec == 1)


def test_multi_tissue_tortuosity_no_s0_no_correction():
stick = cylinder_models.C1Stick()
zeppelin = gaussian_models.G2Zeppelin()
ball = gaussian_models.G1Ball()

model = modeling_framework.MultiCompartmentModel(
models=[stick, zeppelin, ball]
)
model.set_tortuous_parameter('G2Zeppelin_1_lambda_perp',
'C1Stick_1_lambda_par',
'partial_volume_0',
'partial_volume_1',
False)
tort = model.parameter_links[0][2]
s0ic, s0ec = tort.S0_intra, tort.S0_extra
assert_(s0ic == 1 and s0ec == 1)
11 changes: 10 additions & 1 deletion dmipy/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,15 @@ def __init__(self, S0_intra=1., S0_extra=1.):
"""Tortuosity model for perpendicular extra-axonal diffusivity
[1, 2, 3].
Parameters
----------
S0_intra: float,
S0 response of the tissue associated to the intra-cellular
compartment. Default: 1.
S0_extra: float,
S0 response of the tissue associated to the extra-cellular
compartment. Default: 1.
References
-------
.. [1] Bruggeman, Von DAG. "Berechnung verschiedener physikalischer
Expand Down Expand Up @@ -214,7 +223,7 @@ def __call__(self, lambda_par, vf_intra, vf_extra=None):
Returns
-------
lambda_perp : float,
Rotation matrix.
Perpendicular diffusivity.
"""
if vf_extra is None:
vf_extra = 1. - vf_intra
Expand Down

0 comments on commit 8065936

Please sign in to comment.