Skip to content

feat: redesign subplot_fit panels — add Source Plane (Mid Zoom) #517

Closed

Description

@Jammy2211

Overview

The subplot_fit 3×4 layout currently devotes two panels to "Data" — full
scale and source scale — but the source-scale Data panel is near-useless, and
"Source Plane (Zoomed)" frequently over-zooms, making the fit hard to judge.
This task reshuffles the panels so Model Image sits beside Data, promotes the
zoomed source plane to the top right (rename: "Max Zoom"), and adds a new
"Source Plane (Mid Zoom)" panel — same centre as Max Zoom, but with x and y
extents 2.5× larger for context.

Plan

  • Remove the "Data (Source Scale)" panel from subplot_fit.
  • Move "Model Image" to the now-vacant slot beside "Data".
  • Promote "Source Plane (Zoomed)" to the top-right slot and rename it
    "Source Plane (Max Zoom)".
  • Add a new "Source Plane (Mid Zoom)" panel below Max Zoom — same centre, x
    and y extents 2.5× larger.
  • Plumb a zoom_extent_scale kwarg through the parametric and inversion
    source-plane code paths (PyAutoLens + PyAutoArray) so the wider view can be
    requested without duplicating logic.
  • Mirror the panel reshuffle in subplot_fit_log10 for consistency.
Detailed implementation plan

Affected Repositories

  • PyAutoLens (primary) — panel reshuffle, new Mid Zoom panel, zoom_extent_scale in _plot_source_plane and plane_image_from
  • PyAutoArray — zoom_extent_scale plumbed through plot_mapper, plot_inversion_reconstruction, and mapper.extent_from

Work Classification

Library

Branch Survey

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

Suggested branch: feature/subplot-fit-mid-zoom
Worktree root: ~/Code/PyAutoLabs-wt/subplot-fit-mid-zoom/ (created later by /start_library)

New subplot_fit 3×4 layout

idx row,col Title Notes
0 0,0 Data unchanged
1 0,1 Model Image moved from idx 3
2 0,2 Signal-To-Noise Map unchanged
3 0,3 Source Plane (Max Zoom) moved from idx 7, renamed
4 1,0 Lens Light Model Image unchanged
5 1,1 Lens Light Subtracted unchanged
6 1,2 Source Model Image unchanged
7 1,3 Source Plane (Mid Zoom) NEW — 2.5× wider extent, same centre as Max Zoom
8 2,0 Normalized Residual Map unchanged
9 2,1 Normalized Residual Map 1σ unchanged
10 2,2 Chi-Squared Map unchanged
11 2,3 Source Plane (No Zoom) unchanged

Implementation Steps

  1. PyAutoArray: add zoom_extent_scale: float = 1.0 to mapper.extent_from (scale the brightness-derived extent symmetrically about its centre when > 1.0). Thread it through plot_inversion_reconstruction and plot_mapper. Default value preserves current behaviour. Add a unit test for the new parameter.
  2. PyAutoLens tracer_plots.plane_image_from: accept zoom_extent_scale: float = 1.0. After the brightest extent is computed, expand (x_min, x_max, y_min, y_max) symmetrically around its centre by the scale factor before passing to extent_symmetric_from. Default value preserves current behaviour.
  3. PyAutoLens fit_imaging_plots._plot_source_plane: accept zoom_extent_scale: float = 1.0 and forward it to plane_image_from and plot_mapper.
  4. PyAutoLens fit_imaging_plots.subplot_fit: reorder panels per the new 12-panel layout. Drop the Data (Source Scale) call. Add a Mid Zoom call: _plot_source_plane(..., zoom_to_brightest=True, zoom_extent_scale=2.5, title="Source Plane (Mid Zoom)").
  5. PyAutoLens fit_imaging_plots.subplot_fit_log10: mirror the same panel reshuffle.
  6. Tests:
    • test_autolens/imaging/plot/test_fit_imaging_plots.py: update panel-count / title assertions; smoke-test the Mid Zoom panel for parametric and inversion source fits.
    • test_autoarray/inversion/plot/...: exercise zoom_extent_scale=2.5 on the inversion path.

