Skip to content

virgil.aliases

Orbits whose epochs undersample the period: the alias bands N = round(T/P), a cheap position-level profile, and the band evidences from the closure phases of every epoch, with per-epoch error scales integrated out.

Orbits whose epochs undersample the period: alias bands and their evidences.

Provisional

May change in any 0.4.x release without a deprecation cycle.

When epochs are far apart compared with the period, the number of orbital cycles between them is ambiguous, and the likelihood has one narrow ridge per candidate count. fit_orbit_aliases labels the ridges N = round(T/P) (T the span), fits each band of periods directly to the observables of every epoch and weighs the bands by their marginal likelihoods. Positions only start the fits. Each epoch's observable blocks have an error scale with a Jeffreys prior, integrated out (marginal_loglike); a band's evidence is the sum over its modes of a Laplace approximation, checked by importance sampling.

Source: VanderPlas (2018), Lucy (2014), Price-Whelan et al. (2017), Jeffreys (1946), MacKay (1992).

AliasResult dataclass

Result of fit_orbit_aliases.

save and load keep it as JSON; scene, residuals and chi2_per_night use the best band.

Attributes:

Name Type Description
t_ref, times, span (float, ndarray, float)

Reference time of dt_peri, epochs' mean times (MJD), span (days).

bands list of AliasBandResult

One per alias band, by decreasing log_z.

samples dict

{N: {name: array}} draws for the best band and those with p > p_min_samples.

positions list of dict or None

Per-band position diagnostic (not saved).

primary_diam, vis_amp, p_range, prior, unseeded optional

The primary, the V^2 amplitude range, the period window (days), the prior ranges, and flagged nights that seeded nothing.

period_bound, period_at_lower_bound bool

P is unconstrained (best P within 10% of the top of p_range, or sigma(log P) at least a quarter of the window); the best P is within 10% of the bottom, where the sampling limit may have cut the truth.

window_capped, primary_fit, temper_f, temper_blocks, temper_f_raw, temper_rho

Lower end wanted when a default window was capped; the "auto" estimate; likelihood tempering (virgil.tempering).

outlier, night_flags, short_arc dict or None

Outlier mixture (eps, names, probability; near 1: the fit ignored the night); {night: {"code", "reason"}} of nights preferring another peak (reported only); the short-arc stage (band p is then conditional on the bands fitted).

t_ref instance-attribute

times instance-attribute

span instance-attribute

bands instance-attribute

samples instance-attribute

positions = None class-attribute instance-attribute

primary_diam = None class-attribute instance-attribute

vis_amp = None class-attribute instance-attribute

unseeded = () class-attribute instance-attribute

p_range = None class-attribute instance-attribute

period_bound = False class-attribute instance-attribute

primary_fit = None class-attribute instance-attribute

period_at_lower_bound = False class-attribute instance-attribute

window_capped = None class-attribute instance-attribute

temper_f = None class-attribute instance-attribute

temper_blocks = None class-attribute instance-attribute

temper_f_raw = None class-attribute instance-attribute

temper_rho = None class-attribute instance-attribute

prior = None class-attribute instance-attribute

short_arc = None class-attribute instance-attribute

outlier = None class-attribute instance-attribute

night_flags = None class-attribute instance-attribute

tempering property

Whether the tempering is outside what the likelihood can trust: a block f above 2, a raw f below 0.5, or a flat (not AR(1)) correlation in temper_rho. False without a factor.

Returns:

Type Description
bool

best property

The band with the highest evidence.

labels_free property

Whether the stars' labels are not determined by the data: in the best band, a mode that is the point reflection of the best mode has an evidence within LABELS_FREE_NATS (3 nats) of it. A comparison with another orbit may then accept the reflection (ω + 180°, Ω unchanged).

__init__(t_ref, times, span, bands, samples, positions=None, primary_diam=None, vis_amp=None, unseeded=(), p_range=None, period_bound=False, primary_fit=None, period_at_lower_bound=False, window_capped=None, temper_f=None, temper_blocks=None, temper_f_raw=None, temper_rho=None, prior=None, short_arc=None, outlier=None, night_flags=None)

__post_init__()

block_dof()

The block-keyed dof ({block: 1/f_b}) that reproduces this fit's tempering in marginal_loglike(block_dof=).

Returns:

Type Description
dict

Empty when no factor was applied.

table()

One row per band: raw χ²/ν, error scales (scales flat over epochs and blocks; epoch_scales one list per epoch), log Z (Laplace and IS), p, ESS and the flags.

scene(params=None)

The best band's fitted scene; see AliasBandResult.scene.

residuals(data, params=None)

Whitened residuals at the best band's best orbit; see AliasBandResult.residuals.

