Skip to content

Commit 34488dd

Browse files
Fix boxplot conversion by mapping 'none' colors to transparent rgba
1 parent c0740bf commit 34488dd

2 files changed

Lines changed: 39 additions & 8 deletions

File tree

plotly/matplotlylib/renderer.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,24 @@
1414
from plotly.matplotlylib import mpltools
1515

1616

17+
def _export_color(color):
18+
"""Export a matplotlib color for use as a plotly color.
19+
20+
matplotlib uses "none" for fully transparent colors, which plotly does not
21+
accept, so transparent colors are exported as transparent black.
22+
Colors already exported by the mplexporter (hex or rgba strings) are
23+
passed through unchanged.
24+
"""
25+
if isinstance(color, str):
26+
return "rgba(0,0,0,0)" if color == "none" else color
27+
if isinstance(color, (list, tuple)) and all(
28+
isinstance(c, str) for c in color
29+
):
30+
return [_export_color(c) for c in color]
31+
bgcolor = export_color(color)
32+
return "rgba(0,0,0,0)" if bgcolor == "none" else bgcolor
33+
34+
1735
class PlotlyRenderer(Renderer):
1836
"""A renderer class inheriting from base for rendering mpl plots in plotly.
1937
@@ -317,7 +335,7 @@ def draw_bar(self, coll):
317335
yaxis="y{0}".format(self.axis_ct),
318336
opacity=trace[0]["alpha"], # TODO: get all alphas if array?
319337
marker=go.bar.Marker(
320-
color=trace[0]["facecolor"], # TODO: get all
338+
color=_export_color(trace[0]["facecolor"]), # TODO: get all
321339
line=dict(width=trace[0]["edgewidth"]),
322340
),
323341
) # TODO ditto
@@ -379,9 +397,13 @@ def draw_marked_line(self, **props):
379397
self.msg += "... with just markers\n"
380398
mode = "markers"
381399
if props["linestyle"]:
382-
color = mpltools.merge_color_and_opacity(
383-
props["linestyle"]["color"], props["linestyle"]["alpha"]
384-
)
400+
if props["linestyle"]["color"] == "none":
401+
# a fully transparent line; plotly rejects "none" as a color
402+
color = "rgba(0,0,0,0)"
403+
else:
404+
color = mpltools.merge_color_and_opacity(
405+
props["linestyle"]["color"], props["linestyle"]["alpha"]
406+
)
385407

386408
if props["coordinates"] == "data":
387409
line = go.scatter.Line(
@@ -401,22 +423,22 @@ def draw_marked_line(self, **props):
401423
if props["coordinates"] == "data":
402424
marker = go.scatter.Marker(
403425
opacity=props["markerstyle"]["alpha"],
404-
color=props["markerstyle"]["facecolor"],
426+
color=_export_color(props["markerstyle"]["facecolor"]),
405427
symbol=mpltools.convert_symbol(props["markerstyle"]["marker"]),
406428
size=props["markerstyle"]["markersize"],
407429
line=dict(
408-
color=props["markerstyle"]["edgecolor"],
430+
color=_export_color(props["markerstyle"]["edgecolor"]),
409431
width=props["markerstyle"]["edgewidth"],
410432
),
411433
)
412434
else:
413435
shape = dict(
414436
opacity=props["markerstyle"]["alpha"],
415-
fillcolor=props["markerstyle"]["facecolor"],
437+
fillcolor=_export_color(props["markerstyle"]["facecolor"]),
416438
symbol=mpltools.convert_symbol(props["markerstyle"]["marker"]),
417439
size=props["markerstyle"]["markersize"],
418440
line=dict(
419-
color=props["markerstyle"]["edgecolor"],
441+
color=_export_color(props["markerstyle"]["edgecolor"]),
420442
width=props["markerstyle"]["edgewidth"],
421443
),
422444
)

plotly/matplotlylib/tests/test_renderer.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import numpy as np
12
import matplotlib.pyplot as plt
23
import plotly.tools as tls
34

@@ -84,3 +85,11 @@ def test_multiple_traces_native_legend():
8485
assert plotly_fig.data[0].mode == "lines"
8586
assert plotly_fig.data[1].mode == "markers"
8687
assert plotly_fig.data[2].mode == "lines+markers"
88+
89+
90+
def test_boxplot_converts_with_none_marker_facecolor():
91+
"""Boxplot outlier markers use facecolor 'none', which plotly rejects."""
92+
fig, ax = plt.subplots()
93+
ax.boxplot(np.random.randn(100, 4))
94+
plotly_fig = tls.mpl_to_plotly(fig) # used to raise ValueError
95+
assert len(plotly_fig.data) > 0

0 commit comments

Comments
 (0)