Skip to content

Sparse interferometer inversion: support linear func lists and multiple mappers - #500

Merged
Jammy2211 merged 2 commits into
mainfrom
feature/interferometer-sparse-func-list
Aug 28, 2026
Merged

Jammy2211 merged 2 commits into
mainfrom
feature/interferometer-sparse-func-list

Conversation

@Jammy2211

Copy link
Copy Markdown
Collaborator

Summary

InversionInterferometerSparse now supports an AbstractLinearObjFuncList (e.g. linear light profiles) fitted simultaneously with one or more Mappers, matching what InversionImagingSparse already does. Previously curvature_matrix returned only the first mapper's diagonal block; since the factory routes any list containing a mapper to the sparse class whenever dataset.sparse_operator is set, a mixed list silently dropped every linear-function and cross-mapper term from F.

Every block of F is now built with the same operator W~ = Re(Fᴴ W F) applied by InterferometerSparseOperator on the extent grid: mapper–mapper diagonal (A_iᵀ W~ A_i, unchanged), mapper–mapper off-diagonal (A_iᵀ W~ A_j), mapper–function (A_iᵀ W~ B_k) and function–function (B_kᵀ W~ B_l). Because W~ already contains the inverse-variance weighting, linear-function columns are passed un-weighted (unlike the imaging operator, which is split as Hᵀ N⁻¹ H). The data_vector = Lᵀ d~ expression already covered linear functions exactly and is unchanged.

Also applies no_regularization_add_to_curvature_diag_value as the dense interferometer path does, and fixes __init__ overwriting the parent's settings or Settings() with None when no settings were passed.

Closes #499 (reported by @HRSAstro).

API Changes

Purely additive. Four new methods on InterferometerSparseOperator and func-list / multi-mapper support in InversionInterferometerSparse.curvature_matrix. The single-mapper sparse path is bit-identical to before. One behaviour change: an unregularized mapper in a sparse interferometer inversion now gets the no_regularization_add_to_curvature_diag_value diagonal add (0.001), as the dense path always did.
See full details below.

Test Plan

  • pytest test_autoarray/inversion — 377 passed (368 before; 9 new)
  • pytest test_autoarray — 1246 passed
  • Parity vs InversionInterferometerMapping (7x7 mask, Delaunay, TransformerDFT): func+mapper, mapper+func, two mappers, func+two mappers — curvature_matrix / data_vector max rel err ~6e-16 with unit noise; with a non-uniform noise map the residual (1.2e-9) equals the pre-existing single-mapper baseline, i.e. it is the operator's numerics, not the new blocks.
  • JAX (xp=jnp) path bit-identical to NumPy on all multi-object cases
  • Downstream: PyAutoGalaxy -k "interferometer or inversion" 68 passed; PyAutoLens 65 passed
Full API Changes (for automation & release notes)

Added

  • InterferometerSparseOperator.curvature_matrix_off_diag_from(rows0, cols0, vals0, rows1, cols1, vals1, *, S0, S1) — mapper–mapper off-diagonal block A0ᵀ W~ A1
  • InterferometerSparseOperator.curvature_matrix_off_diag_func_list_from(curvature_weights, extent_index_for_masked_pixel, rows, cols, vals, *, S) — mapper–function block Aᵀ W~ B
  • InterferometerSparseOperator.curvature_matrix_func_list_from(curvature_weights_0, curvature_weights_1, extent_index_for_masked_pixel) — function–function block B0ᵀ W~ B1
  • InterferometerSparseOperator.operated_matrix_slim_from(matrix_slim, extent_index_for_masked_pixel) — scatter slim → extent, apply W~, gather back
  • InversionInterferometerSparse._sparse_triplets_curvature_from, _curvature_matrix_mapper_diag, _curvature_matrix_off_diag_from, _curvature_matrix_multi_mapper, _curvature_matrix_func_list_and_mapper (private)

Changed Behaviour

  • InversionInterferometerSparse.curvature_matrix — now correct for any mix of AbstractLinearObjFuncList and Mapper objects; previously returned only the first mapper's block. Applies settings.no_regularization_add_to_curvature_diag_value to unregularized linear objects (matches InversionInterferometerMapping).
  • InversionInterferometerSparse.__init__ — no longer overwrites self.settings with None when settings is not passed.

Still unsupported

  • A linear object with an operated_mapping_matrix_override (visibility-space) still raises InversionException on the sparse path, as before.

Generated by the PyAutoLabs agent workflow.

🤖 Generated with Claude Code

https://claude.ai/code/session_012JM45sA4YGEUw6KYW8Pm96

…le mappers

`InversionInterferometerSparse.curvature_matrix` previously returned the
single-mapper diagonal block only. A mixed `[AbstractLinearObjFuncList, Mapper]`
list (or several mappers) with a sparse operator attached was still routed to
the sparse class by the factory, so the linear-function and cross-mapper terms
were silently dropped from F. This gives the interferometer sparse path parity
with `InversionImagingSparse`.

- `InterferometerSparseOperator`: add `curvature_matrix_off_diag_from`
  (A0ᵀ W~ A1), `curvature_matrix_off_diag_func_list_from` (Aᵀ W~ B),
  `curvature_matrix_func_list_from` (B0ᵀ W~ B1) and the
  `operated_matrix_slim_from` helper. Every block is formed with the same
  W~ = Re(Fᴴ W F) operator; because W~ already contains the inverse-variance
  weighting, func-list columns are passed un-weighted (unlike imaging).
- `InversionInterferometerSparse`: dispatch `curvature_matrix` over
  single-mapper (unchanged, bit-identical) / multi-mapper / func-list+mapper
  paths, mirror the upper blocks, and apply
  `no_regularization_add_to_curvature_diag_value` as the dense path does.
  `data_vector = Lᵀ d~` already covered func lists and is unchanged.
- Fix `__init__` overwriting the parent's `settings or Settings()` with `None`.
- Tests: parity vs `InversionInterferometerMapping` for func+mapper, two
  mappers, func+two mappers (max rel err ~6e-16 in curvature_matrix and
  data_vector); operator unit tests for each new method.

Closes #499

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012JM45sA4YGEUw6KYW8Pm96
The four new operator tests call methods that import jax internally, so
the unittest-nojax leg failed with ModuleNotFoundError. Guard each with
pytest.importorskip("jax"), matching test_kernel_jax_gradients.py.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012JM45sA4YGEUw6KYW8Pm96
@Jammy2211

Copy link
Copy Markdown
Collaborator Author

Workspace PRs (library-first gate — merge after this PR): PyAutoLabs/autolens_workspace_test#283, PyAutoLabs/autogalaxy_workspace_test#115

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sparse interferometer inversion to combine linear function lists with a Mapper

1 participant