diff --git a/Orange/widgets/visualize/owheatmap.py b/Orange/widgets/visualize/owheatmap.py index cd2cb54e191..d1bb6dc2b07 100644 --- a/Orange/widgets/visualize/owheatmap.py +++ b/Orange/widgets/visualize/owheatmap.py @@ -19,8 +19,10 @@ QTransform, QIcon, QBrush, QStandardItemModel, QStandardItem, ) -from AnyQt.QtCore import Qt, QSize, QPointF, QSizeF, QRectF, QObject, QEvent -from AnyQt.QtCore import pyqtSignal as Signal +from AnyQt.QtCore import ( + Qt, QSize, QPointF, QSizeF, QRectF, QObject, QEvent, + pyqtSignal as Signal, +) import pyqtgraph as pg from Orange.data import Domain, Table, DiscreteVariable, StringVariable @@ -32,7 +34,6 @@ from Orange.widgets.utils.annotated_data import (create_annotated_table, ANNOTATED_DATA_SIGNAL_NAME) from Orange.widgets import widget, gui, settings -from Orange.widgets.io import FileFormat from Orange.widgets.unsupervised.owhierarchicalclustering import \ DendrogramWidget @@ -57,7 +58,7 @@ def split_domain(domain, split_label): domains.append((value, group_domain)) if domains: - assert(all(len(dom) == len(domains[0][1]) for _, dom in domains)) + assert all(len(dom) == len(domains[0][1]) for _, dom in domains) return sorted(domains, key=lambda t: attr_values.index(t[0])) @@ -334,7 +335,7 @@ def cluster_ord(self): "domain", #: list of Variable "cluster", #: hierarchical.Tree option "cluster_ordered", #: hierarchical.Tree option - ] + ] ) @@ -368,7 +369,7 @@ def cluster_ord(self): ["rows", #: A list of RowPart descriptors "columns", #: A list of ColumnPart descriptors "span", #: (min, max) global data range - ] + ] ) Parts.levels = property(lambda self: self.span) @@ -556,7 +557,12 @@ def __init__(self): callback=self.__aspect_mode_changed) gui.rubber(self.controlArea) - gui.auto_commit(self.controlArea, self, "auto_commit", "Send Selection", "Send Automatically") + gui.auto_commit(self.controlArea, + self, + "auto_commit", + "Send Selection", + "Send Automatically" + ) # Scene with heatmap self.heatmap_scene = self.scene = HeatmapScene(parent=self) @@ -702,7 +708,6 @@ def set_dataset(self, data=None): self.openContext(self.data) if self.annotation_index >= len(self.annotation_vars): self.annotation_index = 0 - self.update_heatmaps() def update_heatmaps(self): @@ -827,7 +832,7 @@ def cluster_columns(self, data, parts): col_groups = [col._replace(cluster=cluster, cluster_ordered=cluster_ord) for col in parts.columns] - return parts._replace(columns=col_groups, rows=parts.rows) + return parts._replace(columns=col_groups, rows=parts.rows) def construct_heatmaps(self, data, split_label=None): if split_label is not None: @@ -854,6 +859,7 @@ def construct_heatmaps(self, data, split_label=None): ) nclust = min(self.merge_kmeans_k, len(effective_data) - 1) self.kmeans_model = kmeans_compress(effective_data, k=nclust) + effective_data.domain = self.kmeans_model.pre_domain self.merge_indices = [np.flatnonzero(self.kmeans_model.labels_ == ind) for ind in range(nclust)] effective_data = Orange.data.Table( @@ -974,7 +980,7 @@ def setup_scene(self, parts, data): QSizePolicy.Expanding, QSizePolicy.Ignored) dendrogram.itemClicked.connect( lambda item, partindex=i: - self.__select_by_cluster(item, partindex) + self.__select_by_cluster(item, partindex) ) grid.addItem(dendrogram, Row0 + i * 2 + 1, DendrogramColumn) @@ -1731,8 +1737,8 @@ def cell_at(self, pos): """Return the cell row, column from `pos` in local coordinates. """ if self.__pixmap.isNull() or not ( - self.heatmap_item.geometry().contains(pos) or - self.averages_item.geometry().contains(pos)): + self.heatmap_item.geometry().contains(pos) or + self.averages_item.geometry().contains(pos)): return (-1, -1) if self.heatmap_item.geometry().contains(pos): diff --git a/Orange/widgets/visualize/tests/test_owheatmap.py b/Orange/widgets/visualize/tests/test_owheatmap.py index 3a97c6e3fb4..2e29d7b15e6 100644 --- a/Orange/widgets/visualize/tests/test_owheatmap.py +++ b/Orange/widgets/visualize/tests/test_owheatmap.py @@ -1,11 +1,9 @@ # Test methods with long descriptive names can omit docstrings # pylint: disable=missing-docstring -import numpy as np - from Orange.data import Table, Domain, DiscreteVariable, ContinuousVariable from Orange.preprocess import Continuize from Orange.widgets.visualize.owheatmap import OWHeatMap -from Orange.widgets.tests.base import WidgetTest, WidgetOutputsTestMixin +from Orange.widgets.tests.base import WidgetTest, WidgetOutputsTestMixin, datasets class TestOWHeatMap(WidgetTest, WidgetOutputsTestMixin): @@ -101,9 +99,21 @@ def test_not_enough_data_settings_changed(self): def test_color_low_high(self): """ - GH-2025 Prevent horizontal sliders to set Low >= High. + GH-2025 """ self.widget.controls.threshold_low.setValue(4) self.widget.controls.threshold_high.setValue(2) self.assertGreater(self.widget.threshold_high, self.widget.threshold_low) + + def test_data_column_nans(self): + """ + Send data with one column with all values set to NaN. + ValueError should not be thrown (Invalid number of variable columns) + That column is now suppose to be removed in a table array and + in a domain as well. + GH-2057 + """ + table = datasets.data_one_column_nans() + self.widget.controls.merge_kmeans.setChecked(True) + self.send_signal("Data", table)