Skip to content

Commit 0da5f04

Browse files
committed
Allow multiple alignment values for colorbar texts
1 parent 345f3c2 commit 0da5f04

File tree

6 files changed

+69
-5
lines changed

6 files changed

+69
-5
lines changed

doc/changelog.qmd

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ title: Changelog
1010
- Added [](:class:`~plotnine.composition.plot_layout`) with which you can customise the
1111
layout of plots in composition.
1212

13+
- You can now pass a sequence of horizontal and vertical alignment (ha & va) values in
14+
element_text for colorbars.
15+
1316
### Bug Fixes
1417

1518
- Fixed [](:class:`~plotnine.geom_smooth`) / [](:class:`~plotnine.stat_smooth`) when using a linear model via "lm" with weights for the model to do a weighted regression. This bug did not affect the formula API of the linear model. ({{< issue 1005 >}})

plotnine/guides/guide.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from ..themes.theme import theme as Theme
1212

1313
if TYPE_CHECKING:
14-
from typing import Literal, Optional, TypeAlias
14+
from typing import Literal, Optional, Sequence, TypeAlias
1515

1616
import pandas as pd
1717
from matplotlib.offsetbox import PackerBase
@@ -176,6 +176,10 @@ class GuideElements:
176176
theme: Theme
177177
guide: guide
178178

179+
@cached_property
180+
def text(self):
181+
raise NotImplementedError
182+
179183
def __post_init__(self):
180184
self.guide_kind = type(self.guide).__name__.split("_")[-1]
181185
self._elements_cls = GuideElements
@@ -275,3 +279,33 @@ def is_horizontal(self) -> bool:
275279
Whether the guide is horizontal
276280
"""
277281
return self.direction == "horizontal"
282+
283+
def has(self, n: int) -> Sequence[str]:
284+
"""
285+
Horizontal alignments per legend text
286+
"""
287+
ha = self.text.ha
288+
if isinstance(ha, (list, tuple)):
289+
if len(ha) != n:
290+
raise ValueError(
291+
"If `ha` is a sequence, its length should match the "
292+
f"number of texts. ({len(ha)} != {n})"
293+
)
294+
else:
295+
ha = (ha,) * n
296+
return ha
297+
298+
def vas(self, n: int) -> Sequence[str]:
299+
"""
300+
Vertical alignments per legend texts
301+
"""
302+
va = self.text.va
303+
if isinstance(va, (list, tuple)):
304+
if len(va) != n:
305+
raise ValueError(
306+
"If `va` is a sequence, its length should match the "
307+
f"number of texts. ({len(va)} != {n})"
308+
)
309+
else:
310+
va = (va,) * n
311+
return va

plotnine/guides/guide_colorbar.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,8 @@ def add_labels(
420420
n = len(labels)
421421
sep = elements.text.margin
422422
texts: list[Text] = []
423-
props = {"ha": elements.text.ha, "va": elements.text.va}
423+
has = elements.has(n)
424+
vas = elements.vas(n)
424425

425426
# The horizontal and vertical alignments are set in the theme
426427
# or dynamically calculates in GuideElements and added to the
@@ -437,8 +438,8 @@ def add_labels(
437438
else:
438439
ys = [elements.key_width + sep] * n
439440

440-
for x, y, s in zip(xs, ys, labels):
441-
t = Text(x, y, s, **props)
441+
for x, y, s, ha, va in zip(xs, ys, labels, has, vas):
442+
t = Text(x, y, s, ha=ha, va=va)
442443
auxbox.add_artist(t)
443444
texts.append(t)
444445

plotnine/themes/elements/element_text.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,21 @@ def __init__(
8686
| None
8787
) = None,
8888
size: float | Sequence[float] | None = None,
89-
ha: Literal["center", "left", "right"] | float | None = None,
89+
ha: (
90+
Literal["center", "left", "right"]
91+
| float
92+
| Sequence[Literal["center", "left", "right"] | float]
93+
| None
94+
) = None,
9095
va: (
9196
Literal["center", "top", "bottom", "baseline", "center_baseline"]
9297
| float
98+
| Sequence[
99+
Literal[
100+
"center", "top", "bottom", "baseline", "center_baseline"
101+
]
102+
| float
103+
]
93104
| None
94105
) = None,
95106
ma: Literal["center", "left", "right"] | float | None = None,
12.6 KB
Loading

tests/test_theme.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,21 @@ def test_element_text_with_sequence_values():
175175
assert p == "element_text_with_sequence_values"
176176

177177

178+
def test_guide_colorbar_sequence_alignments():
179+
p = (
180+
ggplot(mtcars, aes("wt", "mpg", color="cyl"))
181+
+ geom_point()
182+
+ theme(
183+
legend_text_colorbar=element_text(
184+
size=12,
185+
va=("bottom", "center", "center", "center", "top"),
186+
ha=("left", "center", "center", "center", "right"),
187+
),
188+
)
189+
)
190+
assert p == "test_guide_colorbar_sequence_ha_va"
191+
192+
178193
g = (
179194
ggplot(mtcars, aes(x="wt", y="mpg", color="factor(gear)"))
180195
+ geom_point()

0 commit comments

Comments
 (0)