-
Notifications
You must be signed in to change notification settings - Fork 52
Expand file tree
/
Copy path__main__.py
More file actions
211 lines (185 loc) · 9.17 KB
/
Copy path__main__.py
File metadata and controls
211 lines (185 loc) · 9.17 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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
import comet_ml
import tensorflow as tf
import json
import os
import copy
import click
import deepprofiler.dataset.compression
import deepprofiler.dataset.image_dataset
import deepprofiler.dataset.indexing
import deepprofiler.dataset.illumination_statistics
import deepprofiler.dataset.metadata
import deepprofiler.dataset.utils
import deepprofiler.dataset.image_dataset
import deepprofiler.dataset.sampling
import deepprofiler.learning.training
import deepprofiler.learning.tf2train
import deepprofiler.learning.profiling
# Main interaction point
@click.group()
@click.option("--root", prompt="Root directory for DeepProfiler experiment",
help="Root directory for DeepProfiler experiment",
type=click.Path("r"))
@click.option("--config", default=None,
help="Path to existing config file (filename in project_root/inputs/config/)",
type=click.STRING)
@click.option("--cores", default=0,
help="Number of CPU cores for parallel processing (all=0) for prepare command",
type=click.INT)
@click.option("--gpu", default="0",
help="GPU device id (the id can be checked with nvidia-smi)",
type=click.STRING)
@click.option("--exp", default="results",
help="Name of experiment, this folder will be created in project_root/outputs/",
type=click.STRING)
@click.option("--single-cells", default="single-cells",
help="Name of the folder with single-cell dataset (output for export-sc command, "
"input for training with sampled crop generator or online labels crop generator)",
type=click.STRING)
@click.option("--metadata", default='index.csv',
help="data filename, for exporting or profiling it is a filename for project_root/inputs/metadata/, "
"for training with sampled crop generator or online labels crop generator "
"the filename in project_root/outputs/<single-cell-dataset>/",
type=click.STRING)
@click.option("--logging", default=None,
help="Path to file with comet.ml API key (filename in project_root/inputs/config/)",
type=click.STRING)
@click.pass_context
def cli(context, root, config, exp, cores, gpu, single_cells, metadata, logging):
dirs = {
"root": root,
"locations": root + "/inputs/locations/", # TODO: use os.path.join()
"config": root + "/inputs/config/",
"images": root + "/inputs/images/",
"metadata": root + "/inputs/metadata/",
"intensities": root + "/outputs/intensities/",
"compressed_images": root + "/outputs/compressed/images/",
"single_cell_set": root + "/outputs/" + single_cells + "/",
"results": root + "/outputs/" + exp + "/",
"checkpoints": root + "/outputs/" + exp + "/checkpoint/",
"logs": root + "/outputs/" + exp + "/logs/",
"summaries": root + "/outputs/" + exp + "/summaries/",
"features": root + "/outputs/" + exp + "/features/"
}
if context.invoked_subcommand == 'setup':
context.obj["dirs"] = dirs
return
config = dirs["config"] + "/" + config
context.obj["cores"] = cores
context.obj["gpu"] = gpu
os.environ["CUDA_VISIBLE_DEVICES"] = gpu
# Load configuration file
if config is not None and os.path.isfile(config):
with open(config, "r") as f:
params = json.load(f)
# Override paths defined by user
if "paths" in params.keys():
for key, value in dirs.items():
if key not in params["paths"].keys():
params["paths"][key] = dirs[key]
else:
dirs[key] = params["paths"][key]
else:
params["paths"] = copy.deepcopy(dirs)
if os.path.isdir(dirs["root"]):
for k in ["results", "checkpoints", "logs", "summaries", "features"]:
os.makedirs(dirs[k], exist_ok=True)
# Update references
params["experiment_name"] = exp
params["paths"]["index"] = params["paths"]["metadata"] + metadata
if metadata != 'index.csv':
params["paths"]["sc_index"] = os.path.join(params["paths"]["single_cell_set"], metadata)
else:
params["paths"]["sc_index"] = os.path.join(params["paths"]["single_cell_set"], 'sc-metadata.csv')
context.obj["config"] = params
if logging:
with open(os.path.join(dirs["config"], logging), "r") as f:
logging_params = json.load(f)
if logging_params["log_type"] == "comet_ml":
context.obj["config"]["train"]["comet_ml"] = {}
context.obj["config"]["train"]["comet_ml"]["api_key"] = logging_params["api_key"]
context.obj["config"]["train"]["comet_ml"]["project_name"] = logging_params["project_name"]
else:
raise Exception("Config does not exists; make sure that the file exists in /inputs/config/")
context.obj["dirs"] = dirs
# Optional tool: Create the support file and folder structure in a root directory
@cli.command(help='initialize folder structure of DeepProfiler project')
@click.pass_context
def setup(context):
for path in context.obj["dirs"].values():
if not os.path.isdir(path):
print("Creating directory: ", path)
os.makedirs(path)
else:
print("Directory exists: ", path)
context.obj["config"] = {}
context.obj["config"]["paths"] = context.obj["dirs"]
# First tool: Compute illumination statistics and compress images
@cli.command(help='Run illumination correction and compression')
@click.pass_context
def prepare(context):
metadata = deepprofiler.dataset.metadata.read_plates(context.obj["config"]["paths"]["index"])
process = deepprofiler.dataset.utils.Parallel(context.obj["config"], numProcs=context.obj["cores"])
process.compute(deepprofiler.dataset.illumination_statistics.calculate_statistics, metadata)
print("Illumination complete!")
metadata = deepprofiler.dataset.metadata.read_plates(
context.obj["config"]["paths"]["index"]) # reinitialize generator
process.compute(deepprofiler.dataset.compression.compress_plate, metadata)
print("Compression complete!")
# Second tool: Export single cells for training
@cli.command(help='export crops of single-cells for training')
@click.pass_context
def export_sc(context):
os.environ["CUDA_VISIBLE_DEVICES"] = ""
if context.parent.obj["config"]["prepare"]["compression"]["implement"]:
context.parent.obj["config"]["paths"]["images"] = context.obj["config"]["paths"]["compressed_images"]
dset = deepprofiler.dataset.image_dataset.read_dataset(context.obj["config"])
deepprofiler.dataset.sampling.export_dataset(context.obj["config"], dset)
print("Single-cell sampling complete.")
# Third tool: Train a network
@cli.command(help='train a model')
@click.option("--epoch", default=1)
@click.option("--seed", default=None)
@click.pass_context
def train(context, epoch, seed):
if context.parent.obj["config"]["prepare"]["compression"]["implement"]:
context.parent.obj["config"]["paths"]["images"] = context.obj["config"]["paths"]["compressed_images"]
if context.parent.obj["config"]["train"]["model"]["crop_generator"] == 'crop_generator':
dset = deepprofiler.dataset.image_dataset.read_dataset(context.obj["config"], mode='train')
deepprofiler.learning.training.learn_model(context.obj["config"], dset, epoch, seed)
else:
deepprofiler.learning.training.learn_model(context.obj["config"], None, epoch, seed)
# Third tool (b): Train a network with TF dataset
@cli.command(help='train a model with TensorFlow 2 dataset')
@click.option("--epoch", default=1)
@click.pass_context
def traintf2(context, epoch):
deepprofiler.learning.training.learn_model_v2(context.obj["config"], epoch)
# Fourth tool: Profile cells and extract features
@cli.command(help='run feature extraction')
@click.pass_context
@click.option("--part",
help="Part of index to process",
default=-1,
type=click.INT)
def profile(context, part):
if context.parent.obj["config"]["prepare"]["compression"]["implement"]:
context.parent.obj["config"]["paths"]["images"] = context.obj["config"]["paths"]["compressed_images"]
config = context.obj["config"]
if part >= 0:
partfile = "index-{0:03d}.csv".format(part)
config["paths"]["index"] = context.obj["config"]["paths"]["index"].replace("index.csv", partfile)
dset = deepprofiler.dataset.image_dataset.read_dataset(context.obj["config"], mode='profile')
deepprofiler.learning.profiling.profile(context.obj["config"], dset)
# Auxiliary tool: Split index in multiple parts
@cli.command(help='split metadata into multiple parts')
@click.pass_context
@click.option("--parts",
help="Number of parts to split the index",
type=click.INT)
def split(context, parts):
if context.parent.obj["config"]["prepare"]["compression"]["implement"]:
context.parent.obj["config"]["paths"]["images"] = context.obj["config"]["paths"]["compressed_images"]
deepprofiler.dataset.indexing.split_index(context.obj["config"], parts)
if __name__ == "__main__":
cli(obj={})