Skip to content

Commit 3539fc7

Browse files
timtreisclaude
andcommitted
Extract _build_color_key_from_categorical helper to deduplicate
The color_key construction logic was duplicated between _render_shapes and _render_points. Extract into a shared helper that also caches the categories lookup and keeps the hex-vs-named-color guard in one place. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fe7421c commit 3539fc7

File tree

1 file changed

+17
-18
lines changed

1 file changed

+17
-18
lines changed

src/spatialdata_plot/pl/render.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,21 @@
6262
_Normalize = Normalize | abc.Sequence[Normalize]
6363

6464

65+
def _build_color_key_from_categorical(color_vector: object) -> list[str] | None:
66+
"""Build a datashader ``color_key`` list from a categorical color vector.
67+
68+
Returns ``None`` when *color_vector* is not a :class:`pd.Categorical` or
69+
has no categories. Hex colours are stripped of their alpha channel;
70+
named colours (e.g. ``"red"``) are passed through unchanged.
71+
"""
72+
if type(color_vector) is not pd.core.arrays.categorical.Categorical:
73+
return None
74+
cat_values = color_vector.categories.values
75+
if len(cat_values) == 0:
76+
return None
77+
return [_hex_no_alpha(x) if isinstance(x, str) and x.startswith("#") else x for x in cat_values]
78+
79+
6580
def _split_colorbar_params(params: dict[str, object] | None) -> tuple[dict[str, object], dict[str, object], str | None]:
6681
"""Split colorbar params into layout hints, Matplotlib kwargs, and label override."""
6782
layout: dict[str, object] = {}
@@ -356,15 +371,7 @@ def _render_shapes(
356371
agg = agg.where((agg <= norm.vmin) | (np.isnan(agg)), other=2)
357372
agg = agg.where((agg != norm.vmin) | (np.isnan(agg)), other=0.5)
358373

359-
color_key = (
360-
[
361-
_hex_no_alpha(x) if isinstance(x, str) and x.startswith("#") else x
362-
for x in color_vector.categories.values
363-
]
364-
if (type(color_vector) is pd.core.arrays.categorical.Categorical)
365-
and (len(color_vector.categories.values) > 0)
366-
else None
367-
)
374+
color_key = _build_color_key_from_categorical(color_vector)
368375

369376
if color_by_categorical or col_for_color is None:
370377
ds_cmap = None
@@ -855,15 +862,7 @@ def _render_points(
855862
agg = agg.where((agg <= norm.vmin) | (np.isnan(agg)), other=2)
856863
agg = agg.where((agg != norm.vmin) | (np.isnan(agg)), other=0.5)
857864

858-
color_key: list[str] | None = (
859-
[
860-
_hex_no_alpha(x) if isinstance(x, str) and x.startswith("#") else x
861-
for x in color_vector.categories.values
862-
]
863-
if (type(color_vector) is pd.core.arrays.categorical.Categorical)
864-
and (len(color_vector.categories.values) > 0)
865-
else None
866-
)
865+
color_key = _build_color_key_from_categorical(color_vector)
867866
if isinstance(color_vector[0], str) and (
868867
color_vector is not None and all(len(x) == 9 for x in color_vector) and color_vector[0][0] == "#"
869868
):

0 commit comments

Comments
 (0)