From 2e533411c24b7bee66c1f83ff37667fd708982a7 Mon Sep 17 00:00:00 2001 From: Saumya Date: Tue, 9 Dec 2025 01:12:30 +0530 Subject: [PATCH] FIX: Prevent warning when clearing axes with shared non-linear scale 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 #9970 --- lib/matplotlib/axes/_base.py | 9 +++++++-- lib/matplotlib/axis.py | 9 ++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py index f047fe1809aa..97c432f13fa8 100644 --- a/lib/matplotlib/axes/_base.py +++ b/lib/matplotlib/axes/_base.py @@ -1274,9 +1274,10 @@ def sharex(self, other): self._sharex = other self.xaxis.major = other.xaxis.major # Ticker instances holding self.xaxis.minor = other.xaxis.minor # locator and formatter. + # Set scale before limits to avoid warnings with non-linear scales + self.xaxis._scale = other.xaxis._scale x0, x1 = other.get_xlim() self.set_xlim(x0, x1, emit=False, auto=other.get_autoscalex_on()) - self.xaxis._scale = other.xaxis._scale def sharey(self, other): """ @@ -1293,9 +1294,10 @@ def sharey(self, other): self._sharey = other self.yaxis.major = other.yaxis.major # Ticker instances holding self.yaxis.minor = other.yaxis.minor # locator and formatter. + # Set scale before limits to avoid warnings with non-linear scales + self.yaxis._scale = other.yaxis._scale y0, y1 = other.get_ylim() self.set_ylim(y0, y1, emit=False, auto=other.get_autoscaley_on()) - self.yaxis._scale = other.yaxis._scale def __clear(self): """Clear the Axes.""" @@ -1419,6 +1421,9 @@ def __clear(self): share = getattr(self, f"_share{name}") if share is not None: getattr(self, f"share{name}")(share) + # Don't set default limits for shared axes - they will be + # synchronized from the shared axis and may have non-linear + # scales that would reject the (0, 1) default limits. else: # Although the scale was set to linear as part of clear, # polar requires that _set_scale is called again diff --git a/lib/matplotlib/axis.py b/lib/matplotlib/axis.py index c3b6fcac569f..bf0bbcdf3b21 100644 --- a/lib/matplotlib/axis.py +++ b/lib/matplotlib/axis.py @@ -1263,7 +1263,14 @@ def _set_lim(self, v0, v1, *, emit=True, auto): for other in self._get_shared_axes(): 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 + # non-linear scales during clear operations to avoid warnings + other_axis = other._axis_map[name] + if (self.get_scale() == 'linear' and + other_axis.get_scale() != 'linear' and + v0 == 0 and v1 == 1): + continue + other_axis._set_lim(v0, v1, emit=False, auto=auto) if emit: other.callbacks.process(f"{name}lim_changed", other) if ((other_fig := other.get_figure(root=False)) !=