From 6a6d6994439fe36609f68a6e39419c8b9f7a1d6b Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 13 Mar 2020 11:29:12 +0100 Subject: [PATCH] ScatterplotGraph.update_density: Ignore points with mising value for color --- .../widgets/visualize/owscatterplotgraph.py | 10 ++++-- .../visualize/tests/test_owscatterplotbase.py | 35 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/Orange/widgets/visualize/owscatterplotgraph.py b/Orange/widgets/visualize/owscatterplotgraph.py index c4007004e24..b3a232037c1 100644 --- a/Orange/widgets/visualize/owscatterplotgraph.py +++ b/Orange/widgets/visualize/owscatterplotgraph.py @@ -1101,16 +1101,22 @@ def update_density(self): self.plot_widget.removeItem(self.density_img) self.density_img = None if self.class_density and self.scatterplot_item is not None: + c_data = self.master.get_color_data() + if c_data is None: + return + mask = np.isfinite(self._filter_visible(c_data)) + pens = self.scatterplot_item.data['pen'] rgb_data = [ pen.color().getRgb()[:3] if pen is not None else (255, 255, 255) - for pen in self.scatterplot_item.data['pen']] + for known, pen in zip(mask, pens) + if known] if len(set(rgb_data)) <= 1: return [min_x, max_x], [min_y, max_y] = self.view_box.viewRange() x_data, y_data = self.scatterplot_item.getData() self.density_img = classdensity.class_density_image( min_x, max_x, min_y, max_y, self.resolution, - x_data, y_data, rgb_data) + x_data[mask], y_data[mask], rgb_data) self.plot_widget.addItem(self.density_img) def update_selection_colors(self): diff --git a/Orange/widgets/visualize/tests/test_owscatterplotbase.py b/Orange/widgets/visualize/tests/test_owscatterplotbase.py index 8b9391a9b7b..b73b536344b 100644 --- a/Orange/widgets/visualize/tests/test_owscatterplotbase.py +++ b/Orange/widgets/visualize/tests/test_owscatterplotbase.py @@ -740,6 +740,41 @@ def test_density(self): self.assertIsNone(graph.density_img) self.assertIs(graph.plot_widget.removeItem.call_args[0][0], density) + @patch("Orange.widgets.utils.classdensity.class_density_image") + def test_density_with_missing(self, class_density_image): + graph = self.graph + graph.reset_graph() + graph.plot_widget.addItem = Mock() + graph.plot_widget.removeItem = Mock() + + graph.class_density = True + d = np.arange(10, dtype=float) % 2 + self.master.get_color_data = lambda: d + + # All colors known + graph.update_colors() + x_data0, y_data0, colors0 = class_density_image.call_args[0][5:] + + # Some missing colors + d[:3] = np.nan + graph.update_colors() + x_data, y_data, colors = class_density_image.call_args[0][5:] + np.testing.assert_equal(x_data, x_data0[3:]) + np.testing.assert_equal(y_data, y_data0[3:]) + np.testing.assert_equal(colors, colors0[3:]) + + # Missing colors + only subsample plotted + graph.set_sample_size(8) + graph.reset_graph() + d_known = np.isfinite(graph._filter_visible(d)) + x_data0 = graph._filter_visible(x_data0)[d_known] + y_data0 = graph._filter_visible(y_data0)[d_known] + colors0 = graph._filter_visible(np.array(colors0))[d_known] + x_data, y_data, colors = class_density_image.call_args[0][5:] + np.testing.assert_equal(x_data, x_data0) + np.testing.assert_equal(y_data, y_data0) + np.testing.assert_equal(colors, colors0) + def test_labels(self): graph = self.graph graph.reset_graph()