diff --git a/skimage/viewer/tests/test_widgets.py b/skimage/viewer/tests/test_widgets.py index ee4c91fb..a9f84fbd 100644 --- a/skimage/viewer/tests/test_widgets.py +++ b/skimage/viewer/tests/test_widgets.py @@ -3,7 +3,7 @@ import os from skimage import data, img_as_float, io from skimage.viewer import ImageViewer, viewer_available from skimage.viewer.widgets import ( - Slider, OKCancelButtons, SaveButtons, ComboBox, Text) + Slider, OKCancelButtons, SaveButtons, ComboBox, CheckBox, Text) from skimage.viewer.plugins.base import Plugin from skimage.viewer.qt import QtGui, QtCore from numpy.testing import assert_almost_equal, assert_equal @@ -17,6 +17,21 @@ def get_image_viewer(): return viewer +@skipif(not viewer_available) +def test_check_box(): + viewer = get_image_viewer() + cb = CheckBox('hello', value=True, alignment='left') + viewer.plugins[0] += cb + + assert_equal(cb.val, True) + cb.val = False + assert_equal(cb.val, False) + cb.val = 1 + assert_equal(cb.val, True) + cb.val = 0 + assert_equal(cb.val, False) + + @skipif(not viewer_available) def test_combo_box(): viewer = get_image_viewer() diff --git a/skimage/viewer/widgets/core.py b/skimage/viewer/widgets/core.py index 74fe9de4..91265633 100644 --- a/skimage/viewer/widgets/core.py +++ b/skimage/viewer/widgets/core.py @@ -22,7 +22,7 @@ from ..qt.QtCore import Qt from ..utils import RequiredAttr -__all__ = ['BaseWidget', 'Slider', 'ComboBox', 'Text'] +__all__ = ['BaseWidget', 'Slider', 'ComboBox', 'CheckBox', 'Text'] class BaseWidget(QtGui.QWidget): @@ -211,16 +211,16 @@ class ComboBox(BaseWidget): Parameters ---------- name : str - Name of slider parameter. If this parameter is passed as a keyword + Name of ComboBox parameter. If this parameter is passed as a keyword argument, it must match the name of that keyword argument (spaces are replaced with underscores). In addition, this name is displayed as the - name of the slider. - items: list + name of the ComboBox. + items: list of str Allowed parameter values. ptype : {'arg' | 'kwarg' | 'plugin'} Parameter type. callback : function - Callback function called in response to slider changes. This function + Callback function called in response to ComboBox changes. This function is typically set when the widget is added to a plugin. """ @@ -253,3 +253,55 @@ class ComboBox(BaseWidget): @index.setter def index(self, i): self._combo_box.setCurrentIndex(i) + + +class CheckBox(BaseWidget): + """CheckBox widget + + Parameters + ---------- + name : str + Name of CheckBox parameter. If this parameter is passed as a keyword + argument, it must match the name of that keyword argument (spaces are + replaced with underscores). In addition, this name is displayed as the + name of the CheckBox. + value: {False, True} + Initial state of the CheckBox. + alignment: {'center','left','right'} + Checkbox alignment + ptype : {'arg' | 'kwarg' | 'plugin'} + Parameter type + callback : function + Callback function called in response to CheckBox changes. This function + is typically set when the widget is added to a plugin. + """ + + def __init__(self, name, value=False, alignment='center', ptype='kwarg', + callback=None): + super(CheckBox, self).__init__(name, ptype, callback) + + self._check_box = QtGui.QCheckBox() + self._check_box.setChecked(value) + self._check_box.setText(self.name) + + self.layout = QtGui.QHBoxLayout(self) + if alignment == 'center': + self.layout.setAlignment(QtCore.Qt.AlignCenter) + elif alignment == 'left': + self.layout.setAlignment(QtCore.Qt.AlignLeft) + elif alignment == 'right': + self.layout.setAlignment(QtCore.Qt.AlignRight) + else: + raise ValueError("Unexpected value %s for 'alignment'" % alignment) + + self.layout.addWidget(self._check_box) + + self._check_box.stateChanged.connect(self._value_changed) + + @property + def val(self): + return self._check_box.isChecked() + + @val.setter + def val(self, i): + self._check_box.setChecked(i) diff --git a/viewer_examples/plugins/tv_denoise.py b/viewer_examples/plugins/tv_denoise.py new file mode 100644 index 00000000..5ad527ec --- /dev/null +++ b/viewer_examples/plugins/tv_denoise.py @@ -0,0 +1,27 @@ +from skimage import data +from skimage.restoration import denoise_tv_chambolle +from skimage.util import img_as_float +from numpy import random, clip + +from skimage.viewer import ImageViewer +from skimage.viewer.widgets import (Slider, CheckBox, OKCancelButtons, + SaveButtons) +from skimage.viewer.plugins.base import Plugin + + +image = img_as_float(data.chelsea()) +sigma = 30/255. + +image = image + random.normal(loc=0, scale=sigma, size=image.shape) +image = clip(image, 0, 1) +viewer = ImageViewer(image) + +plugin = Plugin(image_filter=denoise_tv_chambolle) +plugin += Slider('weight', 0.01, 5, value=0.3, value_type='float') +plugin += Slider('n_iter_max', 1, 100, value=20, value_type='int') +plugin += CheckBox('multichannel', value=True) +plugin += SaveButtons() +plugin += OKCancelButtons() + +viewer += plugin +viewer.show()