source: orange/Orange/OrangeWidgets/Data/OWConcatenate.py @ 11763:7d6c7587cfb2

Revision 11763:7d6c7587cfb2, 8.7 KB checked in by Ales Erjavec <ales.erjavec@…>, 5 months ago (diff)

Fixed "Concatenate" widget layout.

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