source: orange/Orange/OrangeWidgets/Data/OWMergeData.py @ 11748:467f952c108d

Revision 11748:467f952c108d, 11.5 KB checked in by blaz <blaz.zupan@…>, 6 months ago (diff)

Changes in headers, widget descriptions text.

Line 
1import orange
2from OWWidget import *
3import OWGUI
4
5NAME = "Merge Data"
6DESCRIPTION = """Merges data sets based on values of selected attributes."""
7LONG_DESCRIPTION = ""
8ICON = "icons/MergeData.svg"
9PRIORITY = 1110
10AUTHOR = "Peter Juvan"
11AUTHOR_EMAIL = "peter.juvan(@at@)fri.uni-lj.si"
12INPUTS = [("Data A", Orange.data.Table, "onDataAInput"),
13          ("Data B", Orange.data.Table, "onDataBInput")]
14OUTPUTS = [("Merged Data A+B", Orange.data.Table, ),
15           ("Merged Data B+A", Orange.data.Table, )]
16
17
18class OWMergeData(OWWidget):
19
20    contextHandlers = {"A": DomainContextHandler("A",
21                                [ContextField("varA")],
22                                syncWithGlobal=False,
23                                contextDataVersion=2),
24                       "B": DomainContextHandler("B",
25                                [ContextField("varB")],
26                                syncWithGlobal=False,
27                                contextDataVersion=2)}
28
29    def __init__(self, parent = None, signalManager = None, name = "Merge data"):
30        OWWidget.__init__(self, parent, signalManager, name, wantMainArea = 0)  #initialize base class
31
32        # set channels
33        self.inputs = [("Data A", ExampleTable, self.onDataAInput),
34                       ("Data B", ExampleTable, self.onDataBInput)]
35       
36        self.outputs = [("Merged Data A+B", ExampleTable),
37                        ("Merged Data B+A", ExampleTable)]
38
39        # data
40        self.dataA = None
41        self.dataB = None
42        self.varListA = []
43        self.varListB = []
44        self.varA = None
45        self.varB = None
46        self.lbAttrAItems = []
47        self.lbAttrBItems = []
48
49        # load settings
50        self.loadSettings()
51
52        # GUI
53        w = QWidget(self)
54        self.controlArea.layout().addWidget(w)
55        grid = QGridLayout()
56        grid.setMargin(0)
57        w.setLayout(grid)
58       
59        # attribute A
60        boxAttrA = OWGUI.widgetBox(self, 'Attribute A', orientation = "vertical", addToLayout=0)
61        grid.addWidget(boxAttrA, 0,0)
62        self.lbAttrA = OWGUI.listBox(boxAttrA, self, "lbAttrAItems", callback = self.lbAttrAChange)
63       
64        # attribute  B
65        boxAttrB = OWGUI.widgetBox(self, 'Attribute B', orientation = "vertical", addToLayout=0)
66        grid.addWidget(boxAttrB, 0,1)
67        self.lbAttrB = OWGUI.listBox(boxAttrB, self, "lbAttrBItems", callback = self.lbAttrBChange)
68
69        # info A
70        boxDataA = OWGUI.widgetBox(self, 'Data A', orientation = "vertical", addToLayout=0)
71        grid.addWidget(boxDataA, 1,0)
72        self.lblDataAExamples = OWGUI.widgetLabel(boxDataA, "num examples")
73        self.lblDataAAttributes = OWGUI.widgetLabel(boxDataA, "num attributes")
74
75        # info B
76        boxDataB = OWGUI.widgetBox(self, 'Data B', orientation = "vertical", addToLayout=0)
77        grid.addWidget(boxDataB, 1,1)
78        self.lblDataBExamples = OWGUI.widgetLabel(boxDataB, "num examples")
79        self.lblDataBAttributes = OWGUI.widgetLabel(boxDataB, "num attributes")
80
81        # icons
82        self.icons = self.createAttributeIconDict()
83
84        # resize
85        self.resize(400,500)
86
87
88    ############################################################################################################################################################
89    ## Data input and output management
90    ############################################################################################################################################################
91       
92    def inVarList(self, varList, var):
93        varList = [(v.name, v.varType) for v in varList]
94        if var in varList:
95            return True, varList.index(var)
96        else:
97            return False, -1
98       
99    def onDataAInput(self, data):
100        self.closeContext("A")
101        self.dataA = data
102        # update self.varListA and self.varA
103        if self.dataA:
104            self.varListA = list(self.dataA.domain.variables) + self.dataA.domain.getmetas().values()
105        else:
106            self.varListA = []
107           
108        # update info
109        self.updateInfoA()
110        # update attribute A listbox
111        self.lbAttrA.clear()
112        for var in self.varListA:
113            self.lbAttrA.addItem(QListWidgetItem(self.icons[var.varType], var.name))
114        if self.dataA:
115            self.openContext("A", self.dataA)
116        match, index = self.inVarList(self.varListA, self.varA)
117        if match:
118            var = self.varListA[index]
119            self.varA = (var.name, var.varType)
120            self.lbAttrA.setCurrentItem(self.lbAttrA.item(index))
121        else:
122            self.varA = None
123           
124        self.sendData()
125
126    def onDataBInput(self, data):
127        self.closeContext("B")
128        self.dataB = data
129        # update self.varListB and self.varB
130        if self.dataB:
131            self.varListB = list(self.dataB.domain.variables) + self.dataB.domain.getmetas().values()
132        else:
133            self.varListB = []
134       
135        # update info
136        self.updateInfoB()
137        # update attribute B listbox
138        self.lbAttrB.clear()
139        for var in self.varListB:
140            self.lbAttrB.addItem(QListWidgetItem(self.icons[var.varType], var.name))
141       
142        if self.dataB:
143            self.openContext("B", self.dataB)
144        match, index = self.inVarList(self.varListB, self.varB)
145        if match:
146            var = self.varListB[index]
147            self.varB = (var.name, var.varType)
148            self.lbAttrB.setCurrentItem(self.lbAttrB.item(index))
149        else:
150            self.varB = None
151           
152        self.sendData()
153
154
155    def updateInfoA(self):
156        """Updates data A info box.
157        """
158        if self.dataA:
159            self.lblDataAExamples.setText("%s example%s" % self._sp(self.dataA))
160            self.lblDataAAttributes.setText("%s attribute%s" % self._sp(self.varListA))
161        else:
162            self.lblDataAExamples.setText("No data on input A.")
163            self.lblDataAAttributes.setText("")
164
165
166    def updateInfoB(self):
167        """Updates data B info box.
168        """
169        if self.dataB:
170            self.lblDataBExamples.setText("%s example%s" % self._sp(self.dataB))
171            self.lblDataBAttributes.setText("%s attribute%s" % self._sp(self.varListB))
172        else:
173            self.lblDataBExamples.setText("No data on input B.")
174            self.lblDataBAttributes.setText("")
175
176    def sendData(self):
177        self.error(0)
178        if self.dataA and self.dataB and self.varA and self.varB:
179            try:
180                self.send("Merged Data A+B", self.merge(self.dataA, self.dataB, self.varA[0], self.varB[0]))
181                self.send("Merged Data B+A", self.merge(self.dataB, self.dataA, self.varB[0], self.varA[0]))
182            except orange.KernelException, ex:
183                self.error(0, "Cannot merge the two tables (%r)" % str(ex))
184        else:
185            self.send("Merged Data A+B", None)
186            self.send("Merged Data B+A", None)
187
188    ############################################################################################################################################################
189    ## Event handlers
190    ############################################################################################################################################################
191
192    def lbAttrAChange(self):
193        if self.dataA:
194            if self.lbAttrA.selectedItems() != []:
195                ind = self.lbAttrA.row(self.lbAttrA.selectedItems()[0])
196                var = self.varListA[ind]
197                self.varA = (var.name, var.varType)
198            else:
199                self.varA = None
200        else:
201            self.varA = None
202        self.sendData()
203
204
205    def lbAttrBChange(self):
206        if self.dataB:
207            if self.lbAttrB.selectedItems() != []:
208                ind = self.lbAttrB.row(self.lbAttrB.selectedItems()[0])
209                var = self.varListB[ind]
210                self.varB = (var.name, var.varType)
211            else:
212                self.varB = None
213        else:
214            self.varB = None
215        self.sendData()
216
217
218    ############################################################################################################################################################
219    ## Utility functions
220    ############################################################################################################################################################
221
222    def _sp(self, l, capitalize=True):
223        """Input: list; returns tuple (str(len(l)), "s"/"")
224        """
225        n = len(l)
226        if n == 0:
227            if capitalize:
228                return "No", "s"
229            else:
230                return "no", "s"
231        elif n == 1:
232            return str(n), ''
233        else:
234            return str(n), 's'
235
236    def merge(self, dataA, dataB, varA, varB):
237        """ Merge two tables
238        """
239       
240        val2idx = dict([(e[varB].native(), i) for i, e in reversed(list(enumerate(dataB)))])
241       
242        for key in ["?", "~", ""]:
243            if key in val2idx:
244                val2idx.pop(key)
245                 
246        metasA = dataA.domain.getmetas().items()
247        metasB = dataB.domain.getmetas().items()
248       
249        includedAttsB = [attrB for attrB in dataB.domain if attrB not in dataA.domain]
250        includedMetaB = [(mid, meta) for mid, meta in metasB if (mid, meta) not in metasA]
251        includedClassVarB = dataB.domain.classVar and dataB.domain.classVar not in dataA.domain
252       
253        reducedDomainB = orange.Domain(includedAttsB, includedClassVarB)
254        reducedDomainB.addmetas(dict(includedMetaB))
255       
256       
257        mergingB = orange.ExampleTable(reducedDomainB)
258       
259        for ex in dataA:
260            ind = val2idx.get(ex[varA].native(), None)
261            if ind is not None:
262                mergingB.append(orange.Example(reducedDomainB, dataB[ind]))
263               
264            else:
265                mergingB.append(orange.Example(reducedDomainB, ["?"] * len(reducedDomainB)))
266               
267        return orange.ExampleTable([dataA, mergingB])
268   
269if __name__=="__main__":
270    """
271    import sys
272    import OWDataTable, orngSignalManager
273    signalManager = orngSignalManager.SignalManager(0)
274    #data = orange.ExampleTable('dicty_800_genes_from_table07.tab')
275##    data = orange.ExampleTable(r'..\..\doc\datasets\adult_sample.tab')
276##    dataA = orange.ExampleTable(r'c:\Documents and Settings\peterjuv\My Documents\STEROLTALK\Sterolgene v.0 mouse\sterolgene v.0 mouse probeRatios.tab')
277##    dataA = orange.ExampleTable(r'c:\Documents and Settings\peterjuv\My Documents\STEROLTALK\Sterolgene v.0 mouse\Copy of sterolgene v.0 mouse probeRatios.tab')
278##    dataB = orange.ExampleTable(r'c:\Documents and Settings\peterjuv\My Documents\STEROLTALK\Sterolgene v.0 mouse\sterolgene v.0 mouse probeRatios.tab')
279    dataA = orange.ExampleTable(r'c:\Documents and Settings\peterjuv\My Documents\et1.tab')
280    dataB = orange.ExampleTable(r'c:\Documents and Settings\peterjuv\My Documents\et2.tab')
281    a=QApplication(sys.argv)
282    ow=OWMergeData()
283    a.setMainWidget(ow)
284    ow.show()
285    ow.onDataAInput(dataA)
286    ow.onDataBInput(dataB)
287    # data table
288    dt = OWDataTable.OWDataTable(signalManager = signalManager)
289    signalManager.addWidget(ow)
290    signalManager.addWidget(dt)
291    signalManager.setFreeze(1)
292    signalManager.addLink(ow, dt, 'Merged Examples A+B', 'Examples', 1)
293    signalManager.addLink(ow, dt, 'Merged Examples B+A', 'Examples', 1)
294    signalManager.setFreeze(0)
295    dt.show()
296    a.exec_()
297    """
298    import sys
299    a=QApplication(sys.argv)
300    ow=OWMergeData()
301    ow.show()
302    data = orange.ExampleTable("iris.tab")
303    ow.onDataAInput(data)
304    a.exec_()
Note: See TracBrowser for help on using the repository browser.