From a36f8932f818aaaf3d05e13a78c9d5712f5190e6 Mon Sep 17 00:00:00 2001 From: Markus Rosenstihl Date: Wed, 16 Apr 2014 17:56:32 +0200 Subject: [PATCH] long running fits made abortable --- ConductivityGroupBox.py | 2 +- Container.py | 15 +++++++++++++-- PeakGroupBox.py | 2 +- PowerLawGroupBox.py | 2 +- QDS.py | 31 +++++++++++++++++++++++++------ QDSMain.py | 2 +- StaticGroupBox.py | 2 +- YAFFConfig.py | 2 +- YAFFparameters.py | 16 ++++++++-------- YAFFparameters.ui | 14 +++++++------- images_rc.py | 2 +- mathlib.py | 21 ++++++++++++++++++--- 12 files changed, 78 insertions(+), 33 deletions(-) diff --git a/ConductivityGroupBox.py b/ConductivityGroupBox.py index 0839720..3431099 100644 --- a/ConductivityGroupBox.py +++ b/ConductivityGroupBox.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'ConductivityGroupBox.ui' # -# Created: Tue Apr 15 15:17:02 2014 +# Created: Wed Apr 16 14:28:54 2014 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! diff --git a/Container.py b/Container.py index 85a3406..920f851 100644 --- a/Container.py +++ b/Container.py @@ -1,6 +1,6 @@ # -*- encoding: utf8 -*- -from PyQt4.QtCore import QObject, pyqtSignal, Qt +from PyQt4.QtCore import QObject, Qt, pyqtSignal, pyqtSlot from PyQt4.QtGui import QColor import numpy as np import pyqtgraph as pg @@ -45,6 +45,11 @@ class BaseObject(QObject): self._sd_beta = None self._selector_mask = None self._param_number = 0 + self._abort = False + + @pyqtSlot(bool) + def abort(self, abort=False): + self._abort = abort @property def param_number(self): @@ -134,7 +139,8 @@ class BaseObject(QObject): self.data_curve_imag.setData(x=[np.nan], y=[np.nan]) def function(self,p,x): - raise NotImplementedError, "This needs to be implemented in your subclass" + if self._abort: raise StopIteration + #raise NotImplementedError, "This needs to be implemented in your subclass" class Conductivity(BaseObject): @@ -165,6 +171,7 @@ class PowerComplex(BaseObject): self.param_number = 2 def function( self, p, x ): + BaseObject.function(self,p,x) om = 2*np.pi*x sgma,n = p power = sgma/(om*1j)**n @@ -182,6 +189,8 @@ class Static(BaseObject): self.param_number = 1 def function( self, p, x ): + BaseObject.function(self,p,x) + eps_inf = p[0] static = np.ones( (2,x.size) )*eps_inf static[1,:] *= 0 # set imag part zero @@ -201,6 +210,7 @@ class Peak(BaseObject): self.param_number = 4 def function( self, p, x ): + BaseObject.function(self,p,x) eps,t,a,b = p om = 2*np.pi*x hn = eps/(1+(1j*om*t)**a)**b @@ -242,6 +252,7 @@ class YAFF(BaseObject): self.updateData() def function( self, p, x ): + BaseObject.function(self,p,x) ya = self._libyaff.loss( p, x) cplx = np.array([ya.imag, ya.real]) return cplx \ No newline at end of file diff --git a/PeakGroupBox.py b/PeakGroupBox.py index d0a92eb..ca5973b 100644 --- a/PeakGroupBox.py +++ b/PeakGroupBox.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'PeakGroupBox.ui' # -# Created: Tue Apr 15 15:17:02 2014 +# Created: Wed Apr 16 14:28:54 2014 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! diff --git a/PowerLawGroupBox.py b/PowerLawGroupBox.py index 8d6f6c1..2a9d71e 100644 --- a/PowerLawGroupBox.py +++ b/PowerLawGroupBox.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'PowerLawGroupBox.ui' # -# Created: Tue Apr 15 15:17:02 2014 +# Created: Wed Apr 16 14:28:54 2014 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! diff --git a/QDS.py b/QDS.py index 2222ada..70382a8 100755 --- a/QDS.py +++ b/QDS.py @@ -206,7 +206,9 @@ class AppWindow(QMainWindow): def abortFit(self): - self._fit_thread.quit() + for container in self.function_registry.get_registered_functions(): + container.abort(True) + self._fit_thread.terminate() def saveFitResult(self): """ @@ -347,7 +349,6 @@ class AppWindow(QMainWindow): self.updatePlot() def delParamterObject(self, obj): - print "unregister",obj self.function_registry.unregister_function(obj) self.updatePlot() @@ -405,13 +406,20 @@ class AppWindow(QMainWindow): funcs.append(fcn) fixed_params.extend(fcn.getFixed()) + for container in self.function_registry.get_registered_functions(): + container.abort(False) + + self.data.set_fit(odr_result.beta, funcs) self.ui.statusbar.showMessage(" ".join(odr_result.stopreason)) ndx = 0 for i,fcn in enumerate(self.function_registry.get_registered_functions()): num_p = len(fcn.getParameter()) beta = odr_result.beta[ndx:num_p+ndx] - sd_beta = odr_result.sd_beta[ndx:num_p+ndx] + if odr_result.sd_beta is not None: + sd_beta = odr_result.sd_beta[ndx:num_p+ndx] + else: + sd_beta = None fcn.setParameter(beta, sd_beta) ndx += num_p @@ -469,12 +477,23 @@ class AppWindow(QMainWindow): self.data.set_data(_freq, _die_stor, _die_loss) self.data.meta["T"] = Temp self.fit_boundary_imag.setRegion([np.log10(_freq.min()), np.log10(_freq.max())]) - self.ui.pgPlotWidget_imag.enableAutoRange() - self.ui.pgPlotWidget_real.enableAutoRange() - self.updatePlot() +# self.ui.pgPlotWidget_imag.enableAutoRange() +# self.ui.pgPlotWidget_real.enableAutoRange() self.ui.pgPlotWidget_imag.disableAutoRange() self.ui.pgPlotWidget_real.disableAutoRange() + self.ui.pgPlotWidget_imag.setXRange(np.log10(_freq.min()), np.log10(_freq.max())) + self.ui.pgPlotWidget_imag.setYRange(np.log10(_die_loss.min()), np.log10(_die_loss.max())) + + self.ui.pgPlotWidget_real.setXRange(np.log10(_freq.min()), np.log10(_freq.max())) + self.ui.pgPlotWidget_real.setYRange(np.log10(_die_stor.min()), np.log10(_die_stor.max())) + + + #self.ui.pgPlotWidget_real.setRange(xRange=(_freq.min(), _freq.max()), + # yRange=(_die_stor.min(), _die_stor.max()) ) + self.updatePlot() + + def updatePlot(self): log10fmin, log10fmax = self.fit_boundary_imag.getRegion() diff --git a/QDSMain.py b/QDSMain.py index dec1a3b..1cf385f 100644 --- a/QDSMain.py +++ b/QDSMain.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'QDSMain.ui' # -# Created: Tue Apr 15 15:17:02 2014 +# Created: Wed Apr 16 14:28:54 2014 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! diff --git a/StaticGroupBox.py b/StaticGroupBox.py index 2e8605d..5657101 100644 --- a/StaticGroupBox.py +++ b/StaticGroupBox.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'StaticGroupBox.ui' # -# Created: Tue Apr 15 15:17:03 2014 +# Created: Wed Apr 16 14:28:54 2014 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! diff --git a/YAFFConfig.py b/YAFFConfig.py index a2c190b..5a8ffca 100644 --- a/YAFFConfig.py +++ b/YAFFConfig.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'YAFFConfig.ui' # -# Created: Tue Apr 15 15:17:03 2014 +# Created: Wed Apr 16 14:28:55 2014 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! diff --git a/YAFFparameters.py b/YAFFparameters.py index 6c61bcb..083ac1e 100644 --- a/YAFFparameters.py +++ b/YAFFparameters.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'YAFFparameters.ui' # -# Created: Tue Apr 15 15:17:03 2014 +# Created: Wed Apr 16 14:28:55 2014 # by: PyQt4 UI code generator 4.10.4 # # WARNING! All changes made in this file will be lost! @@ -26,7 +26,7 @@ except AttributeError: class Ui_Form(object): def setupUi(self, Form): Form.setObjectName(_fromUtf8("Form")) - Form.resize(271, 322) + Form.resize(300, 322) self.gridLayout = QtGui.QGridLayout(Form) self.gridLayout.setMargin(0) self.gridLayout.setSpacing(1) @@ -268,12 +268,12 @@ class Ui_Form(object): def retranslateUi(self, Form): Form.setWindowTitle(_translate("Form", "Form", None)) - self.label_422.setText(_translate("Form", "b", None)) + self.label_422.setText(_translate("Form", "β", None)) self.label_10.setText(_translate("Form", "TextLabel", None)) - self.label_111.setText(_translate("Form", "eps", None)) + self.label_111.setText(_translate("Form", "Δε", None)) self.label_4.setText(_translate("Form", "TextLabel", None)) self.label_5.setText(_translate("Form", "TextLabel", None)) - self.label_522.setText(_translate("Form", "lambda", None)) + self.label_522.setText(_translate("Form", "λ", None)) self.label_112.setText(_translate("Form", "s", None)) self.label_9.setText(_translate("Form", "TextLabel", None)) self.label_6.setText(_translate("Form", "TextLabel", None)) @@ -281,13 +281,13 @@ class Ui_Form(object): self.label_huh.setText(_translate("Form", "TextLabel", None)) self.label_2.setText(_translate("Form", "TextLabel", None)) self.label_102.setText(_translate("Form", "g", None)) - self.label_222.setText(_translate("Form", "tau_a", None)) - self.label_322.setText(_translate("Form", "a", None)) + self.label_222.setText(_translate("Form", "

τα

", None)) + self.label_322.setText(_translate("Form", "α", None)) self.label_8.setText(_translate("Form", "TextLabel", None)) self.label_1.setText(_translate("Form", "TextLabel", None)) self.label_3.setText(_translate("Form", "TextLabel", None)) self.label_82.setText(_translate("Form", "b", None)) - self.label_622.setText(_translate("Form", "tau_b", None)) + self.label_622.setText(_translate("Form", "

τβ

", None)) self.label_7.setText(_translate("Form", "TextLabel", None)) self.label_72.setText(_translate("Form", "a", None)) self.label_23.setText(_translate("Form", "Fix", None)) diff --git a/YAFFparameters.ui b/YAFFparameters.ui index bb165ec..ed8fa34 100644 --- a/YAFFparameters.ui +++ b/YAFFparameters.ui @@ -6,7 +6,7 @@ 0 0 - 271 + 300 322 @@ -37,7 +37,7 @@ - b + β Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -73,7 +73,7 @@ - eps + Δε Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -112,7 +112,7 @@ - lambda + λ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -208,7 +208,7 @@ - tau_a + <html><head/><body><p>τ<span style=" vertical-align:sub;">α</span></p></body></html> Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -218,7 +218,7 @@ - a + α Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter @@ -287,7 +287,7 @@ - tau_b + <html><head/><body><p>τ<span style=" vertical-align:sub;">β</span></p></body></html> Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter diff --git a/images_rc.py b/images_rc.py index 25d5c10..8984e49 100644 --- a/images_rc.py +++ b/images_rc.py @@ -2,7 +2,7 @@ # Resource object code # -# Created: Di. Apr. 15 15:17:02 2014 +# Created: Mi. Apr. 16 14:28:54 2014 # by: The Resource Compiler for PyQt (Qt v4.8.5) # # WARNING! All changes made in this file will be lost! diff --git a/mathlib.py b/mathlib.py index 9120166..5cce244 100644 --- a/mathlib.py +++ b/mathlib.py @@ -48,6 +48,7 @@ class FitFunctionCreator(QObject): if x.ndim == 2: x = x[0] result = f(p, x) + #fn.widget.updateTable(p) self.data += result # fit functions take only 1-dim x ndx += num_p self.new_data.emit(x, self.data) @@ -74,13 +75,21 @@ class FitFunctionCreator(QObject): class FitRoutine(QObject): finished_fit = pyqtSignal() data_ready = pyqtSignal(np.ndarray, np.ndarray) + def __init__(self): super(FitRoutine,self).__init__() self.f = FitFunctionCreator() self.f.new_data.connect(self.data_ready.emit) self._fitter = self.fit_odr_cmplx self._odr_fit = None + self._start_parameter = None + @property + def start_parameter(self): + return self._start_parameter + @start_parameter.setter + def start_paramter(self, p0): + self._start_parameter = p0 @property def fitter(self): return self._fitter @@ -90,8 +99,7 @@ class FitRoutine(QObject): self._fitter = f def fit_odr_cmplx(self, x, y, p0, fixed, fcns): - #if x.ndim < 2: - # x = N.resize(x, (2,x.size)) + self._start_parameter = p0 if np.iscomplexobj(y) and y.ndim == 1: weights = 1/np.abs(y)**2 we = np.resize(weights, (2, weights.size)) @@ -104,6 +112,7 @@ class FitRoutine(QObject): self._odr_fit = odr.ODR(dat, mod, p0, ifixx=(0,), ifixb=fixed, maxit=800) def fit_odr_imag(self, x, y, p0, fixed, fcns): + self._start_parameter = p0 if np.iscomplexobj(y) and y.ndim == 1: we = 1/np.imag(y)**2 else: @@ -115,10 +124,16 @@ class FitRoutine(QObject): @pyqtSlot() def fit(self): #print "TID in FitRoutine", QThread.thread() - self._odr_fit.run() + try: + self._odr_fit.run() + except RuntimeError: + print "muh" self.finished_fit.emit() def result(self): + if self._odr_fit.output is None: + self._odr_fit.output = odr.Output([self.start_parameter, None, None ]) + self._odr_fit.output.stopreason = ["Aborted by user"] return self._odr_fit.output