Rootscope / rootscope /cli.py
ct-tranchau's picture
RootScope Gradio app (ZeroGPU)
73e760d verified
Raw
History Blame Contribute Delete
4.02 kB
"""
Command-line entry point for Rootscope: `rootscope ...`
Examples
--------
# one image (GPU auto-detected)
rootscope --tif image.tif --out results/
# a whole folder of TIFFs
rootscope --tif-dir my_tifs/ --out results/
# force CPU (slow), or point at your own weights
rootscope --tif image.tif --cpu
rootscope --tif image.tif --model-dir /path/to/models --cnn-weights /path/to/backbone.pt
"""
import argparse
import sys
from . import __version__, api
def _gpu_available() -> bool:
try:
import torch
return torch.cuda.is_available()
except Exception: # noqa: BLE001
return False
def build_parser() -> argparse.ArgumentParser:
p = argparse.ArgumentParser(
prog="rootscope",
description="Predict cell types in confocal root-tip TIFF images "
"(segmentation + prediction in one step).",
)
src = p.add_mutually_exclusive_group(required=True)
src.add_argument("--tif", help="Path to a single TIFF image.")
src.add_argument("--tif-dir", help="Folder of TIFF images (batch mode).")
p.add_argument("--out", "--out-dir", dest="out_dir", default="results",
help="Output folder for CSVs + overlays (default: results/).")
p.add_argument("--um-per-px", type=float, default=1.0,
help="Microns per pixel (default: 1.0).")
p.add_argument("--max-rounds", type=int, default=10,
help="Max iterative refinement rounds (default: 10).")
p.add_argument("--label-cells", action="store_true",
help="Write the cell-type name inside each cell on the "
"overlay. Off by default (the text overlaps on dense "
"sections); the color legend already shows the types.")
g = p.add_mutually_exclusive_group()
g.add_argument("--gpu", dest="gpu", action="store_true", default=None,
help="Force GPU (default: auto-detect).")
g.add_argument("--cpu", dest="gpu", action="store_false",
help="Force CPU (slow).")
p.add_argument("--model-dir", default=None,
help="Folder with trained model weights (default: "
"auto-download/cache).")
p.add_argument("--cnn-weights", default=None,
help="Fine-tuned DINOv2 backbone.pt (default: "
"auto-download/cache).")
p.add_argument("--pattern", default="*.tif",
help="Glob for --tif-dir mode (default: *.tif).")
p.add_argument("--version", action="version",
version=f"rootscope {__version__}")
return p
def main(argv=None):
args = build_parser().parse_args(argv)
use_gpu = _gpu_available() if args.gpu is None else args.gpu
if args.gpu is None:
print(f"[rootscope] GPU {'detected' if use_gpu else 'not found (using CPU)'}.")
try:
if args.tif:
df = api.predict_tif(
args.tif, out_dir=args.out_dir, gpu=use_gpu,
model_dir=args.model_dir, cnn_weights=args.cnn_weights,
um_per_px=args.um_per_px, max_rounds=args.max_rounds,
label_cells=args.label_cells,
)
n = 0 if df is None else len(df)
print(f"\n[rootscope] Done — {n} cell predictions written to {args.out_dir}/")
else:
df = api.predict_folder(
args.tif_dir, out_dir=args.out_dir, gpu=use_gpu,
model_dir=args.model_dir, cnn_weights=args.cnn_weights,
um_per_px=args.um_per_px, max_rounds=args.max_rounds,
label_cells=args.label_cells, pattern=args.pattern,
)
n = 0 if df is None else len(df)
print(f"\n[rootscope] Done — {n} total predictions written to {args.out_dir}/")
except (FileNotFoundError, RuntimeError) as e:
print(f"\n[rootscope] ERROR: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()