Skip to content

Fix errorbar autoscaling inconsistency on log axes (fixes #31462)#31478

Open
Vikash-Kumar-23 wants to merge 4 commits intomatplotlib:mainfrom
Vikash-Kumar-23:fix/errorbar-log-autoscale-31462
Open

Fix errorbar autoscaling inconsistency on log axes (fixes #31462)#31478
Vikash-Kumar-23 wants to merge 4 commits intomatplotlib:mainfrom
Vikash-Kumar-23:fix/errorbar-log-autoscale-31462

Conversation

@Vikash-Kumar-23
Copy link
Copy Markdown
Contributor

@Vikash-Kumar-23 Vikash-Kumar-23 commented Apr 8, 2026

PR summary

closes #31462

This PR fixes an autoscaling inconsistency for errorbar on log-scaled axes by addressing a root-cause bug in Collection.get_datalim.

Why this change is necessary

When log scale is set before calling errorbar, autoscaling can produce incorrect lower limits (often collapsing near 1).
If errorbar is called first and log scale is applied afterward, the limits are correct.

This order-dependent behavior is unexpected and inconsistent.


What this PR changes

As suggested by maintainers in the review, the root cause was traced to Collection.get_datalim.

When calculating limits on log axes, transform.get_affine() - transData yields an inverse non-affine (inverse log) component. However, this was being passed to the C wrapper (_path_wrapper.cpp), which only accepts affine matrices. The non-affine part was completely discarded at the C boundary, causing extents to be computed in log-transformed coordinates instead of original data coordinates.

To fix this:

  • This PR pre-applies the non-affine component to the paths in Python before passing the remaining affine transform to the C extents call.
  • Adds a regression test to ensure both call orders now produce consistent limits.

Before fix (incorrect behavior)

Screenshot 2026-04-08 201640
  • Lower limits collapse near ~1 when using scale → errorbar

After fix (correct behavior)

image
  • Both orders now produce consistent and reasonable limits

Minimum self-contained example

import numpy as np
import matplotlib.pyplot as plt

x = 10 ** np.array([18, 18.1, 18.2, 18.3])
y = np.array([100, 80, 60, 30])
yerr = np.ones_like(y) * 10

# Order 1: scale -> errorbar
fig1, ax1 = plt.subplots()
ax1.set_xscale("log")
ax1.set_yscale("log")
ax1.errorbar(x, y, yerr=yerr)

# Order 2: errorbar -> scale
fig2, ax2 = plt.subplots()
ax2.errorbar(x, y, yerr=yerr)
ax2.set_xscale("log")
ax2.set_yscale("log")

print(ax1.get_xlim(), ax1.get_ylim())
print(ax2.get_xlim(), ax2.get_ylim())

Expected after this PR

  • Both orders produce consistent, reasonable limits

AI Disclosure

AI tools were used to assist in drafting text and suggesting validation scenarios.
All code changes, final implementation decisions, and verification were done manually.


PR checklist

Comment thread lib/matplotlib/axes/_axes.py
Comment thread lib/matplotlib/tests/test_axes.py
@rcomer
Copy link
Copy Markdown
Member

rcomer commented Apr 13, 2026

I recommend installing the pre-commit hooks to help with the linting
https://matplotlib.org/devdocs/devel/development_setup.html#install-pre-commit-hooks

@Vikash-Kumar-23
Copy link
Copy Markdown
Contributor Author

Hi @rcomer @timhoffm, just checking in! I've verified the remaining CI failures are unrelated to these changes. Is there anything else needed on my end? I'm ready to help further if needed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Errorbar plot on log-scaled Axes sets incorrect automatic lower limits

5 participants