-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gtm tortuosity #84
Gtm tortuosity #84
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -558,7 +558,8 @@ def _add_fixed_parameter_array(self, parameter_name, parameter_array): | |
def set_tortuous_parameter(self, lambda_perp_parameter_name, | ||
lambda_par_parameter_name, | ||
volume_fraction_intra_parameter_name, | ||
volume_fraction_extra_parameter_name): | ||
volume_fraction_extra_parameter_name, | ||
S0_responses=None): | ||
""" | ||
Allows the user to set a tortuosity constraint on the perpendicular | ||
diffusivity of the extra-axonal compartment, which depends on the | ||
|
@@ -581,6 +582,8 @@ 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_responses : list, (optional) | ||
s0 response of the tissues associated to IC and EC. | ||
""" | ||
params = [lambda_perp_parameter_name, lambda_par_parameter_name, | ||
volume_fraction_intra_parameter_name, | ||
|
@@ -597,7 +600,8 @@ def set_tortuous_parameter(self, lambda_perp_parameter_name, | |
self.parameter_links.append([model, name, T1_tortuosity, [ | ||
self._parameter_map[lambda_par_parameter_name], | ||
self._parameter_map[volume_fraction_intra_parameter_name], | ||
self._parameter_map[volume_fraction_extra_parameter_name]] | ||
self._parameter_map[volume_fraction_extra_parameter_name], | ||
S0_responses] | ||
]) | ||
del self.parameter_ranges[lambda_perp_parameter_name] | ||
del self.parameter_cardinality[lambda_perp_parameter_name] | ||
|
@@ -1212,8 +1216,24 @@ def fit(self, acquisition_scheme, data, | |
start = time() | ||
mt_fractions = np.empty( | ||
np.r_[N_voxels, self.N_models], dtype=float) | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need to add this also for MC-SM models. |
||
S0_responses = [] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We know what will be the length of |
||
for i, (m, s) in enumerate(zip(self.models, | ||
matteofrigo marked this conversation as resolved.
Show resolved
Hide resolved
|
||
self.S0_tissue_responses)): | ||
if s is None: | ||
# If the S0 of the tissue is None, the model is composite | ||
# and the corresponding S0 is treated as the weighted | ||
# average of the S0 tissues modelled by the "submodels". | ||
s0 = 0.0 | ||
for k, mm in enumerate(m.models): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nicely done, but while this may work here at the top level to the second level - just for this project - it means that the top level now has the logic to infer what is the S0 of a lower level distributed model. In my opinion this is not so clean, as the we should be able to ask the distributed model what is it's S0 based on its signal volume fractions. This has the added benefit of it being to (potentially) generalize to more than 2 layers - we want to have the code as modular as possible. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It makes sense. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What I mean is that we should be able to say Hold on, I how is line 1229 even getting the |
||
s0 += (mm['partial_volume_{}'.format(k)] * | ||
mm.S0_tissue_responses[k]) | ||
S0_responses.append(s0) | ||
else: | ||
S0_responses.append(s) | ||
|
||
fit_func = MultiTissueConvexOptimizer( | ||
acquisition_scheme, self, self.S0_tissue_responses) | ||
acquisition_scheme, self, S0_responses) | ||
for idx, pos in enumerate(zip(*mask_pos)): | ||
voxel_S = data_[pos] | ||
parameters = fitted_parameters_lin[idx] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -275,7 +275,8 @@ def set_fixed_parameter(self, parameter_name, value): | |
|
||
def set_tortuous_parameter(self, lambda_perp, | ||
lambda_par, | ||
volume_fraction_intra): | ||
volume_fraction_intra, | ||
S0_responses=None): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the S0_responses should not be given as a parameter of the You could, potentially, add a parameter here like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For the moment I would opt for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah of course keep things consistent. I just meant that I didn't like the multiple places to give perfect on the option. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See my comment above, we do need to find a way to nicely define which model is associated with what S0 response for intra or extra. Perhaps we can make the signature even simpler and do
Internally we can just check for the appropriate model with |
||
""" | ||
Allows the user to set a tortuosity constraint on the perpendicular | ||
diffusivity of the extra-axonal compartment, which depends on the | ||
|
@@ -295,6 +296,8 @@ def set_tortuous_parameter(self, lambda_perp, | |
volume_fraction_intra: string | ||
name of the intra-axonal volume fraction parameter, see | ||
self.parameter_names. | ||
S0_responses: list | ||
list of the s0 responses of the tissues associated to IC and EC. | ||
""" | ||
params = [lambda_perp, lambda_par, volume_fraction_intra] | ||
for param in params: | ||
|
@@ -308,7 +311,10 @@ def set_tortuous_parameter(self, lambda_perp, | |
model, name = self._parameter_map[lambda_perp] | ||
self.parameter_links.append([model, name, T1_tortuosity, [ | ||
self._parameter_map[lambda_par], | ||
self._parameter_map[volume_fraction_intra]] | ||
self._parameter_map[volume_fraction_intra], | ||
None, | ||
S0_responses | ||
] | ||
]) | ||
del self.parameter_ranges[lambda_perp] | ||
del self.parameter_scales[lambda_perp] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -170,7 +170,7 @@ def rotation_matrix_100_to_theta_phi_psi(theta, phi, psi): | |
return np.dot(R_100_to_theta_phi, R_around_100) | ||
|
||
|
||
def T1_tortuosity(lambda_par, vf_intra, vf_extra=None): | ||
def T1_tortuosity(lambda_par, vf_intra, vf_extra=None, S0_responses=None): | ||
"""Tortuosity model for perpendicular extra-axonal diffusivity [1, 2, 3]. | ||
If vf_extra=None, then vf_intra must be a nested volume fraction, in the | ||
sense that E_bundle = vf_intra * E_intra + (1 - vf_intra) * E_extra, with | ||
|
@@ -186,6 +186,8 @@ def T1_tortuosity(lambda_par, vf_intra, vf_extra=None): | |
intra-axonal volume fraction [0, 1]. | ||
vf_extra : float, (optional) | ||
extra-axonal volume fraction [0, 1]. | ||
S0_responses : list, (optional) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indicate the length of the list |
||
s0 response of the tissues associated to IC and EC. | ||
|
||
Returns | ||
------- | ||
|
@@ -204,12 +206,16 @@ def T1_tortuosity(lambda_par, vf_intra, vf_extra=None): | |
.. [3] Szafer et al. "Theoretical model for water diffusion in tissues." | ||
Magnetic resonance in medicine 33.5 (1995): 697-712. | ||
""" | ||
if vf_extra is None: | ||
lambda_perp = (1 - vf_intra) * lambda_par | ||
else: | ||
fraction_intra = vf_intra / (vf_intra + vf_extra) | ||
lambda_perp = (1 - fraction_intra) * lambda_par | ||
return lambda_perp | ||
fraction_intra = vf_intra | ||
fraction_extra = 1.0 - fraction_intra if vf_extra is None else vf_extra | ||
|
||
if S0_responses is not None: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add detailed comment either here or in the doctring of the tortuosity function here - add a preliminary citation to your abstract if you want. |
||
fraction_intra /= S0_responses[0] | ||
fraction_extra /= S0_responses[1] | ||
|
||
fraction_intra /= fraction_extra + fraction_intra | ||
|
||
return (1. - fraction_intra) * lambda_par | ||
|
||
|
||
def parameter_equality(param): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again (see below) I don't think we should be able to give S0 responses twice for any MC-model - it should be unique in the definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a shortcut for knowing which of the S0s in
self.S0_tissue_responses
list corresponds to the intra and which one to the extra?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't even thing about this when I first coded this... I especially kept the parameter names as input because I didn't want to have to hardcode the ordering or definitions of models to get the tortuosity regardless.
Actually we do need to find a solution here - what you were doing with adding the S0_responses as a parameter may be the easiest way to make this work after all... Either this or we need to define a nice way to just point to the models that are intra and extra, and then make the function just find which parameters and S0s are associated with this...