chi2_per_night(data, params=None)

Raw χ² and N per night at the best band's best orbit; see AliasBandResult.chi2_per_night.

to_json(path, n_samples=0)

Write the band table and each band's modes to path as JSON.

Parameters:

Name Type Description Default
path str or PathLike

The file to write.

required
n_samples int or None

Posterior draws written per band: none by default, the first n_samples, or, with None, all of them (what save does).

0
Notes

load reads the file back. positions is not written.

save(path)

Write the whole result to path as JSON, every posterior draw included; load is its inverse.

Non-finite numbers are written as null (strict JSON) and restored on loading. The positions diagnostic is not written.

load(path, primary_diam=UNRECORDED, vis_amp=UNRECORDED) classmethod

Read a result written by save or to_json.

Parameters:

Name Type Description Default
path str or PathLike

The JSON file.

required
primary_diam optional

Settings for a file written before they were saved (else the accessors raise); they override a file that records them.

UNRECORDED
vis_amp optional

Settings for a file written before they were saved (else the accessors raise); they override a file that records them.

UNRECORDED

Returns:

Type Description
AliasResult

samples are those written (none after to_json with the default); positions is None.

AliasBandResult dataclass

The fit of one alias band (see AliasResult).

A band from a legacy file lacking t_ref, primary_diam or vis_amp has UNRECORDED, and scene, residuals and chi2_per_night raise unless AliasResult.load was given them.

Attributes:

Name Type Description
t_ref float or None

Reference time (MJD) of best["dt_peri"].

primary_diam float, ``"fit"`` or None

A point (None), a uniform disk (mas), or one fitted (best["diam"]).

vis_amp tuple or None

Range of the per-epoch V^2 amplitude if fitted.

flipped, labels_free bool

The best mode has the stars' labels swapped; a point-reflected partner is within LABELS_FREE_NATS of it.

n instance-attribute

p_lo instance-attribute

p_hi instance-attribute

modes instance-attribute

log_z instance-attribute

log_z_is instance-attribute

ess instance-attribute

flagged instance-attribute

flags = dataclasses.field(default_factory=list) class-attribute instance-attribute

p = float('nan') class-attribute instance-attribute

best = dataclasses.field(default_factory=dict) class-attribute instance-attribute

chi2_red = float('nan') class-attribute instance-attribute

epochs = dataclasses.field(default_factory=list) class-attribute instance-attribute

flipped = False class-attribute instance-attribute

labels_free = False class-attribute instance-attribute

error = '' class-attribute instance-attribute

n_starts_failed = 0 class-attribute instance-attribute

t_ref = None class-attribute instance-attribute

primary_diam = None class-attribute instance-attribute

vis_amp = None class-attribute instance-attribute

__init__(n, p_lo, p_hi, modes, log_z, log_z_is, ess, flagged, flags=list(), p=float('nan'), best=dict(), chi2_red=float('nan'), epochs=list(), flipped=False, labels_free=False, error='', n_starts_failed=0, t_ref=None, primary_diam=None, vis_amp=None)

scene(params=None)

The scene the band was fitted with, at its best orbit.

Built from best (or params) as the fit's likelihood builds it; the swapped scene if flipped.

Parameters:

Name Type Description Default
params dict

Elements to use instead of best (diam only if fitted).

None

Returns:

Type Description
OrbitalBinary

Raises:

Type Description
ValueError

If the band failed, has no t_ref, or primary_diam is UNRECORDED or inconsistent with params.

residuals(data, params=None)

Whitened residuals of data at the best orbit, block by block.

The fit's own residuals on the quoted errors (float64, V^2 amplitude re-profiled), from virgil's model: they check the bookkeeping, not the model.

Parameters:

Name Type Description Default
data sequence of OIData

The epochs the band was fitted to, in order.

required
params dict

Elements to use instead of best; see scene.

None

Returns:

Type Description
list of dict

One {block name: residuals} per epoch, in whitened-residual order (the penalty rows of correlated closure phases are the last rows of "phi").

Raises:

Type Description
ValueError

If primary_diam or vis_amp is unrecorded, or data does not match the epochs.

chi2_per_night(data, params=None)

Raw chi-squared and its count of independent observables, per night.

On the quoted errors, at the best orbit. chi2 counts only the n independent observables; chi2_fit adds the fit's penalty rows.

Parameters:

Name Type Description Default
data sequence of OIData

The epochs the band was fitted to, in order.

required
params dict

Elements to use instead of best; see scene.

None

Returns:

Type Description
list of dict

Per epoch: chi2, chi2_fit, n, chi2_per_n, chi2_per_n_fit, vis_amp and blocks. Sum chi2 and n over nights for a pooled value; do not average chi2_per_n.

