@@ -1603,7 +1603,9 @@ def __init__(self, *args, **kwargs):
1603
1603
e.g., [1, 2, 4, 5, 10]
1604
1604
1605
1605
*integer*
1606
- If True, ticks will take only integer values.
1606
+ If True, ticks will take only integer values, provided
1607
+ at least `min_n_ticks` integers are found within the
1608
+ view limits.
1607
1609
1608
1610
*symmetric*
1609
1611
If True, autoscaling will result in a range symmetric
@@ -1613,16 +1615,16 @@ def __init__(self, *args, **kwargs):
1613
1615
['lower' | 'upper' | 'both' | None]
1614
1616
Remove edge ticks -- useful for stacked or ganged plots
1615
1617
where the upper tick of one axes overlaps with the lower
1616
- tick of the axes above it.
1617
- If prune=='lower', the smallest tick will
1618
- be removed. If prune=='upper', the largest tick will be
1619
- removed. If prune=='both', the largest and smallest ticks
1620
- will be removed. If prune==None, no ticks will be removed.
1618
+ tick of the axes above it, primarily when
1619
+ `rcParams['axes.autolimit_mode']` is `'round_numbers'`.
1620
+ If `prune=='lower'`, the smallest tick will
1621
+ be removed. If `prune=='upper'`, the largest tick will be
1622
+ removed. If `prune=='both'`, the largest and smallest ticks
1623
+ will be removed. If `prune==None`, no ticks will be removed.
1621
1624
1622
1625
*min_n_ticks*
1623
- While the estimated number of ticks is less than the minimum,
1624
- the target value *nbins* is incremented and the ticks are
1625
- recalculated.
1626
+ Relax `nbins` and `integer` constraints if necessary to
1627
+ obtain this minimum number of ticks.
1626
1628
1627
1629
"""
1628
1630
if args :
@@ -1643,8 +1645,6 @@ def set_params(self, **kwargs):
1643
1645
warnings .warn (
1644
1646
"The 'trim' keyword has no effect since version 2.0." ,
1645
1647
mplDeprecation )
1646
- if 'integer' in kwargs :
1647
- self ._integer = kwargs ['integer' ]
1648
1648
if 'symmetric' in kwargs :
1649
1649
self ._symmetric = kwargs ['symmetric' ]
1650
1650
if 'prune' in kwargs :
@@ -1662,6 +1662,13 @@ def set_params(self, **kwargs):
1662
1662
steps = list (steps )
1663
1663
steps .append (10 )
1664
1664
self ._steps = steps
1665
+ # Make an extended staircase within which the needed
1666
+ # step will be found. This is probably much larger
1667
+ # than necessary.
1668
+ flights = (0.1 * np .array (self ._steps [:- 1 ]),
1669
+ self ._steps ,
1670
+ [10 * self ._steps [1 ]])
1671
+ self ._extended_steps = np .hstack (flights )
1665
1672
if 'integer' in kwargs :
1666
1673
self ._integer = kwargs ['integer' ]
1667
1674
if self ._integer :
@@ -1676,42 +1683,38 @@ def _raw_ticks(self, vmin, vmax):
1676
1683
else :
1677
1684
nbins = self ._nbins
1678
1685
1679
- while True :
1680
- ticks = self ._try_raw_ticks (vmin , vmax , nbins )
1686
+ scale , offset = scale_range (vmin , vmax , nbins )
1687
+ _vmin = vmin - offset
1688
+ _vmax = vmax - offset
1689
+ raw_step = (vmax - vmin ) / nbins
1690
+ steps = self ._extended_steps * scale
1691
+ istep = np .nonzero (steps >= raw_step )[0 ][0 ]
1692
+
1693
+ # Classic round_numbers mode may require a larger step.
1694
+ if rcParams ['axes.autolimit_mode' ] == 'round_numbers' :
1695
+ for istep in range (istep , len (steps )):
1696
+ step = steps [istep ]
1697
+ best_vmin = (_vmin // step ) * step
1698
+ best_vmax = best_vmin + step * nbins
1699
+ if (best_vmax >= _vmax ):
1700
+ break
1701
+
1702
+ # This is an upper limit; move to smaller steps if necessary.
1703
+ for i in range (istep ):
1704
+ step = steps [istep - i ]
1705
+ if (self ._integer and
1706
+ np .floor (_vmax ) - np .ceil (_vmin ) > self ._min_n_ticks - 1 ):
1707
+ step = max (1 , step )
1708
+ best_vmin = (_vmin // step ) * step
1709
+
1710
+ low = round (Base (step ).le (_vmin - best_vmin ) / step )
1711
+ high = round (Base (step ).ge (_vmax - best_vmin ) / step )
1712
+ ticks = np .arange (low , high + 1 ) * step + best_vmin + offset
1681
1713
nticks = ((ticks <= vmax ) & (ticks >= vmin )).sum ()
1682
1714
if nticks >= self ._min_n_ticks :
1683
1715
break
1684
- nbins += 1
1685
-
1686
- self ._nbins_used = nbins # Maybe useful for troubleshooting.
1687
1716
return ticks
1688
1717
1689
- def _try_raw_ticks (self , vmin , vmax , nbins ):
1690
- scale , offset = scale_range (vmin , vmax , nbins )
1691
- if self ._integer :
1692
- scale = max (1 , scale )
1693
- vmin = vmin - offset
1694
- vmax = vmax - offset
1695
- raw_step = (vmax - vmin ) / nbins
1696
- scaled_raw_step = raw_step / scale
1697
- best_vmax = vmax
1698
- best_vmin = vmin
1699
-
1700
- steps = (x for x in self ._steps if x >= scaled_raw_step )
1701
- for step in steps :
1702
- step *= scale
1703
- best_vmin = vmin // step * step
1704
- best_vmax = best_vmin + step * nbins
1705
- if best_vmax >= vmax :
1706
- break
1707
-
1708
- # More than nbins may be required, e.g. vmin, vmax = -4.1, 4.1 gives
1709
- # nbins=9 but 10 bins are actually required after rounding. So we just
1710
- # create the bins that span the range we need instead.
1711
- low = round (Base (step ).le (vmin - best_vmin ) / step )
1712
- high = round (Base (step ).ge (vmax - best_vmin ) / step )
1713
- return np .arange (low , high + 1 ) * step + best_vmin + offset
1714
-
1715
1718
@cbook .deprecated ("2.0" )
1716
1719
def bin_boundaries (self , vmin , vmax ):
1717
1720
return self ._raw_ticks (vmin , vmax )
0 commit comments