Repository: biolab/orange3

Issue:
Mosaic crashes if data size is 1 and it has a subset
As discovered by @VesnaT in the review of #3284 (but unrelated to it), Mosaic crashes when given data set with a single instance (say from data table) and a subset (say from data sample).

![48947752-809d5d00-ef32-11e8-8a83-30f1fd50e2d1](https://user-images.githubusercontent.com/2387315/48961755-81a4ad80-ef77-11e8-99be-5778fe0f81be.png)



Discussion:

Resolving patch:
diff --git a/Orange/widgets/visualize/owmosaic.py b/Orange/widgets/visualize/owmosaic.py
--- a/Orange/widgets/visualize/owmosaic.py
+++ b/Orange/widgets/visualize/owmosaic.py
@@ -6,7 +6,7 @@
 
 import numpy as np
 from scipy.stats import distributions
-from scipy.misc import comb
+from scipy.special import comb
 from AnyQt.QtCore import Qt, QSize, pyqtSignal as Signal
 from AnyQt.QtGui import QColor, QPainter, QPen, QStandardItem
 from AnyQt.QtWidgets import QGraphicsScene, QGraphicsLineItem
@@ -457,7 +457,7 @@ def reset_graph(self):
         self.update_graph()
 
     def set_color_data(self):
-        if self.data is None or len(self.data) < 2:
+        if self.data is None:
             return
         self.bar_button.setEnabled(self.variable_color is not None)
         attrs = [v for v in self.model_1 if v and v is not self.variable_color]
@@ -712,7 +712,7 @@ def line(x1, y1, x2, y2):
                     (apriori_dists[i][used_vals[i]] / float(s)
                      for i in range(len(used_vals))))
                 actual = conditionaldict[attr_vals]
-                pearson = (actual - expected) / sqrt(expected)
+                pearson = float((actual - expected) / sqrt(expected))
                 if pearson == 0:
                     ind = 0
                 else:


Test patch:
diff --git a/Orange/widgets/visualize/tests/test_owmosaic.py b/Orange/widgets/visualize/tests/test_owmosaic.py
--- a/Orange/widgets/visualize/tests/test_owmosaic.py
+++ b/Orange/widgets/visualize/tests/test_owmosaic.py
@@ -15,6 +15,7 @@
 from Orange.widgets.visualize.owmosaic import OWMosaicDisplay
 from Orange.widgets.tests.utils import simulate
 
+
 class TestOWMosaicDisplay(WidgetTest, WidgetOutputsTestMixin):
     @classmethod
     def setUpClass(cls):
@@ -112,6 +113,22 @@ def test_different_number_of_attributes(self, canvas_rectangle):
             self.widget.update_graph()
             self.assertEqual(canvas_rectangle.call_count, 7 + 2 ** (i + 1))
 
+    def test_change_domain(self):
+        """Test for GH-3419 fix"""
+        self.send_signal(self.widget.Inputs.data, self.data[:, :2])
+        subset = self.data[:1, 2:3]
+        self.send_signal(self.widget.Inputs.data, subset)
+        output = self.get_output(self.widget.Outputs.annotated_data)
+        np.testing.assert_array_equal(output.X, subset.X)
+
+    def test_subset(self):
+        """Test for GH-3416 fix"""
+        self.send_signal(self.widget.Inputs.data, self.data)
+        self.send_signal(self.widget.Inputs.data_subset, self.data[10:])
+        self.send_signal(self.widget.Inputs.data, self.data[:1])
+        output = self.get_output(self.widget.Outputs.annotated_data)
+        np.testing.assert_array_equal(output.X, self.data[:1].X)
+
 
 # Derive from WidgetTest to simplify creation of the Mosaic widget, although
 # we are actually testing the MosaicVizRank dialog and not the widget