Releases: jvines/Nereus.jl
Release list
Nereus v0.4.4
Nereus v0.4.4
Everything Nereus can do is now reachable from the Python API. Three gaps
turned up in one session, which is a pattern rather than bad luck, so this
closes the whole list instead of the next complaint.
Plots
fit_* wrote chains.nc and nothing else. Nereus's own figures were reachable
only by rewriting the call as a run_job JSON config — in a different prior
vocabulary.
gaia4 = s.fit_astrometry(..., plots=["corner", "iad_residuals"])
for name in sorted(gaia4.figures):
display(Image(str(gaia4.figures[name])))_finish calls _make_plots, the same function run_job calls, and builds
the identical manifest: logical name → path.
The daemon dropped every keyword it did not hardcode
act_fit_* forwarded exactly planets/engine/output_dir/priors and threw the
rest away. A Python caller could pass transdim, external_priors, plots —
and nothing happened, silently, which is worse than not offering them.
It now forwards anything outside the transport envelope, converting
Symbol-valued options from their JSON strings.
The whole model surface
_target_from forwarded six of build_target's keywords and dropped the rest;
build_target in turn forwarded only part of what Params accepts. Now plumbed
end to end and declared on every fit_*:
transdim, external_priors, plots, plot_kwargs, save_pdf,
parametrization, time_anchor, stability, M_s, R_s,
phot_trend_order, as_names, sharing, transdim_noise, ttv_n_transits,
ttv_backend.
None of this needed new capability — only wiring. An unknown keyword now raises
with the known list rather than vanishing.
Breaking: PY_API_VERSION 2 → 3
A 0.4.4 client against an older runtime would forward plots= to a fit_*
with no such keyword and die on a MethodError several frames into Julia.
That is exactly what the handshake exists to turn into a sentence, so it bumps.
Upgrading the pip package is not enough — refresh the runtime too:
astronereus.install(force=True)Nereus v0.4.3
Nereus v0.4.3
external_priors now works through the fit_* API.
Params has always accepted them; build_target simply never forwarded the
keyword, so priors on derived quantities were reachable only through a
run_job JSON config. Same shape of gap trans-dim had before v0.4.1.
fit_astrometry(...; external_priors = [
Dict("quantity" => "ecc",
"prior" => Dict("type" => "normal", "mu" => 0.0, "sigma" => 0.3))])Uses the same prior spelling as the priors dict, so there is no switching
vocabularies mid-call. per_planet defaults by quantity — true for ecc,
false for rho_s — because the alternative is silently wrong. An unknown or
missing quantity throws.
Only ecc and rho_s exist (_VALID_EXTERNAL_QUANTITIES, model.jl:1093).
Verified the prior bites: on a synthetic e = 0.30 RV set the free fit gives
e = 0.103, and an N(0, 0.1) external prior pulls it to e = 0.003.
Also ships test/data/gaia4_rv.dat — the 23 Gaia-4 radial velocities from
Stefansson et al. 2025 (AJ 169, 107; arXiv:2410.05654) table 5, via VizieR
J/AJ/169/107/table5. HPF, NEID and FIES over 1.43 yr against a 1.56 yr
period, so they do not cover a full cycle alone.
PY_API_VERSION stays at 2 — an added keyword an old client never sends is not
a breaking change.
Nereus v0.4.2
Nereus v0.4.2
One fix: pt_emcee's default n_temps goes 5 → 16, on both the Julia and
Python sides.
Five was slower and worse mixed. Measured on the HD 114762 joint
RV + astrometry target:
n_temps |
time | min swap acceptance |
|---|---|---|
| 5 | 5.1 min | 0.0030 |
| 16 | 2.0 min | 0.0144 |
| 24 | 2.5 min | 0.0185 |
A denser ladder pays for itself: better mixing reaches the convergence checks
sooner, so the run ends earlier. There was no speed argument for 5.
It was also the most fragile setting measured. At 16 temps with one particular
seed the eccentricity still collapsed to 0.002 against a published 0.335 —
exit code 0, tight error bars, and only min swap accept = 0.006 to show for
it. That is why examples/02 ships at n_temps = 24. A default of 5 sat below
even the value that failed.
Joint astrometry targets should pass n_temps = 24 explicitly.
Existing clients are unaffected: PY_API_VERSION stays at 2, since a changed
default is not a changed signature.
Nereus v0.4.1
Nereus v0.4.1
Fixes found by executing the example notebooks for the first time.
logdensity_bounded
NereusTarget has two logdensity methods and build_target returns the
transformed one, which expects unconstrained coordinates. Chains store
bounded values. So taking posterior draws out of a chain and feeding them
back returned -Inf for every point, with no error and no hint why.
logdensity_bounded(target, x) # bounded input, either target typeThe transformed method now warns once when a point that returned -Inf would
have been valid in bounded space, naming the fix.
Engine defaults are chosen by shape
All fit_* entry points default to pt_emcee, and to transdim_pt_emcee
when a transdim block is present. pt's within-model explorer is
coordinate-wise slice sampling — axis-aligned moves only — so it cannot follow
a diagonal ridge, and it reports no swap acceptance or R-hat, so it fails
silently. On this repo's own validation set it gets HD 159062 wrong
(e = 0.359 against a true 0.11) where pt_emcee recovers it.
Naming an engine explicitly still overrides. pt remains available.
Trans-dim from fit_*
fit_rv(data; planets = 4, transdim = true)Accepts true, an Int, a config block, or a TransDimConfig. max_kplanet
comes from planets, so the planet count is stated once. No run_job, no JSON
config — the trans-dim and fixed-dim paths are now symmetric.
Also
examples/01andexamples/02use the default engine instead of hardcoding
sample_pt. Measured: nb01 2.9 min, nb02 2.7 min.docs/src/api.md'sfit_astrometryexample passedparallax=/m_pri=,
removed in the priors refactor. Now usespriors.test_builderassertedM_sback-filled fromM_pri, a contract removed in
0.4.0. It had been failing since, unnoticed.
Compatibility
PY_API_VERSION stays at 2 — nothing here breaks an existing client, so a
deployed astronereus 0.4.0 keeps working against these bundles.
Nereus v0.4.0
Nereus v0.4.0
Breaking. A client on 0.3.x will refuse to start against these bundles, and
0.3.x bundles are refused by astronereus 0.4.0 — by design, see below.
Breaking
Engines renamed. ptemcee → pt_emcee, transdim_ptemcee →
transdim_pt_emcee. The PT family reads as "PT with " — pt_hmc,
pt_whitening — and these two were the outliers. Update any job config with
"engine": "ptemcee".
A prior is a prior. plx and M_pri live in the priors dictionary and
nowhere else. fit_astrometry no longer takes parallax= or m_pri=, and
M_pri is a prior only — it no longer doubles as a mass value.
Version handshake
A runtime bundle is a compiled Nereus cached under ~/.cache/nereus, while the
daemon ships inside the pip package. pip install -U astronereus moves the
client and leaves the Julia API where it was. That skew previously surfaced as
ArgumentError: No value arguments present
several frames deep in fit_astrometry, saying nothing about versions.
Nereus.PY_API_VERSION is now reported by the daemon's ping and checked by
Session.start(). On a mismatch you get a message naming the fix:
astronereus.install(force=True)
NEREUS_SKIP_API_CHECK=1 bypasses it. Bundles predating the constant report
api=0 and are refused.
Fixes
fit_jointcould not run at all — channel parallax arrived as a raw JSON
dict and the planet block was built from channels that were not present.priors=was forwarded to Julia as raw JSON rather thanPriorSpecobjects.- Three sampler registries had drifted out of step:
oftiwas unreachable from
Python andpt_hmcskipped keyword validation. There is now one registry. Session.stop()works as an alias forclose().
Bundles
Built from a single commit on all three platforms, each gated on a real
fit_rv dispatch and a contract-version check before compression.
BUILD_INFO.txt inside each bundle records commit, CPU target, py_api and
build time.
linux-aarch64 is built natively on Apple Silicon under
docker --platform linux/arm64 — not qemu.
Nereus v0.2.3
Nereus v0.2.3
Breaking: a prior is a prior.
plx and M_pri were keywords on fit_astrometry, and fields on the
astrometry channel, and keys in run_job's priors block — three spellings for
one concept, while build_target folded both straight into the same priors dict
anyway. They now live in priors and nowhere else.
Removed, not deprecated: the parallax= / m_pri= keywords and the matching
channel fields.
fit_astrometry(iad = [...], planets = 1,
priors = Dict("plx" => NormalPrior(13.628, 0.021),
"M_pri" => FixedPrior(0.644),
"a_k1" => LogUniformPrior(0.3, 4.0),
"M_sec_k1" => LogUniformPrior(0.001, 0.05)))M_pri also secretly doubled as M_s, the numeric stellar mass for transit
a/R*. That made one name mean a prior or a constant depending on whether the fit
had astrometry, and it meant a sampled M_pri hit a TypeError — which
nobody had tried. They were never the same quantity. The back-fill is gone; if
you want a stellar mass for transits, pass M_s.
Runtime bundles
| platform | size | sha256 |
|---|---|---|
macos-arm64 |
481 MB | a53233241ac556c89fe69266c4e2225f9ac9c236e5d12fc852b9d8b0e5ff08ae |
linux-x86_64 |
689 MB | b45b061a8643d1b689852bcff3072030fb3b215f4972e07bc3b22becd8921159 |
linux-aarch64 |
657 MB | 2d1bd4a8888236177142921fb7d8d1aabab6e31202d4f8313e117e9fdf945ae1 |
All three built from this commit and each verified by dispatching a real
fit_rv through its own bundled depot before compression. SHA256SUMS is
attached; astronereus.install() checks it automatically.
Nereus v0.2.2
Nereus v0.2.2
fit_joint could not run at all. Two bugs in _target_from, both only
reachable through the multi-channel path: a parallax arriving on an astrometry
channel reached build_target as a raw dict instead of a prior, and the
planet spec was built with no default block, so build_target refused with
"planet must declare a mass parameter". fit_rv and fit_astrometry each pass
their own block; only fit_joint hit it.
Runtime bundles
| platform | size | sha256 |
|---|---|---|
macos-arm64 |
465 MiB | 282411ed11b06aee29b13c7cf106aa99c7d264aa7a20ea8ea677a3df145348f3 |
linux-x86_64 |
688 MiB | 0e8726f407085a3438ab1edbf09af0d8349bbd7dcb6f37e96a125f38f24cff6e |
linux-aarch64 |
649 MiB | 6f0abb0306108b12bc38225822fb0d9c35d421f8adab2e92017e0ee687eb431b |
linux-aarch64 is new. ARM Linux previously raised BundleError with no
bundle to fetch.
All three were built from the same commit, and each was verified by dispatching
a real fit_rv through its own bundled depot before it was compressed — 18
engines resolved, fit returned. SHA256SUMS is attached and
astronereus.install() checks it automatically.
For a workshop, fetch one once and point everyone at the local copy:
export NEREUS_BUNDLE_URL=/path/to/nereus-runtime-1.11.9-macos-arm64.tar.zstNereus v0.2.1
Nereus v0.2.1
Prebuilt runtime bundles for macOS arm64 and Linux x86_64. No Julia
required from Python: pip install astronereus, then astronereus.install().
Runtime bundles
| platform | size | sha256 |
|---|---|---|
macos-arm64 |
481 MB | 0bfcc9428bea78b76d77ae4becb6b1c67cc9baba73c8ed482bdbe5c0cd7cbc09 |
linux-x86_64 |
689 MB | d6bf0e45588c06d10b815a67836ef4f2dd7868c3fcc1786dd585b6710fc4cff7 |
Both built from this commit and verified by dispatching a real fit through
the bundled depot. SHA256SUMS is attached; astronereus.install() checks
it automatically.
For a workshop, fetch one bundle once and point everyone at the local copy:
export NEREUS_BUNDLE_URL=/path/to/nereus-runtime-1.11.9-macos-arm64.tar.zst