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
@@ -1,495 +1,773 @@
1
1
  import numpy as np
2
- from PyQt5.QtWidgets import QApplication, QFrame, QSizePolicy, QWidget, QLineEdit, QListWidget, QVBoxLayout, QComboBox, \
3
- QPushButton, QLabel, QHBoxLayout, QCheckBox
4
- from PyQt5.QtCore import QEvent
2
+ from PyQt5.QtWidgets import QApplication, QMessageBox, QFrame, QSizePolicy, QWidget, QLineEdit, QListWidget, QVBoxLayout, QComboBox, \
3
+ QPushButton, QLabel, QHBoxLayout, QCheckBox, QButtonGroup, QRadioButton, QGridLayout, QSpacerItem
4
+ from PyQt5.QtCore import QEvent, Qt, QSize
5
+ from PyQt5.QtGui import QDoubleValidator, QIntValidator
6
+
5
7
  from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
6
8
  from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT
7
9
  import matplotlib.pyplot as plt
8
10
  import celldetective.extra_properties as extra_properties
9
11
  from inspect import getmembers, isfunction
12
+ from superqt import QLabeledDoubleRangeSlider, QLabeledSlider, QLabeledDoubleSlider
13
+ from superqt.fonticon import icon
14
+ from fonticon_mdi6 import MDI6
10
15
 
16
+ from celldetective.io import auto_load_number_of_frames, load_frames
17
+ from celldetective.utils import _extract_channel_indices_from_config
18
+ from celldetective.filters import *
19
+ from celldetective.segmentation import filter_image
20
+ from stardist import fill_label_holes
11
21
 
12
22
  def center_window(window):
13
- """
14
- Center window in the middle of the screen.
15
- """
23
+ """
24
+ Center window in the middle of the screen.
25
+ """
16
26
 
17
- frameGm = window.frameGeometry()
18
- screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
19
- centerPoint = QApplication.desktop().screenGeometry(screen).center()
20
- frameGm.moveCenter(centerPoint)
21
- window.move(frameGm.topLeft())
27
+ frameGm = window.frameGeometry()
28
+ screen = QApplication.desktop().screenNumber(QApplication.desktop().cursor().pos())
29
+ centerPoint = QApplication.desktop().screenGeometry(screen).center()
30
+ frameGm.moveCenter(centerPoint)
31
+ window.move(frameGm.topLeft())
22
32
 
23
33
 
24
34
  class QHSeperationLine(QFrame):
25
- '''
26
- a horizontal seperation line\n
27
- '''
35
+ '''
36
+ a horizontal seperation line\n
37
+ '''
28
38
 
29
- def __init__(self):
30
- super().__init__()
31
- self.setMinimumWidth(1)
32
- self.setFixedHeight(20)
33
- self.setFrameShape(QFrame.HLine)
34
- self.setFrameShadow(QFrame.Sunken)
35
- self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
39
+ def __init__(self):
40
+ super().__init__()
41
+ self.setMinimumWidth(1)
42
+ self.setFixedHeight(20)
43
+ self.setFrameShape(QFrame.HLine)
44
+ self.setFrameShadow(QFrame.Sunken)
45
+ self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum)
36
46
 
37
47
 
38
48
  class FeatureChoice(QWidget):
39
49
 
40
- def __init__(self, parent):
41
- super().__init__()
42
- self.parent = parent
43
- self.setWindowTitle("Add feature")
44
- # Create the QComboBox and add some items
45
- self.combo_box = QComboBox(self)
46
- center_window(self)
47
-
48
- standard_measurements = ["area",
49
- "area_bbox",
50
- "area_convex",
51
- "area_filled",
52
- "major_axis_length",
53
- "minor_axis_length",
54
- "eccentricity",
55
- "equivalent_diameter_area",
56
- "euler_number",
57
- "extent",
58
- "feret_diameter_max",
59
- "orientation",
60
- "perimeter",
61
- "perimeter_crofton",
62
- "solidity",
63
- "intensity_mean",
64
- "intensity_max",
65
- "intensity_min",
66
- ]
67
-
68
- extra_props = getmembers(extra_properties, isfunction)
69
- extra_props = [extra_props[i][0] for i in range(len(extra_props))]
70
- if len(extra_props) > 0:
71
- standard_measurements.extend(extra_props)
72
-
73
- self.combo_box.addItems(standard_measurements)
74
-
75
- self.add_btn = QPushButton("Add")
76
- self.add_btn.clicked.connect(self.add_current_feature)
77
-
78
- # Create the layout
79
- layout = QVBoxLayout(self)
80
- layout.addWidget(self.combo_box)
81
- layout.addWidget(self.add_btn)
82
-
83
- def add_current_feature(self):
84
- filtername = self.combo_box.currentText()
85
- self.parent.list_widget.addItems([filtername])
86
- self.close()
50
+ def __init__(self, parent_window):
51
+ super().__init__()
52
+ self.parent_window = parent_window
53
+ self.setWindowTitle("Add feature")
54
+ # Create the QComboBox and add some items
55
+ self.combo_box = QComboBox(self)
56
+ center_window(self)
57
+
58
+ standard_measurements = ["area",
59
+ "area_bbox",
60
+ "area_convex",
61
+ "area_filled",
62
+ "major_axis_length",
63
+ "minor_axis_length",
64
+ "eccentricity",
65
+ "equivalent_diameter_area",
66
+ "euler_number",
67
+ "extent",
68
+ "feret_diameter_max",
69
+ "orientation",
70
+ "perimeter",
71
+ "perimeter_crofton",
72
+ "solidity",
73
+ "intensity_mean",
74
+ "intensity_max",
75
+ "intensity_min",
76
+ ]
77
+
78
+ extra_props = getmembers(extra_properties, isfunction)
79
+ extra_props = [extra_props[i][0] for i in range(len(extra_props))]
80
+ if len(extra_props) > 0:
81
+ standard_measurements.extend(extra_props)
82
+
83
+ self.combo_box.addItems(standard_measurements)
84
+
85
+ self.add_btn = QPushButton("Add")
86
+ self.add_btn.clicked.connect(self.add_current_feature)
87
+
88
+ # Create the layout
89
+ layout = QVBoxLayout(self)
90
+ layout.addWidget(self.combo_box)
91
+ layout.addWidget(self.add_btn)
92
+
93
+ def add_current_feature(self):
94
+ filtername = self.combo_box.currentText()
95
+ self.parent_window.list_widget.addItems([filtername])
96
+ self.close()
87
97
 
