From 32cb5e027d2ff830b26daf262de0a270f3aa51b7 Mon Sep 17 00:00:00 2001 From: cvanelteren Date: Tue, 12 May 2026 18:31:09 +1000 Subject: [PATCH] Fix tick visibility leaking from styles in alternative axes When applying custom styles like dark_background, matplotlib's styling dictionaries often include explicit boolean flags for tick visibility on all sides (e.g. left, right, top, bottom). Previously, UltraPlot queried these style settings using _get_tickline_props and inadvertently reapplied them to the axes, completely overriding UltraPlot's internal locators. This caused bugs such as the left axis displaying right ticks and the right axis displaying left ticks when a style was active. By aggressively popping visibility keys out of the retrieved styling dictionary, we ensure that themes strictly govern visual appearances (color, width, padding) without hijacking the structural tick visibility correctly managed by the format methods. --- ultraplot/config.py | 7 ++++ ultraplot/tests/test_axes_alt_styles.py | 45 +++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 ultraplot/tests/test_axes_alt_styles.py diff --git a/ultraplot/config.py b/ultraplot/config.py index 89af0e4dc..6ff402a11 100644 --- a/ultraplot/config.py +++ b/ultraplot/config.py @@ -1296,6 +1296,13 @@ def _get_tickline_props(self, axis=None, which="major", native=True, rebuild=Fal context = not rebuild and (native or self._context_mode == 2) kwticks = self.category(f"{axis}tick.{which}", context=context) kwticks.pop("visible", None) + + # NOTE: We pop visibility properties from the styling dictionary so that + # stylistic updates (like applying a dark_background theme) do not override + # the tick visibility logic strictly managed by ax._update_locs() and alternate axes. + for key in ("bottom", "top", "left", "right"): + kwticks.pop(key, None) + for key in ("color", "direction"): value = self.find(f"{axis}tick.{key}", context=context) if value is not None: diff --git a/ultraplot/tests/test_axes_alt_styles.py b/ultraplot/tests/test_axes_alt_styles.py new file mode 100644 index 000000000..3031168d9 --- /dev/null +++ b/ultraplot/tests/test_axes_alt_styles.py @@ -0,0 +1,45 @@ +import pytest +import ultraplot as uplt + + +def test_alt_axes_styling_dark_background(): + """ + Test that applying dark_background style does not leak tick visibility + settings and correctly preserves alternative axes tick locations. + """ + with uplt.rc.context(style="dark_background"): + fig, ax = uplt.subplots() + ax.format(ycolor="C0", ylabel="Left Axis") + + ax2 = ax.alty(color="C1") + ax2.format(ycolor="C1", ylabel="Right Axis", ylim=(0, 1)) + + # The left axis should ONLY have visible ticks on the left + left_ax_left_ticks = sum( + 1 + for t in ax.yaxis.get_ticklines() + if t.get_visible() and t.get_xdata()[0] == 0 + ) + left_ax_right_ticks = sum( + 1 + for t in ax.yaxis.get_ticklines() + if t.get_visible() and t.get_xdata()[0] == 1 + ) + + # The right axis (ax2) should ONLY have visible ticks on the right + right_ax_left_ticks = sum( + 1 + for t in ax2.yaxis.get_ticklines() + if t.get_visible() and t.get_xdata()[0] == 0 + ) + right_ax_right_ticks = sum( + 1 + for t in ax2.yaxis.get_ticklines() + if t.get_visible() and t.get_xdata()[0] == 1 + ) + + assert left_ax_left_ticks > 0, "Left axis should have left ticks" + assert left_ax_right_ticks == 0, "Left axis should NOT have right ticks" + + assert right_ax_left_ticks == 0, "Right axis should NOT have left ticks" + assert right_ax_right_ticks > 0, "Right axis should have right ticks"