Skip to content

fix: Chameleon potential_2d_from inconsistent with its deflections #682

Closed

Description

@Jammy2211

Overview

mp.Chameleon.potential_2d_from does not match its own deflections: for Chameleon(ell_comps=(0.2,-0.1), intensity=1.0) the gradient of the potential is ~1.57× the deflection (≈1/q), i.e. max|∇ψ − α| ≈ 52% of max|α|. The deflections are correct (div α = 2κ to 4 d.p. everywhere). The potential is wrong: its MGE call uses ellipticity_convention="circularised" (copied from Sersic) while Chameleon's convergence uses the major-axis elliptical radius. Fixing the convention alone still leaves ~0.35% of max|α| (8–11% at r≈3″), so the fix replaces the MGE route with the exact analytic potential.

Plan

  • Replace the MGE potential with the exact analytic potential: the difference of two cored isothermals (Keeton's closed form), reusing the deflections' own psi_from, b and core radii rescaled by 2/(1+q); numpy and JAX.
  • Prototype gives max|∇ψ − α| ≈ 2e-8 (finite-difference noise) for elliptical, spherical and large-core cases.
  • No existing test pins Chameleon potential values, so nothing has to be re-baselined.
  • Add tests: central finite-difference ∇ψ matches α to < 1e-4 of max|α| (elliptical, spherical, large-core); ∇²ψ = 2κ; one spot value.
  • Run the PyAutoGalaxy suite, check the JAX path, smoke-test PyAutoLens downstream.
  • Flagged, not fixed: the class docstring says the second core is s0+s1, but the code uses core_radius_1 directly in all three methods (convergence, deflections and potential). Noted in the PR, not changed.

Tier: judge — merge mode: human /prm

Detailed implementation plan

Affected Repositories

  • PyAutoGalaxy (primary)

Branch Survey

Repository Current Branch Dirty?
./PyAutoGalaxy main clean

Suggested branch: feature/chameleon-analytic-potential

Implementation Steps

  1. autogalaxy/profiles/mass/stellar/chameleon.py — Chameleon.potential_2d_from: keep decorators, drop the MGEDecomposer import. With q = axis_ratio, b = 2ΥI/(1+q), s_i = 2·core_radius_i/(1+q), per component: ψ_s = xα_x + yα_y − b·q·s·ln√((Ψ+s)² + (1−q²)x²) + b·q·s·ln((1+q)s), with α_x = bq/√(1−q²)·atan(√(1−q²)x/(Ψ+s)), α_y = bq/√(1−q²)·atanh(√(1−q²)y/(Ψ+q²s)), Ψ = psi_from. Return ψ_{s0} − ψ_{s1}. Small inner helper per component.
  2. test_autogalaxy/profiles/mass/stellar/test_chameleon.py — gradient-vs-deflection test (3 cases), Laplacian = 2κ test, spot value.
  3. Run PyAutoGalaxy tests; check the xp=jnp path; smoke-test PyAutoLens.

Key Files

  • autogalaxy/profiles/mass/stellar/chameleon.py — potential fix
  • autogalaxy/profiles/mass/total/isothermal.py — psi_from (reused)
  • test_autogalaxy/profiles/mass/stellar/test_chameleon.py — new tests

Original Prompt

Click to expand starting prompt

mp.Chameleon.potential_2d_from is inconsistent with its deflections (~60%)

Type: bug
Target: autogalaxy
Repos:

  • PyAutoGalaxy
    Difficulty: small
    Autonomy: supervised
    Priority: medium
    Status: formalised
    Consequence: judge
    Witness: for an elliptical and a circular ag.mp.Chameleon, the central finite-difference gradient of potential_2d_from matches deflections_yx_2d_from to < 1e-4 of max|alpha| at off-centre points, and lap(psi) = 2 kappa; tests pin it
    Filed: 2026-10-29

Found while fixing PyAutoGalaxy#680/#681 (the lmp.Gaussian potential was wrong: its gradient did not reproduce its deflections). Same check on main 2026-10-29: Sersic (MGE potential) agrees to ~1e-3 of |alpha| (MGE accuracy, fine); Chameleon(ell_comps=(0.2,-0.1), intensity=1.0) gives max|grad psi - alpha| = 6.4e-3 with max|alpha| = 1.0e-2 at (0.7,0.3), (-0.5,0.9), (1.2,-1.0). Determine whether the potential (MGE route in autogalaxy/profiles/mass/stellar/chameleon.py) or the deflections are wrong (check div(alpha) = 2 kappa first), then fix the wrong one. A Chameleon is a difference of two cored isothermals, so an analytic potential may exist.

Activity

  1. Jammy2211 commented on Oct 30, 2026

    @Jammy2211
    CollaboratorAuthor

    Library PR Created

    PR: #683 (commit a7b6bdc, label pending-release)

    • PyAutoGalaxy tests: 1459 passed. The new Chameleon tests fail 7/14 on main and pass 14/14 with the fix.
    • Downstream PyAutoLens tests: 1015 passed, 1 xfailed.
    • autolens_workspace_test/scripts/misc/mass/stellar.py self-consistency sweep: 42 PASS / 0 FAIL (Chameleon med 2.7e-05, ChameleonSph 3.1e-05).
    • Workspace impact: none required. One nit: that script's Chameleon block docstring still says "computed via MGE decomposition" (left for a follow-up).
    • Heart: STALE (release validation stale), acknowledged by the human at ship.

    Tier: judge. Awaiting human /prm.

  2. Jammy2211 commented on Oct 30, 2026

    @Jammy2211
    CollaboratorAuthor

    Follow-ups added (human request)

    • PyAutoGalaxy#683 (commit 0b62e62):
      • Chameleon.axis_ratio (mass + light) now uses xp.where instead of a Python if, and lp.Chameleon.image_2d_from now passes xp through. Chameleon deflections, potential, convergence and light image now work under jax.jit (traced ell_comps) and match numpy to ~3e-16.
      • The docstrings now state the implemented convergence (second core = core_radius_1, not s0+s1). Decision taken, flagged in the PR: the parametrisation is unchanged.
      • Full suite: 1461 passed.
    • autolens_workspace_test#350: stale "computed via MGE decomposition" comment fixed. Merge after fix: analytic Chameleon potential + jit-safe Chameleon profiles #683.

    Tier: judge. Awaiting human /prm (library first).

  3. Jammy2211 commented on Oct 30, 2026

    @Jammy2211
    CollaboratorAuthor

    Shipped

    CI green on every leg (unittest 3.12/3.13/nojax, docs, smoke 3.12/3.13).

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