pure imaginary part fitting implemented
This commit is contained in:
parent
6b84d6da95
commit
9da511b92a
44
QDS.py
44
QDS.py
@ -10,7 +10,7 @@ from PyQt4.QtGui import *
|
|||||||
import matplotlib
|
import matplotlib
|
||||||
from Container import Conductivity, PowerComplex, Static, Peak, YAFF
|
from Container import Conductivity, PowerComplex, Static, Peak, YAFF
|
||||||
|
|
||||||
from mathlib import fit_anneal, fit_lbfgsb, fit_odr_cmplx, FunctionRegister, FitRoutine
|
from mathlib import FunctionRegister, FitRoutine
|
||||||
|
|
||||||
matplotlib.use('agg')
|
matplotlib.use('agg')
|
||||||
|
|
||||||
@ -26,11 +26,8 @@ import QDSMain
|
|||||||
from data import Data
|
from data import Data
|
||||||
import pyqtgraph as pg
|
import pyqtgraph as pg
|
||||||
|
|
||||||
#import yaff
|
from ContainerWidgets import ParameterWidget
|
||||||
|
|
||||||
from ContainerWidgets import ParameterWidget, YaffWidget
|
|
||||||
|
|
||||||
USE_CROSSH=False
|
|
||||||
|
|
||||||
class AppWindow(QMainWindow):
|
class AppWindow(QMainWindow):
|
||||||
|
|
||||||
@ -73,16 +70,6 @@ class AppWindow(QMainWindow):
|
|||||||
self.ui.pgPlotWidget_imag.addItem(self.data.fitted_curve_imag)
|
self.ui.pgPlotWidget_imag.addItem(self.data.fitted_curve_imag)
|
||||||
self.ui.pgPlotWidget_real.addItem(self.data.fitted_curve_real)
|
self.ui.pgPlotWidget_real.addItem(self.data.fitted_curve_real)
|
||||||
|
|
||||||
# cross hair
|
|
||||||
if USE_CROSSH:
|
|
||||||
#self.poslabel = pg.LabelItem(justify='right')
|
|
||||||
self.horizontalLine = pg.InfiniteLine(angle=0)
|
|
||||||
self.verticalLine = pg.InfiniteLine(angle=90)
|
|
||||||
|
|
||||||
#self.ui.pgPlotWidget_imag.plotItem.addItem(self.poslabel)
|
|
||||||
self.ui.pgPlotWidget_imag.addItem(self.horizontalLine)
|
|
||||||
self.ui.pgPlotWidget_imag.addItem(self.verticalLine)
|
|
||||||
|
|
||||||
self.ui.pgPlotWidget_imag.addItem(self.fit_boundary_imag)
|
self.ui.pgPlotWidget_imag.addItem(self.fit_boundary_imag)
|
||||||
self.ui.pgPlotWidget_real.addItem(self.fit_boundary_real)
|
self.ui.pgPlotWidget_real.addItem(self.fit_boundary_real)
|
||||||
|
|
||||||
@ -144,21 +131,15 @@ class AppWindow(QMainWindow):
|
|||||||
# fitting methods
|
# fitting methods
|
||||||
fitMenu = self.menuBar().addMenu("Standard Fits")
|
fitMenu = self.menuBar().addMenu("Standard Fits")
|
||||||
# lm
|
# lm
|
||||||
fit_lmAction = QAction("&Levenberg-Marquardt", self)
|
fit_lmAction = QAction("Complex NLS", self)
|
||||||
fit_lmAction.setShortcut(QKeySequence("Ctrl+F"))
|
fit_lmAction.setShortcut(QKeySequence("Ctrl+F"))
|
||||||
fitMenu.addAction(fit_lmAction)
|
fitMenu.addAction(fit_lmAction)
|
||||||
# lbfgsb
|
# lbfgsb
|
||||||
fit_lbfgsbAction = QAction("&L-BFGS-B", self)
|
fit_lbfgsbAction = QAction("NLS (Imag.)", self)
|
||||||
fitMenu.addAction(fit_lbfgsbAction)
|
fitMenu.addAction(fit_lbfgsbAction)
|
||||||
# Simulated Annealing
|
# Simulated Annealing
|
||||||
fit_annealAction = QAction("&Simulated Annealing", self)
|
fit_annealAction = QAction("&Simulated Annealing", self)
|
||||||
fitMenu.addAction(fit_annealAction)
|
fitMenu.addAction(fit_annealAction)
|
||||||
# YAFF
|
|
||||||
yaffMenu = self.menuBar().addMenu("YAFF")
|
|
||||||
start_yaff = QAction("&Startparam.", self)
|
|
||||||
yaffMenu.addAction(start_yaff)
|
|
||||||
fit_yaff = QAction("&Fit", self)
|
|
||||||
yaffMenu.addAction(fit_yaff)
|
|
||||||
|
|
||||||
self.signalMapper = QSignalMapper(self)
|
self.signalMapper = QSignalMapper(self)
|
||||||
for i, fit_action in enumerate([fit_lmAction, fit_lbfgsbAction, fit_annealAction
|
for i, fit_action in enumerate([fit_lmAction, fit_lbfgsbAction, fit_annealAction
|
||||||
@ -179,17 +160,11 @@ class AppWindow(QMainWindow):
|
|||||||
else:
|
else:
|
||||||
pos = QPointF(0.0, 0.0)
|
pos = QPointF(0.0, 0.0)
|
||||||
self.last_pos = pos
|
self.last_pos = pos
|
||||||
if USE_CROSSH:
|
|
||||||
self.horizontalLine.setBounds([self.data.frequency.min(), self.data.frequency.max()])
|
|
||||||
self.horizontalLine.setPos(pos.y())
|
|
||||||
self.verticalLine.setPos(pos.x())
|
|
||||||
|
|
||||||
def mousePress(self, evt):
|
def mousePress(self, evt):
|
||||||
data_pos = self.last_pos
|
data_pos = self.last_pos
|
||||||
|
|
||||||
mouse_in_imag = self.ui.pgPlotWidget_imag.underMouse()
|
mouse_in_imag = self.ui.pgPlotWidget_imag.underMouse()
|
||||||
mouse_in_real = self.ui.pgPlotWidget_real.underMouse()
|
mouse_in_real = self.ui.pgPlotWidget_real.underMouse()
|
||||||
|
|
||||||
msgBox = QMessageBox()
|
msgBox = QMessageBox()
|
||||||
|
|
||||||
if self.ui.actionAdd_Peak.isChecked():
|
if self.ui.actionAdd_Peak.isChecked():
|
||||||
@ -396,7 +371,13 @@ class AppWindow(QMainWindow):
|
|||||||
self.updatePlot()
|
self.updatePlot()
|
||||||
|
|
||||||
def fitData_start(self, method):
|
def fitData_start(self, method):
|
||||||
fit_methods = [fit_odr_cmplx, fit_lbfgsb, fit_anneal]
|
print method
|
||||||
|
#fit_methods = [fit_odr_cmplx, fit_odr_imag, fit_lbfgsb, fit_anneal]
|
||||||
|
|
||||||
|
fit_method = [
|
||||||
|
self._fit_method.fit_odr_cmplx,
|
||||||
|
self._fit_method.fit_odr_imag,
|
||||||
|
][method]
|
||||||
|
|
||||||
# build function list
|
# build function list
|
||||||
p0,funcs,fixed_params = [],[],[]
|
p0,funcs,fixed_params = [],[],[]
|
||||||
@ -408,7 +389,8 @@ class AppWindow(QMainWindow):
|
|||||||
_freq, _fit = self.data.get_data()
|
_freq, _fit = self.data.get_data()
|
||||||
|
|
||||||
if not self._fit_thread.isRunning():
|
if not self._fit_thread.isRunning():
|
||||||
self._fit_method.fit_odr_cmplx(_freq, _fit, p0, fixed_params, funcs)
|
#self._fit_method.fit_odr_cmplx(_freq, _fit, p0, fixed_params, funcs)
|
||||||
|
fit_method(_freq, _fit, p0, fixed_params, funcs)
|
||||||
self._fit_thread.start()
|
self._fit_thread.start()
|
||||||
self.ui.statusbar.showMessage("Fitting ...")
|
self.ui.statusbar.showMessage("Fitting ...")
|
||||||
else:
|
else:
|
||||||
|
409
mathlib.py
409
mathlib.py
@ -11,6 +11,217 @@ from scipy import optimize as opt, odr
|
|||||||
import libyaff
|
import libyaff
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def id_to_color(id):
|
||||||
|
colors = [
|
||||||
|
QColor(54,22,115),
|
||||||
|
QColor(160,16,36),
|
||||||
|
QColor(45,142,15),
|
||||||
|
QColor(168,149,17),
|
||||||
|
QColor(36,10,85),
|
||||||
|
QColor(118,8,23),
|
||||||
|
QColor(31,105,7),
|
||||||
|
QColor(124,109,8),
|
||||||
|
]
|
||||||
|
return colors[id % len(colors)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class FitFunctionCreator(QObject):
|
||||||
|
new_data = pyqtSignal(np.ndarray, np.ndarray)
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(FitFunctionCreator,self).__init__()
|
||||||
|
self.data = None
|
||||||
|
self.functions = Functions()
|
||||||
|
|
||||||
|
|
||||||
|
def fitfcn(self, p0, x, *funcs):
|
||||||
|
if x.ndim == 2:
|
||||||
|
self.data = np.zeros( x.shape )
|
||||||
|
else:
|
||||||
|
self.data = np.zeros( (2,x.size) )
|
||||||
|
ndx = 0
|
||||||
|
for fn in funcs: # loop over functions and add the results
|
||||||
|
f, num_p = fn.function, fn.param_number
|
||||||
|
p = p0[ndx:ndx + num_p]
|
||||||
|
if x.ndim == 2:
|
||||||
|
x = x[0]
|
||||||
|
result = f(p, x)
|
||||||
|
self.data += result # fit functions take only 1-dim x
|
||||||
|
ndx += num_p
|
||||||
|
self.new_data.emit(x, self.data)
|
||||||
|
return self.data
|
||||||
|
|
||||||
|
def fitfcn_imag(self, p0, x, *funcs):
|
||||||
|
if x.ndim == 2:
|
||||||
|
self.data = np.zeros( x.shape )
|
||||||
|
else:
|
||||||
|
self.data = np.zeros( (2,x.size) )
|
||||||
|
ndx = 0
|
||||||
|
for fn in funcs: # loop over functions and add the results
|
||||||
|
f, num_p = fn.function, fn.param_number
|
||||||
|
p = p0[ndx:ndx + num_p]
|
||||||
|
if x.ndim == 2:
|
||||||
|
x = x[0]
|
||||||
|
result = f(p, x)
|
||||||
|
self.data += result # fit functions take only 1-dim x
|
||||||
|
ndx += num_p
|
||||||
|
self.new_data.emit(x, self.data)
|
||||||
|
return self.data[1]
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
@property
|
||||||
|
def fitter(self):
|
||||||
|
return self._fitter
|
||||||
|
|
||||||
|
@fitter.setter
|
||||||
|
def fitter(self, f):
|
||||||
|
self._fitter = f
|
||||||
|
|
||||||
|
def fit_odr_cmplx(self, x, y, p0, fixed, fcns):
|
||||||
|
#if x.ndim < 2:
|
||||||
|
# x = N.resize(x, (2,x.size))
|
||||||
|
if np.iscomplexobj(y) and y.ndim == 1:
|
||||||
|
weights = 1/np.abs(y)**2
|
||||||
|
we = np.resize(weights, (2, weights.size))
|
||||||
|
#we = 1/N.array([y.real**2, y.imag**2])
|
||||||
|
y = np.array([y.real, y.imag])
|
||||||
|
else:
|
||||||
|
raise NotImplementedError, "need complex input for now"
|
||||||
|
dat = odr.Data(x, y, we=we)
|
||||||
|
mod = odr.Model(self.f.fitfcn, extra_args=fcns)
|
||||||
|
self._odr_fit = odr.ODR(dat, mod, p0, ifixx=(0,), ifixb=fixed, maxit=800)
|
||||||
|
|
||||||
|
def fit_odr_imag(self, x, y, p0, fixed, fcns):
|
||||||
|
if np.iscomplexobj(y) and y.ndim == 1:
|
||||||
|
we = 1/np.imag(y)**2
|
||||||
|
else:
|
||||||
|
raise NotImplementedError, "need complex input for now"
|
||||||
|
dat = odr.Data(x, y.imag, we=we)
|
||||||
|
mod = odr.Model(self.f.fitfcn_imag, extra_args=fcns)
|
||||||
|
self._odr_fit = odr.ODR(dat, mod, p0, ifixx=(0,), ifixb=fixed, maxit=800)
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def fit(self):
|
||||||
|
#print "TID in FitRoutine", QThread.thread()
|
||||||
|
self._odr_fit.run()
|
||||||
|
self.finished_fit.emit()
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
return self._odr_fit.output
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionRegister:
|
||||||
|
def __init__(self):
|
||||||
|
self.registry = {}
|
||||||
|
|
||||||
|
def register_function(self, obj):
|
||||||
|
#print "FR: Registering:",obj
|
||||||
|
id_string = obj.id_label
|
||||||
|
if self.registry.has_key(obj):
|
||||||
|
raise AssertionError,"The object is already registered! This should NOT happen"
|
||||||
|
self.registry[obj]=id_string
|
||||||
|
#print "FR: ",self.registry
|
||||||
|
|
||||||
|
def unregister_function(self, obj):
|
||||||
|
#print "FR: UnRegistering:",obj
|
||||||
|
if self.registry.has_key(obj):
|
||||||
|
self.registry.pop(obj)
|
||||||
|
else:
|
||||||
|
obj.deleteLater()
|
||||||
|
raise AssertionError,"The object is not in the registry! This should NOT happen"
|
||||||
|
#print "FR: ",self.registry
|
||||||
|
|
||||||
|
def get_registered_functions(self):
|
||||||
|
return self.registry
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
############## deprecated #####################
|
||||||
|
def fit_odr_cmplx(x, y, p0, fixed, fcns):
|
||||||
|
f = FitFunctionCreator()
|
||||||
|
#if x.ndim < 2:
|
||||||
|
# x = N.resize(x, (2,x.size))
|
||||||
|
if np.iscomplexobj(y) and y.ndim == 1:
|
||||||
|
weights = 1/np.abs(y)**2
|
||||||
|
we = np.resize(weights, (2, weights.size))
|
||||||
|
#we = 1/N.array([y.real**2, y.imag**2])
|
||||||
|
y = np.array([y.real, y.imag])
|
||||||
|
else:
|
||||||
|
raise NotImplementedError, "need complex input for now"
|
||||||
|
dat = odr.Data(x, y, we=we)
|
||||||
|
mod = odr.Model(f.fitfcn, extra_args=fcns)
|
||||||
|
fit = odr.ODR(dat, mod, p0, ifixx=(0,), ifixb=fixed, maxit=8000)
|
||||||
|
fit.run()
|
||||||
|
#print fit.output.pprint()
|
||||||
|
return fit.output
|
||||||
|
|
||||||
|
### define funcs here
|
||||||
|
class Functions(QObject):
|
||||||
|
def __init__(self):
|
||||||
|
super(Functions,self).__init__()
|
||||||
|
self.list = {
|
||||||
|
# provides functions: "id_string":(function, number_of_parameters)
|
||||||
|
"hn":(self.hn_cmplx, 4),
|
||||||
|
"conductivity":(self.cond_cmplx, 3),
|
||||||
|
"power":(self.power_cmplx, 2),
|
||||||
|
"static":(self.static_cmplx, 1),
|
||||||
|
"yaff":(self.yaff, 8)
|
||||||
|
}
|
||||||
|
self.YAFF = libyaff.Yaff()
|
||||||
|
|
||||||
|
def hn_cmplx(self, p, x):
|
||||||
|
om = 2*np.pi*x
|
||||||
|
#hn = om*1j
|
||||||
|
eps,t,a,b = p
|
||||||
|
hn = eps/(1+(1j*om*t)**a)**b
|
||||||
|
cplx = np.array([hn.real, -hn.imag])
|
||||||
|
return cplx
|
||||||
|
|
||||||
|
def cond_cmplx(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
|
||||||
|
|
||||||
|
def power_cmplx(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
|
||||||
|
|
||||||
|
def static_cmplx(self, p, x):
|
||||||
|
eps_inf = p[0]
|
||||||
|
static = np.ones( (2,x.size) )*eps_inf
|
||||||
|
static[1,:] *= 0 # set imag part zero
|
||||||
|
#cplx = N.array([static.real, static.imag])
|
||||||
|
return static
|
||||||
|
|
||||||
|
def yaff(self,p,x):
|
||||||
|
ya = self.YAFF.yaff(p[:8],x)
|
||||||
|
cplx = np.array([ya.imag, ya.real])
|
||||||
|
return cplx
|
||||||
|
|
||||||
|
def get(self,name):
|
||||||
|
return self.list[name]
|
||||||
|
|
||||||
|
def get_function(self,name):
|
||||||
|
return self.list[name][0]
|
||||||
|
|
||||||
|
|
||||||
def fit_anneal(x, y, p0, fixed, funcs):
|
def fit_anneal(x, y, p0, fixed, funcs):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
bounds = [(0, 1e14), (0, 1)]
|
bounds = [(0, 1e14), (0, 1)]
|
||||||
@ -85,19 +296,6 @@ def hn(p, nu):
|
|||||||
return e_loss # 2* oder nicht?
|
return e_loss # 2* oder nicht?
|
||||||
|
|
||||||
|
|
||||||
def id_to_color(id):
|
|
||||||
colors = [
|
|
||||||
QColor(54,22,115),
|
|
||||||
QColor(160,16,36),
|
|
||||||
QColor(45,142,15),
|
|
||||||
QColor(168,149,17),
|
|
||||||
QColor(36,10,85),
|
|
||||||
QColor(118,8,23),
|
|
||||||
QColor(31,105,7),
|
|
||||||
QColor(124,109,8),
|
|
||||||
]
|
|
||||||
return colors[id % len(colors)]
|
|
||||||
|
|
||||||
|
|
||||||
def mini_func(p, x, y):
|
def mini_func(p, x, y):
|
||||||
res = y - multi_hn(p, x)
|
res = y - multi_hn(p, x)
|
||||||
@ -133,188 +331,3 @@ def tau_peak(f, a, b):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### define funcs here
|
|
||||||
class Functions(QObject):
|
|
||||||
def __init__(self):
|
|
||||||
super(Functions,self).__init__()
|
|
||||||
self.list = {
|
|
||||||
# provides functions: "id_string":(function, number_of_parameters)
|
|
||||||
"hn":(self.hn_cmplx, 4),
|
|
||||||
"conductivity":(self.cond_cmplx, 3),
|
|
||||||
"power":(self.power_cmplx, 2),
|
|
||||||
"static":(self.static_cmplx, 1),
|
|
||||||
"yaff":(self.yaff, 8)
|
|
||||||
}
|
|
||||||
self.YAFF = libyaff.Yaff()
|
|
||||||
|
|
||||||
def hn_cmplx(self, p, x):
|
|
||||||
om = 2*np.pi*x
|
|
||||||
#hn = om*1j
|
|
||||||
eps,t,a,b = p
|
|
||||||
hn = eps/(1+(1j*om*t)**a)**b
|
|
||||||
cplx = np.array([hn.real, -hn.imag])
|
|
||||||
return cplx
|
|
||||||
|
|
||||||
def cond_cmplx(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
|
|
||||||
|
|
||||||
def power_cmplx(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
|
|
||||||
|
|
||||||
def static_cmplx(self, p, x):
|
|
||||||
eps_inf = p[0]
|
|
||||||
static = np.ones( (2,x.size) )*eps_inf
|
|
||||||
static[1,:] *= 0 # set imag part zero
|
|
||||||
#cplx = N.array([static.real, static.imag])
|
|
||||||
return static
|
|
||||||
|
|
||||||
def yaff(self,p,x):
|
|
||||||
ya = self.YAFF.yaff(p[:8],x)
|
|
||||||
cplx = np.array([ya.imag, ya.real])
|
|
||||||
return cplx
|
|
||||||
|
|
||||||
def get(self,name):
|
|
||||||
return self.list[name]
|
|
||||||
|
|
||||||
def get_function(self,name):
|
|
||||||
return self.list[name][0]
|
|
||||||
|
|
||||||
|
|
||||||
class FitFunctionCreator(QObject):
|
|
||||||
new_data = pyqtSignal(np.ndarray, np.ndarray)
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
super(FitFunctionCreator,self).__init__()
|
|
||||||
self.data = None
|
|
||||||
self.functions = Functions()
|
|
||||||
|
|
||||||
|
|
||||||
def fitfcn(self, p0, x, *funcs):
|
|
||||||
if x.ndim == 2:
|
|
||||||
self.data = np.zeros( x.shape )
|
|
||||||
else:
|
|
||||||
self.data = np.zeros( (2,x.size) )
|
|
||||||
ndx = 0
|
|
||||||
for fn in funcs: # loop over functions and add the results
|
|
||||||
f, num_p = fn.function, fn.param_number
|
|
||||||
p = p0[ndx:ndx + num_p]
|
|
||||||
if x.ndim == 2:
|
|
||||||
x = x[0]
|
|
||||||
result = f(p, x)
|
|
||||||
self.data += result # fit functions take only 1-dim x
|
|
||||||
ndx += num_p
|
|
||||||
self.new_data.emit(x, self.data)
|
|
||||||
return self.data
|
|
||||||
|
|
||||||
def _fitfcn(self, p0, x, *funcs):
|
|
||||||
if x.ndim == 2:
|
|
||||||
self.data = np.zeros( x.shape )
|
|
||||||
else:
|
|
||||||
self.data = np.zeros( (2,x.size) )
|
|
||||||
ndx = 0
|
|
||||||
for fn in funcs: # loop over functions and add the results
|
|
||||||
f,num_p = self.functions.get(fn)
|
|
||||||
p = p0[ndx:ndx + num_p]
|
|
||||||
if x.ndim == 2:
|
|
||||||
x = x[0]
|
|
||||||
result = f(p, x)
|
|
||||||
self.data += result # fit functions take only 1-dim x
|
|
||||||
ndx += num_p
|
|
||||||
self.new_data.emit(x, self.data)
|
|
||||||
return self.data
|
|
||||||
|
|
||||||
|
|
||||||
def fit_odr_cmplx(x, y, p0, fixed, fcns):
|
|
||||||
f = FitFunctionCreator()
|
|
||||||
#if x.ndim < 2:
|
|
||||||
# x = N.resize(x, (2,x.size))
|
|
||||||
if np.iscomplexobj(y) and y.ndim == 1:
|
|
||||||
weights = 1/np.abs(y)**2
|
|
||||||
we = np.resize(weights, (2, weights.size))
|
|
||||||
#we = 1/N.array([y.real**2, y.imag**2])
|
|
||||||
y = np.array([y.real, y.imag])
|
|
||||||
else:
|
|
||||||
raise NotImplementedError, "need complex input for now"
|
|
||||||
dat = odr.Data(x, y, we=we)
|
|
||||||
mod = odr.Model(f.fitfcn, extra_args=fcns)
|
|
||||||
fit = odr.ODR(dat, mod, p0, ifixx=(0,), ifixb=fixed, maxit=8000)
|
|
||||||
fit.run()
|
|
||||||
#print fit.output.pprint()
|
|
||||||
return fit.output
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fitter(self):
|
|
||||||
return self._fitter
|
|
||||||
|
|
||||||
@fitter.setter
|
|
||||||
def fitter(self,f):
|
|
||||||
self._fitter = f
|
|
||||||
|
|
||||||
def fit_odr_cmplx(self, x, y, p0, fixed, fcns):
|
|
||||||
#if x.ndim < 2:
|
|
||||||
# x = N.resize(x, (2,x.size))
|
|
||||||
if np.iscomplexobj(y) and y.ndim == 1:
|
|
||||||
weights = 1/np.abs(y)**2
|
|
||||||
we = np.resize(weights, (2, weights.size))
|
|
||||||
#we = 1/N.array([y.real**2, y.imag**2])
|
|
||||||
y = np.array([y.real, y.imag])
|
|
||||||
else:
|
|
||||||
raise NotImplementedError, "need complex input for now"
|
|
||||||
|
|
||||||
dat = odr.Data(x, y, we=we)
|
|
||||||
mod = odr.Model(self.f.fitfcn, extra_args=fcns)
|
|
||||||
self._odr_fit = odr.ODR(dat, mod, p0, ifixx=(0,), ifixb=fixed, maxit=10)
|
|
||||||
|
|
||||||
@pyqtSlot()
|
|
||||||
def fit(self):
|
|
||||||
#print "TID in FitRoutine", QThread.thread()
|
|
||||||
self._odr_fit.run()
|
|
||||||
self.finished_fit.emit()
|
|
||||||
|
|
||||||
def result(self):
|
|
||||||
return self._odr_fit.output
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class FunctionRegister:
|
|
||||||
def __init__(self):
|
|
||||||
self.registry = {}
|
|
||||||
|
|
||||||
def register_function(self, obj):
|
|
||||||
#print "FR: Registering:",obj
|
|
||||||
id_string = obj.id_label
|
|
||||||
if self.registry.has_key(obj):
|
|
||||||
raise AssertionError,"The object is already registered! This should NOT happen"
|
|
||||||
self.registry[obj]=id_string
|
|
||||||
#print "FR: ",self.registry
|
|
||||||
|
|
||||||
def unregister_function(self, obj):
|
|
||||||
#print "FR: UnRegistering:",obj
|
|
||||||
if self.registry.has_key(obj):
|
|
||||||
self.registry.pop(obj)
|
|
||||||
else:
|
|
||||||
obj.deleteLater()
|
|
||||||
raise AssertionError,"The object is not in the registry! This should NOT happen"
|
|
||||||
#print "FR: ",self.registry
|
|
||||||
|
|
||||||
def get_registered_functions(self):
|
|
||||||
return self.registry
|
|
||||||
|
Loading…
Reference in New Issue
Block a user