Skip to content
Draft
27 changes: 25 additions & 2 deletions docs/subplots.py
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,9 @@
# `~matplotlib.figure.Figure.supxlabel` and `~matplotlib.figure.Figure.supylabel`,
# these labels are aligned between gridspec edges rather than figure edges.
# #. Supporting five sharing "levels". These values can be passed to `sharex`,
# `sharey`, or `share`, or assigned to :rcraw:`subplots.share`. The levels
# are defined as follows:
# `sharey`, or `share`, or assigned to :rcraw:`subplots.share`.
# UltraPlot supports five explicit sharing levels plus ``'auto'``.
# The levels are defined as follows:
#
# * ``False`` or ``0``: Axis sharing is disabled.
# * ``'labels'``, ``'labs'``, or ``1``: Axis labels are shared, but nothing else.
Expand All @@ -384,6 +385,14 @@
# in the same row or column of the :class:`~ultraplot.gridspec.GridSpec`; a space
# or empty plot will add the labels, but not break the limit sharing. See below
# for a more complex example.
# * ``'limits'``, ``'lims'``, or ``2``: As above, plus share limits/scales/ticks.
# * ``True`` or ``3``: As above, plus hide inner tick labels.
# * ``'all'`` or ``4``: As above, plus share limits across the full subplot grid.
# * ``'auto'`` (default): Start from level ``3`` and only share compatible axes.
# This suppresses warnings for mixed axis families (e.g., cartesian + polar).
#
# Explicit sharing levels still force sharing attempts and may warn when
# incompatible axes are encountered.
#
# The below examples demonstrate the effect of various axis and label sharing
# settings on the appearance of several subplot grids.
Expand Down Expand Up @@ -422,6 +431,20 @@
import ultraplot as uplt
import numpy as np

# The default `share='auto'` keeps incompatible axis families unshared.
fig, axs = uplt.subplots(ncols=2, proj=("cart", "polar"))
x = np.linspace(0, 2 * np.pi, 100)
axs[0].plot(x, np.sin(x))
axs[1].plot(x, np.abs(np.sin(2 * x)))
axs.format(
suptitle="Auto sharing with mixed cartesian and polar axes",
title=("cartesian", "polar"),
)

# %%
import ultraplot as uplt
import numpy as np

state = np.random.RandomState(51423)

# Plots with minimum and maximum sharing settings
Expand Down
42 changes: 30 additions & 12 deletions ultraplot/axes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -1702,21 +1702,39 @@ def shared(paxs):
iax._sharey_setup(left)

# External axes sharing, sometimes overrides panel axes sharing
# Share x axes
parent, *children = self._get_share_axes("x")
for child in children:
child._sharex_setup(parent)
# Share y axes
parent, *children = self._get_share_axes("y")
for child in children:
child._sharey_setup(parent)
# Global sharing, use the reference subplot because why not
# Share x axes within compatible groups
axes_x = self._get_share_axes("x")
for group in self.figure._partition_share_axes(axes_x, "x"):
if not group:
continue
parent, *children = group
for child in children:
child._sharex_setup(parent)

# Share y axes within compatible groups
axes_y = self._get_share_axes("y")
for group in self.figure._partition_share_axes(axes_y, "y"):
if not group:
continue
parent, *children = group
for child in children:
child._sharey_setup(parent)

# Global sharing, use the reference subplot where compatible
ref = self.figure._subplot_dict.get(self.figure._refnum, None)
if self is not ref:
if self is not ref and ref is not None:
if self.figure._sharex > 3:
self._sharex_setup(ref, labels=False)
ok, reason = self.figure._share_axes_compatible(ref, self, "x")
if ok:
self._sharex_setup(ref, labels=False)
else:
self.figure._warn_incompatible_share("x", ref, self, reason)
if self.figure._sharey > 3:
self._sharey_setup(ref, labels=False)
ok, reason = self.figure._share_axes_compatible(ref, self, "y")
if ok:
self._sharey_setup(ref, labels=False)
else:
self.figure._warn_incompatible_share("y", ref, self, reason)

def _artist_fully_clipped(self, artist):
"""
Expand Down
18 changes: 18 additions & 0 deletions ultraplot/axes/cartesian.py
Original file line number Diff line number Diff line change
Expand Up @@ -869,13 +869,31 @@ def _apply_log_formatter_on_scale(self, s):
self._update_formatter(s, "log")

def set_xscale(self, value, **kwargs):
fig = getattr(self, "figure", None)
if (
fig is not None
and hasattr(fig, "_is_auto_share_mode")
and fig._is_auto_share_mode("x")
):
self._unshare(which="x")
result = super().set_xscale(value, **kwargs)
self._apply_log_formatter_on_scale("x")
if fig is not None and hasattr(fig, "_refresh_auto_share"):
fig._refresh_auto_share("x")
return result

def set_yscale(self, value, **kwargs):
fig = getattr(self, "figure", None)
if (
fig is not None
and hasattr(fig, "_is_auto_share_mode")
and fig._is_auto_share_mode("y")
):
self._unshare(which="y")
result = super().set_yscale(value, **kwargs)
self._apply_log_formatter_on_scale("y")
if fig is not None and hasattr(fig, "_refresh_auto_share"):
fig._refresh_auto_share("y")
return result

def _update_formatter(
Expand Down
Loading
Loading