source: orange-bioinformatics/widgets/OWKEGGPathwayBrowser.py @ 1582:32734bec7ddd

Revision 1582:32734bec7ddd, 32.2 KB checked in by ales_erjavec, 2 years ago (diff)

Show a warning with a download link if suds is not installed.

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