@@ -1564,7 +1564,9 @@ def __init__(self, *args, **kwargs):
1564
1564
e.g., [1, 2, 4, 5, 10]
1565
1565
1566
1566
*integer*
1567
- If True, ticks will take only integer values.
1567
+ If True, ticks will take only integer values, provided
1568
+ at least `min_n_ticks` integers are found within the
1569
+ view limits.
1568
1570
1569
1571
*symmetric*
1570
1572
If True, autoscaling will result in a range symmetric
@@ -1574,16 +1576,16 @@ def __init__(self, *args, **kwargs):
1574
1576
['lower' | 'upper' | 'both' | None]
1575
1577
Remove edge ticks -- useful for stacked or ganged plots
1576
1578
where the upper tick of one axes overlaps with the lower
1577
- tick of the axes above it.
1578
- If prune=='lower', the smallest tick will
1579
- be removed. If prune=='upper', the largest tick will be
1580
- removed. If prune=='both', the largest and smallest ticks
1581
- will be removed. If prune==None, no ticks will be removed.
1579
+ tick of the axes above it, primarily when
1580
+ `rcParams['axes.autolimit_mode']` is `'round_numbers'`.
1581
+ If `prune=='lower'`, the smallest tick will
1582
+ be removed. If `prune=='upper'`, the largest tick will be
1583
+ removed. If `prune=='both'`, the largest and smallest ticks
1584
+ will be removed. If `prune==None`, no ticks will be removed.
1582
1585
1583
1586
*min_n_ticks*
1584
- While the estimated number of ticks is less than the minimum,
1585
- the target value *nbins* is incremented and the ticks are
1586
- recalculated.
1587
+ Relax `nbins` and `integer` constraints if necessary to
1588
+ obtain this minimum number of ticks.
1587
1589
1588
1590
"""
1589
1591
if args :
@@ -1604,8 +1606,6 @@ def set_params(self, **kwargs):
1604
1606
warnings .warn (
1605
1607
"The 'trim' keyword has no effect since version 2.0." ,
1606
1608
mplDeprecation )
1607
- if 'integer' in kwargs :
1608
- self ._integer = kwargs ['integer' ]
1609
1609
if 'symmetric' in kwargs :
1610
1610
self ._symmetric = kwargs ['symmetric' ]
1611
1611
if 'prune' in kwargs :
@@ -1623,6 +1623,13 @@ def set_params(self, **kwargs):
1623
1623
steps = list (steps )
1624
1624
steps .append (10 )
1625
1625
self ._steps = steps
1626
+ # Make an extended staircase within which the needed
1627
+ # step will be found. This is probably much larger
1628
+ # than necessary.
1629
+ flights = (0.1 * np .array (self ._steps [:- 1 ]),
1630
+ self ._steps ,
1631
+ [10 * self ._steps [1 ]])
1632
+ self ._extended_steps = np .hstack (flights )
1626
1633
if 'integer' in kwargs :
1627
1634
self ._integer = kwargs ['integer' ]
1628
1635
if self ._integer :
@@ -1637,42 +1644,38 @@ def _raw_ticks(self, vmin, vmax):
1637
1644
else :
1638
1645
nbins = self ._nbins
1639
1646
1640
- while True :
1641
- ticks = self ._try_raw_ticks (vmin , vmax , nbins )
1647
+ scale , offset = scale_range (vmin , vmax , nbins )
1648
+ _vmin = vmin - offset
1649
+ _vmax = vmax - offset
1650
+ raw_step = (vmax - vmin ) / nbins
1651
+ steps = self ._extended_steps * scale
1652
+ istep = np .nonzero (steps >= raw_step )[0 ][0 ]
1653
+
1654
+ # Classic round_numbers mode may require a larger step.
1655
+ if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1656
+ for istep in range (istep , len (steps )):
1657
+ step = steps [istep ]
1658
+ best_vmin = (_vmin // step ) * step
1659
+ best_vmax = best_vmin + step * nbins
1660
+ if (best_vmax >= _vmax ):
1661
+ break
1662
+
1663
+ # This is an upper limit; move to smaller steps if necessary.
1664
+ for i in range (istep ):
1665
+ step = steps [istep - i ]
1666
+ if (self ._integer and
1667
+ np .floor (_vmax ) - np .ceil (_vmin ) >= self ._min_n_ticks - 1 ):
1668
+ step = max (1 , step )
1669
+ best_vmin = (_vmin // step ) * step
1670
+
1671
+ low = round (Base (step ).le (_vmin - best_vmin ) / step )
1672
+ high = round (Base (step ).ge (_vmax - best_vmin ) / step )
1673
+ ticks = np .arange (low , high + 1 ) * step + best_vmin + offset
1642
1674
nticks = ((ticks <= vmax ) & (ticks >= vmin )).sum ()
1643
1675
if nticks >= self ._min_n_ticks :
1644
1676
break
1645
- nbins += 1
1646
-
1647
- self ._nbins_used = nbins # Maybe useful for troubleshooting.
1648
1677
return ticks
1649
1678
1650
- def _try_raw_ticks (self , vmin , vmax , nbins ):
1651
- scale , offset = scale_range (vmin , vmax , nbins )
1652
- if self ._integer :
1653
- scale = max (1 , scale )
1654
- vmin = vmin - offset
1655
- vmax = vmax - offset
1656
- raw_step = (vmax - vmin ) / nbins
1657
- scaled_raw_step = raw_step / scale
1658
- best_vmax = vmax
1659
- best_vmin = vmin
1660
-
1661
- steps = (x for x in self ._steps if x >= scaled_raw_step )
1662
- for step in steps :
1663
- step *= scale
1664
- best_vmin = vmin // step * step
1665
- best_vmax = best_vmin + step * nbins
1666
- if best_vmax >= vmax :
1667
- break
1668
-
1669
- # More than nbins may be required, e.g. vmin, vmax = -4.1, 4.1 gives
1670
- # nbins=9 but 10 bins are actually required after rounding. So we just
1671
- # create the bins that span the range we need instead.
1672
- low = round (Base (step ).le (vmin - best_vmin ) / step )
1673
- high = round (Base (step ).ge (vmax - best_vmin ) / step )
1674
- return np .arange (low , high + 1 ) * step + best_vmin + offset
1675
-
1676
1679
@cbook .deprecated ("2.0" )
1677
1680
def bin_boundaries (self , vmin , vmax ):
1678
1681
return self ._raw_ticks (vmin , vmax )
0 commit comments