long running fits made abortable

This commit is contained in:
Markus Rosenstihl 2014-04-16 17:56:32 +02:00
parent 67fbeffb6f
commit a36f8932f8
12 changed files with 78 additions and 33 deletions

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'ConductivityGroupBox.ui' # 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 # by: PyQt4 UI code generator 4.10.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!

View File

@ -1,6 +1,6 @@
# -*- encoding: utf8 -*- # -*- encoding: utf8 -*-
from PyQt4.QtCore import QObject, pyqtSignal, Qt from PyQt4.QtCore import QObject, Qt, pyqtSignal, pyqtSlot
from PyQt4.QtGui import QColor from PyQt4.QtGui import QColor
import numpy as np import numpy as np
import pyqtgraph as pg import pyqtgraph as pg
@ -45,6 +45,11 @@ class BaseObject(QObject):
self._sd_beta = None self._sd_beta = None
self._selector_mask = None self._selector_mask = None
self._param_number = 0 self._param_number = 0
self._abort = False
@pyqtSlot(bool)
def abort(self, abort=False):
self._abort = abort
@property @property
def param_number(self): def param_number(self):
@ -134,7 +139,8 @@ class BaseObject(QObject):
self.data_curve_imag.setData(x=[np.nan], y=[np.nan]) self.data_curve_imag.setData(x=[np.nan], y=[np.nan])
def function(self,p,x): 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): class Conductivity(BaseObject):
@ -165,6 +171,7 @@ class PowerComplex(BaseObject):
self.param_number = 2 self.param_number = 2
def function( self, p, x ): def function( self, p, x ):
BaseObject.function(self,p,x)
om = 2*np.pi*x om = 2*np.pi*x
sgma,n = p sgma,n = p
power = sgma/(om*1j)**n power = sgma/(om*1j)**n
@ -182,6 +189,8 @@ class Static(BaseObject):
self.param_number = 1 self.param_number = 1
def function( self, p, x ): def function( self, p, x ):
BaseObject.function(self,p,x)
eps_inf = p[0] eps_inf = p[0]
static = np.ones( (2,x.size) )*eps_inf static = np.ones( (2,x.size) )*eps_inf
static[1,:] *= 0 # set imag part zero static[1,:] *= 0 # set imag part zero
@ -201,6 +210,7 @@ class Peak(BaseObject):
self.param_number = 4 self.param_number = 4
def function( self, p, x ): def function( self, p, x ):
BaseObject.function(self,p,x)
eps,t,a,b = p eps,t,a,b = p
om = 2*np.pi*x om = 2*np.pi*x
hn = eps/(1+(1j*om*t)**a)**b hn = eps/(1+(1j*om*t)**a)**b
@ -242,6 +252,7 @@ class YAFF(BaseObject):
self.updateData() self.updateData()
def function( self, p, x ): def function( self, p, x ):
BaseObject.function(self,p,x)
ya = self._libyaff.loss( p, x) ya = self._libyaff.loss( p, x)
cplx = np.array([ya.imag, ya.real]) cplx = np.array([ya.imag, ya.real])
return cplx return cplx

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'PeakGroupBox.ui' # 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 # by: PyQt4 UI code generator 4.10.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'PowerLawGroupBox.ui' # 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 # by: PyQt4 UI code generator 4.10.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!

31
QDS.py
View File

