source: orange/orange/OrangeWidgets/Prototypes/OWQuickSelect.py @ 9546:2b6cc6f397fe

Revision 9546:2b6cc6f397fe, 6.2 KB checked in by ales_erjavec <ales.erjavec@…>, 2 years ago (diff)

Renamed widget channel names in line with the new naming rules/convention.
Added backwards compatibility in orngDoc loadDocument to enable loading of schemas saved before the change.

Line 
1"""<name>Quick Select</name>
2<description>Select examples based on values of a single attribute</description>
3<icon>icons/QuickSelect.png</icon>
4<priority>30</priority>
5<contact>Janez Demsar (janez.demsar@fri.uni-lj.si)</contact>"""
6
7from OWWidget import *
8from OWGUI import *
9from OWDlgs import OWChooseImageSizeDlg
10import OWQCanvasFuncts, OWColorPalette
11
12class OWQuickSelect(OWWidget):
13# Context for this widgets are problematic: when they are retrieved, values
14# of attributes cannot be set since the corresponding listbox is not initialized
15# yet. The widget does saves the selected values using a callback function,
16# while when loading them, it safely stores them into a separate attribute
17# from which they get restored after the corresponding listbox is filled.
18# Even this unfortunately works only when widget is constructed anew or loaded
19# from the file, but not when it simply gets new data. To handle this, the
20# setData method does not reconstruct the listboxes when the domain is the same.
21# This semi-works, but fails when reloading data from file (it changes the domain)
22# and, worse, forgets the settings if domains are switched back
23# and forth or if it recieves a None data signal. I don't know a cure for that.
24   
25    contextHandlers = {"": DomainContextHandler("", [ContextField("attributes", DomainContextHandler.RequiredList + DomainContextHandler.IncludeMetaAttributes, selected="selectedAttribute"),
26                                                    ],
27                                                matchValue = DomainContextHandler.MatchValuesAttributes)}
28       
29    def __init__(self,parent=None, signalManager = None):
30        OWWidget.__init__(self, parent, signalManager, "Quick Select", wantMainArea=0)
31        self.inputs = [("Data", ExampleTable, self.setData, Default)]
32        self.outputs = [("Selected Data", ExampleTable, Default), ("Remaining Data", ExampleTable)]
33        self.icons = self.createAttributeIconDict()
34
35        self.attributes = []
36        self.selectedAttribute = []
37        self.valuesList = []
38        self.selectedValues = []
39        self.inExamples = self.outSelected = self.outRemaining = 0
40        self.data = None
41        self.loadSettings()
42
43        OWGUI.listBox(self.controlArea, self, "selectedAttribute", box="Attribute", labels="attributes", callback=self.attributeChanged, selectionMode=QListWidget.SingleSelection)
44        sv = OWGUI.listBox(self.controlArea, self, "selectedValues", box="Values", labels="valuesList", callback=self.updateOutput, selectionMode=QListWidget.ExtendedSelection)
45        ib = OWGUI.widgetBox(self.controlArea, "Info", orientation=0)
46        OWGUI.label(ib, self, "Input: %(inExamples)i instances")
47        OWGUI.rubber(ib)
48        OWGUI.label(ib, self, "Selected: %(outSelected)i instances")
49        self.resize(300, 620)
50
51    def setData(self, data):
52        if data and self.data and data.domain == self.data.domain:
53            self.data = data
54            self.inExamples = len(self.data)
55            self.updateOutput()
56            return
57       
58        self.closeContext()
59        self.data = data
60        if not data:
61            self.attributes = []
62            self.valuesList = self.selectedValues = []
63            self.inExamples = 0
64        else:
65            self.inExamples = len(self.data)
66            self.rawAttributes = [attr for attr in list(data.domain) + data.domain.getmetas().values()
67                                  if attr.varType in [orange.Variable.Discrete, orange.Variable.String]]
68            self.attributes = [(attr.name, attr.varType) for attr in self.rawAttributes]
69            self.selectedAttribute = []
70        self.openContext("", data)
71        self.attributeChanged()
72
73    def settingsFromWidgetCallback(self, handler, context):
74        context.selectedValues = self.selectedValues
75
76    def settingsToWidgetCallback(self, handler, context):
77        if hasattr(context, "selectedValues"):
78             self.storedSelectedValues = context.selectedValues
79
80    def attributeChanged(self):
81        if self.data and self.selectedAttribute:
82            attr = self.rawAttributes[self.selectedAttribute[0]]
83            if attr.varType == orange.Variable.Discrete:
84                self.valuesList = [a.decode("utf-8") for a in attr.values]
85            else:
86                self.valuesList = list(set(str(ex[attr]).decode("utf-8") for ex in self.data))
87            if hasattr(self, "storedSelectedValues"):
88                try:
89                    # may fail if values do not match (can they not match?!)
90                    self.selectedValues = self.storedSelectedValues
91                except:
92                    pass 
93                delattr(self, "storedSelectedValues") 
94        else:
95            self.valuesList = []
96        self.updateOutput()
97       
98    def updateOutput(self):
99        if not self.data or not self.selectedAttribute or not self.selectedValues:
100            self.send("Selected Data", None)
101            self.send("Remaining Data", None)
102            self.outSelected = self.outRemaining = 0
103            return
104       
105        attr = self.rawAttributes[self.selectedAttribute[0]]
106        pp = orange.Preprocessor_take() 
107        pp.values[attr] = [self.valuesList[j].encode("utf-8") for j in self.selectedValues]
108        selected = pp(self.data)
109        self.send("Selected Data", selected)
110       
111        pp = orange.Preprocessor_drop() 
112        pp.values[attr] = [self.valuesList[j].encode("utf-8") for j in self.selectedValues]
113        remaining = pp(self.data)
114        self.send("Remaining Data", remaining)
115
116        self.outSelected = len(selected)
117        self.outRemaining = len(remaining)
118       
119    def sendReport(self):
120        self.reportSettings("Criteria", [("Attribute", self.attributes[self.selectedAttribute[0]][0] 
121                                                              if self.selectedAttribute and 0 <= self.selectedAttribute[0] <= len(self.attributes) else _("(none)")),
122                                            ("Values", ", ".join(self.valuesList[i] for i in self.selectedValues) if self.selectedValues else _("(none)"))])
123        self.reportSettings("Input/Output", [("Input instances", self.inExamples),
124                                                ("Selected instances", self.outSelected),
125                                                ("Remaining instances", self.outRemaining)])
Note: See TracBrowser for help on using the repository browser.