VESPER
Vetting Exoplanet Signals with Pixel-informed Evidence, Rapidly.
VESPER is a fast, learned vetter for transiting-planet candidates around
TESS M dwarfs. Give it a star's TESS photometry and a candidate
ephemeris (period, epoch, duration); it returns a calibrated probability
that the signal is a planet, seven named impostor scores — in the
output's aux_* column order: background eclipsing binary (aux_beb),
window alias (aux_alias), eclipsing binary on target (aux_eb), stellar
rotation (aux_rot), companion dilution (aux_comp), no signal at the
ephemeris (aux_vide, printed as "empty"), spacecraft systematics
(aux_sys) — and a keep/reject disposition, in about a tenth of a second
per star, entirely offline (no external service calls).
The frozen model, its full performance record and its known limitations are documented in the model card, linked from this page: https://gitlab.com/yohanntschudi/exoplanets-project/-/blob/main/documentation/pipeline_ml/VETTER_MODEL_CARD.md
Install
Python ≥ 3.10 required — check with python3 --version. Work in a
fresh virtual environment (system Pythons are often older and their
site-packages messy):
python3.11 -m venv vesper-env # any Python >= 3.10
source vesper-env/bin/activate # Windows: vesper-env\Scripts\activate
pip install torch --index-url https://download.pytorch.org/whl/cpu
pip install "tess-vesper[acquire]"
CPU-only torch is enough. The [acquire] extra adds lightkurve, used by
vesper fetch to download and prepare TESS photometry for you. The wheel
bundles the frozen model (weights, calibrator, decision threshold, M-dwarf
stellar catalog) — nothing is downloaded at vet time — and the artifacts'
SHA-256 fingerprints are checked at every load.
How it works
- You provide the ephemeris — VESPER judges a candidate at a given (period, T0, duration); it complements your transit search and your follow-up, taking the statistical-vetting step in between.
- VESPER prepares its own photometry. From stitched, median-normalised
PDCSAP flux before any detrending, it removes stellar variability with
its own Gaussian-process model on a 200 s grid — the exact preparation
the network was trained and certified on.
vesper fetchbuilds that input for any TIC directly from the TESS archive. Supplying your own curves instead: one pickle per host, namedTIC{tic}_stitched.pkl, holding a dict with keystime(BTJD),flux(PDCSAP, quality flag 0, per-sector median-normalised to ~1.0, before any stellar-variability detrending), and optionallyflux_errandsector— exactly whatvesper fetchwrites. Do not feed already-detrended flux: the certified numbers do not hold for it. - It folds and judges. The signal is folded into shape views (global, transit zoom, secondary, odd/even, per-observing-block), normalised to the star's own noise, and weighed together with the stellar parameters and — when you have them — difference-image centroid measurements.
- It answers in calibrated units.
p_calis a calibrated probability; the shipped threshold (0.29565…, set on the model's sealed calibration split to keep ≥ 95 % of its planets — 96.1 % realized there, 92.2 % of confirmed planets kept on the certified hold-out) turns it into a disposition, and the named impostor heads tell you what the signal most resembles when it is not a planet.
Domain of validity: TESS M dwarfs (Teff ≲ 4,000 K), periods ~0.5–100 d,
native cadences 20–300 s (served on a uniform 200 s grid; coarser
products — e.g. native 600 s — are not servable). Anything the data
contract cannot serve comes back as an explicit blocked:... status, never
a silent skip. The contract checks the data, not the star: VESPER does
not verify that your target is an M dwarf — a K- or G-dwarf curve will
serve and return a number, but an unvalidated one. Check Teff yourself;
outside the M-dwarf regime the output is uncertified.
Try it — the bundled example
Twelve signals on six M-dwarf hosts, both sides of the decision: L 98-59 (three small confirmed planets, plus one unconfirmed 1.05 d candidate signal — judge it yourself), TOI-700 (four confirmed planets, including the habitable-zone TOI-700 d), and four TFOPWG-certified false positives spanning the impostor zoo — a 22.6 % deep eclipse, a short-period eclipsing binary, a long-period shallow false alarm, and a 790 ppm signal with a perfectly planet-like depth.
vesper example
vesper fetch --candidates candidates_example.csv --out-dir example_curves
vesper vet-batch --candidates candidates_example.csv --curves-dir example_curves --out example_results.csv
The fetch downloads every SPOC-family sector of all six stars — TOI-700
alone has 30+ — through lightkurve's cache (~/.lightkurve/cache): a few
hundred MB of FITS and several network-bound minutes on the first run.
Stars whose pickle already exists in --out-dir are skipped, so an
interrupted fetch can simply be re-run.
For your own targets, write the same kind of CSV (header exactly as below,
no spaces after the commas; extra columns such as toi or note are
ignored):
tic_id,period_days,t0_btjd,duration_hours,depth_ppm,planet_num
307210830,7.450726,1355.290002,1.68,1002.2,4
t0_btjd is BTJD = BJD_TDB − 2,457,000 (native TESS time). ExoFOP
lists full BJD epochs — subtract 2,457,000, or the row comes back
blocked:t0_not_btjd. The four first columns are required on every row;
depth_ppm (feeds the deep-eclipse prior) and planet_num (row labelling)
are optional. Single candidates:
vesper vet --tic 307210830 --period 7.450726 --t0 1355.29 --duration-h 1.68 \
--curves-dir example_curves
Reading the output
The results CSV (--out) echoes your input columns, then carries the
science columns below, plus diagnostics (p_raw — the pre-calibration
score; kept_0.5/kept_0.9 — stricter fixed thresholds;
cascade_depth_source; n_sec_measured/n_sec_served — centroid-evidence
sector count before/after its cap; log_scatter; cadence_s_native/
cadence_s_served). The console prints the same information as one aligned
table per host.
| Column | Meaning |
|---|---|
p_cal |
calibrated P(planet) — the number to read |
kept_literal |
p_cal ≥ the shipped threshold — the threshold-only verdict (the calibration-split recall-95 operating point; hold-out performance in the model card §5) |
cascade_fp |
the deep-eclipse prior fired (depth > 50,000 ppm and p_cal < 0.9). For very deep candidates around small stars, read kept_literal — already in the CSV — since giant planets on M dwarfs can exceed that depth; --no-cascade disables the rule outright |
final_literal |
the disposition: True = keep as a planet candidate |
aux_beb … aux_sys |
the seven impostor heads (mapping in the opening paragraph) — triage pointers to the most likely false-positive channel, not individually calibrated probabilities |
spatial_status |
unmeasured = no centroid evidence supplied (the default for external users); pass --spatial CSVs when you have difference-image measurements |
row_status |
served, or an explicit blocked:... reason |
What p_cal is calibrated against. The calibration set is real M-dwarf
light curves carrying injected planets and constructed impostors, held out
from training — p_cal is well-scaled under that mixture. It is not a
TRICERATOPS-style false-positive probability computed against a Galactic
stellar-population model, and a high p_cal is not by itself grounds for
statistical validation. Use it to rank and triage; validation still
requires independent evidence.
License and citation
MIT. The reference article is in preparation; until it is out, cite this package and its model card (linked above), which carries the full provenance of the frozen model.
Metadata
Release files for tess-vesper 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tess_vesper-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Release files / tess_vesper-0.1.2-py3-none-any.whl
| Download URL | tess_vesper-0.1.2-py3-none-any.whl |
|---|---|
| Size | 636.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c46988e25bca1e51aea876390b90fad37bbd0fc494f7fa38c26237322e0c3eba
|
|
BLAKE2b-256 checksum How to use checksums |
a2d5a56e6173d49673f5179ad41f711a9f1928079d982e33cb11643c1345d85d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|