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

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

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

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