Skip to content

feat: source-plane fit panel paired to each Fit class #789

Closed

Description

@Jammy2211

Overview

The point-source fit.png only shows the image plane, so it cannot show how tightly the observed positions trace back together in the source plane — the quantity a source-plane chi-squared minimises and the intuitive self-consistency check for an image-plane chi-squared. This adds a "Fit Source Plane ()" panel to every positions fit, with its presentation paired to the fit class: image-plane-χ² fits get a context-only panel, source-plane-χ² fits show exactly the noise footprint and χ² their likelihood uses.

Plan

  • Add a source-plane panel to fit.png (1×2; 1×3 with fluxes): observed positions ray-traced to the point's own plane, numbered 1..N, the model source centre, the caustics of that plane, zoomed to the traced positions with a caustic inset in the emptiest corner.
  • Pair the panel to each positions Fit class (explicit table, tested per class):
    • image-plane χ² (ImagePair / PairRepeat / PairAll and their Solved variants): context only — no noise footprints, no χ² box, subtitle "Image-plane χ² — traced positions for context";
    • source-plane χ² (FitPositionsSource, FitPositionsSourceSolved): subtitle naming the weighting; the footprint the χ² uses is primary (σ/|μ| circle for magnification, A·σ ellipse for jacobian), plus a faint dashed A·σ "propagated noise (reference)" under magnification; ★ free centre vs ◆ solved β*; χ² box.
  • Move the source-χ² "Model (source plane)" crosses off the image-plane panel; number observed images 1..N on both panels, using the PointSolver figure's ordering and label-adjacency placement.
  • Multi-plane / cluster: caustics of the point's own plane; the cluster inset frames only the tangential caustic.
  • PyAutoArray: apply_extent tick rounding gains adaptive significant figures so ticks never collapse to identical labels at mas zoom.
  • Re-render point_source_image_chi_squared, point_source_source_chi_squared and cluster in autolens_visualization.
Detailed implementation plan

Work Classification

Both (library first: PyAutoArray → PyAutoLens, then autolens_visualization)

Affected Repositories

  • PyAutoLens (primary)
  • PyAutoArray (tick precision fix)
  • autolens_visualization (re-rendered figures)

Branch Survey

Repository Current Branch Dirty?
./array/PyAutoArray main clean
./lens/PyAutoLens main (57f1e65) clean
./lens/autolens_visualization main clean

Suggested branch: feature/point-fit-source-plane-panel
Worktree root: ~/Code/PyAutoLabs-wt/point-fit-source-plane-panel/

Implementation Steps

  1. PyAutoArray autoarray/plot/utils.py: _round_ticks raises its significant figures until distinct inputs stay distinct (used by apply_extent and yx); test in test_autoarray/plot/test_utils.py.
  2. PyAutoLens new autolens/point/plot/source_plane_panel.py: presentation table per Fit class, traced positions (same path as FitPositionsSource.model_data), σ/|μ| radii, A·σ ellipses from precision_tensor_components_from(fit, "jacobian") (covariance σ²AAᵀ), own-plane caustics via LensCalc.from_tracer(tracer, use_multi_plane=True, plane_i=0, plane_j=fit.plane_index), zoom extent, corner-ranked inset/legend/χ² box.
  3. positions_panel.py: shared image-number placement (generalised from point_solver_plots.number_placements_from), 1..N numbering; drop the source-plane crosses from the image panel.
  4. fit_point_plots.subplot_fit: 1×2 / 1×3 layout with the new panel.
  5. Tests: per-class presentation (all 7 classes, both weightings for source classes), panel artists, fluxes layout, multi-plane caustic plane.
  6. autolens_visualization: re-render the three point domains, rebuild gallery + manifest.

Key Files

  • autolens/point/plot/fit_point_plots.py — subplot layout
  • autolens/point/plot/positions_panel.py — shared panel helpers
  • autolens/point/plot/source_plane_panel.py — new
  • autolens/point/plot/point_solver_plots.py — numbering helper reuse
  • autoarray/plot/utils.py — tick rounding

Original Prompt

Click to expand starting prompt

Point-source fit: source-plane panel showing how closely the positions trace

Consequence: judge
Autonomy: human-required
builds-on: complete/2026/10/point-dataset-positions-panel.md (shipped 2026-10-21; shares the fit_point_plots.py styling: markers, σ legend, titles, solver extent)

@PyAutoLens @autolens_visualization

Request (human, 2026-10-21)

A follow up issue would be to do a source plane plot of the fit showing how close things trace, which is relevent for image chi and source chi.

Intent

Add a source-plane panel to the point-source fit.png, possibly also as its own figure. It shows:

  • every observed position ray-traced to the source plane through the fit's tracer
  • the model source centre
  • the caustics

How tightly the traced positions bunch around the source centre is the quantity FitPositionsSource (source chi-squared) minimises. For image chi-squared (FitPositionsImagePair and its variants) it is the intuitive check that the model is self-consistent.

Open design questions (settle in /start_dev)

  • Scale bar for the scatter. Options are the source-plane noise from magnification-scaled σ (what source chi-squared uses, roughly σ/√μ), a circle per traced position, or a σ annotation.
  • Extent. Zoom to the traced positions plus a margin, the caustic extent, or both as an inset. Too zoomed out and the scatter is invisible; too zoomed in and the caustic context is lost.
  • Multiple planes. For multi-plane and cluster fits, either one panel per source plane or only the point's own plane.
  • Figure placement. In fit.png for both image and source chi-squared, or a separate fit_source_plane.png toggled by config.
  • Re-render set. point_source_image_chi_squared, point_source_source_chi_squared and cluster in autolens_visualization.

