Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 50 additions & 11 deletions Orange/widgets/visualize/owdistributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def mouseReleaseEvent(event):

class DistributionBarItem(pg.GraphicsObject):
def __init__(self, x, width, padding, freqs, colors, stacked, expanded,
tooltip):
tooltip, hidden):
super().__init__()
self.x = x
self.width = width
Expand All @@ -77,8 +77,10 @@ def __init__(self, x, width, padding, freqs, colors, stacked, expanded,
self.__picture = None
self.polygon = None
self.hovered = False
self._tooltip = tooltip
self.hidden = False
self.setHidden(hidden)
self.setAcceptHoverEvents(True)
self.setToolTip(tooltip)

def hoverEnterEvent(self, event):
super().hoverEnterEvent(event)
Expand All @@ -90,7 +92,15 @@ def hoverLeaveEvent(self, event):
self.hovered = False
self.update()

def setHidden(self, hidden):
self.hidden = hidden
if not hidden:
self.setToolTip(self._tooltip)

def paint(self, painter, _options, _widget):
if self.hidden:
return

if self.expanded:
tot = np.sum(self.freqs)
if tot == 0:
Expand Down Expand Up @@ -264,6 +274,7 @@ class Warning(OWWidget.Warning):
number_of_bins = settings.ContextSetting(5, schema_only=True)

fitted_distribution = settings.Setting(0)
hide_bars = settings.Setting(False)
show_probs = settings.Setting(False)
stacked_columns = settings.Setting(False)
cumulative_distr = settings.Setting(False)
Expand Down Expand Up @@ -292,6 +303,7 @@ def __init__(self):
self.data = None
self.valid_data = self.valid_group_data = None
self.bar_items = []
self.curve_items = []
self.curve_descriptions = None
self.binnings = []

Expand Down Expand Up @@ -326,8 +338,9 @@ def __init__(self):
label="Smoothing", orientation=Qt.Horizontal,
minValue=2, maxValue=20, callback=self.replot)
gui.checkBox(
box, self, "cumulative_distr", "Show cumulative distribution",
callback=self.replot)
box, self, "hide_bars", "Hide bars", stateWhenDisabled=False,
callback=self._on_hide_bars_changed,
disabled=not self.fitted_distribution)

box = gui.vBox(self.controlArea, "Columns")
gui.comboBox(
Expand All @@ -341,6 +354,9 @@ def __init__(self):
gui.checkBox(
box, self, "show_probs", "Show probabilities",
callback=self._on_show_probabilities_changed)
gui.checkBox(
box, self, "cumulative_distr", "Show cumulative distribution",
callback=self.replot)

gui.auto_apply(self.controlArea, self, commit=self.apply)

Expand Down Expand Up @@ -385,7 +401,7 @@ def add_new_plot(zvalue):

def _setup_legend(self):
self._legend = LegendItem()
self._legend.setParentItem(self.plot)
self._legend.setParentItem(self.plot_pdf)
self._legend.hide()
self._legend.anchor((1, 0), (1, 0))

Expand Down Expand Up @@ -449,9 +465,16 @@ def _on_bin_slider_released(self):
self.apply()

def _on_fitted_dist_changed(self):
self.controls.hide_bars.setDisabled(not self.fitted_distribution)
self._set_smoothing_visibility()
self.replot()

def _on_hide_bars_changed(self):
for bar in self.bar_items: # pylint: disable=blacklisted-name
bar.setHidden(self.hide_bars)
self._set_curve_brushes()
self.plot.update()

def _set_smoothing_visibility(self):
self.smoothing_box.setVisible(
self.Fitters[self.fitted_distribution][1] is AshCurve)
Expand Down Expand Up @@ -525,6 +548,7 @@ def _clear_plot(self):
self.plot_pdf.clear()
self.plot_mark.clear()
self.bar_items = []
self.curve_items = []
self._legend.clear()
self._legend.hide()

Expand Down Expand Up @@ -564,9 +588,10 @@ def _call_plotting(self):
self.plot.autoRange()

def _add_bar(self, x, width, padding, freqs, colors, stacked, expanded,
tooltip):
tooltip, hidden=False):
item = DistributionBarItem(
x, width, padding, freqs, colors, stacked, expanded, tooltip)
x, width, padding, freqs, colors, stacked, expanded, tooltip,
hidden)
self.plot.addItem(item)
self.bar_items.append(item)