Key Files

  • PyAutoLens/autolens/imaging/plot/fit_imaging_plots.py — subplot_fit, subplot_fit_log10, _plot_source_plane
  • PyAutoLens/autolens/lens/plot/tracer_plots.py — plane_image_from
  • PyAutoArray/autoarray/inversion/plot/mapper_plots.py — plot_mapper
  • PyAutoArray/autoarray/plot/inversion.py — plot_inversion_reconstruction
  • PyAutoArray/autoarray/inversion/mappers/... — extent_from

Original Prompt

Click to expand starting prompt

Currently, subplot_fit is 4 x 3 panels, with two source reconstructions in the middle-right and bottom-right row.

However, it is common for the Zoom panel to over zoom, making it hard to judge the fit.

Equally, the Data (Source Scale) panel is verging on useless.

Therefore, can we:

  1. Move Model Image to where Data (Source Scale) is and remove Data (Scouece Scale).
  2. Move Source Plane (Zoomed) up one to the top right and rename its title (Max Zoom).
  3. Make a new panel, Source Plane (Mid Zoom), which uses the same centre as Max Zoom but expands the y axia and x axis to be 2.5x larger than Max Zoom.

Activity

  1. Jammy2211 commented on May 18, 2026

    @Jammy2211
    CollaboratorAuthor

    Smoke Test Results — 2026-05-18

    All 44 smoke tests passed across 5 workspaces (euclid skipped — no runner).

    Workspace Passed Failed Total
    autofit_workspace 9 0 9
    autogalaxy_workspace 8 0 8
    autolens_workspace 9 0 9
    autolens_workspace_test 12 0 12
    HowToLens 6 0 6

    (euclid_strong_lens_modeling_pipeline skipped — no run_smoke.py runner)

    Tested against feature/subplot-fit-mid-zoom branches in worktree subplot-fit-mid-zoom (PyAutoArray #324, PyAutoLens #518).

  2. Jammy2211 commented on May 18, 2026

    @Jammy2211
    CollaboratorAuthor

    Shipped — 2026-05-18

    PRs

    Summary

    Reshuffled the 12-panel subplot_fit (and subplot_fit_log10) layout: dropped "Data (Source Scale)", moved "Model Image" beside "Data", renamed "Source Plane (Zoomed)" → "Source Plane (Max Zoom)" and promoted it to the top right, and added a new "Source Plane (Mid Zoom)" panel. Mid Zoom uses 2× the Max Zoom extent, kept square, shrunk uniformly so all edges stay inside the No Zoom extent and the half-width never exceeds 0.7 × the No Zoom half-width — guaranteeing it always sits strictly between Max Zoom and No Zoom regardless of bright-pixel offset. Threaded a zoom_extent_scale kwarg through Mapper.extent_from, plot_inversion_reconstruction, plot_mapper, _plot_source_plane, and plane_image_from so the wider view can be requested by other callers.

    Session Notes

    • The shrink-to-fit logic was iterated three times to handle different bright-pixel geometries: (1) per-edge clamping broke square aspect; (2) uniform-shrink kept it square but produced Mid Zoom ≡ No Zoom when bright was centred; (3) added a 0.7 × bound_half cap that ensures Mid Zoom is always visibly tighter than No Zoom.
    • Hit a pre-existing quirk in Zoom2D.extent_from: it returns values in a pixel-shifted coordinate system (centred at pixel index, not at the mask's arcsec origin). Grid2D.from_extent happens to "fix" this by extracting the span only and re-centring at origin. For the Mid Zoom clamp, the bound now goes through the same round-trip (Grid2D.from_extent(...).geometry.extent) so it matches what the No Zoom panel actually displays.
    • Smoke tests: 44/44 passed across autofit, autogalaxy, autolens, autolens_workspace_test, HowToLens. Euclid skipped (no run_smoke.py runner).
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