52
52
import six
53
53
from six .moves import zip
54
54
55
+ import warnings
55
56
import re
56
57
import numpy as np
57
58
from numpy import ma
@@ -617,24 +618,24 @@ def __call__(self, X, alpha=None, bytes=False):
617
618
return rgba
618
619
619
620
def set_bad (self , color = 'k' , alpha = None ):
620
- ''' Set color to be used for masked values.
621
- '''
621
+ """ Set color to be used for masked values.
622
+ """
622
623
self ._rgba_bad = colorConverter .to_rgba (color , alpha )
623
624
if self ._isinit :
624
625
self ._set_extremes ()
625
626
626
627
def set_under (self , color = 'k' , alpha = None ):
627
- ''' Set color to be used for low out-of-range values.
628
+ """ Set color to be used for low out-of-range values.
628
629
Requires norm.clip = False
629
- '''
630
+ """
630
631
self ._rgba_under = colorConverter .to_rgba (color , alpha )
631
632
if self ._isinit :
632
633
self ._set_extremes ()
633
634
634
635
def set_over (self , color = 'k' , alpha = None ):
635
- ''' Set color to be used for high out-of-range values.
636
+ """ Set color to be used for high out-of-range values.
636
637
Requires norm.clip = False
637
- '''
638
+ """
638
639
self ._rgba_over = colorConverter .to_rgba (color , alpha )
639
640
if self ._isinit :
640
641
self ._set_extremes ()
@@ -651,7 +652,7 @@ def _set_extremes(self):
651
652
self ._lut [self ._i_bad ] = self ._rgba_bad
652
653
653
654
def _init (self ):
654
- ''' Generate the lookup table, self._lut'''
655
+ """ Generate the lookup table, self._lut"""
655
656
raise NotImplementedError ("Abstract class only" )
656
657
657
658
def is_gray (self ):
@@ -937,9 +938,9 @@ def inverse(self, value):
937
938
return vmin + value * (vmax - vmin )
938
939
939
940
def autoscale (self , A ):
940
- '''
941
+ """
941
942
Set *vmin*, *vmax* to min, max of *A*.
942
- '''
943
+ """
943
944
self .vmin = ma .min (A )
944
945
self .vmax = ma .max (A )
945
946
@@ -1008,9 +1009,9 @@ def inverse(self, value):
1008
1009
return vmin * pow ((vmax / vmin ), value )
1009
1010
1010
1011
def autoscale (self , A ):
1011
- '''
1012
+ """
1012
1013
Set *vmin*, *vmax* to min, max of *A*.
1013
- '''
1014
+ """
1014
1015
A = ma .masked_less_equal (A , 0 , copy = False )
1015
1016
self .vmin = ma .min (A )
1016
1017
self .vmax = ma .max (A )
@@ -1140,8 +1141,82 @@ def autoscale_None(self, A):
1140
1141
self ._transform_vmin_vmax ()
1141
1142
1142
1143
1144
+ class PowerNorm (Normalize ):
1145
+ """
1146
+ Normalize a given value to the ``[0, 1]`` interval with a power-law
1147
+ scaling. This will clip any negative data points to 0.
1148
+ """
1149
+ def __init__ (self , gamma , vmin = None , vmax = None , clip = False ):
1150
+ Normalize .__init__ (self , vmin , vmax , clip )
1151
+ self .gamma = gamma
1152
+
1153
+ def __call__ (self , value , clip = None ):
1154
+ if clip is None :
1155
+ clip = self .clip
1156
+
1157
+ result , is_scalar = self .process_value (value )
1158
+
1159
+ self .autoscale_None (result )
1160
+ gamma = self .gamma
1161
+ vmin , vmax = self .vmin , self .vmax
1162
+ if vmin > vmax :
1163
+ raise ValueError ("minvalue must be less than or equal to maxvalue" )
1164
+ elif vmin == vmax :
1165
+ result .fill (0 )
1166
+ else :
1167
+ if clip :
1168
+ mask = ma .getmask (result )
1169
+ val = ma .array (np .clip (result .filled (vmax ), vmin , vmax ),
1170
+ mask = mask )
1171
+ resdat = result .data
1172
+ resdat -= vmin
1173
+ np .power (resdat , gamma , resdat )
1174
+ resdat /= (vmax - vmin ) ** gamma
1175
+ result = np .ma .array (resdat , mask = result .mask , copy = False )
1176
+ result [value < 0 ] = 0
1177
+ if is_scalar :
1178
+ result = result [0 ]
1179
+ return result
1180
+
1181
+ def inverse (self , value ):
1182
+ if not self .scaled ():
1183
+ raise ValueError ("Not invertible until scaled" )
1184
+ gamma = self .gamma
1185
+ vmin , vmax = self .vmin , self .vmax
1186
+
1187
+ if cbook .iterable (value ):
1188
+ val = ma .asarray (value )
1189
+ return ma .power (value , 1. / gamma ) * (vmax - vmin ) + vmin
1190
+ else :
1191
+ return pow (value , 1. / gamma ) * (vmax - vmin ) + vmin
1192
+
1193
+ def autoscale (self , A ):
1194
+ """
1195
+ Set *vmin*, *vmax* to min, max of *A*.
1196
+ """
1197
+ self .vmin = ma .min (A )
1198
+ if self .vmin < 0 :
1199
+ self .vmin = 0
1200
+ warnings .warn ("Power-law scaling on negative values is "
1201
+ "ill-defined, clamping to 0." )
1202
+
1203
+ self .vmax = ma .max (A )
1204
+
1205
+ def autoscale_None (self , A ):
1206
+ ' autoscale only None-valued vmin or vmax'
1207
+ if self .vmin is None and np .size (A ) > 0 :
1208
+ self .vmin = ma .min (A )
1209
+ if self .vmin < 0 :
1210
+ self .vmin = 0
1211
+ warnings .warn ("Power-law scaling on negative values is "
1212
+ "ill-defined, clamping to 0." )
1213
+
1214
+ if self .vmax is None and np .size (A ) > 0 :
1215
+ self .vmax = ma .max (A )
1216
+
1217
+
1143
1218
class BoundaryNorm (Normalize ):
1144
- '''
1219
+ """
1145
1220
Generate a colormap index based on discrete intervals.
1146
1221
1147
1222
Unlike :class:`Normalize` or :class:`LogNorm`,
@@ -1152,9 +1227,9 @@ class BoundaryNorm(Normalize):
1152
1227
piece-wise linear interpolation, but using integers seems
1153
1228
simpler, and reduces the number of conversions back and forth
1154
1229
between integer and floating point.
1155
- '''
1230
+ """
1156
1231
def __init__ (self , boundaries , ncolors , clip = False ):
1157
- '''
1232
+ """
1158
1233
*boundaries*
1159
1234
a monotonically increasing sequence
1160
1235
*ncolors*
@@ -1171,7 +1246,7 @@ def __init__(self, boundaries, ncolors, clip=False):
1171
1246
Out-of-range values are mapped to -1 if low and ncolors
1172
1247
if high; these are converted to valid indices by
1173
1248
:meth:`Colormap.__call__` .
1174
- '''
1249
+ """
1175
1250
self .clip = clip
1176
1251
self .vmin = boundaries [0 ]
1177
1252
self .vmax = boundaries [- 1 ]
@@ -1209,11 +1284,11 @@ def inverse(self, value):
1209
1284
1210
1285
1211
1286
class NoNorm (Normalize ):
1212
- '''
1287
+ """
1213
1288
Dummy replacement for Normalize, for the case where we
1214
1289
want to use indices directly in a
1215
1290
:class:`~matplotlib.cm.ScalarMappable` .
1216
- '''
1291
+ """
1217
1292
def __call__ (self , value , clip = None ):
1218
1293
return value
1219
1294
0 commit comments