Построить 4D-график в python2.7

Я хочу отображать красный, синий и зеленый цвета по трем осям и массив, в котором хранится значение, соответствующее каждой комбинации цветов в python2.7.... когда я запускаю свою программу, она либо перестает отвечать на запросы в течение 24 часов, либо дает мне ошибка памяти. Вот мой код:

import pylab
import math
from itertools import product
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np

N=[]
p=np.zeros((256,256,256))
S=[]
fig=plt.figure()
ax=fig.gca(projection='3d')
X=np.arange(0,256,1) #for one of the features either red, blue or green
Y=np.arange(0,256,1)
X,Y = np.meshgrid(X,Y)
R=np.sqrt(X**2 + Y**2)
Z=R/np.sqrt(2)
N=p.flatten();
N=(p[i,j,k] for k in Z)            
surf=ax.plot_surface(X,Y,Z, rstride=1, cstride=1,
                    facecolors=cm.jet(N),
                    linewidth=0, antialiased=False, shade=False)
plt.show()

Пожалуйста помоги. Я прочитал предыдущие сообщения и использовал их, но все равно получаю ошибку памяти. Здесь p представляет собой значения комбинаций красного, зеленого и синего цветов. Для простоты я инициализировал его нулем... он выдает следующую ошибку..colset.append(fcolors[rs][cs]) IndexError: index out of bounds


person Jannat Arora    schedule 26.01.2012    source источник
comment
какое именно сообщение об ошибке?   -  person kmote    schedule 27.01.2012
comment
Трассировка (последний последний вызов): Файл C:/Python27/try2.py, строка 22, в ‹module› N.append(prob_Skin[i,j,k]) MemoryError --- это сообщение об ошибке   -  person Jannat Arora    schedule 27.01.2012
comment
В какой части программы вы получаете ошибку памяти? Это когда вы добавляете к N? Если да, то можно ли передать cm.jet() генератор вместо всего списка N. E.g. возьмите строку N.append(P[i,j,k]), а вместо этого на следующей строке укажите N=(p[i,j,k] для i в X для j в Y для K в Z)   -  person robert king    schedule 27.01.2012
comment
facecolors=cm.jet(N), файл C:\Python27\lib\site-packages\matplotlib\colors.py, строка 565, в вызове lut.take(xa, axis=0, mode = 'clip', out = rgba) ValueError: объект слишком маленькой глубины для желаемого массива. Это ошибка, которую я получаю сейчас. Я новичок в python и matplotlib, поэтому многого не понимаю.   -  person Jannat Arora    schedule 27.01.2012
comment
Я внес изменения в соответствии с предложениями Мэтта, но все равно выдает ошибку   -  person Jannat Arora    schedule 27.01.2012


Ответы (1)


Во-первых, ваша программа работает медленно, потому что вы выполняете много ненужной работы по созданию N. Вы строите список размером 70 МБ по несколько байтов за раз (256*256*256=16 777 216 добавлений!). Лучший (более быстрый, эффективный с точки зрения памяти) способ построить p - использовать широковещательную передачу массива numpy, а затем повторно использовать p для создания N:

import numpy as np
a = np.arange(256)
p = a[:,np.newaxis,np.newaxis] * a[np.newaxis,:,np.newaxis] * a[np.newaxis,np.newaxis,:] 
N = p.flatten()

Во-вторых, что более важно, вы неправильно используете plot_surface(). Согласно документам, X, Y и Z должны быть 2D массивы. X и Y закладывают 2D-сетку, а Z обеспечивает «высоту» для каждой точки этой 2D-сетки. Если вы хотите вручную установить цвет лица, он также должен быть двумерным массивом. Вы должны посмотреть пример в документации для рабочего примера.

РЕДАКТИРОВАТЬ:

Я не уверен, как должен выглядеть ваш график, поэтому давайте пройдемся по MPL демо.

Сделайте необходимые импорты и создайте объект оси (ваш делает это правильно):

from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')

Затем создайте сетку X/Y и соответствующую Z. В вашей программе X, Y и Z являются одномерными. Они описывают линию в трехмерном пространстве, а не поверхность.

X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)  # <-- returns a 2D grid from initial 1D arrays
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

Давайте сначала построим простейшую возможную вещь. Без цветов, сглаживания по умолчанию, линий и т. д.

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1)
plt.show()

введите здесь описание изображения

Теперь добавьте цвета. Обратите внимание, что цвет исходит из компонента Z.

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.jet)
plt.show()

введите здесь описание изображения

Теперь вручную управляйте цветами (вдохновение для MPL).

colortuple = ('y', 'k')  # only use two colors: yellow and black
xlen, ylen = X.shape  # get length of 
colors = np.empty(X.shape, dtype=str)  # make a 2D array of strings
for i in range(xlen):
    for j in range(ylen):
        index = (i + j) % 2  # alternating 0's and 1's
        colors[i,j] = colortuple[index]
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, 
        facecolors=colors)

введите здесь описание изображения

Если вы хотите раскрасить на основе какой-либо другой метрики, вы можете создать свою собственную палитру. Есть много ответов на вопросы о том, как это сделать.

Редактировать 2:

Цвета также могут быть указаны как последовательности RGB. Для чего-то вроде вашего красного на X, зеленого на описании Y вы можете сделать это:

xlen, ylen = X.shape
colors = np.zeros((xlen,ylen,3))
jspan = np.linspace(0., 1., ylen)
ispan = np.linspace(0., 1., xlen)
for i in range(xlen):
    colors[i,:,0] = jspan
for j in range(ylen):
    colors[:,j,1] = ispan

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, facecolors=colors,)

введите здесь описание изображения

person matt    schedule 27.01.2012
comment
Спасибо за помощь. Я внес изменения в вопрос в соответствии с вашими предложениями. Все равно выдает ошибку, помогите - person Jannat Arora; 27.01.2012
comment
Может кто-нибудь, пожалуйста, помогите... я пробовал разные формы, но все равно не получаю требуемого ответа - person Jannat Arora; 27.01.2012