Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] OWPCA: Fix crash for dataset with no rows or no attributes #1915

Merged
merged 1 commit into from Jan 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 18 additions & 0 deletions Orange/widgets/unsupervised/owpca.py
Expand Up @@ -48,6 +48,10 @@ class Warning(widget.OWWidget.Warning):
"All components of the PCA are trivial (explain 0 variance). "
"Input data is constant (or near constant).")

class Error(widget.OWWidget.Error):
no_features = widget.Msg("At least 1 feature is required")
no_instances = widget.Msg("At least 1 data instance is required")

def __init__(self):
super().__init__()
self.data = None
Expand Down Expand Up @@ -178,6 +182,7 @@ def set_data(self, data):
self.fit()

def fit(self):
self.clear_messages()
self.clear()
self.start_button.setEnabled(False)
if self.data is None:
Expand All @@ -190,6 +195,19 @@ def fit(self):
self.start_button.setEnabled(True)
else:
self.sampling_box.setVisible(False)
if len(data.domain.attributes) == 0:
self.Error.no_features()
self.send("Transformed data", None)
self.send("Components", None)
self.send("PCA", None)
return
if len(data) == 0:
self.Error.no_instances()
self.send("Transformed data", None)
self.send("Components", None)
self.send("PCA", None)
return

pca = self._pca_projector(data)
variance_ratio = pca.explained_variance_ratio_
cumulative = numpy.cumsum(variance_ratio)
Expand Down
22 changes: 19 additions & 3 deletions Orange/widgets/unsupervised/tests/test_owpca.py
@@ -1,10 +1,11 @@
from Orange.data import Table
# Test methods with long descriptive names can omit docstrings
# pylint: disable=missing-docstring
from Orange.data import Table, Domain
from Orange.widgets.tests.base import WidgetTest
from Orange.widgets.unsupervised.owpca import OWPCA


class TestOWDistanceMatrix(WidgetTest):

class TestOWPCA(WidgetTest):
def setUp(self):
self.widget = self.create_widget(OWPCA) # type: OWPCA

Expand All @@ -21,3 +22,18 @@ def test_constant_data(self):
self.assertTrue(self.widget.Warning.trivial_components.is_shown())
self.assertIsNone(self.get_output("Transformed Data"))
self.assertIsNone(self.get_output("Components"))

def test_empty_data(self):
""" Check widget for dataset with no rows and for dataset with no attributes """
data = Table("iris")
self.send_signal("Data", data[:0])
self.assertTrue(self.widget.Error.no_instances.is_shown())

domain = Domain([], None, data.domain.variables)
new_data = Table.from_table(domain, data)
self.send_signal("Data", new_data)
self.assertTrue(self.widget.Error.no_features.is_shown())
self.assertFalse(self.widget.Error.no_instances.is_shown())

self.send_signal("Data", None)
self.assertFalse(self.widget.Error.no_features.is_shown())