88
98
 
89
99
  class FilterChoice(QWidget):
90
100
 
91
- def __init__(self, parent):
92
-
93
- super().__init__()
94
- self.parent = parent
95
- self.setWindowTitle("Add filter")
96
- # Create the QComboBox and add some items
97
- center_window(self)
98
-
99
- self.default_params = {
100
- 'gauss_filter': {'sigma': 2},
101
- 'median_filter': {'size': 4},
102
- 'maximum_filter': {'size': 4},
103
- 'minimum_filter': {'size': 4},
104
- 'percentile_filter': {'percentile': 99, 'size': 4},
105
- 'variance_filter': {'size': 4},
106
- 'std_filter': {'size': 4},
107
- 'laplace_filter': None,
108
- 'abs_filter': None,
109
- 'ln_filter': None,
110
- 'subtract_filter': {'value': 1},
111
- 'dog_filter': {'sigma_low': 0.8, 'sigma_high': 1.6},
112
- 'log_filter': {'sigma': 2},
113
- 'tophat_filter': {'size': 4, 'connectivity': 4},
114
- 'otsu_filter': None,
115
- 'local_filter': {'block_size': 73, 'method': 'mean', 'offset': 0},
116
- 'niblack_filter': {'window_size': 15, 'k': 0.2},
117
- # 'sauvola_filter': {'window_size': 15, 'k': 0.2}
118
- }
119
-
120
- layout = QVBoxLayout(self)
121
- self.combo_box = QComboBox(self)
122
- self.combo_box.addItems(list(self.default_params.keys()))
123
- self.combo_box.currentTextChanged.connect(self.update_arguments)
124
- layout.addWidget(self.combo_box)
125
-
126
- self.arguments_le = [QLineEdit() for i in range(3)]
127
- self.arguments_labels = [QLabel('') for i in range(3)]
128
- for i in range(2):
129
- hbox = QHBoxLayout()
130
- hbox.addWidget(self.arguments_labels[i], 20)
131
- hbox.addWidget(self.arguments_le[i], 80)
132
- layout.addLayout(hbox)
133
-
134
- self.add_btn = QPushButton("Add")
135
- self.add_btn.clicked.connect(self.add_current_feature)
136
- layout.addWidget(self.add_btn)
137
-
138
- self.combo_box.setCurrentIndex(0)
139
- self.update_arguments()
140
-
141
- def add_current_feature(self):
142
-
143
- filtername = self.combo_box.currentText()
144
- self.parent.list_widget.addItems([filtername])
145
-
146
- filter_instructions = [filtername.split('_')[0]]
147
- for a in self.arguments_le:
148
- arg = a.text()
149
- arg_num = arg
150
- if (arg != '') and arg_num.replace('.', '').replace(',', '').isnumeric():
151
- num = float(arg)
152
- if num.is_integer():
153
- num = int(num)
154
- filter_instructions.append(num)
155
- elif arg != '':
156
- filter_instructions.append(arg)
157
-
158
- print(f'You added filter {filter_instructions}.')
159
-
160
- self.parent.items.append(filter_instructions)
161
- self.close()
162
-
163
- def update_arguments(self):
164
-
165
- selected_filter = self.combo_box.currentText()
166
- arguments = self.default_params[selected_filter]
167
- if arguments is not None:
168
- args = list(arguments.keys())
169
- for i in range(len(args)):
170
- self.arguments_labels[i].setEnabled(True)
171
- self.arguments_le[i].setEnabled(True)
172
-
173
- self.arguments_labels[i].setText(args[i])
174
- self.arguments_le[i].setText(str(arguments[args[i]]))
175
-
176
- if len(args) < 2:
177
- for i in range(len(args), 2):
178
- self.arguments_labels[i].setEnabled(False)
179
- self.arguments_labels[i].setText('')
180
- self.arguments_le[i].setEnabled(False)
181
- else:
182
- for i in range(2):
183
- self.arguments_labels[i].setEnabled(False)
184
- self.arguments_le[i].setEnabled(False)
185
- self.arguments_labels[i].setText('')
101
+ def __init__(self, parent_window):
102
+
103
+ super().__init__()
104
+ self.parent_window = parent_window
105
+ self.setWindowTitle("Add filter")
106
+ # Create the QComboBox and add some items
107
+ center_window(self)
108
+
109
+ self.default_params = {
110
+ 'gauss_filter': {'sigma': 2},
111
+ 'median_filter': {'size': 4},
112
+ 'maximum_filter': {'size': 4},
113
+ 'minimum_filter': {'size': 4},
114
+ 'percentile_filter': {'percentile': 99, 'size': 4},
115
+ 'variance_filter': {'size': 4},
116
+ 'std_filter': {'size': 4},
117
+ 'laplace_filter': None,
118
+ 'abs_filter': None,
119
+ 'ln_filter': None,
120
+ 'subtract_filter': {'value': 1},
121
+ 'dog_filter': {'sigma_low': 0.8, 'sigma_high': 1.6},
122
+ 'log_filter': {'sigma': 2},
123
+ 'tophat_filter': {'size': 4, 'connectivity': 4},
124
+ 'otsu_filter': None,
125
+ 'local_filter': {'block_size': 73, 'method': 'mean', 'offset': 0},
126
+ 'niblack_filter': {'window_size': 15, 'k': 0.2},
127
+ # 'sauvola_filter': {'window_size': 15, 'k': 0.2}
128
+ }
129
+
130
+ layout = QVBoxLayout(self)
131
+ self.combo_box = QComboBox(self)
132
+ self.combo_box.addItems(list(self.default_params.keys()))
133
+ self.combo_box.currentTextChanged.connect(self.update_arguments)
134
+ layout.addWidget(self.combo_box)
135
+
136
+ self.arguments_le = [QLineEdit() for i in range(3)]
137
+ self.arguments_labels = [QLabel('') for i in range(3)]
138
+ for i in range(2):
139
+ hbox = QHBoxLayout()
140
+ hbox.addWidget(self.arguments_labels[i], 20)
141
+ hbox.addWidget(self.arguments_le[i], 80)
142
+ layout.addLayout(hbox)
143
+
144
+ self.add_btn = QPushButton("Add")
145
+ self.add_btn.clicked.connect(self.add_current_feature)
146
+ layout.addWidget(self.add_btn)
147
+
148
+ self.combo_box.setCurrentIndex(0)
149
+ self.update_arguments()
150
+
151
+ def add_current_feature(self):
152
+
153
+ filtername = self.combo_box.currentText()
154
+ self.parent_window.list_widget.addItems([filtername])
155
+
156
+ filter_instructions = [filtername.split('_')[0]]
157
+ for a in self.arguments_le:
158
+ arg = a.text()
159
+ arg_num = arg
160
+ if (arg != '') and arg_num.replace('.', '').replace(',', '').isnumeric():
161
+ num = float(arg)
162
+ if num.is_integer():
163
+ num = int(num)
164
+ filter_instructions.append(num)
165
+ elif arg != '':
166
+ filter_instructions.append(arg)
167
+
168
+ print(f'You added filter {filter_instructions}.')
169
+
170
+ self.parent_window.items.append(filter_instructions)
171
+ self.close()
172
+
173
+ def update_arguments(self):
174
+
175
+ selected_filter = self.combo_box.currentText()
176
+ arguments = self.default_params[selected_filter]
177
+ if arguments is not None:
178
+ args = list(arguments.keys())
179
+ for i in range(len(args)):
180
+ self.arguments_labels[i].setEnabled(True)
181
+ self.arguments_le[i].setEnabled(True)
182
+
183
+ self.arguments_labels[i].setText(args[i])
184
+ self.arguments_le[i].setText(str(arguments[args[i]]))
185
+
186
+ if len(args) < 2:
187
+ for i in range(len(args), 2):
188
+ self.arguments_labels[i].setEnabled(False)
189
+ self.arguments_labels[i].setText('')
190
+ self.arguments_le[i].setEnabled(False)
191
+ else:
192
+ for i in range(2):
193
+ self.arguments_labels[i].setEnabled(False)
194
+ self.arguments_le[i].setEnabled(False)
195
+ self.arguments_labels[i].setText('')
186
196
 
187
197
 
188
198
  class OperationChoice(QWidget):
189
- """
190
- Mini window to select an operation from numpy to apply on the ROI.
199
+ """
200
+ Mini window to select an operation from numpy to apply on the ROI.
191
201
 
192
- """
202
+ """
193
203
 
194
- def __init__(self, parent):
195
- super().__init__()
196
- self.parent = parent
197
- self.setWindowTitle("Add feature")
198
- # Create the QComboBox and add some items
199
- self.combo_box = QComboBox(self)
200
- center_window(self)
204
+ def __init__(self, parent_window):
205
+ super().__init__()
206
+ self.parent_window = parent_window
207
+ self.setWindowTitle("Add feature")
208
+ # Create the QComboBox and add some items
209
+ self.combo_box = QComboBox(self)
210
+ center_window(self)
201
211
 
202
- self.combo_box.addItems(["mean", "median", "average", "std", "var",
203
- "nanmedian", "nanmean", "nanstd", "nanvar"])
212
+ self.combo_box.addItems(["mean", "median", "average", "std", "var",
213
+ "nanmedian", "nanmean", "nanstd", "nanvar"])
204
214
 
205
- self.add_btn = QPushButton("Add")
206
- self.add_btn.clicked.connect(self.add_current_feature)
215
+ self.add_btn = QPushButton("Add")
216
+ self.add_btn.clicked.connect(self.add_current_feature)
207
217
 
208
- # Create the layout
209
- layout = QVBoxLayout(self)
210
- layout.addWidget(self.combo_box)
211
- layout.addWidget(self.add_btn)
218
+ # Create the layout
219
+ layout = QVBoxLayout(self)
220
+ layout.addWidget(self.combo_box)
221
+ layout.addWidget(self.add_btn)
212
222
 
213
- def add_current_feature(self):
214
- filtername = self.combo_box.currentText()
215
- self.parent.list_widget.addItems([filtername])
216
- self.close()
223
+ def add_current_feature(self):
224
+ filtername = self.combo_box.currentText()
225
+ self.parent_window.list_widget.addItems([filtername])
226
+ self.close()
217
227
 
218
228
 
219
229
  class GeometryChoice(QWidget):
220
230
 
221
- def __init__(self, parent):
231
+ def __init__(self, parent_window):
222
232
 
223
- super().__init__()
224
- self.parent = parent
225
- self.setWindowTitle("Set distances")
226
- center_window(self)
233
+ super().__init__()
234
+ self.parent_window = parent_window
235
+ self.setWindowTitle("Set distances")
236
+ center_window(self)
227
237
 
228
- # Create the QComboBox and add some items
238
+ # Create the QComboBox and add some items
229
239
 
230
- self.dist_label = QLabel('Distance [px]: ')
231
- self.dist_le = QLineEdit('10')
240
+ self.dist_label = QLabel('Distance [px]: ')
241
+ self.dist_le = QLineEdit('10')
232
242
 
