source: orange-bioinformatics/_bioinformatics/widgets/OWKEGGPathwayBrowser.py @ 1726:6778e0225b86

Revision 1726:6778e0225b86, 32.8 KB checked in by Ales Erjavec <ales.erjavec@…>, 17 months ago (diff)

Added new icons by Peter Cuhalev and replaced existing ones with expanded paths.

RevLine 
[188]1"""
[1462]2<name>KEGG Pathways</name>
[1051]3<description>Browse KEGG pathways that include an input set of genes.</description>
[1052]4<priority>2030</priority>
[1726]5<icon>icons/KEGGPathways.svg</icon>
[188]6"""
[1632]7
8from __future__ import absolute_import, with_statement
[188]9
[1712]10if __name__ == "__main__": 
11    __package__ = "Orange.bio.widgets"
12
[188]13import sys
[1632]14from collections import defaultdict
[1142]15import webbrowser
16
[1712]17import Orange
[1632]18import orange
[1643]19from Orange.orng import orngMisc, orngServerFiles
[1632]20from Orange.orng.orngDataCaching import data_hints
21from Orange.OrangeWidgets import OWGUI
22from Orange.OrangeWidgets.OWWidget import *
[188]23
[1632]24from .. import obiTaxonomy
[1716]25from .. import obiKEGG
[1632]26from .. import obiGeneSets
[1118]27
[1534]28USE_THREADING = True
29
30if USE_THREADING:
31    import threading
32    from functools import partial
33    def threading_queued_invoke(qobj, func):
34        def safe_wrapper(*args, **kwargs):
35            QMetaObject.invokeMethod(qobj, "queuedInvoke", 
36                                     Qt.QueuedConnection, 
37                                     Q_ARG("PyQt_PyObject",
38                                           partial(func, *args, **kwargs)))
39        return safe_wrapper
40   
[211]41def split_and_strip(string, sep=None):
42    return [s.strip() for s in string.split(sep)]
43
[1142]44class EntryGraphicsItem(QGraphicsPathItem):
45    def __init__(self, graphics, *args):
46        QGraphicsPathItem.__init__(self, *args)
47        path = QPainterPath()
48        x, y, w, h = [int(graphics.get(c, 0)) for c in ["x", "y", "width", "height"]]
49        type = graphics.get("type", "rectangle")
50        if type == "rectangle":
51            path.addRect(QRectF(x - w/2, y - h/2, w, h))
52        elif type == "roundrectangle":
53            path.addRoundedRect(QRectF(x - w/2, y - h/2, w, h), 10, 10)
54        elif type == "circle":
55            path.addEllipse(QRectF(x - w/2, y - h/2, w, h))
56           
57        self.setPath(path)
58        self.setAcceptHoverEvents(True)
59        self._actions = []
60        self.link = None
61       
62    def hoverEnterEvent(self, event):
63        self.setBrush(QBrush(QColor(0, 100, 0, 100)))
64       
65    def hoverLeaveEvent(self, event):
66        self.setBrush(QBrush(Qt.NoBrush))
67       
68    def contextMenuEvent(self, event):
69        if self._actions:
70            self._menu = menu = QMenu()
71            for action in self._actions:
72                menu.addAction(action)
73            menu.popup(event.screenPos())
74           
75    def itemChange(self, change, value):
76        if change == QGraphicsItem.ItemSelectedHasChanged:
77            self.setPen(QPen(Qt.red if self.isSelected() else Qt.blue, 2))
78           
79        return QGraphicsPathItem.itemChange(self, change, value)
80           
81class GraphicsPathwayItem(QGraphicsPixmapItem):
82    def __init__(self, pathway, objects, *args, **kwargs):
83        QGraphicsPixmapItem.__init__(self, *args)
84        self.setTransformationMode(Qt.SmoothTransformation)
85        self.setPathway(pathway)
86        self.setMarkedObjects(objects, name_mapper=kwargs.get("name_mapper", {}))
87       
88    def setPathway(self, pathway):
89        self.pathway = pathway
90        if pathway:
91            image_filename = pathway.get_image()
92            self._pixmap = QPixmap(image_filename)
93        else:
94            self._pixmap = QPixmap()
95        self.setPixmap(self._pixmap)
96       
97    def setMarkedObjects(self, objects, name_mapper={}):
[1577]98        for entry in self.pathway.entries() if self.pathway else []:
[1142]99            if entry.type == "group":
100                continue
101            graphics = entry.graphics
102            contained_objects = [obj for obj in objects if obj in entry.name]
103            item = EntryGraphicsItem(graphics, self, self.scene())
104            item.setToolTip(self.tooltip(entry, contained_objects, name_mapper))
105            item._actions = self.actions(entry, contained_objects)
106            item.marked_objects = contained_objects
107            if contained_objects:
108                item.setPen(QPen(Qt.blue, 2))
109                item.setFlag(QGraphicsItem.ItemIsSelectable, True)
110   
111    def actions(self, entry, marked_objects=[]):
112        actions = []
113        type = entry.type
114        if marked_objects:
115            action = QAction("View genes on kegg website", None)
116            org = set([s.split(":")[0] for s in marked_objects]).pop()
117            genes = [s.split(":")[-1] for s in marked_objects]
118            address = "http://www.genome.jp/dbget-bin/www_bget?" + "+".join([org] + genes)
119            QObject.connect(action, SIGNAL("triggered()"), lambda toggled=False, address=address: webbrowser.open(address))
120            actions.append(action)
121        elif hasattr(entry, "link"):
122            action = QAction("View %s on KEGG website" % str(type), None)
123            QObject.connect(action, SIGNAL("triggered()"), lambda toggled=False, address=entry.link: webbrowser.open(address))
124            actions.append(action)
125        return actions
126   
127    def tooltip(self, entry, objects, name_mapper={}):
128        names = [obj for obj in objects if obj in entry.name]
129        names = [name_mapper.get(name, name) for name in names]
130        text = "<p>%s</p>" % (entry.name[:16] + " ..." if len(entry.name) > 20 else entry.name)
131        if names:
132            text += "<br>".join(names)
133        return text
134   
135    def contextMenuEvent(self, event):
136        self._menu = menu = QMenu()
137        action = menu.addAction("View this pathway on KEGG website")
138        address ="http://www.kegg.jp/kegg-bin/show_pathway?%s%s" % (self.pathway.org, self.pathway.number)
139        QObject.connect(action, SIGNAL("triggered()"), lambda : webbrowser.open(address))
140        menu.popup(event.screenPos())
[188]141
[195]142class PathwayView(QGraphicsView):
[188]143    def __init__(self, master, *args):
[195]144        QGraphicsView.__init__(self, *args)
[188]145        self.master = master
[1142]146       
[195]147        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
148        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
149       
[1142]150        self.setRenderHints(QPainter.Antialiasing)
151        scene = QGraphicsScene(self)
152        self.pixmapGraphicsItem = QGraphicsPixmapItem(None, scene) 
153        self.setScene(scene)
[195]154       
[188]155        self.setMouseTracking(True)
156        self.viewport().setMouseTracking(True)
157       
[1248]158        self.setFocusPolicy(Qt.WheelFocus)
159       
[188]160    def SetPathway(self, pathway=None, objects=[]):
[1142]161        self.scene().clear()
[188]162        self.pathway = pathway
163        self.objects = objects
[1142]164        self.pathwayItem = GraphicsPathwayItem(pathway, objects, None, self.scene(), name_mapper=getattr(self.master, "uniqueGenesDict", {}))
165        self.scene().setSceneRect(self.pathwayItem.boundingRect())
166        self.updateTransform()
167   
168    def resizeEvent(self, event):
169        self.updateTransform()
170        return QGraphicsView.resizeEvent(self, event)
171           
172    def updateTransform(self):
173        if self.master.autoResize:
174            self.fitInView(self.scene().sceneRect().adjusted(-1, -1, 1, 1), Qt.KeepAspectRatio)
[188]175        else:
[1142]176            self.setTransform(QTransform())
[1248]177           
178    def paintEvent(self, event):
179        QGraphicsView.paintEvent(self, event)
180        if getattr(self, "_userMessage", None):
181            painter = QPainter(self.viewport())
182            font = QFont(self.font())
183            font.setPointSize(15)
184            painter.setFont(font)
185            painter.drawText(self.viewport().geometry(), Qt.AlignCenter, self._userMessage)
186            painter.end()
[1000]187       
[188]188   
189class OWKEGGPathwayBrowser(OWWidget):
[1142]190    settingsList = ["organismIndex", "geneAttrIndex", "autoCommit", "autoResize", "useReference", "useAttrNames", "caseSensitive", "showOrthology"]
[188]191    contextHandlers = {"":DomainContextHandler("",[ContextField("organismIndex", DomainContextHandler.Required + DomainContextHandler.IncludeMetaAttributes),
192                                                   ContextField("geneAttrIndex", DomainContextHandler.Required + DomainContextHandler.IncludeMetaAttributes),
193                                                   ContextField("useAttrNames", DomainContextHandler.Required + DomainContextHandler.IncludeMetaAttributes)])}
[1462]194    def __init__(self, parent=None, signalManager=None, name="KEGG Pathways"):
[1525]195        OWWidget.__init__(self, parent, signalManager, name, wantGraph=True)
[188]196        self.inputs = [("Examples", ExampleTable, self.SetData), ("Reference", ExampleTable, self.SetRefData)]
197        self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable)]
198        self.organismIndex = 0
199        self.geneAttrIndex = 0
200        self.autoCommit = False
201        self.autoResize = True
202        self.useReference = False
[214]203        self.useAttrNames = 0
[188]204        self.caseSensitive = True
[519]205        self.showOrthology = True
[188]206        self.autoFindBestOrg = False
207        self.loadSettings()
208
209        self.controlArea.setMaximumWidth(250)
[1248]210        box = OWGUI.widgetBox(self.controlArea, "Info")
211        self.infoLabel = OWGUI.widgetLabel(box, "No data on input\n")
[1000]212       
[1003]213        self.allOrganismCodes = {} 
[1534]214       
[1003]215        self.organismCodes = []
[188]216       
[1534]217        box = OWGUI.widgetBox(self.controlArea, "Organism")
218        self.organismComboBox = cb = OWGUI.comboBox(box, self,
219                                "organismIndex", 
220                                items=[],
221                                callback=self.OrganismSelectionCallback, 
222                                addSpace=True,
223                                debuggingEnabled=0)
224       
225        self.signalManager.freeze(self).push()
[1003]226       
227        box = OWGUI.widgetBox(self.controlArea, "Gene attribute")
[1534]228        self.geneAttrCombo = OWGUI.comboBox(box, self, "geneAttrIndex",
229                                            callback=self.Update)
230       
231        OWGUI.checkBox(box, self, "useAttrNames",
232                       "Use variable names", 
233                       disables=[(-1, self.geneAttrCombo)],
234                       callback=self.UseAttrNamesCallback)
235       
[216]236        self.geneAttrCombo.setDisabled(bool(self.useAttrNames))
237       
[188]238        OWGUI.separator(self.controlArea)
239       
[1534]240        OWGUI.checkBox(self.controlArea, self, "useReference",
241                       "From signal",
242                       box="Reference",
243                       callback=self.Update)
244       
[188]245        OWGUI.separator(self.controlArea)
246
[1534]247        OWGUI.checkBox(self.controlArea, self, "showOrthology",
248                       "Show pathways in full orthology",
249                       box="Orthology",
250                       callback=self.UpdateListView)
[188]251       
[1534]252        OWGUI.checkBox(self.controlArea, self, "autoResize",
253                       "Resize to fit",
254                       box="Image",
255                       callback=self.UpdatePathwayViewTransform)
256       
[1606]257        box = OWGUI.widgetBox(self.controlArea, "Cache Control")
258       
259        OWGUI.button(box, self, "Clear cache", 
260                     callback=self.ClearCache,
261                     tooltip="Clear all locally cached KEGG data.")
262       
[188]263        OWGUI.separator(self.controlArea)
264
265        box = OWGUI.widgetBox(self.controlArea, "Selection")
266        OWGUI.checkBox(box, self, "autoCommit", "Commit on update")
[1378]267        OWGUI.button(box, self, "Commit", callback=self.Commit, default=True)
[188]268        OWGUI.rubber(self.controlArea)
[195]269       
[188]270        spliter = QSplitter(Qt.Vertical, self.mainArea)
271        self.pathwayView = PathwayView(self, spliter)
[195]272        self.mainArea.layout().addWidget(spliter)
[188]273
[195]274        self.listView = QTreeWidget(spliter)
275        spliter.addWidget(self.listView)
276       
277        self.listView.setAllColumnsShowFocus(1)
278        self.listView.setColumnCount(4)
[1534]279        self.listView.setHeaderLabels(["Pathway", "P value", 
280                                       "Genes", "Reference"])
[195]281
282        self.listView.setSelectionMode(QAbstractItemView.SingleSelection)
283           
284        self.listView.setSortingEnabled(True)
[1534]285       
[188]286        self.listView.setMaximumHeight(200)
287       
[1534]288        self.connect(self.listView,
289                     SIGNAL("itemSelectionChanged()"),
290                     self.UpdatePathwayView)
[188]291       
[1534]292        self.connect(self.graphButton,
293                     SIGNAL("clicked()"),
294                     self.saveGraph)
[1525]295       
[195]296        self.ctrlPressed = False
[188]297        self.selectedObjects = defaultdict(list)
[212]298        self.data = None
[188]299        self.refData = None
300       
[898]301        self.resize(800, 600)
302       
[1534]303        self.connect(self,
304                     SIGNAL("widgetStateChanged(QString, int, QString)"),
305                     self.onStateChange)
306       
307        self.has_new_data = False
308        self.has_new_reference_set = False
309       
310        self.setEnabled(False)
311        QTimer.singleShot(100, self.UpdateOrganismComboBox)
312       
[1248]313       
[1003]314    def UpdateOrganismComboBox(self):
[1582]315        # First try to import suds
316        try:
317            import suds
318        except ImportError:
319            QMessageBox.warning(self,
320                "'suds' library required.",
321                '<p>Please install \
322<a href="http://pypi.python.org/pypi/suds">suds</a> library \
323to use KEGG Pathways widget.</p>'
324                )
325           
[1003]326        try:
[1534]327            genome = obiKEGG.KEGGGenome()
328            all_codes = list(genome)
[1003]329           
330            self.allOrganismCodes = genome
331   
332            essential = genome.essential_organisms()
[1534]333            common = genome.common_organisms()
334            common = [c for c in common if c not in essential]
[1003]335           
[1534]336            self.infoLabel.setText("Fetching organism definitions\n")
337           
338            pb = OWGUI.ProgressBar(self, len(essential + common))
339            codes = []
340            for i, code in enumerate(essential + common):
341                codes.append((code, genome[code].definition))
342                pb.advance()
343            pb.finish()
344            self.organismCodes = codes
345           
[1003]346            items = [desc for code, desc in self.organismCodes]
[1534]347           
[1003]348            self.organismCodes = [code for code, desc in self.organismCodes]
[1534]349
350            # TODO: Add option to specify additional organisms not
351            # in the common list.
352
[1003]353            self.organismComboBox.addItems(items)
354        finally:
[1534]355            self.setEnabled(True)
356            self.infoLabel.setText("No data on input\n")
[1272]357            self.signalManager.freeze(self).pop() #setFreeze(0)
[1003]358
[1534]359    def Clear(self):
360        self.infoLabel.setText("No data on input\n")
361        self.listView.clear()
362        self.ClearPathway()
363       
364        self.send("Selected Examples", None)
365        self.send("Unselected Examples", None)
366       
367    def ClearPathway(self):
368        self.pathwayView.SetPathway(None)
369        self.selectedObjects = defaultdict(list)
[1003]370       
[188]371    def SetData(self, data=None):
372        self.closeContext()
373        self.data = data
[1248]374        self.warning(0)
[1534]375        if data is not None:
[1142]376            self.SetGeneAttrCombo()
[1118]377            taxid = data_hints.get_hint(data, "taxid", None)
[1142]378            if taxid:
379                try:
380                    code = obiKEGG.from_taxid(taxid)
381                    self.organismIndex = self.organismCodes.index(code)
382                except Exception, ex:
[1534]383#                    self.log.exception(self, level=self.log.INFO)
[1142]384                    print ex, taxid
[1099]385           
[1118]386            self.useAttrNames = data_hints.get_hint(data, "genesinrows", self.useAttrNames)
[1099]387           
[188]388            self.openContext("", data)
389        else:
[1534]390            self.Clear()
391           
392        self.has_new_data = True
[188]393
394    def SetRefData(self, data=None):
395        self.refData = data
[1534]396        self.has_new_reference_set = True
397       
398    def handleNewSignals(self):
399        if self.has_new_data or (self.has_new_reference_set and \
400                                 self.useReference):
[188]401            self.Update()
[1534]402           
403            self.has_new_data = False
404            self.has_new_reference_set = False
405       
[188]406    def UseAttrNamesCallback(self):
407        self.Update()
408
[1534]409    def OrganismSelectionCallback(self):
410        self.Update()
411       
[1142]412    def SetGeneAttrCombo(self):
[1534]413        self.geneAttrCandidates = self.data.domain.attributes + \
414                                  self.data.domain.getmetas().values()
415        self.geneAttrCandidates = filter(lambda v:v.varType in [orange.VarTypes.Discrete,
416                                                                orange.VarTypes.String],
417                                         self.geneAttrCandidates)
[188]418        self.geneAttrCombo.clear()
[1534]419       
[195]420        self.geneAttrCombo.addItems([var.name for var in self.geneAttrCandidates])
[1003]421           
[188]422    def UpdateListView(self):
[1248]423        self.bestPValueItem = None
[188]424        self.listView.clear()
[212]425        if not self.data:
426            return
[1003]427        allPathways = self.org.pathways()
428        allRefPathways = obiKEGG.pathways("map")
[1534]429#        self.progressBarFinished()
[188]430        items = []
[1606]431        self.progressBarInit()
[1534]432        kegg_pathways = obiKEGG.KEGGPathways()
[1606]433        kegg_pathways.pre_cache(self.pathways.keys(),
434                                progress_callback=self.progressBarSet)
435        self.progressBarFinished()
[519]436        if self.showOrthology:
[1003]437            self.koOrthology = obiKEGG.KEGGBrite("ko00001")
[188]438            self.listView.setRootIsDecorated(True)
439            path_ids = set([s[-5:] for s in self.pathways.keys()])
[1000]440            def _walkCollect(koEntry):
441                num = koEntry.title[:5] if koEntry.title else None
442                if num  in path_ids:
[1577]443                    return [koEntry] + reduce(lambda li,c:li+_walkCollect(c), [child for child in koEntry.entries], [])
[188]444                else:
[1577]445                    c = reduce(lambda li,c:li+_walkCollect(c), [child for child in koEntry.entries], [])
[1000]446                    return c + (c and [koEntry] or [])
[188]447            allClasses = reduce(lambda li1, li2: li1+li2, [_walkCollect(c) for c in self.koOrthology], [])
[1000]448            def _walkCreate(koEntry, lvItem):
[195]449                item = QTreeWidgetItem(lvItem)
[1000]450                id = "path:"+self.organismCodes[min(self.organismIndex, len(self.organismCodes)-1)] + koEntry.title[:5]
[1534]451                p = kegg_pathways.get_entry(id)
[1000]452                if koEntry.title[:5] in path_ids:
[1534]453                    if p is None:
454                        # In case the genesets still have obsolete entries
455                        name = koEntry.title
456                    else:
457                        name = p.name
[188]458                    genes, p_value, ref = self.pathways[id]
[1534]459                    item.setText(0, name)
[188]460                    item.setText(1, "%.5f" % p_value)
461                    item.setText(2, "%i of %i" %(len(genes), len(self.genes)))
462                    item.setText(3, "%i of %i" %(ref, len(self.referenceGenes)))
[1534]463                    item.pathway_id = id if p is not None else None
[188]464                else:
[1534]465                    item.setText(0, p.name if id in allPathways else koEntry.title)
[188]466                    if id in allPathways:
467                        item.pathway_id = id
[1000]468                    elif "path:map" + koEntry.title[:5] in allRefPathways:
469                        item.pathway_id = "path:map" + koEntry.title[:5]
[188]470                    else:
471                        item.pathway_id = None
472               
[1577]473                for child in koEntry.entries:
[188]474                    if child in allClasses:
[1000]475                        _walkCreate(child, item)
[188]476           
[1000]477            for koEntry in self.koOrthology:
478                if koEntry in allClasses:
479                    _walkCreate(koEntry, self.listView)
[195]480                   
481            self.listView.update()
[188]482        else:
483            self.listView.setRootIsDecorated(False)
484            pathways = self.pathways.items()
485            pathways.sort(lambda a,b:cmp(a[1][1], b[1][1]))
486            for id, (genes, p_value, ref) in pathways:
[206]487                item = QTreeWidgetItem(self.listView)
[1534]488                item.setText(0, kegg_pathways.get_entry(id).name)
[188]489                item.setText(1, "%.5f" % p_value)
490                item.setText(2, "%i of %i" %(len(genes), len(self.genes)))
491                item.setText(3, "%i of %i" %(ref, len(self.referenceGenes)))
492                item.pathway_id = id
493                items.append(item)
[195]494               
[188]495        self.bestPValueItem = items and items[0] or None
[195]496        self.listView.expandAll()
[898]497        for i in range(4):
498            self.listView.resizeColumnToContents(i)
[1248]499           
500        if self.bestPValueItem:
501            self.listView.selectionModel().select(self.listView.indexFromItem(self.bestPValueItem), QItemSelectionModel.ClearAndSelect)
[188]502
[195]503    def UpdatePathwayView(self):
504        items = self.listView.selectedItems()
[188]505       
[195]506        if len(items) > 0:
507            item = items[0]
[1248]508        else:
509            item = None
[195]510           
[1248]511        self.selectedObjects = defaultdict(list)
512        self.Commit()
513        item = item or self.bestPValueItem
514        if not item or not item.pathway_id:
515            self.pathwayView.SetPathway(None)
516            return
[1534]517       
518        if USE_THREADING:
519            result = {}
520            def call(pathway_id):
521                result["pathway"] = p = obiKEGG.KEGGPathway(pathway_id)
[1579]522                p._get_kgml() # makes sure the kgml file is downloaded
523                p._get_image_filename() # makes sure the image is downloaded
[1534]524               
525            self.setEnabled(False)
526            try:
527                thread = threading.Thread(None,
528                                          call,
529                                          name="get_kgml_and_image",
530                                          args=(item.pathway_id,))
531                thread.start()
532                while thread.is_alive():
533                    thread.join(timeout=0.025)
534                    qApp.processEvents()
535            finally:
536                self.setEnabled(True)
537            if "pathway" in result:
538                self.pathway = result["pathway"]
539            else:
540                raise Exception("Could not get kgml and  pathway image")
541        else:
542            self.pathway = obiKEGG.KEGGPathway(item.pathway_id)
543           
[1248]544        self.pathwayView.SetPathway(self.pathway, self.pathways.get(item.pathway_id, [[]])[0])
[195]545           
[1534]546    def UpdatePathwayViewTransform(self):
547        self.pathwayView.updateTransform()
548       
[188]549    def Update(self):
550        if not self.data:
551            return
552        self.error(0)
[211]553        self.information(0)
[1016]554        pb = OWGUI.ProgressBar(self, 100)
[188]555        if self.useAttrNames:
556            genes = [str(v.name).strip() for v in self.data.domain.attributes]
557        elif self.geneAttrCandidates:
558            geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates)-1)]
559            genes = [str(e[geneAttr]) for e in self.data if not e[geneAttr].isSpecial()]
[211]560            if any("," in gene for gene in genes):
561                genes = reduce(list.__add__, (split_and_strip(gene, ",") for gene in genes), [])
[1534]562                self.information(0, "Separators detected in input gene names. Assuming multiple genes per instance.")
[188]563        else:
[1534]564            self.error(0, "Cannot extract gene names from input")
[188]565            genes = []
[1003]566        org_code = self.organismCodes[min(self.organismIndex, len(self.organismCodes)-1)]
[1534]567       
568        if USE_THREADING:
569            result = {}
570            def callable(*args, **kwargs):
571                result["org"] = org = obiKEGG.KEGGOrganism(org_code)
572                # Make sure genes are cached for global reference set
573                result["genes"] = org.genes.keys()
574               
575            self.setEnabled(False)
576            try:
577                thread = threading.Thread(None, callable,
578                                          name="get_organism_genes",
579                                          )
580                thread.start()
581                while thread.is_alive():
582                    thread.join(timeout=0.025)
583                    qApp.processEvents()
584            finally:
585                self.setEnabled(True)
586           
587            if "org" in result:
588                org = result["org"]
589            else:
590                raise Exception("Could not get organism genes")
591        else:
592            org = obiKEGG.KEGGOrganism(org_code)
593       
594        uniqueGenes, conflicting, unknown = org.get_unique_gene_ids(set(genes), self.caseSensitive)
[1331]595        genesCount = len(set(genes))
596        self.infoLabel.setText("%i unique gene names on input\n%i (%.1f%%) genes names matched" % (genesCount, len(uniqueGenes), 100.0*len(uniqueGenes)/genesCount if genes else 0.0)) 
[1534]597       
[211]598        self.information(1)
[188]599        if self.useReference and self.refData:
600            if self.useAttrNames:
601                reference = [str(v.name).strip() for v in self.refData]
602            else:
603                geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates)-1)]
604                reference = [str(e[geneAttr]) for e in self.refData if not e[geneAttr].isSpecial()]
[211]605                if any("," in gene for gene in reference):
606                    reference = reduce(list.__add__, (split_and_strip(gene, ",") for gene in reference), [])
607                    self.information(1, "Separators detected in reference gene names. Assuming multiple genes per example.")
[1534]608            uniqueRefGenes, conflicting, unknown = org.get_unique_gene_ids(set(reference), self.caseSensitive)
[188]609            self.referenceGenes = reference = uniqueRefGenes.keys()
610        else:
[1534]611            self.referenceGenes = reference = org.get_genes()
[188]612        self.uniqueGenesDict = uniqueGenes
613        self.genes = uniqueGenes.keys()
614        self.revUniqueGenesDict = dict([(val, key) for key, val in self.uniqueGenesDict.items()])
[1534]615       
616        taxid = obiKEGG.to_taxid(org.org_code)
617        r_tax_map = dict((v,k) for k, v in obiKEGG.KEGGGenome.TAXID_MAP.items())
618        if taxid in r_tax_map:
619            taxid = r_tax_map[taxid]
620           
621        with orngServerFiles.DownloadProgress.setredirect(self.progressBarSet):
[1554]622            orngServerFiles.update(obiGeneSets.sfdomain, "index.pck")
623            kegg_gs_collections = list(obiGeneSets.collections((("KEGG", "pathways"), taxid)))
[1534]624       
625        if USE_THREADING:
626            result = {}
627            def callable(*args, **kwargs):
628#                result["result"] = org.get_enriched_pathways(*args, **kwargs)
629                result["result"] = pathway_enrichment(*args, **kwargs)
630           
631            self.setEnabled(False)
632            try:
633                thread = threading.Thread(None, callable,
634                                          name="get_enriched_pathways",
635                                          args=(kegg_gs_collections,
636                                                self.genes, 
637                                                reference),
638                                          kwargs={"callback": 
639                                                  threading_queued_invoke(self,
[1606]640                                                  lambda value:self.progressBarSet(value))}
[1534]641                                          )
642               
643                thread.start()
644                while thread.is_alive():
645                    thread.join(timeout=0.025)
646                    qApp.processEvents()
647            finally:
648                self.setEnabled(True)
649               
650            if "result" in result:
651                self.pathways = result["result"]
652            else:
653                raise Exception('Could not get enriched pathways')
[1606]654           
655           
[1534]656        else:
657            self.pathways = org.get_enriched_pathways(self.genes, reference,
[1606]658                                                      callback=lambda value: self.progressBarSet(value))
[1534]659       
660        self.org = org
[1248]661        if not self.pathways:
662            self.warning(0, "No enriched pathways found.")
663        else:
664            self.warning(0)
[1534]665       
[188]666        self.UpdateListView()
[1016]667        pb.finish()
[1534]668   
[188]669
670    def SelectObjects(self, objs):
671        if (not self.selectedObjects or self.ctrlPressed) and not objs:
672            return
673        if self.ctrlPressed:
[1000]674            for id, graphics in objs:
675                graphics = tuple(sorted(graphics.items()))
676                if id in self.selectedObjects[graphics]:
677                    self.selectedObjects[graphics].pop(self.selectedObjects[graphics].index(id))
678                    if not self.selectedObjects[graphics]:
679                        del self.selectedObjects[graphics]
[188]680                else:
[1000]681                    self.selectedObjects[graphics].append(id)
[188]682        else:
683            self.selectedObjects.clear()
[1000]684            for id, graphics in objs:
685                graphics = tuple(sorted(graphics.items()))
686                self.selectedObjects[graphics].append(id)
[188]687        if self.autoCommit:
688            self.Commit()
689           
690
691    def Commit(self):
[212]692        if self.data:
[1142]693            selectedItems = self.pathwayView.scene().selectedItems()
694            selectedGenes = reduce(set.union, [item.marked_objects for item in selectedItems], set())
695           
[212]696            if self.useAttrNames:
697                selectedVars = [self.data.domain[self.uniqueGenesDict[gene]] for gene in selectedGenes]
698                newDomain = orange.Domain(selectedVars ,0)
[1099]699                data = orange.ExampleTable(newDomain, self.data)
700                self.send("Selected Examples", data)
[1142]701            elif self.geneAttrCandidates:
[212]702                geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates)-1)]
703                selectedExamples = []
704                otherExamples = []
705                for ex in self.data:
706                    names = [self.revUniqueGenesDict.get(name, None) for name in split_and_strip(str(ex[geneAttr]), ",")]
707                    if any(name and name in selectedGenes for name in names):
708                        selectedExamples.append(ex)
709                    else:
710                        otherExamples.append(ex)
[1099]711                       
712                if selectedExamples:
713                    selectedExamples = orange.ExampleTable(selectedExamples)
714                else:
715                    selectedExamples = None
716                   
717                if otherExamples:
718                    otherExamples = orange.ExampleTable(otherExamples)
719                else:
720                    otherExamples = None
721                   
722                self.send("Selected Examples", selectedExamples)
723                self.send("Unselected Examples", otherExamples)
[188]724        else:
[212]725            self.send("Selected Examples", None)
726            self.send("Unselected Examples", None)
[188]727       
[1606]728    def ClearCache(self):
[1716]729        from ..obiKEGG import caching
[1606]730        try:
731            caching.clear_cache()
732        except Exception, ex:
733            QMessageBox.warning(self, "Cache clear", 
734                ex.args[0])
735           
736       
[188]737    def keyPressEvent(self, key):
738        if key.key()==Qt.Key_Control:
739            self.ctrlPressed=True
740        else:
741            OWWidget.keyPressEvent(self, key)
742
743    def keyReleaseEvent(self, key):
744        if key.key()==Qt.Key_Control:
745            self.ctrlPressed=False
746        else:
747            OWWidget.keyReleaseEvent(self, key)
[1248]748           
749    def onStateChange(self, stateType, id, text):
750        if stateType == "Warning":
751            self.pathwayView._userMessage = text
752            self.pathwayView.viewport().update()
753           
[1525]754    def saveGraph(self):
[1632]755        from Orange.OrangeWidgets.OWDlgs import OWChooseImageSizeDlg
[1525]756        sizeDlg = OWChooseImageSizeDlg(self.pathwayView.scene(), parent=self)
757        sizeDlg.exec_()
[188]758
[1534]759    @pyqtSignature("queuedInvoke(PyQt_PyObject)")
760    def queuedInvoke(self, func):
761        func()
762       
763    def progressBarSet(self, value):
764#        print "Enter"
765        if not getattr(self, "_in_progress_update", False):
766            self._in_progress_update = True
767            try:
768                OWWidget.progressBarSet(self, value)
769            finally:
770                self._in_progress_update = False
771#        else:
772#            print "====="
773       
774#        print "Exit"
775   
776    def onDeleteWidget(self):
777        """ Called before the widget is removed from the canvas.
778        """
779        self.org = None
780        import gc
781        gc.collect() # Force collection
782       
783    def UpdateToLatestPathways(self):
784        pass       
785         
[1632]786from .. import obiProb
[1534]787
788def pathway_enrichment(genesets, genes, reference, prob=None, callback=None):
789    result_sets = []
790    p_values = []
791    if prob is None:
792        prob = obiProb.Hypergeometric()
793       
794    for i, gs in enumerate(genesets):
795        cluster = gs.genes.intersection(genes)
796        ref = gs.genes.intersection(reference)
797        k = len(cluster)
798        N = len(reference)
799        m = len(ref)
800        n = len(genes)
801        if k:
802            p_val = prob.p_value(k, N, m, n)
803            result_sets.append((gs.id, cluster, ref))
804            p_values.append(p_val)
805        if callback is not None:
[1554]806            callback(100.0 * i / len(genesets))
[1534]807   
808    # FDR correction
809    p_values = obiProb.FDR(p_values)
810   
811    return dict([(id, (genes, p_val, len(ref))) \
812                 for (id, genes, ref), p_val in zip(result_sets, p_values)]
813                )
814   
[188]815if __name__=="__main__":
816    app = QApplication(sys.argv)
[1534]817    data = orange.ExampleTable("brown-selected.tab")
[188]818    w = OWKEGGPathwayBrowser()
[1142]819    w.UpdateOrganismComboBox()
[206]820##    app.setMainWidget(w)
[188]821    w.show()
[1554]822    w.SetData(orange.ExampleTable(data[:]))
[1534]823    QTimer.singleShot(10, w.handleNewSignals)
[206]824    app.exec_()
[188]825    w.saveSettings()
Note: See TracBrowser for help on using the repository browser.