Operator UI guide

Added in version 1.6.

The HTTP service ships an optional browser UI mounted at /ui. It is deliberately tiny — a single static page with vanilla ES modules and Tailwind via CDN, no build step — and is meant for a single operator driving runs end-to-end without curl. For automation, scripted workflows, or multi-user deployments, talk to the JSON endpoints directly.

Open the UI

$ docker run --rm -p 8000:8000 -v "$PWD/.runs:/data" \
    ghcr.io/california-planet-search/radvel-api:latest
$ open http://localhost:8000/ui

If the page renders an empty shell, the service is healthy but RADVEL_API_ENABLE_UI is false and the routes return 404 — see Disabling the UI below.

Page tour

Runs list (#/runs)

The home page lists every run created on the server with its run_id, target starname, planet count, and creation time. Clicking a row drills into the run detail view. The + New run button in the top-right opens the create form.

Note

Screenshots are regenerated by maintainers via scripts/regen_ui_screenshots.py (Playwright-based) and committed to docs/_static/screenshots/. See Refreshing UI screenshots in the project’s CLAUDE.md.

Create a run (#/runs/new)

Three tabs let you build a run in whichever form is most convenient:

  • Form — guided builder. Fill in starname, instrument names, fitting basis, planet count, then per-planet per/tc/k fields (each with a “vary” checkbox), and the standard prior toggles (eccentricity, positive-K, dvdt/curv Gaussian, jitter hardbounds). Click Preview JSON to inspect what will be submitted, or Create run to POST /runs directly. The form covers ~80% of configurations; drop into the JSON tab for anything more exotic.

  • JSON — paste a full setup payload (the schema is documented in Run RadVel as a service). Load example fills in the epic203771098 two-planet payload. Validation errors from Pydantic surface as a structured 422 in a red panel below the textarea.

  • Upload .py — only shown when RADVEL_API_ALLOW_PY_UPLOAD=true. Pick an existing radvel setup module from disk (the same Python file the CLI consumes) and upload it. The server imports the module to extract metadata, then the rest of the pipeline runs against the .py directly with no JSON round-trip. Disabled by default because the upload executes arbitrary Python on the server.

On success any of the three paths navigate to the new run’s detail page.

Run detail (#/runs/{id})

Every CLI step has a button: Fit, MCMC, NS, Derive, IC compare, Tables, Plots (rv/corner), Report. Buttons are enabled or disabled based on the run’s .stat state machine — for example, the corner plot is disabled until MCMC or NS has produced chains. Hovering a disabled button shows the prerequisite as a tooltip.

MCMC and NS open a small modal so you can set nsteps, nwalkers, ensembles, and the serial flag before kickoff. Submitting the modal navigates to the live job view.

Live MCMC progress (#/runs/{id}/jobs/{job_id})

Polls GET /jobs/{id} every two seconds and renders a progress bar plus the convergence telemetry from radvel.mcmc.statevars. Each field is documented in Introduction to Autocorrelation Times:

  • nsteps_complete / totsteps — production-phase progress.

  • rate, ar — sampling rate (steps/s) and acceptance fraction.

  • minafactor, maxarchange — autocorrelation diagnostics.

  • mintz, maxgr — Gelman-Rubin and T_z across ensembles.

  • ismixed, burn_complete — boolean phase flags.

The Cancel button issues DELETE /jobs/{id}; the job reaches the cancelled terminal state within a few seconds.

Files (#/runs/{id}/files)

Lists every file the pipeline wrote (.stat, _post_obj.pkl, chain CSVs, plot PDFs, the report PDF) with size and modified time. Each row is a download link. The chain CSV only appears once MCMC has finished; the report PDF only after POST /runs/{id}/report.

Disabling the UI

Set RADVEL_API_ENABLE_UI=false to unwire the routes. /ui and /ui/{path} return 404. The kill-switch exists so you can deploy the same image on a shared / headless host without exposing the SPA to anyone who can reach /healthz. JSON endpoints stay available.

Air-gapped Tailwind

The UI loads Tailwind from cdn.tailwindcss.com. To run on a host without internet egress:

  1. Vendor a copy of Tailwind locally:

    curl -fsSL https://cdn.tailwindcss.com -o tailwind.min.js
    
  2. Mount it into the container at /usr/local/lib/python3.12/site-packages/radvel/api/static/tailwind.min.js.

  3. Edit index.html (or override via a small bind-mount) to reference /ui/tailwind.min.js instead of the CDN URL.

We deliberately don’t bundle Tailwind by default — the CDN script keeps the image ~50 KB lighter and ensures dynamic utility classes work without a configured purge step.

Browser support

Latest Chrome, Firefox, and Safari. There is no transpiler or polyfill shim; the UI is plain ES modules. IE / very old Edge are not supported.

Keyboard shortcuts

g r

Go to runs list.

g n

Go to “new run”.

?

Show shortcut help.