首先,我要感謝任何能夠讓我通過這個提前完成的人。我是Matplotlib的新手,並且通常不用python編寫代碼。matplotlib生成動畫,每個文件都是一個新框架
我擁有的是大量的數據文件(100'-10,000)。這些文件中的每一個都有20個我想要變成動畫的圖,其中每個文件表示不同的幀。代碼變得難以置信地令人費解,試圖讓事情發揮作用。有6個小區(3,2,1-6)。它們都共享相同的x軸。在任何給定的子圖上,我都有1到6個y值對它進行繪圖。他們還需要適當的標籤,有些是'symlog'圖,因爲我想查看對數數據的正面和負面。我希望動畫的形成不依賴於ffmpeg或mencoder,因爲那些在運行代碼的計算機上可能沒有這些動畫。這似乎是明顯的解決方案在於FuncAnimation,但這真的讓我感到困惑。我見過的大多數例子只是爲單個圖表添加另一點。我想在基本上20個地塊中替換數據。我將只包括兩個子圖,並假設我足夠聰明,可以將其推斷爲6 ...
我已成功獲取圖形以形成一個單獨的「安全」文件中的.png文件。
所以這裏的一些真的,真的,醜陋的代碼:
#!/usr/bin/python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import matplotlib.animation as animation
import glob
import os
import re
from StringIO import StringIO
from matplotlib.ticker import MaxNLocator
from matplotlib.font_manager import FontProperties
def GetFiles(dir_name, extension):
fileList = []
for file in os.listdir(dir_name):
index = file.find(extension)
if index != -1:
dirfile = os.path.join(dir_name, file)
fileList.append(dirfile)
return fileList
dirString = raw_input('Please enter a directory name: ')
extension = raw_input('Please enter the extension: ')
ClearFiles = raw_input('Remove temporary .png files (Y/N): ')
dataName = GetFiles(dirString, extension)
print dataName #just make sure right files are being loaded
pngfilelist = []
figure = plt.figure()
fontP = FontProperties()
fontP.set_size('small')
ax1 = figure.add_subplot(1,2,1)
ax1.grid(True) # Enable Grid Lines
ax1.legend(loc=9, ncol=6, borderaxespad=0., prop=fontP)
ax1.set_title('Band Diagram')
PsiPlot, = ax1.plot([], [], label='Psi')
EcPlot, = ax1.plot([], [], label='Ec')
EvPlot, = ax1.plot([], [], label='Ev')
ax1.legend(loc=9,ncol=6, borderaxespad=0., prop=fontP)
ax2 = figure.add_subplot(1,2,2, sharex=ax1)
NPlot, = ax2.plot([], [], label='n')
PPLot, = ax2.plot([], [], label='p')
ax2.grid(True) # Enable Grid Lines
ax2.set_title('Electron/Hole Concentrations')
ax2.legend(loc=9,ncol=2, borderaxespad=0., prop=fontP)
X = []
Psi = []
Ec = []
Ev = []
n = []
p = []
def UpdatePlot(dataFile):
data = np.genfromtxt(dataFile, autostrip=True, skip_header=4, names=True, usecols=("X", "Psi", "Ec", "Ev", "n", "p")) #Load the specified data into giant list
entries = len(data)
for ctr in range(0,entries):
X.append(data[ctr][0]) # X-value for all plots
Psi.append(data[ctr][1]) #plot 1,1
Ec.append(data[ctr][2])
Ev.append(data[ctr][3])
n.append(data[ctr][4]) # plot 1,2
p.append(data[ctr][5])
figure.suptitle(dataFile, y=0.99)
PsiPlot.set_data(X, Psi)
EcPlot.set_data(X, Ec)
EvPlot.set_data(X, Ev)
NPlot.set_data(X, n)
PPlot.set_data(X, p)
plt.subplot(1,2,1)
plt.xlabel('Position (cm)')
plt.ylabel('Energy (eV)')
plt.subplot(1,2,2)
plt.xlabel('Position (cm)')
plt.ylabel('cm^-3')
plt.yscale('symlog', linthreshy=1e10)
figure.set_size_inches(16,10)
figure.set_dpi(200)
plt.tight_layout(pad=0.2, w_pad=0.2, h_pad=0.2)
filename = dataFile.replace(extension, '.png')
plt.savefig(filename)
pngfilelist.append(filename)
return PsiPlot, EcPlot, EvPlot, NPlot, PPlot,
ani = animation.FuncAnimation(figure, UpdatePlot, dataName, interval=500, blit=True)
ani.save('test.mp4', fps=15)
# remove the temporary png files if wanted.
if ClearFiles == 'y' or ClearFiles == 'Y':
for fname in pngfilelist:
os.remove(fname)
事情我意識到: 追加數據是不是讓所有的X和Y數據列表的最好方式。第二組數據還將包括寫在這段代碼中的第一組數據(尋找刪除它的好方法,以後不會導致問題)。當我嘗試各種各樣的東西時,可能會有比我目前需要的更多的進口產品,然後將它們剪掉。使用這種方法時,X/Y刻度不會自動設置,因爲當我試圖做的是保存到.png文件時(我通過plt.plot完成所有操作並在保存後清除,而不是將所有這些數據設置爲一個軸)。例如,我想將最低的Y值設置爲最低的Ev,將最高的Y值設置爲最高的Psi。此外,第二個情節似乎沒有任何工作。當然,這些值非常大。
有了這段代碼,我得到了一個警告:「找不到標記的對象。」和一個運行時錯誤,說底層的C/C++對象已被刪除 - 兩個錯誤,我沒有收到只是陰謀和保存爲.png文件代碼。但是,我真的只是在如何將所有這些圖形變成FuncAnimation的損失。
有什麼想法?我厭倦了對Python的衝擊 - 我真的需要在我的模擬代碼上敲打我的頭。
最後,這裏是一箇舊的(壞的)數據文件的樣品部分:
Data from: TestLoad.dev
Simulation time: 4.08738e-013
Iteration : 665
Data binning: 5
Point X Psi Ec Ev Fermi Fermi_n Efp n p n*p Rho Ec_Carriers Ev_Carriers Light_Gen Generation_Th Recomb_Thermal SRH_Rate1 SRH_Rate2 SRH_Rate3 SRH_Rate4 Jn_x Jp_x
0 4.9e-006 3.58 -0.500001 -0.500001 -0.5 -0.5 -0.500001 2.72507e+021 2.72507e+021 7.42603e+042 0 2.67057e+008 2.67057e+008 0 0 0 0 0 0 0 4577.65 0
1 9.95e-006 3.58 -0.5 -0.5 -0.5 -0.499999 -0.5 2.72508e+021 2.72508e+021 7.42603e+042 0 8.17523e+006 8.17523e+006 0 0 0 0 0 0 0 0 -114441
2 1.015e-005 3.61356 0.0255559 -1.09444 -0.95916 -0.95916 -0.830208 0 1.08799e+015 0 -0.132665 0 0.971429 0 0 0 0 0 0 0 0 -114441
3 1.025e-005 3.62841 0.0404132 -1.07959 -0.944094 -0.944094 -0.844848 0 2.89096e+015 0 -0.132656 0 3.02857 0 0 0 0 0 0 0 0 -119019
4 1.035e-005 3.64199 0.0539899 -1.06601 -0.930857 -0.930857 -0.854293 0 9.46844e+015 0 -0.131488 0 10.3143 0 0 0 0 0 0 0 0 -114441
5 1.045e-005 3.6543 0.0662974 -1.0537 -0.919519 -0.919519 -0.867723 0 2.36441e+016 0 -0.129511 0 21.6571 0 0 0 0 0 0 0 0 -123596
6 1.055e-005 3.66535 0.0773546 -1.04265 -0.909748 -0.909748 -0.873209 0 4.47623e+016 0 -0.125061 0 48.4286 0 0 0 0 0 0 0 0 -96130.6
7 1.065e-005 3.6752 0.0872047 -1.0328 -0.901449 -0.901449 -0.876584 0 6.9861e+016 0 -0.1222 0 66.2857 0 0 0 0 0 0 0 0 -146485
8 1.075e-005 3.68388 0.0958752 -1.02412 -0.895041 -0.895041 -0.880708 0 1.18029e+017 0 -0.113068 0 124.286 0 0 0 0 0 0 0 0 -86975.3
9 1.085e-005 3.69145 0.103454 -1.01655 -0.889233 -0.889233 -0.879943 0 1.57625e+017 0 -0.111058 0 136.829 0 0 0 0 0 0 0 0 -137329
10 1.095e-005 3.69796 0.109961 -1.01004 -0.885743 -0.885743 -0.881837 0 2.16895e+017 0 -0.0941347 0 240.457 0 0 0 0 0 0 0 0 -22888.2
788 0.00998975 4.19373 0.605734 -0.514266 -0.3792 -0.3792 -0.287991 0 5.78298e+015 0 -0.131942 0 5.48571 0 0 0 0 0 0 0 0 77820
789 0.00998985 4.17975 0.591751 -0.528249 -0.393181 -0.393181 -0.292558 0 2.27746e+015 0 -0.132404 0 1.6 0 0 0 0 0 0 0 0 68664.7
790 0.0099904 4.08 -1.45745e-006 -1.45745e-006 3.16863e-016 4.06816e-008 -7.67735e-007 2.72507e+021 2.72507e+021 7.42603e+042 0 2.72507e+007 2.72507e+007 0 0 0 0 0 0 0 0 0
791 0.00999545 4.08 -1.45745e-006 -1.45745e-006 3.16863e-016 4.06816e-008 -7.67735e-007 2.72507e+021 2.72507e+021 7.42603e+042 0 2.47982e+008 2.47982e+008 0 6.27943e+027 0 0 0 0 0 0 0
萬一將來人看這個,這裏就是結束了我最後的,簡化的答案(證明的概念),然後我開始投擲所有其他地塊。
#!/usr/bin/python
import numpy as np
import matplotlib as mpl
mpl.use("agg")
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import os
from StringIO import StringIO
from matplotlib.font_manager import FontProperties
def GetFiles(dir_name, extension):
fileList = []
for file in os.listdir(dir_name):
index = file.find(extension)
if index != -1:
dirfile = os.path.join(dir_name, file)
fileList.append(dirfile)
return fileList
def UpdatePlot(dataFile):
global MinX, MaxX, ax1MinY, ax1MaxY, ax2MinY, ax2MaxY, first
print 'loading data for ', dataFile
data = np.genfromtxt(dataFile, autostrip=True, skip_header=4, names=True, usecols=("X", "Psi", "Ec", "Ev", "n", "p")) #Load the specified data into giant list
# get new bounds on limits for graphs
tempMin = data['X'].min()
tempMax = data['X'].max()
if tempMax > MaxX or first == True:
MaxX = tempMax + (tempMax - tempMin) * 0.01
ax1.set_xlim(MinX, MaxX)
ax2.set_xlim(MinX, MaxX)
if tempMin < MinX or first == True:
MinX = tempMin - (tempMax - tempMin) * 0.01
ax1.set_xlim(MinX, MaxX)
ax2.set_xlim(MinX, MaxX)
tempMin = data['Psi'].min()
tempMax = data['Psi'].max()
if tempMax > ax1MaxY or first == True:
ax1MaxY = tempMax + (tempMax - tempMin) * 0.5
ax1.set_ylim(ax1MinY, ax1MaxY)
tempMin = data['Ev'].min()
tempMax = data['Ev'].max()
if tempMin < ax1MinY or first == True:
ax1MinY = tempMin - (tempMax - tempMin) * 0.2
ax1.set_ylim(ax1MinY, ax1MaxY)
tempMax = data['n'].max()
if tempMax > ax1MaxY or first == True:
ax2MaxY = tempMax * 2 # This is basically a log plot...
ax2.set_ylim(ax2MinY, ax2MaxY)
tempMax = data['p'].max()
if tempMax > ax1MaxY or first == True:
ax2MaxY = tempMax * 2 # This is basically a log plot...
ax2.set_ylim(ax2MinY, ax2MaxY)
# Now update all the data for the plots
titleText.set_text(dataFile)
PsiPlot.set_data(data['X'], data['Psi'])
EcPlot.set_data(data['X'], data['Ec'])
EvPlot.set_data(data['X'], data['Ev'])
NPlot.set_data(data['X'], data['n'])
PPlot.set_data(data['X'], data['p'])
plt.draw() # need to update the figure regardless because the title changes
if GeneratePNG == 'Y' or GeneratePNG == 'y':
filename = dataFile.replace(extension, '.png')
plt.savefig(filename)
first = False
return
dirString = raw_input('Please enter a directory name: ')
extension = raw_input('Please enter the extension: ')
GeneratePNG = raw_input('Generate .png files of each file (Y/N): ')
framesps = raw_input('Frames per second: ')
outname = raw_input('Output file name (no extension): ')
outname = outname + '.mp4'
dataName = GetFiles(dirString, extension)
# print dataName
MinX = 0
MaxX = 0
ax1MinY = 0
ax1MaxY = 0
ax2MinY = 0
ax2MaxY = 0
first = True
figure = plt.figure()
fontP = FontProperties()
fontP.set_size('small')
figure.set_size_inches(16,10)
figure.set_dpi(200)
titleText = figure.suptitle('Title', y=0.99) # must do this way to allow title to be changed later
ax1 = figure.add_subplot(1,2,1)
ax1.grid(True) # Enable Grid Lines
ax1.set_title('Band Diagram')
plt.xlabel('Position (cm)')
plt.ylabel('Energy (eV)')
PsiPlot, = ax1.plot([], [], label='Psi')
EcPlot, = ax1.plot([], [], label='Ec')
EvPlot, = ax1.plot([], [], label='Ev')
ax1.legend(loc=9,ncol=6, borderaxespad=0., prop=fontP)
ax2 = figure.add_subplot(1,2,2, sharex=ax1)
plt.xlabel('Position (cm)')
plt.ylabel('cm^-3')
plt.yscale('symlog', linthreshy=1e10)
ax2.grid(True) # Enable Grid Lines
ax2.set_title('Electron/Hole Concentrations')
NPlot, = ax2.plot([], [], label='n')
PPlot, = ax2.plot([], [], label='p')
ax2.legend(loc=9,ncol=2, borderaxespad=0., prop=fontP)
plt.tight_layout(pad=0.5, w_pad=0.5, h_pad=0.5)
ani = mpl.animation.FuncAnimation(figure, UpdatePlot, dataName, init_func=None, interval=500, blit=True)
ani.save(outname, fps=framesps, codec='mpeg4')
再次感謝您指點我正確的方向!
只是爲了讓我想起你要做的基本事情:你有大量的數據文件,每個文件代表一個時間戳。對於每個時間戳記,繪製一些計算值與x(20個圖表,因爲我看到大約20列)。但是,爲什麼/如何進行各種子圖和子圖;你是否儘量將數據壓縮成幾塊地塊?還是20個地塊都是這些子地塊? – Evert 2012-07-30 08:43:19
至於爲什麼所有的subplots和數據壓縮 - 這可能會有所幫助:[鏈接](http://en.wikipedia.org/wiki/Band_diagram)我試圖調試蒙特卡洛代碼,我需要可視化所有的數據一次看到發生了什麼事情,試圖瞭解什麼和事情如何搞砸。有些數據很好地融合在一起,其他數據必須一次全部顯示,纔能有真正的意義。 – 2012-07-30 16:41:35
如果你厭倦了蟒蛇頭,也許你應該嘗試用另一種方式解決你的問題。不過,我認爲將你的問題(和你的問題)分解爲一些子問題(對於你和試圖回答你的問題的用戶)是有用的。 – bmu 2012-07-30 17:02:59