Skip to content

Add opt-in Offner et al. 2023 multiplicity model (Table 1, including BDs) - #160

Open
jluastro wants to merge 16 commits into
synphot_updatefrom
cursor/offner-2023-multiplicity-ad2c
Open

Add opt-in Offner et al. 2023 multiplicity model (Table 1, including BDs)#160
jluastro wants to merge 16 commits into
synphot_updatefrom
cursor/offner-2023-multiplicity-ad2c

Conversation

@jluastro

@jluastro jluastro commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Adds an opt-in multiplicity model based on Offner et al. 2023, Protostars and Planets VII, ASPC 534, 275 (arXiv:2203.10066; ADS 2023ASPC..534..275O; Table 1 on Zenodo 10.5281/zenodo.6628915).

The SPISEA v2.5 MultiplicityUnresolved / MultiplicityResolvedDK objects remain the default. Frozen FITS in tests/test_data/ are unchanged.

Documentation

docs/multiplicity.rst fully describes the Offner models (formulas, coefficients, BD policy, Table 1 companion-assignment note) and includes the five comparison figures vs SPISEA v2.5. Changelog and docs/imf.rst point at the opt-in. Figures are generated from the multiplicity object methods (python docs/figures/plot_mf_offner_vs_spisea2.5.py and plot_q_sep_offner_vs_spisea2.5.py).

New and modified callables in spisea/imf/multiplicity.py have numpy-style Parameters/Returns with types and units (Msun, AU, dex of log10(a/AU), dimensionless MF/CSF/q/γ). Private model helpers (_logistic_in_logm, etc.) are at the bottom of the file so Sphinx/source order documents the public classes first. Primary mass must be positive; massless (M≤0) primaries are not supported.

MF vs primary mass

Offner 2023 vs SPISEA v2.5: multiplicity fraction vs primary mass

Left: brown-dwarf zoom. Right: BD through early B. Solid: Offner logistic in log-mass. Dashed: SPISEA v2.5 (0.44 M^{0.51}). Dotted: SPISEA v2.5 scalar BD staircase.

q and separations vs mass

Offner 2023 vs SPISEA v2.5: mass-ratio index vs primary mass

Offner γ is an error-weighted logistic in log M fitted to Table 1 γ_trunc (not interpolation):

γ(M) = A + (B - A) / (1 + (M / M0)**(-k))
A=6.6, B=-1.77, M0=0.0651, k=0.629

The fit undershoots Fontanive 4.8±2.2 (~3.3 at 0.033 Msun). Offner BD companions are more equal-mass than the SPISEA v2.5 stellar q_pow (6.1 / −0.4 step). Mean-q companion panel: docs/figures/meanq_offner_vs_spisea2.5.png.

Offner 2023 vs SPISEA v2.5: characteristic separation vs primary mass

Offner μ(a) is a smooth broken power law in log10(a) vs log10(M), s=0.1 dex, FGK-pulled (C∞ via stable logcosh):

v = log10(M / Mp);  yp = log10(μp)
log10(a) = yp + 0.5*(αL+αR)*v + 0.5*(αR-αL)*s * logcosh(v/s)
μp=44.46 AU, Mp=0.819 Msun, αL=1.005, αR=-0.308, s=0.10

Offner BD a peaks at a few AU (μ(0.033)≈2 AU); SPISEA v2.5 DK is a Duchêne–Kraus broken power law with a BD blend and is not meant for that range.

Offner 2023 vs SPISEA v2.5: sigma of log10 a vs primary mass

Offner σ(log10 a) is a 2-parameter logistic pinned at 0.7 / 1.5:

σ(M) = 0.7 + 0.8 / (1 + (M / 0.354)**(-6.05))

Resolved draws use loc = log_a_mean(mass), scale = sigma_log_a(mass) in a truncated lognormal (0.01–2000 AU).

How to use

from spisea.imf import imf, multiplicity
from spisea import synthetic

multi = multiplicity.MultiplicityUnresolvedOffner2023()
# alias: multiplicity.MultiplicityOffner2023()
# resolved: multiplicity.MultiplicityResolvedOffner2023()

imf_obj = imf.Kroupa_2001(multiplicity=multi)
cluster = synthetic.ResolvedCluster(iso, imf_obj, Mcl)

Logistic in log-mass MF/CSF

MF(M)  = A + (B - A) / (1 + (M / M0)**(-k))
CSF(M) = same form, different coefficients

MF:  A=0.14, B=0.99, M0=1.41, k=1.25
CSF: A=0.12, B=2.35, M0=3.57, k=0.96

