RHEPLICANT¶
A REPLICa of an ANTenna — a JAX model of a radio telescope, run as a digital twin. Built for RHINO, a horn antenna measuring the 21 cm global signal, and domain-agnostic underneath: horns, dipoles and dishes alike.
A RHEPLICANT twin is one pure function from sky and instrument parameters to raw data. Because every stage 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.
Four things it is built to do¶
Simulate what any stage of the experiment would produce — a sky, a receiver output, a processed product. Where you stop is a property of the graph.
Read the same twin backwards. Free any subset of what it contains; the noise model is the likelihood; the engine follows from the model’s structure.
Replace an expensive stage with a trained network and leave the graph’s shape untouched — or amortize the posterior itself.
Keep a campaign after its recordings are archived: compress each night to a fixed-size likelihood factor, then discard the data.
None of the four is a separate mode. They all read the same twin object, which is what makes the calibration you fit the simulator you trust.
Two nouns¶
An operator takes the whole scientific context and returns it one step later.¶
An operator takes the whole scientific context and returns it one step later.¶
StateThe complete scientific context — data, coordinates, environment, randomness, metadata. It is an organisation of references to buffers, not the buffers themselves, so a derived state allocates the shell and nothing else: 48 bytes, with a 16 MB array shared rather than copied. JAX arrays are immutable, which is what makes sharing safe.
OperatorOne step,
Statein andStateout. Sky models, instrument effects, calibration, filtering and neural networks are all the same kind of thing, and each carries its own physical parameters as differentiable leaves.
state.data always references what the instrument has produced so far.
For example: the sky engine produces the (n_time, n_freq) antenna
temperature, the antenna’s ohmic loss produces that array after loss, the
receiver produces a system temperature. Nothing is written in place — each
stage hands back a new State whose data points at its own result, while
the fields it did not touch go on pointing where they already did.
The sky map itself is not in state.data — it is a parameter of the sky
model, differentiable like every other, which is why a map can be inferred
rather than merely assumed.
Three ways to join them — and you rarely write any¶
Structure |
Combinator |
Physics it expresses |
|---|---|---|
Cascade |
|
sequential effects: each stage transforms what the last produced |
Sum |
|
independent contributions that add into one signal |
Switch |
|
alternative paths, one selected per time sample |
You normally write none of them. Declare the operators you want and
assemble reads the canonical signal path to decide
what joins to what — so the composition is a consequence of the physics you
declared, not something you wrote out. Reach for the three combinators directly
only when you are building a structure the template does not describe.
A canonical signal path is a template saying which operators exist and which
structure joins them: node kinds source, transform, junction
and selector map one-to-one onto “creates data”, cascade, sum and switch. You
provide a set of operators, and assemble folds
them into exactly those three combinators.
The template shipped as the default,
RADIO_GRAPH, is RHINO’s structure: a single-antenna,
switched-load, drift-scanning horn. It is a default, not the framework — the
machinery underneath knows nothing about radio astronomy, and another
instrument is another template registered the same way.
The eight principles the design follows
Everything is an operator acting on a state — one contract covers sky models, instrument effects, processing, filters, neural networks; and exactly three structures compose them.
The twin is a differentiable function —
jit/grad/vmapapply to the entire instrument; systematics become inferable parameters.Composition is physics, implicit in the signal path — cascades, sums and switches assemble themselves from the canonical graph, which is a template you can replace rather than a fixed instrument.
Purity everywhere — immutable states, randomness as data, one seed reproduces a run.
Forward models never contain inference — one seam serves every inference engine, and a
ParameterSpacere-parameterizes freely without ever editing the instrument description.Interfaces first, physics second — placeholder bodies, real tested contracts; ports replace functions, never structure.
Loud failure over silent wrongness — trace-time validation, provenance-tagged matrices, assembly-time graph errors.
The core is domain-agnostic — radio astronomy is the first application, not the design center (a test enforces the layering).
Where to start¶
You want to… |
Start here |
|---|---|
install it |
Install — limTOD resolves from PyPI; |
understand the whole thing in one sitting |
The guided tour — one worked example, simulated then inferred |
simulate an instrument |
|
write or run a YAML configuration |
Configuration — what a document contains and what v1 covers. A first document, start to finish, is the tutorial; the command line is what validates and runs it |
edit a YAML configuration in a browser |
Configuration workbench — Model, Config, Execute and Results over exact YAML, plus install and trusted-server boundaries |
turn a RHINO recording into a |
Ingestion — every other page starts from a |
see one instrument end to end |
|
fit or sample parameters |
Tutorial: an exact posterior or Tutorial: a gradient posterior first, then Inference for the rules they cite |
keep a campaign after the recordings are archived |
Evidence — accumulate likelihood factors, discard the data |
run something and read its output |
Examples — fifteen scripts, with measured wall clocks |
look something up |
The API reference, contracts between stages, design decisions |
Start here
Configuration
The instrument
- From the sky to the receiver
- The one identification
- The path, as the graph builds it
- Step 1 — the horn
- Step 2 — the antenna chain, assembled from the graph
- Step 3 — three effects, none standing in for another
- Step 4 — a real switching cycle
- Step 5 — closing the loop
- Step 6 — one differentiable object
- The horizon split, measured
- What is tested
- Sky engines: the general path and the drift-scan fast path
Inference
- Inference
- Tutorial: an exact posterior for a big linear block
- Step 1 — the world
- Step 2 — declare the block linear, and have the claim checked
- Step 3 — read the conditioning before solving
- Step 4 — the covariance is not given
- Step 5 — the mean, then exact draws
- Step 6 — is the answer honest?
- Step 7 — now break it on purpose
- Where each step’s rule comes from
- Next
- Tutorial: a gradient posterior, and how to tell it is wrong
- Step 1 — why this is not a conjugate solve
- Step 2 — priors, and two latents into one leaf
- Step 3 — the model
- Step 4 — the obvious run, and its diagnostics
- Step 5 — diagnose it: two hypotheses, both testable
- Step 6 — the fix, and two fixes that are not the fix
- Step 6b — now the answer
- Step 7 — an independent check
- Step 8 — does the model explain its data?
- Which engine
- A checklist for any NUTS run