feat: analytically-solved point-source likelihood variants (#657) - #659
Merged
Conversation
FitPositionsSourceSolved (tensor-weighted, marginalized centre; Lombardi 2024 arXiv:2406.15280 §5.1), FitPositionsImagePairAllSolved / FitPositionsImagePairRepeatSolved (solved centre driving the existing PointSolver forward solve), FitFluxesSolved (analytic flux, flux-space, magnification-first), FitTimeDelaysSolved (analytic reference time); SolvedCentre mixin; fit_flux_cls / fit_time_delays_cls hooks; pytree registration incl. FitPositionsSource; informative mismatch errors; docstring truth sweep. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tches, kwarg order, test gaps - FitPositionsSourceSolved.noise_normalization now uses the observed-plane det(Theta_i) (model-independent; Lombardi Eq. 46), not det(W_i) which spuriously favoured high-magnification models. - New exc.PointProfileMismatchException (NOT a PointExtractionException subclass) for profile/fit mismatches, so FitPointDataset's component-skip handlers can no longer swallow them; regression test through FitPointDataset added. - fit_flux_cls / fit_time_delays_cls moved to the end of the FitPointDataset / AnalysisPoint signatures — positional callers unbroken. - Tests: RecordingMockSolver asserts beta* is actually forwarded to the solver; flux/time marginalization + normalization constants pinned to closed forms. - Solved source-plane path verified numpy==jax under vmap+jit (-94.70750993 both backends on the workspace_test harness). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Jul 30, 2026
Collaborator
Author
3 tasks
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
Implements the analytically-solved point-source likelihood variants designed in #657 (phase 2 of 5; Lombardi 2024, arXiv:2406.15280). Point-source models no longer need to sample a source-plane centre (y,x) — or a flux, or a reference time — as non-linear free parameters: paired with the new zero-parameter
al.ps.PointSolvedprofile, the*Solvedfit classes solve them in closed form each likelihood call. The source-plane variant uses the paper's linearized likelihood with full Jacobian-tensor noise weighting (exact per-eigendirection stretch weighting; the traditional scalarµ²/σ²remains available asweighting="magnification") plus the analytic marginalization determinant term. The solved image-plane variants (all-to-all and pair-repeat) feed the solved centre into the existingPointSolverforward solve — an extension in the spirit of glafic's source-position optimization, not a paper result. Also: pluggablefit_flux_cls/fit_time_delays_clshooks (previously hard-wired), pytree registration for the new classes andFitPositionsSource, informative errors replacing bareAttributeErroron profile/fit mismatches, and a truth sweep of five docstrings that claimed an unimplemented "barycenter" option.API Changes
All additions — existing classes, defaults, and behaviour are unchanged. Five new fit classes (
FitPositionsSourceSolved,FitPositionsImagePairAllSolved,FitPositionsImagePairRepeatSolved,FitFluxesSolved,FitTimeDelaysSolved), theSolvedCentremixin, and two new optional keywords (fit_flux_cls,fit_time_delays_cls) onFitPointDataset/AnalysisPoint. Invalid profile×fit pairings now raise informativePointExtractionExceptions instead of bareAttributeErrors.See full details below.
Test Plan
pytest test_autolens/point/(85 passed locally) and fullpytest test_autolens/(473 passed locally)PairAllpermutation-count penalty regression; loud-failure matrix over{Point, PointFlux, PointSolved}× fit classesFull API Changes (for automation & release notes)
Added
al.FitPositionsSourceSolved— source-plane chi-squared with analytically-solved centre (Lombardi 2024 §5.1); class attributeweighting = "jacobian"(default, exact tensor) or"magnification"(traditional scalarµ²/σ²); includes the analytic marginalization term-0.5*log(det(ΣWᵢ)/(2π)²).al.FitPositionsImagePairAllSolved,al.FitPositionsImagePairRepeatSolved— existing image-plane chi-squareds driven by the solved centre (glafic-style extension).al.FitFluxesSolved— flux solved in closed form (F* = Σµᵢf̂ᵢ/σᵢ² / Σµᵢ²/σᵢ², magnification-first flux space); works withPointorPointSolved; raises onPointFlux(its flux prior would be silently ignored).al.FitTimeDelaysSolved— precision-weighted analytic reference timeT*(alternative to the min-subtraction inFitTimeDelays, which is unchanged).autolens.point.fit.solved.SolvedCentremixin +precision_tensor_components_from— the shared β* linear algebra.FitPointDataset(..., fit_flux_cls=FitFluxes, fit_time_delays_cls=FitTimeDelays)and the same onAnalysisPoint— previously hard-wired; defaults preserve current behaviour exactly.FitPositionsSource.Changed Behaviour
PointExtractionExceptions naming the fix (e.g. centre-bearing profile ×*Solvedfit; profile withoutcentre× centre-requiring fit;PointFlux×FitFluxesSolved), instead of bareAttributeErrors.FitPositionsSource's "common centroid" wording corrected (the reference point is the profilecentre, orβ*in the Solved class).Migration
point_0 = af.Model(al.ps.PointSolved)(0 free parameters) +al.AnalysisPoint(..., fit_positions_cls=al.FitPositionsSourceSolved)(or anImagePair*Solvedclass; addfit_flux_cls=al.FitFluxesSolved/fit_time_delays_cls=al.FitTimeDelaysSolvedfor datasets with fluxes/delays).Depends on the companion PyAutoArray PR (xp threading through
Grid2DIrregular.grid_2d_via_deflection_grid_from) and PyAutoGalaxy PR (ag.ps.PointSolved) on the same branch name — merge those first.Closes nothing on merge — #657 stays open for phases 3–5 (workspace/profiling examples, guides, JAX gradients).
Generated by the PyAutoLabs agent workflow.