mirror of
https://github.com/mims-harvard/ToolUniverse.git
synced 2026-09-19 07:31:47 +08:00
4ef3afd401
* Add DeepSpotMTool: spatial gene expression from an H&E tile The spatial-transcriptomics skill covers analysing spatial data that already exists -- Visium, MERFISH, seqFISH, Xenium -- and treats H&E only as the image that ships alongside a Visium slide. Nothing in ToolUniverse goes the other way, from histology to expression, which is the case that matters when a sample has an H&E slide and no assay. DeepSpot-M (https://doi.org/10.64898/2026.06.19.26356060) fills that gap. It represents genes as queryable embeddings drawn from DNA, RNA, protein, single-cell and text foundation models rather than as fixed outputs, so one model spans the protein-coding transcriptome and covers genes unseen during training. The tool takes a 224x224 H&E tile and a list of gene symbols and returns predicted log1p-CPM values. Following the cellpose/admet-ai pattern, `deepspotm` is an optional dependency declared via `required_packages` and is never vendored. Two deliberate differences: - The model loads lazily on first run() rather than in __init__. DeepSpot-M's weights are gated on the Hugging Face Hub, so loading at construction time would make every ToolUniverse start-up reach for a gated download. - The tile must be exactly 224x224. The model was trained at ~20x (0.5 mpp) and a tile at another scale degrades predictions silently, but magnification cannot be recovered from a bare image file, so the one check that is available is enforced rather than warned about. The tool description and every successful response state that the values are predicted from morphology rather than measured, so an agent cannot mistake them for assay output, and that use is restricted to non-commercial research. Tests cover config/implementation drift and every validation path that runs before the model is touched, so they pass with `deepspotm` absent and without network access. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Describe the output as virtual spatial transcriptomics Use the term the method is named for instead of repeated predicted-not-measured warnings, and state the tile requirement rather than what happens when it is not met. Licence stated once. --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
85 lines
2.6 KiB
Python
85 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
DeepSpot-M Tool Usage Example
|
|
|
|
Predicts spatial gene expression for a single H&E histology tile with
|
|
DeepSpot-M, a multimodal foundation model that represents genes as queryable
|
|
embeddings and so spans the protein-coding transcriptome.
|
|
|
|
The example shows:
|
|
1. How to initialize ToolUniverse and load the DeepSpot-M tool
|
|
2. How to predict a few marker genes for one tile
|
|
3. How to switch the frozen gene-embedding source
|
|
|
|
Requirements:
|
|
- ToolUniverse installed
|
|
- pip install deepspotm
|
|
- Access to the gated weights: request it at
|
|
https://huggingface.co/ratschlab/DeepSpotM and run `huggingface-cli login`
|
|
- A local 224x224 H&E tile cut at roughly 20x (~0.5 microns per pixel)
|
|
|
|
The predicted values are model output, NOT measured transcriptomics, and the
|
|
model is for non-commercial research use only, not for clinical or diagnostic
|
|
use. Paper: https://doi.org/10.64898/2026.06.19.26356060
|
|
"""
|
|
|
|
import argparse
|
|
import json
|
|
|
|
from tooluniverse import ToolUniverse
|
|
|
|
|
|
def main():
|
|
"""Predict marker-gene expression for one H&E tile."""
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument(
|
|
"tile",
|
|
help="Path to a local 224x224 H&E tile (.png/.tif/.jpg) cut at ~20x.",
|
|
)
|
|
parser.add_argument(
|
|
"--genes",
|
|
nargs="+",
|
|
default=["EPCAM", "CD3D", "PTPRC"],
|
|
help="Gene symbols to predict (default: EPCAM CD3D PTPRC).",
|
|
)
|
|
parser.add_argument(
|
|
"--source",
|
|
default="scgpt",
|
|
choices=["evo2", "orthrus", "prott5", "scgpt", "apertus"],
|
|
help="Frozen gene-embedding source to query (default: scgpt).",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
print("🔬 DeepSpot-M Tool Usage Example")
|
|
print("=" * 50)
|
|
|
|
print("Initializing ToolUniverse...")
|
|
tooluni = ToolUniverse()
|
|
tooluni.load_tools()
|
|
print("✅ ToolUniverse initialized successfully")
|
|
|
|
query = {
|
|
"name": "DeepSpotM_predict_gene_expression",
|
|
"arguments": {
|
|
"image_path": args.tile,
|
|
"genes": args.genes,
|
|
"source": args.source,
|
|
},
|
|
}
|
|
|
|
print(f"\nPredicting {', '.join(args.genes)} for {args.tile} ...")
|
|
print("(the first call loads the checkpoint and is slow)")
|
|
result = tooluni.run_one_function(query)
|
|
|
|
if isinstance(result, dict) and result.get("status") == "error":
|
|
# Covers a missing package, gated weights you have no access to yet,
|
|
# a wrongly sized tile, or genes outside the model's panel.
|
|
print(f"❌ {result['error']}")
|
|
return
|
|
|
|
print(json.dumps(result, indent=2))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|