-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathcli.py
More file actions
187 lines (164 loc) · 5.51 KB
/
cli.py
File metadata and controls
187 lines (164 loc) · 5.51 KB
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
"""Command-line interface for SubCellPortable."""
import argparse
import sys
from typing import Optional
def create_parser() -> argparse.ArgumentParser:
"""Create and configure argument parser.
Returns:
Configured ArgumentParser instance
"""
parser = argparse.ArgumentParser(
description="SubCellPortable: Run SubCell model inference on microscopy images",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
epilog="""
Examples:
python process.py # Use config.yaml settings
python process.py -o ./results # Specify output directory
python process.py -o ./results -g 0 -b 256 # Use GPU 0 with batch size 256
python process.py -o ./results --embeddings_only # Generate only embeddings (faster)
python process.py --config custom.yaml --path_list experiment1.csv # Custom config and input
Common mistakes:
✗ python process.py 2 # Missing flag for GPU
✓ python process.py -g 2 # Correct: use -g for GPU ID
✗ python process.py output/ # Missing -o flag
✓ python process.py -o output/ # Correct: use -o for output directory
For more help: python process.py --help
Configuration file: Edit config.yaml for easier parameter management
"""
)
# Input/config files
parser.add_argument(
"--config",
help="Path to configuration YAML file (default: config.yaml)",
default=argparse.SUPPRESS,
type=str,
)
parser.add_argument(
"--path_list",
help="Path to input CSV file with image paths (default: path_list.csv)",
default=argparse.SUPPRESS,
type=str,
)
# Model configuration
parser.add_argument(
"-c",
"--model_channels",
help="Channel images to be used",
choices=["rybg", "rbg", "ybg", "bg"],
default=argparse.SUPPRESS,
type=str,
)
parser.add_argument(
"-m",
"--model_type",
help="Model type to be used",
choices=["mae_contrast_supcon_model", "vit_supcon_model"],
default=argparse.SUPPRESS,
type=str,
)
parser.add_argument(
"-u",
"--update_model",
action="store_true",
help="Download/update the selected model files (default: False)",
)
# Output configuration
parser.add_argument(
"-o",
"--output_dir",
help="Output directory for all results (required for new CSV format without output_folder column)",
default=argparse.SUPPRESS,
type=str,
)
parser.add_argument(
"-csv",
"--create_csv",
action="store_true",
help="Generate a combined CSV of probabilities and embeddings (default: False)",
)
parser.add_argument(
"--embeddings_only",
action="store_true",
help="Only generate embeddings, skip classification (faster)",
)
parser.add_argument(
"--output_format",
choices=["individual", "combined"],
default=argparse.SUPPRESS,
help="Output format: individual (.npy files) or combined (.h5ad file)",
)
parser.add_argument(
"--save_attention_maps",
action="store_true",
help="Save attention map images (default: False)",
)
# Performance configuration
parser.add_argument(
"-g",
"--gpu",
help="The GPU id to use [0, 1, 2, 3...]. -1 for CPU usage",
default=argparse.SUPPRESS,
type=int,
)
parser.add_argument(
"-b",
"--batch_size",
help="Batch size for processing",
default=argparse.SUPPRESS,
type=int,
)
parser.add_argument(
"-w",
"--num_workers",
help="Number of workers for data loading",
default=argparse.SUPPRESS,
type=int,
)
parser.add_argument(
"-p",
"--prefetch_factor",
help="Prefetch factor for data loading",
default=argparse.SUPPRESS,
type=int,
)
parser.add_argument(
"--async_saving",
action="store_true",
help="Save individual files asynchronously (only for individual format, not combined; default: False)",
)
# Logging
parser.add_argument(
"-q",
"--quiet",
action="store_true",
help="Suppress verbose logging (quiet mode)",
)
return parser
def parse_args(args: Optional[list] = None) -> dict:
"""Parse command-line arguments.
Only returns arguments that were explicitly provided by the user.
This ensures CLI defaults don't override config file values.
Args:
args: List of arguments to parse. If None, uses sys.argv
Returns:
Dictionary of only explicitly provided arguments
"""
parser = create_parser()
# Only parse if there are actual arguments beyond the script name
if args is None:
args = sys.argv[1:]
if len(args) == 0:
# No arguments provided, return empty dict to use defaults
return {}
parsed = parser.parse_args(args)
result = vars(parsed)
# Filter out store_true arguments that are False (not provided)
# These have default False when not specified, but we don't want them
# to override config file values
filtered_result = {}
for key, value in result.items():
# Keep all non-boolean values (SUPPRESS handles those)
# Only keep boolean values if True (meaning flag was provided)
if not isinstance(value, bool) or value is True:
filtered_result[key] = value
return filtered_result