source: orange-bioinformatics/_bioinformatics/widgets/OWKEGGPathwayBrowser.py @ 1712:bcd52ead3d93

Revision 1712:bcd52ead3d93, 32.8 KB checked in by markotoplak, 20 months ago (diff)

Classes for storing gene set data moved to Orange.bio.geneset. obiGeneSets adapted to make new pickled classes.

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