catch errors in fit preparation

This commit is contained in:
Dominik Demuth
2023-09-07 19:52:53 +02:00
parent e2e52cebde
commit a406908a69
4 changed files with 79 additions and 60 deletions

View File

@ -916,10 +916,12 @@ class NMRMainWindow(QtWidgets.QMainWindow, Ui_BaseWindow):
self.action_odr_fit: 'odr'
}[self.ac_group.checkedAction()]
self.fit_dialog.fit_button.setEnabled(False)
self.management.start_fit(parameter, links, fit_options)
self.status.setText('Fit running...'.format(self.management.fitter.step))
self.fit_timer.start(500)
fit_is_ready = self.management.prepare_fit(parameter, links, fit_options)
if fit_is_ready:
self.management.start_fit()
self.fit_dialog.fit_button.setEnabled(False)
self.status.setText('Fit running...'.format(self.management.fitter.step))
self.fit_timer.start(500)
@QtCore.pyqtSlot(dict, int, bool)
def show_fit_preview(self, funcs: dict, num: int, show: bool):

View File

@ -424,9 +424,9 @@ class UpperManagement(QtCore.QObject):
for d in self.data.values():
d.mask = np.ones_like(d.mask, dtype=bool)
def start_fit(self, parameter: dict, links: list, fit_options: dict):
def prepare_fit(self, parameter: dict, links: list, fit_options: dict) -> bool:
if self._fit_active:
return
return False
self.__fit_options = (parameter, links, fit_options)
@ -436,67 +436,80 @@ class UpperManagement(QtCore.QObject):
fit_mode = fit_options['fit_mode']
we_option = fit_options['we']
for model_id, model_p in parameter.items():
m = Model(model_p['func'])
models[model_id] = m
self.fitter.fitmethod = fit_mode
m_complex = model_p['complex']
# all-encompassing error catch
try:
for model_id, model_p in parameter.items():
m = Model(model_p['func'])
models[model_id] = m
# sets are not in active order but in order they first appeared in fit dialog
# iterate over order of set id in active order and access parameter inside loop
# instead of directly looping
list_ids = list(model_p['parameter'].keys())
set_order = [self.active_id.index(i) for i in list_ids]
for pos in set_order:
set_id = list_ids[pos]
m_complex = model_p['complex']
data_i = self.data[set_id]
set_params = model_p['parameter'][set_id]
# sets are not in active order but in order they first appeared in fit dialog
# iterate over order of set id in active order and access parameter inside loop
# instead of directly looping
list_ids = list(model_p['parameter'].keys())
set_order = [self.active_id.index(i) for i in list_ids]
for pos in set_order:
set_id = list_ids[pos]
if we_option.lower() == 'deltay':
we = data_i.y_err**2
else:
we = we_option
data_i = self.data[set_id]
set_params = model_p['parameter'][set_id]
if m_complex is None or m_complex == 1:
_y = data_i.y.real
elif m_complex == 2 and np.iscomplexobj(data_i.y):
_y = data_i.y.imag
else:
_y = data_i.y
if we_option.lower() == 'deltay':
we = data_i.y_err**2
else:
we = we_option
_x = data_i.x
if m_complex is None or m_complex == 1:
_y = data_i.y.real
elif m_complex == 2 and np.iscomplexobj(data_i.y):
_y = data_i.y.imag
else:
_y = data_i.y
if fit_limits == 'none':
inside = slice(None)
elif fit_limits == 'x':
x_lim, _ = self.graphs[self.current_graph].ranges
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
else:
inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
_x = data_i.x
if isinstance(we, str):
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
else:
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
if fit_limits == 'none':
inside = slice(None)
elif fit_limits == 'x':
x_lim, _ = self.graphs[self.current_graph].ranges
inside = np.where((_x >= x_lim[0]) & (_x <= x_lim[1]))
else:
inside = np.where((_x >= fit_limits[0]) & (_x <= fit_limits[1]))
d.set_model(m)
d.set_parameter(set_params[0], var=model_p['var'],
lb=model_p['lb'], ub=model_p['ub'],
fun_kwargs=set_params[1])
if isinstance(we, str):
d = fit_d.Data(_x[inside], _y[inside], we=we, idx=set_id)
else:
d = fit_d.Data(_x[inside], _y[inside], we=we[inside], idx=set_id)
self.fitter.add_data(d)
d.set_model(m)
d.set_parameter(set_params[0], var=model_p['var'],
lb=model_p['lb'], ub=model_p['ub'],
fun_kwargs=set_params[1])
model_globs = model_p['glob']
if model_globs:
m.set_global_parameter(**model_p['glob'])
self.fitter.add_data(d)
for links_i in links:
self.fitter.set_link_parameter((models[links_i[0]], links_i[1]),
(models[links_i[2]], links_i[3]))
model_globs = model_p['glob']
if model_globs:
m.set_global_parameter(**model_p['glob'])
for links_i in links:
self.fitter.set_link_parameter((models[links_i[0]], links_i[1]),
(models[links_i[2]], links_i[3]))
return True
except Exception as e:
logger.error('Fit preparation failed', *e.args)
QtWidgets.QMessageBox.warning(QtWidgets.QWidget(),
'Fit prep failed',
f'Fit preparation failed with message\n{e.args}')
return False
def start_fit(self):
with busy_cursor():
self.fit_worker = FitWorker(self.fitter, fit_mode)
self.fit_worker = FitWorker(self.fitter)
self.fit_thread = QtCore.QThread()
self.fit_worker.moveToThread(self.fit_thread)
@ -532,7 +545,8 @@ class UpperManagement(QtCore.QObject):
for set_id, set_parameter in parameter.items():
new_values = [v.value for v in res[set_id].parameter.values()]
parameter[set_id] = (new_values, set_parameter[1])
self.start_fit(*self.__fit_options)
if self.prepare_fit(*self.__fit_options):
self.start_fit()
def make_fits(self, res: dict, opts: list, param_graph: str, show_fit: bool, parts: bool, extrapolate: list) -> None:
"""
@ -1270,16 +1284,15 @@ class UpperManagement(QtCore.QObject):
class FitWorker(QtCore.QObject):
finished = QtCore.pyqtSignal(list, bool)
def __init__(self, fitter, mode):
def __init__(self, fitter):
super().__init__()
self.fitter = fitter
self.mode = mode
@QtCore.pyqtSlot()
def run(self):
try:
res = self.fitter.run(mode=self.mode)
res = self.fitter.run()
success = True
except Exception as e:
res = [e]