How soma works

soma takes a cohort of images with labels and splits, extracts features with a frozen foundation model, trains a downstream model on those features, and scores its predictions. Inputs can be tiles, regions of interest or whole slides, and the same steps serve classification, regression, survival, segmentation and detection.

Five modular blocks in sequence: Data, Preprocess, Encode with a frozen foundation model, Train with a trained downstream model, and Evaluate.

A frozen foundation model produces reusable features. The downstream model is trained for the task.

The steps

Each step is a public function, a verb, that takes and returns plain objects you can inspect:

Step

Verb

What you choose

Learn more

Data

soma.Cohort holds the targets and splits; soma.ImageManifest holds the image paths

Images, targets, and train/tune/test or K-fold splits

Data

Preprocess

soma.extract() tiles the images

Tissue masking, spacing, tile size and overlap

Preprocessing

Encode

soma.extract() encodes the tiles and returns a feature source

A frozen foundation model; its features are cached for later runs

Encoders

Train

soma.fit() trains a learner and returns a soma.FitResult; soma.save() writes the model as a bundle

An aggregator or a decoder, a task head, the optimizer and the budget

Components, Training

Evaluate

soma.predict() returns soma.Predictions; soma.evaluate() scores them and returns an soma.Evaluation

Metrics and subgroups

Evaluation

Features reach the downstream model in one of two shapes. A set is one feature vector per sample, or a bag of tile features that an aggregator pools; the mil learner trains it, with a classification, regression or survival head. A grid is a dense token grid per tile or region that a decoder maps back to pixels; the dense learner trains it, with a segmentation or detection head. Modeling helps you choose.

Three ways to run

  • A preset returns a complete experiment for a common task from a few arguments, such as soma.presets.mil_classification(encoder="uni2"), or soma run --preset on the command line.

  • A config, an soma.ExperimentConfig in Python or the same fields in YAML, states every step. soma.resolve() expands it into a soma.Plan with every default filled in, and soma.Pipeline runs it: extraction, every fold, and the run directory.

  • The verbs, called one by one. Pipeline calls the same verbs in a fixed order, so a run composed by hand gives the same predictions and weights, and you can change any step and hand the result back to the pipeline.

The getting-started notebook takes one experiment through all three. Every managed run writes a run directory: the config as given (config.yaml), its plan (plan.yaml), the predictions, the metrics, and one model bundle per fold (see Run outputs).

Compare experiments

Features are cached under the image, preprocessing and encoder settings, so runs that change only the downstream model reuse them; Caching explains when extraction must run again. For a controlled comparison, hold the cohort, labels, splits and the rest of the protocol fixed while varying one component. Registered benchmarks are fixed protocols for reproducing public results and comparing encoders.

Use cases

Each use case is a preset (or a task head swapped into one) over one source shape. The end-to-end scenarios in the last column run it in soma’s test suite, on synthetic images with a weight-free encoder; tests/e2e/README.md lists what each scenario checks.

Use case

Preset or head

Source

End-to-end scenario

Slide classification

mil_classification(encoder, aggregator="abmil")

Bags of tile features

slide_mil_binary_classification, slide_mil_multiclass_classification

Survival

survival(encoder, aggregator); the cox_survival head

Bags of tile features

slide_mil_survival_nll, slide_mil_survival_cox

Regression

The regression head in mil_classification

Bags of tile features

slide_mil_regression

Tile-level classification

tile_classification(encoder)

One embedding per image

tile_binary_classification

Segmentation

segmentation(encoder, decoder, num_classes=2)

Dense token grids

dense_segmentation, dense_preset_segmentation, grid_live_segmentation

Detection

detection(encoder, decoder, num_classes=1, match_distance=3.0)

Dense token grids

dense_detection, dense_preset_detection, grid_live_detection

Next: install soma, then run the getting-started notebook.