Skip to content

fix(latent): build the latent instance the Fitness way under JAX (#732) - #734

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/vis-lp-latent-jit-assertions
Sep 10, 2026
Merged

Jammy2211 merged 1 commit into
mainfrom
feature/vis-lp-latent-jit-assertions

Conversation

@Jammy2211

Copy link
Copy Markdown
Collaborator

Summary

Closes #732. The Euclid initial_lens_model/vis_lp stage (two-basis MGE lens light, SIE + shear, MGE source) of RAL job 342398 wrote no latent output on all ten euclid_dr1_prelim tiles. LatentLens.variables built its per-sample instance with model.instance_from_vector(vector=parameters), whose default assertion check applies a Python not to a traced boolean. The latent engine evaluates variables under a per-sample jax.jit, so a model carrying any assertion (the ordered MGE bases added to vis_lp on 2026-09-08) raised TracerBoolConversionError on every sample; the engine swallowed each raise into a NaN row, the global mask found nothing, and the search logged only "no finite latent samples remained".

This adds latent_instance_from(model, parameters, xp): the NumPy path is unchanged (assertions checked, a violation raises FitException and is dropped as a NaN row); under JAX it skips assertions and threads xp, exactly as Fitness does on its JAX path. LatentLens.variables uses it, and the class docstring tells subclasses that build their own instance to do the same. The companion PyAutoFit PR makes the engine report the exceptions it swallows; the euclid pipeline's own two trace failures are filed in PyAutoMind as draft/bug/euclid/vis_lp_latent_euclid_jit_trace.md.

API Changes

Added one public helper, autolens.analysis.latent.latent_instance_from. No existing symbol changed; NumPy-path behaviour of LatentLens.variables is unchanged, the JAX path now succeeds where it silently produced NaN rows.
See full details below.

Test Plan

  • test_latent_instance_from_numpy_checks_assertions — violation raises FitException, satisfied builds the instance
  • test_latent_instance_from_jax_skips_assertions_under_jit — the default path raises TracerBoolConversionError under jax.jit, the helper traces
  • test_latent_lens_variables_traces_under_jit_with_model_assertion — end to end on the 7x7 fixture with use_jax=True, every latent finite and equal to the NumPy evaluation
  • Full suite: 621 passed, 1 skipped, 1 xfailed
  • Reproduction on the euclid pipeline's simulated dataset: with this and the pipeline follow-up, jax.jit(LatentEuclid.variables) returns all 12 latents finite and equal to the eager values
Full API Changes (for automation & release notes)

Added

  • autolens.analysis.latent.latent_instance_from(model, parameters, xp=np) — builds the instance a latent function is evaluated on; NumPy checks assertions, JAX skips them with ignore_assertions=True, xp=xp

Changed Behaviour

  • LatentLens.variables under JAX: previously raised inside the engine's per-sample jax.jit for any model with an assertion (silently masked to NaN rows); now evaluates

Migration

  • A LatentLens subclass that builds its own instance: replace model.instance_from_vector(vector=parameters) with latent_instance_from(model=model, parameters=parameters, xp=analysis._xp)

Generated by the PyAutoLabs agent workflow.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FFSFgEBiZc7kTRutfK1RsN


Generated by Claude Code

`LatentLens.variables` built its per-sample instance with
`model.instance_from_vector(vector=parameters)`, whose default assertion
check applies a Python `not` to a traced boolean. The latent engine evaluates
`variables` under a per-sample `jax.jit`, so a model carrying any assertion
(the ordered two-basis MGE lens light of the Euclid `vis_lp` stage) raised
`TracerBoolConversionError` on every sample; the engine swallowed each raise
into a NaN row, the global mask found nothing, and the search wrote no latent
output at all (RAL job 342398, all ten euclid_dr1_prelim tiles).

Add `latent_instance_from(model, parameters, xp)`: the NumPy path is
unchanged (assertions checked, a violation raises FitException and is dropped
as a NaN row); under JAX it skips assertions and threads `xp`, exactly as
`Fitness` does on its JAX path. `LatentLens.variables` uses it and the class
docstring tells subclasses that build their own instance to do the same.

Tests: the helper on both backends (the default path is shown to raise under
jit), and `LatentLens.variables` end to end under `jax.jit` on a model with an
assertion, finite and equal to the NumPy evaluation.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FFSFgEBiZc7kTRutfK1RsN
@Jammy2211 Jammy2211 added the pending-release PR queued for the next release build label Sep 10, 2026 — with Claude
@Jammy2211
Jammy2211 merged commit 0da06de into main Sep 10, 2026
4 checks passed
@Jammy2211
Jammy2211 deleted the feature/vis-lp-latent-jit-assertions branch September 10, 2026 18:49
@Jammy2211 Jammy2211 removed the pending-release PR queued for the next release build label Sep 26, 2026
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.

fix(latent): JAX jit assertion check drops every vis_lp latent

1 participant