Backbone + SlideInference) for explicit control; the Inference pipeline wraps the same steps.
Runnable notebook
See
m-jumpstart for a full, runnable M-Optimus example.1. Configure the model and tissue masking
Pick your backend — the rest of the guide is identical for both.- On-premise
- AWS SageMaker
2. Run inference (image only)
SlideInference tiles the slide at 0.5 µm/pixel, dispatches tiles concurrently, and streams results to Zarr so memory stays constant regardless of slide size.
mask_threshold sets the minimum tissue fraction to keep a tile (default 0.5).
On a single-GPU SageMaker endpoint (
ml.g5.xlarge), lower max_concurrency (e.g. 32) to avoid out-of-memory from concurrent tile requests. On a multi-GPU on-premise server, 256 is a reasonable default. See Performance tuning for more.3. Add bulk RNA (multimodal prediction)
M-Optimus prediction can be conditioned on bulk RNA for a multimodal readout, attached through aCohort via late-binding: run image-only first, then link RNA and re-predict. Modality-aware tracking reruns only what changed, keeping both outputs for comparison.
Send TPM-normalized expression values — do not
log1p them yourself. The server transforms the input and the model output for you. Genes are auto-aligned to the model’s input set; genes the model expects but your file lacks are encoded as -1 (non-measured).4. Inspect the output
Load either output — image-only or multimodal — with the built-in helper:5. Visualize
Genes are identified by Ensembl gene ID. This guide’s panel:bioptimus.utils.plot_gene_panel_overlay renders a whole panel in one call. Compare the step 3 outputs — multimodal (with bulk RNA) vs. image-only:
- With bulk RNA (multimodal)
- Without bulk RNA (image only)

Panel predicted from H&E with bulk RNA (TCGA-LUAD TCGA-75-7027) — the multimodal output. Representative example.
A FP16 model variant is available for faster inference. Run the FP32 and FP16 outputs through the same analysis to compare the impact of quantization.
6. Get embedding + prediction together (optional)
Need both outputs for the same tiles? Request the combined mode instead of callingpredict() and embed() separately — one backbone pass instead of two:
Reduce each to a slide-level vector:
M-Optimus only — raises
NotImplementedError on the H-Optimus family (embedding-only, no prediction head), on any backend including Hugging Face. Call embed() directly for those. On M-Optimus itself, call predict()/embed() separately if you want both outputs without the combined call.

