File: test_angle_helper.py

package info (click to toggle)
matplotlib 3.10.7%2Bdfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 72,816 kB
  • sloc: python: 147,545; cpp: 62,988; objc: 1,679; ansic: 1,426; javascript: 788; makefile: 92; sh: 53
file content (141 lines) | stat: -rw-r--r-- 5,670 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import re

import numpy as np
import pytest

from mpl_toolkits.axisartist.angle_helper import (
    FormatterDMS, FormatterHMS, select_step, select_step24, select_step360)


_MS_RE = (
    r'''\$  # Mathtext
        (
            # The sign sometimes appears on a 0 when a fraction is shown.
            # Check later that there's only one.
            (?P<degree_sign>-)?
            (?P<degree>[0-9.]+)  # Degrees value
            {degree}  # Degree symbol (to be replaced by format.)
        )?
        (
            (?(degree)\\,)  # Separator if degrees are also visible.
            (?P<minute_sign>-)?
            (?P<minute>[0-9.]+)  # Minutes value
            {minute}  # Minute symbol (to be replaced by format.)
        )?
        (
            (?(minute)\\,)  # Separator if minutes are also visible.
            (?P<second_sign>-)?
            (?P<second>[0-9.]+)  # Seconds value
            {second}  # Second symbol (to be replaced by format.)
        )?
        \$  # Mathtext
    '''
)
DMS_RE = re.compile(_MS_RE.format(degree=re.escape(FormatterDMS.deg_mark),
                                  minute=re.escape(FormatterDMS.min_mark),
                                  second=re.escape(FormatterDMS.sec_mark)),
                    re.VERBOSE)
HMS_RE = re.compile(_MS_RE.format(degree=re.escape(FormatterHMS.deg_mark),
                                  minute=re.escape(FormatterHMS.min_mark),
                                  second=re.escape(FormatterHMS.sec_mark)),
                    re.VERBOSE)


def dms2float(degrees, minutes=0, seconds=0):
    return degrees + minutes / 60.0 + seconds / 3600.0


@pytest.mark.parametrize('args, kwargs, expected_levels, expected_factor', [
    ((-180, 180, 10), {'hour': False}, np.arange(-180, 181, 30), 1.0),
    ((-12, 12, 10), {'hour': True}, np.arange(-12, 13, 2), 1.0)
])
def test_select_step(args, kwargs, expected_levels, expected_factor):
    levels, n, factor = select_step(*args, **kwargs)

    assert n == len(levels)
    np.testing.assert_array_equal(levels, expected_levels)
    assert factor == expected_factor


@pytest.mark.parametrize('args, kwargs, expected_levels, expected_factor', [
    ((-180, 180, 10), {}, np.arange(-180, 181, 30), 1.0),
    ((-12, 12, 10), {}, np.arange(-750, 751, 150), 60.0)
])
def test_select_step24(args, kwargs, expected_levels, expected_factor):
    levels, n, factor = select_step24(*args, **kwargs)

    assert n == len(levels)
    np.testing.assert_array_equal(levels, expected_levels)
    assert factor == expected_factor


@pytest.mark.parametrize('args, kwargs, expected_levels, expected_factor', [
    ((dms2float(20, 21.2), dms2float(21, 33.3), 5), {},
     np.arange(1215, 1306, 15), 60.0),
    ((dms2float(20.5, seconds=21.2), dms2float(20.5, seconds=33.3), 5), {},
     np.arange(73820, 73835, 2), 3600.0),
    ((dms2float(20, 21.2), dms2float(20, 53.3), 5), {},
     np.arange(1220, 1256, 5), 60.0),
    ((21.2, 33.3, 5), {},
     np.arange(20, 35, 2), 1.0),
    ((dms2float(20, 21.2), dms2float(21, 33.3), 5), {},
     np.arange(1215, 1306, 15), 60.0),
    ((dms2float(20.5, seconds=21.2), dms2float(20.5, seconds=33.3), 5), {},
     np.arange(73820, 73835, 2), 3600.0),
    ((dms2float(20.5, seconds=21.2), dms2float(20.5, seconds=21.4), 5), {},
     np.arange(7382120, 7382141, 5), 360000.0),
    # test threshold factor
    ((dms2float(20.5, seconds=11.2), dms2float(20.5, seconds=53.3), 5),
     {'threshold_factor': 60}, np.arange(12301, 12310), 600.0),
    ((dms2float(20.5, seconds=11.2), dms2float(20.5, seconds=53.3), 5),
     {'threshold_factor': 1}, np.arange(20502, 20517, 2), 1000.0),
])
def test_select_step360(args, kwargs, expected_levels, expected_factor):
    levels, n, factor = select_step360(*args, **kwargs)

    assert n == len(levels)
    np.testing.assert_array_equal(levels, expected_levels)
    assert factor == expected_factor


@pytest.mark.parametrize('Formatter, regex',
                         [(FormatterDMS, DMS_RE),
                          (FormatterHMS, HMS_RE)],
                         ids=['Degree/Minute/Second', 'Hour/Minute/Second'])
@pytest.mark.parametrize('direction, factor, values', [
    ("left", 60, [0, -30, -60]),
    ("left", 600, [12301, 12302, 12303]),
    ("left", 3600, [0, -30, -60]),
    ("left", 36000, [738210, 738215, 738220]),
    ("left", 360000, [7382120, 7382125, 7382130]),
    ("left", 1., [45, 46, 47]),
    ("left", 10., [452, 453, 454]),
])
def test_formatters(Formatter, regex, direction, factor, values):
    fmt = Formatter()
    result = fmt(direction, factor, values)

    prev_degree = prev_minute = prev_second = None
    for tick, value in zip(result, values):
        m = regex.match(tick)
        assert m is not None, f'{tick!r} is not an expected tick format.'

        sign = sum(m.group(sign + '_sign') is not None
                   for sign in ('degree', 'minute', 'second'))
        assert sign <= 1, f'Only one element of tick {tick!r} may have a sign.'
        sign = 1 if sign == 0 else -1

        degree = float(m.group('degree') or prev_degree or 0)
        minute = float(m.group('minute') or prev_minute or 0)
        second = float(m.group('second') or prev_second or 0)
        if Formatter == FormatterHMS:
            # 360 degrees as plot range -> 24 hours as labelled range
            expected_value = pytest.approx((value // 15) / factor)
        else:
            expected_value = pytest.approx(value / factor)
        assert sign * dms2float(degree, minute, second) == expected_value, \
            f'{tick!r} does not match expected tick value.'

        prev_degree = degree
        prev_minute = minute
        prev_second = second