Raises:

Type Description
ValueError

As for residuals.

AliasBand dataclass

One period band, N = round(T/P): p_lo <= P <= p_hi (days).

n instance-attribute

p_lo instance-attribute

p_hi instance-attribute

__init__(n, p_lo, p_hi)

fit_orbit_aliases(data, p_range=None, *, positions=None, times=None, t_ref=None, a_range=(1.0, 30.0), flux_range=(0.01, 1.0), ecc_max=0.9, s_max=None, n_candidates=100, n_refine=6, n_random=None, k=9.0, eccs=None, sign_free=True, min_distance_mas=0.5, max_steps=200, n_is=2000, n_samples=1000, p_min_samples=0.01, flag_nats=1.0, ess_min=50.0, seed=0, checkpoint_dir=None, on_band=None, primary_diam='auto', diam_range=None, vis_amp=True, flip_flux=True, init=None, skip_flagged=True, n_bands_max=_N_BANDS_MAX, temper=True, batch_size=None, memory_budget=None, short_arcs=True, arc_jitter=ARC_JITTER, arc_delta_chi2=ARC_DELTA_CHI2, arc_min_gap=ARC_MIN_GAP, outlier_eps=0.0)

Weigh the period aliases of an undersampled orbit with the observables.

Each alias band (an integer number of orbits between the epochs) is fitted to all epochs and given an evidence; the defaults need no per-system arguments (how, settings).

Parameters:

Name Type Description Default
data sequence of OIData

One dataset per epoch.

required
p_range (float, float)

Period range (days); default period_window.

None
positions PositionData or EpochPositions

Seeds for the fits (else random orbits).

None
times optional

Epoch times and dt_peri reference (MJD; default the mean times), prior ranges (a_range in mas), eccentricity cap.

None
t_ref optional

Epoch times and dt_peri reference (MJD; default the mean times), prior ranges (a_range in mas), eccentricity cap.

None
a_range optional

Epoch times and dt_peri reference (MJD; default the mean times), prior ranges (a_range in mas), eccentricity cap.

None
flux_range optional

Epoch times and dt_peri reference (MJD; default the mean times), prior ranges (a_range in mas), eccentricity cap.

None
ecc_max optional

Epoch times and dt_peri reference (MJD; default the mean times), prior ranges (a_range in mas), eccentricity cap.

None
s_max optional

Epoch times and dt_peri reference (MJD; default the mean times), prior ranges (a_range in mas), eccentricity cap.

None
n_candidates optional

Search effort, sampling and a warm start.

100
n_refine optional

Search effort, sampling and a warm start.

100
n_random optional

Search effort, sampling and a warm start.

100
n_is optional

Search effort, sampling and a warm start.

100
n_samples optional

Search effort, sampling and a warm start.

100
seed optional

Search effort, sampling and a warm start.

100
init optional

Search effort, sampling and a warm start.

100
min_distance_mas optional

Modes closer than min_distance_mas (mas, along the orbit) are one; optimizer steps per start; bands with p above p_min_samples also get posterior samples; evidence margin (nats) and importance-sample size below which a band is flagged.

0.5
max_steps optional

Modes closer than min_distance_mas (mas, along the orbit) are one; optimizer steps per start; bands with p above p_min_samples also get posterior samples; evidence margin (nats) and importance-sample size below which a band is flagged.

0.5
p_min_samples optional

Modes closer than min_distance_mas (mas, along the orbit) are one; optimizer steps per start; bands with p above p_min_samples also get posterior samples; evidence margin (nats) and importance-sample size below which a band is flagged.

0.5
flag_nats optional

Modes closer than min_distance_mas (mas, along the orbit) are one; optimizer steps per start; bands with p above p_min_samples also get posterior samples; evidence margin (nats) and importance-sample size below which a band is flagged.

0.5
ess_min optional

Modes closer than min_distance_mas (mas, along the orbit) are one; optimizer steps per start; bands with p above p_min_samples also get posterior samples; evidence margin (nats) and importance-sample size below which a band is flagged.

0.5
checkpoint_dir optional

Bands finished in checkpoint_dir are reloaded; on_band is called with each band's result.

None
on_band optional

Bands finished in checkpoint_dir are reloaded; on_band is called with each band's result.

None
primary_diam optional

"auto" fits the primary diameter if resolved, a float (mas) fixes it, "fit" samples it (prior diam_range).

'auto'
diam_range optional

"auto" fits the primary diameter if resolved, a float (mas) fixes it, "fit" samples it (prior diam_range).

'auto'
vis_amp optional

Profiled V^2 amplitude; sign-free seeds; label-swapped refit at the flux ceiling; flagged nights seed nothing.

True
sign_free optional

