The Joker [YO-ker] /’joʊkər/


The Joker [1] is a custom Monte Carlo sampler for the two-body problem that generates posterior samplings in Keplerian orbital parameters given radial velocity observations of stars. It is designed to deliver converged posterior samplings even when the radial velocity measurements are sparse or very noisy. It is therefore useful for constraining the orbital properties of binary star or star-planet systems. Though it fundamentally assumes that any system has two massive bodies (and only the primary is observed), The Joker can also be used for hierarchical systems in which the velocity perturbations from a third or other bodies are much longer than the dominant companion. See the paper [2] for more details about the method and applications.


Science demonstrations

Getting started

Generating samples with The Joker requires three things:

  1. The data, RVData: radial velocity measurements, uncertainties, and observation times

  2. The priors, JokerPrior: the prior distributions over the parameters in The Joker

  3. The sampler, TheJoker: the work horse that runs the rejection sampler

Here, we’ll work through a simple example to generate poserior samples for orbital parameters given some sparse, simulated radial velocity data (shown below). We’ll first use these plain arrays to construct a RVData object:

>>> import astropy.units as u
>>> import thejoker as tj
>>> t = [0., 49.452, 95.393, 127.587, 190.408]
>>> rv = [38.77, 39.70, 37.45, 38.31, 38.31] *
>>> err = [0.184, 0.261, 0.112, 0.155, 0.223] *
>>> data = tj.RVData(t=t, rv=rv, rv_err=err)
>>> ax = data.plot() 
>>> ax.set_xlim(-10, 200) 

(Source code, png)


We next need to specify the prior distributions for the parameters of The Joker. The default prior, explained in the docstring of default(), assumes some reasonable defaults where possible, but requires specifying the minimum and maximum period to sample over, along with parameters that specify the prior over the linear parameters in The Joker (the velocity semi-amplitude, K, and the systemic velocity, v0):

>>> import numpy as np
>>> prior = tj.JokerPrior.default(P_min=2*, P_max=256*,
...                               sigma_K0=30*,
...                               sigma_v=100*

With the data and prior created, we can now instantiate the sampler object and run the rejection sampler:

>>> joker = tj.TheJoker(prior)
>>> prior_samples = prior.sample(size=100_000)
>>> samples = joker.rejection_sample(data, prior_samples) 

Of the 100_000 prior samples we generated, only a handful pass the rejection sampling step of The Joker. Let’s visualize the surviving samples in the subspace of the period \(P\) and velocity semi-amplitude \(K\). We’ll also plot the true values as a green marker. As a separate plot, we’ll also visualize orbits computed from these posterior samples (check the source code below to see how these were made):

(Source code)






thejoker Package


MAP_sample(samples[, return_index])

Return the maximum a posteriori sample.

is_P_Kmodal(samples, data[, n_clusters])


is_P_unimodal(samples, data)

Check whether the samples returned are within one period mode.

max_phase_gap(sample, data)

Based on the MPG statistic defined here:

periods_spanned(sample, data)

Compute the number of periods spanned by the data

phase_coverage(sample, data[, n_bins])

Based on the PC statistic defined here:

phase_coverage_per_period(sample, data)

The maximum number of data points within a period.

plot_phase_fold(sample[, data, ax, ...])

Plot phase-folded radial velocity curves for the input orbital parameter sample, optionally with data phase-folded to the same period.

plot_rv_curves(samples[, t_grid, rv_unit, ...])

Plot radial velocity curves for the input set of orbital parameter samples over the input grid of times.


Run the tests for the package.


JokerPrior([pars, poly_trend, v0_offsets, model])

This class controls the prior probability distributions for the parameters used in The Joker.

JokerSamples([samples, t_ref, n_offsets, ...])

A dictionary-like object for storing prior or posterior samples from The Joker, with some extra functionality.

RVData(t, rv, rv_err[, t_ref, clean])

Time-domain radial velocity measurements for a single target.

TheJoker(prior[, pool, random_state, ...])

A custom Monte-Carlo sampler for two-body systems.