Python scripts for managing annotations on the WASABI platform, which is powered by HistomicsTK and Girder.
These scripts interact with the Annotations section of WASABI using the Girder REST API.
| Script | Description |
|---|---|
upload_one.py |
Upload a single annotation JSON to one WSI item |
download_one.py |
Download all annotations from one WSI item |
delete_one.py |
Delete annotations matching a name suffix from one WSI item |
bulk_upload.py |
Bulk upload annotation JSONs to matching WSI items in a folder |
bulk_download.py |
Bulk download all annotations from every WSI item in a folder |
bulk_delete.py |
Bulk delete annotations matching a name suffix across a folder |
list_all_annotations.py |
List all annotations in a folder and optionally save to CSV |
tiatoolbox_demo.py |
Run a TIAToolbox model on a directory of WSIs and save annotation stores |
annotationstore_to_wasabi_json.py |
Convert TIAToolbox annotation stores (.db) to WASABI-format JSON files |
- Python 3.10+
- A WASABI account with API key access
Install dependencies:
pip install -r requirements.txtFor the TIAToolbox scripts (tiatoolbox_demo.py, annotationstore_to_wasabi_json.py), install TIAToolbox>=2.0 separately:
pip install tiatoolbox>=2.0All scripts read your API key from the GIRDER_API_KEY environment variable. Never hard-code credentials.
export GIRDER_API_KEY=your_api_key_hereYou can find your API key in WASABI under Account → API keys.
See .env.example for reference.
Each script has a short Configuration block near the top. Edit these values before running:
| Variable | Description |
|---|---|
API_URL |
WASABI Girder API base URL (default: https://wasabi.dcs.warwick.ac.uk/api/v1) |
FOLDER_ID |
Girder folder ID (from the URL when browsing a folder of whole-slide images in WASABI) |
ITEM_ID |
Girder item ID for a single WSI |
OUTPUT_DIR |
Local directory for downloaded annotation JSON files |
ANNOTATION_DIR |
Local directory containing annotation JSON files for upload |
ANNOTATION_SUFFIX |
Name suffix used to match annotations for deletion or upload |
python list_all_annotations.pyPrints every annotation on every WSI in the folder, grouped by WSI, and optionally saves a CSV.
Edit download_one.py:
ITEM_ID = "your_item_id"
OUTPUT_DIR = Path("downloaded_annotations")python download_one.pyDownloads each annotation as a separate JSON file into downloaded_annotations/<wsi_name>/.
Edit bulk_download.py:
FOLDER_ID = "your_folder_id"
OUTPUT_DIR = Path("downloaded_annotations")python bulk_download.pyOutput structure:
downloaded_annotations/
wsi_1/
annotation_1.json
wsi_2/
annotation_1.json
annotation_2.json
Edit upload_one.py:
ITEM_ID = "your_item_id"
ANNOTATION_JSON = Path("annotations/my_annotation.json")python upload_one.pyEdit bulk_upload.py:
FOLDER_ID = "your_folder_id"
ANNOTATION_DIR = Path("annotations")Each JSON filename is matched to the corresponding WSI item by name. Existing annotations with the same name are skipped.
Run a dry run first (set dry_run=True in __main__):
python bulk_upload.pyEdit delete_one.py:
ITEM_ID = "your_item_id"
ANNOTATION_SUFFIX = "_prediction"python delete_one.pyPrints all matching annotations and asks you to type yes before deleting.
Edit bulk_delete.py:
FOLDER_ID = "your_folder_id"
ANNOTATION_SUFFIX = "_prediction"python bulk_delete.pyScans every WSI in the folder, prints all matches, and requires yes confirmation before any deletion occurs.
These scripts use the standard Girder large-image annotation format:
{
"annotation": {
"name": "my_annotation_name",
"description": "",
"elements": [
{
"type": "polyline",
"points": [[x1, y1, 0], [x2, y2, 0], ...],
"closed": true
}
]
}
}Both wrapped ({"annotation": {...}}) and unwrapped ({"name": ..., "elements": [...]}) formats are accepted on upload.
These two scripts form a complete pipeline for generating model predictions on WSIs and publishing them as WASABI annotations.
Edit tiatoolbox_demo.py:
SLIDES_DIR = Path("/path/to/slides") # .svs files
OUTPUT_DIR = Path("/path/to/annotation_stores") # output .db files
MODEL = "grandqc_tissue_detection"
DEVICE = "cuda" # or "cpu"python tiatoolbox_demo.pyProduces one .db annotation store per slide in OUTPUT_DIR.
Edit annotationstore_to_wasabi_json.py:
INPUT_DIR = Path("/path/to/annotation_stores")
OUTPUT_DIR = Path("/path/to/wasabi_jsons")
SAVE_SUFFIX = "_tissue_mask" # appended to each output filename
ANNOTATOR = "GrandQC_Model" # displayed in WASABI as the annotator name
COLOR_DICT = {
"Background": [0, 0, 0, 0],
"Tissue": [0, 255, 0, 255],
}python annotationstore_to_wasabi_json.pyProduces one WASABI-format JSON per slide in OUTPUT_DIR.
Follow the Bulk upload instructions above, pointing ANNOTATION_DIR at the JSON directory from Step 2.
- The
bulk_deleteanddelete_onescripts require interactive confirmation (yes) before any data is deleted. Use with Caution!!! - The
bulk_downloadanddownload_onescripts skip files that already exist locally by default (overwrite=False). - The
bulk_uploadscript skips annotations that already exist on the target WSI on WASABI by name.