Skip to content

feat: per-call arcsec_after_decimal option for arcsecond tick labels #546

Closed

Description

@Jammy2211

Overview

aplt.plot_array(..., arcsec_after_decimal=True) — the acceptance criterion of the originating PyAutoMind prompt — does not work today. The formatting half of that prompt already shipped: _arcsec_labels (autoarray/plot/utils.py:1109) renders the double-prime over the decimal point (3.″8), driven by ticks.symbol_over_decimal in autoarray/config/visualize/general.yaml, with four tests in test_autoarray/plot/test_utils.py covering the default, enabled, negative and integer-like cases.

What is missing is that the switch is global config only. A paper-figure script wanting this for one panel has to mutate conf.instance (which is exactly what the existing tests do) and restore it afterwards — the fragile, stateful pattern the prompt was filed to remove. This task threads a per-call override down the plotting stack so the option can be passed to a single call.

Plan

  • Give _arcsec_labels an optional symbol_over_decimal argument that overrides the config flag when passed and falls back to the config value when None. Default behaviour is unchanged.
  • Thread the same optional argument through apply_extent, the one helper that calls _arcsec_labels.
  • Expose it on the public entry points that call apply_extent — plot_array, the grid plotter and the inversion plotter — under the prompt's chosen public name arcsec_after_decimal.
  • Forward it through PyAutoGalaxy's plot_array wrapper, which has an explicit keyword signature and no **kwargs, so it must name the parameter to pass it on. This is what makes the option reachable from both autogalaxy.plot and autolens.plot.
  • Add tests for the per-call override: enabled without touching config, disabled while config is on, and config-only behaviour preserved when nothing is passed.
Detailed implementation plan

Affected Repositories

  • PyAutoArray (primary)
  • PyAutoGalaxy

PyAutoLens needs no change: autolens/plot/__init__.py:12 re-exports plot_array from autogalaxy.util.plot_utils, so the PyAutoGalaxy leg is what satisfies the prompt's aplt.plot_array acceptance criterion for lens users.

Branch Survey

Repository Current Branch Dirty?
./PyAutoArray main clean
./PyAutoGalaxy main clean

Suggested branch: feature/arcsec-after-decimal

Work Classification

Library (library-first merge gate: PyAutoArray merges before PyAutoGalaxy)

Implementation Steps

  1. autoarray/plot/utils.py — _arcsec_labels(ticks, symbol_over_decimal=None). Replace the bare _conf_ticks_flag("symbol_over_decimal", False) read with the argument when it is not None, else the config read. None must keep reading config so every existing caller and the config-driven tests are untouched.
  2. autoarray/plot/utils.py — apply_extent(ax, extent, symbol_over_decimal=None), forwarding to both _arcsec_labels calls (lines 1169-1170).
  3. autoarray/plot/array.py — add arcsec_after_decimal: Optional[bool] = None to plot_array (cosmetics block) and pass it at the apply_extent call (line 323).
  4. autoarray/plot/grid.py (line 181) and autoarray/plot/inversion.py (line 166) — same optional parameter on their public functions, forwarded to apply_extent.
  5. autogalaxy/util/plot_utils.py — add arcsec_after_decimal=None to plot_array (line 183) and forward it to autoarray.plot.plot_array.
  6. Tests in test_autoarray/plot/test_utils.py — per-call override cases that do not mutate conf.instance, plus one asserting None still honours config.

Key trade-off

