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
|
@@ -5,122 +5,154 @@ Copright © 2022 Laboratoire Adhesion et Inflammation, Authored by Remy Torro.
|
|
|
5
5
|
import argparse
|
|
6
6
|
import os
|
|
7
7
|
import json
|
|
8
|
-
from celldetective.
|
|
8
|
+
from celldetective.utils.image_loaders import (
|
|
9
|
+
auto_load_number_of_frames,
|
|
10
|
+
load_frames,
|
|
11
|
+
_get_img_num_per_channel,
|
|
12
|
+
)
|
|
13
|
+
from celldetective.utils.experiment import (
|
|
14
|
+
extract_position_name,
|
|
15
|
+
extract_experiment_channels,
|
|
16
|
+
)
|
|
9
17
|
from celldetective.segmentation import segment_frame_from_thresholds
|
|
10
|
-
from celldetective.utils import
|
|
18
|
+
from celldetective.utils.parsing import (
|
|
19
|
+
config_section_to_dict,
|
|
20
|
+
_extract_channel_indices_from_config,
|
|
21
|
+
_extract_nbr_channels_from_config,
|
|
22
|
+
)
|
|
11
23
|
from pathlib import Path, PurePath
|
|
12
24
|
from glob import glob
|
|
13
25
|
from shutil import rmtree
|
|
14
26
|
from tqdm import tqdm
|
|
15
27
|
import numpy as np
|
|
16
|
-
from
|
|
28
|
+
from celldetective.utils.io import save_tiff_imagej_compatible
|
|
17
29
|
import gc
|
|
18
30
|
from art import tprint
|
|
19
31
|
import concurrent.futures
|
|
20
32
|
|
|
21
33
|
tprint("Segment")
|
|
22
34
|
|
|
23
|
-
parser = argparse.ArgumentParser(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
parser.add_argument("
|
|
28
|
-
parser.add_argument("
|
|
35
|
+
parser = argparse.ArgumentParser(
|
|
36
|
+
description="Segment a movie in position with a threshold pipeline",
|
|
37
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument("-p", "--position", required=True, help="Path to the position")
|
|
40
|
+
parser.add_argument("-c", "--config", required=True, help="Threshold instructions")
|
|
41
|
+
parser.add_argument(
|
|
42
|
+
"--mode",
|
|
43
|
+
default="target",
|
|
44
|
+
choices=["target", "effector", "targets", "effectors"],
|
|
45
|
+
help="Cell population of interest",
|
|
46
|
+
)
|
|
47
|
+
parser.add_argument("--threads", default="1", help="Number of parallel threads")
|
|
29
48
|
|
|
30
49
|
args = parser.parse_args()
|
|
31
50
|
process_arguments = vars(args)
|
|
32
|
-
pos = str(process_arguments[
|
|
33
|
-
mode = str(process_arguments[
|
|
34
|
-
n_threads = int(process_arguments[
|
|
51
|
+
pos = str(process_arguments["position"])
|
|
52
|
+
mode = str(process_arguments["mode"])
|
|
53
|
+
n_threads = int(process_arguments["threads"])
|
|
35
54
|
|
|
36
|
-
threshold_instructions = str(process_arguments[
|
|
55
|
+
threshold_instructions = str(process_arguments["config"])
|
|
37
56
|
equalize = False
|
|
38
57
|
|
|
39
58
|
if os.path.exists(threshold_instructions):
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
59
|
+
with open(threshold_instructions, "r") as f:
|
|
60
|
+
threshold_instructions = json.load(f)
|
|
61
|
+
required_channels = [threshold_instructions["target_channel"]]
|
|
62
|
+
if "equalize_reference" in threshold_instructions:
|
|
63
|
+
equalize_info = threshold_instructions["equalize_reference"]
|
|
64
|
+
equalize = equalize_info[0]
|
|
65
|
+
equalize_time = equalize_info[1]
|
|
47
66
|
|
|
48
67
|
else:
|
|
49
|
-
|
|
50
|
-
|
|
68
|
+
print("The configuration path is not valid. Abort.")
|
|
69
|
+
os.abort()
|
|
51
70
|
|
|
52
|
-
if mode.lower()=="target" or mode.lower()=="targets":
|
|
53
|
-
|
|
54
|
-
elif mode.lower()=="effector" or mode.lower()=="effectors":
|
|
55
|
-
|
|
71
|
+
if mode.lower() == "target" or mode.lower() == "targets":
|
|
72
|
+
label_folder = "labels_targets"
|
|
73
|
+
elif mode.lower() == "effector" or mode.lower() == "effectors":
|
|
74
|
+
label_folder = "labels_effectors"
|
|
56
75
|
|
|
57
76
|
# Locate experiment config
|
|
58
77
|
parent1 = Path(pos).parent
|
|
59
78
|
expfolder = parent1.parent
|
|
60
|
-
config = PurePath(expfolder,Path("config.ini"))
|
|
61
|
-
assert os.path.exists(
|
|
79
|
+
config = PurePath(expfolder, Path("config.ini"))
|
|
80
|
+
assert os.path.exists(
|
|
81
|
+
config
|
|
82
|
+
), "The configuration file for the experiment could not be located. Abort."
|
|
62
83
|
|
|
63
84
|
print(f"Position: {extract_position_name(pos)}...")
|
|
64
|
-
print("Configuration file: ",config)
|
|
85
|
+
print("Configuration file: ", config)
|
|
65
86
|
print(f"Population: {mode}...")
|
|
66
87
|
|
|
67
88
|
channel_indices = _extract_channel_indices_from_config(config, required_channels)
|
|
68
89
|
# need to abort if channel not found
|
|
69
|
-
print(
|
|
90
|
+
print(
|
|
91
|
+
f"Required channels: {required_channels} located at channel indices {channel_indices}..."
|
|
92
|
+
)
|
|
70
93
|
|
|
71
|
-
threshold_instructions.update({
|
|
94
|
+
threshold_instructions.update({"target_channel": channel_indices[0]})
|
|
72
95
|
|
|
73
96
|
movie_prefix = config_section_to_dict(config, "MovieSettings")["movie_prefix"]
|
|
74
97
|
len_movie = float(config_section_to_dict(config, "MovieSettings")["len_movie"])
|
|
75
98
|
channel_names, channel_indices = extract_experiment_channels(expfolder)
|
|
76
|
-
threshold_instructions.update({
|
|
99
|
+
threshold_instructions.update({"channel_names": channel_names})
|
|
77
100
|
|
|
78
101
|
# Try to find the file
|
|
79
102
|
try:
|
|
80
|
-
|
|
103
|
+
file = glob(pos + f"movie/{movie_prefix}*.tif")[0]
|
|
81
104
|
except IndexError:
|
|
82
|
-
|
|
83
|
-
|
|
105
|
+
print("Movie could not be found. Check the prefix.")
|
|
106
|
+
os.abort()
|
|
84
107
|
|
|
85
108
|
len_movie_auto = auto_load_number_of_frames(file)
|
|
86
109
|
if len_movie_auto is not None:
|
|
87
|
-
|
|
110
|
+
len_movie = len_movie_auto
|
|
88
111
|
|
|
89
112
|
nbr_channels = _extract_nbr_channels_from_config(config)
|
|
90
|
-
#print(f'Number of channels in the input movie: {nbr_channels}')
|
|
91
|
-
img_num_channels = _get_img_num_per_channel(
|
|
113
|
+
# print(f'Number of channels in the input movie: {nbr_channels}')
|
|
114
|
+
img_num_channels = _get_img_num_per_channel(
|
|
115
|
+
np.arange(nbr_channels), len_movie, nbr_channels
|
|
116
|
+
)
|
|
92
117
|
|
|
93
118
|
# If everything OK, prepare output, load models
|
|
94
|
-
if os.path.exists(os.sep.join([pos,label_folder])):
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
os.mkdir(os.sep.join([pos,label_folder]))
|
|
98
|
-
print(f
|
|
119
|
+
if os.path.exists(os.sep.join([pos, label_folder])):
|
|
120
|
+
print("Erasing the previous labels folder...")
|
|
121
|
+
rmtree(os.sep.join([pos, label_folder]))
|
|
122
|
+
os.mkdir(os.sep.join([pos, label_folder]))
|
|
123
|
+
print(f"Labels folder successfully generated...")
|
|
99
124
|
|
|
100
125
|
if equalize:
|
|
101
|
-
|
|
102
|
-
|
|
126
|
+
f_reference = load_frames(
|
|
127
|
+
img_num_channels[:, equalize_time], file, scale=None, normalize_input=False
|
|
128
|
+
)
|
|
129
|
+
f_reference = f_reference[:, :, threshold_instructions["target_channel"]]
|
|
103
130
|
else:
|
|
104
|
-
|
|
131
|
+
f_reference = None
|
|
105
132
|
|
|
106
|
-
threshold_instructions.update({
|
|
133
|
+
threshold_instructions.update({"equalize_reference": f_reference})
|
|
107
134
|
print(f"Instructions: {threshold_instructions}...")
|
|
108
135
|
|
|
136
|
+
|
|
109
137
|
# Loop over all frames and segment
|
|
110
138
|
def segment_index(indices):
|
|
111
139
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
140
|
+
for t in tqdm(indices, desc="frame"):
|
|
141
|
+
|
|
142
|
+
# Load channels at time t
|
|
143
|
+
f = load_frames(img_num_channels[:, t], file, scale=None, normalize_input=False)
|
|
144
|
+
mask = segment_frame_from_thresholds(f, **threshold_instructions)
|
|
145
|
+
save_tiff_imagej_compatible(
|
|
146
|
+
os.sep.join([pos, label_folder, f"{str(t).zfill(4)}.tif"]),
|
|
147
|
+
mask.astype(np.uint16),
|
|
148
|
+
axes="YX",
|
|
149
|
+
)
|
|
118
150
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
151
|
+
del f
|
|
152
|
+
del mask
|
|
153
|
+
gc.collect()
|
|
122
154
|
|
|
123
|
-
|
|
155
|
+
return
|
|
124
156
|
|
|
125
157
|
|
|
126
158
|
print(f"Starting the segmentation with {n_threads} thread(s)...")
|
|
@@ -130,17 +162,13 @@ indices = list(range(img_num_channels.shape[1]))
|
|
|
130
162
|
chunks = np.array_split(indices, n_threads)
|
|
131
163
|
|
|
132
164
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
165
|
+
results = executor.map(segment_index, chunks)
|
|
166
|
+
try:
|
|
167
|
+
for i, return_value in enumerate(results):
|
|
168
|
+
print(f"Thread {i} output check: ", return_value)
|
|
169
|
+
except Exception as e:
|
|
170
|
+
print("Exception: ", e)
|
|
139
171
|
|
|
140
|
-
print(
|
|
172
|
+
print("Done.")
|
|
141
173
|
|
|
142
174
|
gc.collect()
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|