Skip to content

Commit

Permalink
Merge pull request #5141 from janezd/projection-allow-transparent-subset
Browse files Browse the repository at this point in the history
[ENH] Projections: Allow transparent subset
  • Loading branch information
BlazZupan authored Jan 21, 2021
2 parents 9c593cc + e5e3366 commit 3d6b923
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 15 deletions.
26 changes: 15 additions & 11 deletions Orange/widgets/visualize/owscatterplotgraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ def get_size_data(self):

COLOR_NOT_SUBSET = (128, 128, 128, 0)
COLOR_SUBSET = (128, 128, 128, 255)
COLOR_DEFAULT = (128, 128, 128, 0)
COLOR_DEFAULT = (128, 128, 128, 255)

MAX_VISIBLE_LABELS = 500

Expand Down Expand Up @@ -1048,15 +1048,19 @@ def _get_same_colors(self, subset):
"""
color = self.plot_widget.palette().color(OWPalette.Data)
pen = [_make_pen(color, 1.5)] * self.n_shown # use a single QPen instance

# Prepare all brushes; we use the first two or the last
brushes = []
for c in (self.COLOR_SUBSET, self.COLOR_NOT_SUBSET, self.COLOR_DEFAULT):
color = QColor(*c)
if color.alpha():
color.setAlpha(self.alpha_value)
brushes.append(QBrush(color))

if subset is not None:
brush = np.where(
subset,
*(QBrush(QColor(*col))
for col in (self.COLOR_SUBSET, self.COLOR_NOT_SUBSET)))
brush = np.where(subset, *brushes[:2])
else:
color = QColor(*self.COLOR_DEFAULT)
color.setAlpha(self.alpha_value)
brush = [QBrush(color)] * self.n_shown # use a single QBrush instance
brush = brushes[-1:] * self.n_shown # use a single QBrush instance
return pen, brush

def _get_continuous_colors(self, c_data, subset):
Expand Down Expand Up @@ -1102,7 +1106,7 @@ def create_brush(col):

if subset is not None:
brush[:, 3] = 0
brush[subset, 3] = 255
brush[subset, 3] = self.alpha_value

cached_brushes = {}
brush = np.array([reuse(cached_brushes, create_brush, *col)
Expand Down Expand Up @@ -1133,7 +1137,7 @@ def _get_discrete_colors(self, c_data, subset):
pens = np.array(
[_make_pen(col.darker(self.DarkerValue), 1.5) for col in colors])
pen = pens[c_data]
if subset is None and self.alpha_value < 255:
if self.alpha_value < 255:
for col in colors:
col.setAlpha(self.alpha_value)
brushes = np.array([QBrush(col) for col in colors])
Expand Down Expand Up @@ -1504,7 +1508,7 @@ def _update_colored_legend(self, legend, labels, symbols):
for color, label, symbol in zip(colors, labels, symbols):
color = QColor(*color)
pen = _make_pen(color.darker(self.DarkerValue), 1.5)
color.setAlpha(255 if self.subset_is_shown else self.alpha_value)
color.setAlpha(self.alpha_value)
brush = QBrush(color)
legend.addItem(
SymbolItemSample(pen=pen, brush=brush, size=10, symbol=symbol),
Expand Down
15 changes: 15 additions & 0 deletions Orange/widgets/visualize/tests/test_owscatterplot.py
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,21 @@ def test_subset_data(self):
self.send_signal(w.Inputs.data_subset, data[::30])
self.assertEqual(len(w.subset_indices), 5)

def test_opacity_warning(self):
data = Table("iris")
w = self.widget
self.send_signal(w.Inputs.data, data)
w.graph.controls.alpha_value.setSliderPosition(10)
self.assertFalse(w.Warning.transparent_subset.is_shown())
self.send_signal(w.Inputs.data_subset, data[::30])
self.assertTrue(w.Warning.transparent_subset.is_shown())
w.graph.controls.alpha_value.setSliderPosition(200)
self.assertFalse(w.Warning.transparent_subset.is_shown())
w.graph.controls.alpha_value.setSliderPosition(10)
self.assertTrue(w.Warning.transparent_subset.is_shown())
self.send_signal(w.Inputs.data_subset, None)
self.assertFalse(w.Warning.transparent_subset.is_shown())

def test_metas_zero_column(self):
"""
Prevent crash when metas column is zero.
Expand Down
6 changes: 3 additions & 3 deletions Orange/widgets/visualize/tests/test_owscatterplotbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -614,9 +614,9 @@ def run_tests():
self.assertEqual(brushes[0].color().alpha(), 0)
self.assertEqual(brushes[1].color().alpha(), 0)
self.assertEqual(brushes[4].color().alpha(), 0)
self.assertEqual(brushes[5].color().alpha(), 255)
self.assertEqual(brushes[6].color().alpha(), 255)
self.assertEqual(brushes[7].color().alpha(), 255)
self.assertEqual(brushes[5].color().alpha(), 123)
self.assertEqual(brushes[6].color().alpha(), 123)
self.assertEqual(brushes[7].color().alpha(), 123)

graph = self.graph

Expand Down
9 changes: 8 additions & 1 deletion Orange/widgets/visualize/utils/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ def can_draw_density(self):

def colors_changed(self):
self.graph.update_colors()
self._update_opacity_warning()
self.cb_class_density.setEnabled(self.can_draw_density())

# Labels
Expand Down Expand Up @@ -378,6 +379,8 @@ class Warning(OWProjectionWidgetBase.Warning):
"input data")
subset_independent = Msg(
"No subset data instances appear in input data")
transparent_subset = Msg(
"Increase opacity if subset is difficult to see")

settingsHandler = DomainContextHandler()
selection = Setting(None, schema_only=True)
Expand Down Expand Up @@ -473,7 +476,6 @@ def enable_controls(self):
@check_sql_input
def set_subset_data(self, subset):
self.subset_data = subset
self.controls.graph.alpha_value.setEnabled(subset is None)

def handleNewSignals(self):
self._handle_subset_data()
Expand All @@ -482,6 +484,7 @@ def handleNewSignals(self):
self.setup_plot()
else:
self.graph.update_point_props()
self._update_opacity_warning()
self.unconditional_commit()

def _handle_subset_data(self):
Expand All @@ -497,6 +500,10 @@ def _handle_subset_data(self):
elif self.subset_indices - ids:
self.Warning.subset_not_subset()

def _update_opacity_warning(self):
self.Warning.transparent_subset(
shown=self.subset_indices and self.graph.alpha_value < 128)

def set_input_summary(self, data):
summary = len(data) if data else self.info.NoInput
detail = format_summary_details(data) if data else ""
Expand Down

0 comments on commit 3d6b923

Please sign in to comment.