plotnine 0.14.4__py3-none-any.whl → 0.15.0.dev1__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/__init__.py +31 -37
- plotnine/_mpl/gridspec.py +265 -0
- plotnine/_mpl/layout_manager/__init__.py +6 -0
- plotnine/_mpl/layout_manager/_engine.py +87 -0
- plotnine/_mpl/layout_manager/_layout_items.py +775 -0
- plotnine/_mpl/layout_manager/_layout_tree.py +625 -0
- plotnine/_mpl/layout_manager/_spaces.py +1007 -0
- plotnine/_mpl/utils.py +78 -10
- plotnine/_utils/__init__.py +4 -4
- plotnine/_utils/dev.py +45 -27
- plotnine/animation.py +1 -1
- plotnine/coords/coord_trans.py +1 -1
- plotnine/data/__init__.py +12 -8
- plotnine/doctools.py +1 -1
- plotnine/facets/facet.py +30 -39
- plotnine/facets/facet_grid.py +14 -6
- plotnine/facets/facet_wrap.py +3 -5
- plotnine/facets/strips.py +2 -7
- plotnine/geoms/geom_crossbar.py +2 -3
- plotnine/geoms/geom_path.py +1 -1
- plotnine/geoms/geom_text.py +3 -1
- plotnine/ggplot.py +94 -65
- plotnine/guides/guide.py +10 -8
- plotnine/guides/guide_colorbar.py +3 -3
- plotnine/guides/guide_legend.py +5 -5
- plotnine/guides/guides.py +3 -3
- plotnine/iapi.py +1 -0
- plotnine/labels.py +5 -0
- plotnine/options.py +14 -7
- plotnine/plot_composition/__init__.py +10 -0
- plotnine/plot_composition/_compose.py +427 -0
- plotnine/plot_composition/_plotspec.py +50 -0
- plotnine/plot_composition/_spacer.py +32 -0
- plotnine/positions/position_dodge.py +1 -1
- plotnine/positions/position_dodge2.py +1 -1
- plotnine/positions/position_stack.py +1 -2
- plotnine/qplot.py +1 -2
- plotnine/scales/__init__.py +0 -6
- plotnine/scales/scale.py +1 -1
- plotnine/stats/binning.py +1 -1
- plotnine/stats/smoothers.py +3 -5
- plotnine/stats/stat_density.py +1 -1
- plotnine/stats/stat_qq_line.py +1 -1
- plotnine/stats/stat_sina.py +1 -1
- plotnine/themes/elements/__init__.py +2 -0
- plotnine/themes/elements/element_text.py +34 -24
- plotnine/themes/elements/margin.py +73 -60
- plotnine/themes/targets.py +2 -0
- plotnine/themes/theme.py +13 -7
- plotnine/themes/theme_gray.py +27 -31
- plotnine/themes/theme_matplotlib.py +25 -28
- plotnine/themes/theme_seaborn.py +31 -34
- plotnine/themes/theme_void.py +17 -26
- plotnine/themes/themeable.py +286 -153
- {plotnine-0.14.4.dist-info → plotnine-0.15.0.dev1.dist-info}/METADATA +4 -3
- {plotnine-0.14.4.dist-info → plotnine-0.15.0.dev1.dist-info}/RECORD +59 -52
- {plotnine-0.14.4.dist-info → plotnine-0.15.0.dev1.dist-info}/WHEEL +1 -1
- plotnine/_mpl/_plot_side_space.py +0 -888
- plotnine/_mpl/_plotnine_tight_layout.py +0 -293
- plotnine/_mpl/layout_engine.py +0 -110
- {plotnine-0.14.4.dist-info → plotnine-0.15.0.dev1.dist-info/licenses}/LICENSE +0 -0
- {plotnine-0.14.4.dist-info → plotnine-0.15.0.dev1.dist-info}/top_level.txt +0 -0
plotnine/ggplot.py
CHANGED
|
@@ -6,7 +6,15 @@ from io import BytesIO
|
|
|
6
6
|
from itertools import chain
|
|
7
7
|
from pathlib import Path
|
|
8
8
|
from types import SimpleNamespace as NS
|
|
9
|
-
from typing import
|
|
9
|
+
from typing import (
|
|
10
|
+
TYPE_CHECKING,
|
|
11
|
+
Any,
|
|
12
|
+
Dict,
|
|
13
|
+
Iterable,
|
|
14
|
+
Optional,
|
|
15
|
+
cast,
|
|
16
|
+
overload,
|
|
17
|
+
)
|
|
10
18
|
from warnings import warn
|
|
11
19
|
|
|
12
20
|
from ._utils import (
|
|
@@ -44,9 +52,11 @@ if TYPE_CHECKING:
|
|
|
44
52
|
from typing_extensions import Self
|
|
45
53
|
|
|
46
54
|
from plotnine import watermark
|
|
55
|
+
from plotnine._mpl.gridspec import p9GridSpec
|
|
47
56
|
from plotnine.coords.coord import coord
|
|
48
57
|
from plotnine.facets.facet import facet
|
|
49
58
|
from plotnine.layer import layer
|
|
59
|
+
from plotnine.plot_composition import Compose
|
|
50
60
|
from plotnine.typing import DataLike
|
|
51
61
|
|
|
52
62
|
class PlotAddable(Protocol):
|
|
@@ -95,9 +105,7 @@ class ggplot:
|
|
|
95
105
|
|
|
96
106
|
figure: Figure
|
|
97
107
|
axs: list[Axes]
|
|
98
|
-
|
|
99
|
-
facet: facet
|
|
100
|
-
coordinates: coord
|
|
108
|
+
_gridspec: p9GridSpec
|
|
101
109
|
|
|
102
110
|
def __init__(
|
|
103
111
|
self,
|
|
@@ -110,7 +118,7 @@ class ggplot:
|
|
|
110
118
|
data, mapping = order_as_data_mapping(data, mapping)
|
|
111
119
|
self.data = data
|
|
112
120
|
self.mapping = mapping if mapping is not None else aes()
|
|
113
|
-
self.facet = facet_null()
|
|
121
|
+
self.facet: facet = facet_null()
|
|
114
122
|
self.labels = make_labels(self.mapping)
|
|
115
123
|
self.layers = Layers()
|
|
116
124
|
self.guides = guides()
|
|
@@ -147,6 +155,11 @@ class ggplot:
|
|
|
147
155
|
Users should prefer this method instead of printing or repring
|
|
148
156
|
the object.
|
|
149
157
|
"""
|
|
158
|
+
# Prevent against any modifications to the users
|
|
159
|
+
# ggplot object. Do the copy here as we may/may not
|
|
160
|
+
# assign a default theme
|
|
161
|
+
self = deepcopy(self)
|
|
162
|
+
|
|
150
163
|
if is_inline_backend() or is_quarto_environment():
|
|
151
164
|
# Take charge of the display because we have to make
|
|
152
165
|
# adjustments for retina output.
|
|
@@ -167,18 +180,15 @@ class ggplot:
|
|
|
167
180
|
format = get_option("figure_format") or ip.config.InlineBackend.get(
|
|
168
181
|
"figure_format", "retina"
|
|
169
182
|
)
|
|
170
|
-
save_format = format
|
|
171
|
-
|
|
172
183
|
# While jpegs can be displayed as retina, we restrict the output
|
|
173
184
|
# of "retina" to png
|
|
174
185
|
if format == "retina":
|
|
175
186
|
self = copy(self)
|
|
176
187
|
self.theme = self.theme.to_retina()
|
|
177
|
-
save_format = "png"
|
|
178
188
|
|
|
179
|
-
figure_size_px = self.theme._figure_size_px
|
|
180
189
|
buf = BytesIO()
|
|
181
|
-
self.save(buf, format
|
|
190
|
+
self.save(buf, "png" if format == "retina" else format, verbose=False)
|
|
191
|
+
figure_size_px = self.theme._figure_size_px
|
|
182
192
|
display_func = get_display_function(format, figure_size_px)
|
|
183
193
|
display_func(buf.getvalue())
|
|
184
194
|
|
|
@@ -193,7 +203,7 @@ class ggplot:
|
|
|
193
203
|
new = result.__dict__
|
|
194
204
|
|
|
195
205
|
# don't make a deepcopy of data
|
|
196
|
-
shallow = {"data", "figure", "_build_objs"}
|
|
206
|
+
shallow = {"data", "figure", "gs", "_build_objs"}
|
|
197
207
|
for key, item in old.items():
|
|
198
208
|
if key in shallow:
|
|
199
209
|
new[key] = item
|
|
@@ -220,9 +230,20 @@ class ggplot:
|
|
|
220
230
|
other.__radd__(self)
|
|
221
231
|
return self
|
|
222
232
|
|
|
223
|
-
|
|
233
|
+
@overload
|
|
234
|
+
def __add__(
|
|
235
|
+
self, rhs: PlotAddable | list[PlotAddable] | None
|
|
236
|
+
) -> ggplot: ...
|
|
237
|
+
|
|
238
|
+
@overload
|
|
239
|
+
def __add__(self, rhs: ggplot | Compose) -> Compose: ...
|
|
240
|
+
|
|
241
|
+
def __add__(
|
|
242
|
+
self,
|
|
243
|
+
rhs: PlotAddable | list[PlotAddable] | None | ggplot | Compose,
|
|
244
|
+
) -> ggplot | Compose:
|
|
224
245
|
"""
|
|
225
|
-
Add to ggplot
|
|
246
|
+
Add to ggplot
|
|
226
247
|
|
|
227
248
|
Parameters
|
|
228
249
|
----------
|
|
@@ -230,8 +251,37 @@ class ggplot:
|
|
|
230
251
|
Either an object that knows how to "radd"
|
|
231
252
|
itself to a ggplot, or a list of such objects.
|
|
232
253
|
"""
|
|
254
|
+
from .plot_composition import ADD, Compose
|
|
255
|
+
|
|
256
|
+
if isinstance(rhs, (ggplot, Compose)):
|
|
257
|
+
return ADD([self, rhs])
|
|
258
|
+
|
|
233
259
|
self = deepcopy(self)
|
|
234
|
-
return self.__iadd__(
|
|
260
|
+
return self.__iadd__(rhs)
|
|
261
|
+
|
|
262
|
+
def __or__(self, rhs: ggplot | Compose) -> Compose:
|
|
263
|
+
"""
|
|
264
|
+
Compose 2 plots columnwise
|
|
265
|
+
"""
|
|
266
|
+
from .plot_composition import OR
|
|
267
|
+
|
|
268
|
+
return OR([self, rhs])
|
|
269
|
+
|
|
270
|
+
def __truediv__(self, rhs: ggplot | Compose) -> Compose:
|
|
271
|
+
"""
|
|
272
|
+
Compose 2 plots rowwise
|
|
273
|
+
"""
|
|
274
|
+
from .plot_composition import DIV
|
|
275
|
+
|
|
276
|
+
return DIV([self, rhs])
|
|
277
|
+
|
|
278
|
+
def __sub__(self, rhs: ggplot | Compose) -> Compose:
|
|
279
|
+
"""
|
|
280
|
+
Compose 2 plots columnwise
|
|
281
|
+
"""
|
|
282
|
+
from .plot_composition import OR
|
|
283
|
+
|
|
284
|
+
return OR([self, rhs])
|
|
235
285
|
|
|
236
286
|
def __rrshift__(self, other: DataLike) -> ggplot:
|
|
237
287
|
"""
|
|
@@ -248,7 +298,7 @@ class ggplot:
|
|
|
248
298
|
raise TypeError(msg.format(type(other)))
|
|
249
299
|
return self
|
|
250
300
|
|
|
251
|
-
def draw(self, show: bool = False) -> Figure:
|
|
301
|
+
def draw(self, *, show: bool = False) -> Figure:
|
|
252
302
|
"""
|
|
253
303
|
Render the complete plot
|
|
254
304
|
|
|
@@ -262,23 +312,17 @@ class ggplot:
|
|
|
262
312
|
:
|
|
263
313
|
Matplotlib figure
|
|
264
314
|
"""
|
|
265
|
-
from ._mpl.
|
|
266
|
-
|
|
267
|
-
# Do not draw if drawn already.
|
|
268
|
-
# This prevents a needless error when reusing
|
|
269
|
-
# figure & axes in the jupyter notebook.
|
|
270
|
-
if hasattr(self, "figure"):
|
|
271
|
-
return self.figure
|
|
315
|
+
from ._mpl.layout_manager import PlotnineLayoutEngine
|
|
272
316
|
|
|
273
|
-
# Prevent against any modifications to the users
|
|
274
|
-
# ggplot object. Do the copy here as we may/may not
|
|
275
|
-
# assign a default theme
|
|
276
|
-
self = deepcopy(self)
|
|
277
317
|
with plot_context(self, show=show):
|
|
318
|
+
if not hasattr(self, "figure"):
|
|
319
|
+
self._create_figure()
|
|
320
|
+
figure = self.figure
|
|
321
|
+
|
|
278
322
|
self._build()
|
|
279
323
|
|
|
280
324
|
# setup
|
|
281
|
-
self.
|
|
325
|
+
self.axs = self.facet.setup(self)
|
|
282
326
|
self.guides._setup(self)
|
|
283
327
|
self.theme.setup(self)
|
|
284
328
|
|
|
@@ -289,51 +333,24 @@ class ggplot:
|
|
|
289
333
|
self.guides.draw()
|
|
290
334
|
self._draw_figure_texts()
|
|
291
335
|
self._draw_watermarks()
|
|
336
|
+
self._draw_figure_background()
|
|
292
337
|
|
|
293
338
|
# Artist object theming
|
|
294
339
|
self.theme.apply()
|
|
295
|
-
|
|
340
|
+
figure.set_layout_engine(PlotnineLayoutEngine(self))
|
|
296
341
|
|
|
297
|
-
return
|
|
342
|
+
return figure
|
|
298
343
|
|
|
299
|
-
def
|
|
344
|
+
def _create_figure(self):
|
|
300
345
|
"""
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
This is can be used to draw animation frames,
|
|
304
|
-
or inset plots. It is intended to be used
|
|
305
|
-
after the key plot has been drawn.
|
|
306
|
-
|
|
307
|
-
Parameters
|
|
308
|
-
----------
|
|
309
|
-
figure :
|
|
310
|
-
Matplotlib figure
|
|
311
|
-
axs :
|
|
312
|
-
Array of Axes onto which to draw the plots
|
|
346
|
+
Create gridspec for the panels
|
|
313
347
|
"""
|
|
314
|
-
|
|
348
|
+
import matplotlib.pyplot as plt
|
|
315
349
|
|
|
316
|
-
|
|
317
|
-
self.figure = figure
|
|
318
|
-
self.axs = axs
|
|
319
|
-
with plot_context(self):
|
|
320
|
-
self._build()
|
|
350
|
+
from ._mpl.gridspec import p9GridSpec
|
|
321
351
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
self.guides._setup(self)
|
|
325
|
-
self.theme.setup(self)
|
|
326
|
-
|
|
327
|
-
# drawing
|
|
328
|
-
self._draw_layers()
|
|
329
|
-
self._draw_breaks_and_labels()
|
|
330
|
-
self.guides.draw()
|
|
331
|
-
|
|
332
|
-
# artist theming
|
|
333
|
-
self.theme.apply()
|
|
334
|
-
self.figure.set_layout_engine(PlotnineLayoutEngine(self))
|
|
335
|
-
|
|
336
|
-
return self
|
|
352
|
+
self.figure = plt.figure()
|
|
353
|
+
self._gridspec = p9GridSpec(1, 1, self.figure)
|
|
337
354
|
|
|
338
355
|
def _build(self):
|
|
339
356
|
"""
|
|
@@ -491,6 +508,7 @@ class ggplot:
|
|
|
491
508
|
title = self.labels.get("title", "")
|
|
492
509
|
subtitle = self.labels.get("subtitle", "")
|
|
493
510
|
caption = self.labels.get("caption", "")
|
|
511
|
+
tag = self.labels.get("tag", "")
|
|
494
512
|
|
|
495
513
|
# Get the axis labels (default or specified by user)
|
|
496
514
|
# and let the coordinate modify them e.g. flip
|
|
@@ -508,6 +526,9 @@ class ggplot:
|
|
|
508
526
|
if caption:
|
|
509
527
|
targets.plot_caption = figure.text(0, 0, caption)
|
|
510
528
|
|
|
529
|
+
if tag:
|
|
530
|
+
targets.plot_tag = figure.text(0, 0, tag)
|
|
531
|
+
|
|
511
532
|
if labels.x:
|
|
512
533
|
targets.axis_title_x = figure.text(0, 0, labels.x)
|
|
513
534
|
|
|
@@ -521,6 +542,14 @@ class ggplot:
|
|
|
521
542
|
for wm in self.watermarks:
|
|
522
543
|
wm.draw(self.figure)
|
|
523
544
|
|
|
545
|
+
def _draw_figure_background(self):
|
|
546
|
+
from matplotlib.patches import Rectangle
|
|
547
|
+
|
|
548
|
+
rect = Rectangle((0, 0), 0, 0, facecolor="none", zorder=-1000)
|
|
549
|
+
self.figure.add_artist(rect)
|
|
550
|
+
self._gridspec.patch = rect
|
|
551
|
+
self.theme.targets.plot_background = rect
|
|
552
|
+
|
|
524
553
|
def _save_filename(self, ext: str) -> Path:
|
|
525
554
|
"""
|
|
526
555
|
Make a filename for use by the save method
|
|
@@ -572,7 +601,7 @@ class ggplot:
|
|
|
572
601
|
fig_kwargs: Dict[str, Any] = {"format": format, **kwargs}
|
|
573
602
|
|
|
574
603
|
if limitsize is None:
|
|
575
|
-
limitsize = cast(bool, get_option("limitsize"))
|
|
604
|
+
limitsize = cast("bool", get_option("limitsize"))
|
|
576
605
|
|
|
577
606
|
# filename, depends on the object
|
|
578
607
|
if filename is None:
|
|
@@ -598,7 +627,7 @@ class ggplot:
|
|
|
598
627
|
raise PlotnineError("You must specify both width and height")
|
|
599
628
|
else:
|
|
600
629
|
width, height = cast(
|
|
601
|
-
tuple[float, float], self.theme.getp("figure_size")
|
|
630
|
+
"tuple[float, float]", self.theme.getp("figure_size")
|
|
602
631
|
)
|
|
603
632
|
|
|
604
633
|
if limitsize and (width > 25 or height > 25):
|
plotnine/guides/guide.py
CHANGED
|
@@ -76,7 +76,7 @@ class guide(ABC, metaclass=Register):
|
|
|
76
76
|
self.plot_layers: Layers
|
|
77
77
|
self.plot_mapping: aes
|
|
78
78
|
self._elements_cls = GuideElements
|
|
79
|
-
self.elements = cast(GuideElements, None)
|
|
79
|
+
self.elements = cast("GuideElements", None)
|
|
80
80
|
self.guides_elements: GuidesElements
|
|
81
81
|
|
|
82
82
|
def legend_aesthetics(self, layer):
|
|
@@ -132,14 +132,14 @@ class guide(ABC, metaclass=Register):
|
|
|
132
132
|
pos = self.elements.position
|
|
133
133
|
just_view = asdict(self.guides_elements.justification)
|
|
134
134
|
if isinstance(pos, str):
|
|
135
|
-
just = cast(float, just_view[pos])
|
|
135
|
+
just = cast("float", just_view[pos])
|
|
136
136
|
return (pos, just)
|
|
137
137
|
else:
|
|
138
138
|
# If no justification is given for an inside legend,
|
|
139
139
|
# we use the position of the legend
|
|
140
140
|
if (just := just_view["inside"]) is None:
|
|
141
141
|
just = pos
|
|
142
|
-
just = cast(tuple[float, float], just)
|
|
142
|
+
just = cast("tuple[float, float]", just)
|
|
143
143
|
return (pos, just)
|
|
144
144
|
|
|
145
145
|
def train(
|
|
@@ -191,9 +191,9 @@ class GuideElements:
|
|
|
191
191
|
def title(self):
|
|
192
192
|
ha = self.theme.getp(("legend_title", "ha"))
|
|
193
193
|
va = self.theme.getp(("legend_title", "va"), "center")
|
|
194
|
-
_margin = self.theme.getp(("legend_title", "margin"))
|
|
194
|
+
_margin = self.theme.getp(("legend_title", "margin")).pt
|
|
195
195
|
_loc = get_opposite_side(self.title_position)[0]
|
|
196
|
-
margin = _margin
|
|
196
|
+
margin = getattr(_margin, _loc)
|
|
197
197
|
top_or_bottom = self.title_position in ("top", "bottom")
|
|
198
198
|
is_blank = self.theme.T.is_blank("legend_title")
|
|
199
199
|
|
|
@@ -218,9 +218,11 @@ class GuideElements:
|
|
|
218
218
|
|
|
219
219
|
@cached_property
|
|
220
220
|
def _text_margin(self) -> float:
|
|
221
|
-
_margin = self.theme.getp(
|
|
222
|
-
|
|
223
|
-
|
|
221
|
+
_margin = self.theme.getp(
|
|
222
|
+
(f"legend_text_{self.guide_kind}", "margin")
|
|
223
|
+
).pt
|
|
224
|
+
_loc = get_opposite_side(self.text_position)[0]
|
|
225
|
+
return getattr(_margin, _loc)
|
|
224
226
|
|
|
225
227
|
@cached_property
|
|
226
228
|
def title_position(self) -> SidePosition:
|
|
@@ -75,8 +75,8 @@ class guide_colorbar(guide):
|
|
|
75
75
|
self.nbin = 300 # if self.display == "gradient" else 300
|
|
76
76
|
|
|
77
77
|
def train(self, scale: scale, aesthetic=None):
|
|
78
|
-
self.nbin = cast(int, self.nbin)
|
|
79
|
-
self.title = cast(str, self.title)
|
|
78
|
+
self.nbin = cast("int", self.nbin)
|
|
79
|
+
self.title = cast("str", self.title)
|
|
80
80
|
|
|
81
81
|
if not isinstance(scale, scale_continuous):
|
|
82
82
|
warn("colorbar guide needs continuous scales", PlotnineWarning)
|
|
@@ -213,7 +213,7 @@ class guide_colorbar(guide):
|
|
|
213
213
|
auxbox = DPICorAuxTransformBox(IdentityTransform())
|
|
214
214
|
|
|
215
215
|
# title
|
|
216
|
-
title = cast(str, self.title)
|
|
216
|
+
title = cast("str", self.title)
|
|
217
217
|
props = {"ha": elements.title.ha, "va": elements.title.va}
|
|
218
218
|
title_box = TextArea(title, textprops=props)
|
|
219
219
|
targets.legend_title = title_box._text # type: ignore
|
plotnine/guides/guide_legend.py
CHANGED
|
@@ -226,10 +226,10 @@ class guide_legend(guide):
|
|
|
226
226
|
ncol = int(np.ceil(nbreak / 15))
|
|
227
227
|
|
|
228
228
|
if nrow is None:
|
|
229
|
-
ncol = cast(int, ncol)
|
|
229
|
+
ncol = cast("int", ncol)
|
|
230
230
|
nrow = int(np.ceil(nbreak / ncol))
|
|
231
231
|
elif ncol is None:
|
|
232
|
-
nrow = cast(int, nrow)
|
|
232
|
+
nrow = cast("int", nrow)
|
|
233
233
|
ncol = int(np.ceil(nbreak / nrow))
|
|
234
234
|
|
|
235
235
|
return nrow, ncol
|
|
@@ -255,7 +255,7 @@ class guide_legend(guide):
|
|
|
255
255
|
elements = self.elements
|
|
256
256
|
|
|
257
257
|
# title
|
|
258
|
-
title = cast(str, self.title)
|
|
258
|
+
title = cast("str", self.title)
|
|
259
259
|
title_box = TextArea(title)
|
|
260
260
|
targets.legend_title = title_box._text # type: ignore
|
|
261
261
|
|
|
@@ -403,7 +403,7 @@ class GuideElementsLegend(GuideElements):
|
|
|
403
403
|
dimensions are big enough.
|
|
404
404
|
"""
|
|
405
405
|
# Note the different height sizes for the entries
|
|
406
|
-
guide = cast(guide_legend, self.guide)
|
|
406
|
+
guide = cast("guide_legend", self.guide)
|
|
407
407
|
min_size = (
|
|
408
408
|
self.theme.getp("legend_key_width"),
|
|
409
409
|
self.theme.getp("legend_key_height"),
|
|
@@ -452,7 +452,7 @@ class GuideElementsLegend(GuideElements):
|
|
|
452
452
|
If legend is horizontal, then key heights must be equal, so we
|
|
453
453
|
use the maximum
|
|
454
454
|
"""
|
|
455
|
-
hs = [h for
|
|
455
|
+
hs = [h for _, h in self._key_dimensions]
|
|
456
456
|
if self.is_horizontal:
|
|
457
457
|
return [max(hs)] * len(hs)
|
|
458
458
|
return hs
|
plotnine/guides/guides.py
CHANGED
|
@@ -342,8 +342,8 @@ class guides:
|
|
|
342
342
|
if isinstance(position, str) and isinstance(just, (float, int)):
|
|
343
343
|
setattr(legends, position, outside_legend(aob, just))
|
|
344
344
|
else:
|
|
345
|
-
position = cast(tuple[float, float], position)
|
|
346
|
-
just = cast(tuple[float, float], just)
|
|
345
|
+
position = cast("tuple[float, float]", position)
|
|
346
|
+
just = cast("tuple[float, float]", just)
|
|
347
347
|
legends.inside.append(inside_legend(aob, just, position))
|
|
348
348
|
|
|
349
349
|
return legends
|
|
@@ -467,7 +467,7 @@ class GuidesElements:
|
|
|
467
467
|
if just is None:
|
|
468
468
|
just = (0.5, 0.5)
|
|
469
469
|
elif just in VALID_JUSTIFICATION_WORDS:
|
|
470
|
-
just = ensure_xy_location(just)
|
|
470
|
+
just = ensure_xy_location(just)
|
|
471
471
|
elif isinstance(just, (float, int)):
|
|
472
472
|
just = (just, just)
|
|
473
473
|
return just[idx]
|
plotnine/iapi.py
CHANGED
plotnine/labels.py
CHANGED
plotnine/options.py
CHANGED
|
@@ -10,14 +10,11 @@ if TYPE_CHECKING:
|
|
|
10
10
|
from plotnine import theme
|
|
11
11
|
from plotnine.typing import FigureFormat
|
|
12
12
|
|
|
13
|
-
close_all_figures = False
|
|
14
|
-
"""
|
|
15
|
-
Development flag, e.g. set to `True` to prevent
|
|
16
|
-
the queuing up of figures when errors happen.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
13
|
current_theme: Optional[theme | Type[theme]] = None
|
|
20
|
-
"""Theme used when none is added to the ggplot object
|
|
14
|
+
"""Theme used when none is added to the ggplot object
|
|
15
|
+
|
|
16
|
+
Another way to do it, to set a default theme using `theme_set()`.
|
|
17
|
+
"""
|
|
21
18
|
|
|
22
19
|
base_family: str = "sans-serif"
|
|
23
20
|
"""
|
|
@@ -77,6 +74,11 @@ def get_option(name: str) -> Any:
|
|
|
77
74
|
----------
|
|
78
75
|
name :
|
|
79
76
|
Name of the option
|
|
77
|
+
|
|
78
|
+
Notes
|
|
79
|
+
-----
|
|
80
|
+
See [reference](/reference/#options) for a list of all the available
|
|
81
|
+
options.
|
|
80
82
|
"""
|
|
81
83
|
d = globals()
|
|
82
84
|
|
|
@@ -103,6 +105,11 @@ def set_option(name: str, value: Any) -> Any:
|
|
|
103
105
|
-------
|
|
104
106
|
:
|
|
105
107
|
Old value of the option
|
|
108
|
+
|
|
109
|
+
Notes
|
|
110
|
+
-----
|
|
111
|
+
See [reference](/reference/#options) for a list of all the available
|
|
112
|
+
options.
|
|
106
113
|
"""
|
|
107
114
|
d = globals()
|
|
108
115
|
|