Profiled V^2 amplitude; sign-free seeds; label-swapped refit at the flux ceiling; flagged nights seed nothing.

True
flip_flux optional

Profiled V^2 amplitude; sign-free seeds; label-swapped refit at the flux ceiling; flagged nights seed nothing.

True
skip_flagged optional

Profiled V^2 amplitude; sign-free seeds; label-swapped refit at the flux ceiling; flagged nights seed nothing.

True
temper bool or float

True estimates the evidence tempering (needs EpochPositions), a float

= 1 fixes it, False is off.

True
outlier_eps float

Outlier weight in [0, 1); default 0 (no mixture), unlike OrbitPipeline.

0.0
n_bands_max optional

Band cap, grid density, seed eccentricities, batching.

_N_BANDS_MAX
k optional

Band cap, grid density, seed eccentricities, batching.

_N_BANDS_MAX
eccs optional

Band cap, grid density, seed eccentricities, batching.

_N_BANDS_MAX
batch_size optional

Band cap, grid density, seed eccentricities, batching.

_N_BANDS_MAX
memory_budget optional

Band cap, grid density, seed eccentricities, batching.

_N_BANDS_MAX
short_arcs optional

Fit only the bands the short arcs admit (virgil.arcs); needs EpochPositions and skip_flagged, with every seeding night decided; otherwise every band is seeded from the positions.

True
arc_jitter optional

Fit only the bands the short arcs admit (virgil.arcs); needs EpochPositions and skip_flagged, with every seeding night decided; otherwise every band is seeded from the positions.

True
arc_delta_chi2 optional

Fit only the bands the short arcs admit (virgil.arcs); needs EpochPositions and skip_flagged, with every seeding night decided; otherwise every band is seeded from the positions.

True
arc_min_gap optional

Fit only the bands the short arcs admit (virgil.arcs); needs EpochPositions and skip_flagged, with every seeding night decided; otherwise every band is seeded from the positions.

True

Returns:

Type Description
AliasResult

Raises:

Type Description
RuntimeError

If every band fails (chained to the last error).

ValueError

If no band lies in p_range, or checkpoint_dir data cannot be hashed. Preflight likelihood errors propagate unchanged.

alias_bands(times, p_range)

The alias bands of the epochs within p_range.

Band N holds the periods T/(N + 1/2) <= P <= T/(N - 1/2) that fit N cycles, rounded, between the first and last epoch (span T), clipped to p_range. The bands are one cycle wide in frequency, so they tile the period prior without gaps. Periods above 2T form band N = 0: not an alias, but the part of the prior with less than one cycle across the span.

Parameters:

Name Type Description Default
times array - like

The epochs' times (days).

required
p_range (float, float)

The shortest and longest period (days) to consider.

required

Returns:

Type Description
list of AliasBand

Ordered by N (longest period last).

period_window(times, field, night_length, *, resolution, motion_fraction=0.5, span_factor=4.0, p_floor=_P_FLOOR)

The periods worth searching, from the data alone: (p_min, p_max).

The lower end is a Nyquist-style sampling limit (the companion must not move much in a night); the upper end is span_factor times the span. No published period enters (why).

Parameters:

Name Type Description Default
times array - like

The epochs' times (days).

required
field float

The largest companion separation (mas), the longest span within one night (days) and the finest resolution lambda/B_max (mas).

required
night_length float

The largest companion separation (mas), the longest span within one night (days) and the finest resolution lambda/B_max (mas).

required
resolution float

The largest companion separation (mas), the longest span within one night (days) and the finest resolution lambda/B_max (mas).

required
motion_fraction float

Fraction of resolution moved in a night (0.5), upper end in spans (4), shortest period in days (0.2).

0.5
span_factor float

Fraction of resolution moved in a night (0.5), upper end in spans (4), shortest period in days (0.2).

0.5
p_floor float

Fraction of resolution moved in a night (0.5), upper end in spans (4), shortest period in days (0.2).

0.5

Returns:

Type Description
(float, float)

(p_min, p_max) in days.

Raises:

Type Description
ValueError

If the epochs span no time, an input is not positive, or the window is empty.

position_profile(positions, bands, k=9.0, n_best=3, eccs=None, sign_free=False)

A cheap diagnostic: the best position-level χ² in each band.

For each band, the best Thiele–Innes fits (starting_orbits) of positions on a coherent period grid. Positions are lossy: use this to see which bands are viable and to seed the fits, not to weigh them.

With sign_free the orbits of the sign-free fit (each night's position known only up to its sign) are added to those of the signed fit: n_best of each.

Returns:

Type Description
list of dict

Per band: n, chi2 (best), period of the best orbit and the orbits [(KeplerOrbit, χ²), ...].