Commit 9f18d0d7 authored by William Clarke's avatar William Clarke
Browse files

Move reslist output to optional method of dynres results object. Add more...

Move reslist output to optional method of dynres results object. Add more tests for nifti mrs interator.
parent 39ed3cf0
......@@ -70,6 +70,16 @@ def test_nifti_mrs_generator():
0, 0)
break
for gen_data, slice_idx in obj.iterate_over_dims(dim='DIM_COIL'):
assert gen_data.shape == (1, 1, 1, 4096, 32)
assert slice_idx == (slice(None, None, None),
slice(None, None, None),
slice(None, None, None),
slice(None, None, None),
slice(None, None, None),
0)
break
for gen_data, slice_idx in obj.iterate_over_dims(dim='DIM_DYN'):
assert gen_data.shape == (1, 1, 1, 4096, 64)
assert slice_idx == (slice(None, None, None),
......@@ -90,6 +100,32 @@ def test_nifti_mrs_generator():
assert slice_idx == (0, 0, 0, slice(None, None, None), 0)
break
obj2 = gen_new_nifti_mrs(
np.zeros((1, 1, 1, 100, 2, 10), dtype=complex),
0.0005,
120.0,
dim_tags=['DIM_EDIT', 'DIM_DYN', None])
for gen_data, slice_idx in obj2.iterate_over_dims(dim='DIM_DYN'):
assert gen_data.shape == (1, 1, 1, 100, 10)
assert slice_idx == (slice(None, None, None),
slice(None, None, None),
slice(None, None, None),
slice(None, None, None),
0,
slice(None, None, None))
break
for gen_data, slice_idx in obj2.iterate_over_dims(dim='DIM_EDIT'):
assert gen_data.shape == (1, 1, 1, 100, 2)
assert slice_idx == (slice(None, None, None),
slice(None, None, None),
slice(None, None, None),
slice(None, None, None),
slice(None, None, None),
0)
break
def test_nifti_mrs_spatial_generator():
obj = NIFTI_MRS(data['unprocessed'])
......
......@@ -50,12 +50,10 @@ def test_dynRes(fixed_ratio_mrs):
baseline_order=0,
metab_groups=[0, 0],
rescale=False)
res = dyn_obj.fit()
res_obj = dyn_obj.fit()[0]
resinit = dyn_obj.initialise()
res_obj = res['result']
import plotly
fig = res_obj.plot_spectra(init=True, fit_to_init=True)
assert isinstance(fig, plotly.graph_objs._figure.Figure)
......@@ -102,9 +100,8 @@ def test_dynRes_newton(fixed_ratio_mrs):
baseline_order=0,
metab_groups=[0, 0],
rescale=False)
res = dyn_obj.fit()
res_obj = dyn_obj.fit()[0]
res_obj = res['result']
assert isinstance(res_obj.cov_dyn, pd.DataFrame)
assert res_obj.cov_dyn.shape == (10, 10)
......@@ -122,6 +119,9 @@ def test_dynRes_newton(fixed_ratio_mrs):
assert isinstance(res_obj.mapped_params, pd.DataFrame)
assert res_obj.mapped_params.shape == (2, 8)
assert isinstance(res_obj.reslist, list)
assert len(res_obj.reslist) == 2
def test_dynRes_mcmc(fixed_ratio_mrs):
"""Test mcmc optimiser specific components"""
......@@ -136,9 +136,8 @@ def test_dynRes_mcmc(fixed_ratio_mrs):
metab_groups=[0, 0],
rescale=False)
res = dyn_obj.fit(method='MH', mh_jumps=20)
res_obj = dyn_obj.fit(method='MH', mh_jumps=20)[0]
res_obj = res['result']
assert isinstance(res_obj.cov_dyn, pd.DataFrame)
assert res_obj.cov_dyn.shape == (10, 10)
......@@ -169,7 +168,7 @@ def test_load_save(fixed_ratio_mrs, tmp_path):
metab_groups=[0, 0],
rescale=False)
res = dyn_obj.fit()['result']
res = dyn_obj.fit()[0]
res.save(tmp_path / 'res_save_test')
res_loaded = dyn.load_dyn_result(tmp_path / 'res_save_test', dyn_obj)
......
......@@ -150,9 +150,9 @@ def test_dynMRS_fit(fixed_ratio_mrs):
baseline_order=0,
metab_groups=[0, 0],
rescale=False)
res = dyn_obj.fit()
res, _ = dyn_obj.fit()
concs = res['result'].data_frame.filter(like='conc').to_numpy()
concs = res.data_frame.filter(like='conc').to_numpy()
assert np.allclose(concs, [1, 1, 1, 1], atol=0.1)
......@@ -167,9 +167,10 @@ def test_dynMRS_fit_mcmc(fixed_ratio_mrs):
baseline_order=0,
metab_groups=[0, 0],
rescale=False)
res = dyn_obj.fit(method='MH', mh_jumps=50)
init = dyn_obj.initialise(indiv_init=None)
res, _ = dyn_obj.fit(method='MH', mh_jumps=50, init=init)
concs = res['result'].data_frame.filter(like='conc').mean(axis=0).to_numpy()
concs = res.data_frame.filter(like='conc').mean(axis=0).to_numpy()
assert np.allclose(concs, [1, 1, 1, 1], atol=0.1)
......
......@@ -528,6 +528,15 @@ class dynRes_mcmc(dynRes):
"""
super().__init__(samples, dyn, init)
@property
def reslist(self):
"""Generate a list of (independent) results objects.
:return: List of FitRes objects.
:rtype: list
"""
return self._dyn.form_FitRes(self.dataframe.to_numpy(), 'MH')
@property
def cov_dyn(self):
"""Returns the covariance matrix of free parameters
......@@ -611,6 +620,15 @@ class dynRes_newton(dynRes):
std[name] = np.array(s).T
self._std = std
@property
def reslist(self):
"""Generate a list of (independent) results objects.
:return: List of FitRes objects.
:rtype: list
"""
return self._dyn.form_FitRes(self.x, 'Newton')
@property
def cov_dyn(self):
"""Returns the covariance matrix of free parameters
......
......@@ -228,7 +228,7 @@ class dynMRS(object):
:type init: dict, optional
:param verbose: Verbosity flag, defaults to False
:type verbose: bool, optional
:return: Tuple containing dedicated results object, list of fitRes objects, optimisation output (Newton only)
:return: Tuple containing dedicated results object, and optimisation output (Newton only)
:rtype: tuple
"""
if verbose:
......@@ -258,25 +258,18 @@ class dynMRS(object):
# Results
if verbose:
print('Collect results')
# 1. Create dedicated dynamic fit results
# Create dedicated dynamic fit results
if method.lower() == 'newton':
results = dyn_results.dynRes_newton(sol.x, self, init)
elif method.lower() == 'mh':
results = dyn_results.dynRes_mcmc(x, self, init)
else:
raise (Exception(f'Unrecognised method {method}'))
# 2. Create a list of fitRes objects for each timepoint for fsl_mrs like capabilities
res_list = self._form_FitRes(
x,
self._fit_args['model'],
method,
self._fit_args['ppmlim'],
self._fit_args['baseline_order'])
if verbose:
print(f"...completed in {time.time()-end_fit_time} seconds.")
return {'result': results, 'resList': res_list, 'optimisation_sol': sol}
return results, sol
def fit_mean_spectrum(self):
"""Return the parameters from the fit of the mean spectra stored in mrs_list."""
......@@ -288,12 +281,12 @@ class dynMRS(object):
mean_mrs.FID = mean_fid
return fitting.fit_FSLModel(mean_mrs, method='Newton', **self._fit_args).params
def initialise(self, indiv_init=None, verbose=False):
def initialise(self, indiv_init='mean', verbose=False):
"""Initialise the dynamic fitting using seperate fits of each spectrum.
:param indiv_init: Optional initilisation of individual fits.
Can be a numpy array of mapped parameters, 'mean' (fits the mean spectrum), or None (independent).
Defaults to None
Defaults to 'mean'.
:param verbose: Print information during fitting, defaults to False
:type verbose: bool, optional
:return: Dict containing free parameters and individual FitRes objects
......@@ -460,7 +453,7 @@ class dynMRS(object):
fwd[time_index, :] = self.forward[time_index](p)
return fwd.flatten()
def _form_FitRes(self, x, model, method, ppmlim, baseline_order):
def form_FitRes(self, x, method):
"""Create list of FitRes object"""
_, _, _, base_poly, metab_groups, _, _, _ = self._get_constants(
self.mrs_list[0],
......@@ -486,13 +479,13 @@ class dynMRS(object):
dynresList = []
for t in range(self.vm.ntimes):
mrs = self.mrs_list[t]
results = FitRes(model,
results = FitRes(self._fit_args['model'],
method,
mrs.names,
metab_groups,
baseline_order,
self._fit_args['baseline_order'],
base_poly,
ppmlim)
self._fit_args['ppmlim'])
results.loadResults(mrs, mapped[t])
dynresList.append(results)
return dynresList
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