Skip to content

Commit 88eb46b

Browse files
Jammy2211Jammy2211claude
authored
fix: skip the JAX-only sparse-operator tests where jax is unavailable (#658)
unit_tests (3.9, PyAutoLens) and (3.10, PyAutoLens) have been red in PyAutoHands/python_matrix with 5 failures, all: ModuleNotFoundError: No module named 'jax' .../inversion_interferometer_util.py:654: in from_nufft_precision_operator import jax.numpy as jnp reached via Interferometer.apply_sparse_operator (dataset.py:280). The whole sparse-operator subsystem is JAX-only by design — InterferometerSparseOperator builds its FFT kernel with jax.numpy and projects with jax.ops.segment_sum / jax.lax, and the imaging counterpart even types a field as 'jax.Array'. There is no NumPy equivalent, and autonerves[jax] gates jax to Python >= 3.11. So these are JAX-feature tests sitting in matrix legs that have no jax: a test placement problem, not a library bug. Marking exactly the 5 cases that call apply_sparse_operator() with a find_spec-based skipif, matching the pytest.importorskip idiom already used in test_autolens/interop/test_coolest.py. This also restores the standing 'library unit tests are numpy-only' rule for these files: the dense-route cases stay NumPy-only and keep running on 3.9/3.10, which is exactly what those legs exist to prove. Verified both ways: jax present -> 9 passed, 0 skipped jax absent -> 4 passed, 5 skipped (the 5 CI failures, and only those) Co-authored-by: Jammy2211 <JNightingale2211@gmail.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 56dfacf commit 88eb46b

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

test_autolens/potential_correction/test_fit_interferometer.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import importlib.util
2+
13
import numpy as np
24
import pytest
35

@@ -7,6 +9,17 @@
79
FitDpsiSrcInterferometer,
810
)
911

12+
# `apply_sparse_operator` is a JAX-only code path: `InterferometerSparseOperator`
13+
# builds its FFT kernel with `jax.numpy` and projects with `jax.ops.segment_sum`
14+
# / `jax.lax`, with no NumPy equivalent. `autonerves[jax]` gates jax to
15+
# Python >= 3.11, so the sparse-route case cannot run on the 3.9/3.10 matrix
16+
# legs — skip it there rather than fail. The dense-route cases stay NumPy-only
17+
# and run everywhere, which is what those legs exist to prove.
18+
requires_jax = pytest.mark.skipif(
19+
importlib.util.find_spec("jax") is None,
20+
reason="apply_sparse_operator is a JAX-only path; jax requires Python >= 3.11",
21+
)
22+
1023

1124
def fit_from(dataset, use_sparse_operator):
1225
lens = al.Galaxy(
@@ -50,6 +63,7 @@ def test__dense_route__end_to_end_evidence_is_finite(interferometer_7):
5063
)
5164

5265

66+
@requires_jax
5367
def test__sparse_route__matches_dense_route(interferometer_7):
5468
dataset_sparse = interferometer_7.apply_sparse_operator()
5569

test_autolens/potential_correction/test_iterative_interferometer.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
1+
import importlib.util
2+
13
import numpy as np
24
import pytest
35

46
import autoarray as aa
57
import autolens as al
68

9+
# `apply_sparse_operator` is a JAX-only code path: `InterferometerSparseOperator`
10+
# builds its FFT kernel with `jax.numpy` and projects with `jax.ops.segment_sum`
11+
# / `jax.lax`, with no NumPy equivalent. `autonerves[jax]` gates jax to
12+
# Python >= 3.11, so the cases below cannot run on the 3.9/3.10 matrix legs —
13+
# skip them there rather than fail. The dense-route cases stay NumPy-only and
14+
# run everywhere, which is what those legs exist to prove.
15+
requires_jax = pytest.mark.skipif(
16+
importlib.util.find_spec("jax") is None,
17+
reason="apply_sparse_operator is a JAX-only path; jax requires Python >= 3.11",
18+
)
19+
720

821
def iter_fit_from(dataset, gauge_constraints=False, n_iter=2):
922
lens = al.Galaxy(
@@ -33,6 +46,7 @@ def test__requires_sparse_operator(interferometer_7):
3346
iter_fit_from(interferometer_7)
3447

3548

49+
@requires_jax
3650
def test__solve_joint_optimization__finite_state_and_decreasing_cost(
3751
interferometer_7,
3852
):
@@ -56,6 +70,7 @@ def test__solve_joint_optimization__finite_state_and_decreasing_cost(
5670
assert cost_opt < 0.5 * fit.data_weighted_norm
5771

5872

73+
@requires_jax
5974
def test__cost_identity_matches_direct_visibility_chi2(interferometer_7):
6075
"""
6176
The normal-equation chi^2 identity (d^H C^-1 d - 2 x^T D + x^T F x) must
@@ -88,6 +103,7 @@ def test__cost_identity_matches_direct_visibility_chi2(interferometer_7):
88103
assert chi2_half == pytest.approx(chi2_direct, rel=1e-3)
89104

90105

106+
@requires_jax
91107
def test__gauge_constraints_are_satisfied(interferometer_7):
92108
dataset = interferometer_7.apply_sparse_operator()
93109
fit = iter_fit_from(dataset, gauge_constraints=True)
@@ -103,6 +119,7 @@ def test__gauge_constraints_are_satisfied(interferometer_7):
103119
assert G @ dpsi_opt == pytest.approx(np.zeros(3), abs=1.0e-6)
104120

105121

122+
@requires_jax
106123
def test__log_evidence__finite_at_optimum(interferometer_7):
107124
dataset = interferometer_7.apply_sparse_operator()
108125
fit = iter_fit_from(dataset)

0 commit comments

Comments
 (0)