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" )
15531573class 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" )
16081578def 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 )
0 commit comments