Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Fix concurrent first access to lazily initialized graph object properties, which could raise `ValueError("Invalid value")` [[#5691](https://github.com/plotly/plotly.py/pull/5691)], with thanks to @hb1915 for the contribution!
- Fix `mpl_to_plotly` crashing on touching bars (such as `plt.hist`) due to floating-point noise producing negative `bargap` values by clamping `bargap` to `[0, 1]` [[#5696](https://github.com/plotly/plotly.py/pull/5696)], with thanks to @robertoffmoura for the contribution!
- Fix `mpl_to_plotly` drawing step plots with diagonal lines instead of vertical/horizontal step segments by mapping matplotlib step drawstyles (`steps-pre`, `steps-post`, `steps-mid`) to plotly line shapes [[#5697](https://github.com/plotly/plotly.py/pull/5697)], with thanks to @robertoffmoura for the contribution!
- Fix `mpl_to_plotly` showing unwanted legends with placeholder or internal label entries (`_nolegend_`, `_childN`) by defaulting `layout.showlegend=False` unless the matplotlib figure explicitly defines a legend [[#5699](https://github.com/plotly/plotly.py/pull/5699)], with thanks to @robertoffmoura for the contribution!
- Export tick label colors to the plotly tickfont in `mpl_to_plotly` [[#5716](https://github.com/plotly/plotly.py/pull/5716)], with thanks to @robertoffmoura for the contribution!
- Fix `px.sunburst`, `px.treemap` and `px.icicle` listing sectors in a different order on every run when `path` is used with a Polars DataFrame; sectors now follow their order of first appearance for all dataframe backends [[#5766](https://github.com/plotly/plotly.py/pull/5766)], with thanks to @Irahan2 for the contribution!

Expand Down
19 changes: 14 additions & 5 deletions plotly/matplotlylib/renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ def open_figure(self, fig, props):
height=int(props["figheight"] * props["dpi"]),
autosize=False,
hovermode="closest",
# plotly.js auto-names unnamed traces "trace N" and shows them
# in the legend; the legend is only enabled when the mpl figure
# actually has one (see open_legend)
showlegend=False,
)
self.plotly_fig["layout"].paper_bgcolor = _export_color(props["figbg"])
self.mpl_x_bounds, self.mpl_y_bounds = mpltools.get_axes_bounds(fig)
Expand Down Expand Up @@ -485,13 +489,18 @@ def draw_marked_line(self, **props):
),
)
if props["coordinates"] == "data":
label = props["label"]
# matplotlib uses "_nolegend_" and auto-generated "_childN"
# labels for artists that must not appear in a legend
if not label or (isinstance(label, str) and label.startswith("_")):
label = None
showlegend = False
else:
showlegend = None
marked_line = go.Scatter(
mode=mode,
name=(
str(props["label"])
if isinstance(props["label"], str)
else props["label"]
),
name=label,
showlegend=showlegend,
x=[xy_pair[0] for xy_pair in props["data"]],
y=[xy_pair[1] for xy_pair in props["data"]],
xaxis="x{0}".format(self.axis_ct),
Expand Down
28 changes: 28 additions & 0 deletions plotly/matplotlylib/tests/test_renderer.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,34 @@ def test_fixed_formatter_ticktext():
assert plotly_fig.layout.xaxis.ticktext == ("Baseline", "param = 1", "param = 2")


def test_no_legend_entries_for_internal_mpl_labels():
"""mpl internal labels (_nolegend_, _childN) must not become legend entries."""
fig, ax = plt.subplots()
ax.plot([0, 1, 2, 3], [0, 1, 0, 1], "b", [0, 1, 2, 3], [1, 0, 1, 0], "r--")

plotly_fig = tls.mpl_to_plotly(fig)

assert plotly_fig.layout.showlegend == False
assert all(t.name is None for t in plotly_fig.data)


def test_unlabeled_traces_hidden_from_legend_when_figure_has_legend():
"""Traces without labels must have showlegend=False when a figure has a legend."""
fig, ax = plt.subplots()
ax.plot([0, 1], [0, 1], label="Labeled line")
ax.plot([0, 1], [1, 0]) # Unlabeled line
ax.legend()

plotly_fig = tls.mpl_to_plotly(fig)

assert plotly_fig.layout.showlegend == True
assert len(plotly_fig.data) == 2
assert plotly_fig.data[0].name == "Labeled line"
assert plotly_fig.data[0].showlegend is not False
assert plotly_fig.data[1].name is None
assert plotly_fig.data[1].showlegend is False


def test_custom_date_xtickvals_are_converted():
"""Custom tick values on a date axis must be converted to date strings,
not left as raw matplotlib date numbers or datetime objects."""
Expand Down
Loading