Skip to main content

RHEPLICANT

Documentation Status

A REPLICa of an ANTenna — a JAX + Equinox framework for building differentiable replicas of single-antenna radio telescopes: horns, dipoles, and dishes alike. Documentation: rheplicant.readthedocs.io

A RHEPLICANT twin is one pure function from sky and instrument parameters to raw data. Because every stage — foregrounds, ionosphere, beam, receiver reflections, gain drifts, digitisation — is differentiable, the same twin that simulates an observation also calibrates it: gradients, Bayesian posteriors, Fisher forecasts, and neural surrogates all run through the instrument model itself, with no re-implementation.

from rheplicant.radio import assemble, GlobalSignalOperator, ForegroundOperator, GainOperator

twin = assemble(GlobalSignalOperator(...), ForegroundOperator(...), GainOperator(...))
observation = twin(state)          # simulate — and differentiate, fit, sample

First deployed for RHINO (a horn antenna targeting the 21 cm global signal); the core is domain-agnostic by construction.

The name

RHEPLICANT is REPLICANT wearing RHINO's horn. REPLICANT is itself a portmanteau of REPLICa and ANTenna — a digital twin is a replica, and this one is of a radio antenna — the two words overlapping on their shared A. Slip an H in behind the first letter and R… becomes RH…, the mark of RHINO, the horn antenna the framework was first built for:

R E P L I C A            replica
            A N T         antenna
─────────────────
R E P L I C A N T        replicant
  + H  →  RH…            (for RHINO)
─────────────────
R H E P L I C A N T      rheplicant

One-line gloss: a differentiable replica of a radio antenna — first, of RHINO.

Philosophy

  1. Everything is an operator acting on a state. One contract — State in, State out — covers sky models, instrument effects, data processing, filters, even neural networks. If it transforms the scientific context, it is an operator; there is nothing else to learn.

  2. The twin is a differentiable function. Every physical parameter is a pytree leaf, so jit, grad, and vmap apply to the entire instrument. Systematics stop being nuisances you correct for and become parameters you infer, forecast, and marginalise.

  3. Composition is physics — and it is implicit in the signal path. Sequential effects chain (Pipeline), independent contributions add (SumOperator), switched paths select (SelectOperator). The canonical signal-path graph knows how elements connect, so assemble(*operators) builds the right composition from a set: provide only a sky and a beam, get exactly the beam-convolved sky — partial models come free.

  4. Purity everywhere. States are immutable (functional updates only), randomness is data flowing through the state (one seed reproduces an entire run), and operators have no hidden side effects. This is what makes the whole twin safe to transform.

  5. Forward models never contain inference. A single seam — build_forward_fn — turns any twin into f(params) -> prediction. Gradient and Adam calibrators, NumPyro posteriors, Fisher forecasts, and surrogate training all connect there; calibration never contaminates the instrument description.

  6. Interfaces first, physics second. Every operator ships as a trivial-but-runnable placeholder whose contract (shapes, PRNG consumption, linearity in calibration parameters) is real and tested. Real physics replaces function bodies, never interfaces — the native differentiable limTOD sky engine arrived exactly this way.

  7. Loud failure over silent wrongness. Structural validation at every boundary, trace-time (jit-safe) shape checks, provenance-tagged covariance matrices, assembly-time graph errors. In a framework built to chase 0.1 % systematics, a wrong number is worse than an exception.

  8. The core is domain-agnostic. rheplicant.core never imports the radio layer (a test enforces it). Radio astronomy is the first application, not the design center.

Install

pip install rheplicant
# or, for development:
git clone https://github.com/zzhang0123/rheplicant
cd rheplicant && uv sync          # extras: uv sync --extra numpyro

Requires Python ≥ 3.11, jax ≥ 0.5, equinox ≥ 0.13. Distribution and import name are the same: rheplicant.

Sixty seconds of RHEPLICANT

import jax, jax.numpy as jnp, equinox as eqx
from rheplicant import State, Coordinates
from rheplicant.radio import assemble, SkyOperator, GainOperator, NoiseOperator
from rheplicant.inference import build_forward_fn, GradientCalibrator

state = State(
    coords=Coordinates(time=jnp.linspace(0, 60, 128),
                       freq=jnp.linspace(60e6, 85e6, 32)),
    key=jax.random.key(0),
    meta={"telescope": "my-antenna"},
)

