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.

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.0.tar.gz (114.5 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.0-py3-none-any.whl (87.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: rheplicant-0.1.0.tar.gz
  • Upload date:
  • Size: 114.5 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.0.tar.gz
Algorithm Hash digest
SHA256 42f7d3ef665b73e5b220ce34c59204f27c0aeccb036b060ea40dd98d96a8e2aa
MD5 7b608da8d30514e56ff4183bfed69f86
BLAKE2b-256 c3801808896d7016b804f709a4c886803cafa2d53d528798c9f8505d07ba3b69

See more details on using hashes here.

Provenance

The following attestation bundles were made for rheplicant-0.1.0.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.0-py3-none-any.whl.

File metadata

  • Download URL: rheplicant-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 87.5 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c1aeb3a353914dc2255c12d1fbd1de287527dcc9674e1fa1f6b6c4b8d3e6235f
MD5 1d22feff06b0a8c1e7b8026e5c13b070
BLAKE2b-256 4c30490ab017d311aeebe01736cce4423199d2706a557f7d30b0240f48b57e8e

See more details on using hashes here.

Provenance

The following attestation bundles were made for rheplicant-0.1.0-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

0.1.2

2 files

0.1.1

2 files

This release

0.1.0 This release

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