Expand Down Expand Up @@ -618,7 +643,8 @@ def _cont_plot(self):
f"{freq} ({100 * freq / total:.2f} %)</p>"
self._add_bar(
x0, x1 - x0, 0, [tot_freq if self.cumulative_distr else freq],
colors, stacked=False, expanded=False, tooltip=tooltip)
colors, stacked=False, expanded=False, tooltip=tooltip,
hidden=self.hide_bars)

if self.fitted_distribution:
self._plot_approximations(
Expand Down Expand Up @@ -657,6 +683,7 @@ def _cont_split_plot(self):
self._add_bar(
x0, x1 - x0, 0 if self.stacked_columns else 0.1, plotfreqs,
gcolors, stacked=self.stacked_columns, expanded=self.show_probs,
hidden=self.hide_bars,
tooltip=self._split_tooltip(
self.str_int(x0, x1, not i, i == lasti),
np.sum(plotfreqs), total, gvalues, plotfreqs))
Expand Down Expand Up @@ -734,12 +761,24 @@ def _plot_approximations(self, x0, x1, fitters, colors, prior_probs):
tot = (y_p + (tots - y) * (1 - prior_prob))
tot[tot == 0] = 1
y = y_p / tot
plot.addItem(pg.PlotCurveItem(
x=x, y=y,
curve = pg.PlotCurveItem(
x=x, y=y, fillLevel=0,
pen=pg.mkPen(width=5, color=color),
shadowPen=pg.mkPen(width=8, color=color.darker(120))))
shadowPen=pg.mkPen(width=8, color=color.darker(120)))
plot.addItem(curve)
self.curve_items.append(curve)
if not show_probs:
self.plot_pdf.autoRange()
self._set_curve_brushes()

def _set_curve_brushes(self):
for curve in self.curve_items:
if self.hide_bars:
color = curve.opts['pen'].color().lighter(160)
color.setAlpha(128)
curve.setBrush(pg.mkBrush(color))
else:
curve.setBrush(None)

@staticmethod
def _split_tooltip(valname, tot_group, total, gvalues, freqs):
Expand Down
48 changes: 47 additions & 1 deletion Orange/widgets/visualize/tests/test_owdistributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from unittest.mock import Mock

import numpy as np
from AnyQt.QtCore import QItemSelection
from AnyQt.QtCore import QItemSelection, Qt

from Orange.data import Table, Domain, DiscreteVariable
from Orange.widgets.tests.base import WidgetTest
Expand Down Expand Up @@ -461,6 +461,52 @@ def test_selection_grouping(self):
self.assertEqual(
len(out_selected.domain[ANNOTATED_DATA_FEATURE_NAME].values), 3)

def test_disable_hide_bars(self):
widget = self.widget
self.send_signal(widget.Inputs.data, self.iris)
domain = self.iris.domain

cb = widget.controls.hide_bars

for var in ("petal length", "iris"):
for fitter in (0, 1):
self._set_var(domain[var])
self._set_fitter(fitter)
self.assertEqual(cb.isEnabled(),
var == "petal length" and fitter == 1)

def test_hide_bars(self):
# bar is a valid name in this context, pylint: disable=blacklisted-name
widget = self.widget
cb = widget.controls.hide_bars
self._set_check(cb, True)
self._set_fitter(1)

self.send_signal(widget.Inputs.data, self.iris)

domain = self.iris.domain
self._set_var(domain["petal length"])

for cvar in (None, domain["iris"]):
self._set_cvar(cvar)
self.assertTrue(cb.isEnabled())
self.assertTrue(all(bar.hidden
for bar in widget.bar_items))
self.assertTrue(all(curve.opts["brush"] is not None
for curve in widget.curve_items))

self._set_check(cb, False)
self.assertTrue(all(not bar.hidden
for bar in widget.bar_items))
self.assertTrue(all(curve.opts["brush"].style() == Qt.NoBrush
for curve in widget.curve_items))

self._set_check(cb, True)
self.assertTrue(all(bar.hidden
for bar in widget.bar_items))
self.assertTrue(all(curve.opts["brush"] is not None
for curve in widget.curve_items))

def test_report(self):
"""Report doesn't crash"""
widget = self.widget
Expand Down