Skip to content

Commit ba741fe

Browse files
committed
Merge pull request biolab#1915 from VesnaT/fix_pca
[FIX] OWPCA: Fix crash for dataset with no rows or no attributes (cherry picked from commit bdf8f2c)
1 parent d39c89e commit ba741fe

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

Orange/widgets/unsupervised/owpca.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ class Warning(widget.OWWidget.Warning):
4848
"All components of the PCA are trivial (explain 0 variance). "
4949
"Input data is constant (or near constant).")
5050

51+
class Error(widget.OWWidget.Error):
52+
no_features = widget.Msg("At least 1 feature is required")
53+
no_instances = widget.Msg("At least 1 data instance is required")
54+
5155
def __init__(self):
5256
super().__init__()
5357
self.data = None
@@ -178,6 +182,7 @@ def set_data(self, data):
178182
self.fit()
179183

180184
def fit(self):
185+
self.clear_messages()
181186
self.clear()
182187
self.start_button.setEnabled(False)
183188
if self.data is None:
@@ -190,6 +195,19 @@ def fit(self):
190195
self.start_button.setEnabled(True)
191196
else:
192197
self.sampling_box.setVisible(False)
198+
if len(data.domain.attributes) == 0:
199+
self.Error.no_features()
200+
self.send("Transformed data", None)
201+
self.send("Components", None)
202+
self.send("PCA", None)
203+
return
204+
if len(data) == 0:
205+
self.Error.no_instances()
206+
self.send("Transformed data", None)
207+
self.send("Components", None)
208+
self.send("PCA", None)
209+
return
210+
193211
pca = self._pca_projector(data)
194212
variance_ratio = pca.explained_variance_ratio_
195213
cumulative = numpy.cumsum(variance_ratio)

Orange/widgets/unsupervised/tests/test_owpca.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
from Orange.data import Table
1+
# Test methods with long descriptive names can omit docstrings
2+
# pylint: disable=missing-docstring
3+
from Orange.data import Table, Domain
24
from Orange.widgets.tests.base import WidgetTest
35
from Orange.widgets.unsupervised.owpca import OWPCA
46

57

6-
class TestOWDistanceMatrix(WidgetTest):
7-
8+
class TestOWPCA(WidgetTest):
89
def setUp(self):
910
self.widget = self.create_widget(OWPCA) # type: OWPCA
1011

@@ -21,3 +22,18 @@ def test_constant_data(self):
2122
self.assertTrue(self.widget.Warning.trivial_components.is_shown())
2223
self.assertIsNone(self.get_output("Transformed Data"))
2324
self.assertIsNone(self.get_output("Components"))
25+
26+
def test_empty_data(self):
27+
""" Check widget for dataset with no rows and for dataset with no attributes """
28+
data = Table("iris")
29+
self.send_signal("Data", data[:0])
30+
self.assertTrue(self.widget.Error.no_instances.is_shown())
31+
32+
domain = Domain([], None, data.domain.variables)
33+
new_data = Table.from_table(domain, data)
34+
self.send_signal("Data", new_data)
35+
self.assertTrue(self.widget.Error.no_features.is_shown())
36+
self.assertFalse(self.widget.Error.no_instances.is_shown())
37+
38+
self.send_signal("Data", None)
39+
self.assertFalse(self.widget.Error.no_features.is_shown())

0 commit comments

Comments
 (0)