我编写了一个python脚本,它打开了紫外 - 可见光谱并尝试使用大量函数来拟合它们。但是,我希望在图中显示拟合步骤,因为找到了最小残差。 Stackoverflow实际上有一些涉及这个想法的例子(http://stackoverflow.com/questions/4098131/matplotlib-update-a-plot),但由于某种原因,这种方法对我来说不是很好。我的意思是“效果不好”是绘图窗口不响应脚本中发生的更新。 我试图将我的代码减少到更容易理解的东西,但仍然编译,但也比我的代码更接近于示例,如下所示。
重新说出我的问题:是否有更好的方法通过拟合过程刷新此类屏幕,以使窗口不会变为“(无响应)”?
这是我的简化代码:
# import modules that I'm using
import matplotlib
matplotlib.use('GTKAgg')
import Tkinter
from Tkinter import *
import numpy as np
import scipy as sc
import matplotlib.pyplot as pltlib
# lmfit is imported becuase parameters are allowed to depend on each other along with bounds, etc.
from lmfit import minimize, Parameters, Minimizer
#If button is pressed on the window, open a file and get the data
def open_File():
# file is opened here and some data is taken
# I've just set some arrays here so it will compile alone
x=[]
y=[]
for num in range(0,1000):x.append(num*.001+1)
# just some random function is given here, the real data is a UV-Vis spectrum
for num2 in range(0,1000):y.append(sc.math.sin(num2*.06)+sc.math.e**(num2*.001))
X = np.array(x)
Y = np.array(y)
# plot the initial data in one figure
pltlib.ion()
pltlib.interactive(True)
pltlib.figure(1)
pltlib.plot(X,Y, "r-")
pltlib.show()
#deconvolute this initial data into deveral lorentzian profiles
deconvolute(X,Y)
#lorentz line for constructing the more complex function
def lorentz(x, amp, center, width):
return amp*1/sc.math.pi*(width/((x-center)**2+width**2))
def deconvolute(X,Y):
#make 2nd figure for the refreshing screen
deconvFig = pltlib.figure(2)
ax = deconvFig.add_subplot(111)
line1,line2=ax.plot(X,Y,'r-',X,Y,'r-')
# setup parameters for several (here is 30, I potentially hae many more in the real program)
params = Parameters()
for p in range(0,30):
params.add('amp' + str(p), value=1)
params.add('center' + str(p), value=1)
params.add('width' + str(p), value=1)
#get residual function for minimizing
def residual(params, X, data=None):
model = 0
# get values for each lorentz and sum them up
for p in range(0,30):
amp = params['amp' + str(p)].value
center = params['center' + str(p)].value
width = params['width' + str(p)].value
tmpLorentz = lorentz(X, amp, center, width)
model = model + tmpLorentz
# This is where the main problem is.
# This 2nd figure stops responding after a very small (1?) number of iterations
########################################
# I want redraw the figure at every step through the fitting process
line2.set_ydata(model)
deconvFig.canvas.draw()
print 'screen should be refreshed'
########################################
return (data - model)
#fit the function to the data
result = minimize(residual, params, args=(X, Y))
print 'done fitting the program'
#create a window with a button
MainWindow = Tk()
Button(text='Open a File', command=open_File).pack(side=BOTTOM)
MainWindow.mainloop()
答案 0 :(得分:0)
import time
from matplotlib import pyplot as pltlib
deconvFig = pltlib.figure(2)
ax = deconvFig.add_subplot(111)
X, Y = range(10), range(10)
line1,line2 = ax.plot(X,Y,'r-',X,Y,'r-')
for x in xrange(2, 6, 1):
line2.set_ydata(range(0, 10*x, x))
deconvFig.canvas.draw()
time.sleep(2)
>>> import matplotlib
>>> matplotlib.__version__
'1.1.0'
并且它按预期工作。
也许是因为你产生了第二个数字。
import time
from matplotlib import pyplot as pltlib
pltlib.ion()
pltlib.interactive(True)
pltlib.figure(1)
pltlib.plot(range(10),range(10), "r-")
pltlib.show()
deconvFig = pltlib.figure(2)
ax = deconvFig.add_subplot(111)
X, Y = range(10), range(10)
line1,line2 = ax.plot(X,Y,'r-',X,Y,'r-')
for x in xrange(2, 6, 1):
line2.set_ydata(range(0, 10*x, x))
deconvFig.canvas.draw()
time.sleep(2)
nope仍然工作正常 这可能是我的设置。
虽然它也可能以非常慢的速率进行最小化,所以当您绘制更新时无法区分时,您可以计算RMSE以查看差异有多大
print numpy.sqrt(numpy.sum((data - model)**2)/model.shape[0])/numpy.mean(data) * 100
另外我通常使用scipy的最小化函数http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html,因为它可以最大限度地减少大多数函数,虽然它通过随机改变输入来工作,所以我不知道它有多快,但它可以应用于很多很多情况。
我希望这会有所帮助。