celldetective 1.3.9.post5__py3-none-any.whl → 1.4.0__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/extra_properties.py +132 -0
- celldetective/gui/InitWindow.py +33 -45
- celldetective/gui/__init__.py +1 -0
- celldetective/gui/about.py +19 -15
- celldetective/gui/analyze_block.py +34 -19
- celldetective/gui/base_components.py +23 -0
- celldetective/gui/btrack_options.py +26 -34
- celldetective/gui/classifier_widget.py +68 -81
- celldetective/gui/configure_new_exp.py +113 -17
- celldetective/gui/control_panel.py +68 -141
- celldetective/gui/generic_signal_plot.py +9 -12
- celldetective/gui/gui_utils.py +49 -21
- celldetective/gui/json_readers.py +5 -4
- celldetective/gui/layouts.py +246 -22
- celldetective/gui/measurement_options.py +32 -17
- celldetective/gui/neighborhood_options.py +10 -13
- celldetective/gui/plot_measurements.py +21 -17
- celldetective/gui/plot_signals_ui.py +125 -72
- celldetective/gui/process_block.py +180 -123
- celldetective/gui/processes/compute_neighborhood.py +594 -0
- celldetective/gui/processes/measure_cells.py +5 -0
- celldetective/gui/processes/segment_cells.py +27 -6
- celldetective/gui/processes/track_cells.py +6 -0
- celldetective/gui/retrain_segmentation_model_options.py +12 -20
- celldetective/gui/retrain_signal_model_options.py +57 -56
- celldetective/gui/seg_model_loader.py +21 -62
- celldetective/gui/signal_annotator.py +129 -70
- celldetective/gui/signal_annotator2.py +431 -635
- celldetective/gui/signal_annotator_options.py +8 -11
- celldetective/gui/survival_ui.py +49 -95
- celldetective/gui/tableUI.py +28 -25
- celldetective/gui/thresholds_gui.py +617 -1221
- celldetective/gui/viewers.py +106 -39
- celldetective/gui/workers.py +9 -3
- celldetective/io.py +57 -20
- celldetective/measure.py +63 -27
- celldetective/neighborhood.py +342 -268
- celldetective/preprocessing.py +25 -17
- celldetective/relative_measurements.py +50 -29
- celldetective/scripts/analyze_signals.py +4 -1
- celldetective/scripts/measure_relative.py +4 -1
- celldetective/scripts/segment_cells.py +0 -6
- celldetective/scripts/track_cells.py +3 -1
- celldetective/scripts/train_segmentation_model.py +7 -4
- celldetective/signals.py +29 -14
- celldetective/tracking.py +7 -2
- celldetective/utils.py +36 -8
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.0.dist-info}/METADATA +24 -16
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.0.dist-info}/RECORD +57 -55
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.0.dist-info}/WHEEL +1 -1
- tests/test_qt.py +21 -21
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.0.dist-info}/entry_points.txt +0 -0
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.0.dist-info/licenses}/LICENSE +0 -0
- {celldetective-1.3.9.post5.dist-info → celldetective-1.4.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
from PyQt5.QtWidgets import QApplication, QComboBox, QFrame, QCheckBox, QVBoxLayout,
|
|
1
|
+
from PyQt5.QtWidgets import QApplication, QComboBox, QFrame, QCheckBox, QVBoxLayout, QLabel, QHBoxLayout, QPushButton
|
|
2
2
|
from PyQt5.QtCore import Qt, QSize
|
|
3
|
-
from PyQt5.QtGui import QIcon
|
|
4
3
|
from celldetective.gui.gui_utils import center_window, ListWidget, DistanceChoice
|
|
5
4
|
from superqt.fonticon import icon
|
|
6
5
|
from fonticon_mdi6 import MDI6
|
|
@@ -10,9 +9,10 @@ import os
|
|
|
10
9
|
from glob import glob
|
|
11
10
|
import pandas as pd
|
|
12
11
|
from celldetective.gui.viewers import CellSizeViewer, CellEdgeVisualizer
|
|
13
|
-
from celldetective.gui import
|
|
12
|
+
from celldetective.gui import CelldetectiveWidget
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
|
|
15
|
+
class ConfigNeighborhoods(CelldetectiveWidget):
|
|
16
16
|
|
|
17
17
|
"""
|
|
18
18
|
Widget to configure neighborhood measurements.
|
|
@@ -24,7 +24,6 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
24
24
|
super().__init__(*args, **kwargs)
|
|
25
25
|
self.parent_window = parent_window
|
|
26
26
|
self.attr_parent = self.parent_window.parent_window
|
|
27
|
-
self.setWindowIcon(QIcon(os.sep.join(['celldetective','icons','logo.png'])))
|
|
28
27
|
|
|
29
28
|
self.neighborhood_type = neighborhood_type
|
|
30
29
|
self.neighborhood_parameter_name = neighborhood_parameter_name
|
|
@@ -43,7 +42,6 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
43
42
|
self.generate_main_layout()
|
|
44
43
|
self.load_previous_neighborhood_instructions()
|
|
45
44
|
center_window(self)
|
|
46
|
-
self.setAttribute(Qt.WA_DeleteOnClose)
|
|
47
45
|
|
|
48
46
|
def generate_main_layout(self):
|
|
49
47
|
|
|
@@ -140,7 +138,7 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
140
138
|
|
|
141
139
|
layout.addLayout(list_header_layout)
|
|
142
140
|
|
|
143
|
-
self.measurements_list = ListWidget(DistanceChoice, initial_features=[
|
|
141
|
+
self.measurements_list = ListWidget(DistanceChoice, initial_features=[], dtype=int)
|
|
144
142
|
self.measurements_list.setToolTip('Neighborhoods to compute.')
|
|
145
143
|
layout.addWidget(self.measurements_list)
|
|
146
144
|
|
|
@@ -211,7 +209,7 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
211
209
|
population_layout = QHBoxLayout()
|
|
212
210
|
population_layout.addWidget(QLabel('population: '),30)
|
|
213
211
|
self.reference_population_cb = QComboBox()
|
|
214
|
-
self.reference_population_cb.addItems(
|
|
212
|
+
self.reference_population_cb.addItems(self.parent_window.parent_window.populations)
|
|
215
213
|
self.reference_population_cb.setToolTip('Select a reference population.')
|
|
216
214
|
population_layout.addWidget(self.reference_population_cb,70)
|
|
217
215
|
layout.addLayout(population_layout)
|
|
@@ -271,7 +269,7 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
271
269
|
population_layout = QHBoxLayout()
|
|
272
270
|
population_layout.addWidget(QLabel('population: '),30)
|
|
273
271
|
self.neighbor_population_cb = QComboBox()
|
|
274
|
-
self.neighbor_population_cb.addItems(
|
|
272
|
+
self.neighbor_population_cb.addItems(self.parent_window.parent_window.populations)
|
|
275
273
|
self.neighbor_population_cb.setToolTip('Select a neighbor population.')
|
|
276
274
|
population_layout.addWidget(self.neighbor_population_cb,70)
|
|
277
275
|
layout.addLayout(population_layout)
|
|
@@ -315,15 +313,14 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
315
313
|
population = self.neighbor_population_cb.currentText()
|
|
316
314
|
class_cols, status_cols, group_cols, time_cols = self.locate_population_specific_columns(population)
|
|
317
315
|
self.neighbor_population_status_cb.clear()
|
|
318
|
-
self.neighbor_population_status_cb.addItems(['--','class', 'status']+class_cols+status_cols+group_cols)
|
|
316
|
+
self.neighbor_population_status_cb.addItems(list(np.unique(['--','class', 'status']+class_cols+status_cols+group_cols)))
|
|
319
317
|
|
|
320
318
|
def fill_cbs_of_reference_population(self):
|
|
321
319
|
|
|
322
320
|
population = self.reference_population_cb.currentText()
|
|
323
321
|
class_cols, status_cols, group_cols, time_cols = self.locate_population_specific_columns(population)
|
|
324
|
-
self.
|
|
325
|
-
self.
|
|
326
|
-
self.event_time_cb.addItems(['--', 't0']+time_cols)
|
|
322
|
+
self.event_time_cb.clear()
|
|
323
|
+
self.event_time_cb.addItems(list(np.unique(['--', 't0']+time_cols)))
|
|
327
324
|
|
|
328
325
|
def switch_not_reference(self):
|
|
329
326
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
from PyQt5.QtWidgets import QMessageBox, QScrollArea, QButtonGroup, QComboBox, \
|
|
2
|
-
QCheckBox, QVBoxLayout,
|
|
2
|
+
QCheckBox, QVBoxLayout, QLabel, QHBoxLayout, QPushButton, \
|
|
3
3
|
QRadioButton, QSizePolicy
|
|
4
4
|
from PyQt5.QtCore import Qt, QRect
|
|
5
|
-
from PyQt5.QtGui import
|
|
5
|
+
from PyQt5.QtGui import QDoubleValidator
|
|
6
6
|
|
|
7
|
-
from celldetective.gui import
|
|
7
|
+
from celldetective.gui import CelldetectiveWidget
|
|
8
8
|
from celldetective.gui.gui_utils import center_window, FigureCanvas
|
|
9
9
|
|
|
10
10
|
from superqt.fonticon import icon
|
|
@@ -12,7 +12,6 @@ from fonticon_mdi6 import MDI6
|
|
|
12
12
|
from celldetective.utils import get_software_location, _extract_labels_from_config
|
|
13
13
|
from celldetective.io import load_experiment_tables, get_experiment_antibodies, get_experiment_cell_types, get_experiment_concentrations, \
|
|
14
14
|
get_positions_in_well, get_experiment_wells
|
|
15
|
-
from celldetective.signals import mean_signal
|
|
16
15
|
import numpy as np
|
|
17
16
|
import json
|
|
18
17
|
import os
|
|
@@ -26,7 +25,7 @@ import math
|
|
|
26
25
|
import seaborn as sns
|
|
27
26
|
|
|
28
27
|
|
|
29
|
-
class ConfigMeasurementsPlot(
|
|
28
|
+
class ConfigMeasurementsPlot(CelldetectiveWidget):
|
|
30
29
|
"""
|
|
31
30
|
UI to set survival instructions.
|
|
32
31
|
|
|
@@ -37,7 +36,6 @@ class ConfigMeasurementsPlot(QWidget,Styles):
|
|
|
37
36
|
super().__init__()
|
|
38
37
|
self.parent_window = parent_window
|
|
39
38
|
self.setWindowTitle("Configure signal plot")
|
|
40
|
-
self.setWindowIcon(QIcon(os.sep.join(['celldetective', 'icons', 'mexican-hat.png'])))
|
|
41
39
|
self.exp_dir = self.parent_window.exp_dir
|
|
42
40
|
self.soft_path = get_software_location()
|
|
43
41
|
self.exp_config = self.exp_dir + "config.ini"
|
|
@@ -109,7 +107,7 @@ class ConfigMeasurementsPlot(QWidget,Styles):
|
|
|
109
107
|
main_layout.addWidget(panel_title, alignment=Qt.AlignCenter)
|
|
110
108
|
|
|
111
109
|
labels = [QLabel('population: '), QLabel('class: '), QLabel('group: ')] # , QLabel('time of\ninterest: ')]
|
|
112
|
-
self.cb_options = [
|
|
110
|
+
self.cb_options = [self.parent_window.parent_window.populations, ['class'], ['group']] # , ['t0','first detection']]
|
|
113
111
|
self.cbs = [QComboBox() for i in range(len(labels))]
|
|
114
112
|
self.cbs[0].currentIndexChanged.connect(self.set_classes_and_times)
|
|
115
113
|
|
|
@@ -145,7 +143,7 @@ class ConfigMeasurementsPlot(QWidget,Styles):
|
|
|
145
143
|
# self.abs_time_checkbox = QCheckBox('absolute time')
|
|
146
144
|
# self.frame_slider = QLabeledSlider()
|
|
147
145
|
# self.frame_slider.setSingleStep(1)
|
|
148
|
-
# self.frame_slider.setOrientation(
|
|
146
|
+
# self.frame_slider.setOrientation(Qt.Horizontal)
|
|
149
147
|
# self.frame_slider.setRange(0,self.parent.parent.len_movie)
|
|
150
148
|
# self.frame_slider.setValue(0)
|
|
151
149
|
# self.frame_slider.setEnabled(False)
|
|
@@ -202,14 +200,20 @@ class ConfigMeasurementsPlot(QWidget,Styles):
|
|
|
202
200
|
class_idx = np.array([s.startswith('class_') for s in self.all_columns])
|
|
203
201
|
group_idx = np.array([s.startswith('group_') for s in self.all_columns])
|
|
204
202
|
|
|
203
|
+
print(f'{class_idx=} {group_idx=} {self.all_columns=}')
|
|
205
204
|
# time_idx = np.array([s.startswith('t_') for s in self.all_columns])
|
|
206
|
-
|
|
207
205
|
try:
|
|
208
|
-
|
|
209
|
-
|
|
206
|
+
if len(class_idx)>0:
|
|
207
|
+
class_columns = list(self.all_columns[class_idx])
|
|
208
|
+
else:
|
|
209
|
+
class_columns = []
|
|
210
|
+
if len(group_idx)>0:
|
|
211
|
+
group_columns = list(self.all_columns[group_idx])
|
|
212
|
+
else:
|
|
213
|
+
group_columns = []
|
|
210
214
|
# time_columns = list(self.all_columns[time_idx])
|
|
211
|
-
except:
|
|
212
|
-
print('columns not found')
|
|
215
|
+
except Exception as e:
|
|
216
|
+
print(f'L210 columns not found {e}')
|
|
213
217
|
self.auto_close = True
|
|
214
218
|
return None
|
|
215
219
|
|
|
@@ -227,7 +231,7 @@ class ConfigMeasurementsPlot(QWidget,Styles):
|
|
|
227
231
|
is_number = np.vectorize(lambda x: np.issubdtype(x, np.number))
|
|
228
232
|
feats = cols[is_number(self.df.dtypes)]
|
|
229
233
|
|
|
230
|
-
self.feature_choice_widget =
|
|
234
|
+
self.feature_choice_widget = CelldetectiveWidget()
|
|
231
235
|
self.feature_choice_widget.setWindowTitle("Select numeric feature")
|
|
232
236
|
layout = QVBoxLayout()
|
|
233
237
|
self.feature_choice_widget.setLayout(layout)
|
|
@@ -250,7 +254,7 @@ class ConfigMeasurementsPlot(QWidget,Styles):
|
|
|
250
254
|
is_number = np.vectorize(lambda x: np.issubdtype(x, np.number))
|
|
251
255
|
feats = cols[is_number(self.df.dtypes)]
|
|
252
256
|
|
|
253
|
-
self.feature_choice_widget =
|
|
257
|
+
self.feature_choice_widget = CelldetectiveWidget()
|
|
254
258
|
self.feature_choice_widget.setWindowTitle("Select numeric feature")
|
|
255
259
|
layout = QVBoxLayout()
|
|
256
260
|
self.feature_choice_widget.setLayout(layout)
|
|
@@ -299,7 +303,7 @@ class ConfigMeasurementsPlot(QWidget,Styles):
|
|
|
299
303
|
# prepare survival
|
|
300
304
|
|
|
301
305
|
# plot survival
|
|
302
|
-
self.survivalWidget =
|
|
306
|
+
self.survivalWidget = CelldetectiveWidget()
|
|
303
307
|
self.scroll = QScrollArea()
|
|
304
308
|
self.survivalWidget.setMinimumHeight(int(0.8 * self.screen_height))
|
|
305
309
|
self.survivalWidget.setWindowTitle('signals')
|
|
@@ -500,7 +504,7 @@ class ConfigMeasurementsPlot(QWidget,Styles):
|
|
|
500
504
|
if name + ':' in lbl:
|
|
501
505
|
self.usable_well_labels.append(lbl)
|
|
502
506
|
|
|
503
|
-
self.line_choice_widget =
|
|
507
|
+
self.line_choice_widget = CelldetectiveWidget()
|
|
504
508
|
self.line_check_vbox = QVBoxLayout()
|
|
505
509
|
self.line_choice_widget.setLayout(self.line_check_vbox)
|
|
506
510
|
if len(self.well_indices) > 1:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
from PyQt5.QtWidgets import
|
|
2
|
-
QCheckBox, QLineEdit, QVBoxLayout,
|
|
1
|
+
from PyQt5.QtWidgets import QComboBox, \
|
|
2
|
+
QCheckBox, QLineEdit, QVBoxLayout, QLabel, QHBoxLayout, QPushButton
|
|
3
3
|
from PyQt5.QtCore import Qt
|
|
4
|
-
from PyQt5.QtGui import
|
|
4
|
+
from PyQt5.QtGui import QDoubleValidator
|
|
5
5
|
|
|
6
|
-
from celldetective.gui.gui_utils import center_window
|
|
6
|
+
from celldetective.gui.gui_utils import center_window, generic_message
|
|
7
7
|
from celldetective.gui.generic_signal_plot import GenericSignalPlotWidget
|
|
8
8
|
from superqt import QLabeledSlider, QColormapComboBox, QSearchableComboBox
|
|
9
9
|
from celldetective.utils import get_software_location, _extract_labels_from_config, extract_cols_from_table_list
|
|
@@ -16,12 +16,14 @@ plt.rcParams['svg.fonttype'] = 'none'
|
|
|
16
16
|
from glob import glob
|
|
17
17
|
from natsort import natsorted
|
|
18
18
|
import math
|
|
19
|
-
from celldetective.gui import
|
|
19
|
+
from celldetective.gui import CelldetectiveWidget
|
|
20
20
|
from matplotlib import colormaps
|
|
21
21
|
import matplotlib.cm
|
|
22
|
+
from celldetective.relative_measurements import expand_pair_table
|
|
23
|
+
from celldetective.neighborhood import extract_neighborhood_in_pair_table
|
|
22
24
|
|
|
23
25
|
|
|
24
|
-
class ConfigSignalPlot(
|
|
26
|
+
class ConfigSignalPlot(CelldetectiveWidget):
|
|
25
27
|
|
|
26
28
|
"""
|
|
27
29
|
UI to set survival instructions.
|
|
@@ -33,7 +35,6 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
33
35
|
super().__init__()
|
|
34
36
|
self.parent_window = parent_window
|
|
35
37
|
self.setWindowTitle("Configure signal plot")
|
|
36
|
-
self.setWindowIcon(QIcon(os.sep.join(['celldetective','icons','mexican-hat.png'])))
|
|
37
38
|
self.exp_dir = self.parent_window.exp_dir
|
|
38
39
|
self.soft_path = get_software_location()
|
|
39
40
|
self.exp_config = self.exp_dir +"config.ini"
|
|
@@ -57,7 +58,6 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
57
58
|
|
|
58
59
|
if self.auto_close:
|
|
59
60
|
self.close()
|
|
60
|
-
self.setAttribute(Qt.WA_DeleteOnClose)
|
|
61
61
|
|
|
62
62
|
def interpret_pos_location(self):
|
|
63
63
|
|
|
@@ -92,10 +92,30 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
92
92
|
main_layout.addWidget(panel_title, alignment=Qt.AlignCenter)
|
|
93
93
|
|
|
94
94
|
pops = []
|
|
95
|
-
|
|
95
|
+
self.cols_per_pop = {}
|
|
96
|
+
for population in self.parent_window.parent_window.populations:
|
|
96
97
|
tables = glob(self.exp_dir+os.sep.join(['W*','*','output','tables',f'trajectories_{population}.csv']))
|
|
97
98
|
if len(tables)>0:
|
|
98
99
|
pops.append(population)
|
|
100
|
+
cols = extract_cols_from_table_list(tables)
|
|
101
|
+
|
|
102
|
+
# check for neighbor pairs
|
|
103
|
+
neigh_cols = [c for c in cols if c.startswith('inclusive_count_neighborhood')]
|
|
104
|
+
neigh_pairs = [c.split('_(')[-1].split(')_')[0].split('-') for c in neigh_cols]
|
|
105
|
+
neigh_pairs = ['-'.join(c) for c in neigh_pairs]
|
|
106
|
+
for k in range(len(neigh_pairs)):
|
|
107
|
+
if "_self_" in neigh_pairs[k]:
|
|
108
|
+
neigh_pairs[k] = '-'.join([population, population])
|
|
109
|
+
pops.extend(neigh_pairs)
|
|
110
|
+
|
|
111
|
+
self.cols_per_pop.update({population: cols})
|
|
112
|
+
|
|
113
|
+
# pops = []
|
|
114
|
+
# for population in self.parent_window.parent_window.populations+['pairs']:
|
|
115
|
+
# tables = glob(self.exp_dir+os.sep.join(['W*','*','output','tables',f'trajectories_{population}.csv']))
|
|
116
|
+
# if len(tables)>0:
|
|
117
|
+
# pops.append(population)
|
|
118
|
+
|
|
99
119
|
|
|
100
120
|
labels = [QLabel('population: '), QLabel('class: '), QLabel('time of\ninterest: '), QLabel('cmap: ')]
|
|
101
121
|
self.cb_options = [pops,[], [], []]
|
|
@@ -128,7 +148,7 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
128
148
|
self.abs_time_checkbox = QCheckBox('absolute time')
|
|
129
149
|
self.frame_slider = QLabeledSlider()
|
|
130
150
|
self.frame_slider.setSingleStep(1)
|
|
131
|
-
self.frame_slider.setOrientation(
|
|
151
|
+
self.frame_slider.setOrientation(Qt.Horizontal)
|
|
132
152
|
self.frame_slider.setRange(0,self.parent_window.parent_window.len_movie)
|
|
133
153
|
self.frame_slider.setValue(0)
|
|
134
154
|
self.frame_slider.setEnabled(False)
|
|
@@ -168,7 +188,7 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
168
188
|
n_cells_layout.setContentsMargins(20,3,20,3)
|
|
169
189
|
self.n_cells_slider = QLabeledSlider()
|
|
170
190
|
self.n_cells_slider.setSingleStep(1)
|
|
171
|
-
self.n_cells_slider.setOrientation(
|
|
191
|
+
self.n_cells_slider.setOrientation(Qt.Horizontal)
|
|
172
192
|
self.n_cells_slider.setRange(1,100)
|
|
173
193
|
self.n_cells_slider.setValue(2)
|
|
174
194
|
n_cells_layout.addWidget(QLabel('min # cells\nfor pool:'), 33)
|
|
@@ -188,35 +208,83 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
188
208
|
# self.show()
|
|
189
209
|
|
|
190
210
|
def set_classes_and_times(self):
|
|
191
|
-
|
|
192
|
-
# Look for all classes and times
|
|
193
|
-
population = self.cbs[0].currentText()
|
|
194
|
-
tables = natsorted(glob(self.exp_dir+os.sep.join(['W*','*','output','tables',f'trajectories_{population}.csv'])))
|
|
195
211
|
|
|
196
|
-
|
|
212
|
+
# Look for all classes and times
|
|
213
|
+
self.neighborhood_keys = None
|
|
214
|
+
self.population = self.cbs[0].currentText()
|
|
215
|
+
pop_split = self.population.split('-')
|
|
216
|
+
|
|
217
|
+
if len(pop_split)==2:
|
|
218
|
+
|
|
219
|
+
self.population = 'pairs'
|
|
220
|
+
tables_pairs = glob(self.exp_dir+os.sep.join(['W*','*','output','tables',f'trajectories_pairs.csv']))
|
|
221
|
+
if not tables_pairs:
|
|
222
|
+
print('No pair table found... please compute the pair measurements...')
|
|
223
|
+
return None
|
|
224
|
+
self.cols_pairs = extract_cols_from_table_list(tables_pairs)
|
|
225
|
+
|
|
226
|
+
self.population_reference = pop_split[0]
|
|
227
|
+
self.population_neigh = pop_split[1]
|
|
228
|
+
|
|
229
|
+
cols_ref = self.cols_per_pop[self.population_reference]
|
|
230
|
+
cols_neigh = self.cols_per_pop[self.population_neigh]
|
|
231
|
+
|
|
232
|
+
time_cols_ref = np.array([s.startswith('t_') or s=='t0' for s in cols_ref])
|
|
233
|
+
if len(time_cols_ref)>0:
|
|
234
|
+
time_cols_ref = list(cols_ref[time_cols_ref])
|
|
235
|
+
time_cols_ref = ['reference_'+t for t in time_cols_ref]
|
|
236
|
+
|
|
237
|
+
time_cols_neigh = np.array([s.startswith('t_') or s=='t0' for s in cols_neigh])
|
|
238
|
+
if len(time_cols_neigh)>0:
|
|
239
|
+
time_cols_neigh = list(cols_neigh[time_cols_neigh])
|
|
240
|
+
time_cols_neigh = ['neighbor_'+t for t in time_cols_neigh]
|
|
241
|
+
|
|
242
|
+
if self.population_reference!=self.population_neigh:
|
|
243
|
+
self.neighborhood_keys = [c[16:] for c in cols_ref if c.startswith('inclusive_count_neighborhood') and str(self.population_neigh) in c]
|
|
244
|
+
else:
|
|
245
|
+
self.neighborhood_keys = [c[16:] for c in cols_ref if c.startswith('inclusive_count_neighborhood') and str(self.population_neigh) not in c]
|
|
246
|
+
|
|
247
|
+
time_idx = np.array([s.startswith('t_') or s.startswith('t0') for s in self.cols_pairs])
|
|
248
|
+
time_cols_pairs = list(self.cols_pairs[time_idx])
|
|
249
|
+
time_columns = time_cols_ref + time_cols_neigh + time_cols_pairs
|
|
250
|
+
|
|
251
|
+
class_cols_ref = [c.replace('reference_t_','reference_class_') for c in time_cols_ref]
|
|
252
|
+
class_cols_neigh = [c.replace('neighbor_t_','neighbor_class_') for c in time_cols_neigh]
|
|
253
|
+
class_cols_pairs = [c.replace('t_','class_') for c in time_cols_neigh if c.startswith('t_')]
|
|
254
|
+
class_columns = class_cols_ref + class_cols_neigh + class_cols_pairs
|
|
255
|
+
else:
|
|
256
|
+
tables = natsorted(glob(self.exp_dir+os.sep.join(['W*','*','output','tables',f'trajectories_{self.population}.csv'])))
|
|
257
|
+
self.all_columns = extract_cols_from_table_list(tables)
|
|
258
|
+
|
|
259
|
+
class_idx = np.array([s.startswith('class_') for s in self.all_columns])
|
|
260
|
+
time_idx = np.array([s.startswith('t_') or s.startswith('t0_') for s in self.all_columns])
|
|
261
|
+
print(f'{class_idx=} {time_idx=} {self.all_columns=}')
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
if len(class_idx)>0:
|
|
265
|
+
class_columns = list(self.all_columns[class_idx])
|
|
266
|
+
else:
|
|
267
|
+
class_columns = []
|
|
268
|
+
if len(time_idx)>0:
|
|
269
|
+
time_columns = list(self.all_columns[time_idx])
|
|
270
|
+
else:
|
|
271
|
+
time_columns = []
|
|
272
|
+
except Exception as e:
|
|
273
|
+
print(f'L266 columns not found {e}')
|
|
274
|
+
self.auto_close = True
|
|
275
|
+
return None
|
|
276
|
+
|
|
277
|
+
if 'class' in self.all_columns:
|
|
278
|
+
class_columns.append("class")
|
|
279
|
+
if 't0' in self.all_columns:
|
|
280
|
+
time_columns.append('t0')
|
|
197
281
|
|
|
198
|
-
class_idx = np.array([s.startswith('class_') for s in self.all_columns])
|
|
199
|
-
time_idx = np.array([s.startswith('t_') for s in self.all_columns])
|
|
200
|
-
|
|
201
|
-
try:
|
|
202
|
-
class_columns = list(self.all_columns[class_idx])
|
|
203
|
-
time_columns = list(self.all_columns[time_idx])
|
|
204
|
-
except:
|
|
205
|
-
print('columns not found')
|
|
206
|
-
self.auto_close = True
|
|
207
|
-
return None
|
|
208
|
-
|
|
209
|
-
if 'class' in self.all_columns:
|
|
210
|
-
class_columns.append("class")
|
|
211
|
-
if 't0' in self.all_columns:
|
|
212
|
-
time_columns.append('t0')
|
|
213
|
-
|
|
214
282
|
self.class_columns = np.unique(class_columns)
|
|
215
283
|
self.time_columns = np.unique(time_columns)
|
|
216
|
-
thresh =
|
|
284
|
+
thresh = 30
|
|
217
285
|
self.class_truncated = [w[:thresh - 3]+'...' if len(w)>thresh else w for w in self.class_columns]
|
|
218
286
|
self.time_truncated = [w[:thresh - 3]+'...' if len(w)>thresh else w for w in self.time_columns]
|
|
219
|
-
|
|
287
|
+
|
|
220
288
|
self.cbs[2].clear()
|
|
221
289
|
self.cbs[2].addItems(self.time_truncated)
|
|
222
290
|
for i in range(len(self.time_columns)):
|
|
@@ -233,7 +301,7 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
233
301
|
is_number = np.vectorize(lambda x: np.issubdtype(x, np.number))
|
|
234
302
|
feats = cols[is_number(self.df.dtypes)]
|
|
235
303
|
|
|
236
|
-
self.feature_choice_widget =
|
|
304
|
+
self.feature_choice_widget = CelldetectiveWidget()
|
|
237
305
|
self.feature_choice_widget.setWindowTitle("Select numeric feature")
|
|
238
306
|
layout = QVBoxLayout()
|
|
239
307
|
self.feature_choice_widget.setLayout(layout)
|
|
@@ -256,7 +324,7 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
256
324
|
is_number = np.vectorize(lambda x: np.issubdtype(x, np.number))
|
|
257
325
|
feats = cols[is_number(self.df.dtypes)]
|
|
258
326
|
|
|
259
|
-
self.feature_choice_widget =
|
|
327
|
+
self.feature_choice_widget = CelldetectiveWidget()
|
|
260
328
|
self.feature_choice_widget.setWindowTitle("Select numeric feature")
|
|
261
329
|
layout = QVBoxLayout()
|
|
262
330
|
self.feature_choice_widget.setLayout(layout)
|
|
@@ -316,14 +384,8 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
316
384
|
if self.df is not None:
|
|
317
385
|
|
|
318
386
|
if class_col not in list(self.df.columns):
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
msgBox.setText("The class of interest could not be found in the data. Abort.")
|
|
322
|
-
msgBox.setWindowTitle("Warning")
|
|
323
|
-
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
324
|
-
returnValue = msgBox.exec()
|
|
325
|
-
if returnValue == QMessageBox.Ok:
|
|
326
|
-
return None
|
|
387
|
+
generic_message("The class of interest could not be found in the data. Abort.")
|
|
388
|
+
return None
|
|
327
389
|
else:
|
|
328
390
|
self.ask_for_features()
|
|
329
391
|
else:
|
|
@@ -341,23 +403,17 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
341
403
|
self.well_option = self.parent_window.parent_window.well_list.getSelectedIndices()
|
|
342
404
|
self.position_option = self.parent_window.parent_window.position_list.getSelectedIndices()
|
|
343
405
|
|
|
344
|
-
self.df, self.df_pos_info = load_experiment_tables(self.exp_dir, well_option=self.well_option, position_option=self.position_option, population=self.
|
|
406
|
+
self.df, self.df_pos_info = load_experiment_tables(self.exp_dir, well_option=self.well_option, position_option=self.position_option, population=self.population, return_pos_info=True)
|
|
407
|
+
|
|
408
|
+
if self.population=='pairs':
|
|
409
|
+
self.df = expand_pair_table(self.df)
|
|
410
|
+
self.df = extract_neighborhood_in_pair_table(self.df, reference_population=self.population_reference, neighbor_population=self.population_neigh, neighborhood_key=self.neighborhood_keys[0], contact_only=True)
|
|
345
411
|
|
|
346
412
|
if self.df is None:
|
|
347
|
-
|
|
348
413
|
print('No table could be found...')
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
msgBox.setWindowTitle("Warning")
|
|
353
|
-
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
354
|
-
returnValue = msgBox.exec()
|
|
355
|
-
if returnValue == QMessageBox.Ok:
|
|
356
|
-
self.close()
|
|
357
|
-
return None
|
|
358
|
-
else:
|
|
359
|
-
self.close()
|
|
360
|
-
return None
|
|
414
|
+
generic_message("No table could be found to compute survival...")
|
|
415
|
+
self.close()
|
|
416
|
+
return None
|
|
361
417
|
else:
|
|
362
418
|
self.df_well_info = self.df_pos_info.loc[:,['well_path', 'well_index', 'well_name', 'well_number', 'well_alias']].drop_duplicates()
|
|
363
419
|
|
|
@@ -366,14 +422,7 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
366
422
|
# Check to move at the beginning
|
|
367
423
|
self.open_widget = True
|
|
368
424
|
if len(self.time_columns)==0:
|
|
369
|
-
|
|
370
|
-
msgBox.setIcon(QMessageBox.Warning)
|
|
371
|
-
msgBox.setText("No synchronizing time is available...")
|
|
372
|
-
msgBox.setWindowTitle("Warning")
|
|
373
|
-
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
374
|
-
returnValue = msgBox.exec()
|
|
375
|
-
if returnValue == QMessageBox.Ok:
|
|
376
|
-
pass
|
|
425
|
+
generic_message("No synchronizing time is available...")
|
|
377
426
|
self.open_widget = False
|
|
378
427
|
return None
|
|
379
428
|
|
|
@@ -383,6 +432,10 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
383
432
|
print('Warning... The dataset is empty. Please check your filters. Abort...')
|
|
384
433
|
return None
|
|
385
434
|
|
|
435
|
+
pairs=False
|
|
436
|
+
if self.population=='pairs':
|
|
437
|
+
pairs=True
|
|
438
|
+
|
|
386
439
|
max_time = int(self.df.FRAME.max()) + 1
|
|
387
440
|
class_col = self.class_columns[self.cbs[1].currentIndex()]
|
|
388
441
|
time_col = self.time_columns[self.cbs[2].currentIndex()]
|
|
@@ -391,9 +444,9 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
391
444
|
|
|
392
445
|
for block,movie_group in self.df.groupby(['well','position']):
|
|
393
446
|
|
|
394
|
-
well_signal_mean, well_std_mean, timeline_all, matrix_all = mean_signal(movie_group, self.feature_selected, class_col, time_col=time_col, class_value=None, return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value())
|
|
395
|
-
well_signal_event, well_std_event, timeline_event, matrix_event = mean_signal(movie_group, self.feature_selected, class_col, time_col=time_col, class_value=[0], return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value())
|
|
396
|
-
well_signal_no_event, well_std_no_event, timeline_no_event, matrix_no_event = mean_signal(movie_group, self.feature_selected, class_col, time_col=time_col, class_value=[1], return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value())
|
|
447
|
+
well_signal_mean, well_std_mean, timeline_all, matrix_all = mean_signal(movie_group, self.feature_selected, class_col, time_col=time_col, class_value=None, return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value(),pairs=pairs)
|
|
448
|
+
well_signal_event, well_std_event, timeline_event, matrix_event = mean_signal(movie_group, self.feature_selected, class_col, time_col=time_col, class_value=[0], return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value(),pairs=pairs)
|
|
449
|
+
well_signal_no_event, well_std_no_event, timeline_no_event, matrix_no_event = mean_signal(movie_group, self.feature_selected, class_col, time_col=time_col, class_value=[1], return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value(),pairs=pairs)
|
|
397
450
|
self.mean_plots_timeline = timeline_all
|
|
398
451
|
|
|
399
452
|
self.df_pos_info.loc[self.df_pos_info['pos_path'] == block[1], 'signal'] = [
|
|
@@ -406,9 +459,9 @@ class ConfigSignalPlot(QWidget, Styles):
|
|
|
406
459
|
# Per well
|
|
407
460
|
for well,well_group in self.df.groupby('well'):
|
|
408
461
|
|
|
409
|
-
well_signal_mean, well_std_mean, timeline_all, matrix_all = mean_signal(well_group, self.feature_selected, class_col, time_col=time_col, class_value=None, return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value())
|
|
410
|
-
well_signal_event, well_std_event, timeline_event, matrix_event = mean_signal(well_group, self.feature_selected, class_col, time_col=time_col, class_value=[0], return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value())
|
|
411
|
-
well_signal_no_event, well_std_no_event, timeline_no_event, matrix_no_event = mean_signal(well_group, self.feature_selected, class_col, time_col=time_col, class_value=[1], return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value())
|
|
462
|
+
well_signal_mean, well_std_mean, timeline_all, matrix_all = mean_signal(well_group, self.feature_selected, class_col, time_col=time_col, class_value=None, return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value(),pairs=pairs)
|
|
463
|
+
well_signal_event, well_std_event, timeline_event, matrix_event = mean_signal(well_group, self.feature_selected, class_col, time_col=time_col, class_value=[0], return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value(),pairs=pairs)
|
|
464
|
+
well_signal_no_event, well_std_no_event, timeline_no_event, matrix_no_event = mean_signal(well_group, self.feature_selected, class_col, time_col=time_col, class_value=[1], return_matrix=True, forced_max_duration=max_time, projection=self.pool_option_cb.currentText(), min_nbr_values=self.n_cells_slider.value(),pairs=pairs)
|
|
412
465
|
|
|
413
466
|
self.df_well_info.loc[self.df_well_info['well_path']==well,'signal'] = [{'mean_all': well_signal_mean, 'std_all': well_std_mean,'matrix_all': matrix_all,'mean_event': well_signal_event, 'std_event': well_std_event,
|
|
414
467
|
'matrix_event': matrix_event,'mean_no_event': well_signal_no_event, 'std_no_event': well_std_no_event, 'matrix_no_event': matrix_no_event, 'timeline': self.mean_plots_timeline}]
|