233
- self.dist_outer_label = QLabel('Max distance [px]')
234
- self.dist_outer_le = QLineEdit('100')
235
- self.outer_to_hide = [self.dist_outer_le, self.dist_outer_label]
243
+ self.dist_outer_label = QLabel('Max distance [px]')
244
+ self.dist_outer_le = QLineEdit('100')
245
+ self.outer_to_hide = [self.dist_outer_le, self.dist_outer_label]
236
246
 
237
- self.outer_btn = QCheckBox('outer distance')
238
- self.outer_btn.clicked.connect(self.activate_outer_value)
247
+ self.outer_btn = QCheckBox('outer distance')
248
+ self.outer_btn.clicked.connect(self.activate_outer_value)
239
249
 
240
- self.add_btn = QPushButton("Add")
241
- self.add_btn.clicked.connect(self.add_current_feature)
250
+ self.add_btn = QPushButton("Add")
251
+ self.add_btn.clicked.connect(self.add_current_feature)
242
252
 
243
- # Create the layout
244
- layout = QVBoxLayout(self)
245
- dist_layout = QHBoxLayout()
246
- dist_layout.addWidget(self.dist_label, 30)
247
- dist_layout.addWidget(self.dist_le, 70)
253
+ # Create the layout
254
+ layout = QVBoxLayout(self)
255
+ dist_layout = QHBoxLayout()
256
+ dist_layout.addWidget(self.dist_label, 30)
257
+ dist_layout.addWidget(self.dist_le, 70)
248
258
 
249
- self.dist_outer_layout = QHBoxLayout()
250
- self.dist_outer_layout.addWidget(self.dist_outer_label, 30)
251
- self.dist_outer_layout.addWidget(self.dist_outer_le, 70)
259
+ self.dist_outer_layout = QHBoxLayout()
260
+ self.dist_outer_layout.addWidget(self.dist_outer_label, 30)
261
+ self.dist_outer_layout.addWidget(self.dist_outer_le, 70)
252
262
 
253
- layout.addLayout(dist_layout)
254
- layout.addLayout(self.dist_outer_layout)
255
- layout.addWidget(self.outer_btn)
256
- layout.addWidget(self.add_btn)
263
+ layout.addLayout(dist_layout)
264
+ layout.addLayout(self.dist_outer_layout)
265
+ layout.addWidget(self.outer_btn)
266
+ layout.addWidget(self.add_btn)
257
267
 
258
- for el in self.outer_to_hide:
259
- el.hide()
268
+ for el in self.outer_to_hide:
269
+ el.hide()
260
270
 
261
- def activate_outer_value(self):
262
- if self.outer_btn.isChecked():
263
- self.dist_label.setText('Min distance [px]: ')
264
- for el in self.outer_to_hide:
265
- el.show()
266
- else:
267
- self.dist_label.setText('Distance [px]: ')
268
- for el in self.outer_to_hide:
269
- el.hide()
271
+ def activate_outer_value(self):
272
+ if self.outer_btn.isChecked():
273
+ self.dist_label.setText('Min distance [px]: ')
274
+ for el in self.outer_to_hide:
275
+ el.show()
276
+ else:
277
+ self.dist_label.setText('Distance [px]: ')
278
+ for el in self.outer_to_hide:
279
+ el.hide()
270
280
 
271
- def add_current_feature(self):
281
+ def add_current_feature(self):
272
282
 
273
- value = self.dist_le.text()
274
- if self.outer_btn.isChecked():
275
- value2 = self.dist_outer_le.text()
276
- values = [value + '-' + value2]
277
- else:
278
- values = [value]
279
- self.parent.list_widget.addItems(values)
280
- self.close()
283
+ value = self.dist_le.text()
284
+ if self.outer_btn.isChecked():
285
+ value2 = self.dist_outer_le.text()
286
+ values = [value + '-' + value2]
287
+ else:
288
+ values = [value]
289
+ self.parent_window.list_widget.addItems(values)
290
+ self.close()
281
291
 
282
292
 
283
293
  class DistanceChoice(QWidget):
284
294
 
285
- def __init__(self, parent):
286
- super().__init__()
287
- self.parent = parent
288
- self.setWindowTitle("Set distances")
289
- center_window(self)
295
+ def __init__(self, parent_window):
296
+ super().__init__()
297
+ self.parent_window = parent_window
298
+ self.setWindowTitle("Set distances")
299
+ center_window(self)
290
300
 
291
- # Create the QComboBox and add some items
301
+ # Create the QComboBox and add some items
292
302
 
293
- self.dist_label = QLabel('Distance [px]: ')
294
- self.dist_le = QLineEdit('10')
303
+ self.dist_label = QLabel('Distance [px]: ')
304
+ self.dist_le = QLineEdit('10')
295
305
 
296
- self.add_btn = QPushButton("Add")
297
- self.add_btn.clicked.connect(self.add_current_feature)
306
+ self.add_btn = QPushButton("Add")
307
+ self.add_btn.clicked.connect(self.add_current_feature)
298
308
 
299
- # Create the layout
300
- layout = QVBoxLayout(self)
301
- dist_layout = QHBoxLayout()
302
- dist_layout.addWidget(self.dist_label, 30)
303
- dist_layout.addWidget(self.dist_le, 70)
309
+ # Create the layout
310
+ layout = QVBoxLayout(self)
311
+ dist_layout = QHBoxLayout()
312
+ dist_layout.addWidget(self.dist_label, 30)
313
+ dist_layout.addWidget(self.dist_le, 70)
304
314
 
305
- layout.addLayout(dist_layout)
306
- layout.addWidget(self.add_btn)
315
+ layout.addLayout(dist_layout)
316
+ layout.addWidget(self.add_btn)
307
317
 
308
- def add_current_feature(self):
309
- value = self.dist_le.text()
310
- values = [value]
311
- self.parent.list_widget.addItems(values)
312
- self.close()
318
+ def add_current_feature(self):
319
+ value = self.dist_le.text()
320
+ values = [value]
321
+ self.parent_window.list_widget.addItems(values)
322
+ self.close()
313
323
 
314
324
 
315
325
  class ListWidget(QWidget):
316
- """
317
- Generic list widget.
318
- """
326
+ """
327
+ Generic list widget.
328
+ """
319
329
 
320
- def __init__(self, parent, choiceWidget, initial_features, dtype=str, channel_names=None):
330
+ def __init__(self, parent_window, choiceWidget, initial_features, dtype=str, channel_names=None):
321
331
 
322
- super().__init__()
323
- self.parent = parent
324
- self.initial_features = initial_features
325
- self.choiceWidget = choiceWidget
326
- self.dtype = dtype
327
- self.items = []
328
- self.channel_names=channel_names
332
+ super().__init__()
333
+ self.parent_window = parent_window
334
+ self.initial_features = initial_features
335
+ self.choiceWidget = choiceWidget
336
+ self.dtype = dtype
337
+ self.items = []
338
+ self.channel_names=channel_names
329
339
 
330
- self.setFixedHeight(80)
340
+ self.setFixedHeight(80)
331
341
 
332
- # Initialize list widget
333
- self.list_widget = QListWidget()
334
- self.list_widget.addItems(initial_features)
342
+ # Initialize list widget
343
+ self.list_widget = QListWidget()
344
+ self.list_widget.addItems(initial_features)
335
345
 
336
- # Set up layout
337
- main_layout = QVBoxLayout()
338
- main_layout.addWidget(self.list_widget)
339
- self.setLayout(main_layout)
346
+ # Set up layout
347
+ main_layout = QVBoxLayout()
348
+ main_layout.addWidget(self.list_widget)
349
+ self.setLayout(main_layout)
340
350
 
341
- def addItem(self):
351
+ def addItem(self):
342
352
 
343
- """
344
- Add a new item.
345
- """
353
+ """
354
+ Add a new item.
355
+ """
346
356
 
347
- self.addItemWindow = self.choiceWidget(self)
348
- self.addItemWindow.show()
357
+ self.addItemWindow = self.choiceWidget(self)
358
+ self.addItemWindow.show()
349
359
 
350
- def getItems(self):
360
+ def getItems(self):
351
361
 
352
- """
353
- Get all the items as a list.
354
- """
362
+ """
363
+ Get all the items as a list.
364
+ """
355
365
 
356
- items = []
357
- for x in range(self.list_widget.count()):
358
- if len(self.list_widget.item(x).text().split('-')) == 2:
359
- if self.list_widget.item(x).text()[0] == '-':
360
- items.append(self.dtype(self.list_widget.item(x).text()))
361
- else:
362
- minn, maxx = self.list_widget.item(x).text().split('-')
363
- to_add = [self.dtype(minn), self.dtype(maxx)]
364
- items.append(to_add)
365
- else:
366
- items.append(self.dtype(self.list_widget.item(x).text()))
367
- return items
366
+ items = []
367
+ for x in range(self.list_widget.count()):
368
+ if len(self.list_widget.item(x).text().split('-')) == 2:
369
+ if self.list_widget.item(x).text()[0] == '-':
370
+ items.append(self.dtype(self.list_widget.item(x).text()))
371
+ else:
372
+ minn, maxx = self.list_widget.item(x).text().split('-')
373
+ to_add = [self.dtype(minn), self.dtype(maxx)]
374
+ items.append(to_add)
375
+ else:
376
+ items.append(self.dtype(self.list_widget.item(x).text()))
377
+ return items
368
378
 
369
379
 
370
380
 
371
- def removeSel(self):
381
+ def removeSel(self):
372
382
 
373
- """
374
- Remove selected items.
375
- """
383
+ """
384
+ Remove selected items.
385
+ """
376
386
 
377
- listItems = self.list_widget.selectedItems()
378
- if not listItems: return
379
- for item in listItems:
380
- idx = self.list_widget.row(item)
381
- self.list_widget.takeItem(idx)
382
- if self.items:
383
- del self.items[idx]
387
+ listItems = self.list_widget.selectedItems()
388
+ if not listItems: return
389
+ for item in listItems:
390
+ idx = self.list_widget.row(item)
391
+ self.list_widget.takeItem(idx)
392
+ if self.items:
393
+ del self.items[idx]
384
394
 
385
395
 
386
396
  class FigureCanvas(QWidget):
387
- """
388
- Generic figure canvas.
389
- """
390
-
391
- def __init__(self, fig, title="", interactive=True):
392
- super().__init__()
393
- self.fig = fig
394
- self.setWindowTitle(title)
395
- center_window(self)
396
- self.canvas = FigureCanvasQTAgg(self.fig)
397
- self.canvas.setStyleSheet("background-color: transparent;")
398
- if interactive:
399
- self.toolbar = NavigationToolbar2QT(self.canvas)
400
- self.layout = QVBoxLayout(self)
401
- self.layout.addWidget(self.canvas)
402
- if interactive:
403
- self.layout.addWidget(self.toolbar)
404
-
405
- def closeEvent(self, event):
406
- """ Delete figure on closing window. """
407
- # self.canvas.ax.cla() # ****
408
- self.fig.clf() # ****
409
- plt.close(self.fig)
410
- super(FigureCanvas, self).closeEvent(event)
397
+ """
398
+ Generic figure canvas.
399
+ """
400
+
401
+ def __init__(self, fig, title="", interactive=True):
402
+ super().__init__()
403
+ self.fig = fig
404
+ self.setWindowTitle(title)
405
+ self.canvas = FigureCanvasQTAgg(self.fig)
406
+ self.canvas.setStyleSheet("background-color: transparent;")
407
+ if interactive:
408
+ self.toolbar = NavigationToolbar2QT(self.canvas)
409
+ self.layout = QVBoxLayout(self)
410
+ self.layout.addWidget(self.canvas)
411
+ if interactive:
412
+ self.layout.addWidget(self.toolbar)
413
+
414
+ center_window(self)
415
+ self.setAttribute(Qt.WA_DeleteOnClose)
416
+
417
+ def draw(self):
418
+ self.canvas.draw()
419
+
420
+ def closeEvent(self, event):
421
+ """ Delete figure on closing window. """
422
+ # self.canvas.ax.cla() # ****
423
+ self.fig.clf() # ****
424
+ plt.close(self.fig)
425
+ super(FigureCanvas, self).closeEvent(event)
426
+
427
+
428
+ class QuickSliderLayout(QHBoxLayout):
429
+
430
+ """docstring for ClassName"""
431
+
432
+ def __init__(self, label=None, slider=None, layout_ratio=(0.25,0.75), slider_initial_value=1, slider_range=(0,1), slider_tooltip=None, decimal_option=True, precision=1.0E-03, *args):
433
+ super().__init__(*args)
434
+
435
+ if label is not None and isinstance(label,str):
436
+ self.qlabel = QLabel(label)
437
+ self.addWidget(self.qlabel, int(100*layout_ratio[0]))
438
+
439
+ self.slider = slider
440
+ self.slider.setOrientation(1)
441
+ if decimal_option:
442
+ self.slider.setSingleStep(precision)
443
+ self.slider.setTickInterval(precision)
444
+ else:
445
+ self.slider.setSingleStep(1)
446
+ self.slider.setTickInterval(1)
447
+
448
+ self.slider.setRange(*slider_range)
449
+ self.slider.setValue(slider_initial_value)
450
+ if isinstance(slider_tooltip,str):
451
+ self.slider.setToolTip(slider_tooltip)
452
+
453
+ self.addWidget(self.slider, int(100*layout_ratio[1]))
454
+
455
+ class ThresholdLineEdit(QLineEdit):
456
+
457
+ """docstring for ClassName"""
458
+
459
+ def __init__(self, init_value=2.0, connected_buttons=None, placeholder='px > thresh are masked',value_type='float',*args):
460
+ super().__init__(*args)
461
+
462
+ self.init_value = init_value
463
+ self.value_type = value_type
464
+ self.connected_buttons = connected_buttons
465
+ self.setPlaceholderText(placeholder)
466
+
467
+ if self.value_type=="float":
468
+ self.setValidator(QDoubleValidator())
469
+ else:
470
+ self.init_value = int(self.init_value)
471
+ self.setValidator(QIntValidator())
472
+
473
+ if self.connected_buttons is not None:
474
+ self.textChanged.connect(self.enable_btn)
475
+ print("init value of ",self.init_value," for threshold LE")
476
+ self.set_threshold(self.init_value)
477
+
478
+ def enable_btn(self):
479
+
480
+ thresh = self.get_threshold(show_warning=False)
481
+ if isinstance(self.connected_buttons, QPushButton):
482
+ cbs = [self.connected_buttons]
483
+ else:
484
+ cbs = self.connected_buttons
485
+
486
+ if thresh is None:
487
+ for c in cbs:
488
+ c.setEnabled(False)
489
+ else:
490
+ for c in cbs:
491
+ c.setEnabled(True)
492
+
493
+ def set_threshold(self, value):
494
+
495
+ try:
496
+ self.setText(str(value).replace('.',','))
497
+ except:
498
+ print('Please provide a valid threshold value...')
499
+
500
+ def get_threshold(self, show_warning=True):
501
+
502
+ try:
503
+ if self.value_type=='float':
504
+ thresh = float(self.text().replace(',','.'))
505
+ else:
506
+ thresh = int(self.text().replace(',','.'))
507
+ except ValueError:
508
+ if show_warning:
509
+ msgBox = QMessageBox()
510
+ msgBox.setWindowTitle('warning')
511
+ msgBox.setIcon(QMessageBox.Critical)
512
+ msgBox.setText("Please set a valid threshold value.")
513
+ msgBox.setWindowTitle("")
514
+ msgBox.setStandardButtons(QMessageBox.Ok)
515
+ returnValue = msgBox.exec()
516
+ thresh = None
517
+
518
+ return thresh
519
+
520
+ # class BackgroundFitCorrectionLayout(QGridLayout):
521
+
522
+ # """docstring for ClassName"""
523
+
524
+ # def __init__(self, parent=None, *args):
525
+ # super().__init__(*args)
526
+
527
+ # self.parent = parent
528
+ # self.channel_names = self.parent.channel_names # check this
529
+
530
+ # self.setContentsMargins(15,15,15,15)
531
+ # self.generate_widgets()
532
+ # self.add_to_layout()
533
+
534
+ # def generate_widgets(self):
535
+
536
+ # self.channel_lbl = QLabel('Channel: ')
537
+ # self.channels_cb = QComboBox()
538
+ # self.channels_cb.addItems(self.channel_names)
539
+
540
+ # self.thresh_lbl = QLabel('Threshold: ')
541
+ # self.thresh_lbl.setToolTip('Threshold on the STD-filtered image.\nPixel values above the threshold are\nconsidered as non-background and are\nmasked prior to background estimation.')
542
+ # self.threshold_viewer_btn = QPushButton()
543
+ # self.threshold_viewer_btn.setIcon(icon(MDI6.image_check, color="k"))
544
+ # self.threshold_viewer_btn.setStyleSheet(self.parent.parent.parent.button_select_all)
545
+ # self.threshold_viewer_btn.clicked.connect(self.set_threshold_graphically)
546
+
547
+ # self.model_lbl = QLabel('Model: ')
548
+ # self.models_cb = QComboBox()
549
+ # self.models_cb.addItems(['Paraboloid', 'Place'])
550
+
551
+ # self.operation_lbl = QLabel('Operation: ')
552
+ # self.operation_group = QButtonGroup()
553
+ # self.subtract_btn = QRadioButton('Subtract')
554
+ # self.divide_btn = QRadioButton('Divide')
555
+ # self.subtract_btn.toggled.connect(self.activate_clipping_options)
556
+ # self.divide_btn.toggled.connect(self.activate_clipping_options)
557
+
558
+ # self.operation_group.addButton(self.subtract_btn)
559
+ # self.operation_group.addButton(self.divide_btn)
560
+
561
+ # self.clip_group = QButtonGroup()
562
+ # self.clip_btn = QRadioButton('Clip')
563
+ # self.clip_not_btn = QRadioButton('Do not clip')
564
+
565
+ # self.clip_group.addButton(self.clip_btn)
566
+ # self.clip_group.addButton(self.clip_not_btn)
567
+
568
+ # self.corrected_stack_viewer = QPushButton("")
569
+ # self.corrected_stack_viewer.setStyleSheet(self.parent.parent.parent.button_select_all)
570
+ # self.corrected_stack_viewer.setIcon(icon(MDI6.eye_outline, color="black"))
571
+ # self.corrected_stack_viewer.setToolTip("View corrected image")
572
+ # self.corrected_stack_viewer.setIconSize(QSize(20, 20))
573
+
574
+ # self.add_correction_btn = QPushButton('Add correction')
575
+ # self.add_correction_btn.setStyleSheet(self.parent.parent.parent.button_style_sheet_2)
576
+ # self.add_correction_btn.setIcon(icon(MDI6.plus, color="#1565c0"))
577
+ # self.add_correction_btn.setToolTip('Add correction.')
578
+ # self.add_correction_btn.setIconSize(QSize(25, 25))
579
+ # self.add_correction_btn.clicked.connect(self.add_instructions_to_parent_list)
580
+
581
+ # self.threshold_le = ThresholdLineEdit(init_value=2, connected_buttons=[self.threshold_viewer_btn,
582
+ # self.corrected_stack_viewer,
583
+ # self.add_correction_btn
584
+ # ])
585
+
586
+ # def add_to_layout(self):
587
+
588
+ # channel_layout = QHBoxLayout()
589
+ # channel_layout.addWidget(self.channel_lbl, 25)
590
+ # channel_layout.addWidget(self.channels_cb, 75)
591
+ # self.addLayout(channel_layout, 0, 0, 1, 3)
592
+
593
+ # threshold_layout = QHBoxLayout()
594
+ # threshold_layout.addWidget(self.thresh_lbl, 25)
595
+ # threshold_layout.addWidget(self.threshold_le, 70)
596
+ # threshold_layout.addWidget(self.threshold_viewer_btn, 5)
597
+ # self.addLayout(threshold_layout, 1, 0, 1, 3)
598
+
599
+ # model_layout = QHBoxLayout()
600
+ # model_layout.addWidget(self.model_lbl, 25)
601
+ # model_layout.addWidget(self.models_cb, 75)
602
+ # self.addLayout(model_layout, 2, 0, 1, 3)
603
+
604
+ # operation_layout = QHBoxLayout()
605
+ # operation_layout.addWidget(self.operation_lbl, 25)
606
+ # operation_layout.addWidget(self.subtract_btn, 75//2, alignment=Qt.AlignCenter)
607
+ # operation_layout.addWidget(self.divide_btn, 75//2, alignment=Qt.AlignCenter)
608
+ # self.addLayout(operation_layout, 3, 0, 1, 3)
609
+
610
+ # clip_layout = QHBoxLayout()
611
+ # clip_layout.addWidget(QLabel(''), 25)
612
+ # clip_layout.addWidget(self.clip_btn, 75//4, alignment=Qt.AlignCenter)
613
+ # clip_layout.addWidget(self.clip_not_btn, 75//4, alignment=Qt.AlignCenter)
614
+ # clip_layout.addWidget(QLabel(''), 75//2)
615
+ # self.addLayout(clip_layout, 4, 0, 1, 3)
616
+
617
+ # self.addWidget(self.corrected_stack_viewer, 4, 2, 1, 1)
618
+ # self.addWidget(self.add_correction_btn, 5, 0, 1, 3)
619
+
620
+ # self.subtract_btn.click()
621
+ # self.clip_not_btn.click()
622
+
623
+ # verticalSpacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)
624
+ # self.addItem(verticalSpacer, 5, 0, 1, 3)
625
+
626
+ # def add_instructions_to_parent_list(self):
627
+
628
+ # self.generate_instructions()
629
+ # self.parent.background_correction.append(self.instructions)
630
+ # correction_description = ""
631
+ # for index, (key, value) in enumerate(self.instructions.items()):
632
+ # if index > 0:
633
+ # correction_description += ", "
634
+ # correction_description += str(key) + " : " + str(value)
635
+ # self.parent.normalisation_list.addItem(correction_description)
636
+
637
+ # def generate_instructions(self):
638
+
639
+ # if self.subtract_btn.isChecked():
640
+ # operation = "subtract"
641
+ # else:
642
+ # operation = "divide"
643
+ # clip = None
644
+
645
+ # if self.clip_btn.isChecked() and self.subtract_btn.isChecked():
646
+ # clip = True
647
+ # else:
648
+ # clip = False
649
+
650
+ # self.instructions = {
651
+ # "target_channel": self.channels_cb.currentText(),
652
+ # "correction_type": "fit",
653
+ # "threshold_on_std": self.threshold_le.get_threshold(),
654
+ # "operation": operation,
655
+ # "clip": clip
656
+ # }
657
+
658
+ # def activate_clipping_options(self):
659
+
660
+ # if self.subtract_btn.isChecked():
661
+ # self.clip_btn.setEnabled(True)
662
+ # self.clip_not_btn.setEnabled(True)
663
+
664
+ # else:
665
+ # self.clip_btn.setEnabled(False)
666
+ # self.clip_not_btn.setEnabled(False)
667
+
668
+ # def set_target_channel(self):
669
+
670
+ # channel_indices = _extract_channel_indices_from_config(self.parent.parent.exp_config, [self.channels_cb.currentText()])
671
+ # self.target_channel = channel_indices[0]
672
+
673
+ # def set_threshold_graphically(self):
674
+
675
+ # self.parent.locate_image()
676
+ # self.set_target_channel()
677
+ # thresh = self.threshold_le.get_threshold()
678
+
679
+ # if self.parent.current_stack is not None and thresh is not None:
680
+ # self.viewer = ThresholdedStackVisualizer(initial_threshold=thresh,
681
+ # parent_le = self.threshold_le,
682
+ # preprocessing=[['gauss',2],["std",4]],
683
+ # stack_path=self.parent.current_stack,
684
+ # n_channels=len(self.channel_names),
685
+ # target_channel=self.target_channel,
686
+ # window_title='Set the exclusion threshold',
687
+ # )
688
+ # self.viewer.show()
411
689
 
