Построение трехмерного массива секунда за секундой без преобразования его в 2D с помощью np.объединения, np.добавления или индексирования

#python #python-3.x #numpy #matplotlib #multidimensional-array

Вопрос:

 x = np.array[[[8, 7, 1, 0, 3],
              [2, 8, 5, 5, 2],
              [1, 1, 1, 1, 1]],

             [[8, 4, 1, 0, 0],
              [6, 8, 5, 5, 2],
              [1, 1, 1, 1, 1]],

             [[2, 4, 0, 2, 3],
              [2, 5, 5, 3, 2],
              [1, 1, 1, 1, 1]],

             [[4, 7, 2, 8, 0],
              [1, 3, 6, 5, 2],
              [1, 1, 1, 1, 1]]]
 

У меня есть NumPy массив, называемый x , и я хочу построить его. Каждые 5 столбцов данных здесь представляют 1 секунду. Таким образом, мой массив составляет 5*4=20 секунд данных. Я хочу, чтобы этот массив, который я нарисую с plt.imshow помощью команды, увеличивался, добавляя его рядом с ним каждую секунду. Другими словами, только

 [8, 7, 1, 0, 3],
[2, 8, 5, 5, 2],
[1, 1, 1, 1, 1]]
 

будет разыграна в первую секунду, затем

 [[8, 7, 1, 0, 3, 8, 4, 1, 0, 0],
 [2, 8, 5, 5, 2, 6, 8, 5, 5, 2],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
 

будет нарисован во вторую секунду, и так далее до 4 секунд.

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

Но здесь есть очень важная проблема. Мой реальный массив намного больше. Поэтому, когда я хочу преобразовать 3D-массив , который у меня есть , в 2D np.concatenate , np.append или indexing мой компьютер выходит из строя, потому что массив слишком большой. Есть ли какой-нибудь способ сделать это с matplotlib библиотекой, не преобразуя ее в 2D? Я думаю, что это можно сделать с помощью цикла for, но проблема здесь в том, что в примерах, которые я видел в Интернете, они полностью обновляют изображение, а не добавляют его рядом с другим.

Ответ №1:

ОБНОВЛЕННЫЙ ОТВЕТ:

Следующий код занял менее 5 минут работы на моем ноутбуке с 8 ГБ оперативной памяти и массивом данных формы (475,5400,200).

 d1,d2,d3 = 475,5400,200 # dimensions of the data

# Create some data
values = np.zeros((d1,d2,d3))
values[:] = 1 np.cos(np.arange(d2)/200)[:,None]
values[:] *= 1 np.sin(np.arange(d1*d3)/1000).reshape(d1,d3)[:,None,:]

# Produce plots
fig = plt.figure(figsize=(10,2))
plt.xlim((0,d1*d3))
yaxis = range(d2,-1,-1)
vmin = values.min()
vmax = values.max()

# plot a background of zeros
plt.pcolormesh([0,d1*d3],[d2,0],[[0]], vmin=vmin,vmax=vmax)
plt.savefig('test-000.png')
plt.clf() # clear figure

# plot the data
for i,v in enumerate(values):
    print(i)
    plt.xlim((0,d1*d3)); plt.xticks([], ""); plt.yticks([], "")
    xaxis = range(i*d3,(i 1)*d3 1)
    plt.pcolormesh(xaxis,yaxis,v, vmin=vmin,vmax=vmax)
    plt.savefig('test-{:03d}.png'.format(i 1), transparent=True)
    plt.clf() # clear figure
plt.close()
 

Приведенный выше код создает 476 кадров, которые необходимо наложить, чтобы сформировать анимированный gif. Для этого я использовал ImageMagick:

 convert -delay 2 -layers 'optimize' -dispose none test-*.png test.gif
 

Это результирующая анимация:

анимация pcolormesh

Я надеюсь, что этот метод работает и на вашем компьютере тоже!

ОРИГИНАЛЬНЫЙ ОТВЕТ: (не работает для OP, так как у его компьютера заканчивается оперативная память)

Я не знаю, как это сделать imshow , но вот как я это сделал с pcolormesh :

 d1,d2,d3 = x.shape # dimensions of x
vmin = x.min()
vmax = x.max()

fig = plt.figure(figsize=(10,2))
plt.xlim((0,d1*d3))
yaxis = range(d2,-1,-1)

# plot a background of zeros
xaxis = range(0,d1*d3 1)
plt.pcolormesh(xaxis,yaxis,np.zeros((d2,d1*d3)), vmin=vmin,vmax=vmax)
plt.savefig('test-0.png')

# plot your data 5 seconds at a time
for i,xi in enumerate(x):
    xaxis = range(i*d3,(i 1)*d3 1)
    plt.pcolormesh(xaxis,yaxis,xi, vmin=vmin,vmax=vmax)
    plt.savefig('test-{}.png'.format(i 1))
plt.close()
 

Этот фрагмент кода сохраняет кадр каждые 5 секунд в формате png. Чтобы создать анимированный gif ниже, я использовал ImageMagick: convert -delay 50 test*.png test.gif

анимированный gif

Я уверен, что есть более эффективные способы создания анимации вместо сохранения каждого кадра, а затем создания gif из кадров. Однако у меня нет большого опыта работы с matplotlib и анимированными сюжетами, так что, может быть, кто-то еще может порекомендовать лучший способ создания анимированного gif?

Комментарии:

1. Спасибо, я собираюсь попробовать это.

2. Извините, но это не сработало. Массив, с которым я на самом деле работаю, слишком велик, и, вероятно, поэтому он не работает. Я думаю, что этот метод потребляет много оперативной памяти.

3. @mehmet_kacmaz_03 Насколько велик ваш массив? (и сколько у вас оперативной памяти). Возможно, вы заставите его работать, если снизите качество изображения, и в зависимости от размера изображения эта потеря качества может быть даже не видна глазу. Попробуйте fig = plt.figure(dpi=10) , но dpi , возможно, потребуется даже меньшее значение, поэтому попробуйте и меньшие значения dpi .

4. Спасибо, я постараюсь прямо сейчас. Кстати, размеры массива составляют (475,5400,200), а моя оперативная память составляет 12 Гб.

5. @mehmet_kacmaz_03 . Я обновил свой ответ методом, который занимает очень мало оперативной памяти и намного быстрее, чем мой первоначальный ответ. Я надеюсь, что это будет работать и на вашем компьютере.