Skip to content

Commit

Permalink
Merge pull request biolab#5857 from VesnaT/som_replot
Browse files Browse the repository at this point in the history
SOM: Recompute only when effective data changes
  • Loading branch information
janezd authored Mar 11, 2022
2 parents b7515c1 + c0809df commit 62549d2
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 10 deletions.
25 changes: 15 additions & 10 deletions Orange/widgets/unsupervised/owsom.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
QGraphicsPathItem

from Orange.data import Table, Domain
from Orange.data.util import array_equal
from Orange.preprocess import decimal_binnings, time_binnings
from Orange.projection.som import SOM

Expand Down Expand Up @@ -330,12 +331,10 @@ def set_warnings():
elif missing > 1:
self.Warning.missing_values(missing, "s", "are")

self.stop_optimization_and_wait()

cont_x = self.cont_x.copy() if self.cont_x is not None else None
self.data = self.cont_x = None
self.closeContext()
self.clear()
self.Error.clear()
self.Warning.clear()
self.clear_messages()

if data is not None:
attrs = data.domain.attributes
Expand All @@ -345,6 +344,12 @@ def set_warnings():
else:
prepare_data()

invalidated = cont_x is None or self.cont_x is None \
or not array_equal(cont_x, self.cont_x)
if invalidated:
self.stop_optimization_and_wait()
self.clear()

if self.data is not None:
self.controls.attr_color.model().set_domain(data.domain)
self.attr_color = data.domain.class_var
Expand All @@ -353,11 +358,13 @@ def set_warnings():
self.openContext(self.data)
self.set_color_bins()
self.create_legend()
self.recompute_dimensions()
self.start_som()
if invalidated:
self.recompute_dimensions()
self.start_som()
else:
self._redraw()

def clear(self):
self.data = self.cont_x = None
self.cells = self.member_data = None
self.attr_color = None
self.colors = self.thresholds = self.bin_labels = None
Expand All @@ -366,8 +373,6 @@ def clear(self):
self.elements = None
self.clear_selection()
self.controls.attr_color.model().set_domain(None)
self.Warning.clear()
self.Error.clear()

def recompute_dimensions(self):
if not self.auto_dimension or self.cont_x is None:
Expand Down
36 changes: 36 additions & 0 deletions Orange/widgets/unsupervised/tests/test_owsom.py
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,42 @@ def test_output(self):
self.assertIsNone(self.get_output(widget.Outputs.selected_data))
self.assertIsNone(self.get_output(widget.Outputs.annotated_data))

def test_invalidated(self):
heart = Table("heart_disease")
self.widget._recompute_som = Mock()

# New data - replot
self.send_signal(self.widget.Inputs.data, heart)
self.widget._recompute_som.assert_called_once()

# Same data - no replot
self.widget._recompute_som.reset_mock()
self.send_signal(self.widget.Inputs.data, heart)
self.widget._recompute_som.assert_not_called()

# Same data.X - no replot
domain = heart.domain
domain = Domain(domain.attributes, metas=domain.class_vars)
heart_with_metas = self.iris.transform(domain)
self.widget._recompute_som.reset_mock()
self.send_signal(self.widget.Inputs.data, heart_with_metas)
self.widget._recompute_som.assert_not_called()

# Different data, same set of cont. vars - no replot
attrs = [a for a in heart.domain.attributes if a.is_continuous]
domain = Domain(attrs)
heart_with_cont_features = self.iris.transform(domain)
self.widget._recompute_som.reset_mock()
self.send_signal(self.widget.Inputs.data, heart_with_cont_features)
self.widget._recompute_som.assert_not_called()

# Different data.X - replot
domain = Domain(heart.domain.attributes[:5])
heart_with_less_features = heart.transform(domain)
self.widget._recompute_som.reset_mock()
self.send_signal(self.widget.Inputs.data, heart_with_less_features)
self.widget._recompute_som.assert_called_once()


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

0 comments on commit 62549d2

Please sign in to comment.