plotnine 0.16.0a2__py3-none-any.whl → 0.16.0a3__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/_composition_layout_items.py +43 -0
- plotnine/_mpl/layout_manager/_composition_side_space.py +33 -0
- plotnine/_mpl/layout_manager/_plot_layout_items.py +43 -0
- plotnine/_mpl/layout_manager/_plot_side_space.py +20 -0
- plotnine/_utils/context.py +12 -8
- plotnine/composition/_compose.py +21 -1
- plotnine/composition/_plot_annotation.py +6 -1
- plotnine/ggplot.py +24 -1
- plotnine/guides/guide_legend.py +17 -3
- plotnine/iapi.py +3 -2
- plotnine/labels.py +7 -0
- plotnine/themes/targets.py +4 -0
- plotnine/themes/theme.py +4 -0
- plotnine/themes/theme_gray.py +10 -0
- plotnine/themes/theme_matplotlib.py +9 -0
- plotnine/themes/theme_seaborn.py +10 -0
- plotnine/themes/theme_void.py +8 -0
- plotnine/themes/themeable.py +91 -2
- {plotnine-0.16.0a2.dist-info → plotnine-0.16.0a3.dist-info}/METADATA +2 -2
- {plotnine-0.16.0a2.dist-info → plotnine-0.16.0a3.dist-info}/RECORD +23 -23
- {plotnine-0.16.0a2.dist-info → plotnine-0.16.0a3.dist-info}/WHEEL +1 -1
- {plotnine-0.16.0a2.dist-info → plotnine-0.16.0a3.dist-info}/licenses/LICENSE +0 -0
- {plotnine-0.16.0a2.dist-info → plotnine-0.16.0a3.dist-info}/top_level.txt +0 -0
|
@@ -14,6 +14,9 @@ from plotnine._mpl.utils import (
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from typing import Any
|
|
16
16
|
|
|
17
|
+
from matplotlib.lines import Line2D
|
|
18
|
+
from matplotlib.patches import Rectangle
|
|
19
|
+
|
|
17
20
|
from plotnine.composition._compose import Compose
|
|
18
21
|
|
|
19
22
|
from ._composition_side_space import CompositionSideSpaces
|
|
@@ -44,6 +47,11 @@ class CompositionLayoutItems:
|
|
|
44
47
|
self.plot_title: Text | None = get("plot_title")
|
|
45
48
|
self.plot_subtitle: Text | None = get("plot_subtitle")
|
|
46
49
|
self.plot_caption: Text | None = get("plot_caption")
|
|
50
|
+
self.plot_footer: Text | None = get("plot_footer")
|
|
51
|
+
self.plot_footer_background: Rectangle | None = get(
|
|
52
|
+
"plot_footer_background"
|
|
53
|
+
)
|
|
54
|
+
self.plot_footer_line: Line2D | None = get("plot_footer_line")
|
|
47
55
|
|
|
48
56
|
def _is_blank(self, name: str) -> bool:
|
|
49
57
|
return self.cmp.theme.T.is_blank(name)
|
|
@@ -55,6 +63,7 @@ class CompositionLayoutItems:
|
|
|
55
63
|
theme = self.cmp.theme
|
|
56
64
|
plot_title_position = theme.getp("plot_title_position", "panel")
|
|
57
65
|
plot_caption_position = theme.getp("plot_caption_position", "panel")
|
|
66
|
+
plot_footer_position = theme.getp("plot_footer_position", "plot")
|
|
58
67
|
justify = CompositionTextJustifier(spaces)
|
|
59
68
|
|
|
60
69
|
if self.plot_title:
|
|
@@ -78,6 +87,40 @@ class CompositionLayoutItems:
|
|
|
78
87
|
self.plot_caption, ha, plot_caption_position
|
|
79
88
|
)
|
|
80
89
|
|
|
90
|
+
if self.plot_footer:
|
|
91
|
+
ha = theme.getp(("plot_footer", "ha"), "left")
|
|
92
|
+
self.plot_footer.set_y(spaces.b.y1("plot_footer"))
|
|
93
|
+
justify.horizontally_about(
|
|
94
|
+
self.plot_footer, ha, plot_footer_position
|
|
95
|
+
)
|
|
96
|
+
self._resize_plot_footer_background(spaces)
|
|
97
|
+
self._resize_plot_footer_line(spaces)
|
|
98
|
+
|
|
99
|
+
def _resize_plot_footer_background(self, spaces: CompositionSideSpaces):
|
|
100
|
+
"""
|
|
101
|
+
Resize the plot footer to the size of the footer
|
|
102
|
+
"""
|
|
103
|
+
if not self.plot_footer_background:
|
|
104
|
+
return
|
|
105
|
+
|
|
106
|
+
self.plot_footer_background.set_x(spaces.l.offset)
|
|
107
|
+
self.plot_footer_background.set_y(spaces.b.offset)
|
|
108
|
+
self.plot_footer_background.set_height(spaces.b.footer_height)
|
|
109
|
+
self.plot_footer_background.set_width(spaces.plot_width)
|
|
110
|
+
|
|
111
|
+
def _resize_plot_footer_line(self, spaces: CompositionSideSpaces):
|
|
112
|
+
"""
|
|
113
|
+
Resize the footer line to be a border above the footer
|
|
114
|
+
"""
|
|
115
|
+
if not self.plot_footer_line:
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
x1 = spaces.l.offset
|
|
119
|
+
x2 = x1 + spaces.plot_width
|
|
120
|
+
y1 = y2 = spaces.b.offset + spaces.b.footer_height
|
|
121
|
+
self.plot_footer_line.set_xdata([x1, x2])
|
|
122
|
+
self.plot_footer_line.set_ydata([y1, y2])
|
|
123
|
+
|
|
81
124
|
|
|
82
125
|
class CompositionTextJustifier(TextJustifier):
|
|
83
126
|
"""
|
|
@@ -218,6 +218,9 @@ class composition_bottom_space(_composition_side_space):
|
|
|
218
218
|
Ordered from the edge of the figure and going inwards
|
|
219
219
|
"""
|
|
220
220
|
|
|
221
|
+
plot_footer_margin_bottom: float = 0
|
|
222
|
+
plot_footer: float = 0
|
|
223
|
+
plot_footer_margin_top: float = 0
|
|
221
224
|
plot_margin: float = 0
|
|
222
225
|
plot_caption_margin_bottom: float = 0
|
|
223
226
|
plot_caption: float = 0
|
|
@@ -231,6 +234,11 @@ class composition_bottom_space(_composition_side_space):
|
|
|
231
234
|
F = W / H
|
|
232
235
|
|
|
233
236
|
self.plot_margin = theme.getp("plot_margin_bottom") * F
|
|
237
|
+
if items.plot_footer:
|
|
238
|
+
m = theme.get_margin("plot_footer").fig
|
|
239
|
+
self.plot_footer_margin_bottom = m.b * F
|
|
240
|
+
self.plot_footer = geometry.height(items.plot_footer)
|
|
241
|
+
self.plot_footer_margin_top = m.t * F
|
|
234
242
|
|
|
235
243
|
if items.plot_caption:
|
|
236
244
|
m = theme.get_margin("plot_caption").fig
|
|
@@ -269,6 +277,17 @@ class composition_bottom_space(_composition_side_space):
|
|
|
269
277
|
"""
|
|
270
278
|
return self.to_figure_space(self.sum_incl(item))
|
|
271
279
|
|
|
280
|
+
@property
|
|
281
|
+
def footer_height(self):
|
|
282
|
+
"""
|
|
283
|
+
The height of the footer including the margins
|
|
284
|
+
"""
|
|
285
|
+
return (
|
|
286
|
+
self.plot_footer_margin_bottom
|
|
287
|
+
+ self.plot_footer
|
|
288
|
+
+ self.plot_footer_margin_top
|
|
289
|
+
)
|
|
290
|
+
|
|
272
291
|
@property
|
|
273
292
|
def items_bottom_relative(self):
|
|
274
293
|
"""
|
|
@@ -361,6 +380,20 @@ class CompositionSideSpaces:
|
|
|
361
380
|
0,
|
|
362
381
|
)
|
|
363
382
|
|
|
383
|
+
@property
|
|
384
|
+
def plot_width(self) -> float:
|
|
385
|
+
"""
|
|
386
|
+
Width [figure dimensions] of the whole plot composition
|
|
387
|
+
"""
|
|
388
|
+
return float(self.gridspec.width)
|
|
389
|
+
|
|
390
|
+
@property
|
|
391
|
+
def plot_height(self) -> float:
|
|
392
|
+
"""
|
|
393
|
+
Height [figure dimensions] of the whole plot composition
|
|
394
|
+
"""
|
|
395
|
+
return float(self.gridspec.height)
|
|
396
|
+
|
|
364
397
|
@property
|
|
365
398
|
def horizontal_space(self) -> float:
|
|
366
399
|
"""
|
|
@@ -26,6 +26,8 @@ if TYPE_CHECKING:
|
|
|
26
26
|
|
|
27
27
|
from matplotlib.axes import Axes
|
|
28
28
|
from matplotlib.axis import Tick
|
|
29
|
+
from matplotlib.lines import Line2D
|
|
30
|
+
from matplotlib.patches import Rectangle
|
|
29
31
|
from matplotlib.transforms import Transform
|
|
30
32
|
|
|
31
33
|
from plotnine import ggplot
|
|
@@ -86,12 +88,18 @@ class PlotLayoutItems:
|
|
|
86
88
|
# # AnchoredOffsetboxes (groups of legends)
|
|
87
89
|
self.legends: legend_artists | None = get("legends")
|
|
88
90
|
self.plot_caption: Text | None = get("plot_caption")
|
|
91
|
+
self.plot_footer: Text | None = get("plot_footer")
|
|
89
92
|
self.plot_subtitle: Text | None = get("plot_subtitle")
|
|
90
93
|
self.plot_title: Text | None = get("plot_title")
|
|
91
94
|
self.plot_tag: Text | None = get("plot_tag")
|
|
92
95
|
self.strip_text_x: list[StripText] | None = get("strip_text_x")
|
|
93
96
|
self.strip_text_y: list[StripText] | None = get("strip_text_y")
|
|
94
97
|
|
|
98
|
+
self.plot_footer_background: Rectangle | None = get(
|
|
99
|
+
"plot_footer_background"
|
|
100
|
+
)
|
|
101
|
+
self.plot_footer_line: Line2D | None = get("plot_footer_line")
|
|
102
|
+
|
|
95
103
|
def _is_blank(self, name: str) -> bool:
|
|
96
104
|
return self.plot.theme.T.is_blank(name)
|
|
97
105
|
|
|
@@ -345,6 +353,7 @@ class PlotLayoutItems:
|
|
|
345
353
|
theme = self.plot.theme
|
|
346
354
|
plot_title_position = theme.getp("plot_title_position", "panel")
|
|
347
355
|
plot_caption_position = theme.getp("plot_caption_position", "panel")
|
|
356
|
+
plot_footer_position = theme.getp("plot_footer_position", "plot")
|
|
348
357
|
justify = PlotTextJustifier(spaces)
|
|
349
358
|
|
|
350
359
|
if self.plot_tag:
|
|
@@ -371,6 +380,15 @@ class PlotLayoutItems:
|
|
|
371
380
|
self.plot_caption, ha, plot_caption_position
|
|
372
381
|
)
|
|
373
382
|
|
|
383
|
+
if self.plot_footer:
|
|
384
|
+
ha = theme.getp(("plot_footer", "ha"), "left")
|
|
385
|
+
self.plot_footer.set_y(spaces.b.y1("plot_footer"))
|
|
386
|
+
justify.horizontally_about(
|
|
387
|
+
self.plot_footer, ha, plot_footer_position
|
|
388
|
+
)
|
|
389
|
+
self._resize_plot_footer_background(spaces)
|
|
390
|
+
self._resize_plot_footer_line(spaces)
|
|
391
|
+
|
|
374
392
|
if self.axis_title_x:
|
|
375
393
|
ha = theme.getp(("axis_title_x", "ha"), "center")
|
|
376
394
|
self.axis_title_x.set_y(spaces.b.y1("axis_title_x"))
|
|
@@ -505,6 +523,31 @@ class PlotLayoutItems:
|
|
|
505
523
|
for text, scale in zip(self.strip_text_y, relative_widths):
|
|
506
524
|
text.patch.expand = scale
|
|
507
525
|
|
|
526
|
+
def _resize_plot_footer_background(self, spaces: PlotSideSpaces):
|
|
527
|
+
"""
|
|
528
|
+
Resize the plot footer to the size of the footer
|
|
529
|
+
"""
|
|
530
|
+
if not self.plot_footer_background:
|
|
531
|
+
return
|
|
532
|
+
|
|
533
|
+
self.plot_footer_background.set_x(spaces.l.offset)
|
|
534
|
+
self.plot_footer_background.set_y(spaces.b.offset)
|
|
535
|
+
self.plot_footer_background.set_height(spaces.b.footer_height)
|
|
536
|
+
self.plot_footer_background.set_width(spaces.plot_width)
|
|
537
|
+
|
|
538
|
+
def _resize_plot_footer_line(self, spaces: PlotSideSpaces):
|
|
539
|
+
"""
|
|
540
|
+
Resize the footer line to be a border above the footer
|
|
541
|
+
"""
|
|
542
|
+
if not self.plot_footer_line:
|
|
543
|
+
return
|
|
544
|
+
|
|
545
|
+
x1 = spaces.l.offset
|
|
546
|
+
x2 = x1 + spaces.plot_width
|
|
547
|
+
y1 = y2 = spaces.b.offset + spaces.b.footer_height
|
|
548
|
+
self.plot_footer_line.set_xdata([x1, x2])
|
|
549
|
+
self.plot_footer_line.set_ydata([y1, y2])
|
|
550
|
+
|
|
508
551
|
|
|
509
552
|
def _text_is_visible(text: Text) -> bool:
|
|
510
553
|
"""
|
|
@@ -553,6 +553,9 @@ class bottom_space(_plot_side_space):
|
|
|
553
553
|
Ordered from the edge of the figure and going inwards
|
|
554
554
|
"""
|
|
555
555
|
|
|
556
|
+
plot_footer_margin_bottom: float = 0
|
|
557
|
+
plot_footer: float = 0
|
|
558
|
+
plot_footer_margin_top: float = 0
|
|
556
559
|
plot_margin: float = 0
|
|
557
560
|
tag_alignment: float = 0
|
|
558
561
|
plot_tag_margin_bottom: float = 0
|
|
@@ -602,6 +605,12 @@ class bottom_space(_plot_side_space):
|
|
|
602
605
|
self.plot_caption = geometry.height(items.plot_caption)
|
|
603
606
|
self.plot_caption_margin_top = m.t * F
|
|
604
607
|
|
|
608
|
+
if items.plot_footer:
|
|
609
|
+
m = theme.get_margin("plot_footer").fig
|
|
610
|
+
self.plot_footer_margin_bottom = m.b * F
|
|
611
|
+
self.plot_footer = geometry.height(items.plot_footer)
|
|
612
|
+
self.plot_footer_margin_top = m.t * F
|
|
613
|
+
|
|
605
614
|
if items.legends and items.legends.bottom:
|
|
606
615
|
self.legend = self.legend_height
|
|
607
616
|
self.legend_box_spacing = theme.getp("legend_box_spacing") * F
|
|
@@ -680,6 +689,17 @@ class bottom_space(_plot_side_space):
|
|
|
680
689
|
"""
|
|
681
690
|
return self.y1("legend")
|
|
682
691
|
|
|
692
|
+
@property
|
|
693
|
+
def footer_height(self):
|
|
694
|
+
"""
|
|
695
|
+
The height of the footer including the margins
|
|
696
|
+
"""
|
|
697
|
+
return (
|
|
698
|
+
self.plot_footer_margin_bottom
|
|
699
|
+
+ self.plot_footer
|
|
700
|
+
+ self.plot_footer_margin_top
|
|
701
|
+
)
|
|
702
|
+
|
|
683
703
|
@property
|
|
684
704
|
def tag_height(self):
|
|
685
705
|
"""
|
plotnine/_utils/context.py
CHANGED
|
@@ -4,6 +4,7 @@ from dataclasses import dataclass
|
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
import pandas as pd
|
|
7
|
+
from packaging.version import Version
|
|
7
8
|
|
|
8
9
|
if TYPE_CHECKING:
|
|
9
10
|
from typing_extensions import Self
|
|
@@ -11,6 +12,8 @@ if TYPE_CHECKING:
|
|
|
11
12
|
from plotnine import ggplot
|
|
12
13
|
from plotnine.composition import Compose
|
|
13
14
|
|
|
15
|
+
PANDAS_LT_3 = Version(pd.__version__) < Version("3.0")
|
|
16
|
+
|
|
14
17
|
|
|
15
18
|
def reopen(fig):
|
|
16
19
|
"""
|
|
@@ -55,12 +58,11 @@ class plot_context:
|
|
|
55
58
|
|
|
56
59
|
# Contexts
|
|
57
60
|
self.rc_context = mpl.rc_context(plot.theme.rcParams)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
)
|
|
61
|
+
if PANDAS_LT_3:
|
|
62
|
+
self.pd_option_context = pd.option_context(
|
|
63
|
+
"mode.copy_on_write",
|
|
64
|
+
True,
|
|
65
|
+
)
|
|
64
66
|
|
|
65
67
|
def __enter__(self) -> Self:
|
|
66
68
|
"""
|
|
@@ -68,7 +70,8 @@ class plot_context:
|
|
|
68
70
|
"""
|
|
69
71
|
|
|
70
72
|
self.rc_context.__enter__()
|
|
71
|
-
|
|
73
|
+
if PANDAS_LT_3:
|
|
74
|
+
self.pd_option_context.__enter__()
|
|
72
75
|
|
|
73
76
|
return self
|
|
74
77
|
|
|
@@ -89,7 +92,8 @@ class plot_context:
|
|
|
89
92
|
plt.close(self.plot.figure)
|
|
90
93
|
|
|
91
94
|
self.rc_context.__exit__(exc_type, exc_value, exc_traceback)
|
|
92
|
-
|
|
95
|
+
if PANDAS_LT_3:
|
|
96
|
+
self.pd_option_context.__exit__(exc_type, exc_value, exc_traceback)
|
|
93
97
|
|
|
94
98
|
|
|
95
99
|
@dataclass
|
plotnine/composition/_compose.py
CHANGED
|
@@ -123,6 +123,8 @@ class Compose:
|
|
|
123
123
|
| ------------- |
|
|
124
124
|
| |
|
|
125
125
|
| caption |
|
|
126
|
+
|-------------------|
|
|
127
|
+
| footer |
|
|
126
128
|
-------------------
|
|
127
129
|
"""
|
|
128
130
|
_sidespaces: CompositionSideSpaces
|
|
@@ -573,13 +575,28 @@ class Compose:
|
|
|
573
575
|
"""
|
|
574
576
|
Draw the background rectangle of the composition
|
|
575
577
|
"""
|
|
578
|
+
from matplotlib.lines import Line2D
|
|
576
579
|
from matplotlib.patches import Rectangle
|
|
577
580
|
|
|
578
|
-
|
|
581
|
+
zorder = -1000
|
|
582
|
+
rect = Rectangle((0, 0), 0, 0, facecolor="none", zorder=zorder)
|
|
579
583
|
self.figure.add_artist(rect)
|
|
580
584
|
self._gridspec.patch = rect
|
|
581
585
|
self.theme.targets.plot_background = rect
|
|
582
586
|
|
|
587
|
+
if self.annotation.footer:
|
|
588
|
+
rect = Rectangle(
|
|
589
|
+
(0, 0), 0, 0, facecolor="none", linewidth=0, zorder=zorder + 1
|
|
590
|
+
)
|
|
591
|
+
self.figure.add_artist(rect)
|
|
592
|
+
self.theme.targets.plot_footer_background = rect
|
|
593
|
+
|
|
594
|
+
line = Line2D(
|
|
595
|
+
[0, 0], [0, 0], color="none", linewidth=0, zorder=zorder + 2
|
|
596
|
+
)
|
|
597
|
+
self.figure.add_artist(line)
|
|
598
|
+
self.theme.targets.plot_footer_line = line
|
|
599
|
+
|
|
583
600
|
def _draw_annotation(self):
|
|
584
601
|
"""
|
|
585
602
|
Draw the items in the annotation
|
|
@@ -602,6 +619,9 @@ class Compose:
|
|
|
602
619
|
if caption := self.annotation.caption:
|
|
603
620
|
targets.plot_caption = figure.text(0, 0, caption)
|
|
604
621
|
|
|
622
|
+
if footer := self.annotation.footer:
|
|
623
|
+
targets.plot_footer = figure.text(0, 0, footer)
|
|
624
|
+
|
|
605
625
|
def save(
|
|
606
626
|
self,
|
|
607
627
|
filename: str | Path | BytesIO,
|
|
@@ -36,9 +36,14 @@ class plot_annotation(ComposeAddable):
|
|
|
36
36
|
The caption of the composition
|
|
37
37
|
"""
|
|
38
38
|
|
|
39
|
+
footer: str | None = None
|
|
40
|
+
"""
|
|
41
|
+
The footer of the composition
|
|
42
|
+
"""
|
|
43
|
+
|
|
39
44
|
theme: theme = field(default_factory=theme) # pyright: ignore[reportUnboundVariable]
|
|
40
45
|
"""
|
|
41
|
-
Theme
|
|
46
|
+
Theme for the plot title, subtitle, caption, footer, margin and background
|
|
42
47
|
|
|
43
48
|
It also controls the [](`~plotnine.themes.themeables.figure_size`) of the
|
|
44
49
|
composition. The default theme is the same as the default one used for the
|
plotnine/ggplot.py
CHANGED
|
@@ -127,6 +127,8 @@ class ggplot:
|
|
|
127
127
|
| axis_text |
|
|
128
128
|
| axis_title |
|
|
129
129
|
| caption |
|
|
130
|
+
|-------------------------|
|
|
131
|
+
| footer |
|
|
130
132
|
-------------------------
|
|
131
133
|
"""
|
|
132
134
|
|
|
@@ -553,6 +555,7 @@ class ggplot:
|
|
|
553
555
|
subtitle = self.labels.get("subtitle", "")
|
|
554
556
|
caption = self.labels.get("caption", "")
|
|
555
557
|
tag = self.labels.get("tag", "")
|
|
558
|
+
footer = self.labels.get("footer", "")
|
|
556
559
|
|
|
557
560
|
# Get the axis labels (default or specified by user)
|
|
558
561
|
# and let the coordinate modify them e.g. flip
|
|
@@ -570,6 +573,9 @@ class ggplot:
|
|
|
570
573
|
if caption:
|
|
571
574
|
targets.plot_caption = figure.text(0, 0, caption)
|
|
572
575
|
|
|
576
|
+
if footer:
|
|
577
|
+
targets.plot_footer = figure.text(0, 0, footer)
|
|
578
|
+
|
|
573
579
|
if tag:
|
|
574
580
|
targets.plot_tag = figure.text(0, 0, tag)
|
|
575
581
|
|
|
@@ -587,13 +593,30 @@ class ggplot:
|
|
|
587
593
|
wm.draw(self.figure)
|
|
588
594
|
|
|
589
595
|
def _draw_plot_background(self):
|
|
596
|
+
from matplotlib.lines import Line2D
|
|
590
597
|
from matplotlib.patches import Rectangle
|
|
591
598
|
|
|
592
|
-
|
|
599
|
+
zorder = -1000
|
|
600
|
+
rect = Rectangle((0, 0), 0, 0, facecolor="none", zorder=zorder)
|
|
593
601
|
self.figure.add_artist(rect)
|
|
594
602
|
self._gridspec.patch = rect
|
|
595
603
|
self.theme.targets.plot_background = rect
|
|
596
604
|
|
|
605
|
+
# Footer background and line only if there is a footer, and put
|
|
606
|
+
# it on top of the plot background
|
|
607
|
+
if self.labels.get("footer", ""):
|
|
608
|
+
rect = Rectangle(
|
|
609
|
+
(0, 0), 0, 0, facecolor="none", linewidth=0, zorder=zorder + 1
|
|
610
|
+
)
|
|
611
|
+
self.figure.add_artist(rect)
|
|
612
|
+
self.theme.targets.plot_footer_background = rect
|
|
613
|
+
|
|
614
|
+
line = Line2D(
|
|
615
|
+
[0, 0], [0, 0], color="none", linewidth=0, zorder=zorder + 2
|
|
616
|
+
)
|
|
617
|
+
self.figure.add_artist(line)
|
|
618
|
+
self.theme.targets.plot_footer_line = line
|
|
619
|
+
|
|
597
620
|
def _save_filename(self, ext: str) -> Path:
|
|
598
621
|
"""
|
|
599
622
|
Make a filename for use by the save method
|
plotnine/guides/guide_legend.py
CHANGED
|
@@ -272,9 +272,12 @@ class guide_legend(guide):
|
|
|
272
272
|
# Drawings
|
|
273
273
|
drawings: list[ColoredDrawingArea] = []
|
|
274
274
|
for i in range(nbreak):
|
|
275
|
-
|
|
276
|
-
elements.key_widths[i], elements.key_heights[i]
|
|
277
|
-
|
|
275
|
+
try:
|
|
276
|
+
w, h = elements.key_widths[i], elements.key_heights[i]
|
|
277
|
+
except IndexError:
|
|
278
|
+
w, h = elements.empty_key_size
|
|
279
|
+
|
|
280
|
+
da = ColoredDrawingArea(w, h, 0, 0)
|
|
278
281
|
|
|
279
282
|
# overlay geoms
|
|
280
283
|
for params in self._layer_parameters:
|
|
@@ -482,3 +485,14 @@ class GuideElementsLegend(GuideElements):
|
|
|
482
485
|
if self.is_horizontal:
|
|
483
486
|
return [max(hs)] * len(hs)
|
|
484
487
|
return hs
|
|
488
|
+
|
|
489
|
+
@cached_property
|
|
490
|
+
def empty_key_size(self) -> tuple[float, float]:
|
|
491
|
+
"""
|
|
492
|
+
Size of an empty key
|
|
493
|
+
"""
|
|
494
|
+
return (
|
|
495
|
+
(max(self.key_widths), min(self.key_heights))
|
|
496
|
+
if self.is_vertical
|
|
497
|
+
else (min(self.key_widths), max(self.key_heights))
|
|
498
|
+
)
|
plotnine/iapi.py
CHANGED
|
@@ -66,7 +66,7 @@ class range_view:
|
|
|
66
66
|
@dataclass
|
|
67
67
|
class labels_view:
|
|
68
68
|
"""
|
|
69
|
-
Scale labels (incl. caption
|
|
69
|
+
Scale labels (incl. caption, title, footer) for the plot
|
|
70
70
|
"""
|
|
71
71
|
|
|
72
72
|
x: Optional[str] = None
|
|
@@ -80,8 +80,9 @@ class labels_view:
|
|
|
80
80
|
size: Optional[str] = None
|
|
81
81
|
stroke: Optional[str] = None
|
|
82
82
|
title: Optional[str] = None
|
|
83
|
-
caption: Optional[str] = None
|
|
84
83
|
subtitle: Optional[str] = None
|
|
84
|
+
caption: Optional[str] = None
|
|
85
|
+
footer: Optional[str] = None
|
|
85
86
|
tag: Optional[str] = None
|
|
86
87
|
|
|
87
88
|
def update(self, other: labels_view):
|
plotnine/labels.py
CHANGED
plotnine/themes/targets.py
CHANGED
|
@@ -7,6 +7,7 @@ if TYPE_CHECKING:
|
|
|
7
7
|
from typing import Optional
|
|
8
8
|
|
|
9
9
|
from matplotlib.collections import LineCollection
|
|
10
|
+
from matplotlib.lines import Line2D
|
|
10
11
|
from matplotlib.patches import Rectangle
|
|
11
12
|
from matplotlib.text import Text
|
|
12
13
|
|
|
@@ -37,9 +38,12 @@ class ThemeTargets:
|
|
|
37
38
|
panel_border: list[Rectangle] = field(default_factory=list)
|
|
38
39
|
plot_caption: Optional[Text] = None
|
|
39
40
|
plot_subtitle: Optional[Text] = None
|
|
41
|
+
plot_footer: Optional[Text] = None
|
|
40
42
|
plot_tag: Optional[Text] = None
|
|
41
43
|
plot_title: Optional[Text] = None
|
|
42
44
|
plot_background: Optional[Rectangle] = None
|
|
45
|
+
plot_footer_background: Optional[Rectangle] = None
|
|
46
|
+
plot_footer_line: Optional[Line2D] = None
|
|
43
47
|
strip_background_x: list[StripTextPatch] = field(default_factory=list)
|
|
44
48
|
strip_background_y: list[StripTextPatch] = field(default_factory=list)
|
|
45
49
|
strip_text_x: list[StripText] = field(default_factory=list)
|
plotnine/themes/theme.py
CHANGED
|
@@ -124,9 +124,11 @@ class theme:
|
|
|
124
124
|
plot_title=None,
|
|
125
125
|
plot_subtitle=None,
|
|
126
126
|
plot_caption=None,
|
|
127
|
+
plot_footer=None,
|
|
127
128
|
plot_tag=None,
|
|
128
129
|
plot_title_position=None,
|
|
129
130
|
plot_caption_position=None,
|
|
131
|
+
plot_footer_position=None,
|
|
130
132
|
plot_tag_location=None,
|
|
131
133
|
plot_tag_position=None,
|
|
132
134
|
strip_text_x=None,
|
|
@@ -157,6 +159,7 @@ class theme:
|
|
|
157
159
|
panel_grid_major=None,
|
|
158
160
|
panel_grid_minor=None,
|
|
159
161
|
panel_grid=None,
|
|
162
|
+
plot_footer_line=None,
|
|
160
163
|
line=None,
|
|
161
164
|
legend_key=None,
|
|
162
165
|
legend_frame=None,
|
|
@@ -165,6 +168,7 @@ class theme:
|
|
|
165
168
|
panel_background=None,
|
|
166
169
|
panel_border=None,
|
|
167
170
|
plot_background=None,
|
|
171
|
+
plot_footer_background=None,
|
|
168
172
|
strip_background_x=None,
|
|
169
173
|
strip_background_y=None,
|
|
170
174
|
strip_background=None,
|
plotnine/themes/theme_gray.py
CHANGED
|
@@ -109,6 +109,15 @@ class theme_gray(theme):
|
|
|
109
109
|
ma="left",
|
|
110
110
|
margin=margin(t=m, unit="fig"),
|
|
111
111
|
),
|
|
112
|
+
plot_footer=element_text(
|
|
113
|
+
size=base_size * 0.8,
|
|
114
|
+
ha="left",
|
|
115
|
+
va="bottom",
|
|
116
|
+
ma="left",
|
|
117
|
+
margin=margin(t=1 / 3, b=1 / 3, unit="lines"),
|
|
118
|
+
),
|
|
119
|
+
plot_footer_background=element_blank(),
|
|
120
|
+
plot_footer_line=element_blank(),
|
|
112
121
|
plot_margin=m,
|
|
113
122
|
plot_subtitle=element_text(
|
|
114
123
|
va="top",
|
|
@@ -128,6 +137,7 @@ class theme_gray(theme):
|
|
|
128
137
|
),
|
|
129
138
|
plot_title_position="panel",
|
|
130
139
|
plot_caption_position="panel",
|
|
140
|
+
plot_footer_position="plot",
|
|
131
141
|
plot_tag_location="margin",
|
|
132
142
|
plot_tag_position="topleft",
|
|
133
143
|
strip_align=0,
|
|
@@ -85,6 +85,12 @@ class theme_matplotlib(theme):
|
|
|
85
85
|
ma="left",
|
|
86
86
|
margin=margin(t=m, unit="fig"),
|
|
87
87
|
),
|
|
88
|
+
plot_footer=element_text(
|
|
89
|
+
ha="left",
|
|
90
|
+
va="bottom",
|
|
91
|
+
ma="left",
|
|
92
|
+
margin=margin(t=1 / 3, b=1 / 3, unit="lines"),
|
|
93
|
+
),
|
|
88
94
|
plot_margin=m,
|
|
89
95
|
plot_subtitle=element_text(
|
|
90
96
|
size=base_size * 0.9,
|
|
@@ -92,6 +98,8 @@ class theme_matplotlib(theme):
|
|
|
92
98
|
ma="left",
|
|
93
99
|
margin=margin(b=m, unit="fig"),
|
|
94
100
|
),
|
|
101
|
+
plot_footer_background=element_blank(),
|
|
102
|
+
plot_footer_line=element_blank(),
|
|
95
103
|
plot_title=element_text(
|
|
96
104
|
va="top",
|
|
97
105
|
ma="left",
|
|
@@ -104,6 +112,7 @@ class theme_matplotlib(theme):
|
|
|
104
112
|
),
|
|
105
113
|
plot_title_position="panel",
|
|
106
114
|
plot_caption_position="panel",
|
|
115
|
+
plot_footer_position="plot",
|
|
107
116
|
plot_tag_location="margin",
|
|
108
117
|
plot_tag_position="topleft",
|
|
109
118
|
strip_align=0,
|
plotnine/themes/theme_seaborn.py
CHANGED
|
@@ -100,6 +100,15 @@ class theme_seaborn(theme):
|
|
|
100
100
|
ma="left",
|
|
101
101
|
margin=margin(t=m, unit="fig"),
|
|
102
102
|
),
|
|
103
|
+
plot_footer=element_text(
|
|
104
|
+
size=base_size * 0.8,
|
|
105
|
+
ha="left",
|
|
106
|
+
va="bottom",
|
|
107
|
+
ma="left",
|
|
108
|
+
margin=margin(t=1 / 3, b=1 / 3, unit="lines"),
|
|
109
|
+
),
|
|
110
|
+
plot_footer_background=element_blank(),
|
|
111
|
+
plot_footer_line=element_blank(),
|
|
103
112
|
plot_margin=m,
|
|
104
113
|
plot_subtitle=element_text(
|
|
105
114
|
size=base_size * 1,
|
|
@@ -120,6 +129,7 @@ class theme_seaborn(theme):
|
|
|
120
129
|
),
|
|
121
130
|
plot_title_position="panel",
|
|
122
131
|
plot_caption_position="panel",
|
|
132
|
+
plot_footer_position="plot",
|
|
123
133
|
plot_tag_location="margin",
|
|
124
134
|
plot_tag_position="topleft",
|
|
125
135
|
strip_align=0,
|
plotnine/themes/theme_void.py
CHANGED
|
@@ -74,6 +74,13 @@ class theme_void(theme):
|
|
|
74
74
|
ma="left",
|
|
75
75
|
margin=margin(t=m, unit="fig"),
|
|
76
76
|
),
|
|
77
|
+
plot_footer=element_text(
|
|
78
|
+
size=base_size * 0.8,
|
|
79
|
+
ha="left",
|
|
80
|
+
va="bottom",
|
|
81
|
+
ma="left",
|
|
82
|
+
margin=margin(t=1 / 3, b=1 / 3, unit="lines"),
|
|
83
|
+
),
|
|
77
84
|
plot_margin=0,
|
|
78
85
|
plot_subtitle=element_text(
|
|
79
86
|
size=base_size * 1,
|
|
@@ -94,6 +101,7 @@ class theme_void(theme):
|
|
|
94
101
|
),
|
|
95
102
|
plot_title_position="panel",
|
|
96
103
|
plot_caption_position="panel",
|
|
104
|
+
plot_footer_position="plot",
|
|
97
105
|
plot_tag_location="margin",
|
|
98
106
|
plot_tag_position="topleft",
|
|
99
107
|
strip_align=0,
|
plotnine/themes/themeable.py
CHANGED
|
@@ -768,6 +768,28 @@ class plot_caption(themeable):
|
|
|
768
768
|
text.set_visible(False)
|
|
769
769
|
|
|
770
770
|
|
|
771
|
+
class plot_footer(themeable):
|
|
772
|
+
"""
|
|
773
|
+
Plot footer
|
|
774
|
+
|
|
775
|
+
Parameters
|
|
776
|
+
----------
|
|
777
|
+
theme_element : element_text
|
|
778
|
+
"""
|
|
779
|
+
|
|
780
|
+
_omit = ["margin"]
|
|
781
|
+
|
|
782
|
+
def apply_figure(self, figure: Figure, targets: ThemeTargets):
|
|
783
|
+
super().apply_figure(figure, targets)
|
|
784
|
+
if text := targets.plot_footer:
|
|
785
|
+
text.set(**self.properties)
|
|
786
|
+
|
|
787
|
+
def blank_figure(self, figure: Figure, targets: ThemeTargets):
|
|
788
|
+
super().blank_figure(figure, targets)
|
|
789
|
+
if text := targets.plot_footer:
|
|
790
|
+
text.set_visible(False)
|
|
791
|
+
|
|
792
|
+
|
|
771
793
|
class plot_tag(themeable):
|
|
772
794
|
"""
|
|
773
795
|
Plot tag
|
|
@@ -834,6 +856,19 @@ class plot_caption_position(themeable):
|
|
|
834
856
|
"""
|
|
835
857
|
|
|
836
858
|
|
|
859
|
+
class plot_footer_position(themeable):
|
|
860
|
+
"""
|
|
861
|
+
How to align the plot footer
|
|
862
|
+
|
|
863
|
+
Parameters
|
|
864
|
+
----------
|
|
865
|
+
theme_element : Literal["panel", "plot"], default = "plot"
|
|
866
|
+
If "panel", the footer is aligned with respect to the
|
|
867
|
+
panels. If "plot", it is aligned with the plot, excluding
|
|
868
|
+
the margin space.
|
|
869
|
+
"""
|
|
870
|
+
|
|
871
|
+
|
|
837
872
|
class plot_tag_location(themeable):
|
|
838
873
|
"""
|
|
839
874
|
The area where the tag will be positioned
|
|
@@ -919,7 +954,13 @@ class strip_text(strip_text_x, strip_text_y):
|
|
|
919
954
|
|
|
920
955
|
|
|
921
956
|
class title(
|
|
922
|
-
axis_title,
|
|
957
|
+
axis_title,
|
|
958
|
+
legend_title,
|
|
959
|
+
plot_title,
|
|
960
|
+
plot_subtitle,
|
|
961
|
+
plot_caption,
|
|
962
|
+
plot_footer,
|
|
963
|
+
plot_tag,
|
|
923
964
|
):
|
|
924
965
|
"""
|
|
925
966
|
All titles on the plot
|
|
@@ -1476,7 +1517,27 @@ class panel_grid(panel_grid_major, panel_grid_minor):
|
|
|
1476
1517
|
"""
|
|
1477
1518
|
|
|
1478
1519
|
|
|
1479
|
-
class
|
|
1520
|
+
class plot_footer_line(themeable):
|
|
1521
|
+
"""
|
|
1522
|
+
Line above the footer
|
|
1523
|
+
|
|
1524
|
+
Parameters
|
|
1525
|
+
----------
|
|
1526
|
+
theme_element : element_line
|
|
1527
|
+
"""
|
|
1528
|
+
|
|
1529
|
+
def apply_figure(self, figure: Figure, targets: ThemeTargets):
|
|
1530
|
+
super().apply_figure(figure, targets)
|
|
1531
|
+
if targets.plot_footer_line:
|
|
1532
|
+
targets.plot_footer_line.set(**self.properties)
|
|
1533
|
+
|
|
1534
|
+
def blank_figure(self, figure: Figure, targets: ThemeTargets):
|
|
1535
|
+
super().blank_figure(figure, targets)
|
|
1536
|
+
if targets.plot_footer_line:
|
|
1537
|
+
targets.plot_footer_line.set_visible(False)
|
|
1538
|
+
|
|
1539
|
+
|
|
1540
|
+
class line(axis_line, axis_ticks, panel_grid, legend_ticks, plot_footer_line):
|
|
1480
1541
|
"""
|
|
1481
1542
|
All line elements
|
|
1482
1543
|
|
|
@@ -1691,6 +1752,33 @@ class plot_background(themeable):
|
|
|
1691
1752
|
targets.plot_background.set_visible(False)
|
|
1692
1753
|
|
|
1693
1754
|
|
|
1755
|
+
class plot_footer_background(themeable):
|
|
1756
|
+
"""
|
|
1757
|
+
Footer background
|
|
1758
|
+
|
|
1759
|
+
The background is placed across the entire with of the plot,
|
|
1760
|
+
or the composition. And the height is determined by the height
|
|
1761
|
+
of the footer including the top and bottom margin.
|
|
1762
|
+
|
|
1763
|
+
Parameters
|
|
1764
|
+
----------
|
|
1765
|
+
theme_element : element_rect
|
|
1766
|
+
"""
|
|
1767
|
+
|
|
1768
|
+
def apply_figure(self, figure: Figure, targets: ThemeTargets):
|
|
1769
|
+
super().apply_figure(figure, targets)
|
|
1770
|
+
if targets.plot_footer_background:
|
|
1771
|
+
props = self.properties
|
|
1772
|
+
props["linewidth"] = 0
|
|
1773
|
+
props["edgecolor"] = "none"
|
|
1774
|
+
targets.plot_footer_background.set(**props)
|
|
1775
|
+
|
|
1776
|
+
def blank_figure(self, figure: Figure, targets: ThemeTargets):
|
|
1777
|
+
super().blank_figure(figure, targets)
|
|
1778
|
+
if targets.plot_footer_background:
|
|
1779
|
+
targets.plot_footer_background.set_visible(False)
|
|
1780
|
+
|
|
1781
|
+
|
|
1694
1782
|
class strip_background_x(MixinSequenceOfValues):
|
|
1695
1783
|
"""
|
|
1696
1784
|
Horizontal facet label background
|
|
@@ -1747,6 +1835,7 @@ class rect(
|
|
|
1747
1835
|
panel_background,
|
|
1748
1836
|
panel_border,
|
|
1749
1837
|
plot_background,
|
|
1838
|
+
plot_footer_background,
|
|
1750
1839
|
strip_background,
|
|
1751
1840
|
):
|
|
1752
1841
|
"""
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plotnine
|
|
3
|
-
Version: 0.16.
|
|
3
|
+
Version: 0.16.0a3
|
|
4
4
|
Summary: A Grammar of Graphics for Python
|
|
5
5
|
Author-email: Hassan Kibirige <has2k1@gmail.com>
|
|
6
6
|
License: The MIT License (MIT)
|
|
@@ -49,7 +49,7 @@ Requires-Dist: pandas>=2.2.0
|
|
|
49
49
|
Requires-Dist: mizani~=0.14.0
|
|
50
50
|
Requires-Dist: numpy>=1.23.5
|
|
51
51
|
Requires-Dist: scipy>=1.8.0
|
|
52
|
-
Requires-Dist: statsmodels>=0.14.
|
|
52
|
+
Requires-Dist: statsmodels>=0.14.6
|
|
53
53
|
Provides-Extra: all
|
|
54
54
|
Requires-Dist: plotnine[extra]; extra == "all"
|
|
55
55
|
Requires-Dist: plotnine[doc]; extra == "all"
|
|
@@ -2,10 +2,10 @@ plotnine/__init__.py,sha256=_Q18ZKrippC4L27KdYUhuJon95AE8JPZXEYeXZyutms,10372
|
|
|
2
2
|
plotnine/animation.py,sha256=5UK3Y5IHHRtf0sRU5x288XCldn1OhK1NGdMQoTi_Tlg,7683
|
|
3
3
|
plotnine/doctools.py,sha256=JBF55q1MX2fXYQcGDpVrGPdlKf5OiQ5gyTdWhnM_IzU,14558
|
|
4
4
|
plotnine/exceptions.py,sha256=SgTxBHkV65HjGI3aFy2q1_lHP9HAdiuxVLN3U-PJWSQ,1616
|
|
5
|
-
plotnine/ggplot.py,sha256=
|
|
5
|
+
plotnine/ggplot.py,sha256=nPa16xmivwCHsNLWer2kJ418sp0RIArcpzAOaziUwhI,26628
|
|
6
6
|
plotnine/helpers.py,sha256=4R3KZmtGH46-kRNSGOA0JxZaLKBo0ge8Vnx1cDQ8_gI,966
|
|
7
|
-
plotnine/iapi.py,sha256=
|
|
8
|
-
plotnine/labels.py,sha256=
|
|
7
|
+
plotnine/iapi.py,sha256=YGOM4U2z3RB87o2S3p4M3VJkfFHcTHEko_yJ1EyMMI0,9469
|
|
8
|
+
plotnine/labels.py,sha256=5uZdYLXutzife_a7xJIqJ31L_bNCThiIbIqh84PLwVU,2966
|
|
9
9
|
plotnine/layer.py,sha256=l9ehqvWoDpaZdVFLGoiA5USL79NYWWaiZM_ZuDeGzpo,17294
|
|
10
10
|
plotnine/options.py,sha256=j3zXv4wc3J4nOI_TqJ5s_abuifodt_UN8MR8M4i8UVA,3108
|
|
11
11
|
plotnine/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -21,16 +21,16 @@ plotnine/_mpl/ticker.py,sha256=RY_7AdTggc7QBq9_t0KBJXg36oxKfB-Vtc9FzLnaGnQ,393
|
|
|
21
21
|
plotnine/_mpl/transforms.py,sha256=DNaOlNq76xlT696sN8ot1bmYyp4mmrjXQHk3kTi4HIg,76
|
|
22
22
|
plotnine/_mpl/utils.py,sha256=CHRhcOnB7O3Fj953COiwBi6ccF2TQG8puvUVLWO3e_k,11051
|
|
23
23
|
plotnine/_mpl/layout_manager/__init__.py,sha256=w3OZfdMJAFIDrQYVoYG6pvRPqwTNoQ4KJ0zXdJq8L7U,79
|
|
24
|
-
plotnine/_mpl/layout_manager/_composition_layout_items.py,sha256=
|
|
25
|
-
plotnine/_mpl/layout_manager/_composition_side_space.py,sha256=
|
|
24
|
+
plotnine/_mpl/layout_manager/_composition_layout_items.py,sha256=1GQwH1ZvzbenRyi3zmDnLkLck5ndC8UV3u0WdMp0qpw,4705
|
|
25
|
+
plotnine/_mpl/layout_manager/_composition_side_space.py,sha256=VZ56K0agpcQ0XSMgMyCluFkPI1NKS0YmzYD0-LF5H9Q,14538
|
|
26
26
|
plotnine/_mpl/layout_manager/_engine.py,sha256=Fn5Xsk2oPywlG5qj6PTqjgTxxR9tN8npGw7XEaZyXL4,1511
|
|
27
27
|
plotnine/_mpl/layout_manager/_grid.py,sha256=dLzLv5BFVErVoI0DsDeca3zn4JMMcg5tv-BajSV9Ag0,2382
|
|
28
28
|
plotnine/_mpl/layout_manager/_layout_tree.py,sha256=m9QVRa3N6pBVMaoZPTzhXzh_RUVdF54wUgKoxlMpfgw,20794
|
|
29
|
-
plotnine/_mpl/layout_manager/_plot_layout_items.py,sha256=
|
|
30
|
-
plotnine/_mpl/layout_manager/_plot_side_space.py,sha256=
|
|
29
|
+
plotnine/_mpl/layout_manager/_plot_layout_items.py,sha256=XyRDmqEbZSCKeowfx2_OVfZNnhNDR5RS6uoGTHIAyEM,25540
|
|
30
|
+
plotnine/_mpl/layout_manager/_plot_side_space.py,sha256=NqhYZeQBXoqQNpSag26nEh-dnyr8uyhiZF53quAWg0Q,33650
|
|
31
31
|
plotnine/_mpl/layout_manager/_side_space.py,sha256=RjsVctYLzDJyoGpPVEEyGEfJSfEetVhRRiBVz-eQXkI,5303
|
|
32
32
|
plotnine/_utils/__init__.py,sha256=wefs_rvVdrWwhyWtDLarI6Bm7CDNUSSBWYlvbdWDzLQ,31528
|
|
33
|
-
plotnine/_utils/context.py,sha256=
|
|
33
|
+
plotnine/_utils/context.py,sha256=VrM2SP91xSwYZAflJYgp4WaglxFBn222NyrMM8ux-sk,3988
|
|
34
34
|
plotnine/_utils/dataclasses.py,sha256=ahEoC7WeMsRB4_M9YBAuMpR-xm6LkpryAueLwJMXkNo,609
|
|
35
35
|
plotnine/_utils/dev.py,sha256=0qgRbMhcd4dfuLuYxx0skocKAtfwHF02ntyILRBogbg,1629
|
|
36
36
|
plotnine/_utils/ipython.py,sha256=mGD83wi3q0Sk2XfAbr9zyBxYNXVwXv-lmgnA3QXH0bI,1768
|
|
@@ -39,8 +39,8 @@ plotnine/_utils/registry.py,sha256=HoiB2NnbEHufXjYnVJyrJKflk2RwKtTYk2L3n7tH4XA,3
|
|
|
39
39
|
plotnine/_utils/yippie.py,sha256=DbmxvVrd34P24CCmOZrAulyGQ35rXNaSr8BuutS2Uio,2392
|
|
40
40
|
plotnine/composition/__init__.py,sha256=OoJG-K08x_c7abAGRfdWIBnGcBfRlC_WekjMd2ktQ6g,360
|
|
41
41
|
plotnine/composition/_beside.py,sha256=TxrmQCFnmMnqoMawDhTLj5l-J4_VWL1XRDnjoQChFBQ,1436
|
|
42
|
-
plotnine/composition/_compose.py,sha256=
|
|
43
|
-
plotnine/composition/_plot_annotation.py,sha256=
|
|
42
|
+
plotnine/composition/_compose.py,sha256=4wPU3P-2WNBGnLFhPLaQZSyy_vTujovJhpe3cBOtpiw,18465
|
|
43
|
+
plotnine/composition/_plot_annotation.py,sha256=RMA_vdcHFT9KVUbhwS-NZdPTbqb-XgAYRflWs8J3bVE,2116
|
|
44
44
|
plotnine/composition/_plot_layout.py,sha256=JPYPtRutHtILOLU1xf6x0c1G_263Q_62GtN0kI0LqxE,3732
|
|
45
45
|
plotnine/composition/_plot_spacer.py,sha256=RSzH4yRdcK0iairZZ88CE8onpr6NzNaDgtNnSW6ePzY,1859
|
|
46
46
|
plotnine/composition/_stack.py,sha256=djjFrqO3-lOvKMYw87OSrF4BbHU9deFrk0l1wpUYSS8,1454
|
|
@@ -131,7 +131,7 @@ plotnine/guides/__init__.py,sha256=ulI-mDhtq3jAQEAqPv8clrn3UHGFOu3xRuO7jXlq-LY,2
|
|
|
131
131
|
plotnine/guides/guide.py,sha256=09Zojde0stGEZbVNyx6m5As2PCaLRxzQvYNid-Y0YBU,8596
|
|
132
132
|
plotnine/guides/guide_axis.py,sha256=zG_5Ot1kTuHOeuQspL5V1A1-7c7X8cNeMDoF01Ghh2w,296
|
|
133
133
|
plotnine/guides/guide_colorbar.py,sha256=1RbF2WjqrouoELBdZNpy-4olsnJoSTOX--RYgbCx-Gw,18322
|
|
134
|
-
plotnine/guides/guide_legend.py,sha256=
|
|
134
|
+
plotnine/guides/guide_legend.py,sha256=EshNFzbYUiR31J0ZFLGrJmdZk9AwRawIcY5INpr8vcw,15486
|
|
135
135
|
plotnine/guides/guides.py,sha256=SzdmK-XX5cR6YgysjNjdoynCATThX1pDDX2a6ghvseU,15485
|
|
136
136
|
plotnine/mapping/__init__.py,sha256=DLu9E0kwwuHxzTUenoVjCNTTdkWMwIDtkExLleBq1MI,205
|
|
137
137
|
plotnine/mapping/_atomic.py,sha256=TbobHVJlHRoSHibi6OOWMVM2J1r_kKQJMS6G5zvEhrg,4029
|
|
@@ -199,22 +199,22 @@ plotnine/stats/stat_unique.py,sha256=1SdLNm2CjhjONAwo714uB3tc5KX7vSDHAi1geJdWtDY
|
|
|
199
199
|
plotnine/stats/stat_ydensity.py,sha256=_OVYc-QELPKMc24BvQaA9cPkfEoC_hW2teeo8yL8iao,5661
|
|
200
200
|
plotnine/themes/__init__.py,sha256=tEKIF4gYmOF2Z1-_UDdK8zh41dLl-61HUGIhOQvki6I,916
|
|
201
201
|
plotnine/themes/seaborn_rcmod.py,sha256=Pi-UX5LyH9teSuteYpqPOEnfLgKUz01LnKDyDA7Aois,15502
|
|
202
|
-
plotnine/themes/targets.py,sha256=
|
|
203
|
-
plotnine/themes/theme.py,sha256=
|
|
202
|
+
plotnine/themes/targets.py,sha256=yEwkaDhL1UoOBdlx9SWCQsSRg9oOjnFZgtJrtY_LyFA,1866
|
|
203
|
+
plotnine/themes/theme.py,sha256=zucHnZ4pJC_iLxBEy-ZNRLa6sRuKEeMq6SHW-sywoiE,16218
|
|
204
204
|
plotnine/themes/theme_538.py,sha256=hr0FaGAffZYU3m8o90WuUWntaPgI2O_eGiaBz259MiM,1088
|
|
205
205
|
plotnine/themes/theme_bw.py,sha256=XXUt9KXEIkROiU0ZVIZicypneb-zL5K1cQFPqYd5WAI,1010
|
|
206
206
|
plotnine/themes/theme_classic.py,sha256=B6QkU6blGnEY5iaiPtu4VsvFzC0peWSAhlKiC2SJSkM,923
|
|
207
207
|
plotnine/themes/theme_dark.py,sha256=tF6BJ2A4jE6C-Mhl95DQiAbu-mK0Hr1MaymhbJzaD2Q,1255
|
|
208
|
-
plotnine/themes/theme_gray.py,sha256=
|
|
208
|
+
plotnine/themes/theme_gray.py,sha256=yKbjIowSSFiP5lBDk30dBSuUwtRyv8L8b5XZi6TEfWQ,5641
|
|
209
209
|
plotnine/themes/theme_light.py,sha256=1vDa6QlLz2vJaa1gYfyttVuXxde2MwDnMnJAqToJMGs,1415
|
|
210
210
|
plotnine/themes/theme_linedraw.py,sha256=woMr18xoEJmsD8ZCiUpdyn-CE-P1AGFHRNapwCGWUjg,1350
|
|
211
|
-
plotnine/themes/theme_matplotlib.py,sha256=
|
|
211
|
+
plotnine/themes/theme_matplotlib.py,sha256=8isOcIJlq8c3RbZnPLj6aUIAMHbTzLSF7gFHGdiO0Wk,4586
|
|
212
212
|
plotnine/themes/theme_minimal.py,sha256=YhkKNA48jP2OLa8-kHMfXFEFRjcsfWBLMID2orITrmo,884
|
|
213
|
-
plotnine/themes/theme_seaborn.py,sha256=
|
|
213
|
+
plotnine/themes/theme_seaborn.py,sha256=iJM3HR0BlElhIj0PvqR1bGyJGaWPKQnz6K7AQGkGmps,4695
|
|
214
214
|
plotnine/themes/theme_tufte.py,sha256=qUOrZhQyfJgc0fmy8Es7tT7aYqUSzCjvkP7-dBilwHE,1926
|
|
215
|
-
plotnine/themes/theme_void.py,sha256=
|
|
215
|
+
plotnine/themes/theme_void.py,sha256=e7OgZPR0pmAewwKxKYtRR2X6zGSySGjdXKPHikZK6S0,3501
|
|
216
216
|
plotnine/themes/theme_xkcd.py,sha256=5MOdj_H23Kr_jbDnepmq1DQDbn8-TfUmtzYBZTb4RB4,2207
|
|
217
|
-
plotnine/themes/themeable.py,sha256=
|
|
217
|
+
plotnine/themes/themeable.py,sha256=mCqZzo7gm0J1AqpSfeUOsfKijwuI8o1dOcU33he6kT4,74782
|
|
218
218
|
plotnine/themes/elements/__init__.py,sha256=xV1la_mTv1BQ3zQp7ZGVGPdV6KohvEVhKAi1uPTeAs0,327
|
|
219
219
|
plotnine/themes/elements/element_base.py,sha256=D7cfEglzsSuhW91KpZVAZ2MAHWZp64r9Aajoh8uMGZ4,832
|
|
220
220
|
plotnine/themes/elements/element_blank.py,sha256=4r7-6HeR1494oWNIGQh0ASrFQ4SLvYa6aQHA85eH-Ds,187
|
|
@@ -222,8 +222,8 @@ plotnine/themes/elements/element_line.py,sha256=zJ6KL2_LcQ0aQjT4fzNA1f9c1QZ3xEeT
|
|
|
222
222
|
plotnine/themes/elements/element_rect.py,sha256=w5cLH-Sr4cTRXVdkRiu8kBqFt3TXHhIb1MUITfi89gE,1767
|
|
223
223
|
plotnine/themes/elements/element_text.py,sha256=NrHlGKB0cO0v_C7hkarTMPb2QVsTOoxVuCMS6hmv62U,6552
|
|
224
224
|
plotnine/themes/elements/margin.py,sha256=jMHe-UKHHer_VYwAVDC-Tz2-AP_4YDuXPTWAuacoqgU,4080
|
|
225
|
-
plotnine-0.16.
|
|
226
|
-
plotnine-0.16.
|
|
227
|
-
plotnine-0.16.
|
|
228
|
-
plotnine-0.16.
|
|
229
|
-
plotnine-0.16.
|
|
225
|
+
plotnine-0.16.0a3.dist-info/licenses/LICENSE,sha256=GY4tQiUd17Tq3wWR42Zs9MRTFOTf6ahIXhZTcwAdOeU,1082
|
|
226
|
+
plotnine-0.16.0a3.dist-info/METADATA,sha256=O9d0UTthOHQ1pUScUwJSfK9v02LSQlJASwALXCa3vNs,9498
|
|
227
|
+
plotnine-0.16.0a3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
228
|
+
plotnine-0.16.0a3.dist-info/top_level.txt,sha256=t340Mbko1ZbmvYPkQ81dIiPHcaQdTUszYz-bWUpr8ys,9
|
|
229
|
+
plotnine-0.16.0a3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|