-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
FIX: Prevent warning when clearing axes with shared non-linear scale #30843
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
FIX: Prevent warning when clearing axes with shared non-linear scale #30843
Conversation
When clearing an axes (via cla() or clf()) that has a shared axis with a non-linear scale (e.g., log, logit), a warning was incorrectly generated: 'Attempt to set non-positive xlim on a log-scaled axis will be ignored.' This occurred because when an axes with linear scale sets default limits (0, 1), these limits propagate to shared axes that may have non-linear scales which reject these limits. Fixed by skipping propagation of default (0, 1) limits from linear scale axes to non-linear scale shared axes. This preserves the behavior for other cases (like inverted axes) while eliminating the spurious warning. Additionally, reordered scale assignment before limit setting in sharex()/sharey() methods to ensure scale is set before limits are applied. Fixes matplotlib#9970
|
Can anyone tell me what is the meaning of failed tests. Is there any correction that I can make in PR? Kindly help me. |
|
The test failure is unrelated. See #30703 (comment). Note: It‘s unnecessary and discouraged to close a PR and open a new one for the same topic, as you‘ve done here/in #30826. For the future, please force-push instead if needed. |
timhoffm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a test.
| if other is self.axes: | ||
| continue | ||
| other._axis_map[name]._set_lim(v0, v1, emit=False, auto=auto) | ||
| # Skip propagating default (0, 1) limits from linear scale to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please convince me that this is the correct solution and not just fixing a special case. I don’t have full oversight on the details of the topic, but doing selective action on scale and limits doesn’t feel like it it’s a general solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pushing back on this—it's a fair concern! Let me explain why I think this is actually a proper fix rather than just patching one edge case.
The core idea:
The problem we're solving is: when you clear an axes, it shouldn't try to force invalid default values onto other axes that share with it. My fix prevents exactly that—it stops (0, 1) limits from being passed to axes with non-linear scales that can't handle them.
Why focus on (0, 1)?
Those are the hardcoded default limits that [clear()] uses (you can see this on line 1427 in [_base.py]. They're literally the only values that would cause this issue during a clear operation. So checking specifically for (0, 1) isn't narrowing the fix—it's targeting the exact source of the problem.
What about other non-linear scales?
The condition [other_axis.get_scale() != 'linear'] handles everything: log, logit, symlog, asinh—any scale that isn't linear. They all have their own domain restrictions, and (0, 1) is problematic for many of them. So this actually covers all the cases where this warning could appear.
Why fix it in the propagation logic?
I chose this spot because it's where shared axes sync up their limits. When one axis changes its limits, it tells its shared partners. By catching the issue here, we prevent bad values from even reaching the point where they'd trigger warnings. It felt cleaner than trying to suppress warnings or changing how [clear()] itself works.
What I tried first:
I actually started by using [emit=False] when clearing, which would just stop all propagation. But that broke a different feature—when you clear an inverted shared axis, the other axes need to get that update. So [emit=False] was too heavy-handed.
|
How and where can I add the test code? Kindly guide me with this @timhoffm |
Verify that clearing an axes with shared non-linear scales (log, logit, symlog) does not generate spurious warnings. Tests both sharex and sharey configurations. Regression test for matplotlib#9970.
Removed unnecessary blank lines in the test for shared axes with non-linear scale.
|
I have also added a test in the tests folder in test_axes.py. Kindly review my PR and suggest changes if any. |
PR summary
When clearing an axes (via cla() or clf()) that has a shared axis with a non-linear scale (e.g., log, logit), an incorrect warning was generated:
Attempt to set non-positive xlim on a log-scaled axis will be ignored.
Why is this change necessary?
This warning appeared even though the user's code was perfectly valid. Clearing axes with shared non-linear scales is a common operation and should not generate spurious warnings.
What problem does it solve?
The issue occurred during the axis limit propagation in the Axis._set_lim() method in axis.py. When an axes with linear scale clears and resets to default limits (0, 1), these limits automatically propagate to all shared axes. If a shared axis has a non-linear scale (like log), it rejects these limits because they contain non-positive values, triggering the warning.
What is the reasoning for this implementation?
The fix adds a targeted check in the limit propagation loop (axis.py, lines 1267-1272) to skip propagating default (0, 1) limits when:
The source axis has linear scale, AND
The receiving shared axis has a non-linear scale, AND
The limits being propagated are exactly (0, 1)
This prevents the spurious warning while preserving all other propagation behavior (including for inverted shared axes, which rely on propagation to work correctly).
Additionally, in _base.py (lines 1278 and 1298), the sharex() and sharey() methods now set the scale before copying limits from the shared axis. This prevents temporary scale/limit mismatches during axis sharing initialization.
Minimal self-contained example:
PR checklist