segfault on closing QDS fixed, threading simplified

This commit is contained in:
Markus Rosenstihl 2014-04-14 14:01:45 +02:00
parent 4913924222
commit eca637c35a
6 changed files with 278 additions and 313 deletions

241
Container.py Normal file
View File

@ -0,0 +1,241 @@
# -*- encoding: utf8 -*-
from PyQt4.QtCore import QObject, pyqtSignal, Qt
from PyQt4.QtGui import QColor
import numpy as np
import pyqtgraph as pg
import ContainerWidgets
import libyaff
from mathlib import Functions, id_to_color
__author__ = 'markusro'
class BaseObject(QObject):
changedData = pyqtSignal()
removeObj = pyqtSignal(QObject)
def __init__(self, plt_real=None, plt_imag=None, limits=None):
super(BaseObject, self).__init__()
myPen = pg.mkPen( style=Qt.DotLine,
width=2.5)
self.data_curve_real = pg.PlotDataItem(x=np.array([np.nan]),y=np.array([np.nan]), pen=myPen)
self.plt_real = plt_real
self.plt_real.addItem(self.data_curve_real)
self.data_curve_imag = pg.PlotDataItem(x=np.array([np.nan]),y=np.array([np.nan]), pen=myPen)
self.plt_imag = plt_imag
self.plt_imag.addItem(self.data_curve_imag)
self.limits = limits
# private varaibles
#self.functions = Functions()
self._color = QColor("white")
self._id_label = None
self._id_string = None
self._widget = None
self._frequency = np.logspace(np.log10(limits[0]), np.log10(limits[1]), 256)
self._data = None
self._func = None
self._beta = None
self._sd_beta = None
self._selector_mask = None
self._param_number = 0
@property
def param_number(self):
return self._param_number
@param_number.setter
def param_number(self, num):
self._param_number = num
@property
def id_string(self):
return self._id_string
@id_string.setter
def id_string(self, id):
#self._func = self.functions.get_function(id)
self._id_string = id
@property
def id_label(self):
return self._id_label
@id_label.setter
def id_label(self, id):
#self._func = self.functions.get_function(id)
self._func = self.function
self._id_label = id
@property
def color(self):
return self._color
@color.setter
def color(self, c):
self._color = c
self.data_curve_real.setPen(c)
self.data_curve_imag.setPen(c)
@property
def widget(self):
return self._widget
@widget.setter
def widget(self, wdgt):
self._widget = wdgt
self._widget.changedTable.connect(self.updateData) # TODO better to use self.setParameter
self.removeObj.connect(self._widget.deleteLater)
self._widget.removeMe.connect(self.removeMe)
def getParameter(self):
p = self.widget.getTable() # TODO ugly ... should return self._beta etc ...?
return p
def getFixed(self):
p = self.widget.fixedParameter()
return p
def setParameter(self, beta, sd_beta=None):
self._beta = beta
self._sd_beta = sd_beta
self.widget.updateTable(beta, sd_beta)
self.updateData()
def get_data(self):
return self._frequency, self._data
def removeMe(self):
self.plt_imag.removeItem(self.data_curve_imag)
self.plt_real.removeItem(self.data_curve_real)
self.removeObj.emit(self)
self.changedData.emit()
def updateData(self):
self._data = self._func(self.getParameter(), self._frequency)
self.data_curve_real.setData(x=self._frequency, y=self._data[0])
self.data_curve_imag.setData(x=self._frequency, y=self._data[1])
self.changedData.emit()
def resampleData(self, x):
data = self._func(self.getParameter(), x)
return np.array([x,data[0],data[1]]).T
def clearData(self):
self.data_curve_real.setData(x=[np.nan], y=[np.nan])
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"
class Conductivity(BaseObject):
def __init__( self, plt_imag=None, plt_real=None, limits=None ):
super(Conductivity, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = ContainerWidgets.ConductivityWidget()
self.color = QColor("blue")
self.id_label = "Cond."
self.id_string = "cond"
self.param_number = 3
def function(self, p, x ):
om = 2*np.pi*x
sgma, isgma, n = p
cond = sgma/(om**n) + isgma/(1j*om**n) # Jonscher (Universal Dielectric Response: e",e' prop sigma/omega**n
cplx = np.array([cond.real, -cond.imag])
return cplx
class PowerComplex(BaseObject):
def __init__( self, plt_real=None, plt_imag=None, limits=None ):
super(PowerComplex, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = ContainerWidgets.PowerLawWidget()
self.color = QColor("#ff44c4")
self.id_label = 'Power Law'
self.id_string = "pwr"
self.param_number = 2
def function( self, p, x ):
om = 2*np.pi*x
sgma,n = p
power = sgma/(om*1j)**n
cplx = np.array([power.real, -power.imag])
return cplx
class Static(BaseObject):
def __init__( self, plt_real=None, plt_imag=None, limits=None ):
super(Static, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = ContainerWidgets.StaticWidget()
self.color = QColor('#FF0F13')
self.id_label = u'ε(∞)'
self.id_string = "eps_infty"
self.param_number = 1
def function( self, p, x ):
eps_inf = p[0]
static = np.ones( (2,x.size) )*eps_inf
static[1,:] *= 0 # set imag part zero
return static
class Peak(BaseObject):
def __init__( self, id_num=None, plt_real=None, plt_imag=None, limits=None ):
super(Peak, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = ContainerWidgets.PeakWidget()
self.widget.setId(id_num)
self.color = id_to_color(id_num)
self.widget.setColor(self.color)
self.id_num = id_num
self.id_label = "Hav-Neg"
self.id_string = "hn"
self.param_number = 4
def function( self, p, x ):
eps,t,a,b = p
om = 2*np.pi*x
hn = eps/(1+(1j*om*t)**a)**b
cplx = np.array([hn.real, -hn.imag])
return cplx
class YAFF(BaseObject):
def __init__( self, plt_real=None, plt_imag=None, limits=None ):
super(YAFF, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = ContainerWidgets.YaffWidget()
self.widget.on_model_changed.connect(self.change_model)
self.color = QColor(32, 120, 29, int(255*0.82))
self._libyaff = libyaff.Yaff(self.widget.getYaffType())
self.id_label = self._libyaff.label
self.id_string = "yaff"
self._param_number = self._libyaff.params
self._selector_mask = self.widget.selector_mask
@property
def param_number(self):
return self._param_number
@param_number.setter
def param_number(self, num=None):
self._param_number = self._libyaff.params
def change_model(self):
self._libyaff = libyaff.Yaff(self.widget.getYaffType())
self._selector_mask = self.widget.selector_mask
self.id_label = self._libyaff.label
self.param_number = self._libyaff.params
self.updateData()
def function( self, p, x ):
ya = self._libyaff.loss( p, x)
cplx = np.array([ya.imag, ya.real])
return cplx

View File

@ -1,5 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
__author__ = 'markusro'
from PyQt4.QtGui import QGroupBox, QPalette, QColor from PyQt4.QtGui import QGroupBox, QPalette, QColor
import ConductivityGroupBox import ConductivityGroupBox
import PeakGroupBox import PeakGroupBox
@ -7,18 +9,26 @@ import PowerLawGroupBox
import StaticGroupBox import StaticGroupBox
import YAFFparameters import YAFFparameters
__author__ = 'markusro'
from PyQt4 import QtGui
from PyQt4.QtGui import * from PyQt4.QtGui import *
from PyQt4.QtCore import QRegExp, pyqtSignal,pyqtSlot from PyQt4.QtCore import QRegExp, pyqtSignal,pyqtSlot
#import PeakWidget
class ParameterWidget(QWidget):
def __init__(self, parent = None):
super(ParameterWidget, self).__init__(parent)
self.vlayout = QVBoxLayout(self)
self.vlayout.addSpacerItem(QSpacerItem(10,10,QSizePolicy.Minimum, QSizePolicy.Expanding) )
self.blockSignals(True)
def add(self, wdgt):
self.vlayout.insertWidget(self.vlayout.count()-1, wdgt)
self.vlayout.update()
class LogFSpinBox(QDoubleSpinBox): class LogFSpinBox(QDoubleSpinBox):
scientificNotationValidator = QRegExpValidator(QRegExp("[+-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+-]?\\d+)?")) scientificNotationValidator = QRegExpValidator(QRegExp("[+-]?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+-]?\\d+)?"))
def __init__(self, parent = None): def __init__(self, parent = None):
super(LogFSpinBox, self).__init__(parent) super(LogFSpinBox, self).__init__(parent)
self.setRange(0.0,1e18) self.setRange(0.0,1e18)
@ -39,19 +49,6 @@ class LogFSpinBox(QDoubleSpinBox):
def validate(self, str_value, p_int): def validate(self, str_value, p_int):
return self.scientificNotationValidator.validate(str_value, p_int) return self.scientificNotationValidator.validate(str_value, p_int)
class ParameterWidget(QWidget):
def __init__(self, parent = None):
super(ParameterWidget, self).__init__(parent)
self.vlayout = QVBoxLayout(self)
self.vlayout.addSpacerItem(QSpacerItem(10,10,QSizePolicy.Minimum, QSizePolicy.Expanding) )
self.blockSignals(True)
def add(self, wdgt):
self.vlayout.insertWidget(self.vlayout.count()-1, wdgt)
self.vlayout.update()
if __name__ == "__main__":
app = QApplication([])
class BaseWidget(QGroupBox): class BaseWidget(QGroupBox):
@ -370,19 +367,15 @@ class YaffWidget(BaseWidget):
super(YaffWidget, self).__init__(parent) super(YaffWidget, self).__init__(parent)
self.ui = YAFFparameters.Ui_Form() self.ui = YAFFparameters.Ui_Form()
self.ui.setupUi(self) self.ui.setupUi(self)
self.ui.doubleSpinBox_1.setParent(None) self.ui.doubleSpinBox_1.setParent(None)
self.ui.doubleSpinBox_1 = LogFSpinBox(self) self.ui.doubleSpinBox_1 = LogFSpinBox(self)
self.ui.gridLayout.addWidget(self.ui.doubleSpinBox_1, 2, 1) self.ui.gridLayout.addWidget(self.ui.doubleSpinBox_1, 2, 1)
self.ui.doubleSpinBox_2.setParent(None) self.ui.doubleSpinBox_2.setParent(None)
self.ui.doubleSpinBox_2 = LogFSpinBox(self) self.ui.doubleSpinBox_2 = LogFSpinBox(self)
self.ui.gridLayout.addWidget(self.ui.doubleSpinBox_2, 3, 1) self.ui.gridLayout.addWidget(self.ui.doubleSpinBox_2, 3, 1)
self.ui.doubleSpinBox_6.setParent(None) self.ui.doubleSpinBox_6.setParent(None)
self.ui.doubleSpinBox_6 = LogFSpinBox(self) self.ui.doubleSpinBox_6 = LogFSpinBox(self)
self.ui.gridLayout.addWidget(self.ui.doubleSpinBox_6, 9, 1) self.ui.gridLayout.addWidget(self.ui.doubleSpinBox_6, 9, 1)
self.ui.doubleSpinBox_9.setParent(None) self.ui.doubleSpinBox_9.setParent(None)
self.ui.doubleSpinBox_9 = LogFSpinBox(self) self.ui.doubleSpinBox_9 = LogFSpinBox(self)
self.ui.gridLayout.addWidget(self.ui.doubleSpinBox_9, 12, 1) self.ui.gridLayout.addWidget(self.ui.doubleSpinBox_9, 12, 1)
@ -452,8 +445,8 @@ class YaffWidget(BaseWidget):
] ]
for dsb in self.inputs: for dsb in self.inputs:
dsb.valueChanged.connect(self.changeValues) dsb.valueChanged.connect(self.changeValues)
self.change_model(0) self.change_model(0)
def getYaffType(self): def getYaffType(self):
return self.ui.comboBox.currentIndex() return self.ui.comboBox.currentIndex()

View File

@ -6,3 +6,5 @@ all:
pyuic4 PowerLawGroupBox.ui -o PowerLawGroupBox.py pyuic4 PowerLawGroupBox.ui -o PowerLawGroupBox.py
pyuic4 StaticGroupBox.ui -o StaticGroupBox.py pyuic4 StaticGroupBox.ui -o StaticGroupBox.py
pyuic4 YAFFparameters.ui -o YAFFparameters.py pyuic4 YAFFparameters.ui -o YAFFparameters.py
stats:
wc -l QDS.py ContainerWidgets.py Container.py libyaff.py mathlib.py data.py

77
QDS.py
View File

@ -8,6 +8,7 @@ import signal
from PyQt4.QtCore import * from PyQt4.QtCore import *
from PyQt4.QtGui import * from PyQt4.QtGui import *
import matplotlib import matplotlib
from Container import Conductivity, PowerComplex, Static, Peak, YAFF
from mathlib import fit_anneal, fit_lbfgsb, fit_odr_cmplx, FunctionRegister, FitRoutine from mathlib import fit_anneal, fit_lbfgsb, fit_odr_cmplx, FunctionRegister, FitRoutine
@ -22,12 +23,12 @@ import numpy as np
import QDSMain import QDSMain
from data import Data, Conductivity, Peak, PowerComplex, Static, YAFF from data import Data
import pyqtgraph as pg import pyqtgraph as pg
#import yaff #import yaff
from CustomWidgets import ParameterWidget, YaffWidget from ContainerWidgets import ParameterWidget, YaffWidget
USE_CROSSH=False USE_CROSSH=False
@ -157,10 +158,15 @@ class AppWindow(QMainWindow):
sc_imag.sigMouseMoved.connect(self.updateCrosshair) sc_imag.sigMouseMoved.connect(self.updateCrosshair)
# process cmd line args # process cmd line args
if files is not None: if files != []:
self.openFile(files[0]) self.openFile(files[0])
self._current_file_index = 0 self._current_file_index = 0
self._fit_method = FitRoutine()
self._fit_method.moveToThread(self._fit_thread)
self._fit_method.finished_fit.connect(self.fitData_update)
self._fit_method.data_ready.connect(self.updateIntermediatePlot)
self._fit_thread.started.connect(self._fit_method.fit)
def updateCrosshair(self,evt): def updateCrosshair(self,evt):
@ -215,8 +221,6 @@ class AppWindow(QMainWindow):
msgBox.setText("Click in imaginary part") msgBox.setText("Click in imaginary part")
msgBox.exec_() msgBox.exec_()
if self.ui.actionAdd_PowerLaw.isChecked(): if self.ui.actionAdd_PowerLaw.isChecked():
if mouse_in_imag: if mouse_in_imag:
self.addPowerComplex(data_pos) self.addPowerComplex(data_pos)
@ -317,7 +321,6 @@ class AppWindow(QMainWindow):
def addYaff(self, pos): def addYaff(self, pos):
_yaff = YAFF(plt_real=self.ui.pgPlotWidget_real, _yaff = YAFF(plt_real=self.ui.pgPlotWidget_real,
plt_imag=self.ui.pgPlotWidget_imag, plt_imag=self.ui.pgPlotWidget_imag,
limits=self.data.fit_limits) limits=self.data.fit_limits)
@ -341,13 +344,10 @@ class AppWindow(QMainWindow):
_conductivity.blockSignals(True) _conductivity.blockSignals(True)
_conductivity.changedData.connect(self.updatePlot) _conductivity.changedData.connect(self.updatePlot)
_conductivity.removeObj.connect(self.delParamterObject) _conductivity.removeObj.connect(self.delParamterObject)
cond_par = [0.0, 10**(pos.y() + pos.x())*2*np.pi , 1.0] cond_par = [0.0, 10**(pos.y() + pos.x())*2*np.pi , 1.0]
_conductivity.setParameter(beta=cond_par) _conductivity.setParameter(beta=cond_par)
self.parameterWidget.add(_conductivity.widget) self.parameterWidget.add(_conductivity.widget)
self.function_registry.register_function(_conductivity) ##todo self.function_registry.register_function(_conductivity) ##todo
self.updatePlot() self.updatePlot()
_conductivity.blockSignals(False) _conductivity.blockSignals(False)
@ -358,10 +358,8 @@ class AppWindow(QMainWindow):
limits=self.data.fit_limits) limits=self.data.fit_limits)
_power_complex.changedData.connect(self.updatePlot) _power_complex.changedData.connect(self.updatePlot)
_power_complex.removeObj.connect(self.delParamterObject) _power_complex.removeObj.connect(self.delParamterObject)
cond_par = [10**(pos.y() + pos.x())*2*np.pi , 1.0] cond_par = [10**(pos.y() + pos.x())*2*np.pi , 1.0]
_power_complex.setParameter(beta=cond_par) _power_complex.setParameter(beta=cond_par)
self.parameterWidget.add(_power_complex.widget) self.parameterWidget.add(_power_complex.widget)
self.function_registry.register_function(_power_complex) self.function_registry.register_function(_power_complex)
self.updatePlot() self.updatePlot()
@ -372,10 +370,8 @@ class AppWindow(QMainWindow):
limits=self.data.fit_limits) limits=self.data.fit_limits)
_eps_infty.changedData.connect(self.updatePlot) _eps_infty.changedData.connect(self.updatePlot)
_eps_infty.removeObj.connect(self.delParamterObject) _eps_infty.removeObj.connect(self.delParamterObject)
cond_par = [10**pos.y()] cond_par = [10**pos.y()]
_eps_infty.setParameter(beta=cond_par) _eps_infty.setParameter(beta=cond_par)
self.parameterWidget.add(_eps_infty.widget) self.parameterWidget.add(_eps_infty.widget)
self.function_registry.register_function(_eps_infty) self.function_registry.register_function(_eps_infty)
self.updatePlot() self.updatePlot()
@ -389,42 +385,21 @@ class AppWindow(QMainWindow):
id_list = [ key.id_num for key in id_list = [ key.id_num for key in
self.function_registry.get_registered_functions().keys() self.function_registry.get_registered_functions().keys()
if key.id_label == 'hn'] if key.id_label == 'hn']
self.peakId = 1 self.peakId = 1
while self.peakId in id_list: while self.peakId in id_list:
self.peakId += 1 self.peakId += 1
_peak = Peak(id_num=self.peakId, _peak = Peak(id_num=self.peakId,
plt_real=self.ui.pgPlotWidget_real, plt_real=self.ui.pgPlotWidget_real,
plt_imag=self.ui.pgPlotWidget_imag, plt_imag=self.ui.pgPlotWidget_imag,
limits=self.data.fit_limits) limits=self.data.fit_limits)
_peak.changedData.connect(self.updatePlot) _peak.changedData.connect(self.updatePlot)
_peak.removeObj.connect(self.delParamterObject) _peak.removeObj.connect(self.delParamterObject)
new_peak = [2*10**pos.y(), 1 / (2*np.pi*10**pos.x()), 1, 1] new_peak = [2*10**pos.y(), 1 / (2*np.pi*10**pos.x()), 1, 1]
_peak.setParameter(beta = new_peak) _peak.setParameter(beta = new_peak)
self.function_registry.register_function(_peak) self.function_registry.register_function(_peak)
self.parameterWidget.add(_peak.widget) self.parameterWidget.add(_peak.widget)
self.updatePlot() self.updatePlot()
def delPeak(self):
for i, peak in enumerate(self.peakBoxes.keys()):
if peak.widget.isHidden():
self.ui.pgPlotWidget_imag.removeItem(peak.mpl_line)
self.parameterWidget.vlayout.removeWidget(peak.widget)
self.function_registry.unregister_function(peak)
self.peakBoxes.pop(peak)
self.parameterWidget.vlayout.update()
self.updatePlot()
@pyqtSlot(np.ndarray)
def test(self, t=None):
print "test",t
def fitData_start(self, method): def fitData_start(self, method):
fit_methods = [fit_odr_cmplx, fit_lbfgsb, fit_anneal] fit_methods = [fit_odr_cmplx, fit_lbfgsb, fit_anneal]
@ -439,58 +414,40 @@ class AppWindow(QMainWindow):
# Prepare # Prepare
if not self._fit_thread.isRunning(): if not self._fit_thread.isRunning():
self._fit_method = FitRoutine() # self._fit_method = FitRoutine()
self._fit_method.moveToThread(self._fit_thread) # self._fit_method.moveToThread(self._fit_thread)
self._fit_method.finished_fit.connect(self.fitData_update) # self._fit_method.finished_fit.connect(self.fitData_update)
self._fit_method.fit_odr_cmplx(_freq, _fit, p0, fixed_params, funcs) self._fit_method.fit_odr_cmplx(_freq, _fit, p0, fixed_params, funcs)
self._fit_method.data_ready.connect(self.updateIntermediatePlot) # self._fit_method.data_ready.connect(self.updateIntermediatePlot)
#for fun in funcs: # self._fit_thread.started.connect(self._fit_method.fit)
# self._fit_method.data_ready.connect(fun.updateData) # self._fit_thread.finished.connect(self._fit_method.deleteLater)
self._fit_thread.started.connect(self._fit_method.fit)
self._fit_thread.finished.connect(self._fit_method.deleteLater)
self._fit_thread.start() self._fit_thread.start()
self.ui.statusbar.showMessage("Fitting ...") self.ui.statusbar.showMessage("Fitting ...")
else: else:
print "fit is still running" print "fit is still running"
pass
def fitData_update(self): def fitData_update(self):
print "before thread.quit"
print "running thread?:",self._fit_thread.isRunning()
self._fit_thread.quit() self._fit_thread.quit()
print "after thread.quit"
print "running thread?:",self._fit_thread.isRunning()
odr_result = self._fit_method.result() odr_result = self._fit_method.result()
print odr_result
# build function list
p0,funcs,fixed_params = [],[],[] p0,funcs,fixed_params = [],[],[]
for fcn in self.function_registry.get_registered_functions(): for fcn in self.function_registry.get_registered_functions():
p0.extend(fcn.getParameter()) p0.extend(fcn.getParameter())
funcs.append(fcn) funcs.append(fcn)
fixed_params.extend(fcn.getFixed()) fixed_params.extend(fcn.getFixed())
#print "Set fit data"
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))
for i,fcn in enumerate(self.function_registry.get_registered_functions()):
i = 0
for fcn in self.function_registry.get_registered_functions():
num_p = len(fcn.getParameter()) num_p = len(fcn.getParameter())
beta = odr_result.beta[i:num_p+i] beta = odr_result.beta[i:num_p+i]
sd_beta = odr_result.sd_beta[i:num_p+i] sd_beta = odr_result.sd_beta[i:num_p+i]
fcn.setParameter(beta, sd_beta) fcn.setParameter(beta, sd_beta)
i += num_p
#self.updatePlot()
def getFileNames(self): def getFileNames(self):
# TODO: multiple files, advance by button # TODO: multiple files, advance by button
self._file_paths = QFileDialog.getOpenFileNames(self, "Open file", "", '*.dat') self._file_paths = QFileDialog.getOpenFileNames(self, "Open file", "", '*.dat')
print "here", len(self._file_paths)
self._current_file_index = 0 self._current_file_index = 0
path = unicode(self._file_paths[self._current_file_index]) path = unicode(self._file_paths[self._current_file_index])
self.openFile(path) self.openFile(path)
#path = unicode(QFileDialog.getOpenFileName(self, "Open file")) #path = unicode(QFileDialog.getOpenFileName(self, "Open file"))
#path = "MCM42PG0_199.96K.dat" #path = "MCM42PG0_199.96K.dat"
@ -506,7 +463,7 @@ class AppWindow(QMainWindow):
def openFile(self,path): def openFile(self,path):
print "opening: %s"%path print "opening: %s"%path
self.filepath=path self.filepath=path
# TODO analyize file (LF,MF, HF) and act accordingly # TODO analyze file (LF,MF, HF) and act accordingly
data = np.loadtxt(path, skiprows=4) data = np.loadtxt(path, skiprows=4)
self.setWindowTitle(os.path.basename(path)) self.setWindowTitle(os.path.basename(path))
numpat = re.compile('\d+\.\d+') numpat = re.compile('\d+\.\d+')

