auto-options-python 0.1.4__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.
autooptions/widget.py ADDED
@@ -0,0 +1,370 @@
1
+ from qtpy.QtWidgets import QVBoxLayout, QHBoxLayout, QPushButton
2
+ from napari.utils.events import Event
3
+ from qtpy.QtWidgets import QWidget
4
+ from autooptions.qtutil import WidgetTool
5
+ from autooptions.napari_util import NapariUtil
6
+
7
+
8
+
9
+ class OptionsWidget(QWidget):
10
+ """
11
+ Automatically creates a widget from an options object. The option values can be changed in the dialog.
12
+ When the Apply or the Ok-button is pressed the values are copied from the dialog to the options object and saved
13
+ to the options file.
14
+ """
15
+
16
+ def __init__(self, viewer, options, client=None):
17
+ """
18
+ Create a new options widget. Layer add and remove events are caught and
19
+ the combo-boxes are updated accordingly, depending on the layer types.
20
+
21
+ :param viewer: The napari viewer
22
+ :param options: The options from which the dialog is created
23
+ :param client: The client that handles callbacks when option values change
24
+ """
25
+ super().__init__()
26
+ self.setWindowTitle(options.optionsName)
27
+ self.viewer = viewer
28
+ self.client = client
29
+ self.options = options
30
+ self.fieldWidth = 50
31
+ self.napariUtil = NapariUtil(self.viewer)
32
+ self.imageLayers = self.napariUtil.getImageLayers()
33
+ self.fftLayers = self.napariUtil.getFFTLayers()
34
+ self.labelLayers = self.napariUtil.getLabelLayers()
35
+ self.pointLayers = self.napariUtil.getPointsLayers()
36
+ self.mainLayout = None
37
+ self.buttonsLayout = None
38
+ self.buttons = {}
39
+ self.imageComboBoxes = []
40
+ self.fftComboBoxes = []
41
+ self.labelComboBoxes = []
42
+ self.pointComboBoxes = []
43
+ self.widgets = {}
44
+ self.viewer.layers.events.inserted.connect(self._onLayerAddedOrRemoved)
45
+ self.viewer.layers.events.removed.connect(self._onLayerAddedOrRemoved)
46
+ self.input_layer = None
47
+ self._createLayout()
48
+
49
+
50
+ def addApplyButton(self, callback):
51
+ """
52
+ Add an apply button to the options widget. When the button is pressed the value are copied from the dialog
53
+ to the options object. The dialog remains open.
54
+
55
+ :param callback: The client can register a callback that is called when the apply button is pressed
56
+ """
57
+ button = self._createApplyButton(callback)
58
+ self.buttons['Apply'] = button
59
+ self._getButtonsLayout().addWidget(button)
60
+
61
+
62
+ def addOKButton(self, callback):
63
+ """
64
+ Add an ok button to the options widget. When the button is pressed the value are copied from the dialog
65
+ to the options object. The dialog is closed.
66
+
67
+ :param callback: The client can register a callback that is called when the ok button is pressed
68
+ """
69
+ button = self._createOKButton(callback)
70
+ self.buttons['Ok'] = button
71
+ self._getButtonsLayout().addWidget(button)
72
+
73
+
74
+ def addCancelButton(self, callback):
75
+ """
76
+ Add a cancel button to the options widget. When the button is pressed the dialog is closed, the values in the
77
+ dialog are not copied to the options object.
78
+
79
+ :param callback: The client can register a callback that is called when the ok button is pressed
80
+ """
81
+ button = self._createCancelButton(callback)
82
+ self.buttons['Cancel'] = button
83
+ self._getButtonsLayout().addWidget(button)
84
+
85
+
86
+ def getApplyButton(self):
87
+ """
88
+ Answers the apply button if it exists and None otherwise.
89
+ """
90
+ if 'Apply' in self.buttons.keys():
91
+ return self.buttons['Apply']
92
+ return None
93
+
94
+
95
+ def getOKButton(self):
96
+ """
97
+ Answers the ok button if it exists and None otherwise.
98
+ """
99
+ if 'Ok' in self.buttons.keys():
100
+ return self.buttons['Ok']
101
+ return None
102
+
103
+
104
+ def getCancelButton(self):
105
+ """
106
+ Answers the cancel button if it exists and None otherwise.
107
+ """
108
+ if 'Cancel' in self.buttons.keys():
109
+ return self.buttons['Cancel']
110
+ return None
111
+
112
+
113
+ def shut(self):
114
+ """
115
+ Shut down the options widget. Removes the dock-widget from the window and closes the widget.
116
+ """
117
+ self.viewer.window.remove_dock_widget(self)
118
+ self.close()
119
+
120
+
121
+ def getImageLayer(self, name):
122
+ """
123
+ Answer the image layer that has the name of the value of the option with the given name. The option must be
124
+ a layer selection option (image, labels, points, fft).
125
+
126
+ :param name: The name of an option
127
+ :return: The layer that has the name corresponding to the value of the option
128
+ """
129
+ layer = self.napariUtil.getLayerWithName(self.options.get(name)['value'])
130
+ return layer
131
+
132
+
133
+ def _callbackFor(self, name):
134
+ func = None
135
+ if self.client and name:
136
+ func = getattr(self.client, name)
137
+ return func
138
+
139
+
140
+ def _createLayout(self):
141
+ self.mainLayout = QVBoxLayout()
142
+ for name, item in self.options.items.items():
143
+ widget = None
144
+ if item['type'] == 'image':
145
+ layout, widget = self._getImageWidget(name, item)
146
+ self.mainLayout.addLayout(layout)
147
+ self.imageComboBoxes.append(widget)
148
+ if item['type'] == 'labels':
149
+ layout, widget = self._getLabelsWidget(name, item)
150
+ self.mainLayout.addLayout(layout)
151
+ self.labelComboBoxes.append(widget)
152
+ if item['type'] == 'points':
153
+ layout, widget = self._getPointsWidget(name, item)
154
+ self.mainLayout.addLayout(layout)
155
+ self.pointComboBoxes.append(widget)
156
+ if item['type'] == 'fft':
157
+ layout, widget = self._getFFTWidget(name, item)
158
+ self.mainLayout.addLayout(layout)
159
+ self.fftComboBoxes.append(widget)
160
+ if item['type'] == 'int':
161
+ layout, widget = self._getIntWidget(name, item)
162
+ self.mainLayout.addLayout(layout)
163
+ if item['type'] == 'float':
164
+ layout, widget = self._getFloatWidget(name, item)
165
+ self.mainLayout.addLayout(layout)
166
+ if item['type'] == 'choice':
167
+ layout, widget = self._getChoiceWidget(name, item)
168
+ self.mainLayout.addLayout(layout)
169
+ if item['type'] == 'str':
170
+ layout, widget = self._getStrWidget(name, item)
171
+ self.mainLayout.addLayout(layout)
172
+ if item['type'] == 'bool':
173
+ layout, widget = self._getBoolWidget(name, item)
174
+ self.mainLayout.addLayout(layout)
175
+ self.widgets[name] = widget
176
+ self.setLayout(self.mainLayout)
177
+
178
+
179
+ def _getImageWidget(self, name, item):
180
+ layout = QHBoxLayout()
181
+ self.imageLayers = self.napariUtil.getImageLayers()
182
+ label, widget = WidgetTool.getComboInput(self,
183
+ name +":",
184
+ self.imageLayers,
185
+ callback=self._callbackFor(item['callback']))
186
+ layout.addWidget(label)
187
+ layout.addWidget(widget)
188
+ return layout, widget
189
+
190
+
191
+ def _getLabelsWidget(self, name, item):
192
+ layout = QHBoxLayout()
193
+ self.labelLayers = self.napariUtil.getLabelLayers()
194
+ label, widget = WidgetTool.getComboInput(self,
195
+ name +":",
196
+ self.labelLayers,
197
+ callback=self._callbackFor(item['callback']))
198
+ layout.addWidget(label)
199
+ layout.addWidget(widget)
200
+ return layout, widget
201
+
202
+
203
+ def _getPointsWidget(self, name, item):
204
+ layout = QHBoxLayout()
205
+ self.pointsLayers = self.napariUtil.getPointsLayers()
206
+ label, widget = WidgetTool.getComboInput(self,
207
+ name +":",
208
+ self.pointsLayers,
209
+ callback=self._callbackFor(item['callback']))
210
+ layout.addWidget(label)
211
+ layout.addWidget(widget)
212
+ return layout, widget
213
+
214
+
215
+ def _getFFTWidget(self, name, item):
216
+ layout = QHBoxLayout()
217
+ self.fftLayers = self.napariUtil.getFFTLayers()
218
+ label, widget = WidgetTool.getComboInput(self,
219
+ name +":",
220
+ self.fftLayers,
221
+ callback=self._callbackFor(item['callback']))
222
+ layout.addWidget(label)
223
+ layout.addWidget(widget)
224
+ return layout, widget
225
+
226
+
227
+ def _getIntWidget(self, name, item):
228
+ layout = QHBoxLayout()
229
+ label, widget = WidgetTool.getLineInput(self,
230
+ name +":",
231
+ item['value'],
232
+ self.fieldWidth,
233
+ self._callbackFor(item['callback']))
234
+ layout.addWidget(label)
235
+ layout.addWidget(widget)
236
+ return layout, widget
237
+
238
+
239
+ def _getFloatWidget(self, name, item):
240
+ layout = QHBoxLayout()
241
+ label, widget = WidgetTool.getLineInput(self,
242
+ name +":",
243
+ item['value'],
244
+ self.fieldWidth,
245
+ self._callbackFor(item['callback']))
246
+ layout.addWidget(label)
247
+ layout.addWidget(widget)
248
+ return layout, widget
249
+
250
+
251
+ def _getStrWidget(self, name, item):
252
+ layout = QHBoxLayout()
253
+ label, widget = WidgetTool.getLineInput(self,
254
+ name +":",
255
+ item['value'],
256
+ self.fieldWidth,
257
+ self._callbackFor(item['callback']))
258
+ layout.addWidget(label)
259
+ layout.addWidget(widget)
260
+ return layout, widget
261
+
262
+
263
+ def _getChoiceWidget(self, name, item):
264
+ layout = QHBoxLayout()
265
+ label, widget = WidgetTool.getComboInput(self,
266
+ name +":",
267
+ item['choices'],
268
+ callback=self._callbackFor(item['callback']))
269
+ widget.setCurrentText(item['value'])
270
+ layout.addWidget(label)
271
+ layout.addWidget(widget)
272
+ return layout, widget
273
+
274
+
275
+ def _getBoolWidget(self, name, item):
276
+ layout = QHBoxLayout()
277
+ label, widget = WidgetTool.getCheckbox(self,
278
+ name,
279
+ item['value'],
280
+ self.fieldWidth,
281
+ self._callbackFor(item['callback']))
282
+ layout.addWidget(label)
283
+ layout.addWidget(widget)
284
+ return layout, widget
285
+
286
+ def _getButtonsLayout(self):
287
+ if not self.buttonsLayout:
288
+ self.buttonsLayout = QHBoxLayout()
289
+ self.mainLayout.addLayout(self.buttonsLayout)
290
+ return self.buttonsLayout
291
+
292
+
293
+ def _createApplyButton(self, callback):
294
+ button = self._createButton("&Apply", callback)
295
+ button.clicked.connect(self._onApplyButtonClicked)
296
+ return button
297
+
298
+
299
+ def _createOKButton(self, callback):
300
+ button = self._createButton("&Ok", callback)
301
+ button.clicked.connect(self._onOKButtonClicked)
302
+ return button
303
+
304
+
305
+ def _createCancelButton(self, callback):
306
+ button = self._createButton("&Cancel", callback)
307
+ button.clicked.connect(self._onCancelButtonClicked)
308
+ return button
309
+
310
+
311
+ @classmethod
312
+ def _createButton(cls, name, callback):
313
+ button = QPushButton(name)
314
+ if callback:
315
+ button.clicked.connect(callback)
316
+ return button
317
+
318
+
319
+ def _onApplyButtonClicked(self):
320
+ self._transferValues()
321
+ self.options.save()
322
+ self.options.load()
323
+
324
+
325
+ def _onOKButtonClicked(self):
326
+ self._transferValues()
327
+ self.options.save()
328
+ self.options.load()
329
+ self.shut()
330
+
331
+
332
+ def _onCancelButtonClicked(self):
333
+ self.shut()
334
+
335
+
336
+ def _transferValues(self):
337
+ for name, item in self.options.items.items():
338
+ widget = self.widgets[name]
339
+ if item['type'] in ['image', 'choice', 'fft']:
340
+ text = widget.currentText()
341
+ item['value'] = text
342
+ if item['type'] == 'int':
343
+ item['value'] = int(widget.text().strip())
344
+ if item['type'] == 'float':
345
+ item['value'] = float(widget.text().strip())
346
+ if item['type'] == 'str':
347
+ item['value'] = widget.text()
348
+ if item['type'] == 'bool':
349
+ item['value'] = widget.isChecked()
350
+
351
+
352
+ def _onLayerAddedOrRemoved(self, event: Event):
353
+ self._updateLayerSelectionComboBoxes()
354
+
355
+
356
+ def _updateLayerSelectionComboBoxes(self):
357
+ imageLayers = self.napariUtil.getImageLayers()
358
+ labelLayers = self.napariUtil.getLabelLayers()
359
+ pointLayers = self.napariUtil.getPointsLayers()
360
+ fftLayers = self.napariUtil.getFFTLayers()
361
+ for comboBox in self.imageComboBoxes:
362
+ WidgetTool.replaceItemsInComboBox(comboBox, imageLayers)
363
+ for comboBox in self.labelComboBoxes:
364
+ WidgetTool.replaceItemsInComboBox(comboBox, labelLayers)
365
+ for comboBox in self.pointComboBoxes:
366
+ WidgetTool.replaceItemsInComboBox(comboBox, pointLayers)
367
+ for comboBox in self.fftComboBoxes:
368
+ WidgetTool.replaceItemsInComboBox(comboBox, fftLayers)
369
+
370
+
scratch/options.py ADDED
@@ -0,0 +1,36 @@
1
+ import napari
2
+ from autooptions.options import Options
3
+ from autooptions.widget import OptionsWidget
4
+
5
+ class Client:
6
+
7
+ def __init__(self):
8
+ self.viewer = napari.Viewer()
9
+ self.options = None
10
+ self.widget = None
11
+
12
+
13
+ def onInputChanged(self, value):
14
+ if not value.isnumeric():
15
+ self.widget.widgets["size xy"].setText(str(self.options.value("size xy")))
16
+
17
+
18
+ def showOptions(self):
19
+ # Create a Qt widget, which will be our window.
20
+ self.options = Options("Test_Auto_Options", "Median Filter")
21
+ self.options.addImage('image', value=None, transient=True)
22
+ self.options.addInt('size xy', value=3, widget="input", callback=self.onInputChanged)
23
+ self.options.addInt('size z', value=1, widget="input")
24
+ self.options.addChoice('footprint', value=None, choices=["none", "cube", "ball", "octahedron"])
25
+ self.options.addInt('radius', value=1, widget="input")
26
+ self.options.load()
27
+ self.widget = OptionsWidget(self.viewer, self.options, self)
28
+ self.widget.addApplyButton(None)
29
+ #self.widget.addOKButton(None)
30
+ #self.widget.addCancelButton(None)
31
+ self.viewer.window.add_dock_widget(self.widget, name=self.options.optionsName)
32
+ self.viewer.show()
33
+ napari.run()
34
+
35
+ client = Client()
36
+ client.showOptions()