Skip to content

Fix boxplot conversion by mapping 'none' colors to transparent rgba - #5700

Open
robertoffmoura wants to merge 1 commit into
plotly:mainfrom
robertoffmoura:rm/fix-boxplot
Open

robertoffmoura wants to merge 1 commit into
plotly:mainfrom
robertoffmoura:rm/fix-boxplot

Conversation

@robertoffmoura

Copy link
Copy Markdown
Contributor

mpl_to_plotly crashes when converting boxplots:

ValueError: Invalid value of type 'builtins.str' received for the 'color' property of scatter.marker
    Received value: 'none'

Boxplot outlier markers use facecolor="none" (fully transparent) in matplotlib. The converter passes that color verbatim into the plotly trace, and plotly.py's validators reject "none" for color property.

Fix: transparent matplotlib colors are mapped to rgba(0,0,0,0), which plotly accepts.

Snippet to reproduce:

import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import numpy as np
import plotly.tools as tls

fig, ax = plt.subplots()
ax.boxplot(np.random.randn(100, 4))
fig.savefig("boxplot_mpl.png")

p = tls.mpl_to_plotly(fig)   # raised ValueError before the fix
p.write_image("boxplot_plotly.png")

@camdecoster camdecoster left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for another update! I left some suggestions that I think would simplify/improve the code.

On another note, what do you think of updating our copy of mplexporter? It wouldn't be simple, but it might be worth the effort to take advantage of the updates that have been made in the last 12 years.

Comment on lines +405 to +407
color = mpltools.merge_color_and_opacity(
props["linestyle"]["color"], props["linestyle"]["alpha"]
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will still throw if the line color has an alpha value, which can happen with mplexporter (because the returned color is rgba and merge_color_and_opacity calls hex_to_rgb). This is a preexisting bug, but you might as well address it since you're in this area.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of combining merge_color_and_opacity and _export_color? They seem similar enough and you could deal with converting "none" internally rather than having to add a special case. Additionally, merge_color_and_opacity only gets called once, so we could remove that and replace it with the combined function.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you could run into the same issue with "none" colors for text. That might be rare, but it could still happen. You can see this on L735 where color=props["style"]["color"] gets passed in without being run through _export_color. I'll let you decide if you make an update in this PR or a future one.

@camdecoster

Copy link
Copy Markdown
Contributor

Could you also please add a changelog entry?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants