Skip to content

Instantly share code, notes, and snippets.

@tacaswell
Last active February 12, 2023 07:19
Show Gist options
  • Star 16 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save tacaswell/3144287 to your computer and use it in GitHub Desktop.
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
@Zenkai19
Copy link

@ianhi Can you please post an example code in which we zoom a plot. I'm a beginner with matplotlib and can't get to work the function right. Thanks!

@ozsolarwind
Copy link

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
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

@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

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

@tacaswell
Copy link
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
Copy link

ianhi commented Jun 17, 2020

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
Author

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

@ianhi
Copy link

ianhi commented Jun 18, 2020

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
Copy link

peroman200 commented Feb 9, 2021

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
Author

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

@hrieke
Copy link

hrieke commented Dec 29, 2022

License for your code?
Thanks

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