2012-01-23 235 views
13

this question相关,我需要一个三维散点图,每个点都有指定的颜色。该问题中发布的示例适用于我的系统,但在第一次重绘之后(例如保存后或如果我旋转图像),颜色似乎丢失,即所有点都以常规深度信息以蓝色绘制。请参阅下面的修改示例。Matplotlib重绘后丢失三维散点图颜色

我的系统是Python 2.6.7,在mac 10.8.0上从macports安装了matplotlib 1.1.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') 

这里有两个图像,我得到: First image Second image

+0

嗯,在窗户上。如果我注释掉'col = np.arange(30) '这一行,这两个地块都是相同的。不能解释为什么。 'pyplot'是一个有状态的模块,我认为不关闭旧模块就开启一个新数字并不明智。如果一直只有一个数字开放,我认为可以防止这种影响。 –

+0

我只注意到代码实际上使用了两个数字。不过,这不是问题的原因。我从示例代码中删除了第一个数字,问题依然存在。感谢您指出该问题也存在于Windows上。在我看来,这是一种错误。 –

+0

就像未来访问者的笔记一样,这似乎是在MatPlotLib 1.2.0中修复:) – Poik

回答

11

它为什么发生这种情况目前尚不清楚,这肯定是一个错误。在这里,我提供了一个黑客来获得你想要的结果,虽然它不是,因为它可以自动地按照你想要的那样自动生成

由于某些原因,代表散点的Patch3DCollection在第一次渲染后未更新。此更新至关重要,因为它是为每个集合补丁设置独特颜色的地方。要强制重新初始化,您可以在Patch3DCollection(真正的ScalarMappable方法)上使用changed方法,这只是记录了更改发生的事情。当绘制图形时,它会检查是否发生更新,然后重新定义颜色。如果没有,则跳过此过程。

要强制此更新自动发生,人们希望在每个“绘制”事件中执行此操作。为此,必须使用canvasmpl_connect方法register a method(请参阅链接教程)。

这个例子显示了如何将图保存两次保留颜色映射,但是如果取消注释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应该使用其他方法(我正在这样做)进行访问。但现在这个工程...

相关问题