From 1856db3d87054bec1b086d794c0038087b1294e2 Mon Sep 17 00:00:00 2001 From: janezd Date: Sun, 17 Sep 2023 19:08:28 +0200 Subject: [PATCH] Distributions: Fix selection output --- Orange/widgets/visualize/owdistributions.py | 57 +++++++++++++-------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/Orange/widgets/visualize/owdistributions.py b/Orange/widgets/visualize/owdistributions.py index bd6f656c443..ed9e74e6a03 100644 --- a/Orange/widgets/visualize/owdistributions.py +++ b/Orange/widgets/visualize/owdistributions.py @@ -246,6 +246,16 @@ def labelString(self): return f"{self.labelText}" +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." @@ -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 @@ -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() @@ -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)) @@ -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)) @@ -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 @@ -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() @@ -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): @@ -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: @@ -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): @@ -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