Skip to content

Commit b90afd6

Browse files
FBumannclaude
andcommitted
fix: continuous colorscale strings with discrete-only chart types
Passing a continuous colorscale like `colors='turbo'` to area(), line(), fast_bar(), box(), or pie() previously failed because `resolve_colors` set `color_continuous_scale` which these px functions don't accept. Now samples from the continuous scale into a discrete sequence for these chart types. bar() and scatter() natively support continuous scales so are left unchanged. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 63f37a7 commit b90afd6

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

xarray_plotly/common.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,20 @@ def _get_qualitative_scale_names() -> frozenset[str]:
251251
)
252252

253253

254-
def resolve_colors(colors: Colors, px_kwargs: dict[str, Any]) -> dict[str, Any]:
254+
def _sample_colorscale(name: str, n: int) -> list[str]:
255+
"""Sample *n* evenly-spaced colors from a named Plotly colorscale."""
256+
scale = px.colors.get_colorscale(name)
257+
samplepoints = [i / max(n - 1, 1) for i in range(n)]
258+
result: list[str] = px.colors.sample_colorscale(scale, samplepoints)
259+
return result
260+
261+
262+
def resolve_colors(
263+
colors: Colors,
264+
px_kwargs: dict[str, Any],
265+
*,
266+
n_colors: int | None = None,
267+
) -> dict[str, Any]:
255268
"""Map unified `colors` parameter to appropriate Plotly px_kwargs.
256269
257270
Direct color_* kwargs take precedence and trigger a warning if
@@ -260,6 +273,10 @@ def resolve_colors(colors: Colors, px_kwargs: dict[str, Any]) -> dict[str, Any]:
260273
Args:
261274
colors: Unified color specification (str, list, dict, or None).
262275
px_kwargs: Existing kwargs to pass to Plotly Express.
276+
n_colors: When set, continuous colorscale strings are sampled
277+
into a discrete sequence of this length instead of setting
278+
``color_continuous_scale``. Use for chart types that only
279+
accept discrete color parameters (line, area, box, pie).
263280
264281
Returns:
265282
Updated px_kwargs with color parameters injected.
@@ -284,6 +301,9 @@ def resolve_colors(colors: Colors, px_kwargs: dict[str, Any]) -> dict[str, Any]:
284301
# Check if it's a qualitative (discrete) palette name
285302
if colors in _get_qualitative_scale_names():
286303
px_kwargs["color_discrete_sequence"] = getattr(px.colors.qualitative, colors)
304+
elif n_colors is not None:
305+
# Sample from continuous scale into a discrete sequence
306+
px_kwargs["color_discrete_sequence"] = _sample_colorscale(colors, n_colors)
287307
else:
288308
# Assume continuous scale
289309
px_kwargs["color_continuous_scale"] = colors

xarray_plotly/plotting.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ def line(
8282
-------
8383
plotly.graph_objects.Figure
8484
"""
85-
px_kwargs = resolve_colors(colors, px_kwargs)
8685
slots = assign_slots(
8786
list(darray.dims),
8887
"line",
@@ -94,6 +93,7 @@ def line(
9493
facet_row=facet_row,
9594
animation_frame=animation_frame,
9695
)
96+
px_kwargs = resolve_colors(colors, px_kwargs, n_colors=darray.sizes.get(slots.get("color")))
9797

9898
df = to_dataframe(darray)
9999
value_col = get_value_col(darray)
@@ -329,7 +329,6 @@ def fast_bar(
329329
-------
330330
plotly.graph_objects.Figure
331331
"""
332-
px_kwargs = resolve_colors(colors, px_kwargs)
333332
slots = assign_slots(
334333
list(darray.dims),
335334
"fast_bar",
@@ -339,6 +338,7 @@ def fast_bar(
339338
facet_row=facet_row,
340339
animation_frame=animation_frame,
341340
)
341+
px_kwargs = resolve_colors(colors, px_kwargs, n_colors=darray.sizes.get(slots.get("color")))
342342

343343
df = to_dataframe(darray)
344344
value_col = get_value_col(darray)
@@ -410,7 +410,6 @@ def area(
410410
-------
411411
plotly.graph_objects.Figure
412412
"""
413-
px_kwargs = resolve_colors(colors, px_kwargs)
414413
slots = assign_slots(
415414
list(darray.dims),
416415
"area",
@@ -421,6 +420,7 @@ def area(
421420
facet_row=facet_row,
422421
animation_frame=animation_frame,
423422
)
423+
px_kwargs = resolve_colors(colors, px_kwargs, n_colors=darray.sizes.get(slots.get("color")))
424424

425425
df = to_dataframe(darray)
426426
value_col = get_value_col(darray)
@@ -487,7 +487,6 @@ def box(
487487
-------
488488
plotly.graph_objects.Figure
489489
"""
490-
px_kwargs = resolve_colors(colors, px_kwargs)
491490
slots = assign_slots(
492491
list(darray.dims),
493492
"box",
@@ -498,6 +497,7 @@ def box(
498497
facet_row=facet_row,
499498
animation_frame=animation_frame,
500499
)
500+
px_kwargs = resolve_colors(colors, px_kwargs, n_colors=darray.sizes.get(slots.get("color")))
501501

502502
df = to_dataframe(darray)
503503
value_col = get_value_col(darray)
@@ -746,14 +746,14 @@ def pie(
746746
-------
747747
plotly.graph_objects.Figure
748748
"""
749-
px_kwargs = resolve_colors(colors, px_kwargs)
750749
slots = assign_slots(
751750
list(darray.dims),
752751
"pie",
753752
names=names,
754753
facet_col=facet_col,
755754
facet_row=facet_row,
756755
)
756+
px_kwargs = resolve_colors(colors, px_kwargs, n_colors=darray.sizes.get(slots.get("names")))
757757

758758
df = to_dataframe(darray)
759759
value_col = get_value_col(darray)

0 commit comments

Comments
 (0)