@ -206,7 +206,9 @@ class AppWindow(QMainWindow):
def abortFit(self): 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): def saveFitResult(self):
""" """
@ -347,7 +349,6 @@ class AppWindow(QMainWindow):
self.updatePlot() self.updatePlot()
def delParamterObject(self, obj): def delParamterObject(self, obj):
print "unregister",obj
self.function_registry.unregister_function(obj) self.function_registry.unregister_function(obj)
self.updatePlot() self.updatePlot()
@ -405,13 +406,20 @@ class AppWindow(QMainWindow):
funcs.append(fcn) funcs.append(fcn)
fixed_params.extend(fcn.getFixed()) 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.data.set_fit(odr_result.beta, funcs)
self.ui.statusbar.showMessage(" ".join(odr_result.stopreason)) self.ui.statusbar.showMessage(" ".join(odr_result.stopreason))
ndx = 0 ndx = 0
for i,fcn in enumerate(self.function_registry.get_registered_functions()): for i,fcn in enumerate(self.function_registry.get_registered_functions()):
num_p = len(fcn.getParameter()) num_p = len(fcn.getParameter())
beta = odr_result.beta[ndx:num_p+ndx] 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) fcn.setParameter(beta, sd_beta)
ndx += num_p ndx += num_p
@ -469,12 +477,23 @@ class AppWindow(QMainWindow):
self.data.set_data(_freq, _die_stor, _die_loss) self.data.set_data(_freq, _die_stor, _die_loss)
self.data.meta["T"] = Temp self.data.meta["T"] = Temp
self.fit_boundary_imag.setRegion([np.log10(_freq.min()), np.log10(_freq.max())]) self.fit_boundary_imag.setRegion([np.log10(_freq.min()), np.log10(_freq.max())])
self.ui.pgPlotWidget_imag.enableAutoRange() # self.ui.pgPlotWidget_imag.enableAutoRange()
self.ui.pgPlotWidget_real.enableAutoRange() # self.ui.pgPlotWidget_real.enableAutoRange()
self.updatePlot()
self.ui.pgPlotWidget_imag.disableAutoRange() self.ui.pgPlotWidget_imag.disableAutoRange()
self.ui.pgPlotWidget_real.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): def updatePlot(self):
log10fmin, log10fmax = self.fit_boundary_imag.getRegion() log10fmin, log10fmax = self.fit_boundary_imag.getRegion()

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'QDSMain.ui' # 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 # by: PyQt4 UI code generator 4.10.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'StaticGroupBox.ui' # 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 # by: PyQt4 UI code generator 4.10.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'YAFFConfig.ui' # 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 # by: PyQt4 UI code generator 4.10.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!

View File

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'YAFFparameters.ui' # 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 # by: PyQt4 UI code generator 4.10.4
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -26,7 +26,7 @@ except AttributeError:
class Ui_Form(object): class Ui_Form(object):
def setupUi(self, Form): def setupUi(self, Form):
Form.setObjectName(_fromUtf8("Form")) Form.setObjectName(_fromUtf8("Form"))
Form.resize(271, 322) Form.resize(300, 322)
self.gridLayout = QtGui.QGridLayout(Form) self.gridLayout = QtGui.QGridLayout(Form)
self.gridLayout.setMargin(0) self.gridLayout.setMargin(0)
self.gridLayout.setSpacing(1) self.gridLayout.setSpacing(1)
@ -268,12 +268,12 @@ class Ui_Form(object):
def retranslateUi(self, Form): def retranslateUi(self, Form):
Form.setWindowTitle(_translate("Form", "Form", None)) 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_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_4.setText(_translate("Form", "TextLabel", None))
self.label_5.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_112.setText(_translate("Form", "s", None))
self.label_9.setText(_translate("Form", "TextLabel", None)) self.label_9.setText(_translate("Form", "TextLabel", None))
self.label_6.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_huh.setText(_translate("Form", "TextLabel", None))
self.label_2.setText(_translate("Form", "TextLabel", None)) self.label_2.setText(_translate("Form", "TextLabel", None))
self.label_102.setText(_translate("Form", "g", None)) self.label_102.setText(_translate("Form", "g", None))
self.label_222.setText(_translate("Form", "tau_a", None)) self.label_222.setText(_translate("Form", "<html><head/><body><p>τ<span style=\" vertical-align:sub;\">α</span></p></body></html>", None))
self.label_322.setText(_translate("Form", "a", None)) self.label_322.setText(_translate("Form", "α", None))
self.label_8.setText(_translate("Form", "TextLabel", None)) self.label_8.setText(_translate("Form", "TextLabel", None))
self.label_1.setText(_translate("Form", "TextLabel", None)) self.label_1.setText(_translate("Form", "TextLabel", None))
self.label_3.setText(_translate("Form", "TextLabel", None)) self.label_3.setText(_translate("Form", "TextLabel", None))
self.label_82.setText(_translate("Form", "b", None)) self.label_82.setText(_translate("Form", "b", None))
self.label_622.setText(_translate("Form", "tau_b", None)) self.label_622.setText(_translate("Form", "<html><head/><body><p>τ<span style=\" vertical-align:sub;\">β</span></p></body></html>", None))
self.label_7.setText(_translate("Form", "TextLabel", None)) self.label_7.setText(_translate("Form", "TextLabel", None))
self.label_72.setText(_translate("Form", "a", None)) self.label_72.setText(_translate("Form", "a", None))
self.label_23.setText(_translate("Form", "Fix", None)) self.label_23.setText(_translate("Form", "Fix", None))

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>271</width> <width>300</width>
<height>322</height> <height>322</height>
</rect> </rect>
</property> </property>
@ -37,7 +37,7 @@
<item row="7" column="0"> <item row="7" column="0">
<widget class="QLabel" name="label_422"> <widget class="QLabel" name="label_422">
<property name="text"> <property name="text">
<string>b</string> <string>β</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -73,7 +73,7 @@
<item row="2" column="0"> <item row="2" column="0">
<widget class="QLabel" name="label_111"> <widget class="QLabel" name="label_111">
<property name="text"> <property name="text">
<string>eps</string> <string>Δε</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -112,7 +112,7 @@
<item row="8" column="0"> <item row="8" column="0">
<widget class="QLabel" name="label_522"> <widget class="QLabel" name="label_522">
<property name="text"> <property name="text">
<string>lambda</string> <string>λ</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -208,7 +208,7 @@
<item row="3" column="0"> <item row="3" column="0">
<widget class="QLabel" name="label_222"> <widget class="QLabel" name="label_222">
<property name="text"> <property name="text">
<string>tau_a</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;τ&lt;span style=&quot; vertical-align:sub;&quot;&gt;α&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -218,7 +218,7 @@
<item row="5" column="0"> <item row="5" column="0">
<widget class="QLabel" name="label_322"> <widget class="QLabel" name="label_322">
<property name="text"> <property name="text">
<string>a</string> <string>α</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
@ -287,7 +287,7 @@
<item row="9" column="0"> <item row="9" column="0">
<widget class="QLabel" name="label_622"> <widget class="QLabel" name="label_622">
<property name="text"> <property name="text">
<string>tau_b</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;τ&lt;span style=&quot; vertical-align:sub;&quot;&gt;β&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>

