Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cdbe7e5

Browse files
committed
Test some untested Locator code and code improvements
1 parent 4dbba98 commit cdbe7e5

File tree

2 files changed

+78
-42
lines changed

2 files changed

+78
-42
lines changed

lib/matplotlib/tests/test_ticker.py

Lines changed: 53 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,25 @@ 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+
fig, ax = plt.subplots()
629+
sym = mticker.SymmetricalLogLocator(base=10, linthresh=1, subs=[2.0, 4.0])
630+
ax.xaxis.set_major_locator(sym)
631+
ax.set_xlim(-10, 10)
632+
assert (sym() == [-20., -40., -2., -4., 0., 2., 4., 20., 40.]).all()
633+
634+
def test_extending(self):
635+
fig, ax = plt.subplots()
636+
sym = mticker.SymmetricalLogLocator(base=10, linthresh=1)
637+
ax.xaxis.set_major_locator(sym)
638+
ax.set_xlim(8, 9)
639+
assert (sym() == [1.0]).all()
640+
ax.set_xlim(8, 12)
641+
assert (sym() == [1.0, 10.0]).all()
642+
assert sym.view_limits(10, 10) == (1, 100)
643+
assert sym.view_limits(-10, -10) == (-100, -1)
644+
assert sym.view_limits(0, 0) == (-0.001, 0.001)
645+
593646

594647
class TestAsinhLocator:
595648
def test_init(self):

lib/matplotlib/ticker.py

Lines 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)