celldetective 1.4.2__py3-none-any.whl → 1.5.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- celldetective/__init__.py +25 -0
- celldetective/__main__.py +62 -43
- celldetective/_version.py +1 -1
- celldetective/extra_properties.py +477 -399
- celldetective/filters.py +192 -97
- celldetective/gui/InitWindow.py +541 -411
- celldetective/gui/__init__.py +0 -15
- celldetective/gui/about.py +44 -39
- celldetective/gui/analyze_block.py +120 -84
- celldetective/gui/base/__init__.py +0 -0
- celldetective/gui/base/channel_norm_generator.py +335 -0
- celldetective/gui/base/components.py +249 -0
- celldetective/gui/base/feature_choice.py +92 -0
- celldetective/gui/base/figure_canvas.py +52 -0
- celldetective/gui/base/list_widget.py +133 -0
- celldetective/gui/{styles.py → base/styles.py} +92 -36
- celldetective/gui/base/utils.py +33 -0
- celldetective/gui/base_annotator.py +900 -767
- celldetective/gui/classifier_widget.py +6 -22
- celldetective/gui/configure_new_exp.py +777 -671
- celldetective/gui/control_panel.py +635 -524
- celldetective/gui/dynamic_progress.py +449 -0
- celldetective/gui/event_annotator.py +2023 -1662
- celldetective/gui/generic_signal_plot.py +1292 -944
- celldetective/gui/gui_utils.py +899 -1289
- celldetective/gui/interactions_block.py +658 -0
- celldetective/gui/interactive_timeseries_viewer.py +447 -0
- celldetective/gui/json_readers.py +48 -15
- celldetective/gui/layouts/__init__.py +5 -0
- celldetective/gui/layouts/background_model_free_layout.py +537 -0
- celldetective/gui/layouts/channel_offset_layout.py +134 -0
- celldetective/gui/layouts/local_correction_layout.py +91 -0
- celldetective/gui/layouts/model_fit_layout.py +372 -0
- celldetective/gui/layouts/operation_layout.py +68 -0
- celldetective/gui/layouts/protocol_designer_layout.py +96 -0
- celldetective/gui/pair_event_annotator.py +3130 -2435
- celldetective/gui/plot_measurements.py +586 -267
- celldetective/gui/plot_signals_ui.py +724 -506
- celldetective/gui/preprocessing_block.py +395 -0
- celldetective/gui/process_block.py +1678 -1831
- celldetective/gui/seg_model_loader.py +580 -473
- celldetective/gui/settings/__init__.py +0 -7
- celldetective/gui/settings/_cellpose_model_params.py +181 -0
- celldetective/gui/settings/_event_detection_model_params.py +95 -0
- celldetective/gui/settings/_segmentation_model_params.py +159 -0
- celldetective/gui/settings/_settings_base.py +77 -65
- celldetective/gui/settings/_settings_event_model_training.py +752 -526
- celldetective/gui/settings/_settings_measurements.py +1133 -964
- celldetective/gui/settings/_settings_neighborhood.py +574 -488
- celldetective/gui/settings/_settings_segmentation_model_training.py +779 -564
- celldetective/gui/settings/_settings_signal_annotator.py +329 -305
- celldetective/gui/settings/_settings_tracking.py +1304 -1094
- celldetective/gui/settings/_stardist_model_params.py +98 -0
- celldetective/gui/survival_ui.py +422 -312
- celldetective/gui/tableUI.py +1665 -1701
- celldetective/gui/table_ops/_maths.py +295 -0
- celldetective/gui/table_ops/_merge_groups.py +140 -0
- celldetective/gui/table_ops/_merge_one_hot.py +95 -0
- celldetective/gui/table_ops/_query_table.py +43 -0
- celldetective/gui/table_ops/_rename_col.py +44 -0
- celldetective/gui/thresholds_gui.py +382 -179
- celldetective/gui/viewers/__init__.py +0 -0
- celldetective/gui/viewers/base_viewer.py +700 -0
- celldetective/gui/viewers/channel_offset_viewer.py +331 -0
- celldetective/gui/viewers/contour_viewer.py +394 -0
- celldetective/gui/viewers/size_viewer.py +153 -0
- celldetective/gui/viewers/spot_detection_viewer.py +341 -0
- celldetective/gui/viewers/threshold_viewer.py +309 -0
- celldetective/gui/workers.py +403 -126
- celldetective/log_manager.py +92 -0
- celldetective/measure.py +1895 -1478
- celldetective/napari/__init__.py +0 -0
- celldetective/napari/utils.py +1025 -0
- celldetective/neighborhood.py +1914 -1448
- celldetective/preprocessing.py +1620 -1220
- celldetective/processes/__init__.py +0 -0
- celldetective/processes/background_correction.py +271 -0
- celldetective/processes/compute_neighborhood.py +894 -0
- celldetective/processes/detect_events.py +246 -0
- celldetective/processes/downloader.py +137 -0
- celldetective/processes/measure_cells.py +565 -0
- celldetective/processes/segment_cells.py +760 -0
- celldetective/processes/track_cells.py +435 -0
- celldetective/processes/train_segmentation_model.py +694 -0
- celldetective/processes/train_signal_model.py +265 -0
- celldetective/processes/unified_process.py +292 -0
- celldetective/regionprops/_regionprops.py +358 -317
- celldetective/relative_measurements.py +987 -710
- celldetective/scripts/measure_cells.py +313 -212
- celldetective/scripts/measure_relative.py +90 -46
- celldetective/scripts/segment_cells.py +165 -104
- celldetective/scripts/segment_cells_thresholds.py +96 -68
- celldetective/scripts/track_cells.py +198 -149
- celldetective/scripts/train_segmentation_model.py +324 -201
- celldetective/scripts/train_signal_model.py +87 -45
- celldetective/segmentation.py +844 -749
- celldetective/signals.py +3514 -2861
- celldetective/tracking.py +30 -15
- celldetective/utils/__init__.py +0 -0
- celldetective/utils/cellpose_utils/__init__.py +133 -0
- celldetective/utils/color_mappings.py +42 -0
- celldetective/utils/data_cleaning.py +630 -0
- celldetective/utils/data_loaders.py +450 -0
- celldetective/utils/dataset_helpers.py +207 -0
- celldetective/utils/downloaders.py +235 -0
- celldetective/utils/event_detection/__init__.py +8 -0
- celldetective/utils/experiment.py +1782 -0
- celldetective/utils/image_augmenters.py +308 -0
- celldetective/utils/image_cleaning.py +74 -0
- celldetective/utils/image_loaders.py +926 -0
- celldetective/utils/image_transforms.py +335 -0
- celldetective/utils/io.py +62 -0
- celldetective/utils/mask_cleaning.py +348 -0
- celldetective/utils/mask_transforms.py +5 -0
- celldetective/utils/masks.py +184 -0
- celldetective/utils/maths.py +351 -0
- celldetective/utils/model_getters.py +325 -0
- celldetective/utils/model_loaders.py +296 -0
- celldetective/utils/normalization.py +380 -0
- celldetective/utils/parsing.py +465 -0
- celldetective/utils/plots/__init__.py +0 -0
- celldetective/utils/plots/regression.py +53 -0
- celldetective/utils/resources.py +34 -0
- celldetective/utils/stardist_utils/__init__.py +104 -0
- celldetective/utils/stats.py +90 -0
- celldetective/utils/types.py +21 -0
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/METADATA +1 -1
- celldetective-1.5.0b1.dist-info/RECORD +187 -0
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/WHEEL +1 -1
- tests/gui/test_new_project.py +129 -117
- tests/gui/test_project.py +127 -79
- tests/test_filters.py +39 -15
- tests/test_notebooks.py +8 -0
- tests/test_tracking.py +232 -13
- tests/test_utils.py +123 -77
- celldetective/gui/base_components.py +0 -23
- celldetective/gui/layouts.py +0 -1602
- celldetective/gui/processes/compute_neighborhood.py +0 -594
- celldetective/gui/processes/downloader.py +0 -111
- celldetective/gui/processes/measure_cells.py +0 -360
- celldetective/gui/processes/segment_cells.py +0 -499
- celldetective/gui/processes/track_cells.py +0 -303
- celldetective/gui/processes/train_segmentation_model.py +0 -270
- celldetective/gui/processes/train_signal_model.py +0 -108
- celldetective/gui/table_ops/merge_groups.py +0 -118
- celldetective/gui/viewers.py +0 -1354
- celldetective/io.py +0 -3663
- celldetective/utils.py +0 -3108
- celldetective-1.4.2.dist-info/RECORD +0 -123
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/entry_points.txt +0 -0
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/licenses/LICENSE +0 -0
- {celldetective-1.4.2.dist-info → celldetective-1.5.0b1.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import os
|
|
3
|
-
from celldetective.relative_measurements import
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
from celldetective.relative_measurements import (
|
|
4
|
+
measure_pair_signals_at_position,
|
|
5
|
+
extract_neighborhoods_from_pickles,
|
|
6
|
+
)
|
|
7
|
+
from celldetective.utils.experiment import (
|
|
8
|
+
extract_experiment_channels,
|
|
9
|
+
get_experiment_populations,
|
|
10
|
+
)
|
|
11
|
+
from celldetective.utils.parsing import config_section_to_dict
|
|
6
12
|
|
|
7
13
|
from pathlib import Path, PurePath
|
|
8
14
|
|
|
@@ -13,21 +19,25 @@ from art import tprint
|
|
|
13
19
|
|
|
14
20
|
tprint("Measure pairs")
|
|
15
21
|
|
|
16
|
-
parser = argparse.ArgumentParser(
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
parser = argparse.ArgumentParser(
|
|
23
|
+
description="Measure features and intensities in a multichannel timeseries.",
|
|
24
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
25
|
+
)
|
|
26
|
+
parser.add_argument("-p", "--position", required=True, help="Path to the position")
|
|
19
27
|
|
|
20
28
|
args = parser.parse_args()
|
|
21
29
|
process_arguments = vars(args)
|
|
22
|
-
pos = str(process_arguments[
|
|
30
|
+
pos = str(process_arguments["position"])
|
|
23
31
|
|
|
24
|
-
instruction_file = os.sep.join([
|
|
32
|
+
instruction_file = os.sep.join(["configs", "neighborhood_instructions.json"])
|
|
25
33
|
|
|
26
34
|
# Locate experiment config
|
|
27
35
|
parent1 = Path(pos).parent
|
|
28
36
|
expfolder = parent1.parent
|
|
29
37
|
config = PurePath(expfolder, Path("config.ini"))
|
|
30
|
-
assert os.path.exists(
|
|
38
|
+
assert os.path.exists(
|
|
39
|
+
config
|
|
40
|
+
), "The configuration file for the experiment could not be located. Abort."
|
|
31
41
|
print("Configuration file: ", config)
|
|
32
42
|
|
|
33
43
|
# from exp config fetch spatial calib, channel names
|
|
@@ -42,51 +52,85 @@ populations = get_experiment_populations(expfolder, dtype=str)
|
|
|
42
52
|
|
|
43
53
|
# from tracking instructions, fetch btrack config, features, haralick, clean_traj, idea: fetch custom timeline?
|
|
44
54
|
instr_path = PurePath(expfolder, Path(f"{instruction_file}"))
|
|
45
|
-
previous_pair_table_path = pos + os.sep.join(
|
|
55
|
+
previous_pair_table_path = pos + os.sep.join(
|
|
56
|
+
["output", "tables", "trajectories_pairs.csv"]
|
|
57
|
+
)
|
|
46
58
|
|
|
47
59
|
|
|
48
60
|
previous_neighborhoods = []
|
|
49
61
|
associated_reference_population = []
|
|
50
62
|
|
|
51
63
|
|
|
52
|
-
neighborhoods_to_measure = extract_neighborhoods_from_pickles(
|
|
64
|
+
neighborhoods_to_measure = extract_neighborhoods_from_pickles(
|
|
65
|
+
pos, populations=populations
|
|
66
|
+
)
|
|
53
67
|
all_df_pairs = []
|
|
54
68
|
if os.path.exists(previous_pair_table_path):
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
for
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
69
|
+
df_0 = pd.read_csv(previous_pair_table_path)
|
|
70
|
+
previous_neighborhoods = [
|
|
71
|
+
c.replace("status_", "")
|
|
72
|
+
for c in list(df_0.columns)
|
|
73
|
+
if c.startswith("status_neighborhood")
|
|
74
|
+
]
|
|
75
|
+
for n in previous_neighborhoods:
|
|
76
|
+
associated_reference_population.append(
|
|
77
|
+
df_0.loc[~df_0["status_" + n].isnull(), "reference_population"].values[0]
|
|
78
|
+
)
|
|
79
|
+
print(f"{previous_neighborhoods=} {associated_reference_population=}")
|
|
80
|
+
all_df_pairs.append(df_0)
|
|
81
|
+
for k, neigh_protocol in enumerate(neighborhoods_to_measure):
|
|
82
|
+
if neigh_protocol["description"] not in previous_neighborhoods:
|
|
83
|
+
df_pairs = measure_pair_signals_at_position(pos, neigh_protocol)
|
|
84
|
+
print(f"{df_pairs=}")
|
|
85
|
+
if "REFERENCE_ID" in list(df_pairs.columns):
|
|
86
|
+
all_df_pairs.append(df_pairs)
|
|
87
|
+
elif (
|
|
88
|
+
neigh_protocol["description"] in previous_neighborhoods
|
|
89
|
+
and neigh_protocol["reference"]
|
|
90
|
+
!= associated_reference_population[
|
|
91
|
+
previous_neighborhoods.index(neigh_protocol["description"])
|
|
92
|
+
]
|
|
93
|
+
):
|
|
94
|
+
df_pairs = measure_pair_signals_at_position(pos, neigh_protocol)
|
|
95
|
+
if "REFERENCE_ID" in list(df_pairs.columns):
|
|
96
|
+
all_df_pairs.append(df_pairs)
|
|
97
|
+
|
|
98
|
+
print(f"{len(all_df_pairs)} neighborhood measurements sets were computed...")
|
|
99
|
+
|
|
100
|
+
if len(all_df_pairs) > 1:
|
|
101
|
+
print("Merging...")
|
|
102
|
+
df_pairs = all_df_pairs[0]
|
|
103
|
+
for i in range(1, len(all_df_pairs)):
|
|
104
|
+
cols = [
|
|
105
|
+
c1
|
|
106
|
+
for c1, c2 in zip(list(df_pairs.columns), list(all_df_pairs[i].columns))
|
|
107
|
+
if c1 == c2
|
|
108
|
+
]
|
|
109
|
+
df_pairs = pd.merge(
|
|
110
|
+
df_pairs.round(decimals=6),
|
|
111
|
+
all_df_pairs[i].round(decimals=6),
|
|
112
|
+
how="outer",
|
|
113
|
+
on=cols,
|
|
114
|
+
)
|
|
115
|
+
elif len(all_df_pairs) == 1:
|
|
116
|
+
df_pairs = all_df_pairs[0]
|
|
82
117
|
else:
|
|
83
|
-
|
|
84
|
-
|
|
118
|
+
df_pairs = None
|
|
119
|
+
print("No dataframe could be computed for the pairs...")
|
|
85
120
|
|
|
86
121
|
if df_pairs is not None:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
122
|
+
print("Writing table...")
|
|
123
|
+
if "reference_population" in list(
|
|
124
|
+
df_pairs.columns
|
|
125
|
+
) and "neighbor_population" in list(df_pairs.columns):
|
|
126
|
+
df_pairs = df_pairs.sort_values(
|
|
127
|
+
by=[
|
|
128
|
+
"reference_population",
|
|
129
|
+
"neighbor_population",
|
|
130
|
+
"REFERENCE_ID",
|
|
131
|
+
"NEIGHBOR_ID",
|
|
132
|
+
"FRAME",
|
|
133
|
+
]
|
|
134
|
+
)
|
|
135
|
+
df_pairs.to_csv(previous_pair_table_path, index=False)
|
|
136
|
+
print("Done.")
|
|
@@ -6,90 +6,129 @@ import argparse
|
|
|
6
6
|
import datetime
|
|
7
7
|
import os
|
|
8
8
|
import json
|
|
9
|
-
from celldetective.
|
|
10
|
-
from celldetective.utils import
|
|
9
|
+
from celldetective.utils.model_loaders import locate_segmentation_model
|
|
10
|
+
from celldetective.utils.image_loaders import (
|
|
11
|
+
auto_load_number_of_frames,
|
|
12
|
+
_load_frames_to_segment,
|
|
13
|
+
_get_img_num_per_channel,
|
|
14
|
+
)
|
|
15
|
+
from celldetective.utils.mask_cleaning import _check_label_dims
|
|
16
|
+
from celldetective.utils.experiment import extract_position_name
|
|
17
|
+
from celldetective.utils.stardist_utils import (
|
|
18
|
+
_prep_stardist_model,
|
|
19
|
+
_segment_image_with_stardist_model,
|
|
20
|
+
)
|
|
21
|
+
from celldetective.utils.cellpose_utils import (
|
|
22
|
+
_segment_image_with_cellpose_model,
|
|
23
|
+
_prep_cellpose_model,
|
|
24
|
+
)
|
|
25
|
+
from celldetective.utils.mask_transforms import _rescale_labels
|
|
26
|
+
from celldetective.utils.image_transforms import _estimate_scale_factor
|
|
27
|
+
from celldetective.utils.parsing import (
|
|
28
|
+
_get_normalize_kwargs_from_config,
|
|
29
|
+
config_section_to_dict,
|
|
30
|
+
_extract_channel_indices_from_config,
|
|
31
|
+
_extract_nbr_channels_from_config,
|
|
32
|
+
)
|
|
11
33
|
from pathlib import Path, PurePath
|
|
12
34
|
from glob import glob
|
|
13
35
|
from shutil import rmtree
|
|
14
36
|
from tqdm import tqdm
|
|
15
37
|
import numpy as np
|
|
16
|
-
from
|
|
38
|
+
from celldetective.utils.io import save_tiff_imagej_compatible
|
|
17
39
|
import gc
|
|
18
40
|
from art import tprint
|
|
19
41
|
import concurrent.futures
|
|
20
42
|
|
|
21
43
|
tprint("Segment")
|
|
22
44
|
|
|
23
|
-
parser = argparse.ArgumentParser(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
parser.add_argument("
|
|
28
|
-
parser.add_argument("
|
|
29
|
-
parser.add_argument(
|
|
45
|
+
parser = argparse.ArgumentParser(
|
|
46
|
+
description="Segment a movie in position with the selected model",
|
|
47
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument("-p", "--position", required=True, help="Path to the position")
|
|
50
|
+
parser.add_argument("-m", "--model", required=True, help="Model name")
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--mode",
|
|
53
|
+
default="target",
|
|
54
|
+
choices=["target", "effector", "targets", "effectors"],
|
|
55
|
+
help="Cell population of interest",
|
|
56
|
+
)
|
|
57
|
+
parser.add_argument(
|
|
58
|
+
"--use_gpu", default="True", choices=["True", "False"], help="use GPU"
|
|
59
|
+
)
|
|
60
|
+
parser.add_argument("--threads", default="1", help="Number of parallel threads")
|
|
30
61
|
|
|
31
62
|
args = parser.parse_args()
|
|
32
63
|
process_arguments = vars(args)
|
|
33
|
-
pos = str(process_arguments[
|
|
34
|
-
mode = str(process_arguments[
|
|
35
|
-
use_gpu = process_arguments[
|
|
36
|
-
n_threads = int(process_arguments[
|
|
37
|
-
|
|
38
|
-
if use_gpu==
|
|
39
|
-
|
|
40
|
-
|
|
64
|
+
pos = str(process_arguments["position"])
|
|
65
|
+
mode = str(process_arguments["mode"])
|
|
66
|
+
use_gpu = process_arguments["use_gpu"]
|
|
67
|
+
n_threads = int(process_arguments["threads"])
|
|
68
|
+
|
|
69
|
+
if use_gpu == "True" or use_gpu == "true" or use_gpu == "1":
|
|
70
|
+
use_gpu = True
|
|
71
|
+
n_threads = 1 # avoid misbehavior on GPU with multithreading
|
|
41
72
|
else:
|
|
42
|
-
|
|
43
|
-
|
|
73
|
+
use_gpu = False
|
|
74
|
+
# n_threads = 1 # force 1 threads since all CPUs seem to be in use anyway
|
|
44
75
|
|
|
45
76
|
if not use_gpu:
|
|
46
|
-
|
|
77
|
+
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
|
|
47
78
|
|
|
48
|
-
modelname = str(process_arguments[
|
|
79
|
+
modelname = str(process_arguments["model"])
|
|
49
80
|
|
|
50
|
-
if mode.lower()=="target" or mode.lower()=="targets":
|
|
51
|
-
|
|
52
|
-
elif mode.lower()=="effector" or mode.lower()=="effectors":
|
|
53
|
-
|
|
81
|
+
if mode.lower() == "target" or mode.lower() == "targets":
|
|
82
|
+
label_folder = "labels_targets"
|
|
83
|
+
elif mode.lower() == "effector" or mode.lower() == "effectors":
|
|
84
|
+
label_folder = "labels_effectors"
|
|
54
85
|
|
|
55
86
|
# Locate experiment config
|
|
56
87
|
parent1 = Path(pos).parent
|
|
57
88
|
expfolder = parent1.parent
|
|
58
|
-
config = PurePath(expfolder,Path("config.ini"))
|
|
59
|
-
assert os.path.exists(
|
|
89
|
+
config = PurePath(expfolder, Path("config.ini"))
|
|
90
|
+
assert os.path.exists(
|
|
91
|
+
config
|
|
92
|
+
), "The configuration file for the experiment could not be located. Abort."
|
|
60
93
|
|
|
61
94
|
print(f"Position: {extract_position_name(pos)}...")
|
|
62
|
-
print("Configuration file: ",config)
|
|
95
|
+
print("Configuration file: ", config)
|
|
63
96
|
print(f"Population: {mode}...")
|
|
64
97
|
|
|
65
98
|
####################################
|
|
66
99
|
# Check model requirements #########
|
|
67
100
|
####################################
|
|
68
101
|
|
|
69
|
-
modelpath = os.sep.join(
|
|
102
|
+
modelpath = os.sep.join(
|
|
103
|
+
[os.path.split(os.path.dirname(os.path.realpath(__file__)))[0], "models"]
|
|
104
|
+
)
|
|
70
105
|
model_complete_path = locate_segmentation_model(modelname)
|
|
71
106
|
if model_complete_path is None:
|
|
72
|
-
|
|
73
|
-
|
|
107
|
+
print("Model could not be found. Abort.")
|
|
108
|
+
os.abort()
|
|
74
109
|
else:
|
|
75
|
-
|
|
110
|
+
print(f"Model path: {model_complete_path}...")
|
|
76
111
|
|
|
77
112
|
# load config
|
|
78
|
-
assert os.path.exists(
|
|
79
|
-
|
|
80
|
-
|
|
113
|
+
assert os.path.exists(
|
|
114
|
+
model_complete_path + "config_input.json"
|
|
115
|
+
), "The configuration for the inputs to the model could not be located. Abort."
|
|
116
|
+
with open(model_complete_path + "config_input.json") as config_file:
|
|
117
|
+
input_config = json.load(config_file)
|
|
81
118
|
|
|
82
119
|
# Parse target channels
|
|
83
120
|
required_channels = input_config["channels"]
|
|
84
121
|
|
|
85
122
|
channel_indices = _extract_channel_indices_from_config(config, required_channels)
|
|
86
|
-
print(
|
|
87
|
-
|
|
88
|
-
|
|
123
|
+
print(
|
|
124
|
+
f"Required channels: {required_channels} located at channel indices {channel_indices}."
|
|
125
|
+
)
|
|
126
|
+
required_spatial_calibration = input_config["spatial_calibration"]
|
|
127
|
+
print(f"Spatial calibration expected by the model: {required_spatial_calibration}...")
|
|
89
128
|
|
|
90
129
|
normalize_kwargs = _get_normalize_kwargs_from_config(input_config)
|
|
91
130
|
|
|
92
|
-
model_type = input_config[
|
|
131
|
+
model_type = input_config["model_type"]
|
|
93
132
|
|
|
94
133
|
movie_prefix = config_section_to_dict(config, "MovieSettings")["movie_prefix"]
|
|
95
134
|
spatial_calibration = float(config_section_to_dict(config, "MovieSettings")["pxtoum"])
|
|
@@ -97,75 +136,102 @@ len_movie = float(config_section_to_dict(config, "MovieSettings")["len_movie"])
|
|
|
97
136
|
|
|
98
137
|
# Try to find the file
|
|
99
138
|
try:
|
|
100
|
-
|
|
139
|
+
file = glob(pos + f"movie/{movie_prefix}*.tif")[0]
|
|
101
140
|
except IndexError:
|
|
102
|
-
|
|
103
|
-
|
|
141
|
+
print("Movie could not be found. Check the prefix.")
|
|
142
|
+
os.abort()
|
|
104
143
|
|
|
105
144
|
len_movie_auto = auto_load_number_of_frames(file)
|
|
106
145
|
if len_movie_auto is not None:
|
|
107
|
-
|
|
146
|
+
len_movie = len_movie_auto
|
|
108
147
|
|
|
109
|
-
if model_type==
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
148
|
+
if model_type == "cellpose":
|
|
149
|
+
diameter = input_config["diameter"]
|
|
150
|
+
# if diameter!=30:
|
|
151
|
+
# required_spatial_calibration = None # ignore spatial calibration and use diameter
|
|
152
|
+
cellprob_threshold = input_config["cellprob_threshold"]
|
|
153
|
+
flow_threshold = input_config["flow_threshold"]
|
|
115
154
|
|
|
116
155
|
scale = _estimate_scale_factor(spatial_calibration, required_spatial_calibration)
|
|
117
156
|
print(f"Scale: {scale}...")
|
|
118
157
|
|
|
119
158
|
nbr_channels = _extract_nbr_channels_from_config(config)
|
|
120
|
-
#print(f'Number of channels in the input movie: {nbr_channels}')
|
|
121
|
-
img_num_channels = _get_img_num_per_channel(
|
|
159
|
+
# print(f'Number of channels in the input movie: {nbr_channels}')
|
|
160
|
+
img_num_channels = _get_img_num_per_channel(
|
|
161
|
+
channel_indices, int(len_movie), nbr_channels
|
|
162
|
+
)
|
|
122
163
|
|
|
123
164
|
# If everything OK, prepare output, load models
|
|
124
|
-
if os.path.exists(pos+label_folder):
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
os.mkdir(pos+label_folder)
|
|
128
|
-
print(f
|
|
165
|
+
if os.path.exists(pos + label_folder):
|
|
166
|
+
print("Erasing the previous labels folder...")
|
|
167
|
+
rmtree(pos + label_folder)
|
|
168
|
+
os.mkdir(pos + label_folder)
|
|
169
|
+
print(f"Labels folder successfully generated...")
|
|
129
170
|
|
|
130
|
-
log=f
|
|
131
|
-
with open(pos+f
|
|
132
|
-
|
|
133
|
-
|
|
171
|
+
log = f"segmentation model: {modelname}\n"
|
|
172
|
+
with open(pos + f"log_{mode}.json", "a") as f:
|
|
173
|
+
f.write(f"{datetime.datetime.now()} SEGMENT \n")
|
|
174
|
+
f.write(log)
|
|
134
175
|
|
|
135
176
|
|
|
136
177
|
# Loop over all frames and segment
|
|
137
178
|
def segment_index(indices):
|
|
138
179
|
|
|
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
|
-
|
|
180
|
+
if model_type == "stardist":
|
|
181
|
+
model, scale_model = _prep_stardist_model(
|
|
182
|
+
modelname, Path(model_complete_path).parent, use_gpu=use_gpu, scale=scale
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
elif model_type == "cellpose":
|
|
186
|
+
model, scale_model = _prep_cellpose_model(
|
|
187
|
+
modelname,
|
|
188
|
+
model_complete_path,
|
|
189
|
+
use_gpu=use_gpu,
|
|
190
|
+
n_channels=len(required_channels),
|
|
191
|
+
scale=scale,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
for t in tqdm(indices, desc="frame"):
|
|
195
|
+
|
|
196
|
+
f = _load_frames_to_segment(
|
|
197
|
+
file,
|
|
198
|
+
img_num_channels[:, t],
|
|
199
|
+
scale_model=scale_model,
|
|
200
|
+
normalize_kwargs=normalize_kwargs,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
if model_type == "stardist":
|
|
204
|
+
Y_pred = _segment_image_with_stardist_model(
|
|
205
|
+
f, model=model, return_details=False
|
|
206
|
+
)
|
|
207
|
+
elif model_type == "cellpose":
|
|
208
|
+
Y_pred = _segment_image_with_cellpose_model(
|
|
209
|
+
f,
|
|
210
|
+
model=model,
|
|
211
|
+
diameter=diameter,
|
|
212
|
+
cellprob_threshold=cellprob_threshold,
|
|
213
|
+
flow_threshold=flow_threshold,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
if scale is not None:
|
|
217
|
+
Y_pred = _rescale_labels(Y_pred, scale_model=scale_model)
|
|
218
|
+
|
|
219
|
+
Y_pred = _check_label_dims(Y_pred, file)
|
|
220
|
+
|
|
221
|
+
save_tiff_imagej_compatible(
|
|
222
|
+
pos + os.sep.join([label_folder, f"{str(t).zfill(4)}.tif"]),
|
|
223
|
+
Y_pred,
|
|
224
|
+
axes="YX",
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
del f
|
|
228
|
+
del Y_pred
|
|
229
|
+
gc.collect()
|
|
230
|
+
|
|
231
|
+
del model
|
|
232
|
+
gc.collect()
|
|
233
|
+
|
|
234
|
+
return
|
|
169
235
|
|
|
170
236
|
|
|
171
237
|
print(f"Starting the segmentation with {n_threads} thread(s) and GPU={use_gpu}...")
|
|
@@ -175,17 +241,12 @@ indices = list(range(img_num_channels.shape[1]))
|
|
|
175
241
|
chunks = np.array_split(indices, n_threads)
|
|
176
242
|
|
|
177
243
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
print(
|
|
244
|
+
results = executor.map(segment_index, chunks)
|
|
245
|
+
try:
|
|
246
|
+
for i, return_value in enumerate(results):
|
|
247
|
+
print(f"Thread {i} output check: ", return_value)
|
|
248
|
+
except Exception as e:
|
|
249
|
+
print("Exception: ", e)
|
|
250
|
+
|
|
251
|
+
print("Done.")
|
|
186
252
|
gc.collect()
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|