matplotlib 中 Poly3DCollection 图的透明度
Posted
技术标签:
【中文标题】matplotlib 中 Poly3DCollection 图的透明度【英文标题】:Transparency for Poly3DCollection plot in matplotlib 【发布时间】:2013-09-24 17:18:36 【问题描述】:我正在尝试使用用于 Python 的神话般的 Matplotlib 包绘制一些对象。这些对象由plt.scatter()
实现的点和Poly3DCollection
实现的补丁组成。我希望补丁具有轻微的透明度,以便可以看到补丁后面的点和边缘。
这里是我已经生成的代码和绘图。似乎我快到了,只是缺少透明度的功能。有趣的是,如果我先绘制Ploy3DCollection
,然后绘制scatter
点,则可以看到点,但看不到边缘。
有人对我有建议吗?
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [0, 2, 1, 1]
y = [0, 0, 1, 0]
z = [0, 0, 0, 1]
vertices = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]
tupleList = list(zip(x, y, z))
poly3d = [[tupleList[vertices[ix][iy]] for iy in range(len(vertices[0]))] for ix in range(len(vertices))]
ax.scatter(x,y,z)
ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.5))
plt.show()
【问题讨论】:
【参考方案1】:我找到了一个很好的解决方法:绘制数据后,在顶部使用相同的颜色和较浅的线条样式绘制另一个图。而不是Poly3DCollection
我使用Line3DCollection
,所以没有绘制任何面孔。结果看起来非常符合预期。
请参阅下面的新情节和创建它的脚本。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [0, 2, 1, 1]
y = [0, 0, 1, 0]
z = [0, 0, 0, 1]
vertices = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]
tupleList = list(zip(x, y, z))
poly3d = [[tupleList[vertices[ix][iy]] for iy in range(len(vertices[0]))] for ix in range(len(vertices))]
ax.scatter(x,y,z)
ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.5))
ax.add_collection3d(Line3DCollection(poly3d, colors='k', linewidths=0.2, linestyles=':'))
plt.show()
【讨论】:
一般来说Line3DCollection
的补丁必须关闭(不像Poly3DCollection
)。在这个例子中没关系,但通常我们应该以重复第一个顶点结束,即vertices = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3], [0, 1, 2]]
。
对于后代,x
、y
和 z
是 vertices
的索引。这有点令人困惑,因为它们都是小的正整数。 Poly3DCollection
的参数是 [[v1, v2, v3], [v2, v3, v4], [v3, v4, v5]]
,其中 v1
是 x、y、z 位置值的元组。【参考方案2】:
我对 OP 代码稍作修改,让透明度工作正常。 Poly3DCollection 的 facecolors 参数似乎覆盖了透明度参数,因此解决方案是在对 Poly3DCollection.set_color
或 Poly3DCollection.set_facecolor
的单独调用中设置颜色:
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [0, 2, 1, 1]
y = [0, 0, 1, 0]
z = [0, 0, 0, 1]
vertices = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]
tupleList = zip(x, y, z)
poly3d = [[tupleList[vertices[ix][iy]] for iy in range(len(vertices[0]))] for ix in range(len(vertices))]
ax.scatter(x,y,z)
collection = Poly3DCollection(poly3d, linewidths=1, alpha=0.2)
face_color = [0.5, 0.5, 1] # alternative: matplotlib.colors.rgb2hex([0.5, 0.5, 1])
collection.set_facecolor(face_color)
ax.add_collection3d(collection)
plt.show()
有趣的是,如果您使用collection.set_edgecolor('k')
明确设置边缘颜色,则边缘也将遵循透明度设置。
【讨论】:
【参考方案3】:非常感谢 Chilichiller 和 Julian。您的示例目前对我非常有用,因为我正在做一个关于使用 matplotlib 进行矩阵 3D 表示的小项目,而 Poly3DCollection 似乎适合这项任务。
一个小笔记,也许对未来的读者有用。 在 Python 3 中运行您的示例会给出 TypeError: 'zip' object is not subscriptable。
最简单的解决方案是将 zip 的返回值包装在对 list() 的调用中(如“深入 Python 3”所示:http://www.diveintopython3.net/porting-code-to-python-3-with-2to3.html)。
【讨论】:
很高兴它对你有用。我现在在原始的 sn-p 中添加了 list() 命令,以使示例代码与 python3 兼容。【参考方案4】:此错误已在新的 matplotlib 中修复。我正在运行 1.5.1 版。
你可以通过运行python查看你的版本,然后执行:
import matplotlib
matplotlib.__version__
您可以使用 pip 获取 matplotlib。如果您使用的是 Ubuntu,请从终端运行:
sudo apt-get install python-pip
sudo pip install matplotlib
【讨论】:
【参考方案5】:这是一个仅使用一次调用Poly3DCollection
的版本,其中edgecolors='k'
控制线条的颜色,facecolors='w'
控制面的颜色。请注意 Matplotlib 如何将多边形后面的边缘用浅灰色着色。
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [0, 2, 1, 1]
y = [0, 0, 1, 0]
z = [0, 0, 0, 1]
vertices = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]
tupleList = list(zip(x, y, z))
poly3d = [[tupleList[vertices[ix][iy]] for iy in range(len(vertices[0]))] for ix in range(len(vertices))]
ax.scatter(x,y,z)
ax.add_collection3d(Poly3DCollection(poly3d, edgecolors='k', facecolors='w', linewidths=1, alpha=0.5))
plt.show()
注意Poly3DCollection
的 API 相当混乱:接受的关键字参数都是 colors
、edgecolor
、edgecolors
、facecolor
和 facecolors
(使用别名和装饰器来定义多个 kwargs 来表示同一件事,其中“s”对于facecolor
和edgecolor
是可选的)。
【讨论】:
以上是关于matplotlib 中 Poly3DCollection 图的透明度的主要内容,如果未能解决你的问题,请参考以下文章
如何从 matplotlib 中删除框架(pyplot.figure vs matplotlib.figure)(frameon=False 在 matplotlib 中有问题)