1
0
forked from IPKM/nmreval

fit results save weight; closes #139

This commit is contained in:
Dominik Demuth 2023-11-13 18:46:46 +01:00
parent f04cadf780
commit 8fb17b22fd
3 changed files with 82 additions and 25 deletions

View File

@ -13,7 +13,7 @@ class Data(object):
if self.y.shape[0] != self.x.shape[0]: if self.y.shape[0] != self.x.shape[0]:
raise ValueError(f'x and y have different lengths {self.x.shape[0]} and {self.y.shape[0]}') raise ValueError(f'x and y have different lengths {self.x.shape[0]} and {self.y.shape[0]}')
self.we = self._calc_weights(we) self.we, self.we_string = self._calc_weights(we)
self.idx = idx self.idx = idx
self.model = None self.model = None
self.minimizer = None self.minimizer = None
@ -24,16 +24,16 @@ class Data(object):
def __len__(self): def __len__(self):
return self.y.shape[0] return self.y.shape[0]
def _calc_weights(self, we): def _calc_weights(self, we: str | np.ndarray | None) -> tuple[np.ndarray, str]:
if we is None: if isinstance(we, str) or we is None:
return 1. if we is None or we.lower() == 'none':
we_string = 'None'
if isinstance(we, str):
if we == 'y2':
we_func = lambda yy: 1. / yy**2
elif we.lower() == 'none':
we_func = lambda yy: np.ones_like(len(yy)) we_func = lambda yy: np.ones_like(len(yy))
elif we == 'y2':
we_string = we
we_func = lambda yy: 1. / yy**2
else: else:
we_string = we
we_func = lambda yy: 1. / np.abs(yy) we_func = lambda yy: 1. / np.abs(yy)
if np.iscomplexobj(self.y): if np.iscomplexobj(self.y):
@ -42,6 +42,7 @@ class Data(object):
weights = we_func(self.y) weights = we_func(self.y)
else: else:
we_string = 'yerr' # This is pure speculation that array equals error
we = 1. / np.asarray(we) we = 1. / np.asarray(we)
if np.iscomplexobj(self.y): if np.iscomplexobj(self.y):
if np.iscomplexobj(we): if np.iscomplexobj(we):
@ -53,7 +54,7 @@ class Data(object):
weights[weights == np.inf] = np.finfo(float).max weights[weights == np.inf] = np.finfo(float).max
return weights return weights, we_string
def set_model(self, func, *args, **kwargs): def set_model(self, func, *args, **kwargs):
if isinstance(func, Model): if isinstance(func, Model):

View File

@ -484,9 +484,18 @@ class FitRoutine(object):
idx = self.data.index(data) idx = self.data.index(data)
model = data.get_model() model = data.get_model()
self.result[idx] = FitResultCreator.make_with_model(model, data.x, data.y, self.result[idx] = FitResultCreator.make_with_model(
actual_parameters, data.fun_kwargs, data.idx, model,
*shape, corr=actual_corr, pcorr=actual_pcorr) data.x,
data.y,
actual_parameters,
data.fun_kwargs,
data.we_string,
data.idx,
*shape,
corr=actual_corr,
pcorr=actual_pcorr,
)
return self.result return self.result

View File

