thi*_*ngs 3 python plot matplotlib
我想要做一个matplotlibcontour
或contourf
非网格的三维数据(X,Y,Z),这是在x和y(见示意图)在某种程度上C形的曲线图-因此封闭船体的部分周围的数据是凹在 x 和 y 中。
通常我会通过首先插入它来绘制非网格 3D 数据
from matplotlib.mlab import griddata
griddata...
Run Code Online (Sandbox Code Playgroud)
但这会在数据的凹部产生伪影,使得凹部被插值填充。
是否可以进行插值或轮廓 / 轮廓图,以便尊重数据的凹入部分?
下面是一个示例,说明如何使用tricontourf
遮罩来获得没有数据外插值部分的凹面形状。它依赖于根据条件屏蔽数据的能力。
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np
# create some data
rawx = np.random.rand(500)
rawy = np.random.rand(len(rawx))
cond01 = (rawx-1)**2 + rawy**2 <=1
cond02 = (rawx-0.7)**2 + rawy**2 >0.3
x = rawx[cond01 & cond02]
y = rawy[cond01 & cond02]
f = lambda x,y: np.sin(x*4)+np.cos(y)
z = f(x,y)
# now, x,y are points within a partially concave shape
triang0 = tri.Triangulation(x, y)
triang = tri.Triangulation(x, y)
x2 = x[triang.triangles].mean(axis=1)
y2 = y[triang.triangles].mean(axis=1)
#note the very obscure mean command, which, if not present causes an error.
#now we need some masking condition.
# this is easy in this case where we generated the data according to the same condition
cond1 = (x2-1)**2 + y2**2 <=1
cond2 = (x2-0.7)**2 + (y2)**2 >0.3
mask = np.where(cond1 & cond2,0,1)
# apply masking
triang.set_mask(mask)
fig, (ax, ax2) = plt.subplots(ncols=2, figsize=(6,3))
ax.set_aspect("equal")
ax2.set_aspect("equal")
ax.tricontourf(triang0, z, cmap="Oranges")
ax.scatter(x,y, s=3, color="k")
ax2.tricontourf(triang, z, cmap="Oranges")
ax2.scatter(x,y, s=3, color="k")
ax.set_title("tricontourf without mask")
ax2.set_title("tricontourf with mask")
ax.set_xlim(0,1)
ax.set_ylim(0,1)
ax2.set_xlim(0,1)
ax2.set_ylim(0,1)
plt.show()
Run Code Online (Sandbox Code Playgroud)
如果您无法访问确切条件,但点之间有最大边长(距离),则以下将是一个解决方案。它会掩盖所有至少一侧比某个最大距离长的三角形。如果点密度相当高,这可以很好地应用。
import matplotlib.pyplot as plt
import matplotlib.tri as tri
import numpy as np
# create some data
rawx = np.random.rand(500)
rawy = np.random.rand(len(rawx))
cond01 = (rawx-1)**2 + rawy**2 <=1
cond02 = (rawx-0.7)**2 + rawy**2 >0.3
x = rawx[cond01 & cond02]
y = rawy[cond01 & cond02]
f = lambda x,y: np.sin(x*4)+np.cos(y)
z = f(x,y)
# now, x,y are points within a partially concave shape
triang1 = tri.Triangulation(x, y)
triang2 = tri.Triangulation(x, y)
triang3 = tri.Triangulation(x, y)
def apply_mask(triang, alpha=0.4):
# Mask triangles with sidelength bigger some alpha
triangles = triang.triangles
# Mask off unwanted triangles.
xtri = x[triangles] - np.roll(x[triangles], 1, axis=1)
ytri = y[triangles] - np.roll(y[triangles], 1, axis=1)
maxi = np.max(np.sqrt(xtri**2 + ytri**2), axis=1)
# apply masking
triang.set_mask(maxi > alpha)
apply_mask(triang2, alpha=0.1)
apply_mask(triang3, alpha=0.3)
fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, figsize=(9,3))
ax1.tricontourf(triang1, z, cmap="Oranges")
ax1.scatter(x,y, s=3, color="k")
ax2.tricontourf(triang2, z, cmap="Oranges")
ax2.scatter(x,y, s=3, color="k")
ax3.tricontourf(triang3, z, cmap="Oranges")
ax3.scatter(x,y, s=3, color="k")
ax1.set_title("tricontourf without mask")
ax2.set_title("with mask (alpha=0.1)")
ax3.set_title("with mask (alpha=0.3)")
for ax in (ax1, ax2, ax3):
ax.set(xlim=(0,1), ylim=(0,1), aspect="equal")
plt.show()
Run Code Online (Sandbox Code Playgroud)
可以看出,在alpha
这里找到正确的参数 ( ) 可能需要一些调整。