Python Backend
Python modules are called via a persistent forge_dispatcher.py session. The forge_studio package provides the full API for logging, progress, convergence, and image preview.
Module Structure
Every Python module must export a run() function:
def run(config_path: str) -> list[str]:
...
return [output_path]config_path— path to the JSON config written by FORGE Studio.- Return value — list of absolute output file paths. These become the inputs for the next pipeline stage.
Minimal Example
"""Minimal FORGE Studio Python module."""
import os
import numpy as np
from forge_studio import forge_log, forge_read_config
def run(config_path: str) -> list[str]:
config = forge_read_config(config_path)
output_dir = config["output_dir"]
forge_log("info", "starting")
result = np.zeros((64, 64, 32), dtype=np.float32) # replace with real recon
out_path = os.path.join(output_dir, "result.npy")
np.save(out_path, result)
forge_log("info", "done, wrote %s", os.path.basename(out_path))
return [out_path]Iterative Reconstruction Example
import os
import numpy as np
from forge_studio import (
forge_log, forge_read_config, forge_param,
forge_progress, forge_progress_done, forge_convergence,
)
def run(config_path: str) -> list[str]:
config = forge_read_config(config_path)
output_dir = config["output_dir"]
input_path = config["input_paths"][0]
n_iter = forge_param(config, "n_iter", default=100)
step_size = forge_param(config, "step_size", default=0.01)
forge_log("info", "starting: n_iter=%d step_size=%.4f", n_iter, step_size)
x = np.zeros((64, 64, 32), dtype=np.complex64)
for i in range(1, n_iter + 1):
# --- your reconstruction update here ---
error_norm = 1.0 / i
penalty = 0.5 / i
forge_progress("iter", i, n_iter, "Iterating",
postfix=f"err={error_norm:.3g}")
forge_convergence("iter", i, error_norm, penalty)
forge_progress_done("iter")
out_path = os.path.join(output_dir, "recon.npy")
np.save(out_path, x)
forge_log("info", "done")
return [out_path]API Reference
forge_read_config(config_path: str) -> dict
Loads and validates the step config JSON. Automatically initialises the session state so all other forge_* functions work without extra setup.
config = forge_read_config(config_path)
config["job_id"] # str — job identifier
config["step_id"] # str — step identifier
config["stage_index"] # int — 0-based stage number
config["input_paths"] # list[str] — input files from previous stage
config["output_dir"] # str — directory to write outputs
config["input_format"] # str — "twix" | "ismrmrd" | "mat" | "jld2" | "npy" | "npz"
config["params"] # dict — user-configured parameter values
# Optional acquisition context (when available):
config["channels"] # int — number of receive channels
config["platform"] # str — e.g. "VE11E", "XA61"forge_param(config: dict, name: str, default=None)
Reads a named parameter from config["params"]. Returns default if the key is absent, empty string, or empty list.
n_iter = forge_param(config, "n_iter", default=100)forge_log(level: str, message: str, *args)
Emits a log event visible in the Monitor tab console.
forge_log("info", "Starting calibration")
forge_log("warn", "Low SNR detected: %d channels", n_channels)
forge_log("error", "Convergence failed at iter %d", i)Levels: "debug", "info", "warn", "error".
When running outside FORGE Studio (e.g. in a script), messages are printed to stderr.
forge_progress(bar_id, current, max_val, label, postfix="")
Reports progress for a named progress bar. The first call creates the bar; subsequent calls update it.
forge_progress("recon", i, n_iter, "Reconstructing", postfix=f"err={err:.3g}")forge_progress_done(bar_id: str)
Marks a progress bar complete.
forge_progress_done("recon")forge_convergence(bar_id, iter, error_norm, penalty, **kwargs)
Emits a metrics event plotted on the Monitor tab convergence chart.
forge_convergence("recon", i, error_norm, penalty, step_size=alpha)**kwargs are additional named metrics shown in the chart.
forge_image_preview(bar_id: str, iter: int, volume: np.ndarray)
Emits orthogonal slice previews visible in the Monitor tab (if image preview is enabled).
# volume shape: (nx, ny, nz), any numeric dtype
forge_image_preview("recon", i, x)forge_is_session() -> bool
Returns True when the module is running inside a FORGE Studio session. Use for conditional behaviour:
if forge_is_session():
forge_log("info", "running in FORGE Studio")
else:
print("standalone mode")Running Outside FORGE Studio
All forge_* functions degrade gracefully when called outside a session:
forge_log→ prints tostderr.forge_progress→ prints a text progress line tostderr.forge_convergence→ prints metrics tostderr.forge_image_preview→ no-op.
This means you can test your module directly:
# Write a minimal config JSON first, then:
python3 my_module.py /tmp/test_config.jsonOr use the forge-session dev tool →.
Package Location
The forge_studio package lives at resources/python/forge_studio/ within the app bundle. It is added to sys.path automatically by the dispatcher. You do not need to install it.
For development, install the project's Python venv:
uv sync
.venv/bin/python3 -c "from forge_studio import forge_log; print('ok')"