Curation¶
soma includes curators for converting supported public benchmark layouts into
the standard dataset.csv and splits.csv manifests described in
Dataset.
CRoMa cohorts¶
The CRoMa benchmark uses three tile cohorts from the PathoROB study. Acquire and decode the pinned sources once:
pip install 'soma-pathology[croma]'
soma prepare-croma /data/croma
Or from Python:
from soma.benchmark.croma.robustness import prepare_croma
prepared = prepare_croma("/data/croma")
The command downloads the exact pinned dataset revisions, verifies every checksum, and decodes the tiles. Allow at least 5 GB of free space. The source datasets retain their upstream licenses: CC0-1.0 for Camelyon, CC-BY-NC-SA-4.0 for TCGA, and CC-BY-SA-4.0 for Tolkach-ESCA.
Curate one cohort, or all three with family-wide sample-ID validation:
from soma.benchmark.croma.curate import curate_croma_view, curate_croma_views
camelyon = curate_croma_view(
"/data/croma",
"data/croma/camelyon",
cohort="camelyon",
)
manifests = curate_croma_views("/data/croma", "data/croma")
The cohorts are fixed, balanced label-by-center grids: Camelyon has 20,400
rows, TCGA-4x4 has 5,760, and Tolkach-ESCA has 9,000. Every emitted row is
assigned to test, fold 0.
EVA patch-level classification¶
The EVA patch curator supports these tile-level datasets:
bachmhistcrcbreakhisgleason_arvanitipatch_camelyon
Use the curator from Python:
from soma.benchmark.eva.curate import curate_eva_patch_dataset
manifest = curate_eva_patch_dataset(
"mhist",
raw_root="/path/to/mhist",
output_dir="data/eva/mhist",
)
print(manifest.dataset_csv)
print(manifest.splits_csv)
The generated dataset.csv stores EVA numeric target indices in label and
keeps the readable class in class_name metadata. This preserves EVA’s class
orientation for binary tasks.
soma reproduce eva/<dataset> runs this curation for you (see the
EVA benchmark).
The EVA segmentation datasets have their own curators, curate_consep and
curate_monusac (soma.benchmark.eva.curate_segmentation). They write 224 px
tiles and class-index masks that reproduce EVA’s sample geometry, so the
curated directory holds images as well as the manifest.
The EVA slide-level datasets have curate_camelyon16_small and
curate_panda_small (soma.benchmark.eva.curate_slide). They choose each slide’s
tiles with EVA’s sampler and write one hs2p tiling artifact per slide; the
slide manifest names it in coordinates_path (see
Bring your own coordinates). The curated directory holds these
artifacts and the manifest, not tile images.
Split policy¶
The curator follows EVA’s official protocol and has no split knob. EVA train
is soma train. When EVA provides only a validation split, it becomes soma
test and the run sets cohort.tune_is_test: true. When EVA also
provides a test split, validation becomes tune and test becomes test.
Raw layout expectations¶
HDF5 or archive inputs are materialized to image folders on first use; a completed materialization is reused on later runs.
bachICIAR2018_BACH_Challenge/Photos/{Benign,InSitu,Invasive,Normal}/*.tif. Pre-split extractions withICIAR2018_BACH_Challenge/{train,test}/{Benign,InSitu,Invasive,Normal}/*.tifare also accepted when they match the EVA train/validation counts.mhistimages/*.pngandannotations.csvwithImage Name,Majority Vote Label, andPartitioncolumns.crcNCT-CRC-HE-100K/<class>/*.tifandCRC-VAL-HE-7K/<class>/*.tif. Extractions nested underoriginal/<class>are also accepted.breakhisBreaKHis images in the original nested layout. Only
40X*.pngimages with EVA classesTA,MC,F, andDCare used. The EVA validation patient-id list is used to assign validation samples to somatest.gleason_arvanititrain_validation_patches_750/**/*.jpg. Files from microarrayZT76are assigned to EVA validation and files fromZT111,ZT199, andZT204to EVA train. EVA reports GleasonArvaniti on the validation cohort and does not usetest_patches_750— its test split “leads to unstable evaluation results” — so those patches are ignored even when present.If
train_validation_patches_750is absent, soma slices the 750×750 patches itself from the raw Harvard Dataverse download: place theZT{76,111,199,204}_*.tar.gzarchives andGleason_masks_train.tar.gzunder<root>(extracted folders or aTMA_images/dir are also accepted). The ZT80 test cohort is skipped.patch_camelyonEither materialized image folders
{train,val,test}/{normal|no_tumor,tumor}/*.{png,jpg,jpeg,tif,tiff}, or EVA’s six official HDF5 files (camelyonpatch_level_2_split_{train,valid,test}_{x,y}.h5) under the raw root. HDF5 files are materialized as PNGs under a writable raw root.
Segmentation datasets from EVA, such as MoNuSAC, CoNSeP, and BCSS, are not covered by this tile-classification curation path.
OCELOT 2023 cell detection¶
The OCELOT curator targets soma’s detection path. It converts
the unzipped OCELOT 2023 release
(ocelot2023_v1.0.1.zip) into soma’s detection manifests. Download and unzip
it first.
Curate from Python:
from soma.benchmark.ocelot.curate import curate_ocelot_detection
curate_ocelot_detection("<raw>/ocelot2023_v1.0.1", "<out>/curated")
or from the command line:
python -m soma.benchmark.ocelot.curate \
--raw-root <raw>/ocelot2023_v1.0.1 \
--output-dir <out>/curated
OCELOT ships paired cell and tissue patches; the detection benchmark uses the cell
patches only (1024×1024 JPEGs at ~0.2 µm/px). Each is paired with a headerless
x,y,label point CSV whose 1-based cell label (1 = background cell, 2 =
tumor cell) is remapped to soma’s 0-based class ids (BC→0, TC→1). The curator
writes dataset.csv (sample_id, image_path, points_path, spacing_at_level_0),
splits.csv, one points/<sample_id>.csv per sample, and summary.json.
Split policy¶
OCELOT’s own train/val/test split is emitted verbatim as a single fold, with
train → train, val → tune (threshold sweep / monitor), and test →
test. soma never partitions the data itself.
MIDOG 2022 mitosis detection¶
The MIDOG curator converts the MIDOG 2022
training set into soma’s detection manifests, cut into fixed tiles. Use the PNG
release from Zenodo record 6547151: the
images and MIDOG2022_training_png.json.
The public annotation file has no tumour type or scanner per image, and soma uses the tumour type to stratify the split. Recover both from MIDOG++, which republishes the same images with this metadata. Download the two MIDOG++ files at the pinned commits:
Then write the enriched annotation file next to the images:
python -m soma.benchmark.midog.prepare_metadata \
--raw-json <raw_root>/MIDOG2022_training_png.json \
--midogpp-json <MIDOG++.json> \
--midogpp-xval-csv <datasets_xvalidation.csv> \
--out <raw_root>/MIDOG2022_training_enriched.json
The script matches each image to its MIDOG++ copy by image size and annotation
positions, and fails if the recovered counts differ from the published ones. It
drops the 51 human melanoma images: the challenge ships them without mitosis
labels, as an unlabeled domain for adaptation methods. Pass --keep-melanoma
to keep them as images without mitoses. The result has 354 images from 5 tumour
types and 4 scanners, with 9,501 mitoses.
The curator expects this layout under <raw_root>:
images/<file_name> # 001.png ... as named in the JSON
MIDOG2022_training_enriched.json
Curate from Python:
from soma.benchmark import get_benchmark
get_benchmark("detection/midog").curate("<raw_root>", "<out>/curated")
This runs two steps:
Per-image manifest in
<out>/curated/roi/. Each image is one sample. Each mitosis box is reduced to its centre and written as class 0. The look-alike “not mitotic figure” annotations are left out. Every image is declared at 0.25 µm/px and kept in its own pixel grid, although the scanners differ slightly.Tiles in
<out>/curated/. Each image is cut into 1024 px tiles with 128 px overlap. Each tile keeps its image’s split, tumour type and scanner, and the benchmark stitches tile predictions back to the image before scoring.
python -m soma.benchmark.midog.curate runs only the first step, without the nominal
0.25 µm/px.
Split policy¶
The official MIDOG 2022 test set is hidden, so the curator writes a local split
as a single fold. Within each tumour type, the images are put in a fixed order
by a hash of their id. The first 20% go to test, the next 20% to tune
and the rest to train: 212, 71 and 71 images. Each image is its own
patient, and re-curating gives the same split. These results are not
comparable to the published leaderboard.
MONKEY inflammatory-cell detection¶
The MONKEY curator targets soma’s detection path. It converts the public training set of the MONKEY challenge (81 PAS-stained kidney-biopsy slides from centres A–D, one slide per patient) into soma’s detection manifests. Download the slides and the annotations first. The bucket is public, so no account is needed:
aws s3 sync s3://monkey-training <raw_root> --no-sign-request \
--exclude "*" --include "images/pas-cpg/*" --include "annotations/json_mm/*"
The curator expects this layout under <raw_root>:
images/pas-cpg/<case>_PAS_CPG.tif
annotations/json_mm/<case>_lymphocytes.json
annotations/json_mm/<case>_monocytes.json
annotations/json_mm/<case>_inflammatory-cells.json
It fails with the download command when a folder or a file is missing.
Curate from Python:
from soma.benchmark.monkey.curate import curate_monkey_detection
curate_monkey_detection("<raw_root>", "<out>/roi")
or from the command line:
python -m soma.benchmark.monkey.curate --raw-root <raw_root> --output-dir <out>/roi
Cells are annotated only inside ROI polygons, so the curator writes one sample
per ROI. It reads the polygon’s level-0 bounding box from the slide, writes it as
a PNG, and writes the points in crop coordinates (lymphocytes → class 0,
monocytes → class 1). Each sample has an ignore mask (ignore_mask_path): the
valid region is the polygon dilated by 5 µm. Points further than 5 µm from their
polygon are dropped, and summary.json records the kept and dropped counts,
the valid area and the annotated area_rois. dataset.csv also records the
source slide (source_slide) and the crop offset (crop_x, crop_y).
The ROIs are larger than a training tile. The detection/monkey benchmark tiles
them with soma.benchmark.tiles.tile_detection_manifest() into
1024 px tiles with 128 px overlap, as for MIDOG, and the tiles carry the ignore
masks.
Split policy¶
The official MONKEY test set is hidden, so the curator writes a 5-fold
cross-validation by patient, with each centre spread evenly over the folds. In
fold k, fold k is test, fold (k + 1) % 5 is tune and the other
three folds are train, so every slide is test exactly once. These results
are not comparable to the published leaderboard.