33from axes import Axes , Subplot , PolarSubplot , PolarAxes
44from cbook import flatten , allequal , popd , Stack , iterable
55import _image
6- from colors import normalize
6+ from colors import normalize , rgb2hex
77from image import FigureImage
88from matplotlib import rcParams
9- from patches import Rectangle
9+ from patches import Rectangle , Polygon
1010from text import Text , _process_text_args
1111
1212from legend import Legend
1313from transforms import Bbox , Value , Point , get_bbox_transform , unit_bbox
1414from numerix import array , clip , transpose
15- from mlab import linspace
15+ from mlab import linspace , meshgrid
1616from ticker import FormatStrFormatter
17-
17+ from cm import ScalarMappable
18+ from contour import ContourMappable
1819
1920class SubplotParams :
2021 """
@@ -635,8 +636,7 @@ def savefig(self, *args, **kwargs):
635636
636637 self .canvas .print_figure (* args , ** kwargs )
637638
638-
639- def colorbar (self , mappable , tickfmt = '%1.1f' , cax = None , orientation = 'vertical' ):
639+ def colorbar (self ,mappable ,tickfmt = '%1.1f' ,cax = None ,orientation = 'vertical' ,cspacing = 'proportional' ,clabels = None ,drawedges = False ,edgewidth = 0.5 ,edgecolor = 'k' ):
640640 """
641641 Create a colorbar for mappable image
642642
@@ -652,6 +652,28 @@ def colorbar(self, mappable, tickfmt='%1.1f', cax=None, orientation='vertical'):
652652 will be used and the other axes positions will be unchanged.
653653
654654 orientation is the colorbar orientation: one of 'vertical' | 'horizontal'
655+
656+ cspacing controls how colors are distributed on the colorbar.
657+ if cspacing == 'linear', each color occupies an equal area
658+ on the colorbar, regardless of the contour spacing.
659+ if cspacing == 'proportional' (Default), the area each color
660+ occupies on the the colorbar is proportional to the contour interval.
661+ Only relevant for a Contour image.
662+
663+ clabels can be a sequence containing the
664+ contour levels to be labelled on the colorbar, or None (Default).
665+ If clabels is None, labels for all contour intervals are
666+ displayed. Only relevant for a Contour image.
667+
668+ if drawedges == True, lines are drawn at the edges between
669+ each color on the colorbar. Default False.
670+
671+ edgecolor is the line color delimiting the edges of the colors
672+ on the colorbar (if drawedges == True). Default black ('k')
673+
674+ edgewidth is the width of the lines delimiting the edges of
675+ the colors on the colorbar (if drawedges == True). Default 0.5
676+
655677 return value is the colorbar axes instance
656678 """
657679
@@ -665,12 +687,6 @@ def colorbar(self, mappable, tickfmt='%1.1f', cax=None, orientation='vertical'):
665687 ax = self .gca ()
666688
667689 cmap = mappable .cmap
668- norm = mappable .norm
669-
670- if norm .vmin is None or norm .vmax is None :
671- mappable .autoscale ()
672- cmin = norm .vmin
673- cmax = norm .vmax
674690
675691 if cax is None :
676692 l ,b ,w ,h = ax .get_position ()
@@ -687,34 +703,87 @@ def colorbar(self, mappable, tickfmt='%1.1f', cax=None, orientation='vertical'):
687703 if not isinstance (cax , Axes ):
688704 raise TypeError ('Expected an Axes instance for cax' )
689705
690- N = cmap .N
706+ if isinstance (mappable , ContourMappable ):
707+ # mappable image is from contourf
708+ clevs = mappable .levels .tolist ()
709+ if mappable .level_upper is not None :
710+ clevs = array (clevs + [mappable .level_upper ])
711+ else :
712+ clevs = array (clevs )
713+ iscontourf = True
714+ elif isinstance (mappable , ScalarMappable ):
715+ # from imshow or pcolor.
716+ iscontourf = False
717+ norm = mappable .norm
718+ if norm .vmin is None or norm .vmax is None :
719+ mappable .autoscale ()
720+ cmin = norm .vmin
721+ cmax = norm .vmax
722+ clevs = linspace (cmin , cmax , cmap .N )
723+ else :
724+ raise TypeError ("don't know how to handle type %s" % type (mappable ))
691725
692- c = linspace (cmin , cmax , N )
693- C = array ([c ,c ])
726+ cmin = min (clevs ); cmax = max (clevs )
727+ N = len (clevs )
728+ C = array ([clevs ,clevs ])
694729
695730 if orientation == 'vertical' :
696731 C = transpose (C )
697732
698733 if orientation == 'vertical' :
699- extent = (0 , 1 , cmin , cmax )
734+ if cspacing == 'linear' :
735+ X ,Y = meshgrid ([cmin ,cmax ],(clevs - cmin )/ (cmax - cmin ))
736+ elif cspacing == 'proportional' :
737+ X ,Y = meshgrid ([cmin ,cmax ],linspace (0. ,1. ,N ))
738+ else :
739+ raise ValueError ("cspacing must be 'linear' or 'proportional'" )
740+ if drawedges :
741+ levs ,coll = cax .contour (X , C , Y , N - 2 ,linewidths = edgewidth ,colors = edgecolor )
742+ levs ,coll = cax .contourf (X , C , Y , N - 2 , cmap = cmap )
700743 else :
701- extent = (cmin , cmax , 0 , 1 )
702- coll = cax .imshow (C ,
703- interpolation = 'nearest' ,
704- #interpolation='bilinear',
705- origin = 'lower' ,
706- cmap = cmap , norm = norm ,
707- extent = extent )
708- mappable .add_observer (coll )
709- mappable .set_colorbar (coll , cax )
710-
744+ if cspacing == 'linear' :
745+ X ,Y = meshgrid ((clevs - cmin )/ (cmax - cmin ),[cmin ,cmax ])
746+ elif cspacing == 'proportional' :
747+ X ,Y = meshgrid (linspace (0. ,1. ,N ),[cmin ,cmax ])
748+ else :
749+ raise ValueError ("cspacing must be 'linear' or 'proportional'" )
750+ if drawedges :
751+ levs ,coll = cax .contour (C , Y , X , N - 2 ,linewidths = edgewidth ,colors = edgecolor )
752+ levs ,coll = cax .contourf (C , Y , X , N - 2 , cmap = cmap )
753+
754+ mappable .add_observer (coll .mappable )
755+ mappable .set_colorbar (coll .mappable , cax )
756+
757+ labs = [tickfmt % clev for clev in clevs ]
758+ if iscontourf and clabels is not None :
759+ for cl in clabels :
760+ if cl not in clevs :
761+ raise ValueError , 'clabels contains a value (%s) that is not a valid contour in the Contour image mappable' % (cl )
762+ n = 0
763+ for cl ,lab in zip (clevs ,labs ):
764+ if cl not in clabels : labs [n ]= ''
765+ n = n + 1
711766 if orientation == 'vertical' :
712767 cax .set_xticks ([])
713768 cax .yaxis .tick_right ()
714- cax .yaxis .set_major_formatter (FormatStrFormatter (tickfmt ))
769+ if iscontourf :
770+ if cspacing == 'linear' :
771+ cax .set_yticks (linspace (cmin ,cmax ,N ))
772+ else :
773+ cax .set_yticks (clevs )
774+ cax .set_yticklabels (labs )
775+ else :
776+ cax .yaxis .set_major_formatter (FormatStrFormatter (tickfmt ))
715777 else :
716778 cax .set_yticks ([])
717- cax .xaxis .set_major_formatter (FormatStrFormatter (tickfmt ))
779+ if iscontourf :
780+ if cspacing == 'linear' :
781+ cax .set_xticks (linspace (cmin ,cmax ,N ))
782+ else :
783+ cax .set_xticks (clevs )
784+ cax .set_xticklabels (labs )
785+ else :
786+ cax .xaxis .set_major_formatter (FormatStrFormatter (tickfmt ))
718787
719788 self .sca (ax )
720789 return cax
0 commit comments