diff --git a/plotly/matplotlylib/mpltools.py b/plotly/matplotlylib/mpltools.py index ad01b37520..bf7316bd23 100644 --- a/plotly/matplotlylib/mpltools.py +++ b/plotly/matplotlylib/mpltools.py @@ -269,7 +269,9 @@ def get_bar_gap(bar_starts, bar_ends, tol=1e-10): gap0 = gaps[0] uniform = all([abs(gap0 - gap) < tol for gap in gaps]) if uniform: - return gap0 + # plotly's bargap must be in [0, 1]; clamp to guard against + # floating point noise (e.g. -8.9e-16 for touching bars) + return min(max(gap0, 0.0), 1.0) def convert_rgba_array(color_list): diff --git a/plotly/matplotlylib/tests/test_renderer.py b/plotly/matplotlylib/tests/test_renderer.py index 18ce2d02b3..e2eaa74f85 100644 --- a/plotly/matplotlylib/tests/test_renderer.py +++ b/plotly/matplotlylib/tests/test_renderer.py @@ -235,6 +235,19 @@ def test_semitransparent_axes_background_preserved(): assert plotly_fig.layout.plot_bgcolor == "rgba(26, 51, 76, 0.4)" +def test_histogram_converts(): + """Histograms must convert without error and keep bargap in plotly's + valid [0, 1] range; get_bar_gap can return a gap with floating point + noise for touching bars, which plotly rejects.""" + fig, ax = plt.subplots() + ax.hist(np.random.randn(1000), 30) + + plotly_fig = tls.mpl_to_plotly(fig) + + assert len(plotly_fig.data) == 1 + assert 0 <= plotly_fig.layout.bargap <= 1 + + def test_line_color_is_valid_plotly_color(): """Converted line colors are valid plotly color strings: plotly rejects a space between 'rgba' and the opening parenthesis."""