fix: total_source_flux_mujy wrong value for linear light profiles#536
Merged
Conversation
For fits using linear light profiles (any lp_linear.* or MGE basis), `fit.tracer.galaxies[-1]` carries unsolved profiles — image_2d_from returns zeros because the linear intensities are filled in by the inversion at fit time, not propagated back into the source-plane profile objects. The library's `total_source_flux_mujy` therefore returned wrong values for any linear-profile fit, and `magnification` inherited the bug via its source-flux denominator. Read from `fit.tracer_linear_light_profiles_to_light_profiles` instead: the property invokes `append_linear_light_profiles_to_model(...)` which rebuilds the tracer with intensities filled in from the inversion's `linear_light_profile_intensity_dict` (already cached as a side-effect of computing figure_of_merit). For non-linear fits the property short-circuits to `self.model_obj` (== `fit.tracer`), so the change is a no-op pass-through and existing tests using `al.lp.Sersic(intensity=...)` continue to pass. Empirical proof this is JIT-safe: euclid_strong_lens_modeling_pipeline uses this exact pattern (util.py:378) inside `compute_latent_variables` under `LATENT_BATCH_MODE = "jit"`. Add a regression test that builds a fit fixture where the un-solved tracer returns zeros and the converted tracer returns a non-zero image, asserting the function reads from the converted one. Existing `total_source_flux_mujy` / `magnification` fixtures gain the new attribute for the no-op pass-through path. Discovered while planning #17 (Euclid pipeline migration); fix unblocks that work. Refs: #535
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
total_source_flux_mujy(shipped in #534) returns wrong values for fits using linear light profiles (anylp_linear.*or MGE basis). For linear profilesfit.tracer.galaxies[-1]carries unsolved profiles —image_2d_fromreturns zeros because intensities are filled by the inversion at fit time, not propagated back into the source-plane profile objects.magnificationinherits the bug via its source-flux denominator.Fix: read from
fit.tracer_linear_light_profiles_to_light_profiles(which rebuilds the tracer with intensities filled in from the inversion). For non-linear fits this property short-circuits toself.model_obj— pure no-op pass-through, no behaviour change.Discovered while planning the Euclid pipeline migration (PyAutoLabs/euclid_strong_lens_modeling_pipeline#17). Euclid had already coded the workaround locally at
util.py:378— this PR lifts it into the library so other lens projects with linear profiles get correct values without each one re-discovering the issue.Closes #535.
API Changes
None — internal change only. Function signatures, registry keys, config layout, and
AnalysisImagingwiring are all unchanged. Only the body oftotal_source_flux_mujyis modified (one extra attribute access).magnificationautomatically returns correct values via the fix.Test Plan
pytest test_autolens/analysis/test_latent.py -x -v— 18/18 pass (including the newtest_total_source_flux_mujy_uses_converted_tracer_for_linear_profiles).pytest test_autolens/— 312/312 pass (no regression).util.py:378) underLATENT_BATCH_MODE = "jit"in production.Stress-test notes
Why the fix is safe:
Non-linear fits:
autogalaxy/abstract_fit.py:214—model_obj_linear_light_profiles_to_light_profilesearly-returnsself.model_objwhenlinear_light_profile_intensity_dict is None. Pure pass-through.Linear-profile fits:
append_linear_light_profiles_to_model(...)rebuilds the tracer with intensities filled in. The intensity dict is populated as a side-effect of the inversion that already runs to producefigure_of_merit— no extra inversion solve.JIT path: euclid empirically validates this —
util.py:378runs under JIT in production. The property's Python branches (if linear_light_profile_intensity_dict is None) are structural (static across samples), so JAX traces them cleanly.total_lens_flux_mujy/total_lensed_source_flux_mujyare unchanged: they readfit.galaxy_image_dict[...]which already mergesgalaxy_linear_obj_data_dict_fromfor linear-obj galaxies viaFitImaging.galaxy_image_dict. Correct for both linear and non-linear.effective_einstein_radiusis unchanged: light-profile-independent (depends on mass model only).Performance: O(1) attribute access for non-linear fits; one tracer rebuild per
compute_latent_variablescall for linear fits. Inside JIT, the rebuild is traced once and reused per sample.🤖 Generated with Claude Code