Matplotlib 3D散点图重绘后颜色丢失
与这个问题相关,我想要一个3D散点图,每个点都有指定的颜色。问题中提供的例子在我的系统上可以运行,但在第一次重新绘制后(比如保存图像或者旋转图像),颜色似乎就消失了,也就是说,所有的点都变成了蓝色,只有深度信息还在。请看下面修改过的例子。
我的系统是Python 2.6.7,安装了matplotlib 1.1.0,使用的是macports,运行在mac 10.8.0上。我使用的是MacOSX后端。
有没有人知道怎么解决这个问题?
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Create Map
cm = plt.get_cmap("RdYlGn")
x = np.random.rand(30)
y = np.random.rand(30)
z = np.random.rand(30)
col = np.arange(30)
fig = plt.figure()
ax3D = fig.add_subplot(111, projection='3d')
ax3D.scatter(x, y, z, s=30, c=col, marker='o', cmap=cm)
plt.savefig('image1.png')
plt.savefig('image2.png')
这是我得到的两张图片:


1 个回答
11
现在还不太清楚为什么会出现这个问题,这肯定是个bug。不过,我这里提供一个解决方法,虽然它没有那么自动化。
出于某种原因,表示散点的 Patch3DCollection
在第一次渲染后并没有更新。这个更新是很重要的,因为它是为每个集合的补丁设置独特颜色的地方。为了强制它重新初始化,你可以在 Patch3DCollection
上使用 changed
方法(其实这是 ScalarMappable
的一个方法),这个方法只是用来记录发生了变化。当图形被绘制时,它会检查是否发生了更新,如果有,就会重新定义颜色。如果没有,这个过程就会被跳过。
为了让这个更新自动发生,最好是在每次“绘制”事件时都这样做。要实现这一点,需要使用 canvas
的 mpl_connect
方法来 注册一个方法(可以参考链接中的教程)。
这个例子展示了保存图形两次可以保持颜色映射,但如果你取消注释 plt.show()
这一行,它仍然会正常工作(比如在旋转时)。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Create Map
cm = plt.get_cmap("RdYlGn")
# added a seed so consistant plotting of points
np.random.seed(101)
x = np.random.rand(30)
y = np.random.rand(30)
z = np.random.rand(30)
col = np.arange(30)
fig = plt.figure()
#ax = fig.add_subplot(111)
#scatCollection = ax.scatter(x,y,
ax3D = fig.add_subplot(111, projection='3d')
# keep track of the Patch3DCollection:
scatCollection = ax3D.scatter(x, y, z, s=30,
c=col,
marker='o',
cmap=cm
)
def forceUpdate(event):
global scatCollection
scatCollection.changed()
fig.canvas.mpl_connect('draw_event',forceUpdate)
#plt.show()
plt.savefig('image1.png')
plt.savefig('image2.png')
理想情况下,不应该需要这样做,应该可以通过其他方法访问全局的 scatCollection
(我正在努力实现这一点)。不过现在这样也能用……