# 1. Simulate: provide operators; the signal-path graph composes them.
twin = assemble(
    SkyOperator(amplitude=jnp.array(1e3)),
    GainOperator(gain=jnp.array(1.1)),          # the truth to recover
    NoiseOperator(sigma=jnp.array(0.5)),
)
observed = eqx.filter_jit(twin)(state)

# 2. Calibrate: freeze everything except the gain, descend the gradient.
model = twin.replace_node("gain", GainOperator(gain=jnp.array(1.0)))
spec = jax.tree.map(lambda _: False, model)
spec = eqx.tree_at(lambda p: p["gain"].gain, spec, replace=True)
forward, params0 = build_forward_fn(model, state, filter_spec=spec)
params_fit, losses = GradientCalibrator(learning_rate=2e-7, n_steps=200).fit(
    forward, params0, observed.data
)
print(jax.tree.leaves(params_fit)[0])           # ~1.1

The same forward plugs into NUTS posteriors (to_numpyro_model), Fisher forecasts (fisher_information), and neural-surrogate training — see the guided tour.

What is in the box

  • CoreState (immutable pytree context), Pipeline / SumOperator / SelectOperator composition, SignalGraph + assemble (graph-guided auto-composition with lit/dim mermaid & HTML rendering).
  • Radio — a 29-node canonical signal-path graph covering every element of a single-antenna experiment: sky components, ionosphere, RFI, shared chromatic beam, noise-wave/reflection terms, CW tone and switched calibration loads, gain, thermal noise, EMI, ADC, flagging, averaging — plus a modular sky engine (limTOD bridge / projection matrices / m-mode / native differentiable limTOD) and linear analysis filters (sidereal, sky-space map-making, fringe-rate/delay).
  • Inference — gradient & Adam calibrators, NumPyro bridge with pytree priors and posterior predictive, Fisher / Cramér-Rao / delta-method uncertainty propagation, Monte Carlo pushforward, NeuralOperator surrogate stages, MomentRFI flagging bridge, masked likelihoods.

Documentation

Rendered docs: rheplicant.readthedocs.io (Sphinx + furo; build locally with uv run sphinx-build -b html docs docs/_build/html).

Document What it covers
Guided tour The complete API, top to bottom, with runnable snippets
Operator catalog Every operator: graph node, role, parameters
Architecture Design decisions D1–D13, element taxonomy, physics roadmap
Changelog What arrived when
examples/ Four end-to-end runnable demos

Status

The architecture and inference layer are complete and tested end-to-end (330+ tests, ~96 % coverage, jit+grad+vmap through the full twin; assembly is regression-tested bitwise against hand-built composition). Radio operator physics is deliberately placeholder pending ports from limTOD and friends — except the native differentiable sky engine, which is real. Conventions: degrees in public APIs, radians internally; strings in meta (static), numbers in coords/env/aux (traced); one seed reproduces a run.

No CI yet — run uv run pytest and uv run ruff check before pushing.

Developers and maintainers

  • Zheng Zhang
  • Phil Bull
  • Jordan Norris
  • Rashi Srivastava

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rheplicant-0.1.2.tar.gz (115.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rheplicant-0.1.2-py3-none-any.whl (87.8 kB view details)

Uploaded Python 3

File details

Details for the file rheplicant-0.1.2.tar.gz.

File metadata

  • Download URL: rheplicant-0.1.2.tar.gz
  • Upload date:
  • Size: 115.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for rheplicant-0.1.2.tar.gz
Algorithm Hash digest
SHA256 4ba6e120e9e1a0974c96c33cd1aef02209615ae251944d7b22a94028f2d41b2c
MD5 92a635689e8dea7eadb00eb3378d35d3
BLAKE2b-256 d7913dd990d0d21c41a125b653937d97329a7c08160709e594619e1253d40690

See more details on using hashes here.

Provenance

The following attestation bundles were made for rheplicant-0.1.2.tar.gz:

Publisher: publish.yml on zzhang0123/rheplicant

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rheplicant-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: rheplicant-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 87.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for rheplicant-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 6180bf0bf6cd560652188be698fbe5ff61597184fc9c6f6e1b304af4da9b3ef6
MD5 4e791845d871d94a80c8b651666d0669
BLAKE2b-256 1f4ea44862682a94b26f18b8315f6481a4aee08f124be8e3dcf5fdc4f388ed55

See more details on using hashes here.

Provenance

The following attestation bundles were made for rheplicant-0.1.2-py3-none-any.whl:

Publisher: publish.yml on zzhang0123/rheplicant

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.0

2 files

0.1.4

2 files

0.1.3

2 files

This release

0.1.2 This release

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page