Sparse interferometer inversion: support linear func lists and multiple mappers - #500
Merged
Merged
Conversation
…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
Collaborator
Author
|
Workspace PRs (library-first gate — merge after this PR): PyAutoLabs/autolens_workspace_test#283, PyAutoLabs/autogalaxy_workspace_test#115 |
This was referenced Aug 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
InversionInterferometerSparsenow supports anAbstractLinearObjFuncList(e.g. linear light profiles) fitted simultaneously with one or moreMappers, matching whatInversionImagingSparsealready does. Previouslycurvature_matrixreturned only the first mapper's diagonal block; since the factory routes any list containing a mapper to the sparse class wheneverdataset.sparse_operatoris set, a mixed list silently dropped every linear-function and cross-mapper term fromF.Every block of
Fis now built with the same operatorW~ = Re(Fᴴ W F)applied byInterferometerSparseOperatoron 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). BecauseW~already contains the inverse-variance weighting, linear-function columns are passed un-weighted (unlike the imaging operator, which is split asHᵀ N⁻¹ H). Thedata_vector = Lᵀ d~expression already covered linear functions exactly and is unchanged.Also applies
no_regularization_add_to_curvature_diag_valueas the dense interferometer path does, and fixes__init__overwriting the parent'ssettings or Settings()withNonewhen no settings were passed.Closes #499 (reported by @HRSAstro).
API Changes
Purely additive. Four new methods on
InterferometerSparseOperatorand func-list / multi-mapper support inInversionInterferometerSparse.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 theno_regularization_add_to_curvature_diag_valuediagonal 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 passedInversionInterferometerMapping(7x7 mask, Delaunay,TransformerDFT): func+mapper, mapper+func, two mappers, func+two mappers —curvature_matrix/data_vectormax 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.xp=jnp) path bit-identical to NumPy on all multi-object cases-k "interferometer or inversion"68 passed; PyAutoLens 65 passedFull 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 blockA0ᵀ W~ A1InterferometerSparseOperator.curvature_matrix_off_diag_func_list_from(curvature_weights, extent_index_for_masked_pixel, rows, cols, vals, *, S)— mapper–function blockAᵀ W~ BInterferometerSparseOperator.curvature_matrix_func_list_from(curvature_weights_0, curvature_weights_1, extent_index_for_masked_pixel)— function–function blockB0ᵀ W~ B1InterferometerSparseOperator.operated_matrix_slim_from(matrix_slim, extent_index_for_masked_pixel)— scatter slim → extent, applyW~, gather backInversionInterferometerSparse._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 ofAbstractLinearObjFuncListandMapperobjects; previously returned only the first mapper's block. Appliessettings.no_regularization_add_to_curvature_diag_valueto unregularized linear objects (matchesInversionInterferometerMapping).InversionInterferometerSparse.__init__— no longer overwritesself.settingswithNonewhensettingsis not passed.Still unsupported
operated_mapping_matrix_override(visibility-space) still raisesInversionExceptionon the sparse path, as before.Generated by the PyAutoLabs agent workflow.
🤖 Generated with Claude Code
https://claude.ai/code/session_012JM45sA4YGEUw6KYW8Pm96