Repository: biolab/orange3

Issue:
Scatter Plot: show warning when domains don't match
##### Orange version
3.17.dev

##### Expected behavior
When connecting a subset to Scatter Plot and data domains don't match, the widget should display a warning.


##### Actual behavior
The projection is correct, but there is no warning saying what happened.


##### Steps to reproduce the behavior
File (iris) - Scatter Plot. File (1) (titanic) - connect as Subset to Scatter Plot.


##### Additional info (worksheets, data, screenshots, ...)





Discussion:

Resolving patch:
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
@@ -363,6 +363,11 @@ class Outputs:
     class Warning(OWProjectionWidgetBase.Warning):
         too_many_labels = Msg(
             "Too many labels to show (zoom in or label only selected)")
+        subset_not_subset = Msg(
+            "Subset data contains some instances that do not appear in "
+            "input data")
+        subset_independent = Msg(
+            "None of subset data instance appear in input data")
 
     settingsHandler = DomainContextHandler()
     selection = Setting(None, schema_only=True)
@@ -463,10 +468,19 @@ def handleNewSignals(self):
         self.commit()
 
     def get_subset_mask(self):
-        if self.subset_indices:
-            return np.array([ex.id in self.subset_indices
-                             for ex in self.data[self.valid_data]])
-        return None
+        self.Warning.subset_independent.clear()
+        self.Warning.subset_not_subset.clear()
+        if not self.subset_indices:
+            return None
+        valid_data = self.data[self.valid_data]
+        mask = np.fromiter((ex.id in self.subset_indices for ex in valid_data),
+                           dtype=np.bool, count=len(valid_data))
+        in_mask = mask.sum()
+        if not in_mask:
+            self.Warning.subset_independent()
+        elif in_mask < len(self.subset_indices):
+            self.Warning.subset_not_subset()
+        return mask
 
     # Plot
     def get_embedding(self):


Test patch:
diff --git a/Orange/widgets/visualize/tests/test_owprojectionwidget.py b/Orange/widgets/visualize/tests/test_owprojectionwidget.py
--- a/Orange/widgets/visualize/tests/test_owprojectionwidget.py
+++ b/Orange/widgets/visualize/tests/test_owprojectionwidget.py
@@ -1,5 +1,6 @@
 # Test methods with long descriptive names can omit docstrings
 # pylint: disable=missing-docstring
+import unittest
 from unittest.mock import patch
 
 import numpy as np
@@ -164,3 +165,39 @@ def test_too_many_labels(self):
 
         self.widget.graph.too_many_labels.emit(False)
         self.assertFalse(w.is_shown())
+
+    def test_invalid_subset(self):
+        widget = self.widget
+
+        data = Table("iris")
+        self.send_signal(widget.Inputs.data_subset, data[40:60])
+        self.assertFalse(widget.Warning.subset_independent.is_shown())
+        self.assertFalse(widget.Warning.subset_not_subset.is_shown())
+
+        self.send_signal(widget.Inputs.data, data[30:70])
+        self.assertFalse(widget.Warning.subset_independent.is_shown())
+        self.assertFalse(widget.Warning.subset_not_subset.is_shown())
+
+        self.send_signal(widget.Inputs.data, data[30:50])
+        self.assertFalse(widget.Warning.subset_independent.is_shown())
+        self.assertTrue(widget.Warning.subset_not_subset.is_shown())
+
+        self.send_signal(widget.Inputs.data, data[20:30])
+        self.assertTrue(widget.Warning.subset_independent.is_shown())
+        self.assertFalse(widget.Warning.subset_not_subset.is_shown())
+
+        self.send_signal(widget.Inputs.data, data[30:70])
+        self.assertFalse(widget.Warning.subset_independent.is_shown())
+        self.assertFalse(widget.Warning.subset_not_subset.is_shown())
+
+        self.send_signal(widget.Inputs.data, data[30:50])
+        self.assertFalse(widget.Warning.subset_independent.is_shown())
+        self.assertTrue(widget.Warning.subset_not_subset.is_shown())
+
+        self.send_signals([(widget.Inputs.data, Table("titanic")),
+                           (widget.Inputs.data_subset, None)])
+        self.assertFalse(widget.Warning.subset_independent.is_shown())
+        self.assertFalse(widget.Warning.subset_not_subset.is_shown())
+
+if __name__ == "__main__":
+    unittest.main()