Matplotlib: построение матрицы в al oop при обновлении диапазона значений цветовой шкалы - PullRequest
0 голосов
/ 11 марта 2020

Я хочу построить трехмерную тензорную плоскость, используя matplotlib в al oop. Однако в этом примере matplotlib продолжает добавлять цветные полосы к рисунку:

data = np.random.rand(100,100,10)
for i in range(10):
    plt.imshow(np.squeeze(data[:, :, i]))
    plt.colorbar()
    plt.pause(2)
    print(i)

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

Ответы [ 3 ]

0 голосов
/ 12 марта 2020

Этот вопрос заинтриговал меня, так как взлом на matplotlib - мое хобби. Рядом с решением, предложенным @mcExchange, можно использовать это

from matplotlib.pyplot import subplots 
import numpy as np

%matplotlib notebook
d = np.random.rand(10, 10)
fig, ax = subplots(figsize = (2,2))
# create mappable
h = ax.imshow(d)
# create colorbar
cb = fig.colorbar(h)
# show non-blocking
fig.show(0)
for i in range(100):
    # generate new data
    h.set_data(np.random.randn(*d.shape) + 1)
    h.autoscale()
    # flush events update time 
    ax.set_title(f't = {i}')
    fig.canvas.draw(); fig.canvas.flush_events(); 

Как я получил это решение?

В документе указано, что colorbar.update_normal обновляется только в том случае, если норма для сопоставляемого элемента равна отличается от ранее. Установка данных не меняет этого. Поэтому, чтобы зарегистрировать это обновление, необходимо вызвать функцию вручную. За сценой происходит следующее:

    # rescale data for cb trigger
    h.norm.autoscale(h._A) #h._A is the representation of the data
    # update mappable
    h.colorbar.update_normal(h.colorbar.mappable)
0 голосов
/ 12 марта 2020

Простое решение

Очистить фигуру при каждом запуске l oop.

import numpy as np
import matplotlib.pyplot as plt

data = np.random.rand(100,100,10) * np.linspace(1,7,10)

fig = plt.figure()

for i in range(10):
    plt.clf()
    plt.imshow(np.squeeze(data[:, :, i]))
    plt.colorbar()
    plt.pause(2)

plt.show()

Эффективное решение

Используйте одно и то же изображение и просто обновите данные , Также используйте FuncAnimation вместо al oop для запуска всего события GUI l oop.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

data = np.random.rand(100,100,10) * np.linspace(1,7,10)

fig, ax = plt.subplots()
im = ax.imshow(np.squeeze(data[:, :, 0]))
cbar = fig.colorbar(im, ax=ax)

def update(i):
    im.set_data(data[:, :, i])
    im.autoscale()

ani = FuncAnimation(fig, update, frames=data.shape[2], interval=2000)
plt.show()
0 голосов
/ 11 марта 2020

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

Это слегка измененная версия этот ответ

import matplotlib.pyplot as plt
import numpy as np


def visualize_tensor(data, delay=0.5):
    """ data must be 3 dimensional array and
    have format:
    [height x width x channels]"""
    assert(np.ndim(data) == 3)

    # Get number of channels from last dimension
    num_channels = np.shape(data)[-1]

    # Plot data of first channel
    fig = plt.figure()
    ax = fig.add_subplot(111)
    data_first_channel = data[:, :, 0]
    plot = ax.imshow(data_first_channel)

    # Create colorbar
    cbar = plt.colorbar(plot)
    plt.show(block=False)

    # Iterate over all channels
    for i in range(num_channels):
        print(f"channel = {i}")
        data_nth_channel = np.squeeze(data[:, :, i])
        plot.set_data(data_nth_channel)
        plot.autoscale()
        vmin = np.min(data_nth_channel.view())  # get minimum of nth channel
        vmax = np.max(data_nth_channel.view())  # get maximum of nth channel
        cbar.set_clim(vmin=vmin, vmax=vmax)     
        cbar_ticks = np.linspace(vmin, vmax, num=11, endpoint=True)
        cbar.set_ticks(cbar_ticks)
        cbar.draw_all()
        plt.draw()
        plt.pause(delay)

Пример выполнения:

data = np.random.rand(20,20,10)
visualize_tensor(data)

Обновление : Использование plot.autoscale() заставляет цветовую полосу динамически адаптироваться, см. этот ответ

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...