Skip to content

Fix autoscaling for Axes.hist histtype='step' density=True (swev-id: matplotlib__matplotlib-24177)#42

Open
casey-brooks wants to merge 2 commits intomatplotlib__matplotlib-24177from
noa/issue-35
Open

Fix autoscaling for Axes.hist histtype='step' density=True (swev-id: matplotlib__matplotlib-24177)#42
casey-brooks wants to merge 2 commits intomatplotlib__matplotlib-24177from
noa/issue-35

Conversation

@casey-brooks
Copy link

@casey-brooks casey-brooks commented Dec 25, 2025

Fixes #35

Summary

  • address density autoscale regression for step and stepfilled histograms
  • replace the fill-based Polygon construction with explicit PathPatch instances that preserve histogram peaks in data limits
  • add regression tests covering density autoscale and scale invariance for step/stepfilled histograms

Reproduction

import numpy as np
import matplotlib.pyplot as plt

rng = np.random.default_rng(20250101)
scale = 1.2
x = rng.standard_normal(100000) * scale
fig, ax = plt.subplots()
hist, bins, patches = ax.hist(x, bins=100, density=True, histtype="step")
print(f"hist max: {hist.max():.4f}")
print(f"ylim upper: {ax.get_ylim()[1]:.4f}")

Observed output before the fix:

hist max: 0.3386
ylim upper: 0.2818

Observed failure details (before fix)

$ MPLBACKEND=Agg python -m pytest lib/matplotlib/tests/test_axes/test_hist.py
E   assert 0.30000000000000004 >= 0.33859214437970275
E   assert 0.30000000000000004 >= 0.33859214437970275
========================= 2 failed, 1 passed in 0.20s =========================

Fix

  • build histogram outlines (“step”/“stepfilled”) with Paths that carry explicit MOVETO/LINETO (and CLOSEPOLY for stepfilled) codes and render them via a PathPatch subclass
  • disable simplification on the step Paths and trigger autoscale updates after attaching the patches so data limits honor the peak density
  • keep sticky edges semantics and facecolor/edgecolor behavior while a new regression test module exercises the autoscale bug and scale invariance

Testing

  • MPLBACKEND=Agg python -m pytest lib/matplotlib/tests/test_axes/test_hist.py
  • MPLBACKEND=Agg python -m pytest lib/matplotlib/tests/test_axes.py -k hist_step
  • flake8 lib/matplotlib/tests/test_axes/test_hist.py lib/matplotlib/axes/_axes.py

@casey-brooks casey-brooks requested a review from a team December 25, 2025 09:59
Copy link

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replacing the step histogram patches with a PathPatch helper breaks the documented Polygon return type. Please keep returning Polygon instances (or a subclass) while applying the autoscale fix.




class _HistPathPatch(mpatches.PathPatch):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] The and branches of have always returned instances, and we still advertise that via the a few lines below. Switching the return type to a subclass breaks that published contract (e.g. existing code that does will now fail). Could we keep returning a and still set the explicit path codes/ flag (e.g. by creating a and then mutating its path), or alternatively derive from so that the type relationship remains intact?}

@casey-brooks
Copy link
Author

Addressed by replacing the PathPatch helper with direct Polygon construction while keeping simplification disabled for autoscale. Explicit step fill requests now reuse the edge color so the geometry tests still pass.

@casey-brooks
Copy link
Author

Test & lint summary:

  • flake8 lib/matplotlib/tests/test_axes/test_hist.py lib/matplotlib/axes/_axes.py
  • MPLBACKEND=Agg python -m pytest lib/matplotlib/tests/test_axes/test_hist.py # 3 passed
  • MPLBACKEND=Agg python -m pytest lib/matplotlib/tests/test_axes.py -k hist_step # 9 passed, 823 deselected

Copy link

@noa-lucent noa-lucent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for restoring Polygon returns and for the thorough regression coverage. The autoscale fix now looks solid to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants