Curation¶
Soma includes small curators for converting known public benchmark layouts into
the standard dataset.csv and splits.csv manifests described in
Dataset.
EVA patch-level classification¶
The first supported EVA slice covers patch-level classification datasets that
fit Soma’s dataset_type: tile workflow:
bachmhistcrcbreakhisgleason_arvanitipatch_camelyon
Use the curator from Python:
from soma.curation import curate_eva_patch_dataset
manifest = curate_eva_patch_dataset(
"mhist",
raw_root="/path/to/mhist",
output_dir="data/eva/mhist",
# 0.0 reproduces the kaiko-ai/eva leaderboard (train-on-all-train, evaluate
# on EVA validation via tune_is_test). Use a positive fraction (e.g. 0.2)
# only if you want a separate carved-out tune split for model selection.
tune_fraction=0.0,
)
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.
Note
The registered EVA benchmark
curates with tune_fraction=0.0 for you (its CURATION_TUNE_FRACTION), so
soma reproduce eva/<dataset> follows the leaderboard protocol without any
manual split choice.
Split policy¶
For datasets where EVA provides only train/validation-style splits, Soma
reserves EVA validation as test and creates tune by deterministic
stratified sampling from EVA train.
To reproduce EVA’s train-on-all-train/evaluate-on-validation protocol, curate
with tune_fraction=0.0 and set training.tune_is_test: true in the run
config. The generated split file will contain only train and test rows.
For datasets where EVA provides train/validation/test splits, Soma preserves
EVA validation as tune and EVA test as test. This lets one run report
both the EVA validation benchmark metric and the EVA test metric.
Raw layout expectations¶
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 materializes it from the raw Harvard Dataverse download: drop the train/validation TMA archives (ZT{76,111,199,204}_*.tar.gz) andGleason_masks_train.tar.gzinto<root>(already-extracted folders or aTMA_images/dir are also accepted). Soma slices the 750×750 patches itself — a vendored, dependency-free port ofcreate_patches.pyfrom the gleason_CNN repo — so you do not need to run that (Python 2-era) script. Materialization is atomic and idempotent: a completedtrain_validation_patches_750is reused as-is on later runs. Only the train/validation patches are produced; 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. When only the HDF5 files are present the curator materializes them to the class-folder layout above on first use (writing PNGs under a writable raw root; idempotent, so an interrupted pass resumes on the next run).
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 dataset_type: detection path. It converts
the unzipped OCELOT 2023 release
(Zenodo record 8417503, ocelot2023_v1.0.1.zip) into Soma’s detection
manifests. Like the EVA curators it does not download anything; accept the Zenodo
terms and unzip first (see examples/ocelot/README.md for the download step).
Curate from Python:
from soma.curation.ocelot import curate_ocelot_detection
curate_ocelot_detection("<raw>/ocelot2023_v1.0.1", "<out>/curated")
or from the command line:
python -m soma.curation.ocelot \
--raw-root <raw>/ocelot2023_v1.0.1 \
--output-dir <out>/curated
OCELOT ships paired cell and tissue patches; detection-v1 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), 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.