celldetective 1.0.2.post1__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. celldetective/__main__.py +2 -2
  2. celldetective/events.py +2 -44
  3. celldetective/filters.py +4 -5
  4. celldetective/gui/__init__.py +1 -1
  5. celldetective/gui/analyze_block.py +37 -10
  6. celldetective/gui/btrack_options.py +24 -23
  7. celldetective/gui/classifier_widget.py +62 -19
  8. celldetective/gui/configure_new_exp.py +32 -35
  9. celldetective/gui/control_panel.py +115 -81
  10. celldetective/gui/gui_utils.py +674 -396
  11. celldetective/gui/json_readers.py +7 -6
  12. celldetective/gui/layouts.py +755 -0
  13. celldetective/gui/measurement_options.py +168 -487
  14. celldetective/gui/neighborhood_options.py +322 -270
  15. celldetective/gui/plot_measurements.py +1114 -0
  16. celldetective/gui/plot_signals_ui.py +20 -20
  17. celldetective/gui/process_block.py +449 -169
  18. celldetective/gui/retrain_segmentation_model_options.py +27 -26
  19. celldetective/gui/retrain_signal_model_options.py +25 -24
  20. celldetective/gui/seg_model_loader.py +31 -27
  21. celldetective/gui/signal_annotator.py +2326 -2295
  22. celldetective/gui/signal_annotator_options.py +18 -16
  23. celldetective/gui/styles.py +16 -1
  24. celldetective/gui/survival_ui.py +61 -39
  25. celldetective/gui/tableUI.py +60 -23
  26. celldetective/gui/thresholds_gui.py +68 -66
  27. celldetective/gui/viewers.py +596 -0
  28. celldetective/io.py +234 -23
  29. celldetective/measure.py +37 -32
  30. celldetective/neighborhood.py +495 -27
  31. celldetective/preprocessing.py +683 -0
  32. celldetective/scripts/analyze_signals.py +7 -0
  33. celldetective/scripts/measure_cells.py +12 -0
  34. celldetective/scripts/segment_cells.py +5 -0
  35. celldetective/scripts/track_cells.py +11 -0
  36. celldetective/signals.py +221 -98
  37. celldetective/tracking.py +0 -1
  38. celldetective/utils.py +178 -36
  39. celldetective-1.1.0.dist-info/METADATA +305 -0
  40. celldetective-1.1.0.dist-info/RECORD +80 -0
  41. {celldetective-1.0.2.post1.dist-info → celldetective-1.1.0.dist-info}/top_level.txt +1 -0
  42. tests/__init__.py +0 -0
  43. tests/test_events.py +28 -0
  44. tests/test_filters.py +24 -0
  45. tests/test_io.py +70 -0
  46. tests/test_measure.py +141 -0
  47. tests/test_neighborhood.py +70 -0
  48. tests/test_segmentation.py +93 -0
  49. tests/test_signals.py +135 -0
  50. tests/test_tracking.py +164 -0
  51. tests/test_utils.py +71 -0
  52. celldetective-1.0.2.post1.dist-info/METADATA +0 -221
  53. celldetective-1.0.2.post1.dist-info/RECORD +0 -66
  54. {celldetective-1.0.2.post1.dist-info → celldetective-1.1.0.dist-info}/LICENSE +0 -0
  55. {celldetective-1.0.2.post1.dist-info → celldetective-1.1.0.dist-info}/WHEEL +0 -0
  56. {celldetective-1.0.2.post1.dist-info → celldetective-1.1.0.dist-info}/entry_points.txt +0 -0
@@ -37,28 +37,33 @@ from pathlib import Path, PurePath
37
37
  import gc
38
38
  from stardist import fill_label_holes
39
39
 
40
+ from celldetective.gui.viewers import CellEdgeVisualizer
41
+ from celldetective.gui.layouts import ProtocolDesignerLayout, BackgroundFitCorrectionLayout, LocalCorrectionLayout, OperationLayout
42
+ from celldetective.gui.gui_utils import ThresholdLineEdit
43
+ from celldetective.gui import Styles
40
44
 
