From 0d6807386a222d9fe07184cd946fc8ba6f4b326f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Primo=C5=BE=20Godec?=
Date: Mon, 1 Jul 2019 08:28:43 +0200
Subject: [PATCH] OWDBSCAN: remove widget from Prototypes
---
.../prototypes/widgets/icons/DBSCAN.svg | 53 ------
orangecontrib/prototypes/widgets/owdbscan.py | 153 ------------------
.../prototypes/widgets/tests/test_owdbscan.py | 119 --------------
3 files changed, 325 deletions(-)
delete mode 100644 orangecontrib/prototypes/widgets/icons/DBSCAN.svg
delete mode 100644 orangecontrib/prototypes/widgets/owdbscan.py
delete mode 100644 orangecontrib/prototypes/widgets/tests/test_owdbscan.py
diff --git a/orangecontrib/prototypes/widgets/icons/DBSCAN.svg b/orangecontrib/prototypes/widgets/icons/DBSCAN.svg
deleted file mode 100644
index 6efec89a4..000000000
--- a/orangecontrib/prototypes/widgets/icons/DBSCAN.svg
+++ /dev/null
@@ -1,53 +0,0 @@
-
-
-
diff --git a/orangecontrib/prototypes/widgets/owdbscan.py b/orangecontrib/prototypes/widgets/owdbscan.py
deleted file mode 100644
index 2b1d8a55c..000000000
--- a/orangecontrib/prototypes/widgets/owdbscan.py
+++ /dev/null
@@ -1,153 +0,0 @@
-import numpy as np
-
-from AnyQt.QtWidgets import QLayout
-from AnyQt.QtCore import Qt
-
-from Orange.widgets import widget, gui
-from Orange.widgets.settings import Setting
-from Orange.data import Table, Domain, DiscreteVariable
-from Orange.clustering import DBSCAN
-from Orange import distance
-from Orange.widgets.utils.annotated_data import ANNOTATED_DATA_SIGNAL_NAME
-from Orange.widgets.utils.signals import Input, Output
-from Orange.widgets.widget import Msg
-
-
-class OWDBSCAN(widget.OWWidget):
- name = "DBSCAN"
- description = "Density-based spatial clustering."
- icon = "icons/DBSCAN.svg"
- priority = 2150
-
- class Inputs:
- data = Input("Data", Table)
-
- class Outputs:
- annotated_data = Output(ANNOTATED_DATA_SIGNAL_NAME, Table)
-
- class Error(widget.OWWidget.Error):
- not_enough_instances = Msg("Not enough unique data instances. "
- "At least two are required.")
-
- METRICS = [
- ("Euclidean", "euclidean"),
- ("Manhattan", "manhattan"),
- ("Cosine", distance.Cosine),
- ("Jaccard", distance.Jaccard),
- # ("Spearman", distance.SpearmanR),
- # ("Spearman absolute", distance.SpearmanRAbsolute),
- # ("Pearson", distance.PearsonR),
- # ("Pearson absolute", distance.PearsonRAbsolute),
- ]
-
- min_samples = Setting(5)
- eps = Setting(0.5)
- metric_idx = Setting(0)
- auto_commit = Setting(True)
-
- want_main_area = False
-
- def __init__(self):
- super().__init__()
-
- self.data = None
- self.db = None
- self.model = None
-
- box = gui.widgetBox(self.controlArea, "Parameters")
- gui.spin(box, self, "min_samples", 1, 100, 1, callback=self._invalidate,
- label="Core point neighbors")
- gui.doubleSpin(box, self, "eps", 0.1, 10, 0.01,
- callback=self._invalidate,
- label="Neighborhood distance")
-
- box = gui.widgetBox(self.controlArea, self.tr("Distance Metric"))
- gui.comboBox(box, self, "metric_idx",
- items=list(zip(*self.METRICS))[0],
- callback=self._invalidate)
-
- gui.auto_commit(self.controlArea, self, "auto_commit", "Apply",
- orientation=Qt.Horizontal)
- gui.rubber(self.controlArea)
-
- self.controlArea.setMinimumWidth(self.controlArea.sizeHint().width())
- self.layout().setSizeConstraint(QLayout.SetFixedSize)
-
- def adjustSize(self):
- self.ensurePolished()
- self.resize(self.controlArea.sizeHint())
-
- def check_data_size(self):
- if len(self.data) < 2:
- self.Error.not_enough_instances()
- return False
- return True
-
- def commit(self):
- self.cluster()
-
- def cluster(self):
- if not self.check_data_size():
- return
- self.model = DBSCAN(
- eps=self.eps,
- min_samples=self.min_samples,
- metric=self.METRICS[self.metric_idx][1]
- ).get_model(self.data)
- self.send_data()
-
- def send_data(self):
- model = self.model
-
- clusters = [c if c >= 0 else np.nan for c in model.labels]
- k = len(set(clusters) - {np.nan})
- clusters = np.array(clusters).reshape(len(self.data), 1)
- core_samples = set(model.projector.core_sample_indices_)
- in_core = np.array([1 if (i in core_samples) else 0
- for i in range(len(self.data))])
- in_core = in_core.reshape(len(self.data), 1)
-
- clust_var = DiscreteVariable(
- "Cluster", values=["C%d" % (x + 1) for x in range(k)])
- in_core_var = DiscreteVariable("DBSCAN Core", values=["0", "1"])
-
- domain = self.data.domain
- attributes, classes = domain.attributes, domain.class_vars
- meta_attrs = domain.metas
- x, y, metas = self.data.X, self.data.Y, self.data.metas
-
- meta_attrs += (clust_var, )
- metas = np.hstack((metas, clusters))
- meta_attrs += (in_core_var, )
- metas = np.hstack((metas, in_core))
-
- domain = Domain(attributes, classes, meta_attrs)
- new_table = Table(domain, x, y, metas, self.data.W)
-
- self.Outputs.annotated_data.send(new_table)
-
- @Inputs.data
- def set_data(self, data):
- self.data = data
- if self.data is None:
- self.Outputs.annotated_data.send(None)
- self.Error.clear()
- if self.data is None:
- return
- self.unconditional_commit()
-
- def _invalidate(self):
- self.commit()
-
-
-if __name__ == "__main__":
- import sys
- from AnyQt.QtWidgets import QApplication
-
- a = QApplication(sys.argv)
- ow = OWDBSCAN()
- d = Table("iris.tab")
- ow.set_data(d)
- ow.show()
- a.exec()
- ow.saveSettings()
diff --git a/orangecontrib/prototypes/widgets/tests/test_owdbscan.py b/orangecontrib/prototypes/widgets/tests/test_owdbscan.py
deleted file mode 100644
index f70d65028..000000000
--- a/orangecontrib/prototypes/widgets/tests/test_owdbscan.py
+++ /dev/null
@@ -1,119 +0,0 @@
-import numpy as np
-from Orange.data import Table
-from Orange.widgets.tests.base import WidgetTest
-from Orange.widgets.tests.utils import simulate
-from scipy.sparse import csr_matrix
-
-from orangecontrib.prototypes.widgets.owdbscan import OWDBSCAN
-
-
-class TestOWCSVFileImport(WidgetTest):
- def setUp(self):
- self.widget = self.create_widget(OWDBSCAN)
- self.iris = Table("iris")
-
- def tearDown(self):
- self.widgets.remove(self.widget)
- self.widget.onDeleteWidget()
- self.widget = None
-
- def test_cluster(self):
- w = self.widget
-
- self.send_signal(w.Inputs.data, self.iris)
-
- output = self.get_output(w.Outputs.annotated_data)
- self.assertIsNotNone(output)
- self.assertEqual(len(self.iris), len(output))
- self.assertTupleEqual(self.iris.X.shape, output.X.shape)
- self.assertTupleEqual(self.iris.Y.shape, output.Y.shape)
- self.assertEqual(2, output.metas.shape[1])
-
- self.assertEqual("Cluster", str(output.domain.metas[0]))
- self.assertEqual("DBSCAN Core", str(output.domain.metas[1]))
-
- def test_bad_input(self):
- w = self.widget
-
- self.send_signal(w.Inputs.data, self.iris[:1])
- self.assertTrue(w.Error.not_enough_instances.is_shown())
-
- self.send_signal(w.Inputs.data, self.iris[:2])
- self.assertFalse(w.Error.not_enough_instances.is_shown())
-
- self.send_signal(w.Inputs.data, self.iris)
- self.assertFalse(w.Error.not_enough_instances.is_shown())
-
- def test_data_none(self):
- w = self.widget
-
- self.send_signal(w.Inputs.data, self.iris[:5])
- self.send_signal(w.Inputs.data, None)
-
- output = self.get_output(w.Outputs.annotated_data)
- self.assertIsNone(output)
-
- def test_change_eps(self):
- w = self.widget
-
- self.send_signal(w.Inputs.data, self.iris)
-
- # change parameters
- self.widget.controls.eps.valueChanged.emit(0.5)
- output1 = self.get_output(w.Outputs.annotated_data)
- self.widget.controls.eps.valueChanged.emit(1)
- output2 = self.get_output(w.Outputs.annotated_data)
-
- # on this data higher eps has greater sum of clusters - less nan
- # values
- self.assertGreater(np.nansum(output2.metas[:, 0]),
- np.nansum(output1.metas[:, 0]))
-
- def test_change_min_samples(self):
- w = self.widget
-
- self.send_signal(w.Inputs.data, self.iris)
-
- # change parameters
- self.widget.controls.min_samples.valueChanged.emit(5)
- output1 = self.get_output(w.Outputs.annotated_data)
- self.widget.controls.min_samples.valueChanged.emit(1)
- output2 = self.get_output(w.Outputs.annotated_data)
-
- # on this data lower min_samples has greater sum of clusters - less nan
- # values
- self.assertGreater(np.nansum(output2.metas[:, 0]),
- np.nansum(output1.metas[:, 0]))
-
- def test_change_metric_idx(self):
- w = self.widget
-
- self.send_signal(w.Inputs.data, self.iris)
-
- # change parameters
- cbox = self.widget.controls.metric_idx
- simulate.combobox_activate_index(cbox, 0) # Euclidean
- output1 = self.get_output(w.Outputs.annotated_data)
- simulate.combobox_activate_index(cbox, 1) # Manhattan
- output2 = self.get_output(w.Outputs.annotated_data)
-
- # Manhattan has more nan clusters
- self.assertGreater(np.nansum(output1.metas[:, 0]),
- np.nansum(output2.metas[:, 0]))
-
- def test_sparse_data(self):
- self.iris.X = csr_matrix(self.iris.X)
-
- w = self.widget
-
- self.send_signal(w.Inputs.data, self.iris)
-
- output = self.get_output(w.Outputs.annotated_data)
- self.assertIsNotNone(output)
- self.assertEqual(len(self.iris), len(output))
- self.assertTupleEqual(self.iris.X.shape, output.X.shape)
- self.assertTupleEqual(self.iris.Y.shape, output.Y.shape)
- self.assertEqual(2, output.metas.shape[1])
-
- self.assertEqual("Cluster", str(output.domain.metas[0]))
- self.assertEqual("DBSCAN Core", str(output.domain.metas[1]))