@ -42,7 +42,19 @@ class FitResultCreator:
kwargs['name'], stats, idx) kwargs['name'], stats, idx)
@staticmethod @staticmethod
def make_with_model(model, x_orig, y_orig, p, fun_kwargs, idx, nobs, nvar, corr, pcorr) -> FitResult: def make_with_model(
model: 'Model',
x_orig: np.ndarray,
y_orig: np.ndarray,
p: 'Parameters',
fun_kwargs: dict,
we: str,
idx: str | None,
nobs: int,
nvar: int,
corr: np.ndarray,
pcorr: np.ndarray,
) -> FitResult:
if np.all(x_orig > 0) and (np.max(x_orig) > 100 * np.min(x_orig)): if np.all(x_orig > 0) and (np.max(x_orig) > 100 * np.min(x_orig)):
islog = True islog = True
else: else:
@ -104,10 +116,25 @@ class FitResultCreator:
correlation = corr correlation = corr
partial_correlation = pcorr partial_correlation = pcorr
return FitResult(_x, _y, x_orig, y_orig, parameters, fun_kwargs, resid, return FitResult(
nobs, nvar, model.name, stats, x=_x,
idx=idx, corr=correlation, pcorr=partial_correlation, y=_y,
islog=islog, func=model) x_data=x_orig,
y_data=y_orig,
params=parameters,
fun_kwargs=fun_kwargs,
resid=resid,
nobs=nobs,
nvar=nvar,
we=we,
name=model.name,
stats=stats,
idx=idx,
corr=correlation,
pcorr=partial_correlation,
islog=islog,
func=model,
)
@staticmethod @staticmethod
def calc_statistics(y, residual, nobs=None, nvar=None): def calc_statistics(y, residual, nobs=None, nvar=None):
@ -145,12 +172,27 @@ class FitResultCreator:
class FitResult(Points): class FitResult(Points):
def __init__(self, x: np.ndarray, y: np.ndarray, def __init__(
x_data: np.ndarray, y_data: np.ndarray, self: FitResult,
params: dict, fun_kwargs: dict, x: np.ndarray,
resid: np.ndarray, nobs: int, nvar: int, name: str, stats: dict, y: np.ndarray,
idx=None, corr=None, pcorr=None, islog=False, func=None, x_data: np.ndarray,
**kwargs): y_data: np.ndarray,
params: dict,
fun_kwargs: dict,
resid: np.ndarray,
nobs: int,
nvar: int,
we: str,
name: str,
stats: dict,
idx: int = None,
corr: np.ndarray = None,
pcorr: np.ndarray = None,
islog: bool = False,
func=None,
**kwargs
):
self.parameter, name = self._prepare_names(params, name) self.parameter, name = self._prepare_names(params, name)
label = kwargs.get('label', name) label = kwargs.get('label', name)
@ -161,6 +203,7 @@ class FitResult(Points):
self.statistics = stats self.statistics = stats
self.nobs = nobs self.nobs = nobs
self.nvar = nvar self.nvar = nvar
self.we = we
self.fun_kwargs = fun_kwargs self.fun_kwargs = fun_kwargs
self.correlation = corr self.correlation = corr
self.partial_correlation = pcorr self.partial_correlation = pcorr
@ -229,6 +272,7 @@ class FitResult(Points):
s.write(f' model : {self.name}\n') s.write(f' model : {self.name}\n')
s.write(f' #data : {self.nobs}\n') s.write(f' #data : {self.nobs}\n')
s.write(f' #var : {self.nvar}\n') s.write(f' #var : {self.nvar}\n')
s.write(f' #weight: {self.we}\n')
s.write('\nParameter\n') s.write('\nParameter\n')
s.write(self.parameter_string()) s.write(self.parameter_string())
@ -322,10 +366,13 @@ class FitResult(Points):
err = 0. err = 0.
f.write(f'{p.value:.8e}\t{err:.8e}\t') f.write(f'{p.value:.8e}\t{err:.8e}\t')
f.write('# ')
if self.fun_kwargs: if self.fun_kwargs:
f.write('# ')
for k, v in self.fun_kwargs.items(): for k, v in self.fun_kwargs.items():
f.write(f"{convert(k, old='tex', new='str')}: {convert(str(v), old='tex', new='str')}\t") f.write(f"{convert(k, old='tex', new='str')}: {convert(str(v), old='tex', new='str')}\t")
f.write(f'weight: {self.we}\t')
f.write('\n') f.write('\n')
f.write(f'# line above from: {self.name} (model: {self.model_name})') f.write(f'# line above from: {self.name} (model: {self.model_name})')
f.write('\n') f.write('\n')