Skip to content

Missing input validation across light & mass profiles #440

@rhayes777

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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions