From bdb7bbe91730537e436c074b4a07322cbd5a5989 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Thu, 4 Jun 2026 21:44:15 +0200 Subject: [PATCH] Backport PR #31685: FIX: Handle height units in broken_barh() --- .../lines_bars_and_markers/broken_barh.py | 16 ++++++------- lib/matplotlib/axes/_axes.py | 24 ++++++++++--------- lib/matplotlib/tests/test_axes.py | 12 ++++++++++ 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/galleries/examples/lines_bars_and_markers/broken_barh.py b/galleries/examples/lines_bars_and_markers/broken_barh.py index a709e911773d..6245ce576a9d 100644 --- a/galleries/examples/lines_bars_and_markers/broken_barh.py +++ b/galleries/examples/lines_bars_and_markers/broken_barh.py @@ -19,16 +19,14 @@ fig, ax = plt.subplots() # broken_barh(xranges, (ypos, height)) -ax.broken_barh(cpu_1, (0, 0.4), align="center") -ax.broken_barh(cpu_2, (1, 0.4), align="center") -ax.broken_barh(cpu_3, (2, 0.4), align="center") -ax.broken_barh(cpu_4, (3, 0.4), align="center") -ax.broken_barh(disk, (4, 0.4), align="center", color="tab:orange") -ax.broken_barh(network, (5, 0.4), align="center", color="tab:green") +ax.broken_barh(cpu_1, ("CPU 1", 0.4), align="center") +ax.broken_barh(cpu_2, ("CPU 2", 0.4), align="center") +ax.broken_barh(cpu_3, ("CPU 3", 0.4), align="center") +ax.broken_barh(cpu_4, ("CPU 4", 0.4), align="center") +ax.broken_barh(disk, ("disk", 0.4), align="center", color="tab:orange") +ax.broken_barh(network, ("network", 0.4), align="center", color="tab:green") ax.set_xlim(0, 10) -ax.set_yticks(range(6), - labels=["CPU 1", "CPU 2", "CPU 3", "CPU 4", "disk", "network"]) -ax.invert_yaxis() +ax.invert_yaxis() # order the bars from top to bottom ax.set_title("Resource usage") plt.show() diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py index 244aab09551b..0a3db368841d 100644 --- a/lib/matplotlib/axes/_axes.py +++ b/lib/matplotlib/axes/_axes.py @@ -2242,13 +2242,10 @@ def _convert_dx(dx, x0, xconv, convert): except (TypeError, IndexError, KeyError): x = xconv - delist = False - if not np.iterable(dx): - dx = [dx] - delist = True - dx = [convert(x0 + ddx) - x for ddx in dx] - if delist: - dx = dx[0] + if np.iterable(dx): + dx = [convert(x0 + ddx) - x for ddx in dx] + else: + dx = convert(x0 + dx) - x except (ValueError, TypeError, AttributeError): # if the above fails (for any reason) just fallback to what # we do by default and convert dx by itself. @@ -3036,15 +3033,20 @@ def broken_barh(self, xranges, yrange, align="bottom", **kwargs): [("x", xdata), ("y", ydata)], kwargs, convert=False) vertices = [] - y0, dy = yrange + ypos, height = yrange + + # Unit conversion: handling of the difference quantity height is done through + # _convert_dx() in the same way as width handling in bar(). + y0 = self.convert_yunits(ypos) + dy = self._convert_dx(height, ypos, np.array(y0), self.convert_yunits) _api.check_in_list(['bottom', 'center', 'top'], align=align) if align == "bottom": - y0, y1 = self.convert_yunits((y0, y0 + dy)) + y1 = y0 + dy elif align == "center": - y0, y1 = self.convert_yunits((y0 - dy/2, y0 + dy/2)) + y0, y1 = y0 - dy / 2, y0 + dy / 2 else: - y0, y1 = self.convert_yunits((y0 - dy, y0)) + y0, y1 = y0 - dy, y0 for xr in xranges: # convert the absolute values, not the x and dx try: diff --git a/lib/matplotlib/tests/test_axes.py b/lib/matplotlib/tests/test_axes.py index 0f7f8e37add0..3a82c9c3295c 100644 --- a/lib/matplotlib/tests/test_axes.py +++ b/lib/matplotlib/tests/test_axes.py @@ -7703,6 +7703,18 @@ def test_broken_barh_align(): assert_array_equal(path.get_extents().intervaly, [18, 20]) +def test_broken_barh_categorical(): + fig, ax = plt.subplots() + pc = ax.broken_barh([(0, 10)], ('a', 0.8)) + assert tuple(pc.get_datalim(ax.transData).intervaly) == (0, 0.8) + + pc = ax.broken_barh([(0, 10)], ('a', 0.8), align="center") + assert tuple(pc.get_datalim(ax.transData).intervaly) == (-0.4, 0.4) + + pc = ax.broken_barh([(0, 10)], ('a', 0.8), align="top") + assert tuple(pc.get_datalim(ax.transData).intervaly) == (-0.8, 0) + + def test_pandas_pcolormesh(pd): time = pd.date_range('2000-01-01', periods=10) depth = np.arange(20)