Skip to content

Commit

Permalink
OWTreeLearner: report error instead of crashing when can't binarize
Browse files Browse the repository at this point in the history
  • Loading branch information
janezd committed Dec 23, 2016
1 parent a2d4385 commit 6065e3a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 0 deletions.
21 changes: 21 additions & 0 deletions Orange/widgets/classify/owclassificationtree.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from Orange.widgets import gui
from Orange.widgets.settings import Setting
from Orange.widgets.utils.owlearnerwidget import OWBaseLearner
from Orange.widgets.widget import Msg


class OWTreeLearner(OWBaseLearner):
Expand All @@ -29,6 +30,12 @@ class OWTreeLearner(OWBaseLearner):
("Limit the maximal tree depth to: ",
"limit_depth", "max_depth", 1, 1000))

class Error(OWBaseLearner.Error):
cannot_binarize = Msg("Binarization cannot handle '{}'\n"
"because it has {} values. "
"Binarization can handle up to {}.\n"
"Disable 'Induce binary tree' to proceed.")

def add_main_layout(self):
box = gui.vBox(self.controlArea, True)
# the checkbox is put into vBox for alignemnt with other checkboxes
Expand All @@ -49,6 +56,20 @@ def learner_kwargs(self):
binarize=self.binary_trees,
preprocessors=self.preprocessors)

def check_data(self):
self.Error.cannot_binarize.clear()
if not super().check_data():
return False
max_values, max_attr = max(
((len(attr.values), attr)
for attr in self.data.domain.attributes if attr.is_discrete),
default=(0, None))
if max_values > self.LEARNER.MAX_BINARIZATION:
self.Error.cannot_binarize(
max_attr.name, max_values, self.LEARNER.MAX_BINARIZATION)
return False
return True

def create_learner(self):
# pylint: disable=not-callable
return self.LEARNER(**self.learner_kwargs())
Expand Down
28 changes: 28 additions & 0 deletions Orange/widgets/classify/tests/test_owclassificationtree.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
# Test methods with long descriptive names can omit docstrings
# pylint: disable=missing-docstring
from Orange.data import Table, Domain, DiscreteVariable
from Orange.base import Model
from Orange.widgets.classify.owclassificationtree import OWClassificationTree
from Orange.widgets.tests.base import (WidgetTest, DefaultParameterMapping,
ParameterMapping, WidgetLearnerTestMixin)


class TestOWClassificationTree(WidgetTest, WidgetLearnerTestMixin):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.iris = Table("iris")

def setUp(self):
self.widget = self.create_widget(OWClassificationTree,
stored_settings={"auto_apply": False})
Expand Down Expand Up @@ -34,3 +40,25 @@ def test_parameters_unchecked(self):
for par, val in zip(self.parameters, (None, 2, 1))]
self.test_parameters()

def test_cannot_binarize(self):
widget = self.widget
error_shown = self.widget.Error.cannot_binarize.is_shown
self.assertFalse(error_shown())
self.send_signal("Data", self.iris)
self.assertFalse(error_shown())
domain = Domain([
DiscreteVariable(
values=[str(x)
for x in range(widget.LEARNER.MAX_BINARIZATION + 1)])],
DiscreteVariable(values="01"))
self.send_signal("Data", Table(domain, [[0, 0], [1, 1]]))
self.assertTrue(error_shown())
self.send_signal("Data", self.iris)
self.assertFalse(error_shown())
domain = Domain([
DiscreteVariable(
values=[str(x)
for x in range(widget.LEARNER.MAX_BINARIZATION + 1)])],
DiscreteVariable(values="01"))
self.send_signal("Data", Table(domain))
self.assertFalse(error_shown())

0 comments on commit 6065e3a

Please sign in to comment.