Как я могу прикрепить функцию pyplot к экземпляру фигуры?

Раньше у меня была проблема с помехой между несколькими показателями Matplotlib. Наконец, я узнал об этом, что некоторые функции pyplot не прикрепляются к их экземпляру фигуры, но могут быть отображены в некоторых других экземплярах фигур, которые создаются параллельно.

Вот пример кода:

from django.http import HttpResponse
from numpy import arange, meshgrid
from matplotlib.mlab import bivariate_normal

def show_chart(request):
    delta = 0.025
    x = arange(-3.0, 3.0, delta)
    y = arange(-2.0, 2.0, delta)
    X, Y = meshgrid(x, y)
    Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
    Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
    Z = 10.0 * (Z2 - Z1)

    from matplotlib.pyplot import figure, contour
    fig1 = figure(figsize=(4, 4), facecolor='white')
    contour(X, Y, Z)

    response = HttpResponse(content_type='image/png')
    fig1.savefig(response, format='png')
    fig1.clear()
    return response

Функция контура pyplot в приведенном выше примере может быть отображена на рис. 1, но иногда также в некоторой другой фигуре, которая генерируется параллельно. Это очень раздражает. Есть ли способ привязать функцию контурного пистолета к рис. 1?

Ответ 1

Вы можете создать подзаголовок и вызвать метод contour для подзаголовка:

fig1 = figure(figsize=(4, 4), facecolor='white')
ax = fig1.add_subplot(111)
ax.contour(X, Y, Z)

plt.subplots позволяет удобно создавать фигуру и подзаголовки с помощью одного вызова:

import matplotlib.pyplot as plt

fig, ax = plt.subplots()

Ответ 2

В качестве небольшого объяснения того, что здесь происходит, matplotlib имеет два полунезависимых интерфейса; конечный автомат и интерфейс OO.

Код конечного автомата предназначен для работы в интерактивной оболочке (и имитирует интерфейс Matlab). Он делает это, обертывая интерфейс OO в набор команд, которые отслеживают, что такое текущие figure и axes. Когда вы используете команду из matplotlib.pyplot (я подозреваю, что у вас есть from matploblib.pyplot import * в вашем коде), более или менее эквивалентно выполнению gcf().gca().contour(...). Когда вы создаете новую фигуру, она автоматически становится текущей (это то, что вы хотите, если вы используете ее в итеративной оболочке), поэтому поведение, которое вы видите, является "правильным" поведением. Интерфейс конечного автомата также имеет код в нем, чтобы убедиться, что цифры перерисовываются, когда им нужно, управлять циклами gui и т.д. (Все, что вам нужно сделать, чтобы интерактивный интерфейс работал плавно). Как упоминалось в комментариях hayden, запуск ipython --pylab будет автоматически запускаться from matplotlib.pyplot import *, что даст вам очень приятную интерактивную оболочку.

Интерфейс OO предназначен для программирования с matplotlib. Что он добавляет в многословии (теперь вы должны выполнять большую часть работы конечного автомата), это компенсируется ясностью. В модели OO большинство (возможно, все) функций построения привязки связаны с объектами axes (doc) (так как может быть несколько осей, связанных с (ex подзаголовки с помощью gridspec).

Альтернативный способ решить вашу проблему -

ax = fig1.gca()

который будет захватывать текущие оси из fig1, создавая при необходимости. Это может быть полезно, если вы отслеживаете объекты фигуры, но не объекты ваших осей, и хотите добавить еще один график к рисунку.