2012-01-23 172 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應該使用其他方法(我正在這樣做)進行訪問。但現在這個工程...

相關問題