Skip to content

Commit 633fc1b

Browse files
Jammy2211claude
authored andcommitted
Colorbar tick fontsize reduction and scientific notation consistency
- Reduce default colorbar tick labelsize from 22 → 18 (both single-figure and subplot) - Add _to_scientific() helper for Unicode ×10 notation (e.g. 4.3×10⁴) - Fix colorbar tick notation inconsistency: when any tick uses ×10 notation, all non-zero ticks are normalised to the same notation so the central tick never shows plain decimal while outer ticks show scientific Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
1 parent 2044037 commit 633fc1b

4 files changed

Lines changed: 101 additions & 24 deletions

File tree

CLAUDE.md

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,31 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
99
pip install -e ".[dev]"
1010
```
1111

12-
### Run Tests
13-
```bash
14-
# All tests
15-
python -m pytest test_autoarray/
12+
### Run Tests
13+
```bash
14+
# All tests
15+
python -m pytest test_autoarray/
1616

1717
# Single test file
1818
python -m pytest test_autoarray/structures/test_arrays.py
1919

20-
# With output
21-
python -m pytest test_autoarray/structures/test_arrays.py -s
22-
```
23-
24-
### Formatting
25-
```bash
26-
black autoarray/
20+
# With output
21+
python -m pytest test_autoarray/structures/test_arrays.py -s
22+
```
23+
24+
### Codex / sandboxed runs
25+
26+
When running Python from Codex or any restricted environment, set writable cache directories so `numba` and `matplotlib` do not fail on unwritable home or source-tree paths:
27+
28+
```bash
29+
NUMBA_CACHE_DIR=/tmp/numba_cache MPLCONFIGDIR=/tmp/matplotlib python -m pytest test_autoarray/
30+
```
31+
32+
This workspace is often imported from `/mnt/c/...` and Codex may not be able to write to module `__pycache__` directories or `/home/jammy/.cache`, which can cause import-time `numba` caching failures without this override.
33+
34+
### Formatting
35+
```bash
36+
black autoarray/
2737
```
2838

2939
## Architecture

autoarray/dataset/plot/interferometer_plots.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,31 +42,33 @@ def subplot_interferometer_dataset(
4242
fig, axes = plt.subplots(2, 3, figsize=conf_subplot_figsize(2, 3))
4343
axes = axes.flatten()
4444

45-
plot_grid(dataset.data.in_grid, ax=axes[0], title="Visibilities")
45+
plot_grid(dataset.data.in_grid, ax=axes[0], title="Visibilities", xlabel="", ylabel="")
4646
plot_grid(
4747
Grid2DIrregular.from_yx_1d(
4848
y=dataset.uv_wavelengths[:, 1] / 10**3.0,
4949
x=dataset.uv_wavelengths[:, 0] / 10**3.0,
5050
),
5151
ax=axes[1],
5252
title="UV-Wavelengths",
53+
xlabel="",
54+
ylabel="",
5355
)
5456
plot_yx(
5557
dataset.amplitudes,
5658
dataset.uv_distances / 10**3.0,
5759
ax=axes[2],
5860
title="Amplitudes vs UV-distances",
59-
ylabel="Jy",
60-
xlabel="k$\\lambda$",
61+
xtick_suffix='"',
62+
ytick_suffix="Jy",
6163
plot_axis_type="scatter",
6264
)
6365
plot_yx(
6466
dataset.phases,
6567
dataset.uv_distances / 10**3.0,
6668
ax=axes[3],
6769
title="Phases vs UV-distances",
68-
ylabel="deg",
69-
xlabel="k$\\lambda$",
70+
xtick_suffix='"',
71+
ytick_suffix="deg",
7072
plot_axis_type="scatter",
7173
)
7274
plot_array(

autoarray/plot/utils.py

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -533,15 +533,52 @@ def _colorbar_tick_values(norm) -> Optional[List[float]]:
533533
return [lo, mid, hi]
534534

535535

536+
_SUPERSCRIPT_DIGITS = str.maketrans("0123456789-", "⁰¹²³⁴⁵⁶⁷⁸⁹⁻")
537+
538+
539+
def _to_scientific(v: float) -> Optional[str]:
540+
"""Convert *v* to Unicode scientific notation (e.g. ``4.3×10⁴``).
541+
542+
Returns ``None`` when ``f"{v:.2g}"`` does not produce an exponent (unusual
543+
edge case for certain values near the g-format threshold).
544+
"""
545+
s = f"{v:.2g}"
546+
if "e" not in s:
547+
return None
548+
mantissa, exp = s.split("e")
549+
sign = "-" if exp.startswith("-") else ""
550+
exp_num = exp.lstrip("+-").lstrip("0") or "0"
551+
superscript = f"{sign}{exp_num}".translate(_SUPERSCRIPT_DIGITS)
552+
return f"{mantissa}×10{superscript}"
553+
554+
536555
def _fmt_tick(v: float) -> str:
537-
"""Format a single tick value to 2 decimal places without scientific notation."""
556+
"""Format a single tick value compactly.
557+
558+
Values with 5 or more digits (abs(v) >= 10000) or very small values
559+
(abs(v) < 0.001) are rendered as compact scientific notation using
560+
Unicode superscripts, e.g. ``4.3×10⁴`` or ``1.2×10⁻⁵``. This avoids
561+
LaTeX expansion that would overflow the colorbar width. Values in
562+
between are rendered with ``:.2f``.
563+
"""
564+
abs_v = abs(v)
565+
if abs_v != 0 and (abs_v >= 10000 or abs_v < 0.001):
566+
sci = _to_scientific(v)
567+
return sci if sci is not None else f"{v:.2g}"
538568
return f"{v:.2f}"
539569

540570

541571
def _colorbar_tick_labels(tick_values: List[float], cb_unit: Optional[str] = None) -> List[str]:
542-
"""Format tick values without scientific notation, appending *cb_unit* to the middle label.
572+
"""Format tick values, appending *cb_unit* to the middle label.
573+
574+
All three labels use a consistent notation style: if any tick is rendered
575+
in scientific notation (``×10ⁿ``), every non-zero tick is forced through
576+
the same format. This prevents the central tick from showing e.g.
577+
``-5000.00`` when the outer ticks show ``-2×10⁴`` / ``1.5×10⁴`` because
578+
the midpoint happens to fall below the per-value threshold.
543579
544-
If *cb_unit* is ``None`` the unit is read from config; pass ``""`` for unitless panels.
580+
If *cb_unit* is ``None`` the unit is read from config; pass ``""`` for
581+
unitless panels.
545582
"""
546583
if cb_unit is None:
547584
try:
@@ -551,6 +588,18 @@ def _colorbar_tick_labels(tick_values: List[float], cb_unit: Optional[str] = Non
551588
cb_unit = ""
552589
labels = [_fmt_tick(v) for v in tick_values]
553590
mid = len(labels) // 2
591+
592+
# Enforce consistent notation: if any label uses ×10, convert all others.
593+
if any("×10" in lbl for lbl in labels):
594+
for i, (lbl, v) in enumerate(zip(labels, tick_values)):
595+
if "×10" not in lbl:
596+
if v == 0:
597+
labels[i] = "0"
598+
else:
599+
sci = _to_scientific(v)
600+
if sci is not None:
601+
labels[i] = sci
602+
554603
labels[mid] = f"{labels[mid]}{cb_unit}"
555604
return labels
556605

@@ -569,8 +618,8 @@ def _apply_colorbar(
569618
Override the unit string on the middle tick. Pass ``""`` for unitless panels.
570619
``None`` reads the unit from config.
571620
is_subplot
572-
When ``True`` uses ``labelsize_subplot`` from config (default 22) instead of
573-
the single-figure ``labelsize`` (default 22).
621+
When ``True`` uses ``labelsize_subplot`` from config (default 18) instead of
622+
the single-figure ``labelsize`` (default 18).
574623
"""
575624
tick_values = _colorbar_tick_values(getattr(mappable, "norm", None))
576625

@@ -582,7 +631,7 @@ def _apply_colorbar(
582631
ticks=tick_values,
583632
)
584633
labelsize_key = "labelsize_subplot" if is_subplot else "labelsize"
585-
labelsize = float(_conf_colorbar(labelsize_key, 22))
634+
labelsize = float(_conf_colorbar(labelsize_key, 18))
586635
labelrotation = float(_conf_colorbar("labelrotation", 90))
587636
if tick_values is not None:
588637
cb.ax.set_yticklabels(

autoarray/plot/yx.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ def plot_yx(
2525
title: str = "",
2626
xlabel: str = "",
2727
ylabel: str = "",
28+
xtick_suffix: str = "",
29+
ytick_suffix: str = "",
2830
label: Optional[str] = None,
29-
color: str = "b",
31+
color: str = "k",
3032
linestyle: str = "-",
3133
plot_axis_type: str = "linear",
3234
# --- figure control (used only when ax is None) -----------------------------
@@ -129,7 +131,21 @@ def plot_yx(
129131
ax.fill_between(x, y1, y2, alpha=0.3)
130132

131133
# --- labels ----------------------------------------------------------------
132-
apply_labels(ax, title=title, xlabel=xlabel, ylabel=ylabel)
134+
apply_labels(ax, title=title, xlabel=xlabel, ylabel=ylabel, is_subplot=not owns_figure)
135+
136+
# --- 3-point ticks with optional unit suffixes ----------------------------
137+
from autoarray.plot.utils import _inward_ticks, _round_ticks, _conf_ticks
138+
139+
factor = _conf_ticks("extent_factor_2d", 0.75)
140+
141+
xlo, xhi = ax.get_xlim()
142+
ylo, yhi = ax.get_ylim()
143+
xticks = _round_ticks(_inward_ticks(xlo, xhi, factor, 3))
144+
yticks = _round_ticks(_inward_ticks(ylo, yhi, factor, 3))
145+
ax.set_xticks(xticks)
146+
ax.set_xticklabels([f"{v:g}{xtick_suffix}" for v in xticks])
147+
ax.set_yticks(yticks)
148+
ax.set_yticklabels([f"{v:g}{ytick_suffix}" for v in yticks])
133149

134150
if label is not None:
135151
ax.legend(fontsize=12)

0 commit comments

Comments
 (0)