Skip to content

Commit 8d59096

Browse files
committed
Add labels to combo when data comes from matrix
1 parent 4d6c13c commit 8d59096

File tree

2 files changed

+126
-7
lines changed

2 files changed

+126
-7
lines changed

Orange/widgets/unsupervised/owmds.py

Lines changed: 11 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,13 +267,18 @@ 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
272274
self.graph.attr_shape = None
273275
self.graph.attr_size = None
274276
self.graph.attr_label = None
277+
if domain is not None:
278+
for var in domain.metas:
279+
if var.is_string:
280+
self.graph.attr_label = var
281+
break
275282

276283
def prepare_data(self):
277284
pass
@@ -326,10 +333,7 @@ def set_disimilarity(self, matrix):
326333
self.Error.matrix_too_small.clear()
327334

328335
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
336+
self.matrix_data = matrix.row_items if matrix is not None else None
333337
self._invalidated = True
334338

335339
@Inputs.data_subset

Orange/widgets/unsupervised/tests/test_owmds.py

Lines changed: 115 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,106 @@ 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.assertIs(w.graph.attr_label, row_items.domain["label"])
200+
201+
# Distances matrix without labels
202+
self.towns.row_items = None
203+
self.send_signal(w.Inputs.distances, self.towns)
204+
self.assertIsNone(w.graph.attr_label)
205+
206+
# No data
207+
self.send_signal(w.Inputs.distances, None)
208+
self.assertIsNone(w.graph.attr_label)
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.assertIs(w.graph.attr_label, row_items.domain["label"])
214+
215+
# Followed by no data
216+
self.towns.row_items = None
217+
self.send_signal(w.Inputs.distances, self.towns)
218+
self.assertIsNone(w.graph.attr_label)
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+
self.assertIs(w.graph.attr_label, data.domain.metas[0])
233+
234+
def test_attr_label_from_data(self):
235+
w = self.widget
236+
# Don't run the MDS optimization to save time and to prevent the
237+
# widget be in a blocking state when trying to send the next signal
238+
w.start = Mock()
239+
240+
# Data with string attribute: all attributes present, string selected
241+
data = Table("zoo")
242+
dist = Euclidean(data)
243+
self.send_signal(w.Inputs.distances, dist)
244+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
245+
< set(w.label_model))
246+
self.assertIs(w.graph.attr_label, data.domain.metas[0])
247+
248+
# Data without string attribute: all attributes present, none selected
249+
data = Table("iris")
250+
dist = Euclidean(data)
251+
self.send_signal(w.Inputs.distances, dist)
252+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
253+
< set(w.label_model))
254+
self.assertIsNone(w.graph.attr_label)
255+
256+
def test_attr_label_matrix_and_data(self):
257+
w = self.widget
258+
# Don't run the MDS optimization to save time and to prevent the
259+
# widget be in a blocking state when trying to send the next signal
260+
w.start = Mock()
261+
262+
# Data and matrix
263+
data = Table("zoo")
264+
dist = Euclidean(data)
265+
self.send_signal(w.Inputs.distances, dist)
266+
self.send_signal(w.Inputs.data, data)
267+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
268+
< set(w.label_model))
269+
self.assertIs(w.graph.attr_label, data.domain.metas[0])
270+
271+
# Has data, but receives a signal without data: has to keep the label
272+
dist.row_items = None
273+
self.send_signal(w.Inputs.distances, dist)
274+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
275+
< set(w.label_model))
276+
self.assertIs(w.graph.attr_label, data.domain.metas[0])
277+
278+
# Has matrix without data, and loses the data: remove the label
279+
self.send_signal(w.Inputs.data, None)
280+
self.assertEqual(len(w.label_model), 1) # just None
281+
self.assertIsNone(w.graph.attr_label)
282+
283+
# Has matrix without data, receives data: add attrs to combo, select
284+
self.send_signal(w.Inputs.data, data)
285+
self.assertTrue(set(chain(data.domain.variables, data.domain.metas))
286+
< set(w.label_model))
287+
self.assertIs(w.graph.attr_label, data.domain.metas[0])
288+
289+
290+
if __name__ == "__main__":
291+
unittest.main()

0 commit comments

Comments
 (0)