まずは疑似データをつくりましょう。
from IPython.core.display import Image
def save_and_display(filename,dpi=50):
import matplotlib.pyplot as plt
plt.savefig(filename,dpi=dpi)
return Image(filename=filename)
sizex=25.0# データの横(x),縦(y)のサイズ
sizey=15.0#
"""
xy平面内に50個の山をランダムに作る
"""
x0=np.random.randint(sizex+1,size=50)
y0=np.random.randint(sizey+1,size=50)
#x0=np.random.random(50)*sizex#山の頂点のx座標
#y0=np.random.random(50)*sizey#山の頂点のy座標
z0=np.random.random(50)*sizey*0.1#山の高さの幅のパラメータ
M=np.zeros((sizey,sizex))#データの初期化。すべてゼロ。
def lorentz(x,y,x0,y0,width,height):
return height/(1+((x-x0)/width)**2+((y-y0)/width)**2)
for j,_m in enumerate(M):
for i,m in enumerate(_m):
for xyz in zip(x0,y0,z0):
M[j,i]=M[j,i]+lorentz(i,j,xyz[0],xyz[1],xyz[2],xyz[2])
print(M.shape)
(15, 25)
plt.imshow(M,origin='lower',interpolation='none')
plt.colorbar()
<matplotlib.colorbar.Colorbar instance at 0x04C80B48>
img=save_and_display('test.png',dpi=100)
img
plt.clf()
plt.pcolormesh(M)
plt.colorbar()
plt.xlim(1,sizex)
plt.ylim(1,sizey)
ax=plt.gca()
ax.set_aspect('equal')
img=save_and_display('test.png',dpi=100)
img
plt.clf()
plt.contourf(M)
plt.colorbar()
ax=plt.gca()
ax.set_aspect('equal')
img=save_and_display('test.png',dpi=100)
img
plt.clf()
plt.contour(M)
plt.colorbar()
ax=plt.gca()
ax.set_aspect('equal')
img=save_and_display('test.png',dpi=100)
img
plt.clf()
imshowのデフォルトの原点は左上になっています。 上の例のように、
origin='lower'
とすれば左下になり、contour、contourfと一致します。
このように、4つの関数はとてもよく似ています。 しかし、よく見るとpcolormeshのみ、座標軸のとり方が他と異なっています。ピクセルの左下に座標点があります。
また、xy平面内のデータ範囲やスケールを変えると違いが現れます。
plt.imshow(M,origin='lower',interpolation='none',extent=(1,sizex,1,sizey))
plt.colorbar()
plt.xscale('log')
plt.yscale('log')
img=save_and_display('test.png',dpi=100)
img
C:\Python27\lib\site-packages\matplotlib\image.py:336: UserWarning: Images are not supported on non-linear axes. warnings.warn("Images are not supported on non-linear axes.")
plt.clf()
plt.pcolormesh(M)
plt.colorbar()
plt.xlim(1,sizex)
plt.ylim(1,sizey)
plt.xscale('log')
plt.yscale('log')
img=save_and_display('test.png',dpi=100)
img
plt.clf()
plt.contourf(M)# contourは省略
plt.colorbar()
plt.xscale('log')
plt.yscale('log')
img=save_and_display('test.png',dpi=100)
img
plt.clf()
imshowはaxesの中に配列データを元に等間隔のピクセルを埋めていくだけなのに対し、pcolormesh,contour,contourfはaxesの座標に対してデータを並べてくれます。 なので、imshowはaxesがログスケールになっても知らん顔をしているのに対し、pcolomesh, contour(f)はちゃんとログスケールの座標に基づいたプロットをし直します。
pcolormesh,contour(f)では、各データに対応するxy座標を明確に定義する事ができます。
ただし、pcolormeshだけは、各ピクセルの左下の座標を指定しているので、通常は、ピクセルの真ん中に調整しなおす必要があるでしょう。
xs=np.logspace(0,np.log10(sizex),num=25)# ログスケールでx座標の値を決める
ys=np.logspace(0,np.log10(sizey),num=15)# ログスケールでy座標の値を決める
#xx_m,yy_M=np.meshgrid(np.sqrt(xs[:-1]*xs[1:]),np.sqrt(ys[:-1]*ys[1:]))# xs、ysからメッシュを作る。
xx,yy=np.meshgrid(xs,ys)# xs、ysからメッシュを作る。
M2=np.zeros(xx.shape)# メッシュのサイズのゼロデータを作る。
for xyz in zip(x0,y0,z0):# データを計算する。
M2=M2+lorentz(xx,yy,xyz[0],xyz[1],xyz[2],xyz[2])
plt.contourf(xx,yy,M2)
plt.colorbar()
plt.xscale('log')
plt.yscale('log')
img=save_and_display('test.png',dpi=100)
img
plt.clf()
xs_mesh=np.sqrt(xs[:-1]*xs[1:])
xs_mesh=np.insert(xs_mesh,0,xs[0]**2/xs_mesh[0])
xs_mesh=np.append(xs_mesh,xs[-1]**2/xs_mesh[-1])
ys_mesh=np.sqrt(ys[:-1]*ys[1:])
ys_mesh=np.insert(ys_mesh,0,ys[0]**2/ys_mesh[0])
ys_mesh=np.append(ys_mesh,ys[-1]**2/ys_mesh[-1])
xx_mesh,yy_mesh=np.meshgrid(xs_mesh,ys_mesh)# ピクセルの真ん中(今回は相乗平均)で計算するように座標を選びなおす。
plt.pcolormesh(xx_mesh,yy_mesh,M2)#メッシュの座標を増やしたが、データは元のまま。その結果、メッシュとデータのサイズが異なる。
plt.colorbar()
plt.xscale('log')
plt.yscale('log')
plt.xlim(xs_mesh.min(),xs_mesh.max())
plt.ylim(ys_mesh.min(),ys_mesh.max())
(0.90781371727843896, 16.5232136445007)
img=save_and_display('test.png',dpi=100)
img
plt.clf()
plt.imshow(M2,extent=(xs_mesh.min(),xs_mesh.max(),ys_mesh.min(),ys_mesh.max()),origin='lower',interpolation='none')
plt.xscale('log')
plt.yscale('log')
plt.colorbar()
<matplotlib.colorbar.Colorbar instance at 0x04C80620>
img=save_and_display('test.png',dpi=100)
img
今度は奇麗なプロットができました。 このように、データの間隔が一定でない場合にはpcolormeshやcontour(f)の方が柔軟性があります。
画像計測のデータ表示ではimshowかpcolormeshを使う事になると思います。
今回は紹介しませんでしたが、imshowではRGBの値を直接、配列で指定することも可能です。 ですから、例えば3つの画像データにRGBを対応させることで、互いの相関を直観的に表示することも可能です。
pcolormeshだとデータと座標を結び付けられますが、ピクセルの左下を指定するので注意が必要です。 上の例を見ると、imshowにextent=を用いた場合との差はあまりありませんが、 実験データの場合にはpcolormeshを使う方が、座標変換などを想定すると柔軟性があってよいのではないか、と思います。
contourfは座標軸の扱いは楽ですが、ピクセル毎のデータを見ることはできません。
複数データ間の相関を見る方法としては、 plt.hexbin という関数も便利です。 これは hexagoal binning と呼ばれる新しいプロットの仕方です。
解析関数の振る舞いを把握したい場合には、contour(f)が有用な事が多いと思います。 今回は省略しましたが、等高線の上に値のラベルを書く機能 ( clabel ) もありますので、必要な方は参照してください。