Skip to content

Missing input validation across light & mass profiles #440

Description

@rhayes777

Title: Missing input validation across light & mass profiles

Repo: Jammy2211/PyAutoGalaxy

Tag: @Jammy2211


Four small validation gaps in lp.* / mp.* constructors. Each turns a clear
"invalid parameter" into a numba / NumPy traceback. Found while auditing
autogalaxy == 2026.5.21.1.

B9. NFW(scale_radius=0) produces an all-NaN deflection field

import autolens as al, numpy as np
grid = al.Grid2D.uniform(shape_native=(40, 40), pixel_scales=0.05)
m = al.mp.NFW(centre=(0, 0), kappa_s=0.1, scale_radius=0.0)
defl = m.deflections_yx_2d_from(grid=grid)
np.isnan(np.array(defl)).sum()    # 3200 (= 40 × 40 × 2)

B10. Isothermal(ell_comps=(0, 0))IsothermalSph numerically

grid = al.Grid2D.uniform(shape_native=(20, 20), pixel_scales=0.05)
ell  = al.mp.Isothermal(centre=(0, 0), ell_comps=(0.0, 0.0), einstein_radius=1.0)
sph  = al.mp.IsothermalSph(centre=(0, 0), einstein_radius=1.0)
diff = np.abs(
    np.array(ell.deflections_yx_2d_from(grid=grid))
    - np.array(sph.deflections_yx_2d_from(grid=grid))
).max()
# 2.357e-06

They're analytically identical; presumably the Ell form goes through a
slightly different evaluation path even at the degenerate point. Not
load-bearing for science, but worth a regression unit test.

B11. Sersic(sersic_index=0) raises ZeroDivisionError

al.lp.Sersic(intensity=1.0, effective_radius=0.5, sersic_index=0.0)\
    .image_2d_from(grid=grid)
# ZeroDivisionError: float division by zero (from deep in the profile)

Rather than a ValueError("sersic_index must be > 0") from the constructor.

B12. |ell_comps| > 1 silently accepted on light profiles

al.lp.Sersic(centre=(0, 0), ell_comps=(2.0, 0.0),
             intensity=1.0, effective_radius=0.5, sersic_index=4
).image_2d_from(grid=grid)
# returns a finite, non-physical image

e1**2 + e2**2 < 1 is the definition of a valid axis ratio; outside that
range the underlying $q$ is undefined.

Suggested fix shape

Either a shared _validate_ell_comps() helper called from every elliptical
profile constructor, or a slot-level @field_validator if the profiles are
already attrs / pydantic dataclasses. For Sersic.sersic_index and
NFW.scale_radius, a plain if value <= 0: guard.

Environment

  • autogalaxy == 2026.5.21.1, Python 3.12.8.

Full repro at work/edge_case_tests/02_profiles.py and
work/edge_case_tests/10_final_edges.py in the audit workspace.

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