source: orange-bioinformatics/_bioinformatics/widgets/OWKEGGPathwayBrowser.py @ 1701:761bf570c1f4

Revision 1701:761bf570c1f4, 32.7 KB checked in by Ales Erjavec <ales.erjavec@…>, 22 months ago (diff)

Added SVG icons for some widgets.

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