Skip to content

Commit 209bf11

Browse files
committed
Fold ColorbarPatch into Colorbar, deprecate colorbar_factory.
It is easier to have an internal switch on the mappable type, rather than having a separate "internal" (per the documentation) API to support hatchings. Also note that the previous version would fail in obscure cases where the contourset was changed from not using hatches to using hatches after the colorbar was created.
1 parent 3b576e6 commit 209bf11

File tree

4 files changed

+56
-95
lines changed

4 files changed

+56
-95
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
``ColorbarPatch`` and ``colorbar_factory`` are deprecated
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
All the relevant functionality has been moved to the
4+
`~matplotlib.colorbar.Colorbar` class.

lib/matplotlib/colorbar.py

Lines changed: 50 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@
1919
On top of `.ColorbarBase` this connects the colorbar with a
2020
`.ScalarMappable` such as an image or contour plot.
2121
22-
:class:`ColorbarPatch`
23-
A specialized `.Colorbar` to support hatched contour plots.
24-
2522
:func:`make_axes`
2623
Create an `~.axes.Axes` suitable for a colorbar. This functions can be
2724
used with figures containing a single axes or with freely placed axes.
@@ -472,6 +469,7 @@ def __init__(self, ax, cmap=None,
472469
self.extendfrac = extendfrac
473470
self.extendrect = extendrect
474471
self.solids = None
472+
self.solids_patches = []
475473
self.lines = []
476474

477475
for spine in ax.spines.values():
@@ -807,33 +805,50 @@ def _edges(self, X, Y):
807805
return [list(zip(Y[i], X[i])) for i in range(1, N - 1)]
808806

809807
def _add_solids(self, X, Y, C):
810-
"""
811-
Draw the colors using `~.axes.Axes.pcolormesh`;
812-
optionally add separators.
813-
"""
814-
if self.orientation == 'vertical':
815-
args = (X, Y, C)
816-
else:
817-
args = (np.transpose(Y), np.transpose(X), np.transpose(C))
818-
kw = dict(cmap=self.cmap,
819-
norm=self.norm,
820-
alpha=self.alpha,
821-
edgecolors='None')
822-
_log.debug('Setting pcolormesh')
823-
col = self.ax.pcolormesh(*args, **kw, shading='flat')
824-
# self.add_observer(col) # We should observe, not be observed...
825-
808+
"""Draw the colors; optionally add separators."""
809+
# Cleanup previously set artists.
826810
if self.solids is not None:
827811
self.solids.remove()
828-
self.solids = col
829-
830-
if self.drawedges:
831-
self.dividers.set_segments(self._edges(X, Y))
812+
for solid in self.solids_patches:
813+
solid.remove()
814+
# Add new artist(s), based on mappable type. Use individual patches if
815+
# hatching is needed, pcolormesh otherwise.
816+
mappable = getattr(self, 'mappable', None)
817+
if (isinstance(mappable, contour.ContourSet)
818+
and any(hatch is not None for hatch in mappable.hatches)):
819+
self._add_solids_patches(X, Y, C, mappable)
832820
else:
833-
self.dividers.set_segments([])
821+
self._add_solids_pcolormesh(X, Y, C)
822+
self.dividers.set_segments(self._edges(X, Y) if self.drawedges else [])
823+
824+
def _add_solids_pcolormesh(self, X, Y, C):
825+
_log.debug('Setting pcolormesh')
826+
args = (X, Y, C) if self.orientation == 'vertical' else (Y.T, X.T, C.T)
827+
self.solids = self.ax.pcolormesh(
828+
*args, cmap=self.cmap, norm=self.norm, alpha=self.alpha,
829+
edgecolors='none', shading='flat')
830+
if not self.drawedges:
834831
if len(self._y) >= self.n_rasterize:
835832
self.solids.set_rasterized(True)
836833

834+
def _add_solids_patches(self, X, Y, C, mappable):
835+
hatches = mappable.hatches * len(C) # Have enough hatches.
836+
patches = []
837+
for i in range(len(X) - 1):
838+
xy = np.array([[X[i, 0], Y[i, 0]],
839+
[X[i, 1], Y[i, 0]],
840+
[X[i + 1, 1], Y[i + 1, 0]],
841+
[X[i + 1, 0], Y[i + 1, 1]]])
842+
if self.orientation == 'horizontal':
843+
xy = xy[..., ::-1] # Swap x/y.
844+
patch = mpatches.PathPatch(mpath.Path(xy),
845+
facecolor=self.cmap(self.norm(C[i][0])),
846+
hatch=hatches[i], linewidth=0,
847+
antialiased=False, alpha=self.alpha)
848+
self.ax.add_patch(patch)
849+
patches.append(patch)
850+
self.solids_patches = patches
851+
837852
def add_lines(self, levels, colors, linewidths, erase=True):
838853
"""
839854
Draw lines on the colorbar.
@@ -1082,7 +1097,7 @@ def _proportional_y(self):
10821097

10831098
def _mesh(self):
10841099
"""
1085-
Return ``(X, Y)``, the coordinate arrays for the colorbar pcolormesh.
1100+
Return the coordinate arrays for the colorbar pcolormesh/patches.
10861101
These are suitable for a vertical colorbar; swapping and transposition
10871102
for a horizontal colorbar are done outside this function.
10881103
@@ -1213,6 +1228,10 @@ def __init__(self, ax, mappable, **kwargs):
12131228
_add_disjoint_kwargs(kwargs, alpha=mappable.get_alpha())
12141229
super().__init__(ax, **kwargs)
12151230

1231+
mappable.colorbar = self
1232+
mappable.colorbar_cid = mappable.callbacksSM.connect(
1233+
'changed', self.update_normal)
1234+
12161235
@cbook.deprecated("3.3", alternative="update_normal")
12171236
def on_mappable_changed(self, mappable):
12181237
"""
@@ -1550,61 +1569,12 @@ def make_axes_gridspec(parent, *, location=None, orientation=None,
15501569
return cax, kw
15511570

15521571

1572+
@cbook.deprecated("3.4", alternative="Colorbar")
15531573
class ColorbarPatch(Colorbar):
1554-
"""
1555-
A Colorbar that uses a list of `~.patches.Patch` instances rather than the
1556-
default `~.collections.PatchCollection` created by `~.axes.Axes.pcolor`,
1557-
because the latter does not allow the hatch pattern to vary among the
1558-
members of the collection.
1559-
"""
1560-
1561-
def __init__(self, ax, mappable, **kw):
1562-
# we do not want to override the behaviour of solids
1563-
# so add a new attribute which will be a list of the
1564-
# colored patches in the colorbar
1565-
self.solids_patches = []
1566-
super().__init__(ax, mappable, **kw)
1567-
1568-
def _add_solids(self, X, Y, C):
1569-
"""
1570-
Draw the colors using `~matplotlib.patches.Patch`;
1571-
optionally add separators.
1572-
"""
1573-
n_segments = len(C)
1574-
1575-
# ensure there are sufficient hatches
1576-
hatches = self.mappable.hatches * n_segments
1577-
1578-
patches = []
1579-
for i in range(len(X) - 1):
1580-
val = C[i][0]
1581-
hatch = hatches[i]
1582-
1583-
xy = np.array([[X[i][0], Y[i][0]],
1584-
[X[i][1], Y[i][0]],
1585-
[X[i + 1][1], Y[i + 1][0]],
1586-
[X[i + 1][0], Y[i + 1][1]]])
1587-
1588-
if self.orientation == 'horizontal':
1589-
# if horizontal swap the xs and ys
1590-
xy = xy[..., ::-1]
1591-
1592-
patch = mpatches.PathPatch(mpath.Path(xy),
1593-
facecolor=self.cmap(self.norm(val)),
1594-
hatch=hatch, linewidth=0,
1595-
antialiased=False, alpha=self.alpha)
1596-
self.ax.add_patch(patch)
1597-
patches.append(patch)
1598-
1599-
if self.solids_patches:
1600-
for solid in self.solids_patches:
1601-
solid.remove()
1602-
1603-
self.solids_patches = patches
1604-
1605-
self.dividers.set_segments(self._edges(X, Y) if self.drawedges else [])
1574+
pass
16061575

16071576

1577+
@cbook.deprecated("3.4", alternative="Colorbar")
16081578
def colorbar_factory(cax, mappable, **kwargs):
16091579
"""
16101580
Create a colorbar on the given axes for the given mappable.
@@ -1626,20 +1596,7 @@ def colorbar_factory(cax, mappable, **kwargs):
16261596
16271597
Returns
16281598
-------
1629-
`.Colorbar` or `.ColorbarPatch`
1630-
The created colorbar instance. `.ColorbarPatch` is only used if
1631-
*mappable* is a `.ContourSet` with hatches.
1599+
`.Colorbar`
1600+
The created colorbar instance.
16321601
"""
1633-
# if the given mappable is a contourset with any hatching, use
1634-
# ColorbarPatch else use Colorbar
1635-
if (isinstance(mappable, contour.ContourSet)
1636-
and any(hatch is not None for hatch in mappable.hatches)):
1637-
cb = ColorbarPatch(cax, mappable, **kwargs)
1638-
else:
1639-
cb = Colorbar(cax, mappable, **kwargs)
1640-
1641-
cid = mappable.callbacksSM.connect('changed', cb.update_normal)
1642-
mappable.colorbar = cb
1643-
mappable.colorbar_cid = cid
1644-
1645-
return cb
1602+
return Colorbar(cax, mappable, **kwargs)

lib/matplotlib/figure.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2380,7 +2380,7 @@ def colorbar(self, mappable, cax=None, ax=None, use_gridspec=True, **kw):
23802380
NON_COLORBAR_KEYS = ['fraction', 'pad', 'shrink', 'aspect', 'anchor',
23812381
'panchor']
23822382
cb_kw = {k: v for k, v in kw.items() if k not in NON_COLORBAR_KEYS}
2383-
cb = cbar.colorbar_factory(cax, mappable, **cb_kw)
2383+
cb = cbar.Colorbar(cax, mappable, **cb_kw)
23842384

23852385
self.sca(current_ax)
23862386
self.stale = True

lib/mpl_toolkits/axes_grid1/axes_grid.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def colorbar(self, mappable, *, ticks=None, **kwargs):
5050
mappable.colorbar = cb
5151
self._locator = cb.cbar_axis.get_major_locator()
5252
else:
53-
cb = mpl.colorbar.colorbar_factory(
53+
cb = mpl.colorbar.Colorbar(
5454
self, mappable, orientation=orientation, ticks=ticks, **kwargs)
5555
self._cbid = mappable.colorbar_cid # deprecated.
5656
self._locator = cb.locator # deprecated.

0 commit comments

Comments
 (0)