Skip to content

Commit

Permalink
Distributions: Fix selection output
Browse files Browse the repository at this point in the history
  • Loading branch information
janezd committed Sep 17, 2023
1 parent f502668 commit 1856db3
Showing 1 changed file with 37 additions and 20 deletions.
57 changes: 37 additions & 20 deletions Orange/widgets/visualize/owdistributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,16 @@ def labelString(self):
return f"<span style='{style}'>{self.labelText}</span>"


class IdemOrder:
@staticmethod
def __getitem__(x):
return x

@staticmethod
def index(x):
return x


class OWDistributions(OWWidget):
name = "Distributions"
description = "Display value distributions of a data feature in a graph."
Expand Down Expand Up @@ -311,6 +321,7 @@ def __init__(self):
self.curve_items = []
self.curve_descriptions = None
self.binnings = []
self.order = IdemOrder()

self.last_click_idx = None
self.drag_operation = self.DragNone
Expand Down Expand Up @@ -571,6 +582,8 @@ def _clear_plot(self):
self.plot_pdf.clear()
self.plot_mark.clear()
self.bar_items = []
self.order = IdemOrder()
self.last_click_idx = None
self.curve_items = []
self._legend.clear()
self._legend.hide()
Expand Down Expand Up @@ -625,6 +638,7 @@ def _disc_plot(self):
dist = np.array(dist) # Distribution misbehaves in further operations
if self.sort_by_freq:
order = np.argsort(dist)[::-1]
self.order = list(order)
else:
order = np.arange(len(dist))

Expand All @@ -647,6 +661,7 @@ def _disc_split_plot(self):
conts = np.array(conts) # Contingency misbehaves in further operations
if self.sort_by_freq:
order = np.argsort(conts.sum(axis=1))[::-1]
self.order = list(order)
else:
order = np.arange(len(conts))

Expand Down Expand Up @@ -933,23 +948,23 @@ def str_int(self, x0, x1, first, last, unique=False):
# Selection

def _on_item_clicked(self, item, modifiers, drag):
def add_or_remove(idx, add):
def add_or_remove(value_idx, add):
self.drag_operation = [self.DragRemove, self.DragAdd][add]
if add:
self.selection.add(idx)
self.selection.add(value_idx)
else:
if idx in self.selection:
if value_idx in self.selection:
# This can be False when removing with dragging and the
# mouse crosses unselected items
self.selection.remove(idx)
self.selection.remove(value_idx)

def add_range(add):
if self.last_click_idx is None:
add = True
idx_range = {idx}
idx_range = {self.order[idx]}
else:
from_idx, to_idx = sorted((self.last_click_idx, idx))
idx_range = set(range(from_idx, to_idx + 1))
idx_range = {self.order[idx] for idx in range(from_idx, to_idx + 1)}
self.drag_operation = [self.DragRemove, self.DragAdd][add]
if add:
self.selection |= idx_range
Expand All @@ -966,19 +981,20 @@ def add_range(add):
# Dragging has to add a range, otherwise fast dragging skips bars
add_range(self.drag_operation == self.DragAdd)
else:
value_idx = self.order[idx]
if modifiers & Qt.ShiftModifier:
add_range(self.drag_operation == self.DragAdd)
elif modifiers & Qt.ControlModifier:
add_or_remove(idx, add=idx not in self.selection)
add_or_remove(value_idx, add=value_idx not in self.selection)
else:
if self.selection == {idx}:
# Clicking on a single selected bar deselects it,
if self.selection == {value_idx}:
# Clicking on a single selected bar deselects it,
# but dragging from here will select
add_or_remove(idx, add=False)
add_or_remove(value_idx, add=False)
self.drag_operation = self.DragAdd
else:
self.selection.clear()
add_or_remove(idx, add=True)
add_or_remove(value_idx, add=True)
self.last_click_idx = idx

self.show_selection()
Expand Down Expand Up @@ -1047,7 +1063,8 @@ def _padding(i):

def grouped_selection(self):
return [[g[1] for g in group]
for _, group in groupby(enumerate(sorted(self.selection)),
for _, group in groupby(enumerate(sorted(map(self.order.index,
self.selection))),
key=lambda x: x[1] - x[0])]

def keyPressEvent(self, e):
Expand All @@ -1056,7 +1073,7 @@ def on_nothing_selected():
self.last_click_idx = len(self.bar_items) - 1
else:
self.last_click_idx = 0
self.selection.add(self.last_click_idx)
self.selection.add(self.order[self.last_click_idx])

def on_key_left():
if e.modifiers() & Qt.ShiftModifier:
Expand All @@ -1065,26 +1082,26 @@ def on_key_left():
self.last_click_idx = last - 1
elif first:
self.key_operation = Qt.Key_Left
self.selection.add(first - 1)
self.selection.add(self.order[first - 1])
self.last_click_idx = first - 1
else:
self.selection.clear()
self.last_click_idx = max(first - 1, 0)
self.selection.add(self.last_click_idx)
self.selection.add(self.order[self.last_click_idx])

def on_key_right():
if e.modifiers() & Qt.ShiftModifier:
if self.key_operation == Qt.Key_Left and first != last:
self.selection.remove(first)
self.selection.remove(self.order[first])
self.last_click_idx = first + 1
elif not self._is_last_bar(last):
self.key_operation = Qt.Key_Right
self.selection.add(last + 1)
self.selection.add(self.order[last + 1])
self.last_click_idx = last + 1
else:
self.selection.clear()
self.last_click_idx = min(last + 1, len(self.bar_items) - 1)
self.selection.add(self.last_click_idx)
self.selection.add(self.order[self.last_click_idx])

if not self.is_valid or not self.bar_items \
or e.key() not in (Qt.Key_Left, Qt.Key_Right):
Expand Down Expand Up @@ -1143,8 +1160,8 @@ def apply(self):
def _get_output_indices_disc(self):
group_indices = np.zeros(len(self.data), dtype=np.int32)
col = self.data.get_column(self.var)
for group_idx, val_idx in enumerate(self.selection, start=1):
group_indices[col == val_idx] = group_idx
for group_idx, idx in enumerate(self.selection, start=1):
group_indices[col == self.order[idx]] = group_idx
values = [self.var.values[i] for i in self.selection]
return group_indices, values

Expand Down

0 comments on commit 1856db3

Please sign in to comment.