59
59
60
60
colormap_kw_doc = '''
61
61
62
- =========== ====================================================
62
+ ============ ====================================================
63
63
Property Description
64
- =========== ====================================================
64
+ ============ ====================================================
65
65
*extend* [ 'neither' | 'both' | 'min' | 'max' ]
66
66
If not 'neither', make pointed end(s) for out-of-
67
67
range values. These are set for a given colormap
68
68
using the colormap set_under and set_over methods.
69
+ *extendfrac* [ *None* | 'auto' | length | lengths ]
70
+ If set to *None*, both the minimum and maximum
71
+ triangular colorbar extensions with have a length of
72
+ 5% of the interior colorbar length (this is the
73
+ default setting). If set to 'auto', makes the
74
+ triangular colorbar extensions the same lengths as
75
+ the interior boxes (when *spacing* is set to
76
+ 'uniform') or the same lengths as the respective
77
+ adjacent interior boxes (when *spacing* is set to
78
+ 'proportional'). If a scalar, indicates the length
79
+ of both the minimum and maximum triangular colorbar
80
+ extensions as a fraction of the interior colorbar
81
+ length. A two-element sequence of fractions may also
82
+ be given, indicating the lengths of the minimum and
83
+ maximum colorbar extensions respectively as a
84
+ fraction of the interior colorbar length.
69
85
*spacing* [ 'uniform' | 'proportional' ]
70
86
Uniform spacing gives each discrete color the same
71
87
space; proportional makes the space proportional to
82
98
given instead.
83
99
*drawedges* [ False | True ] If true, draw lines at color
84
100
boundaries.
85
- =========== ====================================================
101
+ ============ ====================================================
86
102
87
103
The following will probably be useful only in the context of
88
104
indexed colors (that is, when the mappable has norm=NoNorm()),
@@ -221,6 +237,7 @@ def __init__(self, ax, cmap=None,
221
237
format = None ,
222
238
drawedges = False ,
223
239
filled = True ,
240
+ extendfrac = None ,
224
241
):
225
242
self .ax = ax
226
243
self ._patch_ax ()
@@ -236,6 +253,7 @@ def __init__(self, ax, cmap=None,
236
253
self .orientation = orientation
237
254
self .drawedges = drawedges
238
255
self .filled = filled
256
+ self .extendfrac = extendfrac
239
257
self .solids = None
240
258
self .lines = None
241
259
self .outline = None
@@ -616,6 +634,35 @@ def _extended_N(self):
616
634
N += 1
617
635
return N
618
636
637
+ def _get_extension_lengths (self , frac , automin , automax , default = 0.05 ):
638
+ '''
639
+ Get the lengths of colorbar extensions.
640
+
641
+ A helper method for _uniform_y and _proportional_y.
642
+ '''
643
+ # Set the default value.
644
+ extendlength = np .array ([default , default ])
645
+ if isinstance (frac , str ):
646
+ if frac .lower () == 'auto' :
647
+ # Use the provided values when 'auto' is required.
648
+ extendlength [0 ] = automin
649
+ extendlength [1 ] = automax
650
+ else :
651
+ # Any other string is invalid.
652
+ raise ValueError ('invalid value for extendfrac' )
653
+ elif frac is not None :
654
+ try :
655
+ # Try to set min and max extension fractions directly.
656
+ extendlength [:] = frac
657
+ # If frac is a sequence contaning None then NaN may
658
+ # be encountered. This is an error.
659
+ if np .isnan (extendlength ).any ():
660
+ raise ValueError ()
661
+ except (TypeError , ValueError ):
662
+ # Raise an error on encountering an invalid value for frac.
663
+ raise ValueError ('invalid value for extendfrac' )
664
+ return extendlength
665
+
619
666
def _uniform_y (self , N ):
620
667
'''
621
668
Return colorbar data coordinates for *N* uniformly
@@ -624,16 +671,19 @@ def _uniform_y(self, N):
624
671
if self .extend == 'neither' :
625
672
y = np .linspace (0 , 1 , N )
626
673
else :
674
+ automin = automax = 1. / (N - 1. )
675
+ extendlength = self ._get_extension_lengths (self .extendfrac ,
676
+ automin , automax , default = 0.05 )
627
677
if self .extend == 'both' :
628
678
y = np .zeros (N + 2 , 'd' )
629
- y [0 ] = - 0.05
630
- y [- 1 ] = 1.05
679
+ y [0 ] = 0. - extendlength [ 0 ]
680
+ y [- 1 ] = 1. + extendlength [ 1 ]
631
681
elif self .extend == 'min' :
632
682
y = np .zeros (N + 1 , 'd' )
633
- y [0 ] = - 0.05
683
+ y [0 ] = 0. - extendlength [ 0 ]
634
684
else :
635
685
y = np .zeros (N + 1 , 'd' )
636
- y [- 1 ] = 1.05
686
+ y [- 1 ] = 1. + extendlength [ 1 ]
637
687
y [self ._inside ] = np .linspace (0 , 1 , N )
638
688
return y
639
689
@@ -648,10 +698,27 @@ def _proportional_y(self):
648
698
y = y / (self ._boundaries [- 1 ] - self ._boundaries [0 ])
649
699
else :
650
700
y = self .norm (self ._boundaries .copy ())
651
- if self ._extend_lower ():
652
- y [0 ] = - 0.05
653
- if self ._extend_upper ():
654
- y [- 1 ] = 1.05
701
+ if self .extend == 'min' :
702
+ # Exclude leftmost interval of y.
703
+ clen = y [- 1 ] - y [1 ]
704
+ automin = (y [2 ] - y [1 ]) / clen
705
+ automax = (y [- 1 ] - y [- 2 ]) / clen
706
+ elif self .extend == 'max' :
707
+ # Exclude rightmost interval in y.
708
+ clen = y [- 2 ] - y [0 ]
709
+ automin = (y [1 ] - y [0 ]) / clen
710
+ automax = (y [- 2 ] - y [- 3 ]) / clen
711
+ else :
712
+ # Exclude leftmost and rightmost intervals in y.
713
+ clen = y [- 2 ] - y [1 ]
714
+ automin = (y [2 ] - y [1 ]) / clen
715
+ automax = (y [- 2 ] - y [- 3 ]) / clen
716
+ extendlength = self ._get_extension_lengths (self .extendfrac ,
717
+ automin , automax , default = 0.05 )
718
+ if self .extend in ('both' , 'min' ):
719
+ y [0 ] = 0. - extendlength [0 ]
720
+ if self .extend in ('both' , 'max' ):
721
+ y [- 1 ] = 1. + extendlength [1 ]
655
722
yi = y [self ._inside ]
656
723
norm = colors .Normalize (yi [0 ], yi [- 1 ])
657
724
y [self ._inside ] = norm (yi )
0 commit comments