Skip to content

Commit a6d4f7f

Browse files
authored
Merge pull request #2866 from janezd/fix-mds-label
[FIX] Add labels to combo when data comes from distance matrix
2 parents c841a1e + 1a8901e commit a6d4f7f

File tree

2 files changed

+106
-7
lines changed

2 files changed

+106
-7
lines changed

Orange/widgets/unsupervised/owmds.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,10 @@ def __init__(self):
216216
g = self.graph.gui
217217
box = g.point_properties_box(self.controlArea)
218218
self.models = g.points_models
219-
self.models[2].order = \
220-
self.models[2].order[:1] + ("Stress", ) + self.models[2].order[1:]
219+
self.size_model = self.models[2]
220+
self.label_model = self.models[3]
221+
self.size_model.order = \
222+
self.size_model.order[:1] + ("Stress", ) + self.models[2].order[1:]
221223

222224
gui.hSlider(box, self, "connected_pairs", label="Show similar pairs:", minValue=0,
223225
maxValue=20, createLabel=False, callback=self._on_connected_changed)
@@ -265,7 +267,7 @@ def update_regression_line(self):
265267
self.update_graph(reset_view=False)
266268

267269
def init_attr_values(self):
268-
domain = self.data and len(self.data) and self.data.domain or None
270+
domain = self.data.domain if self.data and len(self.data) else None
269271
for model in self.models:
270272
model.set_domain(domain)
271273
self.graph.attr_color = self.data.domain.class_var if domain else None
@@ -326,10 +328,7 @@ def set_disimilarity(self, matrix):
326328
self.Error.matrix_too_small.clear()
327329

328330
self.matrix = matrix
329-
if matrix is not None and matrix.row_items:
330-
self.matrix_data = matrix.row_items
331-
if matrix is None:
332-
self.matrix_data = None
331+
self.matrix_data = matrix.row_items if matrix is not None else None
333332
self._invalidated = True
334333

335334
@Inputs.data_subset

Orange/widgets/unsupervised/tests/test_owmds.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
11
# Test methods with long descriptive names can omit docstrings
22
# pylint: disable=missing-docstring
3+
import os
4+
from itertools import chain
5+
import unittest
36
from unittest.mock import patch, Mock
47

58
import numpy as np
69
from AnyQt.QtCore import QRectF, QPointF
710

11+
from Orange.data import Table
12+
from Orange.misc import DistMatrix
813
from Orange.distance import Euclidean
914
from Orange.widgets.settings import Context
1015
from Orange.widgets.unsupervised.owmds import OWMDS
@@ -22,6 +27,10 @@ def setUpClass(cls):
2227
cls.signal_data = Euclidean(cls.data)
2328
cls.same_input_output_domain = False
2429

30+
my_dir = os.path.dirname(__file__)
31+
datasets_dir = os.path.join(my_dir, '..', '..', '..', 'datasets')
32+
cls.datasets_dir = os.path.realpath(datasets_dir)
33+
2534
def setUp(self):
2635
self.widget = self.create_widget(
2736
OWMDS, stored_settings={
@@ -30,6 +39,9 @@ def setUp(self):
3039
"initialization": OWMDS.PCA,
3140
}
3241
) # type: OWMDS
42+
self.towns = DistMatrix.from_file(
43+
os.path.join(self.datasets_dir, "slovenian-towns.dst"))
44+
3345

3446
def tearDown(self):
3547
self.widget.onDeleteWidget()
@@ -174,3 +186,91 @@ def test_migrate_settings_from_version_1(self):
174186
(g.jitter_size, 0.5)):
175187
self.assertTrue(a, value)
176188
self.assertFalse(w.auto_commit)
189+
190+
def test_attr_label_from_dist_matrix_from_file(self):
191+
w = self.widget
192+
# Don't run the MDS optimization to save time and to prevent the
193+
# widget be in a blocking state when trying to send the next signal
194+
w.start = Mock()
195+
row_items = self.towns.row_items
196+
197+
# Distance matrix with labels
198+
self.send_signal(w.Inputs.distances, self.towns)
199+
self.assertIn(row_items.domain["label"], w.label_model)
200+
201+
# Distances matrix without labels
202+
self.towns.row_items = None
203+
self.send_signal(w.Inputs.distances, self.towns)
204+
self.assertEqual(list(w.label_model), [None])
205+
206+
# No data
207+
self.send_signal(w.Inputs.distances, None)
208+
self.assertEqual(list(w.label_model), [None])
209+
210+
# Distances matrix with labels again
211+
self.towns.row_items = row_items
212+
self.send_signal(w.Inputs.distances, self.towns)
213+
self.assertIn(row_items.domain["label"], w.label_model)
214+
215+
# Followed by no data
216+
self.towns.row_items = None
217+
self.send_signal(w.Inputs.distances, self.towns)
218+
self.assertEqual(list(w.label_model), [None])
219+
220+
def test_attr_label_from_dist_matrix_from_data(self):
221+
w = self.widget
222+
# Don't run the MDS optimization to save time and to prevent the
223+
# widget be in a blocking state when trying to send the next signal
224+
w.start = Mock()
225+
226+
data = Table("zoo")
227+
dist = Euclidean(data)
228+
self.send_signal(w.Inputs.distances, dist)
229+
self.send_signal(w.Inputs.data, data)
230+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
231+
< set(w.label_model))
232+
233+
def test_attr_label_from_data(self):
234+
w = self.widget
235+
# Don't run the MDS optimization to save time and to prevent the
236+
# widget be in a blocking state when trying to send the next signal
237+
w.start = Mock()
238+
239+
data = Table("zoo")
240+
dist = Euclidean(data)
241+
self.send_signal(w.Inputs.distances, dist)
242+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
243+
< set(w.label_model))
244+
245+
def test_attr_label_matrix_and_data(self):
246+
w = self.widget
247+
# Don't run the MDS optimization to save time and to prevent the
248+
# widget be in a blocking state when trying to send the next signal
249+
w.start = Mock()
250+
251+
# Data and matrix
252+
data = Table("zoo")
253+
dist = Euclidean(data)
254+
self.send_signal(w.Inputs.distances, dist)
255+
self.send_signal(w.Inputs.data, data)
256+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
257+
< set(w.label_model))
258+
259+
# Has data, but receives a signal without data: has to keep the label
260+
dist.row_items = None
261+
self.send_signal(w.Inputs.distances, dist)
262+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
263+
< set(w.label_model))
264+
265+
# Has matrix without data, and loses the data: remove the label
266+
self.send_signal(w.Inputs.data, None)
267+
self.assertEqual(list(w.label_model), [None])
268+
269+
# Has matrix without data, receives data: add attrs to combo, select
270+
self.send_signal(w.Inputs.data, data)
271+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
272+
< set(w.label_model))
273+
274+
275+
if __name__ == "__main__":
276+
unittest.main()

0 commit comments

Comments
 (0)