Getting Started

Everything on this site is generated by the clocks repository. To run it yourself:

Prerequisites

  • Python 3.12+
  • uv — handles the virtual environment and every dependency.

Install

git clone https://github.com/jbwhit/clocks.git
cd clocks
uv sync

Run the demos

Five animated demos plus the density figure. Rough runtimes on a laptop:

uv run demo-1d                  # → output/demo_1d.gif            (~2 min)
uv run demo-2d                  # → output/demo_2d.gif            (~3 min)
uv run demo-multi-mass          # → output/demo_multi_mass.gif    (~3 min)
uv run demo-multi-mass-2d       # → output/demo_multi_mass_2d.gif (~5 min)
uv run demo-model-comparison    # → output/demo_model_comparison.gif (~5 min)
uv run demo-density             # → output/demo_density.png       (~2 min)

Use the library

The same example as the repository README, executed live on this page — if you can read the output below, the install instructions above work:

import numpy as np

from clocks import (
    ClockArray,
    InferenceConfig,
    MassConfig,
    NoiseConfig,
    PriorConfig,
    SimulationConfig,
    infer,
    simulate,
)

clock_array = ClockArray(
    positions=np.array([[-6.0], [-3.0], [0.0], [3.0], [6.0]]),
    track_offset=1.0,
)
ground_truth = MassConfig(
    positions=np.array([[-2.0], [3.0]]),
    masses=np.array([0.6, 0.4]),
)

simulation = simulate(
    SimulationConfig(
        clock_array=clock_array,
        ground_truth=ground_truth,
        noise=NoiseConfig(observation_std=0.005),
        n_observations=40,
        seed=42,
    )
)

result = infer(
    simulation.observations,
    InferenceConfig(
        clock_array=clock_array,
        noise=NoiseConfig(observation_std=0.005),
        prior=PriorConfig(position_range=(-8.0, 8.0), mass_range=(0.1, 2.0)),
        n_particles=1500,
        n_masses=(1, 2, 3),
        seed=42,
    ),
)

print(result.best_model)
print(result.posterior_by_model)
2
{1: 0.0, 2: 1.0, 3: 0.0}

For fixed-K inference, pass an integer to n_masses; to drive the filter observation-by-observation (e.g. for animation), use build_particle_filter — both are documented in the README.

Next: Reproducibility — seeds, tests, and CI.