source: orange/orange/OrangeWidgets/Data/OWConcatenate.py @ 9546:2b6cc6f397fe

Revision 9546:2b6cc6f397fe, 8.3 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"""
2<name>Concatenate</name>
3<description>Concatenates Example Tables.</description>
4<icon>icons/Concatenate.png</icon>
5<priority>1111</priority>
6<contact>Janez Demsar (janez.demsar(@at@)fri.uni-lj.si)</contact>
7"""
8
9from OWWidget import *
10import OWGUI
11from itertools import izip
12
13class OWConcatenate(OWWidget):
14    settingsList = ["mergeAttributes", "dataSourceSelected", "addIdAs", "dataSourceName"]
15   
16    def __init__(self,parent=None, signalManager = None):
17        OWWidget.__init__(self, parent, signalManager, "Concatenate", wantMainArea=0)
18        self.inputs = [("Primary Data", orange.ExampleTable, self.setData), ("Additional Data", orange.ExampleTable, self.setMoreData, Multiple)]
19        self.outputs = [("Data", ExampleTable)]
20
21        self.mergeAttributes = 0
22        self.dataSourceSelected = 1
23        self.addIdAs = 0
24        self.dataSourceName = "clusterId"
25
26        self.primary = None
27        self.additional = {}
28       
29        self.loadSettings()
30       
31        bg = self.bgMerge = OWGUI.radioButtonsInBox(self.controlArea, self, "mergeAttributes", [], "Domains merging", callback = self.apply)
32        OWGUI.widgetLabel(bg, "When there is no primary table, the domain should be")
33        OWGUI.appendRadioButton(bg, self, "mergeAttributes", "Union of attributes appearing in all tables")
34        OWGUI.appendRadioButton(bg, self, "mergeAttributes", "Intersection of attributes in all tables")
35        OWGUI.widgetLabel(bg, "The resulting table will have class only if there is no conflict between input classes.")
36
37        OWGUI.separator(self.controlArea)
38        box = OWGUI.widgetBox(self.controlArea, "Data source IDs", addSpace=True)
39        cb = OWGUI.checkBox(box, self, "dataSourceSelected", "Append data source IDs")
40        self.classificationBox = ib = OWGUI.indentedBox(box, sep=OWGUI.checkButtonOffsetHint(cb))
41        le = OWGUI.lineEdit(ib, self, "dataSourceName", "Name" + "  ", orientation='horizontal', valueType = str)
42        OWGUI.separator(ib, height = 4)
43        aa = OWGUI.comboBox(ib, self, "addIdAs", label = "Place" + "  ", orientation = 'horizontal', items = ["Class attribute", "Attribute", "Meta attribute"])
44        cb.disables.append(ib)
45        cb.makeConsistent()
46       
47        OWGUI.button(self.controlArea, self, "Apply Changes", callback = self.apply, default=True)
48       
49        OWGUI.rubber(self.controlArea)
50
51        self.adjustSize()
52       
53        self.dataReport = None
54
55
56    def setData(self, data):
57        self.primary = data
58        self.bgMerge.setEnabled(not data)
59        self.apply()
60       
61
62    def setMoreData(self, data, id):
63        if not data:
64            if id in self.additional:
65                del self.additional[id]
66        else:
67            self.additional[id] = data
68        self.apply()
69       
70   
71    def apply(self):
72        dataSourceIDs = []
73        currentID = 1
74       
75        if self.primary:
76            if not self.additional:
77                newTable = self.primary
78                dataSourceIDs.extend([currentID] * len(self.primary))
79                currentID += 1
80            else:
81                newTable = orange.ExampleTable(self.primary)
82                dataSourceIDs.extend([currentID] * len(self.primary))
83                currentID += 1
84               
85                for additional in self.additional.values():
86                    newTable.extend(additional)
87                    dataSourceIDs.extend([currentID] * len(additional))
88                    currentID += 1
89
90        else:
91            if not self.additional:
92                newTable = None
93               
94            else:
95                classVar = False
96                for additional in self.additional.values():
97                    if additional.domain.classVar:
98                        if classVar == False: # can also be None
99                            classVar = additional.domain.classVar
100                        elif classVar != additional.domain.classVar:
101                            classVar = None
102                           
103                if self.mergeAttributes: # intersection
104                    attributes = metas = None
105                    for additional in self.additional.values():
106                        if attributes == None:
107                            if classVar:
108                                attributes = additional.domain.attributes
109                            else:
110                                attributes = additional.domain
111                            metas = dict((attr, id) for id, attr in additional.domain.getmetas().items())
112                        else:
113                            attributes = [attr for attr in attributes if attr in additional.domain and not attr == classVar]
114                            metas = dict((attr, id) for id, attr in additional.domain.getmetas().items() if attr in metas)
115                    if attributes == None:
116                        attributes = []
117                        metas = {}
118                else: # union
119                    attributes = []
120                    metas = {}
121                    for additional in self.additional.values():
122                        for attr in additional.domain:
123                            if attr not in attributes and attr != classVar:
124                                attributes.append(attr)
125                        for id, attr in additional.domain.getmetas().items():
126                            if not attr in metas:
127                                metas[attr] = id
128                if not attributes and not classVar:
129                    self.error(1, "The output domain is empty.")
130                    newTable = None
131                else:
132                    self.error(1)
133                    newDomain = orange.Domain(attributes, classVar)
134                    newDomain.addmetas(dict((x[1], x[0]) for x in metas.items())) 
135                    newTable = orange.ExampleTable(newDomain)
136                    for additional in self.additional.values():
137                        newTable.extend(additional)
138                        dataSourceIDs.extend([currentID] * len(additional))
139                        currentID += 1
140       
141        if newTable != None:
142            tableCount = 0
143            if self.primary:
144                tableCount += 1
145            if self.additional:
146                tableCount += len(self.additional)
147           
148            origDomain = newTable.domain
149            if self.dataSourceSelected:
150                dataSourceVar = orange.EnumVariable(self.dataSourceName, values = [str(x) for x in range(1, 1 + tableCount)])
151                if self.addIdAs == 0:
152                    domain = orange.Domain(origDomain.attributes, dataSourceVar)
153                    if origDomain.classVar:
154                        domain.addmeta(orange.newmetaid(), origDomain.classVar)
155                    aid = -1
156                elif self.addIdAs == 1:
157                    domain=orange.Domain(origDomain.attributes+[dataSourceVar], origDomain.classVar)
158                    aid = len(origDomain.attributes)
159                else:
160                    domain=orange.Domain(origDomain.attributes, origDomain.classVar)
161                    aid=orange.newmetaid()
162                    domain.addmeta(aid, dataSourceVar)
163            else:
164                domain = orange.Domain(origDomain.attributes, origDomain.classVar)
165
166            domain.addmetas(origDomain.getmetas())
167           
168            table1 = orange.ExampleTable(domain)
169            table1.extend(newTable)
170           
171            if self.dataSourceSelected:
172                for ex, id in izip(table1, dataSourceIDs):
173                    ex[aid] = dataSourceVar(str(id))
174
175            newTable = table1
176
177        self.dataReport = self.prepareDataReport(newTable)
178        self.send("Data", newTable)
179
180    def sendReport(self):
181        self.reportData(self.primary, "Primary table", 
182                        "None; outputting the %s of attributes from all tables" % ["union", "intersection"][self.mergeAttributes]) 
183        for additional in self.additional.values():
184            self.reportData(additional, "Additional table")
185        if not self.additional:
186            self.reportData(None, "Additional table")
187        self.reportData(self.dataReport, "Merged data")
188       
189if __name__ == "__main__":
190    app = QApplication(sys.argv)
191    w = OWConcatenate()
192    data = orange.ExampleTable("../../doc/datasets/iris.tab")
193    w.setData(data)
194    w.setMoreData(data, 0)
195    w.show()
196    app.exec_()
197
Note: See TracBrowser for help on using the repository browser.