@@ -969,6 +969,80 @@ def scaled(self):
969
969
return (self .vmin is not None and self .vmax is not None )
970
970
971
971
972
+ class OffsetNorm (Normalize ):
973
+ def __init__ (self , vmin = None , vcenter = None , vmax = None , clip = False ):
974
+ self .vmin = vmin
975
+ self .vcenter = vcenter
976
+ self .vmax = vmax
977
+ self .clip = clip
978
+
979
+ def __call__ (self , value , clip = False ):
980
+ if clip is None :
981
+ clip = self .clip
982
+
983
+ result , is_scalar = self .process_value (value )
984
+
985
+ self .autoscale_None (result )
986
+ vmin , vcenter , vmax = self .vmin , self .vcenter , self .vmax
987
+ if vmin == vmax == vcenter :
988
+ result .fill (0 )
989
+ elif not vmin <= vcenter <= vmax :
990
+ raise ValueError ("minvalue must be less than or equal to "
991
+ "centervalue which must be less than or "
992
+ "equal to maxvalue" )
993
+ else :
994
+ vmin = float (vmin )
995
+ vcenter = float (vcenter )
996
+ vmax = float (vmax )
997
+ if clip :
998
+ mask = ma .getmask (result )
999
+ result = ma .array (np .clip (result .filled (vmax ), vmin , vmax ),
1000
+ mask = mask )
1001
+
1002
+ resdat = result .data
1003
+ lower = resdat [resdat < vcenter ]
1004
+ upper = resdat [resdat >= vcenter ]
1005
+
1006
+ lower -= vmin
1007
+ lower /= ((vcenter - vmin ) * 2 )
1008
+
1009
+ upper -= vcenter
1010
+ upper /= ((vmax - vcenter ) * 2 )
1011
+ upper += 0.5
1012
+
1013
+ resdat = np .hstack ([lower , upper ])
1014
+
1015
+ result = np .ma .array (resdat , mask = result .mask , copy = False )
1016
+
1017
+ if is_scalar :
1018
+ result = result [0 ]
1019
+
1020
+ return result
1021
+
1022
+ def inverse (self , value ):
1023
+ midpoint = 0.5
1024
+ if not self .scaled ():
1025
+ raise ValueError ("Not invertible until scaled" )
1026
+
1027
+ vmin = float (self .vmin )
1028
+ vcenter = float (self .vcenter )
1029
+ vmax = float (self .vmax )
1030
+
1031
+ if cbook .iterable (value ):
1032
+ val = ma .asarray (value )
1033
+ else :
1034
+ val = ma .asarray ([value ])
1035
+
1036
+ lower = vmin + val [val <= midpoint ] * (2 * (vcenter - vmin ))
1037
+ upper = vcenter + val [val > midpoint ] * (2 * (vmax - vcenter )) - vmax
1038
+
1039
+ inverted = np .hstack ([lower , upper ])
1040
+ if cbook .iterable (value ):
1041
+ return inverted
1042
+ else :
1043
+ return inverted [0 ]
1044
+
1045
+
972
1046
class LogNorm (Normalize ):
973
1047
"""
974
1048
Normalize a given value to the 0-1 range on a log scale
0 commit comments