41
- class ConfigMeasurements(QMainWindow):
45
+ class ConfigMeasurements(QMainWindow, Styles):
42
46
  """
43
47
  UI to set measurement instructions.
44
48
 
45
49
  """
46
50
 
47
- def __init__(self, parent=None):
51
+ def __init__(self, parent_window=None):
48
52
 
49
53
  super().__init__()
50
- self.parent = parent
54
+
55
+ self.parent_window = parent_window
51
56
  self.setWindowTitle("Configure measurements")
52
57
  self.setWindowIcon(QIcon(os.sep.join(['celldetective', 'icons', 'mexican-hat.png'])))
53
- self.mode = self.parent.mode
54
- self.exp_dir = self.parent.exp_dir
58
+ self.mode = self.parent_window.mode
59
+ self.exp_dir = self.parent_window.exp_dir
55
60
  self.background_correction = []
56
61
  if self.mode == "targets":
57
62
  self.config_name = "btrack_config_targets.json"
58
- self.measure_instructions_path = self.parent.exp_dir + "configs/measurement_instructions_targets.json"
63
+ self.measure_instructions_path = self.parent_window.exp_dir + "configs/measurement_instructions_targets.json"
59
64
  elif self.mode == "effectors":
60
65
  self.config_name = "btrack_config_effectors.json"
61
- self.measure_instructions_path = self.parent.exp_dir + "configs/measurement_instructions_effectors.json"
66
+ self.measure_instructions_path = self.parent_window.exp_dir + "configs/measurement_instructions_effectors.json"
62
67
  self.soft_path = get_software_location()
63
68
  self.clear_previous = False
64
69
 
@@ -68,7 +73,7 @@ class ConfigMeasurements(QMainWindow):
68
73
  self.channel_names = np.array(self.channel_names)
69
74
  self.channels = np.array(self.channels)
70
75
 
71
- self.screen_height = self.parent.parent.parent.screen_height
76
+ self.screen_height = self.parent_window.parent_window.parent_window.screen_height
72
77
  center_window(self)
73
78
 
74
79
  self.onlyFloat = QDoubleValidator()
@@ -96,7 +101,20 @@ class ConfigMeasurements(QMainWindow):
96
101
 
97
102
  self.normalisation_frame = QFrame()
98
103
  self.normalisation_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
99
- self.populate_normalisation_tabs()
104
+
105
+ self.local_correction_layout = LocalCorrectionLayout(self)
106
+ self.fit_correction_layout = BackgroundFitCorrectionLayout(self)
107
+
108
+ self.protocol_layout = ProtocolDesignerLayout(parent_window=self,
109
+ tab_layouts=[ self.local_correction_layout, self.fit_correction_layout],
110
+ tab_names=['Local', 'Fit'],
111
+ title='BACKGROUND CORRECTION',
112
+ list_title='Corrections to apply:'
113
+ )
114
+
115
+ self.normalisation_frame.setLayout(self.protocol_layout)
116
+
117
+ #self.populate_normalisation_tabs()
100
118
  main_layout.addWidget(self.normalisation_frame)
101
119
 
102
120
  # first frame for FEATURES
@@ -120,7 +138,7 @@ class ConfigMeasurements(QMainWindow):
120
138
  main_layout.addWidget(self.clear_previous_btn)
121
139
 
122
140
  self.submit_btn = QPushButton('Save')
123
- self.submit_btn.setStyleSheet(self.parent.parent.parent.button_style_sheet)
141
+ self.submit_btn.setStyleSheet(self.button_style_sheet)
124
142
  self.submit_btn.clicked.connect(self.write_instructions)
125
143
  main_layout.addWidget(self.submit_btn)
126
144
 
@@ -186,14 +204,14 @@ class ConfigMeasurements(QMainWindow):
186
204
  radii_layout.addWidget(self.radii_lbl, 90)
187
205
 
188
206
  self.del_radius_btn = QPushButton("")
189
- self.del_radius_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
207
+ self.del_radius_btn.setStyleSheet(self.button_select_all)
190
208
  self.del_radius_btn.setIcon(icon(MDI6.trash_can, color="black"))
191
209
  self.del_radius_btn.setToolTip("Remove radius")
192
210
  self.del_radius_btn.setIconSize(QSize(20, 20))
