Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • _bioinformatics/widgets/OWSetEnrichment.py

    r1748 r1761  
    4141            painter.drawText(self.viewport().geometry(), Qt.AlignCenter, self._userMessage) 
    4242            painter.end() 
    43              
     43 
    4444class MyTreeWidgetItem(QTreeWidgetItem): 
    4545    def __lt__(self, other): 
     
    5050        rhs = _toPyObject(other.data(column, Qt.DisplayRole)) 
    5151        return lhs < rhs 
    52      
     52 
    5353def name_or_none(id): 
    5454    """Return organism name for ncbi taxid or None if not found. 
     
    5858    except obiTaxonomy.UnknownSpeciesIdentifier: 
    5959        return None 
    60              
     60 
    6161class OWSetEnrichment(OWWidget): 
    6262    settingsList = ["speciesIndex", "genesinrows", "geneattr", "categoriesCheckState"] 
    6363    contextHandlers = {"":DomainContextHandler("", ["speciesIndex", "genesinrows", "geneattr", "categoriesCheckState"])} 
    64      
     64 
    6565    def __init__(self, parent=None, signalManager=None, name="Gene Set Enrichment Analysis", **kwargs): 
    6666        OWWidget.__init__(self, parent, signalManager, name, **kwargs) 
    6767        self.inputs = [("Example Table", ExampleTable, self.setData, Default), ("Reference", ExampleTable, self.setReference)] 
    6868        self.outputs = [("Selected Examples", ExampleTable)] 
    69          
     69 
    7070        self.speciesIndex = 0 
    7171        self.genesinrows = False 
     
    7777        self.minClusterCount = 0 
    7878        self.maxPValue = 0.01 
    79          
     79 
    8080        self.useFDR = True 
    81          
     81 
    8282        self.categoriesCheckState = {} 
    83          
     83 
    8484        self.loadSettings() 
    85          
     85 
    8686        if self.signalManager: 
    8787            self.signalManager.freeze(self).push() 
    8888        QTimer.singleShot(50, self.updateHierarchy) 
    89          
     89 
    9090        box = OWGUI.widgetBox(self.controlArea, "Info") 
    9191        self.infoBox = OWGUI.widgetLabel(box, "Info") 
    9292        self.infoBox.setText("No data on input") 
    93          
     93 
    9494        self.speciesComboBox = OWGUI.comboBox(self.controlArea, self, 
    9595                      "speciesIndex", "Species", 
    9696                      callback=lambda :self.data and self.updateAnnotations(), 
    9797                      debuggingEnabled=0) 
    98          
     98 
    9999        box = OWGUI.widgetBox(self.controlArea, "Gene names") 
    100100        self.geneAttrComboBox = OWGUI.comboBox(box, self, "geneattr", 
     
    102102                                sendSelectedValue=0, 
    103103                                callback=self.updateAnnotations) 
    104          
     104 
    105105        cb = OWGUI.checkBox(box, self, "genesinrows", "Use attribute names", 
    106106                            callback=lambda :self.data and self.updateAnnotations(), 
    107107                            disables=[(-1, self.geneAttrComboBox)]) 
    108108        cb.makeConsistent() 
    109          
     109 
    110110        OWGUI.button(box, self, "Gene matcher settings", 
    111111                     callback=self.updateGeneMatcherSettings, 
    112112                     tooltip="Open gene matching settings dialog", 
    113113                     debuggingEnabled=0) 
    114          
     114 
    115115        self.referenceRadioBox = OWGUI.radioButtonsInBox(self.controlArea, 
    116116                    self, "useReferenceData", ["Entire genome", "Reference set (input)"], 
     
    118118                              "Use genes from Referece Examples input signal as reference"], 
    119119                    box="Reference", callback=self.updateAnnotations) 
    120          
    121         box = OWGUI.widgetBox(self.controlArea, "Annotation Summary") 
     120 
     121        box = OWGUI.widgetBox(self.controlArea, "Gene Sets") 
    122122        self.groupsWidget = QTreeWidget(self) 
    123123        self.groupsWidget.setHeaderLabels(["Category"]) 
     
    128128        hWidget = OWGUI.widgetBox(self.mainArea, orientation=hLayout) 
    129129        sb, sbcb = OWGUI.spin(hWidget, self, "minClusterCount", 
    130                               0, 100, label="Min. Count", 
     130                              0, 100, label="Genes", 
    131131                              tooltip="Minimum gene count", 
    132132                              callback=self.filterAnnotationsChartView, 
     
    134134                              checked="useMinCountFilter", 
    135135                              checkCallback=self.filterAnnotationsChartView) 
    136          
     136 
    137137        dsp, dspcb = OWGUI.doubleSpin(hWidget, self, 
    138138                        "maxPValue", 0.0, 1.0, 0.0001, 
    139                         label="Max. P-Value", 
     139                        label="P-Value (FDR corrected)", 
    140140                        tooltip="Maximum (FDR corrected) P-Value", 
    141141                        callback=self.filterAnnotationsChartView, 
     
    143143                        checked="useMaxPValFilter", 
    144144                        checkCallback=self.filterAnnotationsChartView) 
    145          
     145 
    146146        from Orange.OrangeWidgets import OWGUIEx 
    147147        self.filterLineEdit = OWGUIEx.QLineEditWithActions(self) 
     
    149149        action = QAction(QIcon(os.path.join(orngEnviron.canvasDir, 
    150150                        "icons", "delete_gray.png")), "Clear", self) 
    151          
     151 
    152152        self.filterLineEdit.addAction(action, 0, Qt.AlignHCenter) 
    153153        self.connect(action, SIGNAL("triggered()"), self.filterLineEdit.clear) 
    154          
     154 
    155155        self.filterCompleter = QCompleter(self.filterLineEdit) 
    156156        self.filterCompleter.setCaseSensitivity(Qt.CaseInsensitive) 
    157157        self.filterLineEdit.setCompleter(self.filterCompleter) 
    158          
     158 
    159159        hLayout.addWidget(self.filterLineEdit) 
    160160        self.mainArea.layout().addWidget(hWidget) 
    161          
     161 
    162162        self.connect(self.filterLineEdit, SIGNAL("textChanged(QString)"), 
    163163                     self.filterAnnotationsChartView) 
    164          
     164 
    165165        self.annotationsChartView = MyTreeWidget(self) 
    166166        self.annotationsChartView.setHeaderLabels(["Category", "Term", 
     
    173173#        self.annotationsChartView.viewport().setAttribute(Qt.WA_Hover) 
    174174        self.mainArea.layout().addWidget(self.annotationsChartView) 
    175          
     175 
    176176        contextEventFilter = OWGUI.VisibleHeaderSectionContextEventFilter(self.annotationsChartView) 
    177177        self.annotationsChartView.header().installEventFilter(contextEventFilter) 
    178          
     178 
    179179        self.taxid_list = [] 
    180          
     180 
    181181        self.connect(self.groupsWidget, SIGNAL("itemClicked(QTreeWidgetItem *, int)"), self.subsetSelectionChanged) 
    182          
     182 
    183183        OWGUI.button(self.controlArea, self, "Commit", callback=self.commit) 
    184          
     184 
    185185        self.loadedGenematcher = "None" 
    186186        self.referenceData = None 
    187187        self.data = None 
    188          
     188 
    189189        self.treeItems = [] 
    190          
     190 
    191191        self.resize(1024, 600) 
    192          
     192 
    193193        self.connect(self, SIGNAL("widgetStateChanged(QString, int, QString)"), self.onStateChange) 
    194          
     194 
    195195        self.updatingAnnotationsFlag = False 
    196          
     196 
    197197    def updateHierarchy(self): 
    198198        try: 
     
    202202                organisms = set(obiTaxonomy.essential_taxids() + [t[1] for t in all]) 
    203203            self.progressBarFinished() 
    204              
     204 
    205205            organism_names = map(name_or_none, organisms) 
    206206            organisms = [taxid for taxid, name in zip(organisms, organism_names) \ 
    207207                         if name is not None] 
    208              
     208 
    209209            self.taxid_list = list(organisms) 
    210210            self.speciesComboBox.clear() 
     
    213213        finally: 
    214214            if self.signalManager: 
    215                 self.signalManager.freeze(self).pop() 
    216          
     215                self.signalManager.freeze(self).pop() #setFreeze(self.signalManager.freezing - 1) 
     216 
    217217    def setData(self, data=None): 
    218218        self.data = data 
     
    222222        self.groupsWidget.clear() 
    223223        self.annotationsChartView.clear() 
    224          
     224 
    225225        if not getattr(self,"taxid_list", None): 
    226226            QTimer.singleShot(100, lambda data=data: self.setData(data)) 
    227             return  
     227            return 
    228228        if data: 
    229229            self.geneAttrs = [attr for attr in data.domain.variables + data.domain.getmetas().values() \ 
    230230                              if attr.varType != orange.VarTypes.Continuous] 
    231              
     231 
    232232            self.geneAttrComboBox.addItems([attr.name for attr in self.geneAttrs]) 
    233233            self.geneattr = min(self.geneattr, len(self.geneAttrs) - 1) 
    234               
     234 
    235235            taxid = data_hints.get_hint(data, "taxid", "") 
    236236            try: 
     
    239239                pass 
    240240            self.genesinrows = data_hints.get_hint(data, "genesinrows", self.genesinrows) 
    241              
     241 
    242242            self.openContext("", data) 
    243              
     243 
    244244#            print self.speciesIndex 
    245              
     245 
    246246            self.setHierarchy(self.getHierarchy(taxid=self.taxid_list[self.speciesIndex])) 
    247              
     247 
    248248            self.loadedGenematcher = "None" 
    249249            self.updateAnnotations() 
    250              
     250 
    251251    def setReference(self, data=None): 
    252252        self.referenceData = data 
    253253        self.referenceRadioBox.setEnabled(bool(data)) 
    254          
     254 
    255255    def getHierarchy(self, taxid): 
    256256        def recursive_dict(): 
    257257            return defaultdict(recursive_dict) 
    258258        collection = recursive_dict() 
    259          
     259 
    260260        def collect(col, hier): 
    261261            if hier: 
    262262                collect(col[hier[0]], hier[1:]) 
    263                  
     263 
    264264        for hierarchy, t_id, _ in self.genesets: 
    265265            collect(collection[t_id], hierarchy) 
    266266        return collection[taxid] 
    267          
     267 
    268268    def setHierarchy(self, hierarchy): 
    269269        self.groupsWidgetItems = {} 
     
    275275                if value: 
    276276                    item.setFlags(item.flags() | Qt.ItemIsTristate) 
    277                      
     277 
    278278                item.setData(0, Qt.CheckStateRole, QVariant(self.categoriesCheckState.get(full_cat, Qt.Checked))) 
    279279                item.setExpanded(True) 
     
    281281                self.groupsWidgetItems[full_cat] = item 
    282282                fill(value, item, full_cat) 
    283                  
     283 
    284284        fill(hierarchy, self.groupsWidget) 
    285          
     285 
    286286#    def updateCategoryCounts(self): 
    287287#        for cat, item in self.groupWidgetItem: 
    288288#            item.setData(1, QVariant(), Qt.DisplayRole) 
    289          
     289 
    290290    def selectedCategories(self): 
    291291        taxid = self.taxid_list[self.speciesIndex] 
     
    301301                result.extend(collect(item.child(i), full_cat)) 
    302302            return result 
    303              
     303 
    304304        items = [self.groupsWidget.topLevelItem(i) for i in range(self.groupsWidget.topLevelItemCount())] 
    305305        states = reduce(list.__add__, [collect(item) for item in items], []) 
    306306        return dict(states) 
    307              
     307 
    308308    def subsetSelectionChanged(self, item, column): 
    309309        self.categoriesCheckState = self.getHierarchyCheckState() 
    310          
     310 
    311311        categories = self.selectedCategories() 
    312312        if not set(categories) <= set(self.currentAnnotatedCategories): 
     
    314314        else: 
    315315            self.filterAnnotationsChartView() 
    316          
     316 
    317317    def updateGeneMatcherSettings(self): 
    318318        from .OWGOEnrichmentAnalysis import GeneMatcherDialog 
     
    323323            if self.data: 
    324324                self.updateAnnotations() 
    325                  
     325 
    326326    def updateGenematcher(self): 
    327327        taxid = self.taxid_list[self.speciesIndex] 
     
    342342                self.loadedGenematcher = taxid 
    343343            self.progressBarFinished() 
    344              
     344 
    345345    def genesFromExampleTable(self, table): 
    346346        if self.genesinrows: 
     
    350350            genes = [str(ex[geneattr]) for ex in table] 
    351351        return genes 
    352      
     352 
    353353    def clusterGenes(self): 
    354354        return self.genesFromExampleTable(self.data) 
    355      
     355 
    356356    def referenceGenes(self): 
    357357        if self.referenceData and self.useReferenceData: 
     
    364364                call.__call__() 
    365365                return call.get_result() 
    366      
     366 
    367367    def _cached_name_lookup(self, func, cache): 
    368368        def f(name, cache=cache): 
     
    371371            return cache[name] 
    372372        return f 
    373      
     373 
    374374    def mapGeneNames(self, names, cache=None, passUnknown=False): 
    375375        if cache is not None: 
     
    381381#            return [(mapped_name or name, mapped_name is not None) for mapped_name, name in zip(mapped, names)] 
    382382        return [n for n in [umatch(name) for name in names] if n is not None] 
    383      
     383 
    384384    def enrichment(self, geneset, cluster, reference, pval=obiProb.Hypergeometric(), cache=None): 
    385385        genes = set(self.mapGeneNames(geneset.genes, cache, passUnknown=False)) 
    386          
     386 
    387387        cmapped = genes.intersection(cluster) 
    388388        rmapped = genes.intersection(reference) 
    389389        return (cmapped, rmapped, pval.p_value(len(cmapped), len(reference), len(rmapped), len(cluster)), float(len(cmapped)) / (len(cluster) or 1) / (float(len(rmapped) or 1) / (len(reference) or 1))) # TODO: compute all statistics here 
    390      
     390 
    391391    def updateAnnotations(self): 
    392392        self.updatingAnnotationsFlag = True 
     
    396396            self.error(0, "Input data contains no attributes with gene names") 
    397397            return 
    398          
     398 
    399399        self.progressBarInit() 
    400400        self.updateGenematcher() 
    401401        self.currentAnnotatedCategories = categories = self.selectedCategories() 
    402          
     402 
    403403        ## Load collections in a worker thread 
    404404        call = self.asyncCall(obiGeneSets.collections, categories, name="Loading collections", blocking=True, thread=self.thread()) 
     
    407407            call.__call__() 
    408408            collections = list(call.get_result()) 
    409              
     409 
    410410#        with orngServerFiles.DownloadProgress.setredirect(self.progressBarSet): 
    411 #            collections = list(obiGeneSets.collections(*categories))  
     411#            collections = list(obiGeneSets.collections(*categories)) 
    412412        clusterGenes, referenceGenes = self.clusterGenes(), self.referenceGenes() 
    413413        cache = {} 
    414414 
    415415        self.genematcher.set_targets(referenceGenes) 
    416          
     416 
    417417        countAll = len(set(clusterGenes)) 
    418418        infoText = "%i unique gene names on input\n" % countAll 
     
    423423        infoText += "%i (%.1f) gene names matched" % (len(clusterGenes), 100.0 * len(clusterGenes) / countAll) 
    424424        self.infoBox.setText(infoText) 
    425          
     425 
    426426        results = [] 
    427427        from Orange.orng.orngMisc import progressBarMilestones 
    428          
     428 
    429429        milestones = progressBarMilestones(len(collections), 100) 
    430430        for i, geneset in enumerate(collections): 
     
    432432            if i in milestones: 
    433433                self.progressBarSet(100.0 * i / len(collections)) 
    434                  
     434 
    435435        if self.useFDR: 
    436436            results = sorted(results, key=lambda a:a[1][2]) 
    437437            pvals = obiProb.FDR([pval for _, (_, _, pval, _) in results]) 
    438438            results = [(geneset, (cmapped, rmapped, pvals[i], es)) for i, (geneset, (cmapped, rmapped, _, es)) in enumerate(results)] 
    439          
     439 
    440440        fmt = lambda score, max_decimals=10: "%%.%if" % min(int(abs(math.log(max(score, 1e-10)))) + 2, max_decimals) if score > math.pow(10, -max_decimals) and score < 1 else "%.1f" 
    441441        self.annotationsChartView.clear() 
    442          
     442 
    443443        maxCount = max([len(cm) for _, (cm, _, _, _) in results] + [1]) 
    444444        maxRefCount = max([len(rc) for _, (_, rc, _, _) in results] + [1]) 
    445445        countSpaces = int(math.ceil(math.log10(maxCount))) 
     446        #print maxRefCount 
    446447        refSpaces = int(math.ceil(math.log(maxRefCount))) 
    447448        countFmt = "%"+str(countSpaces) + "s  (%.2f%%)" 
    448449        refFmt = "%"+str(refSpaces) + "s  (%.2f%%)" 
    449              
     450 
    450451        self.filterCompleter.setModel(None) 
    451452        linkFont = QFont(self.annotationsChartView.viewOptions().font) 
     
    458459                item.setData(2, Qt.ToolTipRole, QVariant(len(cmapped))) # For filtering 
    459460                item.setData(3, Qt.DisplayRole, QVariant(refFmt % (len(rmapped), 100.0*len(rmapped)/len(referenceGenes)))) 
    460                 item.setData(4, Qt.DisplayRole, QVariant(p_val)) 
     461                item.setData(4, Qt.DisplayRole, QVariant("%0.2e"% p_val)) 
     462                item.setData(4, 42, QVariant(p_val)) 
     463                #stoplec 4 - zelim sort po p_val 
     464                item.setData(4, Qt.ToolTipRole, QVariant("%0.10f" % p_val)) 
    461465                item.setData(5, Qt.DisplayRole, QVariant(enrichment)) 
    462466                item.setData(5, Qt.ToolTipRole, QVariant("%.3f" % enrichment)) 
     
    468472                    item.setFont(1, linkFont) 
    469473                    item.setForeground(1, QColor(Qt.blue)) 
    470                      
     474 
    471475        if not self.treeItems: 
    472476            self.warning(0, "No enriched sets found.") 
    473477        else: 
    474478            self.warning(0) 
    475                  
     479 
    476480        replace = lambda s:s.replace(",", " ").replace("(", " ").replace(")", " ") 
    477481        self._completerModel = completerModel = QStringListModel(sorted(reduce(set.union, [[geneset.name] + replace(geneset.name).split() for geneset, (c, _, _, _) in results if c], set()))) 
    478482        self.filterCompleter.setModel(completerModel) 
    479          
     483 
    480484        self.annotationsChartView.setItemDelegateForColumn(5, BarItemDelegate(self, scale=(0.0, max(t[1][3] for t in results)))) 
    481485        self.annotationsChartView.setItemDelegateForColumn(1, LinkStyledItemDelegate(self.annotationsChartView)) 
    482                  
     486 
    483487        for i in range(self.annotationsChartView.columnCount()): 
    484488            self.annotationsChartView.resizeColumnToContents(i) 
    485              
     489 
    486490        self.annotationsChartView.setColumnWidth(1, min(self.annotationsChartView.columnWidth(1), 300)) 
    487491        self.progressBarFinished() 
    488492        QTimer.singleShot(10, self.filterAnnotationsChartView) 
    489493        self.updatingAnnotationsFlag = False 
    490      
     494 
    491495    def filterAnnotationsChartView(self, filterString=""): 
    492496        if self.updatingAnnotationsFlag: 
     
    497501        for item in self.treeItems: 
    498502            item_cat = str(item.data(0, Qt.EditRole).toString()) 
    499             count, pval = _toPyObject(item.data(2, Qt.ToolTipRole)), _toPyObject(item.data(4, Qt.DisplayRole)) 
     503            count, pval = _toPyObject(item.data(2, Qt.ToolTipRole)), _toPyObject(item.data(4, 42)) 
    500504            geneset = item.geneset.name.lower() 
    501505            hidden = item_cat not in categories or (self.useMinCountFilter and count < self.minClusterCount) or \ 
     
    503507            item.setHidden(hidden) 
    504508            itemsHidden.append(hidden) 
    505              
     509 
    506510        if self.treeItems and all(itemsHidden): 
    507511            self.information(0, "All sets were filtered out.") 
    508512        else: 
    509513            self.information(0) 
    510              
    511          
     514 
     515 
    512516    def commit(self): 
    513517        selected = self.annotationsChartView.selectedItems() 
     
    522526        else: 
    523527            geneattr = self.geneAttrs[self.geneattr] 
    524             selected = [1 if self.genematcher.umatch(str(ex[geneattr])) in mappedNames else 0 for ex in self.data]                 
     528            selected = [1 if self.genematcher.umatch(str(ex[geneattr])) in mappedNames else 0 for ex in self.data] 
    525529            data = self.data.select(selected) 
    526              
     530 
    527531#            if self.appendAnnotations: 
    528532#                meta = orange.StringVariable("Annotations") 
     
    532536#                    gene = str(ex[geneattr]) 
    533537#                    annotations = getgene 
    534          
     538 
    535539        self.send("Selected Examples", data) 
    536          
     540 
    537541    def sendReport(self): 
    538542        self.reportSettings("Settings", [("Organism", obiTaxonomy.name(self.taxid_list[self.speciesIndex]))]) 
    539543        self.reportSettings("Filter", [("Min cluster size", self.minClusterCount if self.useMinCountFilter else 0), 
    540544                                       ("Max p-value", self.maxPValue if self.useMaxPValFilter else 1.0)]) 
    541      
     545 
    542546        self.reportSubsection("Annotations") 
    543547        self.reportRaw(reportItemView(self.annotationsChartView)) 
    544          
     548 
    545549    def onStateChange(self, stateType, id, text): 
    546550        if stateType == "Warning" or stateType == "Info": 
    547551            self.annotationsChartView._userMessage = text 
    548552            self.annotationsChartView.viewport().update() 
    549          
    550          
     553 
     554 
    551555def reportItemView(view): 
    552556    model = view.model() 
    553557    return reportItemModel(view, model) 
    554      
     558 
    555559def reportItemModel(view, model, index=QModelIndex()): 
    556560    if not index.isValid() or model.hasChildren(index): 
     
    569573        return str(variant.toString()) if variant.isValid() else "" 
    570574 
    571      
     575 
     576 
    572577if __name__ == "__main__": 
    573578    import cProfile 
    574      
     579 
    575580    app = QApplication(sys.argv) 
    576581    w = OWSetEnrichment() 
    577582    w.updateHierarchy() 
    578     data = orange.ExampleTable("brown-selected") 
     583    data = orange.ExampleTable("yeast-class-RPR.tab") 
    579584#    data = orange.ExampleTable("../human") 
    580585#    print cProfile.runctx("w.setData(data)", globals(), locals()) 
     
    583588    app.exec_() 
    584589    w.saveSettings() 
    585      
     590 
     591 
Note: See TracChangeset for help on using the changeset viewer.