source: orange-bioinformatics/widgets/OWKEGGPathwayBrowser.py @ 1272:c9926ac6d345

Revision 1272:c9926ac6d345, 25.2 KB checked in by ales_erjavec <ales.erjavec@…>, 3 years ago (diff)
  • reworked the OWConcurrent API
  • added helper methods in OWBaseWidget for concurrency
  • signalManager is aware of blocking widgets, but for the moment this is useless
  • reworked the signal managers signal "freeze" functionality (signal processing can be frozen at any time in the GUI by a new Pause-Play button)
  • added Dynamic output signals (for now in use only by "Load model" and "Python Script" widget)
Line 
1"""
2<name>KEGG Pathway Browser</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 webbrowser
15
16from OWWidget import *
17import OWGUI
18from collections import defaultdict
19
20from orngDataCaching import data_hints
21
22def split_and_strip(string, sep=None):
23    return [s.strip() for s in string.split(sep)]
24
25class EntryGraphicsItem(QGraphicsPathItem):
26    def __init__(self, graphics, *args):
27        QGraphicsPathItem.__init__(self, *args)
28        path = QPainterPath()
29        x, y, w, h = [int(graphics.get(c, 0)) for c in ["x", "y", "width", "height"]]
30        type = graphics.get("type", "rectangle")
31        if type == "rectangle":
32            path.addRect(QRectF(x - w/2, y - h/2, w, h))
33        elif type == "roundrectangle":
34            path.addRoundedRect(QRectF(x - w/2, y - h/2, w, h), 10, 10)
35        elif type == "circle":
36            path.addEllipse(QRectF(x - w/2, y - h/2, w, h))
37           
38        self.setPath(path)
39        self.setAcceptHoverEvents(True)
40        self._actions = []
41        self.link = None
42       
43    def hoverEnterEvent(self, event):
44        self.setBrush(QBrush(QColor(0, 100, 0, 100)))
45       
46    def hoverLeaveEvent(self, event):
47        self.setBrush(QBrush(Qt.NoBrush))
48       
49    def contextMenuEvent(self, event):
50        if self._actions:
51            self._menu = menu = QMenu()
52            for action in self._actions:
53                menu.addAction(action)
54            menu.popup(event.screenPos())
55           
56    def itemChange(self, change, value):
57        if change == QGraphicsItem.ItemSelectedHasChanged:
58            self.setPen(QPen(Qt.red if self.isSelected() else Qt.blue, 2))
59           
60        return QGraphicsPathItem.itemChange(self, change, value)
61           
62class GraphicsPathwayItem(QGraphicsPixmapItem):
63    def __init__(self, pathway, objects, *args, **kwargs):
64        QGraphicsPixmapItem.__init__(self, *args)
65        self.setTransformationMode(Qt.SmoothTransformation)
66        self.setPathway(pathway)
67        self.setMarkedObjects(objects, name_mapper=kwargs.get("name_mapper", {}))
68       
69    def setPathway(self, pathway):
70        self.pathway = pathway
71        if pathway:
72            image_filename = pathway.get_image()
73            self._pixmap = QPixmap(image_filename)
74        else:
75            self._pixmap = QPixmap()
76        self.setPixmap(self._pixmap)
77       
78    def setMarkedObjects(self, objects, name_mapper={}):
79        for entry in self.pathway.entrys() if self.pathway else []:
80            if entry.type == "group":
81                continue
82            graphics = entry.graphics
83            contained_objects = [obj for obj in objects if obj in entry.name]
84            item = EntryGraphicsItem(graphics, self, self.scene())
85            item.setToolTip(self.tooltip(entry, contained_objects, name_mapper))
86            item._actions = self.actions(entry, contained_objects)
87            item.marked_objects = contained_objects
88            if contained_objects:
89                item.setPen(QPen(Qt.blue, 2))
90                item.setFlag(QGraphicsItem.ItemIsSelectable, True)
91   
92    def actions(self, entry, marked_objects=[]):
93        actions = []
94        type = entry.type
95        if marked_objects:
96            action = QAction("View genes on kegg website", None)
97            org = set([s.split(":")[0] for s in marked_objects]).pop()
98            genes = [s.split(":")[-1] for s in marked_objects]
99            address = "http://www.genome.jp/dbget-bin/www_bget?" + "+".join([org] + genes)
100            QObject.connect(action, SIGNAL("triggered()"), lambda toggled=False, address=address: webbrowser.open(address))
101            actions.append(action)
102        elif hasattr(entry, "link"):
103            action = QAction("View %s on KEGG website" % str(type), None)
104            QObject.connect(action, SIGNAL("triggered()"), lambda toggled=False, address=entry.link: webbrowser.open(address))
105            actions.append(action)
106        return actions
107   
108    def tooltip(self, entry, objects, name_mapper={}):
109        names = [obj for obj in objects if obj in entry.name]
110        names = [name_mapper.get(name, name) for name in names]
111        text = "<p>%s</p>" % (entry.name[:16] + " ..." if len(entry.name) > 20 else entry.name)
112        if names:
113            text += "<br>".join(names)
114        return text
115   
116    def contextMenuEvent(self, event):
117        self._menu = menu = QMenu()
118        action = menu.addAction("View this pathway on KEGG website")
119        address ="http://www.kegg.jp/kegg-bin/show_pathway?%s%s" % (self.pathway.org, self.pathway.number)
120        QObject.connect(action, SIGNAL("triggered()"), lambda : webbrowser.open(address))
121        menu.popup(event.screenPos())
122
123class PathwayView(QGraphicsView):
124    def __init__(self, master, *args):
125        QGraphicsView.__init__(self, *args)
126        self.master = master
127       
128        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded)
129        self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
130       
131        self.setRenderHints(QPainter.Antialiasing)
132        scene = QGraphicsScene(self)
133        self.pixmapGraphicsItem = QGraphicsPixmapItem(None, scene) 
134        self.setScene(scene)
135       
136        self.setMouseTracking(True)
137        self.viewport().setMouseTracking(True)
138       
139        self.setFocusPolicy(Qt.WheelFocus)
140       
141    def SetPathway(self, pathway=None, objects=[]):
142        self.scene().clear()
143        self.pathway = pathway
144        self.objects = objects
145        self.pathwayItem = GraphicsPathwayItem(pathway, objects, None, self.scene(), name_mapper=getattr(self.master, "uniqueGenesDict", {}))
146        self.scene().setSceneRect(self.pathwayItem.boundingRect())
147        self.updateTransform()
148   
149    def resizeEvent(self, event):
150        self.updateTransform()
151        return QGraphicsView.resizeEvent(self, event)
152           
153    def updateTransform(self):
154        if self.master.autoResize:
155            self.fitInView(self.scene().sceneRect().adjusted(-1, -1, 1, 1), Qt.KeepAspectRatio)
156        else:
157            self.setTransform(QTransform())
158           
159    def paintEvent(self, event):
160        QGraphicsView.paintEvent(self, event)
161        if getattr(self, "_userMessage", None):
162            painter = QPainter(self.viewport())
163            font = QFont(self.font())
164            font.setPointSize(15)
165            painter.setFont(font)
166            painter.drawText(self.viewport().geometry(), Qt.AlignCenter, self._userMessage)
167            painter.end()
168       
169   
170class OWKEGGPathwayBrowser(OWWidget):
171    settingsList = ["organismIndex", "geneAttrIndex", "autoCommit", "autoResize", "useReference", "useAttrNames", "caseSensitive", "showOrthology"]
172    contextHandlers = {"":DomainContextHandler("",[ContextField("organismIndex", DomainContextHandler.Required + DomainContextHandler.IncludeMetaAttributes),
173                                                   ContextField("geneAttrIndex", DomainContextHandler.Required + DomainContextHandler.IncludeMetaAttributes),
174                                                   ContextField("useAttrNames", DomainContextHandler.Required + DomainContextHandler.IncludeMetaAttributes)])}
175    def __init__(self, parent=None, signalManager=None, name="KEGG Pathway Browser"):
176        OWWidget.__init__(self, parent, signalManager, name)
177        self.inputs = [("Examples", ExampleTable, self.SetData), ("Reference", ExampleTable, self.SetRefData)]
178        self.outputs = [("Selected Examples", ExampleTable), ("Unselected Examples", ExampleTable)]
179        self.organismIndex = 0
180        self.geneAttrIndex = 0
181        self.autoCommit = False
182        self.autoResize = True
183        self.useReference = False
184        self.useAttrNames = 0
185        self.caseSensitive = True
186        self.showOrthology = True
187        self.autoFindBestOrg = False
188        self.loadSettings()
189
190        self.controlArea.setMaximumWidth(250)
191        box = OWGUI.widgetBox(self.controlArea, "Info")
192        self.infoLabel = OWGUI.widgetLabel(box, "No data on input\n")
193       
194        self.allOrganismCodes = {} 
195
196        self.organismCodes = []
197
198        self.organismComboBox = cb = OWGUI.comboBox(self.controlArea, self, "organismIndex", box="Organism", items=[], callback=self.Update, addSpace=True, debuggingEnabled=0)
199        cb.setMaximumWidth(200)
200       
201        self.signalManager.freeze(self).push() #setFreeze(1)
202        QTimer.singleShot(100, self.UpdateOrganismComboBox)
203       
204        box = OWGUI.widgetBox(self.controlArea, "Gene attribute")
205        self.geneAttrCombo = OWGUI.comboBox(box, self, "geneAttrIndex", callback=self.Update)
206        OWGUI.checkBox(box, self, "useAttrNames", "Use variable names", disables=[(-1, self.geneAttrCombo)], callback=self.UseAttrNamesCallback)
207        self.geneAttrCombo.setDisabled(bool(self.useAttrNames))
208       
209        OWGUI.checkBox(box, self, "caseSensitive", "Case sensitive gene matching", callback=self.Update)
210        OWGUI.separator(self.controlArea)
211       
212        OWGUI.checkBox(self.controlArea, self, "useReference", "From signal", box="Reference", callback=self.Update)
213        OWGUI.separator(self.controlArea)
214
215        OWGUI.checkBox(self.controlArea, self, "showOrthology", "Show pathways in full orthology", box="Orthology", callback=self.UpdateListView)
216       
217        OWGUI.checkBox(self.controlArea, self, "autoResize", "Resize to fit", box="Image", callback=lambda :self.pathwayView.updateTransform())
218        OWGUI.separator(self.controlArea)
219
220        box = OWGUI.widgetBox(self.controlArea, "Selection")
221        OWGUI.checkBox(box, self, "autoCommit", "Commit on update")
222        OWGUI.button(box, self, "Commit", callback=self.Commit)
223        OWGUI.rubber(self.controlArea)
224       
225        spliter = QSplitter(Qt.Vertical, self.mainArea)
226        self.pathwayView = PathwayView(self, spliter)
227        self.mainArea.layout().addWidget(spliter)
228
229        self.listView = QTreeWidget(spliter)
230        spliter.addWidget(self.listView)
231       
232        self.listView.setAllColumnsShowFocus(1)
233        self.listView.setColumnCount(4)
234        self.listView.setHeaderLabels(["Pathway", "P value", "Genes", "Reference"])
235
236        self.listView.setSelectionMode(QAbstractItemView.SingleSelection)
237           
238        self.listView.setSortingEnabled(True)
239        #self.listView.setAllColumnsShowFocus(1)
240        self.listView.setMaximumHeight(200)
241       
242        self.connect(self.listView, SIGNAL("itemSelectionChanged()"), self.UpdatePathwayView)
243       
244        self.ctrlPressed = False
245        self.selectedObjects = defaultdict(list)
246        self.data = None
247        self.refData = None
248        self.loadedOrganism = None
249       
250        self.resize(800, 600)
251       
252        self.connect(self, SIGNAL("widgetStateChanged(QString, int, QString)"), self.onStateChange)
253       
254    def UpdateOrganismComboBox(self):
255        try:
256            self.progressBarInit()
257            with orngServerFiles.DownloadProgress.setredirect(self.progressBarSet):
258                genome = obiKEGG.KEGGGenome()
259            self.progressBarFinished()
260           
261            self.allOrganismCodes = genome
262   
263            essential = genome.essential_organisms()
264           
265            local = [name.split(".")[0].split("_")[-1] for name in orngServerFiles.listfiles("KEGG") if "kegg_genes" in name]
266            self.organismCodes = [(code, organism.definition) for code, organism in self.allOrganismCodes.items() if code in local or code in essential]
267            self.organismCodes.sort()
268            items = [desc for code, desc in self.organismCodes]
269            self.organismCodes = [code for code, desc in self.organismCodes]
270           
271            self.organismComboBox.addItems(items)
272        finally:
273            self.signalManager.freeze(self).pop() #setFreeze(0)
274
275       
276    def SetData(self, data=None):
277        if not self.organismCodes: ## delay this call until we retrieve organism codes from the server files
278            QTimer.singleShot(200, lambda: self.SetData(data))
279            return
280
281        self.closeContext()
282        self.data = data
283        self.warning(0)
284        if data:
285            self.SetGeneAttrCombo()
286            taxid = data_hints.get_hint(data, "taxid", None)
287            if taxid:
288                try:
289                    code = obiKEGG.from_taxid(taxid)
290                    self.organismIndex = self.organismCodes.index(code)
291                except Exception, ex:
292                    print ex, taxid
293           
294            self.useAttrNames = data_hints.get_hint(data, "genesinrows", self.useAttrNames)
295           
296            self.openContext("", data)
297            self.Update()
298        else:
299            self.infoLabel.setText("No data on input\n")
300            self.listView.clear()
301            self.selectedObjects = defaultdict(list)
302            self.pathwayView.SetPathway(None)
303            self.send("Selected Examples", None)
304            self.send("Unselected Examples", None)
305
306    def SetRefData(self, data=None):
307        self.refData = data
308        if self.useReference and self.data and self.organismCodes:
309            self.Update()
310
311    def UseAttrNamesCallback(self):
312##        self.geneAttrCombo.setDisabled(bool(self.useAttrNames))
313        self.Update()
314
315    def SetGeneAttrCombo(self):
316        self.geneAttrCandidates = self.data.domain.attributes + self.data.domain.getmetas().values()
317        self.geneAttrCandidates = filter(lambda v:v.varType in [orange.VarTypes.Discrete ,orange.VarTypes.String], self.geneAttrCandidates)
318        self.geneAttrCombo.clear()
319        #print 'geneAttrCandidates', self.geneAttrCandidates
320        self.geneAttrCombo.addItems([var.name for var in self.geneAttrCandidates])
321        return
322               
323    def PreDownload(self, org=None, pb=None):
324        pb, finish = (OWGUI.ProgressBar(self, 0), True) if pb is None else (pb, False)
325        files = ["kegg_brite.tar.gz", "kegg_pathways_map.tar.gz", "kegg_genome.tar.gz"]
326        if org:
327            files += ["kegg_genes_%s.tar.gz" % org, "kegg_pathways_%s.tar.gz" % org]
328        files = [file for file in files if file not in orngServerFiles.listfiles("KEGG")]
329        pb.iter += len(files) * 100
330        for i, filename in enumerate(files):
331#            print filename
332            orngServerFiles.download("KEGG", filename, callback=pb.advance)
333        if finish:
334            pb.finish()
335           
336    def UpdateListView(self):
337        self.bestPValueItem = None
338        self.listView.clear()
339        if not self.data:
340            return
341        allPathways = self.org.pathways()
342        allRefPathways = obiKEGG.pathways("map")
343        self.progressBarFinished()
344        items = []
345        if self.showOrthology:
346            self.koOrthology = obiKEGG.KEGGBrite("ko00001")
347            self.listView.setRootIsDecorated(True)
348            path_ids = set([s[-5:] for s in self.pathways.keys()])
349            def _walkCollect(koEntry):
350                num = koEntry.title[:5] if koEntry.title else None
351                if num  in path_ids:
352                    return [koEntry] + reduce(lambda li,c:li+_walkCollect(c), [child for child in koEntry.entrys], [])
353                else:
354                    c = reduce(lambda li,c:li+_walkCollect(c), [child for child in koEntry.entrys], [])
355                    return c + (c and [koEntry] or [])
356            allClasses = reduce(lambda li1, li2: li1+li2, [_walkCollect(c) for c in self.koOrthology], [])
357            def _walkCreate(koEntry, lvItem):
358                item = QTreeWidgetItem(lvItem)
359                id = "path:"+self.organismCodes[min(self.organismIndex, len(self.organismCodes)-1)] + koEntry.title[:5]
360                if koEntry.title[:5] in path_ids:
361                    genes, p_value, ref = self.pathways[id]
362                    item.setText(0, obiKEGG.KEGGPathway(id).title)
363#                    print id, obiKEGG.KEGGPathway(id).title
364                    item.setText(1, "%.5f" % p_value)
365                    item.setText(2, "%i of %i" %(len(genes), len(self.genes)))
366                    item.setText(3, "%i of %i" %(ref, len(self.referenceGenes)))
367                    item.pathway_id = id
368                else:
369                    item.setText(0, obiKEGG.KEGGPathway(id).title if id in allPathways else koEntry.title)
370                    if id in allPathways:
371                        item.pathway_id = id
372                    elif "path:map" + koEntry.title[:5] in allRefPathways:
373                        item.pathway_id = "path:map" + koEntry.title[:5]
374                    else:
375                        item.pathway_id = None
376               
377                for child in koEntry.entrys:
378                    if child in allClasses:
379                        _walkCreate(child, item)
380           
381            for koEntry in self.koOrthology:
382                if koEntry in allClasses:
383                    _walkCreate(koEntry, self.listView)
384                   
385            self.listView.update()
386        else:
387            self.listView.setRootIsDecorated(False)
388            pathways = self.pathways.items()
389            pathways.sort(lambda a,b:cmp(a[1][1], b[1][1]))
390            for id, (genes, p_value, ref) in pathways:
391                item = QTreeWidgetItem(self.listView)
392                item.setText(0, obiKEGG.KEGGPathway(id).title)
393                item.setText(1, "%.5f" % p_value)
394                item.setText(2, "%i of %i" %(len(genes), len(self.genes)))
395                item.setText(3, "%i of %i" %(ref, len(self.referenceGenes)))
396                item.pathway_id = id
397                items.append(item)
398               
399        self.bestPValueItem = items and items[0] or None
400        self.listView.expandAll()
401        for i in range(4):
402            self.listView.resizeColumnToContents(i)
403           
404        if self.bestPValueItem:
405            self.listView.selectionModel().select(self.listView.indexFromItem(self.bestPValueItem), QItemSelectionModel.ClearAndSelect)
406
407    def UpdatePathwayView(self):
408        items = self.listView.selectedItems()
409       
410        if len(items) > 0:
411            item = items[0]
412        else:
413            item = None
414           
415        self.selectedObjects = defaultdict(list)
416        self.Commit()
417        item = item or self.bestPValueItem
418        if not item or not item.pathway_id:
419            self.pathwayView.SetPathway(None)
420            return
421        self.pathway = obiKEGG.KEGGPathway(item.pathway_id)
422        self.pathwayView.SetPathway(self.pathway, self.pathways.get(item.pathway_id, [[]])[0])
423           
424           
425    def Update(self):
426        if not self.data:
427            return
428        self.error(0)
429        self.information(0)
430        pb = OWGUI.ProgressBar(self, 100)
431        if self.useAttrNames:
432            genes = [str(v.name).strip() for v in self.data.domain.attributes]
433        elif self.geneAttrCandidates:
434            geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates)-1)]
435            genes = [str(e[geneAttr]) for e in self.data if not e[geneAttr].isSpecial()]
436            if any("," in gene for gene in genes):
437                genes = reduce(list.__add__, (split_and_strip(gene, ",") for gene in genes), [])
438                self.information(0, "Separators detected in input gene names. Assuming multiple genes per example.")
439        else:
440            self.error(0, "Cannot extact gene names from input")
441            genes = []
442        org_code = self.organismCodes[min(self.organismIndex, len(self.organismCodes)-1)]
443        if self.loadedOrganism != org_code:
444            self.PreDownload(org_code, pb=pb)
445            self.org = obiKEGG.KEGGOrganism(org_code)
446            self.loadedOrganism = org_code
447        uniqueGenes, conflicting, unknown = self.org.get_unique_gene_ids(set(genes), self.caseSensitive)
448        self.infoLabel.setText("%i genes on input\n%i (%.1f%%) genes matched" % (len(genes), len(uniqueGenes), 100.0*len(uniqueGenes)/len(genes) if genes else 0.0)) 
449#        if conflicting:
450#            print >> sys.stderr, "Conflicting genes:", conflicting
451#        if unknown:
452#            print >> sys.stderr, "Unknown genes:", unknown
453        self.information(1)
454        if self.useReference and self.refData:
455            if self.useAttrNames:
456                reference = [str(v.name).strip() for v in self.refData]
457            else:
458                geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates)-1)]
459                reference = [str(e[geneAttr]) for e in self.refData if not e[geneAttr].isSpecial()]
460                if any("," in gene for gene in reference):
461                    reference = reduce(list.__add__, (split_and_strip(gene, ",") for gene in reference), [])
462                    self.information(1, "Separators detected in reference gene names. Assuming multiple genes per example.")
463            uniqueRefGenes, conflicting, unknown = self.org.get_unique_gene_ids(set(reference), self.caseSensitive)
464            self.referenceGenes = reference = uniqueRefGenes.keys()
465        else:
466            self.referenceGenes = reference = self.org.get_genes()
467        self.uniqueGenesDict = uniqueGenes
468        self.genes = uniqueGenes.keys()
469        self.revUniqueGenesDict = dict([(val, key) for key, val in self.uniqueGenesDict.items()])
470#        self.progressBarInit()
471#        with orngServerFiles.DownloadProgress.setredirect(self.progressBarSet):
472        self.pathways = self.org.get_enriched_pathways(self.genes, reference, callback=lambda value: pb.advance()) #self.progressBarSet)
473        if not self.pathways:
474            self.warning(0, "No enriched pathways found.")
475        else:
476            self.warning(0)
477           
478#        self.progressBarFinished()
479        self.UpdateListView()
480        pb.finish()
481##        print self.bestPValueItem
482        #self.bestPValueItem.setSelected(True)
483        #self.UpdatePathwayView()
484
485    def SelectObjects(self, objs):
486        if (not self.selectedObjects or self.ctrlPressed) and not objs:
487            return
488        if self.ctrlPressed:
489            for id, graphics in objs:
490                graphics = tuple(sorted(graphics.items()))
491                if id in self.selectedObjects[graphics]:
492                    self.selectedObjects[graphics].pop(self.selectedObjects[graphics].index(id))
493                    if not self.selectedObjects[graphics]:
494                        del self.selectedObjects[graphics]
495                else:
496                    self.selectedObjects[graphics].append(id)
497        else:
498            self.selectedObjects.clear()
499            for id, graphics in objs:
500                graphics = tuple(sorted(graphics.items()))
501                self.selectedObjects[graphics].append(id)
502        if self.autoCommit:
503            self.Commit()
504           
505
506    def Commit(self):
507        if self.data:
508            selectedItems = self.pathwayView.scene().selectedItems()
509            selectedGenes = reduce(set.union, [item.marked_objects for item in selectedItems], set())
510           
511            if self.useAttrNames:
512#                selectedGenes = reduce(set.union, self.selectedObjects.values(), set())
513                selectedVars = [self.data.domain[self.uniqueGenesDict[gene]] for gene in selectedGenes]
514                newDomain = orange.Domain(selectedVars ,0)
515                data = orange.ExampleTable(newDomain, self.data)
516                self.send("Selected Examples", data)
517            elif self.geneAttrCandidates:
518                geneAttr = self.geneAttrCandidates[min(self.geneAttrIndex, len(self.geneAttrCandidates)-1)]
519                selectedExamples = []
520                otherExamples = []
521#                selectedGenes = reduce(set.union, self.selectedObjects.values(), set())
522                for ex in self.data:
523                    names = [self.revUniqueGenesDict.get(name, None) for name in split_and_strip(str(ex[geneAttr]), ",")]
524                    if any(name and name in selectedGenes for name in names):
525                        selectedExamples.append(ex)
526                    else:
527                        otherExamples.append(ex)
528                       
529                if selectedExamples:
530                    selectedExamples = orange.ExampleTable(selectedExamples)
531                else:
532                    selectedExamples = None
533                   
534                if otherExamples:
535                    otherExamples = orange.ExampleTable(otherExamples)
536                else:
537                    otherExamples = None
538                   
539                self.send("Selected Examples", selectedExamples)
540                self.send("Unselected Examples", otherExamples)
541        else:
542            self.send("Selected Examples", None)
543            self.send("Unselected Examples", None)
544       
545    def keyPressEvent(self, key):
546        if key.key()==Qt.Key_Control:
547            self.ctrlPressed=True
548        else:
549            OWWidget.keyPressEvent(self, key)
550
551    def keyReleaseEvent(self, key):
552        if key.key()==Qt.Key_Control:
553            self.ctrlPressed=False
554        else:
555            OWWidget.keyReleaseEvent(self, key)
556           
557    def onStateChange(self, stateType, id, text):
558        if stateType == "Warning":
559            self.pathwayView._userMessage = text
560            self.pathwayView.viewport().update()
561           
562
563if __name__=="__main__":
564    app = QApplication(sys.argv)
565    data = orange.ExampleTable("../../../../orange/doc/datasets/brown-selected.tab")
566    w = OWKEGGPathwayBrowser()
567    w.UpdateOrganismComboBox()
568##    app.setMainWidget(w)
569    w.show()
570    w.SetData(data)
571    app.exec_()
572    w.saveSettings()
Note: See TracBrowser for help on using the repository browser.