412
690
 
413
691
  def color_from_status(status, recently_modified=False):
414
- if not recently_modified:
415
- if status == 0:
416
- return 'tab:blue'
417
- elif status == 1:
418
- return 'tab:red'
419
- elif status == 2:
420
- return 'yellow'
421
- else:
422
- return 'k'
423
- else:
424
- if status == 0:
425
- return 'tab:cyan'
426
- elif status == 1:
427
- return 'tab:orange'
428
- elif status == 2:
429
- return 'tab:olive'
430
- else:
431
- return 'k'
692
+ if not recently_modified:
693
+ if status == 0:
694
+ return 'tab:blue'
695
+ elif status == 1:
696
+ return 'tab:red'
697
+ elif status == 2:
698
+ return 'yellow'
699
+ else:
700
+ return 'k'
701
+ else:
702
+ if status == 0:
703
+ return 'tab:cyan'
704
+ elif status == 1:
705
+ return 'tab:orange'
706
+ elif status == 2:
707
+ return 'tab:olive'
708
+ else:
709
+ return 'k'
432
710
 
433
711
  def color_from_state(state, recently_modified=False):
434
- unique_values = np.unique(state)
435
- color_map={}
436
- for value in unique_values:
437
- color_map[value] = plt.cm.tab10(value)
438
- if value == 99:
439
- color_map[value] = 'k'
440
- # colors = plt.cm.tab10(len(unique_values))
441
- # color_map = dict(zip(unique_values, colors))
442
- # print(color_map)
443
- return color_map
712
+ unique_values = np.unique(state)
713
+ color_map={}
714
+ for value in unique_values:
715
+ color_map[value] = plt.cm.tab10(value)
716
+ if value == 99:
717
+ color_map[value] = 'k'
718
+ # colors = plt.cm.tab10(len(unique_values))
719
+ # color_map = dict(zip(unique_values, colors))
720
+ # print(color_map)
721
+ return color_map
444
722
 
