From 87fff89ee2bbbbc7e7aba82132fdafb473a229e6 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Tue, 6 Oct 2020 15:09:11 +0200 Subject: [PATCH 01/19] CreateInstance: New widget --- Orange/widgets/data/icons/CreateInstance.svg | 42 +++ Orange/widgets/data/owsimulator.py | 310 ++++++++++++++++++ Orange/widgets/data/tests/test_owsimulator.py | 89 +++++ 3 files changed, 441 insertions(+) create mode 100644 Orange/widgets/data/icons/CreateInstance.svg create mode 100644 Orange/widgets/data/owsimulator.py create mode 100644 Orange/widgets/data/tests/test_owsimulator.py diff --git a/Orange/widgets/data/icons/CreateInstance.svg b/Orange/widgets/data/icons/CreateInstance.svg new file mode 100644 index 00000000000..2a7b039df6d --- /dev/null +++ b/Orange/widgets/data/icons/CreateInstance.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Orange/widgets/data/owsimulator.py b/Orange/widgets/data/owsimulator.py new file mode 100644 index 00000000000..7976c8a5cbf --- /dev/null +++ b/Orange/widgets/data/owsimulator.py @@ -0,0 +1,310 @@ +from typing import Optional +from collections import namedtuple +from functools import singledispatch + +import numpy as np + +from AnyQt.QtCore import Qt, QSortFilterProxyModel, QSize +from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon +from AnyQt.QtWidgets import QLineEdit, QTableView, QSlider, QHeaderView, \ + QComboBox, QStyledItemDelegate, QWidget, QDateTimeEdit + +from Orange.data import Variable, DiscreteVariable, ContinuousVariable, \ + TimeVariable, Table +from Orange.widgets import gui +from Orange.widgets.settings import Setting +from Orange.widgets.utils.state_summary import format_summary_details, \ + format_multiple_summaries +from Orange.widgets.utils.widgetpreview import WidgetPreview +from Orange.widgets.widget import OWWidget, Input, Output + +VariableRole = next(gui.OrangeUserRole) +ValuesRole = next(gui.OrangeUserRole) +ValueRole = next(gui.OrangeUserRole) + + +class VariableDelegate(QStyledItemDelegate): + def paint(self, painter, option, index): + self.parent().view.openPersistentEditor(index) + super().paint(painter, option, index) + + def createEditor(self, parent, option, index): + # TODO: check ordering (proxy) + variable = index.data(VariableRole) + values = index.data(ValuesRole) + return _create_editor(variable, values, parent, self._commit_data) + + def _commit_data(self): + self.commitData.emit(self.sender()) + + def setEditorData(self, widget, index): + _set_value(widget, index.model().data(index, ValueRole)) + + def setModelData(self, widget, model, index): + model.setData(index, _get_value(widget), ValueRole) + + +@singledispatch +def _create_editor(_: Variable, __: np.ndarray, ___: QWidget, cb) -> QWidget: + raise NotImplementedError + + +@_create_editor.register(DiscreteVariable) +def _(variable: DiscreteVariable, _: np.ndarray, parent: QWidget, cb) -> QComboBox: + combo = QComboBox(parent) + combo.addItems(variable.values) + combo.currentIndexChanged.connect(cb) + return combo + + +@_create_editor.register(ContinuousVariable) +def _(_: ContinuousVariable, __: np.ndarray, parent: QWidget, cb) -> QSlider: + slider = QSlider(parent, orientation=Qt.Horizontal) + slider.valueChanged.connect(cb) + return slider + + +@_create_editor.register(TimeVariable) +def _(variable: TimeVariable, _: np.ndarray, parent: QWidget, cb) -> QDateTimeEdit: + edit = QDateTimeEdit(parent) + date_format = "yyyy-MM-dd hh:mm:ss" + if variable.have_date and not variable.have_time: + date_format = "yyyy-MM-dd" + elif not variable.have_date and variable.have_time: + date_format = "hh:mm:ss" + edit.setDisplayFormat(date_format) + edit.dateChanged.connect(cb) + return edit + + +@singledispatch +def _set_value(_: QWidget, __: float): + raise NotImplementedError + + +@_set_value.register(QComboBox) +def _(widget: QComboBox, value: str): + if isinstance(value, str): + widget.setCurrentText(value) + else: + widget.setCurrentIndex(int(value)) + + +@_set_value.register(QSlider) +def _(widget: QSlider, value: float): + widget.setValue(int(value)) + + +@_set_value.register(QDateTimeEdit) +def _(widget: QDateTimeEdit, value: float): + # TODO + widget.setDate(value) + + +@singledispatch +def _get_value(_: QWidget): + raise NotImplementedError + + +@_get_value.register(QComboBox) +def _(widget: QComboBox): + return widget.currentText() + + +@_get_value.register(QSlider) +def _(widget: QSlider): + return widget.value() + + +@_get_value.register(QDateTimeEdit) +def _(widget: QDateTimeEdit): + # TODO + return widget.date() + + +class OWCreateInstance(OWWidget): + name = "Create Instance" + description = "Interactively create a data instance from sample dataset." + icon = "icons/CreateInstance.svg" + category = "Data" + keywords = ["simulator"] + priority = 4000 + + class Inputs: + data = Input("Data", Table) + reference = Input("Reference", Table) + + class Outputs: + data = Output("Data", Table) + + want_main_area = True + HEADER = [ + ['name', "Variable"], + ['variable', "Value"], + ] + + auto_commit = Setting(True) + + def __init__(self): + super().__init__() + self.data: Optional[Table] = None + self.reference: Optional[Table] = None + self.Header = \ + namedtuple("header", [tag for tag, _ in self.HEADER])( + *range(len(self.HEADER)) + ) + self.setup_gui() + + def setup_gui(self): + self._add_controls() + self._add_table() + self._set_input_summary() + self._set_output_summary() + + def _add_controls(self): + box = gui.vBox(self.controlArea, "Initialize values") + kwargs = {"autoDefault": False} + gui.button(box, self, "Median", self.__median_button_clicked, **kwargs) + gui.button(box, self, "Mean", self.__mean_button_clicked, **kwargs) + gui.button(box, self, "Input", self.__input_button_clicked, **kwargs) + gui.rubber(self.controlArea) + gui.auto_apply(self.controlArea, self, "auto_commit") + + def __median_button_clicked(self): + print("median") + self.commit() + + def __mean_button_clicked(self): + print("mean") + self.commit() + + def __input_button_clicked(self): + print("input") + self.commit() + + def _add_table(self): + self.model = QStandardItemModel(self) + self.model.dataChanged.connect(self.__table_data_changed) + self.filter_edit = QLineEdit( + textChanged=self.__filter_edit_changed, + placeholderText="Filter..." + ) + self.view = QTableView(sortingEnabled=True) + self.view.setItemDelegateForColumn( + self.Header.variable, VariableDelegate(self) + ) + self.view.verticalHeader().hide() + header: QHeaderView = self.view.horizontalHeader() + header.setStretchLastSection(True) + header.setMaximumSectionSize(300) + self.proxy_model = QSortFilterProxyModel() + self.proxy_model.setFilterKeyColumn(-1) + self.proxy_model.setFilterCaseSensitivity(False) + self.proxy_model.setSourceModel(self.model) + self.view.setModel(self.proxy_model) + self.mainArea.layout().addWidget(self.filter_edit) + self.mainArea.layout().addWidget(self.view) + + def __table_data_changed(self): + self.commit() + + def __filter_edit_changed(self): + self.proxy_model.setFilterFixedString(self.filter_edit.text().strip()) + + @Inputs.data + def set_data(self, data: Table): + self.data = data + self._set_model_data() + + def _set_model_data(self): + def variable_icon() -> QIcon: + if var.is_discrete: + return gui.attributeIconDict[1] + elif var.is_time: + return gui.attributeIconDict[4] + elif var.is_continuous: + return gui.attributeIconDict[2] + else: + return gui.attributeIconDict[-1] + + def add_row(): + var_item = QStandardItem() + var_item.setData(var.name, Qt.DisplayRole) + var_item.setIcon(variable_icon()) + + control_item = QStandardItem() + values = self.data.get_column_view(var)[0] + control_item.setData(var, VariableRole) + control_item.setData(values, ValuesRole) + value = np.nanmedian(values.astype(float)) + if var.is_continuous: + value = round(value, var.number_of_decimals) + control_item.setData(value, ValueRole) + + self.model.appendRow([var_item, control_item]) + + self.model.clear() + self.model.setHorizontalHeaderLabels([x for _, x in self.HEADER]) + if not self.data: + return + for var in self.data.domain.variables + self.data.domain.metas: + if var.is_primitive(): + add_row() + self.view.resizeColumnsToContents() + + @Inputs.reference + def set_reference(self, data: Table): + self.reference = data + + def handleNewSignals(self): + self._set_input_summary() + self.unconditional_commit() + + def _set_input_summary(self): + n_data = len(self.data) if self.data else 0 + n_refs = len(self.reference) if self.reference else 0 + summary, details, kwargs = self.info.NoInput, "", {} + + if self.data or self.reference: + summary = f"{self.info.format_number(n_data)}, " \ + f"{self.info.format_number(n_refs)}" + data_list = [("Data", self.data), ("Reference", self.reference)] + details = format_multiple_summaries(data_list) + kwargs = {"format": Qt.RichText} + self.info.set_input_summary(summary, details, **kwargs) + + def _set_output_summary(self, data: Optional[Table] = None): + if data: + summary, details = len(data), format_summary_details(data) + else: + summary, details = self.info.NoOutput, "" + self.info.set_output_summary(summary, details) + + def commit(self): + data = None + if self.data: + data = Table.from_domain(self.data.domain, 1) + data = self._set_sample_values(data) + self._set_output_summary(data) + self.Outputs.data.send(data) + + def _set_sample_values(self, data: Table) -> Table: + for row in range(self.model.rowCount()): + model: QStandardItemModel = self.model + index = model.index(row, self.Header.variable) + var = model.data(index, VariableRole) + data[:, var] = model.data(index, ValueRole) + return data + + def send_report(self): + pass + + @staticmethod + def sizeHint(): + return QSize(800, 500) + + +if __name__ == "__main__": # pragma: no cover + table = Table("heart_disease") + WidgetPreview(OWCreateInstance).run(set_data=table, + set_reference=table[::2]) diff --git a/Orange/widgets/data/tests/test_owsimulator.py b/Orange/widgets/data/tests/test_owsimulator.py new file mode 100644 index 00000000000..cdcff8dc1e6 --- /dev/null +++ b/Orange/widgets/data/tests/test_owsimulator.py @@ -0,0 +1,89 @@ +# pylint: disable=missing-docstring +from Orange.data import Table +from Orange.widgets.data.owsimulator import OWCreateInstance +from Orange.widgets.tests.base import WidgetTest, datasets +from Orange.widgets.utils.state_summary import format_summary_details, \ + format_multiple_summaries + + +class TestOWCreateInstance(WidgetTest): + def setUp(self): + self.widget = self.create_widget(OWCreateInstance) + + def test_output(self): + data = Table("iris") + self.send_signal(self.widget.Inputs.data, data) + output = self.get_output(self.widget.Outputs.data) + self.assertEqual(len(output), 1) + self.assertEqual(output.domain, data.domain) + + def test_summary(self): + info = self.widget.info + data, reference = Table("iris"), Table("iris")[:1] + no_input, no_output = "No data on input", "No data on output" + + self.assertEqual(info._StateInfo__input_summary.brief, "") + self.assertEqual(info._StateInfo__input_summary.details, no_input) + self.assertEqual(info._StateInfo__output_summary.brief, "") + self.assertEqual(info._StateInfo__output_summary.details, no_output) + + self.send_signal(self.widget.Inputs.data, data) + data_list = [("Data", data), ("Reference", None)] + summary, details = "150, 0", format_multiple_summaries(data_list) + self.assertEqual(info._StateInfo__input_summary.brief, summary) + self.assertEqual(info._StateInfo__input_summary.details, details) + + output = self.get_output(self.widget.Outputs.data) + summary, details = f"{len(output)}", format_summary_details(output) + self.assertEqual(info._StateInfo__output_summary.brief, summary) + self.assertEqual(info._StateInfo__output_summary.details, details) + + self.send_signal(self.widget.Inputs.reference, reference) + data_list = [("Data", data), ("Reference", reference)] + summary, details = "150, 1", format_multiple_summaries(data_list) + self.assertEqual(info._StateInfo__input_summary.brief, summary) + self.assertEqual(info._StateInfo__input_summary.details, details) + + self.send_signal(self.widget.Inputs.data, None) + data_list = [("Data", None), ("Reference", reference)] + summary, details = "0, 1", format_multiple_summaries(data_list) + self.assertEqual(info._StateInfo__input_summary.brief, summary) + self.assertEqual(info._StateInfo__input_summary.details, details) + self.assertEqual(info._StateInfo__output_summary.brief, "") + self.assertEqual(info._StateInfo__output_summary.details, no_output) + + self.send_signal(self.widget.Inputs.reference, None) + self.assertEqual(info._StateInfo__input_summary.brief, "") + self.assertEqual(info._StateInfo__input_summary.details, no_input) + + def test_default_buttons(self): + self.send_signal(self.widget.Inputs.data, Table("iris")) + default_box = self.widget.controlArea.layout().itemAt(0).widget() + buttons = default_box.children()[1:] + buttons[0].click() + buttons[1].click() + buttons[2].click() + + def test_table(self): + data = Table("iris") + self.send_signal(self.widget.Inputs.data, data) + self.assertEqual(self.widget.view.model().rowCount(), 5) + self.assertEqual(self.widget.view.horizontalHeader().count(), 2) + + data = Table("zoo") + self.send_signal(self.widget.Inputs.data, data) + self.assertEqual(self.widget.view.model().rowCount(), 17) + self.assertEqual(self.widget.view.horizontalHeader().count(), 2) + + self.send_signal(self.widget.Inputs.data, None) + self.assertEqual(self.widget.view.model().rowCount(), 0) + self.assertEqual(self.widget.view.horizontalHeader().count(), 2) + + def test_datasets(self): + for ds in datasets.datasets(): + self.send_signal(self.widget.Inputs.data, ds) + + +if __name__ == "__main__": + import unittest + unittest.main() From ef6ecfaddec4487c515cd7269d50d538dc0fdcf5 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Thu, 15 Oct 2020 09:35:33 +0200 Subject: [PATCH 02/19] CreateInstance: Rename src file --- Orange/widgets/data/{owsimulator.py => owcreateinstance.py} | 0 .../tests/{test_owsimulator.py => test_owcreateinstance.py} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename Orange/widgets/data/{owsimulator.py => owcreateinstance.py} (100%) rename Orange/widgets/data/tests/{test_owsimulator.py => test_owcreateinstance.py} (98%) diff --git a/Orange/widgets/data/owsimulator.py b/Orange/widgets/data/owcreateinstance.py similarity index 100% rename from Orange/widgets/data/owsimulator.py rename to Orange/widgets/data/owcreateinstance.py diff --git a/Orange/widgets/data/tests/test_owsimulator.py b/Orange/widgets/data/tests/test_owcreateinstance.py similarity index 98% rename from Orange/widgets/data/tests/test_owsimulator.py rename to Orange/widgets/data/tests/test_owcreateinstance.py index cdcff8dc1e6..320f26cc357 100644 --- a/Orange/widgets/data/tests/test_owsimulator.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -1,6 +1,6 @@ # pylint: disable=missing-docstring from Orange.data import Table -from Orange.widgets.data.owsimulator import OWCreateInstance +from Orange.widgets.data.owcreateinstance import OWCreateInstance from Orange.widgets.tests.base import WidgetTest, datasets from Orange.widgets.utils.state_summary import format_summary_details, \ format_multiple_summaries From 346803bd8b4e4f327d3feaaa55aec156a6f41c1a Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Wed, 14 Oct 2020 09:33:05 +0200 Subject: [PATCH 03/19] CreateInstance: Improve editors --- Orange/widgets/data/owcreateinstance.py | 300 +++++++++++++----- .../data/tests/test_owcreateinstance.py | 115 ++++++- 2 files changed, 336 insertions(+), 79 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 7976c8a5cbf..4e608e07249 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -1,15 +1,18 @@ -from typing import Optional +from typing import Optional, Callable, List, Union from collections import namedtuple from functools import singledispatch import numpy as np -from AnyQt.QtCore import Qt, QSortFilterProxyModel, QSize -from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon +from AnyQt.QtCore import Qt, QSortFilterProxyModel, QSize, QDateTime, \ + QModelIndex, Signal +from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon, QPainter, \ + QDoubleValidator from AnyQt.QtWidgets import QLineEdit, QTableView, QSlider, QHeaderView, \ - QComboBox, QStyledItemDelegate, QWidget, QDateTimeEdit + QComboBox, QStyledItemDelegate, QWidget, QDateTimeEdit, QHBoxLayout, \ + QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem -from Orange.data import Variable, DiscreteVariable, ContinuousVariable, \ +from Orange.data import DiscreteVariable, ContinuousVariable, \ TimeVariable, Table from Orange.widgets import gui from Orange.widgets.settings import Setting @@ -23,103 +26,242 @@ ValueRole = next(gui.OrangeUserRole) +class VariableEditor(QWidget): + value_changed = Signal(float) + + def __init__(self, parent: QWidget, callback: Callable): + super().__init__(parent) + layout = QHBoxLayout() + layout.setContentsMargins(0, 0, 0, 0) + self.setLayout(layout) + self.value_changed.connect(callback) + + @property + def value(self) -> Union[int, float]: + return NotImplemented + + @value.setter + def value(self, value: float): + raise NotImplementedError + + +class DiscreteVariableEditor(VariableEditor): + value_changed = Signal(int) + + def __init__(self, parent: QWidget, items: List[str], callback: Callable): + super().__init__(parent, callback) + self._combo = QComboBox(parent) + self._combo.addItems(items) + self._combo.currentIndexChanged.connect(self.value_changed) + self.layout().addWidget(self._combo) + + @property + def value(self) -> int: + return self._combo.currentIndex() + + @value.setter + def value(self, value: float): + assert value == int(value) + self._combo.setCurrentIndex(int(value)) + + +class ContinuousVariableEditor(VariableEditor): + class Validator(QDoubleValidator): + def validate(self, string: str, pos: int): + if string == "": + return QDoubleValidator.Acceptable, "0", 1 + try: + float(string) + except ValueError: + return QDoubleValidator.Invalid, string, pos + return super().validate(string, pos) + + def __init__(self, parent: QWidget, variable: ContinuousVariable, + min_value: float, max_value: float, callback: Callable): + super().__init__(parent, callback) + self._value: float = min_value + self._min_value: float = min_value + self._max_value: float = max_value + self._n_decimals: int = variable.number_of_decimals + + kwargs = {"singleStep": 1, + "minimum": self.__map_to_slider(self.min_value), + "maximum": self.__map_to_slider(self.max_value), + "orientation": Qt.Horizontal} + self._slider = QSlider(parent, **kwargs) + self._slider.setMinimumWidth(100) + + kwargs = {"singleStep": 10 ** (-self._n_decimals), + "minimum": self.min_value, + "maximum": self.max_value, + "decimals": self._n_decimals} + self._spin = QDoubleSpinBox(parent, **kwargs) + self._spin.setFixedWidth(80) + + self._min_edit = QLineEdit( + parent, text=variable.repr_val(min_value), + frame=False, alignment=Qt.AlignRight, maximumWidth=80 + ) + self._min_edit.setValidator(self.Validator(decimals=self._n_decimals)) + + self._max_edit = QLineEdit( + parent, text=variable.repr_val(max_value), + frame=False, alignment=Qt.AlignLeft, maximumWidth=80 + ) + self._max_edit.setValidator(self.Validator(decimals=self._n_decimals)) + + self._slider.valueChanged.connect(self._apply_slider_value) + self._spin.valueChanged.connect(self._apply_spin_value) + self._min_edit.editingFinished.connect( + lambda: setattr(self, "min_value", float(self._min_edit.text())) + ) + self._max_edit.editingFinished.connect( + lambda: setattr(self, "max_value", float(self._max_edit.text())) + ) + + self._min_edit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) + self._slider.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + self._max_edit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) + self._spin.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + + self.layout().addWidget(self._min_edit) + self.layout().addWidget(self._slider) + self.layout().addWidget(self._max_edit) + self.layout().addWidget(self._spin) + self.layout().setContentsMargins(0, 0, 10, 0) + + @property + def value(self) -> float: + return self.__round_value(self._value) + + @value.setter + def value(self, value): + value = min(self._max_value, max(self._min_value, value)) + if self._value is None or self.__round_value(value) != self.value: + self._value = value + self.value_changed.emit(self.value) + self._value_to_slider() + self._value_to_spin() + + @property + def min_value(self): + return self.__round_value(self._min_value) + + @min_value.setter + def min_value(self, value): + self._min_value = value + self._slider.setMinimum(self.__map_to_slider(self.min_value)) + self._spin.setMinimum(self.min_value) + + @property + def max_value(self): + return self.__round_value(self._max_value) + + @max_value.setter + def max_value(self, value): + self._max_value = value + self._slider.setMaximum(self.__map_to_slider(self.max_value)) + self._spin.setMaximum(self.max_value) + + def _value_to_slider(self): + self._slider.setValue(self.__map_to_slider(self.value)) + + def _apply_slider_value(self): + self.value = self.__map_from_slider(self._slider.value()) + + def _value_to_spin(self): + self._spin.setValue(self.value) + + def _apply_spin_value(self): + self.value = self._spin.value() + + def __round_value(self, value): + return round(value, self._n_decimals) + + def __map_to_slider(self, value: float) -> int: + return round(value * 10 ** self._n_decimals) + + def __map_from_slider(self, value: int) -> float: + return value * 10 ** (-self._n_decimals) + + +# TODO +class TimeVariableEditor(VariableEditor): + def __init__(self, parent: QWidget, have_date: bool, + have_time: bool, callback: Callable): + super().__init__(parent) + self._editor = QDateTimeEdit(parent) + date_format = "yyyy-MM-dd hh:mm:ss" + if have_date and not have_time: + date_format = "yyyy-MM-dd" + elif not have_date and have_time: + date_format = "hh:mm:ss" + self._editor.setDisplayFormat(date_format) + self._editor.dateChanged.connect(callback) + self.layout().addWidget(self._editor) + + @property + def value(self): + return self._editor.date() + + @value.setter + def value(self, value): + self._editor.setDateTime(QDateTime(value)) + + class VariableDelegate(QStyledItemDelegate): - def paint(self, painter, option, index): + def paint(self, painter: QPainter, option: QStyleOptionViewItem, + index: QModelIndex): self.parent().view.openPersistentEditor(index) super().paint(painter, option, index) - def createEditor(self, parent, option, index): - # TODO: check ordering (proxy) + def createEditor(self, parent: QWidget, option: QStyleOptionViewItem, + index: QModelIndex) -> VariableEditor: variable = index.data(VariableRole) values = index.data(ValuesRole) return _create_editor(variable, values, parent, self._commit_data) def _commit_data(self): - self.commitData.emit(self.sender()) + editor = self.sender() + assert isinstance(editor, VariableEditor) + self.commitData.emit(editor) + + def setEditorData(self, editor: VariableEditor, index: QModelIndex): + editor.value = index.model().data(index, ValueRole) - def setEditorData(self, widget, index): - _set_value(widget, index.model().data(index, ValueRole)) + def setModelData(self, editor: VariableEditor, + model: QSortFilterProxyModel, index: QModelIndex): + model.setData(index, editor.value, ValueRole) - def setModelData(self, widget, model, index): - model.setData(index, _get_value(widget), ValueRole) + def sizeHint(self, option: QStyleOptionViewItem, + index: QModelIndex) -> QSize: + sh = super().sizeHint(option, index) + return QSize(sh.width(), sh.height() + 20) @singledispatch -def _create_editor(_: Variable, __: np.ndarray, ___: QWidget, cb) -> QWidget: +def _create_editor(*_) -> VariableEditor: raise NotImplementedError @_create_editor.register(DiscreteVariable) -def _(variable: DiscreteVariable, _: np.ndarray, parent: QWidget, cb) -> QComboBox: - combo = QComboBox(parent) - combo.addItems(variable.values) - combo.currentIndexChanged.connect(cb) - return combo +def _(variable: DiscreteVariable, _: np.ndarray, + parent: QWidget, callback: Callable) -> DiscreteVariableEditor: + return DiscreteVariableEditor(parent, variable.values, callback) @_create_editor.register(ContinuousVariable) -def _(_: ContinuousVariable, __: np.ndarray, parent: QWidget, cb) -> QSlider: - slider = QSlider(parent, orientation=Qt.Horizontal) - slider.valueChanged.connect(cb) - return slider +def _(variable: ContinuousVariable, values: np.ndarray, + parent: QWidget, callback: Callable) -> ContinuousVariableEditor: + return ContinuousVariableEditor(parent, variable, np.nanmin(values), + np.nanmax(values), callback) @_create_editor.register(TimeVariable) -def _(variable: TimeVariable, _: np.ndarray, parent: QWidget, cb) -> QDateTimeEdit: - edit = QDateTimeEdit(parent) - date_format = "yyyy-MM-dd hh:mm:ss" - if variable.have_date and not variable.have_time: - date_format = "yyyy-MM-dd" - elif not variable.have_date and variable.have_time: - date_format = "hh:mm:ss" - edit.setDisplayFormat(date_format) - edit.dateChanged.connect(cb) - return edit - - -@singledispatch -def _set_value(_: QWidget, __: float): - raise NotImplementedError - - -@_set_value.register(QComboBox) -def _(widget: QComboBox, value: str): - if isinstance(value, str): - widget.setCurrentText(value) - else: - widget.setCurrentIndex(int(value)) - - -@_set_value.register(QSlider) -def _(widget: QSlider, value: float): - widget.setValue(int(value)) - - -@_set_value.register(QDateTimeEdit) -def _(widget: QDateTimeEdit, value: float): - # TODO - widget.setDate(value) - - -@singledispatch -def _get_value(_: QWidget): - raise NotImplementedError - - -@_get_value.register(QComboBox) -def _(widget: QComboBox): - return widget.currentText() - - -@_get_value.register(QSlider) -def _(widget: QSlider): - return widget.value() - - -@_get_value.register(QDateTimeEdit) -def _(widget: QDateTimeEdit): - # TODO - return widget.date() +def _(variable: TimeVariable, _: np.ndarray, + parent: QWidget, callback: Callable) -> TimeVariableEditor: + return TimeVariableEditor(parent, variable.have_date, + variable.have_time, callback) class OWCreateInstance(OWWidget): @@ -231,6 +373,7 @@ def add_row(): var_item = QStandardItem() var_item.setData(var.name, Qt.DisplayRole) var_item.setIcon(variable_icon()) + var_item.setEditable(False) control_item = QStandardItem() values = self.data.get_column_view(var)[0] @@ -251,6 +394,7 @@ def add_row(): if var.is_primitive(): add_row() self.view.resizeColumnsToContents() + self.view.resizeRowsToContents() @Inputs.reference def set_reference(self, data: Table): diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index 320f26cc357..38431ab51db 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -1,6 +1,14 @@ # pylint: disable=missing-docstring +from unittest.mock import Mock + +import numpy as np + +from AnyQt.QtWidgets import QWidget + +from orangewidget.tests.base import GuiTest from Orange.data import Table -from Orange.widgets.data.owcreateinstance import OWCreateInstance +from Orange.widgets.data.owcreateinstance import OWCreateInstance, \ + DiscreteVariableEditor, ContinuousVariableEditor from Orange.widgets.tests.base import WidgetTest, datasets from Orange.widgets.utils.state_summary import format_summary_details, \ format_multiple_summaries @@ -84,6 +92,111 @@ def test_datasets(self): self.send_signal(self.widget.Inputs.data, ds) +class TestDiscreteVariableEditor(GuiTest): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.parent = QWidget() + + def setUp(self): + self.callback = Mock() + self.editor = DiscreteVariableEditor( + self.parent, ["Foo", "Bar"], self.callback + ) + + def test_init(self): + self.assertEqual(self.editor.value, 0) + self.assertEqual(self.editor._combo.currentText(), "Foo") + self.callback.assert_not_called() + + def test_edit(self): + """ Edit combo by user. """ + self.editor._combo.setCurrentText("Bar") + self.assertEqual(self.editor.value, 1) + self.assertEqual(self.editor._combo.currentText(), "Bar") + self.callback.assert_called_once() + + def test_set_value(self): + """ Programmatically set combo box value. """ + self.editor.value = 1 + self.assertEqual(self.editor.value, 1) + self.assertEqual(self.editor._combo.currentText(), "Bar") + self.callback.assert_called_once() + + +class TestContinuousVariableEditor(GuiTest): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.parent = QWidget() + + def setUp(self): + self.callback = Mock() + self.data = Table("iris") + self.variable = self.data.domain[0] + values = self.data.get_column_view(self.variable)[0] + self.min_value = np.nanmin(values) + self.max_value = np.nanmax(values) + self.editor = ContinuousVariableEditor( + self.parent, self.variable, self.min_value, + self.max_value, self.callback + ) + + def test_init(self): + self.assertEqual(self.editor.value, self.min_value) + self.assertEqual(self.editor._slider.value(), self.min_value * 10) + self.assertEqual(self.editor._spin.value(), self.min_value) + self.callback.assert_not_called() + + def test_edit_slider(self): + """ Edit slider by user. """ + self.editor._slider.setValue(self.max_value * 10) + self.assertEqual(self.editor.value, self.max_value) + self.assertEqual(self.editor._slider.value(), self.max_value * 10) + self.assertEqual(self.editor._spin.value(), self.max_value) + self.callback.assert_called_once() + + self.callback.reset_mock() + value = self.min_value + (self.max_value - self.min_value) / 2 + self.editor._slider.setValue(value * 10) + self.assertEqual(self.editor.value, value) + self.assertEqual(self.editor._slider.value(), value * 10) + self.assertEqual(self.editor._spin.value(), value) + self.callback.assert_called_once() + + def test_edit_spin(self): + """ Edit spin by user. """ + self.editor._spin.setValue(self.max_value) + self.assertEqual(self.editor.value, self.max_value) + self.assertEqual(self.editor._slider.value(), self.max_value * 10) + self.assertEqual(self.editor._spin.value(), self.max_value) + self.callback.assert_called_once() + + self.callback.reset_mock() + value = self.min_value + (self.max_value - self.min_value) / 2 + self.editor._spin.setValue(value) + self.assertEqual(self.editor.value, value) + self.assertEqual(self.editor._slider.value(), value * 10) + self.assertEqual(self.editor._spin.value(), value) + self.callback.assert_called_once() + + def test_set_value(self): + """ Programmatically set slider/spin value. """ + self.editor.value = -2 + self.assertEqual(self.editor._slider.value(), self.min_value * 10) + self.assertEqual(self.editor._spin.value(), self.min_value) + self.assertEqual(self.editor.value, self.min_value) + self.callback.assert_not_called() + + self.callback.reset_mock() + value = self.min_value + (self.max_value - self.min_value) / 4 + self.editor.value = value + self.assertEqual(self.editor._slider.value(), value * 10) + self.assertEqual(self.editor._spin.value(), value) + self.assertEqual(self.editor.value, value) + self.callback.assert_called_once() + + if __name__ == "__main__": import unittest unittest.main() From b7fab5f88a265c8ed23cb02a2f59d738fae24ad8 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Fri, 16 Oct 2020 12:58:18 +0200 Subject: [PATCH 04/19] ContinuousVariableEditor: Simplify editor --- Orange/widgets/data/owcreateinstance.py | 162 +++++++++--------- .../data/tests/test_owcreateinstance.py | 34 ++-- 2 files changed, 100 insertions(+), 96 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 4e608e07249..5dc04fcba87 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -6,11 +6,10 @@ from AnyQt.QtCore import Qt, QSortFilterProxyModel, QSize, QDateTime, \ QModelIndex, Signal -from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon, QPainter, \ - QDoubleValidator +from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon, QPainter from AnyQt.QtWidgets import QLineEdit, QTableView, QSlider, QHeaderView, \ QComboBox, QStyledItemDelegate, QWidget, QDateTimeEdit, QHBoxLayout, \ - QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem + QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem, QLabel from Orange.data import DiscreteVariable, ContinuousVariable, \ TimeVariable, Table @@ -66,112 +65,103 @@ def value(self, value: float): class ContinuousVariableEditor(VariableEditor): - class Validator(QDoubleValidator): - def validate(self, string: str, pos: int): - if string == "": - return QDoubleValidator.Acceptable, "0", 1 - try: - float(string) - except ValueError: - return QDoubleValidator.Invalid, string, pos - return super().validate(string, pos) + MAX_FLOAT = 2147483647 def __init__(self, parent: QWidget, variable: ContinuousVariable, min_value: float, max_value: float, callback: Callable): super().__init__(parent, callback) + + if np.isnan(min_value) or np.isnan(max_value): + raise ValueError("Min/Max cannot be NaN.") + + n_decimals = variable.number_of_decimals + abs_max = max(abs(min_value), max_value) + if abs_max * 10 ** n_decimals > self.MAX_FLOAT: + n_decimals = int(np.log10(self.MAX_FLOAT / abs_max)) + self._value: float = min_value - self._min_value: float = min_value - self._max_value: float = max_value - self._n_decimals: int = variable.number_of_decimals - - kwargs = {"singleStep": 1, - "minimum": self.__map_to_slider(self.min_value), - "maximum": self.__map_to_slider(self.max_value), - "orientation": Qt.Horizontal} - self._slider = QSlider(parent, **kwargs) - self._slider.setMinimumWidth(100) - - kwargs = {"singleStep": 10 ** (-self._n_decimals), - "minimum": self.min_value, - "maximum": self.max_value, - "decimals": self._n_decimals} - self._spin = QDoubleSpinBox(parent, **kwargs) - self._spin.setFixedWidth(80) - - self._min_edit = QLineEdit( - parent, text=variable.repr_val(min_value), - frame=False, alignment=Qt.AlignRight, maximumWidth=80 + self._n_decimals: int = n_decimals + self._min_value: float = self.__round_value(min_value) + self._max_value: float = self.__round_value(max_value) + + sp_spin = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + sp_slider = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + sp_slider.setHorizontalStretch(5) + sp_edit = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + sp_edit.setHorizontalStretch(1) + + self._spin = QDoubleSpinBox( + parent, + value=self._min_value, + minimum=-np.inf, + maximum=np.inf, + singleStep=10 ** (-self._n_decimals), + decimals=self._n_decimals, + minimumWidth=70, + sizePolicy=sp_spin, ) - self._min_edit.setValidator(self.Validator(decimals=self._n_decimals)) - - self._max_edit = QLineEdit( - parent, text=variable.repr_val(max_value), - frame=False, alignment=Qt.AlignLeft, maximumWidth=80 + self._slider = QSlider( + parent, + minimum=self.__map_to_slider(self._min_value), + maximum=self.__map_to_slider(self._max_value), + singleStep=1, + orientation=Qt.Horizontal, + minimumWidth=20, + sizePolicy=sp_slider, ) - self._max_edit.setValidator(self.Validator(decimals=self._n_decimals)) - - self._slider.valueChanged.connect(self._apply_slider_value) - self._spin.valueChanged.connect(self._apply_spin_value) - self._min_edit.editingFinished.connect( - lambda: setattr(self, "min_value", float(self._min_edit.text())) + self._label_min = QLabel( + parent, + text=variable.repr_val(min_value), + alignment=Qt.AlignRight, + minimumWidth=60, + sizePolicy=sp_edit, ) - self._max_edit.editingFinished.connect( - lambda: setattr(self, "max_value", float(self._max_edit.text())) + self._label_max = QLabel( + parent, + text=variable.repr_val(max_value), + alignment=Qt.AlignLeft, + minimumWidth=60, + sizePolicy=sp_edit, ) - self._min_edit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) - self._slider.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) - self._max_edit.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) - self._spin.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + self._slider.valueChanged.connect(self._apply_slider_value) + self._spin.valueChanged.connect(self._apply_spin_value) - self.layout().addWidget(self._min_edit) - self.layout().addWidget(self._slider) - self.layout().addWidget(self._max_edit) self.layout().addWidget(self._spin) - self.layout().setContentsMargins(0, 0, 10, 0) + self.layout().addWidget(self._label_min) + self.layout().addWidget(self._slider) + self.layout().addWidget(self._label_max) + self.layout().setContentsMargins(4, 0, 0, 4) + self.setMinimumWidth(200) + + self.setFocusProxy(self._spin) + + # FIXME: after setting focus proxy to the spin, the text is highlighted + + def deselect(): + self._spin.lineEdit().deselect() + try: + self._spin.lineEdit().selectionChanged.disconnect(deselect) + except TypeError: + pass + + self._spin.lineEdit().selectionChanged.connect(deselect) @property def value(self) -> float: return self.__round_value(self._value) @value.setter - def value(self, value): - value = min(self._max_value, max(self._min_value, value)) + def value(self, value: float): if self._value is None or self.__round_value(value) != self.value: self._value = value self.value_changed.emit(self.value) - self._value_to_slider() - self._value_to_spin() - - @property - def min_value(self): - return self.__round_value(self._min_value) - - @min_value.setter - def min_value(self, value): - self._min_value = value - self._slider.setMinimum(self.__map_to_slider(self.min_value)) - self._spin.setMinimum(self.min_value) - - @property - def max_value(self): - return self.__round_value(self._max_value) - - @max_value.setter - def max_value(self, value): - self._max_value = value - self._slider.setMaximum(self.__map_to_slider(self.max_value)) - self._spin.setMaximum(self.max_value) - - def _value_to_slider(self): - self._slider.setValue(self.__map_to_slider(self.value)) + self._spin.setValue(self.value) + self._slider.setValue(self.__map_to_slider(self.value)) def _apply_slider_value(self): self.value = self.__map_from_slider(self._slider.value()) - def _value_to_spin(self): - self._spin.setValue(self.value) - def _apply_spin_value(self): self.value = self._spin.value() @@ -179,6 +169,7 @@ def __round_value(self, value): return round(value, self._n_decimals) def __map_to_slider(self, value: float) -> int: + value = min(self._max_value, max(self._min_value, value)) return round(value * 10 ** self._n_decimals) def __map_from_slider(self, value: int) -> float: @@ -331,7 +322,8 @@ def _add_table(self): textChanged=self.__filter_edit_changed, placeholderText="Filter..." ) - self.view = QTableView(sortingEnabled=True) + self.view = QTableView(sortingEnabled=True, + selectionMode=QTableView.NoSelection) self.view.setItemDelegateForColumn( self.Header.variable, VariableDelegate(self) ) diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index 38431ab51db..3b4fefb0856 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -132,13 +132,12 @@ def setUpClass(cls): def setUp(self): self.callback = Mock() - self.data = Table("iris") - self.variable = self.data.domain[0] - values = self.data.get_column_view(self.variable)[0] - self.min_value = np.nanmin(values) - self.max_value = np.nanmax(values) + data = Table("iris") + values = data.get_column_view(data.domain[0])[0] + self.min_value = np.min(values) + self.max_value = np.max(values) self.editor = ContinuousVariableEditor( - self.parent, self.variable, self.min_value, + self.parent, data.domain[0], self.min_value, self.max_value, self.callback ) @@ -150,7 +149,7 @@ def test_init(self): def test_edit_slider(self): """ Edit slider by user. """ - self.editor._slider.setValue(self.max_value * 10) + self.editor._slider.setValue(int(self.max_value * 10)) self.assertEqual(self.editor.value, self.max_value) self.assertEqual(self.editor._slider.value(), self.max_value * 10) self.assertEqual(self.editor._spin.value(), self.max_value) @@ -158,7 +157,7 @@ def test_edit_slider(self): self.callback.reset_mock() value = self.min_value + (self.max_value - self.min_value) / 2 - self.editor._slider.setValue(value * 10) + self.editor._slider.setValue(int(value * 10)) self.assertEqual(self.editor.value, value) self.assertEqual(self.editor._slider.value(), value * 10) self.assertEqual(self.editor._spin.value(), value) @@ -172,6 +171,13 @@ def test_edit_spin(self): self.assertEqual(self.editor._spin.value(), self.max_value) self.callback.assert_called_once() + self.callback.reset_mock() + self.editor._spin.setValue(self.max_value + 1) + self.assertEqual(self.editor.value, self.max_value + 1) + self.assertEqual(self.editor._slider.value(), self.max_value * 10) + self.assertEqual(self.editor._spin.value(), self.max_value + 1) + self.callback.assert_called_once() + self.callback.reset_mock() value = self.min_value + (self.max_value - self.min_value) / 2 self.editor._spin.setValue(value) @@ -184,9 +190,9 @@ def test_set_value(self): """ Programmatically set slider/spin value. """ self.editor.value = -2 self.assertEqual(self.editor._slider.value(), self.min_value * 10) - self.assertEqual(self.editor._spin.value(), self.min_value) - self.assertEqual(self.editor.value, self.min_value) - self.callback.assert_not_called() + self.assertEqual(self.editor._spin.value(), -2) + self.assertEqual(self.editor.value, -2) + self.callback.assert_called_once() self.callback.reset_mock() value = self.min_value + (self.max_value - self.min_value) / 4 @@ -196,6 +202,12 @@ def test_set_value(self): self.assertEqual(self.editor.value, value) self.callback.assert_called_once() + def test_missing_values(self): + domain = Domain([ContinuousVariable("var")]) + data = Table(domain, np.array([[np.nan], [np.nan]])) + self.assertRaises(ValueError, ContinuousVariableEditor, self.parent, + data.domain[0], np.nan, np.nan, Mock()) + if __name__ == "__main__": import unittest From b4a11f943dee2e2e3d34b6fd0978601edd1f4deb Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Mon, 19 Oct 2020 10:00:06 +0200 Subject: [PATCH 05/19] OWCreateInstance: Init values --- Orange/widgets/data/owcreateinstance.py | 125 ++++++++++++++---- .../data/tests/test_owcreateinstance.py | 87 +++++++++--- 2 files changed, 173 insertions(+), 39 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 5dc04fcba87..8825876f861 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -18,7 +18,7 @@ from Orange.widgets.utils.state_summary import format_summary_details, \ format_multiple_summaries from Orange.widgets.utils.widgetpreview import WidgetPreview -from Orange.widgets.widget import OWWidget, Input, Output +from Orange.widgets.widget import OWWidget, Input, Output, Msg VariableRole = next(gui.OrangeUserRole) ValuesRole = next(gui.OrangeUserRole) @@ -255,6 +255,18 @@ def _(variable: TimeVariable, _: np.ndarray, variable.have_time, callback) +def majority(values: np.ndarray) -> int: + return np.bincount(values[~np.isnan(values)].astype(int)).argmax() + + +def disc_random(values: np.ndarray) -> int: + return np.random.randint(low=np.nanmin(values), high=np.nanmax(values) + 1) + + +def cont_random(values: np.ndarray) -> float: + return np.random.uniform(low=np.nanmin(values), high=np.nanmax(values)) + + class OWCreateInstance(OWWidget): name = "Create Instance" description = "Interactively create a data instance from sample dataset." @@ -270,6 +282,10 @@ class Inputs: class Outputs: data = Output("Data", Table) + class Information(OWWidget.Information): + nans_removed = Msg("Variables with only missing values were " + "removed from the list.") + want_main_area = True HEADER = [ ['name', "Variable"], @@ -286,6 +302,11 @@ def __init__(self): namedtuple("header", [tag for tag, _ in self.HEADER])( *range(len(self.HEADER)) ) + + self.model: Optional[QStandardItemModel] = None + self.proxy_model: Optional[QSortFilterProxyModel] = None + self.view: Optional[QTableView] = None + self.filter_edit: Optional[QLineEdit] = None self.setup_gui() def setup_gui(self): @@ -299,25 +320,32 @@ def _add_controls(self): kwargs = {"autoDefault": False} gui.button(box, self, "Median", self.__median_button_clicked, **kwargs) gui.button(box, self, "Mean", self.__mean_button_clicked, **kwargs) + gui.button(box, self, "Random", self.__random_button_clicked, **kwargs) gui.button(box, self, "Input", self.__input_button_clicked, **kwargs) gui.rubber(self.controlArea) gui.auto_apply(self.controlArea, self, "auto_commit") def __median_button_clicked(self): - print("median") + self._initialize_values("median") self.commit() def __mean_button_clicked(self): - print("mean") + self._initialize_values("mean") + self.commit() + + def __random_button_clicked(self): + self._initialize_values("random") self.commit() def __input_button_clicked(self): - print("input") + if not self.reference: + return + self._initialize_values("input") self.commit() def _add_table(self): self.model = QStandardItemModel(self) - self.model.dataChanged.connect(self.__table_data_changed) + # self.model.dataChanged.connect(self.__table_data_changed) self.filter_edit = QLineEdit( textChanged=self.__filter_edit_changed, placeholderText="Filter..." @@ -348,53 +376,98 @@ def __filter_edit_changed(self): @Inputs.data def set_data(self, data: Table): self.data = data + self._set_input_summary() self._set_model_data() + self.unconditional_commit() def _set_model_data(self): - def variable_icon() -> QIcon: - if var.is_discrete: + def variable_icon(variable) -> QIcon: + if variable.is_discrete: return gui.attributeIconDict[1] - elif var.is_time: + elif variable.is_time: return gui.attributeIconDict[4] - elif var.is_continuous: + elif variable.is_continuous: return gui.attributeIconDict[2] else: return gui.attributeIconDict[-1] - def add_row(): + def add_row(variable, values): var_item = QStandardItem() - var_item.setData(var.name, Qt.DisplayRole) - var_item.setIcon(variable_icon()) + var_item.setData(variable.name, Qt.DisplayRole) + var_item.setIcon(variable_icon(variable)) var_item.setEditable(False) control_item = QStandardItem() - values = self.data.get_column_view(var)[0] - control_item.setData(var, VariableRole) + control_item.setData(variable, VariableRole) control_item.setData(values, ValuesRole) - value = np.nanmedian(values.astype(float)) - if var.is_continuous: - value = round(value, var.number_of_decimals) - control_item.setData(value, ValueRole) self.model.appendRow([var_item, control_item]) + self.Information.nans_removed.clear() self.model.clear() self.model.setHorizontalHeaderLabels([x for _, x in self.HEADER]) if not self.data: return for var in self.data.domain.variables + self.data.domain.metas: if var.is_primitive(): - add_row() + vals = self.data.get_column_view(var)[0].astype(float) + if all(np.isnan(vals)): + self.Information.nans_removed() + continue + add_row(var, vals) + + self.model.dataChanged.connect(self.__table_data_changed) + self._initialize_values("median") self.view.resizeColumnsToContents() self.view.resizeRowsToContents() + def _initialize_values(self, fun: str): + cont_fun = {"median": np.nanmedian, + "mean": np.nanmean, + "random": cont_random, + "input": np.nanmean}.get(fun, NotImplemented) + disc_fun = {"median": majority, + "mean": majority, + "random": disc_random, + "input": majority}.get(fun, NotImplemented) + + if not self.data: + return + + # do not commit between initialization + self.model.dataChanged.disconnect(self.__table_data_changed) + for row in range(self.model.rowCount()): + index = self.model.index(row, self.Header.variable) + variable = self.model.data(index, VariableRole) + + if fun == "input": + if variable not in self.reference.domain: + continue + values = self.reference.get_column_view(variable)[0] + if variable.is_primitive(): + values = values.astype(float) + if all(np.isnan(values)): + continue + else: + values = self.model.data(index, ValuesRole) + + if variable.is_continuous: + value = cont_fun(values) + value = round(value, variable.number_of_decimals) + elif variable.is_discrete: + value = disc_fun(values) + elif variable.is_string: + value = "" + else: + raise NotImplementedError + + self.model.setData(index, value, ValueRole) + self.model.dataChanged.connect(self.__table_data_changed) + @Inputs.reference def set_reference(self, data: Table): self.reference = data - - def handleNewSignals(self): self._set_input_summary() - self.unconditional_commit() def _set_input_summary(self): n_data = len(self.data) if self.data else 0 @@ -420,11 +493,15 @@ def commit(self): data = None if self.data: data = Table.from_domain(self.data.domain, 1) - data = self._set_sample_values(data) + data.X[:] = np.nan + data.Y[:] = np.nan + for i, m in enumerate(self.data.domain.metas): + data.metas[:, i] = "" if m.is_string else np.nan + data = self._set_values(data) self._set_output_summary(data) self.Outputs.data.send(data) - def _set_sample_values(self, data: Table) -> Table: + def _set_values(self, data: Table) -> Table: for row in range(self.model.rowCount()): model: QStandardItemModel = self.model index = model.index(row, self.Header.variable) diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index 3b4fefb0856..52282150b4c 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -6,7 +6,7 @@ from AnyQt.QtWidgets import QWidget from orangewidget.tests.base import GuiTest -from Orange.data import Table +from Orange.data import Table, ContinuousVariable, Domain, DiscreteVariable from Orange.widgets.data.owcreateinstance import OWCreateInstance, \ DiscreteVariableEditor, ContinuousVariableEditor from Orange.widgets.tests.base import WidgetTest, datasets @@ -17,17 +17,19 @@ class TestOWCreateInstance(WidgetTest): def setUp(self): self.widget = self.create_widget(OWCreateInstance) + self.data = Table("iris") def test_output(self): - data = Table("iris") - self.send_signal(self.widget.Inputs.data, data) + self.send_signal(self.widget.Inputs.data, self.data) output = self.get_output(self.widget.Outputs.data) self.assertEqual(len(output), 1) - self.assertEqual(output.domain, data.domain) + self.assertEqual(output.domain, self.data.domain) + array = np.round(np.median(self.data.X, axis=0), 1).reshape(1, 4) + np.testing.assert_array_equal(output.X, array) def test_summary(self): info = self.widget.info - data, reference = Table("iris"), Table("iris")[:1] + reference = self.data[:1] no_input, no_output = "No data on input", "No data on output" self.assertEqual(info._StateInfo__input_summary.brief, "") @@ -35,8 +37,8 @@ def test_summary(self): self.assertEqual(info._StateInfo__output_summary.brief, "") self.assertEqual(info._StateInfo__output_summary.details, no_output) - self.send_signal(self.widget.Inputs.data, data) - data_list = [("Data", data), ("Reference", None)] + self.send_signal(self.widget.Inputs.data, self.data) + data_list = [("Data", self.data), ("Reference", None)] summary, details = "150, 0", format_multiple_summaries(data_list) self.assertEqual(info._StateInfo__input_summary.brief, summary) self.assertEqual(info._StateInfo__input_summary.details, details) @@ -47,7 +49,7 @@ def test_summary(self): self.assertEqual(info._StateInfo__output_summary.details, details) self.send_signal(self.widget.Inputs.reference, reference) - data_list = [("Data", data), ("Reference", reference)] + data_list = [("Data", self.data), ("Reference", reference)] summary, details = "150, 1", format_multiple_summaries(data_list) self.assertEqual(info._StateInfo__input_summary.brief, summary) self.assertEqual(info._StateInfo__input_summary.details, details) @@ -64,17 +66,39 @@ def test_summary(self): self.assertEqual(info._StateInfo__input_summary.brief, "") self.assertEqual(info._StateInfo__input_summary.details, no_input) - def test_default_buttons(self): - self.send_signal(self.widget.Inputs.data, Table("iris")) + def test_initialize_buttons(self): + self.send_signal(self.widget.Inputs.data, self.data) + self.send_signal(self.widget.Inputs.reference, self.data[:1]) + output = self.get_output(self.widget.Outputs.data) + default_box = self.widget.controlArea.layout().itemAt(0).widget() buttons = default_box.children()[1:] - buttons[0].click() - buttons[1].click() - buttons[2].click() + + buttons[3].click() # Input + output_input = self.get_output(self.widget.Outputs.data) + self.assert_table_equal(output_input, self.data[:1]) + + buttons[0].click() # Median + output_median = self.get_output(self.widget.Outputs.data) + self.assert_table_equal(output_median, output) + + buttons[1].click() # Mean + output_mean = self.get_output(self.widget.Outputs.data) + output.X = np.round(np.mean(self.data.X, axis=0), 1).reshape(1, 4) + self.assert_table_equal(output_mean, output) + + buttons[2].click() # Random + output_random = self.get_output(self.widget.Outputs.data) + self.assertTrue((self.data.X.max(axis=0) >= output_random.X).all()) + self.assertTrue((self.data.X.min(axis=0) <= output_random.X).all()) + + self.send_signal(self.widget.Inputs.data, self.data[9:10]) + buttons[2].click() # Random + output_random = self.get_output(self.widget.Outputs.data) + self.assert_table_equal(output_random, self.data[9:10]) def test_table(self): - data = Table("iris") - self.send_signal(self.widget.Inputs.data, data) + self.send_signal(self.widget.Inputs.data, self.data) self.assertEqual(self.widget.view.model().rowCount(), 5) self.assertEqual(self.widget.view.horizontalHeader().count(), 2) @@ -91,6 +115,39 @@ def test_datasets(self): for ds in datasets.datasets(): self.send_signal(self.widget.Inputs.data, ds) + def test_missing_values(self): + domain = Domain([ContinuousVariable("c")], + class_vars=[DiscreteVariable("m", ("a", "b"))]) + data = Table(domain, np.array([[np.nan], [np.nan]]), + np.array([np.nan, np.nan])) + self.send_signal(self.widget.Inputs.data, data) + output = self.get_output(self.widget.Outputs.data) + self.assert_table_equal(output, data[:1]) + + def test_missing_values_reference(self): + reference = self.data[:1].copy() + reference[:] = np.nan + self.send_signal(self.widget.Inputs.data, self.data) + self.send_signal(self.widget.Inputs.reference, reference) + output1 = self.get_output(self.widget.Outputs.data) + default_box = self.widget.controlArea.layout().itemAt(0).widget() + default_box.children()[1:][2].click() + output2 = self.get_output(self.widget.Outputs.data) + self.assert_table_equal(output1, output2) + + def test_commit_once(self): + self.widget.commit = self.widget.unconditional_commit = Mock() + self.send_signal(self.widget.Inputs.data, self.data) + self.widget.unconditional_commit.assert_called_once() + + self.widget.commit.reset_mock() + self.send_signal(self.widget.Inputs.data, None) + self.widget.commit.assert_called_once() + + self.widget.commit.reset_mock() + self.send_signal(self.widget.Inputs.data, self.data) + self.widget.commit.assert_called_once() + class TestDiscreteVariableEditor(GuiTest): @classmethod From 876310983af55f0672169f99c31dbc0564a0072b Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Tue, 20 Oct 2020 07:16:23 +0200 Subject: [PATCH 06/19] StringVariableEditor: Include StringVariable --- Orange/widgets/data/owcreateinstance.py | 34 ++++++++++++++++-- .../data/tests/test_owcreateinstance.py | 36 +++++++++++++++++-- 2 files changed, 65 insertions(+), 5 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 8825876f861..0e33271a91b 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -12,7 +12,7 @@ QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem, QLabel from Orange.data import DiscreteVariable, ContinuousVariable, \ - TimeVariable, Table + TimeVariable, Table, StringVariable from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.utils.state_summary import format_summary_details, \ @@ -176,6 +176,26 @@ def __map_from_slider(self, value: int) -> float: return value * 10 ** (-self._n_decimals) +class StringVariableEditor(VariableEditor): + value_changed = Signal() + + def __init__(self, parent: QWidget, callback: Callable): + super().__init__(parent, callback) + self._edit = QLineEdit(parent) + self._edit.textChanged.connect(self.value_changed) + self._edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self.layout().addWidget(self._edit) + self.setFocusProxy(self._edit) + + @property + def value(self) -> str: + return self._edit.text() + + @value.setter + def value(self, value: str): + self._edit.setText(value) + + # TODO class TimeVariableEditor(VariableEditor): def __init__(self, parent: QWidget, have_date: bool, @@ -248,6 +268,12 @@ def _(variable: ContinuousVariable, values: np.ndarray, np.nanmax(values), callback) +@_create_editor.register(StringVariable) +def _(_: StringVariable, __: np.ndarray, parent: QWidget, + callback: Callable) -> StringVariableEditor: + return StringVariableEditor(parent, callback) + + @_create_editor.register(TimeVariable) def _(variable: TimeVariable, _: np.ndarray, parent: QWidget, callback: Callable) -> TimeVariableEditor: @@ -388,6 +414,8 @@ def variable_icon(variable) -> QIcon: return gui.attributeIconDict[4] elif variable.is_continuous: return gui.attributeIconDict[2] + elif variable.is_string: + return gui.attributeIconDict[3] else: return gui.attributeIconDict[-1] @@ -414,7 +442,9 @@ def add_row(variable, values): if all(np.isnan(vals)): self.Information.nans_removed() continue - add_row(var, vals) + else: + vals = np.array([]) + add_row(var, vals) self.model.dataChanged.connect(self.__table_data_changed) self._initialize_values("median") diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index 52282150b4c..8c2694268b5 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -8,7 +8,7 @@ from orangewidget.tests.base import GuiTest from Orange.data import Table, ContinuousVariable, Domain, DiscreteVariable from Orange.widgets.data.owcreateinstance import OWCreateInstance, \ - DiscreteVariableEditor, ContinuousVariableEditor + DiscreteVariableEditor, ContinuousVariableEditor, StringVariableEditor from Orange.widgets.tests.base import WidgetTest, datasets from Orange.widgets.utils.state_summary import format_summary_details, \ format_multiple_summaries @@ -104,7 +104,7 @@ def test_table(self): data = Table("zoo") self.send_signal(self.widget.Inputs.data, data) - self.assertEqual(self.widget.view.model().rowCount(), 17) + self.assertEqual(self.widget.view.model().rowCount(), 18) self.assertEqual(self.widget.view.horizontalHeader().count(), 2) self.send_signal(self.widget.Inputs.data, None) @@ -131,7 +131,7 @@ def test_missing_values_reference(self): self.send_signal(self.widget.Inputs.reference, reference) output1 = self.get_output(self.widget.Outputs.data) default_box = self.widget.controlArea.layout().itemAt(0).widget() - default_box.children()[1:][2].click() + default_box.children()[1:][3].click() # Input output2 = self.get_output(self.widget.Outputs.data) self.assert_table_equal(output1, output2) @@ -266,6 +266,36 @@ def test_missing_values(self): data.domain[0], np.nan, np.nan, Mock()) +class TestStringVariableEditor(GuiTest): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.parent = QWidget() + + def setUp(self): + self.callback = Mock() + self.editor = StringVariableEditor(self.parent, self.callback) + + def test_init(self): + self.assertEqual(self.editor.value, "") + self.assertEqual(self.editor._edit.text(), "") + self.callback.assert_not_called() + + def test_edit(self): + """ Set lineedit by user. """ + self.editor._edit.setText("Foo") + self.assertEqual(self.editor.value, "Foo") + self.assertEqual(self.editor._edit.text(), "Foo") + self.callback.assert_called_once() + + def test_set_value(self): + """ Programmatically set lineedit value. """ + self.editor.value = "Foo" + self.assertEqual(self.editor.value, "Foo") + self.assertEqual(self.editor._edit.text(), "Foo") + self.callback.assert_called_once() + + if __name__ == "__main__": import unittest unittest.main() From b6b840dc4be8965815b6f59850a50e655259489e Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Tue, 20 Oct 2020 07:44:54 +0200 Subject: [PATCH 07/19] TimeVariableEditor: Update editor --- Orange/widgets/data/owcreateinstance.py | 81 +++++++++++------ .../data/tests/test_owcreateinstance.py | 90 ++++++++++++++++++- 2 files changed, 141 insertions(+), 30 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 0e33271a91b..3fc6bddbb63 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -196,28 +196,54 @@ def value(self, value: str): self._edit.setText(value) -# TODO class TimeVariableEditor(VariableEditor): - def __init__(self, parent: QWidget, have_date: bool, - have_time: bool, callback: Callable): - super().__init__(parent) - self._editor = QDateTimeEdit(parent) - date_format = "yyyy-MM-dd hh:mm:ss" - if have_date and not have_time: - date_format = "yyyy-MM-dd" - elif not have_date and have_time: - date_format = "hh:mm:ss" - self._editor.setDisplayFormat(date_format) - self._editor.dateChanged.connect(callback) - self.layout().addWidget(self._editor) + DATE_FORMAT = "yyyy-MM-dd" + TIME_FORMAT = "hh:mm:ss" + + def __init__(self, parent: QWidget, variable: TimeVariable, + callback: Callable): + super().__init__(parent, callback) + self._value: float = 0 + self._variable: TimeVariable = variable + + if variable.have_date and not variable.have_time: + self._format = TimeVariableEditor.DATE_FORMAT + elif not variable.have_date and variable.have_time: + self._format = TimeVariableEditor.TIME_FORMAT + else: + self._format = f"{TimeVariableEditor.DATE_FORMAT} " \ + f"{TimeVariableEditor.TIME_FORMAT}" + + self._edit = QDateTimeEdit( + parent, + dateTime=self.__map_to_datetime(self._value), + displayFormat=self._format, + ) + self._edit.dateTimeChanged.connect(self._apply_edit_value) + + self.layout().addWidget(self._edit) + self.setFocusProxy(self._edit) @property - def value(self): - return self._editor.date() + def value(self) -> float: + return self._value @value.setter - def value(self, value): - self._editor.setDateTime(QDateTime(value)) + def value(self, value: float): + if value != self.value: + self._value = value + self.value_changed.emit(self.value) + self._edit.setDateTime(self.__map_to_datetime(self.value)) + + def _apply_edit_value(self): + self.value = self.__map_from_datetime(self._edit.dateTime()) + + def __map_from_datetime(self, date_time: QDateTime) -> float: + return self._variable.to_val(date_time.toString(self._format)) + + def __map_to_datetime(self, value: float) -> QDateTime: + return QDateTime.fromString(self._variable.repr_val(value), + self._format) class VariableDelegate(QStyledItemDelegate): @@ -226,7 +252,7 @@ def paint(self, painter: QPainter, option: QStyleOptionViewItem, self.parent().view.openPersistentEditor(index) super().paint(painter, option, index) - def createEditor(self, parent: QWidget, option: QStyleOptionViewItem, + def createEditor(self, parent: QWidget, _: QStyleOptionViewItem, index: QModelIndex) -> VariableEditor: variable = index.data(VariableRole) values = index.data(ValuesRole) @@ -237,11 +263,13 @@ def _commit_data(self): assert isinstance(editor, VariableEditor) self.commitData.emit(editor) - def setEditorData(self, editor: VariableEditor, index: QModelIndex): + @staticmethod + def setEditorData(editor: VariableEditor, index: QModelIndex): editor.value = index.model().data(index, ValueRole) - def setModelData(self, editor: VariableEditor, - model: QSortFilterProxyModel, index: QModelIndex): + @staticmethod + def setModelData(editor: VariableEditor, model: QSortFilterProxyModel, + index: QModelIndex): model.setData(index, editor.value, ValueRole) def sizeHint(self, option: QStyleOptionViewItem, @@ -277,8 +305,7 @@ def _(_: StringVariable, __: np.ndarray, parent: QWidget, @_create_editor.register(TimeVariable) def _(variable: TimeVariable, _: np.ndarray, parent: QWidget, callback: Callable) -> TimeVariableEditor: - return TimeVariableEditor(parent, variable.have_date, - variable.have_time, callback) + return TimeVariableEditor(parent, variable, callback) def majority(values: np.ndarray) -> int: @@ -317,6 +344,9 @@ class Information(OWWidget.Information): ['name', "Variable"], ['variable', "Value"], ] + Header = namedtuple( + "header", [tag for tag, _ in HEADER] + )(*range(len(HEADER))) auto_commit = Setting(True) @@ -324,11 +354,6 @@ def __init__(self): super().__init__() self.data: Optional[Table] = None self.reference: Optional[Table] = None - self.Header = \ - namedtuple("header", [tag for tag, _ in self.HEADER])( - *range(len(self.HEADER)) - ) - self.model: Optional[QStandardItemModel] = None self.proxy_model: Optional[QSortFilterProxyModel] = None self.view: Optional[QTableView] = None diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index 8c2694268b5..1bd721c2917 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -3,12 +3,15 @@ import numpy as np +from AnyQt.QtCore import QDateTime, QDate, QTime from AnyQt.QtWidgets import QWidget from orangewidget.tests.base import GuiTest -from Orange.data import Table, ContinuousVariable, Domain, DiscreteVariable +from Orange.data import Table, ContinuousVariable, Domain, DiscreteVariable, \ + TimeVariable from Orange.widgets.data.owcreateinstance import OWCreateInstance, \ - DiscreteVariableEditor, ContinuousVariableEditor, StringVariableEditor + DiscreteVariableEditor, ContinuousVariableEditor, StringVariableEditor, \ + TimeVariableEditor from Orange.widgets.tests.base import WidgetTest, datasets from Orange.widgets.utils.state_summary import format_summary_details, \ format_multiple_summaries @@ -296,6 +299,89 @@ def test_set_value(self): self.callback.assert_called_once() +class TestTimeVariableEditor(GuiTest): + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.parent = QWidget() + + def setUp(self): + self.callback = Mock() + self.editor = TimeVariableEditor( + self.parent, TimeVariable("var", have_date=1), self.callback + ) + + def test_init(self): + self.assertEqual(self.editor.value, 0) + self.assertEqual(self.editor._edit.dateTime(), + QDateTime(QDate(1970, 1, 1))) + self.callback.assert_not_called() + + def test_edit(self): + """ Edit datetimeedit by user. """ + datetime = QDateTime(QDate(2001, 9, 9)) + self.editor._edit.setDateTime(datetime) + self.assertEqual(self.editor.value, 999993600) + self.assertEqual(self.editor._edit.dateTime(), datetime) + self.callback.assert_called_once() + + def test_set_value(self): + """ Programmatically set datetimeedit value. """ + value = 999993600 + self.editor.value = value + self.assertEqual(self.editor._edit.dateTime(), + QDateTime(QDate(2001, 9, 9))) + self.assertEqual(self.editor.value, value) + self.callback.assert_called_once() + + def test_have_date_have_time(self): + callback = Mock() + editor = TimeVariableEditor( + self.parent, TimeVariable("var", have_date=1, have_time=1), + callback + ) + self.assertEqual(editor.value, 0) + self.assertEqual(self.editor._edit.dateTime(), + QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0))) + self.callback.assert_not_called() + + datetime = QDateTime(QDate(2001, 9, 9), QTime(1, 2, 3)) + editor._edit.setDateTime(datetime) + self.assertEqual(editor._edit.dateTime(), datetime) + self.assertEqual(editor.value, 999993600 + 3723) + callback.assert_called_once() + + def test_have_time(self): + callback = Mock() + editor = TimeVariableEditor( + self.parent, TimeVariable("var", have_time=1), callback + ) + self.assertEqual(editor.value, 0) + self.assertEqual(self.editor._edit.dateTime(), + QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0))) + self.callback.assert_not_called() + + datetime = QDateTime(QDate(1900, 1, 1), QTime(1, 2, 3)) + editor._edit.setDateTime(datetime) + self.assertEqual(editor._edit.dateTime(), datetime) + self.assertEqual(editor.value, 3723) + callback.assert_called_once() + + def test_no_date_no_time(self): + callback = Mock() + editor = TimeVariableEditor(self.parent, TimeVariable("var"), callback) + self.assertEqual(editor.value, 0) + self.assertEqual(self.editor._edit.dateTime(), + QDateTime(QDate(1970, 1, 1), QTime(0, 0, 0))) + self.callback.assert_not_called() + + datetime = QDateTime(QDate(2001, 9, 9), QTime(1, 2, 3)) + editor._edit.setDateTime(datetime) + self.assertEqual(editor._edit.dateTime(), datetime) + self.assertEqual(editor.value, 999993600 + 3723) + callback.assert_called_once() + + if __name__ == "__main__": import unittest unittest.main() From 5122151e845cc6197b6f1436b51cd8a95d1318e4 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Wed, 21 Oct 2020 07:23:13 +0200 Subject: [PATCH 08/19] OWCreateInstance: Values as schema_only setting --- Orange/widgets/data/owcreateinstance.py | 18 ++++++++++++++++-- .../data/tests/test_owcreateinstance.py | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 3fc6bddbb63..5c3f54cf571 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -1,4 +1,4 @@ -from typing import Optional, Callable, List, Union +from typing import Optional, Callable, List, Union, Dict from collections import namedtuple from functools import singledispatch @@ -348,6 +348,8 @@ class Information(OWWidget.Information): "header", [tag for tag, _ in HEADER] )(*range(len(HEADER))) + values = Setting( + {}, schema_only=True) # type: Dict[str, Union[float, str]] auto_commit = Setting(True) def __init__(self): @@ -358,6 +360,7 @@ def __init__(self): self.proxy_model: Optional[QSortFilterProxyModel] = None self.view: Optional[QTableView] = None self.filter_edit: Optional[QLineEdit] = None + self.__pending_values: Dict[str, Union[float, str]] = self.values self.setup_gui() def setup_gui(self): @@ -473,6 +476,7 @@ def add_row(variable, values): self.model.dataChanged.connect(self.__table_data_changed) self._initialize_values("median") + self.__pending_values = {} self.view.resizeColumnsToContents() self.view.resizeRowsToContents() @@ -516,6 +520,13 @@ def _initialize_values(self, fun: str): else: raise NotImplementedError + if self.__pending_values: # read values from settings + saved_value = self.__pending_values.get(variable.name) + if saved_value is not None and not ( + variable.is_discrete and + saved_value >= len(variable.values)): + value = saved_value + self.model.setData(index, value, ValueRole) self.model.dataChanged.connect(self.__table_data_changed) @@ -557,11 +568,14 @@ def commit(self): self.Outputs.data.send(data) def _set_values(self, data: Table) -> Table: + self.values = {} for row in range(self.model.rowCount()): model: QStandardItemModel = self.model index = model.index(row, self.Header.variable) var = model.data(index, VariableRole) - data[:, var] = model.data(index, ValueRole) + value = model.data(index, ValueRole) + data[:, var] = value + self.values[model.data(index, VariableRole).name] = value return data def send_report(self): diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index 1bd721c2917..d230ac52e04 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -138,6 +138,20 @@ def test_missing_values_reference(self): output2 = self.get_output(self.widget.Outputs.data) self.assert_table_equal(output1, output2) + def test_saved_workflow(self): + data = self.data + data.X[:, 0] = np.nan + self.send_signal(self.widget.Inputs.data, data) + default_box = self.widget.controlArea.layout().itemAt(0).widget() + default_box.children()[1:][2].click() # Random + output1 = self.get_output(self.widget.Outputs.data) + + settings = self.widget.settingsHandler.pack_data(self.widget) + widget = self.create_widget(OWCreateInstance, stored_settings=settings) + self.send_signal(widget.Inputs.data, data, widget=widget) + output2 = self.get_output(widget.Outputs.data) + self.assert_table_equal(output1, output2) + def test_commit_once(self): self.widget.commit = self.widget.unconditional_commit = Mock() self.send_signal(self.widget.Inputs.data, self.data) From 09ce05d2dc097ef49541f58550388ad411859534 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Wed, 21 Oct 2020 08:04:57 +0200 Subject: [PATCH 09/19] VariableItemModel: Introduce a custom model --- Orange/widgets/data/owcreateinstance.py | 194 ++++++++++-------- .../data/tests/test_owcreateinstance.py | 4 + 2 files changed, 110 insertions(+), 88 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 5c3f54cf571..2f406a9a4b0 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -12,7 +12,7 @@ QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem, QLabel from Orange.data import DiscreteVariable, ContinuousVariable, \ - TimeVariable, Table, StringVariable + TimeVariable, Table, StringVariable, Variable from Orange.widgets import gui from Orange.widgets.settings import Setting from Orange.widgets.utils.state_summary import format_summary_details, \ @@ -320,6 +320,65 @@ def cont_random(values: np.ndarray) -> float: return np.random.uniform(low=np.nanmin(values), high=np.nanmax(values)) +class VariableItemModel(QStandardItemModel): + dataHasNanColumn = Signal() + + def set_data(self, data: Table, saved_values={}): + for variable in data.domain.variables + data.domain.metas: + if variable.is_primitive(): + values = data.get_column_view(variable)[0].astype(float) + if all(np.isnan(values)): + self.dataHasNanColumn.emit() + continue + else: + values = np.array([]) + self._add_row(variable, values, saved_values.get(variable.name)) + + def _add_row(self, variable: Variable, values: np.ndarray, + saved_value: Optional[Union[int, float, str]]): + var_item = QStandardItem() + var_item.setData(variable.name, Qt.DisplayRole) + var_item.setIcon(self._variable_icon(variable)) + var_item.setEditable(False) + + control_item = QStandardItem() + control_item.setData(variable, VariableRole) + control_item.setData(values, ValuesRole) + + value = self._default_for_variable(variable, values) + if saved_value is not None and not \ + (variable.is_discrete and saved_value >= len(variable.values)): + value = saved_value + control_item.setData(value, ValueRole) + + self.appendRow([var_item, control_item]) + + @staticmethod + def _default_for_variable(variable: Variable, values: np.ndarray) \ + -> Union[float, int, str]: + if variable.is_continuous: + return round(np.nanmedian(values), variable.number_of_decimals) + elif variable.is_discrete: + return majority(values) + elif variable.is_string: + return "" + else: + raise NotImplementedError + + @staticmethod + def _variable_icon(variable: Variable) -> QIcon: + if variable.is_discrete: + return gui.attributeIconDict[1] + elif variable.is_time: + return gui.attributeIconDict[4] + elif variable.is_continuous: + return gui.attributeIconDict[2] + elif variable.is_string: + return gui.attributeIconDict[3] + else: + return gui.attributeIconDict[-1] + + class OWCreateInstance(OWWidget): name = "Create Instance" description = "Interactively create a data instance from sample dataset." @@ -356,7 +415,7 @@ def __init__(self): super().__init__() self.data: Optional[Table] = None self.reference: Optional[Table] = None - self.model: Optional[QStandardItemModel] = None + self.model: Optional[VariableItemModel] = None self.proxy_model: Optional[QSortFilterProxyModel] = None self.view: Optional[QTableView] = None self.filter_edit: Optional[QLineEdit] = None @@ -379,31 +438,9 @@ def _add_controls(self): gui.rubber(self.controlArea) gui.auto_apply(self.controlArea, self, "auto_commit") - def __median_button_clicked(self): - self._initialize_values("median") - self.commit() - - def __mean_button_clicked(self): - self._initialize_values("mean") - self.commit() - - def __random_button_clicked(self): - self._initialize_values("random") - self.commit() - - def __input_button_clicked(self): - if not self.reference: - return - self._initialize_values("input") - self.commit() - def _add_table(self): - self.model = QStandardItemModel(self) - # self.model.dataChanged.connect(self.__table_data_changed) - self.filter_edit = QLineEdit( - textChanged=self.__filter_edit_changed, - placeholderText="Filter..." - ) + self.filter_edit = QLineEdit(textChanged=self.__filter_edit_changed, + placeholderText="Filter...") self.view = QTableView(sortingEnabled=True, selectionMode=QTableView.NoSelection) self.view.setItemDelegateForColumn( @@ -413,72 +450,32 @@ def _add_table(self): header: QHeaderView = self.view.horizontalHeader() header.setStretchLastSection(True) header.setMaximumSectionSize(300) + + self.model = VariableItemModel(self) + self.model.dataChanged.connect(self.__table_data_changed) + self.model.dataHasNanColumn.connect(self.Information.nans_removed) self.proxy_model = QSortFilterProxyModel() self.proxy_model.setFilterKeyColumn(-1) self.proxy_model.setFilterCaseSensitivity(False) self.proxy_model.setSourceModel(self.model) self.view.setModel(self.proxy_model) + self.mainArea.layout().addWidget(self.filter_edit) self.mainArea.layout().addWidget(self.view) - def __table_data_changed(self): - self.commit() - - def __filter_edit_changed(self): - self.proxy_model.setFilterFixedString(self.filter_edit.text().strip()) - - @Inputs.data - def set_data(self, data: Table): - self.data = data - self._set_input_summary() - self._set_model_data() - self.unconditional_commit() - - def _set_model_data(self): - def variable_icon(variable) -> QIcon: - if variable.is_discrete: - return gui.attributeIconDict[1] - elif variable.is_time: - return gui.attributeIconDict[4] - elif variable.is_continuous: - return gui.attributeIconDict[2] - elif variable.is_string: - return gui.attributeIconDict[3] - else: - return gui.attributeIconDict[-1] - - def add_row(variable, values): - var_item = QStandardItem() - var_item.setData(variable.name, Qt.DisplayRole) - var_item.setIcon(variable_icon(variable)) - var_item.setEditable(False) + def __median_button_clicked(self): + self._initialize_values("median") - control_item = QStandardItem() - control_item.setData(variable, VariableRole) - control_item.setData(values, ValuesRole) + def __mean_button_clicked(self): + self._initialize_values("mean") - self.model.appendRow([var_item, control_item]) + def __random_button_clicked(self): + self._initialize_values("random") - self.Information.nans_removed.clear() - self.model.clear() - self.model.setHorizontalHeaderLabels([x for _, x in self.HEADER]) - if not self.data: + def __input_button_clicked(self): + if not self.reference: return - for var in self.data.domain.variables + self.data.domain.metas: - if var.is_primitive(): - vals = self.data.get_column_view(var)[0].astype(float) - if all(np.isnan(vals)): - self.Information.nans_removed() - continue - else: - vals = np.array([]) - add_row(var, vals) - - self.model.dataChanged.connect(self.__table_data_changed) - self._initialize_values("median") - self.__pending_values = {} - self.view.resizeColumnsToContents() - self.view.resizeRowsToContents() + self._initialize_values("input") def _initialize_values(self, fun: str): cont_fun = {"median": np.nanmedian, @@ -493,7 +490,6 @@ def _initialize_values(self, fun: str): if not self.data: return - # do not commit between initialization self.model.dataChanged.disconnect(self.__table_data_changed) for row in range(self.model.rowCount()): index = self.model.index(row, self.Header.variable) @@ -520,15 +516,37 @@ def _initialize_values(self, fun: str): else: raise NotImplementedError - if self.__pending_values: # read values from settings - saved_value = self.__pending_values.get(variable.name) - if saved_value is not None and not ( - variable.is_discrete and - saved_value >= len(variable.values)): - value = saved_value - self.model.setData(index, value, ValueRole) self.model.dataChanged.connect(self.__table_data_changed) + self.commit() + + def __table_data_changed(self): + self.commit() + + def __filter_edit_changed(self): + self.proxy_model.setFilterFixedString(self.filter_edit.text().strip()) + + @Inputs.data + def set_data(self, data: Table): + self.data = data + self._set_input_summary() + self._clear() + self._set_model_data() + self.unconditional_commit() + + def _clear(self): + self.Information.nans_removed.clear() + self.model.clear() + self.model.setHorizontalHeaderLabels([x for _, x in self.HEADER]) + + def _set_model_data(self): + if not self.data: + return + + self.model.set_data(self.data, self.__pending_values) + self.__pending_values = {} + self.view.resizeColumnsToContents() + self.view.resizeRowsToContents() @Inputs.reference def set_reference(self, data: Table): diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index d230ac52e04..a864ff985f1 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -126,6 +126,10 @@ def test_missing_values(self): self.send_signal(self.widget.Inputs.data, data) output = self.get_output(self.widget.Outputs.data) self.assert_table_equal(output, data[:1]) + self.assertTrue(self.widget.Information.nans_removed.is_shown()) + + self.send_signal(self.widget.Inputs.data, None) + self.assertFalse(self.widget.Information.nans_removed.is_shown()) def test_missing_values_reference(self): reference = self.data[:1].copy() From f9de285e5425b02e5a5ca37e9c3c7ff080b3df1d Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Wed, 21 Oct 2020 10:14:45 +0200 Subject: [PATCH 10/19] OWCreateInstance: Change layout --- Orange/widgets/data/owcreateinstance.py | 87 ++++++++++--------- .../data/tests/test_owcreateinstance.py | 28 ++++-- 2 files changed, 69 insertions(+), 46 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 2f406a9a4b0..ce705dc3e3c 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -31,7 +31,7 @@ class VariableEditor(QWidget): def __init__(self, parent: QWidget, callback: Callable): super().__init__(parent) layout = QHBoxLayout() - layout.setContentsMargins(0, 0, 0, 0) + layout.setContentsMargins(4, 0, 4, 0) self.setLayout(layout) self.value_changed.connect(callback) @@ -53,6 +53,7 @@ def __init__(self, parent: QWidget, items: List[str], callback: Callable): self._combo.addItems(items) self._combo.currentIndexChanged.connect(self.value_changed) self.layout().addWidget(self._combo) + self.layout().setContentsMargins(0, 1, 0, 0) @property def value(self) -> int: @@ -84,13 +85,19 @@ def __init__(self, parent: QWidget, variable: ContinuousVariable, self._min_value: float = self.__round_value(min_value) self._max_value: float = self.__round_value(max_value) - sp_spin = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + sp_spin = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + sp_spin.setHorizontalStretch(1) sp_slider = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) - sp_slider.setHorizontalStretch(5) + sp_slider.setHorizontalStretch(6) sp_edit = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) - sp_edit.setHorizontalStretch(1) + sp_edit.setHorizontalStretch(2) - self._spin = QDoubleSpinBox( + class DoubleSpinBox(QDoubleSpinBox): + def sizeHint(self) -> QSize: + size: QSize = super().sizeHint() + return QSize(size.width(), size.height() + 2) + + self._spin = DoubleSpinBox( parent, value=self._min_value, minimum=-np.inf, @@ -131,7 +138,6 @@ def __init__(self, parent: QWidget, variable: ContinuousVariable, self.layout().addWidget(self._label_min) self.layout().addWidget(self._slider) self.layout().addWidget(self._label_max) - self.layout().setContentsMargins(4, 0, 0, 4) self.setMinimumWidth(200) self.setFocusProxy(self._spin) @@ -183,8 +189,9 @@ def __init__(self, parent: QWidget, callback: Callable): super().__init__(parent, callback) self._edit = QLineEdit(parent) self._edit.textChanged.connect(self.value_changed) - self._edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) + self._edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.layout().addWidget(self._edit) + self.layout().setContentsMargins(5, 0, 5, 0) self.setFocusProxy(self._edit) @property @@ -214,7 +221,12 @@ def __init__(self, parent: QWidget, variable: TimeVariable, self._format = f"{TimeVariableEditor.DATE_FORMAT} " \ f"{TimeVariableEditor.TIME_FORMAT}" - self._edit = QDateTimeEdit( + class DateTimeEdit(QDateTimeEdit): + def sizeHint(self) -> QSize: + size: QSize = super().sizeHint() + return QSize(size.width(), size.height() + 2) + + self._edit = DateTimeEdit( parent, dateTime=self.__map_to_datetime(self._value), displayFormat=self._format, @@ -275,7 +287,7 @@ def setModelData(editor: VariableEditor, model: QSortFilterProxyModel, def sizeHint(self, option: QStyleOptionViewItem, index: QModelIndex) -> QSize: sh = super().sizeHint(option, index) - return QSize(sh.width(), sh.height() + 20) + return QSize(sh.width(), 40) @singledispatch @@ -398,7 +410,7 @@ class Information(OWWidget.Information): nans_removed = Msg("Variables with only missing values were " "removed from the list.") - want_main_area = True + want_main_area = False HEADER = [ ['name', "Variable"], ['variable', "Value"], @@ -415,30 +427,8 @@ def __init__(self): super().__init__() self.data: Optional[Table] = None self.reference: Optional[Table] = None - self.model: Optional[VariableItemModel] = None - self.proxy_model: Optional[QSortFilterProxyModel] = None - self.view: Optional[QTableView] = None - self.filter_edit: Optional[QLineEdit] = None self.__pending_values: Dict[str, Union[float, str]] = self.values - self.setup_gui() - - def setup_gui(self): - self._add_controls() - self._add_table() - self._set_input_summary() - self._set_output_summary() - def _add_controls(self): - box = gui.vBox(self.controlArea, "Initialize values") - kwargs = {"autoDefault": False} - gui.button(box, self, "Median", self.__median_button_clicked, **kwargs) - gui.button(box, self, "Mean", self.__mean_button_clicked, **kwargs) - gui.button(box, self, "Random", self.__random_button_clicked, **kwargs) - gui.button(box, self, "Input", self.__input_button_clicked, **kwargs) - gui.rubber(self.controlArea) - gui.auto_apply(self.controlArea, self, "auto_commit") - - def _add_table(self): self.filter_edit = QLineEdit(textChanged=self.__filter_edit_changed, placeholderText="Filter...") self.view = QTableView(sortingEnabled=True, @@ -460,8 +450,31 @@ def _add_table(self): self.proxy_model.setSourceModel(self.model) self.view.setModel(self.proxy_model) - self.mainArea.layout().addWidget(self.filter_edit) - self.mainArea.layout().addWidget(self.view) + vbox = gui.vBox(self.controlArea, box=True) + vbox.layout().addWidget(self.filter_edit) + vbox.layout().addWidget(self.view) + + box = gui.hBox(vbox) + gui.rubber(box) + kwargs = {"autoDefault": False} + gui.button(box, self, "Median", self.__median_button_clicked, **kwargs) + gui.button(box, self, "Mean", self.__mean_button_clicked, **kwargs) + gui.button(box, self, "Random", self.__random_button_clicked, **kwargs) + gui.button(box, self, "Input", self.__input_button_clicked, **kwargs) + gui.rubber(box) + + box = gui.auto_apply(self.controlArea, self, "auto_commit") + box.button.setFixedWidth(180) + box.layout().insertStretch(0) + + self._set_input_summary() + self._set_output_summary() + + def __filter_edit_changed(self): + self.proxy_model.setFilterFixedString(self.filter_edit.text().strip()) + + def __table_data_changed(self): + self.commit() def __median_button_clicked(self): self._initialize_values("median") @@ -520,12 +533,6 @@ def _initialize_values(self, fun: str): self.model.dataChanged.connect(self.__table_data_changed) self.commit() - def __table_data_changed(self): - self.commit() - - def __filter_edit_changed(self): - self.proxy_model.setFilterFixedString(self.filter_edit.text().strip()) - @Inputs.data def set_data(self, data: Table): self.data = data diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index a864ff985f1..827c55ee8f7 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -69,13 +69,18 @@ def test_summary(self): self.assertEqual(info._StateInfo__input_summary.brief, "") self.assertEqual(info._StateInfo__input_summary.details, no_input) + def _get_init_buttons(self, widget=None): + if not widget: + widget = self.widget + box = widget.controlArea.layout().itemAt(0).widget().children()[3] + return box.children()[1:] + def test_initialize_buttons(self): self.send_signal(self.widget.Inputs.data, self.data) self.send_signal(self.widget.Inputs.reference, self.data[:1]) output = self.get_output(self.widget.Outputs.data) - default_box = self.widget.controlArea.layout().itemAt(0).widget() - buttons = default_box.children()[1:] + buttons = self._get_init_buttons() buttons[3].click() # Input output_input = self.get_output(self.widget.Outputs.data) @@ -100,6 +105,17 @@ def test_initialize_buttons(self): output_random = self.get_output(self.widget.Outputs.data) self.assert_table_equal(output_random, self.data[9:10]) + def test_initialize_buttons_commit_once(self): + self.widget.commit = self.widget.unconditional_commit = Mock() + self.send_signal(self.widget.Inputs.data, self.data) + self.send_signal(self.widget.Inputs.reference, self.data[:1]) + self.widget.unconditional_commit.assert_called_once() + + self.widget.commit.reset_mock() + buttons = self._get_init_buttons() + buttons[3].click() # Input + self.widget.commit.assert_called_once() + def test_table(self): self.send_signal(self.widget.Inputs.data, self.data) self.assertEqual(self.widget.view.model().rowCount(), 5) @@ -137,8 +153,8 @@ def test_missing_values_reference(self): self.send_signal(self.widget.Inputs.data, self.data) self.send_signal(self.widget.Inputs.reference, reference) output1 = self.get_output(self.widget.Outputs.data) - default_box = self.widget.controlArea.layout().itemAt(0).widget() - default_box.children()[1:][3].click() # Input + buttons = self._get_init_buttons() + buttons[3].click() # Input output2 = self.get_output(self.widget.Outputs.data) self.assert_table_equal(output1, output2) @@ -146,8 +162,8 @@ def test_saved_workflow(self): data = self.data data.X[:, 0] = np.nan self.send_signal(self.widget.Inputs.data, data) - default_box = self.widget.controlArea.layout().itemAt(0).widget() - default_box.children()[1:][2].click() # Random + buttons = self._get_init_buttons() + buttons[2].click() # Random output1 = self.get_output(self.widget.Outputs.data) settings = self.widget.settingsHandler.pack_data(self.widget) From 25092c2f2a0d320b1ab50e51c72d1c60cb8adc0a Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Wed, 21 Oct 2020 12:41:23 +0200 Subject: [PATCH 11/19] OWCreateInstance: Add report --- Orange/widgets/data/owcreateinstance.py | 12 +++++++++++- Orange/widgets/data/tests/test_owcreateinstance.py | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index ce705dc3e3c..a3d23b24dc1 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -604,7 +604,17 @@ def _set_values(self, data: Table) -> Table: return data def send_report(self): - pass + if not self.data: + return + self.report_domain("Input", self.data.domain) + self.report_domain("Output", self.data.domain) + items = [] + for var in self.data.domain.variables + self.data.domain.metas: + val = self.values.get(var.name, np.nan) + if var.is_primitive(): + val = var.repr_val(val) + items.append([f"{var.name}:", val]) + self.report_table("Values", items) @staticmethod def sizeHint(): diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index 827c55ee8f7..bab6e5b9ddd 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -185,6 +185,18 @@ def test_commit_once(self): self.send_signal(self.widget.Inputs.data, self.data) self.widget.commit.assert_called_once() + def test_report(self): + self.widget.send_report() + self.send_signal(self.widget.Inputs.data, self.data) + self.widget.send_report() + self.send_signal(self.widget.Inputs.data, None) + self.widget.send_report() + + def test_sparse(self): + data = self.data.to_sparse() + self.send_signal(self.widget.Inputs.data, data) + self.send_signal(self.widget.Inputs.reference, data) + class TestDiscreteVariableEditor(GuiTest): @classmethod From be7941d8ae06903bb45ec6708ef6deca5545e827 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Thu, 22 Oct 2020 08:54:18 +0200 Subject: [PATCH 12/19] OWCreateInstance: Add context menu --- Orange/widgets/data/owcreateinstance.py | 65 ++++++++++++++----------- 1 file changed, 37 insertions(+), 28 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index a3d23b24dc1..9e01cd1c7e6 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -5,11 +5,11 @@ import numpy as np from AnyQt.QtCore import Qt, QSortFilterProxyModel, QSize, QDateTime, \ - QModelIndex, Signal + QModelIndex, Signal, QPoint from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon, QPainter from AnyQt.QtWidgets import QLineEdit, QTableView, QSlider, QHeaderView, \ QComboBox, QStyledItemDelegate, QWidget, QDateTimeEdit, QHBoxLayout, \ - QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem, QLabel + QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem, QLabel, QMenu, QAction from Orange.data import DiscreteVariable, ContinuousVariable, \ TimeVariable, Table, StringVariable, Variable @@ -411,10 +411,9 @@ class Information(OWWidget.Information): "removed from the list.") want_main_area = False - HEADER = [ - ['name', "Variable"], - ['variable', "Value"], - ] + ACTIONS = ["median", "mean", "random", "input"] + HEADER = [["name", "Variable"], + ["variable", "Value"]] Header = namedtuple( "header", [tag for tag, _ in HEADER] )(*range(len(HEADER))) @@ -432,7 +431,9 @@ def __init__(self): self.filter_edit = QLineEdit(textChanged=self.__filter_edit_changed, placeholderText="Filter...") self.view = QTableView(sortingEnabled=True, + contextMenuPolicy=Qt.CustomContextMenu, selectionMode=QTableView.NoSelection) + self.view.customContextMenuRequested.connect(self.__menu_requested) self.view.setItemDelegateForColumn( self.Header.variable, VariableDelegate(self) ) @@ -456,11 +457,12 @@ def __init__(self): box = gui.hBox(vbox) gui.rubber(box) - kwargs = {"autoDefault": False} - gui.button(box, self, "Median", self.__median_button_clicked, **kwargs) - gui.button(box, self, "Mean", self.__mean_button_clicked, **kwargs) - gui.button(box, self, "Random", self.__random_button_clicked, **kwargs) - gui.button(box, self, "Input", self.__input_button_clicked, **kwargs) + for name in self.ACTIONS: + gui.button( + box, self, name.capitalize(), + lambda *args, fun=name: self._initialize_values(fun), + autoDefault=False + ) gui.rubber(box) box = gui.auto_apply(self.controlArea, self, "auto_commit") @@ -476,21 +478,26 @@ def __filter_edit_changed(self): def __table_data_changed(self): self.commit() - def __median_button_clicked(self): - self._initialize_values("median") - - def __mean_button_clicked(self): - self._initialize_values("mean") - - def __random_button_clicked(self): - self._initialize_values("random") - - def __input_button_clicked(self): - if not self.reference: - return - self._initialize_values("input") - - def _initialize_values(self, fun: str): + def __menu_requested(self, point: QPoint): + index = self.view.indexAt(point) + model: QSortFilterProxyModel = index.model() + source_index = model.mapToSource(index) + menu = QMenu(self) + for action in self._create_actions(source_index): + menu.addAction(action) + menu.popup(self.view.viewport().mapToGlobal(point)) + + def _create_actions(self, index: QModelIndex) -> List[QAction]: + actions = [] + for name in self.ACTIONS: + action = QAction(name.capitalize(), self) + action.triggered.connect( + lambda *args, fun=name: self._initialize_values(fun, [index]) + ) + actions.append(action) + return actions + + def _initialize_values(self, fun: str, indices: List[QModelIndex] = None): cont_fun = {"median": np.nanmedian, "mean": np.nanmean, "random": cont_random, @@ -500,11 +507,13 @@ def _initialize_values(self, fun: str): "random": disc_random, "input": majority}.get(fun, NotImplemented) - if not self.data: + if not self.data or fun == "input" and not self.reference: return self.model.dataChanged.disconnect(self.__table_data_changed) - for row in range(self.model.rowCount()): + rows = range(self.proxy_model.rowCount()) if indices is None else \ + [index.row() for index in indices] + for row in rows: index = self.model.index(row, self.Header.variable) variable = self.model.data(index, VariableRole) From 01597780dbe7214e20ec7f675fc514f72b8f763e Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Thu, 22 Oct 2020 12:19:49 +0200 Subject: [PATCH 13/19] OWCreateInstance: Fix controls sizes --- Orange/widgets/data/owcreateinstance.py | 102 +++++++++++------- .../data/tests/test_owcreateinstance.py | 88 +++++++++++++-- 2 files changed, 145 insertions(+), 45 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 9e01cd1c7e6..08869243bf1 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -5,9 +5,9 @@ import numpy as np from AnyQt.QtCore import Qt, QSortFilterProxyModel, QSize, QDateTime, \ - QModelIndex, Signal, QPoint + QModelIndex, Signal, QPoint, QRect from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon, QPainter -from AnyQt.QtWidgets import QLineEdit, QTableView, QSlider, QHeaderView, \ +from AnyQt.QtWidgets import QLineEdit, QTableView, QSlider, \ QComboBox, QStyledItemDelegate, QWidget, QDateTimeEdit, QHBoxLayout, \ QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem, QLabel, QMenu, QAction @@ -31,29 +31,36 @@ class VariableEditor(QWidget): def __init__(self, parent: QWidget, callback: Callable): super().__init__(parent) layout = QHBoxLayout() - layout.setContentsMargins(4, 0, 4, 0) + layout.setContentsMargins(6, 0, 6, 0) + layout.setAlignment(Qt.AlignLeft) self.setLayout(layout) self.value_changed.connect(callback) @property - def value(self) -> Union[int, float]: + def value(self) -> Union[int, float, str]: return NotImplemented @value.setter - def value(self, value: float): + def value(self, value: Union[float, str]): raise NotImplementedError + def sizeHint(self): + return QSize(super().sizeHint().width(), 40) + class DiscreteVariableEditor(VariableEditor): value_changed = Signal(int) def __init__(self, parent: QWidget, items: List[str], callback: Callable): super().__init__(parent, callback) - self._combo = QComboBox(parent) + self._combo = QComboBox( + parent, + maximumWidth=180, + sizePolicy=QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + ) self._combo.addItems(items) self._combo.currentIndexChanged.connect(self.value_changed) self.layout().addWidget(self._combo) - self.layout().setContentsMargins(0, 1, 0, 0) @property def value(self) -> int: @@ -88,9 +95,9 @@ def __init__(self, parent: QWidget, variable: ContinuousVariable, sp_spin = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sp_spin.setHorizontalStretch(1) sp_slider = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) - sp_slider.setHorizontalStretch(6) + sp_slider.setHorizontalStretch(5) sp_edit = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) - sp_edit.setHorizontalStretch(2) + sp_edit.setHorizontalStretch(1) class DoubleSpinBox(QDoubleSpinBox): def sizeHint(self) -> QSize: @@ -113,7 +120,6 @@ def sizeHint(self) -> QSize: maximum=self.__map_to_slider(self._max_value), singleStep=1, orientation=Qt.Horizontal, - minimumWidth=20, sizePolicy=sp_slider, ) self._label_min = QLabel( @@ -138,12 +144,9 @@ def sizeHint(self) -> QSize: self.layout().addWidget(self._label_min) self.layout().addWidget(self._slider) self.layout().addWidget(self._label_max) - self.setMinimumWidth(200) self.setFocusProxy(self._spin) - # FIXME: after setting focus proxy to the spin, the text is highlighted - def deselect(): self._spin.lineEdit().deselect() try: @@ -151,6 +154,13 @@ def deselect(): except TypeError: pass + # Invoking self.setFocusProxy(self._spin), causes the + # self._spin.lineEdit()s to have selected texts (focus is set to + # provide keyboard functionality, i.e.: pressing ESC after changing + # spinbox value). Since the spin text is selected only after the + # delegate draws it, it cannot be deselected during initialization. + # Therefore connect the deselect() function to + # self._spin.lineEdit().selectionChanged only for editor creation. self._spin.lineEdit().selectionChanged.connect(deselect) @property @@ -163,7 +173,11 @@ def value(self, value: float): self._value = value self.value_changed.emit(self.value) self._spin.setValue(self.value) - self._slider.setValue(self.__map_to_slider(self.value)) + # prevent emitting self.value_changed again, due to slider change + slider_value = self.__map_to_slider(self.value) + self._value = self.__map_from_slider(slider_value) + self._slider.setValue(slider_value) + self._value = value def _apply_slider_value(self): self.value = self.__map_from_slider(self._slider.value()) @@ -187,11 +201,12 @@ class StringVariableEditor(VariableEditor): def __init__(self, parent: QWidget, callback: Callable): super().__init__(parent, callback) - self._edit = QLineEdit(parent) + self._edit = QLineEdit( + parent, + sizePolicy=QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) + ) self._edit.textChanged.connect(self.value_changed) - self._edit.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.layout().addWidget(self._edit) - self.layout().setContentsMargins(5, 0, 5, 0) self.setFocusProxy(self._edit) @property @@ -230,6 +245,7 @@ def sizeHint(self) -> QSize: parent, dateTime=self.__map_to_datetime(self._value), displayFormat=self._format, + sizePolicy=QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) ) self._edit.dateTimeChanged.connect(self._apply_edit_value) @@ -275,19 +291,29 @@ def _commit_data(self): assert isinstance(editor, VariableEditor) self.commitData.emit(editor) - @staticmethod - def setEditorData(editor: VariableEditor, index: QModelIndex): + # pylint: disable=no-self-use + def setEditorData(self, editor: VariableEditor, index: QModelIndex): editor.value = index.model().data(index, ValueRole) - @staticmethod - def setModelData(editor: VariableEditor, model: QSortFilterProxyModel, - index: QModelIndex): + # pylint: disable=no-self-use + def setModelData(self, editor: VariableEditor, + model: QSortFilterProxyModel, index: QModelIndex): model.setData(index, editor.value, ValueRole) - def sizeHint(self, option: QStyleOptionViewItem, - index: QModelIndex) -> QSize: - sh = super().sizeHint(option, index) - return QSize(sh.width(), 40) + # pylint: disable=no-self-use + def updateEditorGeometry(self, editor: VariableEditor, + option: QStyleOptionViewItem, _: QModelIndex): + rect: QRect = option.rect + if isinstance(editor, ContinuousVariableEditor): + width = editor.sizeHint().width() + if width > rect.width(): + rect.setWidth(width) + editor.setGeometry(rect) + + # pylint: disable=no-self-use + def sizeHint(self, _: QStyleOptionViewItem, index: QModelIndex) -> QSize: + return _create_editor(index.data(role=VariableRole), np.array([0]), + None, lambda: 1).sizeHint() @singledispatch @@ -335,6 +361,7 @@ def cont_random(values: np.ndarray) -> float: class VariableItemModel(QStandardItemModel): dataHasNanColumn = Signal() + # pylint: disable=dangerous-default-value def set_data(self, data: Table, saved_values={}): for variable in data.domain.variables + data.domain.metas: if variable.is_primitive(): @@ -350,6 +377,7 @@ def _add_row(self, variable: Variable, values: np.ndarray, saved_value: Optional[Union[int, float, str]]): var_item = QStandardItem() var_item.setData(variable.name, Qt.DisplayRole) + var_item.setToolTip(variable.name) var_item.setIcon(self._variable_icon(variable)) var_item.setEditable(False) @@ -438,11 +466,11 @@ def __init__(self): self.Header.variable, VariableDelegate(self) ) self.view.verticalHeader().hide() - header: QHeaderView = self.view.horizontalHeader() - header.setStretchLastSection(True) - header.setMaximumSectionSize(300) + self.view.horizontalHeader().setStretchLastSection(True) + self.view.horizontalHeader().setMaximumSectionSize(350) self.model = VariableItemModel(self) + self.model.setHorizontalHeaderLabels([x for _, x in self.HEADER]) self.model.dataChanged.connect(self.__table_data_changed) self.model.dataHasNanColumn.connect(self.Information.nans_removed) self.proxy_model = QSortFilterProxyModel() @@ -546,23 +574,21 @@ def _initialize_values(self, fun: str, indices: List[QModelIndex] = None): def set_data(self, data: Table): self.data = data self._set_input_summary() - self._clear() self._set_model_data() self.unconditional_commit() - def _clear(self): - self.Information.nans_removed.clear() - self.model.clear() - self.model.setHorizontalHeaderLabels([x for _, x in self.HEADER]) - def _set_model_data(self): + self.Information.nans_removed.clear() + self.model.removeRows(0, self.model.rowCount()) if not self.data: return self.model.set_data(self.data, self.__pending_values) self.__pending_values = {} + self.view.horizontalHeader().setStretchLastSection(False) self.view.resizeColumnsToContents() self.view.resizeRowsToContents() + self.view.horizontalHeader().setStretchLastSection(True) @Inputs.reference def set_reference(self, data: Table): @@ -627,10 +653,10 @@ def send_report(self): @staticmethod def sizeHint(): - return QSize(800, 500) + return QSize(600, 500) if __name__ == "__main__": # pragma: no cover - table = Table("heart_disease") + table = Table("housing") WidgetPreview(OWCreateInstance).run(set_data=table, - set_reference=table[::2]) + set_reference=table[:1]) diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index bab6e5b9ddd..eda94cea45c 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -1,17 +1,17 @@ -# pylint: disable=missing-docstring +# pylint: disable=missing-docstring,protected-access from unittest.mock import Mock import numpy as np -from AnyQt.QtCore import QDateTime, QDate, QTime -from AnyQt.QtWidgets import QWidget +from AnyQt.QtCore import QDateTime, QDate, QTime, QPoint +from AnyQt.QtWidgets import QWidget, QLineEdit, QStyleOptionViewItem, QMenu from orangewidget.tests.base import GuiTest from Orange.data import Table, ContinuousVariable, Domain, DiscreteVariable, \ TimeVariable from Orange.widgets.data.owcreateinstance import OWCreateInstance, \ DiscreteVariableEditor, ContinuousVariableEditor, StringVariableEditor, \ - TimeVariableEditor + TimeVariableEditor, VariableDelegate, VariableItemModel, ValueRole from Orange.widgets.tests.base import WidgetTest, datasets from Orange.widgets.utils.state_summary import format_summary_details, \ format_multiple_summaries @@ -105,6 +105,11 @@ def test_initialize_buttons(self): output_random = self.get_output(self.widget.Outputs.data) self.assert_table_equal(output_random, self.data[9:10]) + self.send_signal(self.widget.Inputs.reference, None) + buttons[3].click() # Input + output = self.get_output(self.widget.Outputs.data) + self.assert_table_equal(output_random, output) + def test_initialize_buttons_commit_once(self): self.widget.commit = self.widget.unconditional_commit = Mock() self.send_signal(self.widget.Inputs.data, self.data) @@ -185,6 +190,19 @@ def test_commit_once(self): self.send_signal(self.widget.Inputs.data, self.data) self.widget.commit.assert_called_once() + def test_context_menu(self): + self.send_signal(self.widget.Inputs.data, self.data) + self.send_signal(self.widget.Inputs.reference, self.data[:1]) + output1 = self.get_output(self.widget.Outputs.data) + self.widget.view.customContextMenuRequested.emit(QPoint(0, 0)) + menu = [w for w in self.widget.children() if isinstance(w, QMenu)][0] + self.assertEqual(len(menu.actions()), 4) + + menu.actions()[3].trigger() # Input + output2 = self.get_output(self.widget.Outputs.data) + np.testing.assert_array_equal(output2.X[:, 1:], output1.X[:, 1:]) + np.testing.assert_array_equal(output2.X[:, :1], self.data.X[:1, :1]) + def test_report(self): self.widget.send_report() self.send_signal(self.widget.Inputs.data, self.data) @@ -309,10 +327,22 @@ def test_set_value(self): self.callback.assert_called_once() def test_missing_values(self): - domain = Domain([ContinuousVariable("var")]) - data = Table(domain, np.array([[np.nan], [np.nan]])) + var = ContinuousVariable("var") self.assertRaises(ValueError, ContinuousVariableEditor, self.parent, - data.domain[0], np.nan, np.nan, Mock()) + var, np.nan, np.nan, Mock()) + + def test_overflow(self): + var = ContinuousVariable("var", number_of_decimals=10) + editor = ContinuousVariableEditor( + self.parent, var, -100000, 1, self.callback + ) + self.assertLess(editor._n_decimals, 10) + + def test_spin_selection_after_init(self): + edit: QLineEdit = self.editor._spin.lineEdit() + edit.selectAll() + self.assertEqual(edit.selectedText(), "") + self.assertIs(self.editor.focusProxy(), edit.parent()) class TestStringVariableEditor(GuiTest): @@ -428,6 +458,50 @@ def test_no_date_no_time(self): callback.assert_called_once() +class TestVariableDelegate(GuiTest): + def setUp(self): + self.data = Table("iris") + self.model = model = VariableItemModel() + model.set_data(self.data) + widget = OWCreateInstance() + self.delegate = VariableDelegate(widget) + self.parent = QWidget() + self.opt = QStyleOptionViewItem() + + def test_create_editor(self): + index = self.model.index(0, 1) + editor = self.delegate.createEditor(self.parent, self.opt, index) + self.assertIsInstance(editor, ContinuousVariableEditor) + + index = self.model.index(4, 1) + editor = self.delegate.createEditor(self.parent, self.opt, index) + self.assertIsInstance(editor, DiscreteVariableEditor) + + def test_set_editor_data(self): + index = self.model.index(0, 1) + editor = self.delegate.createEditor(self.parent, self.opt, index) + self.delegate.setEditorData(editor, index) + self.assertEqual(editor.value, np.median(self.data.X[:, 0])) + + def test_set_model_data(self): + index = self.model.index(0, 1) + editor = self.delegate.createEditor(self.parent, self.opt, index) + editor.value = 7.5 + self.delegate.setModelData(editor, self.model, index) + self.assertEqual(self.model.data(index, ValueRole), 7.5) + + def test_editor_geometry(self): + index = self.model.index(0, 1) + editor = self.delegate.createEditor(self.parent, self.opt, index) + self.delegate.updateEditorGeometry(editor, self.opt, index) + self.assertGreaterEqual(editor.geometry().width(), + self.opt.rect.width()) + + size = self.delegate.sizeHint(self.opt, index) + self.assertEqual(size.width(), editor.geometry().width()) + self.assertEqual(size.height(), 40) + + if __name__ == "__main__": import unittest unittest.main() From f3753930557d2e572c48f40d17e31b52fcb69a8a Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Mon, 26 Oct 2020 08:05:19 +0100 Subject: [PATCH 14/19] OWCreateInstance: Disable scrolling to change value --- Orange/widgets/data/owcreateinstance.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 08869243bf1..2b100c5fdd6 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -5,7 +5,7 @@ import numpy as np from AnyQt.QtCore import Qt, QSortFilterProxyModel, QSize, QDateTime, \ - QModelIndex, Signal, QPoint, QRect + QModelIndex, Signal, QPoint, QRect, QEvent from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon, QPainter from AnyQt.QtWidgets import QLineEdit, QTableView, QSlider, \ QComboBox, QStyledItemDelegate, QWidget, QDateTimeEdit, QHBoxLayout, \ @@ -163,6 +163,9 @@ def deselect(): # self._spin.lineEdit().selectionChanged only for editor creation. self._spin.lineEdit().selectionChanged.connect(deselect) + self._slider.installEventFilter(self) + self._spin.installEventFilter(self) + @property def value(self) -> float: return self.__round_value(self._value) @@ -195,6 +198,12 @@ def __map_to_slider(self, value: float) -> int: def __map_from_slider(self, value: int) -> float: return value * 10 ** (-self._n_decimals) + def eventFilter(self, obj: Union[QSlider, QDoubleSpinBox], event: QEvent) \ + -> bool: + if event.type() == QEvent.Wheel: + return True + return super().eventFilter(obj, event) + class StringVariableEditor(VariableEditor): value_changed = Signal() @@ -252,6 +261,8 @@ def sizeHint(self) -> QSize: self.layout().addWidget(self._edit) self.setFocusProxy(self._edit) + self._edit.installEventFilter(self) + @property def value(self) -> float: return self._value @@ -273,6 +284,11 @@ def __map_to_datetime(self, value: float) -> QDateTime: return QDateTime.fromString(self._variable.repr_val(value), self._format) + def eventFilter(self, obj: QDateTimeEdit, event: QEvent) -> bool: + if event.type() == QEvent.Wheel: + return True + return super().eventFilter(obj, event) + class VariableDelegate(QStyledItemDelegate): def paint(self, painter: QPainter, option: QStyleOptionViewItem, From 2d76bbc0a12a3a5a4c1940a939c49c71024ee523 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Tue, 27 Oct 2020 05:58:31 +0100 Subject: [PATCH 15/19] OWCreateInstance: Save settings regardless of commit --- Orange/widgets/data/owcreateinstance.py | 49 ++++++++++++++----------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 2b100c5fdd6..05eb2e4f39d 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -462,15 +462,13 @@ class Information(OWWidget.Information): "header", [tag for tag, _ in HEADER] )(*range(len(HEADER))) - values = Setting( - {}, schema_only=True) # type: Dict[str, Union[float, str]] + values: Dict[str, Union[float, str]] = Setting({}, schema_only=True) auto_commit = Setting(True) def __init__(self): super().__init__() self.data: Optional[Table] = None self.reference: Optional[Table] = None - self.__pending_values: Dict[str, Union[float, str]] = self.values self.filter_edit = QLineEdit(textChanged=self.__filter_edit_changed, placeholderText="Filter...") @@ -515,6 +513,7 @@ def __init__(self): self._set_input_summary() self._set_output_summary() + self.settingsAboutToBePacked.connect(self.pack_settings) def __filter_edit_changed(self): self.proxy_model.setFilterFixedString(self.filter_edit.text().strip()) @@ -599,8 +598,8 @@ def _set_model_data(self): if not self.data: return - self.model.set_data(self.data, self.__pending_values) - self.__pending_values = {} + self.model.set_data(self.data, self.values) + self.values = {} self.view.horizontalHeader().setStretchLastSection(False) self.view.resizeColumnsToContents() self.view.resizeRowsToContents() @@ -634,34 +633,39 @@ def _set_output_summary(self, data: Optional[Table] = None): def commit(self): data = None if self.data: - data = Table.from_domain(self.data.domain, 1) - data.X[:] = np.nan - data.Y[:] = np.nan - for i, m in enumerate(self.data.domain.metas): - data.metas[:, i] = "" if m.is_string else np.nan - data = self._set_values(data) + data = self._create_data_from_values() self._set_output_summary(data) self.Outputs.data.send(data) - def _set_values(self, data: Table) -> Table: - self.values = {} - for row in range(self.model.rowCount()): - model: QStandardItemModel = self.model - index = model.index(row, self.Header.variable) - var = model.data(index, VariableRole) - value = model.data(index, ValueRole) - data[:, var] = value - self.values[model.data(index, VariableRole).name] = value + def _create_data_from_values(self) -> Table: + data = Table.from_domain(self.data.domain, 1) + data.X[:] = np.nan + data.Y[:] = np.nan + for i, m in enumerate(self.data.domain.metas): + data.metas[:, i] = "" if m.is_string else np.nan + + values = self._get_values() + for var_name, value in values.items(): + data[:, var_name] = value return data + def _get_values(self) -> Dict[str, Union[str, float]]: + values = {} + for row in range(self.model.rowCount()): + index = self.model.index(row, self.Header.variable) + values[self.model.data(index, VariableRole).name] = \ + self.model.data(index, ValueRole) + return values + def send_report(self): if not self.data: return self.report_domain("Input", self.data.domain) self.report_domain("Output", self.data.domain) items = [] + values: Dict = self._get_values() for var in self.data.domain.variables + self.data.domain.metas: - val = self.values.get(var.name, np.nan) + val = values.get(var.name, np.nan) if var.is_primitive(): val = var.repr_val(val) items.append([f"{var.name}:", val]) @@ -671,6 +675,9 @@ def send_report(self): def sizeHint(): return QSize(600, 500) + def pack_settings(self): + self.values: Dict[str, Union[str, float]] = self._get_values() + if __name__ == "__main__": # pragma: no cover table = Table("housing") From a5d9c19dc22e0e16cdd9f55f2571a2574f4a35f0 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Tue, 27 Oct 2020 06:22:52 +0100 Subject: [PATCH 16/19] VariableEditor: Rename signal --- Orange/widgets/data/owcreateinstance.py | 18 +++++++++--------- .../data/tests/test_owcreateinstance.py | 8 ++++++++ 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 05eb2e4f39d..38dba660fb1 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -26,7 +26,7 @@ class VariableEditor(QWidget): - value_changed = Signal(float) + valueChanged = Signal(float) def __init__(self, parent: QWidget, callback: Callable): super().__init__(parent) @@ -34,7 +34,7 @@ def __init__(self, parent: QWidget, callback: Callable): layout.setContentsMargins(6, 0, 6, 0) layout.setAlignment(Qt.AlignLeft) self.setLayout(layout) - self.value_changed.connect(callback) + self.valueChanged.connect(callback) @property def value(self) -> Union[int, float, str]: @@ -49,7 +49,7 @@ def sizeHint(self): class DiscreteVariableEditor(VariableEditor): - value_changed = Signal(int) + valueChanged = Signal(int) def __init__(self, parent: QWidget, items: List[str], callback: Callable): super().__init__(parent, callback) @@ -59,7 +59,7 @@ def __init__(self, parent: QWidget, items: List[str], callback: Callable): sizePolicy=QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) ) self._combo.addItems(items) - self._combo.currentIndexChanged.connect(self.value_changed) + self._combo.currentIndexChanged.connect(self.valueChanged) self.layout().addWidget(self._combo) @property @@ -174,9 +174,9 @@ def value(self) -> float: def value(self, value: float): if self._value is None or self.__round_value(value) != self.value: self._value = value - self.value_changed.emit(self.value) + self.valueChanged.emit(self.value) self._spin.setValue(self.value) - # prevent emitting self.value_changed again, due to slider change + # prevent emitting self.valueChanged again, due to slider change slider_value = self.__map_to_slider(self.value) self._value = self.__map_from_slider(slider_value) self._slider.setValue(slider_value) @@ -206,7 +206,7 @@ def eventFilter(self, obj: Union[QSlider, QDoubleSpinBox], event: QEvent) \ class StringVariableEditor(VariableEditor): - value_changed = Signal() + valueChanged = Signal() def __init__(self, parent: QWidget, callback: Callable): super().__init__(parent, callback) @@ -214,7 +214,7 @@ def __init__(self, parent: QWidget, callback: Callable): parent, sizePolicy=QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) ) - self._edit.textChanged.connect(self.value_changed) + self._edit.textChanged.connect(self.valueChanged) self.layout().addWidget(self._edit) self.setFocusProxy(self._edit) @@ -271,7 +271,7 @@ def value(self) -> float: def value(self, value: float): if value != self.value: self._value = value - self.value_changed.emit(self.value) + self.valueChanged.emit(self.value) self._edit.setDateTime(self.__map_to_datetime(self.value)) def _apply_edit_value(self): diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index eda94cea45c..4005e235a0e 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -135,6 +135,14 @@ def test_table(self): self.assertEqual(self.widget.view.model().rowCount(), 0) self.assertEqual(self.widget.view.horizontalHeader().count(), 2) + def test_table_data_changed(self): + self.send_signal(self.widget.Inputs.data, self.data) + index = self.widget.model.index(0, 1) + self.widget.model.setData(index, 7, role=ValueRole) + output = self.get_output(self.widget.Outputs.data) + self.assertEqual(len(output), 1) + self.assertEqual(output.X[0, 0], 7) + def test_datasets(self): for ds in datasets.datasets(): self.send_signal(self.widget.Inputs.data, ds) From ad1c5d564b4673c9dab8e99f12071cdbe22fbfde Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Wed, 28 Oct 2020 06:16:44 +0100 Subject: [PATCH 17/19] VariableItemModel: Color row background according to domain --- Orange/widgets/data/owcreateinstance.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index 38dba660fb1..a3ac83a2c7c 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -6,7 +6,8 @@ from AnyQt.QtCore import Qt, QSortFilterProxyModel, QSize, QDateTime, \ QModelIndex, Signal, QPoint, QRect, QEvent -from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon, QPainter +from AnyQt.QtGui import QStandardItemModel, QStandardItem, QIcon, QPainter, \ + QColor from AnyQt.QtWidgets import QLineEdit, QTableView, QSlider, \ QComboBox, QStyledItemDelegate, QWidget, QDateTimeEdit, QHBoxLayout, \ QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem, QLabel, QMenu, QAction @@ -14,6 +15,7 @@ from Orange.data import DiscreteVariable, ContinuousVariable, \ TimeVariable, Table, StringVariable, Variable from Orange.widgets import gui +from Orange.widgets.utils.itemmodels import TableModel from Orange.widgets.settings import Setting from Orange.widgets.utils.state_summary import format_summary_details, \ format_multiple_summaries @@ -379,7 +381,11 @@ class VariableItemModel(QStandardItemModel): # pylint: disable=dangerous-default-value def set_data(self, data: Table, saved_values={}): - for variable in data.domain.variables + data.domain.metas: + domain = data.domain + variables = [(TableModel.Attribute, a) for a in domain.attributes] + \ + [(TableModel.ClassVar, c) for c in domain.class_vars] + \ + [(TableModel.Meta, m) for m in domain.metas] + for place, variable in variables: if variable.is_primitive(): values = data.get_column_view(variable)[0].astype(float) if all(np.isnan(values)): @@ -387,19 +393,25 @@ def set_data(self, data: Table, saved_values={}): continue else: values = np.array([]) - self._add_row(variable, values, saved_values.get(variable.name)) + color = TableModel.ColorForRole.get(place) + self._add_row(variable, values, color, + saved_values.get(variable.name)) - def _add_row(self, variable: Variable, values: np.ndarray, + def _add_row(self, variable: Variable, values: np.ndarray, color: QColor, saved_value: Optional[Union[int, float, str]]): var_item = QStandardItem() var_item.setData(variable.name, Qt.DisplayRole) var_item.setToolTip(variable.name) var_item.setIcon(self._variable_icon(variable)) var_item.setEditable(False) + if color: + var_item.setBackground(color) control_item = QStandardItem() control_item.setData(variable, VariableRole) control_item.setData(values, ValuesRole) + if color: + control_item.setBackground(color) value = self._default_for_variable(variable, values) if saved_value is not None and not \ From 023fc015cf02833ccc61d32567383bc55aafb8e1 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Wed, 28 Oct 2020 07:24:04 +0100 Subject: [PATCH 18/19] OWCreateInstance: Append instance to input dataset --- Orange/widgets/data/owcreateinstance.py | 31 +++++++++++++--- .../data/tests/test_owcreateinstance.py | 37 ++++++++++++++++--- 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index a3ac83a2c7c..c4623d9611b 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -13,7 +13,7 @@ QDoubleSpinBox, QSizePolicy, QStyleOptionViewItem, QLabel, QMenu, QAction from Orange.data import DiscreteVariable, ContinuousVariable, \ - TimeVariable, Table, StringVariable, Variable + TimeVariable, Table, StringVariable, Variable, Domain from Orange.widgets import gui from Orange.widgets.utils.itemmodels import TableModel from Orange.widgets.settings import Setting @@ -475,6 +475,7 @@ class Information(OWWidget.Information): )(*range(len(HEADER))) values: Dict[str, Union[float, str]] = Setting({}, schema_only=True) + append_to_data = Setting(True) auto_commit = Setting(True) def __init__(self): @@ -522,6 +523,10 @@ def __init__(self): box = gui.auto_apply(self.controlArea, self, "auto_commit") box.button.setFixedWidth(180) box.layout().insertStretch(0) + # pylint: disable=unnecessary-lambda + append = gui.checkBox(None, self, "append_to_data", "Append to data", + callback=lambda: self.commit()) + box.layout().insertWidget(0, append) self._set_input_summary() self._set_output_summary() @@ -643,14 +648,17 @@ def _set_output_summary(self, data: Optional[Table] = None): self.info.set_output_summary(summary, details) def commit(self): - data = None + output_data = None if self.data: - data = self._create_data_from_values() - self._set_output_summary(data) - self.Outputs.data.send(data) + output_data = self._create_data_from_values() + if self.append_to_data: + output_data = self._append_to_data(output_data) + self._set_output_summary(output_data) + self.Outputs.data.send(output_data) def _create_data_from_values(self) -> Table: data = Table.from_domain(self.data.domain, 1) + data.name = "created" data.X[:] = np.nan data.Y[:] = np.nan for i, m in enumerate(self.data.domain.metas): @@ -661,6 +669,19 @@ def _create_data_from_values(self) -> Table: data[:, var_name] = value return data + def _append_to_data(self, data: Table) -> Table: + assert self.data + assert len(data) == 1 + + var = DiscreteVariable("Source ID", values=(self.data.name, data.name)) + data = Table.concatenate([self.data, data], axis=0) + domain = Domain(data.domain.attributes, data.domain.class_vars, + data.domain.metas + (var,)) + data = data.transform(domain) + data.metas[: len(self.data), -1] = 0 + data.metas[len(self.data):, -1] = 1 + return data + def _get_values(self) -> Dict[str, Union[str, float]]: values = {} for row in range(self.model.rowCount()): diff --git a/Orange/widgets/data/tests/test_owcreateinstance.py b/Orange/widgets/data/tests/test_owcreateinstance.py index 4005e235a0e..c0aa850c7a3 100644 --- a/Orange/widgets/data/tests/test_owcreateinstance.py +++ b/Orange/widgets/data/tests/test_owcreateinstance.py @@ -24,12 +24,37 @@ def setUp(self): def test_output(self): self.send_signal(self.widget.Inputs.data, self.data) + self.widget.controls.append_to_data.setChecked(False) output = self.get_output(self.widget.Outputs.data) self.assertEqual(len(output), 1) + self.assertEqual(output.name, "created") self.assertEqual(output.domain, self.data.domain) array = np.round(np.median(self.data.X, axis=0), 1).reshape(1, 4) np.testing.assert_array_equal(output.X, array) + def test_output_append_data(self): + self.send_signal(self.widget.Inputs.data, self.data) + self.widget.controls.append_to_data.setChecked(True) + + output = self.get_output(self.widget.Outputs.data) + self.assertEqual(len(output), 151) + + np.testing.assert_array_equal(output.X[:150], self.data.X) + np.testing.assert_array_equal(output.Y[:150], self.data.Y) + array = np.zeros((150, 1), dtype=object) + np.testing.assert_array_equal(output.metas[:150], array) + + array = np.round(np.median(self.data.X, axis=0), 1).reshape(1, 4) + np.testing.assert_array_equal(output.X[150:], array) + np.testing.assert_array_equal(output.Y[150:], np.array([0])) + np.testing.assert_array_equal(output.metas[150:], np.array([[1]])) + + self.assertEqual(output.domain.attributes, self.data.domain.attributes) + self.assertEqual(output.domain.class_vars, self.data.domain.class_vars) + self.assertIn("Source ID", [m.name for m in output.domain.metas]) + self.assertTupleEqual(output.domain.metas[0].values, + ("iris", "created")) + def test_summary(self): info = self.widget.info reference = self.data[:1] @@ -47,8 +72,8 @@ def test_summary(self): self.assertEqual(info._StateInfo__input_summary.details, details) output = self.get_output(self.widget.Outputs.data) - summary, details = f"{len(output)}", format_summary_details(output) - self.assertEqual(info._StateInfo__output_summary.brief, summary) + details = format_summary_details(output) + self.assertEqual(info._StateInfo__output_summary.brief, "151") self.assertEqual(info._StateInfo__output_summary.details, details) self.send_signal(self.widget.Inputs.reference, reference) @@ -76,6 +101,7 @@ def _get_init_buttons(self, widget=None): return box.children()[1:] def test_initialize_buttons(self): + self.widget.controls.append_to_data.setChecked(False) self.send_signal(self.widget.Inputs.data, self.data) self.send_signal(self.widget.Inputs.reference, self.data[:1]) output = self.get_output(self.widget.Outputs.data) @@ -140,8 +166,8 @@ def test_table_data_changed(self): index = self.widget.model.index(0, 1) self.widget.model.setData(index, 7, role=ValueRole) output = self.get_output(self.widget.Outputs.data) - self.assertEqual(len(output), 1) - self.assertEqual(output.X[0, 0], 7) + self.assertEqual(len(output), 151) + self.assertEqual(output.X[150, 0], 7) def test_datasets(self): for ds in datasets.datasets(): @@ -152,6 +178,7 @@ def test_missing_values(self): class_vars=[DiscreteVariable("m", ("a", "b"))]) data = Table(domain, np.array([[np.nan], [np.nan]]), np.array([np.nan, np.nan])) + self.widget.controls.append_to_data.setChecked(False) self.send_signal(self.widget.Inputs.data, data) output = self.get_output(self.widget.Outputs.data) self.assert_table_equal(output, data[:1]) @@ -209,7 +236,7 @@ def test_context_menu(self): menu.actions()[3].trigger() # Input output2 = self.get_output(self.widget.Outputs.data) np.testing.assert_array_equal(output2.X[:, 1:], output1.X[:, 1:]) - np.testing.assert_array_equal(output2.X[:, :1], self.data.X[:1, :1]) + np.testing.assert_array_equal(output2.X[150:, :1], self.data.X[:1, :1]) def test_report(self): self.widget.send_report() From b392407d027ab1cd78c3b709be008cd24cbe03f7 Mon Sep 17 00:00:00 2001 From: Vesna Tanko Date: Wed, 28 Oct 2020 10:06:46 +0100 Subject: [PATCH 19/19] OWCreateInstance: Docs --- Orange/widgets/data/owcreateinstance.py | 3 +- doc/visual-programming/source/index.rst | 1 + .../source/widgets/data/createinstance.md | 44 ++++++++++++++++++ .../data/images/CreateInstance-example.png | Bin 0 -> 83689 bytes .../data/images/CreateInstance-example2.png | Bin 0 -> 99909 bytes .../data/images/CreateInstance-stamped.png | Bin 0 -> 22003 bytes doc/widgets.json | 9 ++++ 7 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 doc/visual-programming/source/widgets/data/createinstance.md create mode 100644 doc/visual-programming/source/widgets/data/images/CreateInstance-example.png create mode 100644 doc/visual-programming/source/widgets/data/images/CreateInstance-example2.png create mode 100644 doc/visual-programming/source/widgets/data/images/CreateInstance-stamped.png diff --git a/Orange/widgets/data/owcreateinstance.py b/Orange/widgets/data/owcreateinstance.py index c4623d9611b..615bbb6a6b6 100644 --- a/Orange/widgets/data/owcreateinstance.py +++ b/Orange/widgets/data/owcreateinstance.py @@ -524,7 +524,8 @@ def __init__(self): box.button.setFixedWidth(180) box.layout().insertStretch(0) # pylint: disable=unnecessary-lambda - append = gui.checkBox(None, self, "append_to_data", "Append to data", + append = gui.checkBox(None, self, "append_to_data", + "Append this instance to input data", callback=lambda: self.commit()) box.layout().insertWidget(0, append) diff --git a/doc/visual-programming/source/index.rst b/doc/visual-programming/source/index.rst index 0a53138796e..7f62026896f 100644 --- a/doc/visual-programming/source/index.rst +++ b/doc/visual-programming/source/index.rst @@ -35,6 +35,7 @@ Data widgets/data/transpose widgets/data/discretize widgets/data/continuize + widgets/data/createinstance widgets/data/createclass widgets/data/randomize widgets/data/concatenate diff --git a/doc/visual-programming/source/widgets/data/createinstance.md b/doc/visual-programming/source/widgets/data/createinstance.md new file mode 100644 index 00000000000..16725371f2a --- /dev/null +++ b/doc/visual-programming/source/widgets/data/createinstance.md @@ -0,0 +1,44 @@ +Create Instance +=============== + +Interactively creates an instance from a sample dataset. + +**Inputs** + +- Data: input dataset +- Reference: refrence dataset + +**Outputs** + +- Data: input dataset appended the created instance + +The **Create Instance** widget creates a new instance, based on the input data. The widget displays all variables of the input dataset in a table of two columns. The column *Variable* represents the variable's name, meanwhile the column *Value* enables setting the variable's value. Each value is initially set to median value of the variable. The values can be manually set to *Median*, *Mean*, *Random* or *Input* by clicking the corresponding button. For easier searching through the variables, the table has filter attached. When clicking upon one of the mentioned buttons, only filtered variables are considered. One can also set the value by right-clicking a row and selecting an option in a context menu. + +![](images/CreateInstance-stamped.png) + +1. Filter table by variable name. +2. The column represents a variable's name and type. The table can be sorted by clicking the columns header. +3. Provides controls for value editing. +4. Set filtered variables' values to: + - *Median*: median value of variable in the input dataset + - *Mean*: mean value of variable in the input dataset + - *Random*: random value in a range of variable in the input dataset + - *Input*: median value of variable in the reference dataset +5. If *Append this instance to input data* is ticked, the created instance is appended to the input dataset. Otherwise, a single instance appears on the output. To distinguish between created and original data, *Source ID* variable is added. +5. If *Apply automatically* is ticked, changes are committed automatically. Otherwise, you have to press *Apply* after each change. +6. Produce a report. +7. Information on input and reference dataset. +8. Information on output dataset. + +Example +------- + +The **Create Instance** is usually used to examine a model performance on some arbitrary data. The basic usage is shown in the following workflow, where a (*Housing*) dataset is used to fit a [Linear Regression](../model/linearregression.md) model, which is than used to [predict](../evaluate/predictions.md) a target value for data, created by the *Create Instance* widget. Inserting a [Rank](../data/rank.md) widget between [File](../data/file.md) and *Create Instance* enables outputting (and therefore making predictions on) the most important features. +A [Select Column](../data/selectcolumns.md) widget is inserted to omit the actual target value. + +![](images/CreateInstance-example.png) + +The next example shows how to check whether the created instance is some kind of outlier. The creates instance is feed to [PCA](../unsupervised/PCA.md) whose first and second componens are then examined in a [Scatter Plot](../visualize/scatterplot.md). The created instance is colored red in the plot and it could be considered as an outlier if it appears far from the original data (blue). + +![](images/CreateInstance-example2.png) + diff --git a/doc/visual-programming/source/widgets/data/images/CreateInstance-example.png b/doc/visual-programming/source/widgets/data/images/CreateInstance-example.png new file mode 100644 index 0000000000000000000000000000000000000000..5b78b9d072989e9294600213dad69b65c174a18a GIT binary patch literal 83689 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
*5AdSRaD((32r#K)L8l((E3NbHGCaS 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 Ye9U4Et9sYq|3Jt|DNELfn|%3y0Hm;uSO5S3 literal 0 HcmV?d00001 diff --git a/doc/visual-programming/source/widgets/data/images/CreateInstance-example2.png b/doc/visual-programming/source/widgets/data/images/CreateInstance-example2.png new file mode 100644 index 0000000000000000000000000000000000000000..164f2a66276d657e9fd59d88db6f9045e342e7ca GIT binary patch literal 99909 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 literal 0 HcmV?d00001 diff --git a/doc/visual-programming/source/widgets/data/images/CreateInstance-stamped.png b/doc/visual-programming/source/widgets/data/images/CreateInstance-stamped.png new file mode 100644 index 0000000000000000000000000000000000000000..c39e7985813c082051c129ae5dc5d4b5b367f3c0 GIT binary patch literal 22003 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 P00000NkvXXu0mjf4GHR% literal 0 HcmV?d00001 diff --git a/doc/widgets.json b/doc/widgets.json index 8358e80c430..251a9c288d0 100644 --- a/doc/widgets.json +++ b/doc/widgets.json @@ -228,6 +228,15 @@ "program" ] }, + { + "text": "Create Instance", + "doc": "visual-programming/source/widgets/data/createinstance.md", + "icon": "../Orange/widgets/data/icons/CreateInstance.svg", + "background": "#FFD39F", + "keywords": [ + "simulator" + ] + }, { "text": "Color", "doc": "visual-programming/source/widgets/data/color.md",