Repository navigation
astrometry: model the gaia/abs photocenter wobble of a COMPANION-group target (review 8.10.6) - #502
Merged
Merged
Conversation
…view 8.10.6) _photocenter_terms summed only the orbits whose PRIMARY group held the target and warned for the rest, so a Gaia DR4-style fit of a binary's companion star dropped its orbit (and, since #498 tied its pm/distance to the anchor, was silently a system-pm fit). Every Keplerian orbit holding the target now moves its photocenter, on either side: x_rel (b - M_c/M) from the primary group (unchanged, built as the same expression -> bit-identical), x_rel (M_p/M - b) from the companion group, b always "the other side's share of the PSF light". On the SED path companion_star_ndx names that other star, placed by its own role in every orbit (so nested targets such as KELT-4 C get BC and A-BC); a sampled nonzero fluxfrac that cannot say where its light is (target in two orbits, or a nested other group) raises. The SED path's companion must share a Keplerian orbit with the target (raises), and a band the BC grid lacks now raises instead of silently going dark. One membership rule, orbit.bodies.photocenter_stars, feeds the model and every "which orbits does astrometry measure" predicate in orbit.py. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S5pG2s9aJEo6Xqk6hWvnkW
…t (review 8.10.6) The test pinned the old primary-only gap; its fake system gains the raw config photocenter_stars reads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01S5pG2s9aJEo6Xqk6hWvnkW
jdeast
force-pushed
the
feat/companion-wobble-8.10.6
branch
from
October 27, 2026 16:22
5d123ba to
b9d4f58
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
A gaia/abs/catalog dataset whose target star sits in an orbit's COMPANION group now gets that orbit's photocenter wobble. Before,
_photocenter_termssummed only the orbits whose PRIMARY group held the target and warned for the rest ("not modeled for gaia/abs data yet"), so the orbital term was silently dropped -- and since #498 tied a companion's distance/pm to its orbit anchor, such a fit was silently a system-pm fit with no orbit at all. With Gaia DR4 epoch astrometry for every source, the companion of a binary will routinely be the target. (Gap dated from 4d46179, the hierarchical body groups.)Physics and signs (derived from the code, not assumed)
Orbit.get_sky_position(relative=False)traces the PRIMARY group's own orbit about the barycenter (omega_), i.e. the direction of-x_rel, withx_rel = x_companion_group - x_primary_group(relative=True, omega_ + 180). The existing primary-target amplitudea_rel (M_c/M - beta)throughrelative=Falseis thereforex_rel (beta - M_c/M)-- matching x_P = -(M_c/M) x_rel and a PSF photocenter(1 - b) x_target + b x_other. The brief's convention agrees with the code; nothing disagreed.relative=Falseb - M_c/Ma_rel (M_c/M - b)-- the old expression, unchangedM_p/M - ba_rel (b - M_p/M)-- negated, like RV's-K M_p/M_c-M_c/Mor+M_p/M(1 - b)(...)b (...)Summed over every Keplerian orbit that moves the photocenter, each with its own mass fractions -- so KELT-4 C gets BC (as primary) and A-BC (inside the companion group). The new sign claim is written up in
skyframe.md, "The photocenter of an unresolved pair".One spelling for the flux fraction.
fluxfracand the SED fraction now always mean the other star's share of the light in this PSF: the companion side's for a primary-group target, the primary side's for a companion-group one.companion_star_ndxnames "the other luminous star inside the target's PSF" (for a companion target that is the primary); the SED computesF_c/(F_c + F_target)exactly as before, so a luminous primary dragging a companion target needs no new key. The PSF holds the target and at most one other light (orbit.bodies.photocenter_stars). On the SED path that star sits at its own position in every orbit, including orbits the target is not in (its own inner orbit moves it too); every other star is outside the PSF. With a sampledfluxfrac, the other light sits at the other group's barycenter._pair_beta(rel mode) was not reused. It weighs both sides of a nested orbit with full group fluxes, a different question; the absolute model's coefficients come from the per-star roles above.One membership rule.
bodies.photocenter_stars+Orbit.star_membership(both sides) is used by the model (_photocenter_orbits) and by every "which orbits does astrometry measure" predicate:_astrometric_orbits(->amplitude_constrained_orbits/inclination_constrained_orbits, so fitmsini/log_q/transit-only),_node_degenerate_orbits, the Taylor refusal in_taylor_consumers, andepochs_constraining(whose amplitude estimate now usesM_p/Mfor a companion-group target). Before, they all said "primary only", so they agreed with the old model. Now they agree with the new one.The reference point (interaction with #498 / #501)
The abs track is
star.<target>.ra/decat the epoch + the system pm and parallax (linked to the anchor for members) + the wobble about the system barycenter, for a primary and a companion target alike. Sostar.<target>.ra/decis the barycenter's position at the epoch as that dataset sees it, not the star's own mean position (that was already true for primary targets, and is now documented). ra/dec is NOT on the #498 link list, so two datasets on two members of one system fit two independent barycenter zero points, and their separation information is not used. See Decision 2.What raises (no warn-and-drop left)
fluxfracwhen the target is in two or more Keplerian orbits (KELT-4 A: is the light the planet b's or B+C's?), naming the dataset and the orbits.fluxfracwhen the other group of the target's one orbit holds a Keplerian orbit of its own (the light wobbles inside that group by an amount one number cannot split). For both, the remedy in the message is the SED path orfluxfracpinned at 0. The dark default (0) is legal in any topology.companion_star_ndxsharing no Keplerian orbit with the target (stage 3). Such a star is a blend on its own track, and it used to be read as if its light rode the target's orbit. Two existing tests (test_sed_flux_constraints,test_component_override_channel) used exactly that topology (the companion star C in no orbit). C now rides the BH orbit's companion group, and their assertions are unchanged.companion_star_ndx == star_ndx._pair_betais left alone.Tests (
tests/test_astrometry_companion_wobble.py, slow-marked)b = 0.2vs an independent rotation-matrix Kepler orbit,x_rel (M_p/M - b), atol 1e-9 of the amplitude.(M_p/M - b_p)/(b_c - M_c/M)to 1e-9. Also: with consistent fractions (b_p = 1 - b_c) the two tracks are identical (one PSF, one photocenter).companion_star_ndx: A.fluxfrac_sed= F_A/(F_A+F_B), and the wobble uses that b.The probes evaluate at
system.get_raw_starts(model)with RVs replaced by value vars. Evaluating on the RVs draws from the prior, andmodel.initial_point()is not the start: both silently gave wrong numbers in the first draft of these tests.Bit-identity (master 2d75d79 vs branch, repr of start logp)
Every top-level shipped example config (45 + theophylline, which fails identically on both for a missing data file): all identical. That includes every astrometry config (GaiaBH1, HIP1349, astrometry_sim/simbinary, kelt4 x3) and every config with orbits. No shipped config has a companion-group gaia/abs target, so none was expected to move. The primary-only path builds the identical expression (
a[omap] * RSUN_AU * (m_c[omap]/m_tot[omap] - beta) * plx).table
Full suite
Local full suite (
-n6, box load ~28): 5382 passed, 4 skipped, 1 xfailed, 1 failed:test_chen.py::test_astrometry_gaia_mode_uses_primary_membership. That test pinned the old primary-only gap (a gaia target in the companion group "does not count as mass-constrained"). It is updated in the second commit to the new rule (renamed..._counts_companion_membership, and its fake system gains the rawconfigthatphotocenter_starsreads).test_chen.pythen passes 36/36. The targeted astrometry/orbit set (14 files, 241 tests) passes.Decisions for review
companion_star_ndx, so a PSF holding three luminous stars (KELT-4 C with both B and A unresolved) cannot be stated. It is not guessed: every star not named is outside the PSF. Accepting a list (scalar broadcast at the boundary) is a small extension if wanted. Merging this with the lensed datasets'psf_stars:(whose members ride their own tracks, not the orbit) would be the bigger, cleaner unification.fluxfracwith a multi-orbit target (the old code applied one beta to every primary orbit, wrong for KELT-4 A's planet orbit), and acompanion_star_ndxoutside the target's orbits. No shipped example hits either.fluxfrac's table description stays "Companion Flux Fraction" ("the target's companion in the PSF"); only the defaults.yaml comment and the docs changed.lensrel, as before. lensrel "measures no orbit" (epochs_constraining skips it), so excluding it there would be more correct, but it is a separate behavior change.Conflicts
Rebased onto master after #501 (1c69fd8). The one conflict was
orbit.md's "A star in an orbit group shares ..." paragraph. The resolution keeps #501's text (rv on the linked list, thestar.rvsentence) and applies this PR's two edits to it: the wobble is from a star "in either group", and the "still primary-group only" sentence is replaced by the companion-wobble and ra/dec sentences.Review item 8.10.6.
🤖 Generated with Claude Code
https://claude.ai/code/session_01S5pG2s9aJEo6Xqk6hWvnkW