plotnine 0.15.0a1__py3-none-any.whl → 0.15.0a2__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.
- plotnine/_mpl/layout_manager/_layout_items.py +85 -23
- plotnine/_mpl/layout_manager/_spaces.py +5 -5
- plotnine/_mpl/patches.py +70 -34
- plotnine/_mpl/text.py +150 -63
- plotnine/_mpl/utils.py +1 -1
- plotnine/_utils/__init__.py +26 -0
- plotnine/doctools.py +1 -1
- plotnine/facets/strips.py +17 -28
- plotnine/geoms/annotation_logticks.py +2 -0
- plotnine/geoms/annotation_stripes.py +2 -0
- plotnine/helpers.py +49 -0
- plotnine/iapi.py +28 -5
- plotnine/scales/scale_identity.py +10 -2
- plotnine/stats/binning.py +4 -1
- plotnine/stats/stat_bindot.py +1 -3
- plotnine/stats/stat_density.py +1 -1
- plotnine/themes/elements/__init__.py +2 -1
- plotnine/themes/elements/margin.py +64 -1
- plotnine/themes/theme_gray.py +5 -3
- plotnine/themes/theme_matplotlib.py +5 -4
- plotnine/themes/theme_seaborn.py +7 -4
- plotnine/themes/theme_void.py +11 -4
- plotnine/themes/themeable.py +2 -2
- plotnine/typing.py +2 -2
- {plotnine-0.15.0a1.dist-info → plotnine-0.15.0a2.dist-info}/METADATA +6 -3
- {plotnine-0.15.0a1.dist-info → plotnine-0.15.0a2.dist-info}/RECORD +29 -28
- {plotnine-0.15.0a1.dist-info → plotnine-0.15.0a2.dist-info}/WHEEL +1 -1
- {plotnine-0.15.0a1.dist-info → plotnine-0.15.0a2.dist-info}/licenses/LICENSE +0 -0
- {plotnine-0.15.0a1.dist-info → plotnine-0.15.0a2.dist-info}/top_level.txt +0 -0
plotnine/_utils/__init__.py
CHANGED
|
@@ -35,8 +35,10 @@ if TYPE_CHECKING:
|
|
|
35
35
|
DataLike,
|
|
36
36
|
FloatArray,
|
|
37
37
|
FloatArrayLike,
|
|
38
|
+
HorizontalJustification,
|
|
38
39
|
IntArray,
|
|
39
40
|
Side,
|
|
41
|
+
VerticalJustification,
|
|
40
42
|
)
|
|
41
43
|
|
|
42
44
|
T = TypeVar("T")
|
|
@@ -1264,3 +1266,27 @@ def ensure_xy_location(
|
|
|
1264
1266
|
if isinstance(h, (int, float)) and isinstance(v, (int, float)):
|
|
1265
1267
|
return (h, v)
|
|
1266
1268
|
raise ValueError(f"Cannot make a location from '{loc}'")
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
def ha_as_float(ha: HorizontalJustification | float) -> float:
|
|
1272
|
+
"""
|
|
1273
|
+
Return horizontal alignment as a float
|
|
1274
|
+
"""
|
|
1275
|
+
lookup = {"left": 0.0, "center": 0.5, "right": 1.0}
|
|
1276
|
+
return lookup[ha] if isinstance(ha, str) else ha
|
|
1277
|
+
|
|
1278
|
+
|
|
1279
|
+
def va_as_float(va: VerticalJustification | float) -> float:
|
|
1280
|
+
"""
|
|
1281
|
+
Return vertical alignment as a float
|
|
1282
|
+
"""
|
|
1283
|
+
lookup = {
|
|
1284
|
+
"top": 1.0,
|
|
1285
|
+
"center": 0.5,
|
|
1286
|
+
"bottom": 0.0,
|
|
1287
|
+
# baseline and center_baseline are valid for texts but we do
|
|
1288
|
+
# not handle them accurately
|
|
1289
|
+
"baseline": 0.5,
|
|
1290
|
+
"center_baseline": 0.5,
|
|
1291
|
+
}
|
|
1292
|
+
return lookup[va] if isinstance(va, str) else va
|
plotnine/doctools.py
CHANGED
|
@@ -451,7 +451,7 @@ def document_geom(geom: type[geom]) -> type[geom]:
|
|
|
451
451
|
table = dict_to_table(("Aesthetic", "Default value"), contents)
|
|
452
452
|
aesthetics_table = AESTHETICS_TABLE_TPL.format(table=table)
|
|
453
453
|
tpl = dedent(geom._aesthetics_doc).strip()
|
|
454
|
-
aesthetics_doc = tpl.
|
|
454
|
+
aesthetics_doc = tpl.replace("{aesthetics_table}", aesthetics_table)
|
|
455
455
|
aesthetics_doc = indent(aesthetics_doc, " " * 4)
|
|
456
456
|
|
|
457
457
|
# common_parameters
|
plotnine/facets/strips.py
CHANGED
|
@@ -67,56 +67,45 @@ class strip:
|
|
|
67
67
|
if position == "top":
|
|
68
68
|
# The x & y values are just starting locations
|
|
69
69
|
# The final location is determined by the layout manager.
|
|
70
|
-
|
|
70
|
+
bg_y = 1
|
|
71
71
|
ha = theme.getp(("strip_text_x", "ha"), "center")
|
|
72
|
-
va = theme.getp(("strip_text_x", "va"), "
|
|
72
|
+
va = theme.getp(("strip_text_x", "va"), "center")
|
|
73
73
|
rotation = theme.getp(("strip_text_x", "rotation"))
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
# TODO: Allow two unique paddings for either side.
|
|
77
|
-
# Requires implementing an mpl.patches.boxstyle that recognises
|
|
78
|
-
# two padding values.
|
|
79
|
-
strip_text_margin = (
|
|
80
|
-
theme.getp(("strip_text_x", "margin")).to("lines").b
|
|
81
|
-
)
|
|
74
|
+
bg_height = 0 # Determined by the text size
|
|
75
|
+
margin = theme.getp(("strip_text_x", "margin")).to("lines")
|
|
82
76
|
strip_align = theme.getp("strip_align_x")
|
|
83
77
|
|
|
84
78
|
# x & width properties of the background slide and
|
|
85
79
|
# shrink the strip horizontally.
|
|
86
|
-
|
|
87
|
-
|
|
80
|
+
bg_x = theme.getp(("strip_text_x", "x"), 0)
|
|
81
|
+
bg_width = theme.getp(("strip_background_x", "width"), 1)
|
|
88
82
|
|
|
89
83
|
elif position == "right":
|
|
90
84
|
# The x & y values are just starting locations
|
|
91
85
|
# The final location is determined by the layout manager.
|
|
92
|
-
|
|
93
|
-
ha = theme.getp(("strip_text_y", "ha"), "
|
|
86
|
+
bg_x = 1
|
|
87
|
+
ha = theme.getp(("strip_text_y", "ha"), "center")
|
|
94
88
|
va = theme.getp(("strip_text_y", "va"), "center")
|
|
95
89
|
rotation = theme.getp(("strip_text_y", "rotation"))
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
# Requires implementing an mpl.patches.boxstyle that recognises
|
|
99
|
-
# two padding values.
|
|
100
|
-
strip_text_margin = (
|
|
101
|
-
theme.getp(("strip_text_y", "margin")).to("lines").r
|
|
102
|
-
)
|
|
90
|
+
bg_width = 0 # Determine by the text height
|
|
91
|
+
margin = theme.getp(("strip_text_y", "margin")).to("lines")
|
|
103
92
|
strip_align = theme.getp("strip_align_y")
|
|
104
93
|
|
|
105
94
|
# y & height properties of the background slide and
|
|
106
95
|
# shrink the strip vertically.
|
|
107
|
-
|
|
108
|
-
|
|
96
|
+
bg_y = theme.getp(("strip_text_y", "y"), 0)
|
|
97
|
+
bg_height = theme.getp(("strip_background_y", "height"), 1)
|
|
109
98
|
else:
|
|
110
99
|
raise ValueError(f"Unknown position for strip text: {position!r}")
|
|
111
100
|
|
|
112
101
|
return strip_draw_info(
|
|
113
|
-
|
|
114
|
-
|
|
102
|
+
bg_x=bg_x,
|
|
103
|
+
bg_y=bg_y,
|
|
115
104
|
ha=ha,
|
|
116
105
|
va=va,
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
106
|
+
bg_width=bg_width,
|
|
107
|
+
bg_height=bg_height,
|
|
108
|
+
margin=margin,
|
|
120
109
|
strip_align=strip_align,
|
|
121
110
|
position=position,
|
|
122
111
|
label=self.label_info.text(),
|
plotnine/helpers.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from copy import deepcopy
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from typing import Sequence
|
|
8
|
+
|
|
9
|
+
from plotnine import ggplot
|
|
10
|
+
|
|
11
|
+
__all__ = ("get_aesthetic_limits",)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_aesthetic_limits(
|
|
15
|
+
plot: ggplot,
|
|
16
|
+
ae: str,
|
|
17
|
+
) -> (
|
|
18
|
+
tuple[float, float]
|
|
19
|
+
| Sequence[str]
|
|
20
|
+
| list[tuple[float]]
|
|
21
|
+
| list[Sequence[str]]
|
|
22
|
+
):
|
|
23
|
+
"""
|
|
24
|
+
Get the limits of an aesthetic
|
|
25
|
+
|
|
26
|
+
These are the limits before they are expanded.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
plot :
|
|
31
|
+
ggplot object
|
|
32
|
+
|
|
33
|
+
ae :
|
|
34
|
+
Name of aesthetic
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
out :
|
|
39
|
+
The limits of the aesthetic. If the plot is facetted, (has many
|
|
40
|
+
panels), it is a sequence of limits, one for each panel.
|
|
41
|
+
"""
|
|
42
|
+
plot = deepcopy(plot)
|
|
43
|
+
plot._build()
|
|
44
|
+
limits = [
|
|
45
|
+
getattr(panel, ae).limits
|
|
46
|
+
for panel in plot._build_objs.layout.panel_params
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
return limits[0] if len(limits) == 1 else limits
|
plotnine/iapi.py
CHANGED
|
@@ -10,6 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
import itertools
|
|
11
11
|
from copy import copy
|
|
12
12
|
from dataclasses import dataclass, field, fields
|
|
13
|
+
from functools import cached_property
|
|
13
14
|
from typing import TYPE_CHECKING
|
|
14
15
|
|
|
15
16
|
if TYPE_CHECKING:
|
|
@@ -19,6 +20,7 @@ if TYPE_CHECKING:
|
|
|
19
20
|
from matplotlib.figure import Figure
|
|
20
21
|
|
|
21
22
|
from plotnine.scales.scale import scale
|
|
23
|
+
from plotnine.themes.elements.margin import margin
|
|
22
24
|
from plotnine.typing import (
|
|
23
25
|
CoordRange,
|
|
24
26
|
FloatArrayLike,
|
|
@@ -231,13 +233,27 @@ class strip_draw_info:
|
|
|
231
233
|
Information required to draw strips
|
|
232
234
|
"""
|
|
233
235
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
+
bg_x: float
|
|
237
|
+
"""Left of the strip background in transAxes"""
|
|
238
|
+
|
|
239
|
+
bg_y: float
|
|
240
|
+
"""Bottom of the strip background in transAxes"""
|
|
241
|
+
|
|
236
242
|
ha: HorizontalJustification | float
|
|
243
|
+
"""Horizontal justification of strip text within the background"""
|
|
244
|
+
|
|
237
245
|
va: VerticalJustification | float
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
246
|
+
"""Vertical justification of strip text within the background"""
|
|
247
|
+
|
|
248
|
+
bg_width: float
|
|
249
|
+
"""Width of the strip background in transAxes"""
|
|
250
|
+
|
|
251
|
+
bg_height: float
|
|
252
|
+
"""Height of the strip background in transAxes"""
|
|
253
|
+
|
|
254
|
+
margin: margin
|
|
255
|
+
"""Strip text margin with the units in lines"""
|
|
256
|
+
|
|
241
257
|
strip_align: float
|
|
242
258
|
position: StripPosition
|
|
243
259
|
label: str
|
|
@@ -245,6 +261,13 @@ class strip_draw_info:
|
|
|
245
261
|
rotation: float
|
|
246
262
|
layout: layout_details
|
|
247
263
|
|
|
264
|
+
@cached_property
|
|
265
|
+
def is_oneline(self) -> bool:
|
|
266
|
+
"""
|
|
267
|
+
Whether the strip text is a single line
|
|
268
|
+
"""
|
|
269
|
+
return len(self.label.split("\n")) == 1
|
|
270
|
+
|
|
248
271
|
|
|
249
272
|
@dataclass
|
|
250
273
|
class strip_label_details:
|
|
@@ -43,6 +43,8 @@ class scale_color_identity(MapTrainMixin, scale_discrete):
|
|
|
43
43
|
"""
|
|
44
44
|
|
|
45
45
|
_aesthetics = ["color"]
|
|
46
|
+
_: KW_ONLY
|
|
47
|
+
guide: Literal["legend"] | None = None
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
@dataclass
|
|
@@ -52,6 +54,8 @@ class scale_fill_identity(scale_color_identity):
|
|
|
52
54
|
"""
|
|
53
55
|
|
|
54
56
|
_aesthetics = ["fill"]
|
|
57
|
+
_: KW_ONLY
|
|
58
|
+
guide: Literal["legend"] | None = None
|
|
55
59
|
|
|
56
60
|
|
|
57
61
|
@dataclass
|
|
@@ -61,6 +65,8 @@ class scale_shape_identity(MapTrainMixin, scale_discrete):
|
|
|
61
65
|
"""
|
|
62
66
|
|
|
63
67
|
_aesthetics = ["shape"]
|
|
68
|
+
_: KW_ONLY
|
|
69
|
+
guide: Literal["legend"] | None = None
|
|
64
70
|
|
|
65
71
|
|
|
66
72
|
@dataclass
|
|
@@ -70,6 +76,8 @@ class scale_linetype_identity(MapTrainMixin, scale_discrete):
|
|
|
70
76
|
"""
|
|
71
77
|
|
|
72
78
|
_aesthetics = ["linetype"]
|
|
79
|
+
_: KW_ONLY
|
|
80
|
+
guide: Literal["legend"] | None = None
|
|
73
81
|
|
|
74
82
|
|
|
75
83
|
@dataclass
|
|
@@ -82,7 +90,7 @@ class scale_alpha_identity(
|
|
|
82
90
|
|
|
83
91
|
_aesthetics = ["alpha"]
|
|
84
92
|
_: KW_ONLY
|
|
85
|
-
guide: Literal["legend"] | None =
|
|
93
|
+
guide: Literal["legend"] | None = None
|
|
86
94
|
|
|
87
95
|
|
|
88
96
|
@dataclass
|
|
@@ -95,7 +103,7 @@ class scale_size_identity(
|
|
|
95
103
|
|
|
96
104
|
_aesthetics = ["size"]
|
|
97
105
|
_: KW_ONLY
|
|
98
|
-
guide: Literal["legend"] | None =
|
|
106
|
+
guide: Literal["legend"] | None = None
|
|
99
107
|
|
|
100
108
|
|
|
101
109
|
# American to British spelling
|
plotnine/stats/binning.py
CHANGED
|
@@ -165,7 +165,10 @@ def assign_bins(
|
|
|
165
165
|
if weight is None:
|
|
166
166
|
weight = np.ones(len(x))
|
|
167
167
|
else:
|
|
168
|
-
weight
|
|
168
|
+
# If weight is a dtype that isn't writeable
|
|
169
|
+
# and does not own it's memory. Using a list
|
|
170
|
+
# as an intermediate easily solves this.
|
|
171
|
+
weight = np.array(list(weight))
|
|
169
172
|
weight[np.isnan(weight)] = 0
|
|
170
173
|
|
|
171
174
|
bin_idx = pd.cut(
|
plotnine/stats/stat_bindot.py
CHANGED
|
@@ -281,9 +281,7 @@ def densitybin(
|
|
|
281
281
|
if all(pd.isna(x)):
|
|
282
282
|
return pd.DataFrame()
|
|
283
283
|
|
|
284
|
-
if weight is None
|
|
285
|
-
weight = np.ones(len(x))
|
|
286
|
-
weight = np.asarray(weight)
|
|
284
|
+
weight = np.ones(len(x)) if weight is None else np.array(list(weight))
|
|
287
285
|
weight[np.isnan(weight)] = 0
|
|
288
286
|
|
|
289
287
|
if rangee is None:
|
plotnine/stats/stat_density.py
CHANGED
|
@@ -102,9 +102,9 @@ class stat_density(stat):
|
|
|
102
102
|
# useful for stacked density plots
|
|
103
103
|
|
|
104
104
|
'scaled' # density estimate, scaled to maximum of 1
|
|
105
|
+
'n' # Number of observations at a position
|
|
105
106
|
```
|
|
106
107
|
|
|
107
|
-
'n' # Number of observations at a position
|
|
108
108
|
|
|
109
109
|
"""
|
|
110
110
|
REQUIRED_AES = {"x"}
|
|
@@ -2,7 +2,7 @@ from .element_blank import element_blank
|
|
|
2
2
|
from .element_line import element_line
|
|
3
3
|
from .element_rect import element_rect
|
|
4
4
|
from .element_text import element_text
|
|
5
|
-
from .margin import margin
|
|
5
|
+
from .margin import margin, margin_auto
|
|
6
6
|
|
|
7
7
|
__all__ = (
|
|
8
8
|
"element_blank",
|
|
@@ -10,4 +10,5 @@ __all__ = (
|
|
|
10
10
|
"element_rect",
|
|
11
11
|
"element_text",
|
|
12
12
|
"margin",
|
|
13
|
+
"margin_auto",
|
|
13
14
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Margin
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from __future__ import annotations
|
|
@@ -17,17 +17,55 @@ if TYPE_CHECKING:
|
|
|
17
17
|
|
|
18
18
|
@dataclass
|
|
19
19
|
class margin:
|
|
20
|
+
"""
|
|
21
|
+
Margin
|
|
22
|
+
"""
|
|
23
|
+
|
|
20
24
|
t: float = 0
|
|
25
|
+
"""
|
|
26
|
+
Top margin
|
|
27
|
+
"""
|
|
28
|
+
|
|
21
29
|
r: float = 0
|
|
30
|
+
"""
|
|
31
|
+
Right margin
|
|
32
|
+
"""
|
|
33
|
+
|
|
22
34
|
b: float = 0
|
|
35
|
+
"""
|
|
36
|
+
Bottom margin
|
|
37
|
+
"""
|
|
38
|
+
|
|
23
39
|
l: float = 0
|
|
40
|
+
"""
|
|
41
|
+
Left Margin
|
|
42
|
+
"""
|
|
43
|
+
|
|
24
44
|
unit: Literal["pt", "in", "lines", "fig"] = "pt"
|
|
45
|
+
"""
|
|
46
|
+
The units (coordinate space) of the values
|
|
47
|
+
"""
|
|
25
48
|
|
|
26
49
|
# These are set by the themeable when it is applied
|
|
27
50
|
fontsize: float = field(init=False, default=0)
|
|
51
|
+
"""
|
|
52
|
+
Font size of text that this margin applies to
|
|
53
|
+
"""
|
|
54
|
+
|
|
28
55
|
figure_size: tuple[float, float] = field(init=False, default=(0, 0))
|
|
56
|
+
"""
|
|
57
|
+
Size of the figure in inches
|
|
58
|
+
"""
|
|
29
59
|
|
|
30
60
|
def setup(self, theme: theme, themeable_name: str):
|
|
61
|
+
"""
|
|
62
|
+
Setup the margin to be used in the layout
|
|
63
|
+
|
|
64
|
+
For the margin's values to be useful, we need to be able to
|
|
65
|
+
convert them to different units as is required. Here we get
|
|
66
|
+
all the parameters that we shall need to do the conversions.
|
|
67
|
+
"""
|
|
68
|
+
self.themeable_name = themeable_name
|
|
31
69
|
self.fontsize = theme.getp((themeable_name, "size"), 11)
|
|
32
70
|
self.figure_size = theme.getp("figure_size")
|
|
33
71
|
|
|
@@ -35,6 +73,8 @@ class margin:
|
|
|
35
73
|
def pt(self) -> margin:
|
|
36
74
|
"""
|
|
37
75
|
Return margin in points
|
|
76
|
+
|
|
77
|
+
These are the units of the display coordinate system
|
|
38
78
|
"""
|
|
39
79
|
return self.to("pt")
|
|
40
80
|
|
|
@@ -42,6 +82,8 @@ class margin:
|
|
|
42
82
|
def inch(self) -> margin:
|
|
43
83
|
"""
|
|
44
84
|
Return margin in inches
|
|
85
|
+
|
|
86
|
+
These are the units of the figure-inches coordinate system
|
|
45
87
|
"""
|
|
46
88
|
return self.to("in")
|
|
47
89
|
|
|
@@ -56,6 +98,8 @@ class margin:
|
|
|
56
98
|
def fig(self) -> margin:
|
|
57
99
|
"""
|
|
58
100
|
Return margin in figure units
|
|
101
|
+
|
|
102
|
+
These are the units of the figure coordinate system
|
|
59
103
|
"""
|
|
60
104
|
return self.to("fig")
|
|
61
105
|
|
|
@@ -102,3 +146,22 @@ class margin:
|
|
|
102
146
|
}
|
|
103
147
|
|
|
104
148
|
return functions[conversion](value)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def margin_auto(
|
|
152
|
+
t: float = 0.0,
|
|
153
|
+
r: float | None = None,
|
|
154
|
+
b: float | None = None,
|
|
155
|
+
l: float | None = None,
|
|
156
|
+
unit: Literal["pt", "in", "lines", "fig"] = "pt",
|
|
157
|
+
) -> margin:
|
|
158
|
+
"""
|
|
159
|
+
Create margin with minimal arguments
|
|
160
|
+
"""
|
|
161
|
+
if r is None:
|
|
162
|
+
r = t
|
|
163
|
+
if b is None:
|
|
164
|
+
b = t
|
|
165
|
+
if l is None:
|
|
166
|
+
l = r
|
|
167
|
+
return margin(t, r, b, l, unit)
|
plotnine/themes/theme_gray.py
CHANGED
|
@@ -6,6 +6,7 @@ from .elements import (
|
|
|
6
6
|
element_rect,
|
|
7
7
|
element_text,
|
|
8
8
|
margin,
|
|
9
|
+
margin_auto,
|
|
9
10
|
)
|
|
10
11
|
from .theme import theme
|
|
11
12
|
|
|
@@ -27,6 +28,7 @@ class theme_gray(theme):
|
|
|
27
28
|
|
|
28
29
|
def __init__(self, base_size=11, base_family=None):
|
|
29
30
|
base_family = base_family or get_option("base_family")
|
|
31
|
+
half_line = base_size / 2
|
|
30
32
|
quarter_line = base_size / 4
|
|
31
33
|
fifth_line = base_size / 5
|
|
32
34
|
eighth_line = base_size / 8
|
|
@@ -88,7 +90,7 @@ class theme_gray(theme):
|
|
|
88
90
|
legend_spacing=10, # points
|
|
89
91
|
legend_text=element_text(
|
|
90
92
|
size=base_size * 0.8,
|
|
91
|
-
margin=
|
|
93
|
+
margin=margin_auto(m / 1.5, unit="fig"),
|
|
92
94
|
),
|
|
93
95
|
legend_ticks=element_line(color="#CCCCCC", size=1),
|
|
94
96
|
legend_title=element_text(
|
|
@@ -135,8 +137,8 @@ class theme_gray(theme):
|
|
|
135
137
|
strip_text=element_text(
|
|
136
138
|
color="#1A1A1A",
|
|
137
139
|
size=base_size * 0.8,
|
|
138
|
-
linespacing=1.
|
|
139
|
-
margin=
|
|
140
|
+
linespacing=1.5,
|
|
141
|
+
margin=margin_auto(half_line * 0.8),
|
|
140
142
|
),
|
|
141
143
|
strip_text_y=element_text(rotation=-90),
|
|
142
144
|
complete=True,
|
|
@@ -5,6 +5,7 @@ from .elements import (
|
|
|
5
5
|
element_rect,
|
|
6
6
|
element_text,
|
|
7
7
|
margin,
|
|
8
|
+
margin_auto,
|
|
8
9
|
)
|
|
9
10
|
from .theme import theme
|
|
10
11
|
|
|
@@ -33,6 +34,7 @@ class theme_matplotlib(theme):
|
|
|
33
34
|
m = get_option("base_margin")
|
|
34
35
|
base_size = mpl.rcParams.get("font.size", 11)
|
|
35
36
|
linewidth = mpl.rcParams.get("grid.linewidth", 0.8)
|
|
37
|
+
half_line = base_size / 2
|
|
36
38
|
|
|
37
39
|
super().__init__(
|
|
38
40
|
line=element_line(size=linewidth),
|
|
@@ -68,9 +70,7 @@ class theme_matplotlib(theme):
|
|
|
68
70
|
legend_margin=0,
|
|
69
71
|
legend_position="right",
|
|
70
72
|
legend_spacing=10,
|
|
71
|
-
legend_text=element_text(
|
|
72
|
-
margin=margin(m / 2, m / 2, m / 2, m / 2, "fig")
|
|
73
|
-
),
|
|
73
|
+
legend_text=element_text(margin=margin_auto(m / 2, unit="fig")),
|
|
74
74
|
legend_ticks=element_line(color="black"),
|
|
75
75
|
legend_title=element_text(
|
|
76
76
|
ha="left",
|
|
@@ -111,7 +111,8 @@ class theme_matplotlib(theme):
|
|
|
111
111
|
fill="#D9D9D9", color="black", size=linewidth
|
|
112
112
|
),
|
|
113
113
|
strip_text=element_text(
|
|
114
|
-
|
|
114
|
+
linespacing=1.5,
|
|
115
|
+
margin=margin_auto(half_line * 0.8),
|
|
115
116
|
),
|
|
116
117
|
strip_text_y=element_text(rotation=-90),
|
|
117
118
|
complete=True,
|
plotnine/themes/theme_seaborn.py
CHANGED
|
@@ -5,6 +5,7 @@ from .elements import (
|
|
|
5
5
|
element_rect,
|
|
6
6
|
element_text,
|
|
7
7
|
margin,
|
|
8
|
+
margin_auto,
|
|
8
9
|
)
|
|
9
10
|
from .theme import theme
|
|
10
11
|
|
|
@@ -20,7 +21,7 @@ class theme_seaborn(theme):
|
|
|
20
21
|
|
|
21
22
|
Parameters
|
|
22
23
|
----------
|
|
23
|
-
style: "
|
|
24
|
+
style: "white", "dark", "whitegrid", "darkgrid", "ticks"
|
|
24
25
|
Style of axis background.
|
|
25
26
|
context: "notebook", "talk", "paper", "poster"]``
|
|
26
27
|
Intended context for resulting figures.
|
|
@@ -83,13 +84,15 @@ class theme_seaborn(theme):
|
|
|
83
84
|
legend_position="right",
|
|
84
85
|
legend_spacing=10, # points
|
|
85
86
|
legend_text=element_text(
|
|
86
|
-
|
|
87
|
+
size=base_size * 0.8,
|
|
88
|
+
margin=margin_auto(m / 1.5, unit="fig"),
|
|
87
89
|
),
|
|
88
90
|
legend_ticks=element_line(color="#CCCCCC", size=1),
|
|
89
91
|
legend_title=element_text(
|
|
90
92
|
margin=margin(t=m, l=m * 2, b=m / 2, r=m * 2, unit="fig")
|
|
91
93
|
),
|
|
92
94
|
panel_spacing=m,
|
|
95
|
+
panel_background=element_rect(fill=rcparams["axes.facecolor"]),
|
|
93
96
|
plot_caption=element_text(
|
|
94
97
|
size=base_size * 0.8,
|
|
95
98
|
ha="right",
|
|
@@ -123,8 +126,8 @@ class theme_seaborn(theme):
|
|
|
123
126
|
strip_background=element_rect(color="none", fill="#D1CDDF"),
|
|
124
127
|
strip_text=element_text(
|
|
125
128
|
size=base_size * 0.8,
|
|
126
|
-
linespacing=1.
|
|
127
|
-
margin=
|
|
129
|
+
linespacing=1.5,
|
|
130
|
+
margin=margin_auto(half_line * 0.8),
|
|
128
131
|
),
|
|
129
132
|
strip_text_y=element_text(rotation=-90),
|
|
130
133
|
complete=True,
|
plotnine/themes/theme_void.py
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
from ..options import get_option
|
|
2
|
-
from .elements import
|
|
2
|
+
from .elements import (
|
|
3
|
+
element_blank,
|
|
4
|
+
element_line,
|
|
5
|
+
element_text,
|
|
6
|
+
margin,
|
|
7
|
+
margin_auto,
|
|
8
|
+
)
|
|
3
9
|
from .theme import theme
|
|
4
10
|
|
|
5
11
|
|
|
@@ -19,6 +25,7 @@ class theme_void(theme):
|
|
|
19
25
|
|
|
20
26
|
def __init__(self, base_size=11, base_family=None):
|
|
21
27
|
base_family = base_family or get_option("base_family")
|
|
28
|
+
half_line = base_size / 2
|
|
22
29
|
m = get_option("base_margin")
|
|
23
30
|
# Use only inherited elements and make everything blank
|
|
24
31
|
theme.__init__(
|
|
@@ -54,7 +61,7 @@ class theme_void(theme):
|
|
|
54
61
|
legend_spacing=10,
|
|
55
62
|
legend_text=element_text(
|
|
56
63
|
size=base_size * 0.8,
|
|
57
|
-
margin=
|
|
64
|
+
margin=margin_auto(m / 1.5, unit="fig"),
|
|
58
65
|
),
|
|
59
66
|
legend_ticks=element_line(color="#CCCCCC", size=1),
|
|
60
67
|
legend_title=element_text(
|
|
@@ -94,8 +101,8 @@ class theme_void(theme):
|
|
|
94
101
|
strip_text=element_text(
|
|
95
102
|
color="#1A1A1A",
|
|
96
103
|
size=base_size * 0.8,
|
|
97
|
-
linespacing=1.
|
|
98
|
-
margin=
|
|
104
|
+
linespacing=1.5,
|
|
105
|
+
margin=margin_auto(half_line * 0.8),
|
|
99
106
|
),
|
|
100
107
|
complete=True,
|
|
101
108
|
)
|
plotnine/themes/themeable.py
CHANGED
|
@@ -852,7 +852,7 @@ class strip_text_x(MixinSequenceOfValues):
|
|
|
852
852
|
theme_element : element_text
|
|
853
853
|
"""
|
|
854
854
|
|
|
855
|
-
_omit = ["margin", "ha"]
|
|
855
|
+
_omit = ["margin", "ha", "va"]
|
|
856
856
|
|
|
857
857
|
def apply_figure(self, figure: Figure, targets: ThemeTargets):
|
|
858
858
|
super().apply_figure(figure, targets)
|
|
@@ -875,7 +875,7 @@ class strip_text_y(MixinSequenceOfValues):
|
|
|
875
875
|
theme_element : element_text
|
|
876
876
|
"""
|
|
877
877
|
|
|
878
|
-
_omit = ["margin", "va"]
|
|
878
|
+
_omit = ["margin", "ha", "va"]
|
|
879
879
|
|
|
880
880
|
def apply_figure(self, figure: Figure, targets: ThemeTargets):
|
|
881
881
|
super().apply_figure(figure, targets)
|
plotnine/typing.py
CHANGED
|
@@ -80,7 +80,7 @@ FacetSpaceRatios: TypeAlias = dict[Literal["x", "y"], Sequence[float]]
|
|
|
80
80
|
|
|
81
81
|
StripPosition: TypeAlias = Literal["top", "right"]
|
|
82
82
|
|
|
83
|
-
|
|
83
|
+
# Scales
|
|
84
84
|
|
|
85
85
|
# Name names of scaled aesthetics
|
|
86
86
|
ScaledAestheticsName: TypeAlias = Literal[
|
|
@@ -110,7 +110,7 @@ ScaledAestheticsName: TypeAlias = Literal[
|
|
|
110
110
|
"upper",
|
|
111
111
|
]
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
# Coords
|
|
114
114
|
CoordRange: TypeAlias = tuple[float, float]
|
|
115
115
|
|
|
116
116
|
# Guide
|