From afcff08c119bdf574d2b87b935ce781024e400fa Mon Sep 17 00:00:00 2001
From: PrimozGodec
Date: Mon, 24 Apr 2023 11:43:13 +0200
Subject: [PATCH] SOM - Store selection Settings in list instead of np.ndarray
---
Orange/widgets/unsupervised/owsom.py | 30 +++++++++++++------
.../widgets/unsupervised/tests/test_owsom.py | 5 ++++
2 files changed, 26 insertions(+), 9 deletions(-)
diff --git a/Orange/widgets/unsupervised/owsom.py b/Orange/widgets/unsupervised/owsom.py
index ac58129a106..a6423734d16 100644
--- a/Orange/widgets/unsupervised/owsom.py
+++ b/Orange/widgets/unsupervised/owsom.py
@@ -422,15 +422,18 @@ def on_selection_change(self, selection, action=SomView.SelectionSet):
return
if self.selection is None:
self.selection = np.zeros(self.grid_cells.T.shape, dtype=np.int16)
+
+ selection_np = np.array(self.selection)
if action == SomView.SelectionSet:
- self.selection[:] = 0
- self.selection[selection] = 1
+ selection_np[:] = 0
+ selection_np[selection] = 1
elif action == SomView.SelectionAddToGroup:
- self.selection[selection] = max(1, np.max(self.selection))
+ selection_np[selection] = max(1, np.max(selection_np))
elif action == SomView.SelectionNewGroup:
- self.selection[selection] = 1 + np.max(self.selection)
+ selection_np[selection] = 1 + np.max(selection_np)
elif action & SomView.SelectionRemove:
- self.selection[selection] = 0
+ selection_np[selection] = 0
+ self.selection = selection_np.tolist()
self.redraw_selection()
self.update_output()
@@ -445,6 +448,7 @@ def on_selection_move(self, event: QKeyEvent):
x, y = np.nonzero(self.selection)
if len(x) > 1:
return
+ x, y = x[0], y[0]
if event.key() == Qt.Key_Up and y > 0:
y -= 1
if event.key() == Qt.Key_Down and y < self.size_y - 1:
@@ -455,11 +459,11 @@ def on_selection_move(self, event: QKeyEvent):
x += 1
x -= self.hexagonal and x == self.size_x - 1 and y % 2
- if self.selection is not None and self.selection[x, y]:
+ if self.selection is not None and self.selection[x][y]:
return
selection = np.zeros(self.grid_cells.shape, dtype=bool)
selection[x, y] = True
- self.on_selection_change(selection)
+ self.on_selection_change(selection.tolist())
def on_selection_mark_change(self, marks):
self.redraw_selection(marks=marks)
@@ -484,7 +488,7 @@ def redraw_selection(self, marks=None):
for x in range(self.size_x - (y % 2) * self.hexagonal):
cell = self.grid_cells[y, x]
marked = marks is not None and marks[x, y]
- sel_group = self.selection is not None and self.selection[x, y]
+ sel_group = self.selection is not None and self.selection[x][y]
if marked:
cell.setBrush(mark_brush)
cell.setPen(mark_pen)
@@ -821,7 +825,7 @@ def update_output(self):
for y in range(self.size_y):
for x in range(self.size_x):
rows = self.get_member_indices(x, y)
- indices[rows] = self.selection[x, y]
+ indices[rows] = self.selection[x][y]
if np.any(indices):
sel_data = create_groups_table(self.data, indices, False, "Group")
@@ -930,6 +934,14 @@ def send_report(self):
self.report_caption(
f"Self-organizing map colored by '{self.attr_color.name}'")
+ @classmethod
+ def migrate_settings(cls, settings, _):
+ # previously selection was saved as np.ndarray which is not supported
+ # by widget-base, change selection to list
+ selection = settings.get('selection')
+ if selection is not None and isinstance(selection, np.ndarray):
+ settings['selection'] = selection.tolist()
+
def _draw_hexagon():
path = QPainterPath()
diff --git a/Orange/widgets/unsupervised/tests/test_owsom.py b/Orange/widgets/unsupervised/tests/test_owsom.py
index 8cbab3a6a0b..71e618ba822 100644
--- a/Orange/widgets/unsupervised/tests/test_owsom.py
+++ b/Orange/widgets/unsupervised/tests/test_owsom.py
@@ -543,24 +543,29 @@ def selm(*cells):
m = selm((0, 0)).astype(int)
widget.on_selection_change(selm((0, 0)))
np.testing.assert_equal(widget.selection, m)
+ self.assertIsInstance(widget.selection, list)
widget.redraw_selection.assert_called_once()
widget.update_output.assert_called_once()
m = selm((0, 1)).astype(int)
widget.on_selection_change(selm((0, 1)))
np.testing.assert_equal(widget.selection, m)
+ self.assertIsInstance(widget.selection, list)
m[0, 0] = 1
widget.on_selection_change(selm((0, 0)), SomView.SelectionAddToGroup)
np.testing.assert_equal(widget.selection, m)
+ self.assertIsInstance(widget.selection, list)
m[0, 0] = 0
widget.on_selection_change(selm((0, 0)), SomView.SelectionRemove)
np.testing.assert_equal(widget.selection, m)
+ self.assertIsInstance(widget.selection, list)
m[0, 0] = 2
widget.on_selection_change(selm((0, 0)), SomView.SelectionNewGroup)
np.testing.assert_equal(widget.selection, m)
+ self.assertIsInstance(widget.selection, list)
@_patch_recompute_som
def test_on_selection_change_on_empty(self):