Skip to content

Commit 3768215

Browse files
Combine disjoint line collection subpaths using None separators
1 parent 4f7e7f7 commit 3768215

2 files changed

Lines changed: 24 additions & 14 deletions

File tree

plotly/matplotlylib/renderer.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -563,8 +563,8 @@ def per_path(colors, i, default):
563563
edgecolor = per_path(edgecolors, i, "rgba(0,0,0,0)")
564564
linewidth = per_path(linewidths, i, 0)
565565
# a path may contain several disjoint lines (e.g. contour lines
566-
# of the same level); drawing them in one trace would connect
567-
# them, so draw each subpath separately.
566+
# of the same level); separate disjoint subpaths with None so
567+
# plotly does not connect them.
568568
# In SVG paths, codes carry different numbers of vertices:
569569
# M/L: 1, C: 3 (cubic curve), S: 2 (smooth/quad curve), Z: 0.
570570
code_steps = {"M": 1, "L": 1, "C": 3, "S": 2, "Z": 0}
@@ -587,17 +587,27 @@ def per_path(colors, i, default):
587587
vi += step
588588
if current:
589589
subpaths.append((current, closed))
590+
x_combined = []
591+
y_combined = []
590592
for sub, closed in subpaths:
591593
if len(sub) < 2:
592594
continue
593595
# a closed subpath (Z code) must be closed explicitly since
594596
# plotly's lines mode does not close the loop
595597
if closed:
596598
sub = sub + [sub[0]]
599+
sub_x = self._convert_x_dates([v[0] for v in sub])
600+
sub_y = [v[1] for v in sub]
601+
if x_combined:
602+
x_combined.append(None)
603+
y_combined.append(None)
604+
x_combined.extend(sub_x)
605+
y_combined.extend(sub_y)
606+
if x_combined:
597607
self.plotly_fig.add_trace(
598608
go.Scatter(
599-
x=self._convert_x_dates([v[0] for v in sub]),
600-
y=[v[1] for v in sub],
609+
x=x_combined,
610+
y=y_combined,
601611
mode="lines",
602612
line=go.scatter.Line(
603613
color=_export_color(edgecolor), width=linewidth

plotly/matplotlylib/tests/test_renderer.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -358,17 +358,17 @@ def test_custom_date_xtickvals_given_as_numbers_are_converted():
358358

359359
def test_contour_rings_are_closed():
360360
"""Closed contour loops (Z codes) must close in plotly, not leave a gap."""
361-
x = np.linspace(-3, 3, 30)
361+
x = np.linspace(-3, 3, 50)
362362
X, Y = np.meshgrid(x, x)
363363
fig, ax = plt.subplots()
364-
ax.contour(X, Y, np.sin(X) * np.cos(Y), 10)
364+
ax.contour(X, Y, X**2 + Y**2, levels=[1, 4])
365365
plotly_fig = tls.mpl_to_plotly(fig)
366-
rings = [
367-
t
368-
for t in plotly_fig.data
369-
if len(t.x) > 30 and t.x[0] == t.x[-1] and t.y[0] == t.y[-1]
370-
]
371-
assert len(rings) >= 2
366+
367+
assert len(plotly_fig.data) == 2
368+
assert plotly_fig.data[0].x[0] == plotly_fig.data[0].x[-1]
369+
assert plotly_fig.data[0].y[0] == plotly_fig.data[0].y[-1]
370+
assert plotly_fig.data[1].x[0] == plotly_fig.data[1].x[-1]
371+
assert plotly_fig.data[1].y[0] == plotly_fig.data[1].y[-1]
372372

373373

374374
def test_line_collection_date_xaxis():
@@ -385,5 +385,5 @@ def test_line_collection_date_xaxis():
385385
plotly_fig = tls.mpl_to_plotly(fig)
386386
lines = [t for t in plotly_fig.data if t.mode == "lines"]
387387
assert len(lines) >= 1
388-
assert all(isinstance(x, str) for t in lines for x in t.x)
389-
388+
assert any(isinstance(x, str) for t in lines for x in t.x)
389+
assert all(x is None or isinstance(x, str) for t in lines for x in t.x)

0 commit comments

Comments
 (0)