Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit c991a46

Browse filesBrowse files
authored
Merge pull request #26651 from meeseeksmachine/auto-backport-of-pr-26348-on-v3.8.x
Backport PR #26348 on branch v3.8.x (Test some untested Locator code)
2 parents 6e4a684 + 10504d5 commit c991a46
Copy full SHA for c991a46

File tree

2 files changed

+76
-42
lines changed
Filter options

2 files changed

+76
-42
lines changed

‎lib/matplotlib/tests/test_ticker.py

Copy file name to clipboardExpand all lines: lib/matplotlib/tests/test_ticker.py
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,38 @@ def test_integer(self, vmin, vmax, steps, expected):
3838
loc = mticker.MaxNLocator(nbins=5, integer=True, steps=steps)
3939
assert_almost_equal(loc.tick_values(vmin, vmax), expected)
4040

41+
@pytest.mark.parametrize('kwargs, errortype, match', [
42+
({'foo': 0}, TypeError,
43+
re.escape("set_params() got an unexpected keyword argument 'foo'")),
44+
({'steps': [2, 1]}, ValueError, "steps argument must be an increasing"),
45+
({'steps': 2}, ValueError, "steps argument must be an increasing"),
46+
({'steps': [2, 11]}, ValueError, "steps argument must be an increasing"),
47+
])
48+
def test_errors(self, kwargs, errortype, match):
49+
with pytest.raises(errortype, match=match):
50+
mticker.MaxNLocator(**kwargs)
51+
52+
@pytest.mark.parametrize('steps, result', [
53+
([1, 2, 10], [1, 2, 10]),
54+
([2, 10], [1, 2, 10]),
55+
([1, 2], [1, 2, 10]),
56+
([2], [1, 2, 10]),
57+
])
58+
def test_padding(self, steps, result):
59+
loc = mticker.MaxNLocator(steps=steps)
60+
assert (loc._steps == result).all()
61+
4162

4263
class TestLinearLocator:
4364
def test_basic(self):
4465
loc = mticker.LinearLocator(numticks=3)
4566
test_value = np.array([-0.8, -0.3, 0.2])
4667
assert_almost_equal(loc.tick_values(-0.8, 0.2), test_value)
4768

69+
def test_zero_numticks(self):
70+
loc = mticker.LinearLocator(numticks=0)
71+
loc.tick_values(-0.8, 0.2) == []
72+
4873
def test_set_params(self):
4974
"""
5075
Create linear locator with presets={}, numticks=2 and change it to
@@ -55,6 +80,15 @@ def test_set_params(self):
5580
assert loc.numticks == 8
5681
assert loc.presets == {(0, 1): []}
5782

83+
def test_presets(self):
84+
loc = mticker.LinearLocator(presets={(1, 2): [1, 1.25, 1.75],
85+
(0, 2): [0.5, 1.5]})
86+
assert loc.tick_values(1, 2) == [1, 1.25, 1.75]
87+
assert loc.tick_values(2, 1) == [1, 1.25, 1.75]
88+
assert loc.tick_values(0, 2) == [0.5, 1.5]
89+
assert loc.tick_values(0.0, 2.0) == [0.5, 1.5]
90+
assert (loc.tick_values(0, 1) == np.linspace(0, 1, 11)).all()
91+
5892

5993
class TestMultipleLocator:
6094
def test_basic(self):
@@ -590,6 +624,23 @@ def test_values(self, vmin, vmax, expected):
590624
ticks = sym.tick_values(vmin=vmin, vmax=vmax)
591625
assert_array_equal(ticks, expected)
592626

627+
def test_subs(self):
628+
sym = mticker.SymmetricalLogLocator(base=10, linthresh=1, subs=[2.0, 4.0])
629+
sym.create_dummy_axis()
630+
sym.axis.set_view_interval(-10, 10)
631+
assert (sym() == [-20., -40., -2., -4., 0., 2., 4., 20., 40.]).all()
632+
633+
def test_extending(self):
634+
sym = mticker.SymmetricalLogLocator(base=10, linthresh=1)
635+
sym.create_dummy_axis()
636+
sym.axis.set_view_interval(8, 9)
637+
assert (sym() == [1.0]).all()
638+
sym.axis.set_view_interval(8, 12)
639+
assert (sym() == [1.0, 10.0]).all()
640+
assert sym.view_limits(10, 10) == (1, 100)
641+
assert sym.view_limits(-10, -10) == (-100, -1)
642+
assert sym.view_limits(0, 0) == (-0.001, 0.001)
643+
593644

594645
class TestAsinhLocator:
595646
def test_init(self):

‎lib/matplotlib/ticker.py

Copy file name to clipboardExpand all lines: lib/matplotlib/ticker.py
+25-42Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -657,12 +657,12 @@ def format_data(self, value):
657657
# docstring inherited
658658
e = math.floor(math.log10(abs(value)))
659659
s = round(value / 10**e, 10)
660-
exponent = self._format_maybe_minus_and_locale("%d", e)
661660
significand = self._format_maybe_minus_and_locale(
662661
"%d" if s % 1 == 0 else "%1.10g", s)
663662
if e == 0:
664663
return significand
665-
elif self._useMathText or self._usetex:
664+
exponent = self._format_maybe_minus_and_locale("%d", e)
665+
if self._useMathText or self._usetex:
666666
exponent = "10^{%s}" % exponent
667667
return (exponent if s == 1 # reformat 1x10^y as 10^y
668668
else rf"{significand} \times {exponent}")
@@ -675,7 +675,6 @@ def get_offset(self):
675675
"""
676676
if len(self.locs) == 0:
677677
return ''
678-
s = ''
679678
if self.orderOfMagnitude or self.offset:
680679
offsetStr = ''
681680
sciNotStr = ''
@@ -694,8 +693,8 @@ def get_offset(self):
694693
s = fr'${sciNotStr}\mathdefault{{{offsetStr}}}$'
695694
else:
696695
s = ''.join((sciNotStr, offsetStr))
697-
698-
return self.fix_minus(s)
696+
return self.fix_minus(s)
697+
return ''
699698

