2012-01-23 11 views
13

Relacionado con this question, quiero un diagrama de dispersión 3D con colores prescritos para cada punto. El ejemplo publicado en la pregunta funciona en mi sistema, pero después del primer redibujado (por ejemplo después de guardar o si giro la imagen) el color parece perderse, es decir, todos los puntos se dibujan en color azul con la información de profundidad habitual. Por favor vea el ejemplo modificado a continuación.Matplotlib Color de dispersión 3D perdido después de volver a dibujar

Mi sistema es Python 2.6.7 con matplotlib 1.1.0 instalado desde macports en mac 10.8.0. Yo uso el backend de MacOSX.

¿Alguien sabe cómo eludir este problema?

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

Estas son las dos imágenes, me sale: First image Second image

+0

Hm, lo mismo en windows. Si comento la línea 'col = np.arange (30) ', ambas tramas salen idénticas. Sin embargo, no puedo explicar por qué. 'pyplot' es un módulo con estado, y no creo que sea aconsejable abrir una nueva figura sin cerrar la antigua. Si mantiene solo una figura abierta en todo momento, creo que tales efectos podrían prevenirse. –

+0

Acabo de notar que el código realmente usa dos figuras. Sin embargo, esta no fue la causa del problema. Eliminé la primera figura del código de ejemplo y el problema persiste. Gracias por señalar que el problema también existe en Windows. Me parece que esto es algún tipo de error. –

+0

Al igual que una nota para futuros visitantes, esto parece estar corregido en MatPlotLib 1.2.0 :) – Poik

Respuesta

11

No está claro por qué ocurre esto, y sin duda es un error. Aquí proporciono un truco para obtener el resultado que desea, aunque no es como automático como uno quisiera.

Por alguna razón, el Patch3DCollection que representa los puntos de dispersión no se actualiza después de la primera representación. Esta actualización es esencial, porque es donde se establecen colores únicos para cada parche de colección. Para obligarlo a reiniciar, puede usar el método changed en el Patch3DCollection (realmente es un método ScalarMappable), y esto solo documenta que un cambio ocurrió. Cuando se dibuja la figura, comprueba si se produjo una actualización y luego redefine los colores. Si no fue así, este proceso se omite.

Para forzar esta actualización para que ocurra automáticamente, a uno le gustaría hacer esto en cada evento 'dibujar'. Para hacer esto, uno debe register a method usando el método canvasmpl_connect (vea el tutorial vinculado).

Este ejemplo muestra cómo guardar la figura dos veces conserva la asignación de color, pero si descomenta la línea plt.show(), seguirá funcionando (en la rotación, por ejemplo).

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

Lo ideal sería que no deberían estar obligados a ello, y lo global scatCollection se debe tener acceso utilizando otros métodos (Estoy trabajando en hacer esto). Pero esto funciona por ahora ...

Cuestiones relacionadas