Skip to content

Commit

Permalink
OWKmeans: Do not recluster when X does not change
Browse files Browse the repository at this point in the history
  • Loading branch information
pavlin-policar committed Feb 19, 2018
1 parent 8228d3c commit 4fe83c0
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
9 changes: 7 additions & 2 deletions Orange/widgets/unsupervised/owkmeans.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,13 @@ def send_data(self):
@Inputs.data
@check_sql_input
def set_data(self, data):
self.data = data
self.invalidate()
self.data, old_data = data, self.data

# Do not needlessly recluster the data if X hasn't changed
if old_data and self.data and np.array_equal(self.data.X, old_data.X):
self.send_data()
else:
self.invalidate()

def send_report(self):
# False positives (Setting is not recognized as int)
Expand Down
39 changes: 38 additions & 1 deletion Orange/widgets/unsupervised/tests/test_owkmeans.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from AnyQt.QtWidgets import QRadioButton

import Orange.clustering
from Orange.data import Table
from Orange.data import Table, Domain
from Orange.widgets import gui
from Orange.widgets.tests.base import WidgetTest
from Orange.widgets.unsupervised.owkmeans import OWKMeans, ClusterTableModel
Expand Down Expand Up @@ -377,6 +377,43 @@ def test_invalidate_clusterings_cancels_jobs(self):

self.assertEqual(widget.clusterings, {})

def test_do_not_recluster_on_same_data(self):
"""Do not recluster data points when targets or metas change."""

# Prepare some dummy data
x = np.eye(5)
y1, y2 = np.ones((5, 1)), np.ones((5, 2))
meta1, meta2 = np.ones((5, 1)), np.ones((5, 2))

table1 = Table.from_numpy(
domain=Domain.from_numpy(X=x, Y=y1, metas=meta1),
X=x, Y=y1, metas=meta1,
)
# X is same, should not cause update
table2 = Table.from_numpy(
domain=Domain.from_numpy(X=x, Y=y2, metas=meta2),
X=x, Y=y2, metas=meta2,
)
# X is different, should cause update
table3 = table1.copy()
table3.X[:, 0] = 1

with patch.object(self.widget, 'commit') as commit:
self.send_signal(self.widget.Inputs.data, table1)
self.commit_and_wait()
call_count = commit.call_count
print(call_count)

# Sending data with same X should not recompute the clustering
self.send_signal(self.widget.Inputs.data, table2)
self.commit_and_wait()
self.assertEqual(call_count, commit.call_count)

# Sending data with different X should recompute the clustering
self.send_signal(self.widget.Inputs.data, table3)
self.commit_and_wait()
self.assertEqual(call_count + 1, commit.call_count)


if __name__ == "__main__":
unittest.main()

0 comments on commit 4fe83c0

Please sign in to comment.