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
@@ -1221,7 +1231,7 @@ def view_limits(self, vmin, vmax):
1221
1231
vmax += 1
1222
1232
1223
1233
if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1224
- exponent , remainder = divmod (math .log10 (vmax - vmin ), 1 )
1234
+ exponent , remainder = _divmod (math .log10 (vmax - vmin ), 1 )
1225
1235
if remainder < 0.5 :
1226
1236
exponent -= 1
1227
1237
scale = 10 ** (- exponent )
@@ -1247,30 +1257,30 @@ def __init__(self, base):
1247
1257
1248
1258
def lt (self , x ):
1249
1259
'return the largest multiple of base < x'
1250
- d , m = divmod (x , self ._base )
1260
+ d , m = _divmod (x , self ._base )
1251
1261
if closeto (m , 0 ) and not closeto (m / self ._base , 1 ):
1252
1262
return (d - 1 ) * self ._base
1253
1263
return d * self ._base
1254
1264
1255
1265
def le (self , x ):
1256
1266
'return the largest multiple of base <= x'
1257
- d , m = divmod (x , self ._base )
1267
+ d , m = _divmod (x , self ._base )
1258
1268
if closeto (m / self ._base , 1 ): # was closeto(m, self._base)
1259
1269
#looks like floating point error
1260
1270
return (d + 1 ) * self ._base
1261
1271
return d * self ._base
1262
1272
1263
1273
def gt (self , x ):
1264
1274
'return the smallest multiple of base > x'
1265
- d , m = divmod (x , self ._base )
1275
+ d , m = _divmod (x , self ._base )
1266
1276
if closeto (m / self ._base , 1 ):
1267
1277
#looks like floating point error
1268
1278
return (d + 2 ) * self ._base
1269
1279
return (d + 1 ) * self ._base
1270
1280
1271
1281
def ge (self , x ):
1272
1282
'return the smallest multiple of base >= x'
1273
- d , m = divmod (x , self ._base )
1283
+ d , m = _divmod (x , self ._base )
1274
1284
if closeto (m , 0 ) and not closeto (m / self ._base , 1 ):
1275
1285
return d * self ._base
1276
1286
return (d + 1 ) * self ._base
@@ -1326,23 +1336,13 @@ def view_limits(self, dmin, dmax):
1326
1336
1327
1337
1328
1338
def scale_range (vmin , vmax , n = 1 , threshold = 100 ):
1329
- dv = abs (vmax - vmin )
1330
- if dv == 0 : # maxabsv == 0 is a special case of this.
1331
- return 1.0 , 0.0
1332
- # Note: this should never occur because
1333
- # vmin, vmax should have been checked by nonsingular(),
1334
- # and spread apart if necessary.
1335
- meanv = 0.5 * (vmax + vmin )
1339
+ dv = abs (vmax - vmin ) # > 0 as nonsingular is called before.
1340
+ meanv = (vmax + vmin ) / 2
1336
1341
if abs (meanv ) / dv < threshold :
1337
1342
offset = 0
1338
- elif meanv > 0 :
1339
- ex = divmod (math .log10 (meanv ), 1 )[0 ]
1340
- offset = 10 ** ex
1341
1343
else :
1342
- ex = divmod (math .log10 (- meanv ), 1 )[0 ]
1343
- offset = - 10 ** ex
1344
- ex = divmod (math .log10 (dv / n ), 1 )[0 ]
1345
- scale = 10 ** ex
1344
+ offset = math .copysign (10 ** (math .log10 (abs (meanv )) // 1 ), meanv )
1345
+ scale = 10 ** (math .log10 (dv / n ) // 1 )
1346
1346
return scale , offset
1347
1347
1348
1348
@@ -1352,7 +1352,6 @@ class MaxNLocator(Locator):
1352
1352
"""
1353
1353
default_params = dict (nbins = 10 ,
1354
1354
steps = None ,
1355
- trim = True ,
1356
1355
integer = False ,
1357
1356
symmetric = False ,
1358
1357
prune = None )
@@ -1388,9 +1387,6 @@ def __init__(self, *args, **kwargs):
1388
1387
will be removed. If prune==None, no ticks will be removed.
1389
1388
1390
1389
"""
1391
- # I left "trim" out; it defaults to True, and it is not
1392
- # clear that there is any use case for False, so we may
1393
- # want to remove that kwarg. EF 2010/04/18
1394
1390
if args :
1395
1391
kwargs ['nbins' ] = args [0 ]
1396
1392
if len (args ) > 1 :
@@ -1406,7 +1402,9 @@ def set_params(self, **kwargs):
1406
1402
if self ._nbins != 'auto' :
1407
1403
self ._nbins = int (self ._nbins )
1408
1404
if 'trim' in kwargs :
1409
- self ._trim = kwargs ['trim' ]
1405
+ warnings .warn (
1406
+ "The 'trim' keyword has no effect since version 2.0." ,
1407
+ mplDeprecation )
1410
1408
if 'integer' in kwargs :
1411
1409
self ._integer = kwargs ['integer' ]
1412
1410
if 'symmetric' in kwargs :
@@ -1429,9 +1427,9 @@ def set_params(self, **kwargs):
1429
1427
if 'integer' in kwargs :
1430
1428
self ._integer = kwargs ['integer' ]
1431
1429
if self ._integer :
1432
- self ._steps = [n for n in self ._steps if divmod (n , 1 )[1 ] < 0.001 ]
1430
+ self ._steps = [n for n in self ._steps if _divmod (n , 1 )[1 ] < 0.001 ]
1433
1431
1434
- def bin_boundaries (self , vmin , vmax ):
1432
+ def _raw_ticks (self , vmin , vmax ):
1435
1433
nbins = self ._nbins
1436
1434
if nbins == 'auto' :
1437
1435
nbins = max (min (self .axis .get_tick_space (), 9 ), 1 )
@@ -1449,23 +1447,30 @@ def bin_boundaries(self, vmin, vmax):
1449
1447
if step < scaled_raw_step :
1450
1448
continue
1451
1449
step *= scale
1452
- best_vmin = step * divmod ( vmin , step )[ 0 ]
1450
+ best_vmin = vmin // step * step
1453
1451
best_vmax = best_vmin + step * nbins
1454
- if ( best_vmax >= vmax ) :
1452
+ if best_vmax >= vmax :
1455
1453
break
1456
- if self ._trim :
1457
- extra_bins = int (divmod ((best_vmax - vmax ), step )[0 ])
1458
- nbins -= extra_bins
1459
- return (np .arange (nbins + 1 ) * step + best_vmin + offset )
1454
+
1455
+ # More than nbins may be required, e.g. vmin, vmax = -4.1, 4.1 gives
1456
+ # nbins=9 but 10 bins are actually required after rounding. So we just
1457
+ # create the bins that span the range we need instead.
1458
+ low = round (Base (step ).le (vmin - best_vmin ) / step )
1459
+ high = round (Base (step ).ge (vmax - best_vmin ) / step )
1460
+ return np .arange (low , high + 1 ) * step + best_vmin + offset
1461
+
1462
+ @cbook .deprecated ("2.0" )
1463
+ def bin_boundaries (self , vmin , vmax ):
1464
+ return self ._raw_ticks (vmin , vmax )
1460
1465
1461
1466
def __call__ (self ):
1462
1467
vmin , vmax = self .axis .get_view_interval ()
1463
1468
return self .tick_values (vmin , vmax )
1464
1469
1465
1470
def tick_values (self , vmin , vmax ):
1466
- vmin , vmax = mtransforms .nonsingular (vmin , vmax , expander = 1e-13 ,
1467
- tiny = 1e-14 )
1468
- locs = self .bin_boundaries (vmin , vmax )
1471
+ vmin , vmax = mtransforms .nonsingular (
1472
+ vmin , vmax , expander = 1e-13 , tiny = 1e-14 )
1473
+ locs = self ._raw_ticks (vmin , vmax )
1469
1474
prune = self ._prune
1470
1475
if prune == 'lower' :
1471
1476
locs = locs [1 :]
@@ -1482,11 +1487,11 @@ def view_limits(self, dmin, dmax):
1482
1487
dmin = - maxabs
1483
1488
dmax = maxabs
1484
1489
1485
- dmin , dmax = mtransforms .nonsingular (dmin , dmax , expander = 1e-12 ,
1486
- tiny = 1.e -13 )
1490
+ dmin , dmax = mtransforms .nonsingular (
1491
+ dmin , dmax , expander = 1e-12 , tiny = 1e -13 )
1487
1492
1488
1493
if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1489
- return np . take ( self .bin_boundaries (dmin , dmax ), [ 0 , - 1 ])
1494
+ return self ._raw_ticks (dmin , dmax )[[ 0 , - 1 ]]
1490
1495
else :
1491
1496
return dmin , dmax
1492
1497
0 commit comments