◆ FORGE Suite
GitHubMechanical Neuroimaging Lab · Univ. of Delaware
Skip to content

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:

python
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 ​

python
"""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 ​

python
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.

python
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.

python
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.

python
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.

python
forge_progress("recon", i, n_iter, "Reconstructing", postfix=f"err={err:.3g}")

forge_progress_done(bar_id: str) ​

Marks a progress bar complete.

python
forge_progress_done("recon")

forge_convergence(bar_id, iter, error_norm, penalty, **kwargs) ​

Emits a metrics event plotted on the Monitor tab convergence chart.

python
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).

python
# 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:

python
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 to stderr.
  • forge_progress → prints a text progress line to stderr.
  • forge_convergence → prints metrics to stderr.
  • forge_image_preview → no-op.

This means you can test your module directly:

bash
# Write a minimal config JSON first, then:
python3 my_module.py /tmp/test_config.json

Or 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:

bash
uv sync
.venv/bin/python3 -c "from forge_studio import forge_log; print('ok')"

FORGE Studio