Увеличение или панорамирование matplotlib замедляется, если на холст добавляется ax.text или ax.anotate - PullRequest
0 голосов
/ 13 апреля 2020

Сводка об ошибках

Масштабирование и панорамирование работают должным образом (быстро), если на рисунке присутствуют только линии или маркеры, после добавления ax.text или ax.annotate это становится очень медленный. Я намерен использовать этот код как минимум для 3000 текста и 1000 строк и перемещаться по холсту в GUI (PySimple GUI). Мой опыт программирования невелик, поэтому может быть так, как написан класс, что и является причиной этого. Фрагмент кода является минимальным примером проблемы.

Код для воспроизведения

class _Zoom_Pan_():

    def __init__(self, fig, ax1, base_scale):
        'Declarar variables'
        self.fig, self.ax1, self.base_scale, self.x_init, self.y_init, = fig, ax1, base_scale, None, None
        "Conectar funcion"
        self._add_connection("button_press_event", self._OnPress_)
        self._add_connection("motion_notify_event", self._OnMotion_)
        self._add_connection("button_release_event", self._OffPress_)
        self._add_connection("scroll_event", self._Zoom_)

    def _add_connection(self, event_name, callback):
        self.fig.canvas.mpl_connect(event_name, callback)

    def Canvas_Draw(self):
        self.fig.canvas.draw_idle()

    def _OnPress_(self, event):
        if event.xdata != None and event.button == 2:
                self. x_init, self.y_init = event.xdata, event.ydata

    def _OnMotion_(self, event):
        if self.x_init != None and event.xdata != None:
            xmin, xmax, ymin, ymax = self.ax1.axis()
            dx, dy = self.x_init - event.xdata, self.y_init - event.ydata
            self.ax1.set(xlim=(xmin + dx, xmax + dx), ylim=(ymin + dy, ymax + dy))
            self.Canvas_Draw()

    def _OffPress_(self, event):
        self.x_init = None

    def _Zoom_(self, event):
        if event.step:
            'Obtener limites de ax1'
            xmin, xmax, ymin, ymax = self.ax1.axis()
            xdata, ydata = event.xdata, event.ydata
            'Obtener factor de escala'
            if event.step < 0:
                scale_factor = 1 / self.base_scale
            if event.step > 0:
                scale_factor = self.base_scale
            'Asignar nuevos limites'
            xmin_new, xmax_new = xdata - (xdata - xmin) / scale_factor, xdata + (xmax - xdata) / scale_factor
            ymin_new, ymax_new = ydata - (ydata - ymin) / scale_factor, ydata + (ymax - ydata) / scale_factor
            self.ax1.set(xlim=(xmin_new, xmax_new), ylim=(ymin_new, ymax_new))
            self.Canvas_Draw()



import matplotlib.pyplot as plt
import numpy as np

"Create data"
count = 1000
data = np.random.rand(1, count)[0]

"plot data"
fig = plt.figure()
ax1 = fig.add_subplot(111, rasterized=True)
for i in range(len(data) - 1):
    ax1.plot([i, i + 1], [data[i], data[i + 1]], rasterized=True, gid='Line' + str(i))
    ax1.annotate('Text', xy=(np.asarray([i, i + 1]).mean(),
                         np.asarray([data[i], data[i + 1]]).mean()),
                 xytext=(np.asarray([i, i + 1]).mean(),
                         np.asarray([data[i], data[i + 1]]).mean()),
                 arrowprops=dict(arrowstyle="->", color='red'),
                 rasterized=True,
                 gid='arrow_' + str(i))

"Apply zoom and pan"
Mpl_func = _Zoom_Pan_(fig, ax1, 2.5)

"Show figure"
plt.show()

Фактический результат

Медленное панорамирование и масштабирование

Ожидаемый результат

Быстрое панорамирование и масштабирование

Версия Matplotlib

  • Эксплуатация система: Windows
  • Версия Matplotlib: 3.1.1
  • Бэкэнд Matplotlib: TkAgg
  • Python Версия: 3.7
  • Другие библиотеки: Использование этого код внутри PySiple GUI Canvas
...