からっぽのしょこ

読んだら書く!書いたら読む!同じ事は二度調べ(たく)ない

quiver関数の矢印色の設定:2次元の場合【Matplotlib】

はじめに

 Matplotlibライブラリを利用して、矢印プロットを作成します。

【前の内容】

www.anarchive-beta.com

【目次】

quiver関数の矢印色の設定:2次元の場合

 Matplotlibライブラリのquiver関数で矢印を描画できます。前回は、2次元の場合の矢のサイズ・形状に関する引数を確認しました。今回は、矢の色に関する引数を確認します。

 利用するライブラリを読み込みます。

# 利用ライブラリ
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation


矢印の作図

 まずは、2次元の場合の矢印の座標・長さに関する引数を簡単に確認します。
 詳しくは「矢印プロットの作図【ゼロつく1のノート(Python)】 - からっぽのしょこ」を参照してください。

 座標と移動量を指定して、矢印を描画します。

# 座標・移動量を指定
x, y = 0.0, 1.0
u, v = 3.0, 2.0

# 枠色・面色・枠線幅を指定
fc = 'lightgreen'
ec = 'orange'
lw = 2.0

# ラベル用の文字列を作成
str_fc = 'None' if fc == None else "'" + fc + "'"
str_ec = 'None' if ec == None else "'" + ec + "'"

# 2Dベクトルを作図
fig, ax = plt.subplots(figsize=(6, 5), facecolor='white')
ax.scatter(x, y, s=100, label='(X, Y)') # 始点
ax.scatter(x+u, y+v, s=100, label='(X+U, Y+V)') # 終点
ax.quiver(x, y, u, v, 
          facecolor=fc, edgecolor=ec, linewidth=lw, 
          units='dots', width=6, headwidth=3, headlength=5, headaxislength=4.5, 
          angles='xy', scale_units='xy', scale=1, 
          label='({: .2f}, {: .2f}, {: .2f}, {: .2f})'.format(x, y, u, v)) # 矢印
ax.set_xticks(ticks=np.arange(np.floor(x-abs(u))-1, np.ceil(x+abs(u))+2))
ax.set_yticks(ticks=np.arange(np.floor(y-abs(v))-1, np.ceil(y+abs(v))+2))
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('facecolor='+str_fc+', edgecolor='+str_ec+', linewidth='+str(lw), 
             loc='left', fontsize=10)
fig.suptitle('pyplot.quiver(X, Y, U, V)', fontsize=15)
ax.grid()
ax.legend()
ax.set_aspect('equal')
plt.show()

quiver関数の座標と移動量の引数

 2次元ベクトルの場合は、第1・2引数に始点の座標 X, Y、第3・4引数に移動量 U, V を指定します。終点の座標は X + U, Y + V になります。
 angles='xy'scale_units='xy'scale=1 を指定すると、指定した座標の通りに描画されます。デフォルトでは矢印の長さ(終点の座標)が自動調整されます。
 width 引数は矢全体の幅、headwidth 引数は矢頭の幅、headlength 引数は矢頭の最大幅までの長さ、headaxislength 引数は矢頭の長さです。

 終点の座標と矢の長さの関係については「矢印の色の設定」を参照してください。

 (ラベル用の文字列でごにょごにょやってるのは、文字列を表すためにクォーテーションマーク ' を前後に追加して、しかし None のときは追加しない拘りのためです。矢印の作図自体には不要な処理です。)

色に関する引数

 次からは、矢印の色に関する引数を確認していきます。

cmap引数

 cmap 引数で矢の色のグラデーションを設定できます。

 引数の値を変更した矢印を並べて描画します。

・作図コード(クリックで展開)

# 矢印の数を指定
n = 20

# カラーマップ・枠色・枠線幅を指定
cmap = 'viridis'
ec = None
lw = 0.0

# x軸方向の移動量を指定
u = 3.0

# 座標・移動量を作成
os = np.repeat(0, repeats=n)
ys = np.arange(n)
us = np.repeat(u, repeats=n)

# グラデーション用の値を指定
cs = ys**2

# ラベル用の文字列を作成
str_cmap = 'None' if cmap == None else "'" + cmap + "'"
str_ec   = 'None' if ec == None else "'" + ec + "'"

# 2Dベクトルを作図
fig, ax = plt.subplots(figsize=(6, 8), facecolor='white')
quiv = ax.quiver(os, ys, us, os, cs, 
                 cmap=cmap, edgecolor=ec, linewidth=lw, 
                 units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, 
                 angles='xy', scale_units='xy', scale=1) # 矢印
for i in range(n):
    ax.text(0, i, s='C='+str(cs[i])+' ', 
            size=10, ha='right', va='center') # 引数ラベル
ax.set_xticks(ticks=np.arange(u+1))
ax.set_yticks(ticks=np.arange(n))
ax.set_xlim(-6, np.ceil(u)+1)
ax.set_ylim(-1, n)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('cmap='+str_cmap+', edgecolor='+str_ec+', linewidth='+str(lw), 
             loc='left', fontsize=10)
fig.suptitle('pyplot.quiver(cmap)', fontsize=15)
plt.colorbar(quiv)
ax.grid(axis='x')
ax.set_aspect('equal')
plt.show()

quiver関数のグラデーションの引数

 第5引数にグラデーション用の値、cmap 引数にカラーマップ名を指定します。デフォルトは viridis です。
 使用できるカラーマップについては「Choosing Colormaps in Matplotlib — Matplotlib 3.7.2 documentation」を参照してください。

 引数の値を変更した矢印のアニメーションを作成します。

・作図コード(クリックで展開)

# フレーム数を指定
n = 101

# グラデーション用の値の範囲を指定
cs = np.linspace(start=-10, stop=10, num=n)

# カラーマップ・枠色・枠線幅を指定
cmap = None
ec = None
lw = 0.0

# x軸方向の移動量を指定
u = 3.0

# ラベル用の文字列を作成
str_cmap = 'None' if cmap == None else "'" + cmap + "'"
str_ec   = 'None' if ec == None else "'" + ec + "'"

# グラフオブジェクトを初期化
fig, ax = plt.subplots(figsize=(7, 3), facecolor='white')
fig.suptitle('pyplot.quiver(cmap)', fontsize=15)

# カラーバー描画用のダミーを作成
tmp = ax.quiver(0, 0, u, 0, 0, 
                cmap=cmap, clim=(cs.min(), cs.max()), edgecolor=ec, linewidth=lw, 
                units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, 
                angles='xy', scale_units='xy', scale=1) # 矢印
fig.colorbar(tmp)

# 作図処理を関数として定義
def update(i):
    
    # 前フレームのグラフを初期化
    plt.cla()
    
    # 2Dベクトルを作図
    ax.quiver(0, 0, u, 0, cs[i], 
              cmap=cmap, clim=(cs.min(), cs.max()), edgecolor=ec, linewidth=lw, 
              units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, 
              angles='xy', scale_units='xy', scale=1) # 矢印
    ax.text(0, 0, s='C={: .1f}'.format(cs[i])+' ', 
            size=10, ha='right', va='center') # 引数ラベル
    ax.set_xticks(ticks=np.arange(u+1))
    ax.set_yticks(ticks=[0])
    ax.set_xlim(-3, np.ceil(u)+1)
    ax.set_ylim(-1, 1)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title('cmap='+str_cmap+', edgecolor='+str_ec+', linewidth='+str(lw), 
                 loc='left', fontsize=10)
    ax.grid(axis='x')
    ax.set_aspect('equal')

# gif画像を作成
ani = FuncAnimation(fig=fig, func=update, frames=n, interval=100)

# gif画像を保存
ani.save(filename='2d_quiver_cmap.gif')

 作図処理をupdate()として定義して、FuncAnimation()でgif画像を作成します。
 フレームごとにカラーバーが表示されないように、update() の外でダミーのグラフを使って設定しておきます。( if 文で初回だけ処理しようとしても2つ表示されてしまいます。なぜ?)

quiver関数のグラデーションの引数

 clim 引数にグラデーションの最小値・最大値を指定できます。

facecolor引数

 color, facecolor 引数で矢の内側の色を設定できます。

 引数の値を変更した矢印を並べて描画します。

・作図コード(クリックで展開)

# 面色を指定
fcs = [
    'purple', 'green', 'pink', 'yellow', 'lightblue', 
    'red', 'lightgreen', 'white', '#F8C46E', '#DAC4AA'
]

# 矢印の数を設定
n = len(fcs)

# 枠色・枠線幅を指定
ec = None
lw = 0.0

# x軸方向の移動量を指定
u = 3.0

# 座標・移動量を作成
os = np.repeat(0, repeats=n)
ys = np.arange(n)
us = np.repeat(u, repeats=n)

# ラベル用の文字列を作成
str_ec = 'None' if ec == None else "'" + ec + "'"

# 2Dベクトルを作図
fig, ax = plt.subplots(figsize=(6, 6), facecolor='white')
ax.quiver(os, ys, us, os, 
          facecolor=fcs, edgecolor=ec, linewidth=lw, 
          units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, 
          angles='xy', scale_units='xy', scale=1) # 矢印
for i in range(n):
    str_fc = 'None' if fcs[i] == None else "'" + fcs[i] + "'"
    ax.text(0, i, s='facecolor=' + str_fc + ' ', 
            size=10, ha='right', va='center') # 引数ラベル
ax.set_xticks(ticks=np.arange(u+1))
ax.set_yticks(ticks=np.arange(n))
ax.set_xlim(-6, np.ceil(u)+1)
ax.set_ylim(-1, n)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('edgecolor='+str_ec+', linewidth='+str(lw), 
             loc='left', fontsize=10)
fig.suptitle('pyplot.quiver(facecolor)', fontsize=15)
ax.grid(axis='x')
ax.set_aspect('equal')
plt.show()

quiver関数の矢の塗りつぶし色の引数

 facecolor または省略形の fc, color 引数は、矢全体の塗りつぶし色です。色名やカラーコードを指定できます。デフォルトは黒色で、None を指定するとMatplotlibで良く使われるデフォルト色( C0 )になります。

・作図コード(クリックで展開)

# 面色を指定
fcs = [None, 'C0']

# 矢印の数を設定
n = len(fcs)

# 枠色・枠線幅を指定
ec = None
lw = 0.0

# x軸方向の移動量を指定
u = 3.0

# ラベル用の文字列を作成
str_ec = 'None' if ec == None else "'" + ec + "'"

# 2Dベクトルを作図
fig, ax = plt.subplots(figsize=(6, 3), facecolor='white')
for i in range(n):
    ax.quiver(0, i, u, 0, 
              facecolor=fcs[i], edgecolor=ec, linewidth=lw, 
              units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, 
              angles='xy', scale_units='xy', scale=1) # 矢印
    str_fc = 'None' if fcs[i] == None else "'" + fcs[i] + "'"
    ax.text(0, i, s='facecolor=' + str_fc + ' ', 
            size=10, ha='right', va='center') # 引数ラベル
ax.set_xticks(ticks=np.arange(u+1))
ax.set_yticks(ticks=np.arange(n))
ax.set_xlim(-6, np.ceil(u)+1)
ax.set_ylim(-1, n)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('edgecolor='+str_ec+', linewidth='+str(lw), 
             loc='left', fontsize=10)
fig.suptitle('pyplot.quiver(facecolor)', fontsize=15)
ax.grid(axis='x')
ax.set_aspect('equal')
plt.show()

quiver関数の矢の塗りつぶし色の引数

 配色用のリストや配列に None が含まれると処理できないので、for 文を使って1つずつ設定を変えて描画します。

edgecolor引数

 edgecolor 引数で矢の枠線の色を設定できます。

 引数の値を変更した矢印を並べて描画します。

・作図コード(クリックで展開)

# 枠色を指定
ecs = [
    'purple', 'green', 'pink', 'yellow', 'lightblue', 
    'red', 'lightgreen', 'white', '#F8C46E', '#DAC4AA'
]

# 矢印の数を設定
n = len(ecs)

# 面色・枠線幅を指定
fc = 'white'
lw = 2.0

# x軸方向の移動量を指定
u = 3.0

# 座標・移動量を作成
os = np.repeat(0, repeats=n)
ys = np.arange(n)
us = np.repeat(u, repeats=n)

# ラベル用の文字列を作成
str_fc = 'None' if fc == None else "'" + fc + "'"

# 2Dベクトルを作図
fig, ax = plt.subplots(figsize=(6, 6), facecolor='white')
ax.quiver(os, ys, us, os, 
          facecolor=fc, edgecolor=ecs, linewidth=lw, 
          units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, 
          angles='xy', scale_units='xy', scale=1) # 矢印
for i in range(n):
    str_ec = 'None' if ecs[i] == None else "'" + ecs[i] + "'"
    ax.text(0, i, s='edgecolor=' + str_ec + ' ', 
            size=10, ha='right', va='center') # 引数ラベル
ax.set_xticks(ticks=np.arange(u+1))
ax.set_yticks(ticks=np.arange(n))
ax.set_xlim(-6, np.ceil(u)+1)
ax.set_ylim(-1, n)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('facecolor='+str_fc+', linewidth='+str(lw), 
             loc='left', fontsize=10)
fig.suptitle('pyplot.quiver(edgecolor)', fontsize=15)
ax.grid(axis='x')
ax.set_aspect('equal')
plt.show()

quiver関数の矢の枠線の色の引数

 edgecolor または省略形の ec 引数は、矢の枠の色です。色名やカラーコードを指定できます。デフォルトや None を指定した場合は白色になります。

・作図コード(クリックで展開)

# 枠色を指定
ecs = [None, 'C0']

# 矢印の数を設定
n = len(ecs)

# 面色・枠線幅を指定
fc = 'white'
lw = 2.0

# x軸方向の移動量を指定
u = 3.0

# ラベル用の文字列を作成
str_fc = 'None' if fc == None else "'" + fc + "'"

# 2Dベクトルを作図
fig, ax = plt.subplots(figsize=(6, 3), facecolor='white')
for i in range(n):
    ax.quiver(0, i, u, 0, 
              facecolor=fc, edgecolor=ecs[i], linewidth=lw, 
              units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, 
              angles='xy', scale_units='xy', scale=1) # 矢印
    str_ec = 'None' if ecs[i] == None else "'" + ecs[i] + "'"
    ax.text(0, i, s='edgecolor=' + str_ec + ' ', 
            size=10, ha='right', va='center') # 引数ラベル
ax.set_xticks(ticks=np.arange(u+1))
ax.set_yticks(ticks=np.arange(n))
ax.set_xlim(-6, np.ceil(u)+1)
ax.set_ylim(-1, n)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('facecolor='+str_fc+', linewidth='+str(lw), 
             loc='left', fontsize=10)
fig.suptitle('pyplot.quiver(edgecolor)', fontsize=15)
ax.grid(axis='x')
ax.set_aspect('equal')
plt.show()

quiver関数の矢の枠線の色の引数

 「facecolor引数」のときと同様にして作図します。

linewidth引数

 linewidth 引数で矢の枠線の太さを設定できます。

 引数の値を変更した矢印を並べて描画します。

・作図コード(クリックで展開)

# 矢印の数を指定
n = 21

# 枠線幅の範囲を指定
lws = np.linspace(start=0, stop=10, num=n)

# 面色・枠色を指定
fc = 'lightgreen'
ec = 'orange'

# x軸方向の移動量を指定
u = 3.0

# 座標・移動量を作成
os = np.repeat(0, repeats=n)
ys = np.arange(n)
us = np.repeat(u, repeats=n)

# ラベル用の文字列を作成
str_fc = 'None' if fc == None else "'" + fc + "'"
str_ec = 'None' if ec == None else "'" + ec + "'"

# 2Dベクトルを作図
fig, ax = plt.subplots(figsize=(6, 8), facecolor='white')
ax.quiver(os, ys, us, os, 
          facecolor=fc, edgecolor=ec, linewidth=lws, 
          units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, 
          angles='xy', scale_units='xy', scale=1) # 矢印
for i in range(n):
    ax.text(0, i, s='linewidth='+str(lws[i])+' ', 
            size=10, ha='right', va='center') # 引数ラベル
ax.set_xticks(ticks=np.arange(u+1))
ax.set_yticks(ticks=np.arange(n))
ax.set_xlim(-6, np.ceil(u)+1)
ax.set_ylim(-1, n)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('facecolor='+str_fc+', edgecolor='+str_ec, 
             loc='left', fontsize=10)
fig.suptitle('pyplot.quiver(linewidth)', fontsize=15)
ax.grid(axis='x')
ax.set_aspect('equal')
plt.show()

quiver関数の矢の枠線の太さの引数

 linewidth または省略形の lw 引数は、矢の枠線の幅です。
 負の値を指定した場合は絶対値になるようです(?)。

 引数の値を変更した矢印のアニメーションを作成します。

・作図コード(クリックで展開)

# フレーム数を指定
n = 101

# 枠線幅の範囲を指定
lws = np.linspace(start=0, stop=5, num=n)

# 面色・枠色を指定
fc = 'lightgreen'
ec = 'orange'

# x軸方向の移動量を指定
u = 3.0

# ラベル用の文字列を作成
str_fc = 'None' if fc == None else "'" + fc + "'"
str_ec = 'None' if ec == None else "'" + ec + "'"

# グラフオブジェクトを初期化
fig, ax = plt.subplots(figsize=(6, 3), facecolor='white')
fig.suptitle('pyplot.quiver(linewidth)', fontsize=15)

# 作図処理を関数として定義
def update(i):
    
    # 前フレームのグラフを初期化
    plt.cla()
    
    # 2Dベクトルを作図
    ax.quiver(0, 0, u, 0, 
              facecolor=fc, edgecolor=ec, linewidth=lws[i], 
              units='dots', width=6.0, headwidth=3.0, headlength=5.0, headaxislength=4.5, 
              angles='xy', scale_units='xy', scale=1) # 矢印
    ax.text(0, 0, s='linewidth={:.1f}'.format(lws[i])+' ', 
            size=10, ha='right', va='center') # 引数ラベル
    ax.set_xticks(ticks=np.arange(u+1))
    ax.set_yticks(ticks=[0])
    ax.set_xlim(-3, np.ceil(u)+1)
    ax.set_ylim(-1, 1)
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title('facecolor='+str_fc+', edgecolor='+str_ec, 
                 loc='left', fontsize=10)
    ax.grid(axis='x')
    ax.set_aspect('equal')

# gif画像を作成
ani = FuncAnimation(fig=fig, func=update, frames=n, interval=100)

# gif画像を保存
ani.save(filename='2d_quiver_lw.gif')

quiver関数の矢の枠線の太さの引数


点線の矢印の作図

 最後は、矢全体の形状を調整して点線などの矢印を描画します。

 「矢印の作図」のときと同様にして作図します。

# 座標・移動量を指定
x, y = 0.0, 1.0
u, v = 2.5, 1.5

# 矢幅・矢頭幅・矢頭長・矢軸長を指定
w   = 2.0
hw  = 10.0
hl  = 10.0
hal = 1.5

# 枠色・面色・枠線幅を指定
fc = 'white'
ec = 'orange'
lw = 2.0

# ラベル用の文字列を作成
str_fc = 'None' if fc == None else "'" + fc + "'"
str_ec = 'None' if ec == None else "'" + ec + "'"

# 2Dベクトルを作図
fig, ax = plt.subplots(figsize=(6, 5), facecolor='white')
ax.quiver(x, y, u, v, 
          facecolor=fc, edgecolor=ec, linewidth=lw, linestyle=':', 
          units='dots', width=w, headwidth=hw, headlength=hl, headaxislength=hal, 
          angles='xy', scale_units='xy', scale=1, 
          label='({: .2f}, {: .2f}, {: .2f}, {: .2f})'.format(x, y, u, v)) # 矢印
ax.set_xticks(ticks=np.arange(np.floor(x-abs(u))-1, np.ceil(x+abs(u))+2))
ax.set_yticks(ticks=np.arange(np.floor(y-abs(v))-1, np.ceil(y+abs(v))+2))
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('width={}, headwidth={}, headlength={}, headaxislength={}'.format(w, hw, hl, hal) + '\n' + 
             'facecolor='+str_fc+', edgecolor='+str_ec+', linewidth='+str(lw), 
             loc='left', fontsize=10)
fig.suptitle('pyplot.quiver(X, Y, U, V)', fontsize=15)
ax.grid()
ax.legend()
ax.set_aspect('equal')
plt.show()

quiver関数による点線の矢印のグラフ

 矢の形状を上手いこと調整すると点線や破線の矢印を描画できます。(各辺が二重になっているので上手く点が重ならないと意図通りになりません。)

 この記事では、矢印の色に関する引数を確認しました。ここまでは、2次元プロットを扱いました。次からは、3次元プロットを扱います。

参考リンク

おわりに

 前回のおまけで書きました。書くつもりはなかったのですが、width引数とlinewidth引数の違いが分かからず間違って使ってたのと、グラデーションの周りの引数が分かりにくかった(vminとvmaxじゃなかった)ので、一緒に書いとくかとなりました。

【次の内容】

www.anarchive-beta.com