-
Notifications
You must be signed in to change notification settings - Fork 30
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tournier13 White Matter Response Function Estimation (#19)
* added tournier13 algorithm and peak finding fod * added solver error catch to cvxpy fod solver * optional inclusion of S0-response for MT-CSD fitting using 'fit_s0_reponse' * update mtcsd example with and without S0-response signal fit illustration * added and update tissue wm and 3 tissue response test
- Loading branch information
1 parent
64b4985
commit 4eadf12
Showing
10 changed files
with
655 additions
and
159 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import numpy as np | ||
from dmipy.tissue_response.three_tissue_response import ( | ||
optimal_threshold, signal_decay_metric) | ||
from dmipy.signal_models.gaussian_models import G1Ball | ||
from dmipy.data.saved_acquisition_schemes import ( | ||
wu_minn_hcp_acquisition_scheme) | ||
scheme = wu_minn_hcp_acquisition_scheme() | ||
|
||
|
||
def test_optimal_threshold(): | ||
data = np.linspace(0, 8, 101) | ||
opt = optimal_threshold(data) | ||
np.testing.assert_(np.round(opt) == 8 // 2) | ||
|
||
|
||
def test_signal_decay_metric(): | ||
data_iso1 = G1Ball(lambda_iso=2.5e-9)(scheme) | ||
data_iso2 = G1Ball(lambda_iso=1.5e-9)(scheme) | ||
data = np.array([data_iso1, data_iso2]) | ||
sdm = signal_decay_metric(scheme, data) | ||
np.testing.assert_(sdm[0] > sdm[1]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
from dmipy.core.modeling_framework import ( | ||
MultiCompartmentSphericalHarmonicsModel) | ||
from dmipy.signal_models.gaussian_models import G1Ball, G2Zeppelin | ||
from dmipy.signal_models.tissue_response_models import ( | ||
IsotropicTissueResponseModel, | ||
AnisotropicTissueResponseModel) | ||
from dmipy.data.saved_acquisition_schemes import ( | ||
wu_minn_hcp_acquisition_scheme,) | ||
import numpy as np | ||
scheme = wu_minn_hcp_acquisition_scheme() | ||
|
||
|
||
def test_fit_S0_response(S0_iso=10., S0_aniso=1.): | ||
ball = G1Ball(lambda_iso=3e-9) | ||
data_iso = S0_iso * ball(scheme) | ||
iso_model = IsotropicTissueResponseModel(scheme, np.atleast_2d(data_iso)) | ||
|
||
zeppelin = G2Zeppelin( | ||
lambda_par=2.2e-9, lambda_perp=1e-9, mu=[np.pi / 2, np.pi / 2]) | ||
data_aniso = S0_aniso * zeppelin(scheme) | ||
aniso_model = AnisotropicTissueResponseModel( | ||
scheme, np.atleast_2d(data_aniso)) | ||
|
||
mtcsd = MultiCompartmentSphericalHarmonicsModel([iso_model, aniso_model]) | ||
|
||
data_to_fit = 0.3 * data_iso + 0.7 * data_aniso | ||
|
||
csd_fit_no_S0 = mtcsd.fit(scheme, data_to_fit, fit_S0_response=False) | ||
csd_fit_S0 = mtcsd.fit(scheme, data_to_fit, fit_S0_response=True) | ||
np.testing.assert_almost_equal( | ||
0.3, csd_fit_S0.fitted_parameters['partial_volume_0'], 3) | ||
np.testing.assert_almost_equal( | ||
0.7, csd_fit_S0.fitted_parameters['partial_volume_1'], 3) | ||
|
||
# test iso volume fraction overestimated without S0 response | ||
np.testing.assert_( | ||
csd_fit_no_S0.fitted_parameters['partial_volume_0'] > 0.3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from dmipy.signal_models.gaussian_models import G2Zeppelin | ||
from dmipy.distributions import distribute_models | ||
from dmipy.data.saved_acquisition_schemes import ( | ||
wu_minn_hcp_acquisition_scheme) | ||
from dmipy.signal_models.tissue_response_models import ( | ||
AnisotropicTissueResponseModel) | ||
from dmipy.tissue_response.white_matter_response import ( | ||
white_matter_response_tournier07, | ||
white_matter_response_tournier13) | ||
import numpy as np | ||
from numpy.testing import assert_array_almost_equal, assert_raises | ||
scheme = wu_minn_hcp_acquisition_scheme() | ||
|
||
|
||
def _make_single_and_crossing(): | ||
zeppelin = G2Zeppelin( | ||
lambda_par=1.7e-9, lambda_perp=1e-9, mu=[0., 0.]) | ||
data_aniso = zeppelin(scheme) | ||
aniso_model = AnisotropicTissueResponseModel( | ||
scheme, np.atleast_2d(data_aniso)) | ||
|
||
watson_mod = distribute_models.SD1WatsonDistributed( | ||
[aniso_model]) | ||
watson_params_par = { | ||
'SD1Watson_1_mu': np.array( | ||
[0., 0.]), | ||
'SD1Watson_1_odi': .2 | ||
} | ||
watson_params_perp = { | ||
'SD1Watson_1_mu': np.array( | ||
[np.pi / 2., np.pi / 2.]), | ||
'SD1Watson_1_odi': .2 | ||
} | ||
data_watson_par = watson_mod(scheme, **watson_params_par) | ||
data_watson_perp = watson_mod(scheme, **watson_params_perp) | ||
|
||
data_cross = np.array( | ||
[data_watson_par, data_watson_par + data_watson_perp]) | ||
return data_cross | ||
|
||
|
||
def test_tournier13_picks_single_peak(): | ||
data_cross = _make_single_and_crossing() | ||
|
||
assert_raises(ValueError, | ||
white_matter_response_tournier13, | ||
scheme, data_cross, peak_ratio_setting='bla') | ||
|
||
wm, _ = white_matter_response_tournier13( | ||
scheme, data_cross, peak_ratio_setting='mrtrix', | ||
N_candidate_voxels=1) | ||
assert_array_almost_equal( | ||
wm(scheme, mu=[0., 0.]), | ||
data_cross[0], 4) | ||
|
||
|
||
def test_tournier07_picks_single_peak(): | ||
data_cross = _make_single_and_crossing() | ||
wm, _ = white_matter_response_tournier07( | ||
scheme, data_cross, peak_ratio_setting='mrtrix', | ||
N_candidate_voxels=1) | ||
assert_array_almost_equal( | ||
wm(scheme, mu=[0., 0.]), | ||
data_cross[0], 4) |
Oops, something went wrong.