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
15 changes: 15 additions & 0 deletions autolens/imaging/plot/fit_imaging_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,22 @@ def _compute_critical_curve_lines(tracer, grid):
["white"] * len(_tan_ca_lines) + ["yellow"] * len(_rad_ca_lines)
)
return image_plane_lines, image_plane_line_colors, source_plane_lines, source_plane_line_colors
except (ModuleNotFoundError, ValueError):
# ModuleNotFoundError: jax_zero_contour missing — already warned upstream in
# plot_utils._critical_curves_method().
# ValueError: no zero crossings in the eigenvalue grid (e.g. slope >= 2
# isothermal where lambda_r > 0 everywhere). Curves don't exist for this
# model, so rendering without overlays is correct.
return None, None, None, None
except Exception:
# Anything else — log loudly with traceback so the next regression of the
# "ZeroSolver raised inside model-fit, viz fell back to all-zero" failure
# mode (PyAutoGalaxy abd7b717, PyAutoFit #1280) does not stay silent.
logger.warning(
"Critical-curve computation failed unexpectedly; rendering without "
"overlays. Investigate — this used to be a silent fallback.",
exc_info=True,
)
return None, None, None, None


Expand Down
58 changes: 58 additions & 0 deletions test_autolens/imaging/plot/test_fit_imaging_plots.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import logging
from pathlib import Path

import pytest

from autolens.imaging.plot import fit_imaging_plots
from autolens.imaging.plot.fit_imaging_plots import (
_compute_critical_curve_lines,
subplot_fit,
subplot_fit_log10,
subplot_fit_x1_plane,
Expand Down Expand Up @@ -156,3 +159,58 @@ def test__subplot_fit_combined_log10__list_of_two_fits__output_file_created(
output_format="png",
)
assert str(plot_path / "fit_combined_log10.png") in plot_patch.paths


@pytest.mark.parametrize(
"exc_cls",
[ModuleNotFoundError, ValueError],
ids=["jax_zero_contour_missing", "no_zero_crossings"],
)
def test__compute_critical_curve_lines__known_recoverable_exceptions__silent(
monkeypatch, caplog, exc_cls
):
"""
Two failure modes are expected and pre-handled upstream: ``jax_zero_contour``
not installed (``ModuleNotFoundError``) and a model with no zero crossings
(``ValueError`` raised by ``_init_guess_from_coarse_grid``). These must
fall through silently — no WARNING log — so plot-time noise stays clean
when the absence of critical curves is the correct rendering.
"""
def boom(*args, **kwargs):
raise exc_cls("synthetic failure for test")

monkeypatch.setattr(fit_imaging_plots, "_critical_curves_from", boom)

with caplog.at_level(logging.WARNING, logger=fit_imaging_plots.__name__):
result = _compute_critical_curve_lines(tracer=None, grid=None)

assert result == (None, None, None, None)
assert caplog.records == [], (
"known-recoverable failure must not emit a WARNING log"
)


def test__compute_critical_curve_lines__unexpected_exception__logs_warning(
monkeypatch, caplog
):
"""
Anything OTHER than ``ModuleNotFoundError`` / ``ValueError`` is treated as
an unexpected failure (the silent failure mode that caused the
2026-04-19 PyAutoGalaxy zero_contour revert and the 2026-05-16 Euclid
pipeline regression). Such failures must surface as a WARNING log with
a traceback — never silently swallowed.
"""
def boom(*args, **kwargs):
raise RuntimeError("synthetic unexpected failure for test")

monkeypatch.setattr(fit_imaging_plots, "_critical_curves_from", boom)

with caplog.at_level(logging.WARNING, logger=fit_imaging_plots.__name__):
result = _compute_critical_curve_lines(tracer=None, grid=None)

assert result == (None, None, None, None)
assert len(caplog.records) == 1
record = caplog.records[0]
assert record.levelno == logging.WARNING
assert record.exc_info is not None, "traceback must be attached"
assert isinstance(record.exc_info[1], RuntimeError)
Loading