The public name differs from the internal one: arcsec_after_decimal on the plotting API (the prompt's name, and the one users read) versus symbol_over_decimal for the config key and internal helpers (already shipped, already documented in general.yaml). Renaming the shipped config key would break anyone who has already set it, so the two names are bridged at the plot_array boundary rather than unified.

Key Files

  • autoarray/plot/utils.py — _arcsec_labels (1109), apply_extent (1147)
  • autoarray/plot/array.py — plot_array (31), apply_extent call (323)
  • autoarray/plot/grid.py (181), autoarray/plot/inversion.py (166)
  • autogalaxy/util/plot_utils.py — plot_array (183)
  • test_autoarray/plot/test_utils.py — existing arcsec tests (19-90)

Scope note

The originating prompt is draft/feature/autoarray/arcsecond_to_decimal.md, filed 2026-05-14 with Difficulty: large. That sizing predates the config-flag implementation, which shipped without the prompt being retired to complete/. The remaining delta recorded here is materially smaller than the prompt describes; the prompt is being corrected in the same session.

Original Prompt

Click to expand starting prompt

Claude Development Prompt: Arcsecond Tick Label Decimal Placement

Type: feature
Target: PyAutoArray
Themes:

  • visualization
    Difficulty: large
    Autonomy: supervised
    Priority: normal
    Status: formalised
    Consequence: judge
    Review-minutes: 25
    Unattended: ready
    Filed: 2026-05-14 (backfilled from git)

You are working in the PyAutoLens / PyAutoArray plotting codebase.

Goal

Add a boolean option to the plotting API that changes arcsecond tick labels from the current format:

0.45"
-2.2"
3.1"

to:

0."45
-2."2
3."1

This should be implemented inside the plotting source code, not by user scripts editing Matplotlib tick labels after a figure has been drawn.

Requirements

  • Add a clearly named boolean option, for example arcsec_after_decimal, defaulting to False so existing plots are unchanged.
  • The option should be available from high-level plotting functions such as autolens.plot.plot_array(...).
  • When enabled, only labels that are already formatted as arcseconds should change.
  • Preserve all existing tick locations, precision choices, rotation, font size, and other style settings.
  • Do not change colorbars or non-arcsecond axis labels.
  • Add focused tests or examples covering:
    • default behavior remains 0.45";
    • enabled behavior becomes 0."45;
    • negative values become -2."2;
    • integer-like labels without a decimal either remain unchanged or use a documented behavior.

Suggested Implementation Direction

Find where axis tick labels are formatted in the AutoArray / PyAutoLens plotting stack. Start from:

  • autolens.plot.plot_array(...)
  • autoarray.plot.plot_array(...)
  • the axis / tick helper functions used by autoarray.plot.utils
  • any config-driven tick-label formatter that appends the arcsecond symbol

Implement this as close as possible to the tick-label formatter that appends ", rather than modifying labels after plotting. Ideally the formatter should receive the boolean and place the arcsecond marker either at the end or immediately after the decimal point.

Acceptance Criteria

This example should work without post-processing:

import autolens.plot as aplt

aplt.plot_array(
    array=array,
    title="VIS Data",
    arcsec_after_decimal=True,
)

and should produce axis labels like:

-2."2   0."45   3."1

The same call without arcsec_after_decimal=True should preserve the current default labels.

Notes

This request comes from paper-figure generation, where editing Matplotlib labels after aplt.plot_array works but creates fragile layout and whitespace side effects. The source-level option should keep normal PyAutoLens layout behavior intact.

Activity

  1. Jammy2211 commented on Sep 10, 2026

    @Jammy2211
    CollaboratorAuthor

    Shipped

    What landed

    arcsec_after_decimal is now a per-call keyword on plot_array, plot_grid and plot_inversion_reconstruction, forwarded through apply_extent to _arcsec_labels. True forces the symbol-over-decimal form (3.″8), False forces the suffix form (3.8"), and None — the default — reads the ticks.symbol_over_decimal config flag exactly as before, so the config read simply moved into an if symbol_over_decimal is None: fallback and every existing caller is byte-for-byte unchanged.

    PyAutoGalaxy's plot_array wrapper forwards it too, which is what makes the original acceptance criterion work for lens users:

    aplt.plot_array(array=array, title="VIS Data", arcsec_after_decimal=True)

    PyAutoLens needed no change — it re-exports autogalaxy's function.

    CI

    Green on every leg of every run for both head shas: PyAutoArray 3/3 (unittest 3.12, 3.13, nojax); PyAutoGalaxy 4/4 (unittest 3.12, 3.13, nojax, docs-build). Both PRs merged from mergeable_state: clean.

    Notes for whoever reads this next

    • The public name differs from the config key by design: arcsec_after_decimal on the plotting API, symbol_over_decimal for the config key and internal helpers. The config key already shipped and is documented in general.yaml, so renaming it would have broken anyone who had already set it. The two are bridged at each public function's apply_extent call.
    • Most of the originating prompt was already implemented. The formatter and the config flag shipped earlier without the PyAutoMind prompt being retired, so the prompt kept rendering as backlog claiming the whole feature and this task was picked from it. Only the per-call override actually remained; the prompt's Difficulty: was corrected large → medium at issue time. Worth a wider intake reconcile — nothing suggests this prompt was the only one in that state.
    • Both merged PRs carry the pending-release label: merged is not released, and workspace work depending on this keyword is gated until a publish.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions