Metadata-Version: 2.4
Name: orblet
Version: 0.1.1
Summary: Atoms for Keplerian orbit analysis: forward models, likelihoods, design matrices and linear solves, period search, element conversion. Arrays in, results out.
Author-email: Sahar Shahaf <sahar.shahaf@gmail.com>
License-Expression: MIT
Project-URL: Repository, https://github.com/saharsh1/orblet
Project-URL: Issues, https://github.com/saharsh1/orblet/issues
Keywords: astronomy,binary-stars,orbits,astrometry,radial-velocity,kepler
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Astronomy
Requires-Python: <3.13,>=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy<3,>=2
Requires-Dist: scipy<2,>=1.14
Requires-Dist: astropy<8,>=7
Requires-Dist: matplotlib<4,>=3.8
Provides-Extra: sampling
Requires-Dist: emcee<4,>=3.1; extra == "sampling"
Provides-Extra: plots
Requires-Dist: corner<3,>=2.2; extra == "plots"
Provides-Extra: tables
Requires-Dist: pandas<4,>=2; extra == "tables"
Provides-Extra: progress
Requires-Dist: tqdm>=4.60; extra == "progress"
Provides-Extra: all
Requires-Dist: emcee<4,>=3.1; extra == "all"
Requires-Dist: corner<3,>=2.2; extra == "all"
Requires-Dist: pandas<4,>=2; extra == "all"
Requires-Dist: tqdm>=4.60; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Dynamic: license-file

# orblet <img src="https://raw.githubusercontent.com/saharsh1/orblet/main/docs/assets/orblet.png" alt="orblet" height="44" align="right">

Atoms for Keplerian orbit analysis. Forward models, likelihoods, design
matrices and linear solves, period search, element conversion, plotting —
each a function that takes arrays and returns a result, with its units,
frames and assumptions stated in its docstring.

orblet is **not a solver**. It does not know what a Gaia epoch is, does not
read files, and does not contact the network. You build the pipeline; orblet
supplies the pieces.

```python
from orblet import ti_design_matrix, linear_solve_ti, ti_to_kepler

X = ti_design_matrix(t_mjd, psi_rad, parallax_factor_al, P_days, e, tau, epoch_ref_mjd)
fit = linear_solve_ti(along_scan_mas, sigma_mas, X)
elements = ti_to_kepler({"A": fit.beta[0], "B": fit.beta[1], "F": fit.beta[2], "G": fit.beta[3]})
```

## Install

```
pip install "orblet[all]"
```

To follow the repository instead of a release, install from GitHub:

```
pip install "orblet[all] @ git+https://github.com/saharsh1/orblet.git"
```

or from a local clone, which is the right choice while you are editing it:

```
git clone https://github.com/saharsh1/orblet.git
pip install -e "./orblet[all]"
```

Drop `[all]` for the four core dependencies only — numpy, scipy, astropy,
matplotlib — which is all a fresh install needs to run the atoms and the
quickstarts. The extras (`emcee`, `corner`, `pandas`, `tqdm`; also available
one at a time as `[sampling]`, `[plots]`, `[tables]`, `[progress]`) are each
imported inside the one function that uses them, so a missing extra fails
that call with a message naming it and leaves everything else working.

## What is here

| | |
|---|---|
| `orblet.model` | forward models: RV curve, along-scan astrometry, Thiele-Innes and Campbell photocentre orbits |
| `orblet.likelihood` | Gaussian log-likelihoods with jitter, per channel |
| `orblet.kepler` | the Kepler-equation solver |
| `orblet.design` / `orblet.solve` | design-matrix builders and the generalised-least-squares linear solves for RV and astrometry |
| `orblet.search` / `orblet.periodogram` | the Thiele-Innes frequency scan; Lomb-Scargle and phase-distance-correlation periodograms |
| `orblet.elements` | Thiele-Innes → Campbell, NSS convention, element extraction from chains |
| `orblet.priors` | prior classes and the log-prior composer |
| `orblet.sampling` / `orblet.chain_stats` | emcee helpers; quantiles and circular summaries of chains |
| `orblet.interpret` | companion mass and the astrometric mass-ratio function |
| `orblet.simulate` | a synthetic-orbit simulator and a parallax-consistent cadence, for tests and tutorials |
| `orblet.parallax` | per-direction parallax factors from a DE432s ephemeris |
| `orblet.plotting` | orbit, residual, sky-overlay and corner plots |

The front door — `from orblet import <name>` — exposes 35 names and imports
nothing heavy: `import orblet` pulls in no scipy, no matplotlib, no astropy.
Each name resolves on first use.

## Conventions

Every public function states them in its docstring. The ones that bite:

- radial velocity: positive is receding; `omega` is the **primary's** argument of periastron
- period in **days** at the public surface (Keplerian years only inside the Kepler solver)
- `tau` is the periastron phase in `[0, 1)`; `tp = tau * P + epoch_ref_mjd`
- astrometric amplitudes `A, B, F, G` are **photocentre** amplitudes in mas, positive-amplitude convention; the parallax term enters as `parallax_mas * parallax_factor_al`, additive
- Gaia's `pmra` is already `mu_alpha*` — never apply `cos(dec)` again
- **a seed is initialisation, never a prior**: a starting point for a sampler carries no evidence

## Four laws, each a test

1. A public name **is** the object it claims to be — no silent wrappers.
2. The numerical core does not move: byte-identity baselines pin the forward
   models, the likelihoods and the design columns.
3. Conventions hold: RV sign, primary-frame ω, τ → tp, time scales.
4. orblet imports nothing outside itself, the four dependencies and the
   standard library.

## Status

Grew inside the `gaia-orbits` repository until 2026-09-24; developed here
since, and consumed there as an installed dependency.

Three simulator presets ship. `OrbitSimulator.bh1_like()` is the one the
quickstarts use, through `load_simulated_inputs(scenario="bh1")`: an
illustrative orbit on an invented sky position, with a cadence whose parallax
factor is coupled to that position, so injecting and removing the parallax
signal use the same array and closure is exact. `toy_orbit()` is a compact
short-period orbit for quick smoke tests. `bh3_like()` carries orbital numbers
rounded from a published system and is useful for a realistic-looking truth;
pair it with `DemoParallaxConsistentCadence` for anything closure-grade. The
`scenario=` parameter and the `bh1`/`toy` naming are slated to be simplified.

## Licence

MIT.
