scales-python 1.4.0.9000__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- scales/__init__.py +295 -0
- scales/_colors.py +272 -0
- scales/_palettes_data.py +595 -0
- scales/_utils.py +579 -0
- scales/bounds.py +512 -0
- scales/breaks.py +627 -0
- scales/breaks_log.py +268 -0
- scales/colour_manip.py +681 -0
- scales/colour_mapping.py +593 -0
- scales/colour_ramp.py +126 -0
- scales/labels.py +2144 -0
- scales/minor_breaks.py +197 -0
- scales/palettes.py +1328 -0
- scales/py.typed +0 -0
- scales/range.py +223 -0
- scales/scale_continuous.py +146 -0
- scales/scale_discrete.py +196 -0
- scales/transforms.py +1338 -0
- scales_python-1.4.0.9000.dist-info/METADATA +73 -0
- scales_python-1.4.0.9000.dist-info/RECORD +22 -0
- scales_python-1.4.0.9000.dist-info/WHEEL +4 -0
- scales_python-1.4.0.9000.dist-info/licenses/LICENSE +3 -0
scales/minor_breaks.py
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Minor-break generators for linear (non-log) scales.
|
|
3
|
+
|
|
4
|
+
Python port of ``R/minor_breaks.R`` from the R *scales* package
|
|
5
|
+
(https://github.com/r-lib/scales).
|
|
6
|
+
|
|
7
|
+
All public generators are closure factories: they return a callable with
|
|
8
|
+
signature ``(major_breaks, limits, n) -> numpy.ndarray``.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from typing import Callable, Optional
|
|
14
|
+
|
|
15
|
+
import numpy as np
|
|
16
|
+
from numpy.typing import ArrayLike
|
|
17
|
+
|
|
18
|
+
__all__ = [
|
|
19
|
+
"minor_breaks_n",
|
|
20
|
+
"minor_breaks_width",
|
|
21
|
+
"regular_minor_breaks",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def minor_breaks_n(
|
|
26
|
+
n: int = 2,
|
|
27
|
+
) -> Callable[[np.ndarray, np.ndarray, int], np.ndarray]:
|
|
28
|
+
"""Place *n* minor breaks between each pair of major breaks.
|
|
29
|
+
|
|
30
|
+
Parameters
|
|
31
|
+
----------
|
|
32
|
+
n : int, optional
|
|
33
|
+
Number of minor breaks between consecutive major breaks
|
|
34
|
+
(default 2).
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
callable
|
|
39
|
+
A function ``(major_breaks, limits, n_minor) -> numpy.ndarray``
|
|
40
|
+
of minor-break positions.
|
|
41
|
+
|
|
42
|
+
Examples
|
|
43
|
+
--------
|
|
44
|
+
>>> fn = minor_breaks_n(n=4)
|
|
45
|
+
>>> fn(np.array([0, 10, 20]), np.array([0, 20]), 4)
|
|
46
|
+
array([ 2., 4., 6., 8., 12., 14., 16., 18.])
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def _minor_breaks(
|
|
50
|
+
major: np.ndarray,
|
|
51
|
+
limits: np.ndarray,
|
|
52
|
+
n_minor: int = n,
|
|
53
|
+
) -> np.ndarray:
|
|
54
|
+
major = np.sort(np.asarray(major, dtype=float))
|
|
55
|
+
limits = np.asarray(limits, dtype=float)
|
|
56
|
+
|
|
57
|
+
if len(major) < 2:
|
|
58
|
+
return np.array([], dtype=float)
|
|
59
|
+
|
|
60
|
+
minors: list[float] = []
|
|
61
|
+
for i in range(len(major) - 1):
|
|
62
|
+
lo = major[i]
|
|
63
|
+
hi = major[i + 1]
|
|
64
|
+
step = (hi - lo) / (n_minor + 1)
|
|
65
|
+
for j in range(1, n_minor + 1):
|
|
66
|
+
val = lo + j * step
|
|
67
|
+
if limits[0] <= val <= limits[1]:
|
|
68
|
+
minors.append(val)
|
|
69
|
+
|
|
70
|
+
return np.array(sorted(set(minors)), dtype=float)
|
|
71
|
+
|
|
72
|
+
return _minor_breaks
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def minor_breaks_width(
|
|
76
|
+
width: float,
|
|
77
|
+
offset: float = 0,
|
|
78
|
+
) -> Callable[[np.ndarray, np.ndarray, int], np.ndarray]:
|
|
79
|
+
"""Place minor breaks at fixed-width intervals.
|
|
80
|
+
|
|
81
|
+
Parameters
|
|
82
|
+
----------
|
|
83
|
+
width : float
|
|
84
|
+
Spacing between consecutive minor breaks.
|
|
85
|
+
offset : float, optional
|
|
86
|
+
Offset from zero for the break grid (default 0). The grid is
|
|
87
|
+
placed at ``... , offset - width, offset, offset + width, ...``
|
|
88
|
+
and then clipped to the axis limits.
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
callable
|
|
93
|
+
A function ``(major_breaks, limits, n) -> numpy.ndarray``
|
|
94
|
+
of minor-break positions.
|
|
95
|
+
|
|
96
|
+
Examples
|
|
97
|
+
--------
|
|
98
|
+
>>> fn = minor_breaks_width(2.5)
|
|
99
|
+
>>> fn(np.array([0, 10, 20]), np.array([0, 20]), 5)
|
|
100
|
+
array([ 0. , 2.5, 5. , 7.5, 10. , 12.5, 15. , 17.5, 20. ])
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
def _minor_breaks(
|
|
104
|
+
major: np.ndarray,
|
|
105
|
+
limits: np.ndarray,
|
|
106
|
+
n: int = 5,
|
|
107
|
+
) -> np.ndarray:
|
|
108
|
+
limits = np.asarray(limits, dtype=float)
|
|
109
|
+
lo, hi = float(limits[0]), float(limits[1])
|
|
110
|
+
|
|
111
|
+
# Build grid aligned to offset
|
|
112
|
+
start = np.floor((lo - offset) / width) * width + offset
|
|
113
|
+
stop = np.ceil((hi - offset) / width) * width + offset
|
|
114
|
+
breaks = np.arange(start, stop + width / 2, width)
|
|
115
|
+
|
|
116
|
+
# Clip to limits
|
|
117
|
+
breaks = breaks[(breaks >= lo - 1e-10) & (breaks <= hi + 1e-10)]
|
|
118
|
+
|
|
119
|
+
return breaks
|
|
120
|
+
|
|
121
|
+
return _minor_breaks
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def regular_minor_breaks(
|
|
125
|
+
reverse: bool = False,
|
|
126
|
+
) -> Callable[[np.ndarray, np.ndarray, int], np.ndarray]:
|
|
127
|
+
"""Default minor-break placement: ``n - 1`` evenly spaced between majors.
|
|
128
|
+
|
|
129
|
+
This is the standard minor-break strategy used by ggplot2. Between
|
|
130
|
+
each pair of consecutive major breaks, ``n - 1`` minor breaks are
|
|
131
|
+
inserted at equal spacing.
|
|
132
|
+
|
|
133
|
+
Parameters
|
|
134
|
+
----------
|
|
135
|
+
reverse : bool, optional
|
|
136
|
+
If ``True``, the limits are internally reversed before
|
|
137
|
+
computing breaks and the result is reversed back. Useful for
|
|
138
|
+
reversed continuous scales (default ``False``).
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
callable
|
|
143
|
+
A function ``(major_breaks, limits, n) -> numpy.ndarray``
|
|
144
|
+
of minor-break positions.
|
|
145
|
+
|
|
146
|
+
Examples
|
|
147
|
+
--------
|
|
148
|
+
>>> fn = regular_minor_breaks()
|
|
149
|
+
>>> fn(np.array([0, 5, 10]), np.array([0, 10]), 2)
|
|
150
|
+
array([ 2.5, 7.5])
|
|
151
|
+
"""
|
|
152
|
+
|
|
153
|
+
def _minor_breaks(
|
|
154
|
+
major: np.ndarray,
|
|
155
|
+
limits: np.ndarray,
|
|
156
|
+
n: int = 2,
|
|
157
|
+
) -> np.ndarray:
|
|
158
|
+
# Mirrors R's regular_minor_breaks (R/minor_breaks.R:65-93):
|
|
159
|
+
# drop NAs; if fewer than 2 majors, return empty; extend by one
|
|
160
|
+
# step past each edge depending on which side the limits reach;
|
|
161
|
+
# interpolate (n+1)-length ``seq`` between consecutive majors,
|
|
162
|
+
# dropping the last point, then re-append the final major.
|
|
163
|
+
b = np.asarray(major, dtype=float)
|
|
164
|
+
b = b[~np.isnan(b)]
|
|
165
|
+
b = np.sort(b)
|
|
166
|
+
|
|
167
|
+
if len(b) < 2 or n < 1:
|
|
168
|
+
return np.array([], dtype=float)
|
|
169
|
+
|
|
170
|
+
lim = np.asarray(limits, dtype=float)
|
|
171
|
+
lo_lim, hi_lim = float(np.min(lim)), float(np.max(lim))
|
|
172
|
+
|
|
173
|
+
bd = b[1] - b[0] # step
|
|
174
|
+
|
|
175
|
+
# R: when not reversed, extend low side if limits reach below,
|
|
176
|
+
# high side if limits reach above; reversed swaps the two.
|
|
177
|
+
if not reverse:
|
|
178
|
+
if lo_lim < b[0]:
|
|
179
|
+
b = np.concatenate([[b[0] - bd], b])
|
|
180
|
+
if hi_lim > b[-1]:
|
|
181
|
+
b = np.concatenate([b, [b[-1] + bd]])
|
|
182
|
+
else:
|
|
183
|
+
if hi_lim > b[-1]:
|
|
184
|
+
b = np.concatenate([[b[0] - bd], b])
|
|
185
|
+
if lo_lim < b[0]:
|
|
186
|
+
b = np.concatenate([b, [b[-1] + bd]])
|
|
187
|
+
|
|
188
|
+
# (n+1)-length seq between each consecutive pair, dropping last
|
|
189
|
+
# (that's the next major). Then re-append the final major.
|
|
190
|
+
pieces: list[np.ndarray] = []
|
|
191
|
+
for i in range(len(b) - 1):
|
|
192
|
+
seq = np.linspace(b[i], b[i + 1], n + 1)[:-1]
|
|
193
|
+
pieces.append(seq)
|
|
194
|
+
pieces.append(np.array([b[-1]], dtype=float))
|
|
195
|
+
return np.concatenate(pieces)
|
|
196
|
+
|
|
197
|
+
return _minor_breaks
|