C-infinity smooth, saturates at B ~ 1. RMS vs Table 1 geom-mean MF ~0.026 vs ~0.049 for the old 3-segment law. Fontanive (8 ± 6%) remains ~0.07 below the curve (~15%). MF clipped to [0, 1]; CSF = MF below 0.08 Msun.

Architecture

Companion masses and “is this a multiple?” are drawn in IMF.generate_cluster / IMF.calc_multi, not in synthetic.py.

  1. Mass-aware random_q(x, mass=None) — Offner uses the error-weighted γ logistic.
  2. Companion-count policy — BD cap of 1 companion lives on the multiplicity object.
  3. Duck-typed resolved orbits — Offner resolved does not subclass DK.
  4. log_a_mean / sigma_log_a — public; resolved log_semimajoraxis draws from those.

Tests

pytest -q on this cloud VM cannot collect the full suite: missing synphot, stsynphot, and pandas (no spisea-synphot conda env). With --continue-on-collection-errors: 27 passed, 1 failed (test_resolvedmult → missing stsynphot), 1 skipped (no pysynphot/stsynphot), 5 collection errors, 0 deselected. All Offner unit tests that ran passed, including test_xi2. The test_resolvedmult failure is missing photometry backends, not Offner math.

pytest spisea/tests/test_multiplicity.py spisea/tests/test_imf.py -k "not test_resolvedmult and not test_xi2": 26 passed, 2 deselected.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

Introduce MultiplicityPiecewisePowerLaw plus unresolved/resolved Offner
2023 classes fitted to Table 1 MF/CF (including brown dwarfs). Companion
mass and separation draws now live on the multiplicity object; Lu+2013
defaults are unchanged.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
@jluastro
jluastro marked this pull request as ready for review August 13, 2026 16:36
cursoragent and others added 15 commits August 13, 2026 16:38
calc_multi now only delegates to the multiplicity object. random_q is
mass-aware so Offner γ_trunc applies to BD primaries instead of the
hardcoded Fontanive 6.1. random_companion_count owns the BD binaries-only
cap. synthetic.py duck-types resolved orbits on log_semimajoraxis,
random_e, and random_keplarian_parameters. Docs and IMF tests updated.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Replace the discontinuous 8-segment two-point Table 1 fit with a
3-segment broken power law continuous at 0.08 and 1.5 Msun. Add a
two-panel MF vs mass figure (Lu+2013 vs Offner vs Table 1) to the docs
and PR.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Offner et al. 2023 now subclasses MultiplicityLogistic instead of the
piecewise power law. MF/CSF use equal-weight Table 1 logistic coefficients;
the generic piecewise class remains for tests and other surveys.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Two-panel BD-zoom plus full-range plots of Table 1 gamma_trunc and
characteristic a, plus a mean-q companion panel. Curves come from the
multiplicity objects so they cannot drift from the code.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Two-panel plot of Table 2 separation scatter versus the Duchene-Kraus
linear-in-log-M fit. Offner holds sigma=0.7 for brown dwarfs; Lu DK
shows the 0.08 Msun blend dip.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Replace Table 1/2 log-mass interpolations with an error-weighted
logistic for gamma, a logcosh smooth broken power law for mu(a),
and a 2-parameter logistic for sigma(log10 a). Resolved draws use
those as loc and scale. MF/CSF logistic and Lu+2013 are unchanged.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Expand docs/multiplicity.rst with formulas for MF/CSF, gamma, mu(a),
and sigma(log a), plus the five Lu+2013 comparison figures. Point
imf.rst and the changelog at the opt-in Offner model.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
The comparison plots and docs describe Offner 2023 vs the default
MultiplicityUnresolved / MultiplicityResolvedDK that shipped in
SPISEA v2.5. Keep Lu et al. 2013 citations on the original classes.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Filenames, RST figure paths, and plot-script helpers now match the
SPISEA v2.5 comparison baseline.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Updated the documentation for the multiplicity object, clarifying its functions and usage in the IMF. Revised sections on companion evolution and recommended multiplicity classes.
Add Parameters and Returns (types and units) to every new helper,
class, and method in multiplicity.py. Expand modified methods that
already had a Parameters block but omitted units. No math changes.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Private helpers sit after the public classes and MultiplicityOffner2023
alias so Sphinx/source order documents the classes first. Table arrays
that call _offner2023_table1_geom_mass follow that helper. No behavior
change.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
Evaluate the logistic and smooth broken power law on positive masses
only. Keep M>0 math unchanged. Tests and docs no longer treat M<=0
as mapping to the low-mass asymptote.

Co-authored-by: Jessica Lu <jlu.astro@berkeley.edu>
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.

2 participants