Обновить диапазон палитры в matplotlib

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

См. Следующий минимальный рабочий пример:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111)

# Random data
data = np.random.rand(10, 10)

# Plot data
levels = np.linspace(0., 1., 100)
plot = ax.contourf(data, levels=levels)
clist = plot.collections[:]

# Create colorbar
cbar = plt.colorbar(plot)
cbar_ticks = np.linspace(0., 1., num=6, endpoint=True)
cbar.set_ticks(cbar_ticks)

plt.show()

def update():
    # Remove old plot
    for c in clist:
        ax.collections.remove(c)
        clist.remove(c)

    # Create new data and plot
    new_data   = 2.*np.random.rand(10, 10)
    new_levels = np.linspace(0., 2., 200)
    new_plot = ax.contourf(new_data, levels=new_levels )

    # Modify colorbar
    cbar.set_clim(0., 2.)
    new_cbar_ticks = np.linspace(0., 2., num=21, endpoint=True)
    cbar.set_ticks(new_cbar_ticks)

    plt.draw()

update()

Без звонка update() получаю следующее изображение:

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

Это именно то, что я хочу. В функции update() я в основном меняю диапазон данных с [0,1) на [0,2), создаю новые данные и обновляю график. Я также попытался удвоить выборку в тиках шкалы палитры, чтобы тики были с интервалом 0,1 вместо 0,2. Вот что я получаю:

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

Данные построены правильно, палитра данных верна, отметки и цвет на палитре верны, но диапазон палитры по-прежнему от 0 до 1. Как изменить палитру, чтобы показать полный диапазон вверх до 2?


person Sebastian    schedule 05.12.2016    source источник


Ответы (2)


Можете ли вы работать с imshow вместо contour? В этом случае легко обновить и график, и цветовую шкалу.

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111)

# Random data
data = np.random.rand(10, 10)

# Plot data
plot = ax.imshow(data)


# Create colorbar
cbar = plt.colorbar(plot)
cbar_ticks = np.linspace(0., 1., num=6, endpoint=True)
cbar.set_ticks(cbar_ticks)

plt.show(block=False)

def update():

    new_data   = 2.*np.random.rand(10, 10)

    plot.set_data(new_data)
    cbar.set_clim(vmin=0,vmax=2)
    cbar_ticks = np.linspace(0., 2., num=11, endpoint=True)
    cbar.set_ticks(cbar_ticks) 
    cbar.draw_all() 
    plt.draw()

    plt.show()

update()
person ImportanceOfBeingErnest    schedule 06.12.2016
comment
Фактический сценарий, который я изменяю, довольно сложен и имеет графики в полярных координатах. Я бы предпочел не трогать это. Может imshow иметь дело с полярными координатами? - person Sebastian; 06.12.2016
comment
Нет, не напрямую, нужно было бы вручную преобразовать данные, чтобы они поместились в прямоугольную сетку. Может быть, можно будет удалить и перерисовать шкалу палитры? (Я недавно ответил на вопрос об этом) - person ImportanceOfBeingErnest; 06.12.2016
comment
Это работает. Благодарить. Но знаете ли вы, почему обновление палитры работает при использовании imshow, но не для contourf? - person Sebastian; 06.12.2016
comment
@Sebastian Обновление шкалы палитры будет работать с любым типом сюжета. Проблема в том, что невозможно обновить contour. В тот момент, когда вы удаляете и воссоздаете contour, исходный cbar теряет связь с contour и, следовательно, не может быть обновлен должным образом. Для других графиков, таких как imshow, этой проблемы не существует, поскольку вы можете обновить базовые данные. На самом деле я не уверен, нет ли способа восстановить связь между cbar и вновь созданным contour - я просто не знаю ни о каком. - person ImportanceOfBeingErnest; 06.12.2016

Обновлено Я обновил свой ответ на основе ваших комментариев и этого ответа. Ссылка

Это то, что вы пытаетесь сделать?

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(111)

# Random data
data = np.random.rand(10, 10)

# Plot data
levels = np.linspace(0., 1., 100)
plot = ax.contourf(data, levels=levels)

# Create colorbar
cbar = plt.colorbar(plot)
cbar_ticks = np.linspace(0., 1., num=6, endpoint=True)
cbar.ax.set_autoscale_on(True)
cbar.set_ticks(cbar_ticks)

plt.show(block=False)

def update():
    global cbar

    cbar.remove()
    fig.clear()

    # Create new data and plot
    new_data   = 2.*np.random.rand(10, 10)
    new_levels = np.linspace(0., 2., 200)
    ax = fig.add_subplot(111)
    plot = ax.contourf(new_data, levels=new_levels )

    cbar = plt.colorbar(plot)
    cbar_ticks = np.linspace(0., 2., num=21, endpoint=True)
    cbar.set_ticks(cbar_ticks)    
    plt.draw()

update()
person J.Serra    schedule 06.12.2016
comment
Не совсем. Это отнимает у сюжета место. См. Обходной путь от @ImportanceOfBeingErnest. - person Sebastian; 06.12.2016
comment
@ J.Serra Хотя в principe можно удалить и добавить шкалу палитры, на самом деле она оказывается немного сложнее, как показано в этот вопрос. - person ImportanceOfBeingErnest; 06.12.2016