161
161
from matplotlib import rcParams
162
162
from matplotlib import cbook
163
163
from matplotlib import transforms as mtransforms
164
+ from matplotlib .cbook import mplDeprecation
164
165
165
166
import warnings
166
167
167
168
if six .PY3 :
168
169
long = int
169
170
170
171
172
+ # Work around numpy/numpy#6127.
173
+ def _divmod (x , y ):
174
+ if isinstance (x , np .generic ):
175
+ x = x .item ()
176
+ if isinstance (y , np .generic ):
177
+ y = y .item ()
178
+ return six .moves .builtins .divmod (x , y )
179
+
180
+
171
181
def _mathdefault (s ):
172
182
"""
173
183
For backward compatibility, in classic mode we display
@@ -1218,7 +1228,7 @@ def view_limits(self, vmin, vmax):
1218
1228
vmax += 1
1219
1229
1220
1230
if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1221
- exponent , remainder = divmod (math .log10 (vmax - vmin ), 1 )
1231
+ exponent , remainder = _divmod (math .log10 (vmax - vmin ), 1 )
1222
1232
if remainder < 0.5 :
1223
1233
exponent -= 1
1224
1234
scale = 10 ** (- exponent )
@@ -1244,30 +1254,30 @@ def __init__(self, base):
1244
1254
1245
1255
def lt (self , x ):
1246
1256
'return the largest multiple of base < x'
1247
- d , m = divmod (x , self ._base )
1257
+ d , m = _divmod (x , self ._base )
1248
1258
if closeto (m , 0 ) and not closeto (m / self ._base , 1 ):
1249
1259
return (d - 1 ) * self ._base
1250
1260
return d * self ._base
1251
1261
1252
1262
def le (self , x ):
1253
1263
'return the largest multiple of base <= x'
1254
- d , m = divmod (x , self ._base )
1264
+ d , m = _divmod (x , self ._base )
1255
1265
if closeto (m / self ._base , 1 ): # was closeto(m, self._base)
1256
1266
#looks like floating point error
1257
1267
return (d + 1 ) * self ._base
1258
1268
return d * self ._base
1259
1269
1260
1270
def gt (self , x ):
1261
1271
'return the smallest multiple of base > x'
1262
- d , m = divmod (x , self ._base )
1272
+ d , m = _divmod (x , self ._base )
1263
1273
if closeto (m / self ._base , 1 ):
1264
1274
#looks like floating point error
1265
1275
return (d + 2 ) * self ._base
1266
1276
return (d + 1 ) * self ._base
1267
1277
1268
1278
def ge (self , x ):
1269
1279
'return the smallest multiple of base >= x'
1270
- d , m = divmod (x , self ._base )
1280
+ d , m = _divmod (x , self ._base )
1271
1281
if closeto (m , 0 ) and not closeto (m / self ._base , 1 ):
1272
1282
return d * self ._base
1273
1283
return (d + 1 ) * self ._base
@@ -1323,23 +1333,13 @@ def view_limits(self, dmin, dmax):
1323
1333
1324
1334
1325
1335
def scale_range (vmin , vmax , n = 1 , threshold = 100 ):
1326
- dv = abs (vmax - vmin )
1327
- if dv == 0 : # maxabsv == 0 is a special case of this.
1328
- return 1.0 , 0.0
1329
- # Note: this should never occur because
1330
- # vmin, vmax should have been checked by nonsingular(),
1331
- # and spread apart if necessary.
1332
- meanv = 0.5 * (vmax + vmin )
1336
+ dv = abs (vmax - vmin ) # > 0 as nonsingular is called before.
1337
+ meanv = (vmax + vmin ) / 2
1333
1338
if abs (meanv ) / dv < threshold :
1334
1339
offset = 0
1335
- elif meanv > 0 :
1336
- ex = divmod (math .log10 (meanv ), 1 )[0 ]
1337
- offset = 10 ** ex
1338
1340
else :
1339
- ex = divmod (math .log10 (- meanv ), 1 )[0 ]
1340
- offset = - 10 ** ex
1341
- ex = divmod (math .log10 (dv / n ), 1 )[0 ]
1342
- scale = 10 ** ex
1341
+ offset = math .copysign (10 ** (math .log10 (abs (meanv )) // 1 ), meanv )
1342
+ scale = 10 ** (math .log10 (dv / n ) // 1 )
1343
1343
return scale , offset
1344
1344
1345
1345
@@ -1349,7 +1349,6 @@ class MaxNLocator(Locator):
1349
1349
"""
1350
1350
default_params = dict (nbins = 10 ,
1351
1351
steps = None ,
1352
- trim = True ,
1353
1352
integer = False ,
1354
1353
symmetric = False ,
1355
1354
prune = None )
@@ -1385,9 +1384,6 @@ def __init__(self, *args, **kwargs):
1385
1384
will be removed. If prune==None, no ticks will be removed.
1386
1385
1387
1386
"""
1388
- # I left "trim" out; it defaults to True, and it is not
1389
- # clear that there is any use case for False, so we may
1390
- # want to remove that kwarg. EF 2010/04/18
1391
1387
if args :
1392
1388
kwargs ['nbins' ] = args [0 ]
1393
1389
if len (args ) > 1 :
@@ -1403,7 +1399,8 @@ def set_params(self, **kwargs):
1403
1399
if self ._nbins != 'auto' :
1404
1400
self ._nbins = int (self ._nbins )
1405
1401
if 'trim' in kwargs :
1406
- self ._trim = kwargs ['trim' ]
1402
+ warnings .warn ("The 'trim' keyword has no effect anymore" ,
1403
+ mplDeprecation )
1407
1404
if 'integer' in kwargs :
1408
1405
self ._integer = kwargs ['integer' ]
1409
1406
if 'symmetric' in kwargs :
@@ -1426,9 +1423,9 @@ def set_params(self, **kwargs):
1426
1423
if 'integer' in kwargs :
1427
1424
self ._integer = kwargs ['integer' ]
1428
1425
if self ._integer :
1429
- self ._steps = [n for n in self ._steps if divmod (n , 1 )[1 ] < 0.001 ]
1426
+ self ._steps = [n for n in self ._steps if _divmod (n , 1 )[1 ] < 0.001 ]
1430
1427
1431
- def bin_boundaries (self , vmin , vmax ):
1428
+ def _raw_ticks (self , vmin , vmax ):
1432
1429
nbins = self ._nbins
1433
1430
if nbins == 'auto' :
1434
1431
nbins = self .axis .get_tick_space ()
@@ -1446,23 +1443,26 @@ def bin_boundaries(self, vmin, vmax):
1446
1443
if step < scaled_raw_step :
1447
1444
continue
1448
1445
step *= scale
1449
- best_vmin = step * divmod ( vmin , step )[ 0 ]
1446
+ best_vmin = vmin // step * step
1450
1447
best_vmax = best_vmin + step * nbins
1451
- if ( best_vmax >= vmax ) :
1448
+ if best_vmax >= vmax :
1452
1449
break
1453
- if self ._trim :
1454
- extra_bins = int (divmod ((best_vmax - vmax ), step )[0 ])
1455
- nbins -= extra_bins
1456
- return (np .arange (nbins + 1 ) * step + best_vmin + offset )
1450
+
1451
+ # More than nbins may be required, e.g. vmin, vmax = -4.1, 4.1 gives
1452
+ # nbins=9 but 10 bins are actually required after rounding. So we just
1453
+ # create the bins that span the range we need instead.
1454
+ low = round (Base (step ).le (vmin - best_vmin ) / step )
1455
+ high = round (Base (step ).ge (vmax - best_vmin ) / step )
1456
+ return np .arange (low , high + 1 ) * step + best_vmin + offset
1457
1457
1458
1458
def __call__ (self ):
1459
1459
vmin , vmax = self .axis .get_view_interval ()
1460
1460
return self .tick_values (vmin , vmax )
1461
1461
1462
1462
def tick_values (self , vmin , vmax ):
1463
- vmin , vmax = mtransforms .nonsingular (vmin , vmax , expander = 1e-13 ,
1464
- tiny = 1e-14 )
1465
- locs = self .bin_boundaries (vmin , vmax )
1463
+ vmin , vmax = mtransforms .nonsingular (
1464
+ vmin , vmax , expander = 1e-13 , tiny = 1e-14 )
1465
+ locs = self ._raw_ticks (vmin , vmax )
1466
1466
prune = self ._prune
1467
1467
if prune == 'lower' :
1468
1468
locs = locs [1 :]
@@ -1479,11 +1479,11 @@ def view_limits(self, dmin, dmax):
1479
1479
dmin = - maxabs
1480
1480
dmax = maxabs
1481
1481
1482
- dmin , dmax = mtransforms .nonsingular (dmin , dmax , expander = 1e-12 ,
1483
- tiny = 1.e -13 )
1482
+ dmin , dmax = mtransforms .nonsingular (
1483
+ dmin , dmax , expander = 1e-12 , tiny = 1e -13 )
1484
1484
1485
1485
if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1486
- return np . take ( self .bin_boundaries (dmin , dmax ), [ 0 , - 1 ])
1486
+ return self ._raw_ticks (dmin , dmax )[[ 0 , - 1 ]]
1487
1487
else :
1488
1488
return dmin , dmax
1489
1489
0 commit comments