まず、事前にこれを乗り越えてくれた人に感謝します。私はMatplotlibを初めて使用し、通常はPythonでもコーディングしません。
私が持っているのは膨大な数のデータファイル(100から10,000)です。これらの各ファイルには、アニメーションに変換したい20のプロットがあり、各ファイルは異なるフレームを表しています。コードは、物事を機能させるために非常に複雑になっています。6つのサブプロット(3,2,1-6)があります。それらはすべて同じx軸を共有します。任意のサブプロットで、1〜6個のy値がプロットされています。また、適切なラベルが必要であり、対数データを正と負の両方で表示したいので、いくつかは「symlog」プロットです。コードを実行しているコンピューターでは利用できない可能性があるため、ffmpegやmencoderに依存せずにアニメーションを作成したいと思います。これに対する明らかな解決策はFuncAnimationにあるようですが、それは本当に私を混乱させすぎます。ほとんどの例私は 単一のプロットに別のポイントを追加するだけです。基本的に20プロットのデータを置き換えたいと思います。2つのサブプロットだけを含め、それを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データを取得するための最も良い方法ではありません。2番目のデータセットには、このスニペットに記述されている最初のデータセットも含まれます(後で問題を引き起こさない、データを削除するための適切な方法を探しています)。いろいろ試してみて、切り取ってみたので、今必要以上に輸入品が多いのではないでしょうか。この方法を使用すると、X / Yスケールは、.pngファイルに保存するだけの場合のように自動的に設定されません(データの設定に関するこれらすべてのことの代わりに、plt.plotを介してすべてを実行し、保存後にクリアします軸)。たとえば、最小のY値を最小のEvで設定し、最大のY値を最大のPsiで設定したいと思います。また、2番目のプロットでは何も機能していないようです。確かに、値は非常に大きいです。
このコードでは、「ラベルの付いたオブジェクトが見つかりません」という警告が表示されます。基になるC/C++オブジェクトが削除されたことを示すランタイムエラー-プロットして.pngファイルコードに保存するだけでは受け取れない2つのエラー。
しかし、これらすべてのグラフを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')
私を正しい方向に向けてくれてありがとう!