Как установитьлоту_открытия для графиков matplotlib после show()

Моя настройка:

Debian Linux 8.3 amd64, XMonad WM, python2.7, matplotlib 1.5.1

Проблема:

Я делаю сюжет, например:

import matplotlib.pyplot as plt

x = xrange(10)
y1 = [i ** 2 for i in x]
y2 = [1.0 / (i + 1) for i in x]

fig = plt.figure()
ax1 = plt.subplot(1, 2, 1)
ax1.plot(x, y1)
ax2 = plt.subplot(1, 2, 2)
ax2.plot(x, y2)

plt.show()

и так как я использую оконный менеджер тайлинга, окно matplotlib растягивается до тайла. К сожалению, это делает графики маленькими и несколько рыхлыми.

Если я хочу немного "затянуть" его, щелкнув "Настроить субплоты->Tight Layout", я сделаю это. Но это означает, что мне приходится каждый раз нажимать на значок, а затем на кнопку, и, поскольку я использую этот график для отображения данных тестирования и запуска его очень часто, это довольно раздражает. Поэтому я попробовал несколько вещей, чтобы сделать это проще:

Что я пробовал:

  • призвание plt.tight_layout() до show():

    ...
    ax2.plot(x, y2)
    
    plt.tight_layout()
    plt.show()
    
  • добавление обработчика нажатия клавиш (так что я бы просто нажал "t"):

    ...
    ax2.plot(x, y2)
    
    def kbd_handler(event):
        if event.key == 't':
            plt.tight_layout()
    
    plt.gcf().canvas.mpl_connect('key_press_event', kbd_handler)
    plt.show()
    
  • призвание tight_layout на рисунке:

    ax2.plot(x, y2)
    
    fig.tight_layout()
    plt.show()
    

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

Что я подозреваю:

Я полагаю, что проблема связана с изменением размера, которое, вероятно, происходит после создания окна, поэтому tighten_layout работает с оригинальными размерами окна. Когда Window Manager изменяет размеры окна, макет сохраняет размеры подзаговоров, и у меня получается "свободный" макет с миниатюрными графиками.

Вопрос

Есть ли способ автоматически (или очень легко - как с помощью key_press_event)сжать макет, даже если размер окна изменяется сразу после вызова plt.show()?

1 ответ

Решение

Вы можете достичь желаемого с помощью обработки событий Matplotlib. Просто напишите небольшую функцию, которая вызывает tight_layout и обновляет фигуру каждый раз, когда фигура изменяется:

from matplotlib import pyplot as plt
import numpy as np

x = np.linspace(0,np.pi,100)
y1 = np.sin(x)
y2 = np.cos(x)
fig, (ax1,ax2) = plt.subplots(nrows=1, ncols=2)
fig.tight_layout()
ax1.plot(x,y1)
ax2.plot(x,y2)

def on_resize(event):
    fig.tight_layout()
    fig.canvas.draw()

cid = fig.canvas.mpl_connect('resize_event', on_resize)

plt.show()

Конечно, есть небольшая вероятность того, что это зависит от системы или версии. Я проверил приведенный выше пример на MacOS Sierra с Python 3.5.4 (Matplotlib 2.0.2) и с Python 2.7.14 (Matplotlib 2.1.0). Надеюсь это поможет.

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

На самом деле, я думаю, что ваш обработчик нажатия клавиш сработал бы, если бы вы обновили значение после tight_layoutт.е. если бы вы позвонили fig.canvas.draw(),

Другие вопросы по тегам