Repository navigation
background: the light-curve tie subtracts every star the event puts in the blend (8.10.3) - #503
Merged
Merged
Conversation
…n the blend
In a band a microlensing light curve covers, background.<name>.fluxratio_<k>
is derived as f_blend/f_source - sum_{psf_stars} F_j/F_S. Only the
user-listed psf_stars were subtracted, so a lens left off the list was
silently counted as unresolved background (wrong position, wrong pm).
psf_stars stays the one complete, explicit list of modeled non-source stars
in the PSF (the same meaning it has on an astrometry dataset). In a tied
band it must now hold every star the event itself puts in the blend --
every stellar lens body (the primary always, a luminous companion) and
every star on the far side of a source's xallarap orbit -- and may not
name a source; either raises at stage 1, naming the star
(Background.event_blend_stars / _check_tie_membership). So the identity
F_bg/F_S = f_blend/f_source - F_lens/F_S - sum F_j/F_S holds in every model
that builds.
- The skip of the SED check for an empty psf_stars is gone: the lens is
always a member, so a tied band always needs the SED, a band: block and
a BC-grid filter; a member the SED severed raises at stage 6.
- sed_constrains_blend on a tied light curve raises: it states the same
split a second time through its own neighbor_flux (an extra sampled
dimension held at f_S * fluxratio by a 0.2-mag Gaussian), and its lower
bound duplicates the background's [0, 1000] barrier.
- SED.photometric_readers counts the tie (Background.sed_read_stars), so a
lens only the tie reads is SEEN rather than having its SED knobs pinned.
- The derived role and the soft barrier are unchanged.
Tests: identity to 1e-12 at random points with the lens and a neighbor
subtracted; a luminous lens companion subtracted and SEEN; lens /
source-orbit companion omitted, source listed, duplicate, no SED, filter
outside the BC grid and sed_constrains_blend all raise; C and JAX
gradients of the tied model agree.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S5pG2s9aJEo6Xqk6hWvnkW
jdeast
force-pushed
the
fix/background-lens-tie
branch
from
October 27, 2026 16:40
9cbaa61 to
23c0156
Compare
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.
What
Follow-up to #497 (review 8.10.3). In a band a microlensing light curve covers,
background.<name>.fluxratio_<k>is DERIVED asf_blend/f_source - sum_{j in psf_stars} F_j/F_S, but only the stars the user listed in the background'spsf_stars:were subtracted. A lens left off that list was silently counted as "unresolved background", at the background's position and proper motion instead of its own.This PR makes the identity
hold by construction (JDE 2026-10-27: "f_neighbor = f_blend - f_lens - sum(f_modeled stars)").
The event's own blend members are required in
psf_stars.Background.event_blend_starslists the stars the event itself puts in every light curve's blend:Sources are excluded. In a tied band,
_check_tie_membership(stage 1) RAISES, naming the star, whenpsf_starsleaves one of these out, and also whenpsf_starsnames a source. It also refuses a star listed twice.The "empty psf_stars skips the SED check" path is gone. The lens is always a member, so every tied band needs:
sed:block,band:block naming the band,Each one missing RAISES, naming the fix: leave that light curve out of
light_curves:so the band is sampled. A member the SED severed also raises, at stage 6, the same way astrometry's_flux_ratiosdoes.sed_constrains_blend: trueon a tied light curve RAISES (see the finding below).SED readership.
SED.photometric_readersnow counts the tie throughBackground.sed_read_stars: the primary source plus the tiedpsf_stars. Before this, a lens that only the tie read was "unseen": itsav/teffsed/radiussedwere pinned and itsradius/teff/fehwere inactive, yet the derived flux read its SED magnitude anyway.The derived role, the
member_fluxcontext node and the[0, 1000]soft barrier are unchanged. There is nopt.where.Decisions for review
Spelling: explicit and required, not implicit or auto-added.
psf_stars:keeps one meaning on both the background and the astrometry datasets: every modeled non-source star in this PSF, the lens included. A tied band whose list omits a required member raises; it never auto-adds.psf_stars: [Lens]andpsf_stars: []describe the same light: two spellings for one statement (config.md's one-spelling rule).With the explicit spelling the existing astrometry consistency check is unchanged and still guarantees no star is counted twice or missed.
astrometryinstrument.pyis not touched.Which stars are "necessarily" in the blend.
psf_stars):psf_stars, because their light is f_source.NotImplementedError.A dark lens cannot be tied today. An FFP or remnant that no BC grid hosts has no SED prediction, so its band raises and must stay sampled. An explicit "dark" flag would be a follow-up.
Left as a follow-up: an astrometry dataset reading the background in an UNTIED band is still not required to name the lens. There the background's sampled flux absorbs the lens at the background's photocenter. This is recorded in background.md "Known limits", and I kept it out of this PR to stay clear of the concurrent astrometryinstrument work.
The sed_constrains_blend finding
The two statements constrain THE SAME THING, so the combination raises instead of being merged.
sed_constrains_blendadds-0.5 * (2.5 log10((f_lens_inst + neighbor_flux)/f_blend) / sed_blend_sigma)^2.f_lens_inst = 10^(-0.4 (m_nonsources - zp)).m_S,pred + 2.5 log10 f_S, whether its prior is stated or it is only derived.f_lens_inst = f_S * sum_{non-sources} F_j/F_S, which is exactly the background tie's member term.neighbor_flux(one extra sampled dimension) atf_S * fluxratiowithin 0.2 mag. That is two parameters for one light, which 8.10.3's "one object" ruling forbids.neighbor_flux >= 0) duplicates the background'sfluxratio >= 0barrier, so the potential would be double-counted.The tie is the exact form, so the error says to drop the flag or untie that light curve.
Bit-identity (start logp, repr, origin/master 2d75d79 vs this branch)
All shipped example configs (the same sweep driver as #498/#501): 45/45 buildable configs bit-identical (
diffof the two outputs is empty).theophylline.yamlfails identically on both sides because its data file is not shipped. No shipped config has abackground:block.Test configs with a background tie (tests/test_catalog_astrometry.py builders):
band:already made every star SEEN)The two light-curve-only movers, term by term:
av/teffsed/radiussedwere pinned and theirradius/teff/fehinactive.sed.fbolsed_floor_prior(+62.71 / +94.19);sed.teffsed_floor_prior(-9.50 / -14.25);loggsedbound terms.low_bound.background.fluxratiomoves by 3e-11 relative (-51882.11024417914 -> -51882.1102441789). The members' magnitudes now pass through the sampled knobs' logit round trip, so this is a last-bits change.(The large barrier in the [Lens, Neighbor] rows is the test vehicle's toy photometry: the modeled neighbor is far brighter than that light curve's blend.)
Tests
tests/test_catalog_astrometry.py, section 6:_member_flux.[Lens]alone raises namingComp.SComp; listing it builds.sed_constrains_blendon the tied light curve.psf_stars: [Lens]and an SED.Full suite: 5381 passed, 2 skipped, 1 xfailed (47 min, box load ~30-40); no failures, no flakes.
Overlap
background/(code + md);sed/sed.py(+11 lines: one readership block + docstring) andsed/sed.md(one clause); one sentence inmulensing/mulensing.md; the tests.astrometryinstrument.pyis untouched, so no overlap with the companion-group gaia/abs photocenter work.🤖 Generated with Claude Code
https://claude.ai/code/session_01S5pG2s9aJEo6Xqk6hWvnkW