Skip to main content

Scientific Dashboard

A Python data pipeline with an interactive visualization front-end. The workflow runs matplotlib in a container; the browser renders the output image in real time.

How it works

Loading diagram...
  1. The parameter metaframe emits JSON configuration as outputs
  2. The Python container receives the config as /inputs/config.json, runs the computation, and writes a plot to /outputs/plot.png
  3. The image viewer metaframe receives plot.png and displays it

Container code

# run.py — receives config.json, writes plot.png
import json, os
import matplotlib.pyplot as plt
import numpy as np

inputs_dir = os.environ["JOB_INPUTS"]
outputs_dir = os.environ["JOB_OUTPUTS"]

with open(os.path.join(inputs_dir, "config.json")) as f:
config = json.load(f)

x = np.linspace(0, 2 * np.pi, config.get("points", 100))
y = np.sin(x * config.get("frequency", 1))

fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_title(config.get("title", "Output"))

output_path = os.path.join(outputs_dir, "plot.png")
fig.savefig(output_path, dpi=150, bbox_inches="tight")

Dockerfile

FROM python:3.12-slim
RUN pip install matplotlib numpy
COPY run.py /app/run.py
CMD ["python", "/app/run.py"]

metapage.json

{
"version": "2",
"metaframes": {
"params": {
"url": "https://editor.mtfm.io/#?mode=json"
},
"compute": {
"url": "https://container.mtfm.io/#?queue=<your-queue>&image=<your-image>",
"inputs": [
{ "metaframe": "params", "source": "value", "target": "config.json" }
]
},
"viewer": {
"url": "https://image.mtfm.io/",
"inputs": [
{ "metaframe": "compute", "source": "plot.png", "target": "image" }
]
}
}
}

Embedding in your application

import { renderMetapage } from "@metapages/metapage";

const definition = await fetch("https://metapage.io/m/<id>/metapage.json").then(r => r.json());

const { setInputs } = await renderMetapage({
definition,
rootDiv: document.getElementById("dashboard"),
onOutputs: (outputs) => {
// Access outputs from any metaframe by key
const plotUrl = outputs?.["compute"]?.["plot.png"];
},
});

// Push configuration into the workflow programmatically
setInputs({ "params": { value: JSON.stringify({ frequency: 3, points: 200 }) } });