plt.pause, приводящий к неправильному размещению подзаговора - PullRequest
0 голосов
/ 25 апреля 2019

Я следую этому учебнику, и наткнулся на то, чего я не понимаю.

Идея состоит в том, чтобы иметь функцию, которая строит изображение.Затем эта функция вызывается в цикле, где определены подзаговоры:

минимальный пример

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np    

def show_image(image):
    """Show image"""
    plt.imshow(image)

def show_image_wait(image):
    """show image, and wait a little bit. similar implementation than in the tutorial"""
    plt.imshow(image)
    plt.pause(0.001)

Теперь вызов обеих функций в цикле:
без ожидания:

for i in range(4):
    image = np.random.randint(0,3, (10,10))
    plt.subplot(1, 4, i+1)
    show_image(image)

# expected output: 1 row, with 4 images side by side
# actual output: 1 row, with 4 images, side by side

с ожиданием, однако:

for i in range(4):
    image = np.random.randint(0,3, (10,10))
    plt.subplot(1, 4, i+1)
    show_image_wait(image)

# expected output: 1 row, with 4 images side by side
# actual output: 4 rows, with 1 images each

Функция, подобная show_image_wait, используется в учебном руководстве, указанном выше, где все изображения отображаются в правильном положении.
Я не понимаю, почему ожидание крошечного кусочка отменяет позиционирование субплота в моем случае, а не в связанном примере.

Все это происходит в блокноте Jupyter

Помощь очень ценится!

Ответы [ 2 ]

1 голос
/ 26 апреля 2019

Причина, по которой вы видите несколько строк, заключается в том, что для каждого запуска цикла создается новая фигура.Независимые фигуры располагаются друг над другом в выходной ячейке юпитера.
Это, в свою очередь, вызвано отображением на экране последней итерации цикла, и, следовательно, когда plt.subplot вызывается в другой раз, активная фигура отсутствует -поэтому создается новый.

Основная причина всего этого заключается в том, что plt.pause(..) делает немного больше, чем просто делает паузу.Вместо этого он обрабатывает возможные события на фигуре и в конечном итоге рисует , а показывает фигуру в интерактивном режиме.

Источник plt.pause

manager = _pylab_helpers.Gcf.get_active()
if manager is not None:
    canvas = manager.canvas
    if canvas.figure.stale:
        canvas.draw_idle()
    show(block=False)                 #  <----  here the figure is shown.
    canvas.start_event_loop(interval)
else:
    time.sleep(interval)

, где я пометил критическую строку комментарием.

В общем, если вы хотите истинную паузу, как в «Не делайте ничего в течение x секунд», plt.pauseне очень подходит.В целом также немного сомнительно, насколько это полезно в ноутбуках Jupyter с inline бэкэндом, потому что этот бэкэнд не обеспечивает никакой интерактивности.

1 голос
/ 25 апреля 2019

Я думаю, что это будет работать, если вы используете plt.show() после цикла for, но в ноутбуке JuPyTer, график составляет inline. Обходным решением может быть использование time.sleep(0.001). Вы можете попробовать проверить, служит ли это вашей цели.

%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np    
import time

def show_image_wait(image):
    """show image, and wait a little bit. similar implementation than in the tutorial"""
    plt.imshow(image)
    time.sleep(0.001)

for i in range(4):
    image = np.random.randint(0,3, (10,10))
    plt.subplot(1, 4, i+1)
    show_image_wait(image)    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...