2012-01-23 3 views
13

Относительно this question, я хочу трехмерный график рассеяния с заданными цветами для каждой точки. Пример, опубликованный в вопросе, работает в моей системе, но после первого перерисовки (например, после сохранения или если я поворачиваю изображение) цвет кажется потерянным, т. Е. Все точки рисуются синим цветом с обычной информацией о глубине. См. Приведенный ниже пример.Matplotlib 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') 

Вот два изображения, я получаю: First image Second image

+0

Hm, то же самое на окнах. Если я прокомментирую строку 'col = np.arange (30) ', обе графики будут идентичными. Не могу объяснить, почему. 'pyplot' является модулем с сохранением состояния, и я не думаю, что было бы разумно открыть новую фигуру, не закрывая старую. Если держать только одну фигуру открытой во все времена, я думаю, что такие эффекты могут быть предотвращены. –

+0

Я только заметил, что код фактически использует две цифры. Однако это не было причиной проблемы. Я удалил первую цифру из кода примера, и проблема не устранена. Спасибо за указание, что проблема также существует в Windows. Мне кажется, что это какая-то ошибка. –

+0

Как и примечание для будущих посетителей, это, по-видимому, исправлено в MatPlotLib 1.2.0 :) – Poik

ответ

11

Это не понятно, почему это происходит, и это, конечно, ошибка. Здесь я предлагаю взломать, чтобы получить желаемый результат, хотя это не как автоматический, как хотелось бы.

По какой-то причине Patch3DCollection, представляющий точки разброса, не обновляется после первого рендеринга. Это обновление имеет важное значение, поскольку именно для каждого патча коллекции установлены уникальные цвета. Чтобы заставить его повторно инициализировать, вы можете использовать метод changed на Patch3DCollection (действительно, метод ScalarMappable), и это просто документы, что изменение happend. Когда рисунок рисуется, он проверяет, произошло ли обновление, а затем переопределяет цвета. Если это не так, этот процесс пропускается.

Чтобы заставить это обновление происходить автоматически, хотелось бы сделать это на каждом событии 'draw'. Для этого необходимо register a method с использованием метода canvasmpl_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 должен быть доступен с помощью других методов (я работаю на этом). Но это работает на данный момент ...

Смежные вопросы