193
211
  radii_layout.addWidget(self.del_radius_btn, 5)
194
212
 
195
213
  self.add_radius_btn = QPushButton("")
196
- self.add_radius_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
214
+ self.add_radius_btn.setStyleSheet(self.button_select_all)
197
215
  self.add_radius_btn.setIcon(icon(MDI6.plus, color="black"))
198
216
  self.add_radius_btn.setToolTip("Add radius")
199
217
  self.add_radius_btn.setIconSize(QSize(20, 20))
@@ -213,14 +231,14 @@ class ConfigMeasurements(QMainWindow):
213
231
  operation_layout.addWidget(self.op_lbl, 90)
214
232
 
215
233
  self.del_op_btn = QPushButton("")
216
- self.del_op_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
234
+ self.del_op_btn.setStyleSheet(self.button_select_all)
217
235
  self.del_op_btn.setIcon(icon(MDI6.trash_can, color="black"))
218
236
  self.del_op_btn.setToolTip("Remove operation")
219
237
  self.del_op_btn.setIconSize(QSize(20, 20))
220
238
  operation_layout.addWidget(self.del_op_btn, 5)
221
239
 
222
240
  self.add_op_btn = QPushButton("")
223
- self.add_op_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
241
+ self.add_op_btn.setStyleSheet(self.button_select_all)
224
242
  self.add_op_btn.setIcon(icon(MDI6.plus, color="black"))
225
243
  self.add_op_btn.setToolTip("Add operation")
226
244
  self.add_op_btn.setIconSize(QSize(20, 20))
@@ -244,13 +262,13 @@ class ConfigMeasurements(QMainWindow):
244
262
 
245
263
  self.feature_lbl = QLabel("Add features:")
246
264
  self.del_feature_btn = QPushButton("")
247
- self.del_feature_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
265
+ self.del_feature_btn.setStyleSheet(self.button_select_all)
248
266
  self.del_feature_btn.setIcon(icon(MDI6.trash_can, color="black"))
249
267
  self.del_feature_btn.setToolTip("Remove feature")
250
268
  self.del_feature_btn.setIconSize(QSize(20, 20))
251
269
 
252
270
  self.add_feature_btn = QPushButton("")
253
- self.add_feature_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
271
+ self.add_feature_btn.setStyleSheet(self.button_select_all)
254
272
  self.add_feature_btn.setIcon(icon(MDI6.filter_plus, color="black"))
255
273
  self.add_feature_btn.setToolTip("Add feature")
256
274
  self.add_feature_btn.setIconSize(QSize(20, 20))
@@ -276,22 +294,22 @@ class ConfigMeasurements(QMainWindow):
276
294
  contour_layout.addWidget(self.border_dist_lbl, 90)
277
295
 
278
296
  self.del_contour_btn = QPushButton("")
279
- self.del_contour_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
297
+ self.del_contour_btn.setStyleSheet(self.button_select_all)
280
298
  self.del_contour_btn.setIcon(icon(MDI6.trash_can, color="black"))
281
299
  self.del_contour_btn.setToolTip("Remove distance")
282
300
  self.del_contour_btn.setIconSize(QSize(20, 20))
283
301
  contour_layout.addWidget(self.del_contour_btn, 5)
284
302
 
285
303
  self.add_contour_btn = QPushButton("")
286
- self.add_contour_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
304
+ self.add_contour_btn.setStyleSheet(self.button_select_all)
287
305
  self.add_contour_btn.setIcon(icon(MDI6.plus, color="black"))
288
306
  self.add_contour_btn.setToolTip("Add distance")
289
307
  self.add_contour_btn.setIconSize(QSize(20, 20))
290
308
  contour_layout.addWidget(self.add_contour_btn, 5)
291
309
 
292
310
  self.view_contour_btn = QPushButton("")
293
- self.view_contour_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
294
- self.view_contour_btn.setIcon(icon(MDI6.eye_outline, color="black"))
311
+ self.view_contour_btn.setStyleSheet(self.button_select_all)
312
+ self.view_contour_btn.setIcon(icon(MDI6.eye_plus_outline, color="black"))
295
313
  self.view_contour_btn.setToolTip("View contour")
