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.
Files changed (63) hide show
  1. celldetective/__main__.py +7 -21
  2. celldetective/events.py +2 -44
  3. celldetective/extra_properties.py +62 -52
  4. celldetective/filters.py +4 -5
  5. celldetective/gui/__init__.py +1 -1
  6. celldetective/gui/analyze_block.py +37 -10
  7. celldetective/gui/btrack_options.py +24 -23
  8. celldetective/gui/classifier_widget.py +62 -19
  9. celldetective/gui/configure_new_exp.py +32 -35
  10. celldetective/gui/control_panel.py +120 -81
  11. celldetective/gui/gui_utils.py +674 -396
  12. celldetective/gui/json_readers.py +7 -6
  13. celldetective/gui/layouts.py +756 -0
  14. celldetective/gui/measurement_options.py +98 -513
  15. celldetective/gui/neighborhood_options.py +322 -270
  16. celldetective/gui/plot_measurements.py +1114 -0
  17. celldetective/gui/plot_signals_ui.py +21 -20
  18. celldetective/gui/process_block.py +449 -169
  19. celldetective/gui/retrain_segmentation_model_options.py +27 -26
  20. celldetective/gui/retrain_signal_model_options.py +25 -24
  21. celldetective/gui/seg_model_loader.py +31 -27
  22. celldetective/gui/signal_annotator.py +2326 -2295
  23. celldetective/gui/signal_annotator_options.py +18 -16
  24. celldetective/gui/styles.py +16 -1
  25. celldetective/gui/survival_ui.py +67 -39
  26. celldetective/gui/tableUI.py +337 -48
  27. celldetective/gui/thresholds_gui.py +75 -71
  28. celldetective/gui/viewers.py +743 -0
  29. celldetective/io.py +247 -27
  30. celldetective/measure.py +43 -263
  31. celldetective/models/segmentation_effectors/primNK_cfse/config_input.json +29 -0
  32. celldetective/models/segmentation_effectors/primNK_cfse/cp-cfse-transfer +0 -0
  33. celldetective/models/segmentation_effectors/primNK_cfse/training_instructions.json +37 -0
  34. celldetective/neighborhood.py +498 -27
  35. celldetective/preprocessing.py +1023 -0
  36. celldetective/scripts/analyze_signals.py +7 -0
  37. celldetective/scripts/measure_cells.py +12 -0
  38. celldetective/scripts/segment_cells.py +20 -4
  39. celldetective/scripts/track_cells.py +11 -0
  40. celldetective/scripts/train_segmentation_model.py +35 -34
  41. celldetective/segmentation.py +14 -9
  42. celldetective/signals.py +234 -329
  43. celldetective/tracking.py +2 -2
  44. celldetective/utils.py +602 -49
  45. celldetective-1.1.1.dist-info/METADATA +305 -0
  46. celldetective-1.1.1.dist-info/RECORD +84 -0
  47. {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/top_level.txt +1 -0
  48. tests/__init__.py +0 -0
  49. tests/test_events.py +28 -0
  50. tests/test_filters.py +24 -0
  51. tests/test_io.py +70 -0
  52. tests/test_measure.py +141 -0
  53. tests/test_neighborhood.py +70 -0
  54. tests/test_preprocessing.py +37 -0
  55. tests/test_segmentation.py +93 -0
  56. tests/test_signals.py +135 -0
  57. tests/test_tracking.py +164 -0
  58. tests/test_utils.py +118 -0
  59. celldetective-1.0.2.post1.dist-info/METADATA +0 -221
  60. celldetective-1.0.2.post1.dist-info/RECORD +0 -66
  61. {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/LICENSE +0 -0
  62. {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/WHEEL +0 -0
  63. {celldetective-1.0.2.post1.dist-info → celldetective-1.1.1.dist-info}/entry_points.txt +0 -0
@@ -12,7 +12,7 @@ from skimage.morphology import disk
12
12
 
13
13
  from celldetective.filters import std_filter, gauss_filter
14
14
  from celldetective.gui.gui_utils import center_window, FigureCanvas, ListWidget, FilterChoice, color_from_class
15
- from celldetective.utils import get_software_location, extract_experiment_channels, rename_intensity_column
15
+ from celldetective.utils import get_software_location, extract_experiment_channels, rename_intensity_column, estimate_unreliable_edge
16
16
  from celldetective.io import auto_load_number_of_frames, load_frames
17
17
  from celldetective.segmentation import threshold_image, identify_markers_from_binary, apply_watershed, \
18
18
  segment_frame_from_thresholds
@@ -30,19 +30,21 @@ from skimage.measure import regionprops_table
30
30
  import json
31
31
  import os
32
32
 
33
+ from celldetective.gui.viewers import StackVisualizer
34
+ from celldetective.gui import Styles
33
35
 
34
- class ThresholdConfigWizard(QMainWindow):
36
+ class ThresholdConfigWizard(QMainWindow, Styles):
35
37
  """
36
38
  UI to create a threshold pipeline for segmentation.
37
39
 
38
40
  """
39
41
 
40
- def __init__(self, parent=None):
42
+ def __init__(self, parent_window=None):
41
43
 
42
44
  super().__init__()
43
- self.parent = parent
44
- self.screen_height = self.parent.parent.parent.parent.screen_height
45
- self.screen_width = self.parent.parent.parent.parent.screen_width
45
+ self.parent_window = parent_window
46
+ self.screen_height = self.parent_window.parent_window.parent_window.parent_window.screen_height
47
+ self.screen_width = self.parent_window.parent_window.parent_window.parent_window.screen_width
46
48
  self.setMinimumWidth(int(0.8 * self.screen_width))
47
49
  self.setMinimumHeight(int(0.8 * self.screen_height))
48
50
  self.setWindowTitle("Threshold configuration wizard")
@@ -50,15 +52,16 @@ class ThresholdConfigWizard(QMainWindow):
50
52
  self._createActions()
51
53
  self._createMenuBar()
52
54
 
53
- self.mode = self.parent.mode
54
- self.pos = self.parent.parent.parent.pos
55
- self.exp_dir = self.parent.parent.exp_dir
55
+ self.mode = self.parent_window.mode
56
+ self.pos = self.parent_window.parent_window.parent_window.pos
57
+ self.exp_dir = self.parent_window.parent_window.exp_dir
56
58
  self.soft_path = get_software_location()
57
59
  self.footprint = 30
58
60
  self.min_dist = 30
59
61
  self.onlyFloat = QDoubleValidator()
60
62
  self.onlyInt = QIntValidator()
61
63
  self.cell_properties = ['centroid', 'area', 'perimeter', 'eccentricity', 'intensity_mean', 'solidity']
64
+ self.edge = None
62
65
 
63
66
  if self.mode == "targets":
64
67
  self.config_out_name = "threshold_targets.json"
@@ -157,14 +160,14 @@ class ThresholdConfigWizard(QMainWindow):
157
160
  filter_list_option_grid.addWidget(section_preprocess, 90, alignment=Qt.AlignLeft)
158
161
 
159
162
  self.delete_filter = QPushButton("")
160
- self.delete_filter.setStyleSheet(self.parent.parent.parent.parent.button_select_all)
163
+ self.delete_filter.setStyleSheet(self.button_select_all)
161
164
  self.delete_filter.setIcon(icon(MDI6.trash_can, color="black"))
162
165
  self.delete_filter.setToolTip("Remove filter")
163
166
  self.delete_filter.setIconSize(QSize(20, 20))
164
167
  self.delete_filter.clicked.connect(self.filters_qlist.removeSel)
165
168
 
166
169
  self.add_filter = QPushButton("")
167
- self.add_filter.setStyleSheet(self.parent.parent.parent.parent.button_select_all)
170
+ self.add_filter.setStyleSheet(self.button_select_all)
168
171
  self.add_filter.setIcon(icon(MDI6.filter_plus, color="black"))
169
172
  self.add_filter.setToolTip("Add filter")
170
173
  self.add_filter.setIconSize(QSize(20, 20))
@@ -180,7 +183,7 @@ class ThresholdConfigWizard(QMainWindow):
180
183
  self.apply_filters_btn = QPushButton("Apply")
181
184
  self.apply_filters_btn.setIcon(icon(MDI6.filter_cog_outline, color="white"))
182
185
  self.apply_filters_btn.setIconSize(QSize(20, 20))
183
- self.apply_filters_btn.setStyleSheet(self.parent.parent.parent.parent.button_style_sheet)
186
+ self.apply_filters_btn.setStyleSheet(self.button_style_sheet)
184
187
  self.apply_filters_btn.clicked.connect(self.preprocess_image)
185
188
  grid_preprocess.addWidget(self.apply_filters_btn, 2, 0, 1, 3)
186
189
 
@@ -201,14 +204,14 @@ class ThresholdConfigWizard(QMainWindow):
201
204
 
202
205
  self.ylog_check = QPushButton("")
203
206
  self.ylog_check.setIcon(icon(MDI6.math_log, color="black"))
204
- self.ylog_check.setStyleSheet(self.parent.parent.parent.parent.button_select_all)
207
+ self.ylog_check.setStyleSheet(self.button_select_all)
205
208
  self.ylog_check.clicked.connect(self.switch_to_log)
206
209
  threshold_title_grid.addWidget(self.ylog_check, 5)
207
210
 
208
211
  self.equalize_option_btn = QPushButton("")
209
212
  self.equalize_option_btn.setIcon(icon(MDI6.equalizer, color="black"))
210
213
  self.equalize_option_btn.setIconSize(QSize(20, 20))
211
- self.equalize_option_btn.setStyleSheet(self.parent.parent.parent.parent.button_select_all)
214
+ self.equalize_option_btn.setStyleSheet(self.button_select_all)
212
215
  self.equalize_option_btn.setToolTip("Enable histogram matching")
213
216
  self.equalize_option_btn.clicked.connect(self.activate_histogram_equalizer)
214
217
  self.equalize_option = False
@@ -223,7 +226,7 @@ class ThresholdConfigWizard(QMainWindow):
223
226
  self.threshold_slider.setTickInterval(0.00001)
224
227
  self.threshold_slider.setOrientation(1)
225
228
  self.threshold_slider.setDecimals(3)
226
- self.threshold_slider.setRange(np.amin(self.img), np.amax(self.img))
229
+ self.threshold_slider.setRange(np.amin(self.img[self.img==self.img]), np.amax(self.img[self.img==self.img]))
227
230
  self.threshold_slider.setValue([np.percentile(self.img.flatten(), 90), np.amax(self.img)])
228
231
  self.threshold_slider.valueChanged.connect(self.threshold_changed)
229
232
 
@@ -246,7 +249,7 @@ class ThresholdConfigWizard(QMainWindow):
246
249
  #################
247
250
 
248
251
  self.save_btn = QPushButton('Save')
249
- self.save_btn.setStyleSheet(self.parent.parent.parent.parent.button_style_sheet)
252
+ self.save_btn.setStyleSheet(self.button_style_sheet)
250
253
  self.save_btn.clicked.connect(self.write_instructions)
251
254
  self.left_panel.addWidget(self.save_btn)
252
255
 
@@ -290,14 +293,14 @@ class ThresholdConfigWizard(QMainWindow):
290
293
 
291
294
  self.markers_btn = QPushButton("Run")
292
295
  self.markers_btn.clicked.connect(self.detect_markers)
293
- self.markers_btn.setStyleSheet(self.parent.parent.parent.parent.button_style_sheet)
296
+ self.markers_btn.setStyleSheet(self.button_style_sheet)
294
297
  hbox_marker_btns.addWidget(self.markers_btn)
295
298
 
296
299
  self.watershed_btn = QPushButton("Watershed")
297
300
  self.watershed_btn.setIcon(icon(MDI6.waves_arrow_up, color="white"))
298
301
  self.watershed_btn.setIconSize(QSize(20, 20))
299
302
  self.watershed_btn.clicked.connect(self.apply_watershed_to_selection)
300
- self.watershed_btn.setStyleSheet(self.parent.parent.parent.parent.button_style_sheet)
303
+ self.watershed_btn.setStyleSheet(self.button_style_sheet)
301
304
  self.watershed_btn.setEnabled(False)
302
305
  hbox_marker_btns.addWidget(self.watershed_btn)
303
306
  marker_box.addLayout(hbox_marker_btns)
@@ -329,7 +332,7 @@ class ThresholdConfigWizard(QMainWindow):
329
332
  'eliminate points using a query such as: area > 100 or eccentricity > 0.95')
330
333
  hbox_classify.addWidget(self.property_query_le, 70)
331
334
  self.submit_query_btn = QPushButton('Submit...')
332
- self.submit_query_btn.setStyleSheet(self.parent.parent.parent.parent.button_style_sheet)
335
+ self.submit_query_btn.setStyleSheet(self.button_style_sheet)
333
336
  self.submit_query_btn.clicked.connect(self.apply_property_query)
334
337
  hbox_classify.addWidget(self.submit_query_btn, 20)
335
338
  properties_box.addLayout(hbox_classify)
@@ -367,7 +370,7 @@ class ThresholdConfigWizard(QMainWindow):
367
370
  self.contrast_slider.setSingleStep(0.00001)
368
371
  self.contrast_slider.setTickInterval(0.00001)
369
372
  self.contrast_slider.setOrientation(1)
370
- self.contrast_slider.setRange(np.amin(self.img), np.amax(self.img))
373
+ self.contrast_slider.setRange(np.amin(self.img[self.img==self.img]), np.amax(self.img[self.img==self.img]))
371
374
  self.contrast_slider.setValue([np.percentile(self.img.flatten(), 1), np.percentile(self.img.flatten(), 99.99)])
372
375
  self.contrast_slider.valueChanged.connect(self.contrast_slider_action)
373
376
  contrast_hbox.addWidget(QLabel('contrast: '))
@@ -383,7 +386,7 @@ class ThresholdConfigWizard(QMainWindow):
383
386
 
384
387
  print("this is the loaded position: ", self.pos)
385
388
  if isinstance(self.pos, str):
386
- movies = glob(self.pos + f"movie/{self.parent.parent.parent.movie_prefix}*.tif")
389
+ movies = glob(self.pos + f"movie/{self.parent_window.parent_window.parent_window.movie_prefix}*.tif")
387
390
 
388
391
  else:
389
392
  msgBox = QMessageBox()
@@ -392,10 +395,9 @@ class ThresholdConfigWizard(QMainWindow):
392
395
  msgBox.setWindowTitle("Warning")
393
396
  msgBox.setStandardButtons(QMessageBox.Ok)
394
397
  returnValue = msgBox.exec()
395
- if returnValue == QMessageBox.Ok:
396
- self.img = None
397
- self.close()
398
- return None
398
+ self.img = None
399
+ self.close()
400
+ return None
399
401
 
400
402
  if len(movies) == 0:
401
403
  msgBox = QMessageBox()
@@ -404,11 +406,11 @@ class ThresholdConfigWizard(QMainWindow):
404
406
  msgBox.setWindowTitle("Warning")
405
407
  msgBox.setStandardButtons(QMessageBox.Ok)
406
408
  returnValue = msgBox.exec()
407
- if returnValue == QMessageBox.Yes:
408
- self.close()
409
+ self.img = None
410
+ self.close()
409
411
  else:
410
412
  self.stack_path = movies[0]
411
- self.len_movie = self.parent.parent.parent.len_movie
413
+ self.len_movie = self.parent_window.parent_window.parent_window.len_movie
412
414
  len_movie_auto = auto_load_number_of_frames(self.stack_path)
413
415
  if len_movie_auto is not None:
414
416
  self.len_movie = len_movie_auto
@@ -436,7 +438,7 @@ class ThresholdConfigWizard(QMainWindow):
436
438
  self.im = self.ax.imshow(self.img, cmap='gray')
437
439
 
438
440
  self.binary = threshold_image(self.img, self.threshold_slider.value()[0], self.threshold_slider.value()[1],
439
- foreground_value=255., fill_holes=False)
441
+ foreground_value=1., fill_holes=True, edge_exclusion=None)
440
442
  self.thresholded_image = np.ma.masked_where(self.binary == 0., self.binary)
441
443
  self.image_thresholded = self.ax.imshow(self.thresholded_image, cmap="viridis", alpha=0.5, interpolation='none')
442
444
 
@@ -480,10 +482,10 @@ class ThresholdConfigWizard(QMainWindow):
480
482
  self.ax_hist.spines['top'].set_visible(False)
481
483
  self.ax_hist.spines['right'].set_visible(False)
482
484
  # self.ax_hist.set_yticks([])
483
- self.ax_hist.set_xlim(np.amin(self.img), np.amax(self.img))
485
+ self.ax_hist.set_xlim(np.amin(self.img[self.img==self.img]), np.amax(self.img[self.img==self.img]))
484
486
  self.ax_hist.set_ylim(0, self.hist_y.max())
485
487
 
486
- self.threshold_slider.setRange(np.amin(self.img), np.amax(self.img))
488
+ self.threshold_slider.setRange(np.amin(self.img[self.img==self.img]), np.amax(self.img[self.img==self.img]))
487
489
  self.threshold_slider.setValue([np.nanpercentile(self.img.flatten(), 90), np.amax(self.img)])
488
490
  self.add_hist_threshold()
489
491
 
@@ -505,12 +507,12 @@ class ThresholdConfigWizard(QMainWindow):
505
507
  self.ax_hist.spines['top'].set_visible(False)
506
508
  self.ax_hist.spines['right'].set_visible(False)
507
509
  # self.ax_hist.set_yticks([])
508
- self.ax_hist.set_xlim(np.amin(self.img), np.amax(self.img))
510
+ self.ax_hist.set_xlim(np.amin(self.img[self.img==self.img]), np.amax(self.img[self.img==self.img]))
509
511
  self.ax_hist.set_ylim(0, self.hist_y.max())
510
512
  self.add_hist_threshold()
511
513
  self.canvas_hist.canvas.draw()
512
514
 
513
- self.threshold_slider.setRange(np.amin(self.img), np.amax(self.img))
515
+ self.threshold_slider.setRange(np.amin(self.img[self.img==self.img]), np.amax(self.img[self.img==self.img]))
514
516
  self.threshold_slider.setValue([np.nanpercentile(self.img.flatten(), 90), np.amax(self.img)])
515
517
  self.threshold_changed(self.threshold_slider.value())
516
518
 
@@ -571,7 +573,7 @@ class ThresholdConfigWizard(QMainWindow):
571
573
  self.vmax = np.nanpercentile(self.img.flatten(), 99.)
572
574
 
573
575
  self.contrast_slider.disconnect()
574
- self.contrast_slider.setRange(np.amin(self.img), np.amax(self.img))
576
+ self.contrast_slider.setRange(np.amin(self.img[self.img==self.img]), np.amax(self.img[self.img==self.img]))
575
577
  self.contrast_slider.setValue([self.vmin, self.vmax])
576
578
  self.contrast_slider.valueChanged.connect(self.contrast_slider_action)
577
579
 
@@ -590,6 +592,7 @@ class ThresholdConfigWizard(QMainWindow):
590
592
 
591
593
  self.reload_frame()
592
594
  filters = self.filters_qlist.items
595
+ self.edge = estimate_unreliable_edge(filters)
593
596
  self.img = filter_image(self.img, filters)
594
597
  self.refresh_imshow()
595
598
  self.update_histogram()
@@ -636,7 +639,7 @@ class ThresholdConfigWizard(QMainWindow):
636
639
  """
637
640
 
638
641
  self.binary = threshold_image(self.img, self.threshold_slider.value()[0], self.threshold_slider.value()[1],
639
- foreground_value=255., fill_holes=False)
642
+ foreground_value=1., fill_holes=True, edge_exclusion=self.edge)
640
643
  self.thresholded_image = np.ma.masked_where(self.binary == 0., self.binary)
641
644
  self.image_thresholded.set_data(self.thresholded_image)
642
645
  self.fcanvas.canvas.draw_idle()
@@ -657,7 +660,7 @@ class ThresholdConfigWizard(QMainWindow):
657
660
 
658
661
  if self.binary.ndim == 3:
659
662
  self.binary = np.squeeze(self.binary)
660
- self.binary = binary_fill_holes(self.binary)
663
+ #self.binary = binary_fill_holes(self.binary)
661
664
  self.coords, self.edt_map = identify_markers_from_binary(self.binary, self.min_dist,
662
665
  footprint_size=self.footprint, footprint=None,
663
666
  return_edt=True)
@@ -784,7 +787,7 @@ class ThresholdConfigWizard(QMainWindow):
784
787
  self.property_query_le.setText('')
785
788
 
786
789
  self.binary = threshold_image(self.img, self.threshold_slider.value()[0], self.threshold_slider.value()[1],
787
- foreground_value=255., fill_holes=False)
790
+ foreground_value=1., fill_holes=True, edge_exclusion=self.edge)
788
791
  self.thresholded_image = np.ma.masked_where(self.binary == 0., self.binary)
789
792
 
790
793
  self.scat_markers.set_color('tab:red')
@@ -815,9 +818,9 @@ class ThresholdConfigWizard(QMainWindow):
815
818
  outfile.write(json_object)
816
819
  print("Configuration successfully written in ", self.instruction_file)
817
820
 
818
- self.parent.filename = self.instruction_file
819
- self.parent.file_label.setText(self.instruction_file[:16] + '...')
820
- self.parent.file_label.setToolTip(self.instruction_file)
821
+ self.parent_window.filename = self.instruction_file
822
+ self.parent_window.file_label.setText(self.instruction_file[:16] + '...')
823
+ self.parent_window.file_label.setToolTip(self.instruction_file)
821
824
 
822
825
  self.close()
823
826
  else:
@@ -872,11 +875,11 @@ class ThresholdConfigWizard(QMainWindow):
872
875
 
873
876
 
874
877
  class ThresholdNormalisation(ThresholdConfigWizard):
875
- def __init__(self, min_threshold, current_channel, parent=None):
878
+ def __init__(self, min_threshold, current_channel, parent_window=None):
876
879
  QMainWindow.__init__(self)
877
- self.parent = parent
878
- self.screen_height = self.parent.parent.parent.parent.screen_height
879
- self.screen_width = self.parent.parent.parent.parent.screen_width
880
+ self.parent_window = parent_window
881
+ self.screen_height = self.parent_window.parent_window.parent_window.parent_window.screen_height
882
+ self.screen_width = self.parent_window.parent_window.parent_window.parent_window.screen_width
880
883
  self.setMaximumWidth(int(self.screen_width // 3))
881
884
  self.setMinimumHeight(int(0.8 * self.screen_height))
882
885
  self.setWindowTitle("Normalisation threshold preview")
@@ -884,9 +887,9 @@ class ThresholdNormalisation(ThresholdConfigWizard):
884
887
  self.img = None
885
888
  self.min_threshold = min_threshold
886
889
  self.current_channel = current_channel
887
- self.mode = self.parent.mode
888
- self.pos = self.parent.parent.parent.pos
889
- self.exp_dir = self.parent.parent.exp_dir
890
+ self.mode = self.parent_window.mode
891
+ self.pos = self.parent_window.parent_window.parent_window.pos
892
+ self.exp_dir = self.parent_window.parent_window.exp_dir
890
893
  self.soft_path = get_software_location()
891
894
  self.auto_close = False
892
895
 
@@ -945,7 +948,7 @@ class ThresholdNormalisation(ThresholdConfigWizard):
945
948
  self.contrast_slider.setSingleStep(0.00001)
946
949
  self.contrast_slider.setTickInterval(0.00001)
947
950
  self.contrast_slider.setOrientation(1)
948
- self.contrast_slider.setRange(np.amin(self.frame), np.amax(self.frame))
951
+ self.contrast_slider.setRange(np.amin(self.frame[self.frame==self.frame]), np.amax(self.frame[self.frame==self.frame]))
949
952
  self.contrast_slider.setValue(
950
953
  [np.percentile(self.frame.flatten(), 1), np.percentile(self.frame.flatten(), 99.99)])
951
954
  self.contrast_slider.valueChanged.connect(self.contrast_slider_action)
@@ -954,11 +957,11 @@ class ThresholdNormalisation(ThresholdConfigWizard):
954
957
  contrast_slider_layout.addWidget(self.contrast_slider)
955
958
 
956
959
  self.submit_threshold_btn = QPushButton('Submit')
957
- self.submit_threshold_btn.setStyleSheet(self.parent.parent.parent.parent.button_style_sheet_2)
960
+ self.submit_threshold_btn.setStyleSheet(self.button_style_sheet_2)
958
961
  self.submit_threshold_btn.clicked.connect(self.get_threshold)
959
962
  self.ylog_check = QPushButton("")
960
963
  self.ylog_check.setIcon(icon(MDI6.math_log, color="black"))
961
- self.ylog_check.setStyleSheet(self.parent.parent.parent.parent.button_select_all)
964
+ self.ylog_check.setStyleSheet(self.button_select_all)
962
965
  self.ylog_check.clicked.connect(self.switch_to_log)
963
966
  self.ylog_check.setMaximumWidth(30)
964
967
  log_button = QHBoxLayout()
@@ -989,11 +992,11 @@ class ThresholdNormalisation(ThresholdConfigWizard):
989
992
  self.ax_hist.set_xlabel('intensity [a.u.]')
990
993
  self.ax_hist.spines['top'].set_visible(False)
991
994
  self.ax_hist.spines['right'].set_visible(False)
992
- self.ax_hist.set_xlim(np.amin(self.frame), np.amax(self.frame))
995
+ self.ax_hist.set_xlim(np.amin(self.frame[self.frame==self.frame]), np.amax(self.frame[self.frame==self.frame]))
993
996
  self.ax_hist.set_ylim(0, self.hist_y.max())
994
997
  self.threshold_slider.setSingleStep(0.001)
995
998
  self.threshold_slider.setTickInterval(0.001)
996
- self.threshold_slider.setRange(np.amin(self.frame), np.amax(self.frame))
999
+ self.threshold_slider.setRange(np.amin(self.frame[self.frame==self.frame]), np.amax(self.frame[self.frame==self.frame]))
997
1000
  self.threshold_slider.setValue(np.percentile(self.frame,90))
998
1001
  self.add_hist_threshold()
999
1002
 
@@ -1054,7 +1057,7 @@ class ThresholdNormalisation(ThresholdConfigWizard):
1054
1057
  """
1055
1058
 
1056
1059
  if isinstance(self.pos, str):
1057
- movies = glob(self.pos + f"movie/{self.parent.parent.parent.movie_prefix}*.tif")
1060
+ movies = glob(self.pos + f"movie/{self.parent_window.parent_window.parent_window.movie_prefix}*.tif")
1058
1061
  else:
1059
1062
  msgBox = QMessageBox()
1060
1063
  msgBox.setIcon(QMessageBox.Warning)
@@ -1080,7 +1083,7 @@ class ThresholdNormalisation(ThresholdConfigWizard):
1080
1083
  return None
1081
1084
  else:
1082
1085
  self.stack_path = movies[0]
1083
- self.len_movie = self.parent.parent.parent.len_movie
1086
+ self.len_movie = self.parent_window.parent_window.parent_window.len_movie
1084
1087
  len_movie_auto = auto_load_number_of_frames(self.stack_path)
1085
1088
  if len_movie_auto is not None:
1086
1089
  self.len_movie = len_movie_auto
@@ -1096,24 +1099,24 @@ class ThresholdNormalisation(ThresholdConfigWizard):
1096
1099
  print(f'{self.stack_path} successfully located.')
1097
1100
 
1098
1101
  def get_threshold(self):
1099
- self.parent.tab2_txt_threshold.setText(str(self.threshold_slider.value()))
1102
+ self.parent_window.tab2_txt_threshold.setText(str(self.threshold_slider.value()))
1100
1103
  self.close()
1101
1104
 
1102
1105
 
1103
1106
  class ThresholdSpot(ThresholdConfigWizard):
1104
- def __init__(self, current_channel, img, mask, parent=None):
1107
+ def __init__(self, current_channel, img, mask, parent_window=None):
1105
1108
  QMainWindow.__init__(self)
1106
- self.parent = parent
1107
- self.screen_height = self.parent.parent.parent.parent.screen_height
1108
- self.screen_width = self.parent.parent.parent.parent.screen_width
1109
+ self.parent_window = parent_window
1110
+ self.screen_height = self.parent_window.parent_window.parent_window.parent_window.screen_height
1111
+ self.screen_width = self.parent_window.parent_window.parent_window.parent_window.screen_width
1109
1112
  self.setMinimumHeight(int(0.8 * self.screen_height))
1110
1113
  self.setWindowTitle("Spot threshold preview")
1111
1114
  center_window(self)
1112
1115
  self.img = img
1113
1116
  self.current_channel = current_channel
1114
- self.mode = self.parent.mode
1115
- self.pos = self.parent.parent.parent.pos
1116
- self.exp_dir = self.parent.parent.exp_dir
1117
+ self.mode = self.parent_window.mode
1118
+ self.pos = self.parent_window.parent_window.parent_window.pos
1119
+ self.exp_dir = self.parent_window.parent_window.exp_dir
1117
1120
  self.onlyFloat = QDoubleValidator()
1118
1121
  self.onlyInt = QIntValidator()
1119
1122
  self.soft_path = get_software_location()
@@ -1135,7 +1138,7 @@ class ThresholdSpot(ThresholdConfigWizard):
1135
1138
  diameter_layout=QHBoxLayout()
1136
1139
  self.diameter_lbl = QLabel('Spot diameter: ')
1137
1140
  self.diameter_value = QLineEdit()
1138
- self.diameter_value.setText(self.parent.diameter_value.text())
1141
+ self.diameter_value.setText(self.parent_window.diameter_value.text())
1139
1142
  self.diameter_value.setValidator(self.onlyFloat)
1140
1143
  diameter_layout.addWidget(self.diameter_lbl, alignment=Qt.AlignCenter)
1141
1144
  diameter_layout.addWidget(self.diameter_value, alignment=Qt.AlignCenter)
@@ -1144,7 +1147,7 @@ class ThresholdSpot(ThresholdConfigWizard):
1144
1147
  self.threshold_lbl = QLabel('Spot threshold: ')
1145
1148
  self.threshold_value = QLineEdit()
1146
1149
  self.threshold_value.setValidator(self.onlyFloat)
1147
- self.threshold_value.setText(self.parent.threshold_value.text())
1150
+ self.threshold_value.setText(self.parent_window.threshold_value.text())
1148
1151
  threshold_layout.addWidget(self.threshold_lbl, alignment=Qt.AlignCenter)
1149
1152
  threshold_layout.addWidget(self.threshold_value, alignment=Qt.AlignCenter)
1150
1153
  self.left_layout.addLayout(threshold_layout)
@@ -1162,14 +1165,14 @@ class ThresholdSpot(ThresholdConfigWizard):
1162
1165
  def draw_spot_preview(self):
1163
1166
 
1164
1167
  try:
1165
- diameter_value = float(self.parent.diameter_value.text().replace(',','.'))
1168
+ diameter_value = float(self.parent_window.diameter_value.text().replace(',','.'))
1166
1169
  except:
1167
1170
  print('Diameter could not be converted to float... Abort.')
1168
1171
  self.auto_close = True
1169
1172
  return None
1170
1173
 
1171
1174
  try:
1172
- threshold_value = float(self.parent.threshold_value.text().replace(',','.'))
1175
+ threshold_value = float(self.parent_window.threshold_value.text().replace(',','.'))
1173
1176
  except:
1174
1177
  print('Threshold could not be converted to float... Abort.')
1175
1178
  self.auto_close = True
@@ -1212,7 +1215,8 @@ class ThresholdSpot(ThresholdConfigWizard):
1212
1215
  self.contrast_slider.setSingleStep(0.00001)
1213
1216
  self.contrast_slider.setTickInterval(0.00001)
1214
1217
  self.contrast_slider.setOrientation(1)
1215
- self.contrast_slider.setRange(np.amin(self.frame[:, :, self.current_channel]), np.amax(self.frame[:, :, self.current_channel]))
1218
+ selection = self.frame[:, :, self.current_channel]
1219
+ self.contrast_slider.setRange(np.amin(selection[selection==selection]), np.amax(selection[selection==selection]))
1216
1220
  self.contrast_slider.setValue(
1217
1221
  [np.percentile(self.frame[:, :, self.current_channel].flatten(), 1), np.percentile(self.frame[:, :, self.current_channel].flatten(), 99.99)])
1218
1222
  self.contrast_slider.valueChanged.connect(self.contrast_slider_action)
@@ -1221,9 +1225,9 @@ class ThresholdSpot(ThresholdConfigWizard):
1221
1225
  contrast_slider_layout.addWidget(self.contrast_slider)
1222
1226
  self.preview_button=QPushButton("Preview")
1223
1227
  self.preview_button.clicked.connect(self.update_spots)
1224
- self.preview_button.setStyleSheet(self.parent.parent.parent.parent.button_style_sheet_2)
1228
+ self.preview_button.setStyleSheet(self.button_style_sheet_2)
1225
1229
  self.apply_changes=QPushButton("Apply")
1226
- self.apply_changes.setStyleSheet(self.parent.parent.parent.parent.button_style_sheet)
1230
+ self.apply_changes.setStyleSheet(self.button_style_sheet)
1227
1231
  self.apply_changes.clicked.connect(self.apply)
1228
1232
 
1229
1233
  self.diameter_value.textChanged.connect(self.enable_preview)
@@ -1291,8 +1295,8 @@ class ThresholdSpot(ThresholdConfigWizard):
1291
1295
 
1292
1296
 
1293
1297
  def apply(self):
1294
- self.parent.threshold_value.setText(self.threshold_value.text())
1295
- self.parent.diameter_value.setText(self.diameter_value.text())
1298
+ self.parent_window.threshold_value.setText(self.threshold_value.text())
1299
+ self.parent_window.diameter_value.setText(self.diameter_value.text())
1296
1300
  self.close()
1297
1301
 
1298
1302