2012-01-23 12 views
13

Powiązany z this question, chcę 3D wykres punktowy z zalecanymi kolorami dla każdego punktu. Przykład zamieszczony w pytaniu działa na moim systemie, ale po pierwszym odświeżeniu (na przykład po zapisaniu lub obróceniu obrazu) kolor wydaje się być utracony, tj. Wszystkie punkty są rysowane w kolorze niebieskim ze zwykłymi informacjami o głębi. Zobacz zmodyfikowany przykład poniżej.Matplotlib 3D kolor rozproszony utracony po przerysowaniu

Mój system to Python 2.6.7 z zainstalowanym matplotlib 1.1.0 z Macports na Mac 10.8.0. Używam backendu MacOSX.

Czy ktoś wie, jak obejść ten problem?

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') 

Oto dwa zdjęcia, otrzymuję: First image Second image

+0

Hm, to samo w oknach. Jeśli skomentuję linię 'col = np.arange (30) ', oba wykresy są identyczne. Nie potrafię jednak wytłumaczyć dlaczego. 'pyplot' jest modułem stanowym i nie sądzę, że mądrze jest otworzyć nową figurę bez zamykania starego. Jeśli tylko jedna postać będzie otwarta przez cały czas, myślę, że można temu zapobiec. –

+0

Właśnie zauważyłem, że kod faktycznie używa dwóch liczb. Nie było to jednak przyczyną problemu. Usunąłem pierwszą cyfrę z kodu przykładowego i problem nadal występuje. Dzięki za wskazanie, że problem występuje również w oknach. Wydaje mi się, że to jakiś błąd. –

+0

Tak jak w przypadku przyszłych użytkowników, wydaje się, że jest to poprawione w MatPlotLib 1.2.0 :) – Poik

Odpowiedz

11

Nie jest jasne, dlaczego tak się dzieje, i to na pewno jest to błąd. Tutaj dostarczam hack, aby uzyskać pożądany wynik, ale nie jest on automatyczny, jak by chciał.

Z jakiegoś powodu Patch3DCollection reprezentujący punkty rozproszone nie jest aktualizowany po pierwszym renderowaniu. Ta aktualizacja jest niezbędna, ponieważ jest tam, gdzie są ustawione unikalne kolory dla każdej łatki kolekcji. Aby wymusić ponowną inicjalizację, można użyć metody changed w metodzie Patch3DCollection (naprawdę jest to metoda), a to po prostu dokumentuje, że zmiana stała się. Po narysowaniu figury sprawdza, czy nastąpiła aktualizacja, a następnie redefiniuje kolory. Jeśli nie, proces ten zostanie pominięty.

Aby wymusić aktualizację automatycznie, należy to zrobić w każdym zdarzeniu "losowania". Aby to zrobić, należy użyć metody register a method przy użyciu metody canvas (patrz dołączony samouczek).

Ten przykład pokazuje, w jaki sposób zapisanie rysunku dwukrotnie zachowuje mapowanie kolorów, ale jeśli odkomentujesz linię plt.show(), nadal będzie działać (na przykład w obrocie).

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') 

Idealnie nie powinno być wymagane, aby to zrobić, a globalna scatCollection powinny być dostępne za pomocą innych metod (pracuję na robienie tego). Ale to działa na razie ...

Powiązane problemy