Skip to content

Instantly share code, notes, and snippets.

@ianhi
Forked from tacaswell/simp_zoom.py
Last active October 14, 2020 19:45
Show Gist options
  • Save ianhi/b638e09fa7a00764ea539940a0519af9 to your computer and use it in GitHub Desktop.
Save ianhi/b638e09fa7a00764ea539940a0519af9 to your computer and use it in GitHub Desktop.
factory for adding zoom callback to matplotlib imshow - now available via https://github.com/ianhi/mpl-interactions
import matplotlib.pyplot as plt
def zoom_factory(ax,base_scale = 1.1):
"""
parameters
----------
ax : matplotlib axes object
axis on which to implement scroll to zoom
base_scale : float
how much zoom on each tick of scroll wheel
returns
-------
disconnect_zoom : function
call this to disconnect the scroll listener
"""
def limits_to_range(lim):
return lim[1] - lim[0]
fig = ax.get_figure() # get the figure of interest
toolbar = fig.canvas.toolbar
toolbar.push_current()
orig_xlim = ax.get_xlim()
orig_ylim = ax.get_ylim()
orig_yrange = limits_to_range(orig_ylim)
orig_xrange = limits_to_range(orig_xlim)
orig_center = ((orig_xlim[0]+orig_xlim[1])/2, (orig_ylim[0]+orig_ylim[1])/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 = base_scale
elif event.button == 'down':
# deal with zoom out
scale_factor = 1/base_scale
else:
# deal with something that should never happen
scale_factor = 1
# set new limits
new_xlim = [xdata - (xdata-cur_xlim[0]) / scale_factor,
xdata + (cur_xlim[1]-xdata) / scale_factor]
new_ylim = [ydata - (ydata-cur_ylim[0]) / scale_factor,
ydata + (cur_ylim[1]-ydata) / scale_factor]
new_yrange = limits_to_range(new_ylim)
new_xrange = limits_to_range(new_xlim)
if np.abs(new_yrange)>np.abs(orig_yrange):
new_ylim = orig_center[1] -new_yrange/2 , orig_center[1] +new_yrange/2
if np.abs(new_xrange)>np.abs(orig_xrange):
new_xlim = orig_center[0] -new_xrange/2 , orig_center[0] +new_xrange/2
ax.set_xlim(new_xlim)
ax.set_ylim(new_ylim)
toolbar.push_current()
ax.figure.canvas.draw_idle() # force re-draw
# attach the call back
cid = fig.canvas.mpl_connect('scroll_event',zoom_fun)
def disconnect_zoom():
fig.canvas.mpl_disconnect(cid)
#return the disconnect function
return disconnect_zoom
@ianhi
Copy link
Author

ianhi commented Jul 6, 2020

This fork adds on two things:

  1. Pushes initial position to toolbar so the home button will work
  2. If you zoom out past the initial bounds the image will be centered

@ianhi
Copy link
Author

ianhi commented Jul 6, 2020

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