diff --git a/plotly/matplotlylib/mpltools.py b/plotly/matplotlylib/mpltools.py index 0a3206998ba..b6fab3cb8da 100644 --- a/plotly/matplotlylib/mpltools.py +++ b/plotly/matplotlylib/mpltools.py @@ -272,6 +272,23 @@ def get_bar_gap(bar_starts, bar_ends, tol=1e-10): return gap0 +DRAWSTYLE_SHAPE_MAP = { + "steps": "vh", + "steps-pre": "vh", + "steps-post": "hv", + "steps-mid": "hvh", +} + + +def convert_drawstyle(drawstyle): + """Convert a matplotlib line drawstyle to a plotly line shape. + + Matplotlib draws steps as vertical/horizontal segments; plotly's + ``line.shape`` expresses the same via "vh", "hv" and "hvh". + """ + return DRAWSTYLE_SHAPE_MAP.get(drawstyle) + + def convert_rgba_array(color_list): clean_color_list = list() for c in color_list: diff --git a/plotly/matplotlylib/renderer.py b/plotly/matplotlylib/renderer.py index 7c2340180cc..08fc5282bf1 100644 --- a/plotly/matplotlylib/renderer.py +++ b/plotly/matplotlylib/renderer.py @@ -388,6 +388,9 @@ def draw_marked_line(self, **props): color=color, width=props["linestyle"]["linewidth"], dash=mpltools.convert_dash(props["linestyle"]["dasharray"]), + shape=mpltools.convert_drawstyle( + props["linestyle"]["drawstyle"] + ), ) else: shape = dict( diff --git a/plotly/matplotlylib/tests/test_renderer.py b/plotly/matplotlylib/tests/test_renderer.py index 0d63e4815b9..86d96eac240 100644 --- a/plotly/matplotlylib/tests/test_renderer.py +++ b/plotly/matplotlylib/tests/test_renderer.py @@ -84,3 +84,17 @@ def test_multiple_traces_native_legend(): assert plotly_fig.data[0].mode == "lines" assert plotly_fig.data[1].mode == "markers" assert plotly_fig.data[2].mode == "lines+markers" + + +def test_drawstyle_maps_to_line_shape(): + cases = { + "steps-pre": "vh", + "steps": "vh", + "steps-post": "hv", + "steps-mid": "hvh", + } + for drawstyle, shape in cases.items(): + fig, ax = plt.subplots() + ax.plot([0, 1, 2], [0, 1, 0], drawstyle=drawstyle) + plotly_fig = tls.mpl_to_plotly(fig) + assert plotly_fig.data[0].line.shape == shape