Skip to content

Commit

Permalink
Further refactor axes limits setting.
Browse files Browse the repository at this point in the history
  • Loading branch information
anntzer committed Oct 12, 2017
1 parent 268e955 commit 05e383a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 97 deletions.
55 changes: 38 additions & 17 deletions lib/matplotlib/axes/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2817,15 +2817,33 @@ def get_xlim(self):
"""
return tuple(self.viewLim.intervalx)

def _set_lim(self, axis, low, high, low_name, high_name,
target_obj, target_attr, emit, auto, kw):
"""Helper factoring the functionality of `get_{x,y,z}lim`."""
# Perhaps we can use axis.{get,set}_view_interval()... but zaxis seems
# to behave differently.
_called_from_pan = kw.pop("_called_from_pan", False)
if kw:
raise ValueError("Unrecognized kwargs: {}".format(kw))
axis_name = axis.axis_name
def _set_lim(self, axis, axis_name, low, high, low_name, high_name,
target_obj, target_attr, emit, auto):
"""Helper factoring the functionality of ``set_{x,y,z}lim``.
Parameters
----------
axis : Axis
The target axis.
axis_name : str
The axis name to use in ``get_?lim`` and ``_autoscale?on``. (Not
``axis.axis_name`` because the name of `.RadianAxes` is "radius",
not "r". Not using ``axis.{get,set}_view_interval`` because 3D
axes behave differently.)
low, high :
The first two arguments passed to `set_xlim` (and other
axes). Either both ``Optional[float]``, or a pair of two
``Optional[float]`` and ``None``.
low_name, high_name : str
Names of the "low" and "high" arguments, for generating error
messages.
target_obj, target_attr :
Target object holding the limits. The limits are applied as
``target_obj.target_attr = low, high`` (after default handling,
unit conversion, and validation).
emit, auto :
See docstring of `set_xlim` (etc.).
"""
if high is None and iterable(low):
low, high = low
old_low, old_high = getattr(self, "get_{}lim".format(axis_name))()
Expand All @@ -2836,8 +2854,7 @@ def _set_lim(self, axis, low, high, low_name, high_name,
self._process_unit_info(**{"{}data".format(axis_name): [low, high]})
low, high = map(axis.convert_units, [low, high])
for limit in [low, high]:
if not (_called_from_pan or
np.isreal(limit) and np.isfinite(limit)):
if not (np.isreal(limit) and np.isfinite(limit)):
raise ValueError(
"Axis limits must be (or convert to) finite reals")
if low == high:
Expand Down Expand Up @@ -2928,8 +2945,8 @@ def set_xlim(self, left=None, right=None, emit=True, auto=False, **kw):
left = kw.pop('xmin')
if 'xmax' in kw:
right = kw.pop('xmax')
return self._set_lim(self.xaxis, left, right, "left", "right",
self.viewLim, "intervalx", emit, auto, kw)
return self._set_lim(self.xaxis, "x", left, right, "left", "right",
self.viewLim, "intervalx", emit, auto, **kw)

def get_xscale(self):
return self.xaxis.get_scale()
Expand Down Expand Up @@ -3206,8 +3223,8 @@ def set_ylim(self, bottom=None, top=None, emit=True, auto=False, **kw):
bottom = kw.pop('ymin')
if 'ymax' in kw:
top = kw.pop('ymax')
return self._set_lim(self.yaxis, bottom, top, "bottom", "top",
self.viewLim, "intervaly", emit, auto, kw)
return self._set_lim(self.yaxis, "y", bottom, top, "bottom", "top",
self.viewLim, "intervaly", emit, auto, **kw)

def get_yscale(self):
return self.yaxis.get_scale()
Expand Down Expand Up @@ -3776,8 +3793,12 @@ def format_deltas(key, dx, dy):
warnings.warn('Overflow while panning')
return

self.set_xlim(*result.intervalx, _called_from_pan=True)
self.set_ylim(*result.intervaly, _called_from_pan=True)
valid = np.isfinite(result.transformed(p.trans))
points = result.get_points().astype(object)
# Just ignore invalid limits (typically, underflow in log-scale).
points[~valid] = None
self.set_xlim(points[:, 0])
self.set_ylim(points[:, 1])

@cbook.deprecated("2.1")
def get_cursor_props(self):
Expand Down
86 changes: 6 additions & 80 deletions lib/mpl_toolkits/mplot3d/axes3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,45 +612,8 @@ def set_xlim3d(self, left=None, right=None, emit=True, auto=False, **kw):
left = kw.pop('xmin')
if 'xmax' in kw:
right = kw.pop('xmax')
if kw:
raise ValueError("unrecognized kwargs: %s" % list(kw))

if right is None and cbook.iterable(left):
left, right = left

self._process_unit_info(xdata=(left, right))
left = self._validate_converted_limits(left, self.convert_xunits)
right = self._validate_converted_limits(right, self.convert_xunits)

old_left, old_right = self.get_xlim()
if left is None:
left = old_left
if right is None:
right = old_right

if left == right:
warnings.warn(('Attempting to set identical left==right results\n'
'in singular transformations; automatically expanding.\n'
'left=%s, right=%s') % (left, right))
left, right = mtransforms.nonsingular(left, right, increasing=False)
left, right = self.xaxis.limit_range_for_scale(left, right)
self.xy_viewLim.intervalx = (left, right)

if auto is not None:
self._autoscaleXon = bool(auto)

if emit:
self.callbacks.process('xlim_changed', self)
# Call all of the other x-axes that are shared with this one
for other in self._shared_x_axes.get_siblings(self):
if other is not self:
other.set_xlim(self.xy_viewLim.intervalx,
emit=False, auto=auto)
if (other.figure != self.figure and
other.figure.canvas is not None):
other.figure.canvas.draw_idle()
self.stale = True
return left, right
return self._set_lim(self.xaxis, "x", left, right, "left", "right",
self.xy_viewLim, "intervalx", emit, auto, **kw)
set_xlim = set_xlim3d

def set_ylim3d(self, bottom=None, top=None, emit=True, auto=False, **kw):
Expand All @@ -664,45 +627,8 @@ def set_ylim3d(self, bottom=None, top=None, emit=True, auto=False, **kw):
bottom = kw.pop('ymin')
if 'ymax' in kw:
top = kw.pop('ymax')
if kw:
raise ValueError("unrecognized kwargs: %s" % list(kw))

if top is None and cbook.iterable(bottom):
bottom, top = bottom

self._process_unit_info(ydata=(bottom, top))
bottom = self._validate_converted_limits(bottom, self.convert_yunits)
top = self._validate_converted_limits(top, self.convert_yunits)

old_bottom, old_top = self.get_ylim()
if bottom is None:
bottom = old_bottom
if top is None:
top = old_top

if top == bottom:
warnings.warn(('Attempting to set identical bottom==top results\n'
'in singular transformations; automatically expanding.\n'
'bottom=%s, top=%s') % (bottom, top))
bottom, top = mtransforms.nonsingular(bottom, top, increasing=False)
bottom, top = self.yaxis.limit_range_for_scale(bottom, top)
self.xy_viewLim.intervaly = (bottom, top)

if auto is not None:
self._autoscaleYon = bool(auto)

if emit:
self.callbacks.process('ylim_changed', self)
# Call all of the other y-axes that are shared with this one
for other in self._shared_y_axes.get_siblings(self):
if other is not self:
other.set_ylim(self.xy_viewLim.intervaly,
emit=False, auto=auto)
if (other.figure != self.figure and
other.figure.canvas is not None):
other.figure.canvas.draw_idle()
self.stale = True
return bottom, top
return self._set_lim(self.yaxis, "y", bottom, top, "bottom", "top",
self.xy_viewLim, "intervaly", emit, auto, **kw)
set_ylim = set_ylim3d

def set_zlim3d(self, bottom=None, top=None, emit=True, auto=False, **kw):
Expand All @@ -716,8 +642,8 @@ def set_zlim3d(self, bottom=None, top=None, emit=True, auto=False, **kw):
bottom = kw.pop('zmin')
if 'zmax' in kw:
top = kw.pop('zmax')
return self._set_lim(self.zaxis, bottom, top, "bottom", "top",
self.zz_viewLim, "intervalx", emit, auto, kw)
return self._set_lim(self.zaxis, "z", bottom, top, "bottom", "top",
self.zz_viewLim, "intervalx", emit, auto, **kw)
set_zlim = set_zlim3d

def get_xlim3d(self):
Expand Down

0 comments on commit 05e383a

Please sign in to comment.