Skip to main content

Streamtrace SDK — decorator-based ML pipeline contracts for clinical AI

Project description

streamtrace

Decorator-based ML pipeline contracts for clinical AI. Define your pipeline once with typed decorators, get a validated execution DAG and a deployable frontend app.

Installation

pip install streamtrace

Install extras for the output types your pipeline produces:

pip install streamtrace[medical]    # NIfTI + DICOM (nibabel, pydicom, numpy)
pip install streamtrace[imaging]    # images + matplotlib (Pillow, matplotlib, numpy)
pip install streamtrace[plotting]   # interactive plots (matplotlib, plotly, bokeh)
pip install streamtrace[data]       # tabular output (pandas, numpy)
pip install streamtrace[mesh]       # 3D geometry (trimesh, numpy)
pip install streamtrace[all]        # everything

Quick start

import streamtrace as st

@st.app(title="Cardiac Segmentation", version="1.0.0",
        docker_base="pytorch/pytorch:2.1.0-cuda12.1-cudnn8-runtime",
        requirements=["nibabel", "scipy"])
class CardiacSegmentation:

    @st.input(title="CT Scan",
              widget=st.FileInput(accepted_types=[st.InputDataType.NIFTI]),
              returns="scan")
    def load_scan(self, path):
        import nibabel as nib
        return nib.load(path).get_fdata()

    @st.input(title="Threshold",
              widget=st.TextInput(default="0.5", placeholder="0.0 – 1.0"),
              returns="threshold")
    def set_threshold(self, value):
        return float(value)

    @st.preprocess(returns="normalized")
    def normalize(self, scan):
        lo, hi = scan.min(), scan.max()
        return (scan - lo) / (hi - lo + 1e-8)

    @st.infer(returns="raw_mask",
              device="cuda",
              weights_path="checkpoints/best.pth")
    def segment(self, normalized, threshold):
        import torch
        model = torch.load("checkpoints/best.pth", map_location="cpu")
        model.eval()
        with torch.no_grad():
            t = torch.FloatTensor(normalized).unsqueeze(0).unsqueeze(0)
            pred = model(t).squeeze().numpy()
        return (pred > threshold).astype("uint8")

    @st.postprocess(returns="mask")
    def clean(self, raw_mask):
        from scipy.ndimage import binary_fill_holes
        return binary_fill_holes(raw_mask).astype("uint8")

    @st.output(title="Segmentation",
               widget=st.FileOutput(data_type=st.OutputDataType.NIFTI,
                                    filename="segmentation.nii.gz"))
    def save(self, mask):
        import nibabel as nib
        return nib.Nifti1Image(mask, affine=None)

Pipeline contract

A Streamtrace pipeline is a class decorated with @st.app. Each method in the class maps to one node in the execution DAG via its decorator. Wiring is automatic: a method's parameter names are matched against the returns= alias of other nodes.

@st.input  →  @st.preprocess  →  @st.infer  →  @st.postprocess  →  @st.output

Decorators

Decorator Purpose Key args
@st.app Marks the pipeline class title, version, description, docker_base, requirements
@st.input User-provided value (file, text, etc.) title, widget, required, returns
@st.preprocess Data preparation before inference title, returns
@st.infer Model inference step title, returns, device, weights_path
@st.postprocess Clean-up after inference title, returns
@st.output Final (or intermediate) result title, widget, returns, intermediate

Wiring via returns

@st.input(returns="scan")       # produces key "scan"
def load_scan(self, path): ...

@st.preprocess(returns="normalized")
def normalize(self, scan): ...  # "scan" resolves to load_scan's output

@st.infer(returns="mask")
def segment(self, normalized): ...  # "normalized" resolves to normalize's output

If returns is omitted the method name is used as the output key.

Input widgets

Widget Description
FileInput(accepted_types=[...], max_size_mb=500) File upload
TextInput(default="", placeholder="", max_length=None) Single-line text

Accepted file typesInputDataType.ANY, .NIFTI, .DICOM, .PNG, .NUMPY

Output widgets

Widget Description
FileOutput(data_type=OutputDataType.File, filename=None) Generic file download
ImageOutput(caption="", max_size_mb=50) PNG / matplotlib figure
PlotOutput(interactive=True) Plotly / Bokeh / matplotlib
MetricOutput(label="", precision=3) Numeric value or dict of metrics

Output data typesFile, Image, Plot, NIFTI, DICOM, Mesh, CSV, JSON, Text, Metric

Intermediate outputs are uploaded to the frontend while the pipeline is still running:

@st.output(title="Slice Preview", widget=st.ImageOutput(), intermediate=True)
def preview(self, normalized): ...

DAG inspection

from streamtrace import build_dag

dag = build_dag(CardiacSegmentation)

# Validate wiring before deploying
errors = dag.validate()
if errors:
    for e in errors:
        print(e)

# Topological execution order
for node in dag.topological_sort():
    print(node.phase, "→", node.name, "produces", node.output_key)

# JSON schema (used by streamtrace push)
import json
print(json.dumps(dag.to_schema(), indent=2))

Streamtrace CLI

The SDK is the contract layer. The streamtrace CLI handles the rest:

streamtrace init       # surveys your codebase and classifies existing code
streamtrace configure  # builds and validates a complete executable pipeline
streamtrace push       # deploys to Streamtrace infrastructure

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

streamtrace-0.1.0.tar.gz (20.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

streamtrace-0.1.0-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file streamtrace-0.1.0.tar.gz.

File metadata

  • Download URL: streamtrace-0.1.0.tar.gz
  • Upload date:
  • Size: 20.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for streamtrace-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dd227b7681a82208429d474402818025d5456d6df2c02f3de185efce9c7ea3e0
MD5 3a889d64031ebc493f3ca47d8b590ff2
BLAKE2b-256 f9af01c015a2b1c8fe77478288a7b857820090c3d76a897c05df700dda6b2056

See more details on using hashes here.

File details

Details for the file streamtrace-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: streamtrace-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 23.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for streamtrace-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0621701f624ab0bf49683601b783d0daf283ba0007f04c3640d1416cc74ff6c0
MD5 10e14dad7f4b587d30c8d8f3229165dd
BLAKE2b-256 3aac063d990789db8b782690566660aa2d3ee7b557edef9b1021ce1086f1881f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page