231
data.py
View File

@ -2,12 +2,8 @@
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
from PyQt4.QtCore import *
import CustomWidgets from mathlib import FitFunctionCreator
from mathlib import id_to_color, FitFunctionCreator, Functions
import libyaff
class Data: class Data:
@ -69,229 +65,4 @@ class Data:
print "remove fitted_curve" print "remove fitted_curve"
#if self.fitted_curve is not None: self.fitted_curve.remove() #if self.fitted_curve is not None: self.fitted_curve.remove()
class BaseObject(QObject):
changedData = pyqtSignal()
removeObj = pyqtSignal(QObject)
def __init__(self, plt_real=None, plt_imag=None, limits=None):
super(BaseObject, self).__init__()
myPen = pg.mkPen( style=Qt.DotLine,
width=2.5)
self.data_curve_real = pg.PlotDataItem(x=np.array([np.nan]),y=np.array([np.nan]), pen=myPen)
self.plt_real = plt_real
self.plt_real.addItem(self.data_curve_real)
self.data_curve_imag = pg.PlotDataItem(x=np.array([np.nan]),y=np.array([np.nan]), pen=myPen)
self.plt_imag = plt_imag
self.plt_imag.addItem(self.data_curve_imag)
self.limits = limits
# private varaibles
self.functions = Functions()
self._color = QColor("white")
self._id = None
self._id_string = None
self._widget = None
self._frequency = np.logspace(np.log10(limits[0]), np.log10(limits[1]), 256)
self._data = None
self._func = None
self._beta = None
self._sd_beta = None
self._selector_mask = None
self._param_number = 0
@property
def param_number(self):
return self._param_number
@param_number.setter
def param_number(self, num):
self._param_number = num
@property
def id_string(self):
return self._id_string
@id_string.setter
def id_string(self, id):
#self._func = self.functions.get_function(id)
self._id_string = id
@property
def id_label(self):
return self._id
@id_label.setter
def id_label(self, id):
#self._func = self.functions.get_function(id)
self._func = self.function
self._id = id
@property
def color(self):
return self._color
@color.setter
def color(self, c):
self._color = c
self.data_curve_real.setPen(c)
self.data_curve_imag.setPen(c)
@property
def widget(self):
return self._widget
@widget.setter
def widget(self, wdgt):
self._widget = wdgt
self._widget.changedTable.connect(self.updateData) # TODO better to use self.setParameter
self._widget.removeMe.connect(self.removeMe)
def getParameter(self):
p = self.widget.getTable() # TODO ugly ... should return self._beta etc ...?
return p
def getFixed(self):
p = self.widget.fixedParameter()
return p
def setParameter(self, beta, sd_beta=None):
self._beta = beta
self._sd_beta = sd_beta
self.widget.updateTable(beta, sd_beta)
self.updateData()
def get_data(self):
return self._frequency, self._data
def removeMe(self):
self.plt_imag.removeItem(self.data_curve_imag)
self.plt_real.removeItem(self.data_curve_real)
self.removeObj.emit(self)
self.changedData.emit()
def updateData(self):
self._data = self._func(self.getParameter(), self._frequency)
self.data_curve_real.setData(x=self._frequency, y=self._data[0])
self.data_curve_imag.setData(x=self._frequency, y=self._data[1])
self.changedData.emit()
def resampleData(self, x):
data = self._func(self.getParameter(), x)
return np.array([x,data[0],data[1]]).T
def clearData(self):
self.data_curve_real.setData(x=[np.nan], y=[np.nan])
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"
class Conductivity(BaseObject):
def __init__( self, plt_imag=None, plt_real=None, limits=None ):
super(Conductivity, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = CustomWidgets.ConductivityWidget()
self.color = QColor("blue")
self.id_label = "Cond."
self.id_string = "cond"
self.param_number = 3
def function(self, p, x ):
om = 2*np.pi*x
sgma, isgma, n = p
cond = sgma/(om**n) + isgma/(1j*om**n) # Jonscher (Universal Dielectric Response: e",e' prop sigma/omega**n
cplx = np.array([cond.real, -cond.imag])
return cplx
class PowerComplex(BaseObject):
def __init__( self, plt_real=None, plt_imag=None, limits=None ):
super(PowerComplex, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = CustomWidgets.PowerLawWidget()
self.color = QColor("#ff44c4")
self.id_label = 'Power Law'
self.id_string = "pwr"
self.param_number = 2
def function( self, p, x ):
om = 2*np.pi*x
sgma,n = p
power = sgma/(om*1j)**n
cplx = np.array([power.real, -power.imag])
return cplx
class Static(BaseObject):
def __init__( self, plt_real=None, plt_imag=None, limits=None ):
super(Static, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = CustomWidgets.StaticWidget()
self.color = QColor('#FF0F13')
self.id_label = u'ε(∞)'
self.id_string = "eps_infty"
self.param_number = 1
def function( self, p, x ):
eps_inf = p[0]
static = np.ones( (2,x.size) )*eps_inf
static[1,:] *= 0 # set imag part zero
return static
class Peak(BaseObject):
def __init__( self, id_num=None, plt_real=None, plt_imag=None, limits=None ):
super(Peak, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = CustomWidgets.PeakWidget()
self.widget.setId(id_num)
self.color = id_to_color(id_num)
self.widget.setColor(self.color)
self.id_num = id_num
self.id_label = "Hav-Neg"
self.id_string = "hn"
self.param_number = 4
def function( self, p, x ):
eps,t,a,b = p
om = 2*np.pi*x
hn = eps/(1+(1j*om*t)**a)**b
cplx = np.array([hn.real, -hn.imag])
return cplx
class YAFF(BaseObject):
def __init__( self, plt_real=None, plt_imag=None, limits=None ):
super(YAFF, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits)
self.widget = CustomWidgets.YaffWidget()
self.widget.on_model_changed.connect(self.change_model)
self.color = QColor(32, 120, 29, int(255*0.82))
self._libyaff = libyaff.Yaff(self.widget.getYaffType())
self.id_label = self._libyaff.label
self.id_string = "yaff"
self._param_number = self._libyaff.params
self._selector_mask = self.widget.selector_mask
@property
def param_number(self):
return self._param_number
@param_number.setter
def param_number(self, num=None):
self._param_number = self._libyaff.params
def change_model(self):
self._libyaff = libyaff.Yaff(self.widget.getYaffType())
self._selector_mask = self.widget.selector_mask
self.id_label = self._libyaff.label
self.param_number = self._libyaff.params
self.updateData()
def function( self, p, x ):
ya = self._libyaff.loss( p, x)
cplx = np.array([ya.imag, ya.real])
return cplx

View File

@ -312,6 +312,7 @@ class FunctionRegister:
if self.registry.has_key(obj): if self.registry.has_key(obj):
self.registry.pop(obj) self.registry.pop(obj)
else: else:
obj.deleteLater()
raise AssertionError,"The object is not in the registry! This should NOT happen" raise AssertionError,"The object is not in the registry! This should NOT happen"
#print "FR: ",self.registry #print "FR: ",self.registry