Как связать оси графиков imshow для масштабирования и панорамирования? - PullRequest
1 голос
/ 27 мая 2010

Предположим, у меня есть рисунок холста с 3 графиками ... 2 - изображения того же размера, нанесенные с помощью imshow, а другой - это какой-то другой вид вспомогательного сюжета. Я хотел бы иметь возможность связать оси x и y графиков imshow, чтобы при увеличении одной из них (используя инструмент масштабирования, предоставленный NavigationToolbar) другие масштабировались с теми же координатами, а когда я перемещался по одной и другие сковороды.

Методы подзаговора, такие как scatter и гистограмма, могут передаваться kwargs, указывая оси для sharex и sharey, но imshow не имеет такой конфигурации.

Я начал взламывать свой путь, используя подкласс NavigationToolbar2WxAgg (показано ниже) ... но здесь есть несколько проблем. 1) Это свяжет оси всех графиков на холсте, так как все, что я сделал, это избавился от проверок для a.in_axes () 2) Это хорошо работало для панорамирования, но при масштабировании все вспомогательные сюжеты увеличивались с одной и той же глобальной точки, а не с одной и той же точки на каждой из их соответствующих осей.

Кто-нибудь может предложить обходной путь?

Большое спасибо! -Adam

from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg
class MyNavToolbar(NavigationToolbar2WxAgg):
    def __init__(self, canvas, cpfig):
        NavigationToolbar2WxAgg.__init__(self, canvas)

    # overrided
    # As mentioned in the code below, the only difference here from overridden
    # method is that this one doesn't check a.in_axes(event) when deciding which
    # axes to start the pan in...
    def press_pan(self, event):
        'the press mouse button in pan/zoom mode callback'

        if event.button == 1:
            self._button_pressed=1
        elif  event.button == 3:
            self._button_pressed=3
        else:
            self._button_pressed=None
            return

        x, y = event.x, event.y

        # push the current view to define home if stack is empty
        if self._views.empty(): self.push_current()

        self._xypress=[]
        for i, a in enumerate(self.canvas.figure.get_axes()):
            # only difference from overridden method is that this one doesn't
            # check a.in_axes(event)
            if x is not None and y is not None and a.get_navigate():
                a.start_pan(x, y, event.button)
                self._xypress.append((a, i))
                self.canvas.mpl_disconnect(self._idDrag)
                self._idDrag=self.canvas.mpl_connect('motion_notify_event', self.drag_pan)

    # overrided
    def press_zoom(self, event):
        'the press mouse button in zoom to rect mode callback'
        if event.button == 1:
            self._button_pressed=1
        elif  event.button == 3:
            self._button_pressed=3
        else:
            self._button_pressed=None
            return

        x, y = event.x, event.y

        # push the current view to define home if stack is empty
        if self._views.empty(): self.push_current()

        self._xypress=[]
        for i, a in enumerate(self.canvas.figure.get_axes()):
            # only difference from overridden method is that this one doesn't
            # check a.in_axes(event) 
            if x is not None and y is not None and a.get_navigate() and a.can_zoom():
                self._xypress.append(( x, y, a, i, a.viewLim.frozen(), a.transData.frozen()))

        self.press(event)

1 Ответ

3 голосов
/ 27 мая 2010

Я не знал, что sharex может быть передан в add_subplot ...

f = plt.figure()
ax1 = f.add_subplot(211)
ax2 = f.add_subplot(212, sharex=ax1, sharey=ax1)
ax1.imshow(np.random.randn(10,10), interpolation='nearest')
ax2.imshow(np.random.randn(10,10), interpolation='nearest')
f.canvas.draw()

однако, если вы попытаетесь сделать следующее, чтобы установить объекты оси для отображения изображений.

ax1.axis('image')

вы получите:

ValueError: adjustable must be "datalim" for shared axes

Ребята из Matplotlib, скажите мне, что я могу использовать

ax1.set_adjustable("box-forced")
ax2.set_adjustable("box-forced")

вместо этого, но он не работает для меня, используя matplotlib версии 0.98.5.3 ... Я предполагаю, что это будет с более новой версией Обновлюсь, когда получу ответ.

...