5252import six
5353from six .moves import zip
5454
55+ import warnings
5556import re
5657import numpy as np
5758from numpy import ma
@@ -617,24 +618,24 @@ def __call__(self, X, alpha=None, bytes=False):
617618 return rgba
618619
619620 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+ """
622623 self ._rgba_bad = colorConverter .to_rgba (color , alpha )
623624 if self ._isinit :
624625 self ._set_extremes ()
625626
626627 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.
628629 Requires norm.clip = False
629- '''
630+ """
630631 self ._rgba_under = colorConverter .to_rgba (color , alpha )
631632 if self ._isinit :
632633 self ._set_extremes ()
633634
634635 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.
636637 Requires norm.clip = False
637- '''
638+ """
638639 self ._rgba_over = colorConverter .to_rgba (color , alpha )
639640 if self ._isinit :
640641 self ._set_extremes ()
@@ -651,7 +652,7 @@ def _set_extremes(self):
651652 self ._lut [self ._i_bad ] = self ._rgba_bad
652653
653654 def _init (self ):
654- ''' Generate the lookup table, self._lut'''
655+ """ Generate the lookup table, self._lut"""
655656 raise NotImplementedError ("Abstract class only" )
656657
657658 def is_gray (self ):
@@ -937,9 +938,9 @@ def inverse(self, value):
937938 return vmin + value * (vmax - vmin )
938939
939940 def autoscale (self , A ):
940- '''
941+ """
941942 Set *vmin*, *vmax* to min, max of *A*.
942- '''
943+ """
943944 self .vmin = ma .min (A )
944945 self .vmax = ma .max (A )
945946
@@ -1008,9 +1009,9 @@ def inverse(self, value):
10081009 return vmin * pow ((vmax / vmin ), value )
10091010
10101011 def autoscale (self , A ):
1011- '''
1012+ """
10121013 Set *vmin*, *vmax* to min, max of *A*.
1013- '''
1014+ """
10141015 A = ma .masked_less_equal (A , 0 , copy = False )
10151016 self .vmin = ma .min (A )
10161017 self .vmax = ma .max (A )
@@ -1140,8 +1141,82 @@ def autoscale_None(self, A):
11401141 self ._transform_vmin_vmax ()
11411142
11421143
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+
11431218class BoundaryNorm (Normalize ):
1144- '''
1219+ """
11451220 Generate a colormap index based on discrete intervals.
11461221
11471222 Unlike :class:`Normalize` or :class:`LogNorm`,
@@ -1152,9 +1227,9 @@ class BoundaryNorm(Normalize):
11521227 piece-wise linear interpolation, but using integers seems
11531228 simpler, and reduces the number of conversions back and forth
11541229 between integer and floating point.
1155- '''
1230+ """
11561231 def __init__ (self , boundaries , ncolors , clip = False ):
1157- '''
1232+ """
11581233 *boundaries*
11591234 a monotonically increasing sequence
11601235 *ncolors*
@@ -1171,7 +1246,7 @@ def __init__(self, boundaries, ncolors, clip=False):
11711246 Out-of-range values are mapped to -1 if low and ncolors
11721247 if high; these are converted to valid indices by
11731248 :meth:`Colormap.__call__` .
1174- '''
1249+ """
11751250 self .clip = clip
11761251 self .vmin = boundaries [0 ]
11771252 self .vmax = boundaries [- 1 ]
@@ -1209,11 +1284,11 @@ def inverse(self, value):
12091284
12101285
12111286class NoNorm (Normalize ):
1212- '''
1287+ """
12131288 Dummy replacement for Normalize, for the case where we
12141289 want to use indices directly in a
12151290 :class:`~matplotlib.cm.ScalarMappable` .
1216- '''
1291+ """
12171292 def __call__ (self , value , clip = None ):
12181293 return value
12191294
0 commit comments