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
@@ -1323,23 +1333,12 @@ 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, vma
10000
x should have been checked by nonsingular(),
1331
- # and spread apart if necessary.
1332
- meanv = 0.5 * (vmax + vmin )
1333
- if abs (meanv ) / dv < threshold :
1334
- offset = 0
1335
- elif meanv > 0 :
1336
- ex = divmod (math .log10 (meanv ), 1 )[0 ]
1337
- offset = 10 ** ex
1338
- 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
1336
+ dv = abs (vmax - vmin ) # > 0 as nonsingular is called before.
1337
+ meanv = (vmax + vmin ) / 2
1338
+ offset = (math .copysign (10 ** (math .log10 (abs (meanv )) // 1 ), meanv )
1339
+ if abs (meanv ) / dv >= threshold
1340
+ else 0 )
1341
+ scale = 10 ** (math .log10 (dv / n ) // 1 )
1343
1342
return scale , offset
1344
1343
1345
1344
@@ -1349,7 +1348,6 @@ class MaxNLocator(Locator):
1349
1348
"""
1350
1349
default_params = dict (nbins = 10 ,
1351
1350
steps = None ,
1352
- trim = True ,
1353
1351
integer = False ,
1354
1352
symmetric = False ,
1355
1353
prune = None )
@@ -1385,9 +1383,6 @@ def __init__(self, *args, **kwargs):
1385
1383
will be removed. If prune==None, no ticks will be removed.
1386
1384
1387
1385
"""
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
1386
if args :
1392
1387
kwargs ['nbins' ] = args [0 ]
1393
1388
if len (args ) > 1 :
@@ -1403,7 +1398,8 @@ def set_params(self, **kwargs):
1403
1398
if self ._nbins != 'auto' :
1404
1399
self ._nbins = int (self ._nbins )
1405
1400
if 'trim' in kwargs :
1406
- self ._trim = kwargs ['trim' ]
1401
+ warnings .warn ("The 'trim' keyword has no effect anymore" ,
1402
+ mplDeprecation )
1407
1403
if 'integer' in kwargs :
1408
1404
self ._integer = kwargs ['integer' ]
1409
1405
if 'symmetric' in kwargs :
@@ -1428,7 +1424,7 @@ def set_params(self, **kwargs):
1428
1424
if self ._integer :
1429
1425
self ._steps = [n for n in self ._steps if divmod (n , 1 )[1 ] < 0.001 ]
1430
1426
1431
- def bin_boundaries (self , vmin , vmax ):
1427
+ def _raw_ticks (self , vmin , vmax ):
1432
1428
nbins = self ._nbins
1433
1429
if nbins == 'auto' :
1434
1430
nbins = self .axis .get_tick_space ()
@@ -1446,23 +1442,26 @@ def bin_boundaries(self, vmin, vmax):
1446
1442
if step < scaled_raw_step :
1447
1443
continue
1448
1444
step *= scale
1449
- best_vmin = step * divmod ( vmin , step )[ 0 ]
1445
+ best_vmin = vmin // step * step
1450
1446
best_vmax = best_vmin + step * nbins
1451
- if ( best_vmax >= vmax ) :
1447
+ if best_vmax >= vmax :
1452
1448
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 )
1449
+
1450
+ # More than nbins may be required, e.g. vmin, vmax = -4.1, 4.1 gives
1451
+ # nbins=9 but 10 bins are actually required after rounding. So we just
1452
+ # create the bins that span the range we need instead.
1453
+ low = round (Base (step ).le (vmin - best_vmin ) / step )
1454
+ high = round (Base (step ).ge (vmax - best_vmin ) / step )
1455
+ return np .arange (low , high + 1 ) * step + best_vmin + offset
1457
1456
1458
1457
def __call__ (self ):
1459
1458
vmin , vmax = self .axis .get_view_interval ()
1460
1459
return self .tick_values (vmin , vmax )
1461
1460
1462
1461
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 )
1462
+ vmin , vmax = mtransforms .nonsingular (
1463
+ vmin , vmax , expander = 1e-13 , tiny = 1e-14 )
1464
+ locs = self ._raw_ticks (vmin , vmax )
1466
1465
prune = self ._prune
1467
1466
if prune == 'lower' :
1468
1467
locs = locs [1 :]
@@ -1479,11 +1478,11 @@ def view_limits(self, dmin, dmax):
1479
1478
dmin = - maxabs
1480
1479
dmax = maxabs
1481
1480
1482
- dmin , dmax = mtransforms .nonsingular (dmin , dmax , expander = 1e-12 ,
1483
- tiny = 1.e -13 )
1481
+ dmin , dmax = mtransforms .nonsingular (
1482
+ dmin , dmax , expander = 1e-12 , tiny = 1e -13 )
1484
1483
1485
1484
if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1486
- return np . take ( self .bin_boundaries (dmin , dmax ), [ 0 , - 1 ])
1485
+ return self ._raw_ticks (dmin , dmax )[[ 0 , - 1 ]]
1487
1486
else :
1488
1487
return dmin , dmax
1489
1488
0 commit comments