Plug spectro-kernel into an existing app - BeSS dashboard¶
A short walkthrough showing how to migrate an existing spectroscopy app to lean on
spectro-kernel. We use the BeSS dashboard as the
running example because it is small and representative; the same recipe works for
staros-dashboard, aurorex-dashboard, or your own code.
The starting situation¶
BeSS dashboard currently re-implements two operations the kernel already provides:
- a FITS parser that rebuilds the wavelength axis from the WCS,
- a "normalise the continuum at the 95th percentile" step.
Two extra implementations no one wants to maintain. Migrating them to the kernel buys uniform behaviour with every other spectroscopy app and provenance (backend + literature references) for free.
The two-line migration¶
Replace parse_fits_spectrum and the percentile normalisation with two
run_algorithm calls:
from spectro_kernel import WorkContext, run_algorithm
from spectro_kernel.io import read_fits
def parse_fits_spectrum(path):
ctx = WorkContext(spectrum=read_fits(path))
run_algorithm("normalize_percentile", ctx, {"percentile": 95.0})
spec = ctx.spectrum
return {"wavelength": spec.wavelength.tolist(),
"flux": spec.flux.tolist()}
That is the entire change. The dashboard's React side, its API routes, its database, none of it changes. Only the FITS-and-normalise plumbing is rerouted through the kernel.
What you gain immediately¶
- One canonical FITS parser - same WCS reconstruction conventions as every other spectro-kernel-based app.
- SNR, line detection, line fitting for free - same
ctx, add three lines: Now the dashboard can show quality flags and identified lines without writing more code. - Provenance & reproducibility -
ctx.historyrecords every step (algorithm, version, parameters, hashes). You can quote "this measurement was produced with spectro-kernelnormalize_percentilev1.0.0" in a paper. - MCP-ready - the same dashboard can offer the same analysis to an agent later, no extra work.
Two integration shapes¶
flowchart LR
subgraph LIB["A · Library mode - same process"]
D1["BeSS backend (FastAPI)"] -->|import spectro_kernel| K1["spectro-kernel<br/>(in-process)"]
end
subgraph REMOTE["B · MCP mode - kernel hosted separately"]
D2["BeSS backend"] -->|HTTPS / MCP| K2["spectro-mcp on DigitalOcean<br/>(one shared kernel)"]
end
Mode A - import the library (the snippet above). Simplest, fastest, no network. The kernel runs in the dashboard's own Python process. Pick this when the dashboard is already Python and you don't need to share a kernel across services.
Mode B - talk to the remote MCP server. The dashboard calls a cloud-hosted spectro-kernel via the MCP protocol. Useful when the dashboard is not Python (Node/Go/Rust), or when several services should share one hardened kernel instance.
# Mode B sketch - Python backend, kernel lives on DigitalOcean
from fastmcp import Client
KERNEL = "https://spectro-mcp.example/mcp"
async def parse_fits_spectrum(url):
async with Client(KERNEL) as c:
sid = (await c.call_tool("create_session", {})).data["session_id"]
await c.call_tool("load_spectrum", {"session_id": sid, "path": url})
await c.call_tool("normalize_percentile",
{"session_id": sid, "params": {"percentile": 95.0}})
preview = (await c.call_tool("get_spectrum_preview", {"session_id": sid})).data
await c.call_tool("end_session", {"session_id": sid})
return preview
The result is identical to Mode A - same algorithm, same parameters, same numbers. That parity is the whole point.
A recommended migration order¶
- Replace the FITS parser only (1 file).
- Replace the normalisation (1 line).
- Add
snr_derand surface the value in the UI. - Add
detect_lines+ an overlay of identified lines. - Optionally pivot to Mode B once the cloud kernel is up.
Each step is independent, reversible, and visible in the UI within minutes.