2010-05-27 20 views
1

Supposons que j'ai une toile avec 3 graphiques ... 2 sont des images de la même dimension tracées avec imshow, et l'autre est une autre sorte de sous-trame. J'aimerais pouvoir lier les axes x et y des tracés imshow de sorte que lorsque j'en zoome un (en utilisant l'outil de zoom fourni par la barre NavigationToolbar), l'autre zoome sur les mêmes coordonnées, et quand je fais un panoramique dans un , les autres casseroles aussi.Comment lier les axes des tracés imshow pour le zoom et le panoramique?

Des méthodes de sous-graphe telles que scatter et histogramme peuvent être passées kwargs en spécifiant un axe pour sharex et sharey, mais imshow n'a pas cette configuration.

J'ai commencé à contourner ce problème en sous-classant NavigationToolbar2WxAgg (illustré ci-dessous) ... mais il y a plusieurs problèmes ici. 1) Ceci reliera les axes de toutes les tracés dans une toile puisque tout ce que j'ai fait est de se débarrasser des vérifications pour a.in_axes() 2) Cela a bien fonctionné pour le panoramique, mais le zoom a fait que tous les sous-plans même point global, plutôt que du même point dans chacun de leurs axes respectifs.

Quelqu'un peut-il suggérer une solution de contournement?

Merci beaucoup! -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) 

Répondre

3

Je ne savais pas sharex pourrait être passé à 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() 

cependant, si vous essayez de faire ce qui suit pour définir vos objets d'axe pour afficher des images.

ax1.axis('image') 

vous obtiendrez:

ValueError: adjustable must be "datalim" for shared axes 

Les gars matplotlib me disent que je peux utiliser

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

à la place, mais il ne fonctionne pas pour moi d'utiliser la version 0.98.5.3 matplotlib ... Je suppose que ce serait avec une version plus récente. Je mettrai à jour quand j'entendrai.