Repository navigation
Description
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,band 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_1directly 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
autogalaxy/profiles/mass/stellar/chameleon.py—Chameleon.potential_2d_from: keep decorators, drop theMGEDecomposerimport. 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.test_autogalaxy/profiles/mass/stellar/test_chameleon.py— gradient-vs-deflection test (3 cases), Laplacian = 2κ test, spot value.- Run PyAutoGalaxy tests; check the xp=jnp path; smoke-test PyAutoLens.
Key Files
autogalaxy/profiles/mass/stellar/chameleon.py— potential fixautogalaxy/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 circularag.mp.Chameleon, the central finite-difference gradient ofpotential_2d_frommatchesdeflections_yx_2d_fromto < 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
Jammy2211 commentedon Oct 30, 2026
Library PR Created
PR: #683 (commit a7b6bdc, label pending-release)
autolens_workspace_test/scripts/misc/mass/stellar.pyself-consistency sweep: 42 PASS / 0 FAIL (Chameleon med 2.7e-05, ChameleonSph 3.1e-05).Tier: judge. Awaiting human /prm.
Jammy2211 commentedon Oct 30, 2026
Follow-ups added (human request)
Chameleon.axis_ratio(mass + light) now usesxp.whereinstead of a Pythonif, andlp.Chameleon.image_2d_fromnow passesxpthrough. Chameleon deflections, potential, convergence and light image now work underjax.jit(tracedell_comps) and match numpy to ~3e-16.core_radius_1, not s0+s1). Decision taken, flagged in the PR: the parametrisation is unchanged.Tier: judge. Awaiting human /prm (library first).
Jammy2211 commentedon Oct 30, 2026
Shipped
jax.jit, and the docstrings match the implemented convergence. Pending release.CI green on every leg (unittest 3.12/3.13/nojax, docs, smoke 3.12/3.13).