diff --git a/CustomWidgets.py b/CustomWidgets.py index 5b59f17..bbccad1 100644 --- a/CustomWidgets.py +++ b/CustomWidgets.py @@ -12,7 +12,7 @@ __author__ = 'markusro' from PyQt4 import QtGui from PyQt4.QtGui import * -from PyQt4.QtCore import QRegExp, pyqtSignal +from PyQt4.QtCore import QRegExp, pyqtSignal,pyqtSlot #import PeakWidget @@ -65,6 +65,7 @@ class BaseWidget(QGroupBox): self.inputs = [] self.errors = [] self.names = [] + self.selector_mask = None # TODO: clean up def remove(self): self.removeMe.emit() @@ -389,9 +390,7 @@ class YaffWidget(BaseWidget): self.ui.removeButton.clicked.connect(self.remove) self.ui.comboBox.currentIndexChanged.connect(self.change_model) - - self.change_model() - self.names = [ + self._names = [ "Deps", "tau_a", "alpha", @@ -400,10 +399,22 @@ class YaffWidget(BaseWidget): "tau_b", "a", "b", - "none", - "none" + "scale", + "g" ] + self.labels = [ + self.ui.label_111, + self.ui.label_222, + self.ui.label_322, + self.ui.label_422, + self.ui.label_522, + self.ui.label_622, + self.ui.label_72, + self.ui.label_82, + self.ui.label_112, + self.ui.label_102 + ] self.errors = [self.ui.label_1, self.ui.label_2, self.ui.label_3, @@ -442,20 +453,34 @@ class YaffWidget(BaseWidget): for dsb in self.inputs: dsb.valueChanged.connect(self.changeValues) + self.change_model(0) def getYaffType(self): return self.ui.comboBox.currentIndex() - def change_model(self): - ndx = self.ui.comboBox.currentIndex() + @pyqtSlot(int) + def change_model(self,ndx): + #ndx = self.ui.comboBox.currentIndex() mask = [ (0,0,0,0,1,1,1,1,1,1), - (0,0,0,0,0,0,1,1,1,1), + (0,0,0,0,1,1,1,1,0,0), (0,0,0,0,0,0,0,0,1,1), (0,0,0,0,0,0,0,0,0,0), ] + self.names = [] + for i,inp in enumerate(self.inputs): self.inputs[i].setDisabled(mask[ndx][i]) + self.inputs[i].setHidden(mask[ndx][i]) + self.errors[i].setDisabled(mask[ndx][i]) - self.fixedCheckBoxes[i].setDisabled(mask[ndx][i]) + self.errors[i].setHidden(mask[ndx][i]) self.errors[i].setText("(---)") + + self.fixedCheckBoxes[i].setChecked(mask[ndx][i]) + self.fixedCheckBoxes[i].setDisabled(mask[ndx][i]) + self.fixedCheckBoxes[i].setHidden(mask[ndx][i]) + + self.labels[i].setHidden(mask[ndx][i]) + if mask[ndx][i]==0: self.names.append(self._names[i]) + self.selector_mask = [not i for i in mask[ndx] ] self.on_model_changed.emit() diff --git a/QDS.py b/QDS.py index 2d7036e..3d878a2 100755 --- a/QDS.py +++ b/QDS.py @@ -241,9 +241,15 @@ class AppWindow(QMainWindow): for fcn in self.function_registry.get_registered_functions(): for name in fcn.widget.names: # variable names header += "{n:11}{n_sd:11}".format(n=name, n_sd=name+"_sd") - for i,par in enumerate(fcn._beta): # params - pars.extend([par]) - pars.extend([fcn._sd_beta[i]]) + + for i,par in enumerate(fcn._beta): # params # TODO: ughh + if fcn._selector_mask is not None: + if fcn._selector_mask[i]: + pars.extend([par]) + pars.extend([fcn._sd_beta[i]]) + else: + pars.extend([par]) + pars.extend([fcn._sd_beta[i]]) header += "%-11s%-11s\n"%("fit_xlow","fit_xhigh") @@ -263,21 +269,23 @@ class AppWindow(QMainWindow): f.close() def saveFitFigure(self): - fig = pyplot.figure(figsize=(3.54, 2.75)) + fig = pyplot.figure(figsize=(3.54*1.4, 2.75*1.4)) font = {'family' : 'sans serif', 'weight' : 'normal', - 'size' : 8} + 'size' : 9} matplotlib.rc('font', **font) pyplot.grid(linestyle="solid",alpha=0.3, color="0.5") - pyplot.loglog(self.data.frequency, self.data.epsilon.imag, 'bo', markersize=3, label="Data") + pyplot.loglog(self.data.frequency, self.data.epsilon.imag, 'bo', markersize=4, label="Data") pyplot.loglog(self.data.frequency_fit, self.data.epsilon_fit.imag, 'r-', lw=1.2, label="Fit") for fcn in self.function_registry.get_registered_functions(): f,eps = fcn.get_data() - pyplot.loglog(f,eps[1], ls=":", color=hex2color(str(fcn.color.name())) , lw=1, dashes=(1,2)) + label = fcn.id_string + color = hex2color(str(fcn.color.name())) + pyplot.loglog(f,eps[1], ls=":", color=color, lw=1, dashes=(1,1), label=label) for i in (0,1): pyplot.axvline(x=self.data.fit_limits[i], color='b', ls="-", lw=0.5) pyplot.legend(title = "T=%.1f K"%(self.data.meta["T"])) @@ -297,8 +305,8 @@ class AppWindow(QMainWindow): _yaff.blockSignals(True) _yaff.changedData.connect(self.updatePlot) _yaff.removeObj.connect(self.delParamterObject) - gg_y = 10**pos.y() - gg_x = 10**pos.x()*2*np.pi + gg_y = 10**pos.y()*2 + gg_x = 1/(10**pos.x()*2*np.pi) yaff_par = [ gg_y, gg_x , 20.0, 1.0, 0.5, gg_x/100, 1.0, 1.0] _yaff.setParameter(beta=yaff_par) self.parameterWidget.add(_yaff.widget) @@ -405,32 +413,38 @@ class AppWindow(QMainWindow): p0,funcs,fixed_params = [],[],[] for fcn in self.function_registry.get_registered_functions(): p0.extend(fcn.getParameter()) - #funcs.append(fcn.id_string) funcs.append(fcn) fixed_params.extend(fcn.getFixed()) + fcn.clearData() _freq, _fit = self.data.get_data() # Prepare - - self._fit_method = FitRoutine() - self._fit_method.moveToThread(self._fit_thread) - - self._fit_method.finished_fit.connect(self.fitData_update) - - self._fit_method.fit_odr_cmplx(_freq, _fit, p0, fixed_params, funcs) - - self._fit_method.data_ready.connect(self.updateIntermediatePlot) - - self._fit_thread.started.connect(self._fit_method.fit) - - - self._fit_thread.start() - self.ui.statusbar.showMessage("Fitting ...") + if not self._fit_thread.isRunning(): + self._fit_method = FitRoutine() + self._fit_method.moveToThread(self._fit_thread) + self._fit_method.finished_fit.connect(self.fitData_update) + self._fit_method.fit_odr_cmplx(_freq, _fit, p0, fixed_params, funcs) + self._fit_method.data_ready.connect(self.updateIntermediatePlot) + #for fun in funcs: + # self._fit_method.data_ready.connect(fun.updateData) + self._fit_thread.started.connect(self._fit_method.fit) + self._fit_thread.finished.connect(self._fit_method.deleteLater) + self._fit_thread.start() + self.ui.statusbar.showMessage("Fitting ...") + else: + print "fit is still running" + pass def fitData_update(self): - self._fit_thread.quit() - odr_result = self._fit_method.result() + print "before thread.quit" + print "running thread?:",self._fit_thread.isRunning() + self._fit_thread.quit() + print "after thread.quit" + print "running thread?:",self._fit_thread.isRunning() + + odr_result = self._fit_method.result() + print odr_result # build function list p0,funcs,fixed_params = [],[],[] for fcn in self.function_registry.get_registered_functions(): diff --git a/data.py b/data.py index b013acb..7c293be 100644 --- a/data.py +++ b/data.py @@ -1,3 +1,4 @@ +# -*- encoding: utf8 -*- from PyQt4.QtGui import QColor import numpy as np import pyqtgraph as pg @@ -98,6 +99,7 @@ class BaseObject(QObject): self._func = None self._beta = None self._sd_beta = None + self._selector_mask = None self._param_number = 0 @property @@ -114,7 +116,8 @@ class BaseObject(QObject): @id_string.setter def id_string(self, id): - self._func = self.functions.get_function(id) + #self._func = self.functions.get_function(id) + self._func = self.function self._id = id @property @@ -166,6 +169,10 @@ class BaseObject(QObject): self.data_curve_imag.setData(x=self._frequency, y=self._data[1]) self.changedData.emit() + 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" @@ -174,7 +181,7 @@ class Conductivity(BaseObject): super(Conductivity, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits) self.widget = CustomWidgets.ConductivityWidget() self.color = QColor("blue") - self.id_string = "conductivity" + self.id_string = "Cond." self.param_number = 3 @@ -191,7 +198,7 @@ class PowerComplex(BaseObject): super(PowerComplex, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits) self.widget = CustomWidgets.PowerLawWidget() self.color = QColor("#ff44c4") - self.id_string = 'power' + self.id_string = 'Power Law' self.param_number = 2 def function( self, p, x ): @@ -207,7 +214,7 @@ class Static(BaseObject): super(Static, self).__init__(plt_real=plt_real, plt_imag=plt_imag, limits=limits) self.widget = CustomWidgets.StaticWidget() self.color = QColor('#FF0F13') - self.id_string = 'static' + self.id_string = u'ε(∞)' self.param_number = 1 def function( self, p, x ): @@ -240,10 +247,11 @@ class YAFF(BaseObject): 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.id_string = "yaff" - + self.color = QColor(32, 120, 29, int(255*0.82)) self._libyaff = libyaff.Yaff(self.widget.getYaffType()) + self.id_string = self._libyaff.label self._param_number = self._libyaff.params + self._selector_mask = self.widget.selector_mask @property def param_number(self): @@ -255,12 +263,14 @@ class YAFF(BaseObject): def change_model(self): self._libyaff = libyaff.Yaff(self.widget.getYaffType()) + self._selector_mask = self.widget.selector_mask + self.id_string = self._libyaff.label self.param_number = self._libyaff.params self.updateData() def function( self, p, x ): - ya = self._libyaff.loss( p[:self.param_number], x) + ya = self._libyaff.loss( p, x) cplx = np.array([ya.imag, ya.real]) return cplx diff --git a/libyaff.py b/libyaff.py index 3cfa33a..79a53aa 100644 --- a/libyaff.py +++ b/libyaff.py @@ -26,10 +26,12 @@ class PhiT: def __init__(self, dist_x, dist_y): self.dist_x = dist_x self.dist_y = dist_y - def __call__(self,t): - kern = self.dist_y*exp(-t/self.dist_x) - phi = scipy.integrate.simps(kern,log(self.dist_x)) - return phi + def __call__(self, ts): + phis = zeros(ts.size) + for i,t in enumerate(ts): + kern = self.dist_y*exp(-t/self.dist_x) + phis[i] = scipy.integrate.simps(kern, log(self.dist_x)) + return phis class Yaff(QObject): @@ -39,14 +41,13 @@ class Yaff(QObject): self.dist_x = logspace(-10,5,512) self.dist_y = zeros(self.dist_x.size) yaff = [ - (self.yaff_gg, 4), - (self.yaff_gge, 6), - (self.yaff, 8), - (self.yaff_extended, 10), - + (self.yaff_gg, "GG"), + (self.yaff_gge, "GGe"), + (self.yaff, "GG + GGb"), + (self.yaff_extended, "GGe + GGb"), ] - self.loss, self.params = yaff[dist_type] - + self.loss, self.label = yaff[dist_type] + self.params = 10 def gg(self, p, tau): tau0, a, b = p """ @@ -64,7 +65,7 @@ class Yaff(QObject): return norm_ggb*g def gg_hw(self, p ,tau): - tau0, a, b, g, s = p + tau0, a, b, s,g = p """ Generalized Gamma function with HF wing. s gives the onset of the wing in units of tau0, i.e. 100 means 100*tau0 or two decades later @@ -83,22 +84,23 @@ class Yaff(QObject): epp[i] += 1j*scipy.integrate.simps(kern_imag,log(dist_x)) return epp + # serial version def dist_to_relax_(self, ts,dist_x,dist_y): phi = zeros(len(ts)) for i,t in enumerate(ts): phi[i] = self.phi_t(t,dist_x,dist_y) return phi + # parallel version def dist_to_relax(self, ts,dist_x,dist_y): - phi = zeros(len(ts)) pool = multiprocessing.Pool() - result = pool.map(PhiT(dist_x,dist_y), ts) + num_cpus = multiprocessing.cpu_count() + ts_chunks = array_split(ts,num_cpus) + result = pool.map(PhiT(dist_x,dist_y), ts_chunks ) pool.close() pool.terminate() pool.join() - return array(result) - - + return concatenate(result) def phi_t(self, t, dist_x, dist_y): @@ -157,7 +159,7 @@ class Yaff(QObject): """ GG + GB """ - delta_eps, tau1, a1, b1, lambd, tau2, a2, b2 = p + delta_eps, tau1, a1, b1, lambd, tau2, a2, b2, s, g = p dist_ggb = self.ggb(p=[tau2,a2,b2], tau=self.dist_x) dist_gg = self.gg (p=[tau1,a1,b1], tau=self.dist_x) @@ -182,7 +184,7 @@ class Yaff(QObject): """ GG """ - delta_eps, tau1,a1,b1 = p + delta_eps, tau1, a1, b1, lambd, tau2, a2, b2, s, g = p ts = logspace(-10,5,512) dist_gg = self.gg(p=[tau1,a1,b1], tau=self.dist_x) self.dist_y = dist_gg @@ -195,7 +197,7 @@ class Yaff(QObject): """ GG """ - delta_eps, tau1, a1, b1, s, g = p + delta_eps, tau1, a1, b1, lambd, tau2, a2, b2, s, g = p ts = logspace(-10,5,512) dist_gg = self.gg_hw(p=[tau1, a1, b1, s, g], tau=self.dist_x) self.dist_y = dist_gg