source: orange-bioinformatics/widgets/OWGeneMania.py @ 1462:ee4cee02fb85

Revision 1462:ee4cee02fb85, 12.5 KB checked in by markotoplak, 3 years ago (diff)

Bioinformatics widgets name changes, new icon for GeneMANIA.

Line 
1"""<name>GeneMANIA</name>
2<icon>icons/GeneMANIA.png</icon>
3"""
4
5from OWWidget import *
6import OWGUI
7import orngNetwork
8import obiGeneMania
9
10import os, sys
11import multiprocessing
12import random
13
14class BarItemDelegate(QStyledItemDelegate):
15    BarRole = OWGUI.OrangeUserRole.next() 
16    BarForegroundRole = OWGUI.OrangeUserRole.next()
17   
18    def __init__(self, parent, brush=QBrush(QColor(255, 170, 127)), scale=(0.0, 1.0)):
19        QStyledItemDelegate.__init__(self, parent) 
20        self.brush = brush
21        self.scale = scale
22       
23       
24    def paint(self, painter, option, index):
25        painter.save()
26        qApp.style().drawPrimitive(QStyle.PE_PanelItemViewRow, option, painter)
27        qApp.style().drawPrimitive(QStyle.PE_PanelItemViewItem, option, painter)
28        rect = option.rect
29        try:
30            val, ok = index.data(self.BarRole).toDouble()
31            if ok:
32                color = index.data(self.BarForegroundRole)
33                if color.isValid() and color.type() == QVariant.Color:
34                    brush = QBrush(color)
35                else:
36                    brush = self.brush
37                   
38                minval, maxval = self.scale
39                val = (val - minval) / (maxval - minval)
40                painter.save()
41                if option.state & QStyle.State_Selected:
42                    painter.setOpacity(0.75)
43                painter.setBrush(brush)
44                painter.drawRect(rect.adjusted(1, 1, max(-rect.width() * (1.0 - val) - 2, - rect.width() + 2), -2))
45                painter.restore()
46        except Exception, ex:
47            print >> sys.stderr, ex
48           
49        text = index.data(Qt.DisplayRole).toString()
50        if text:
51            align, ok = index.data(Qt.TextAlignmentRole).toInt()
52            if not ok:
53                align = Qt.AlignVCenter | Qt.AlignLeft
54               
55            painter.drawText(option.rect, align, text)
56        painter.restore()
57       
58       
59    def sizeHint(self, option, index):
60        size = QStyledItemDelegate.sizeHint(self, option, index)
61        metrics = QFontMetrics(option.font)
62        height = metrics.lineSpacing() + 2
63        return QSize(size.width(), height)
64   
65
66class OWGeneMania(OWWidget):
67    contextHandlers = {"": DomainContextHandler("", ["selectedOrganismIndex", "selectedGeneAttrIndex", "genesInColumns"])}
68    settingsList = ["serverAddress", "selectedOrganismIndex", "selectedGeneAttrIndex", "genesInColumns", "selectedMethodIndex", "resultCount"]
69    def __init__(self, parent=None, signalManager=None, name="GeneMANIA"):
70        OWWidget.__init__(self, parent, signalManager, name, wantMainArea=True)
71       
72        self.inputs = [("Input Genes", ExampleTable, self.setData)]
73        self.outputs = [("Network", orngNetwork.Network, Default), ("Items", ExampleTable)]
74       
75        self.serverAddress = obiGeneMania.DEFAULT_SERVER
76        self.selectedOrganismIndex = 0
77        self.selectedGeneAttrIndex = 0
78        self.genesInColumns = False
79        self.selectedMethodIndex = 1
80        self.resultCount = 10
81       
82        self.data = None
83       
84        self.loadSettings()
85       
86        #####
87        # GUI
88        #####
89       
90        self.organisms = [("H. sapiens", "9606"),
91                          ("A. thaliana", "3702"),
92                          ("C. elegans", "6239"),
93                          ("D. melanogaster", "7227"),
94                          ("M. musculus", "10090"),
95                          ("S. cerevisiae", "4932")]
96       
97        box = OWGUI.widgetBox(self.controlArea, "Info", addSpace=True)
98        self.info = OWGUI.widgetLabel(box, "No genes on input.")
99        self.infoState = OWGUI.widgetLabel(box, "")
100        self.infoState.setWordWrap(True)
101       
102        box = OWGUI.widgetBox(self.controlArea, "GeneMANIA server address", addSpace=True)
103        OWGUI.lineEdit(box, self, "serverAddress")
104       
105        self.organismCombo = OWGUI.comboBox(self.controlArea, self, "selectedOrganismIndex", "Organims",
106                                            items=[t[0] for t in self.organisms],
107                                            tooltip="Select the organism",
108                                            callback=self.updateInfo)
109       
110        box = OWGUI.widgetBox(self.controlArea, "Genes", addSpace=True)
111        self.geneAttrCombo = OWGUI.comboBox(box, self, "selectedGeneAttrIndex",
112                                            tooltip="Select the attribute with gene names",
113                                            callback=self.updateInfo)
114       
115        cb = OWGUI.checkBox(box, self, "genesInColumns", "Use attribute names",
116                            tooltip="Use attribute names as gene names instead.",
117                            callback=self.updateInfo,
118                            disables=[(-1, self.geneAttrCombo)])
119        cb.makeConsistent()
120        self.methodItems = [("Automatic relevance", "automatic_relevance"),
121                            ("Automatic", "automatic"),
122                            ("Biological process", "bp"),
123                            ("Molecular function", "mf"),
124                            ("Cellular component", "cc"),
125                            ("Average", "average"),
126                            ("Average category", "average_category")]
127       
128        toolTips = ["Assigned based on query genes",
129                    "Automatically selected weighting method",
130                    "Biological process based",
131                    "Molecular function based",
132                    "Cellular component based",
133                    "Equal by data type",
134                    "Equal by network"]
135       
136        OWGUI.comboBox(self.controlArea, self, "selectedMethodIndex", 
137                       box="Net combining method",
138                       items=[t[0] for t in self.methodItems],
139                       callback=self.updateInfo
140                       )
141       
142        OWGUI.spin(self.controlArea, self, "resultCount", 1, 100, 
143                   box="Number of gene results",
144                   callback=self.updateInfo
145                   )
146       
147        self.geneManiaLinkLabel = OWGUI.widgetLabel(self.controlArea, "")
148        self.geneManiaLinkLabel.setOpenExternalLinks(True)
149        OWGUI.button(self.controlArea, self, "Retrieve", callback=self.retrieve)
150        OWGUI.rubber(self.controlArea)
151       
152        self.networksReport = QTreeView()
153        self.networksReport.setEditTriggers(QTreeView.NoEditTriggers)
154        box = OWGUI.widgetBox(self.mainArea, "Networks")
155        box.layout().addWidget(self.networksReport)
156       
157        self.resize(100, 200)
158       
159        self.connect(self, SIGNAL("widgetStateChanged(QString, int, QString)"), self.updateInfo)
160
161
162    def setData(self, data=None):
163        self.error([0,1,2])
164        self.warning([0])
165        self.data = data
166        self.closeContext("")
167        self.geneAttrCombo.clear()
168        self.candidateGeneAttrs = []
169        self.selectedGeneAttrIndex = 0
170       
171        if data is not None:
172            self.candidateGeneAttrs = data.domain.variables + data.domain.getmetas().values()
173            self.candidateGeneAttrs = [attr for attr in self.candidateGeneAttrs if attr.varType != orange.VarTypes.Continuous]
174            self.geneAttrCombo.addItems([attr.name for attr in self.candidateGeneAttrs])
175            self.openContext("", data)
176        else:
177            self.send("Network", None)
178            self.send("Items", None)
179           
180        self.updateInfo()
181           
182    def onGeneSourceSelection(self):
183        genes = self.getSelectedGenes()
184        self.info.setText("")
185       
186    def updateInfo(self, *args):
187        if self.data is not None:
188            genes = self.getSelectedGenes()
189            htmlState = self.widgetStateToHtml()
190            self.info.setText("%i genes on input." % len(genes))
191            self.infoState.setText(htmlState)
192        else:
193            self.info.setText("No data on input.")
194            self.infoState.setText("")
195       
196        if self.data:
197            org = self.organisms[self.selectedOrganismIndex][1]
198            genes = self.getSelectedGenes()
199            method = self.methodItems[self.selectedMethodIndex][1]
200            conn = obiGeneMania.Connection(self.serverAddress)
201            self.geneManiaLinkLabel.setText('<a href="%s">View network in external browser</a>' % conn._queryPage(org, genes, method, self.resultCount))
202        else:
203            self.geneManiaLinkLabel.setText('')
204       
205    def getSelectedGenes(self):
206        if self.data is not None:
207            if self.genesInColumns:
208                names = [attr.name for attr in self.data.domain.attributes]
209            else:
210                attr = self.candidateGeneAttrs[self.selectedGeneAttrIndex]
211                names = set([str(ex[attr]) for ex in self.data if not ex[attr].isSpecial()])
212            return names
213        else:
214            return []
215       
216       
217    def retrieve(self):
218        org = self.organisms[self.selectedOrganismIndex][1]
219        genes = self.getSelectedGenes()
220        method = self.methodItems[self.selectedMethodIndex][1]
221        self.error([0, 1, 2])
222        self.warning([0])
223       
224        conn = obiGeneMania.Connection(self.serverAddress)
225        errorCode, invalid, genes = conn.validate(org, genes)
226        if not genes:
227            self.error(2, "No valid gene names!")
228            self.net, self.netTab = None, None
229            self.updateNetworksReport()
230            return
231        elif invalid:
232            self.warning(0, "There are invalid gene names on input:\n%s" % (",".join(invalid[:5])) + (" ..." if len(invalid) > 5 else ""))
233           
234#        print conn._queryPage(org, genes, method, self.resultCount)
235        call = self.asyncCall(conn.retrieveXML, (org, genes), {"m": method, "r": self.resultCount})
236        call()
237       
238        self.progressBarInit()
239        self.setEnabled(False)
240        try:
241#            net = conn.retrieve(org, genes, m=method, r=self.resultCount)
242            xml = call.get_result(processEvents=True)
243            # Parse the xml in the main thread (pyexpat frequently crashes in
244            # Qt's threading model)
245            dom = obiGeneMania.minidom.parseString(xml)
246            net = obiGeneMania.parse(dom)
247            items = net.items
248        except Exception, ex:
249            self.error(0, "Failed to retrieve network from server!\n" + str(ex))
250            sys.excepthook(*sys.exc_info())
251            net = None
252            items = None
253       
254        if net:
255            try:
256                self.netTab = obiGeneMania.parsePage(conn._page)
257            except Exception:
258                self.error(1, "Failed to parse network tabs!\n" + str(ex))
259                self.netTab = None
260        else:
261            self.netTab = None
262        self.setEnabled(True)
263        self.progressBarFinished()
264       
265        self.net = net
266       
267        self.send("Network", net)
268        self.send("Items", items)
269       
270        self.updateNetworksReport()
271       
272    def updateNetworksReport(self):
273        model = QStandardItemModel(self)
274        model.setHorizontalHeaderLabels(["Networks", "Weight"])
275        root = model.invisibleRootItem()
276        def toFloat(s):
277            if s.strip().endswith("%"):
278                return float(s.strip()[:-1])
279            else:
280                return float(s)
281           
282        if self.netTab and self.net and self.net.links:
283            for group in self.netTab:
284                groupItem = QStandardItem(group.name)
285                groupWeightItem = QStandardItem("%.2f %%" % toFloat(group.weight))
286                groupWeightItem.setData(QVariant(toFloat(group.weight) / 100.0), BarItemDelegate.BarRole)
287                root.appendRow([groupItem, groupWeightItem])
288                for net in group.networks:
289                    netItem = QStandardItem(net.name)
290                    netItem.setData(QVariant(net.description), Qt.ToolTipRole)
291                   
292                    netWeightItem = QStandardItem("%.2f %%" % toFloat(net.weight))
293                    netWeightItem.setData(QVariant(toFloat(net.weight) / 100.0), BarItemDelegate.BarRole)
294                    netWeightItem.setData(QVariant(net.description), Qt.ToolTipRole)
295                    groupItem.appendRow([netItem, netWeightItem])
296               
297        self.networksReport.setModel(model)
298        self.networksReport.setItemDelegateForColumn(1, BarItemDelegate(self))
299        self.networksReport.resizeColumnToContents(0)
300           
301       
302if __name__ == "__main__":
303    app = QApplication(sys.argv)
304    w = OWGeneMania()
305    w.show()
306    data = orange.ExampleTable("../../../doc/datasets/brown-selected.tab")
307    w.setData(orange.ExampleTable(data[:3]))
308    app.exec_()
309    w.saveSettings()
310       
311       
Note: See TracBrowser for help on using the repository browser.