296
314
  self.view_contour_btn.setIconSize(QSize(20, 20))
297
315
  contour_layout.addWidget(self.view_contour_btn, 5)
@@ -354,7 +372,7 @@ class ConfigMeasurements(QMainWindow):
354
372
  self.haralick_percentile_min_le = QLineEdit('0.01')
355
373
  self.haralick_percentile_max_le = QLineEdit('99.9')
356
374
  self.haralick_normalization_mode_btn = QPushButton()
357
- self.haralick_normalization_mode_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
375
+ self.haralick_normalization_mode_btn.setStyleSheet(self.button_select_all)
358
376
  self.haralick_normalization_mode_btn.setIcon(icon(MDI6.percent_circle, color="black"))
359
377
  self.haralick_normalization_mode_btn.setIconSize(QSize(20, 20))
360
378
  self.haralick_normalization_mode_btn.setToolTip("Switch to absolute normalization values.")
@@ -371,12 +389,12 @@ class ConfigMeasurements(QMainWindow):
371
389
  self.haralick_hist_btn = QPushButton()
372
390
  self.haralick_hist_btn.clicked.connect(self.control_haralick_intensity_histogram)
373
391
  self.haralick_hist_btn.setIcon(icon(MDI6.poll, color="k"))
374
- self.haralick_hist_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
392
+ self.haralick_hist_btn.setStyleSheet(self.button_select_all)
375
393
 
376
394
  self.haralick_digit_btn = QPushButton()
377
395
  self.haralick_digit_btn.clicked.connect(self.control_haralick_digitalization)
378
396
  self.haralick_digit_btn.setIcon(icon(MDI6.image_check, color="k"))
379
- self.haralick_digit_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
397
+ self.haralick_digit_btn.setStyleSheet(self.button_select_all)
380
398
 
381
399
  self.haralick_layout = QVBoxLayout()
382
400
  self.haralick_layout.setContentsMargins(20, 20, 20, 20)
@@ -492,7 +510,7 @@ class ConfigMeasurements(QMainWindow):
492
510
 
493
511
  print('Writing instructions...')
494
512
  measurement_options = {}
495
- background_correction = self.background_correction
513
+ background_correction = self.protocol_layout.protocols
496
514
  if not background_correction:
497
515
  background_correction = None
498
516
  measurement_options.update({'background_correction': background_correction})
@@ -581,18 +599,20 @@ class ConfigMeasurements(QMainWindow):
581
599
  measurement_instructions = json.load(f)
582
600
  print(measurement_instructions)
583
601
  if 'background_correction' in measurement_instructions:
584
- self.background_correction = measurement_instructions['background_correction']
585
- if (self.background_correction is not None) and len(self.background_correction) > 0:
586
- self.normalisation_list.clear()
587
- for norm_params in self.background_correction:
602
+ self.protocol_layout.protocols = measurement_instructions['background_correction']
603
+ if self.protocol_layout.protocols is None:
604
+ self.protocol_layout.protocols = []
605
+ if (self.protocol_layout.protocols is not None) and len(self.protocol_layout.protocols) > 0:
606
+ self.protocol_layout.protocol_list.clear()
607
+ for norm_params in self.protocol_layout.protocols:
588
608
  normalisation_description = ""
589
609
  for index, (key, value) in enumerate(norm_params.items()):
590
610
  if index > 0:
591
611
  normalisation_description += ", "
592
612
  normalisation_description += str(key) + " : " + str(value)
593
- self.normalisation_list.addItem(normalisation_description)
613
+ self.protocol_layout.protocol_list.addItem(normalisation_description)
594
614
  else:
595
- self.normalisation_list.clear()
615
+ self.protocol_layout.protocol_list.clear()
596
616
  if 'features' in measurement_instructions:
597
617
  features = measurement_instructions['features']
598
618
  if (features is not None) and len(features) > 0:
@@ -702,30 +722,21 @@ class ConfigMeasurements(QMainWindow):
702
722
  Load the first frame of the first movie found in the experiment folder as a sample.
