From 74f65263cdfda7f0d84f0ab8cbf9515e10aa107d Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Mon, 12 Jun 2017 07:31:16 -1000 Subject: [PATCH 1/7] Simplify axes and axis clearing, sharing, and aspect ratio control - Most of the unnecessary calls to Axis.cla() have been removed. - Axis sharing works across figures. - The "box-forced" adjustable is no longer needed. - Sharing both axes requires the use of "box", not "datalim". - A new "share" kwarg triggers synchronized setting of aspect ratio and adjustable in Axes within shared axis groups. - Added a test for axis sharing with aspect ratio setting. - Fixed and updated skew_rects test. --- lib/matplotlib/axes/_base.py | 152 +- lib/matplotlib/axis.py | 106 +- lib/matplotlib/scale.py | 9 +- lib/matplotlib/spines.py | 8 +- .../baseline_images/test_skew/skew_rects.pdf | Bin 7470 -> 7923 bytes .../baseline_images/test_skew/skew_rects.png | Bin 31973 -> 22740 bytes .../baseline_images/test_skew/skew_rects.svg | 3118 ++++++++--------- lib/matplotlib/tests/test_axes.py | 42 + lib/matplotlib/tests/test_skew.py | 12 +- 9 files changed, 1750 insertions(+), 1697 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 4462cd620ce6..ac89374f27c8 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -488,25 +488,15 @@ def __init__(self, fig, rect, self._originalPosition = self._position.frozen() # self.set_axes(self) self.axes = self - self.set_aspect('auto') + self._aspect = 'auto' self._adjustable = 'box' - self.set_anchor('C') + self._anchor = 'C' self._sharex = sharex self._sharey = sharey if sharex is not None: self._shared_x_axes.join(self, sharex) - if sharex._adjustable == 'box': - sharex._adjustable = 'datalim' - # warnings.warn( - # 'shared axes: "adjustable" is being changed to "datalim"') - self._adjustable = 'datalim' if sharey is not None: self._shared_y_axes.join(self, sharey) - if sharey._adjustable == 'box': - sharey._adjustable = 'datalim' - # warnings.warn( - # 'shared axes: "adjustable" is being changed to "datalim"') - self._adjustable = 'datalim' self.set_label(label) self.set_figure(fig) @@ -537,7 +527,11 @@ def __init__(self, fig, rect, self._hold = True self._connected = {} # a dict from events to (id, func) - self.cla() + try: + self.cla(clear_axis=False) # new xaxis and yaxis are already cleared + except TypeError: + self.cla() # For Axes subclasses lacking clear_axis argument. + # funcs used to format x and y - fall back on major formatters self.fmt_xdata = None self.fmt_ydata = None @@ -607,11 +601,11 @@ def get_window_extent(self, *args, **kwargs): def _init_axis(self): "move this out of __init__ because non-separable axes don't use it" self.xaxis = maxis.XAxis(self) - self.spines['bottom'].register_axis(self.xaxis) - self.spines['top'].register_axis(self.xaxis) + self.spines['bottom'].register_axis(self.xaxis, clear_axis=False) + self.spines['top'].register_axis(self.xaxis, clear_axis=False) self.yaxis = maxis.YAxis(self) - self.spines['left'].register_axis(self.yaxis) - self.spines['right'].register_axis(self.yaxis) + self.spines['left'].register_axis(self.yaxis, clear_axis=False) + self.spines['right'].register_axis(self.yaxis, clear_axis=False) self._update_transScale() def set_figure(self, fig): @@ -634,8 +628,7 @@ def set_figure(self, fig): def _set_lim_and_transforms(self): """ - set the *dataLim* and *viewLim* - :class:`~matplotlib.transforms.Bbox` attributes and the + set the *_xaxis_transform*, *_yaxis_transform*, *transScale*, *transData*, *transLimits* and *transAxes* transformations. @@ -952,7 +945,7 @@ def _gen_axes_spines(self, locations=None, offset=0.0, units='inches'): ('bottom', mspines.Spine.linear_spine(self, 'bottom')), ('top', mspines.Spine.linear_spine(self, 'top'))]) - def cla(self): + def cla(self, clear_axis=True): """Clear the current axes.""" # Note: this is called by Axes.__init__() @@ -965,51 +958,46 @@ def cla(self): xaxis_visible = self.xaxis.get_visible() yaxis_visible = self.yaxis.get_visible() - self.xaxis.cla() - self.yaxis.cla() + # The axis cla() sets the scale and default locators and + # formatters. It needs to know if the axis is shared + # so that it can preserve the shared scale. + shared_x = self._sharex.xaxis if self._sharex else None + shared_y = self._sharey.yaxis if self._sharey else None + + if clear_axis: + self.xaxis.cla(shared_x) + self.yaxis.cla(shared_y) # + for name, spine in six.iteritems(self.spines): - spine.cla() + spine.cla(clear_axis=False) # Clears only the position. self.ignore_existing_data_limits = True self.callbacks = cbook.CallbackRegistry() - if self._sharex is not None: - # major and minor are class instances with + if shared_x is not None: + # major and minor are axis.Ticker class instances with # locator and formatter attributes - self.xaxis.major = self._sharex.xaxis.major - self.xaxis.minor = self._sharex.xaxis.minor + self.xaxis.major = shared_x.major + self.xaxis.minor = shared_x.minor x0, x1 = self._sharex.get_xlim() self.set_xlim(x0, x1, emit=False, auto=None) - self.xaxis._scale = mscale.scale_factory( - self._sharex.xaxis.get_scale(), self.xaxis) else: - self.xaxis._set_scale('linear') try: self.set_xlim(0, 1) except TypeError: pass - if self._sharey is not None: - self.yaxis.major = self._sharey.yaxis.major - self.yaxis.minor = self._sharey.yaxis.minor + if shared_y is not None: + self.yaxis.major = shared_y.major + self.yaxis.minor = shared_y.minor y0, y1 = self._sharey.get_ylim() self.set_ylim(y0, y1, emit=False, auto=None) - self.yaxis._scale = mscale.scale_factory( - self._sharey.yaxis.get_scale(), self.yaxis) else: - self.yaxis._set_scale('linear') try: self.set_ylim(0, 1) except TypeError: pass - # update the minor locator for x and y axis based on rcParams - if (rcParams['xtick.minor.visible']): - self.xaxis.set_minor_locator(mticker.AutoMinorLocator()) - - if (rcParams['ytick.minor.visible']): - self.yaxis.set_minor_locator(mticker.AutoMinorLocator()) - self._autoscaleXon = True self._autoscaleYon = True self._xmargin = rcParams['axes.xmargin'] @@ -1093,6 +1081,14 @@ def cla(self): self.yaxis.set_visible(yaxis_visible) self.patch.set_visible(patch_visible) + # It is not clear to me (EF) why this reset is needed here, but + # it does seem to be needed somewhere in this vicinity. Otherwise, + # setting tick rotation via set_params doesn't work until the + # first draw has occurred. + self.xaxis.reset_ticks() + self.yaxis.reset_ticks() + + self.stale = True @cbook.deprecated("2.1", alternative="Axes.patch") @@ -1224,7 +1220,7 @@ def hold(self, b=None): def get_aspect(self): return self._aspect - def set_aspect(self, aspect, adjustable=None, anchor=None): + def set_aspect(self, aspect, adjustable=None, anchor=None, share=False): """ *aspect* @@ -1245,12 +1241,9 @@ def set_aspect(self, aspect, adjustable=None, anchor=None): ============ ===================================== 'box' change physical size of axes 'datalim' change xlim or ylim - 'box-forced' same as 'box', but axes can be shared ============ ===================================== - 'box' does not allow axes sharing, as this can cause - unintended side effect. For cases when sharing axes is - fine, use 'box-forced'. + When both axes are shared, only 'box' is allowable. *anchor* @@ -1270,8 +1263,17 @@ def set_aspect(self, aspect, adjustable=None, anchor=None): else: self._aspect = float(aspect) # raise ValueError if necessary - if adjustable is not None: - self.set_adjustable(adjustable) + if share and self in self._shared_x_axes: + for ax in self._shared_x_axes.get_siblings(self): + ax._aspect = aspect + if share and self in self._shared_y_axes: + for ax in self._shared_y_axes.get_siblings(self): + ax._aspect = aspect + + if adjustable is None: + adjustable = self._adjustable + self.set_adjustable(adjustable, share=share) # Always call this to handle sharing. + if anchor is not None: self.set_anchor(anchor) self.stale = True @@ -1279,15 +1281,22 @@ def set_aspect(self, aspect, adjustable=None, anchor=None): def get_adjustable(self): return self._adjustable - def set_adjustable(self, adjustable): + def set_adjustable(self, adjustable, share=False): """ - ACCEPTS: [ 'box' | 'datalim' | 'box-forced'] + ACCEPTS: [ 'box' | 'datalim'] """ + # FIXME: add box-forced deprecation if adjustable in ('box', 'datalim', 'box-forced'): - if self in self._shared_x_axes or self in self._shared_y_axes: - if adjustable == 'box': + if self in self._shared_x_axes and self in self._shared_y_axes: + if adjustable == 'datalim': raise ValueError( - 'adjustable must be "datalim" for shared axes') + 'adjustable must be "box" when both axes are shared') + if share and self in self._shared_x_axes: + for ax in self._shared_x_axes.get_siblings(self): + ax._adjustable = adjustable + if share and self in self._shared_y_axes: + for ax in self._shared_y_axes.get_siblings(self): + ax._adjustable = adjustable self._adjustable = adjustable else: raise ValueError('argument must be "box", or "datalim"') @@ -1387,14 +1396,6 @@ def apply_aspect(self, position=None): else: A = aspect - # Ensure at drawing time that any Axes involved in axis-sharing - # does not have its position changed. - if self in self._shared_x_axes or self in self._shared_y_axes: - if self._adjustable == 'box': - self._adjustable = 'datalim' - warnings.warn( - 'shared axes: "adjustable" is being changed to "datalim"') - figW, figH = self.get_figure().get_size_inches() fig_aspect = figH / figW if self._adjustable in ['box', 'box-forced']: @@ -1452,15 +1453,15 @@ def apply_aspect(self, position=None): xm = 0 ym = 0 - changex = (self in self._shared_y_axes and - self not in self._shared_x_axes) - changey = (self in self._shared_x_axes and - self not in self._shared_y_axes) - if changex and changey: - warnings.warn("adjustable='datalim' cannot work with shared " - "x and y axes") - return - if changex: + shared_x = self in self._shared_x_axes + shared_y = self in self._shared_y_axes + # Not sure whether we need this check: + if shared_x and shared_y: + raise RuntimeError("adjustable='datalim' is not allowed when both" + " axes are shared.") + + # If y is shared, then we are only allowed to change x, etc. + if shared_y: adjust_y = False else: if xmarg > xm and ymarg > ym: @@ -1468,7 +1469,8 @@ def apply_aspect(self, position=None): (Xmarg < 0 and y_expander > 0)) else: adjy = y_expander > 0 - adjust_y = changey or adjy # (Ymarg > xmarg) + adjust_y = shared_x or adjy # (Ymarg > xmarg) + if adjust_y: yc = 0.5 * (ymin + ymax) y0 = yc - Ysize / 2.0 @@ -3977,9 +3979,9 @@ def twiny(self): return ax2 def get_shared_x_axes(self): - 'Return a copy of the shared axes Grouper object for x axes' + 'Return a reference to the shared axes Grouper object for x axes' return self._shared_x_axes def get_shared_y_axes(self): - 'Return a copy of the shared axes Grouper object for y axes' + 'Return a reference to the shared axes Grouper object for y axes' return self._shared_y_axes diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 870c5e8f6f72..15ffd47626f1 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -82,6 +82,10 @@ def __init__(self, axes, loc, label, label2On=False, major=True, labelrotation=0, + grid_color=None, + grid_linestyle=None, + grid_linewidth=None, + grid_alpha=None, ): """ bbox is the Bound2D bounding box in display coords of the Axes @@ -149,6 +153,15 @@ def __init__(self, axes, loc, label, zorder = mlines.Line2D.zorder self._zorder = zorder + self._grid_color = (rcParams['grid.color'] + if grid_color is None else grid_color) + self._grid_linestyle = (rcParams['grid.linestyle'] + if grid_linestyle is None else grid_linestyle) + self._grid_linewidth = (rcParams['grid.linewidth'] + if grid_linewidth is None else grid_linewidth) + self._grid_alpha = (rcParams['grid.alpha'] + if grid_alpha is None else grid_alpha) + self.apply_tickdir(tickdir) self.tick1line = self._get_tick1line() @@ -344,6 +357,15 @@ def _apply_params(self, **kw): v = getattr(self.label1, 'get_' + k)() setattr(self, '_label' + k, v) + grid_list = [k for k in six.iteritems(kw) + if k[0] in ['grid_color', 'grid_linestyle', + 'grid_linewidth', 'grid_alpha']] + if grid_list: + grid_kw = {k[5:]: v for k, v in grid_list} + self.gridline.set(**grid_kw) + for k, v in six.iteritems(grid_kw): + setattr(self, '_grid_' + k, v) + def update_position(self, loc): 'Set the location of tick in data coords with scalar *loc*' raise NotImplementedError('Derived must override') @@ -445,10 +467,10 @@ def _get_gridline(self): 'Get the default line2D instance' # x in data coords, y in axes coords l = mlines.Line2D(xdata=(0.0, 0.0), ydata=(0, 1.0), - color=rcParams['grid.color'], - linestyle=rcParams['grid.linestyle'], - linewidth=rcParams['grid.linewidth'], - alpha=rcParams['grid.alpha'], + color=self._grid_color, + linestyle=self._grid_linestyle, + linewidth=self._grid_linewidth, + alpha=self._grid_alpha, markersize=0) l.set_transform(self.axes.get_xaxis_transform(which='grid')) l.get_path()._interpolation_steps = GRIDLINE_INTERPOLATION_STEPS @@ -568,10 +590,10 @@ def _get_gridline(self): 'Get the default line2D instance' # x in axes coords, y in data coords l = mlines.Line2D(xdata=(0, 1), ydata=(0, 0), - color=rcParams['grid.color'], - linestyle=rcParams['grid.linestyle'], - linewidth=rcParams['grid.linewidth'], - alpha=rcParams['grid.alpha'], + color=self._grid_color, + linestyle=self._grid_linestyle, + linewidth=self._grid_linewidth, + alpha=self._grid_alpha, markersize=0) l.set_transform(self.axes.get_yaxis_transform(which='grid')) @@ -626,13 +648,6 @@ def __init__(self, axes, pickradius=15): artist.Artist.__init__(self) self.set_figure(axes.figure) - # Keep track of setting to the default value, this allows use to know - # if any of the following values is explicitly set by the user, so as - # to not overwrite their settings with any of our 'auto' settings. - self.isDefault_majloc = True - self.isDefault_minloc = True - self.isDefault_majfmt = True - self.isDefault_minfmt = True self.isDefault_label = True self.axes = axes @@ -656,7 +671,6 @@ def __init__(self, axes, pickradius=15): self._minor_tick_kw = dict() self.cla() - self._set_scale('linear') def set_label_coords(self, x, y, transform=None): """ @@ -719,24 +733,17 @@ def get_children(self): children.extend(minorticks) return children - def cla(self): + def cla(self, shared=None): 'clear the current axis' - self.set_major_locator(mticker.AutoLocator()) - self.set_major_formatter(mticker.ScalarFormatter()) - self.set_minor_locator(mticker.NullLocator()) - self.set_minor_formatter(mticker.NullFormatter()) - self.set_label_text('') - self._set_artist_props(self.label) + self.label.set_text('') # self.set_label_text would change isDefault_ + self._set_artist_props(self.label) # sets figure; needed here? - # Keep track of setting to the default value, this allows use to know - # if any of the following values is explicitly set by the user, so as - # to not overwrite their settings with any of our 'auto' settings. - self.isDefault_majloc = True - self.isDefault_minloc = True - self.isDefault_majfmt = True - self.isDefault_minfmt = True - self.isDefault_label = True + if shared is None: + self._set_scale('linear') + else: + name = shared.get_scale() + self._scale = mscale.scale_factory(name, self) # Clear the callback registry for this axis, or it may "leak" self.callbacks = cbook.CallbackRegistry() @@ -747,9 +754,6 @@ def cla(self): self._gridOnMinor = (rcParams['axes.grid'] and rcParams['axes.grid.which'] in ('both', 'minor')) - self.label.set_text('') - self._set_artist_props(self.label) - self.reset_ticks() self.converter = None @@ -769,6 +773,11 @@ def reset_ticks(self): self._lastNumMajorTicks = 1 self._lastNumMinorTicks = 1 + try: + self.set_clip_path(self.axes.patch) + except AttributeError: + pass + def set_tick_params(self, which='major', reset=False, **kw): """ Set appearance parameters for ticks and ticklabels. @@ -786,8 +795,10 @@ def set_tick_params(self, which='major', reset=False, **kw): if reset: d.clear() d.update(kwtrans) + if reset: self.reset_ticks() + # Is this "else" correct? Shouldn't kwargs be applied after a reset? else: if which == 'major' or which == 'both': for tick in self.majorTicks: @@ -809,7 +820,9 @@ def _translate_tick_kw(kw, to_init_kw=True): kwkeys1 = ['length', 'direction', 'left', 'bottom', 'right', 'top', 'labelleft', 'labelbottom', 'labelright', 'labeltop', 'rotation'] - kwkeys = kwkeys0 + kwkeys1 + kwkeys2 = ['grid_color', 'grid_linestyle', 'grid_linewidth', + 'grid_alpha'] + kwkeys = kwkeys0 + kwkeys1 + kwkeys2 kwtrans = dict() if to_init_kw: if 'length' in kw: @@ -951,7 +964,7 @@ def _update_ticks(self, renderer): """ interval = self.get_view_interval() - tick_tups = list(self.iter_ticks()) + tick_tups = list(self.iter_ticks()) # iter_ticks calls the locator if self._smart_bounds and tick_tups: # handle inverted limits view_low, view_high = sorted(interval) @@ -1376,30 +1389,21 @@ def grid(self, b=None, which='major', **kwargs): if len(kwargs): b = True which = which.lower() + gridkw = {'grid_' + item[0]: item[1] for item in kwargs.items()} if which in ['minor', 'both']: if b is None: self._gridOnMinor = not self._gridOnMinor else: self._gridOnMinor = b - for tick in self.minorTicks: # don't use get_ticks here! - if tick is None: - continue - tick.gridOn = self._gridOnMinor - if len(kwargs): - tick.gridline.update(kwargs) - self._minor_tick_kw['gridOn'] = self._gridOnMinor + self.set_tick_params(which='minor', gridOn=self._gridOnMinor, + **gridkw) if which in ['major', 'both']: if b is None: self._gridOnMajor = not self._gridOnMajor else: self._gridOnMajor = b - for tick in self.majorTicks: # don't use get_ticks here! - if tick is None: - continue - tick.gridOn = self._gridOnMajor - if len(kwargs): - tick.gridline.update(kwargs) - self._major_tick_kw['gridOn'] = self._gridOnMajor + self.set_tick_params(which='major', gridOn=self._gridOnMajor, + **gridkw) self.stale = True def update_units(self, data): @@ -1429,11 +1433,11 @@ def _update_axisinfo(self): check the axis converter for the stored units to see if the axis info needs to be updated """ - if self.converter is None: return info = self.converter.axisinfo(self.units, self) + if info is None: return if info.majloc is not None and \ diff --git a/lib/matplotlib/scale.py b/lib/matplotlib/scale.py index 29a38b6663c2..b4971d454ad2 100644 --- a/lib/matplotlib/scale.py +++ b/lib/matplotlib/scale.py @@ -10,9 +10,10 @@ from matplotlib.ticker import (NullFormatter, ScalarFormatter, LogFormatterSciNotation, LogitFormatter) from matplotlib.ticker import (NullLocator, LogLocator, AutoLocator, + AutoMinorLocator, SymmetricalLogLocator, LogitLocator) from matplotlib.transforms import Transform, IdentityTransform -from matplotlib import docstring +from matplotlib import docstring, rcParams class ScaleBase(object): @@ -73,8 +74,12 @@ def set_default_locators_and_formatters(self, axis): """ axis.set_major_locator(AutoLocator()) axis.set_major_formatter(ScalarFormatter()) - axis.set_minor_locator(NullLocator()) axis.set_minor_formatter(NullFormatter()) + # update the minor locator for x and y axis based on rcParams + if (rcParams['xtick.minor.visible']): + axis.set_minor_locator(AutoMinorLocator()) + else: + axis.set_minor_locator(NullLocator()) def get_transform(self): """ diff --git a/lib/matplotlib/spines.py b/lib/matplotlib/spines.py index c6b04fe43dba..de5c294ad856 100644 --- a/lib/matplotlib/spines.py +++ b/lib/matplotlib/spines.py @@ -151,7 +151,7 @@ def _ensure_position_is_set(self): self._position = ('outward', 0.0) # in points self.set_position(self._position) - def register_axis(self, axis): + def register_axis(self, axis, clear_axis=True): """register an axis An axis should be registered with its corresponding spine from @@ -159,14 +159,14 @@ def register_axis(self, axis): properties when needed. """ self.axis = axis - if self.axis is not None: + if clear_axis and self.axis is not None: self.axis.cla() self.stale = True - def cla(self): + def cla(self, clear_axis=True): """Clear the current spine""" self._position = None # clear position - if self.axis is not None: + if clear_axis and self.axis is not None: self.axis.cla() def is_frame_like(self): diff --git a/lib/matplotlib/tests/baseline_images/test_skew/skew_rects.pdf b/lib/matplotlib/tests/baseline_images/test_skew/skew_rects.pdf index 209842345b463aa2c0030d50488ac46e4b7a266a..c16fc9c2d916904dc79b2fbd5743088668183f08 100644 GIT binary patch literal 7923 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
_m1wt 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 diff --git a/lib/matplotlib/tests/baseline_images/test_skew/skew_rects.svg b/lib/matplotlib/tests/baseline_images/test_skew/skew_rects.svg index 668efde6a8ad..ff18e2b4df0b 100644 --- a/lib/matplotlib/tests/baseline_images/test_skew/skew_rects.svg +++ b/lib/matplotlib/tests/baseline_images/test_skew/skew_rects.svg @@ -2,7 +2,7 @@ - + - - - - - - - @@ -60,188 +60,188 @@ L 230.4 86.4 +" id="m368fc901b1" style="stroke:#000000;stroke-width:0.5;"/> - + +" id="mc63e59a608" style="stroke:#000000;stroke-width:0.5;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + - + + + + - + - + - + - + - - - + - - - - + - - - - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -249,209 +249,209 @@ L -4 0 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -459,209 +459,209 @@ L 460.8 86.4 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -669,209 +669,209 @@ L 691.2 86.4 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -879,209 +879,209 @@ L 921.6 86.4 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1089,209 +1089,209 @@ L 1152 86.4 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1299,209 +1299,209 @@ L 230.4 247.282759 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1509,209 +1509,209 @@ L 460.8 247.282759 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1719,209 +1719,209 @@ L 691.2 247.282759 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -1929,209 +1929,209 @@ L 921.6 247.282759 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -2139,209 +2139,209 @@ L 1152 247.282759 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -2349,209 +2349,209 @@ L 230.4 408.165517 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -2559,209 +2559,209 @@ L 460.8 408.165517 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -2769,209 +2769,209 @@ L 691.2 408.165517 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -2979,209 +2979,209 @@ L 921.6 408.165517 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -3189,209 +3189,209 @@ L 1152 408.165517 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -3399,209 +3399,209 @@ L 230.4 569.048276 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -3609,209 +3609,209 @@ L 460.8 569.048276 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -3819,209 +3819,209 @@ L 691.2 569.048276 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -4029,209 +4029,209 @@ L 921.6 569.048276 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -4239,209 +4239,209 @@ L 1152 569.048276 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -4449,209 +4449,209 @@ L 230.4 729.931034 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -4659,209 +4659,209 @@ L 460.8 729.931034 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -4869,209 +4869,209 @@ L 691.2 729.931034 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -5079,209 +5079,209 @@ L 921.6 729.931034 - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -5289,80 +5289,80 @@ L 1152 729.931034 - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index f1cc67fde7a4..87c97956aaed 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -4220,6 +4220,48 @@ def test_empty_shared_subplots(): assert y1 >= 6 +def test_shared_with_aspect(): + # allow sharing one axis + for adjustable in ['box', 'datalim']: + fig, axes = plt.subplots(nrows=2, sharex=True) + axes[0].set_aspect(2, adjustable=adjustable, share=True) + assert axes[1].get_aspect() == 2 + assert axes[1].get_adjustable() == adjustable + + fig, axes = plt.subplots(nrows=2, sharex=True) + axes[0].set_aspect(2, adjustable=adjustable) + assert axes[1].get_aspect() == 'auto' + + # Share 2 axes only with 'box': + fig, axes = plt.subplots(nrows=2, sharex=True, sharey=True) + axes[0].set_aspect(2, share=True) + axes[0].plot([1, 2], [3, 4]) + axes[1].plot([3, 4], [1, 2]) + plt.draw() # Trigger apply_aspect(). + assert axes[0].get_xlim() == axes[1].get_xlim() + assert axes[0].get_ylim() == axes[1].get_ylim() + with pytest.raises(ValueError): + axes[0].set_aspect(1, adjustable='datalim', share=True) + + # Different aspect ratios: + for adjustable in ['box', 'datalim']: + fig, axes = plt.subplots(nrows=2, sharey=True) + axes[0].set_aspect(2, adjustable=adjustable) + axes[1].set_aspect(0.5, adjustable=adjustable) + axes[0].plot([1, 2], [3, 4]) + axes[1].plot([3, 4], [1, 2]) + plt.draw() # Trigger apply_aspect(). + assert axes[0].get_xlim() != axes[1].get_xlim() + assert axes[0].get_ylim() == axes[1].get_ylim() + fig_aspect = fig.bbox_inches.height / fig.bbox_inches.width + for ax in axes: + p = ax.get_position() + box_aspect = p.height / p.width + lim_aspect = ax.viewLim.height / ax.viewLim.width + expected = fig_aspect * box_aspect / lim_aspect + assert round(expected, 4) == round(ax.get_aspect(), 4) + + def test_relim_visible_only(): x1 = (0., 10.) y1 = (0., 10.) diff --git a/lib/matplotlib/tests/test_skew.py b/lib/matplotlib/tests/test_skew.py index 79cb75c2c273..a80d3cdaf002 100644 --- a/lib/matplotlib/tests/test_skew.py +++ b/lib/matplotlib/tests/test_skew.py @@ -189,16 +189,16 @@ def test_set_line_coll_dash_image(): @image_comparison(baseline_images=['skew_rects'], remove_text=True) -def test_skew_rectange(): +def test_skew_rectangle(): - fix, axes = plt.subplots(5, 5, sharex=True, sharey=True, figsize=(16, 12)) + fix, axes = plt.subplots(5, 5, sharex=True, sharey=True, figsize=(8, 8)) axes = axes.flat rotations = list(itertools.product([-3, -1, 0, 1, 3], repeat=2)) - axes[0].set_xlim([-4, 4]) - axes[0].set_ylim([-4, 4]) - axes[0].set_aspect('equal') + axes[0].set_xlim([-3, 3]) + axes[0].set_ylim([-3, 3]) + axes[0].set_aspect('equal', share=True) for ax, (xrots, yrots) in zip(axes, rotations): xdeg, ydeg = 45 * xrots, 45 * yrots @@ -209,4 +209,4 @@ def test_skew_rectange(): transform=t + ax.transData, alpha=0.5, facecolor='coral')) - plt.subplots_adjust(wspace=0, left=0, right=1, bottom=0) + plt.subplots_adjust(wspace=0, left=0.01, right=0.99, bottom=0.01, top=0.99) From 2de8089cd98c16409e0a3ef877b2fed6fdeeb659 Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Tue, 13 Jun 2017 08:20:26 -1000 Subject: [PATCH 2/7] Fix PEP8 errors --- lib/matplotlib/axes/_base.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index ac89374f27c8..39f1da6ad522 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -528,7 +528,7 @@ def __init__(self, fig, rect, self._connected = {} # a dict from events to (id, func) try: - self.cla(clear_axis=False) # new xaxis and yaxis are already cleared + self.cla(clear_axis=False) # new xaxis, yaxis are already cleared except TypeError: self.cla() # For Axes subclasses lacking clear_axis argument. @@ -1088,7 +1088,6 @@ def cla(self, clear_axis=True): self.xaxis.reset_ticks() self.yaxis.reset_ticks() - self.stale = True @cbook.deprecated("2.1", alternative="Axes.patch") @@ -1272,7 +1271,7 @@ def set_aspect(self, aspect, adjustable=None, anchor=None, share=False): if adjustable is None: adjustable = self._adjustable - self.set_adjustable(adjustable, share=share) # Always call this to handle sharing. + self.set_adjustable(adjustable, share=share) # Handle sharing. if anchor is not None: self.set_anchor(anchor) From 748c759f6f8963aea98568631d3645a8ac0d19f3 Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Thu, 15 Jun 2017 16:49:33 -0400 Subject: [PATCH 3/7] Minor fixups from qlogic review --- lib/matplotlib/axes/_base.py | 2 +- lib/matplotlib/axis.py | 4 +--- lib/matplotlib/scale.py | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index 39f1da6ad522..b0f0484430a6 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -966,7 +966,7 @@ def cla(self, clear_axis=True): if clear_axis: self.xaxis.cla(shared_x) - self.yaxis.cla(shared_y) # + self.yaxis.cla(shared_y) for name, spine in six.iteritems(self.spines): spine.cla(clear_axis=False) # Clears only the position. diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 15ffd47626f1..70db796c287a 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -160,7 +160,7 @@ def __init__(self, axes, loc, label, self._grid_linewidth = (rcParams['grid.linewidth'] if grid_linewidth is None else grid_linewidth) self._grid_alpha = (rcParams['grid.alpha'] - if grid_alpha is None else grid_alpha) + if grid_alpha is None else grid_alpha) self.apply_tickdir(tickdir) @@ -737,7 +737,6 @@ def cla(self, shared=None): 'clear the current axis' self.label.set_text('') # self.set_label_text would change isDefault_ - self._set_artist_props(self.label) # sets figure; needed here? if shared is None: self._set_scale('linear') @@ -798,7 +797,6 @@ def set_tick_params(self, which='major', reset=False, **kw): if reset: self.reset_ticks() - # Is this "else" correct? Shouldn't kwargs be applied after a reset? else: if which == 'major' or which == 'both': for tick in self.majorTicks: diff --git a/lib/matplotlib/scale.py b/lib/matplotlib/scale.py index b4971d454ad2..e1df53b97a04 100644 --- a/lib/matplotlib/scale.py +++ b/lib/matplotlib/scale.py @@ -76,7 +76,7 @@ def set_default_locators_and_formatters(self, axis): axis.set_major_formatter(ScalarFormatter()) axis.set_minor_formatter(NullFormatter()) # update the minor locator for x and y axis based on rcParams - if (rcParams['xtick.minor.visible']): + if rcParams['xtick.minor.visible']: axis.set_minor_locator(AutoMinorLocator()) else: axis.set_minor_locator(NullLocator()) From bff7e12f7e3b9f8feafc590bfd155a982889ca2f Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Thu, 15 Jun 2017 17:50:28 -0400 Subject: [PATCH 4/7] Single extra space removed to placate PEP 8. --- lib/matplotlib/tests/test_axes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 87c97956aaed..0eb0271fe5f9 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -4259,7 +4259,7 @@ def test_shared_with_aspect(): box_aspect = p.height / p.width lim_aspect = ax.viewLim.height / ax.viewLim.width expected = fig_aspect * box_aspect / lim_aspect - assert round(expected, 4) == round(ax.get_aspect(), 4) + assert round(expected, 4) == round(ax.get_aspect(), 4) def test_relim_visible_only(): From f493ac3db8d8aead809048e4527528b90c4372aa Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Fri, 16 Jun 2017 13:12:04 -0400 Subject: [PATCH 5/7] Handle all Line2D properties for gridlines. This is required for consistency with the present grid() documentation and behavior, but the list of allowed properties should be trimmed. --- lib/matplotlib/axis.py | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 70db796c287a..67d75a31770a 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -24,6 +24,13 @@ GRIDLINE_INTERPOLATION_STEPS = 180 +# This list is being used for compatibility with Axes.grid, which +# allows all Line2D kwargs. +_line_AI = artist.ArtistInspector(mlines.Line2D) +_line_param_names = _line_AI.get_setters() +_line_param_aliases = [list(d.keys())[0] for d in _line_AI.aliasd.values()] +_gridline_param_names = ['grid_' + name + for name in _line_param_names + _line_param_aliases] class Tick(artist.Artist): """ @@ -86,6 +93,7 @@ def __init__(self, axes, loc, label, grid_linestyle=None, grid_linewidth=None, grid_alpha=None, + **kw # Other Line2D kwargs applied to gridlines. ): """ bbox is the Bound2D bounding box in display coords of the Axes @@ -162,6 +170,8 @@ def __init__(self, axes, loc, label, self._grid_alpha = (rcParams['grid.alpha'] if grid_alpha is None else grid_alpha) + self._grid_kw = {k[5:]:v for k, v in kw.items()} + self.apply_tickdir(tickdir) self.tick1line = self._get_tick1line() @@ -358,8 +368,7 @@ def _apply_params(self, **kw): setattr(self, '_label' + k, v) grid_list = [k for k in six.iteritems(kw) - if k[0] in ['grid_color', 'grid_linestyle', - 'grid_linewidth', 'grid_alpha']] + if k[0] in _gridline_param_names] if grid_list: grid_kw = {k[5:]: v for k, v in grid_list} self.gridline.set(**grid_kw) @@ -471,7 +480,8 @@ def _get_gridline(self): linestyle=self._grid_linestyle, linewidth=self._grid_linewidth, alpha=self._grid_alpha, - markersize=0) + markersize=0, + **self._grid_kw) l.set_transform(self.axes.get_xaxis_transform(which='grid')) l.get_path()._interpolation_steps = GRIDLINE_INTERPOLATION_STEPS self._set_artist_props(l) @@ -594,8 +604,8 @@ def _get_gridline(self): linestyle=self._grid_linestyle, linewidth=self._grid_linewidth, alpha=self._grid_alpha, - markersize=0) - + markersize=0, + **self._grid_kw) l.set_transform(self.axes.get_yaxis_transform(which='grid')) l.get_path()._interpolation_steps = GRIDLINE_INTERPOLATION_STEPS self._set_artist_props(l) @@ -761,9 +771,11 @@ def cla(self, shared=None): self.stale = True def reset_ticks(self): - # build a few default ticks; grow as necessary later; only - # define 1 so properties set on ticks will be copied as they - # grow + """ + Re-initialize the major and minor Tick lists. + + Each list starts with a single fresh Tick. + """ del self.majorTicks[:] del self.minorTicks[:] @@ -818,8 +830,7 @@ def _translate_tick_kw(kw, to_init_kw=True): kwkeys1 = ['length', 'direction', 'left', 'bottom', 'right', 'top', 'labelleft', 'labelbottom', 'labelright', 'labeltop', 'rotation'] - kwkeys2 = ['grid_color', 'grid_linestyle', 'grid_linewidth', - 'grid_alpha'] + kwkeys2 = _gridline_param_names kwkeys = kwkeys0 + kwkeys1 + kwkeys2 kwtrans = dict() if to_init_kw: From d575d60170be77d372a18a0343910b2f5f56cb10 Mon Sep 17 00:00:00 2001 From: Eric Firing Date: Fri, 16 Jun 2017 13:33:39 -0400 Subject: [PATCH 6/7] PEP 8 again --- lib/matplotlib/axis.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index 67d75a31770a..91930dd9611a 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -28,10 +28,11 @@ # allows all Line2D kwargs. _line_AI = artist.ArtistInspector(mlines.Line2D) _line_param_names = _line_AI.get_setters() -_line_param_aliases = [list(d.keys())[0] for d in _line_AI.aliasd.values()] +_line_param_aliases = [list(d.keys())[0] for d in _line_AI.aliasd.values()] _gridline_param_names = ['grid_' + name for name in _line_param_names + _line_param_aliases] + class Tick(artist.Artist): """ Abstract base class for the axis ticks, grid lines and labels @@ -170,7 +171,7 @@ def __init__(self, axes, loc, label, self._grid_alpha = (rcParams['grid.alpha'] if grid_alpha is None else grid_alpha) - self._grid_kw = {k[5:]:v for k, v in kw.items()} + self._grid_kw = {k[5:]: v for k, v in kw.items()} self.apply_tickdir(tickdir) From 7dba6868b10a722b37f7ba0d1fc119d9b8a233de Mon Sep 17 00:00:00 2001 From: Thomas A Caswell Date: Sun, 2 Jul 2017 18:49:46 -0400 Subject: [PATCH 7/7] API: re-allow 'datalim' as a valid adjustable with shared axes This is to allow twinx and twiny to work as expected. --- lib/matplotlib/axes/_base.py | 9 ++++----- lib/matplotlib/tests/test_axes.py | 13 +++++++++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index b0f0484430a6..674f56639e5a 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -438,7 +438,7 @@ def __init__(self, fig, rect, ================ ========================================= Keyword Description ================ ========================================= - *adjustable* [ 'box' | 'datalim' | 'box-forced'] + *adjustable* [ 'box' | 'datalim' ] *alpha* float: the alpha transparency (can be None) *anchor* [ 'C', 'SW', 'S', 'SE', 'E', 'NE', 'N', 'NW', 'W' ] @@ -1286,10 +1286,6 @@ def set_adjustable(self, adjustable, share=False): """ # FIXME: add box-forced deprecation if adjustable in ('box', 'datalim', 'box-forced'): - if self in self._shared_x_axes and self in self._shared_y_axes: - if adjustable == 'datalim': - raise ValueError( - 'adjustable must be "box" when both axes are shared') if share and self in self._shared_x_axes: for ax in self._shared_x_axes.get_siblings(self): ax._adjustable = adjustable @@ -3916,6 +3912,9 @@ def _make_twin_axes(self, *kl, **kwargs): make a twinx axes of self. This is used for twinx and twiny. """ ax2 = self.figure.add_axes(self.get_position(True), *kl, **kwargs) + # do not touch every thing shared, just this and it's twin. + self.set_adjustable('datalim') + ax2.set_adjustable('datalim') return ax2 def twinx(self): diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 0eb0271fe5f9..14ef9f04fdbe 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -4240,8 +4240,6 @@ def test_shared_with_aspect(): plt.draw() # Trigger apply_aspect(). assert axes[0].get_xlim() == axes[1].get_xlim() assert axes[0].get_ylim() == axes[1].get_ylim() - with pytest.raises(ValueError): - axes[0].set_aspect(1, adjustable='datalim', share=True) # Different aspect ratios: for adjustable in ['box', 'datalim']: @@ -4262,6 +4260,17 @@ def test_shared_with_aspect(): assert round(expected, 4) == round(ax.get_aspect(), 4) +@pytest.mark.parametrize('twin', ('x', 'y')) +def test_twin_with_aspect(twin): + fig, ax = plt.subplots() + # test twinx or twiny + ax_twin = getattr(ax, 'twin{}'.format(twin))() + ax.set_aspect(5) + ax_twin.set_aspect(2) + assert_array_equal(ax.bbox.extents, + ax_twin.bbox.extents) + + def test_relim_visible_only(): x1 = (0., 10.) y1 = (0., 10.)