Skip to content

Commit 5895f8a

Browse files
authored
Preserve log formatter when setting log scales (#437)
1 parent fb45153 commit 5895f8a

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

ultraplot/axes/cartesian.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,26 @@ def _sharey_setup(self, sharey, *, labels=True, limits=True):
789789
if level > 1 and limits:
790790
self._sharey_limits(sharey)
791791

792+
def _apply_log_formatter_on_scale(self, s):
793+
"""
794+
Enforce log formatter when log scale is set and rc is enabled.
795+
"""
796+
if not rc.find("formatter.log", context=True):
797+
return
798+
if getattr(self, f"get_{s}scale")() != "log":
799+
return
800+
self._update_formatter(s, "log")
801+
802+
def set_xscale(self, value, **kwargs):
803+
result = super().set_xscale(value, **kwargs)
804+
self._apply_log_formatter_on_scale("x")
805+
return result
806+
807+
def set_yscale(self, value, **kwargs):
808+
result = super().set_yscale(value, **kwargs)
809+
self._apply_log_formatter_on_scale("y")
810+
return result
811+
792812
def _update_formatter(
793813
self,
794814
s,
@@ -1399,6 +1419,7 @@ def format(
13991419
# WARNING: Changing axis scale also changes default locators
14001420
# and formatters, and restricts possible range of axis limits,
14011421
# so critical to do it first.
1422+
scale_requested = scale is not None
14021423
if scale is not None:
14031424
scale = constructor.Scale(scale, **scale_kw)
14041425
getattr(self, f"set_{s}scale")(scale)
@@ -1490,10 +1511,40 @@ def format(
14901511
tickrange=tickrange,
14911512
wraprange=wraprange,
14921513
)
1514+
if (
1515+
scale_requested
1516+
and formatter is None
1517+
and not formatter_kw
1518+
and tickrange is None
1519+
and wraprange is None
1520+
and rc.find("formatter.log", context=True)
1521+
and getattr(self, f"get_{s}scale")() == "log"
1522+
):
1523+
self._update_formatter(s, "log")
14931524

14941525
# Ensure ticks are within axis bounds
14951526
self._fix_ticks(s, fixticks=fixticks)
14961527

1528+
if rc.find("formatter.log", context=True):
1529+
if (
1530+
xscale is not None
1531+
and xformatter is None
1532+
and not xformatter_kw
1533+
and xtickrange is None
1534+
and xwraprange is None
1535+
and self.get_xscale() == "log"
1536+
):
1537+
self._update_formatter("x", "log")
1538+
if (
1539+
yscale is not None
1540+
and yformatter is None
1541+
and not yformatter_kw
1542+
and ytickrange is None
1543+
and ywraprange is None
1544+
and self.get_yscale() == "log"
1545+
):
1546+
self._update_formatter("y", "log")
1547+
14971548
# Parent format method
14981549
if aspect is not None:
14991550
self.set_aspect(aspect)

ultraplot/tests/test_plot.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,33 @@ def reset(ax):
361361
uplt.close(fig)
362362

363363

364+
def test_format_log_scale_preserves_log_formatter():
365+
"""
366+
Test that setting a log scale preserves the log formatter when enabled.
367+
"""
368+
x = np.linspace(1, 1e6, 10)
369+
log_formatter = uplt.constructor.Formatter("log")
370+
log_formatter_type = type(log_formatter)
371+
372+
with uplt.rc.context({"formatter.log": True}):
373+
fig, ax = uplt.subplots()
374+
ax.plot(x, x)
375+
ax.format(yscale="log")
376+
assert isinstance(ax.yaxis.get_major_formatter(), log_formatter_type)
377+
ax.set_yscale("log")
378+
assert isinstance(ax.yaxis.get_major_formatter(), log_formatter_type)
379+
380+
with uplt.rc.context({"formatter.log": False}):
381+
fig, ax = uplt.subplots()
382+
ax.plot(x, x)
383+
ax.format(yscale="log")
384+
assert not isinstance(ax.yaxis.get_major_formatter(), log_formatter_type)
385+
ax.set_yscale("log")
386+
assert not isinstance(ax.yaxis.get_major_formatter(), log_formatter_type)
387+
388+
uplt.close(fig)
389+
390+
364391
def test_shading_pcolor(rng):
365392
"""
366393
Pcolormesh by default adjusts the plot by

0 commit comments

Comments
 (0)