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

Skip to content

Commit 98e670d

Browse files
committed
logitscale: tests, creation of TestLogitFormatter
1 parent 584705e commit 98e670d

1 file changed

Lines changed: 179 additions & 0 deletions

File tree

lib/matplotlib/tests/test_ticker.py

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import warnings
2+
import re
23

34
import numpy as np
45
from numpy.testing import assert_almost_equal, assert_array_equal
@@ -788,6 +789,184 @@ def test_LogFormatter_call(self, val):
788789
assert temp_lf(val) == str(val)
789790

790791

792+
class TestLogitFormatter:
793+
@staticmethod
794+
def logit_deformatter(string):
795+
r"""
796+
Parser to convert string as r'$\mathdefault{1.41\cdot10^{-4}}$' in
797+
float 1.41e-4, as '0.5' or as r'$\mathdefault{\frac{1}{2}}$' in float
798+
0.5,
799+
"""
800+
match = re.match(
801+
r"[^\d]*"
802+
r"(?P<comp>1-)?"
803+
r"(?P<mant>\d*\.?\d*)?"
804+
r"(?:\\cdot)?"
805+
r"(?:10\^\{(?P<expo>-?\d*)})?"
806+
r"[^\d]*$",
807+
string,
808+
)
809+
if match:
810+
comp = match["comp"] is not None
811+
mantissa = float(match["mant"]) if match["mant"] else 1
812+
expo = int(match["expo"]) if match["expo"] is not None else 0
813+
value = mantissa * 10 ** expo
814+
if match["mant"] or match["expo"] is not None:
815+
if comp:
816+
return 1 - value
817+
return value
818+
match = re.match(
819+
r"[^\d]*\\frac\{(?P<num>\d+)\}\{(?P<deno>\d+)\}[^\d]*$", string
820+
)
821+
if match:
822+
num, deno = float(match["num"]), float(match["deno"])
823+
return num / deno
824+
raise ValueError("not formatted by LogitFormatter")
825+
826+
@pytest.mark.parametrize(
827+
"fx, x",
828+
[
829+
(r"STUFF0.41OTHERSTUFF", 0.41),
830+
(r"STUFF1.41\cdot10^{-2}OTHERSTUFF", 1.41e-2),
831+
(r"STUFF1-0.41OTHERSTUFF", 1 - 0.41),
832+
(r"STUFF1-1.41\cdot10^{-2}OTHERSTUFF", 1 - 1.41e-2),
833+
(r"STUFF", None),
834+
(r"STUFF12.4e-3OTHERSTUFF", None),
835+
],
836+
)
837+
def test_logit_deformater(self, fx, x):
838+
if x is None:
839+
with pytest.raises(ValueError):
840+
TestLogitFormatter.logit_deformatter(fx)
841+
else:
842+
y = TestLogitFormatter.logit_deformatter(fx)
843+
assert _LogitHelper.isclose(x, y)
844+
845+
decade_test = sorted(
846+
[10 ** (-i) for i in range(1, 10)]
847+
+ [1 - 10 ** (-i) for i in range(1, 10)]
848+
+ [1 / 2]
849+
)
850+
851+
@pytest.mark.parametrize("x", decade_test)
852+
def test_basic(self, x):
853+
"""
854+
Test the formatted value correspond to the value for ideal ticks in
855+
logit space.
856+
"""
857+
formatter = mticker.LogitFormatter(use_overline=False)
858+
formatter.set_locs(self.decade_test)
859+
s = formatter(x)
860+
x2 = TestLogitFormatter.logit_deformatter(s)
861+
assert _LogitHelper.isclose(x, x2)
862+
863+
@pytest.mark.parametrize("x", (-1, -0.5, -0.1, 1.1, 1.5, 2))
864+
def test_invalid(self, x):
865+
"""
866+
Test that invalid value are formatted with empty string without
867+
raising exception.
868+
"""
869+
formatter = mticker.LogitFormatter(use_overline=False)
870+
formatter.set_locs(self.decade_test)
871+
s = formatter(x)
872+
assert s == ""
873+
874+
@pytest.mark.parametrize("x", 1 / (1 + np.exp(-np.linspace(-7, 7, 10))))
875+
def test_variablelength(self, x):
876+
"""
877+
The format length should change depending on the neighbor labels.
878+
"""
879+
formatter = mticker.LogitFormatter(use_overline=False)
880+
for N in (10, 20, 50, 100, 200, 1000, 2000, 5000, 10000):
881+
if x + 1 / N < 1:
882+
formatter.set_locs([x - 1 / N, x, x + 1 / N])
883+
sx = formatter(x)
884+
sx1 = formatter(x + 1 / N)
885+
d = (
886+
TestLogitFormatter.logit_deformatter(sx1)
887+
- TestLogitFormatter.logit_deformatter(sx)
888+
)
889+
assert 0 < d < 2 / N
890+
891+
lims_minor_major = [
892+
(True, (5e-8, 1 - 5e-8), ((25, False), (75, False))),
893+
(True, (5e-5, 1 - 5e-5), ((25, False), (75, True))),
894+
(True, (5e-2, 1 - 5e-2), ((25, True), (75, True))),
895+
(False, (0.75, 0.76, 0.77), ((7, True), (25, True), (75, True))),
896+
]
897+
898+
@pytest.mark.parametrize("method, lims, cases", lims_minor_major)
899+
def test_minor_vs_major(self, method, lims, cases):
900+
"""
901+
Test minor/major displays.
902+
"""
903+
904+
if method:
905+
min_loc = mticker.LogitLocator(minor=True)
906+
ticks = min_loc.tick_values(*lims)
907+
else:
908+
ticks = np.array(lims)
909+
min_form = mticker.LogitFormatter(minor=True)
910+
for threshold, has_minor in cases:
911+
min_form.set_minor_threshold(threshold)
912+
formatted = min_form.format_ticks(ticks)
913+
labelled = [f for f in formatted if len(f) > 0]
914+
if has_minor:
915+
assert len(labelled) > 0, (threshold, has_minor)
916+
else:
917+
assert len(labelled) == 0, (threshold, has_minor)
918+
919+
def test_minor_number(self):
920+
"""
921+
Test the parameter minor_number
922+
"""
923+
min_loc = mticker.LogitLocator(minor=True)
924+
min_form = mticker.LogitFormatter(minor=True)
925+
ticks = min_loc.tick_values(5e-2, 1 - 5e-2)
926+
for minor_number in (2, 4, 8, 16):
927+
min_form.set_minor_number(minor_number)
928+
formatted = min_form.format_ticks(ticks)
929+
labelled = [f for f in formatted if len(f) > 0]
930+
assert len(labelled) == minor_number
931+
932+
def test_use_overline(self):
933+
"""
934+
Test the parameter use_overline
935+
"""
936+
x = 1 - 1e-2
937+
fx1 = r"$\mathdefault{1-10^{-2}}$"
938+
fx2 = r"$\mathdefault{\overline{10^{-2}}}$"
939+
form = mticker.LogitFormatter(use_overline=False)
940+
assert form(x) == fx1
941+
form.use_overline(True)
942+
assert form(x) == fx2
943+
form.use_overline(False)
944+
assert form(x) == fx1
945+
946+
def test_one_half(self):
947+
"""
948+
Test the parameter one_half
949+
"""
950+
form = mticker.LogitFormatter()
951+
assert r"\frac{1}{2}" in form(1/2)
952+
form.set_one_half("1/2")
953+
assert "1/2" in form(1/2)
954+
form.set_one_half("one half")
955+
assert "one half" in form(1/2)
956+
957+
@pytest.mark.parametrize("N", (100, 253, 754))
958+
def test_format_data_short(self, N):
959+
locs = np.linspace(0, 1, N)[1:-1]
960+
form = mticker.LogitFormatter()
961+
for x in locs:
962+
fx = form.format_data_short(x)
963+
if fx.startswith("1-"):
964+
x2 = 1 - float(fx[2:])
965+
else:
966+
x2 = float(fx)
967+
assert np.abs(x - x2) < 1 / N
968+
969+
791970
class TestFormatStrFormatter:
792971
def test_basic(self):
793972
# test % style formatter

0 commit comments

Comments
 (0)