700699
def set_locs(self, locs):
701700
# docstring inherited
@@ -1055,9 +1054,6 @@ def _non_decade_format(self, sign_string, base, fx, usetex):
10551054

10561055
def __call__(self, x, pos=None):
10571056
# docstring inherited
1058-
usetex = mpl.rcParams['text.usetex']
1059-
min_exp = mpl.rcParams['axes.formatter.min_exponent']
1060-
10611057
if x == 0: # Symlog
10621058
return r'$\mathdefault{0}$'
10631059

@@ -1070,23 +1066,25 @@ def __call__(self, x, pos=None):
10701066
is_x_decade = _is_close_to_int(fx)
10711067
exponent = round(fx) if is_x_decade else np.floor(fx)
10721068
coeff = round(b ** (fx - exponent))
1073-
if is_x_decade:
1074-
fx = round(fx)
10751069

10761070
if self.labelOnlyBase and not is_x_decade:
10771071
return ''
10781072
if self._sublabels is not None and coeff not in self._sublabels:
10791073
return ''
10801074

1075+
if is_x_decade:
1076+
fx = round(fx)
1077+
10811078
# use string formatting of the base if it is not an integer
10821079
if b % 1 == 0.0:
10831080
base = '%d' % b
10841081
else:
10851082
base = '%s' % b
10861083

1087-
if abs(fx) < min_exp:
1084+
if abs(fx) < mpl.rcParams['axes.formatter.min_exponent']:
10881085
return r'$\mathdefault{%s%g}$' % (sign_string, x)
10891086
elif not is_x_decade:
1087+
usetex = mpl.rcParams['text.usetex']
10901088
return self._non_decade_format(sign_string, base, fx, usetex)
10911089
else:
10921090
return r'$\mathdefault{%s%s^{%d}}$' % (sign_string, base, fx)
@@ -1554,7 +1552,7 @@ def symbol(self):
15541552
symbol = self._symbol
15551553
if not symbol:
15561554
symbol = ''
1557-
elif mpl.rcParams['text.usetex'] and not self._is_latex:
1555+
elif not self._is_latex and mpl.rcParams['text.usetex']:
15581556
# Source: http://www.personal.ceu.hu/tex/specchar.htm
15591557
# Backslash must be first for this to work correctly since
15601558
# it keeps getting added in
@@ -1801,8 +1799,6 @@ def __call__(self):
18011799

18021800
def tick_values(self, vmin, vmax):
18031801
vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander=0.05)
1804-
if vmax < vmin:
1805-
vmin, vmax = vmax, vmin
18061802

18071803
if (vmin, vmax) in self.presets:
18081804
return self.presets[(vmin, vmax)]
@@ -2356,13 +2352,13 @@ def tick_values(self, vmin, vmax):
23562352
numdec = math.floor(log_vmax) - math.ceil(log_vmin)
23572353

