celldetective 1.0.2.post1__py3-none-any.whl → 1.1.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/__main__.py +7 -21
- celldetective/events.py +2 -44
- celldetective/extra_properties.py +62 -52
- celldetective/filters.py +4 -5
- celldetective/gui/__init__.py +1 -1
- celldetective/gui/analyze_block.py +37 -10
- celldetective/gui/btrack_options.py +24 -23
- celldetective/gui/classifier_widget.py +62 -19
- celldetective/gui/configure_new_exp.py +32 -35
- celldetective/gui/control_panel.py +120 -81
- celldetective/gui/gui_utils.py +674 -396
- celldetective/gui/json_readers.py +7 -6
- celldetective/gui/layouts.py +756 -0
- celldetective/gui/measurement_options.py +98 -513
- celldetective/gui/neighborhood_options.py +322 -270
- celldetective/gui/plot_measurements.py +1114 -0
- celldetective/gui/plot_signals_ui.py +21 -20
- celldetective/gui/process_block.py +449 -169
- celldetective/gui/retrain_segmentation_model_options.py +27 -26
- celldetective/gui/retrain_signal_model_options.py +25 -24
- celldetective/gui/seg_model_loader.py +31 -27
- celldetective/gui/signal_annotator.py +2326 -2295
- celldetective/gui/signal_annotator_options.py +18 -16
- celldetective/gui/styles.py +16 -1
- celldetective/gui/survival_ui.py +67 -39
- celldetective/gui/tableUI.py +337 -48
- celldetective/gui/thresholds_gui.py +75 -71
- celldetective/gui/viewers.py +743 -0
- celldetective/io.py +247 -27
- celldetective/measure.py +43 -263
- celldetective/models/segmentation_effectors/primNK_cfse/config_input.json +29 -0
- celldetective/models/segmentation_effectors/primNK_cfse/cp-cfse-transfer +0 -0
- celldetective/models/segmentation_effectors/primNK_cfse/training_instructions.json +37 -0
- celldetective/neighborhood.py +498 -27
- celldetective/preprocessing.py +1023 -0
- celldetective/scripts/analyze_signals.py +7 -0
- celldetective/scripts/measure_cells.py +12 -0
- celldetective/scripts/segment_cells.py +20 -4
- celldetective/scripts/track_cells.py +11 -0
- celldetective/scripts/train_segmentation_model.py +35 -34
- celldetective/segmentation.py +14 -9
- celldetective/signals.py +234 -329
- celldetective/tracking.py +2 -2
- celldetective/utils.py +602 -49
- celldetective-1.1.1.dist-info/METADATA +305 -0
- celldetective-1.1.1.dist-info/RECORD +84 -0
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/top_level.txt +1 -0
- tests/__init__.py +0 -0
- tests/test_events.py +28 -0
- tests/test_filters.py +24 -0
- tests/test_io.py +70 -0
- tests/test_measure.py +141 -0
- tests/test_neighborhood.py +70 -0
- tests/test_preprocessing.py +37 -0
- tests/test_segmentation.py +93 -0
- tests/test_signals.py +135 -0
- tests/test_tracking.py +164 -0
- tests/test_utils.py +118 -0
- celldetective-1.0.2.post1.dist-info/METADATA +0 -221
- celldetective-1.0.2.post1.dist-info/RECORD +0 -66
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/LICENSE +0 -0
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/WHEEL +0 -0
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/entry_points.txt +0 -0
|
@@ -12,27 +12,28 @@ import numpy as np
|
|
|
12
12
|
from superqt.fonticon import icon
|
|
13
13
|
from fonticon_mdi6 import MDI6
|
|
14
14
|
import os
|
|
15
|
+
from celldetective.gui import Styles
|
|
15
16
|
|
|
16
|
-
class ConfigSignalAnnotator(QMainWindow):
|
|
17
|
+
class ConfigSignalAnnotator(QMainWindow, Styles):
|
|
17
18
|
|
|
18
19
|
"""
|
|
19
20
|
UI to set normalization and animation parameters for the annotator tool.
|
|
20
21
|
|
|
21
22
|
"""
|
|
22
23
|
|
|
23
|
-
def __init__(self,
|
|
24
|
+
def __init__(self, parent_window=None):
|
|
24
25
|
|
|
25
26
|
super().__init__()
|
|
26
|
-
self.
|
|
27
|
+
self.parent_window = parent_window
|
|
27
28
|
self.setWindowTitle("Configure signal annotator")
|
|
28
|
-
self.mode = self.
|
|
29
|
-
self.exp_dir = self.
|
|
29
|
+
self.mode = self.parent_window.mode
|
|
30
|
+
self.exp_dir = self.parent_window.exp_dir
|
|
30
31
|
self.soft_path = get_software_location()
|
|
31
32
|
|
|
32
33
|
if self.mode=="targets":
|
|
33
|
-
self.instructions_path = self.
|
|
34
|
+
self.instructions_path = self.parent_window.exp_dir + "configs/signal_annotator_config_targets.json"
|
|
34
35
|
elif self.mode=="effectors":
|
|
35
|
-
self.instructions_path = self.
|
|
36
|
+
self.instructions_path = self.parent_window.exp_dir + "configs/signal_annotator_config_effectors.json"
|
|
36
37
|
|
|
37
38
|
exp_config = self.exp_dir +"config.ini"
|
|
38
39
|
#self.config_path = self.exp_dir + self.config_name
|
|
@@ -41,7 +42,7 @@ class ConfigSignalAnnotator(QMainWindow):
|
|
|
41
42
|
self.channels = np.array(self.channels)
|
|
42
43
|
self.log_option = False
|
|
43
44
|
|
|
44
|
-
self.screen_height = self.
|
|
45
|
+
self.screen_height = self.parent_window.parent_window.parent_window.screen_height
|
|
45
46
|
center_window(self)
|
|
46
47
|
|
|
47
48
|
self.setMinimumHeight(int(0.4*self.screen_height))
|
|
@@ -49,6 +50,7 @@ class ConfigSignalAnnotator(QMainWindow):
|
|
|
49
50
|
self.populate_widget()
|
|
50
51
|
#self.load_previous_measurement_instructions()
|
|
51
52
|
|
|
53
|
+
|
|
52
54
|
def populate_widget(self):
|
|
53
55
|
|
|
54
56
|
"""
|
|
@@ -59,13 +61,13 @@ class ConfigSignalAnnotator(QMainWindow):
|
|
|
59
61
|
self.scroll_area = QScrollArea(self)
|
|
60
62
|
self.button_widget = QWidget()
|
|
61
63
|
|
|
62
|
-
main_layout = QVBoxLayout()
|
|
63
|
-
main_layout.setContentsMargins(30,30,30,30)
|
|
64
|
+
self.main_layout = QVBoxLayout()
|
|
65
|
+
self.main_layout.setContentsMargins(30,30,30,30)
|
|
64
66
|
|
|
65
67
|
sub_layout = QVBoxLayout()
|
|
66
68
|
sub_layout.setContentsMargins(10,10,10,20)
|
|
67
69
|
|
|
68
|
-
self.button_widget.setLayout(main_layout)
|
|
70
|
+
self.button_widget.setLayout(self.main_layout)
|
|
69
71
|
sub_layout.setContentsMargins(30,30,30,30)
|
|
70
72
|
|
|
71
73
|
sub_layout.addWidget(QLabel('Modality: '))
|
|
@@ -85,13 +87,13 @@ class ConfigSignalAnnotator(QMainWindow):
|
|
|
85
87
|
self.percentile_btn = QPushButton()
|
|
86
88
|
self.percentile_btn.setIcon(icon(MDI6.percent_circle_outline,color="black"))
|
|
87
89
|
self.percentile_btn.setIconSize(QSize(20, 20))
|
|
88
|
-
self.percentile_btn.setStyleSheet(self.
|
|
90
|
+
self.percentile_btn.setStyleSheet(self.button_select_all)
|
|
89
91
|
self.percentile_btn.setToolTip("Switch to percentile normalization values.")
|
|
90
92
|
self.percentile_btn.clicked.connect(self.switch_to_absolute_normalization_mode)
|
|
91
93
|
|
|
92
94
|
self.log_btn = QPushButton()
|
|
93
95
|
self.log_btn.setIcon(icon(MDI6.math_log,color="black"))
|
|
94
|
-
self.log_btn.setStyleSheet(self.
|
|
96
|
+
self.log_btn.setStyleSheet(self.button_select_all)
|
|
95
97
|
self.log_btn.clicked.connect(self.switch_to_log)
|
|
96
98
|
self.log_btn.setToolTip("Log-transform the intensities.")
|
|
97
99
|
self.log_btn.setIconSize(QSize(20, 20))
|
|
@@ -168,12 +170,12 @@ class ConfigSignalAnnotator(QMainWindow):
|
|
|
168
170
|
hbox_interval.addWidget(self.interval_slider, 80)
|
|
169
171
|
sub_layout.addLayout(hbox_interval)
|
|
170
172
|
|
|
171
|
-
main_layout.addLayout(sub_layout)
|
|
173
|
+
self.main_layout.addLayout(sub_layout)
|
|
172
174
|
|
|
173
175
|
self.submit_btn = QPushButton('Save')
|
|
174
|
-
self.submit_btn.setStyleSheet(self.
|
|
176
|
+
self.submit_btn.setStyleSheet(self.button_style_sheet)
|
|
175
177
|
self.submit_btn.clicked.connect(self.write_instructions)
|
|
176
|
-
main_layout.addWidget(self.submit_btn)
|
|
178
|
+
self.main_layout.addWidget(self.submit_btn)
|
|
177
179
|
|
|
178
180
|
|
|
179
181
|
self.button_widget.adjustSize()
|
celldetective/gui/styles.py
CHANGED
|
@@ -4,6 +4,14 @@ class Styles(object):
|
|
|
4
4
|
|
|
5
5
|
self.init_button_styles()
|
|
6
6
|
self.init_tab_styles()
|
|
7
|
+
self.init_label_styles()
|
|
8
|
+
|
|
9
|
+
self.celldetective_blue = "#1565c0"
|
|
10
|
+
|
|
11
|
+
self.action_lbl_style_sheet = """
|
|
12
|
+
font-size: 10px;
|
|
13
|
+
padding-left: 10px;
|
|
14
|
+
"""
|
|
7
15
|
|
|
8
16
|
def init_button_styles(self):
|
|
9
17
|
|
|
@@ -214,4 +222,11 @@ class Styles(object):
|
|
|
214
222
|
QTabBar::tab:left:only-one, QTabBar::tab:right:only-one {
|
|
215
223
|
margin-bottom: 0;
|
|
216
224
|
}
|
|
217
|
-
"""
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
def init_label_styles(self):
|
|
228
|
+
|
|
229
|
+
self.block_title = '''
|
|
230
|
+
font-weight: bold;
|
|
231
|
+
padding: 0px;
|
|
232
|
+
'''
|
celldetective/gui/survival_ui.py
CHANGED
|
@@ -2,7 +2,7 @@ from PyQt5.QtWidgets import QMainWindow, QApplication, QMessageBox, QScrollArea,
|
|
|
2
2
|
from PyQt5.QtCore import Qt, QSize
|
|
3
3
|
from PyQt5.QtGui import QIcon, QDoubleValidator
|
|
4
4
|
from celldetective.gui.gui_utils import center_window, FeatureChoice, ListWidget, QHSeperationLine, FigureCanvas, GeometryChoice, OperationChoice
|
|
5
|
-
from superqt import QLabeledDoubleRangeSlider, QLabeledDoubleSlider,QLabeledSlider
|
|
5
|
+
from superqt import QLabeledDoubleRangeSlider, QLabeledDoubleSlider,QLabeledSlider, QColormapComboBox
|
|
6
6
|
from superqt.fonticon import icon
|
|
7
7
|
from fonticon_mdi6 import MDI6
|
|
8
8
|
from celldetective.utils import extract_experiment_channels, get_software_location, _extract_labels_from_config
|
|
@@ -26,40 +26,39 @@ from tqdm import tqdm
|
|
|
26
26
|
from lifelines import KaplanMeierFitter
|
|
27
27
|
import matplotlib.cm as mcm
|
|
28
28
|
import math
|
|
29
|
-
from celldetective.events import
|
|
29
|
+
from celldetective.events import switch_to_events
|
|
30
|
+
from celldetective.gui import Styles
|
|
31
|
+
from matplotlib import colormaps
|
|
30
32
|
|
|
31
|
-
class ConfigSurvival(QWidget):
|
|
33
|
+
class ConfigSurvival(QWidget, Styles):
|
|
32
34
|
|
|
33
35
|
"""
|
|
34
36
|
UI to set survival instructions.
|
|
35
37
|
|
|
36
38
|
"""
|
|
37
39
|
|
|
38
|
-
def __init__(self,
|
|
40
|
+
def __init__(self, parent_window=None):
|
|
39
41
|
|
|
40
42
|
super().__init__()
|
|
41
|
-
self.
|
|
43
|
+
self.parent_window = parent_window
|
|
42
44
|
self.setWindowTitle("Configure survival")
|
|
43
|
-
self.setWindowIcon(QIcon(os.sep.join(['celldetective','icons','
|
|
45
|
+
self.setWindowIcon(QIcon(os.sep.join(['celldetective','icons','logo.png'])))
|
|
44
46
|
|
|
45
|
-
self.exp_dir = self.
|
|
47
|
+
self.exp_dir = self.parent_window.exp_dir
|
|
46
48
|
self.soft_path = get_software_location()
|
|
47
49
|
self.exp_config = self.exp_dir +"config.ini"
|
|
48
|
-
self.wells = np.array(self.
|
|
50
|
+
self.wells = np.array(self.parent_window.parent_window.wells,dtype=str)
|
|
49
51
|
self.well_labels = _extract_labels_from_config(self.exp_config,len(self.wells))
|
|
50
|
-
self.FrameToMin = self.
|
|
52
|
+
self.FrameToMin = self.parent_window.parent_window.FrameToMin
|
|
51
53
|
self.float_validator = QDoubleValidator()
|
|
52
54
|
self.auto_close = False
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
self.well_option = self.parent.parent.well_list.currentIndex()
|
|
58
|
-
self.position_option = self.parent.parent.position_list.currentIndex()
|
|
56
|
+
self.well_option = self.parent_window.parent_window.well_list.currentIndex()
|
|
57
|
+
self.position_option = self.parent_window.parent_window.position_list.currentIndex()
|
|
59
58
|
self.interpret_pos_location()
|
|
60
59
|
#self.config_path = self.exp_dir + self.config_name
|
|
61
60
|
|
|
62
|
-
self.screen_height = self.
|
|
61
|
+
self.screen_height = self.parent_window.parent_window.parent_window.screen_height
|
|
63
62
|
center_window(self)
|
|
64
63
|
|
|
65
64
|
self.setMinimumWidth(350)
|
|
@@ -69,6 +68,7 @@ class ConfigSurvival(QWidget):
|
|
|
69
68
|
#self.load_previous_measurement_instructions()
|
|
70
69
|
if self.auto_close:
|
|
71
70
|
self.close()
|
|
71
|
+
self.setAttribute(Qt.WA_DeleteOnClose)
|
|
72
72
|
|
|
73
73
|
def interpret_pos_location(self):
|
|
74
74
|
|
|
@@ -109,9 +109,10 @@ class ConfigSurvival(QWidget):
|
|
|
109
109
|
main_layout.addWidget(panel_title, alignment=Qt.AlignCenter)
|
|
110
110
|
|
|
111
111
|
|
|
112
|
-
labels = [QLabel('population: '), QLabel('time of\
|
|
113
|
-
self.cb_options = [['targets','effectors'],['
|
|
112
|
+
labels = [QLabel('population: '), QLabel('time of\nreference: '), QLabel('time of\ninterest: '), QLabel('exclude\nclass: '), QLabel('cmap: ')] #QLabel('class: '),
|
|
113
|
+
self.cb_options = [['targets','effectors'], ['0','t_firstdetection'], ['t0'], ['--'], list(plt.colormaps())] #['class'],
|
|
114
114
|
self.cbs = [QComboBox() for i in range(len(labels))]
|
|
115
|
+
self.cbs[-1] = QColormapComboBox()
|
|
115
116
|
self.cbs[0].currentIndexChanged.connect(self.set_classes_and_times)
|
|
116
117
|
|
|
117
118
|
choice_layout = QVBoxLayout()
|
|
@@ -120,12 +121,20 @@ class ConfigSurvival(QWidget):
|
|
|
120
121
|
hbox = QHBoxLayout()
|
|
121
122
|
hbox.addWidget(labels[i], 33)
|
|
122
123
|
hbox.addWidget(self.cbs[i],66)
|
|
123
|
-
|
|
124
|
+
if i < len(labels)-1:
|
|
125
|
+
self.cbs[i].addItems(self.cb_options[i])
|
|
124
126
|
choice_layout.addLayout(hbox)
|
|
127
|
+
|
|
128
|
+
for cm in list(colormaps):
|
|
129
|
+
try:
|
|
130
|
+
self.cbs[-1].addColormap(cm)
|
|
131
|
+
except:
|
|
132
|
+
pass
|
|
133
|
+
|
|
125
134
|
main_layout.addLayout(choice_layout)
|
|
126
135
|
|
|
127
|
-
self.cbs[0].setCurrentIndex(1)
|
|
128
136
|
self.cbs[0].setCurrentIndex(0)
|
|
137
|
+
self.cbs[1].setCurrentText('t_firstdetection')
|
|
129
138
|
|
|
130
139
|
time_calib_layout = QHBoxLayout()
|
|
131
140
|
time_calib_layout.setContentsMargins(20,20,20,20)
|
|
@@ -137,7 +146,7 @@ class ConfigSurvival(QWidget):
|
|
|
137
146
|
main_layout.addLayout(time_calib_layout)
|
|
138
147
|
|
|
139
148
|
self.submit_btn = QPushButton('Submit')
|
|
140
|
-
self.submit_btn.setStyleSheet(self.
|
|
149
|
+
self.submit_btn.setStyleSheet(self.button_style_sheet)
|
|
141
150
|
self.submit_btn.clicked.connect(self.process_survival)
|
|
142
151
|
main_layout.addWidget(self.submit_btn)
|
|
143
152
|
|
|
@@ -150,7 +159,7 @@ class ConfigSurvival(QWidget):
|
|
|
150
159
|
def set_classes_and_times(self):
|
|
151
160
|
|
|
152
161
|
# Look for all classes and times
|
|
153
|
-
tables = glob(self.exp_dir+os.sep.join(['W*','*','output','tables',f'trajectories_
|
|
162
|
+
tables = glob(self.exp_dir+os.sep.join(['W*','*','output','tables',f'trajectories_*.csv']))
|
|
154
163
|
self.all_columns = []
|
|
155
164
|
for tab in tables:
|
|
156
165
|
cols = pd.read_csv(tab, nrows=1,encoding_errors='ignore').columns.tolist()
|
|
@@ -158,6 +167,8 @@ class ConfigSurvival(QWidget):
|
|
|
158
167
|
self.all_columns = np.unique(self.all_columns)
|
|
159
168
|
#class_idx = np.array([s.startswith('class_') for s in self.all_columns])
|
|
160
169
|
time_idx = np.array([s.startswith('t_') for s in self.all_columns])
|
|
170
|
+
class_idx = np.array([s.startswith('class') for s in self.all_columns])
|
|
171
|
+
|
|
161
172
|
# class_columns = list(self.all_columns[class_idx])
|
|
162
173
|
# for c in ['class_id', 'class_color']:
|
|
163
174
|
# if c in class_columns:
|
|
@@ -170,12 +181,22 @@ class ConfigSurvival(QWidget):
|
|
|
170
181
|
self.auto_close = True
|
|
171
182
|
return None
|
|
172
183
|
|
|
173
|
-
|
|
174
|
-
|
|
184
|
+
try:
|
|
185
|
+
class_columns = list(self.all_columns[class_idx])
|
|
186
|
+
self.cbs[3].clear()
|
|
187
|
+
self.cbs[3].addItems(np.unique(self.cb_options[3]+class_columns))
|
|
188
|
+
except:
|
|
189
|
+
print('no column starts with class')
|
|
190
|
+
self.auto_close = True
|
|
191
|
+
return None
|
|
175
192
|
|
|
176
193
|
self.cbs[2].clear()
|
|
177
194
|
self.cbs[2].addItems(np.unique(self.cb_options[2]+time_columns))
|
|
178
195
|
|
|
196
|
+
self.cbs[1].clear()
|
|
197
|
+
self.cbs[1].addItems(np.unique(self.cb_options[1]+time_columns))
|
|
198
|
+
self.cbs[1].setCurrentText('t_firstdetection')
|
|
199
|
+
|
|
179
200
|
# self.cbs[3].clear()
|
|
180
201
|
# self.cbs[3].addItems(np.unique(self.cb_options[3]+class_columns))
|
|
181
202
|
|
|
@@ -186,7 +207,7 @@ class ConfigSurvival(QWidget):
|
|
|
186
207
|
self.FrameToMin = float(self.time_calibration_le.text().replace(',','.'))
|
|
187
208
|
print(self.FrameToMin, 'set')
|
|
188
209
|
|
|
189
|
-
self.time_of_interest = self.cbs[
|
|
210
|
+
self.time_of_interest = self.cbs[2].currentText()
|
|
190
211
|
if self.time_of_interest=="t0":
|
|
191
212
|
self.class_of_interest = "class"
|
|
192
213
|
else:
|
|
@@ -194,7 +215,14 @@ class ConfigSurvival(QWidget):
|
|
|
194
215
|
|
|
195
216
|
# read instructions from combobox options
|
|
196
217
|
self.load_available_tables_local()
|
|
218
|
+
|
|
197
219
|
if self.df is not None:
|
|
220
|
+
|
|
221
|
+
excluded_class = self.cbs[3].currentText()
|
|
222
|
+
if excluded_class!='--':
|
|
223
|
+
print(f"Excluding {excluded_class}...")
|
|
224
|
+
self.df = self.df.loc[~(self.df[excluded_class].isin([0,2])),:]
|
|
225
|
+
|
|
198
226
|
self.compute_survival_functions()
|
|
199
227
|
# prepare survival
|
|
200
228
|
|
|
@@ -216,7 +244,7 @@ class ConfigSurvival(QWidget):
|
|
|
216
244
|
|
|
217
245
|
self.legend_btn = QPushButton('')
|
|
218
246
|
self.legend_btn.setIcon(icon(MDI6.text_box,color="black"))
|
|
219
|
-
self.legend_btn.setStyleSheet(self.
|
|
247
|
+
self.legend_btn.setStyleSheet(self.button_select_all)
|
|
220
248
|
self.legend_btn.setToolTip('Show or hide the legend')
|
|
221
249
|
self.legend_visible = True
|
|
222
250
|
self.legend_btn.clicked.connect(self.show_hide_legend)
|
|
@@ -225,7 +253,7 @@ class ConfigSurvival(QWidget):
|
|
|
225
253
|
|
|
226
254
|
self.log_btn = QPushButton('')
|
|
227
255
|
self.log_btn.setIcon(icon(MDI6.math_log,color="black"))
|
|
228
|
-
self.log_btn.setStyleSheet(self.
|
|
256
|
+
self.log_btn.setStyleSheet(self.button_select_all)
|
|
229
257
|
self.log_btn.clicked.connect(self.switch_to_log)
|
|
230
258
|
self.log_btn.setToolTip('Enable or disable log scale')
|
|
231
259
|
plot_buttons_hbox.addWidget(self.log_btn, 5, alignment=Qt.AlignRight)
|
|
@@ -369,12 +397,12 @@ class ConfigSurvival(QWidget):
|
|
|
369
397
|
|
|
370
398
|
"""
|
|
371
399
|
|
|
372
|
-
self.well_option = self.
|
|
400
|
+
self.well_option = self.parent_window.parent_window.well_list.currentIndex()
|
|
373
401
|
if self.well_option==len(self.wells):
|
|
374
402
|
wo = '*'
|
|
375
403
|
else:
|
|
376
404
|
wo = self.well_option
|
|
377
|
-
self.position_option = self.
|
|
405
|
+
self.position_option = self.parent_window.parent_window.position_list.currentIndex()
|
|
378
406
|
if self.position_option==0:
|
|
379
407
|
po = '*'
|
|
380
408
|
else:
|
|
@@ -403,14 +431,14 @@ class ConfigSurvival(QWidget):
|
|
|
403
431
|
for block,movie_group in self.df.groupby(['well','position']):
|
|
404
432
|
try:
|
|
405
433
|
classes = movie_group.groupby('TRACK_ID')[self.class_of_interest].min().values
|
|
406
|
-
times = movie_group.groupby('TRACK_ID')[self.cbs[
|
|
434
|
+
times = movie_group.groupby('TRACK_ID')[self.cbs[2].currentText()].min().values
|
|
407
435
|
except Exception as e:
|
|
408
436
|
print(e)
|
|
409
437
|
continue
|
|
410
438
|
max_times = movie_group.groupby('TRACK_ID')['FRAME'].max().values
|
|
411
439
|
first_detections = None
|
|
412
440
|
|
|
413
|
-
if self.cbs[
|
|
441
|
+
if self.cbs[1].currentText()=='first detection':
|
|
414
442
|
left_censored = True
|
|
415
443
|
|
|
416
444
|
first_detections = []
|
|
@@ -427,17 +455,17 @@ class ConfigSurvival(QWidget):
|
|
|
427
455
|
else:
|
|
428
456
|
continue
|
|
429
457
|
|
|
430
|
-
elif self.cbs[
|
|
458
|
+
elif self.cbs[1].currentText().startswith('t'):
|
|
431
459
|
left_censored = True
|
|
432
|
-
first_detections = movie_group.groupby('TRACK_ID')[self.cbs[
|
|
460
|
+
first_detections = movie_group.groupby('TRACK_ID')[self.cbs[1].currentText()].max().values
|
|
433
461
|
print(first_detections)
|
|
434
462
|
|
|
435
463
|
|
|
436
|
-
if self.cbs[
|
|
464
|
+
if self.cbs[1].currentText()=='first detection' or self.cbs[1].currentText().startswith('t'):
|
|
437
465
|
left_censored = True
|
|
438
466
|
else:
|
|
439
467
|
left_censored = False
|
|
440
|
-
events, survival_times =
|
|
468
|
+
events, survival_times = switch_to_events(classes, times, max_times, first_detections, left_censored=left_censored, FrameToMin=self.FrameToMin)
|
|
441
469
|
ks = KaplanMeierFitter()
|
|
442
470
|
if len(events)>0:
|
|
443
471
|
ks.fit(survival_times, event_observed=events)
|
|
@@ -455,14 +483,14 @@ class ConfigSurvival(QWidget):
|
|
|
455
483
|
for block,movie_group in well_group.groupby('position'):
|
|
456
484
|
try:
|
|
457
485
|
classes = movie_group.groupby('TRACK_ID')[self.class_of_interest].min().values
|
|
458
|
-
times = movie_group.groupby('TRACK_ID')[self.cbs[
|
|
486
|
+
times = movie_group.groupby('TRACK_ID')[self.cbs[2].currentText()].min().values
|
|
459
487
|
except Exception as e:
|
|
460
488
|
print(e)
|
|
461
489
|
continue
|
|
462
490
|
max_times = movie_group.groupby('TRACK_ID')['FRAME'].max().values
|
|
463
491
|
first_detections = None
|
|
464
492
|
|
|
465
|
-
if self.cbs[
|
|
493
|
+
if self.cbs[1].currentText()=='first detection':
|
|
466
494
|
|
|
467
495
|
left_censored = True
|
|
468
496
|
first_detections = []
|
|
@@ -477,9 +505,9 @@ class ConfigSurvival(QWidget):
|
|
|
477
505
|
# think about assymmetry with class and times
|
|
478
506
|
continue
|
|
479
507
|
|
|
480
|
-
elif self.cbs[
|
|
508
|
+
elif self.cbs[1].currentText().startswith('t'):
|
|
481
509
|
left_censored = True
|
|
482
|
-
first_detections = movie_group.groupby('TRACK_ID')[self.cbs[
|
|
510
|
+
first_detections = movie_group.groupby('TRACK_ID')[self.cbs[1].currentText()].max().values
|
|
483
511
|
|
|
484
512
|
else:
|
|
485
513
|
pass
|
|
@@ -494,7 +522,7 @@ class ConfigSurvival(QWidget):
|
|
|
494
522
|
well_first_detections = None
|
|
495
523
|
|
|
496
524
|
print(f"{well_classes=}; {well_times=}")
|
|
497
|
-
events, survival_times =
|
|
525
|
+
events, survival_times = switch_to_events(well_classes, well_times, well_max_times, well_first_detections,left_censored=left_censored, FrameToMin=self.FrameToMin)
|
|
498
526
|
print(f"{events=}; {survival_times=}")
|
|
499
527
|
ks = KaplanMeierFitter()
|
|
500
528
|
if len(survival_times)>0:
|