445
723
 
446
724
 
447
725
 
448
726
  def color_from_class(cclass, recently_modified=False):
449
- if not recently_modified:
450
- if cclass == 0:
451
- return 'tab:red'
452
- elif cclass == 1:
453
- return 'tab:blue'
454
- elif cclass == 2:
455
- return 'yellow'
456
- else:
457
- return 'k'
458
- else:
459
- if cclass == 0:
460
- return 'tab:orange'
461
- elif cclass == 1:
462
- return 'tab:cyan'
463
- elif cclass == 2:
464
- return 'tab:olive'
465
- else:
466
- return 'k'
727
+ if not recently_modified:
728
+ if cclass == 0:
729
+ return 'tab:red'
730
+ elif cclass == 1:
731
+ return 'tab:blue'
732
+ elif cclass == 2:
733
+ return 'yellow'
734
+ else:
735
+ return 'k'
736
+ else:
737
+ if cclass == 0:
738
+ return 'tab:orange'
739
+ elif cclass == 1:
740
+ return 'tab:cyan'
741
+ elif cclass == 2:
742
+ return 'tab:olive'
743
+ else:
744
+ return 'k'
467
745
 
468
746
 
469
747
  class ChannelChoice(QWidget):
470
748
 
471
- def __init__(self, parent):
472
- super().__init__()
473
- self.parent = parent
474
- #self.channel_names = channel_names
475
- self.setWindowTitle("Choose target channel")
476
- # Create the QComboBox and add some items
477
- self.combo_box = QComboBox(self)
478
- center_window(self)
749
+ def __init__(self, parent_window):
750
+ super().__init__()
751
+ self.parent_window = parent_window
752
+ #self.channel_names = channel_names
753
+ self.setWindowTitle("Choose target channel")
754
+ # Create the QComboBox and add some items
755
+ self.combo_box = QComboBox(self)
756
+ center_window(self)
479
757
 
480
- channels = parent.channel_names
758
+ channels = parent_window.channel_names
481
759
 
482
- self.combo_box.addItems(channels)
760
+ self.combo_box.addItems(channels)
483
761
 
484
- self.add_btn = QPushButton("Add")
485
- self.add_btn.clicked.connect(self.add_current_channel)
762
+ self.add_btn = QPushButton("Add")
763
+ self.add_btn.clicked.connect(self.add_current_channel)
486
764
 
487
- # Create the layout
488
- layout = QVBoxLayout(self)
489
- layout.addWidget(self.combo_box)
490
- layout.addWidget(self.add_btn)
765
+ # Create the layout
766
+ layout = QVBoxLayout(self)
767
+ layout.addWidget(self.combo_box)
768
+ layout.addWidget(self.add_btn)
491
769
 
492
- def add_current_channel(self):
493
- filtername = self.combo_box.currentText()
494
- self.parent.list_widget.addItems([filtername])
495
- self.close()
770
+ def add_current_channel(self):
771
+ filtername = self.combo_box.currentText()
772
+ self.parent_window.list_widget.addItems([filtername])
773
+ self.close()