celldetective 1.3.9.post5__py3-none-any.whl → 1.4.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 (94) hide show
  1. celldetective/__init__.py +0 -3
  2. celldetective/_version.py +1 -1
  3. celldetective/events.py +2 -4
  4. celldetective/exceptions.py +11 -0
  5. celldetective/extra_properties.py +132 -0
  6. celldetective/filters.py +7 -1
  7. celldetective/gui/InitWindow.py +37 -46
  8. celldetective/gui/__init__.py +3 -9
  9. celldetective/gui/about.py +19 -15
  10. celldetective/gui/analyze_block.py +34 -19
  11. celldetective/gui/base_annotator.py +786 -0
  12. celldetective/gui/base_components.py +23 -0
  13. celldetective/gui/classifier_widget.py +86 -94
  14. celldetective/gui/configure_new_exp.py +163 -46
  15. celldetective/gui/control_panel.py +76 -146
  16. celldetective/gui/{signal_annotator.py → event_annotator.py} +533 -1438
  17. celldetective/gui/generic_signal_plot.py +11 -13
  18. celldetective/gui/gui_utils.py +54 -23
  19. celldetective/gui/help/neighborhood.json +2 -2
  20. celldetective/gui/json_readers.py +5 -4
  21. celldetective/gui/layouts.py +265 -31
  22. celldetective/gui/{signal_annotator2.py → pair_event_annotator.py} +433 -635
  23. celldetective/gui/plot_measurements.py +21 -17
  24. celldetective/gui/plot_signals_ui.py +125 -72
  25. celldetective/gui/process_block.py +283 -188
  26. celldetective/gui/processes/compute_neighborhood.py +594 -0
  27. celldetective/gui/processes/downloader.py +37 -34
  28. celldetective/gui/processes/measure_cells.py +19 -8
  29. celldetective/gui/processes/segment_cells.py +47 -11
  30. celldetective/gui/processes/track_cells.py +18 -13
  31. celldetective/gui/seg_model_loader.py +21 -62
  32. celldetective/gui/settings/__init__.py +7 -0
  33. celldetective/gui/settings/_settings_base.py +70 -0
  34. celldetective/gui/{retrain_signal_model_options.py → settings/_settings_event_model_training.py} +54 -109
  35. celldetective/gui/{measurement_options.py → settings/_settings_measurements.py} +54 -92
  36. celldetective/gui/{neighborhood_options.py → settings/_settings_neighborhood.py} +10 -13
  37. celldetective/gui/settings/_settings_segmentation.py +49 -0
  38. celldetective/gui/{retrain_segmentation_model_options.py → settings/_settings_segmentation_model_training.py} +38 -92
  39. celldetective/gui/{signal_annotator_options.py → settings/_settings_signal_annotator.py} +78 -103
  40. celldetective/gui/{btrack_options.py → settings/_settings_tracking.py} +85 -116
  41. celldetective/gui/styles.py +2 -1
  42. celldetective/gui/survival_ui.py +49 -95
  43. celldetective/gui/tableUI.py +53 -25
  44. celldetective/gui/table_ops/__init__.py +0 -0
  45. celldetective/gui/table_ops/merge_groups.py +118 -0
  46. celldetective/gui/thresholds_gui.py +617 -1221
  47. celldetective/gui/viewers.py +107 -42
  48. celldetective/gui/workers.py +8 -4
  49. celldetective/io.py +137 -57
  50. celldetective/links/zenodo.json +145 -144
  51. celldetective/measure.py +94 -53
  52. celldetective/neighborhood.py +342 -268
  53. celldetective/preprocessing.py +56 -35
  54. celldetective/regionprops/_regionprops.py +16 -5
  55. celldetective/relative_measurements.py +50 -29
  56. celldetective/scripts/analyze_signals.py +4 -1
  57. celldetective/scripts/measure_cells.py +5 -5
  58. celldetective/scripts/measure_relative.py +20 -12
  59. celldetective/scripts/segment_cells.py +4 -10
  60. celldetective/scripts/segment_cells_thresholds.py +3 -3
  61. celldetective/scripts/track_cells.py +10 -8
  62. celldetective/scripts/train_segmentation_model.py +18 -6
  63. celldetective/signals.py +29 -14
  64. celldetective/tracking.py +14 -3
  65. celldetective/utils.py +91 -62
  66. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/METADATA +24 -16
  67. celldetective-1.4.1.dist-info/RECORD +123 -0
  68. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/WHEEL +1 -1
  69. tests/gui/__init__.py +0 -0
  70. tests/gui/test_new_project.py +228 -0
  71. tests/gui/test_project.py +99 -0
  72. tests/test_preprocessing.py +2 -2
  73. celldetective/models/segmentation_effectors/ricm_bf_all_last/config_input.json +0 -79
  74. celldetective/models/segmentation_effectors/ricm_bf_all_last/ricm_bf_all_last +0 -0
  75. celldetective/models/segmentation_effectors/ricm_bf_all_last/training_instructions.json +0 -37
  76. celldetective/models/segmentation_effectors/test-transfer/config_input.json +0 -39
  77. celldetective/models/segmentation_effectors/test-transfer/test-transfer +0 -0
  78. celldetective/models/signal_detection/NucCond/classification_loss.png +0 -0
  79. celldetective/models/signal_detection/NucCond/classifier.h5 +0 -0
  80. celldetective/models/signal_detection/NucCond/config_input.json +0 -1
  81. celldetective/models/signal_detection/NucCond/log_classifier.csv +0 -126
  82. celldetective/models/signal_detection/NucCond/log_regressor.csv +0 -282
  83. celldetective/models/signal_detection/NucCond/regression_loss.png +0 -0
  84. celldetective/models/signal_detection/NucCond/regressor.h5 +0 -0
  85. celldetective/models/signal_detection/NucCond/scores.npy +0 -0
  86. celldetective/models/signal_detection/NucCond/test_confusion_matrix.png +0 -0
  87. celldetective/models/signal_detection/NucCond/test_regression.png +0 -0
  88. celldetective/models/signal_detection/NucCond/validation_confusion_matrix.png +0 -0
  89. celldetective/models/signal_detection/NucCond/validation_regression.png +0 -0
  90. celldetective-1.3.9.post5.dist-info/RECORD +0 -129
  91. tests/test_qt.py +0 -103
  92. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/entry_points.txt +0 -0
  93. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info/licenses}/LICENSE +0 -0
  94. {celldetective-1.3.9.post5.dist-info → celldetective-1.4.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,49 @@
1
+ from PyQt5.QtWidgets import QCheckBox
2
+ from PyQt5.QtCore import QSize
3
+ from superqt.fonticon import icon
4
+ from fonticon_mdi6 import MDI6
5
+ from celldetective.gui.settings._settings_base import CelldetectiveSettingsPanel
6
+ import json
7
+ import os
8
+
9
+ class SettingsSegmentation(CelldetectiveSettingsPanel):
10
+
11
+ def __init__(self, parent_window=None):
12
+
13
+ super().__init__(title="Configure segmentation")
14
+ self.parent_window = parent_window
15
+ self.mode = self.parent_window.mode
16
+ self.exp_dir = self.parent_window.exp_dir
17
+ self._instructions_path = self.parent_window.exp_dir + f"configs/segmentation_instructions_{self.mode}.json"
18
+ self._add_to_layout()
19
+ self._load_previous_instructions()
20
+
21
+ def _create_widgets(self):
22
+ super()._create_widgets()
23
+
24
+ self.flip_segmentation_checkbox: QCheckBox = QCheckBox("Segment frames in reverse order")
25
+ self.flip_segmentation_checkbox.setIcon(icon(MDI6.camera_flip_outline,color="black"))
26
+ self.flip_segmentation_checkbox.setIconSize(QSize(20, 20))
27
+ self.flip_segmentation_checkbox.setStyleSheet(self.button_select_all)
28
+ self.flip_segmentation_checkbox.setToolTip("Flip the order of the frames for segmentation.")
29
+
30
+ def _add_to_layout(self):
31
+ self._layout.addWidget(self.flip_segmentation_checkbox)
32
+ self._layout.addWidget(self.submit_btn)
33
+ #self._widget.adjustSize()
34
+
35
+ def _load_previous_instructions(self):
36
+ if os.path.exists(self._instructions_path):
37
+ with open(self._instructions_path, "r") as f:
38
+ instructions = json.load(f)
39
+ if isinstance(instructions.get("flip"),bool):
40
+ self.flip_segmentation_checkbox.setChecked(instructions.get("flip"))
41
+
42
+ def _write_instructions(self):
43
+ instructions = {"flip": self.flip_segmentation_checkbox.isChecked()}
44
+ print('Segmentation instructions: ', instructions)
45
+ file_name = self._instructions_path
46
+ with open(file_name, 'w') as f:
47
+ json.dump(instructions, f, indent=4)
48
+ print('Done.')
49
+ self.close()
@@ -1,13 +1,11 @@
1
- from PyQt5.QtWidgets import QDialog, QMainWindow, QApplication,QRadioButton, QMessageBox, QScrollArea, QComboBox, QFrame, QFileDialog, QGridLayout, QLineEdit, QVBoxLayout, QWidget, QLabel, QHBoxLayout, QPushButton
1
+ from PyQt5.QtWidgets import QRadioButton, QComboBox, QFrame, QFileDialog, QGridLayout, QLineEdit, QVBoxLayout, QLabel, QHBoxLayout, QPushButton
2
2
  from PyQt5.QtCore import Qt, QSize
3
- from PyQt5.QtGui import QDoubleValidator, QIntValidator, QIcon
4
- from celldetective.gui.gui_utils import center_window
3
+ from celldetective.gui.gui_utils import generic_message
5
4
  from celldetective.gui.layouts import ChannelNormGenerator
6
5
 
7
6
  from superqt import QLabeledDoubleSlider,QLabeledSlider
8
7
  from superqt.fonticon import icon
9
8
  from fonticon_mdi6 import MDI6
10
- from celldetective.utils import get_software_location
11
9
  from celldetective.io import get_segmentation_datasets_list, locate_segmentation_dataset, get_segmentation_models_list
12
10
  from celldetective.segmentation import train_segmentation_model
13
11
  from celldetective.gui.layouts import CellposeParamsWidget
@@ -16,11 +14,9 @@ import json
16
14
  import os
17
15
  from glob import glob
18
16
  from datetime import datetime
19
- from celldetective.gui import Styles
20
- from celldetective.gui.processes.train_segmentation_model import TrainSegModelProcess
21
- from celldetective.gui.workers import ProgressWindow
17
+ from celldetective.gui.settings._settings_base import CelldetectiveSettingsPanel
22
18
 
23
- class ConfigSegmentationModelTraining(QMainWindow, Styles):
19
+ class SettingsSegmentationModelTraining(CelldetectiveSettingsPanel):
24
20
 
25
21
  """
26
22
  UI to set segmentation model training instructions.
@@ -29,86 +25,56 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
29
25
 
30
26
  def __init__(self, parent_window=None):
31
27
 
32
- super().__init__()
33
28
  self.parent_window = parent_window
34
29
  self.use_gpu = self.parent_window.use_gpu
35
- self.setWindowTitle("Train segmentation model")
36
- self.setWindowIcon(QIcon(os.sep.join(['celldetective','icons','mexican-hat.png'])))
37
30
  self.mode = self.parent_window.mode
38
31
  self.exp_dir = self.parent_window.exp_dir
39
- self.soft_path = get_software_location()
40
- self.pretrained_model = None
32
+ self.pretrained_model = None
41
33
  self.dataset_folder = None
42
- self.software_models_dir = os.sep.join([self.soft_path, 'celldetective', 'models', f'segmentation_{self.mode}'])
43
-
44
- self.onlyFloat = QDoubleValidator()
45
- self.onlyInt = QIntValidator()
46
-
47
- self.screen_height = self.parent_window.parent_window.parent_window.screen_height
48
- center_window(self)
34
+ super().__init__(title="Train segmentation model")
49
35
 
50
- self.setMinimumWidth(500)
51
- self.setMinimumHeight(int(0.3*self.screen_height))
52
- self.setMaximumHeight(int(0.8*self.screen_height))
53
- self.populate_widget()
54
- #self.load_previous_measurement_instructions()
55
-
56
- def populate_widget(self):
36
+ self.software_models_dir = os.sep.join([self._software_path, 'celldetective', 'models', f'segmentation_{self.mode}'])
37
+ self._add_to_layout()
38
+ self._load_previous_instructions()
39
+
40
+ self._adjustSize()
41
+ self.resize(int(self.width()), int(self._screen_height * 0.8))
42
+
43
+ def _add_to_layout(self):
44
+
45
+ self._layout.addWidget(self.model_frame)
46
+ self._layout.addWidget(self.data_frame)
47
+ self._layout.addWidget(self.hyper_frame)
48
+ self._layout.addWidget(self.submit_warning)
49
+ self._layout.addWidget(self.submit_btn)
50
+
51
+ def _create_widgets(self):
57
52
 
58
53
  """
59
54
  Create the multibox design.
60
55
 
61
56
  """
62
57
 
63
- # Create button widget and layout
64
- self.scroll_area = QScrollArea(self)
65
- self.button_widget = QWidget()
66
- self.main_layout = QVBoxLayout()
67
- self.button_widget.setLayout(self.main_layout)
68
- self.main_layout.setContentsMargins(30,30,30,30)
69
-
70
- # first frame for FEATURES
58
+ super()._create_widgets()
71
59
  self.model_frame = QFrame()
72
60
  self.model_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
73
61
  self.populate_model_frame()
74
- self.main_layout.addWidget(self.model_frame)
75
62
 
76
63
  self.data_frame = QFrame()
77
64
  self.data_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
78
65
  self.populate_data_frame()
79
- self.main_layout.addWidget(self.data_frame)
80
66
 
81
67
  self.hyper_frame = QFrame()
82
68
  self.hyper_frame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised)
83
69
  self.populate_hyper_frame()
84
- self.main_layout.addWidget(self.hyper_frame)
85
70
 
86
- self.submit_btn = QPushButton('Train')
87
- self.submit_btn.setStyleSheet(self.button_style_sheet)
88
- self.submit_btn.clicked.connect(self.prep_model)
89
- self.main_layout.addWidget(self.submit_btn)
90
71
  self.submit_btn.setEnabled(False)
91
72
  self.submit_warning = QLabel('')
92
- self.main_layout.addWidget(self.submit_warning)
73
+ self.submit_btn.setText("Train")
93
74
 
94
75
  self.spatial_calib_le.textChanged.connect(self.activate_train_btn)
95
76
  self.modelname_le.setText(f"Untitled_model_{datetime.today().strftime('%Y-%m-%d')}")
96
77
 
97
- #self.populate_left_panel()
98
- #grid.addLayout(self.left_side, 0, 0, 1, 1)
99
- self.button_widget.adjustSize()
100
-
101
- self.scroll_area.setAlignment(Qt.AlignCenter)
102
- self.scroll_area.setWidget(self.button_widget)
103
- self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
104
- self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
105
- self.scroll_area.setWidgetResizable(True)
106
- self.setCentralWidget(self.scroll_area)
107
- self.show()
108
-
109
- QApplication.processEvents()
110
- self.adjustScrollArea()
111
-
112
78
  def populate_hyper_frame(self):
113
79
 
114
80
  """
@@ -137,14 +103,14 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
137
103
  lr_layout = QHBoxLayout()
138
104
  lr_layout.addWidget(QLabel('learning rate: '),30)
139
105
  self.lr_le = QLineEdit('0,0003')
140
- self.lr_le.setValidator(self.onlyFloat)
106
+ self.lr_le.setValidator(self._floatValidator)
141
107
  lr_layout.addWidget(self.lr_le, 70)
142
108
  layout.addLayout(lr_layout)
143
109
 
144
110
  bs_layout = QHBoxLayout()
145
111
  bs_layout.addWidget(QLabel('batch size: '),30)
146
112
  self.bs_le = QLineEdit('8')
147
- self.bs_le.setValidator(self.onlyInt)
113
+ self.bs_le.setValidator(self._intValidator)
148
114
  bs_layout.addWidget(self.bs_le, 70)
149
115
  layout.addLayout(bs_layout)
150
116
 
@@ -154,7 +120,7 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
154
120
  self.epochs_slider.setRange(1,300)
155
121
  self.epochs_slider.setSingleStep(1)
156
122
  self.epochs_slider.setTickInterval(1)
157
- self.epochs_slider.setOrientation(1)
123
+ self.epochs_slider.setOrientation(Qt.Horizontal)
158
124
  self.epochs_slider.setValue(100)
159
125
  epochs_layout.addWidget(self.epochs_slider, 70)
160
126
  layout.addLayout(epochs_layout)
@@ -241,7 +207,7 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
241
207
  self.augmentation_slider = QLabeledDoubleSlider()
242
208
  self.augmentation_slider.setSingleStep(0.01)
243
209
  self.augmentation_slider.setTickInterval(0.01)
244
- self.augmentation_slider.setOrientation(1)
210
+ self.augmentation_slider.setOrientation(Qt.Horizontal)
245
211
  self.augmentation_slider.setRange(0.01, 3)
246
212
  self.augmentation_slider.setValue(2.0)
247
213
 
@@ -253,7 +219,7 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
253
219
  self.validation_slider = QLabeledDoubleSlider()
254
220
  self.validation_slider.setSingleStep(0.01)
255
221
  self.validation_slider.setTickInterval(0.01)
256
- self.validation_slider.setOrientation(1)
222
+ self.validation_slider.setOrientation(Qt.Horizontal)
257
223
  self.validation_slider.setRange(0,0.9)
258
224
  self.validation_slider.setValue(0.2)
259
225
  validation_split_layout.addWidget(self.validation_slider, 70)
@@ -320,7 +286,7 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
320
286
  parent_pxtoum = f"{self.parent_window.parent_window.PxToUm}"
321
287
  self.spatial_calib_le = QLineEdit(parent_pxtoum.replace('.',','))
322
288
  self.spatial_calib_le.setPlaceholderText('e.g. 0.1 µm per pixel')
323
- self.spatial_calib_le.setValidator(self.onlyFloat)
289
+ self.spatial_calib_le.setValidator(self._floatValidator)
324
290
  spatial_calib_layout.addWidget(self.spatial_calib_le, 70)
325
291
  layout.addLayout(spatial_calib_layout)
326
292
 
@@ -351,17 +317,11 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
351
317
 
352
318
  def showDialog_pretrained(self):
353
319
 
354
- # try:
355
- # self.cancel_pretrained.click()
356
- # except Exception as e:
357
- # print(e)
358
- # pass
359
-
360
320
  self.clear_pretrained()
361
321
  self.pretrained_model = None
362
322
  self.pretrained_model = QFileDialog.getExistingDirectory(
363
323
  self, "Open Directory",
364
- os.sep.join([self.soft_path, 'celldetective', 'models', f'segmentation_generic','']),
324
+ os.sep.join([self._software_path, 'celldetective', 'models', f'segmentation_generic','']),
365
325
  QFileDialog.ShowDirsOnly | QFileDialog.DontResolveSymlinks,
366
326
  )
367
327
 
@@ -533,18 +493,7 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
533
493
 
534
494
  self.spatial_calib_le.setText(str(spatial_calib).replace('.',','))
535
495
 
536
- def adjustScrollArea(self):
537
-
538
- """
539
- Auto-adjust scroll area to fill space
540
- (from https://stackoverflow.com/questions/66417576/make-qscrollarea-use-all-available-space-of-qmainwindow-height-axis)
541
- """
542
-
543
- step = 5
544
- while self.scroll_area.verticalScrollBar().isVisible() and self.height() < self.maximumHeight():
545
- self.resize(self.width(), self.height() + step)
546
-
547
- def prep_model(self):
496
+ def _write_instructions(self):
548
497
 
549
498
  model_name = self.modelname_le.text()
550
499
  pretrained_model = self.pretrained_model
@@ -587,14 +536,8 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
587
536
  try:
588
537
  lr = float(self.lr_le.text().replace(',','.'))
589
538
  except:
590
- msgBox = QMessageBox()
591
- msgBox.setIcon(QMessageBox.Warning)
592
- msgBox.setText("Invalid value encountered for the learning rate.")
593
- msgBox.setWindowTitle("Warning")
594
- msgBox.setStandardButtons(QMessageBox.Ok)
595
- returnValue = msgBox.exec()
596
- if returnValue == QMessageBox.Ok:
597
- return None
539
+ generic_message('Invalid value encountered for the learning rate.')
540
+ return None
598
541
 
599
542
  bs = int(self.bs_le.text())
600
543
  epochs = self.epochs_slider.value()
@@ -631,4 +574,7 @@ class ConfigSegmentationModelTraining(QMainWindow, Styles):
631
574
 
632
575
  self.parent_window.init_seg_model_list()
633
576
  idx = self.parent_window.seg_model_list.findText(model_name)
634
- self.parent_window.seg_model_list.setCurrentIndex(idx)
577
+ self.parent_window.seg_model_list.setCurrentIndex(idx)
578
+
579
+ def _load_previous_instructions(self):
580
+ pass
@@ -1,8 +1,8 @@
1
1
  """
2
- Copright © 2023 Laboratoire Adhesion et Inflammation, Authored by Remy Torro.
2
+ Copyright © 2023 Laboratoire Adhesion et Inflammation, Authored by Remy Torro.
3
3
  """
4
4
 
5
- from PyQt5.QtWidgets import QMainWindow, QComboBox, QLabel, QRadioButton, QLineEdit, QApplication, QPushButton, QScrollArea, QWidget, QVBoxLayout, QHBoxLayout
5
+ from PyQt5.QtWidgets import QComboBox, QLabel, QRadioButton, QLineEdit, QApplication, QPushButton, QScrollArea, QVBoxLayout, QHBoxLayout
6
6
  from PyQt5.QtCore import Qt, QSize
7
7
  from celldetective.gui.gui_utils import center_window, QHSeperationLine
8
8
  from superqt import QLabeledDoubleSlider, QLabeledSlider
@@ -12,9 +12,9 @@ import numpy as np
12
12
  from superqt.fonticon import icon
13
13
  from fonticon_mdi6 import MDI6
14
14
  import os
15
- from celldetective.gui import Styles
15
+ from celldetective.gui.settings._settings_base import CelldetectiveSettingsPanel
16
16
 
17
- class ConfigSignalAnnotator(QMainWindow, Styles):
17
+ class SettingsSignalAnnotator(CelldetectiveSettingsPanel):
18
18
 
19
19
  """
20
20
  UI to set normalization and animation parameters for the annotator tool.
@@ -23,68 +23,94 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
23
23
 
24
24
  def __init__(self, parent_window=None):
25
25
 
26
- super().__init__()
27
26
  self.parent_window = parent_window
28
- self.setWindowTitle("Configure signal annotator")
29
27
  self.mode = self.parent_window.mode
30
28
  self.exp_dir = self.parent_window.exp_dir
31
- self.soft_path = get_software_location()
32
29
 
33
- if self.mode=="targets":
34
- self.instructions_path = self.parent_window.exp_dir + "configs/signal_annotator_config_targets.json"
35
- elif self.mode=="effectors":
36
- self.instructions_path = self.parent_window.exp_dir + "configs/signal_annotator_config_effectors.json"
37
- elif self.mode == "pairs":
30
+ self.instructions_path = self.parent_window.exp_dir + f"configs/signal_annotator_config_{self.mode}.json"
31
+ if self.mode == "pairs":
38
32
  self.instructions_path = self.parent_window.exp_dir + "configs/signal_annotator_config_neighborhood.json"
39
33
 
40
- exp_config = self.exp_dir +"config.ini"
41
- #self.config_path = self.exp_dir + self.config_name
42
34
  self.channel_names, self.channels = extract_experiment_channels(self.exp_dir)
43
35
  self.channel_names = np.array(self.channel_names)
44
36
  self.channels = np.array(self.channels)
45
37
  self.log_option = False
38
+
39
+ super().__init__(title="Configure signal annotator")
46
40
 
47
- self.screen_height = self.parent_window.parent_window.parent_window.screen_height
48
- center_window(self)
41
+ self._add_to_layout()
42
+ self._load_previous_instructions()
43
+
44
+ self._adjustSize()
45
+ self.resize(int(self.width()), int(self._screen_height * 0.55))
46
+
47
+ def _add_to_layout(self):
48
+
49
+ sub_layout = QVBoxLayout()
50
+ sub_layout.setContentsMargins(10,10,10,20)
51
+ sub_layout.setContentsMargins(30,30,30,30)
52
+ sub_layout.addWidget(self._modality_lbl)
53
+
54
+ # Create radio buttons
55
+ option_layout = QHBoxLayout()
56
+ option_layout.addWidget(self.gs_btn, alignment=Qt.AlignCenter)
57
+ option_layout.addWidget(self.rgb_btn, alignment=Qt.AlignCenter)
58
+ sub_layout.addLayout(option_layout)
59
+
60
+ btn_hbox = QHBoxLayout()
61
+ btn_hbox.addWidget(QLabel(''), 90)
62
+ btn_hbox.addWidget(self.log_btn, 5,alignment=Qt.AlignRight)
63
+ btn_hbox.addWidget(self.percentile_btn, 5,alignment=Qt.AlignRight)
64
+ sub_layout.addLayout(btn_hbox)
49
65
 
50
- self.setMinimumHeight(int(0.4*self.screen_height))
51
- self.setMaximumHeight(int(0.8*self.screen_height))
52
- self.populate_widget()
53
- #self.load_previous_measurement_instructions()
66
+ for i in range(3):
67
+ hlayout = QHBoxLayout()
68
+ hlayout.addWidget(self.channel_cbs_lbls[i], 20)
69
+ hlayout.addWidget(self.channel_cbs[i], 80)
70
+ sub_layout.addLayout(hlayout)
54
71
 
72
+ hlayout2 = QHBoxLayout()
73
+ hlayout2.addWidget(self.min_val_lbls[i], 20)
74
+ hlayout2.addWidget(self.min_val_les[i], 80)
75
+ sub_layout.addLayout(hlayout2)
76
+
77
+ hlayout3 = QHBoxLayout()
78
+ hlayout3.addWidget(self.max_val_lbls[i], 20)
79
+ hlayout3.addWidget(self.max_val_les[i], 80)
80
+ sub_layout.addLayout(hlayout3)
55
81
 
56
- def populate_widget(self):
82
+ sub_layout.addWidget(self.hsep)
83
+ hbox_frac = QHBoxLayout()
84
+ hbox_frac.addWidget(self._fraction_lbl, 20)
85
+ hbox_frac.addWidget(self.fraction_slider, 80)
86
+ sub_layout.addLayout(hbox_frac)
87
+
88
+ hbox_interval = QHBoxLayout()
89
+ hbox_interval.addWidget(self._interval_lbl, 20)
90
+ hbox_interval.addWidget(self.interval_slider, 80)
91
+ sub_layout.addLayout(hbox_interval)
92
+
93
+ self._layout.addLayout(sub_layout)
94
+
95
+ self._layout.addWidget(self.submit_btn)
96
+
97
+ def _create_widgets(self):
57
98
 
58
99
  """
59
100
  Create the widgets.
60
101
 
61
102
  """
62
-
63
- self.scroll_area = QScrollArea(self)
64
- self.button_widget = QWidget()
65
-
66
- self.main_layout = QVBoxLayout()
67
- self.main_layout.setContentsMargins(30,30,30,30)
68
-
69
- sub_layout = QVBoxLayout()
70
- sub_layout.setContentsMargins(10,10,10,20)
71
-
72
- self.button_widget.setLayout(self.main_layout)
73
- sub_layout.setContentsMargins(30,30,30,30)
74
-
75
- sub_layout.addWidget(QLabel('Modality: '))
103
+ super()._create_widgets()
104
+
105
+ self._modality_lbl = QLabel("Modality: ")
106
+ self._fraction_lbl = QLabel("fraction: ")
107
+ self._interval_lbl = QLabel('interval [ms]: ')
76
108
 
77
- # Create radio buttons
78
- option_layout = QHBoxLayout()
79
109
  self.gs_btn = QRadioButton('grayscale')
80
110
  self.gs_btn.setChecked(True)
81
- option_layout.addWidget(self.gs_btn, alignment=Qt.AlignCenter)
82
-
111
+
83
112
  self.rgb_btn = QRadioButton('RGB')
84
- option_layout.addWidget(self.rgb_btn, alignment=Qt.AlignCenter)
85
- sub_layout.addLayout(option_layout)
86
113
 
87
- btn_hbox = QHBoxLayout()
88
114
 
89
115
  self.percentile_btn = QPushButton()
90
116
  self.percentile_btn.setIcon(icon(MDI6.percent_circle_outline,color="black"))
@@ -100,11 +126,6 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
100
126
  self.log_btn.setToolTip("Log-transform the intensities.")
101
127
  self.log_btn.setIconSize(QSize(20, 20))
102
128
 
103
- btn_hbox.addWidget(QLabel(''), 90)
104
- btn_hbox.addWidget(self.log_btn, 5,alignment=Qt.AlignRight)
105
- btn_hbox.addWidget(self.percentile_btn, 5,alignment=Qt.AlignRight)
106
- sub_layout.addLayout(btn_hbox)
107
-
108
129
  self.channel_cbs = [QComboBox() for i in range(3)]
109
130
  self.channel_cbs_lbls = [QLabel() for i in range(3)]
110
131
 
@@ -118,23 +139,13 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
118
139
 
119
140
  for i in range(3):
120
141
 
121
- hlayout = QHBoxLayout()
122
142
  self.channel_cbs[i].addItems(self.channel_names)
123
143
  self.channel_cbs[i].setCurrentIndex(i)
124
144
  self.channel_cbs_lbls[i].setText(self.rgb_text[i])
125
- hlayout.addWidget(self.channel_cbs_lbls[i], 20)
126
- hlayout.addWidget(self.channel_cbs[i], 80)
127
- sub_layout.addLayout(hlayout)
145
+
146
+ self.min_val_les[i].setValidator(self._floatValidator)
147
+ self.max_val_les[i].setValidator(self._floatValidator)
128
148
 
129
- hlayout2 = QHBoxLayout()
130
- hlayout2.addWidget(self.min_val_lbls[i], 20)
131
- hlayout2.addWidget(self.min_val_les[i], 80)
132
- sub_layout.addLayout(hlayout2)
133
-
134
- hlayout3 = QHBoxLayout()
135
- hlayout3.addWidget(self.max_val_lbls[i], 20)
136
- hlayout3.addWidget(self.max_val_les[i], 80)
137
- sub_layout.addLayout(hlayout3)
138
149
 
139
150
  self.enable_channels()
140
151
 
@@ -142,56 +153,22 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
142
153
  self.rgb_btn.toggled.connect(self.enable_channels)
143
154
 
144
155
  self.hsep = QHSeperationLine()
145
- sub_layout.addWidget(self.hsep)
146
-
147
- hbox_frac = QHBoxLayout()
148
- hbox_frac.addWidget(QLabel('fraction: '), 20)
149
156
 
150
157
  self.fraction_slider = QLabeledDoubleSlider()
151
158
  self.fraction_slider.setSingleStep(0.05)
152
159
  self.fraction_slider.setTickInterval(0.05)
153
160
  self.fraction_slider.setSingleStep(1)
154
- self.fraction_slider.setOrientation(1)
161
+ self.fraction_slider.setOrientation(Qt.Horizontal)
155
162
  self.fraction_slider.setRange(0.1,1)
156
163
  self.fraction_slider.setValue(0.25)
157
164
 
158
- hbox_frac.addWidget(self.fraction_slider, 80)
159
- sub_layout.addLayout(hbox_frac)
160
-
161
-
162
- hbox_interval = QHBoxLayout()
163
- hbox_interval.addWidget(QLabel('interval [ms]: '), 20)
164
-
165
165
  self.interval_slider = QLabeledSlider()
166
166
  self.interval_slider.setSingleStep(1)
167
167
  self.interval_slider.setTickInterval(1)
168
168
  self.interval_slider.setSingleStep(1)
169
- self.interval_slider.setOrientation(1)
169
+ self.interval_slider.setOrientation(Qt.Horizontal)
170
170
  self.interval_slider.setRange(1,1000)
171
171
  self.interval_slider.setValue(1)
172
- hbox_interval.addWidget(self.interval_slider, 80)
173
- sub_layout.addLayout(hbox_interval)
174
-
175
- self.main_layout.addLayout(sub_layout)
176
-
177
- self.submit_btn = QPushButton('Save')
178
- self.submit_btn.setStyleSheet(self.button_style_sheet)
179
- self.submit_btn.clicked.connect(self.write_instructions)
180
- self.main_layout.addWidget(self.submit_btn)
181
-
182
-
183
- self.button_widget.adjustSize()
184
- self.scroll_area.setAlignment(Qt.AlignCenter)
185
- self.scroll_area.setWidget(self.button_widget)
186
- self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
187
- self.scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
188
- self.scroll_area.setWidgetResizable(True)
189
- self.setCentralWidget(self.scroll_area)
190
- self.show()
191
-
192
- self.read_instructions()
193
-
194
- QApplication.processEvents()
195
172
 
196
173
  def enable_channels(self):
197
174
 
@@ -210,7 +187,6 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
210
187
  self.channel_cbs_lbls[k].setEnabled(False)
211
188
 
212
189
  for k in range(3):
213
-
214
190
  self.min_val_les[k].setEnabled(False)
215
191
  self.min_val_lbls[k].setEnabled(False)
216
192
  self.max_val_les[k].setEnabled(False)
@@ -222,7 +198,6 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
222
198
  self.percentile_btn.setEnabled(True)
223
199
 
224
200
  for k in range(3):
225
-
226
201
  self.channel_cbs[k].setEnabled(True)
227
202
  self.channel_cbs_lbls[k].setEnabled(True)
228
203
 
@@ -259,7 +234,7 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
259
234
  self.max_val_lbls[k].setText('Max percentile: ')
260
235
  self.max_val_les[k].setText('99.99')
261
236
 
262
- def write_instructions(self):
237
+ def _write_instructions(self):
263
238
 
264
239
  """
265
240
  Save the current configuration.
@@ -270,7 +245,7 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
270
245
  max_i = 3 if self.rgb_btn.isChecked() else 1
271
246
  channels = []
272
247
  for i in range(max_i):
273
- channels.append([self.channel_cbs[i].currentText(), float(self.min_val_les[i].text()), float(self.max_val_les[i].text())])
248
+ channels.append([self.channel_cbs[i].currentText(), float(self.min_val_les[i].text().replace(',','.')), float(self.max_val_les[i].text().replace(',','.'))])
274
249
  instructions.update({'channels': channels})
275
250
 
276
251
  print('Instructions: ', instructions)
@@ -280,7 +255,7 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
280
255
  print('Done.')
281
256
  self.close()
282
257
 
283
- def read_instructions(self):
258
+ def _load_previous_instructions(self):
284
259
 
285
260
  """
286
261
  Read and set the widgets to the last configuration.
@@ -315,8 +290,8 @@ class ConfigSignalAnnotator(QMainWindow, Styles):
315
290
  for i in range(max_iter):
316
291
  idx = self.channel_cbs[i].findText(channels[i][0])
317
292
  self.channel_cbs[i].setCurrentIndex(idx)
318
- self.min_val_les[i].setText(str(channels[i][1]))
319
- self.max_val_les[i].setText(str(channels[i][2]))
293
+ self.min_val_les[i].setText(str(channels[i][1]).replace('.',','))
294
+ self.max_val_les[i].setText(str(channels[i][2]).replace('.',','))
320
295
 
321
296
  if 'fraction' in instructions:
322
297
  fraction = instructions['fraction']