703
723
  """
704
724
 
705
- movies = glob(self.parent.parent.pos + f"movie/{self.parent.parent.movie_prefix}*.tif")
706
- print(movies)
725
+ movies = glob(self.parent_window.parent_window.pos + os.sep.join(['movie', f"{self.parent_window.movie_prefix}*.tif"]))
726
+
707
727
  if len(movies) == 0:
708
728
  msgBox = QMessageBox()
709
729
  msgBox.setIcon(QMessageBox.Warning)
710
- msgBox.setText("No movies are detected in the experiment folder. Cannot load an image...")
730
+ msgBox.setText("Please select a position containing a movie...")
711
731
  msgBox.setWindowTitle("Warning")
712
732
  msgBox.setStandardButtons(QMessageBox.Ok)
713
733
  returnValue = msgBox.exec()
714
734
  if returnValue == QMessageBox.Ok:
715
- self.test_frame = None
735
+ self.current_stack = None
716
736
  return None
717
737
  else:
718
- self.stack0 = movies[0]
719
- n_channels = len(self.channels)
720
- len_movie_auto = auto_load_number_of_frames(self.stack0)
721
- if len_movie_auto is None:
722
- stack = imread(self.stack0)
723
- len_movie_auto = len(stack)
724
- del stack
725
- gc.collect()
726
- self.mid_time = len_movie_auto // 2
727
- self.test_frame = load_frames(n_channels * self.mid_time + np.arange(n_channels), self.stack0, scale=None,
728
- normalize_input=False)
738
+ self.current_stack = movies[0]
739
+
729
740
 
730
741
  def control_haralick_digitalization(self):
731
742
 
@@ -791,119 +802,21 @@ class ConfigMeasurements(QMainWindow):
791
802
  Show the ROI for the selected contour measurement on experimental data.
792
803
 
793
804
  """
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
805
  self.locate_image()
808
806
 
809
- self.locate_mask()
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()
807
+ if self.current_stack is not None:
897
808
 
898
- else:
899
- msgBox = QMessageBox()
900
- msgBox.setIcon(QMessageBox.Warning)
901
- msgBox.setText("No contour was selected. Please first add a contour to the list.")
902
- msgBox.setWindowTitle("Warning")
903
- msgBox.setStandardButtons(QMessageBox.Ok)
904
- returnValue = msgBox.exec()
905
- if returnValue == QMessageBox.Yes:
906
- return None
809
+ self.viewer = CellEdgeVisualizer(cell_type=self.mode,
810
+ stack_path=self.current_stack,
811
+ parent_list_widget=self.contours_list.list_widget,
812
+ n_channels=len(self.channel_names),
813
+ target_channel=0,
814
+ window_title='Set an edge measurement',
815
+ channel_cb=True,
816
+ channel_names = self.channel_names,
817
+ PxToUm = 1,
818
+ )
819
+ self.viewer.show()
907
820
 
908
821
  def locate_mask(self):
909
822
 
@@ -911,7 +824,7 @@ class ConfigMeasurements(QMainWindow):
911
824
  Load the first mask of the detected movie.
