celldetective 1.0.2.post1__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- celldetective/__main__.py +7 -21
- celldetective/events.py +2 -44
- celldetective/extra_properties.py +62 -52
- celldetective/filters.py +4 -5
- celldetective/gui/__init__.py +1 -1
- celldetective/gui/analyze_block.py +37 -10
- celldetective/gui/btrack_options.py +24 -23
- celldetective/gui/classifier_widget.py +62 -19
- celldetective/gui/configure_new_exp.py +32 -35
- celldetective/gui/control_panel.py +120 -81
- celldetective/gui/gui_utils.py +674 -396
- celldetective/gui/json_readers.py +7 -6
- celldetective/gui/layouts.py +756 -0
- celldetective/gui/measurement_options.py +98 -513
- celldetective/gui/neighborhood_options.py +322 -270
- celldetective/gui/plot_measurements.py +1114 -0
- celldetective/gui/plot_signals_ui.py +21 -20
- celldetective/gui/process_block.py +449 -169
- celldetective/gui/retrain_segmentation_model_options.py +27 -26
- celldetective/gui/retrain_signal_model_options.py +25 -24
- celldetective/gui/seg_model_loader.py +31 -27
- celldetective/gui/signal_annotator.py +2326 -2295
- celldetective/gui/signal_annotator_options.py +18 -16
- celldetective/gui/styles.py +16 -1
- celldetective/gui/survival_ui.py +67 -39
- celldetective/gui/tableUI.py +337 -48
- celldetective/gui/thresholds_gui.py +75 -71
- celldetective/gui/viewers.py +743 -0
- celldetective/io.py +247 -27
- celldetective/measure.py +43 -263
- celldetective/models/segmentation_effectors/primNK_cfse/config_input.json +29 -0
- celldetective/models/segmentation_effectors/primNK_cfse/cp-cfse-transfer +0 -0
- celldetective/models/segmentation_effectors/primNK_cfse/training_instructions.json +37 -0
- celldetective/neighborhood.py +498 -27
- celldetective/preprocessing.py +1023 -0
- celldetective/scripts/analyze_signals.py +7 -0
- celldetective/scripts/measure_cells.py +12 -0
- celldetective/scripts/segment_cells.py +20 -4
- celldetective/scripts/track_cells.py +11 -0
- celldetective/scripts/train_segmentation_model.py +35 -34
- celldetective/segmentation.py +14 -9
- celldetective/signals.py +234 -329
- celldetective/tracking.py +2 -2
- celldetective/utils.py +602 -49
- celldetective-1.1.1.dist-info/METADATA +305 -0
- celldetective-1.1.1.dist-info/RECORD +84 -0
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/top_level.txt +1 -0
- tests/__init__.py +0 -0
- tests/test_events.py +28 -0
- tests/test_filters.py +24 -0
- tests/test_io.py +70 -0
- tests/test_measure.py +141 -0
- tests/test_neighborhood.py +70 -0
- tests/test_preprocessing.py +37 -0
- tests/test_segmentation.py +93 -0
- tests/test_signals.py +135 -0
- tests/test_tracking.py +164 -0
- tests/test_utils.py +118 -0
- celldetective-1.0.2.post1.dist-info/METADATA +0 -221
- celldetective-1.0.2.post1.dist-info/RECORD +0 -66
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/LICENSE +0 -0
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/WHEEL +0 -0
- {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/entry_points.txt +0 -0
|
@@ -21,8 +21,7 @@ from fonticon_mdi6 import MDI6
|
|
|
21
21
|
from celldetective.gui.thresholds_gui import ThresholdNormalisation, ThresholdSpot
|
|
22
22
|
from celldetective.utils import extract_experiment_channels, get_software_location
|
|
23
23
|
from celldetective.io import interpret_tracking_configuration, load_frames, auto_load_number_of_frames
|
|
24
|
-
from celldetective.measure import compute_haralick_features, contour_of_instance_segmentation,
|
|
25
|
-
field_normalisation, normalise_by_cell
|
|
24
|
+
from celldetective.measure import compute_haralick_features, contour_of_instance_segmentation, normalise_by_cell
|
|
26
25
|
import numpy as np
|
|
27
26
|
from tifffile import imread
|
|
28
27
|
import json
|
|
@@ -37,28 +36,33 @@ from pathlib import Path, PurePath
|
|
|
37
36
|
import gc
|
|
38
37
|
from stardist import fill_label_holes
|
|
39
38
|
|
|
39
|
+
from celldetective.gui.viewers import CellEdgeVisualizer
|
|
40
|
+
from celldetective.gui.layouts import ProtocolDesignerLayout, BackgroundFitCorrectionLayout, LocalCorrectionLayout, OperationLayout
|
|
41
|
+
from celldetective.gui.gui_utils import ThresholdLineEdit
|
|
42
|
+
from celldetective.gui import Styles
|
|
40
43
|
|
|
41
|
-
class ConfigMeasurements(QMainWindow):
|
|
44
|
+
class ConfigMeasurements(QMainWindow, Styles):
|
|
42
45
|
"""
|
|
43
46
|
UI to set measurement instructions.
|
|
44
47
|
|
|
45
48
|
"""
|
|
46
49
|
|
|
47
|
-
def __init__(self,
|
|
50
|
+
def __init__(self, parent_window=None):
|
|
48
51
|
|
|
49
52
|
super().__init__()
|
|
50
|
-
|
|
53
|
+
|
|
54
|
+
self.parent_window = parent_window
|
|
51
55
|
self.setWindowTitle("Configure measurements")
|
|
52
56
|
self.setWindowIcon(QIcon(os.sep.join(['celldetective', 'icons', 'mexican-hat.png'])))
|
|
53
|
-
self.mode = self.
|
|
54
|
-
self.exp_dir = self.
|
|
57
|
+
self.mode = self.parent_window.mode
|
|
58
|
+
self.exp_dir = self.parent_window.exp_dir
|
|
55
59
|
self.background_correction = []
|
|
56
60
|
if self.mode == "targets":
|
|
57
61
|
self.config_name = "btrack_config_targets.json"
|
|
58
|
-
self.measure_instructions_path = self.
|
|
62
|
+
self.measure_instructions_path = self.parent_window.exp_dir + "configs/measurement_instructions_targets.json"
|
|
59
63
|
elif self.mode == "effectors":
|
|
60
64
|
self.config_name = "btrack_config_effectors.json"
|
|
61
|
-
self.measure_instructions_path = self.
|
|
65
|
+
self.measure_instructions_path = self.parent_window.exp_dir + "configs/measurement_instructions_effectors.json"
|
|
62
66
|
self.soft_path = get_software_location()
|
|
63
67
|
self.clear_previous = False
|
|
64
68
|
|
|
@@ -68,7 +72,7 @@ class ConfigMeasurements(QMainWindow):
|
|
|
68
72
|
self.channel_names = np.array(self.channel_names)
|
|
69
73
|
self.channels = np.array(self.channels)
|
|
70
74
|
|
|
71
|
-
self.screen_height = self.
|
|
75
|
+
self.screen_height = self.parent_window.parent_window.parent_window.screen_height
|
|
72
76
|
center_window(self)
|
|
73
77
|
|
|
74
78
|
self.onlyFloat = QDoubleValidator()
|
|
@@ -96,7 +100,20 @@ class ConfigMeasurements(QMainWindow):
|
|
|
96
100
|
|
|
97
101
|
self.normalisation_frame = QFrame()
|
|
98
102
|
self.normalisation_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
|
|
99
|
-
|
|
103
|
+
|
|
104
|
+
self.local_correction_layout = LocalCorrectionLayout(self)
|
|
105
|
+
self.fit_correction_layout = BackgroundFitCorrectionLayout(self)
|
|
106
|
+
|
|
107
|
+
self.protocol_layout = ProtocolDesignerLayout(parent_window=self,
|
|
108
|
+
tab_layouts=[ self.local_correction_layout, self.fit_correction_layout],
|
|
109
|
+
tab_names=['Local', 'Fit'],
|
|
110
|
+
title='BACKGROUND CORRECTION',
|
|
111
|
+
list_title='Corrections to apply:'
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
self.normalisation_frame.setLayout(self.protocol_layout)
|
|
115
|
+
|
|
116
|
+
#self.populate_normalisation_tabs()
|
|
100
117
|
main_layout.addWidget(self.normalisation_frame)
|
|
101
118
|
|
|
102
119
|
# first frame for FEATURES
|
|
@@ -120,7 +137,7 @@ class ConfigMeasurements(QMainWindow):
|
|
|
120
137
|
main_layout.addWidget(self.clear_previous_btn)
|
|
121
138
|
|
|
122
139
|
self.submit_btn = QPushButton('Save')
|
|
123
|
-
self.submit_btn.setStyleSheet(self.
|
|
140
|
+
self.submit_btn.setStyleSheet(self.button_style_sheet)
|
|
124
141
|
self.submit_btn.clicked.connect(self.write_instructions)
|
|
125
142
|
main_layout.addWidget(self.submit_btn)
|
|
126
143
|
|
|
@@ -186,14 +203,14 @@ class ConfigMeasurements(QMainWindow):
|
|
|
186
203
|
radii_layout.addWidget(self.radii_lbl, 90)
|
|
187
204
|
|
|
188
205
|
self.del_radius_btn = QPushButton("")
|
|
189
|
-
self.del_radius_btn.setStyleSheet(self.
|
|
206
|
+
self.del_radius_btn.setStyleSheet(self.button_select_all)
|
|
190
207
|
self.del_radius_btn.setIcon(icon(MDI6.trash_can, color="black"))
|
|
191
208
|
self.del_radius_btn.setToolTip("Remove radius")
|
|
192
209
|
self.del_radius_btn.setIconSize(QSize(20, 20))
|
|
193
210
|
radii_layout.addWidget(self.del_radius_btn, 5)
|
|
194
211
|
|
|
195
212
|
self.add_radius_btn = QPushButton("")
|
|
196
|
-
self.add_radius_btn.setStyleSheet(self.
|
|
213
|
+
self.add_radius_btn.setStyleSheet(self.button_select_all)
|
|
197
214
|
self.add_radius_btn.setIcon(icon(MDI6.plus, color="black"))
|
|
198
215
|
self.add_radius_btn.setToolTip("Add radius")
|
|
199
216
|
self.add_radius_btn.setIconSize(QSize(20, 20))
|
|
@@ -213,14 +230,14 @@ class ConfigMeasurements(QMainWindow):
|
|
|
213
230
|
operation_layout.addWidget(self.op_lbl, 90)
|
|
214
231
|
|
|
215
232
|
self.del_op_btn = QPushButton("")
|
|
216
|
-
self.del_op_btn.setStyleSheet(self.
|
|
233
|
+
self.del_op_btn.setStyleSheet(self.button_select_all)
|
|
217
234
|
self.del_op_btn.setIcon(icon(MDI6.trash_can, color="black"))
|
|
218
235
|
self.del_op_btn.setToolTip("Remove operation")
|
|
219
236
|
self.del_op_btn.setIconSize(QSize(20, 20))
|
|
220
237
|
operation_layout.addWidget(self.del_op_btn, 5)
|
|
221
238
|
|
|
222
239
|
self.add_op_btn = QPushButton("")
|
|
223
|
-
self.add_op_btn.setStyleSheet(self.
|
|
240
|
+
self.add_op_btn.setStyleSheet(self.button_select_all)
|
|
224
241
|
self.add_op_btn.setIcon(icon(MDI6.plus, color="black"))
|
|
225
242
|
self.add_op_btn.setToolTip("Add operation")
|
|
226
243
|
self.add_op_btn.setIconSize(QSize(20, 20))
|
|
@@ -244,13 +261,13 @@ class ConfigMeasurements(QMainWindow):
|
|
|
244
261
|
|
|
245
262
|
self.feature_lbl = QLabel("Add features:")
|
|
246
263
|
self.del_feature_btn = QPushButton("")
|
|
247
|
-
self.del_feature_btn.setStyleSheet(self.
|
|
264
|
+
self.del_feature_btn.setStyleSheet(self.button_select_all)
|
|
248
265
|
self.del_feature_btn.setIcon(icon(MDI6.trash_can, color="black"))
|
|
249
266
|
self.del_feature_btn.setToolTip("Remove feature")
|
|
250
267
|
self.del_feature_btn.setIconSize(QSize(20, 20))
|
|
251
268
|
|
|
252
269
|
self.add_feature_btn = QPushButton("")
|
|
253
|
-
self.add_feature_btn.setStyleSheet(self.
|
|
270
|
+
self.add_feature_btn.setStyleSheet(self.button_select_all)
|
|
254
271
|
self.add_feature_btn.setIcon(icon(MDI6.filter_plus, color="black"))
|
|
255
272
|
self.add_feature_btn.setToolTip("Add feature")
|
|
256
273
|
self.add_feature_btn.setIconSize(QSize(20, 20))
|
|
@@ -276,22 +293,22 @@ class ConfigMeasurements(QMainWindow):
|
|
|
276
293
|
contour_layout.addWidget(self.border_dist_lbl, 90)
|
|
277
294
|
|
|
278
295
|
self.del_contour_btn = QPushButton("")
|
|
279
|
-
self.del_contour_btn.setStyleSheet(self.
|
|
296
|
+
self.del_contour_btn.setStyleSheet(self.button_select_all)
|
|
280
297
|
self.del_contour_btn.setIcon(icon(MDI6.trash_can, color="black"))
|
|
281
298
|
self.del_contour_btn.setToolTip("Remove distance")
|
|
282
299
|
self.del_contour_btn.setIconSize(QSize(20, 20))
|
|
283
300
|
contour_layout.addWidget(self.del_contour_btn, 5)
|
|
284
301
|
|
|
285
302
|
self.add_contour_btn = QPushButton("")
|
|
286
|
-
self.add_contour_btn.setStyleSheet(self.
|
|
303
|
+
self.add_contour_btn.setStyleSheet(self.button_select_all)
|
|
287
304
|
self.add_contour_btn.setIcon(icon(MDI6.plus, color="black"))
|
|
288
305
|
self.add_contour_btn.setToolTip("Add distance")
|
|
289
306
|
self.add_contour_btn.setIconSize(QSize(20, 20))
|
|
290
307
|
contour_layout.addWidget(self.add_contour_btn, 5)
|
|
291
308
|
|
|
292
309
|
self.view_contour_btn = QPushButton("")
|
|
293
|
-
self.view_contour_btn.setStyleSheet(self.
|
|
294
|
-
self.view_contour_btn.setIcon(icon(MDI6.
|
|
310
|
+
self.view_contour_btn.setStyleSheet(self.button_select_all)
|
|
311
|
+
self.view_contour_btn.setIcon(icon(MDI6.eye_plus_outline, color="black"))
|
|
295
312
|
self.view_contour_btn.setToolTip("View contour")
|
|
296
313
|
self.view_contour_btn.setIconSize(QSize(20, 20))
|
|
297
314
|
contour_layout.addWidget(self.view_contour_btn, 5)
|
|
@@ -354,7 +371,7 @@ class ConfigMeasurements(QMainWindow):
|
|
|
354
371
|
self.haralick_percentile_min_le = QLineEdit('0.01')
|
|
355
372
|
self.haralick_percentile_max_le = QLineEdit('99.9')
|
|
356
373
|
self.haralick_normalization_mode_btn = QPushButton()
|
|
357
|
-
self.haralick_normalization_mode_btn.setStyleSheet(self.
|
|
374
|
+
self.haralick_normalization_mode_btn.setStyleSheet(self.button_select_all)
|
|
358
375
|
self.haralick_normalization_mode_btn.setIcon(icon(MDI6.percent_circle, color="black"))
|
|
359
376
|
self.haralick_normalization_mode_btn.setIconSize(QSize(20, 20))
|
|
360
377
|
self.haralick_normalization_mode_btn.setToolTip("Switch to absolute normalization values.")
|
|
@@ -371,12 +388,12 @@ class ConfigMeasurements(QMainWindow):
|
|
|
371
388
|
self.haralick_hist_btn = QPushButton()
|
|
372
389
|
self.haralick_hist_btn.clicked.connect(self.control_haralick_intensity_histogram)
|
|
373
390
|
self.haralick_hist_btn.setIcon(icon(MDI6.poll, color="k"))
|
|
374
|
-
self.haralick_hist_btn.setStyleSheet(self.
|
|
391
|
+
self.haralick_hist_btn.setStyleSheet(self.button_select_all)
|
|
375
392
|
|
|
376
393
|
self.haralick_digit_btn = QPushButton()
|
|
377
394
|
self.haralick_digit_btn.clicked.connect(self.control_haralick_digitalization)
|
|
378
395
|
self.haralick_digit_btn.setIcon(icon(MDI6.image_check, color="k"))
|
|
379
|
-
self.haralick_digit_btn.setStyleSheet(self.
|
|
396
|
+
self.haralick_digit_btn.setStyleSheet(self.button_select_all)
|
|
380
397
|
|
|
381
398
|
self.haralick_layout = QVBoxLayout()
|
|
382
399
|
self.haralick_layout.setContentsMargins(20, 20, 20, 20)
|
|
@@ -492,7 +509,7 @@ class ConfigMeasurements(QMainWindow):
|
|
|
492
509
|
|
|
493
510
|
print('Writing instructions...')
|
|
494
511
|
measurement_options = {}
|
|
495
|
-
background_correction = self.
|
|
512
|
+
background_correction = self.protocol_layout.protocols
|
|
496
513
|
if not background_correction:
|
|
497
514
|
background_correction = None
|
|
498
515
|
measurement_options.update({'background_correction': background_correction})
|
|
@@ -581,18 +598,20 @@ class ConfigMeasurements(QMainWindow):
|
|
|
581
598
|
measurement_instructions = json.load(f)
|
|
582
599
|
print(measurement_instructions)
|
|
583
600
|
if 'background_correction' in measurement_instructions:
|
|
584
|
-
self.
|
|
585
|
-
if
|
|
586
|
-
self.
|
|
587
|
-
|
|
601
|
+
self.protocol_layout.protocols = measurement_instructions['background_correction']
|
|
602
|
+
if self.protocol_layout.protocols is None:
|
|
603
|
+
self.protocol_layout.protocols = []
|
|
604
|
+
if (self.protocol_layout.protocols is not None) and len(self.protocol_layout.protocols) > 0:
|
|
605
|
+
self.protocol_layout.protocol_list.clear()
|
|
606
|
+
for norm_params in self.protocol_layout.protocols:
|
|
588
607
|
normalisation_description = ""
|
|
589
608
|
for index, (key, value) in enumerate(norm_params.items()):
|
|
590
609
|
if index > 0:
|
|
591
610
|
normalisation_description += ", "
|
|
592
611
|
normalisation_description += str(key) + " : " + str(value)
|
|
593
|
-
self.
|
|
612
|
+
self.protocol_layout.protocol_list.addItem(normalisation_description)
|
|
594
613
|
else:
|
|
595
|
-
self.
|
|
614
|
+
self.protocol_layout.protocol_list.clear()
|
|
596
615
|
if 'features' in measurement_instructions:
|
|
597
616
|
features = measurement_instructions['features']
|
|
598
617
|
if (features is not None) and len(features) > 0:
|
|
@@ -702,30 +721,32 @@ class ConfigMeasurements(QMainWindow):
|
|
|
702
721
|
Load the first frame of the first movie found in the experiment folder as a sample.
|
|
703
722
|
"""
|
|
704
723
|
|
|
705
|
-
movies = glob(self.
|
|
706
|
-
|
|
724
|
+
movies = glob(self.parent_window.parent_window.pos + os.sep.join(['movie', f"{self.parent_window.movie_prefix}*.tif"]))
|
|
725
|
+
|
|
707
726
|
if len(movies) == 0:
|
|
708
727
|
msgBox = QMessageBox()
|
|
709
728
|
msgBox.setIcon(QMessageBox.Warning)
|
|
710
|
-
msgBox.setText("
|
|
729
|
+
msgBox.setText("Please select a position containing a movie...")
|
|
711
730
|
msgBox.setWindowTitle("Warning")
|
|
712
731
|
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
713
732
|
returnValue = msgBox.exec()
|
|
714
733
|
if returnValue == QMessageBox.Ok:
|
|
715
|
-
self.
|
|
734
|
+
self.current_stack = None
|
|
716
735
|
return None
|
|
717
736
|
else:
|
|
718
|
-
self.
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
if
|
|
722
|
-
stack = imread(self.
|
|
723
|
-
|
|
737
|
+
self.current_stack = movies[0]
|
|
738
|
+
self.stack_length = auto_load_number_of_frames(self.current_stack)
|
|
739
|
+
|
|
740
|
+
if self.stack_length is None:
|
|
741
|
+
stack = imread(self.current_stack)
|
|
742
|
+
self.stack_length = len(stack)
|
|
724
743
|
del stack
|
|
725
744
|
gc.collect()
|
|
726
|
-
|
|
727
|
-
self.
|
|
728
|
-
|
|
745
|
+
|
|
746
|
+
self.mid_time = self.stack_length // 2
|
|
747
|
+
indices = self.mid_time + np.arange(len(self.channel_names))
|
|
748
|
+
self.test_frame = load_frames(list(indices.astype(int)),self.current_stack, normalize_input=False)
|
|
749
|
+
|
|
729
750
|
|
|
730
751
|
def control_haralick_digitalization(self):
|
|
731
752
|
|
|
@@ -791,119 +812,21 @@ class ConfigMeasurements(QMainWindow):
|
|
|
791
812
|
Show the ROI for the selected contour measurement on experimental data.
|
|
792
813
|
|
|
793
814
|
"""
|
|
794
|
-
|
|
795
|
-
if self.parent.parent.position_list.currentText() == '*':
|
|
796
|
-
msgBox = QMessageBox()
|
|
797
|
-
msgBox.setIcon(QMessageBox.Warning)
|
|
798
|
-
msgBox.setText("Please select a single position to visualize the border selection.")
|
|
799
|
-
msgBox.setWindowTitle("Warning")
|
|
800
|
-
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
801
|
-
returnValue = msgBox.exec()
|
|
802
|
-
if returnValue == QMessageBox.Ok:
|
|
803
|
-
return None
|
|
804
|
-
else:
|
|
805
|
-
return None
|
|
806
|
-
|
|
807
815
|
self.locate_image()
|
|
808
816
|
|
|
809
|
-
self.
|
|
810
|
-
if self.test_mask is None:
|
|
811
|
-
msgBox = QMessageBox()
|
|
812
|
-
msgBox.setIcon(QMessageBox.Warning)
|
|
813
|
-
msgBox.setText("The segmentation results could not be found for this position.")
|
|
814
|
-
msgBox.setWindowTitle("Warning")
|
|
815
|
-
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
816
|
-
returnValue = msgBox.exec()
|
|
817
|
-
if returnValue == QMessageBox.Yes:
|
|
818
|
-
return None
|
|
819
|
-
else:
|
|
820
|
-
return None
|
|
821
|
-
# plt.imshow(self.test_frame[:,:,0])
|
|
822
|
-
# plt.pause(2)
|
|
823
|
-
# plt.close()
|
|
824
|
-
|
|
825
|
-
# plt.imshow(self.test_mask)
|
|
826
|
-
# plt.pause(2)
|
|
827
|
-
# plt.close()
|
|
828
|
-
|
|
829
|
-
if (self.test_frame is not None) and (self.test_mask is not None):
|
|
830
|
-
|
|
831
|
-
values = self.contours_list.list_widget.selectedItems()
|
|
832
|
-
if len(values) > 0:
|
|
833
|
-
distance = values[0].text()
|
|
834
|
-
if '-' in distance:
|
|
835
|
-
if distance[0] != '-':
|
|
836
|
-
border_dist = distance.split('-')
|
|
837
|
-
border_dist = [float(d) for d in border_dist]
|
|
838
|
-
else:
|
|
839
|
-
border_dist = float(distance)
|
|
840
|
-
elif distance.isnumeric():
|
|
841
|
-
border_dist = float(distance)
|
|
842
|
-
|
|
843
|
-
print(border_dist)
|
|
844
|
-
border_label = contour_of_instance_segmentation(self.test_mask, border_dist)
|
|
845
|
-
|
|
846
|
-
self.fig_contour, self.ax_contour = plt.subplots(figsize=(5, 5))
|
|
847
|
-
self.imshow_contour = FigureCanvas(self.fig_contour, title="Contour measurement", interactive=True)
|
|
848
|
-
self.ax_contour.clear()
|
|
849
|
-
self.im_contour = self.ax_contour.imshow(self.test_frame[:, :, 0], cmap='gray')
|
|
850
|
-
self.im_mask = self.ax_contour.imshow(np.ma.masked_where(border_label == 0, border_label),
|
|
851
|
-
cmap='viridis', interpolation='none')
|
|
852
|
-
self.ax_contour.set_xticks([])
|
|
853
|
-
self.ax_contour.set_yticks([])
|
|
854
|
-
self.ax_contour.set_title(border_dist)
|
|
855
|
-
self.fig_contour.set_facecolor('none') # or 'None'
|
|
856
|
-
self.fig_contour.canvas.setStyleSheet("background-color: transparent;")
|
|
857
|
-
self.imshow_contour.canvas.draw()
|
|
858
|
-
|
|
859
|
-
self.imshow_contour.layout.setContentsMargins(30, 30, 30, 30)
|
|
860
|
-
self.channel_hbox_contour = QHBoxLayout()
|
|
861
|
-
self.channel_hbox_contour.addWidget(QLabel('channel: '), 10)
|
|
862
|
-
self.channel_cb_contour = QComboBox()
|
|
863
|
-
self.channel_cb_contour.addItems(self.channel_names)
|
|
864
|
-
self.channel_cb_contour.currentIndexChanged.connect(self.switch_channel_contour)
|
|
865
|
-
self.channel_hbox_contour.addWidget(self.channel_cb_contour, 90)
|
|
866
|
-
self.imshow_contour.layout.addLayout(self.channel_hbox_contour)
|
|
867
|
-
|
|
868
|
-
self.contrast_hbox_contour = QHBoxLayout()
|
|
869
|
-
self.contrast_hbox_contour.addWidget(QLabel('contrast: '), 10)
|
|
870
|
-
self.contrast_slider_contour = QLabeledDoubleRangeSlider()
|
|
871
|
-
self.contrast_slider_contour.setSingleStep(0.00001)
|
|
872
|
-
self.contrast_slider_contour.setTickInterval(0.00001)
|
|
873
|
-
self.contrast_slider_contour.setOrientation(1)
|
|
874
|
-
self.contrast_slider_contour.setRange(np.amin(self.test_frame[:, :, 0]),
|
|
875
|
-
np.amax(self.test_frame[:, :, 0]))
|
|
876
|
-
self.contrast_slider_contour.setValue([np.percentile(self.test_frame[:, :, 0].flatten(), 1),
|
|
877
|
-
np.percentile(self.test_frame[:, :, 0].flatten(), 99.99)])
|
|
878
|
-
self.im_contour.set_clim(vmin=np.percentile(self.test_frame[:, :, 0].flatten(), 1),
|
|
879
|
-
vmax=np.percentile(self.test_frame[:, :, 0].flatten(), 99.99))
|
|
880
|
-
self.contrast_slider_contour.valueChanged.connect(self.contrast_im_contour)
|
|
881
|
-
self.contrast_hbox_contour.addWidget(self.contrast_slider_contour, 90)
|
|
882
|
-
self.imshow_contour.layout.addLayout(self.contrast_hbox_contour)
|
|
883
|
-
|
|
884
|
-
self.alpha_mask_hbox_contour = QHBoxLayout()
|
|
885
|
-
self.alpha_mask_hbox_contour.addWidget(QLabel('mask transparency: '), 10)
|
|
886
|
-
self.transparency_slider = QLabeledDoubleSlider()
|
|
887
|
-
self.transparency_slider.setSingleStep(0.001)
|
|
888
|
-
self.transparency_slider.setTickInterval(0.001)
|
|
889
|
-
self.transparency_slider.setOrientation(1)
|
|
890
|
-
self.transparency_slider.setRange(0, 1)
|
|
891
|
-
self.transparency_slider.setValue(0.5)
|
|
892
|
-
self.transparency_slider.valueChanged.connect(self.make_contour_transparent)
|
|
893
|
-
self.alpha_mask_hbox_contour.addWidget(self.transparency_slider, 90)
|
|
894
|
-
self.imshow_contour.layout.addLayout(self.alpha_mask_hbox_contour)
|
|
895
|
-
|
|
896
|
-
self.imshow_contour.show()
|
|
817
|
+
if self.current_stack is not None:
|
|
897
818
|
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
819
|
+
self.viewer = CellEdgeVisualizer(cell_type=self.mode,
|
|
820
|
+
stack_path=self.current_stack,
|
|
821
|
+
parent_list_widget=self.contours_list.list_widget,
|
|
822
|
+
n_channels=len(self.channel_names),
|
|
823
|
+
target_channel=0,
|
|
824
|
+
window_title='Set an edge measurement',
|
|
825
|
+
channel_cb=True,
|
|
826
|
+
channel_names = self.channel_names,
|
|
827
|
+
PxToUm = 1,
|
|
828
|
+
)
|
|
829
|
+
self.viewer.show()
|
|
907
830
|
|
|
908
831
|
def locate_mask(self):
|
|
909
832
|
|
|
@@ -911,7 +834,7 @@ class ConfigMeasurements(QMainWindow):
|
|
|
911
834
|
Load the first mask of the detected movie.
|
|
912
835
|
"""
|
|
913
836
|
|
|
914
|
-
labels_path = str(Path(self.
|
|
837
|
+
labels_path = str(Path(self.current_stack).parent.parent) + os.sep+f'labels_{self.mode}'+os.sep
|
|
915
838
|
masks = natsorted(glob(labels_path + '*.tif'))
|
|
916
839
|
if len(masks) == 0:
|
|
917
840
|
print('no mask found')
|
|
@@ -946,208 +869,6 @@ class ConfigMeasurements(QMainWindow):
|
|
|
946
869
|
self.im_mask.set_alpha(value)
|
|
947
870
|
self.fig_contour.canvas.draw_idle()
|
|
948
871
|
|
|
949
|
-
def populate_normalisation_tabs(self):
|
|
950
|
-
layout = QVBoxLayout(self.normalisation_frame)
|
|
951
|
-
self.normalisation_lbl = QLabel("BACKGROUND CORRECTION")
|
|
952
|
-
self.normalisation_lbl.setStyleSheet("""
|
|
953
|
-
font-weight: bold;
|
|
954
|
-
padding: 0px;
|
|
955
|
-
""")
|
|
956
|
-
layout.addWidget(self.normalisation_lbl, alignment=Qt.AlignCenter)
|
|
957
|
-
self.tabs = QTabWidget()
|
|
958
|
-
self.tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
959
|
-
self.tab1 = QWidget()
|
|
960
|
-
self.tab2 = QWidget()
|
|
961
|
-
self.normalisation_list = QListWidget()
|
|
962
|
-
self.tabs.addTab(self.tab1, 'Local')
|
|
963
|
-
self.tabs.addTab(self.tab2, 'Field')
|
|
964
|
-
self.tab1.setLayout(self.populate_local_norm_tab())
|
|
965
|
-
self.tab2.setLayout(self.populate_field_norm_tab())
|
|
966
|
-
layout.addWidget(self.tabs)
|
|
967
|
-
self.norm_list_lbl = QLabel('Background correction to perform:')
|
|
968
|
-
hbox = QHBoxLayout()
|
|
969
|
-
hbox.addWidget(self.norm_list_lbl)
|
|
970
|
-
self.del_norm_btn = QPushButton("")
|
|
971
|
-
self.del_norm_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
|
|
972
|
-
self.del_norm_btn.setIcon(icon(MDI6.trash_can, color="black"))
|
|
973
|
-
self.del_norm_btn.setToolTip("Remove background correction")
|
|
974
|
-
self.del_norm_btn.setIconSize(QSize(20, 20))
|
|
975
|
-
hbox.addWidget(self.del_norm_btn, alignment=Qt.AlignRight)
|
|
976
|
-
layout.addLayout(hbox)
|
|
977
|
-
self.del_norm_btn.clicked.connect(self.remove_item_from_list)
|
|
978
|
-
layout.addWidget(self.normalisation_list)
|
|
979
|
-
|
|
980
|
-
def populate_local_norm_tab(self):
|
|
981
|
-
tab1_layout = QGridLayout(self.tab1)
|
|
982
|
-
|
|
983
|
-
channel_lbl = QLabel()
|
|
984
|
-
channel_lbl.setText("Channel: ")
|
|
985
|
-
tab1_layout.addWidget(channel_lbl, 0, 0)
|
|
986
|
-
|
|
987
|
-
self.tab1_channel_dropdown = QComboBox()
|
|
988
|
-
self.tab1_channel_dropdown.addItems(self.channel_names)
|
|
989
|
-
tab1_layout.addWidget(self.tab1_channel_dropdown, 0, 1)
|
|
990
|
-
|
|
991
|
-
tab1_lbl = QLabel()
|
|
992
|
-
tab1_lbl.setText("Outer distance (in px): ")
|
|
993
|
-
tab1_layout.addWidget(tab1_lbl, 1, 0)
|
|
994
|
-
|
|
995
|
-
self.tab1_txt_distance = QLineEdit()
|
|
996
|
-
tab1_layout.addWidget(self.tab1_txt_distance, 1, 1)
|
|
997
|
-
|
|
998
|
-
self.tab1_vis_brdr = QPushButton()
|
|
999
|
-
self.tab1_vis_brdr.setStyleSheet(self.parent.parent.parent.button_select_all)
|
|
1000
|
-
self.tab1_vis_brdr.setIcon(icon(MDI6.eye_outline, color="black"))
|
|
1001
|
-
self.tab1_vis_brdr.setToolTip("View contour")
|
|
1002
|
-
self.tab1_vis_brdr.setIconSize(QSize(20, 20))
|
|
1003
|
-
self.tab1_vis_brdr.clicked.connect(self.view_normalisation_contour)
|
|
1004
|
-
tab1_layout.addWidget(self.tab1_vis_brdr, 1, 2)
|
|
1005
|
-
|
|
1006
|
-
tab1_lbl_type = QLabel()
|
|
1007
|
-
tab1_lbl_type.setText("Type: ")
|
|
1008
|
-
tab1_layout.addWidget(tab1_lbl_type, 2, 0)
|
|
1009
|
-
|
|
1010
|
-
self.tab1_dropdown = QComboBox()
|
|
1011
|
-
self.tab1_dropdown.addItem("Mean")
|
|
1012
|
-
self.tab1_dropdown.addItem("Median")
|
|
1013
|
-
tab1_layout.addWidget(self.tab1_dropdown, 2, 1)
|
|
1014
|
-
|
|
1015
|
-
self.tab1_subtract = QRadioButton('Subtract')
|
|
1016
|
-
self.tab1_divide = QRadioButton('Divide')
|
|
1017
|
-
tab1_layout.addWidget(self.tab1_subtract, 3, 0, alignment=Qt.AlignRight)
|
|
1018
|
-
tab1_layout.addWidget(self.tab1_divide, 3, 1, alignment=Qt.AlignRight)
|
|
1019
|
-
|
|
1020
|
-
tab1_submit = QPushButton()
|
|
1021
|
-
tab1_submit.setText('Add channel')
|
|
1022
|
-
tab1_submit.setStyleSheet(self.parent.parent.parent.button_style_sheet_2)
|
|
1023
|
-
tab1_layout.addWidget(tab1_submit, 4, 0, 1, 3)
|
|
1024
|
-
tab1_submit.clicked.connect(self.add_item_to_list)
|
|
1025
|
-
|
|
1026
|
-
return tab1_layout
|
|
1027
|
-
|
|
1028
|
-
def populate_field_norm_tab(self):
|
|
1029
|
-
|
|
1030
|
-
tab2_layout = QGridLayout(self.tab2)
|
|
1031
|
-
|
|
1032
|
-
channel_lbl = QLabel()
|
|
1033
|
-
channel_lbl.setText("Channel: ")
|
|
1034
|
-
tab2_layout.addWidget(channel_lbl, 0, 0)
|
|
1035
|
-
|
|
1036
|
-
self.tab2_channel_dropdown = QComboBox()
|
|
1037
|
-
self.tab2_channel_dropdown.addItems(self.channel_names)
|
|
1038
|
-
tab2_layout.addWidget(self.tab2_channel_dropdown, 0, 1)
|
|
1039
|
-
|
|
1040
|
-
tab2_lbl = QLabel()
|
|
1041
|
-
tab2_lbl.setText("std threshold: ")
|
|
1042
|
-
tab2_layout.addWidget(tab2_lbl, 1, 0)
|
|
1043
|
-
|
|
1044
|
-
self.tab2_txt_threshold = QLineEdit()
|
|
1045
|
-
tab2_layout.addWidget(self.tab2_txt_threshold, 1, 1)
|
|
1046
|
-
|
|
1047
|
-
self.norm_digit_btn = QPushButton()
|
|
1048
|
-
self.norm_digit_btn.setIcon(icon(MDI6.image_check, color="k"))
|
|
1049
|
-
self.norm_digit_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
|
|
1050
|
-
|
|
1051
|
-
self.norm_digit_btn.clicked.connect(self.show_threshold_visual)
|
|
1052
|
-
tab2_layout.addWidget(self.norm_digit_btn, 1, 2)
|
|
1053
|
-
|
|
1054
|
-
tab2_lbl_type = QLabel()
|
|
1055
|
-
tab2_lbl_type.setText("Type: ")
|
|
1056
|
-
tab2_layout.addWidget(tab2_lbl_type, 2, 0)
|
|
1057
|
-
|
|
1058
|
-
self.tab2_dropdown = QComboBox()
|
|
1059
|
-
self.tab2_dropdown.addItems(["Paraboloid", "Plane"])
|
|
1060
|
-
tab2_layout.addWidget(self.tab2_dropdown, 2, 1)
|
|
1061
|
-
|
|
1062
|
-
self.tab2_subtract = QRadioButton('Subtract')
|
|
1063
|
-
self.tab2_divide = QRadioButton('Divide')
|
|
1064
|
-
self.tab2_sd_btn_group = QButtonGroup(self)
|
|
1065
|
-
self.tab2_sd_btn_group.addButton(self.tab2_subtract)
|
|
1066
|
-
self.tab2_sd_btn_group.addButton(self.tab2_divide)
|
|
1067
|
-
tab2_layout.addWidget(self.tab2_subtract, 3, 0, alignment=Qt.AlignRight)
|
|
1068
|
-
tab2_layout.addWidget(self.tab2_divide, 3, 1, alignment=Qt.AlignRight)
|
|
1069
|
-
|
|
1070
|
-
self.tab2_clip = QRadioButton('Clip')
|
|
1071
|
-
self.tab2_no_clip = QRadioButton("Don't clip")
|
|
1072
|
-
self.tab2_clip_group = QButtonGroup(self)
|
|
1073
|
-
self.tab2_clip_group.addButton(self.tab2_clip)
|
|
1074
|
-
self.tab2_clip_group.addButton(self.tab2_no_clip)
|
|
1075
|
-
self.tab2_clip.setEnabled(False)
|
|
1076
|
-
self.tab2_no_clip.setEnabled(False)
|
|
1077
|
-
tab2_layout.addWidget(self.tab2_clip, 4, 0, alignment=Qt.AlignLeft)
|
|
1078
|
-
tab2_layout.addWidget(self.tab2_no_clip, 4, 1, alignment=Qt.AlignLeft)
|
|
1079
|
-
self.tab2_subtract.toggled.connect(self.show_clipping_options)
|
|
1080
|
-
self.tab2_divide.toggled.connect(self.show_clipping_options)
|
|
1081
|
-
|
|
1082
|
-
self.view_norm_btn = QPushButton("")
|
|
1083
|
-
self.view_norm_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
|
|
1084
|
-
self.view_norm_btn.setIcon(icon(MDI6.eye_outline, color="black"))
|
|
1085
|
-
self.view_norm_btn.setToolTip("View corrected image")
|
|
1086
|
-
self.view_norm_btn.setIconSize(QSize(20, 20))
|
|
1087
|
-
self.view_norm_btn.clicked.connect(self.preview_normalisation)
|
|
1088
|
-
tab2_layout.addWidget(self.view_norm_btn, 4, 2)
|
|
1089
|
-
|
|
1090
|
-
tab2_submit = QPushButton()
|
|
1091
|
-
tab2_submit.setText('Add channel')
|
|
1092
|
-
tab2_submit.setStyleSheet(self.parent.parent.parent.button_style_sheet_2)
|
|
1093
|
-
tab2_layout.addWidget(tab2_submit, 5, 0, 1, 3)
|
|
1094
|
-
tab2_submit.clicked.connect(self.add_item_to_list)
|
|
1095
|
-
|
|
1096
|
-
return tab2_layout
|
|
1097
|
-
|
|
1098
|
-
def show_threshold_visual(self):
|
|
1099
|
-
min_threshold = self.tab2_txt_threshold.text()
|
|
1100
|
-
if min_threshold == "":
|
|
1101
|
-
min_threshold = 0
|
|
1102
|
-
current_channel = self.tab2_channel_dropdown.currentIndex()
|
|
1103
|
-
self.threshold_visual = ThresholdNormalisation(min_threshold=float(min_threshold),
|
|
1104
|
-
current_channel=current_channel, parent=self)
|
|
1105
|
-
|
|
1106
|
-
def show_clipping_options(self):
|
|
1107
|
-
if self.tab2_subtract.isChecked():
|
|
1108
|
-
for button in self.tab2_clip_group.buttons():
|
|
1109
|
-
button.setEnabled(True)
|
|
1110
|
-
if self.tab2_divide.isChecked():
|
|
1111
|
-
self.tab2_clip_group.setExclusive(False)
|
|
1112
|
-
for button in self.tab2_clip_group.buttons():
|
|
1113
|
-
button.setChecked(False)
|
|
1114
|
-
button.setEnabled(False)
|
|
1115
|
-
self.tab2_clip_group.setExclusive(True)
|
|
1116
|
-
|
|
1117
|
-
def add_item_to_list(self):
|
|
1118
|
-
check = self.check_the_information()
|
|
1119
|
-
if check is True:
|
|
1120
|
-
|
|
1121
|
-
if self.tabs.currentIndex() == 0:
|
|
1122
|
-
|
|
1123
|
-
norm_params = {"target channel": self.tab1_channel_dropdown.currentText(), "mode": "local",
|
|
1124
|
-
"distance": self.tab1_txt_distance.text(),
|
|
1125
|
-
"type": self.tab1_dropdown.currentText()}
|
|
1126
|
-
if self.tab1_subtract.isChecked():
|
|
1127
|
-
norm_params["operation"] = "Subtract"
|
|
1128
|
-
else:
|
|
1129
|
-
norm_params["operation"] = "Divide"
|
|
1130
|
-
elif self.tabs.currentIndex() == 1:
|
|
1131
|
-
norm_params = {"target channel": self.tab2_channel_dropdown.currentText(), "mode": "field",
|
|
1132
|
-
"threshold": self.tab2_txt_threshold.text(),
|
|
1133
|
-
"type": self.tab2_dropdown.currentText()}
|
|
1134
|
-
if self.tab2_subtract.isChecked():
|
|
1135
|
-
norm_params["operation"] = "Subtract"
|
|
1136
|
-
if self.tab2_clip.isChecked():
|
|
1137
|
-
norm_params["clip"] = True
|
|
1138
|
-
else:
|
|
1139
|
-
norm_params["clip"] = False
|
|
1140
|
-
elif self.tab2_divide.isChecked():
|
|
1141
|
-
norm_params["operation"] = "Divide"
|
|
1142
|
-
|
|
1143
|
-
self.background_correction.append(norm_params)
|
|
1144
|
-
normalisation_description = ""
|
|
1145
|
-
for index, (key, value) in enumerate(norm_params.items()):
|
|
1146
|
-
if index > 0:
|
|
1147
|
-
normalisation_description += ", "
|
|
1148
|
-
normalisation_description += str(key) + " : " + str(value)
|
|
1149
|
-
self.normalisation_list.addItem(normalisation_description)
|
|
1150
|
-
|
|
1151
872
|
def remove_item_from_list(self):
|
|
1152
873
|
current_item = self.normalisation_list.currentRow()
|
|
1153
874
|
if current_item > -1:
|
|
@@ -1155,6 +876,7 @@ class ConfigMeasurements(QMainWindow):
|
|
|
1155
876
|
self.normalisation_list.takeItem(current_item)
|
|
1156
877
|
|
|
1157
878
|
def check_the_information(self):
|
|
879
|
+
|
|
1158
880
|
if self.tabs.currentIndex() == 0:
|
|
1159
881
|
if self.background_correction is None:
|
|
1160
882
|
self.background_correction = []
|
|
@@ -1167,38 +889,6 @@ class ConfigMeasurements(QMainWindow):
|
|
|
1167
889
|
self.background_correction .remove(normalisation_opt)
|
|
1168
890
|
self.normalisation_list.takeItem(index)
|
|
1169
891
|
return True
|
|
1170
|
-
if self.tab1_txt_distance.text() == "":
|
|
1171
|
-
self.display_message_box('provide the outer distance')
|
|
1172
|
-
return False
|
|
1173
|
-
if not self.tab1_subtract.isChecked() and not self.tab1_divide.isChecked():
|
|
1174
|
-
self.display_message_box('choose the operation')
|
|
1175
|
-
return False
|
|
1176
|
-
else:
|
|
1177
|
-
return True
|
|
1178
|
-
|
|
1179
|
-
elif self.tabs.currentIndex() == 1:
|
|
1180
|
-
if self.background_correction is None:
|
|
1181
|
-
self.background_correction = []
|
|
1182
|
-
for index, normalisation_opt in enumerate(self.background_correction ):
|
|
1183
|
-
if self.tab2_channel_dropdown.currentText() in normalisation_opt['target channel']:
|
|
1184
|
-
result = self.channel_already_in_list()
|
|
1185
|
-
if result != QMessageBox.Yes:
|
|
1186
|
-
return False
|
|
1187
|
-
else:
|
|
1188
|
-
self.background_correction .remove(normalisation_opt)
|
|
1189
|
-
self.normalisation_list.takeItem(index)
|
|
1190
|
-
return True
|
|
1191
|
-
if self.tab2_txt_threshold.text() == "":
|
|
1192
|
-
self.display_message_box('provide the threshold')
|
|
1193
|
-
return False
|
|
1194
|
-
elif not self.tab2_divide.isChecked() and not self.tab2_subtract.isChecked():
|
|
1195
|
-
self.display_message_box('choose subtraction or division')
|
|
1196
|
-
return False
|
|
1197
|
-
elif self.tab2_subtract.isChecked():
|
|
1198
|
-
if not self.tab2_clip.isChecked() and not self.tab2_no_clip.isChecked():
|
|
1199
|
-
self.display_message_box('provide the clipping mode')
|
|
1200
|
-
return False
|
|
1201
|
-
return True
|
|
1202
892
|
|
|
1203
893
|
def display_message_box(self, missing_info):
|
|
1204
894
|
QMessageBox.about(self, "Message Box Title", "Please " + missing_info + " for background correction")
|
|
@@ -1214,47 +904,6 @@ class ConfigMeasurements(QMainWindow):
|
|
|
1214
904
|
def fun(self, x, y):
|
|
1215
905
|
return x ** 2 + y
|
|
1216
906
|
|
|
1217
|
-
def preview_normalisation(self):
|
|
1218
|
-
plt.close('all')
|
|
1219
|
-
plt.figure("Intensity Profiles",figsize=(10, 5))
|
|
1220
|
-
self.locate_image()
|
|
1221
|
-
diagonal_length = min(self.test_frame[:, :, self.tab2_channel_dropdown.currentIndex()].shape[0], self.test_frame[:, :, self.tab2_channel_dropdown.currentIndex()].shape[1])
|
|
1222
|
-
if self.tab2_subtract.isChecked():
|
|
1223
|
-
norm_operation='Subtract'
|
|
1224
|
-
else:
|
|
1225
|
-
norm_operation='Divide'
|
|
1226
|
-
normalised, bg_fit = field_normalisation(self.test_frame[:, :, self.tab2_channel_dropdown.currentIndex()],
|
|
1227
|
-
threshold=self.tab2_txt_threshold.text(),
|
|
1228
|
-
normalisation_operation=norm_operation,
|
|
1229
|
-
clip=self.tab2_clip.isChecked(),
|
|
1230
|
-
mode=self.tab2_dropdown.currentText())
|
|
1231
|
-
diagonal_original = [self.test_frame[:, :, self.tab2_channel_dropdown.currentIndex()][i, i] for i in
|
|
1232
|
-
range(diagonal_length)]
|
|
1233
|
-
diagonal_corrected = [normalised[i, i] for i in range(diagonal_length)]
|
|
1234
|
-
diagonal_indices = np.arange(diagonal_length)
|
|
1235
|
-
|
|
1236
|
-
plt.subplot(1, 2, 1)
|
|
1237
|
-
plt.plot(diagonal_indices, diagonal_original, color='black', linewidth=0.2) # Adjust linewidth here
|
|
1238
|
-
plt.title('Original Image')
|
|
1239
|
-
plt.xlabel('Pixel Index along Diagonal')
|
|
1240
|
-
plt.ylabel('Intensity')
|
|
1241
|
-
|
|
1242
|
-
plt.subplot(1, 2, 2)
|
|
1243
|
-
plt.plot(diagonal_indices, diagonal_corrected, color='black', linewidth=0.2) # Adjust linewidth here
|
|
1244
|
-
plt.title('Corrected Image')
|
|
1245
|
-
plt.xlabel('Pixel Index along Diagonal')
|
|
1246
|
-
plt.ylabel('Intensity')
|
|
1247
|
-
|
|
1248
|
-
plt.tight_layout()
|
|
1249
|
-
plt.show()
|
|
1250
|
-
|
|
1251
|
-
self.fig, self.ax = plt.subplots()
|
|
1252
|
-
self.normalised_img = FigureCanvas(self.fig, "Corrected background image preview")
|
|
1253
|
-
self.ax.clear()
|
|
1254
|
-
self.ax.imshow(normalised, cmap='gray')
|
|
1255
|
-
self.normalised_img.canvas.draw()
|
|
1256
|
-
self.normalised_img.show()
|
|
1257
|
-
|
|
1258
907
|
def view_normalisation_contour(self):
|
|
1259
908
|
|
|
1260
909
|
"""
|
|
@@ -1262,67 +911,27 @@ class ConfigMeasurements(QMainWindow):
|
|
|
1262
911
|
|
|
1263
912
|
"""
|
|
1264
913
|
|
|
1265
|
-
if self.parent.parent.position_list.currentText() == '*':
|
|
1266
|
-
msgBox = QMessageBox()
|
|
1267
|
-
msgBox.setIcon(QMessageBox.Warning)
|
|
1268
|
-
msgBox.setText("Please select a single position to visualize the border selection.")
|
|
1269
|
-
msgBox.setWindowTitle("Warning")
|
|
1270
|
-
msgBox.setStandardButtons(QMessageBox.Ok)
|
|
1271
|
-
returnValue = msgBox.exec()
|
|
1272
|
-
if returnValue == QMessageBox.Ok:
|
|
1273
|
-
return None
|
|
1274
|
-
else:
|
|
1275
|
-
return None
|
|
1276
|
-
|
|
1277
914
|
self.locate_image()
|
|
1278
915
|
|
|
1279
|
-
self.
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
916
|
+
if self.current_stack is not None:
|
|
917
|
+
|
|
918
|
+
self.viewer = CellEdgeVisualizer(cell_type=self.mode,
|
|
919
|
+
stack_path=self.current_stack,
|
|
920
|
+
parent_le = self.tab1_txt_distance,
|
|
921
|
+
n_channels=len(self.channel_names),
|
|
922
|
+
target_channel=self.tab1_channel_dropdown.currentIndex(),
|
|
923
|
+
edge_range = (0,30),
|
|
924
|
+
initial_edge= self.tab1_txt_distance.get_threshold(),
|
|
925
|
+
invert=True,
|
|
926
|
+
window_title='Set an edge distance to estimate local intensity',
|
|
927
|
+
channel_cb=False,
|
|
928
|
+
PxToUm = 1,
|
|
929
|
+
)
|
|
930
|
+
self.viewer.show()
|
|
1291
931
|
|
|
1292
|
-
if (self.test_frame is not None) and (self.test_mask is not None):
|
|
1293
|
-
contour = float(self.tab1_txt_distance.text())
|
|
1294
|
-
contour = contour * (-1)
|
|
1295
|
-
border_label = contour_of_instance_segmentation(self.test_mask, contour)
|
|
1296
|
-
|
|
1297
|
-
self.fig_contour, self.ax_contour = plt.subplots(figsize=(5, 5))
|
|
1298
|
-
self.imshow_contour = FigureCanvas(self.fig_contour, title="Contour measurement", interactive=True)
|
|
1299
|
-
self.ax_contour.clear()
|
|
1300
|
-
self.im_contour = self.ax_contour.imshow(self.test_frame[:, :, self.tab1_channel_dropdown.currentIndex()],
|
|
1301
|
-
cmap='gray')
|
|
1302
|
-
self.im_mask = self.ax_contour.imshow(np.ma.masked_where(border_label == 0, border_label),
|
|
1303
|
-
cmap='viridis', interpolation='none')
|
|
1304
|
-
self.ax_contour.set_xticks([])
|
|
1305
|
-
self.ax_contour.set_yticks([])
|
|
1306
|
-
self.ax_contour.set_title(contour * (-1))
|
|
1307
|
-
self.fig_contour.set_facecolor('none') # or 'None'
|
|
1308
|
-
self.fig_contour.canvas.setStyleSheet("background-color: transparent;")
|
|
1309
|
-
self.imshow_contour.canvas.draw()
|
|
1310
|
-
|
|
1311
|
-
self.imshow_contour.show()
|
|
1312
|
-
|
|
1313
|
-
# def enable_step_size(self):
|
|
1314
|
-
# if self.radial_intensity_btn.isChecked():
|
|
1315
|
-
# self.step_lbl.setEnabled(True)
|
|
1316
|
-
# self.step_size.setEnabled(True)
|
|
1317
|
-
# for checkbox in self.channel_chechkboxes:
|
|
1318
|
-
# checkbox.setEnabled(True)
|
|
1319
|
-
# else:
|
|
1320
|
-
# self.step_lbl.setEnabled(False)
|
|
1321
|
-
# self.step_size.setEnabled(False)
|
|
1322
|
-
# for checkbox in self.channel_chechkboxes:
|
|
1323
|
-
# checkbox.setEnabled(False)
|
|
1324
932
|
|
|
1325
933
|
def populate_spot_detection(self):
|
|
934
|
+
|
|
1326
935
|
layout = QGridLayout(self.spot_detection_frame)
|
|
1327
936
|
self.spot_detection_lbl = QLabel("SPOT DETECTION")
|
|
1328
937
|
self.spot_detection_lbl.setStyleSheet("""font-weight: bold;padding: 0px;""")
|
|
@@ -1353,7 +962,7 @@ class ConfigMeasurements(QMainWindow):
|
|
|
1353
962
|
layout.addWidget(self.threshold_value, 4, 1)
|
|
1354
963
|
self.preview_spot = QPushButton('Preview')
|
|
1355
964
|
self.preview_spot.clicked.connect(self.spot_preview)
|
|
1356
|
-
self.preview_spot.setStyleSheet(self.
|
|
965
|
+
self.preview_spot.setStyleSheet(self.button_style_sheet_2)
|
|
1357
966
|
layout.addWidget(self.preview_spot, 5, 0, 1, 2)
|
|
1358
967
|
self.spot_channel.setEnabled(False)
|
|
1359
968
|
self.spot_channel_lbl.setEnabled(False)
|
|
@@ -1379,31 +988,7 @@ class ConfigMeasurements(QMainWindow):
|
|
|
1379
988
|
self.locate_mask()
|
|
1380
989
|
if self.test_mask is not None:
|
|
1381
990
|
self.spot_visual = ThresholdSpot(current_channel=self.spot_channel.currentIndex(), img=self.test_frame,
|
|
1382
|
-
mask=self.test_mask,
|
|
1383
|
-
# for dictionary in self.background_correction:
|
|
1384
|
-
# if self.spot_channel.currentText() in dictionary['target channel']:
|
|
1385
|
-
# if dictionary['mode'] == 'field':
|
|
1386
|
-
# if dictionary['operation'] == 'Divide':
|
|
1387
|
-
# normalised, bg_fit = field_normalisation(
|
|
1388
|
-
# self.test_frame[:, :, self.spot_channel.currentIndex()],
|
|
1389
|
-
# threshold=dictionary['threshold'],
|
|
1390
|
-
# normalisation_operation=dictionary['operation'],
|
|
1391
|
-
# clip=False,
|
|
1392
|
-
# mode=dictionary['type'])
|
|
1393
|
-
# else:
|
|
1394
|
-
# normalised, bg_fit = field_normalisation(
|
|
1395
|
-
# self.test_frame[:, :, self.spot_channel.currentIndex()],
|
|
1396
|
-
# threshold=dictionary['threshold'],
|
|
1397
|
-
# normalisation_operation=dictionary['operation'],
|
|
1398
|
-
# clip=dictionary['clip'],
|
|
1399
|
-
# mode=dictionary['type'])
|
|
1400
|
-
# self.test_frame[:, :, self.spot_channel.currentIndex()] = normalised
|
|
1401
|
-
# if dictionary['mode'] == 'local':
|
|
1402
|
-
# normalised_image = normalise_by_cell(self.test_frame[:, :, self.spot_channel.currentIndex()].copy(), self.test_mask,
|
|
1403
|
-
# distance=int(dictionary['distance']), mode=dictionary['type'],
|
|
1404
|
-
# operation=dictionary['operation'])
|
|
1405
|
-
# self.test_frame[:, :, self.spot_channel.currentIndex()] = normalised_image
|
|
1406
|
-
|
|
991
|
+
mask=self.test_mask, parent_window=self)
|
|
1407
992
|
|
|
1408
993
|
def enable_spot_detection(self):
|
|
1409
994
|
if self.spot_check.isChecked():
|