Pan/Zoom Function in matplotlib

Hi all !
I am working on another package, called wxmplot, which permits to quicky plot figures with wxpython. The package is available here, that I forked from newville. We have the Zoom-to-rectangle mode activated by default and I would like to add the Pan/Zoom function also.
I already created the items to do that, like this on the baseframe.py file:

    MenuItem(self, mopts, "Zoom\tCtrl+R",
             "Going back to Zoom if Pan previously activated",
             self.panel.add_cursor_mode('zoom',
             motion = self.panel.zoom_motion,
             leftdown = self.panel.zoom_leftdown,
             leftup   = self.panel.zoom_leftup))
    
MenuItem(self, mopts, "Pan\tCtrl+W", "Pan",self.panel.unzoom)

with the last parameter is the function to call. Currently, I put some random function but I would like to add a function pan for the Pan item. And also I would like pushing Ctrl-X or Ctrl-Y will permit to zoom only on X or Y. Also, if we activate the Pan button, we can pan on the figure, and if we push on Ctrl-X or Ctrl-Y, we can pan only on X or Y.
It’s my first contribution to a package, so I am not really good with that. Can you help me ?
What I added is in the branch Antoine_Kristanek
Cheers,

Hi ! I found this code:

import wx
import random
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar

import matplotlib.pyplot as plt

class p1(wx.Panel):
    def __init__(self, parent):
         wx.Panel.__init__( self , parent)
         self .figure  = plt.figure()
         self .canvas  = FigureCanvas( self , - 1 ,  self .figure)
         self .toolbar  = NavigationToolbar( self .canvas)
         self .toolbar.Hide()

     def plot( self ):
         ''' plot some random stuff '''
         data  = [random.random()  for i  in range ( 25 )]
         ax  = self .figure.add_subplot( 111 )
         ax.hold( False )
         ax.plot(data,  '*-' )
         self .canvas.draw()    
        
class TestFrame(wx.Frame):
     def __init__( self ,parent,title):
         wx.Frame.__init__( self ,parent,title = title,size = ( 650 , 600 ), 
                           style = wx.MINIMIZE_BOX|wx.SYSTEM_MENU|
                           wx.CAPTION|wx.CLOSE_BOX|wx.CLIP_CHILDREN)
         self .sp  = wx.SplitterWindow( self )
         self .p1  = p1( self .sp)
         self .p2  = wx.Panel( self .sp,style = wx.SUNKEN_BORDER)
         self .sp.SplitHorizontally( self .p1, self .p2, 470 )

         self .statusbar  = self .CreateStatusBar()
         self .statusbar.SetStatusText( "Wow" )
         self .plotbut  = wx.Button( self .p2, - 1 , "plot" , size = ( 40 , 20 ),pos = ( 160 , 10 ))
         self .plotbut.Bind(wx.EVT_BUTTON, self .plot)
         self .sibut  = wx.Button( self .p2, - 1 , "Zoom" , size = ( 40 , 20 ),
                                               pos = ( 60 , 10 ))
         self .sibut.Bind(wx.EVT_BUTTON, self .zoom)
         self .hmbut  = wx.Button( self .p2, - 1 , "Home" , size = ( 40 , 20 ),
                                                 pos = ( 110 , 10))
         self .hmbut.Bind(wx.EVT_BUTTON, self .home)
         self .hibut  = wx.Button( self .p2, - 1 , "Pan" , size = ( 40 , 20 ),pos = ( 10 , 10 ))
         self .hibut.Bind(wx.EVT_BUTTON, self .pan)

     def zoom( self ,event):
         self .statusbar.SetStatusText( "Zoom" )
         self .p1.toolbar.zoom()

     def home( self ,event):
         self .statusbar.SetStatusText( "Home" )
         self .p1.toolbar.home()

     def pan( self ,event):
         self .statusbar.SetStatusText( "Pan" )
         self .p1.toolbar.pan()

     def plot( self ,event):
         self .p1.plot()       

app  = wx.App(redirect = False )
frame  = TestFrame( None , "Matplotlib and WxPython with Pan/Zoom functionality" )
frame.Show()
app.MainLoop()

Which permits to use these functions. Particularly I founf that we can use the pan and zoom function with from the self.toolbar defined like that:

self .canvas  = FigureCanvas( self , - 1 ,  self .figure)
self .toolbar  = NavigationToolbar( self .canvas)
self .toolbar.Hide() 

I would like to use self.toolbar.zoom and self.toolbar.pan without creating a other figure.
How do you think that I can do that ?

I am not sure I understand your question.

If you are looking for help contributing to wxmplot its self I suggest opening an issue at https://github.com/newville/wxmplot

If you are embedding in a larger GUI I suggest you do not use pyplot at all and manage the life cycle of Figures your self. See the Wx examples in https://matplotlib.org/gallery/index.html#embedding-matplotlib-in-graphical-user-interfaces In particular https://matplotlib.org/gallery/user_interfaces/embedding_in_wx5_sgskip.html shows how to create the toolbar.

If you want to use the built in pan/zoom logic, but attach it to a different toolbar, I suggest sub-classing https://github.com/matplotlib/matplotlib/blob/ac0bd8f4462e2036b802d6c3ae0b8d5d7a85a6d6/lib/matplotlib/backend_bases.py#L2618 similar to https://github.com/matplotlib/matplotlib/blob/ac0bd8f4462e2036b802d6c3ae0b8d5d7a85a6d6/lib/matplotlib/backends/backend_wx.py#L1122

What I am doing is trying to use pan/zoom function from matplotlib in wxmplot.
I have already discussed with the creator of this package, who told that I can add the pan function and zoom in x or in y only.
I found the way to do that, doing:
self.toolbar = NavigationToolbar(self.panel.canvas)
self.toolbar.Hide()
self.toolbar.pan()
with self.panel.canvas a attribute. But I have some problems, the y axis doesn’t really update its values. And if I have different figures on a frame, I can pan/zoom only on the first figure.

This question should go to Sign in to GitHub · GitHub

That’s what I did, but I need to go forward, so i try to ask questions in this forum too.

I succeeded to use pan function from the matplotlib toolbar in wxmplot, but there is a problem when there are multiple graphs, on one frame. It works in the first graph but in the others. Do you know how I can do that ?