23582354
if isinstance(self._subs, str):
2359-
_first = 2.0 if self._subs == 'auto' else 1.0
23602355
if numdec > 10 or b < 3:
23612356
if self._subs == 'auto':
23622357
return np.array([]) # no minor or major ticks
23632358
else:
23642359
subs = np.array([1.0]) # major ticks
23652360
else:
2361+
_first = 2.0 if self._subs == 'auto' else 1.0
23662362
subs = np.arange(_first, b)
23672363
else:
23682364
subs = self._subs
@@ -2386,23 +2382,14 @@ def tick_values(self, vmin, vmax):
23862382
decades = np.arange(math.floor(log_vmin) - stride,
23872383
math.ceil(log_vmax) + 2 * stride, stride)
23882384

2389-
if hasattr(self, '_transform'):
2390-
ticklocs = self._transform.inverted().transform(decades)
2391-
if have_subs:
2392-
if stride == 1:
2393-
ticklocs = np.ravel(np.outer(subs, ticklocs))
2394-
else:
2395-
# No ticklocs if we have >1 decade between major ticks.
2396-
ticklocs = np.array([])
2397-
else:
2398-
if have_subs:
2399-
if stride == 1:
2400-
ticklocs = np.concatenate(
2401-
[subs * decade_start for decade_start in b ** decades])
2402-
else:
2403-
ticklocs = np.array([])
2385+
if have_subs:
2386+
if stride == 1:
2387+
ticklocs = np.concatenate(
2388+
[subs * decade_start for decade_start in b ** decades])
24042389
else:
2405-
ticklocs = b ** decades
2390+
ticklocs = np.array([])
2391+
else:
2392+
ticklocs = b ** decades
24062393

24072394
_log.debug('ticklocs %r', ticklocs)
24082395
if (len(subs) > 1
@@ -2422,8 +2409,8 @@ def view_limits(self, vmin, vmax):
24222409
vmin, vmax = self.nonsingular(vmin, vmax)
24232410

24242411
if mpl.rcParams['axes.autolimit_mode'] == 'round_numbers':
2425-
vmin = _decade_less_equal(vmin, self._base)
2426-
vmax = _decade_greater_equal(vmax, self._base)
2412+
vmin = _decade_less_equal(vmin, b)
2413+
vmax = _decade_greater_equal(vmax, b)
24272414

24282415
return vmin, vmax
24292416

@@ -2503,7 +2490,6 @@ def __call__(self):
25032490
return self.tick_values(vmin, vmax)
25042491

25052492
def tick_values(self, vmin, vmax):
2506-
base = self._base
25072493
linthresh = self._linthresh
25082494

25092495
if vmax < vmin:
@@ -2540,6 +2526,8 @@ def tick_values(self, vmin, vmax):
25402526
# Check if linear range is present
25412527
has_b = (has_a and vmax > -linthresh) or (has_c and vmin < linthresh)
25422528

2529+
base = self._base
2530+
25432531
def get_log_range(lo, hi):
25442532
lo = np.floor(np.log(lo) / np.log(base))
25452533
hi = np.ceil(np.log(hi) / np.log(base))
@@ -2573,11 +2561,7 @@ def get_log_range(lo, hi):
25732561
if has_c:
25742562
decades.extend(base ** (np.arange(c_lo, c_hi, stride)))
25752563

2576-
# Add the subticks if requested
2577-
if self._subs is None:
2578-
subs = np.arange(2.0, base)
2579-
else:
2580-
subs = np.asarray(self._subs)
2564+
subs = np.asarray(self._subs)
25812565

25822566
if len(subs) > 1 or subs[0] != 1.0:
25832567
ticklocs = []
@@ -2604,8 +2588,7 @@ def view_limits(self, vmin, vmax):
26042588
vmin = _decade_less(vmin, b)
26052589
vmax = _decade_greater(vmax, b)
26062590

2607-
result = mtransforms.nonsingular(vmin, vmax)
2608-
return result
2591+
return mtransforms.nonsingular(vmin, vmax)
26092592

26102593

26112594
class AsinhLocator(Locator):
@@ -2773,7 +2756,7 @@ def tick_values(self, vmin, vmax):
27732756
# linscale: ... 1e-3 1e-2 1e-1 1/2 1-1e-1 1-1e-2 1-1e-3 ...
27742757
# b-scale : ... -3 -2 -1 0 1 2 3 ...
27752758
def ideal_ticks(x):
2776-
return 10 ** x if x < 0 else 1 - (10 ** (-x)) if x > 0 else 1 / 2
2759+
return 10 ** x if x < 0 else 1 - (10 ** (-x)) if x > 0 else 0.5
27772760

27782761
vmin, vmax = self.nonsingular(vmin, vmax)
27792762
binf = int(

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.