912
825
  """
913
826
 
914
- labels_path = str(Path(self.stack0).parent.parent) + f'/labels_{self.mode}/'
827
+ labels_path = str(Path(self.stack0).parent_window.parent_window) + f'/labels_{self.mode}/'
915
828
  masks = natsorted(glob(labels_path + '*.tif'))
916
829
  if len(masks) == 0:
917
830
  print('no mask found')
@@ -946,207 +859,46 @@ class ConfigMeasurements(QMainWindow):
946
859
  self.im_mask.set_alpha(value)
947
860
  self.fig_contour.canvas.draw_idle()
948
861
 
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)
862
+ # def populate_normalisation_tabs(self):
863
+
864
+ # """
865
+ # Multi-tab options to perform background correction before measurements.
866
+ # """
867
+
868
+ # layout = QVBoxLayout(self.normalisation_frame)
869
+
870
+ # self.normalisation_lbl = QLabel("BACKGROUND CORRECTION")
871
+ # self.normalisation_lbl.setStyleSheet("""
872
+ # font-weight: bold;
873
+ # padding: 0px;
874
+ # """)
875
+ # layout.addWidget(self.normalisation_lbl, alignment=Qt.AlignCenter)
876
+
877
+
878
+ # self.tabs = QTabWidget()
879
+ # self.tabs.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
880
+
881
+ # self.tab1, self.tab2 = QWidget(), QWidget()
882
+ # self.normalisation_list = QListWidget()
883
+ # self.tabs.addTab(self.tab1, 'Local')
884
+ # self.tabs.addTab(self.tab2, 'Field')
885
+ # self.local_correction_layout = LocalCorrectionLayout(self, self.tab1)
886
+ # self.fit_correction_layout = BackgroundFitCorrectionLayout(self, self.tab2)
887
+ # layout.addWidget(self.tabs)
888
+
889
+ # self.norm_list_lbl = QLabel('Background correction to perform:')
890
+ # hbox = QHBoxLayout()
891
+ # hbox.addWidget(self.norm_list_lbl)
892
+ # self.del_norm_btn = QPushButton("")
893
+ # self.del_norm_btn.setStyleSheet(self.button_select_all)
894
+ # self.del_norm_btn.setIcon(icon(MDI6.trash_can, color="black"))
895
+ # self.del_norm_btn.setToolTip("Remove background correction")
896
+ # self.del_norm_btn.setIconSize(QSize(20, 20))
897
+ # hbox.addWidget(self.del_norm_btn, alignment=Qt.AlignRight)
898
+ # layout.addLayout(hbox)
899
+ # self.del_norm_btn.clicked.connect(self.remove_item_from_list)
900
+ # layout.addWidget(self.normalisation_list)
901
+
1150
902
 
1151
903
  def remove_item_from_list(self):
1152
904
  current_item = self.normalisation_list.currentRow()
@@ -1155,6 +907,7 @@ class ConfigMeasurements(QMainWindow):
1155
907
  self.normalisation_list.takeItem(current_item)
1156
908
 
1157
909
  def check_the_information(self):
910
+
1158
911
  if self.tabs.currentIndex() == 0:
1159
912
  if self.background_correction is None:
1160
913
  self.background_correction = []
@@ -1167,38 +920,6 @@ class ConfigMeasurements(QMainWindow):
1167
920
  self.background_correction .remove(normalisation_opt)
1168
921
  self.normalisation_list.takeItem(index)
1169
922
  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
923
 
1203
924
  def display_message_box(self, missing_info):
1204
925
  QMessageBox.about(self, "Message Box Title", "Please " + missing_info + " for background correction")
@@ -1214,46 +935,46 @@ class ConfigMeasurements(QMainWindow):
1214
935
  def fun(self, x, y):
1215
936
  return x ** 2 + y
1216
937
 
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()
938
+ # def preview_normalisation(self):
939
+ # plt.close('all')
940
+ # plt.figure("Intensity Profiles",figsize=(10, 5))
941
+ # self.locate_image()
942
+ # diagonal_length = min(self.test_frame[:, :, self.tab2_channel_dropdown.currentIndex()].shape[0], self.test_frame[:, :, self.tab2_channel_dropdown.currentIndex()].shape[1])
943
+ # if self.tab2_subtract.isChecked():
944
+ # norm_operation='Subtract'
945
+ # else:
946
+ # norm_operation='Divide'
947
+ # normalised, bg_fit = field_normalisation(self.test_frame[:, :, self.tab2_channel_dropdown.currentIndex()],
948
+ # threshold=self.tab2_txt_threshold.text(),
949
+ # normalisation_operation=norm_operation,
950
+ # clip=self.tab2_clip.isChecked(),
951
+ # mode=self.tab2_dropdown.currentText())
952
+ # diagonal_original = [self.test_frame[:, :, self.tab2_channel_dropdown.currentIndex()][i, i] for i in
953
+ # range(diagonal_length)]
954
+ # diagonal_corrected = [normalised[i, i] for i in range(diagonal_length)]
955
+ # diagonal_indices = np.arange(diagonal_length)
956
+
957
+ # plt.subplot(1, 2, 1)
958
+ # plt.plot(diagonal_indices, diagonal_original, color='black', linewidth=0.2) # Adjust linewidth here
959
+ # plt.title('Original Image')
960
+ # plt.xlabel('Pixel Index along Diagonal')
961
+ # plt.ylabel('Intensity')
962
+
963
+ # plt.subplot(1, 2, 2)
964
+ # plt.plot(diagonal_indices, diagonal_corrected, color='black', linewidth=0.2) # Adjust linewidth here
965
+ # plt.title('Corrected Image')
966
+ # plt.xlabel('Pixel Index along Diagonal')
967
+ # plt.ylabel('Intensity')
968
+
969
+ # plt.tight_layout()
970
+ # plt.show()
971
+
972
+ # self.fig, self.ax = plt.subplots()
973
+ # self.normalised_img = FigureCanvas(self.fig, "Corrected background image preview")
974
+ # self.ax.clear()
975
+ # self.ax.imshow(normalised, cmap='gray')
976
+ # self.normalised_img.canvas.draw()
977
+ # self.normalised_img.show()
1257
978
 
