-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Fix conversion of matplotlib contour lines #5770
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
adcee67
d670be4
f99d47f
4f7e7f7
3768215
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -526,8 +526,13 @@ def draw_path_collection(self, **props): | |
| self.msg += " Drawing path collection as markers\n" | ||
| self.draw_marked_line(**scatter_props) | ||
| elif props["path_coordinates"] == "data": | ||
| self.msg += " Drawing path collection as filled polygons\n" | ||
| self._draw_filled_path_collection(props) | ||
| if len(props["styles"]["facecolor"]) == 0: | ||
| # no face colors: a line collection (e.g. contour lines) | ||
| self.msg += " Drawing path collection as lines\n" | ||
| self._draw_line_collection(props) | ||
| else: | ||
| self.msg += " Drawing path collection as filled polygons\n" | ||
| self._draw_filled_path_collection(props) | ||
| else: | ||
| self.msg += " Path collection not linked to 'data', not drawing\n" | ||
| warnings.warn( | ||
|
|
@@ -537,6 +542,81 @@ def draw_path_collection(self, **props): | |
| "collections linked to 'data' coordinates" | ||
| ) | ||
|
|
||
| def _draw_line_collection(self, props): | ||
| """Draw a path collection without face colors (e.g. contour lines) | ||
| as plain lines.""" | ||
| edgecolors = mpltools.convert_rgba_array(props["styles"]["edgecolor"]) | ||
| linewidths = mpltools.convert_linewidth_array(props["styles"]["linewidth"]) | ||
|
|
||
| def per_path(colors, i, default): | ||
| if isinstance(colors, str): | ||
| return colors | ||
| if colors is None: | ||
| return default | ||
| try: | ||
| n = len(colors) | ||
| except TypeError: | ||
| return colors | ||
| return colors[i % n] if n else default | ||
|
Comment on lines
+551
to
+560
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This helper function looks like the same one from |
||
|
|
||
| for i, (verts, codes) in enumerate(props["paths"]): | ||
| edgecolor = per_path(edgecolors, i, "rgba(0,0,0,0)") | ||
| linewidth = per_path(linewidths, i, 0) | ||
| # a path may contain several disjoint lines (e.g. contour lines | ||
| # of the same level); separate disjoint subpaths with None so | ||
| # plotly does not connect them. | ||
| # In SVG paths, codes carry different numbers of vertices: | ||
| # M/L: 1, C: 3 (cubic curve), S: 2 (smooth/quad curve), Z: 0. | ||
| code_steps = {"M": 1, "L": 1, "C": 3, "S": 2, "Z": 0} | ||
| subpaths = [] | ||
| current = [] | ||
| closed = False | ||
| vi = 0 | ||
| for c in codes: | ||
| step = code_steps.get(c, 1) | ||
| if c == "M": | ||
| if current: | ||
| subpaths.append((current, closed)) | ||
| current = [verts[vi]] | ||
| closed = False | ||
| vi += 1 | ||
| elif c == "Z": | ||
| closed = True | ||
| else: | ||
| current.extend(verts[vi : vi + step]) | ||
| vi += step | ||
| if current: | ||
| subpaths.append((current, closed)) | ||
| x_combined = [] | ||
| y_combined = [] | ||
| for sub, closed in subpaths: | ||
| if len(sub) < 2: | ||
| continue | ||
| # a closed subpath (Z code) must be closed explicitly since | ||
| # plotly's lines mode does not close the loop | ||
| if closed: | ||
| sub = sub + [sub[0]] | ||
| sub_x = self._convert_x_dates([v[0] for v in sub]) | ||
| sub_y = [v[1] for v in sub] | ||
| if x_combined: | ||
| x_combined.append(None) | ||
| y_combined.append(None) | ||
| x_combined.extend(sub_x) | ||
| y_combined.extend(sub_y) | ||
| if x_combined: | ||
| self.plotly_fig.add_trace( | ||
| go.Scatter( | ||
| x=x_combined, | ||
| y=y_combined, | ||
| mode="lines", | ||
| line=go.scatter.Line( | ||
| color=_export_color(edgecolor), width=linewidth | ||
| ), | ||
|
Comment on lines
+612
to
+614
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will this handle dash styles? What about turning off legend display? I think that came up in another PR. |
||
| xaxis="x{0}".format(self.axis_ct), | ||
| yaxis="y{0}".format(self.axis_ct), | ||
| ) | ||
| ) | ||
|
|
||
| def _draw_filled_path_collection(self, props): | ||
| """Draw a path collection (e.g. violin plot bodies) as filled polygons.""" | ||
| facecolors = mpltools.convert_rgba_array(props["styles"]["facecolor"]) | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you please add a test for the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function currently draws one trace per path. What do you think of updating it to group consecutive same-style lines together into one trace? That would cut down on the number of traces (and make a legend less noisy).