source: orange-bioinformatics/Orange/bioinformatics/widgets/OWKEGGPathwayBrowser.py @ 1625:cefeb35cbfc9

Revision 1625:cefeb35cbfc9, 32.6 KB checked in by mitar, 2 years ago (diff)

Moving files around.

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       
223        self.signalManager.freeze(self).push()
224       
225        box = OWGUI.widgetBox(self.controlArea, "Gene attribute")
226        self.geneAttrCombo = OWGUI.comboBox(box, self, "geneAttrIndex",
227                                            callback=self.Update)
228       
229        OWGUI.checkBox(box, self, "useAttrNames",
230                       "Use variable names", 
231                       disables=[(-1, self.geneAttrCombo)],
232                       callback=self.UseAttrNamesCallback)
233       
234        self.geneAttrCombo.setDisabled(bool(self.useAttrNames))
235       
236        OWGUI.separator(self.controlArea)
237       
238        OWGUI.checkBox(self.controlArea, self, "useReference",
239                       "From signal",
240                       box="Reference",
241                       callback=self.Update)
242       
243        OWGUI.separator(self.controlArea)
244
245        OWGUI.checkBox(self.controlArea, self, "showOrthology",
246                       "Show pathways in full orthology",
247                       box="Orthology",
248                       callback=self.UpdateListView)
249       
250        OWGUI.checkBox(self.controlArea, self, "autoResize",
251                       "Resize to fit",
252                       box="Image",
253                       callback=self.UpdatePathwayViewTransform)
254       
255        box = OWGUI.widgetBox(self.controlArea, "Cache Control")
256       
257        OWGUI.button(box, self, "Clear cache", 
258                     callback=self.ClearCache,
259                     tooltip="Clear all locally cached KEGG data.")
260       
261        OWGUI.separator(self.controlArea)
262
263        box = OWGUI.widgetBox(self.controlArea, "Selection")
264        OWGUI.checkBox(box, self, "autoCommit", "Commit on update")
265        OWGUI.button(box, self, "Commit", callback=self.Commit, default=True)
266        OWGUI.rubber(self.controlArea)
267       
268        spliter = QSplitter(Qt.Vertical, self.mainArea)
269        self.pathwayView = PathwayView(self, spliter)
270        self.mainArea.layout().addWidget(spliter)
271
272        self.listView = QTreeWidget(spliter)
273        spliter.addWidget(self.listView)
274       
275        self.listView.setAllColumnsShowFocus(1)
276        self.listView.setColumnCount(4)
277        self.listView.setHeaderLabels(["Pathway", "P value", 
278                                       "Genes", "Reference"])
279
280        self.listView.setSelectionMode(QAbstractItemView.SingleSelection)
281           
282        self.listView.setSortingEnabled(True)
283       
284        self.listView.setMaximumHeight(200)
285       
286        self.connect(self.listView,
287                     SIGNAL("itemSelectionChanged()"),
288                     self.UpdatePathwayView)
289       
290        self.connect(self.graphButton,
291                     SIGNAL("clicked()"),
292                     self.saveGraph)
293       
294        self.ctrlPressed = False
295        self.selectedObjects = defaultdict(list)
296        self.data = None
297        self.refData = None
298       
299        self.resize(800, 600)
300       
301        self.connect(self,
302                     SIGNAL("widgetStateChanged(QString, int, QString)"),
303                     self.onStateChange)
304       
305        self.has_new_data = False
306        self.has_new_reference_set = False
307       
308        self.setEnabled(False)
309        QTimer.singleShot(100, self.UpdateOrganismComboBox)
310       
311       
312    def UpdateOrganismComboBox(self):
313        # First try to import suds
314        try:
315            import suds
316        except ImportError:
317            QMessageBox.warning(self,
318                "'suds' library required.",
319                '<p>Please install \
320<a href="http://pypi.python.org/pypi/suds">suds</a> library \
321to use KEGG Pathways widget.</p>'
322                )
323           
324        try:
325            genome = obiKEGG.KEGGGenome()
326            all_codes = list(genome)
327           
328            self.allOrganismCodes = genome
329   
330            essential = genome.essential_organisms()
331            common = genome.common_organisms()
332            common = [c for c in common if c not in essential]
333           
334            self.infoLabel.setText("Fetching organism definitions\n")
335           
336            pb = OWGUI.ProgressBar(self, len(essential + common))
337            codes = []
338            for i, code in enumerate(essential + common):
339                codes.append((code, genome[code].definition))
340                pb.advance()
341            pb.finish()
342            self.organismCodes = codes
343           
344            items = [desc for code, desc in self.organismCodes]
345           
346            self.organismCodes = [code for code, desc in self.organismCodes]
347
348            # TODO: Add option to specify additional organisms not
349            # in the common list.
350
351            self.organismComboBox.addItems(items)
352        finally:
353            self.setEnabled(True)
354            self.infoLabel.setText("No data on input\n")
355            self.signalManager.freeze(self).pop() #setFreeze(0)
356
357    def Clear(self):
358        self.infoLabel.setText("No data on input\n")
359        self.listView.clear()
360        self.ClearPathway()
361       
362        self.send("Selected Examples", None)
363        self.send("Unselected Examples", None)
364       
365    def ClearPathway(self):
366        self.pathwayView.SetPathway(None)
367        self.selectedObjects = defaultdict(list)
368       
369    def SetData(self, data=None):
370        self.closeContext()
371        self.data = data
372        self.warning(0)
373        if data is not None:
374            self.SetGeneAttrCombo()
375            taxid = data_hints.get_hint(data, "taxid", None)
376            if taxid:
377                try:
378                    code = obiKEGG.from_taxid(taxid)
379                    self.organismIndex = self.organismCodes.index(code)
380                except Exception, ex:
381#                    self.log.exception(self, level=self.log.INFO)
382                    print ex, taxid
383           
384            self.useAttrNames = data_hints.get_hint(data, "genesinrows", self.useAttrNames)
385           
386            self.openContext("", data)
387        else:
388            self.Clear()
389           
390        self.has_new_data = True
391
392    def SetRefData(self, data=None):
393        self.refData = data
394        self.has_new_reference_set = True
395       
396    def handleNewSignals(self):
397        if self.has_new_data or (self.has_new_reference_set and \
398                                 self.useReference):
399            self.Update()
400           
401            self.has_new_data = False
402            self.has_new_reference_set = False
403       
404    def UseAttrNamesCallback(self):
405        self.Update()
406
407    def OrganismSelectionCallback(self):
408        self.Update()
409       
410    def SetGeneAttrCombo(self):
411        self.geneAttrCandidates = self.data.domain.attributes + \
412                                  self.data.domain.getmetas().values()
413        self.geneAttrCandidates = filter(lambda v:v.varType in [orange.VarTypes.Discrete,
414                                                                orange.VarTypes.String],
415                                         self.geneAttrCandidates)
416        self.geneAttrCombo.clear()
417       
418        self.geneAttrCombo.addItems([var.name for var in self.geneAttrCandidates])
419           
420    def UpdateListView(self):
421        self.bestPValueItem = None
422        self.listView.clear()
423        if not self.data:
424            return
425        allPathways = self.org.pathways()
426        allRefPathways = obiKEGG.pathways("map")
427#        self.progressBarFinished()
428        items = []
429        self.progressBarInit()
430        kegg_pathways = obiKEGG.KEGGPathways()
431        kegg_pathways.pre_cache(self.pathways.keys(),
432                                progress_callback=self.progressBarSet)
433        self.progressBarFinished()
434        if self.showOrthology:
435            self.koOrthology = obiKEGG.KEGGBrite("ko00001")
436            self.listView.setRootIsDecorated(True)
437            path_ids = set([s[-5:] for s in self.pathways.keys()])
438            def _walkCollect(koEntry):
439                num = koEntry.title[:5] if koEntry.title else None
440                if num  in path_ids:
441                    return [koEntry] + reduce(lambda li,c:li+_walkCollect(c), [child for child in koEntry.entries], [])
442                else:
443                    c = reduce(lambda li,c:li+_walkCollect(c), [child for child in koEntry.entries], [])
444                    return c + (c and [koEntry] or [])
445            allClasses = reduce(lambda li1, li2: li1+li2, [_walkCollect(c) for c in self.koOrthology], [])
446            def _walkCreate(koEntry, lvItem):
447                item = QTreeWidgetItem(lvItem)
448                id = "path:"+self.organismCodes[min(self.organismIndex, len(self.organismCodes)-1)] + koEntry.title[:5]
449                p = kegg_pathways.get_entry(id)
450                if koEntry.title[:5] in path_ids:
451                    if p is None:
452                        # In case the genesets still have obsolete entries
453                        name = koEntry.title
454                    else:
455                        name = p.name
456                    genes, p_value, ref = self.pathways[id]
457                    item.setText(0, name)
458                    item.setText(1, "%.5f" % p_value)
459                    item.setText(2, "%i of %i" %(len(genes), len(self.genes)))
460                    item.setText(3, "%i of %i" %(ref, len(self.referenceGenes)))
461                    item.pathway_id = id if p is not None else None
462                else:
463                    item.setText(0, p.name if id in allPathways else koEntry.title)
464                    if id in allPathways:
465                        item.pathway_id = id
466                    elif "path:map" + koEntry.title[:5] in allRefPathways:
467                        item.pathway_id = "path:map" + koEntry.title[:5]
468                    else:
469                        item.pathway_id = None
470               
471                for child in koEntry.entries:
472                    if child in allClasses:
473                        _walkCreate(child, item)
474           
475            for koEntry in self.koOrthology:
476                if koEntry in allClasses:
477                    _walkCreate(koEntry, self.listView)
478                   
479            self.listView.update()
480        else:
481            self.listView.setRootIsDecorated(False)
482            pathways = self.pathways.items()
483            pathways.sort(lambda a,b:cmp(a[1][1], b[1][1]))
484            for id, (genes, p_value, ref) in pathways:
485                item = QTreeWidgetItem(self.listView)
486                item.setText(0, kegg_pathways.get_entry(id).name)
487                item.setText(1, "%.5f" % p_value)
488                item.setText(2, "%i of %i" %(len(genes), len(self.genes)))
489                item.setText(3, "%i of %i" %(ref, len(self.referenceGenes)))
490                item.pathway_id = id
491                items.append(item)
492               
493        self.bestPValueItem = items and items[0] or None
494        self.listView.expandAll()
495        for i in range(4):
496            self.listView.resizeColumnToContents(i)
497           
498        if self.bestPValueItem:
499            self.listView.selectionModel().select(self.listView.indexFromItem(self.bestPValueItem), QItemSelectionModel.ClearAndSelect)
500
501    def UpdatePathwayView(self):
502        items = self.listView.selectedItems()
503       
504        if len(items) > 0:
505            item = items[0]
506        else:
507            item = None
508           
509        self.selectedObjects = defaultdict(list)
510        self.Commit()
511        item = item or self.bestPValueItem
512        if not item or not item.pathway_id:
513            self.pathwayView.SetPathway(None)
514            return
515       
516        if USE_THREADING:
517            result = {}
518            def call(pathway_id):
519                result["pathway"] = p = obiKEGG.KEGGPathway(pathway_id)
520                p._get_kgml() # makes sure the kgml file is downloaded
521                p._get_image_filename() # makes sure the image is downloaded
522               
523            self.setEnabled(False)
524            try:
525                thread = threading.Thread(None,
526                                          call,
527                                          name="get_kgml_and_image",
528                                          args=(item.pathway_id,))
529                thread.start()
530                while thread.is_alive():
531                    thread.join(timeout=0.025)
532                    qApp.processEvents()
533            finally:
534                self.setEnabled(True)
535            if "pathway" in result:
536                self.pathway = result["pathway"]
537            else:
538                raise Exception("Could not get kgml and  pathway image")
539        else:
540            self.pathway = obiKEGG.KEGGPathway(item.pathway_id)
541           
542        self.pathwayView.SetPathway(self.pathway, self.pathways.get(item.pathway_id, [[]])[0])
543           
544    def UpdatePathwayViewTransform(self):
545        self.pathwayView.updateTransform()
546       
547    def Update(self):
548        if not self.data:
549            return
550        self.error(0)
551        self.information(0)
552        pb = OWGUI.ProgressBar(self, 100)
553        if self.useAttrNames:
554            genes = [str(v.name).strip() for v in self.data.domain.attributes]
555        elif self.geneAttrCandidates:
556            geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates)-1)]
557            genes = [str(e[geneAttr]) for e in self.data if not e[geneAttr].isSpecial()]
558            if any("," in gene for gene in genes):
559                genes = reduce(list.__add__, (split_and_strip(gene, ",") for gene in genes), [])
560                self.information(0, "Separators detected in input gene names. Assuming multiple genes per instance.")
561        else:
562            self.error(0, "Cannot extract gene names from input")
563            genes = []
564        org_code = self.organismCodes[min(self.organismIndex, len(self.organismCodes)-1)]
565       
566        if USE_THREADING:
567            result = {}
568            def callable(*args, **kwargs):
569                result["org"] = org = obiKEGG.KEGGOrganism(org_code)
570                # Make sure genes are cached for global reference set
571                result["genes"] = org.genes.keys()
572               
573            self.setEnabled(False)
574            try:
575                thread = threading.Thread(None, callable,
576                                          name="get_organism_genes",
577                                          )
578                thread.start()
579                while thread.is_alive():
580                    thread.join(timeout=0.025)
581                    qApp.processEvents()
582            finally:
583                self.setEnabled(True)
584           
585            if "org" in result:
586                org = result["org"]
587            else:
588                raise Exception("Could not get organism genes")
589        else:
590            org = obiKEGG.KEGGOrganism(org_code)
591       
592        uniqueGenes, conflicting, unknown = org.get_unique_gene_ids(set(genes), self.caseSensitive)
593        genesCount = len(set(genes))
594        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)) 
595       
596        self.information(1)
597        if self.useReference and self.refData:
598            if self.useAttrNames:
599                reference = [str(v.name).strip() for v in self.refData]
600            else:
601                geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates)-1)]
602                reference = [str(e[geneAttr]) for e in self.refData if not e[geneAttr].isSpecial()]
603                if any("," in gene for gene in reference):
604                    reference = reduce(list.__add__, (split_and_strip(gene, ",") for gene in reference), [])
605                    self.information(1, "Separators detected in reference gene names. Assuming multiple genes per example.")
606            uniqueRefGenes, conflicting, unknown = org.get_unique_gene_ids(set(reference), self.caseSensitive)
607            self.referenceGenes = reference = uniqueRefGenes.keys()
608        else:
609            self.referenceGenes = reference = org.get_genes()
610        self.uniqueGenesDict = uniqueGenes
611        self.genes = uniqueGenes.keys()
612        self.revUniqueGenesDict = dict([(val, key) for key, val in self.uniqueGenesDict.items()])
613       
614        taxid = obiKEGG.to_taxid(org.org_code)
615        r_tax_map = dict((v,k) for k, v in obiKEGG.KEGGGenome.TAXID_MAP.items())
616        if taxid in r_tax_map:
617            taxid = r_tax_map[taxid]
618           
619        with orngServerFiles.DownloadProgress.setredirect(self.progressBarSet):
620            orngServerFiles.update(obiGeneSets.sfdomain, "index.pck")
621            kegg_gs_collections = list(obiGeneSets.collections((("KEGG", "pathways"), taxid)))
622       
623        if USE_THREADING:
624            result = {}
625            def callable(*args, **kwargs):
626#                result["result"] = org.get_enriched_pathways(*args, **kwargs)
627                result["result"] = pathway_enrichment(*args, **kwargs)
628           
629            self.setEnabled(False)
630            try:
631                thread = threading.Thread(None, callable,
632                                          name="get_enriched_pathways",
633                                          args=(kegg_gs_collections,
634                                                self.genes, 
635                                                reference),
636                                          kwargs={"callback": 
637                                                  threading_queued_invoke(self,
638                                                  lambda value:self.progressBarSet(value))}
639                                          )
640               
641                thread.start()
642                while thread.is_alive():
643                    thread.join(timeout=0.025)
644                    qApp.processEvents()
645            finally:
646                self.setEnabled(True)
647               
648            if "result" in result:
649                self.pathways = result["result"]
650            else:
651                raise Exception('Could not get enriched pathways')
652           
653           
654        else:
655            self.pathways = org.get_enriched_pathways(self.genes, reference,
656                                                      callback=lambda value: self.progressBarSet(value))
657       
658        self.org = org
659        if not self.pathways:
660            self.warning(0, "No enriched pathways found.")
661        else:
662            self.warning(0)
663       
664        self.UpdateListView()
665        pb.finish()
666   
667
668    def SelectObjects(self, objs):
669        if (not self.selectedObjects or self.ctrlPressed) and not objs:
670            return
671        if self.ctrlPressed:
672            for id, graphics in objs:
673                graphics = tuple(sorted(graphics.items()))
674                if id in self.selectedObjects[graphics]:
675                    self.selectedObjects[graphics].pop(self.selectedObjects[graphics].index(id))
676                    if not self.selectedObjects[graphics]:
677                        del self.selectedObjects[graphics]
678                else:
679                    self.selectedObjects[graphics].append(id)
680        else:
681            self.selectedObjects.clear()
682            for id, graphics in objs:
683                graphics = tuple(sorted(graphics.items()))
684                self.selectedObjects[graphics].append(id)
685        if self.autoCommit:
686            self.Commit()
687           
688
689    def Commit(self):
690        if self.data:
691            selectedItems = self.pathwayView.scene().selectedItems()
692            selectedGenes = reduce(set.union, [item.marked_objects for item in selectedItems], set())
693           
694            if self.useAttrNames:
695                selectedVars = [self.data.domain[self.uniqueGenesDict[gene]] for gene in selectedGenes]
696                newDomain = orange.Domain(selectedVars ,0)
697                data = orange.ExampleTable(newDomain, self.data)
698                self.send("Selected Examples", data)
699            elif self.geneAttrCandidates:
700                geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates)-1)]
701                selectedExamples = []
702                otherExamples = []
703                for ex in self.data:
704                    names = [self.revUniqueGenesDict.get(name, None) for name in split_and_strip(str(ex[geneAttr]), ",")]
705                    if any(name and name in selectedGenes for name in names):
706                        selectedExamples.append(ex)
707                    else:
708                        otherExamples.append(ex)
709                       
710                if selectedExamples:
711                    selectedExamples = orange.ExampleTable(selectedExamples)
712                else:
713                    selectedExamples = None
714                   
715                if otherExamples:
716                    otherExamples = orange.ExampleTable(otherExamples)
717                else:
718                    otherExamples = None
719                   
720                self.send("Selected Examples", selectedExamples)
721                self.send("Unselected Examples", otherExamples)
722        else:
723            self.send("Selected Examples", None)
724            self.send("Unselected Examples", None)
725       
726    def ClearCache(self):
727        from obiKEGG2 import caching
728        try:
729            caching.clear_cache()
730        except Exception, ex:
731            QMessageBox.warning(self, "Cache clear", 
732                ex.args[0])
733           
734       
735    def keyPressEvent(self, key):
736        if key.key()==Qt.Key_Control:
737            self.ctrlPressed=True
738        else:
739            OWWidget.keyPressEvent(self, key)
740
741    def keyReleaseEvent(self, key):
742        if key.key()==Qt.Key_Control:
743            self.ctrlPressed=False
744        else:
745            OWWidget.keyReleaseEvent(self, key)
746           
747    def onStateChange(self, stateType, id, text):
748        if stateType == "Warning":
749            self.pathwayView._userMessage = text
750            self.pathwayView.viewport().update()
751           
752    def saveGraph(self):
753        from OWDlgs import OWChooseImageSizeDlg
754        sizeDlg = OWChooseImageSizeDlg(self.pathwayView.scene(), parent=self)
755        sizeDlg.exec_()
756
757    @pyqtSignature("queuedInvoke(PyQt_PyObject)")
758    def queuedInvoke(self, func):
759        func()
760       
761    def progressBarSet(self, value):
762#        print "Enter"
763        if not getattr(self, "_in_progress_update", False):
764            self._in_progress_update = True
765            try:
766                OWWidget.progressBarSet(self, value)
767            finally:
768                self._in_progress_update = False
769#        else:
770#            print "====="
771       
772#        print "Exit"
773   
774    def onDeleteWidget(self):
775        """ Called before the widget is removed from the canvas.
776        """
777        self.org = None
778        import gc
779        gc.collect() # Force collection
780       
781    def UpdateToLatestPathways(self):
782        pass       
783         
784import obiProb
785
786def pathway_enrichment(genesets, genes, reference, prob=None, callback=None):
787    result_sets = []
788    p_values = []
789    if prob is None:
790        prob = obiProb.Hypergeometric()
791       
792    for i, gs in enumerate(genesets):
793        cluster = gs.genes.intersection(genes)
794        ref = gs.genes.intersection(reference)
795        k = len(cluster)
796        N = len(reference)
797        m = len(ref)
798        n = len(genes)
799        if k:
800            p_val = prob.p_value(k, N, m, n)
801            result_sets.append((gs.id, cluster, ref))
802            p_values.append(p_val)
803        if callback is not None:
804            callback(100.0 * i / len(genesets))
805   
806    # FDR correction
807    p_values = obiProb.FDR(p_values)
808   
809    return dict([(id, (genes, p_val, len(ref))) \
810                 for (id, genes, ref), p_val in zip(result_sets, p_values)]
811                )
812   
813if __name__=="__main__":
814    app = QApplication(sys.argv)
815    data = orange.ExampleTable("brown-selected.tab")
816    w = OWKEGGPathwayBrowser()
817    w.UpdateOrganismComboBox()
818##    app.setMainWidget(w)
819    w.show()
820    w.SetData(orange.ExampleTable(data[:]))
821    QTimer.singleShot(10, w.handleNewSignals)
822    app.exec_()
823    w.saveSettings()
Note: See TracBrowser for help on using the repository browser.