Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2f3b2ca

Browse files
committed
Merge pull request #4970 from ordirules/master
Fixed ZoomPanBase to work with log plots
2 parents d771fa7 + 3e4f696 commit 2f3b2ca

File tree

2 files changed

+73
-30
lines changed

2 files changed

+73
-30
lines changed

lib/matplotlib/axes/_base.py

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -487,14 +487,14 @@ def __init__(self, fig, rect,
487487
self._shared_x_axes.join(self, sharex)
488488
if sharex._adjustable == 'box':
489489
sharex._adjustable = 'datalim'
490-
#warnings.warn(
490+
# warnings.warn(
491491
# 'shared axes: "adjustable" is being changed to "datalim"')
492492
self._adjustable = 'datalim'
493493
if sharey is not None:
494494
self._shared_y_axes.join(self, sharey)
495495
if sharey._adjustable == 'box':
496496
sharey._adjustable = 'datalim'
497-
#warnings.warn(
497+
# warnings.warn(
498498
# 'shared axes: "adjustable" is being changed to "datalim"')
499499
self._adjustable = 'datalim'
500500
self.set_label(label)
@@ -1003,11 +1003,11 @@ def cla(self):
10031003

10041004
self.grid(False) # Disable grid on init to use rcParameter
10051005
self.grid(self._gridOn, which=rcParams['axes.grid.which'],
1006-
axis=rcParams['axes.grid.axis'])
1006+
axis=rcParams['axes.grid.axis'])
10071007
props = font_manager.FontProperties(
1008-
size=rcParams['axes.titlesize'],
1009-
weight=rcParams['axes.titleweight']
1010-
)
1008+
size=rcParams['axes.titlesize'],
1009+
weight=rcParams['axes.titleweight']
1010+
)
10111011

10121012
self.titleOffsetTrans = mtransforms.ScaledTranslation(
10131013
0.0, 5.0 / 72.0, self.figure.dpi_scale_trans)
@@ -1122,7 +1122,7 @@ def set_color_cycle(self, clist):
11221122
.. deprecated:: 1.5
11231123
"""
11241124
cbook.warn_deprecated(
1125-
'1.5', name='set_color_cycle', alternative='set_prop_cycle')
1125+
'1.5', name='set_color_cycle', alternative='set_prop_cycle')
11261126
self.set_prop_cycle('color', clist)
11271127

11281128
def ishold(self):
@@ -3323,8 +3323,12 @@ def _set_view_from_bbox(self, bbox, direction='in',
33233323
Parameters
33243324
----------
33253325
3326-
bbox : tuple
3327-
The selected bounding box limits, in *display* coordinates.
3326+
bbox : 4-tuple or 3 tuple
3327+
* If bbox is a 4 tuple, it is the selected bounding box limits,
3328+
in *display* coordinates.
3329+
* If bbox is a 3 tuple, it is an (xp, yp, scl) triple, where
3330+
(xp,yp) is the center of zooming and scl the scale factor to
3331+
zoom by.
33283332
33293333
direction : str
33303334
The direction to apply the bounding box.
@@ -3343,15 +3347,52 @@ def _set_view_from_bbox(self, bbox, direction='in',
33433347
twiny : bool
33443348
Whether this axis is twinned in the *y*-direction.
33453349
"""
3350+
Xmin, Xmax = self.get_xlim()
3351+
Ymin, Ymax = self.get_ylim()
3352+
3353+
if len(bbox) == 3:
3354+
# Zooming code
3355+
xp, yp, scl = bbox
3356+
3357+
# Should not happen
3358+
if scl == 0:
3359+
scl = 1.
33463360

