From 7de868bd2fa2ae6e766acc262233a18dfe5a2a5e Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Tue, 1 Jun 2021 20:04:10 -0600 Subject: [PATCH 1/5] ENH: Make Colorbar inherit from an Axes base class --- lib/matplotlib/colorbar.py | 90 +++++++++++++-------------- lib/matplotlib/tests/test_colorbar.py | 4 +- 2 files changed, 44 insertions(+), 50 deletions(-) diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 6fa03e994b67..3b8c1082b43d 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -310,7 +310,7 @@ def draw(self, renderer): return ret -class ColorbarBase: +class ColorbarBase(ColorbarAxes): r""" Draw a colorbar in an existing axes. @@ -417,9 +417,9 @@ def __init__(self, ax, *, cmap=None, ['uniform', 'proportional'], spacing=spacing) # wrap the axes so that it can be positioned as an inset axes: - ax = ColorbarAxes(ax, userax=userax) - self.ax = ax - ax.set(navigate=False) + super().__init__(ax, userax=userax) + self.ax = self + self.set(navigate=False) if cmap is None: cmap = cm.get_cmap() @@ -448,24 +448,19 @@ def __init__(self, ax, *, cmap=None, self.extendrect = extendrect self.solids = None self.solids_patches = [] - self.lines = [] + # self.lines = [] - for spine in self.ax.spines.values(): + for spine in self.spines.values(): spine.set_visible(False) - for spine in self.ax.outer_ax.spines.values(): + for spine in self.outer_ax.spines.values(): spine.set_visible(False) - self.outline = self.ax.spines['outline'] = _ColorbarSpine(self.ax) - - self.patch = mpatches.Polygon( - np.empty((0, 2)), - color=mpl.rcParams['axes.facecolor'], linewidth=0.01, zorder=-1) - ax.add_artist(self.patch) + self.outline = self.spines['outline'] = _ColorbarSpine(self) self.dividers = collections.LineCollection( [], colors=[mpl.rcParams['axes.edgecolor']], linewidths=[0.5 * mpl.rcParams['axes.linewidth']]) - self.ax.add_collection(self.dividers) + self.add_collection(self.dividers) self.locator = None self.formatter = None @@ -519,8 +514,8 @@ def draw_all(self): # also adds the outline path to self.outline spine: self._do_extends(extendlen) - self.ax.set_xlim(self.vmin, self.vmax) - self.ax.set_ylim(self.vmin, self.vmax) + self.set_xlim(self.vmin, self.vmax) + self.set_ylim(self.vmin, self.vmax) # set up the tick locators and formatters. A bit complicated because # boundary norms + uniform spacing requires a manual locator. @@ -548,7 +543,7 @@ def _add_solids(self, X, Y, C): and any(hatch is not None for hatch in mappable.hatches)): self._add_solids_patches(X, Y, C, mappable) else: - self.solids = self.ax.pcolormesh( + self.solids = self.pcolormesh( X, Y, C, cmap=self.cmap, norm=self.norm, alpha=self.alpha, edgecolors='none', shading='flat') if not self.drawedges: @@ -569,7 +564,7 @@ def _add_solids_patches(self, X, Y, C, mappable): facecolor=self.cmap(self.norm(C[i][0])), hatch=hatches[i], linewidth=0, antialiased=False, alpha=self.alpha) - self.ax.add_patch(patch) + self.add_patch(patch) patches.append(patch) self.solids_patches = patches @@ -605,7 +600,7 @@ def _do_extends(self, extendlen): if self.orientation == 'horizontal': bounds = bounds[[1, 0, 3, 2]] xyout = xyout[:, ::-1] - self.ax._set_inner_bounds(bounds) + self._set_inner_bounds(bounds) # xyout is the path for the spine: self.outline.set_xy(xyout) @@ -634,9 +629,9 @@ def _do_extends(self, extendlen): color = self.cmap(self.norm(self._values[0])) patch = mpatches.PathPatch( mpath.Path(xy), facecolor=color, linewidth=0, - antialiased=False, transform=self.ax.outer_ax.transAxes, + antialiased=False, transform=self.outer_ax.transAxes, hatch=hatches[0]) - self.ax.outer_ax.add_patch(patch) + self.outer_ax.add_patch(patch) if self._extend_upper(): if not self.extendrect: # triangle @@ -651,8 +646,8 @@ def _do_extends(self, extendlen): patch = mpatches.PathPatch( mpath.Path(xy), facecolor=color, linewidth=0, antialiased=False, - transform=self.ax.outer_ax.transAxes, hatch=hatches[-1]) - self.ax.outer_ax.add_patch(patch) + transform=self.outer_ax.transAxes, hatch=hatches[-1]) + self.outer_ax.add_patch(patch) return def add_lines(self, levels, colors, linewidths, erase=True): @@ -699,25 +694,24 @@ def add_lines(self, levels, colors, linewidths, erase=True): # make a clip path that is just a linewidth bigger than the axes... fac = np.max(linewidths) / 72 xy = np.array([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]) - inches = self.ax.get_figure().dpi_scale_trans + inches = self.get_figure().dpi_scale_trans # do in inches: - xy = inches.inverted().transform(self.ax.transAxes.transform(xy)) + xy = inches.inverted().transform(self.transAxes.transform(xy)) xy[[0, 1, 4], 1] -= fac xy[[2, 3], 1] += fac # back to axes units... - xy = self.ax.transAxes.inverted().transform(inches.transform(xy)) + xy = self.transAxes.inverted().transform(inches.transform(xy)) if self.orientation == 'horizontal': xy = xy.T col.set_clip_path(mpath.Path(xy, closed=True), - self.ax.transAxes) - self.ax.add_collection(col) + self.transAxes) + self.add_collection(col) self.stale = True def update_ticks(self): """ Setup the ticks and ticklabels. This should not be needed by users. """ - ax = self.ax # Get the locator and formatter; defaults to self.locator if not None. self._get_ticker_locator_formatter() self._long_axis().set_major_locator(self.locator) @@ -832,7 +826,7 @@ def minorticks_on(self): """ Turn on colorbar minor ticks. """ - self.ax.minorticks_on() + super().minorticks_on() self.minorlocator = self._long_axis().get_minor_locator() self._short_axis().set_minor_locator(ticker.NullLocator()) @@ -863,9 +857,9 @@ def set_label(self, label, *, loc=None, **kwargs): Supported keywords are *labelpad* and `.Text` properties. """ if self.orientation == "vertical": - self.ax.set_ylabel(label, loc=loc, **kwargs) + self.set_ylabel(label, loc=loc, **kwargs) else: - self.ax.set_xlabel(label, loc=loc, **kwargs) + self.set_xlabel(label, loc=loc, **kwargs) self.stale = True def set_alpha(self, alpha): @@ -874,8 +868,8 @@ def set_alpha(self, alpha): def remove(self): """Remove this colorbar from the figure.""" - self.ax.inner_ax.remove() - self.ax.outer_ax.remove() + self.inner_ax.remove() + self.outer_ax.remove() def _ticker(self, locator, formatter): """ @@ -1009,29 +1003,29 @@ def _reset_locator_formatter_scale(self): isinstance(self.norm, colors.BoundaryNorm)): if self.spacing == 'uniform': funcs = (self._forward_boundaries, self._inverse_boundaries) - self.ax.set_xscale('function', functions=funcs) - self.ax.set_yscale('function', functions=funcs) + self.set_xscale('function', functions=funcs) + self.set_yscale('function', functions=funcs) self.__scale = 'function' elif self.spacing == 'proportional': self.__scale = 'linear' - self.ax.set_xscale('linear') - self.ax.set_yscale('linear') + self.set_xscale('linear') + self.set_yscale('linear') elif hasattr(self.norm, '_scale') and self.norm._scale is not None: # use the norm's scale: - self.ax.set_xscale(self.norm._scale) - self.ax.set_yscale(self.norm._scale) + self.set_xscale(self.norm._scale) + self.set_yscale(self.norm._scale) self.__scale = self.norm._scale.name elif type(self.norm) is colors.Normalize: # plain Normalize: - self.ax.set_xscale('linear') - self.ax.set_yscale('linear') + self.set_xscale('linear') + self.set_yscale('linear') self.__scale = 'linear' else: # norm._scale is None or not an attr: derive the scale from # the Norm: funcs = (self.norm, self.norm.inverse) - self.ax.set_xscale('function', functions=funcs) - self.ax.set_yscale('function', functions=funcs) + self.set_xscale('function', functions=funcs) + self.set_yscale('function', functions=funcs) self.__scale = 'function' def _locate(self, x): @@ -1140,14 +1134,14 @@ def _extend_upper(self): def _long_axis(self): """Return the long axis""" if self.orientation == 'vertical': - return self.ax.yaxis - return self.ax.xaxis + return self.yaxis + return self.xaxis def _short_axis(self): """Return the short axis""" if self.orientation == 'vertical': - return self.ax.xaxis - return self.ax.yaxis + return self.xaxis + return self.yaxis class Colorbar(ColorbarBase): diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index 6167618575dd..c6e5ca0dfef6 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -768,9 +768,9 @@ def test_inset_colorbar_layout(): fig.draw_no_output() # make sure this is in the figure. In the colorbar swapping # it was being dropped from the list of children... - np.testing.assert_allclose(cb.ax.get_position().bounds, + np.testing.assert_allclose(cb.get_position().bounds, [0.87, 0.342, 0.0237, 0.315], atol=0.01) - assert cb.ax.outer_ax in ax.child_axes + assert cb.outer_ax in ax.child_axes @image_comparison(['colorbar_twoslope.png'], remove_text=True, From 7cbeb40e8f10010c6ad4630b08994f3211f16e9d Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Tue, 1 Jun 2021 21:05:39 -0600 Subject: [PATCH 2/5] FIX: Adding a line property to Colorbar to override the axes attribute --- lib/matplotlib/colorbar.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 3b8c1082b43d..7a6b21a21580 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -448,7 +448,7 @@ def __init__(self, ax, *, cmap=None, self.extendrect = extendrect self.solids = None self.solids_patches = [] - # self.lines = [] + self._lines = [] for spine in self.spines.values(): spine.set_visible(False) @@ -484,6 +484,10 @@ def __init__(self, ax, *, cmap=None, self.formatter = format # Assume it is a Formatter or None self.draw_all() + @property + def lines(self): + return self._lines + def draw_all(self): """ Calculate any free parameters based on the current cmap and norm, From 8a3223411d924c7115502ee9bee6ba5b706eaf70 Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Wed, 2 Jun 2021 06:55:27 -0600 Subject: [PATCH 3/5] MAINT: Updating all cbar.ax calls to just cbar This is for clarity that the colorbar is now an Axes itself. --- examples/axes_grid1/demo_axes_divider.py | 2 +- .../contour_demo.py | 4 +- .../contourf_demo.py | 2 +- .../image_annotated_heatmap.py | 2 +- .../colorbar_tick_labelling_demo.py | 4 +- lib/matplotlib/colorbar.py | 8 +- lib/matplotlib/tests/test_colorbar.py | 76 +++++++++---------- .../tests/test_constrainedlayout.py | 6 +- lib/matplotlib/tests/test_contour.py | 6 +- lib/mpl_toolkits/tests/test_mplot3d.py | 2 +- 10 files changed, 55 insertions(+), 57 deletions(-) diff --git a/examples/axes_grid1/demo_axes_divider.py b/examples/axes_grid1/demo_axes_divider.py index dddc2ed4760c..345bb34ef496 100644 --- a/examples/axes_grid1/demo_axes_divider.py +++ b/examples/axes_grid1/demo_axes_divider.py @@ -22,7 +22,7 @@ def demo_simple_image(ax): im = ax.imshow(Z, extent=extent) cb = plt.colorbar(im) - plt.setp(cb.ax.get_yticklabels(), visible=False) + plt.setp(cb.get_yticklabels(), visible=False) def demo_locatable_axes_hard(fig): diff --git a/examples/images_contours_and_fields/contour_demo.py b/examples/images_contours_and_fields/contour_demo.py index 4c98d4c8bc4c..a43e3de1f6c4 100644 --- a/examples/images_contours_and_fields/contour_demo.py +++ b/examples/images_contours_and_fields/contour_demo.py @@ -103,8 +103,8 @@ # so let's improve its position. l, b, w, h = ax.get_position().bounds -ll, bb, ww, hh = CB.ax.get_position().bounds -CB.ax.set_position([ll, b + 0.1*h, ww, h*0.8]) +ll, bb, ww, hh = CB.get_position().bounds +CB.set_position([ll, b + 0.1*h, ww, h*0.8]) plt.show() diff --git a/examples/images_contours_and_fields/contourf_demo.py b/examples/images_contours_and_fields/contourf_demo.py index 699eccd0ffa3..f75c192f6624 100644 --- a/examples/images_contours_and_fields/contourf_demo.py +++ b/examples/images_contours_and_fields/contourf_demo.py @@ -54,7 +54,7 @@ # Make a colorbar for the ContourSet returned by the contourf call. cbar = fig1.colorbar(CS) -cbar.ax.set_ylabel('verbosity coefficient') +cbar.set_ylabel('verbosity coefficient') # Add the contour line levels to the colorbar cbar.add_lines(CS2) diff --git a/examples/images_contours_and_fields/image_annotated_heatmap.py b/examples/images_contours_and_fields/image_annotated_heatmap.py index 301c180cb783..691d1f761686 100644 --- a/examples/images_contours_and_fields/image_annotated_heatmap.py +++ b/examples/images_contours_and_fields/image_annotated_heatmap.py @@ -131,7 +131,7 @@ def heatmap(data, row_labels, col_labels, ax=None, # Create colorbar cbar = ax.figure.colorbar(im, ax=ax, **cbar_kw) - cbar.ax.set_ylabel(cbarlabel, rotation=-90, va="bottom") + cbar.set_ylabel(cbarlabel, rotation=-90, va="bottom") # We want to show all ticks... ax.set_xticks(np.arange(data.shape[1])) diff --git a/examples/ticks_and_spines/colorbar_tick_labelling_demo.py b/examples/ticks_and_spines/colorbar_tick_labelling_demo.py index b0d56943fe30..28dcb609f768 100644 --- a/examples/ticks_and_spines/colorbar_tick_labelling_demo.py +++ b/examples/ticks_and_spines/colorbar_tick_labelling_demo.py @@ -29,7 +29,7 @@ # Add colorbar, make sure to specify tick locations to match desired ticklabels cbar = fig.colorbar(cax, ticks=[-1, 0, 1]) -cbar.ax.set_yticklabels(['< -1', '0', '> 1']) # vertically oriented colorbar +cbar.set_yticklabels(['< -1', '0', '> 1']) # vertically oriented colorbar ############################################################################### # Make plot with horizontal colorbar @@ -42,6 +42,6 @@ ax.set_title('Gaussian noise with horizontal colorbar') cbar = fig.colorbar(cax, ticks=[-1, 0, 1], orientation='horizontal') -cbar.ax.set_xticklabels(['Low', 'Medium', 'High']) # horizontal colorbar +cbar.set_xticklabels(['Low', 'Medium', 'High']) # horizontal colorbar plt.show() diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py index 7a6b21a21580..675ecfc3ae12 100644 --- a/lib/matplotlib/colorbar.py +++ b/lib/matplotlib/colorbar.py @@ -1,6 +1,6 @@ """ Colorbars are a visualization of the mapping from scalar values to colors. -In Matplotlib they are drawn into a dedicated `~.axes.Axes`. +In Matplotlib they are a separate dedicated `~.axes.Axes`. .. note:: Colorbars are typically created through `.Figure.colorbar` or its pyplot @@ -233,7 +233,7 @@ class ColorbarAxes(Axes): over/under colors. Users should not normally instantiate this class, but it is the class - returned by ``cbar = fig.colorbar(im); cax = cbar.ax``. + that the Colorbar inherits from by ``cbar = fig.colorbar(im);``. """ def __init__(self, parent, userax=True): """ @@ -339,8 +339,6 @@ class ColorbarBase(ColorbarAxes): Attributes ---------- - ax : `~matplotlib.axes.Axes` - The `~.axes.Axes` instance in which the colorbar is drawn. lines : list A list of `.LineCollection` (empty if no lines were drawn). dividers : `.LineCollection` @@ -384,7 +382,7 @@ class ColorbarBase(ColorbarAxes): label : str userax : boolean - Whether the user created the axes or not. Default True + Whether the user created the axes or not. Default False """ n_rasterize = 50 # rasterize solids if number of colors >= n_rasterize diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py index c6e5ca0dfef6..6c1a369f0e20 100644 --- a/lib/matplotlib/tests/test_colorbar.py +++ b/lib/matplotlib/tests/test_colorbar.py @@ -284,7 +284,7 @@ def test_colorbar_ticks(): colors = ['r', 'g', 'b', 'c'] cs = ax.contourf(X, Y, Z, clevs, colors=colors, extend='neither') cbar = fig.colorbar(cs, ax=ax, orientation='horizontal', ticks=clevs) - assert len(cbar.ax.xaxis.get_ticklocs()) == len(clevs) + assert len(cbar.xaxis.get_ticklocs()) == len(clevs) def test_colorbar_minorticks_on_off(): @@ -301,17 +301,17 @@ def test_colorbar_minorticks_on_off(): # testing after minorticks_on() cbar.minorticks_on() np.testing.assert_almost_equal( - cbar.ax.yaxis.get_minorticklocs(), + cbar.yaxis.get_minorticklocs(), [-2.2, -1.8, -1.6, -1.4, -1.2, -0.8, -0.6, -0.4, -0.2, 0.2, 0.4, 0.6, 0.8, 1.2, 1.4, 1.6, 1.8, 2.2, 2.4, 2.6, 2.8, 3.2]) # testing after minorticks_off() cbar.minorticks_off() - np.testing.assert_almost_equal(cbar.ax.yaxis.get_minorticklocs(), []) + np.testing.assert_almost_equal(cbar.yaxis.get_minorticklocs(), []) im.set_clim(vmin=-1.2, vmax=1.2) cbar.minorticks_on() np.testing.assert_almost_equal( - cbar.ax.yaxis.get_minorticklocs(), + cbar.yaxis.get_minorticklocs(), [-1.1, -0.9, -0.8, -0.7, -0.6, -0.4, -0.3, -0.2, -0.1, 0.1, 0.2, 0.3, 0.4, 0.6, 0.7, 0.8, 0.9, 1.1, 1.2, 1.3]) @@ -322,20 +322,20 @@ def test_colorbar_minorticks_on_off(): im = ax.pcolormesh(data, norm=LogNorm()) cbar = fig.colorbar(im) fig.canvas.draw() - default_minorticklocks = cbar.ax.yaxis.get_minorticklocs() + default_minorticklocks = cbar.yaxis.get_minorticklocs() # test that minorticks turn off for LogNorm cbar.minorticks_off() - np.testing.assert_equal(cbar.ax.yaxis.get_minorticklocs(), []) + np.testing.assert_equal(cbar.yaxis.get_minorticklocs(), []) # test that minorticks turn back on for LogNorm cbar.minorticks_on() - np.testing.assert_equal(cbar.ax.yaxis.get_minorticklocs(), + np.testing.assert_equal(cbar.yaxis.get_minorticklocs(), default_minorticklocks) # test issue #13339: minorticks for LogNorm should stay off cbar.minorticks_off() cbar.set_ticks([3, 5, 7, 9]) - np.testing.assert_equal(cbar.ax.yaxis.get_minorticklocs(), []) + np.testing.assert_equal(cbar.yaxis.get_minorticklocs(), []) def test_cbar_minorticks_for_rc_xyminortickvisible(): @@ -358,12 +358,12 @@ def test_cbar_minorticks_for_rc_xyminortickvisible(): im = ax.pcolormesh([[1, 2]], vmin=vmin, vmax=vmax) cbar = fig.colorbar(im, extend='both', orientation='vertical') - assert cbar.ax.yaxis.get_minorticklocs()[0] >= vmin - assert cbar.ax.yaxis.get_minorticklocs()[-1] <= vmax + assert cbar.yaxis.get_minorticklocs()[0] >= vmin + assert cbar.yaxis.get_minorticklocs()[-1] <= vmax cbar = fig.colorbar(im, extend='both', orientation='horizontal') - assert cbar.ax.xaxis.get_minorticklocs()[0] >= vmin - assert cbar.ax.xaxis.get_minorticklocs()[-1] <= vmax + assert cbar.xaxis.get_minorticklocs()[0] >= vmin + assert cbar.xaxis.get_minorticklocs()[-1] <= vmax def test_colorbar_autoticks(): @@ -384,7 +384,7 @@ def test_colorbar_autoticks(): cbar2 = fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical', shrink=0.4) # note only -10 to 10 are visible, - np.testing.assert_almost_equal(cbar.ax.yaxis.get_ticklocs(), + np.testing.assert_almost_equal(cbar.yaxis.get_ticklocs(), np.arange(-15, 16, 5)) # note only -10 to 10 are visible np.testing.assert_almost_equal(cbar2.ax.yaxis.get_ticklocs(), @@ -408,7 +408,7 @@ def test_colorbar_autotickslog(): cbar2 = fig.colorbar(pcm, ax=ax[1], extend='both', orientation='vertical', shrink=0.4) # note only -12 to +12 are visible - np.testing.assert_almost_equal(cbar.ax.yaxis.get_ticklocs(), + np.testing.assert_almost_equal(cbar.yaxis.get_ticklocs(), 10**np.arange(-16., 16.2, 4.)) # note only -24 to +24 are visible np.testing.assert_almost_equal(cbar2.ax.yaxis.get_ticklocs(), @@ -488,7 +488,7 @@ def test_colorbar_log_minortick_labels(): pcm = ax.imshow([[10000, 50000]], norm=LogNorm()) cb = fig.colorbar(pcm) fig.canvas.draw() - lb = [l.get_text() for l in cb.ax.yaxis.get_ticklabels(which='both')] + lb = [l.get_text() for l in cb.yaxis.get_ticklabels(which='both')] expected = [r'$\mathdefault{10^{4}}$', r'$\mathdefault{2\times10^{4}}$', r'$\mathdefault{3\times10^{4}}$', @@ -504,7 +504,7 @@ def test_colorbar_renorm(): fig, ax = plt.subplots() im = ax.imshow(z) cbar = fig.colorbar(im) - np.testing.assert_allclose(cbar.ax.yaxis.get_majorticklocs(), + np.testing.assert_allclose(cbar.yaxis.get_majorticklocs(), np.arange(0, 120000.1, 20000)) cbar.set_ticks([1, 2, 3]) @@ -512,13 +512,13 @@ def test_colorbar_renorm(): norm = LogNorm(z.min(), z.max()) im.set_norm(norm) - np.testing.assert_allclose(cbar.ax.yaxis.get_majorticklocs(), + np.testing.assert_allclose(cbar.yaxis.get_majorticklocs(), np.logspace(-10, 7, 18)) # note that set_norm removes the FixedLocator... assert np.isclose(cbar.vmin, z.min()) cbar.set_ticks([1, 2, 3]) assert isinstance(cbar.locator, FixedLocator) - np.testing.assert_allclose(cbar.ax.yaxis.get_majorticklocs(), + np.testing.assert_allclose(cbar.yaxis.get_majorticklocs(), [1.0, 2.0, 3.0]) norm = LogNorm(z.min() * 1000, z.max() * 1000) @@ -536,18 +536,18 @@ def test_colorbar_format(): im = ax.imshow(z) cbar = fig.colorbar(im, format='%4.2e') fig.canvas.draw() - assert cbar.ax.yaxis.get_ticklabels()[4].get_text() == '8.00e+04' + assert cbar.yaxis.get_ticklabels()[4].get_text() == '8.00e+04' # make sure that if we change the clim of the mappable that the # formatting is *not* lost: im.set_clim([4, 200]) fig.canvas.draw() - assert cbar.ax.yaxis.get_ticklabels()[4].get_text() == '2.00e+02' + assert cbar.yaxis.get_ticklabels()[4].get_text() == '2.00e+02' # but if we change the norm: im.set_norm(LogNorm(vmin=0.1, vmax=10)) fig.canvas.draw() - assert (cbar.ax.yaxis.get_ticklabels()[0].get_text() == + assert (cbar.yaxis.get_ticklabels()[0].get_text() == r'$\mathdefault{10^{-2}}$') @@ -559,12 +559,12 @@ def test_colorbar_scale_reset(): pcm = ax.pcolormesh(z, cmap='RdBu_r', rasterized=True) cbar = fig.colorbar(pcm, ax=ax) cbar.outline.set_edgecolor('red') - assert cbar.ax.yaxis.get_scale() == 'linear' + assert cbar.yaxis.get_scale() == 'linear' pcm.set_norm(LogNorm(vmin=1, vmax=100)) - assert cbar.ax.yaxis.get_scale() == 'log' + assert cbar.yaxis.get_scale() == 'log' pcm.set_norm(Normalize(vmin=-20, vmax=20)) - assert cbar.ax.yaxis.get_scale() == 'linear' + assert cbar.yaxis.get_scale() == 'linear' assert cbar.outline.get_edgecolor() == mcolors.to_rgba('red') @@ -583,7 +583,7 @@ def test_colorbar_inverted_ticks(): pc = ax.pcolormesh(10**np.arange(1, 5).reshape(2, 2), norm=LogNorm()) cbar = fig.colorbar(pc, ax=ax, extend='both') ticks = cbar.get_ticks() - cbar.ax.invert_yaxis() + cbar.invert_yaxis() np.testing.assert_allclose(ticks, cbar.get_ticks()) ax = axs[1] @@ -592,7 +592,7 @@ def test_colorbar_inverted_ticks(): cbar.minorticks_on() ticks = cbar.get_ticks() minorticks = cbar.get_ticks(minor=True) - cbar.ax.invert_yaxis() + cbar.invert_yaxis() np.testing.assert_allclose(ticks, cbar.get_ticks()) np.testing.assert_allclose(minorticks, cbar.get_ticks(minor=True)) @@ -603,7 +603,7 @@ def test_extend_colorbar_customnorm(): fig, (ax0, ax1) = plt.subplots(2, 1) pcm = ax0.pcolormesh([[0]], norm=TwoSlopeNorm(vcenter=0., vmin=-2, vmax=1)) cb = fig.colorbar(pcm, ax=ax0, extend='both') - np.testing.assert_allclose(cb.ax.get_position().extents, + np.testing.assert_allclose(cb.get_position().extents, [0.78375, 0.536364, 0.796147, 0.9], rtol=2e-3) @@ -623,11 +623,11 @@ def test_colorbar_label(): fig, ax = plt.subplots() im = ax.imshow([[1, 2], [3, 4]]) cbar = fig.colorbar(im, label='cbar') - assert cbar.ax.get_ylabel() == 'cbar' + assert cbar.get_ylabel() == 'cbar' cbar.set_label(None) - assert cbar.ax.get_ylabel() == '' + assert cbar.get_ylabel() == '' cbar.set_label('cbar 2') - assert cbar.ax.get_ylabel() == 'cbar 2' + assert cbar.get_ylabel() == 'cbar 2' cbar2 = fig.colorbar(im, label=None) assert cbar2.ax.get_ylabel() == '' @@ -663,7 +663,7 @@ def test_anchored_cbar_position_using_specgrid(): # the top right corner of one ax is (x1, y1) # p0: the vertical / horizontal position of anchor x0, y0, x1, y1 = ax.get_position().extents - cx0, cy0, cx1, cy1 = cbar.ax.get_position().extents + cx0, cy0, cx1, cy1 = cbar.get_position().extents p0 = (y1 - y0) * anchor_y + y0 np.testing.assert_allclose( @@ -681,7 +681,7 @@ def test_anchored_cbar_position_using_specgrid(): # the top right corner of one ax is (x1, y1) # p0: the vertical / horizontal position of anchor x0, y0, x1, y1 = ax.get_position().extents - cx0, cy0, cx1, cy1 = cbar.ax.get_position().extents + cx0, cy0, cx1, cy1 = cbar.get_position().extents p0 = (y1 - y0) * anchor_y + y0 np.testing.assert_allclose( @@ -701,7 +701,7 @@ def test_anchored_cbar_position_using_specgrid(): # the top right corner of one ax is (x1, y1) # p0: the vertical / horizontal position of anchor x0, y0, x1, y1 = ax.get_position().extents - cx0, cy0, cx1, cy1 = cbar.ax.get_position().extents + cx0, cy0, cx1, cy1 = cbar.get_position().extents p0 = (x1 - x0) * anchor_x + x0 np.testing.assert_allclose( @@ -721,7 +721,7 @@ def test_anchored_cbar_position_using_specgrid(): # the top right corner of one ax is (x1, y1) # p0: the vertical / horizontal position of anchor x0, y0, x1, y1 = ax.get_position().extents - cx0, cy0, cx1, cy1 = cbar.ax.get_position().extents + cx0, cy0, cx1, cy1 = cbar.get_position().extents p0 = (x1 - x0) * anchor_x + x0 np.testing.assert_allclose( @@ -735,16 +735,16 @@ def test_colorbar_change_lim_scale(): fig, ax = plt.subplots(1, 2, constrained_layout=True) pc = ax[0].pcolormesh(np.arange(100).reshape(10, 10)+1) cb = fig.colorbar(pc, ax=ax[0], extend='both') - cb.ax.set_yscale('log') + cb.set_yscale('log') pc = ax[1].pcolormesh(np.arange(100).reshape(10, 10)+1) cb = fig.colorbar(pc, ax=ax[1], extend='both') - cb.ax.set_ylim([20, 90]) + cb.set_ylim([20, 90]) @check_figures_equal(extensions=["png"]) def test_axes_handles_same_functions(fig_ref, fig_test): - # prove that cax and cb.ax are functionally the same + # prove that cax and cb are functionally the same for nn, fig in enumerate([fig_ref, fig_test]): ax = fig.add_subplot() pc = ax.pcolormesh(np.ones(300).reshape(10, 30)) @@ -753,7 +753,7 @@ def test_axes_handles_same_functions(fig_ref, fig_test): if nn == 0: caxx = cax else: - caxx = cb.ax + caxx = cb caxx.set_yticks(np.arange(20)) caxx.set_yscale('log') caxx.set_position([0.92, 0.1, 0.02, 0.7]) diff --git a/lib/matplotlib/tests/test_constrainedlayout.py b/lib/matplotlib/tests/test_constrainedlayout.py index cfb8ca73980a..da8587bf61e9 100644 --- a/lib/matplotlib/tests/test_constrainedlayout.py +++ b/lib/matplotlib/tests/test_constrainedlayout.py @@ -422,10 +422,10 @@ def test_colorbar_align(): cb = fig.colorbar(pc, ax=ax, location=location, shrink=0.6, pad=0.04) cbs += [cb] - cb.ax.tick_params(direction='in') + cb.tick_params(direction='in') if nn != 1: - cb.ax.xaxis.set_ticks([]) - cb.ax.yaxis.set_ticks([]) + cb.xaxis.set_ticks([]) + cb.yaxis.set_ticks([]) ax.set_xticklabels('') ax.set_yticklabels('') fig.set_constrained_layout_pads(w_pad=4 / 72, h_pad=4 / 72, hspace=0.1, diff --git a/lib/matplotlib/tests/test_contour.py b/lib/matplotlib/tests/test_contour.py index 73a7a3d6ae56..2e3cd2f911b8 100644 --- a/lib/matplotlib/tests/test_contour.py +++ b/lib/matplotlib/tests/test_contour.py @@ -334,9 +334,9 @@ def test_contourf_log_extension(): norm=LogNorm(vmin=levels.min(), vmax=levels.max()), extend='both') cb = plt.colorbar(c1, ax=ax1) - assert cb.ax.get_ylim() == (1e-8, 1e10) + assert cb.get_ylim() == (1e-8, 1e10) cb = plt.colorbar(c2, ax=ax2) - assert cb.ax.get_ylim() == (1e-4, 1e6) + assert cb.get_ylim() == (1e-4, 1e6) cb = plt.colorbar(c3, ax=ax3) @@ -356,7 +356,7 @@ def test_contour_addlines(): cont = ax.contour(X+1000) cb = fig.colorbar(pcm) cb.add_lines(cont) - assert_array_almost_equal(cb.ax.get_ylim(), [114.3091, 9972.30735], 3) + assert_array_almost_equal(cb.get_ylim(), [114.3091, 9972.30735], 3) @image_comparison(baseline_images=['contour_uneven'], diff --git a/lib/mpl_toolkits/tests/test_mplot3d.py b/lib/mpl_toolkits/tests/test_mplot3d.py index edb5c978bb49..9031618233fa 100644 --- a/lib/mpl_toolkits/tests/test_mplot3d.py +++ b/lib/mpl_toolkits/tests/test_mplot3d.py @@ -1346,7 +1346,7 @@ def test_colorbar_pos(): fig.canvas.draw() # check that actually on the bottom - assert cbar.ax.get_position().extents[1] < 0.2 + assert cbar.get_position().extents[1] < 0.2 def test_shared_axes_retick(): From 2f49875f1085ed0cc95bae9f233768f591d5db76 Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Wed, 2 Jun 2021 07:08:56 -0600 Subject: [PATCH 4/5] DOC: Adding a release note for the Colorbar behavior change --- doc/api/next_api_changes/behavior/20XXX-GL.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 doc/api/next_api_changes/behavior/20XXX-GL.rst diff --git a/doc/api/next_api_changes/behavior/20XXX-GL.rst b/doc/api/next_api_changes/behavior/20XXX-GL.rst new file mode 100644 index 000000000000..e513424dadd8 --- /dev/null +++ b/doc/api/next_api_changes/behavior/20XXX-GL.rst @@ -0,0 +1,16 @@ +Colorbars are now an instance of Axes +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The :class:`.colorbar.Colorbar` class now inherits from `.axes.Axes`, +meaning that all of the standard methods of ``Axes`` can be used +directly on the colorbar object itself rather than having to access the +``ax`` attribute. For example, :: + + cbar.set_yticks() + +rather than :: + + cbar.ax.set_yticks() + +We are leaving the ``cbar.ax`` attribute in place as a pass-through for now, +which just maps back to the colorbar object. From 895776b07a239c6af1f3cc2ec4fefd2fb0136e32 Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Fri, 11 Jun 2021 06:56:48 -0600 Subject: [PATCH 5/5] DOC: Fixing old doc cross-reference --- doc/api/prev_api_changes/api_changes_2.1.0.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/api/prev_api_changes/api_changes_2.1.0.rst b/doc/api/prev_api_changes/api_changes_2.1.0.rst index 9673d24c719f..fa434761163d 100644 --- a/doc/api/prev_api_changes/api_changes_2.1.0.rst +++ b/doc/api/prev_api_changes/api_changes_2.1.0.rst @@ -422,8 +422,8 @@ The ``shading`` kwarg to `~matplotlib.axes.Axes.pcolor` has been removed. Set ``edgecolors`` appropriately instead. -Functions removed from the `.lines` module -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Functions removed from the `matplotlib.lines` module +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The :mod:`matplotlib.lines` module no longer imports the ``pts_to_prestep``, ``pts_to_midstep`` and ``pts_to_poststep`` pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy