celldetective 1.2.0__py3-none-any.whl → 1.2.2__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 +12 -5
- celldetective/events.py +28 -2
- celldetective/gui/about.py +0 -1
- celldetective/gui/analyze_block.py +3 -18
- celldetective/gui/btrack_options.py +126 -21
- celldetective/gui/classifier_widget.py +68 -107
- celldetective/gui/configure_new_exp.py +37 -4
- celldetective/gui/control_panel.py +14 -30
- celldetective/gui/generic_signal_plot.py +793 -0
- celldetective/gui/gui_utils.py +401 -226
- celldetective/gui/json_readers.py +0 -2
- celldetective/gui/layouts.py +269 -25
- celldetective/gui/measurement_options.py +14 -23
- celldetective/gui/neighborhood_options.py +6 -16
- celldetective/gui/plot_measurements.py +10 -23
- celldetective/gui/plot_signals_ui.py +53 -687
- celldetective/gui/process_block.py +320 -186
- celldetective/gui/retrain_segmentation_model_options.py +30 -47
- celldetective/gui/retrain_signal_model_options.py +5 -14
- celldetective/gui/seg_model_loader.py +129 -113
- celldetective/gui/signal_annotator.py +93 -103
- celldetective/gui/signal_annotator2.py +9 -13
- celldetective/gui/styles.py +32 -0
- celldetective/gui/survival_ui.py +49 -712
- celldetective/gui/tableUI.py +4 -39
- celldetective/gui/thresholds_gui.py +38 -11
- celldetective/gui/viewers.py +6 -7
- celldetective/io.py +62 -84
- celldetective/measure.py +374 -15
- celldetective/models/segmentation_effectors/ricm-bimodal/config_input.json +130 -0
- celldetective/models/segmentation_effectors/ricm-bimodal/ricm-bimodal +0 -0
- celldetective/models/segmentation_effectors/ricm-bimodal/training_instructions.json +37 -0
- celldetective/neighborhood.py +3 -7
- celldetective/preprocessing.py +2 -4
- celldetective/relative_measurements.py +0 -3
- celldetective/scripts/analyze_signals.py +0 -1
- celldetective/scripts/measure_cells.py +1 -3
- celldetective/scripts/measure_relative.py +1 -2
- celldetective/scripts/segment_cells.py +16 -12
- celldetective/scripts/segment_cells_thresholds.py +17 -10
- celldetective/scripts/track_cells.py +18 -18
- celldetective/scripts/train_segmentation_model.py +1 -2
- celldetective/scripts/train_signal_model.py +0 -3
- celldetective/segmentation.py +1 -1
- celldetective/signals.py +20 -8
- celldetective/tracking.py +2 -1
- celldetective/utils.py +126 -18
- {celldetective-1.2.0.dist-info → celldetective-1.2.2.dist-info}/METADATA +19 -12
- celldetective-1.2.2.dist-info/RECORD +92 -0
- {celldetective-1.2.0.dist-info → celldetective-1.2.2.dist-info}/WHEEL +1 -1
- celldetective-1.2.0.dist-info/RECORD +0 -88
- {celldetective-1.2.0.dist-info → celldetective-1.2.2.dist-info}/LICENSE +0 -0
- {celldetective-1.2.0.dist-info → celldetective-1.2.2.dist-info}/entry_points.txt +0 -0
- {celldetective-1.2.0.dist-info → celldetective-1.2.2.dist-info}/top_level.txt +0 -0
celldetective/gui/layouts.py
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
from PyQt5.QtWidgets import QCheckBox, QLineEdit, QWidget, QListWidget, QTabWidget, QHBoxLayout,QMessageBox, QPushButton, QVBoxLayout, QRadioButton, QLabel, QButtonGroup, QSizePolicy, QComboBox,QSpacerItem, QGridLayout
|
|
2
|
-
from celldetective.gui.gui_utils import ThresholdLineEdit
|
|
2
|
+
from celldetective.gui.gui_utils import ThresholdLineEdit, QuickSliderLayout, center_window
|
|
3
3
|
from PyQt5.QtCore import Qt, QSize
|
|
4
4
|
from PyQt5.QtGui import QIntValidator
|
|
5
5
|
|
|
6
|
-
from superqt import QLabeledRangeSlider, QLabeledSlider, QLabeledDoubleRangeSlider, QSearchableComboBox
|
|
6
|
+
from superqt import QLabeledRangeSlider, QLabeledDoubleSlider, QLabeledSlider, QLabeledDoubleRangeSlider, QSearchableComboBox
|
|
7
7
|
|
|
8
8
|
from superqt.fonticon import icon
|
|
9
9
|
from fonticon_mdi6 import MDI6
|
|
10
10
|
from celldetective.utils import _extract_channel_indices_from_config
|
|
11
|
-
from celldetective.gui.viewers import ThresholdedStackVisualizer, CellEdgeVisualizer, StackVisualizer
|
|
11
|
+
from celldetective.gui.viewers import ThresholdedStackVisualizer, CellEdgeVisualizer, StackVisualizer, CellSizeViewer
|
|
12
12
|
from celldetective.gui import Styles
|
|
13
|
-
from celldetective.gui.gui_utils import QuickSliderLayout
|
|
14
13
|
from celldetective.preprocessing import correct_background_model, correct_background_model_free, estimate_background_per_condition
|
|
15
14
|
from functools import partial
|
|
16
15
|
from glob import glob
|
|
@@ -18,6 +17,239 @@ import os
|
|
|
18
17
|
import pandas as pd
|
|
19
18
|
import numpy as np
|
|
20
19
|
|
|
20
|
+
class StarDistParamsWidget(QWidget, Styles):
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
A widget to configure parameters for StarDist segmentation.
|
|
24
|
+
|
|
25
|
+
This widget allows the user to select specific imaging channels for segmentation and adjust
|
|
26
|
+
parameters for StarDist, a neural network-based image segmentation tool designed to segment
|
|
27
|
+
star-convex shapes (typically nuclei).
|
|
28
|
+
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
parent_window : QWidget, optional
|
|
32
|
+
The parent window hosting this widget (default is None).
|
|
33
|
+
model_name : str, optional
|
|
34
|
+
The name of the StarDist model being used, typically 'SD_versatile_fluo' for versatile
|
|
35
|
+
fluorescence or 'SD_versatile_he' for H&E-stained images (default is 'SD_versatile_fluo').
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def __init__(self, parent_window=None, model_name='SD_versatile_fluo', *args, **kwargs):
|
|
39
|
+
|
|
40
|
+
super().__init__(*args)
|
|
41
|
+
self.setWindowTitle('Channels')
|
|
42
|
+
self.parent_window = parent_window
|
|
43
|
+
self.model_name = model_name
|
|
44
|
+
|
|
45
|
+
# Setting up references to parent window attributes
|
|
46
|
+
if hasattr(self.parent_window.parent_window, 'locate_image'):
|
|
47
|
+
self.attr_parent = self.parent_window.parent_window
|
|
48
|
+
elif hasattr(self.parent_window.parent_window.parent_window, 'locate_image'):
|
|
49
|
+
self.attr_parent = self.parent_window.parent_window.parent_window
|
|
50
|
+
else:
|
|
51
|
+
self.attr_parent = self.parent_window.parent_window.parent_window.parent_window
|
|
52
|
+
|
|
53
|
+
# Set up layout and widgets
|
|
54
|
+
self.layout = QVBoxLayout()
|
|
55
|
+
self.populate_widgets()
|
|
56
|
+
self.setLayout(self.layout)
|
|
57
|
+
center_window(self)
|
|
58
|
+
|
|
59
|
+
def populate_widgets(self):
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
Populates the widget with channel selection comboboxes and a 'set' button to configure
|
|
63
|
+
the StarDist segmentation settings. Handles different models by adjusting the number of
|
|
64
|
+
available channels.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
# Initialize comboboxes based on the selected model
|
|
68
|
+
self.stardist_channel_cb = [QComboBox() for i in range(1)]
|
|
69
|
+
self.stardist_channel_template = ['live_nuclei_channel']
|
|
70
|
+
max_i = 1
|
|
71
|
+
|
|
72
|
+
# If the H&E model is selected, update the combobox configuration
|
|
73
|
+
if self.model_name=="SD_versatile_he":
|
|
74
|
+
self.stardist_channel_template = ["H&E_1","H&E_2","H&E_3"]
|
|
75
|
+
self.stardist_channel_cb = [QComboBox() for i in range(3)]
|
|
76
|
+
max_i = 3
|
|
77
|
+
|
|
78
|
+
# Populate the comboboxes with available channels from the experiment
|
|
79
|
+
for k in range(max_i):
|
|
80
|
+
hbox_channel = QHBoxLayout()
|
|
81
|
+
hbox_channel.addWidget(QLabel(f'channel {k+1}: '))
|
|
82
|
+
hbox_channel.addWidget(self.stardist_channel_cb[k])
|
|
83
|
+
if k==1:
|
|
84
|
+
self.stardist_channel_cb[k].addItems(list(self.attr_parent.exp_channels)+['None'])
|
|
85
|
+
else:
|
|
86
|
+
self.stardist_channel_cb[k].addItems(list(self.attr_parent.exp_channels))
|
|
87
|
+
|
|
88
|
+
# Set the default channel based on the template or fallback to the first option
|
|
89
|
+
idx = self.stardist_channel_cb[k].findText(self.stardist_channel_template[k])
|
|
90
|
+
if idx>0:
|
|
91
|
+
self.stardist_channel_cb[k].setCurrentIndex(idx)
|
|
92
|
+
else:
|
|
93
|
+
self.stardist_channel_cb[k].setCurrentIndex(0)
|
|
94
|
+
|
|
95
|
+
self.layout.addLayout(hbox_channel)
|
|
96
|
+
|
|
97
|
+
# Button to apply the StarDist settings
|
|
98
|
+
self.set_stardist_scale_btn = QPushButton('set')
|
|
99
|
+
self.set_stardist_scale_btn.setStyleSheet(self.button_style_sheet)
|
|
100
|
+
self.set_stardist_scale_btn.clicked.connect(self.parent_window.set_stardist_scale)
|
|
101
|
+
self.layout.addWidget(self.set_stardist_scale_btn)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class CellposeParamsWidget(QWidget, Styles):
|
|
105
|
+
|
|
106
|
+
"""
|
|
107
|
+
A widget to configure parameters for Cellpose segmentation, allowing users to set the cell diameter,
|
|
108
|
+
select imaging channels, and adjust flow and cell probability thresholds for cell detection.
|
|
109
|
+
|
|
110
|
+
This widget is designed for estimating cell diameters and configuring parameters for Cellpose,
|
|
111
|
+
a deep learning-based segmentation tool. It also provides functionality to preview the image stack with a scale bar.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
parent_window : QWidget, optional
|
|
116
|
+
The parent window that hosts the widget (default is None).
|
|
117
|
+
model_name : str, optional
|
|
118
|
+
The name of the Cellpose model being used, typically 'CP_cyto2' for cytoplasm or 'CP_nuclei' for nuclei segmentation
|
|
119
|
+
(default is 'CP_cyto2').
|
|
120
|
+
|
|
121
|
+
Notes
|
|
122
|
+
-----
|
|
123
|
+
- This widget assumes that the parent window or one of its ancestor windows has access to the experiment channels
|
|
124
|
+
and can locate the current image stack via `locate_image()`.
|
|
125
|
+
- This class integrates sliders for flow and cell probability thresholds, as well as a channel selection for running
|
|
126
|
+
Cellpose segmentation.
|
|
127
|
+
- The `view_current_stack_with_scale_bar()` method opens a new window where the user can visually inspect the
|
|
128
|
+
image stack with a superimposed scale bar, to better estimate the cell diameter.
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def __init__(self, parent_window=None, model_name='CP_cyto2', *args, **kwargs):
|
|
134
|
+
|
|
135
|
+
super().__init__(*args)
|
|
136
|
+
self.setWindowTitle('Estimate diameter')
|
|
137
|
+
self.parent_window = parent_window
|
|
138
|
+
self.model_name = model_name
|
|
139
|
+
|
|
140
|
+
# Setting up references to parent window attributes
|
|
141
|
+
if hasattr(self.parent_window.parent_window, 'locate_image'):
|
|
142
|
+
self.attr_parent = self.parent_window.parent_window
|
|
143
|
+
elif hasattr(self.parent_window.parent_window.parent_window, 'locate_image'):
|
|
144
|
+
self.attr_parent = self.parent_window.parent_window.parent_window
|
|
145
|
+
else:
|
|
146
|
+
self.attr_parent = self.parent_window.parent_window.parent_window.parent_window
|
|
147
|
+
|
|
148
|
+
# Layout and widgets setup
|
|
149
|
+
self.layout = QVBoxLayout()
|
|
150
|
+
self.populate_widgets()
|
|
151
|
+
self.setLayout(self.layout)
|
|
152
|
+
center_window(self)
|
|
153
|
+
|
|
154
|
+
def populate_widgets(self):
|
|
155
|
+
|
|
156
|
+
"""
|
|
157
|
+
Populates the widget with UI elements such as buttons, sliders, and comboboxes to allow configuration
|
|
158
|
+
of Cellpose segmentation parameters.
|
|
159
|
+
"""
|
|
160
|
+
|
|
161
|
+
# Button to view the current stack with a scale bar
|
|
162
|
+
self.view_diameter_btn = QPushButton()
|
|
163
|
+
self.view_diameter_btn.setStyleSheet(self.button_select_all)
|
|
164
|
+
self.view_diameter_btn.setIcon(icon(MDI6.image_check, color="black"))
|
|
165
|
+
self.view_diameter_btn.setToolTip("View stack.")
|
|
166
|
+
self.view_diameter_btn.setIconSize(QSize(20, 20))
|
|
167
|
+
self.view_diameter_btn.clicked.connect(self.view_current_stack_with_scale_bar)
|
|
168
|
+
|
|
169
|
+
# Line edit for entering cell diameter
|
|
170
|
+
self.diameter_le = ThresholdLineEdit(init_value=40, connected_buttons=[self.view_diameter_btn],placeholder='cell diameter in pixels', value_type='float')
|
|
171
|
+
|
|
172
|
+
# Comboboxes for selecting imaging channels
|
|
173
|
+
self.cellpose_channel_cb = [QComboBox() for i in range(2)]
|
|
174
|
+
self.cellpose_channel_template = ['brightfield_channel', 'live_nuclei_channel']
|
|
175
|
+
if self.model_name=="CP_nuclei":
|
|
176
|
+
self.cellpose_channel_template = ['live_nuclei_channel', 'None']
|
|
177
|
+
|
|
178
|
+
for k in range(2):
|
|
179
|
+
hbox_channel = QHBoxLayout()
|
|
180
|
+
hbox_channel.addWidget(QLabel(f'channel {k+1}: '))
|
|
181
|
+
hbox_channel.addWidget(self.cellpose_channel_cb[k])
|
|
182
|
+
if k==1:
|
|
183
|
+
self.cellpose_channel_cb[k].addItems(list(self.attr_parent.exp_channels)+['None'])
|
|
184
|
+
else:
|
|
185
|
+
self.cellpose_channel_cb[k].addItems(list(self.attr_parent.exp_channels))
|
|
186
|
+
idx = self.cellpose_channel_cb[k].findText(self.cellpose_channel_template[k])
|
|
187
|
+
if idx>0:
|
|
188
|
+
self.cellpose_channel_cb[k].setCurrentIndex(idx)
|
|
189
|
+
else:
|
|
190
|
+
self.cellpose_channel_cb[k].setCurrentIndex(0)
|
|
191
|
+
|
|
192
|
+
if k==1:
|
|
193
|
+
idx = self.cellpose_channel_cb[k].findText('None')
|
|
194
|
+
self.cellpose_channel_cb[k].setCurrentIndex(idx)
|
|
195
|
+
|
|
196
|
+
self.layout.addLayout(hbox_channel)
|
|
197
|
+
|
|
198
|
+
# Layout for diameter input and button
|
|
199
|
+
hbox = QHBoxLayout()
|
|
200
|
+
hbox.addWidget(QLabel('diameter [px]: '), 33)
|
|
201
|
+
hbox.addWidget(self.diameter_le, 61)
|
|
202
|
+
hbox.addWidget(self.view_diameter_btn)
|
|
203
|
+
self.layout.addLayout(hbox)
|
|
204
|
+
|
|
205
|
+
# Flow threshold slider
|
|
206
|
+
self.flow_slider = QLabeledDoubleSlider()
|
|
207
|
+
self.flow_slider.setOrientation(1)
|
|
208
|
+
self.flow_slider.setRange(-6,6)
|
|
209
|
+
self.flow_slider.setValue(0.4)
|
|
210
|
+
hbox = QHBoxLayout()
|
|
211
|
+
hbox.addWidget(QLabel('flow threshold: '), 33)
|
|
212
|
+
hbox.addWidget(self.flow_slider, 66)
|
|
213
|
+
self.layout.addLayout(hbox)
|
|
214
|
+
|
|
215
|
+
# Cell probability threshold slider
|
|
216
|
+
self.cellprob_slider = QLabeledDoubleSlider()
|
|
217
|
+
self.cellprob_slider.setOrientation(1)
|
|
218
|
+
self.cellprob_slider.setRange(-6,6)
|
|
219
|
+
self.cellprob_slider.setValue(0.)
|
|
220
|
+
hbox = QHBoxLayout()
|
|
221
|
+
hbox.addWidget(QLabel('cellprob threshold: '), 33)
|
|
222
|
+
hbox.addWidget(self.cellprob_slider, 66)
|
|
223
|
+
self.layout.addLayout(hbox)
|
|
224
|
+
|
|
225
|
+
# Button to set the scale for Cellpose segmentation
|
|
226
|
+
self.set_cellpose_scale_btn = QPushButton('set')
|
|
227
|
+
self.set_cellpose_scale_btn.setStyleSheet(self.button_style_sheet)
|
|
228
|
+
self.set_cellpose_scale_btn.clicked.connect(self.parent_window.set_cellpose_scale)
|
|
229
|
+
self.layout.addWidget(self.set_cellpose_scale_btn)
|
|
230
|
+
|
|
231
|
+
def view_current_stack_with_scale_bar(self):
|
|
232
|
+
|
|
233
|
+
"""
|
|
234
|
+
Displays the current image stack with a scale bar, allowing users to visually estimate cell diameters.
|
|
235
|
+
"""
|
|
236
|
+
|
|
237
|
+
self.attr_parent.locate_image()
|
|
238
|
+
if self.attr_parent.current_stack is not None:
|
|
239
|
+
self.viewer = CellSizeViewer(
|
|
240
|
+
initial_diameter = float(self.diameter_le.text().replace(',', '.')),
|
|
241
|
+
parent_le = self.diameter_le,
|
|
242
|
+
stack_path=self.attr_parent.current_stack,
|
|
243
|
+
window_title=f'Position {self.attr_parent.position_list.currentText()}',
|
|
244
|
+
frame_slider = True,
|
|
245
|
+
contrast_slider = True,
|
|
246
|
+
channel_cb = True,
|
|
247
|
+
channel_names = self.attr_parent.exp_channels,
|
|
248
|
+
n_channels = self.attr_parent.nbr_channels,
|
|
249
|
+
PxToUm = 1,
|
|
250
|
+
)
|
|
251
|
+
self.viewer.show()
|
|
252
|
+
|
|
21
253
|
class ChannelNormGenerator(QVBoxLayout, Styles):
|
|
22
254
|
|
|
23
255
|
"""Generator for list of channels"""
|
|
@@ -44,6 +276,8 @@ class ChannelNormGenerator(QVBoxLayout, Styles):
|
|
|
44
276
|
def generate_widgets(self):
|
|
45
277
|
|
|
46
278
|
self.channel_cbs = [QSearchableComboBox() for i in range(self.init_n_channels)]
|
|
279
|
+
self.channel_labels = [QLabel() for i in range(self.init_n_channels)]
|
|
280
|
+
|
|
47
281
|
self.normalization_mode_btns = [QPushButton('') for i in range(self.init_n_channels)]
|
|
48
282
|
self.normalization_mode = [True for i in range(self.init_n_channels)]
|
|
49
283
|
self.normalization_clip_btns = [QPushButton('') for i in range(self.init_n_channels)]
|
|
@@ -127,8 +361,10 @@ class ChannelNormGenerator(QVBoxLayout, Styles):
|
|
|
127
361
|
def add_channel(self):
|
|
128
362
|
|
|
129
363
|
self.channel_cbs.append(QSearchableComboBox())
|
|
364
|
+
self.channel_labels.append(QLabel())
|
|
130
365
|
self.channel_cbs[-1].addItems(self.channel_items)
|
|
131
366
|
self.channel_cbs[-1].currentIndexChanged.connect(self.check_valid_channels)
|
|
367
|
+
self.channel_labels[-1].setText(f'channel {len(self.channel_cbs)-1}: ')
|
|
132
368
|
|
|
133
369
|
self.normalization_mode_btns.append(QPushButton(''))
|
|
134
370
|
self.normalization_mode.append(True)
|
|
@@ -153,18 +389,21 @@ class ChannelNormGenerator(QVBoxLayout, Styles):
|
|
|
153
389
|
self.normalization_max_value_le.append(QLineEdit('99.99'))
|
|
154
390
|
|
|
155
391
|
ch_layout = QHBoxLayout()
|
|
156
|
-
ch_layout.addWidget(
|
|
392
|
+
ch_layout.addWidget(self.channel_labels[-1], 30)
|
|
157
393
|
ch_layout.addWidget(self.channel_cbs[-1], 70)
|
|
158
394
|
self.channels_vb.addLayout(ch_layout)
|
|
159
395
|
|
|
160
396
|
channel_norm_options_layout = QHBoxLayout()
|
|
161
|
-
channel_norm_options_layout.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
397
|
+
channel_norm_options_layout.addWidget(QLabel(''),30)
|
|
398
|
+
ch_norm_sublayout = QHBoxLayout()
|
|
399
|
+
ch_norm_sublayout.addWidget(self.normalization_min_value_lbl[-1])
|
|
400
|
+
ch_norm_sublayout.addWidget(self.normalization_min_value_le[-1])
|
|
401
|
+
ch_norm_sublayout.addWidget(self.normalization_max_value_lbl[-1])
|
|
402
|
+
ch_norm_sublayout.addWidget(self.normalization_max_value_le[-1])
|
|
403
|
+
ch_norm_sublayout.addWidget(self.normalization_clip_btns[-1])
|
|
404
|
+
ch_norm_sublayout.addWidget(self.normalization_mode_btns[-1])
|
|
405
|
+
channel_norm_options_layout.addLayout(ch_norm_sublayout, 70)
|
|
406
|
+
|
|
168
407
|
self.channels_vb.addLayout(channel_norm_options_layout)
|
|
169
408
|
|
|
170
409
|
|
|
@@ -175,20 +414,24 @@ class ChannelNormGenerator(QVBoxLayout, Styles):
|
|
|
175
414
|
for i in range(len(self.channel_cbs)):
|
|
176
415
|
|
|
177
416
|
ch_layout = QHBoxLayout()
|
|
178
|
-
|
|
417
|
+
self.channel_labels[i].setText(f'channel {i}: ')
|
|
418
|
+
ch_layout.addWidget(self.channel_labels[i], 30)
|
|
179
419
|
self.channel_cbs[i].addItems(self.channel_items)
|
|
180
420
|
self.channel_cbs[i].currentIndexChanged.connect(self.check_valid_channels)
|
|
181
421
|
ch_layout.addWidget(self.channel_cbs[i], 70)
|
|
182
422
|
self.channels_vb.addLayout(ch_layout)
|
|
183
423
|
|
|
184
424
|
channel_norm_options_layout = QHBoxLayout()
|
|
185
|
-
channel_norm_options_layout.setContentsMargins(130,0,0,0)
|
|
186
|
-
channel_norm_options_layout.addWidget(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
425
|
+
#channel_norm_options_layout.setContentsMargins(130,0,0,0)
|
|
426
|
+
channel_norm_options_layout.addWidget(QLabel(''),30)
|
|
427
|
+
ch_norm_sublayout = QHBoxLayout()
|
|
428
|
+
ch_norm_sublayout.addWidget(self.normalization_min_value_lbl[i])
|
|
429
|
+
ch_norm_sublayout.addWidget(self.normalization_min_value_le[i])
|
|
430
|
+
ch_norm_sublayout.addWidget(self.normalization_max_value_lbl[i])
|
|
431
|
+
ch_norm_sublayout.addWidget(self.normalization_max_value_le[i])
|
|
432
|
+
ch_norm_sublayout.addWidget(self.normalization_clip_btns[i])
|
|
433
|
+
ch_norm_sublayout.addWidget(self.normalization_mode_btns[i])
|
|
434
|
+
channel_norm_options_layout.addLayout(ch_norm_sublayout, 70)
|
|
192
435
|
self.channels_vb.addLayout(channel_norm_options_layout)
|
|
193
436
|
|
|
194
437
|
self.addLayout(self.channels_vb)
|
|
@@ -249,7 +492,7 @@ class ChannelNormGenerator(QVBoxLayout, Styles):
|
|
|
249
492
|
if np.all([cb.currentText()=='--' for cb in self.channel_cbs]):
|
|
250
493
|
self.parent_window.submit_btn.setEnabled(False)
|
|
251
494
|
|
|
252
|
-
if hasattr(self.parent_window, "spatial_calib_le"):
|
|
495
|
+
if hasattr(self.parent_window, "spatial_calib_le") and hasattr(self.parent_window, "submit_btn"):
|
|
253
496
|
if self.parent_window.spatial_calib_le.text()!='--':
|
|
254
497
|
self.parent_window.submit_btn.setEnabled(True)
|
|
255
498
|
elif hasattr(self.parent_window, "submit_btn"):
|
|
@@ -619,7 +862,6 @@ class ProtocolDesignerLayout(QVBoxLayout, Styles):
|
|
|
619
862
|
|
|
620
863
|
for k in range(len(self.tab_layouts)):
|
|
621
864
|
wg = QWidget()
|
|
622
|
-
print('almost there',self.channel_names)
|
|
623
865
|
self.tab_layouts[k].parent_window = self
|
|
624
866
|
wg.setLayout(self.tab_layouts[k])
|
|
625
867
|
self.tabs.addTab(wg, self.tab_names[k])
|
|
@@ -635,8 +877,11 @@ class ProtocolDesignerLayout(QVBoxLayout, Styles):
|
|
|
635
877
|
self.delete_protocol_btn.clicked.connect(self.remove_protocol_from_list)
|
|
636
878
|
|
|
637
879
|
def generate_layout(self):
|
|
638
|
-
|
|
639
|
-
self.
|
|
880
|
+
|
|
881
|
+
self.title_layout = QHBoxLayout()
|
|
882
|
+
self.title_layout.addWidget(self.title_lbl, 100, alignment=Qt.AlignCenter)
|
|
883
|
+
|
|
884
|
+
self.addLayout(self.title_layout)
|
|
640
885
|
self.addWidget(self.tabs)
|
|
641
886
|
|
|
642
887
|
list_header_layout = QHBoxLayout()
|
|
@@ -692,7 +937,6 @@ class BackgroundModelFreeCorrectionLayout(QGridLayout, Styles):
|
|
|
692
937
|
from PyQt5.QtWidgets import QSlider
|
|
693
938
|
from superqt import QRangeSlider
|
|
694
939
|
self.frame_range_slider = QLabeledRangeSlider(parent=None)
|
|
695
|
-
print('here ok')
|
|
696
940
|
|
|
697
941
|
self.timeseries_rb.toggled.connect(self.activate_time_range)
|
|
698
942
|
self.tiles_rb.toggled.connect(self.activate_time_range)
|
|
@@ -1,43 +1,33 @@
|
|
|
1
|
-
import math
|
|
2
1
|
|
|
3
|
-
import skimage
|
|
4
2
|
from PyQt5.QtWidgets import QMainWindow, QApplication, QMessageBox, QScrollArea, QComboBox, QFrame, QCheckBox, \
|
|
5
|
-
|
|
6
|
-
QRadioButton, QButtonGroup, QSizePolicy, QListWidget, QDialog
|
|
3
|
+
QGridLayout, QLineEdit, QVBoxLayout, QWidget, QLabel, QHBoxLayout, QPushButton
|
|
7
4
|
from PyQt5.QtCore import Qt, QSize
|
|
8
5
|
from PyQt5.QtGui import QIcon, QDoubleValidator, QIntValidator
|
|
9
|
-
from matplotlib.patches import Circle
|
|
10
|
-
from scipy import ndimage
|
|
11
|
-
from skimage.draw import disk
|
|
12
|
-
from skimage.morphology import disk
|
|
13
6
|
|
|
14
|
-
from celldetective.filters import std_filter, gauss_filter
|
|
15
7
|
from celldetective.gui.gui_utils import center_window, FeatureChoice, ListWidget, QHSeperationLine, FigureCanvas, \
|
|
16
|
-
GeometryChoice, OperationChoice
|
|
17
|
-
from superqt import
|
|
8
|
+
GeometryChoice, OperationChoice
|
|
9
|
+
from superqt import QLabeledDoubleSlider
|
|
18
10
|
from superqt.fonticon import icon
|
|
19
11
|
from fonticon_mdi6 import MDI6
|
|
20
12
|
|
|
21
|
-
from celldetective.gui.thresholds_gui import
|
|
13
|
+
from celldetective.gui.thresholds_gui import ThresholdSpot
|
|
22
14
|
from celldetective.utils import extract_experiment_channels, get_software_location
|
|
23
|
-
from celldetective.io import
|
|
24
|
-
from celldetective.measure import compute_haralick_features
|
|
15
|
+
from celldetective.io import load_frames, auto_load_number_of_frames
|
|
16
|
+
from celldetective.measure import compute_haralick_features
|
|
25
17
|
import numpy as np
|
|
26
18
|
from tifffile import imread
|
|
27
19
|
import json
|
|
28
|
-
from shutil import copyfile
|
|
29
20
|
import os
|
|
30
21
|
import matplotlib.pyplot as plt
|
|
31
22
|
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
|
32
23
|
from glob import glob
|
|
33
24
|
from natsort import natsorted
|
|
34
25
|
from tifffile import imread
|
|
35
|
-
from pathlib import Path
|
|
26
|
+
from pathlib import Path
|
|
36
27
|
import gc
|
|
37
|
-
from stardist import fill_label_holes
|
|
38
28
|
|
|
39
29
|
from celldetective.gui.viewers import CellEdgeVisualizer
|
|
40
|
-
from celldetective.gui.layouts import ProtocolDesignerLayout, BackgroundFitCorrectionLayout, LocalCorrectionLayout
|
|
30
|
+
from celldetective.gui.layouts import ProtocolDesignerLayout, BackgroundFitCorrectionLayout, LocalCorrectionLayout
|
|
41
31
|
from celldetective.gui.gui_utils import ThresholdLineEdit
|
|
42
32
|
from celldetective.gui import Styles
|
|
43
33
|
|
|
@@ -217,7 +207,7 @@ class ConfigMeasurements(QMainWindow, Styles):
|
|
|
217
207
|
radii_layout.addWidget(self.add_radius_btn, 5)
|
|
218
208
|
layout.addLayout(radii_layout)
|
|
219
209
|
|
|
220
|
-
self.radii_list = ListWidget(
|
|
210
|
+
self.radii_list = ListWidget(GeometryChoice, initial_features=["10"], dtype=int)
|
|
221
211
|
layout.addWidget(self.radii_list)
|
|
222
212
|
|
|
223
213
|
self.del_radius_btn.clicked.connect(self.radii_list.removeSel)
|
|
@@ -244,7 +234,7 @@ class ConfigMeasurements(QMainWindow, Styles):
|
|
|
244
234
|
operation_layout.addWidget(self.add_op_btn, 5)
|
|
245
235
|
layout.addLayout(operation_layout)
|
|
246
236
|
|
|
247
|
-
self.operations_list = ListWidget(
|
|
237
|
+
self.operations_list = ListWidget(OperationChoice, initial_features=["mean"])
|
|
248
238
|
layout.addWidget(self.operations_list)
|
|
249
239
|
|
|
250
240
|
self.del_op_btn.clicked.connect(self.operations_list.removeSel)
|
|
@@ -272,7 +262,7 @@ class ConfigMeasurements(QMainWindow, Styles):
|
|
|
272
262
|
self.add_feature_btn.setToolTip("Add feature")
|
|
273
263
|
self.add_feature_btn.setIconSize(QSize(20, 20))
|
|
274
264
|
|
|
275
|
-
self.features_list = ListWidget(
|
|
265
|
+
self.features_list = ListWidget(FeatureChoice, initial_features=['area', 'intensity_mean', ])
|
|
276
266
|
|
|
277
267
|
self.del_feature_btn.clicked.connect(self.features_list.removeSel)
|
|
278
268
|
self.add_feature_btn.clicked.connect(self.features_list.addItem)
|
|
@@ -315,7 +305,7 @@ class ConfigMeasurements(QMainWindow, Styles):
|
|
|
315
305
|
|
|
316
306
|
layout.addLayout(contour_layout)
|
|
317
307
|
|
|
318
|
-
self.contours_list = ListWidget(
|
|
308
|
+
self.contours_list = ListWidget(GeometryChoice, initial_features=[], dtype=int)
|
|
319
309
|
layout.addWidget(self.contours_list)
|
|
320
310
|
|
|
321
311
|
self.del_contour_btn.clicked.connect(self.contours_list.removeSel)
|
|
@@ -797,7 +787,8 @@ class ConfigMeasurements(QMainWindow, Styles):
|
|
|
797
787
|
self.fig, self.ax = plt.subplots(1, 1, figsize=(4, 3))
|
|
798
788
|
self.hist_window = FigureCanvas(self.fig, title="Haralick: control digitized histogram")
|
|
799
789
|
self.ax.clear()
|
|
800
|
-
|
|
790
|
+
flat = norm_img.flatten()
|
|
791
|
+
self.ax.hist(flat[flat==flat], bins=self.haralick_options['n_intensity_bins'])
|
|
801
792
|
self.ax.set_xlabel('gray level value')
|
|
802
793
|
self.ax.set_ylabel('#')
|
|
803
794
|
plt.tight_layout()
|
|
@@ -1,25 +1,13 @@
|
|
|
1
|
-
from PyQt5.QtWidgets import
|
|
1
|
+
from PyQt5.QtWidgets import QApplication, QComboBox, QFrame, QCheckBox, QVBoxLayout, QWidget, QLabel, QHBoxLayout, QPushButton
|
|
2
2
|
from PyQt5.QtCore import Qt, QSize
|
|
3
3
|
from PyQt5.QtGui import QIcon
|
|
4
|
-
from celldetective.gui.gui_utils import center_window,
|
|
5
|
-
from superqt import QLabeledDoubleRangeSlider, QLabeledDoubleSlider,QLabeledSlider
|
|
4
|
+
from celldetective.gui.gui_utils import center_window, ListWidget, DistanceChoice
|
|
6
5
|
from superqt.fonticon import icon
|
|
7
6
|
from fonticon_mdi6 import MDI6
|
|
8
|
-
from celldetective.utils import extract_experiment_channels, get_software_location
|
|
9
|
-
from celldetective.io import interpret_tracking_configuration, load_frames, auto_load_number_of_frames
|
|
10
|
-
from celldetective.measure import compute_haralick_features, contour_of_instance_segmentation
|
|
11
7
|
import numpy as np
|
|
12
|
-
from tifffile import imread
|
|
13
8
|
import json
|
|
14
|
-
from shutil import copyfile
|
|
15
9
|
import os
|
|
16
|
-
import matplotlib.pyplot as plt
|
|
17
|
-
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
|
18
10
|
from glob import glob
|
|
19
|
-
from natsort import natsorted
|
|
20
|
-
from tifffile import imread
|
|
21
|
-
from pathlib import Path, PurePath
|
|
22
|
-
import gc
|
|
23
11
|
import pandas as pd
|
|
24
12
|
from celldetective.gui.viewers import CellSizeViewer, CellEdgeVisualizer
|
|
25
13
|
from celldetective.gui import Styles
|
|
@@ -152,7 +140,7 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
152
140
|
|
|
153
141
|
layout.addLayout(list_header_layout)
|
|
154
142
|
|
|
155
|
-
self.measurements_list = ListWidget(
|
|
143
|
+
self.measurements_list = ListWidget(DistanceChoice, initial_features=["60"], dtype=int)
|
|
156
144
|
self.measurements_list.setToolTip('Neighborhoods to compute.')
|
|
157
145
|
layout.addWidget(self.measurements_list)
|
|
158
146
|
|
|
@@ -230,11 +218,12 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
230
218
|
|
|
231
219
|
status_layout = QHBoxLayout()
|
|
232
220
|
|
|
233
|
-
status_layout.addWidget(QLabel('status: '), 30)
|
|
221
|
+
#status_layout.addWidget(QLabel('status: '), 30)
|
|
234
222
|
|
|
235
223
|
status_sublayout = QHBoxLayout()
|
|
236
224
|
self.reference_population_status_cb = QComboBox()
|
|
237
225
|
self.reference_population_status_cb.setToolTip('Status of the reference population.')
|
|
226
|
+
self.reference_population_status_cb.hide()
|
|
238
227
|
status_sublayout.addWidget(self.reference_population_status_cb,95)
|
|
239
228
|
|
|
240
229
|
self.reference_switch_status_btn = QPushButton("")
|
|
@@ -243,6 +232,7 @@ class ConfigNeighborhoods(QWidget, Styles):
|
|
|
243
232
|
self.reference_switch_status_btn.setIconSize(QSize(20, 20))
|
|
244
233
|
self.reference_switch_status_btn.clicked.connect(self.switch_not_reference)
|
|
245
234
|
self.reference_switch_status_btn.setToolTip('Invert status values.')
|
|
235
|
+
self.reference_switch_status_btn.hide()
|
|
246
236
|
|
|
247
237
|
status_sublayout.addWidget(self.reference_switch_status_btn, 5)
|
|
248
238
|
|
|
@@ -1,40 +1,27 @@
|
|
|
1
|
-
from PyQt5.QtWidgets import
|
|
2
|
-
QCheckBox,
|
|
3
|
-
QRadioButton,
|
|
4
|
-
from PyQt5.QtCore import Qt,
|
|
1
|
+
from PyQt5.QtWidgets import QMessageBox, QScrollArea, QButtonGroup, QComboBox, \
|
|
2
|
+
QCheckBox, QVBoxLayout, QWidget, QLabel, QHBoxLayout, QPushButton, \
|
|
3
|
+
QRadioButton, QSizePolicy
|
|
4
|
+
from PyQt5.QtCore import Qt, QRect
|
|
5
5
|
from PyQt5.QtGui import QIcon, QDoubleValidator
|
|
6
|
-
from sklearn.preprocessing import MinMaxScaler
|
|
7
6
|
|
|
8
7
|
from celldetective.gui import Styles
|
|
9
|
-
from celldetective.gui.gui_utils import center_window,
|
|
10
|
-
|
|
11
|
-
from superqt import QLabeledSlider
|
|
8
|
+
from celldetective.gui.gui_utils import center_window, FigureCanvas
|
|
9
|
+
|
|
12
10
|
from superqt.fonticon import icon
|
|
13
11
|
from fonticon_mdi6 import MDI6
|
|
14
|
-
from celldetective.utils import
|
|
15
|
-
from celldetective.io import
|
|
16
|
-
load_experiment_tables, get_experiment_antibodies, get_experiment_cell_types, get_experiment_concentrations, \
|
|
12
|
+
from celldetective.utils import get_software_location, _extract_labels_from_config
|
|
13
|
+
from celldetective.io import load_experiment_tables, get_experiment_antibodies, get_experiment_cell_types, get_experiment_concentrations, \
|
|
17
14
|
get_positions_in_well, get_experiment_wells
|
|
18
|
-
from celldetective.
|
|
19
|
-
from celldetective.signals import columnwise_mean, mean_signal
|
|
15
|
+
from celldetective.signals import mean_signal
|
|
20
16
|
import numpy as np
|
|
21
|
-
from tifffile import imread
|
|
22
17
|
import json
|
|
23
|
-
from shutil import copyfile
|
|
24
18
|
import os
|
|
25
19
|
import matplotlib.pyplot as plt
|
|
26
20
|
|
|
27
21
|
plt.rcParams['svg.fonttype'] = 'none'
|
|
28
|
-
from mpl_toolkits.axes_grid1 import make_axes_locatable
|
|
29
22
|
from glob import glob
|
|
30
|
-
from natsort import natsorted
|
|
31
|
-
from tifffile import imread
|
|
32
|
-
from pathlib import Path, PurePath
|
|
33
|
-
import gc
|
|
34
23
|
import pandas as pd
|
|
35
|
-
from
|
|
36
|
-
from lifelines import KaplanMeierFitter
|
|
37
|
-
from matplotlib.cm import viridis, tab10
|
|
24
|
+
from matplotlib.cm import tab10
|
|
38
25
|
import math
|
|
39
26
|
import seaborn as sns
|
|
40
27
|
|