Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] BoxPlot crashes on variables with no known values (#1568) #1647

Merged
merged 2 commits into from Oct 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 11 additions & 6 deletions Orange/widgets/visualize/owboxplot.py
Expand Up @@ -497,8 +497,11 @@ def mean_label(self, stat, attr, val_name):

def draw_axis(self):
"""Draw the horizontal axis and sets self.scale_x"""
bottom = min(stat.a_min for stat in self.stats)
top = max(stat.a_max for stat in self.stats)
misssing_stats = not self.stats
stats = self.stats or [BoxData(np.array([[0.], [1.]]))]
mean_labels = self.mean_labels or [self.mean_label(stats[0], self.attribute, "")]
bottom = min(stat.a_min for stat in stats)
top = max(stat.a_max for stat in stats)

first_val, step = compute_scale(bottom, top)
while bottom <= first_val:
Expand All @@ -507,8 +510,8 @@ def draw_axis(self):
no_ticks = math.ceil((top - first_val) / step) + 1
top = max(top, first_val + no_ticks * step)

gbottom = min(bottom, min(stat.mean - stat.dev for stat in self.stats))
gtop = max(top, max(stat.mean + stat.dev for stat in self.stats))
gbottom = min(bottom, min(stat.mean - stat.dev for stat in stats))
gtop = max(top, max(stat.mean + stat.dev for stat in stats))

bv = self.box_view
viewrect = bv.viewport().rect().adjusted(15, 15, -15, -30)
Expand All @@ -517,7 +520,7 @@ def draw_axis(self):
# In principle we should repeat this until convergence since the new
# scaling is too conservative. (No chance am I doing this.)
mlb = min(stat.mean + mean_lab.min_x / scale_x
for stat, mean_lab in zip(self.stats, self.mean_labels))
for stat, mean_lab in zip(stats, mean_labels))
if mlb < gbottom:
gbottom = mlb
self.scale_x = scale_x = viewrect.width() / (gtop - gbottom)
Expand All @@ -530,8 +533,10 @@ def draw_axis(self):
l = self.box_scene.addLine(val * scale_x, -1, val * scale_x, 1,
self._pen_axis_tick)
l.setZValue(100)

t = self.box_scene.addSimpleText(
self.attribute.repr_val(val), self._axis_font)
self.attribute.repr_val(val) if not misssing_stats else "?",
self._axis_font)
t.setFlags(
t.flags() | QtGui.QGraphicsItem.ItemIgnoresTransformations)
r = t.boundingRect()
Expand Down
55 changes: 55 additions & 0 deletions Orange/widgets/visualize/tests/test_owboxplot.py
@@ -0,0 +1,55 @@
# Test methods with long descriptive names can omit docstrings
# pylint: disable=missing-docstring
from unittest import skip

import numpy as np
from Orange.data import Table, ContinuousVariable
from Orange.widgets.visualize.owboxplot import OWBoxPlot
from Orange.widgets.tests.base import WidgetTest


class TestOWBoxPlot(WidgetTest):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.iris = Table("iris")
cls.zoo = Table("zoo")
cls.housing = Table("housing")

def setUp(self):
self.widget = self.create_widget(OWBoxPlot)

@skip("Known bug, FIXME!")
def test_input_data(self):
"""Check widget's data"""
self.send_signal("Data", self.iris)
self.assertGreater(len(self.widget.attrs), 0)
self.send_signal("Data", None)
self.assertEqual(len(self.widget.attrs), 0)

def test_input_data_missings_cont_group_var(self):
"""Check widget with continuous data with missing values and group variable"""
data = self.iris
data.X[:, 0] = np.nan
self.send_signal("Data", data)
# used to crash, see #1568

def test_input_data_missings_cont_no_group_var(self):
"""Check widget with continuous data with missing values and no group variable"""
data = self.housing
data.X[:, 0] = np.nan
self.send_signal("Data", data)
# used to crash, see #1568

def test_input_data_missings_disc_group_var(self):
"""Check widget with discrete data with missing values and group variable"""
data = self.zoo
data.X[:, 0] = np.nan
self.send_signal("Data", data)

def test_input_data_missings_disc_no_group_var(self):
"""Check widget discrete data with missing values and no group variable"""
data = self.zoo
data.domain.class_var = ContinuousVariable("cls")
data.X[:, 0] = np.nan
self.send_signal("Data", data)