3361+
# direction = 'in'
3362+
if scl > 1:
3363+
direction = 'in'
3364+
else:
3365+
direction = 'out'
3366+
scl = 1/scl
3367+
3368+
# get the limits of the axes
3369+
tranD2C = self.transData.transform
3370+
xmin, ymin = tranD2C((Xmin, Ymin))
3371+
xmax, ymax = tranD2C((Xmax, Ymax))
3372+
3373+
# set the range
3374+
xwidth = xmax - xmin
3375+
ywidth = ymax - ymin
3376+
xcen = (xmax + xmin)*.5
3377+
ycen = (ymax + ymin)*.5
3378+
xzc = (xp*(scl - 1) + xcen)/scl
3379+
yzc = (yp*(scl - 1) + ycen)/scl
3380+
3381+
bbox = [xzc - xwidth/2./scl, yzc - ywidth/2./scl,
3382+
xzc + xwidth/2./scl, yzc + ywidth/2./scl]
3383+
elif len(bbox) != 4:
3384+
# should be len 3 or 4 but nothing else
3385+
warnings.warn('Warning in _set_view_from_bbox: bounding box is not a\
3386+
tuple of length 3 or 4. Ignoring the view change...')
3387+
return
3388+
3389+
# Just grab bounding box
33473390
lastx, lasty, x, y = bbox
33483391

33493392
# zoom to rect
33503393
inverse = self.transData.inverted()
33513394
lastx, lasty = inverse.transform_point((lastx, lasty))
33523395
x, y = inverse.transform_point((x, y))
3353-
Xmin, Xmax = self.get_xlim()
3354-
Ymin, Ymax = self.get_ylim()
33553396

33563397
if twinx:
33573398
x0, x1 = Xmin, Xmax

lib/matplotlib/backend_tools.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
from matplotlib._pylab_helpers import Gcf
1717
import matplotlib.cbook as cbook
1818
from weakref import WeakKeyDictionary
19-
import numpy as np
2019
from matplotlib.externals import six
20+
import time
2121
import warnings
2222

2323

@@ -74,8 +74,8 @@ class ToolBase(object):
7474

7575
def __init__(self, toolmanager, name):
7676
warnings.warn('Treat the new Tool classes introduced in v1.5 as ' +
77-
'experimental for now, the API will likely change in ' +
78-
'version 2.1, and some tools might change name')
77+
'experimental for now, the API will likely change in ' +
78+
'version 2.1, and some tools might change name')
7979
self._name = name
8080
self._figure = None
8181
self.toolmanager = toolmanager
@@ -599,6 +599,8 @@ def __init__(self, *args):
599599
self._idRelease = None
600600
self._idScroll = None
601601
self.base_scale = 2.
602+
self.scrollthresh = .5 # .5 second scroll threshold
603+
self.lastscroll = time.time()-self.scrollthresh
602604

603605
def enable(self, event):
604606
"""Connect press/release events and lock the canvas"""
@@ -626,30 +628,30 @@ def scroll_zoom(self, event):
626628
# https://gist.github.com/tacaswell/3144287
627629
if event.inaxes is None:
628630
return
629-
ax = event.inaxes
630-
cur_xlim = ax.get_xlim()
631-
cur_ylim = ax.get_ylim()
632-
# set the range
633-
cur_xrange = (cur_xlim[1] - cur_xlim[0])*.5
634-
cur_yrange = (cur_ylim[1] - cur_ylim[0])*.5
635-
xdata = event.xdata # get event x location
636-
ydata = event.ydata # get event y location
631+
637632
if event.button == 'up':
638633
# deal with zoom in
639-
scale_factor = 1 / self.base_scale
634+
scl = self.base_scale
640635
elif event.button == 'down':
641636
# deal with zoom out
642-
scale_factor = self.base_scale
637+
scl = 1/self.base_scale
643638
else:
644639
# deal with something that should never happen
645-
scale_factor = 1
646-
# set new limits
647-
ax.set_xlim([xdata - cur_xrange*scale_factor,
648-
xdata + cur_xrange*scale_factor])
649-
ax.set_ylim([ydata - cur_yrange*scale_factor,
650-
ydata + cur_yrange*scale_factor])
640+
scl = 1
641+
642+
ax = event.inaxes
643+
ax._set_view_from_bbox([event.x, event.y, scl])
644+
645+
# If last scroll was done within the timing threshold, delete the
646+
# previous view
647+
if (time.time()-self.lastscroll) < self.scrollthresh:
648+
self.toolmanager.get_tool(_views_positions).back()
649+
651650
self.figure.canvas.draw_idle() # force re-draw
652651

652+
self.lastscroll = time.time()
653+
self.toolmanager.get_tool(_views_positions).push_current()
654+
653655

654656
class ToolZoom(ZoomPanBase):
655657
"""Zoom to rectangle"""

0 commit comments

Comments
 (0)