Repository: biolab/orange3

Issue:
MDS no longer handles data subsets
##### Orange version
3.20.1

##### Expected behavior
MDS should mark data points that come from Data Subset channel.

##### Actual behavior
The input in Data Subset channel has no effect on the visualisation.

##### Steps to reproduce the behavior
![screen shot 2019-02-20 at 15 14 34](https://user-images.githubusercontent.com/726604/53097648-3ff9b380-3522-11e9-9536-9f57a21d141f.png)

Fails with any data set, I have used brown-selected.


Discussion:

Resolving patch:
diff --git a/Orange/widgets/unsupervised/owmds.py b/Orange/widgets/unsupervised/owmds.py
--- a/Orange/widgets/unsupervised/owmds.py
+++ b/Orange/widgets/unsupervised/owmds.py
@@ -158,7 +158,6 @@ def __init__(self):
         #: Input data table
         self.signal_data = None
 
-        self.__invalidated = True
         self.embedding = None
         self.effective_matrix = None
 
@@ -243,7 +242,7 @@ def clear(self):
     def _initialize(self):
         matrix_existed = self.effective_matrix is not None
         effective_matrix = self.effective_matrix
-        self.__invalidated = True
+        self._invalidated = True
         self.data = None
         self.effective_matrix = None
         self.closeContext()
@@ -285,11 +284,11 @@ def _initialize(self):
 
         self.init_attr_values()
         self.openContext(self.data)
-        self.__invalidated = not (matrix_existed and
-                                  self.effective_matrix is not None and
-                                  np.array_equal(effective_matrix,
-                                                 self.effective_matrix))
-        if self.__invalidated:
+        self._invalidated = not (matrix_existed and
+                                 self.effective_matrix is not None and
+                                 np.array_equal(effective_matrix,
+                                                self.effective_matrix))
+        if self._invalidated:
             self.clear()
         self.graph.set_effective_matrix(self.effective_matrix)
 
@@ -444,12 +443,15 @@ def __next_step(self):
 
     def do_PCA(self):
         self.__invalidate_embedding(self.PCA)
+        self.setup_plot()
 
     def do_random(self):
         self.__invalidate_embedding(self.Random)
+        self.setup_plot()
 
     def do_jitter(self):
         self.__invalidate_embedding(self.Jitter)
+        self.setup_plot()
 
     def __invalidate_embedding(self, initialization=PCA):
         def jitter_coord(part):
@@ -476,8 +478,6 @@ def jitter_coord(part):
             jitter_coord(self.embedding[:, 0])
             jitter_coord(self.embedding[:, 1])
 
-        self.setup_plot()
-
         # restart the optimization if it was interrupted.
         if state == OWMDS.Running:
             self.__start()
@@ -496,15 +496,12 @@ def __invalidate_refresh(self):
 
     def handleNewSignals(self):
         self._initialize()
-        if self.__invalidated:
+        if self._invalidated:
             self.graph.pause_drawing_pairs()
-            self.__invalidated = False
             self.__invalidate_embedding()
-            self.cb_class_density.setEnabled(self.can_draw_density())
+            self.enable_controls()
             self.start()
-        else:
-            self.graph.update_point_props()
-        self.commit()
+        super().handleNewSignals()
 
     def _invalidate_output(self):
         self.commit()
diff --git a/Orange/widgets/visualize/utils/widget.py b/Orange/widgets/visualize/utils/widget.py
--- a/Orange/widgets/visualize/utils/widget.py
+++ b/Orange/widgets/visualize/utils/widget.py
@@ -459,6 +459,15 @@ def set_subset_data(self, subset):
         self.controls.graph.alpha_value.setEnabled(subset is None)
 
     def handleNewSignals(self):
+        self._handle_subset_data()
+        if self._invalidated:
+            self._invalidated = False
+            self.setup_plot()
+        else:
+            self.graph.update_point_props()
+        self.commit()
+
+    def _handle_subset_data(self):
         self.Warning.subset_independent.clear()
         self.Warning.subset_not_subset.clear()
         if self.data is None or self.subset_data is None:
@@ -471,13 +480,6 @@ def handleNewSignals(self):
             elif self.subset_indices - ids:
                 self.Warning.subset_not_subset()
 
-        if self._invalidated:
-            self._invalidated = False
-            self.setup_plot()
-        else:
-            self.graph.update_point_props()
-        self.commit()
-
     def get_subset_mask(self):
         if not self.subset_indices:
             return None


Test patch:
diff --git a/Orange/widgets/tests/base.py b/Orange/widgets/tests/base.py
--- a/Orange/widgets/tests/base.py
+++ b/Orange/widgets/tests/base.py
@@ -947,6 +947,21 @@ def test_plot_once(self, timeout=DEFAULT_TIMEOUT):
         self.widget.setup_plot.assert_called_once()
         self.widget.commit.assert_called_once()
 
+    def test_subset_data_color(self, timeout=DEFAULT_TIMEOUT):
+        self.send_signal(self.widget.Inputs.data, self.data)
+
+        if self.widget.isBlocking():
+            spy = QSignalSpy(self.widget.blockingStateChanged)
+            self.assertTrue(spy.wait(timeout))
+
+        self.send_signal(self.widget.Inputs.data_subset, self.data[:10])
+        subset = [brush.color().name() == "#46befa" for brush in
+                  self.widget.graph.scatterplot_item.data['brush'][:10]]
+        other = [brush.color().name() == "#000000" for brush in
+                 self.widget.graph.scatterplot_item.data['brush'][10:]]
+        self.assertTrue(all(subset))
+        self.assertTrue(all(other))
+
     def test_class_density(self, timeout=DEFAULT_TIMEOUT):
         """Check class density update"""
         self.send_signal(self.widget.Inputs.data, self.data)