Repository: biolab/orange3

Issue:
Nomograms should output data with selected (shown) features
We had data with a large number of attributes. We'd like to select the first 10 features based on their absolute importance and see if the model is still as good as before. I guess the only way to do it currently is to manually select those features in select columns ... which is annoying.


Discussion:
Nomograms cannot output data, because they (probably) don't have it. But they should output shown features, and these features can then be fed into Select columns.

Resolving patch:
diff --git a/Orange/widgets/visualize/ownomogram.py b/Orange/widgets/visualize/ownomogram.py
--- a/Orange/widgets/visualize/ownomogram.py
+++ b/Orange/widgets/visualize/ownomogram.py
@@ -22,7 +22,7 @@
 from Orange.widgets.settings import Setting, ContextSetting, \
     ClassValuesContextHandler
 from Orange.widgets.utils.widgetpreview import WidgetPreview
-from Orange.widgets.widget import OWWidget, Msg, Input
+from Orange.widgets.widget import OWWidget, Msg, Input, Output, AttributeList
 from Orange.widgets import gui
 
 
@@ -573,6 +573,9 @@ class Inputs:
         classifier = Input("Classifier", Model)
         data = Input("Data", Table)
 
+    class Outputs:
+        features = Output("Features", AttributeList)
+
     MAX_N_ATTRS = 1000
     POINT_SCALE = 0
     ALIGN_LEFT = 0
@@ -843,10 +846,12 @@ def calculate_log_reg_coefficients(self):
     def update_scene(self):
         self.clear_scene()
         if self.domain is None or not len(self.points[0]):
+            self.Outputs.features.send(None)
             return
 
         n_attrs = self.n_attributes if self.display_index else int(1e10)
         attr_inds, attributes = zip(*self.get_ordered_attributes()[:n_attrs])
+        self.Outputs.features.send(AttributeList(attributes))
 
         name_items = [QGraphicsTextItem(attr.name) for attr in attributes]
         point_text = QGraphicsTextItem("Points")


Test patch:
diff --git a/Orange/widgets/visualize/tests/test_ownomogram.py b/Orange/widgets/visualize/tests/test_ownomogram.py
--- a/Orange/widgets/visualize/tests/test_ownomogram.py
+++ b/Orange/widgets/visualize/tests/test_ownomogram.py
@@ -213,5 +213,37 @@ def test_tooltip(self):
         m = MovableToolTip()
         m.show(QPoint(0, 0), "Some text.")
 
+    def test_output(self):
+        cls = LogisticRegressionLearner()(self.titanic)
+        data = self.titanic[10:11]
+        status, age, sex = data.domain.attributes
+        self.send_signal(self.widget.Inputs.classifier, cls)
+        self.widget.sort_combo.setCurrentIndex(1)
+        self.widget.sort_combo.activated.emit(1)
+
+        # Output more attributer than there are -> output all
+        self.widget.n_attributes = 5
+        self.widget.n_spin.valueChanged.emit(5)
+        attrs = self.get_output(self.widget.Outputs.features)
+        self.assertEqual(attrs, [age, sex, status])
+
+        # Output the first two
+        self.widget.n_attributes = 2
+        self.widget.n_spin.valueChanged.emit(2)
+        attrs = self.get_output(self.widget.Outputs.features)
+        self.assertEqual(attrs, [age, sex])
+
+        # Set to output all
+        self.widget.display_index = 0
+        self.widget.controls.display_index.group.buttonClicked[int].emit(0)
+        attrs = self.get_output(self.widget.Outputs.features)
+        self.assertEqual(attrs, [age, sex, status])
+
+        # Remove classifier -> output None
+        self.send_signal(self.widget.Inputs.classifier, None)
+        attrs = self.get_output(self.widget.Outputs.features)
+        self.assertIsNone(attrs)
+
+
 if __name__ == "__main__":
     unittest.main()