File size: 2,717 Bytes
9cf3910
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python3
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()