source: orange-bioinformatics/orangecontrib/bio/widgets/OWGeneMania.py @ 1874:b3e32cc5cf6f

Revision 1874:b3e32cc5cf6f, 12.9 KB checked in by Ales Erjavec <ales.erjavec@…>, 6 months ago (diff)

Added new style widget meta descriptions.

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