@@ -1231,9 +1231,10 @@ def __init__(self, linthresh, linscale=1.0,
1231
1231
"""
1232
1232
Normalize .__init__ (self , vmin , vmax , clip )
1233
1233
self .linthresh = float (linthresh )
1234
- self ._linscale_adj = (linscale / (1.0 - np .e ** - 1 ))
1235
- if vmin is not None and vmax is not None :
1236
- self ._transform_vmin_vmax ()
1234
+ # Number of decades in the log region
1235
+ ndec = np .log10 (vmax / linthresh )
1236
+ # Size of the linear region from 0 to linthresh in the transformed space
1237
+ self .linear_size = 1 / (1 + linscale / ndec )
1237
1238
1238
1239
def __call__ (self , value , clip = None ):
1239
1240
if clip is None :
@@ -1254,57 +1255,52 @@ def __call__(self, value, clip=None):
1254
1255
mask = mask )
1255
1256
# in-place equivalent of above can be much faster
1256
1257
resdat = self ._transform (result .data )
1257
- resdat -= self ._lower
1258
- resdat /= (self ._upper - self ._lower )
1259
1258
1260
1259
if is_scalar :
1261
1260
result = result [0 ]
1262
1261
return result
1263
1262
1264
1263
def _transform (self , a ):
1265
- """Inplace transformation. """
1264
+ """In-place mapping from *a* to [0, 1] """
1266
1265
with np .errstate (invalid = "ignore" ):
1267
- masked = np .abs (a ) > self .linthresh
1268
- sign = np .sign (a [masked ])
1269
- log = (self ._linscale_adj + np .log (np .abs (a [masked ]) / self .linthresh ))
1270
- log *= sign * self .linthresh
1271
- a [masked ] = log
1272
- a [~ masked ] *= self ._linscale_adj
1266
+ logregion = np .abs (a ) > self .linthresh
1267
+
1268
+ # Transform log value
1269
+ sign = np .sign (a [logregion ])
1270
+ log = (1 - self .linear_size ) * np .log10 (np .abs (a [logregion ])) + self .linear_size
1271
+ a [logregion ] = log * sign
1272
+
1273
+ # Transform linear values
1274
+ a [~ logregion ] *= self .linear_size / self .linthresh
1275
+
1276
+ # Transform from [-1, 1] to [0, 1]
1277
+ a += 1
1278
+ a /= 2
1273
1279
return a
1274
1280
1275
1281
def _inv_transform (self , a ):
1276
1282
"""Inverse inplace Transformation."""
1277
- masked = np .abs (a ) > (self .linthresh * self ._linscale_adj )
1278
- sign = np .sign (a [masked ])
1279
- exp = np .exp (sign * a [masked ] / self .linthresh - self ._linscale_adj )
1280
- exp *= sign * self .linthresh
1281
- a [masked ] = exp
1282
- a [~ masked ] /= self ._linscale_adj
1283
+ # Transform from [0, 1] to [-1, 1]
1284
+ a *= 2
1285
+ a -= 1
1286
+
1287
+ # Transform back log values
1288
+ logregion = np .abs (a ) > self .linear_size
1289
+ sign = np .sign (a [logregion ])
1290
+ exp = 10 ** ((np .abs (a [logregion ]) - self .linear_size ) /
1291
+ (1 - self .linear_size ))
1292
+ a [logregion ] = exp * sign
1293
+
1294
+ # Transform back linear values
1295
+ a [~ logregion ] /= self .linear_size / self .linthresh
1283
1296
return a
1284
1297
1285
- def _transform_vmin_vmax (self ):
1286
- """Calculates vmin and vmax in the transformed system."""
1287
- vmin , vmax = self .vmin , self .vmax
1288
- arr = np .array ([vmax , vmin ]).astype (float )
1289
- self ._upper , self ._lower = self ._transform (arr )
1290
-
1291
1298
def inverse (self , value ):
1292
1299
if not self .scaled ():
1293
1300
raise ValueError ("Not invertible until scaled" )
1294
1301
val = np .ma .asarray (value )
1295
- val = val * (self ._upper - self ._lower ) + self ._lower
1296
1302
return self ._inv_transform (val )
1297
1303
1298
- def autoscale (self , A ):
1299
- # docstring inherited.
1300
- super ().autoscale (A )
1301
- self ._transform_vmin_vmax ()
1302
-
1303
- def autoscale_None (self , A ):
1304
- # docstring inherited.
1305
- super ().autoscale_None (A )
1306
- self ._transform_vmin_vmax ()
1307
-
1308
1304
1309
1305
class PowerNorm (Normalize ):
1310
1306
"""
0 commit comments