Matplotlib forces pan / zoom to constrain the x axis

Matplotlib has a function where, if you hold down the x or y keys, it limits the pan or zoom of the corresponding axis.

Is there a way to do this by default? For some reason, my CPU does not allow the touchpad to be moved when a letter key is held down. And I want the x axis to be pan / zoom, not the y axis.


edit: found the pan / zoom function in https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes.py#L3001

which contains the internal function format_deltas . But I have no idea how to override the Axes class with a subclass when Axes objects are created automatically from Figure objects.

+4
source share
2 answers

You can use your own axis class. In your case, you can inherit from matplotlib.axes.Axes and change the drag_pan method to always act as if the "x" key was pressed. However, scaling does not appear to be defined in this class. The following will only allow x-axis panning:

 import matplotlib import matplotlib.pyplot as plt class My_Axes(matplotlib.axes.Axes): name = "My_Axes" def drag_pan(self, button, key, x, y): matplotlib.axes.Axes.drag_pan(self, button, 'x', x, y) # pretend key=='x' matplotlib.projections.register_projection(My_Axes) figure = plt.figure() ax = figure.add_subplot(111, projection="My_Axes") ax.plot([0, 1, 2], [0, 1, 0]) plt.show() 

To scale, you may need to look at the toolbar control. The NavigationToolbar2 class has a drag_zoom method that seems to matter here, but tracking how this works is quickly complicated by the fact that different backends have their own versions (e.g. NavigationToolbar2TkAgg

change

You can monkeypatch desired behavior in:

 import types def press_zoom(self, event): event.key='x' matplotlib.backends.backend_tkagg.NavigationToolbar2TkAgg.press_zoom(self,event) figure.canvas.toolbar.press_zoom=types.MethodType(press_zoom, figure.canvas.toolbar) 

You can do it right and subclass the toolbar, but then you need to instantiate the Figure, FigureCanvas and your NavigationToolbar and put them in a Tk application or something like that. I don’t think there is a very simple way to just use your own toolbar with a simple build interface.

+6
source
The simonb approach worked, but I needed to configure it for the press_zoom behavior, so it supports the press_zoom method as a class function, not an instance, but I added a hook to fix the behavior of each instance.
 import types def constrainXPanZoomBehavior(fig): # make sure all figures' toolbars of this class call a postPressZoomHandler() def overrideZoomMode(oldZoom, target): def newZoom(self, event): oldZoom(self, event) if hasattr(self, 'postPressZoomHandler'): self.postPressZoomHandler() return newZoom def overrideToolbarZoom(fig, methodname, functransform, *args): toolbar = fig.canvas.toolbar oldMethod = getattr(toolbar.__class__, methodname) newMethod = functransform(oldMethod, toolbar, *args) setattr(toolbar.__class__, methodname, newMethod) overrideToolbarZoom(fig, 'press_zoom', overrideZoomMode) # for this specific instance, override the zoom mode to 'x' always def postPressZoomHandler(self): self._zoom_mode = 'x' fig.canvas.toolbar.postPressZoomHandler = types.MethodType(postPressZoomHandler, fig.canvas.toolbar) return fig 
+2
source

Source: https://habr.com/ru/post/1482304/


All Articles