| |
| from __future__ import annotations |
|
|
| import argparse |
| from pathlib import Path |
|
|
| from .pipeline import run_pipeline |
|
|
|
|
| def build_parser() -> argparse.ArgumentParser: |
| p = argparse.ArgumentParser( |
| description="Halo: Xenium preprocessing + Cellpose XeniumSeg pipeline" |
| ) |
| p.add_argument( |
| "xenium_dir", |
| type=Path, |
| help="Path to Xenium dataset root directory", |
| ) |
| p.add_argument( |
| "--out-dir", |
| type=Path, |
| default=None, |
| help="Directory for outputs (default: current working directory)", |
| ) |
| p.add_argument( |
| "--dapi", |
| type=Path, |
| default=None, |
| help="Optional path to DAPI image (overrides auto-detect)", |
| ) |
| p.add_argument( |
| "--processed-out", |
| type=Path, |
| default=None, |
| help="Optional path for the processed 2-channel TIFF", |
| ) |
| p.add_argument( |
| "--mask-out", |
| type=Path, |
| default=None, |
| help="Optional path for the output cell mask", |
| ) |
| p.add_argument( |
| "--mask-format", |
| choices=["npy", "tiff"], |
| default="npy", |
| help="Output mask format (default: npy)", |
| ) |
| p.add_argument( |
| "--quantile", |
| type=float, |
| default=0.995, |
| help="Upper quantile for clipping DAPI intensity", |
| ) |
| p.add_argument( |
| "--sigma", |
| type=float, |
| default=2.5, |
| help="Gaussian sigma for transcript density smoothing", |
| ) |
| p.add_argument( |
| "--pixel-size", |
| type=float, |
| default=0.2125, |
| help="Microns per pixel for transcript binning", |
| ) |
| p.add_argument( |
| "--chunk-size", |
| type=int, |
| default=1_000_000, |
| help="Transcripts processed per chunk", |
| ) |
| p.add_argument( |
| "--qv-min", |
| type=int, |
| default=20, |
| help="Minimum transcript QV to keep", |
| ) |
| p.add_argument( |
| "--cpu", |
| action="store_true", |
| help="Force CPU inference (disable GPU)", |
| ) |
| return p |
|
|
|
|
| def main() -> None: |
| p = build_parser() |
| args = p.parse_args() |
|
|
| out_dir = args.out_dir if args.out_dir is not None else Path.cwd() |
|
|
| mask_path = run_pipeline( |
| xenium_dir=args.xenium_dir, |
| out_dir=out_dir, |
| dapi_path=args.dapi, |
| processed_out=args.processed_out, |
| mask_out=args.mask_out, |
| mask_format=args.mask_format, |
| quantile=args.quantile, |
| sigma=args.sigma, |
| pixel_size=args.pixel_size, |
| chunk_size=args.chunk_size, |
| qv_min=args.qv_min, |
| use_gpu=not args.cpu, |
| ) |
|
|
| print(f"✓ Saved cell mask to {mask_path}") |
|
|
|
|
| if __name__ == "__main__": |
| main() |
|
|