1258
979
  def view_normalisation_contour(self):
1259
980
 
@@ -1262,67 +983,27 @@ class ConfigMeasurements(QMainWindow):
1262
983
 
1263
984
  """
1264
985
 
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
986
  self.locate_image()
1278
987
 
1279
- self.locate_mask()
1280
- if self.test_mask is None:
1281
- msgBox = QMessageBox()
1282
- msgBox.setIcon(QMessageBox.Warning)
1283
- msgBox.setText("The segmentation results could not be found for this position.")
1284
- msgBox.setWindowTitle("Warning")
1285
- msgBox.setStandardButtons(QMessageBox.Ok)
1286
- returnValue = msgBox.exec()
1287
- if returnValue == QMessageBox.Yes:
1288
- return None
1289
- else:
1290
- return None
988
+ if self.current_stack is not None:
989
+
990
+ self.viewer = CellEdgeVisualizer(cell_type=self.mode,
991
+ stack_path=self.current_stack,
992
+ parent_le = self.tab1_txt_distance,
993
+ n_channels=len(self.channel_names),
994
+ target_channel=self.tab1_channel_dropdown.currentIndex(),
995
+ edge_range = (0,30),
996
+ initial_edge= self.tab1_txt_distance.get_threshold(),
997
+ invert=True,
998
+ window_title='Set an edge distance to estimate local intensity',
999
+ channel_cb=False,
1000
+ PxToUm = 1,
1001
+ )
1002
+ self.viewer.show()
1291
1003
 
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
1004
 
1325
1005
  def populate_spot_detection(self):
1006
+
1326
1007
  layout = QGridLayout(self.spot_detection_frame)
1327
1008
  self.spot_detection_lbl = QLabel("SPOT DETECTION")
1328
1009
  self.spot_detection_lbl.setStyleSheet("""font-weight: bold;padding: 0px;""")
@@ -1353,7 +1034,7 @@ class ConfigMeasurements(QMainWindow):
1353
1034
  layout.addWidget(self.threshold_value, 4, 1)
1354
1035
  self.preview_spot = QPushButton('Preview')
1355
1036
  self.preview_spot.clicked.connect(self.spot_preview)
1356
- self.preview_spot.setStyleSheet(self.parent.parent.parent.button_style_sheet_2)
1037
+ self.preview_spot.setStyleSheet(self.button_style_sheet_2)
1357
1038
  layout.addWidget(self.preview_spot, 5, 0, 1, 2)
1358
1039
  self.spot_channel.setEnabled(False)
1359
1040
  self.spot_channel_lbl.setEnabled(False)
@@ -1379,7 +1060,7 @@ class ConfigMeasurements(QMainWindow):
1379
1060
  self.locate_mask()
1380
1061
  if self.test_mask is not None:
1381
1062
  self.spot_visual = ThresholdSpot(current_channel=self.spot_channel.currentIndex(), img=self.test_frame,
1382
- mask=self.test_mask, parent=self)
1063
+ mask=self.test_mask, parent_window=self)
1383
1064
  # for dictionary in self.background_correction:
1384
1065
  # if self.spot_channel.currentText() in dictionary['target channel']:
1385
1066
  # if dictionary['mode'] == 'field':