Apply unit conversion to hist2d's x/y/range, fixing datetime input by AdityaJagtap18 · Pull Request #32309 · matplotlib/matplotlib · GitHub
Skip to content

Apply unit conversion to hist2d's x/y/range, fixing datetime input - #32309

Open
AdityaJagtap18 wants to merge 2 commits into
matplotlib:mainfrom
AdityaJagtap18:fix-hist2d-datetime-units
Open

Apply unit conversion to hist2d's x/y/range, fixing datetime input#32309
AdityaJagtap18 wants to merge 2 commits into
matplotlib:mainfrom
AdityaJagtap18:fix-hist2d-datetime-units

Conversation

@AdityaJagtap18

@AdityaJagtap18 AdityaJagtap18 commented Sep 6, 2026

Copy link
Copy Markdown

PR summary

Axes.hist2d passes x and y straight to np.histogram2d without running them through the Axes' unit converters first, unlike plot, scatter, and hist. So datetime input to hist2d was silently treated as raw values instead of Matplotlib's internal date representation — on current NumPy this now raises a hard TypeError (numpy no longer silently mixes datetime64 and float), so the bug is very visible, but the same gap also applies to any other unit-aware input (not just dates), and to the range argument, which wasn't converted either.

Fix: call self._process_unit_info(...) for x/y at the top of hist2d, matching the pattern already used elsewhere in _axes.py, and run range's bounds through convert_xunits/convert_yunits before handing them to np.histogram2d.

Closes nothing filed upstream yet — found this while exercising hist2d with datetime data and hitting the TypeError.

AI Disclosure

I used an AI coding assistant (Claude Code) to help locate this bug, implement the fix, and write the regression tests and this description. Specifically:

  • The assistant found the bug by tracing why hist2d failed on datetime input while hist/scatter on the same data worked, and identified the missing _process_unit_info call by comparing against those methods.
  • The assistant wrote the fix, the two new tests (test_hist2d_datetime, test_hist2d_datetime_range), and the API-changes note.
  • I reviewed the diff, ran the full hist2d-related test suite locally to confirm the fix and no regressions, and I'm responsible for and stand behind this change.

PR quality check

  • Use an expressive title, e.g. "Fix title font property precedence"
  • New and changed code is tested
  • Plotting related features are demonstrated in an example — N/A, this is a bug fix to existing behavior, not a new plotting feature
  • New features and API changes have release notes
  • Documentation complies with general and docstring guidelines

hist2d passed x and y directly to np.histogram2d without applying the
axes' unit converters, unlike plot, scatter, and hist. Datetime64
input therefore reached numpy as raw (nanosecond-scale) integers
instead of Matplotlib's internal date representation, so a hist2d
plot didn't line up with other artists on the same Axes sharing the
same datetime data -- on current numpy this now raises a hard
TypeError instead (numpy no longer silently mixes datetime64 and
float), so the bug currently manifests as a crash rather than
silently wrong bin edges.

Convert x, y, and range (if given) through _process_unit_info /
convert_xunits / convert_yunits before binning, mirroring the
pattern hist already uses for its own x input. Plain numeric input
is unaffected since unit conversion is a no-op without units set.

Fixes matplotlib#17319

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

@iccir iccir added ai-contribution PRs that are AI generated without a human in the loop status: autoclose candidate PRs that are not yet ready for review and may be automatically closed in two weeks labels Sep 6, 2026
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

⏰ This pull request might be automatically closed in two weeks from now.

Thank you for your contribution to Matplotlib and for the effort you have put into this PR. This pull request does not yet meet the quality and clarity standards needed for an effective review. Project maintainers have limited time for code reviews, and our goal is to prioritize well-prepared contributions to keep Matplotlib maintainable.

Matplotlib maintainers cannot provide one-to-one guidance on this PR. However, if you ask focused, well-researched questions, a community member may be willing to help. 💬

To increase the chance of a productive review:

As the author, you are responsible for driving this PR, which entails doing necessary background research as well as presenting its context and your thought process. If you are a new contributor, or do not know how to fulfill these requirements, we recommend that you familiarize yourself with Matplotlib's development conventions or engage with the community via our Discourse or one of our meetings before submitting code.

If you substantially improve this PR within two weeks, leave a comment and a team member may remove the status: autoclose candidate label and the PR stays open. Cosmetic changes or incomplete fixes will not be sufficient. Maintainers will assess improvements on their own schedule. Please do not ping (@) maintainers.

@AdityaJagtap18

Copy link
Copy Markdown
Author

Updated the PR description to follow the template: filled in the PR summary, added an explicit AI Disclosure section describing exactly what the AI assistant did versus what I reviewed/verified myself, and checked off the quality checklist. Happy to make further changes if this still isn't sufficient.

@jklymak jklymak left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not a huge fan of these tests - they rely on the epoch and details of our yday conversion. The tests should test the actual user-facing output not our inner representation of the dates. These would fail needlessly if we change the epoch or decide to use units of seconds instead of days internally.

Per review from @jklymak: the previous tests hardcoded an assumption
about date2num's internal scale (asserting values are "< 1e6"), which
would fail needlessly if the epoch or internal units ever changed,
without actually testing anything user-facing.

Rewrote both tests to compare hist2d's returned bin edges/counts against
np.histogram2d called with matplotlib.dates.date2num(x) directly -- the
same public conversion function a user would reach for -- rather than
asserting anything about the specific numeric scale. This tests exactly
the promised behavior (hist2d converts the same way plot()/scatter() do)
without any coupling to the internal representation.

Verified by monkeypatching the real (unmodified) Axes.hist2d with this
PR's fix in a fresh pip install of matplotlib and running both tests
directly, plus a negative control confirming they fail against the
original, unpatched hist2d (which raises a TypeError mixing datetime64
and float on current numpy, matching the original bug report).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@AdityaJagtap18

Copy link
Copy Markdown
Author

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

Labels

ai-contribution PRs that are AI generated without a human in the loop first-contribution status: autoclose candidate PRs that are not yet ready for review and may be automatically closed in two weeks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants