矢印を描画 matplotlib.pyplot.quiver
matplotlib.pyplot.arrow
ではなくmatplotlib.pyplot.quiver
を使う。
矢印の始点(px, py)、矢印のベクトル(vx, vy)をquiverに与えればよいが、科学目的の場合デフォルトの引数だとやや問題が起きがちなので一つ一つ説明する。なお、矢印ごとに線の太さを変えることはできない。
基本コードは以下の通り。
import matplotlib.pyplot as plt figsize = 5 fig, ax = plt.subplots(figsize=(figsize,figsize)) ax.quiver([0,1,2,3],[0,0,0,0],[0,1,2,3],[0,1,2,3]) ax.set_xlim(-1,6) ax.set_ylim(-1,6) ax.grid(alpha=0.4) plt.show()
矢印のベクトルとして vx=[0,1,2,3], vy=[0,1,2,3]
と与えているのに、ベクトル長はそうなっていない。仕様書によるとベクトル長は自動調整される。つまり、ベクトルの長さを10倍にしても、生成されるグラフは同じである。確認してみてほしい。
#ax.quiver([0,1,2,3],[0,0,0,0],[0,1,2,3],[0,1,2,3]) のかわりに ax.quiver([0,1,2,3],[0,0,0,0],[0,10,20,30],[0,10,20,30])
これでは困るので、仕様書で提示された引数 angles='xy', scale_units='xy', scale=1
を使う。
scale_units='xy', scale=1
で vx, vyを軸のスケール通りに描画する、angles=xy
で軸の向き通りに描画する (もっとも軸の正負を反転させるという特殊な事例でしか効かないが科学目的であれば設定しておいたほうが良いだろう)。
矢印の長さを軸通りに描画したコード
import matplotlib.pyplot as plt figsize = 5 fig, ax = plt.subplots(figsize=(figsize,figsize)) ax.quiver([0,1,2,3],[0,0,0,0],[0,1,2,3],[0,1,2,3],angles='xy',scale_units='xy',scale=1) ax.set_xlim(-1,6) ax.set_ylim(-1,6) ax.grid(alpha=0.4) ax.set_aspect(1) plt.show()
矢印のベクトル vx=[0,1,2,3], vy=[0,1,2,3]
どおりに描画された。
次に、矢印の太さについて知るために、少し複雑なグラフを描いてみる。
import matplotlib.pyplot as plt import numpy as np xmax = 4.0 ymax = 4.0 figsize=15 fig,axs = plt.subplots(1,3,figsize=(figsize,figsize/4)) for ax,N in zip(axs,[5,10,25]): x = np.linspace(-xmax, xmax, N) y = np.linspace(-ymax, ymax, N) X, Y = np.meshgrid(x, y) U = np.cos(X) V = np.sin(Y) ax.quiver(X, Y, U, V,angles='xy',scale_units='xy',scale=1) ax.set_aspect(1) ax.set_xlim(5,-5) plt.show()
quiverは、矢印の数(たぶん密度)が多くなると矢印の太さを自動調整する仕様である。科学目的だと勝手に変えられると困るので、引数 units='xy', width=0.1
を使って太さを制御する。
#ax.quiver(X, Y, U, V,angles='xy',scale_units='xy',scale=1) のかわりに ax.quiver(X, Y, U, V,angles='xy',scale_units='xy',scale=1, units='xy', width=0.1)
次に、矢印の色を制御する。色に相当する配列を作り第5引数にいれて、カラーマップを指定すれば良い。ここでは カラーマップ Reds
を使った。
#ax.quiver(X, Y, U, V,angles='xy',scale_units='xy',scale=1, units='xy', width=0.1) のかわりに C = (U**2+V**2)**0.5 ax.quiver(X, Y, U, V, C, angles='xy',scale_units='xy',scale=1, units='xy', width=0.1, cmap='Reds')
カラーマップの描画やその範囲指定も含めた全体コード(完成形)を示す。
import matplotlib.pyplot as plt import numpy as np xmax = 4.0 ymax = 4.0 figsize=15 fig,axs = plt.subplots(1,3,figsize=(figsize,figsize/4)) for ax,N in zip(axs,[5,10,25]): x = np.linspace(-xmax, xmax, N) y = np.linspace(-ymax, ymax, N) X, Y = np.meshgrid(x, y) U = np.cos(X) V = np.sin(Y) C = (U**2+V**2)**0.5 im = ax.quiver(X, Y, U, V, C, angles='xy',scale_units='xy',scale=1, units='xy', width=0.1, cmap='Reds') fig.colorbar(im) im.set_clim(0,N*0.1) ax.set_aspect(1) ax.set_xlim(5,-5) plt.show()
その他のサンプルコード
import matplotlib.pyplot as plt px=[] py=[] vx=[] vy=[] colors=[] for yi in range(10): for xi in range(10): px.append(xi) py.append(yi) vx.append(yi*0.1) vy.append(xi*0.1) colors.append((xi**2+yi**2)**0.5) fig = plt.figure() plt.gca().set_aspect('equal') im = plt.quiver(px,py,vx,vy,colors, cmap='Reds', scale = 1,scale_units='xy',angles='xy') plt.xlim(0,10) plt.ylim(0,10) fig.colorbar(im) im.set_clim(0,16) plt.savefig("save.pdf") plt.show()
できる絵
px=[0,1,2,3,4,5,6,7,8] py=[0,1,2,3,4,5,6,7,8] vx=[1,1,1,1,1,1,1,1,1] vy=[0,0,0,0,0,0,0,0,0] color=[-1,2,3,4,5,6,7,8,11] import matplotlib.pyplot as plt import matplotlib import copy cmap = copy.copy(matplotlib.colormaps.get_cmap("tab10")) cmap.set_under('black') cmap.set_over('black') im = plt.quiver(px,py,vx,vy,color, cmap=cmap, scale = 1, scale_units='xy',angles='xy') im.set_clim(0,10) plt.xlim(-1,10) plt.ylim(-1,10) plt.colorbar(im,extend='both') plt.gca().set_aspect('equal') plt.show()
できる絵