Plugins
Plugins are how Magellon becomes a full processing platform — every cryo-EM algorithm (CTF estimation, motion correction, particle picking, 2D classification, …) runs through one contract, with form generation, lifecycle control, progress streaming, and multi-backend routing all handled by the framework.
The plugin catalog
Section titled “The plugin catalog”Magellon ships with a curated hub at magellon.org/plugins.
Each plugin is published as a .mpn archive — a zip containing the
plugin’s code, a manifest.yaml, and an optional bundled SDK wheel.
Today’s catalog includes:
| Plugin | Category | What it does |
|---|---|---|
fft | fft | Magnitude-spectrum FFT — the reference / always-on plugin. |
ctf | ctf | CTFFIND4 CTF estimation. |
motioncor | motioncor | MotionCor2 beam-induced motion correction (GPU). |
topaz | topaz_particle_picking | CNN-based particle picking + companion denoiser. |
template-picker | particle_picking | Cross-correlation template matching for particle picking. |
ptolemy | square_detection | ONNX models for low-mag square + med-mag hole detection. |
stack-maker | particle_extraction | Extracts boxed particles into RELION-style stacks. |
can-classifier | two_d_classification | Convolutional autoencoder 2D classification. |
magellon-sample-plugin | (sample) | Minimal worked example for plugin authors. |
Plugins are categorized by the cryo-EM step they implement. A
category (e.g. ctf) can have multiple backends (e.g.
ctffind4, future gctf) — operators pick which backend serves
each category, or pin a specific backend per-dispatch.
Installing a plugin
Section titled “Installing a plugin”Two paths into your Magellon deployment:
One-click install from the hub
Section titled “One-click install from the hub”In the Magellon admin panel, open Plugins → Browse hub, pick a
plugin, click Install. CoreService fetches the .mpn from the
hub, verifies its SHA256 against the catalog, and runs the install
pipeline. Done.
Under the hood:
POST /admin/plugins/install-from-hub {plugin_id, version}- CoreService fetches
https://magellon.org/v1/plugins/<id>.json, resolves the archive URL + sha256, downloads, verifies, then delegates to the standard install path. SHA mismatch fails closed.
A checksum mismatch hard-fails the install and leaves no partial state on disk. If you’re installing a self-hosted mirror or a fork, update the catalog YAML’s sha256 field to match your archive before pointing CoreService at it.
Upload a .mpn directly
Section titled “Upload a .mpn directly”For unpublished plugins, air-gapped sites, or forks: drag the
.mpn onto the Upload archive dialog. Same install pipeline,
different source of bytes.
Install method: uv vs docker
Section titled “Install method: uv vs docker”Each plugin manifest declares one or more install methods. CoreService picks the first whose host predicates pass:
uv— pure-Python plugins install into a per-plugin venv under<plugins_dir>/<plugin_id>/. Linux production usessystemctl --userfor restart-on-crash; Windows/macOS dev falls back to aPopensupervisor.docker— the plugin runs in a container; CoreService manages it via the docker CLI. Supports the full lifecycle including pause and replicas (next sections).
A slurm install method is scaffolded for HPC deployments but is not wired in by default. If you need Slurm-based dispatch, contributions are welcome — see the plugin authoring guide.
Running plugins
Section titled “Running plugins”Every installed plugin shows up on the Plugins page with its identity, install location, live status, and a controls row:
- Start / Stop / Restart — process / container lifecycle.
- Pause / Unpause — docker-only; freezes the container via cgroups (SIGSTOP). uv plugins show the control greyed out with a tooltip (“pause is docker-only — use Stop instead”).
- Scale — docker plugins declaring
resources.replicas.max > 1in their manifest get a “N / max” chip. Clicking opens a stepper that callsPOST /admin/plugins/<id>/scale {desired: N}. RMQ fan-out across the replica set is automatic.
A live Replicas drawer shows per-instance heartbeat freshness.
Multi-backend selection
Section titled “Multi-backend selection”When two plugins serve the same category (e.g. ctffind4 + a future
gctf both serving ctf), the runner UI shows a Backend picker
above the input form. Defaults to the operator-pinned default;
selection rides as target_backend on the dispatched TaskMessage
so the routing is deterministic. “Auto” preserves today’s default
routing.
The per-category drilldown page at
/panel/plugins/categories/<slug> lists every backend side-by-side
with status, replica count, and a one-click “Set as default” action.
Logs + upgrade
Section titled “Logs + upgrade”GET /admin/plugins/<id>/logs?tail=N— one-shot tail ofdocker logs --tail N(docker installs) or<install_dir>/app.log(uv-Popen) orjournalctl --user(uv-systemd).- Socket.IO
plugin_logchannel — live tail; clientsemit("join_plugin_room", {plugin_id})and receive one event per line. The React UI surfaces this on the per-plugin runner page and inline on cards whenHealthy=False. - Upgrade — the Update available chip on a card opens a
dialog that lists hub-published versions, runs a force-downgrade
check, and calls
POST /admin/plugins/<id>/upgrade-from-hub. RMQ requeues in-flight tasks from the killed old container to the surviving / upgraded one — no data loss, possibly duplicate work.
Restart policy
Section titled “Restart policy”Manifest lifecycle.restart_policy is one of no / on-failure /
always / unless-stopped. Docker plugins translate this directly
to docker run --restart=<policy>:<N>; systemd-user installs
parameterize the unit file’s Restart= line. uv-Popen installs are
restricted to no (no watchdog).
Writing your own plugin
Section titled “Writing your own plugin”The platform ships a CLI on magellon-sdk for the full author
workflow:
# 1. Scaffold a runnable skeleton.magellon-sdk plugin scaffold my-plugin --category ctf
# 2. Edit plugin/compute.py + plugin/plugin.py to do your thing.
# 3. Lint before pack — catches stale SDK wheels, missing install# backing files, unreasonable health-check timeouts, etc.magellon-sdk plugin lint my-plugin
# 4. Run the author's checks (lint + pytest + optional /health probe).magellon-sdk plugin test my-plugin
# 5. Pack into a .mpn archive.magellon-sdk plugin pack my-pluginResult: a my-plugin-0.1.0.mpn ready to upload via the admin
dialog or submit as a hub PR. See Plugin authoring
for the full guide.
Plugin layout
Section titled “Plugin layout”my-plugin/├── manifest.yaml # identity + install methods + lifecycle policy├── main.py # FastAPI lifespan + PluginBrokerRunner├── plugin/│ ├── __init__.py│ ├── plugin.py # PluginBase subclass — execute(input, reporter)│ └── compute.py # your algorithm (unit-testable, no SDK glue)├── Dockerfile # for the docker install method├── pyproject.toml # for the uv install method├── requirements.txt└── tests/ └── test_compute.pyThe framework handles discovery, schema exposure, job persistence, progress streaming, replicas, and lifecycle. Your plugin’s job is to:
- Declare inputs / outputs via Pydantic models that subclass the
category’s canonical
input_model/output_model. - Implement
execute(input_data, reporter), yielding progress viareporter.progress(percent, message). - Optionally expose
Capability.SYNCorCapability.PREVIEWfor sub-second HTTP interactions (the picker’s slider does this).
The SDK’s magellon_sdk.runner.PluginBrokerRunner ties the wire
contract to your execute — bus consume, decode, dispatch, encode
result, publish. You won’t touch RMQ or NATS directly.
Publishing to the hub
Section titled “Publishing to the hub”The magellon.org plugin hub is a curated, git-based catalog:
- Pack your plugin:
magellon-sdk plugin pack .→<id>-<v>.mpn. - Drop the
.mpnundermagellon-web/public/assets/plugins/. - Create
magellon-web/src/content/plugins/<id>-<v>.yamlwith metadata (see existing entries for the shape). - Open a PR. A reviewer verifies the SHA256, sets the tier
(
verifiedvscommunity), and merges. - CI/CD redeploys the static site; your plugin appears on /plugins within minutes.
A future magellon-sdk plugin publish will automate the pack → upload → YAML → PR flow end-to-end. For now, the manual steps above take under five minutes.