Version 1.0.1 — Spark
A teaching instrument for turning a barely visible blip into a testable scientific question.
TESS Candidate Finder is an open, reproducible Python workflow for screening public TESS light-curve products for periodic transit-like dimming. It can help astronomers, students, educators, citizen scientists, and software researchers:
- analyze a known TESS Input Catalog star with BLS or TLS;
- scan a resumable list of comparatively uncrowded dwarf-star targets;
- inspect live terminal progress instead of running an opaque batch job;
- retain candidate period, depth, SNR, source-product provenance, search settings, and phase-folded evidence;
- archive and reproduce runs without accumulating full FITS datasets; and
- verify the end-to-end pipeline against ten confirmed transiting planets.
The current confirmed-planet acceptance suite recovers 10/10 published periods from real MAST/SPOC data. Start with:
make setup
make validate
make runThis software identifies signals worth investigating; it does not confirm planets. Candidates may be stellar variability, eclipsing binaries, contamination, aliases, or instrumental systematics and require independent vetting and follow-up. See Limitations before using its output scientifically.
Exoplanet science does not begin with certainty. It begins when someone notices that a star dimmed slightly, predicts that the dimming may repeat, and tests that prediction against more observations. The pioneering teams that found the first exoplanets also began with candidate signals; confidence came later, through careful vetting, repeated measurements, independent instruments, and the elimination of competing explanations.
This project gives students an authentic place in that process. It uses public telescope data and real search methods—not a pre-scripted classroom answer—to move through the same chain of reasoning:
- Observe: obtain a time series of measured starlight.
- Notice: find a small, repeating decrease in brightness.
- Hypothesize: describe that signal as an exoplanet candidate.
- Preserve: record the period, depth, SNR, data provenance, and folded evidence so another person can reproduce the result.
- Question: test whether noise, stellar activity, an eclipsing binary, contamination, or an instrument could explain it instead.
- Confirm: seek additional transits and independent observations before making a discovery claim.
The educationally disruptive idea is simple: students do not merely read what “real scientists” did. They can inspect the same kind of faint signal, make a prediction, retain evidence, experience doubt, and learn why scientific confirmation is earned rather than announced.
A modular Python 3 application for searching raw TESS light curves for previously unflagged transit-like signals. It queries the Mikulski Archive for Space Telescopes (MAST), downloads selected products into a temporary directory, runs Box Least Squares (BLS) or Transit Least Squares (TLS), applies basic candidate vetting, and prints period, transit depth, and signal-to-noise ratio (SNR).
This is a research scaffold, not a scientific validation pipeline. A reported signal can be caused by stellar variability, eclipsing binaries, instrumental systematics, or contamination and must be independently reviewed.
Python 3.10 or newer is recommended.
The supported bootstrap command creates .venv, installs dependencies, and
installs the project in editable mode:
make setup
source .venv/bin/activateThe equivalent manual steps are:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
python -m pip install -e .TLS has a larger scientific dependency stack than BLS, so installation may take a few minutes.
make helpmake help prints the complete command guide, configurable variables, and
examples. The available commands are:
| Command | Purpose |
|---|---|
make setup |
Create .venv, install dependencies, and install the project. |
make run |
Start or resume the default quiet-field survey. |
make archive |
Snapshot active run artifacts without clearing them. |
make reset |
Archive and verify active artifacts, then start fresh. |
make test |
Run the complete unit test suite. |
make validate |
Recover ten confirmed planets from real TESS/MAST data. |
make tic ID |
Analyze one TIC using a positional catalog ID. |
make star TIC=… |
Analyze one TESS Input Catalog target. |
make survey |
Alias for make run. |
make quick-survey |
Run a three-star, one-hour survey check. |
make archives |
List timestamped run archives. |
make check |
Run tests and Git whitespace validation. |
make install |
Refresh dependencies and the editable installation. |
make web |
Start the placeholder FastAPI development server. |
make clean |
Remove generated Python caches and build products. |
make help |
Display command, variable, and example documentation. |
Survey and single-star commands accept Make variable overrides:
| Variable | Meaning | Default |
|---|---|---|
ALGORITHM |
BLS or TLS search |
BLS |
LIMIT |
Light-curve products fetched per star | 1 |
MAX_STARS |
Maximum survey targets | 100 |
HOURS |
Survey time limit | 36 |
RADIUS |
Survey cone radius in degrees | 2 |
TIC |
Catalog ID required by make star |
none |
PYTHON |
Python interpreter override | .venv/bin/python when available |
VALIDATION_LIMIT |
Products fetched per validation star | 1 |
VALIDATION_TOLERANCE |
Relative published-period tolerance | 0.02 |
Examples:
make run MAX_STARS=250 HOURS=48
make tic 307210830
make tic 307210830 ALGORITHM=TLS LIMIT=2
make star TIC=261136679 ALGORITHM=TLS LIMIT=2
make archive
make archives
make validateSee Operations for archive layout, reset safety, resume behavior, and command overrides.
Analyze up to three TESS light curves for TIC 261136679 with BLS:
tess-candidate-finder --tic 261136679 --algorithm BLS --limit 3Use Transit Least Squares:
tess-candidate-finder --tic 261136679 --algorithm TLS --limit 2Run an unattended high-Galactic-latitude survey for up to 36 hours:
make runThe equivalent direct CLI command is:
tess-candidate-finder --survey --algorithm BLS --max-stars 100 --hours 36 --limit 1Survey mode gathers a brightness-prioritized pool of comparatively small TIC stars in a two-degree cone around the North Galactic Pole, then checks MAST and queues only stars with pre-extracted TESS light curves. The discovery stage keeps the number of catalog stars without products visible as an archive coverage lesson rather than reporting them as analysis failures. The sky choice reduces foreground dust, gas, and Galactic-plane crowding; it cannot guarantee that every catalog classification is correct.
The queue, unavailable-product evidence, and genuine failures checkpoint to
data/region_scan_state.json after every analyzed star. Press Ctrl+C to pause
and rerun the same command to resume. A new run checks unavailable stars again
because MAST may publish additional products later.
Survey mode runs as a full-screen terminal dashboard. It continuously displays a heartbeat and elapsed clock, current network or analysis stage, discovery coverage, data-ready and no-data counts, target and queue counters, BLS/TLS progress, candidate and genuine failure counts, recent events, and persistent output locations. The initial TIC request uses bounded network timeouts and retries, preventing an unavailable MAST service from producing an unlimited silent wait.
The equivalent module invocation is:
python -m tess_candidate_finder.cli --tic 261136679 --algorithm BLS --limit 3Candidate output has this form:
Candidate detected: TIC 261136679 | BLS | period=3.141593 d | depth=0.001200 | SNR=9.40
The interactive CLI shows a pulsing star during MAST access. Once data arrives,
it plays a brief archival scan using the real observation timestamps and flux,
colors the star approximately from the FITS-header effective temperature, and
renders a compact Unicode brightness trace. During BLS it reports the actual
period range and completion percentage for each computed grid chunk. It then
displays the strongest result as a candidate card and validates it using the
configured thresholds.
Thresholds in config.py are intentionally conservative examples and should be
calibrated for a real survey.
MAST metadata is written to data/metadata/. Accepted candidates are appended
to data/candidate_results.json. Each record contains source-product provenance, UTC
coverage, the complete search configuration and rerun command, and a compact
100-bin phase-folded flux profile showing the evidence for the detection. Full
FITS light curves are downloaded only to an operating-system temporary
directory and removed after their arrays and provenance have been loaded.
Use make archive to copy active output into:
data/archives/runs/YYYY/MM/YYYYMMDDTHHMMSSZ/
Each archive includes a SHA-256 manifest, timestamps, Git revision, provenance,
and the copied runtime files. make reset always creates and verifies this
archive before clearing active state.
tess_candidate_finder/
├── dashboard.py # full-screen terminal survey interface
├── data_client.py # astroquery metadata and lightkurve product access
├── region.py # quiet-field target selection and checkpoints
├── search.py # interface plus BLS and TLS implementations
├── vetting.py # reusable candidate quality checks
├── notifier.py # console notification adapter
├── monitor.py # analysis service and optional batch/continuous loop
├── storage.py # compact metadata and candidate JSON persistence
├── config.py # shared defaults and thresholds
├── cli.py # argparse entry point
└── web/
└── app.py # placeholder FastAPI interface
tests/ # isolated unit tests (no network calls)
docs/en/ # English project documentation
docs/th/ # เอกสารโครงการภาษาไทย
scripts/ # archive/reset maintenance utility
data/ # active data, metadata, and timestamped archives
.github/ # CI and contribution templates
Makefile # supported end-user commands
README.th.md # Thai root guide
CHANGELOG.md # bilingual English/Thai changelog
The AnalysisService owns the application workflow without depending on a
particular user interface. The CLI calls it today; a scheduled monitor and the
future FastAPI/Flask UI can use the same service. Notifier is an abstraction
that can later publish candidates through a browser, email, or push service.
A small FastAPI placeholder is included. Install the web extra and start it with:
python -m pip install -e ".[web]"
uvicorn tess_candidate_finder.web.app:app --reloadGET /health is ready now. A production analysis endpoint should run the
CPU-intensive search in a task queue rather than in the request process.
make testTests use synthetic arrays and mocks; CI never downloads TESS products.
Start with make validate and choose one known planet. Read its light curve,
search progress, and saved evidence while already knowing that a real transit
is present. Next, run make tic ID on an unfamiliar star and compare the
result. Finally, inspect Limitations and design one
additional vetting test. This progression teaches detection, reproduction,
skepticism, and experimental design—not just command-line operation.
make validate is a separate, network-backed integration workflow. It fetches
real TESS light curves for ten confirmed transiting-planet hosts, runs the
production BLS search, and compares the strongest recovered period with the
NASA Exoplanet Archive value:
make validateThe published period and common ½×/2× BLS harmonics are accepted within 2% and
reported explicitly. All ten targets must pass for a successful exit status.
MAST acquisition problems are classified as ERROR, while valid data with the
wrong recovered period is FAIL. Reports are written to
data/validation/<UTC timestamp>.json and included by make archive.
This is a repeatable recovery smoke test, not proof of completeness or a measured false-positive rate.
Initial end-to-end acceptance run on 2026-07-27:
PASS 10
FAIL 0
ERROR 0
All ten signals were recovered at their published periods; no harmonic match
was needed. The retained report is
data/validation/20260727T025811Z.json.
Use the issue and pull request templates in .github/. Add focused tests for
behavioral changes, document user-facing changes, and run make test before
submitting a pull request.