Prototype findings + recommended defaults (2026-10-21; NOT yet approved — confirm at /start_dev)

Prototypes. /mnt/c/Users/Jammy/Science/scratch/eyes/autolens/source_plane_prototype/ (19 PNGs; producer in producer/). The best views are S3_fit_mockup_image_chi_perturbed_RE.png and S3_fit_mockup_source_chi_truth.png.

Recommended design. fit.png gets a second panel, "Fit Source Plane (point_0)", for every positions fit (image- and source-χ²):

  • Zoom: the traced observed positions plus the model source centre, with a 30% margin.
  • Inset: the full caustic in the emptiest corner, with a box marking the zoom.
  • Traced positions: numbered black dots.
  • Model source centre: red ★.
  • Noise ellipse: an orange A·σ ellipse on every traced point (the honest propagated noise).
  • Noise circle: the σ/|μ| purple circle as well, but only when the fit uses weighting="magnification".
  • χ² box: the fit's χ², plus the Jacobian χ².

Other recommendations:

  • Move the source-χ² "Model (source plane)" ✕ off the image-plane panel into this one.
  • Number images 1–N to match the PointSolver figure (the prototype used 0–N−1).
  • No model-image markers for image-χ² fits (they all land on the ★).
  • Absolute arcsec ticks, with an apply_extent precision fix: at mas zoom its 2-sig-fig rounding collapses all ticks to one value ("1.2″" ×3 on cluster point_1).
  • Cluster inset frames only the tangential caustic.
  • With fluxes, fit.png becomes 1×3.
  • Multi-plane: the point's own plane (LensCalc.from_tracer(..., plane_j=fit.plane_index) works today for caustics). This pairs with the critical-curve redshift bug and the cluster pass.

Related. The default-weighting question is filed separately as draft/bug/autolens/fitpositionssource_default_magnification_weighti.md (check against Gravity.jl).

Side note (uninvestigated). At truth, the image-pair point_source model solves 5 images for 4 observed.

Human approval (2026-10-21)

Points 1–6 and all of the recommendations above are APPROVED.

Additional binding principle: pair each figure to its Fit class.

  • Image-plane χ² fits (FitPositionsImagePair / PairRepeat / PairAll / …): the source-plane panel is context only (traced positions, model source ★, caustic, inset). Draw nothing that looks like a χ²: no noise circles or ellipses, no χ² box. Subtitle e.g. "Image-plane χ² — traced positions for context".
  • Source-plane χ² fits: clearly indicate WHICH source-plane χ².
    • The subtitle names it, e.g. "Source-plane χ² (magnification weighting)" or "(jacobian weighting)".
    • The footprint the χ² actually uses is primary: the σ/|μ| circle for magnification, the A·σ ellipse for jacobian.
    • Under magnification weighting, the A·σ ellipse is also shown, faint or dashed, as "propagated noise (reference)" (approved point 1).
    • Free-centre and solved-β* (FitPositionsSourceSolved) fits use visibly different centre markers (★ vs ◆), with legend text naming them.
    • The χ² box appears only on source-plane fits.
  • Enumerate every positions Fit class in autolens/point/fit/positions/ and map each to one of these presentations, covered by tests.

Activity

  1. Jammy2211 commented on Oct 21, 2026

    @Jammy2211
    CollaboratorAuthor

    PRs open (merge in order; human /prm)

    1. fix: adaptive tick significant figures so apply_extent ticks never collapse PyAutoArray#653 — adaptive tick significant figures (apply_extent ticks never collapse)
    2. feat: source-plane fit panel paired to each positions Fit class #790 — Fit Source Plane panel paired to each positions Fit class
    3. render: point-source fit.png with the Fit Source Plane panel autolens_visualization#13 — re-rendered point-source fit.png (lint red until 1+2 merge)

    Tests: test_autoarray 2184 passed; test_autolens 902 passed. Heart YELLOW (pre-existing, acknowledged).
    Per-class scratch renders: /mnt/c/Users/Jammy/Science/scratch/eyes/autolens/source_plane_fit_classes/{truth,perturbed_RE}//fit.png

    🤖 Generated with Claude Code

  2. Jammy2211 commented on Oct 21, 2026

    @Jammy2211
    CollaboratorAuthor

    Shipped. Merged via /prm on 2026-10-21 in order PyAutoArray#653 → PyAutoLens#790 → autolens_visualization#13. Every CI leg was green; #13's lint was re-run against the merged library mains.

    • PyAutoArray#653 (d99ec2b30), pending release: _round_ticks adds significant figures so ticks never collapse to identical labels.
    • PyAutoLens#790 (826040c), pending release:
      • fit.png gains a "Fit Source Plane" panel matched to each Fit class.
      • Image-plane χ² fits show context only. Source-plane χ² fits show the noise their χ² uses (σ/|μ| circles, or A·σ ellipses for jacobian), plus a dashed A·σ reference under magnification weighting.
      • ★ marks a free source centre and ◆ a solved β*.
      • One χ², the fit's own, appears in the legend. Fit-type cues are carried by the legend only; there are no subtitles.
      • PairAll residual lines are dashed and labelled "Residual (nearest, soft pairing)".
      • Image numbering 1..N is shared with the PointSolver figure.
    • autolens_visualization#13 (279ece6c): re-rendered point_source_* and cluster fit.png.
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