Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion autolens/analysis/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
)
from autolens.lens.tracer import Tracer
from autolens.point.solver import PointSolver
from autoconf.test_mode import skip_checks
from autoconf.test_mode import is_test_mode, skip_checks

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -301,6 +301,19 @@ def positions_likelihood_from(
system is being analysed where the specific plane via its redshift is required to define whihch source
galaxy is used to compute the multiple images.

Notes
-----
Test-mode safeguard (``PYAUTO_TEST_MODE``): integration tests intentionally fit
random / unphysical mass models and the resulting tracer often back-traces to
zero, NaN, or inf image-plane positions. Computing a position threshold from
such positions raises ``ValueError: zero-size array to reduction operation
fmax`` (or propagates NaN) inside ``positions_threshold_from``. When test mode
is active and the resolved positions are empty, contain NaN, or contain inf,
we substitute the synthetic pair ``[(1.0, 0.0), (-1.0, 0.0)]`` so the threshold
and ``PositionsLH`` still build cleanly and the script runs end-to-end.
Outside test mode this branch is never taken — bad positions still surface as
the original error, so production fits are not silently masked.

Returns
-------
The `PositionsLH` object used to apply a likelihood penalty or resample the positions.
Expand Down Expand Up @@ -330,6 +343,15 @@ def positions_likelihood_from(
np.asarray(positions.array if hasattr(positions, "array") else positions)
)

if is_test_mode():
arr = positions.array
if arr.shape[0] < 2 or np.isnan(arr).any() or np.isinf(arr).any():
logger.warning(
"positions_likelihood_from: empty/NaN/inf positions in PYAUTO_TEST_MODE — "
"substituting synthetic fallback [(1.0, 0.0), (-1.0, 0.0)]."
)
positions = aa.Grid2DIrregular(values=[(1.0, 0.0), (-1.0, 0.0)])

threshold = self.positions_threshold_from(
factor=factor,
minimum_threshold=minimum_threshold,
Expand Down
16 changes: 16 additions & 0 deletions autolens/point/solver/point_solver.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
default but can be retained for use inside a ``jax.jit``-traced function.
"""
import logging
import os
from typing import Tuple, Optional

import numpy as np
Expand Down Expand Up @@ -73,7 +74,22 @@ def solve(
-------
A ``Grid2DIrregular`` of image-plane coordinates, always numpy-backed even when the
solver uses a JAX backend internally.

Notes
-----
Smoke-test short-circuit (``PYAUTO_SMALL_DATASETS``): the triangle-tiling solve
is the dominant cost in many simulator scripts and is meaningless on the
downsized grids used for fast smoke tests. When ``PYAUTO_SMALL_DATASETS=1`` is
set the solver returns the fixed pair ``[(1.0, 0.0), (0.0, 1.0)]`` immediately,
skipping ``solve_triangles`` entirely. The two coordinates are well separated
so any downstream ``positions_likelihood_from`` / threshold calculation behaves
normally. ``PYAUTO_SMALL_DATASETS`` is a smoke-test-only flag and is never set
inside a ``jax.jit`` trace, so a plain numpy-backed ``Grid2DIrregular`` is safe
here even when the surrounding analysis uses ``xp=jnp``.
"""
if os.environ.get("PYAUTO_SMALL_DATASETS") == "1":
return aa.Grid2DIrregular(values=[(1.0, 0.0), (0.0, 1.0)])

kept_triangles = super().solve_triangles(
tracer=tracer,
shape=Point(*source_plane_coordinate),
Expand Down
32 changes: 32 additions & 0 deletions test_autolens/analysis/test_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,38 @@ def test__positions_likelihood_from(analysis_imaging_7x7):
assert positions_likelihood.threshold == pytest.approx(0.2, 1.0e-4)


def test__positions_likelihood_from__test_mode_fallback(
monkeypatch, analysis_imaging_7x7,
):
monkeypatch.setenv("PYAUTO_TEST_MODE", "2")

tracer = al.Tracer(
galaxies=[
al.Galaxy(
redshift=0.5,
mass=al.mp.Isothermal(
centre=(0.1, 0.0), einstein_radius=1.0, ell_comps=(0.0, 0.0)
),
),
al.Galaxy(redshift=1.0, bulge=al.lp.SersicSph(centre=(0.0, 0.0))),
]
)

samples_summary = al.m.MockSamplesSummary(max_log_likelihood_instance=tracer)
result = res.Result(samples_summary=samples_summary, analysis=analysis_imaging_7x7)

empty_positions = al.Grid2DIrregular(np.empty((0, 2)))

positions_likelihood = result.positions_likelihood_from(
factor=0.1, minimum_threshold=0.2, positions=empty_positions
)

assert isinstance(positions_likelihood, al.PositionsLH)
assert len(positions_likelihood.positions) == 2
assert positions_likelihood.positions[0] == pytest.approx((1.0, 0.0))
assert positions_likelihood.positions[1] == pytest.approx((-1.0, 0.0))


def test__positions_likelihood_from__mass_centre_radial_distance_min(
analysis_imaging_7x7,
):
Expand Down
Loading