View File

@ -2,7 +2,7 @@
# Resource object code # 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) # by: The Resource Compiler for PyQt (Qt v4.8.5)
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!

View File

@ -48,6 +48,7 @@ class FitFunctionCreator(QObject):
if x.ndim == 2: if x.ndim == 2:
x = x[0] x = x[0]
result = f(p, x) result = f(p, x)
#fn.widget.updateTable(p)
self.data += result # fit functions take only 1-dim x self.data += result # fit functions take only 1-dim x
ndx += num_p ndx += num_p
self.new_data.emit(x, self.data) self.new_data.emit(x, self.data)
@ -74,13 +75,21 @@ class FitFunctionCreator(QObject):
class FitRoutine(QObject): class FitRoutine(QObject):
finished_fit = pyqtSignal() finished_fit = pyqtSignal()
data_ready = pyqtSignal(np.ndarray, np.ndarray) data_ready = pyqtSignal(np.ndarray, np.ndarray)
def __init__(self): def __init__(self):
super(FitRoutine,self).__init__() super(FitRoutine,self).__init__()
self.f = FitFunctionCreator() self.f = FitFunctionCreator()
self.f.new_data.connect(self.data_ready.emit) self.f.new_data.connect(self.data_ready.emit)
self._fitter = self.fit_odr_cmplx self._fitter = self.fit_odr_cmplx
self._odr_fit = None 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 @property
def fitter(self): def fitter(self):
return self._fitter return self._fitter
@ -90,8 +99,7 @@ class FitRoutine(QObject):
self._fitter = f self._fitter = f
def fit_odr_cmplx(self, x, y, p0, fixed, fcns): def fit_odr_cmplx(self, x, y, p0, fixed, fcns):
#if x.ndim < 2: self._start_parameter = p0
# x = N.resize(x, (2,x.size))
if np.iscomplexobj(y) and y.ndim == 1: if np.iscomplexobj(y) and y.ndim == 1:
weights = 1/np.abs(y)**2 weights = 1/np.abs(y)**2
we = np.resize(weights, (2, weights.size)) 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) self._odr_fit = odr.ODR(dat, mod, p0, ifixx=(0,), ifixb=fixed, maxit=800)
def fit_odr_imag(self, x, y, p0, fixed, fcns): def fit_odr_imag(self, x, y, p0, fixed, fcns):
self._start_parameter = p0
if np.iscomplexobj(y) and y.ndim == 1: if np.iscomplexobj(y) and y.ndim == 1:
we = 1/np.imag(y)**2 we = 1/np.imag(y)**2
else: else:
@ -115,10 +124,16 @@ class FitRoutine(QObject):
@pyqtSlot() @pyqtSlot()
def fit(self): def fit(self):
#print "TID in FitRoutine", QThread.thread() #print "TID in FitRoutine", QThread.thread()
self._odr_fit.run() try:
self._odr_fit.run()
except RuntimeError:
print "muh"
self.finished_fit.emit() self.finished_fit.emit()
def result(self): 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 return self._odr_fit.output