celldetective 1.1.1.post1__tar.gz → 1.1.1.post4__tar.gz
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-1.1.1.post1 → celldetective-1.1.1.post4}/PKG-INFO +1 -1
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/__main__.py +17 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/classifier_widget.py +10 -3
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/control_panel.py +11 -4
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/layouts.py +253 -8
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/neighborhood_options.py +11 -5
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/retrain_segmentation_model_options.py +66 -164
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/retrain_signal_model_options.py +18 -164
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/signal_annotator.py +85 -25
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/tableUI.py +174 -65
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/viewers.py +1 -1
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/io.py +69 -3
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/neighborhood.py +96 -26
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/preprocessing.py +95 -63
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/scripts/segment_cells.py +1 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/scripts/train_segmentation_model.py +11 -22
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/segmentation.py +67 -29
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/utils.py +54 -14
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective.egg-info/PKG-INFO +1 -1
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/setup.py +1 -1
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_segmentation.py +1 -1
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/LICENSE +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/README.md +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/__init__.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/datasets/segmentation_annotations/blank +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/datasets/signal_annotations/blank +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/events.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/extra_properties.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/filters.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/__init__.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/about.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/analyze_block.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/btrack_options.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/configure_new_exp.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/gui_utils.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/json_readers.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/measurement_options.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/plot_measurements.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/plot_signals_ui.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/process_block.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/seg_model_loader.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/signal_annotator_options.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/styles.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/survival_ui.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/thresholds_gui.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/icons/logo-large.png +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/icons/logo.png +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/icons/signals_icon.png +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/icons/splash-test.png +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/icons/splash.png +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/icons/splash0.png +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/icons/survival2.png +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/icons/vignette_signals2.png +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/icons/vignette_signals2.svg +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/links/zenodo.json +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/measure.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/segmentation_effectors/blank +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/segmentation_effectors/primNK_cfse/config_input.json +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/segmentation_effectors/primNK_cfse/cp-cfse-transfer +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/segmentation_effectors/primNK_cfse/training_instructions.json +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/segmentation_generic/blank +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/segmentation_targets/blank +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/signal_detection/blank +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/tracking_configs/mcf7.json +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/tracking_configs/ricm.json +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/models/tracking_configs/ricm2.json +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/scripts/analyze_signals.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/scripts/measure_cells.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/scripts/segment_cells_thresholds.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/scripts/track_cells.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/scripts/train_signal_model.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/signals.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/tracking.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective.egg-info/SOURCES.txt +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective.egg-info/dependency_links.txt +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective.egg-info/entry_points.txt +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective.egg-info/not-zip-safe +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective.egg-info/requires.txt +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective.egg-info/top_level.txt +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/setup.cfg +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/__init__.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_events.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_filters.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_io.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_measure.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_neighborhood.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_preprocessing.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_signals.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_tracking.py +0 -0
- {celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/tests/test_utils.py +0 -0
|
@@ -108,6 +108,10 @@ class AppInitWindow(QMainWindow):
|
|
|
108
108
|
OptionsMenu.addAction(self.MemoryAndThreadsAction)
|
|
109
109
|
menuBar.addMenu(OptionsMenu)
|
|
110
110
|
|
|
111
|
+
PluginsMenu = QMenu("Plugins", self)
|
|
112
|
+
PluginsMenu.addAction(self.CorrectAnnotationAction)
|
|
113
|
+
menuBar.addMenu(PluginsMenu)
|
|
114
|
+
|
|
111
115
|
helpMenu = QMenu("Help", self)
|
|
112
116
|
helpMenu.clear()
|
|
113
117
|
helpMenu.addAction(self.DocumentationAction)
|
|
@@ -130,6 +134,8 @@ class AppInitWindow(QMainWindow):
|
|
|
130
134
|
|
|
131
135
|
self.MemoryAndThreadsAction = QAction('Memory & Threads...')
|
|
132
136
|
|
|
137
|
+
self.CorrectAnnotationAction = QAction('Correct a segmentation annotation...')
|
|
138
|
+
|
|
133
139
|
self.newExpAction = QAction('New', self)
|
|
134
140
|
self.newExpAction.setShortcut("Ctrl+N")
|
|
135
141
|
self.newExpAction.setShortcutVisibleInContextMenu(True)
|
|
@@ -156,6 +162,7 @@ class AppInitWindow(QMainWindow):
|
|
|
156
162
|
self.openModels.triggered.connect(self.open_models_folder)
|
|
157
163
|
self.AboutAction.triggered.connect(self.open_about_window)
|
|
158
164
|
self.MemoryAndThreadsAction.triggered.connect(self.set_memory_and_threads)
|
|
165
|
+
self.CorrectAnnotationAction.triggered.connect(self.correct_seg_annotation)
|
|
159
166
|
|
|
160
167
|
self.DocumentationAction.triggered.connect(self.open_documentation)
|
|
161
168
|
|
|
@@ -186,6 +193,15 @@ class AppInitWindow(QMainWindow):
|
|
|
186
193
|
for r in self.recentFileActs:
|
|
187
194
|
r.triggered.connect(lambda checked, item=r: self.load_recent_exp(item.text()))
|
|
188
195
|
|
|
196
|
+
def correct_seg_annotation(self):
|
|
197
|
+
|
|
198
|
+
self.filename,_ = QFileDialog.getOpenFileName(self,"Open Image", "/home/", "TIF Files (*.tif)")
|
|
199
|
+
if self.filename!='':
|
|
200
|
+
print('Opening ',self.filename,' in napari...')
|
|
201
|
+
correct_annotation(self.filename)
|
|
202
|
+
else:
|
|
203
|
+
return None
|
|
204
|
+
|
|
189
205
|
def set_memory_and_threads(self):
|
|
190
206
|
|
|
191
207
|
print('setting memory and threads')
|
|
@@ -405,6 +421,7 @@ if __name__ == "__main__":
|
|
|
405
421
|
import subprocess
|
|
406
422
|
import os
|
|
407
423
|
from celldetective.gui.about import AboutWidget
|
|
424
|
+
from celldetective.io import correct_annotation
|
|
408
425
|
import psutil
|
|
409
426
|
import subprocess
|
|
410
427
|
import json
|
{celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/classifier_widget.py
RENAMED
|
@@ -12,6 +12,7 @@ from sklearn.metrics import r2_score
|
|
|
12
12
|
from scipy.optimize import curve_fit
|
|
13
13
|
from celldetective.gui import Styles
|
|
14
14
|
from math import ceil
|
|
15
|
+
from celldetective.utils import extract_cols_from_query
|
|
15
16
|
|
|
16
17
|
def step_function(t, t_shift, dt):
|
|
17
18
|
return 1/(1+np.exp(-(t-t_shift)/dt))
|
|
@@ -263,17 +264,23 @@ class ClassifierWidget(QWidget, Styles):
|
|
|
263
264
|
self.propscanvas.canvas.draw_idle()
|
|
264
265
|
|
|
265
266
|
def apply_property_query(self):
|
|
267
|
+
|
|
266
268
|
query = self.property_query_le.text()
|
|
267
269
|
self.df[self.class_name] = 1
|
|
268
270
|
|
|
269
|
-
|
|
271
|
+
cols = extract_cols_from_query(query)
|
|
272
|
+
print(cols)
|
|
273
|
+
cols_in_df = np.all([c in list(self.df.columns) for c in cols], axis=0)
|
|
274
|
+
print(f'Testing if columns from query are in the dataframe: {cols_in_df}...')
|
|
270
275
|
|
|
271
276
|
if query=='':
|
|
272
277
|
print('empty query')
|
|
273
278
|
else:
|
|
274
279
|
try:
|
|
275
|
-
|
|
276
|
-
|
|
280
|
+
if cols_in_df:
|
|
281
|
+
self.selection = self.df.dropna(subset=cols).query(query).index
|
|
282
|
+
else:
|
|
283
|
+
self.selection = self.df.query(query).index
|
|
277
284
|
self.df.loc[self.selection, self.class_name] = 0
|
|
278
285
|
except Exception as e:
|
|
279
286
|
print(e)
|
|
@@ -16,6 +16,7 @@ import subprocess
|
|
|
16
16
|
from celldetective.gui.viewers import StackVisualizer
|
|
17
17
|
from celldetective.utils import extract_experiment_channels
|
|
18
18
|
from celldetective.gui import Styles
|
|
19
|
+
import pandas as pd
|
|
19
20
|
|
|
20
21
|
class ControlPanel(QMainWindow, Styles):
|
|
21
22
|
|
|
@@ -452,26 +453,32 @@ class ControlPanel(QMainWindow, Styles):
|
|
|
452
453
|
self.ProcessEffectors.check_tracking_result_btn.setEnabled(False)
|
|
453
454
|
|
|
454
455
|
if os.path.exists(os.sep.join([self.pos,'output','tables','trajectories_effectors.csv'])):
|
|
456
|
+
cols = pd.read_csv(os.sep.join([self.pos,'output','tables','trajectories_effectors.csv']), nrows=1).columns.tolist()
|
|
455
457
|
self.ProcessEffectors.check_measurements_btn.setEnabled(True)
|
|
456
|
-
|
|
458
|
+
if 'TRACK_ID' in cols:
|
|
459
|
+
self.ProcessEffectors.check_signals_btn.setEnabled(True)
|
|
457
460
|
#self.ProcessEffectors.signal_analysis_action.setEnabled(True)
|
|
458
461
|
self.ProcessEffectors.view_tab_btn.setEnabled(True)
|
|
459
|
-
|
|
462
|
+
self.ProcessEffectors.classify_btn.setEnabled(True)
|
|
460
463
|
else:
|
|
461
464
|
self.ProcessEffectors.check_measurements_btn.setEnabled(False)
|
|
462
465
|
self.ProcessEffectors.check_signals_btn.setEnabled(False)
|
|
463
466
|
#self.ProcessEffectors.signal_analysis_action.setEnabled(False)
|
|
464
467
|
self.ProcessEffectors.view_tab_btn.setEnabled(False)
|
|
468
|
+
self.ProcessEffectors.classify_btn.setEnabled(False)
|
|
465
469
|
|
|
466
470
|
if os.path.exists(os.sep.join([self.pos,'output','tables','trajectories_targets.csv'])):
|
|
471
|
+
cols = pd.read_csv(os.sep.join([self.pos,'output','tables','trajectories_targets.csv']), nrows=1).columns.tolist()
|
|
467
472
|
self.ProcessTargets.check_measurements_btn.setEnabled(True)
|
|
468
|
-
|
|
473
|
+
if 'TRACK_ID' in cols:
|
|
474
|
+
self.ProcessTargets.check_signals_btn.setEnabled(True)
|
|
469
475
|
#self.ProcessTargets.signal_analysis_action.setEnabled(True)
|
|
470
476
|
self.ProcessTargets.view_tab_btn.setEnabled(True)
|
|
471
|
-
|
|
477
|
+
self.ProcessTargets.classify_btn.setEnabled(True)
|
|
472
478
|
else:
|
|
473
479
|
self.ProcessTargets.check_measurements_btn.setEnabled(False)
|
|
474
480
|
self.ProcessTargets.check_signals_btn.setEnabled(False)
|
|
475
481
|
#self.ProcessTargets.signal_analysis_action.setEnabled(False)
|
|
476
482
|
self.ProcessTargets.view_tab_btn.setEnabled(False)
|
|
483
|
+
self.ProcessTargets.classify_btn.setEnabled(False)
|
|
477
484
|
|
|
@@ -3,7 +3,7 @@ from celldetective.gui.gui_utils import ThresholdLineEdit
|
|
|
3
3
|
from PyQt5.QtCore import Qt, QSize
|
|
4
4
|
from PyQt5.QtGui import QIntValidator
|
|
5
5
|
|
|
6
|
-
from superqt import QLabeledRangeSlider, QLabeledSlider, QLabeledDoubleRangeSlider
|
|
6
|
+
from superqt import QLabeledRangeSlider, QLabeledSlider, QLabeledDoubleRangeSlider, QSearchableComboBox
|
|
7
7
|
|
|
8
8
|
from superqt.fonticon import icon
|
|
9
9
|
from fonticon_mdi6 import MDI6
|
|
@@ -12,6 +12,249 @@ from celldetective.gui.viewers import ThresholdedStackVisualizer, CellEdgeVisual
|
|
|
12
12
|
from celldetective.gui import Styles
|
|
13
13
|
from celldetective.gui.gui_utils import QuickSliderLayout
|
|
14
14
|
from celldetective.preprocessing import correct_background_model, correct_background_model_free, estimate_background_per_condition
|
|
15
|
+
from functools import partial
|
|
16
|
+
from glob import glob
|
|
17
|
+
import os
|
|
18
|
+
import pandas as pd
|
|
19
|
+
import numpy as np
|
|
20
|
+
|
|
21
|
+
class ChannelNormGenerator(QVBoxLayout, Styles):
|
|
22
|
+
|
|
23
|
+
"""Generator for list of channels"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, parent_window=None, init_n_channels=4, mode='signals', *args):
|
|
26
|
+
super().__init__(*args)
|
|
27
|
+
|
|
28
|
+
self.parent_window = parent_window
|
|
29
|
+
self.mode = mode
|
|
30
|
+
self.init_n_channels = init_n_channels
|
|
31
|
+
|
|
32
|
+
if hasattr(self.parent_window.parent_window, 'locate_image'):
|
|
33
|
+
self.attr_parent = self.parent_window.parent_window
|
|
34
|
+
elif hasattr(self.parent_window.parent_window.parent_window, 'locate_image'):
|
|
35
|
+
self.attr_parent = self.parent_window.parent_window.parent_window
|
|
36
|
+
else:
|
|
37
|
+
self.attr_parent = self.parent_window.parent_window.parent_window.parent_window
|
|
38
|
+
|
|
39
|
+
self.channel_names = self.attr_parent.exp_channels
|
|
40
|
+
self.setContentsMargins(15,15,15,15)
|
|
41
|
+
self.generate_widgets()
|
|
42
|
+
self.add_to_layout()
|
|
43
|
+
|
|
44
|
+
def generate_widgets(self):
|
|
45
|
+
|
|
46
|
+
self.channel_cbs = [QSearchableComboBox() for i in range(self.init_n_channels)]
|
|
47
|
+
self.normalization_mode_btns = [QPushButton('') for i in range(self.init_n_channels)]
|
|
48
|
+
self.normalization_mode = [True for i in range(self.init_n_channels)]
|
|
49
|
+
self.normalization_clip_btns = [QPushButton('') for i in range(self.init_n_channels)]
|
|
50
|
+
self.clip_option = [False for i in range(self.init_n_channels)]
|
|
51
|
+
|
|
52
|
+
for i in range(self.init_n_channels):
|
|
53
|
+
self.normalization_mode_btns[i].setIcon(icon(MDI6.percent_circle,color="#1565c0"))
|
|
54
|
+
self.normalization_mode_btns[i].setIconSize(QSize(20, 20))
|
|
55
|
+
self.normalization_mode_btns[i].setStyleSheet(self.button_select_all)
|
|
56
|
+
self.normalization_mode_btns[i].setToolTip("Switch to absolute normalization values.")
|
|
57
|
+
self.normalization_mode_btns[i].clicked.connect(partial(self.switch_normalization_mode, i))
|
|
58
|
+
|
|
59
|
+
self.normalization_clip_btns[i].setIcon(icon(MDI6.content_cut,color="black"))
|
|
60
|
+
self.normalization_clip_btns[i].setIconSize(QSize(20, 20))
|
|
61
|
+
self.normalization_clip_btns[i].setStyleSheet(self.button_select_all)
|
|
62
|
+
self.normalization_clip_btns[i].clicked.connect(partial(self.switch_clipping_mode, i))
|
|
63
|
+
self.normalization_clip_btns[i].setToolTip('clip')
|
|
64
|
+
|
|
65
|
+
self.normalization_min_value_lbl = [QLabel('Min %: ') for i in range(self.init_n_channels)]
|
|
66
|
+
self.normalization_min_value_le = [QLineEdit('0.1') for i in range(self.init_n_channels)]
|
|
67
|
+
self.normalization_max_value_lbl = [QLabel('Max %: ') for i in range(self.init_n_channels)]
|
|
68
|
+
self.normalization_max_value_le = [QLineEdit('99.99') for i in range(self.init_n_channels)]
|
|
69
|
+
|
|
70
|
+
if self.mode=='signals':
|
|
71
|
+
tables = glob(self.parent_window.exp_dir+os.sep.join(['W*','*','output','tables',f'trajectories_{self.parent_window.mode}.csv']))
|
|
72
|
+
all_measurements = []
|
|
73
|
+
for tab in tables:
|
|
74
|
+
cols = pd.read_csv(tab, nrows=1).columns.tolist()
|
|
75
|
+
all_measurements.extend(cols)
|
|
76
|
+
all_measurements = np.unique(all_measurements)
|
|
77
|
+
|
|
78
|
+
if self.mode=='signals':
|
|
79
|
+
generic_measurements = ['brightfield_channel', 'live_nuclei_channel', 'dead_nuclei_channel',
|
|
80
|
+
'effector_fluo_channel', 'adhesion_channel', 'fluo_channel_1', 'fluo_channel_2',
|
|
81
|
+
"area", "area_bbox","area_convex","area_filled","major_axis_length",
|
|
82
|
+
"minor_axis_length",
|
|
83
|
+
"eccentricity",
|
|
84
|
+
"equivalent_diameter_area",
|
|
85
|
+
"euler_number",
|
|
86
|
+
"extent",
|
|
87
|
+
"feret_diameter_max",
|
|
88
|
+
"orientation",
|
|
89
|
+
"perimeter",
|
|
90
|
+
"perimeter_crofton",
|
|
91
|
+
"solidity",
|
|
92
|
+
"angular_second_moment",
|
|
93
|
+
"contrast",
|
|
94
|
+
"correlation",
|
|
95
|
+
"sum_of_square_variance",
|
|
96
|
+
"inverse_difference_moment",
|
|
97
|
+
"sum_average",
|
|
98
|
+
"sum_variance",
|
|
99
|
+
"sum_entropy",
|
|
100
|
+
"entropy",
|
|
101
|
+
"difference_variance",
|
|
102
|
+
"difference_entropy",
|
|
103
|
+
"information_measure_of_correlation_1",
|
|
104
|
+
"information_measure_of_correlation_2",
|
|
105
|
+
"maximal_correlation_coefficient",
|
|
106
|
+
"POSITION_X",
|
|
107
|
+
"POSITION_Y",
|
|
108
|
+
]
|
|
109
|
+
elif self.mode=='channels':
|
|
110
|
+
generic_measurements = ['brightfield_channel', 'live_nuclei_channel', 'dead_nuclei_channel',
|
|
111
|
+
'effector_fluo_channel', 'adhesion_channel', 'fluo_channel_1', 'fluo_channel_2', 'None']
|
|
112
|
+
|
|
113
|
+
if self.mode=='channels':
|
|
114
|
+
all_measurements = []
|
|
115
|
+
exp_ch = self.attr_parent.exp_channels
|
|
116
|
+
for c in exp_ch:
|
|
117
|
+
all_measurements.append(c)
|
|
118
|
+
|
|
119
|
+
self.channel_items = np.unique(generic_measurements + list(all_measurements))
|
|
120
|
+
self.channel_items = np.insert(self.channel_items, 0, '--')
|
|
121
|
+
|
|
122
|
+
self.add_col_btn = QPushButton('Add channel')
|
|
123
|
+
self.add_col_btn.clicked.connect(self.add_channel)
|
|
124
|
+
self.add_col_btn.setStyleSheet(self.button_add)
|
|
125
|
+
self.add_col_btn.setIcon(icon(MDI6.plus,color="black"))
|
|
126
|
+
|
|
127
|
+
def add_channel(self):
|
|
128
|
+
|
|
129
|
+
self.channel_cbs.append(QSearchableComboBox())
|
|
130
|
+
self.channel_cbs[-1].addItems(self.channel_items)
|
|
131
|
+
self.channel_cbs[-1].currentIndexChanged.connect(self.check_valid_channels)
|
|
132
|
+
|
|
133
|
+
self.normalization_mode_btns.append(QPushButton(''))
|
|
134
|
+
self.normalization_mode.append(True)
|
|
135
|
+
self.normalization_clip_btns.append(QPushButton(''))
|
|
136
|
+
self.clip_option.append(False)
|
|
137
|
+
|
|
138
|
+
self.normalization_mode_btns[-1].setIcon(icon(MDI6.percent_circle,color="#1565c0"))
|
|
139
|
+
self.normalization_mode_btns[-1].setIconSize(QSize(20, 20))
|
|
140
|
+
self.normalization_mode_btns[-1].setStyleSheet(self.button_select_all)
|
|
141
|
+
self.normalization_mode_btns[-1].setToolTip("Switch to absolute normalization values.")
|
|
142
|
+
self.normalization_mode_btns[-1].clicked.connect(partial(self.switch_normalization_mode, len(self.channel_cbs)-1))
|
|
143
|
+
|
|
144
|
+
self.normalization_clip_btns[-1].setIcon(icon(MDI6.content_cut,color="black"))
|
|
145
|
+
self.normalization_clip_btns[-1].setIconSize(QSize(20, 20))
|
|
146
|
+
self.normalization_clip_btns[-1].setStyleSheet(self.button_select_all)
|
|
147
|
+
self.normalization_clip_btns[-1].clicked.connect(partial(self.switch_clipping_mode, len(self.channel_cbs)-1))
|
|
148
|
+
self.normalization_clip_btns[-1].setToolTip('clip')
|
|
149
|
+
|
|
150
|
+
self.normalization_min_value_lbl.append(QLabel('Min %: '))
|
|
151
|
+
self.normalization_min_value_le.append(QLineEdit('0.1'))
|
|
152
|
+
self.normalization_max_value_lbl.append(QLabel('Max %: '))
|
|
153
|
+
self.normalization_max_value_le.append(QLineEdit('99.99'))
|
|
154
|
+
|
|
155
|
+
ch_layout = QHBoxLayout()
|
|
156
|
+
ch_layout.addWidget(QLabel(f'channel {len(self.channel_cbs)-1}: '), 30)
|
|
157
|
+
ch_layout.addWidget(self.channel_cbs[-1], 70)
|
|
158
|
+
self.channels_vb.addLayout(ch_layout)
|
|
159
|
+
|
|
160
|
+
channel_norm_options_layout = QHBoxLayout()
|
|
161
|
+
channel_norm_options_layout.setContentsMargins(130,0,0,0)
|
|
162
|
+
channel_norm_options_layout.addWidget(self.normalization_min_value_lbl[-1])
|
|
163
|
+
channel_norm_options_layout.addWidget(self.normalization_min_value_le[-1])
|
|
164
|
+
channel_norm_options_layout.addWidget(self.normalization_max_value_lbl[-1])
|
|
165
|
+
channel_norm_options_layout.addWidget(self.normalization_max_value_le[-1])
|
|
166
|
+
channel_norm_options_layout.addWidget(self.normalization_clip_btns[-1])
|
|
167
|
+
channel_norm_options_layout.addWidget(self.normalization_mode_btns[-1])
|
|
168
|
+
self.channels_vb.addLayout(channel_norm_options_layout)
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def add_to_layout(self):
|
|
172
|
+
|
|
173
|
+
self.channels_vb = QVBoxLayout()
|
|
174
|
+
self.channel_option_layouts = []
|
|
175
|
+
for i in range(len(self.channel_cbs)):
|
|
176
|
+
|
|
177
|
+
ch_layout = QHBoxLayout()
|
|
178
|
+
ch_layout.addWidget(QLabel(f'channel {i}: '), 30)
|
|
179
|
+
self.channel_cbs[i].addItems(self.channel_items)
|
|
180
|
+
self.channel_cbs[i].currentIndexChanged.connect(self.check_valid_channels)
|
|
181
|
+
ch_layout.addWidget(self.channel_cbs[i], 70)
|
|
182
|
+
self.channels_vb.addLayout(ch_layout)
|
|
183
|
+
|
|
184
|
+
channel_norm_options_layout = QHBoxLayout()
|
|
185
|
+
channel_norm_options_layout.setContentsMargins(130,0,0,0)
|
|
186
|
+
channel_norm_options_layout.addWidget(self.normalization_min_value_lbl[i])
|
|
187
|
+
channel_norm_options_layout.addWidget(self.normalization_min_value_le[i])
|
|
188
|
+
channel_norm_options_layout.addWidget(self.normalization_max_value_lbl[i])
|
|
189
|
+
channel_norm_options_layout.addWidget(self.normalization_max_value_le[i])
|
|
190
|
+
channel_norm_options_layout.addWidget(self.normalization_clip_btns[i])
|
|
191
|
+
channel_norm_options_layout.addWidget(self.normalization_mode_btns[i])
|
|
192
|
+
self.channels_vb.addLayout(channel_norm_options_layout)
|
|
193
|
+
|
|
194
|
+
self.addLayout(self.channels_vb)
|
|
195
|
+
|
|
196
|
+
add_hbox = QHBoxLayout()
|
|
197
|
+
add_hbox.addWidget(QLabel(''), 66)
|
|
198
|
+
add_hbox.addWidget(self.add_col_btn, 33, alignment=Qt.AlignRight)
|
|
199
|
+
self.addLayout(add_hbox)
|
|
200
|
+
|
|
201
|
+
def switch_normalization_mode(self, index):
|
|
202
|
+
|
|
203
|
+
"""
|
|
204
|
+
Use absolute or percentile values for the normalization of each individual channel.
|
|
205
|
+
|
|
206
|
+
"""
|
|
207
|
+
|
|
208
|
+
currentNormMode = self.normalization_mode[index]
|
|
209
|
+
self.normalization_mode[index] = not currentNormMode
|
|
210
|
+
|
|
211
|
+
if self.normalization_mode[index]:
|
|
212
|
+
self.normalization_mode_btns[index].setIcon(icon(MDI6.percent_circle,color="#1565c0"))
|
|
213
|
+
self.normalization_mode_btns[index].setIconSize(QSize(20, 20))
|
|
214
|
+
self.normalization_mode_btns[index].setStyleSheet(self.button_select_all)
|
|
215
|
+
self.normalization_mode_btns[index].setToolTip("Switch to absolute normalization values.")
|
|
216
|
+
self.normalization_min_value_lbl[index].setText('Min %: ')
|
|
217
|
+
self.normalization_max_value_lbl[index].setText('Max %: ')
|
|
218
|
+
self.normalization_min_value_le[index].setText('0.1')
|
|
219
|
+
self.normalization_max_value_le[index].setText('99.99')
|
|
220
|
+
|
|
221
|
+
else:
|
|
222
|
+
self.normalization_mode_btns[index].setIcon(icon(MDI6.percent_circle_outline,color="black"))
|
|
223
|
+
self.normalization_mode_btns[index].setIconSize(QSize(20, 20))
|
|
224
|
+
self.normalization_mode_btns[index].setStyleSheet(self.button_select_all)
|
|
225
|
+
self.normalization_mode_btns[index].setToolTip("Switch to percentile normalization values.")
|
|
226
|
+
self.normalization_min_value_lbl[index].setText('Min: ')
|
|
227
|
+
self.normalization_min_value_le[index].setText('0')
|
|
228
|
+
self.normalization_max_value_lbl[index].setText('Max: ')
|
|
229
|
+
self.normalization_max_value_le[index].setText('1000')
|
|
230
|
+
|
|
231
|
+
def switch_clipping_mode(self, index):
|
|
232
|
+
|
|
233
|
+
currentClipMode = self.clip_option[index]
|
|
234
|
+
self.clip_option[index] = not currentClipMode
|
|
235
|
+
|
|
236
|
+
if self.clip_option[index]:
|
|
237
|
+
self.normalization_clip_btns[index].setIcon(icon(MDI6.content_cut,color="#1565c0"))
|
|
238
|
+
self.normalization_clip_btns[index].setIconSize(QSize(20, 20))
|
|
239
|
+
self.normalization_clip_btns[index].setStyleSheet(self.button_select_all)
|
|
240
|
+
|
|
241
|
+
else:
|
|
242
|
+
self.normalization_clip_btns[index].setIcon(icon(MDI6.content_cut,color="black"))
|
|
243
|
+
self.normalization_clip_btns[index].setIconSize(QSize(20, 20))
|
|
244
|
+
self.normalization_clip_btns[index].setStyleSheet(self.button_select_all)
|
|
245
|
+
|
|
246
|
+
def check_valid_channels(self):
|
|
247
|
+
|
|
248
|
+
if np.all([cb.currentText()=='--' for cb in self.channel_cbs]):
|
|
249
|
+
self.parent_window.submit_btn.setEnabled(False)
|
|
250
|
+
|
|
251
|
+
if hasattr(self.parent_window, "spatial_calib_le"):
|
|
252
|
+
if self.parent_window.spatial_calib_le.text()!='--':
|
|
253
|
+
self.parent_window.submit_btn.setEnabled(True)
|
|
254
|
+
else:
|
|
255
|
+
self.parent_window.submit_btn.setEnabled(True)
|
|
256
|
+
|
|
257
|
+
|
|
15
258
|
|
|
16
259
|
class BackgroundFitCorrectionLayout(QGridLayout, Styles):
|
|
17
260
|
|
|
@@ -747,10 +990,12 @@ class BackgroundModelFreeCorrectionLayout(QGridLayout, Styles):
|
|
|
747
990
|
)
|
|
748
991
|
bg = bg[0]
|
|
749
992
|
bg = bg['bg']
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
993
|
+
print(bg)
|
|
994
|
+
if len(bg)>0:
|
|
995
|
+
|
|
996
|
+
self.viewer = StackVisualizer(
|
|
997
|
+
stack=[bg],
|
|
998
|
+
window_title='Reconstructed background',
|
|
999
|
+
frame_slider = False,
|
|
1000
|
+
)
|
|
1001
|
+
self.viewer.show()
|
{celldetective-1.1.1.post1 → celldetective-1.1.1.post4}/celldetective/gui/neighborhood_options.py
RENAMED
|
@@ -319,16 +319,16 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
319
319
|
def fill_cbs_of_neighbor_population(self):
|
|
320
320
|
|
|
321
321
|
population = self.neighbor_population_cb.currentText()
|
|
322
|
-
class_cols, status_cols, time_cols = self.locate_population_specific_columns(population)
|
|
322
|
+
class_cols, status_cols, group_cols, time_cols = self.locate_population_specific_columns(population)
|
|
323
323
|
self.neighbor_population_status_cb.clear()
|
|
324
|
-
self.neighbor_population_status_cb.addItems(['--','class', 'status']+class_cols+status_cols)
|
|
324
|
+
self.neighbor_population_status_cb.addItems(['--','class', 'status']+class_cols+status_cols+group_cols)
|
|
325
325
|
|
|
326
326
|
def fill_cbs_of_reference_population(self):
|
|
327
327
|
|
|
328
328
|
population = self.reference_population_cb.currentText()
|
|
329
|
-
class_cols, status_cols, time_cols = self.locate_population_specific_columns(population)
|
|
329
|
+
class_cols, status_cols, group_cols, time_cols = self.locate_population_specific_columns(population)
|
|
330
330
|
self.reference_population_status_cb.clear()
|
|
331
|
-
self.reference_population_status_cb.addItems(['--','class', 'status']+class_cols+status_cols)
|
|
331
|
+
self.reference_population_status_cb.addItems(['--','class', 'status']+class_cols+status_cols+group_cols)
|
|
332
332
|
self.event_time_cb.addItems(['--', 't0']+time_cols)
|
|
333
333
|
|
|
334
334
|
def switch_not_reference(self):
|
|
@@ -364,6 +364,7 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
364
364
|
|
|
365
365
|
class_idx = np.array([s.startswith('class_') for s in self.all_columns])
|
|
366
366
|
status_idx = np.array([s.startswith('status_') for s in self.all_columns])
|
|
367
|
+
group_idx = np.array([s.startswith('group_') for s in self.all_columns])
|
|
367
368
|
time_idx = np.array([s.startswith('t_') for s in self.all_columns])
|
|
368
369
|
|
|
369
370
|
if len(class_idx)>0:
|
|
@@ -379,12 +380,17 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
379
380
|
else:
|
|
380
381
|
status_columns = []
|
|
381
382
|
|
|
383
|
+
if len(group_idx)>0:
|
|
384
|
+
group_columns = list(self.all_columns[group_idx])
|
|
385
|
+
else:
|
|
386
|
+
group_columns = []
|
|
387
|
+
|
|
382
388
|
if len(time_idx)>0:
|
|
383
389
|
time_columns = list(self.all_columns[time_idx])
|
|
384
390
|
else:
|
|
385
391
|
time_columns = []
|
|
386
392
|
|
|
387
|
-
return class_columns, status_columns, time_columns
|
|
393
|
+
return class_columns, status_columns, group_columns, time_columns
|
|
388
394
|
|
|
389
395
|
def write_instructions(self):
|
|
390
396
|
|