Skip to content

Instantly share code, notes, and snippets.

@tacaswell
Last active August 11, 2026 21:53
Show Gist options
  • Select an option

  • Save tacaswell/3144287 to your computer and use it in GitHub Desktop.

Select an option

Save tacaswell/3144287 to your computer and use it in GitHub Desktop.
factory for adding zoom callback to matplotlib graphs
import matplotlib.pyplot as plt
def zoom_factory(ax,base_scale = 2.):
def zoom_fun(event):
# get the current x and y limits
cur_xlim = ax.get_xlim()
cur_ylim = ax.get_ylim()
# set the range
cur_xrange = (cur_xlim[1] - cur_xlim[0])*.5
cur_yrange = (cur_ylim[1] - cur_ylim[0])*.5
xdata = event.xdata # get event x location
ydata = event.ydata # get event y location
if event.button == 'up':
# deal with zoom in
scale_factor = 1/base_scale
elif event.button == 'down':
# deal with zoom out
scale_factor = base_scale
else:
# deal with something that should never happen
scale_factor = 1
print event.button
# set new limits
ax.set_xlim([xdata - cur_xrange*scale_factor,
xdata + cur_xrange*scale_factor])
ax.set_ylim([ydata - cur_yrange*scale_factor,
ydata + cur_yrange*scale_factor])
ax.figure.canvas.draw_idle() # force re-draw the next time the GUI refreshes
fig = ax.get_figure() # get the figure of interest
# attach the call back
fig.canvas.mpl_connect('scroll_event',zoom_fun)
#return the function
return zoom_fun
@ozsolarwind

Copy link
Copy Markdown

This may help.
You do the plot, call zoom_factory, then show the plot:

fig = `plt.figure(...
graph = fig.add_subplot(111)
graph.plot(...
zf = zoom_factory(graph)
plt.show()

I've been using it quite happily but my code is a bit too specific but derived from simp_zoom.py

@tacaswell

Copy link
Copy Markdown
Author

@mapfiable Interesting, I also did not know that existing until you pointed it out! The reason for the re-inversion is that you can invert the axis by setting the "min" to be greater than the "max" and inside of axis.zoom (which calls Locator.zoom) the inversion is discarded.

@mapfiable

Copy link
Copy Markdown

@tacaswell: do you think it is a good alternative? There is also Axis.pan, but I didn't manage to make it work properly.

@Khirod1999

Copy link
Copy Markdown

Can we implement this code in jupyter Notebook?
If yes, please explain.

@tacaswell

Copy link
Copy Markdown
Author

Yes, but you must use either %matplotlib notebook or %matplotlib widget which should "just work". If you are using %matplotlib inline it will not work (because that is not an interactive backend).

@ianhi

ianhi commented Jun 17, 2020

Copy link
Copy Markdown

There's a small caveat to "just working" in the notebook - the widget backend doesn't have an option capture scroll events so you will end up scrolling the entire notebook while also zooming:
gif

The workaround I used for this was to to use jupyterlab sidecar widget to display the plot as that won't have a scroll bar so it doesn't matter that the scroll input wasn't captured. Long term - I opened an issue and PR about this matplotlib/ipympl#222 that I think would fix this.
Also I think you will need to install the widget backend (https://github.com/matplotlib/ipympl#installation) as that isn't included with standard matplotlib

@tacaswell

Copy link
Copy Markdown
Author

That is a fun bug! I left a review on your PR at ipympl.

@ianhi

ianhi commented Jun 18, 2020

Copy link
Copy Markdown

Thanks!

For completeness for any future readers: The fix for scrolling in the notebook was merged and should be part of any release of ipympl after 0.5.6 (it is not in that release)

@peroman200

peroman200 commented Feb 9, 2021

Copy link
Copy Markdown

Hey, I tried to implement this in a wxPython Frame, but I keep getting a TypeError: zoom_fun() missing 1 required positional argument: 'event'. I know how to solve missing events in wxPython, but not in matplotlib. It should work because otherwise I wouldn't be getting the error on scrolling...
Edit: Turns out there is a work around, that only works if you're also pressing down the mouse wheel, not just scrolling with it...

@tacaswell

Copy link
Copy Markdown
Author

@peroman200 Interesting, can you still reproduce that issue in mpl3.4?

@hrieke

hrieke commented Dec 29, 2022

Copy link
Copy Markdown

License for your code?
Thanks

@QuLogic

QuLogic commented Aug 11, 2026

Copy link
Copy Markdown

Note that this is implemented directly (using Control+scroll) in Matplotlib as of 3.11: matplotlib/matplotlib#30405

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment