celldetective 1.3.9.post5__py3-none-any.whl → 1.4.1__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 +0 -3
- celldetective/_version.py +1 -1
- celldetective/events.py +2 -4
- celldetective/exceptions.py +11 -0
- celldetective/extra_properties.py +132 -0
- celldetective/filters.py +7 -1
- celldetective/gui/InitWindow.py +37 -46
- celldetective/gui/__init__.py +3 -9
- celldetective/gui/about.py +19 -15
- celldetective/gui/analyze_block.py +34 -19
- celldetective/gui/base_annotator.py +786 -0
- celldetective/gui/base_components.py +23 -0
- celldetective/gui/classifier_widget.py +86 -94
- celldetective/gui/configure_new_exp.py +163 -46
- celldetective/gui/control_panel.py +76 -146
- celldetective/gui/{signal_annotator.py → event_annotator.py} +533 -1438
- celldetective/gui/generic_signal_plot.py +11 -13
- celldetective/gui/gui_utils.py +54 -23
- celldetective/gui/help/neighborhood.json +2 -2
- celldetective/gui/json_readers.py +5 -4
- celldetective/gui/layouts.py +265 -31
- celldetective/gui/{signal_annotator2.py → pair_event_annotator.py} +433 -635
- celldetective/gui/plot_measurements.py +21 -17
- celldetective/gui/plot_signals_ui.py +125 -72
- celldetective/gui/process_block.py +283 -188
- celldetective/gui/processes/compute_neighborhood.py +594 -0
- celldetective/gui/processes/downloader.py +37 -34
- celldetective/gui/processes/measure_cells.py +19 -8
- celldetective/gui/processes/segment_cells.py +47 -11
- celldetective/gui/processes/track_cells.py +18 -13
- celldetective/gui/seg_model_loader.py +21 -62
- celldetective/gui/settings/__init__.py +7 -0
- celldetective/gui/settings/_settings_base.py +70 -0
- celldetective/gui/{retrain_signal_model_options.py → settings/_settings_event_model_training.py} +54 -109
- celldetective/gui/{measurement_options.py → settings/_settings_measurements.py} +54 -92
- celldetective/gui/{neighborhood_options.py → settings/_settings_neighborhood.py} +10 -13
- celldetective/gui/settings/_settings_segmentation.py +49 -0
- celldetective/gui/{retrain_segmentation_model_options.py → settings/_settings_segmentation_model_training.py} +38 -92
- celldetective/gui/{signal_annotator_options.py → settings/_settings_signal_annotator.py} +78 -103
- celldetective/gui/{btrack_options.py → settings/_settings_tracking.py} +85 -116
- celldetective/gui/styles.py +2 -1
- celldetective/gui/survival_ui.py +49 -95
- celldetective/gui/tableUI.py +53 -25
- celldetective/gui/table_ops/__init__.py +0 -0
- celldetective/gui/table_ops/merge_groups.py +118 -0
- celldetective/gui/thresholds_gui.py +617 -1221
- celldetective/gui/viewers.py +107 -42
- celldetective/gui/workers.py +8 -4
- celldetective/io.py +137 -57
- celldetective/links/zenodo.json +145 -144
- celldetective/measure.py +94 -53
- celldetective/neighborhood.py +342 -268
- celldetective/preprocessing.py +56 -35
- celldetective/regionprops/_regionprops.py +16 -5
- celldetective/relative_measurements.py +50 -29
- celldetective/scripts/analyze_signals.py +4 -1
- celldetective/scripts/measure_cells.py +5 -5
- celldetective/scripts/measure_relative.py +20 -12
- celldetective/scripts/segment_cells.py +4 -10
- celldetective/scripts/segment_cells_thresholds.py +3 -3
- celldetective/scripts/track_cells.py +10 -8
- celldetective/scripts/train_segmentation_model.py +18 -6
- celldetective/signals.py +29 -14
- celldetective/tracking.py +14 -3
- celldetective/utils.py +91 -62
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/METADATA +24 -16
- celldetective-1.4.1.dist-info/RECORD +123 -0
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/WHEEL +1 -1
- tests/gui/__init__.py +0 -0
- tests/gui/test_new_project.py +228 -0
- tests/gui/test_project.py +99 -0
- tests/test_preprocessing.py +2 -2
- celldetective/models/segmentation_effectors/ricm_bf_all_last/config_input.json +0 -79
- celldetective/models/segmentation_effectors/ricm_bf_all_last/ricm_bf_all_last +0 -0
- celldetective/models/segmentation_effectors/ricm_bf_all_last/training_instructions.json +0 -37
- celldetective/models/segmentation_effectors/test-transfer/config_input.json +0 -39
- celldetective/models/segmentation_effectors/test-transfer/test-transfer +0 -0
- celldetective/models/signal_detection/NucCond/classification_loss.png +0 -0
- celldetective/models/signal_detection/NucCond/classifier.h5 +0 -0
- celldetective/models/signal_detection/NucCond/config_input.json +0 -1
- celldetective/models/signal_detection/NucCond/log_classifier.csv +0 -126
- celldetective/models/signal_detection/NucCond/log_regressor.csv +0 -282
- celldetective/models/signal_detection/NucCond/regression_loss.png +0 -0
- celldetective/models/signal_detection/NucCond/regressor.h5 +0 -0
- celldetective/models/signal_detection/NucCond/scores.npy +0 -0
- celldetective/models/signal_detection/NucCond/test_confusion_matrix.png +0 -0
- celldetective/models/signal_detection/NucCond/test_regression.png +0 -0
- celldetective/models/signal_detection/NucCond/validation_confusion_matrix.png +0 -0
- celldetective/models/signal_detection/NucCond/validation_regression.png +0 -0
- celldetective-1.3.9.post5.dist-info/RECORD +0 -129
- tests/test_qt.py +0 -103
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/entry_points.txt +0 -0
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info/licenses}/LICENSE +0 -0
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/top_level.txt +0 -0
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
from PyQt5.QtWidgets import QDialog, QFrame, QGridLayout, QComboBox, QListWidget, QLabel, QPushButton, QVBoxLayout, QHBoxLayout, QCheckBox, \
|
|
2
|
-
QMessageBox
|
|
2
|
+
QMessageBox
|
|
3
3
|
from PyQt5.QtCore import Qt, QSize
|
|
4
4
|
from superqt.fonticon import icon
|
|
5
5
|
from fonticon_mdi6 import MDI6
|
|
6
6
|
import gc
|
|
7
7
|
from PyQt5.QtGui import QDoubleValidator, QIntValidator
|
|
8
8
|
|
|
9
|
-
from celldetective.gui.
|
|
10
|
-
from celldetective.gui.
|
|
9
|
+
from celldetective.gui.processes.compute_neighborhood import NeighborhoodProcess
|
|
10
|
+
from celldetective.gui.event_annotator import MeasureAnnotator
|
|
11
11
|
from celldetective.io import get_segmentation_models_list, control_segmentation_napari, get_signal_models_list, \
|
|
12
12
|
control_tracks, load_experiment_tables, get_pair_signal_models_list
|
|
13
|
-
from celldetective.io import locate_segmentation_model, extract_position_name, fix_missing_labels,
|
|
14
|
-
from celldetective.gui import SegmentationModelLoader, ClassifierWidget,
|
|
13
|
+
from celldetective.io import locate_segmentation_model, extract_position_name, fix_missing_labels, locate_signal_model
|
|
14
|
+
from celldetective.gui import SegmentationModelLoader, ClassifierWidget, \
|
|
15
|
+
EventAnnotator, TableUI, CelldetectiveWidget, PairEventAnnotator
|
|
16
|
+
|
|
17
|
+
from celldetective.gui.settings import SettingsSegmentation, SettingsMeasurements, SettingsTracking, \
|
|
18
|
+
SettingsSignalAnnotator, SettingsNeighborhood, SettingsSegmentationModelTraining, SettingsEventDetectionModelTraining
|
|
19
|
+
|
|
15
20
|
from celldetective.gui.gui_utils import QHSeperationLine
|
|
16
21
|
from celldetective.relative_measurements import rel_measure_at_position
|
|
17
|
-
from celldetective.segmentation import segment_at_position, segment_from_threshold_at_position
|
|
18
|
-
from celldetective.tracking import track_at_position
|
|
19
|
-
from celldetective.measure import measure_at_position
|
|
20
22
|
from celldetective.signals import analyze_signals_at_position, analyze_pair_signals_at_position
|
|
21
|
-
from celldetective.utils import extract_experiment_channels
|
|
23
|
+
from celldetective.utils import extract_experiment_channels, remove_file_if_exists
|
|
22
24
|
import numpy as np
|
|
23
25
|
from glob import glob
|
|
24
26
|
from natsort import natsorted
|
|
@@ -27,13 +29,9 @@ import pandas as pd
|
|
|
27
29
|
from celldetective.gui.gui_utils import center_window
|
|
28
30
|
from tifffile import imwrite
|
|
29
31
|
import json
|
|
30
|
-
import psutil
|
|
31
|
-
from celldetective.neighborhood import compute_neighborhood_at_position, compute_contact_neighborhood_at_position
|
|
32
|
-
from celldetective.gui.gui_utils import FigureCanvas
|
|
33
32
|
from celldetective.preprocessing import correct_background_model_free, correct_background_model, correct_channel_offset
|
|
34
|
-
from celldetective.
|
|
35
|
-
from celldetective.gui.
|
|
36
|
-
from celldetective.gui.layouts import CellposeParamsWidget, StarDistParamsWidget, BackgroundModelFreeCorrectionLayout, ProtocolDesignerLayout, BackgroundFitCorrectionLayout, ChannelOffsetOptionsLayout
|
|
33
|
+
from celldetective.gui.gui_utils import help_generic
|
|
34
|
+
from celldetective.gui.layouts import SignalModelParamsWidget, SegModelParamsWidget, CellposeParamsWidget, StarDistParamsWidget, BackgroundModelFreeCorrectionLayout, ProtocolDesignerLayout, BackgroundFitCorrectionLayout, ChannelOffsetOptionsLayout
|
|
37
35
|
from celldetective.gui import Styles
|
|
38
36
|
from celldetective.utils import get_software_location
|
|
39
37
|
|
|
@@ -42,10 +40,8 @@ from celldetective.gui.processes.segment_cells import SegmentCellThresholdProces
|
|
|
42
40
|
from celldetective.gui.processes.track_cells import TrackingProcess
|
|
43
41
|
from celldetective.gui.processes.measure_cells import MeasurementProcess
|
|
44
42
|
|
|
45
|
-
import time
|
|
46
|
-
import asyncio
|
|
47
|
-
|
|
48
43
|
class ProcessPanel(QFrame, Styles):
|
|
44
|
+
|
|
49
45
|
def __init__(self, parent_window, mode):
|
|
50
46
|
|
|
51
47
|
super().__init__()
|
|
@@ -55,17 +51,20 @@ class ProcessPanel(QFrame, Styles):
|
|
|
55
51
|
self.exp_dir = self.parent_window.exp_dir
|
|
56
52
|
self.exp_config = self.parent_window.exp_config
|
|
57
53
|
self.movie_prefix = self.parent_window.movie_prefix
|
|
58
|
-
self.
|
|
59
|
-
self.
|
|
60
|
-
self.wells = np.array(self.parent_window.wells,dtype=str)
|
|
54
|
+
self.threshold_configs = [None for _ in range(len(self.parent_window.populations))]
|
|
55
|
+
self.wells = np.array(self.parent_window.wells, dtype=str)
|
|
61
56
|
self.cellpose_calibrated = False
|
|
62
57
|
self.stardist_calibrated = False
|
|
58
|
+
self.segChannelsSet = False
|
|
59
|
+
self.signalChannelsSet = False
|
|
60
|
+
self.flipSeg = False
|
|
61
|
+
|
|
63
62
|
self.use_gpu = self.parent_window.parent_window.use_gpu
|
|
64
63
|
self.n_threads = self.parent_window.parent_window.n_threads
|
|
65
64
|
|
|
66
65
|
self.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
|
|
67
66
|
self.grid = QGridLayout(self)
|
|
68
|
-
self.grid.setContentsMargins(5,5,5,5)
|
|
67
|
+
self.grid.setContentsMargins(5, 5, 5, 5)
|
|
69
68
|
self.generate_header()
|
|
70
69
|
|
|
71
70
|
def generate_header(self):
|
|
@@ -84,36 +83,35 @@ class ProcessPanel(QFrame, Styles):
|
|
|
84
83
|
title_hbox = QHBoxLayout()
|
|
85
84
|
self.grid.addWidget(panel_title, 0, 0, 1, 4, alignment=Qt.AlignCenter)
|
|
86
85
|
|
|
87
|
-
self.help_pop_btn = QPushButton()
|
|
88
|
-
self.help_pop_btn.setIcon(icon(MDI6.help_circle,color=self.help_color))
|
|
89
|
-
self.help_pop_btn.setIconSize(QSize(20, 20))
|
|
90
|
-
self.help_pop_btn.clicked.connect(self.help_population)
|
|
91
|
-
self.help_pop_btn.setStyleSheet(self.button_select_all)
|
|
92
|
-
self.help_pop_btn.setToolTip("Help.")
|
|
93
|
-
#self.grid.addWidget(self.help_pop_btn, 0, 0, 1, 3, alignment=Qt.AlignRight)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
self.select_all_btn
|
|
97
|
-
self.select_all_btn.
|
|
98
|
-
self.
|
|
99
|
-
self.
|
|
100
|
-
self.select_all_btn.
|
|
101
|
-
self.select_all_btn.setStyleSheet(self.button_select_all)
|
|
86
|
+
# self.help_pop_btn = QPushButton()
|
|
87
|
+
# self.help_pop_btn.setIcon(icon(MDI6.help_circle, color=self.help_color))
|
|
88
|
+
# self.help_pop_btn.setIconSize(QSize(20, 20))
|
|
89
|
+
# self.help_pop_btn.clicked.connect(self.help_population)
|
|
90
|
+
# self.help_pop_btn.setStyleSheet(self.button_select_all)
|
|
91
|
+
# self.help_pop_btn.setToolTip("Help.")
|
|
92
|
+
# self.grid.addWidget(self.help_pop_btn, 0, 0, 1, 3, alignment=Qt.AlignRight)
|
|
93
|
+
|
|
94
|
+
# self.select_all_btn = QPushButton()
|
|
95
|
+
# self.select_all_btn.setIcon(icon(MDI6.checkbox_blank_outline,color="black"))
|
|
96
|
+
# self.select_all_btn.setIconSize(QSize(20, 20))
|
|
97
|
+
# self.all_ticked = False
|
|
98
|
+
# self.select_all_btn.clicked.connect(self.tick_all_actions)
|
|
99
|
+
# self.select_all_btn.setStyleSheet(self.button_select_all)
|
|
102
100
|
#self.grid.addWidget(self.select_all_btn, 0, 0, 1, 4, alignment=Qt.AlignLeft)
|
|
103
101
|
#self.to_disable.append(self.all_tc_actions)
|
|
104
102
|
|
|
105
103
|
self.collapse_btn = QPushButton()
|
|
106
|
-
self.collapse_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
104
|
+
self.collapse_btn.setIcon(icon(MDI6.chevron_down, color="black"))
|
|
107
105
|
self.collapse_btn.setIconSize(QSize(25, 25))
|
|
108
106
|
self.collapse_btn.setStyleSheet(self.button_select_all)
|
|
109
107
|
#self.grid.addWidget(self.collapse_btn, 0, 0, 1, 4, alignment=Qt.AlignRight)
|
|
110
108
|
|
|
111
|
-
title_hbox.addWidget(
|
|
109
|
+
title_hbox.addWidget(QLabel(), 5) #self.select_all_btn
|
|
112
110
|
title_hbox.addWidget(QLabel(), 85, alignment=Qt.AlignCenter)
|
|
113
|
-
title_hbox.addWidget(self.help_pop_btn, 5)
|
|
111
|
+
# title_hbox.addWidget(self.help_pop_btn, 5)
|
|
114
112
|
title_hbox.addWidget(self.collapse_btn, 5)
|
|
115
113
|
|
|
116
|
-
self.grid.addLayout(title_hbox, 0,0,1,4)
|
|
114
|
+
self.grid.addLayout(title_hbox, 0, 0, 1, 4)
|
|
117
115
|
self.populate_contents()
|
|
118
116
|
|
|
119
117
|
self.grid.addWidget(self.ContentsFrame, 1, 0, 1, 4, alignment=Qt.AlignTop)
|
|
@@ -123,47 +121,46 @@ class ProcessPanel(QFrame, Styles):
|
|
|
123
121
|
|
|
124
122
|
def collapse_advanced(self):
|
|
125
123
|
|
|
126
|
-
|
|
127
|
-
targets_open = not self.parent_window.ProcessTargets.ContentsFrame.isHidden()
|
|
124
|
+
panels_open = [not p.ContentsFrame.isHidden() for p in self.parent_window.ProcessPopulations]
|
|
128
125
|
interactions_open = not self.parent_window.NeighPanel.ContentsFrame.isHidden()
|
|
129
126
|
preprocessing_open = not self.parent_window.PreprocessingPanel.ContentsFrame.isHidden()
|
|
130
|
-
is_open = np.array([
|
|
127
|
+
is_open = np.array(panels_open+[interactions_open, preprocessing_open])
|
|
131
128
|
|
|
132
129
|
if self.ContentsFrame.isHidden():
|
|
133
|
-
self.collapse_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
130
|
+
self.collapse_btn.setIcon(icon(MDI6.chevron_down, color="black"))
|
|
134
131
|
self.collapse_btn.setIconSize(QSize(20, 20))
|
|
135
132
|
if len(is_open[is_open])==0:
|
|
136
133
|
self.parent_window.scroll.setMinimumHeight(int(550))
|
|
137
134
|
self.parent_window.adjustSize()
|
|
138
135
|
else:
|
|
139
|
-
self.collapse_btn.setIcon(icon(MDI6.chevron_up,color="black"))
|
|
136
|
+
self.collapse_btn.setIcon(icon(MDI6.chevron_up, color="black"))
|
|
140
137
|
self.collapse_btn.setIconSize(QSize(20, 20))
|
|
141
138
|
self.parent_window.scroll.setMinimumHeight(min(int(930), int(0.9*self.parent_window.screen_height)))
|
|
142
139
|
|
|
143
140
|
|
|
144
|
-
def help_population(self):
|
|
141
|
+
# def help_population(self):
|
|
145
142
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
143
|
+
# """
|
|
144
|
+
# Helper to choose a proper cell population structure.
|
|
145
|
+
# """
|
|
149
146
|
|
|
150
|
-
|
|
147
|
+
# dict_path = os.sep.join([get_software_location(),'celldetective','gui','help','cell-populations.json'])
|
|
151
148
|
|
|
152
|
-
|
|
153
|
-
|
|
149
|
+
# with open(dict_path) as f:
|
|
150
|
+
# d = json.load(f)
|
|
154
151
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
152
|
+
# suggestion = help_generic(d)
|
|
153
|
+
# if isinstance(suggestion, str):
|
|
154
|
+
# print(f"{suggestion=}")
|
|
155
|
+
# msgBox = QMessageBox()
|
|
156
|
+
# msgBox.setIcon(QMessageBox.Information)
|
|
157
|
+
# msgBox.setTextFormat(Qt.RichText)
|
|
158
|
+
# msgBox.setText(suggestion)
|
|
159
|
+
# msgBox.setWindowTitle("Info")
|
|
160
|
+
# msgBox.setStandardButtons(QMessageBox.Ok)
|
|
161
|
+
# returnValue = msgBox.exec()
|
|
162
|
+
# if returnValue == QMessageBox.Ok:
|
|
163
|
+
# return None
|
|
167
164
|
|
|
168
165
|
def populate_contents(self):
|
|
169
166
|
self.ContentsFrame = QFrame()
|
|
@@ -289,9 +286,16 @@ class ProcessPanel(QFrame, Styles):
|
|
|
289
286
|
self.grid_contents.addLayout(signal_layout,6,0,1,4)
|
|
290
287
|
|
|
291
288
|
def refresh_signal_models(self):
|
|
292
|
-
signal_models = get_signal_models_list()
|
|
289
|
+
self.signal_models = get_signal_models_list()
|
|
293
290
|
self.signal_models_list.clear()
|
|
294
|
-
|
|
291
|
+
|
|
292
|
+
thresh = 35
|
|
293
|
+
models_truncated = [m[:thresh - 3]+'...' if len(m)>thresh else m for m in self.signal_models]
|
|
294
|
+
|
|
295
|
+
self.signal_models_list.addItems(models_truncated)
|
|
296
|
+
for i in range(len(self.signal_models)):
|
|
297
|
+
self.signal_models_list.setItemData(i, self.signal_models[i], Qt.ToolTipRole)
|
|
298
|
+
|
|
295
299
|
|
|
296
300
|
def generate_tracking_options(self):
|
|
297
301
|
|
|
@@ -352,14 +356,10 @@ class ProcessPanel(QFrame, Styles):
|
|
|
352
356
|
if returnValue == QMessageBox.No:
|
|
353
357
|
return None
|
|
354
358
|
elif returnValue == QMessageBox.Yes:
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
if os.path.exists(os.sep.join([self.parent_window.pos,'output','tables',f'napari_{self.mode[:-1]}_trajectories.npy'])):
|
|
360
|
-
os.remove(os.sep.join([self.parent_window.pos,'output','tables',f'napari_{self.mode[:-1]}_trajectories.npy']))
|
|
361
|
-
if os.path.exists(os.sep.join([self.parent_window.pos,'output','tables',f'trajectories_pairs.csv'])):
|
|
362
|
-
os.remove(os.sep.join([self.parent_window.pos,'output','tables',f'trajectories_pairs.csv']))
|
|
359
|
+
remove_file_if_exists(os.sep.join([self.parent_window.pos, 'output', 'tables', f'trajectories_{self.mode}.csv']))
|
|
360
|
+
remove_file_if_exists(os.sep.join([self.parent_window.pos, 'output', 'tables', f'trajectories_{self.mode}.pkl']))
|
|
361
|
+
remove_file_if_exists(os.sep.join([self.parent_window.pos, 'output', 'tables', f'napari_{self.mode[:-1]}_trajectories.npy']))
|
|
362
|
+
remove_file_if_exists(os.sep.join([self.parent_window.pos, 'output', 'tables', f'trajectories_pairs.csv']))
|
|
363
363
|
self.parent_window.update_position_options()
|
|
364
364
|
else:
|
|
365
365
|
return None
|
|
@@ -378,6 +378,23 @@ class ProcessPanel(QFrame, Styles):
|
|
|
378
378
|
#self.to_disable.append(self.segment_action)
|
|
379
379
|
grid_segment.addWidget(self.segment_action, 90)
|
|
380
380
|
|
|
381
|
+
# self.flip_segment_btn = QPushButton()
|
|
382
|
+
# self.flip_segment_btn.setIcon(icon(MDI6.camera_flip_outline,color="black"))
|
|
383
|
+
# self.flip_segment_btn.setIconSize(QSize(20, 20))
|
|
384
|
+
# self.flip_segment_btn.clicked.connect(self.flip_segmentation)
|
|
385
|
+
# self.flip_segment_btn.setStyleSheet(self.button_select_all)
|
|
386
|
+
# self.flip_segment_btn.setToolTip("Flip the order of the frames for segmentation.")
|
|
387
|
+
# grid_segment.addWidget(self.flip_segment_btn, 5)
|
|
388
|
+
|
|
389
|
+
self.segmentation_config_btn = QPushButton()
|
|
390
|
+
self.segmentation_config_btn.setIcon(icon(MDI6.cog_outline,color="black"))
|
|
391
|
+
self.segmentation_config_btn.setIconSize(QSize(20, 20))
|
|
392
|
+
self.segmentation_config_btn.setToolTip("Configure segmentation.")
|
|
393
|
+
self.segmentation_config_btn.setStyleSheet(self.button_select_all)
|
|
394
|
+
self.segmentation_config_btn.clicked.connect(self.open_segmentation_configuration_ui)
|
|
395
|
+
grid_segment.addWidget(self.segmentation_config_btn, 5)
|
|
396
|
+
|
|
397
|
+
|
|
381
398
|
self.check_seg_btn = QPushButton()
|
|
382
399
|
self.check_seg_btn.setIcon(icon(MDI6.eye_check_outline,color="black"))
|
|
383
400
|
self.check_seg_btn.setIconSize(QSize(20, 20))
|
|
@@ -430,13 +447,25 @@ class ProcessPanel(QFrame, Styles):
|
|
|
430
447
|
self.seg_model_list.setEnabled(False)
|
|
431
448
|
self.grid_contents.addLayout(seg_option_vbox, 2, 0, 1, 4)
|
|
432
449
|
|
|
450
|
+
def flip_segmentation(self):
|
|
451
|
+
if not self.flipSeg:
|
|
452
|
+
self.flipSeg = True
|
|
453
|
+
self.flip_segment_btn.setIcon(icon(MDI6.camera_flip,color=self.celldetective_blue))
|
|
454
|
+
self.flip_segment_btn.setIconSize(QSize(20, 20))
|
|
455
|
+
self.flip_segment_btn.setToolTip("Unflip the order of the frames for segmentation.")
|
|
456
|
+
else:
|
|
457
|
+
self.flipSeg = False
|
|
458
|
+
self.flip_segment_btn.setIcon(icon(MDI6.camera_flip_outline,color='black'))
|
|
459
|
+
self.flip_segment_btn.setIconSize(QSize(20, 20))
|
|
460
|
+
self.flip_segment_btn.setToolTip("Flip the order of the frames for segmentation.")
|
|
461
|
+
|
|
433
462
|
def help_segmentation(self):
|
|
434
463
|
|
|
435
464
|
"""
|
|
436
465
|
Widget with different decision helper decision trees.
|
|
437
466
|
"""
|
|
438
467
|
|
|
439
|
-
self.help_w =
|
|
468
|
+
self.help_w = CelldetectiveWidget()
|
|
440
469
|
self.help_w.setWindowTitle('Helper')
|
|
441
470
|
layout = QVBoxLayout()
|
|
442
471
|
seg_strategy_btn = QPushButton('A guide to choose a segmentation strategy.')
|
|
@@ -552,16 +581,26 @@ class ProcessPanel(QFrame, Styles):
|
|
|
552
581
|
#QApplication.setOverrideCursor(Qt.WaitCursor)
|
|
553
582
|
test = self.parent_window.locate_selected_position()
|
|
554
583
|
if test:
|
|
555
|
-
print('Memory use: ', dict(psutil.virtual_memory()._asdict()))
|
|
584
|
+
#print('Memory use: ', dict(psutil.virtual_memory()._asdict()))
|
|
585
|
+
print(f"Loading images and labels into napari...")
|
|
556
586
|
try:
|
|
557
587
|
control_segmentation_napari(self.parent_window.pos, prefix=self.parent_window.movie_prefix, population=self.mode,flush_memory=True)
|
|
588
|
+
except FileNotFoundError as e:
|
|
589
|
+
msgBox = QMessageBox()
|
|
590
|
+
msgBox.setIcon(QMessageBox.Warning)
|
|
591
|
+
msgBox.setText(str(e))
|
|
592
|
+
msgBox.setWindowTitle("Warning")
|
|
593
|
+
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
594
|
+
_ = msgBox.exec()
|
|
595
|
+
return
|
|
558
596
|
except Exception as e:
|
|
597
|
+
print(f'Task unsuccessful... Exception {e}...')
|
|
559
598
|
msgBox = QMessageBox()
|
|
560
599
|
msgBox.setIcon(QMessageBox.Warning)
|
|
561
600
|
msgBox.setText(str(e))
|
|
562
601
|
msgBox.setWindowTitle("Warning")
|
|
563
602
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
564
|
-
|
|
603
|
+
_ = msgBox.exec()
|
|
565
604
|
|
|
566
605
|
msgBox = QMessageBox()
|
|
567
606
|
msgBox.setIcon(QMessageBox.Question)
|
|
@@ -586,15 +625,15 @@ class ProcessPanel(QFrame, Styles):
|
|
|
586
625
|
|
|
587
626
|
test = self.parent_window.locate_selected_position()
|
|
588
627
|
if test:
|
|
589
|
-
self.
|
|
590
|
-
self.
|
|
628
|
+
self.event_annotator = EventAnnotator(self)
|
|
629
|
+
self.event_annotator.show()
|
|
591
630
|
|
|
592
631
|
def check_measurements(self):
|
|
593
632
|
|
|
594
633
|
test = self.parent_window.locate_selected_position()
|
|
595
634
|
if test:
|
|
596
|
-
self.
|
|
597
|
-
self.
|
|
635
|
+
self.measure_annotator = MeasureAnnotator(self)
|
|
636
|
+
self.measure_annotator.show()
|
|
598
637
|
|
|
599
638
|
def enable_segmentation_model_list(self):
|
|
600
639
|
if self.segment_action.isChecked():
|
|
@@ -611,39 +650,40 @@ class ProcessPanel(QFrame, Styles):
|
|
|
611
650
|
def init_seg_model_list(self):
|
|
612
651
|
|
|
613
652
|
self.seg_model_list.clear()
|
|
614
|
-
self.
|
|
615
|
-
|
|
616
|
-
self.
|
|
617
|
-
#self.seg_model_list.addItems(models_truncated)
|
|
653
|
+
self.seg_models_specific = get_segmentation_models_list(mode=self.mode, return_path=False)
|
|
654
|
+
self.seg_models = self.seg_models_specific.copy()
|
|
655
|
+
self.n_specific_seg_models = len(self.seg_models)
|
|
618
656
|
|
|
619
657
|
self.seg_models_generic = get_segmentation_models_list(mode="generic", return_path=False)
|
|
620
658
|
self.seg_models.append('Threshold')
|
|
621
659
|
self.seg_models.extend(self.seg_models_generic)
|
|
622
660
|
|
|
623
|
-
|
|
624
|
-
self.
|
|
661
|
+
thresh = 35
|
|
662
|
+
self.models_truncated = [m[:thresh - 3]+'...' if len(m)>thresh else m for m in self.seg_models]
|
|
663
|
+
|
|
664
|
+
self.seg_model_list.addItems(self.models_truncated)
|
|
625
665
|
|
|
626
666
|
for i in range(len(self.seg_models)):
|
|
627
667
|
self.seg_model_list.setItemData(i, self.seg_models[i], Qt.ToolTipRole)
|
|
628
668
|
|
|
629
|
-
self.seg_model_list.insertSeparator(
|
|
630
|
-
|
|
631
|
-
def tick_all_actions(self):
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
def switch_all_ticks_option(self):
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
669
|
+
self.seg_model_list.insertSeparator(self.n_specific_seg_models)
|
|
670
|
+
|
|
671
|
+
# def tick_all_actions(self):
|
|
672
|
+
# self.switch_all_ticks_option()
|
|
673
|
+
# if self.all_ticked:
|
|
674
|
+
# self.select_all_btn.setIcon(icon(MDI6.checkbox_outline,color="black"))
|
|
675
|
+
# self.select_all_btn.setIconSize(QSize(20, 20))
|
|
676
|
+
# self.segment_action.setChecked(True)
|
|
677
|
+
# else:
|
|
678
|
+
# self.select_all_btn.setIcon(icon(MDI6.checkbox_blank_outline,color="black"))
|
|
679
|
+
# self.select_all_btn.setIconSize(QSize(20, 20))
|
|
680
|
+
# self.segment_action.setChecked(False)
|
|
681
|
+
|
|
682
|
+
# def switch_all_ticks_option(self):
|
|
683
|
+
# if self.all_ticked == True:
|
|
684
|
+
# self.all_ticked = False
|
|
685
|
+
# else:
|
|
686
|
+
# self.all_ticked = True
|
|
647
687
|
|
|
648
688
|
def upload_segmentation_model(self):
|
|
649
689
|
print('Load a segmentation model or pipeline...')
|
|
@@ -652,23 +692,28 @@ class ProcessPanel(QFrame, Styles):
|
|
|
652
692
|
|
|
653
693
|
def open_tracking_configuration_ui(self):
|
|
654
694
|
print('Set the tracking parameters...')
|
|
655
|
-
self.
|
|
656
|
-
self.
|
|
695
|
+
self.settings_tracking = SettingsTracking(self)
|
|
696
|
+
self.settings_tracking.show()
|
|
657
697
|
|
|
658
698
|
def open_signal_model_config_ui(self):
|
|
659
699
|
print('Set the training parameters for new signal models...')
|
|
660
|
-
self.
|
|
661
|
-
self.
|
|
700
|
+
self.settings_event_detection_training = SettingsEventDetectionModelTraining(self)
|
|
701
|
+
self.settings_event_detection_training.show()
|
|
662
702
|
|
|
663
703
|
def open_segmentation_model_config_ui(self):
|
|
664
704
|
print('Set the training parameters for a new segmentation model...')
|
|
665
|
-
self.
|
|
666
|
-
self.
|
|
705
|
+
self.settings_segmentation_training = SettingsSegmentationModelTraining(self)
|
|
706
|
+
self.settings_segmentation_training.show()
|
|
667
707
|
|
|
668
708
|
def open_measurement_configuration_ui(self):
|
|
669
709
|
print('Set the measurements to be performed...')
|
|
670
|
-
self.
|
|
671
|
-
self.
|
|
710
|
+
self.settings_measurements = SettingsMeasurements(self)
|
|
711
|
+
self.settings_measurements.show()
|
|
712
|
+
|
|
713
|
+
def open_segmentation_configuration_ui(self):
|
|
714
|
+
print('Set the segmentation settings to be performed...')
|
|
715
|
+
self.settings_segmentation = SettingsSegmentation(self)
|
|
716
|
+
self.settings_segmentation.show()
|
|
672
717
|
|
|
673
718
|
def open_classifier_ui(self):
|
|
674
719
|
|
|
@@ -690,12 +735,16 @@ class ProcessPanel(QFrame, Styles):
|
|
|
690
735
|
self.ClassifierWidget.show()
|
|
691
736
|
|
|
692
737
|
def open_signal_annotator_configuration_ui(self):
|
|
693
|
-
self.
|
|
694
|
-
self.
|
|
738
|
+
self.settings_signal_annotator = SettingsSignalAnnotator(self)
|
|
739
|
+
self.settings_signal_annotator.show()
|
|
695
740
|
|
|
696
741
|
def reset_generalist_setup(self, index):
|
|
697
742
|
self.cellpose_calibrated = False
|
|
698
743
|
self.stardist_calibrated = False
|
|
744
|
+
self.segChannelsSet = False
|
|
745
|
+
|
|
746
|
+
def reset_signals(self):
|
|
747
|
+
self.signalChannelsSet = False
|
|
699
748
|
|
|
700
749
|
def process_population(self):
|
|
701
750
|
|
|
@@ -721,10 +770,8 @@ class ProcessPanel(QFrame, Styles):
|
|
|
721
770
|
# self.freeze()
|
|
722
771
|
# QApplication.setOverrideCursor(Qt.WaitCursor)
|
|
723
772
|
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
elif self.mode=="effectors":
|
|
727
|
-
self.threshold_config = self.threshold_config_effectors
|
|
773
|
+
idx = self.parent_window.populations.index(self.mode)
|
|
774
|
+
self.threshold_config = self.threshold_configs[idx]
|
|
728
775
|
|
|
729
776
|
self.load_available_tables()
|
|
730
777
|
|
|
@@ -742,11 +789,14 @@ class ProcessPanel(QFrame, Styles):
|
|
|
742
789
|
else:
|
|
743
790
|
print('erase tabs!')
|
|
744
791
|
tabs = [pos+os.sep.join(['output', 'tables', f'trajectories_{self.mode}.csv']) for pos in self.df_pos_info['pos_path'].unique()]
|
|
792
|
+
#tabs += [pos+os.sep.join(['output', 'tables', f'trajectories_pairs.csv']) for pos in self.df_pos_info['pos_path'].unique()]
|
|
793
|
+
tabs += [pos+os.sep.join(['output', 'tables', f'napari_{self.mode}_trajectories.npy']) for pos in self.df_pos_info['pos_path'].unique()]
|
|
745
794
|
for t in tabs:
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
795
|
+
remove_file_if_exists(t.replace('.csv','.pkl'))
|
|
796
|
+
try:
|
|
797
|
+
os.remove(t)
|
|
798
|
+
except:
|
|
799
|
+
pass
|
|
750
800
|
loop_iter=0
|
|
751
801
|
|
|
752
802
|
if self.parent_window.position_list.isMultipleSelection():
|
|
@@ -759,11 +809,10 @@ class ProcessPanel(QFrame, Styles):
|
|
|
759
809
|
if returnValue == QMessageBox.No:
|
|
760
810
|
return None
|
|
761
811
|
|
|
762
|
-
if self.seg_model_list.currentIndex() >
|
|
812
|
+
if self.seg_model_list.currentIndex() > self.n_specific_seg_models:
|
|
763
813
|
self.model_name = self.seg_models[self.seg_model_list.currentIndex()-1]
|
|
764
814
|
else:
|
|
765
815
|
self.model_name = self.seg_models[self.seg_model_list.currentIndex()]
|
|
766
|
-
print(self.model_name, self.seg_model_list.currentIndex())
|
|
767
816
|
|
|
768
817
|
if self.segment_action.isChecked() and self.model_name.startswith('CP') and self.model_name in self.seg_models_generic and not self.cellpose_calibrated:
|
|
769
818
|
|
|
@@ -771,12 +820,25 @@ class ProcessPanel(QFrame, Styles):
|
|
|
771
820
|
self.diamWidget.show()
|
|
772
821
|
return None
|
|
773
822
|
|
|
774
|
-
|
|
823
|
+
elif self.segment_action.isChecked() and self.model_name.startswith('SD') and self.model_name in self.seg_models_generic and not self.stardist_calibrated:
|
|
775
824
|
|
|
776
825
|
self.diamWidget = StarDistParamsWidget(self, model_name = self.model_name)
|
|
777
826
|
self.diamWidget.show()
|
|
778
827
|
return None
|
|
779
828
|
|
|
829
|
+
elif self.segment_action.isChecked() and self.model_name in self.seg_models_specific and not self.segChannelsSet:
|
|
830
|
+
|
|
831
|
+
self.segChannelWidget = SegModelParamsWidget(self, model_name = self.model_name)
|
|
832
|
+
self.segChannelWidget.show()
|
|
833
|
+
return None
|
|
834
|
+
|
|
835
|
+
if self.signal_analysis_action.isChecked() and not self.signalChannelsSet:
|
|
836
|
+
self.signal_model_name = self.signal_models[self.signal_models_list.currentIndex()]
|
|
837
|
+
self.signalChannelWidget = SignalModelParamsWidget(self, model_name = self.signal_model_name)
|
|
838
|
+
self.signalChannelWidget.show()
|
|
839
|
+
return None
|
|
840
|
+
|
|
841
|
+
|
|
780
842
|
self.movie_prefix = self.parent_window.movie_prefix
|
|
781
843
|
|
|
782
844
|
for w_idx in self.well_index:
|
|
@@ -828,6 +890,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
828
890
|
if result == QDialog.Accepted:
|
|
829
891
|
pass
|
|
830
892
|
elif result == QDialog.Rejected:
|
|
893
|
+
self.reset_generalist_setup(0)
|
|
831
894
|
return None
|
|
832
895
|
#segment_from_threshold_at_position(self.pos, self.mode, self.threshold_config, threads=self.parent_window.parent_window.n_threads)
|
|
833
896
|
else:
|
|
@@ -842,6 +905,7 @@ class ProcessPanel(QFrame, Styles):
|
|
|
842
905
|
if result == QDialog.Accepted:
|
|
843
906
|
pass
|
|
844
907
|
elif result == QDialog.Rejected:
|
|
908
|
+
self.reset_generalist_setup(0)
|
|
845
909
|
return None
|
|
846
910
|
|
|
847
911
|
if self.track_action.isChecked():
|
|
@@ -890,7 +954,8 @@ class ProcessPanel(QFrame, Styles):
|
|
|
890
954
|
returnValue = msgBox.exec()
|
|
891
955
|
if returnValue == QMessageBox.No:
|
|
892
956
|
return None
|
|
893
|
-
|
|
957
|
+
self.signal_model_name = self.signal_models[self.signal_models_list.currentIndex()]
|
|
958
|
+
analyze_signals_at_position(self.pos, self.signal_model_name, self.mode)
|
|
894
959
|
|
|
895
960
|
|
|
896
961
|
# self.stack = None
|
|
@@ -900,10 +965,20 @@ class ProcessPanel(QFrame, Styles):
|
|
|
900
965
|
action.setChecked(False)
|
|
901
966
|
|
|
902
967
|
self.reset_generalist_setup(0)
|
|
968
|
+
self.reset_signals()
|
|
903
969
|
|
|
904
970
|
def open_napari_tracking(self):
|
|
905
971
|
print(f'View the tracks before post-processing for position {self.parent_window.pos} in napari...')
|
|
906
|
-
|
|
972
|
+
try:
|
|
973
|
+
control_tracks(self.parent_window.pos, prefix=self.parent_window.movie_prefix, population=self.mode, threads=self.parent_window.parent_window.n_threads)
|
|
974
|
+
except FileNotFoundError as e:
|
|
975
|
+
msgBox = QMessageBox()
|
|
976
|
+
msgBox.setIcon(QMessageBox.Warning)
|
|
977
|
+
msgBox.setText(str(e))
|
|
978
|
+
msgBox.setWindowTitle("Warning")
|
|
979
|
+
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
980
|
+
_ = msgBox.exec()
|
|
981
|
+
return
|
|
907
982
|
|
|
908
983
|
def view_table_ui(self):
|
|
909
984
|
|
|
@@ -938,8 +1013,11 @@ class ProcessPanel(QFrame, Styles):
|
|
|
938
1013
|
self.position_option = self.parent_window.position_list.getSelectedIndices()
|
|
939
1014
|
|
|
940
1015
|
self.df, self.df_pos_info = load_experiment_tables(self.exp_dir, well_option=self.well_option, position_option=self.position_option, population=self.mode, return_pos_info=True)
|
|
1016
|
+
self.signals = []
|
|
1017
|
+
if self.df is not None:
|
|
1018
|
+
self.signals = list(self.df.columns)
|
|
941
1019
|
if self.df is None:
|
|
942
|
-
print('No table could be found...')
|
|
1020
|
+
print('No table could be found for the selected position(s)...')
|
|
943
1021
|
|
|
944
1022
|
def set_cellpose_scale(self):
|
|
945
1023
|
|
|
@@ -951,7 +1029,6 @@ class ProcessPanel(QFrame, Styles):
|
|
|
951
1029
|
model_complete_path = locate_segmentation_model(self.model_name)
|
|
952
1030
|
input_config_path = model_complete_path+"config_input.json"
|
|
953
1031
|
new_channels = [self.diamWidget.cellpose_channel_cb[i].currentText() for i in range(2)]
|
|
954
|
-
print(new_channels)
|
|
955
1032
|
with open(input_config_path) as config_file:
|
|
956
1033
|
input_config = json.load(config_file)
|
|
957
1034
|
|
|
@@ -983,6 +1060,46 @@ class ProcessPanel(QFrame, Styles):
|
|
|
983
1060
|
self.diamWidget.close()
|
|
984
1061
|
self.process_population()
|
|
985
1062
|
|
|
1063
|
+
def set_selected_channels_for_segmentation(self):
|
|
1064
|
+
|
|
1065
|
+
model_complete_path = locate_segmentation_model(self.model_name)
|
|
1066
|
+
input_config_path = model_complete_path+"config_input.json"
|
|
1067
|
+
new_channels = [self.segChannelWidget.channel_cbs[i].currentText() for i in range(len(self.segChannelWidget.channel_cbs))]
|
|
1068
|
+
target_cell_size = None
|
|
1069
|
+
if hasattr(self.segChannelWidget, "diameter_le"):
|
|
1070
|
+
target_cell_size = float(self.segChannelWidget.diameter_le.get_threshold())
|
|
1071
|
+
|
|
1072
|
+
with open(input_config_path) as config_file:
|
|
1073
|
+
input_config = json.load(config_file)
|
|
1074
|
+
|
|
1075
|
+
input_config.update({'selected_channels': new_channels, 'target_cell_size_um': target_cell_size})
|
|
1076
|
+
|
|
1077
|
+
#input_config['channels'] = new_channels
|
|
1078
|
+
with open(input_config_path, 'w') as f:
|
|
1079
|
+
json.dump(input_config, f, indent=4)
|
|
1080
|
+
|
|
1081
|
+
self.segChannelsSet = True
|
|
1082
|
+
self.segChannelWidget.close()
|
|
1083
|
+
self.process_population()
|
|
1084
|
+
|
|
1085
|
+
def set_selected_signals_for_event_detection(self):
|
|
1086
|
+
self.signal_model_name = self.signal_models[self.signal_models_list.currentIndex()]
|
|
1087
|
+
model_complete_path = locate_signal_model(self.signal_model_name)
|
|
1088
|
+
input_config_path = model_complete_path+"config_input.json"
|
|
1089
|
+
new_channels = [self.signalChannelWidget.channel_cbs[i].currentText() for i in range(len(self.signalChannelWidget.channel_cbs))]
|
|
1090
|
+
with open(input_config_path) as config_file:
|
|
1091
|
+
input_config = json.load(config_file)
|
|
1092
|
+
|
|
1093
|
+
input_config.update({'selected_channels': new_channels})
|
|
1094
|
+
|
|
1095
|
+
#input_config['channels'] = new_channels
|
|
1096
|
+
with open(input_config_path, 'w') as f:
|
|
1097
|
+
json.dump(input_config, f, indent=4)
|
|
1098
|
+
|
|
1099
|
+
self.signalChannelsSet = True
|
|
1100
|
+
self.signalChannelWidget.close()
|
|
1101
|
+
self.process_population()
|
|
1102
|
+
|
|
986
1103
|
|
|
987
1104
|
|
|
988
1105
|
class NeighPanel(QFrame, Styles):
|
|
@@ -1034,11 +1151,10 @@ class NeighPanel(QFrame, Styles):
|
|
|
1034
1151
|
|
|
1035
1152
|
def collapse_advanced(self):
|
|
1036
1153
|
|
|
1037
|
-
|
|
1038
|
-
targets_open = not self.parent_window.ProcessTargets.ContentsFrame.isHidden()
|
|
1154
|
+
panels_open = [not p.ContentsFrame.isHidden() for p in self.parent_window.ProcessPopulations]
|
|
1039
1155
|
interactions_open = not self.parent_window.NeighPanel.ContentsFrame.isHidden()
|
|
1040
1156
|
preprocessing_open = not self.parent_window.PreprocessingPanel.ContentsFrame.isHidden()
|
|
1041
|
-
is_open = np.array([
|
|
1157
|
+
is_open = np.array(panels_open+[interactions_open, preprocessing_open])
|
|
1042
1158
|
|
|
1043
1159
|
if self.ContentsFrame.isHidden():
|
|
1044
1160
|
self.collapse_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
@@ -1363,12 +1479,12 @@ class NeighPanel(QFrame, Styles):
|
|
|
1363
1479
|
|
|
1364
1480
|
def open_signal_annotator_configuration_ui(self):
|
|
1365
1481
|
self.mode = 'pairs'
|
|
1366
|
-
self.
|
|
1367
|
-
self.
|
|
1482
|
+
self.config_signal_annotator = SettingsSignalAnnotator(self)
|
|
1483
|
+
self.config_signal_annotator.show()
|
|
1368
1484
|
|
|
1369
1485
|
def open_signal_model_config_ui(self):
|
|
1370
|
-
self.
|
|
1371
|
-
self.
|
|
1486
|
+
self.settings_pair_event_detection_training = SettingsEventDetectionModelTraining(self, signal_mode='pairs')
|
|
1487
|
+
self.settings_pair_event_detection_training.show()
|
|
1372
1488
|
|
|
1373
1489
|
def remove_protocol_from_list(self):
|
|
1374
1490
|
|
|
@@ -1379,7 +1495,7 @@ class NeighPanel(QFrame, Styles):
|
|
|
1379
1495
|
|
|
1380
1496
|
def open_config_distance_threshold_neighborhood(self):
|
|
1381
1497
|
|
|
1382
|
-
self.ConfigNeigh =
|
|
1498
|
+
self.ConfigNeigh = SettingsNeighborhood(parent_window=self,
|
|
1383
1499
|
neighborhood_type='distance_threshold',
|
|
1384
1500
|
neighborhood_parameter_name='threshold distance',
|
|
1385
1501
|
)
|
|
@@ -1387,7 +1503,7 @@ class NeighPanel(QFrame, Styles):
|
|
|
1387
1503
|
|
|
1388
1504
|
def open_config_contact_neighborhood(self):
|
|
1389
1505
|
|
|
1390
|
-
self.ConfigNeigh =
|
|
1506
|
+
self.ConfigNeigh = SettingsNeighborhood(parent_window=self,
|
|
1391
1507
|
neighborhood_type='mask_contact',
|
|
1392
1508
|
neighborhood_parameter_name='tolerance contact distance',
|
|
1393
1509
|
)
|
|
@@ -1432,6 +1548,7 @@ class NeighPanel(QFrame, Styles):
|
|
|
1432
1548
|
for pos_idx in pos_indices:
|
|
1433
1549
|
|
|
1434
1550
|
self.pos = natsorted(glob(well+f"{os.path.split(well)[-1].replace('W','').replace(os.sep,'')}*{os.sep}"))[pos_idx]
|
|
1551
|
+
self.pos_name = extract_position_name(self.pos)
|
|
1435
1552
|
print(f"Position {self.pos}...\nLoading stack movie...")
|
|
1436
1553
|
|
|
1437
1554
|
if not os.path.exists(self.pos + 'output' + os.sep):
|
|
@@ -1442,55 +1559,35 @@ class NeighPanel(QFrame, Styles):
|
|
|
1442
1559
|
if self.neigh_action.isChecked():
|
|
1443
1560
|
for protocol in self.protocols:
|
|
1444
1561
|
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
event_time_col=protocol['event_time_col'],
|
|
1455
|
-
neighborhood_kwargs=protocol['neighborhood_kwargs'],
|
|
1456
|
-
)
|
|
1457
|
-
|
|
1458
|
-
elif protocol['neighborhood_type']=='mask_contact':
|
|
1459
|
-
|
|
1460
|
-
compute_contact_neighborhood_at_position(self.pos,
|
|
1461
|
-
protocol['distance'],
|
|
1462
|
-
population=protocol['population'],
|
|
1463
|
-
theta_dist=None,
|
|
1464
|
-
img_shape=(self.parent_window.shape_x,self.parent_window.shape_y),
|
|
1465
|
-
return_tables=False,
|
|
1466
|
-
clear_neigh=protocol['clear_neigh'],
|
|
1467
|
-
event_time_col=protocol['event_time_col'],
|
|
1468
|
-
neighborhood_kwargs=protocol['neighborhood_kwargs'],
|
|
1469
|
-
)
|
|
1562
|
+
process_args = {"pos": self.pos, "pos_name": self.pos_name,"protocol": protocol,"img_shape": (self.parent_window.shape_x,self.parent_window.shape_y)} #"n_threads": self.n_threads
|
|
1563
|
+
self.job = ProgressWindow(NeighborhoodProcess, parent_window=self, title="Neighborhood",
|
|
1564
|
+
process_args=process_args)
|
|
1565
|
+
result = self.job.exec_()
|
|
1566
|
+
if result == QDialog.Accepted:
|
|
1567
|
+
pass
|
|
1568
|
+
elif result == QDialog.Rejected:
|
|
1569
|
+
return None
|
|
1570
|
+
|
|
1470
1571
|
if self.measure_pairs_action.isChecked():
|
|
1471
1572
|
rel_measure_at_position(self.pos)
|
|
1472
1573
|
|
|
1473
1574
|
if self.signal_analysis_action.isChecked():
|
|
1474
1575
|
|
|
1475
|
-
analyze_pair_signals_at_position(self.pos, self.pair_signal_models_list.currentText(), use_gpu=self.parent_window.parent_window.use_gpu)
|
|
1576
|
+
analyze_pair_signals_at_position(self.pos, self.pair_signal_models_list.currentText(), use_gpu=self.parent_window.parent_window.use_gpu, populations=self.parent_window.populations)
|
|
1476
1577
|
|
|
1477
1578
|
self.parent_window.update_position_options()
|
|
1579
|
+
for action in [self.neigh_action, self.measure_pairs_action, self.signal_analysis_action]:
|
|
1580
|
+
if action.isChecked():
|
|
1581
|
+
action.setChecked(False)
|
|
1582
|
+
|
|
1478
1583
|
print('Done.')
|
|
1479
1584
|
|
|
1480
1585
|
def check_signals2(self):
|
|
1481
1586
|
|
|
1482
1587
|
test = self.parent_window.locate_selected_position()
|
|
1483
1588
|
if test:
|
|
1484
|
-
self.
|
|
1485
|
-
self.
|
|
1486
|
-
|
|
1487
|
-
def check_measurements2(self):
|
|
1488
|
-
|
|
1489
|
-
test = self.parent_window.locate_selected_position()
|
|
1490
|
-
if test:
|
|
1491
|
-
self.MeasurementAnnotator2 = MeasureAnnotator2(self)
|
|
1492
|
-
self.MeasurementAnnotator2.show()
|
|
1493
|
-
|
|
1589
|
+
self.pair_event_annotator = PairEventAnnotator(self)
|
|
1590
|
+
self.pair_event_annotator.show()
|
|
1494
1591
|
|
|
1495
1592
|
|
|
1496
1593
|
class PreprocessingPanel(QFrame, Styles):
|
|
@@ -1529,13 +1626,13 @@ class PreprocessingPanel(QFrame, Styles):
|
|
|
1529
1626
|
|
|
1530
1627
|
self.grid.addWidget(panel_title, 0, 0, 1, 4, alignment=Qt.AlignCenter)
|
|
1531
1628
|
|
|
1532
|
-
self.select_all_btn = QPushButton()
|
|
1533
|
-
self.select_all_btn.setIcon(icon(MDI6.checkbox_blank_outline,color="black"))
|
|
1534
|
-
self.select_all_btn.setIconSize(QSize(20, 20))
|
|
1535
|
-
self.all_ticked = False
|
|
1536
|
-
#self.select_all_btn.clicked.connect(self.tick_all_actions)
|
|
1537
|
-
self.select_all_btn.setStyleSheet(self.button_select_all)
|
|
1538
|
-
self.grid.addWidget(self.select_all_btn, 0, 0, 1, 4, alignment=Qt.AlignLeft)
|
|
1629
|
+
# self.select_all_btn = QPushButton()
|
|
1630
|
+
# self.select_all_btn.setIcon(icon(MDI6.checkbox_blank_outline,color="black"))
|
|
1631
|
+
# self.select_all_btn.setIconSize(QSize(20, 20))
|
|
1632
|
+
# self.all_ticked = False
|
|
1633
|
+
# #self.select_all_btn.clicked.connect(self.tick_all_actions)
|
|
1634
|
+
# self.select_all_btn.setStyleSheet(self.button_select_all)
|
|
1635
|
+
# self.grid.addWidget(self.select_all_btn, 0, 0, 1, 4, alignment=Qt.AlignLeft)
|
|
1539
1636
|
#self.to_disable.append(self.all_tc_actions)
|
|
1540
1637
|
|
|
1541
1638
|
self.collapse_btn = QPushButton()
|
|
@@ -1553,12 +1650,11 @@ class PreprocessingPanel(QFrame, Styles):
|
|
|
1553
1650
|
|
|
1554
1651
|
def collapse_advanced(self):
|
|
1555
1652
|
|
|
1556
|
-
|
|
1557
|
-
targets_open = not self.parent_window.ProcessTargets.ContentsFrame.isHidden()
|
|
1653
|
+
panels_open = [not p.ContentsFrame.isHidden() for p in self.parent_window.ProcessPopulations]
|
|
1558
1654
|
interactions_open = not self.parent_window.NeighPanel.ContentsFrame.isHidden()
|
|
1559
1655
|
preprocessing_open = not self.parent_window.PreprocessingPanel.ContentsFrame.isHidden()
|
|
1560
|
-
is_open = np.array([
|
|
1561
|
-
|
|
1656
|
+
is_open = np.array(panels_open+[interactions_open, preprocessing_open])
|
|
1657
|
+
|
|
1562
1658
|
if self.ContentsFrame.isHidden():
|
|
1563
1659
|
self.collapse_btn.setIcon(icon(MDI6.chevron_down,color="black"))
|
|
1564
1660
|
self.collapse_btn.setIconSize(QSize(20, 20))
|
|
@@ -1592,7 +1688,6 @@ class PreprocessingPanel(QFrame, Styles):
|
|
|
1592
1688
|
self.help_background_btn.setToolTip("Help.")
|
|
1593
1689
|
|
|
1594
1690
|
self.protocol_layout.title_layout.addWidget(self.help_background_btn, 5, alignment=Qt.AlignRight)
|
|
1595
|
-
|
|
1596
1691
|
|
|
1597
1692
|
self.channel_offset_correction_layout = QVBoxLayout()
|
|
1598
1693
|
|