diff --git a/Orange/widgets/unsupervised/owmds.py b/Orange/widgets/unsupervised/owmds.py index 2b6c141f1c0..b686e3f961a 100644 --- a/Orange/widgets/unsupervised/owmds.py +++ b/Orange/widgets/unsupervised/owmds.py @@ -133,6 +133,8 @@ class Error(OWWidget.Error): no_attributes = Msg("Data has no attributes") mismatching_dimensions = \ Msg("Data and distances dimensions do not match.") + out_of_memory = Msg("Out of memory") + optimization_error = Msg("Error during optimization\n{}") def __init__(self): super().__init__() @@ -621,6 +623,7 @@ def __next_step(self): return loop = self.__update_loop + self.Error.out_of_memory.clear() try: embedding, stress, progress = next(self.__update_loop) assert self.__update_loop is loop @@ -630,6 +633,14 @@ def __next_step(self): self.__draw_similar_pairs = True self._update_plot() self.plot.autoRange(padding=0.1, items=[self._scatter_item]) + except MemoryError: + self.Error.out_of_memory() + self.__set_update_loop(None) + self.__draw_similar_pairs = True + except Exception as exc: + self.Error.optimization_error(str(exc)) + self.__set_update_loop(None) + self.__draw_similar_pairs = True else: self.progressBarSet(100.0 * progress, processEvents=None) self.embedding = embedding diff --git a/Orange/widgets/unsupervised/tests/test_owmds.py b/Orange/widgets/unsupervised/tests/test_owmds.py index 75fb54396af..0e03be9317c 100644 --- a/Orange/widgets/unsupervised/tests/test_owmds.py +++ b/Orange/widgets/unsupervised/tests/test_owmds.py @@ -1,6 +1,7 @@ # Test methods with long descriptive names can omit docstrings # pylint: disable=missing-docstring import random +from unittest.mock import patch, Mock import numpy as np @@ -69,3 +70,20 @@ def test_nan_plot(self): simulate.combobox_run_through_all(self.widget.cb_shape_value) simulate.combobox_run_through_all(self.widget.cb_size_value) simulate.combobox_run_through_all(self.widget.cb_label_value) + + @patch("Orange.projection.MDS.__call__", Mock(side_effect=MemoryError)) + def test_out_of_memory(self): + with patch("sys.excepthook", Mock()) as hook: + self.send_signal("Data", self.data) + self.process_events() + hook.assert_not_called() + self.assertTrue(self.widget.Error.out_of_memory.is_shown()) + + @patch("Orange.projection.MDS.__call__", Mock(side_effect=ValueError)) + def test_other_error(self): + with patch("sys.excepthook", Mock()) as hook: + self.send_signal("Data", self.data) + self.process_events() + hook.assert_not_called() + self.assertTrue(self.widget.Error.optimization_error.is_shown()) +