Commit 82f4a3c8 authored by William Clarke's avatar William Clarke
Browse files

Further tweaks for 2d dynamic.

parent a464e5f1
......@@ -524,6 +524,60 @@ class NIFTI_MRS(Image):
out = out[0]
return out
def dynamic_hdr_vals(self):
"""Return representations fo the dynamic header values
:return: List of dicts contianing labeled header parameters
:return: List of tuples contianing header values
"""
def list_of_dict_from_dim(dim_hdr, size):
"""Form a list of dicts where each index of the list corresponds to one element"""
out = []
for idx in range(size):
tmp_dict = {}
for key in dim_hdr:
tmp_dict.update({key: dim_hdr[key][idx]})
out.append(tmp_dict)
return out
def sort_output(hdr_list):
if len(hdr_list) == 1:
X = np.meshgrid(hdr_list[0])
tvar = [x for x in X[0]]
elif len(hdr_list) == 2:
X, Y = np.meshgrid(hdr_list[0], hdr_list[1], indexing='ij')
tvar = [dict(x, **y) for x, y in zip(X.ravel(), Y.ravel())]
elif len(hdr_list) == 3:
X, Y, Z = np.meshgrid(hdr_list[0], hdr_list[1], hdr_list[2], indexing='ij')
tvar = [dict(x, **y, **z) for x, y, z in zip(X.ravel(), Y.ravel(), Z.ravel())]
return tvar
def convert_to_tuples(dict_list):
out_list = []
for dl in dict_list:
tl = []
for key in dl:
tl.append(dl[key])
out_list.append(tuple(tl))
return out_list
all_dim_hdrs_dict = []
for dim in range(5, 8):
if f'dim_{dim}_header' in self.hdr_ext:
all_dim_hdrs_dict.append(
list_of_dict_from_dim(self.hdr_ext[f'dim_{dim}_header'], self.shape[dim - 1]))
tvar_dict = sort_output(all_dim_hdrs_dict)
tvar_tuple = convert_to_tuples(tvar_dict)
tvar_dict2 = np.asarray(tvar_dict, dtype=object).reshape(self.shape[4:])
tvar_tuple2 = np.empty_like(tvar_dict2).flatten()
for idx, elm in enumerate(tvar_tuple):
tvar_tuple2[idx] = elm
tvar_array = np.asarray(tvar_tuple, dtype=object).reshape(np.prod(self.shape[4:]), len(tvar_tuple[0]))
return tvar_dict2, tvar_tuple2.reshape(self.shape[4:]), tvar_array
# If save called do some hairy temporary conjugation
# The save method of fsl.data.image.Image makes a call
# to __getitem__ resulting in a final undesired conjugation.
......
......@@ -94,6 +94,15 @@ class dynRes:
"""
return self._dyn.vm.mapped_to_free(self._init_x)
@property
def init_dataframe(self):
"""Free parameters calculated from the inversion of the dynamic model using the initilisation as input.
:return: Free parameters estimated from initilisation
:rtype: np.array
"""
return pd.DataFrame(data=self.free_parameters_init, index=self._dyn.free_names).T
@property
def mapped_parameters_fitted_init(self):
"""Mapped parameters resulting from inversion of model using initilised parameters.
......@@ -176,7 +185,7 @@ class dynRes:
return results
# Plotting
def plot_mapped(self, fit_to_init=False):
def plot_mapped(self, tvals=None, fit_to_init=False):
"""Plot each mapped parameter across time points
:param fit_to_init: Plot the mapped parameters as per initilisation, defaults to False
......@@ -188,7 +197,8 @@ class dynRes:
dyn_params = self.mapped_parameters.mean(axis=0)
dyn_params_sd = self.mapped_parameters.std(axis=0)
names = self.mapped_names
tvals = self._dyn.time_var
if tvals is None:
tvals = self._dyn.time_var
# Plot the lot
row, col = subplot_shape(len(names))
......
......@@ -17,6 +17,7 @@ from . import variable_mapping as varmap
from . import dyn_results
from fsl_mrs.utils.results import FitRes
from fsl_mrs.utils.stats import mh, dist
from fsl_mrs.utils.misc import rescale_FID
conc_index_re = re.compile(r'^(conc_.*?_)(\d+)$')
......@@ -50,8 +51,10 @@ class dynMRS(object):
:param metab_groups: Metabolite group list, defaults to None
:type metab_groups: list, optional
"""
self.mrs_list = mrs_list
self.time_var = time_var
self.mrs_list = mrs_list
self._process_mrs_list()
if metab_groups is None:
metab_groups = [0] * len(self.metabolite_names)
......@@ -70,6 +73,17 @@ class dynMRS(object):
varNames, varSizes = models.FSLModel_vars(model, numBasis, numGroups, baseline_order)
self.vm = self._create_vm(model, config_file, varNames, varSizes)
def _process_mrs_list(self):
"""Apply single scaling
"""
scales = []
for mrs in self.mrs_list:
scales.append(rescale_FID(mrs.FID, scale=100.0)[1])
for mrs in self.mrs_list:
mrs.fid_scaling = np.mean(scales)
mrs.basis_scaling_target = 100.0
@property
def metabolite_names(self):
return self.mrs_list[0].names
......@@ -267,7 +281,7 @@ class dynMRS(object):
mapped = self.vm.free_to_mapped(x)
LUT = self.vm.free_to_mapped(np.arange(self.vm.nfree), copy_only=True)
dfdx = 0
for time_index, time_var in enumerate(self.vm.time_variable):
for time_index, _ in enumerate(self.vm.time_variable):
# dfdmapped
p = np.hstack(mapped[time_index, :])
dfdp = self.loss_grad(p, time_index)
......@@ -280,7 +294,10 @@ class dynMRS(object):
for ip in range(nparams):
gg = np.zeros(self.vm.nfree)
gg[xindex[ip]] = grad_fcn(x[xindex[ip]], time_var)
if isinstance(xindex[ip], (int, np.int64)):
gg[xindex[ip]] = grad_fcn(x[xindex[ip]], self.vm.time_variable)
else:
gg[xindex[ip]] = grad_fcn(x[xindex[ip]], self.vm.time_variable)[:, time_index]
dpdx.append(gg)
dpdx = np.asarray(dpdx)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment