何度も描いてきたような気がするが、今回も探したので、3dプロットの簡単な例をまとめておきます。
###やったこと
・欲しかった図
・オリジナルのデータ
・カラーバーの合成
・hexbinで描画
・自前関数の欲しかった図を作成
###・欲しかった図
なんの変哲もない以下の右の図を探しました。
ありそうで、matplotlibのexampleからもなかなか見つからないので、以下の過去記事から見つけて、ax4.pcolormesh(f(x1, y1), cmap='hsv')
を採用。
(追記)以下のThe mplot3d Toolkitとpcolormeshに例題がありました。
【参考】
・【matplotlib基本】動的グラフを書いてみる♬~動画出力;Gifアニメーション
・The mplot3d Toolkit
・pcolormesh
pcolormeshの使い方のコード
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
#---
from mpl_toolkits.mplot3d.axes3d import get_test_data
X, Y, Z = get_test_data(0.05)
fig = plt.figure(figsize=(12, 6))
ax1 = fig.add_subplot(1, 2, 1, projection='3d')
hs = ax1.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='hsv') # cm.viridis
#fig.colorbar(hs, ax=ax1)
ax2 = fig.add_subplot(1, 2, 2)
hv = ax2.pcolormesh(X,Y,Z, cmap='hsv')
fig.colorbar(hv, ax=ax2)
plt.pause(1)
plt.savefig('orijinal.png')
plt.close()
【参考】
・Source code for mpl_toolkits.mplot3d.axes3d
get_test_dataのコード(参考より)
def get_test_data(delta=0.05):
"""Return a tuple X, Y, Z with a test data set."""
x = y = np.arange(-3.0, 3.0, delta)
X, Y = np.meshgrid(x, y)
Z1 = np.exp(-(X**2 + Y**2) / 2) / (2 * np.pi)
Z2 = (np.exp(-(((X - 1) / 1.5)**2 + ((Y - 1) / 0.5)**2) / 2) /
(2 * np.pi * 0.5 * 1.5))
Z = Z2 - Z1
X = X * 10
Y = Y * 10
Z = Z * 500
return X, Y, Z
###・オリジナルのデータ
参考は、3dプロットをsubplotとして並べられる(配置アレンジできる)ことを有意義としているようだが、今では普通にいろいろなところで使われている。むしろ、オリジナルデータの使い方が美味しそうです。
【参考】
・What's New 1 Subplot3d
オリジナルデータの使い方のコード
fig = plt.figure(figsize=(12, 6))
ax = fig.add_subplot(1, 2, 1, projection='3d')
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.viridis,
linewidth=0, antialiased=False)
ax.set_zlim3d(-1.01, 1.01)
fig.colorbar(surf, shrink=0.5, aspect=5)
ax = fig.add_subplot(1, 2, 2, projection='3d')
#X, Y, Z = get_test_data(0.05)
ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2)
plt.pause(1)
plt.savefig('orijinal2.png')
plt.close()
###・カラーバーの合成
ここでは、負値と正値で一度描画して、それを合成したものを示している。
単純な合成だと思っていたが、3つ目の絵を見ると再計算しているようだ。
因みに、pos; cmap='Blues', neg; cmap='Reds_r', 最後のものはcmap='RdBu'で描画している。
単純に'hsv'で描画したものが、上のように書けているので異なっているようだ。
【参考】
・Colorbar
カラーバーの合成のコード
#https://matplotlib.org/stable/gallery/color/colorbar_basics.html#sphx-glr-gallery-color-colorbar-basics-py
import numpy as np
import matplotlib.pyplot as plt
# setup some generic data
N = 37
#X, Y, Z = get_test_data(0.05)
#x, y = X, Y #np.mgrid[:N, :N]
#Z = Z #(np.cos(x*0.2) + np.sin(y*0.3))
x, y = np.mgrid[:N, :N]
Z = (np.cos(x*0.2) + np.sin(y*0.3))
# mask out the negative and positive values, respectively
Zpos = np.ma.masked_less(Z, 0)
Zneg = np.ma.masked_greater(Z, 0)
fig, (ax1, ax2, ax3) = plt.subplots(figsize=(13, 3), ncols=3)
# plot just the positive data and save the
# color "mappable" object returned by ax1.imshow
pos = ax1.imshow(Zpos, cmap='Blues', interpolation='none')
# add the colorbar using the figure's method,
# telling which mappable we're talking about and
# which axes object it should be near
fig.colorbar(pos, ax=ax1)
# repeat everything above for the negative data
neg = ax2.imshow(Zneg, cmap='Reds_r', interpolation='none')
fig.colorbar(neg, ax=ax2)
# Plot both positive and negative values between +/- 1.2
pos_neg_clipped = ax3.imshow(Z, cmap='RdBu', vmin=-1.2, vmax=1.2,
interpolation='none')
# Add minorticks on the colorbar to make it easy to read the
# values off the colorbar.
cbar = fig.colorbar(pos_neg_clipped, ax=ax3, extend='both')
cbar.minorticks_on()
plt.savefig('AddClolorbar.png')
plt.pause(1)
plt.close()
###・hexbinで描画
これは、調べていると見つけたので、示しておく。コードは分かるがやっている処理内容は完全には理解できない。以下の参考では、scatterをhexbinで置き換えるとと言っているが、上記のX,Y,Zで描画しても綺麗な絵は得られない。
【参考】
・Hexbin Demo
hexbinで描画のコード
#https://matplotlib.org/stable/gallery/statistics/hexbin_demo.html#sphx-glr-gallery-statistics-hexbin-demo-py
import numpy as np
import matplotlib.pyplot as plt
# Fixing random state for reproducibility
np.random.seed(19680801)
n = 100000
x = np.random.standard_normal(n)
y = 2.0 + 3.0 * x + 4.0 * np.random.standard_normal(n)
xmin = x.min()
xmax = x.max()
ymin = y.min()
ymax = y.max()
fig, axs = plt.subplots(ncols=2, sharey=True, figsize=(7, 4))
fig.subplots_adjust(hspace=0.5, left=0.07, right=0.93)
ax = axs[0]
hb = ax.hexbin(x, y, gridsize=50, cmap='inferno')
ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax))
ax.set_title("Hexagon binning")
cb = fig.colorbar(hb, ax=ax)
cb.set_label('counts')
ax = axs[1]
hb = ax.hexbin(x, y, gridsize=50, bins='log', cmap='inferno')
ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax))
ax.set_title("With a log color scale")
cb = fig.colorbar(hb, ax=ax)
cb.set_label('log10(N)')
plt.pause(1)
plt.savefig('hexbin.png')
plt.close()
自前関数の描画コード
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
#---
from mpl_toolkits.mplot3d.axes3d import get_test_data
def func(x, y):
return x*x + 0.1*y*y #+x*y
#X, Y, Z = get_test_data(0.05)
X = np.arange(-15, 15, 1)
Y = np.arange(-15, 15, 1)
X, Y = np.meshgrid(X, Y)
R = X*X + 0.1*Y*Y
Z = R
#print(Z)
fig = plt.figure(figsize=(12, 6))
ax1 = fig.add_subplot(1, 2, 1, projection='3d')
hs = ax1.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='hsv') # cm.viridis
fig.colorbar(hs, ax=ax1)
ax2 = fig.add_subplot(1, 2, 2)
hv = ax2.pcolormesh(X,Y,Z, cmap='hsv')
fig.colorbar(hv, ax=ax2)
plt.pause(1)
plt.savefig('orijinal3.png')
plt.close()
#---
fig = plt.figure(figsize=(12, 6))
ax = fig.add_subplot(1, 2, 1)
X = np.arange(-15, 15, 1)
Y = np.arange(-80, 80, 5)
X, Y = np.meshgrid(X, Y)
R = func(X,Y) #X*X + 0.01*Y*Y #np.sqrt(X**2 + Y**2)
Z = R #np.sin(R)
#print(Z)
#surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.viridis,linewidth=0, antialiased=False)
surf = ax.pcolormesh(X,Y,Z, cmap='hsv')
#ax.set_zlim3d(-1.01, 1.01)
fig.colorbar(surf, shrink=0.5, aspect=5)
ax = fig.add_subplot(1, 2, 2, projection='3d')
ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2)
plt.pause(1)
plt.savefig('orijinal4.png')
plt.close()
###まとめ
・3dプロットで遊んでみた♬
・自前関数で、3d描画、2dマップ、ワイヤーフレーム、そしてcolorbarを使えるようになった
書いた時点で以下を発見、合わせるといい感じです。、
【参考】
・[Pythonによる科学・技術計算] 2次元(カラー)等高線等の描画,可視化,matplotlib
ということで、等高線追記です。
自前関数の等高線追記描画コード
#---
fig = plt.figure(figsize=(12, 6))
ax = fig.add_subplot(1, 2, 1)
X = np.arange(-15, 15, 1)
Y = np.arange(-80, 80, 5)
X, Y = np.meshgrid(X, Y)
R = func(X,Y) #X*X + 0.01*Y*Y #np.sqrt(X**2 + Y**2)
Z = R #np.sin(R)
#print(Z)
#surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.viridis,linewidth=0, antialiased=False)
surf = ax.pcolormesh(X,Y,Z, cmap='jet')
#ax.set_zlim3d(-1.01, 1.01)
fig.colorbar(surf, shrink=0.5, aspect=5)
# 等高線図の生成。
cont=ax.contour(X,Y,Z, 10, Vmax=1,colors=['white'])
cont.clabel(fmt='%1.1f', fontsize=14)
ax = fig.add_subplot(1, 2, 2, projection='3d')
ax.plot_wireframe(X, Y, Z, rstride=2, cstride=2)
plt.pause(1)
plt.savefig('orijinal7.png')
plt.close()