Changeset 1928:ef73516807fb in orange-bioinformatics for orangecontrib/bio/widgets/OWGeneInfo.py


Ignore:
Timestamp:
12/09/13 16:44:55 (4 months ago)
Author:
Ales Erjavec <ales.erjavec@…>
Branch:
default
Message:

Threaded initialization and record retrieval.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • orangecontrib/bio/widgets/OWGeneInfo.py

    r1894 r1928  
    99from __future__ import absolute_import, with_statement 
    1010 
     11import sys 
    1112from collections import defaultdict 
    1213from functools import partial 
     14 
     15from PyQt4.QtCore import pyqtSlot as Slot 
    1316 
    1417from Orange.orng import orngServerFiles 
     
    1619from Orange.OrangeWidgets import OWGUI 
    1720from Orange.OrangeWidgets.OWWidget import * 
     21 
     22from Orange.OrangeWidgets.OWConcurrent import \ 
     23    ThreadExecutor, Task, methodinvoke 
     24 
    1825from Orange.utils import progress_bar_milestones 
    1926 
     
    8996        cache = {} 
    9097         
    91         functools.wraps(func) 
     98        @functools.wraps(func) 
    9299        def wrapped(*args, **kwargs): 
    93100            key = args + tuple(sorted(kwargs.items())) 
     
    184191     
    185192    return schema, ret 
    186      
    187      
    188 INFO_SOURCES = {"default": [("NCBI Info", ncbi_info)], 
    189                 "352472": [("NCBI Info", ncbi_info), 
    190                            ("Dicty Base", dicty_info) 
    191                            ] 
    192                 } 
     193 
     194 
     195INFO_SOURCES = { 
     196    "default": [("NCBI Info", ncbi_info)], 
     197    "352472": [("NCBI Info", ncbi_info), 
     198               ("Dicty Base", dicty_info)] 
     199} 
     200 
    193201 
    194202class OWGeneInfo(OWWidget): 
     
    216224 
    217225        self.__initialized = False 
     226        self.initfuture = None 
     227        self.itemsfuture = None 
    218228 
    219229        self.infoLabel = OWGUI.widgetLabel( 
     
    228238        self.organismComboBox = OWGUI.comboBox( 
    229239            self.organismBox, self, "organismIndex", 
    230             callback=self.setItems, 
     240            callback=self.updateInfoItems, 
    231241            debuggingEnabled=0) 
    232242 
     
    242252        box = OWGUI.widgetBox(self.controlArea, "Gene names", addSpace=True) 
    243253        self.geneAttrComboBox = OWGUI.comboBox(box, self, "geneAttr", 
    244                                 "Gene atttibute", callback=self.setItems) 
     254                                "Gene atttibute", callback=self.updateInfoItems) 
    245255         
    246256        c = OWGUI.checkBox(box, self, "useAttr", "Use attribute names", 
    247                            callback=self.setItems, 
     257                           callback=self.updateInfoItems, 
    248258                           disables=[(-1, self.geneAttrComboBox)]) 
    249259         
     
    295305 
    296306        self.setBlocking(True) 
    297         QTimer.singleShot(0, self.initialize) 
     307        self.executor = ThreadExecutor(self) 
     308 
     309        self.progressBarInit() 
     310 
     311        task = Task( 
     312            function=partial( 
     313                obiTaxonomy.ensure_downloaded, 
     314                callback=methodinvoke(self, "advance", ()) 
     315            ) 
     316        ) 
     317 
     318        task.resultReady.connect(self.initialize) 
     319        task.exceptionReady.connect(self._onInitializeError) 
     320 
     321        self.initfuture = self.executor.submit(task) 
     322 
     323    @Slot() 
     324    def advance(self): 
     325        assert self.thread() is QThread.currentThread() 
     326 
     327        self.progressBarSet(self.progressBarValue + 1, 
     328                            processEventsFlags=None) 
    298329 
    299330    def initialize(self): 
     
    301332            # Already initialized 
    302333            return 
     334 
     335        self.progressBarFinished() 
    303336 
    304337        self.organisms = sorted( 
     
    308341        ) 
    309342 
    310         pb = OWGUI.ProgressBar(self, 100) 
    311         obiTaxonomy.ensure_downloaded(pb.advance) 
    312  
    313343        self.organismComboBox.addItems( 
    314344            [obiTaxonomy.name(tax_id) for tax_id in self.organisms] 
    315345        ) 
    316         pb.finish() 
    317346 
    318347        self.infoLabel.setText("No data on input\n") 
    319348        self.__initialized = True 
     349        self.initfuture = None 
     350 
    320351        self.setBlocking(False) 
     352 
     353    def _onInitializeError(self, exc): 
     354        sys.excepthook(type(exc), exc.args, None) 
     355        self.error(0, "Could not download the necessary files.") 
    321356 
    322357    def setData(self, data=None): 
    323358        if not self.__initialized: 
    324             raise Exception("Not initialized") 
     359            self.initfuture.result() 
     360            self.initialize() 
     361 
     362        if self.itemsfuture is not None: 
     363            raise Exception("Already processing") 
    325364 
    326365        self.closeContext() 
    327366        self.data = data 
     367 
    328368        if data: 
    329369            self.geneAttrComboBox.clear() 
     
    335375            self.openContext("", data) 
    336376            self.geneAttr = min(self.geneAttr, len(self.attributes) - 1) 
    337              
     377 
    338378            taxid = data_hints.get_hint(self.data, "taxid", "") 
    339379            if taxid in self.organisms: 
    340380                self.organismIndex = self.organisms.index(taxid) 
    341                  
     381 
    342382            self.useAttr = data_hints.get_hint(self.data, "genesinrows",  self.useAttr) 
    343              
    344             self.setItems() 
     383 
     384            self.updateInfoItems() 
    345385        else: 
    346386            self.clear() 
     
    356396        name, func =  sources[min(self.useAltSource, len(sources) - 1)] 
    357397        return name, func 
    358          
    359     def setItems(self): 
    360         self.warning(0) 
    361         if not self.data: 
    362             return 
     398 
     399    def inputGenes(self): 
    363400        if self.useAttr: 
    364401            genes = [attr.name for attr in self.data.domain.attributes] 
     
    368405        else: 
    369406            genes = [] 
     407        return genes 
     408 
     409    def updateInfoItems(self): 
     410        self.warning(0) 
     411        if not self.data: 
     412            return 
     413 
     414        genes = self.inputGenes() 
     415        if self.useAttr: 
     416            genes = [attr.name for attr in self.data.domain.attributes] 
     417        elif self.attributes: 
     418            attr = self.attributes[self.geneAttr] 
     419            genes = [str(ex[attr]) for ex in self.data if not ex[attr].isSpecial()] 
     420        else: 
     421            genes = [] 
    370422        if not genes: 
    371423            self.warning(0, "Could not extract genes from input dataset.") 
     424 
    372425        self.warning(1) 
    373426        org = self.organisms[min(self.organismIndex, len(self.organisms) - 1)] 
    374427        source_name, info_getter = self.infoSource() 
    375         info , currorg = self.currentLoaded 
     428        info, currorg = self.currentLoaded 
    376429        self.error(0) 
    377          
     430 
    378431        self.updateDictyExpressLink(genes, show=org == "352472") 
    379432        self.altSourceCheck.setVisible(org == "352472") 
    380          
    381         # get the info for the genes in a separate thread 
     433 
    382434        self.progressBarInit() 
    383 #        call = self.asyncCall(info_getter, (org, genes), 
    384 #                              name="Load NCBI Gene Info", 
    385 #                              blocking=False) 
    386 #        call.connect(call, SIGNAL("progressChanged(float)"), self.progressBarSet, Qt.QueuedConnection) 
    387 #        with orngServerFiles.DownloadProgress.setredirect(call.emitProgressChanged): 
    388 #            call.__call__() 
    389 #            schema, geneinfo = call.get_result() 
    390 #        call.__call__() 
    391 #        schema, geneinfo = call.get_result() 
    392         with orngServerFiles.DownloadProgress.setredirect(self.progressBarSet): 
    393             schema, geneinfo = info_getter(org, genes) 
     435        self.setBlocking(True) 
     436        self.setEnabled(False) 
     437        self.infoLabel.setText("Retrieving info records.\n") 
     438 
     439        self.genes = genes 
     440 
     441        task = Task(function=partial(info_getter, org, genes)) 
     442        self.itemsfuture = self.executor.submit(task) 
     443        task.finished.connect(self._onItemsCompleted) 
     444 
     445    def _onItemsCompleted(self): 
     446        self.setBlocking(False) 
    394447        self.progressBarFinished() 
    395         # schema, geneinfo = info_getter(org, genes)  
    396  
    397         self.geneinfo = geneinfo = list(zip(genes, geneinfo)) 
    398  
    399         self.progressBarInit() 
    400  
    401         milestones = progress_bar_milestones(len(geneinfo)) 
     448        self.setEnabled(True) 
     449 
     450        try: 
     451            schema, geneinfo = self.itemsfuture.result() 
     452        finally: 
     453            self.itemsfuture = None 
     454 
     455        self.geneinfo = geneinfo = list(zip(self.genes, geneinfo)) 
     456 
    402457        self.cells = cells = [] 
    403458        self.row2geneinfo = {} 
    404459        links = [] 
    405         for i, (gene, gi) in enumerate(geneinfo): 
     460        for i, (_, gi) in enumerate(geneinfo): 
    406461            if gi: 
    407462                row = [] 
    408                 for sch, item in zip(schema, gi): 
    409                     if isinstance(item, Link): # TODO: This should be handled by delegates  
     463                for _, item in zip(schema, gi): 
     464                    if isinstance(item, Link): 
     465                        # TODO: This should be handled by delegates 
    410466                        row.append(item.text) 
    411467                        links.append(item.link) 
     
    414470                cells.append(row) 
    415471                self.row2geneinfo[len(cells) - 1] = i 
    416 #                cells.append([gi.gene_id, gi.symbol + " (%s)" % gene if gene != gi.symbol else gi.symbol, 
    417 #                            gi.locus_tag or "", gi.chromosome or "", gi.description or "", 
    418 #                            ", ".join(gi.synonyms), gi.symbol_from_nomenclature_authority or ""]) 
    419 #                links.append("http://www.ncbi.nlm.nih.gov/sites/entrez?Db=gene&Cmd=ShowDetailView&TermToSearch=%s" % gi.gene_id) 
    420  
    421             if i in milestones: 
    422                 self.progressBarSet(100.0*i/len(geneinfo)) 
    423  
    424         model = TreeModel(cells, [str(col) for col in schema], self.treeWidget) 
    425          
     472 
     473        model = TreeModel(cells, [str(col) for col in schema], None) 
     474 
    426475        model.setColumnLinks(0, links) 
    427476        proxyModel = QSortFilterProxyModel(self) 
    428477        proxyModel.setSourceModel(model) 
    429478        self.treeWidget.setModel(proxyModel) 
    430         self.connect(self.treeWidget.selectionModel(), SIGNAL("selectionChanged(QItemSelection , QItemSelection )"), self.commitIf) 
     479        self.connect(self.treeWidget.selectionModel(), 
     480                     SIGNAL("selectionChanged(QItemSelection , QItemSelection )"), 
     481                     self.commitIf) 
     482 
    431483        for i in range(7): 
    432484            self.treeWidget.resizeColumnToContents(i) 
    433485            self.treeWidget.setColumnWidth(i, min(self.treeWidget.columnWidth(i), 200)) 
    434         self.treeWidget.update() 
    435         self.progressBarFinished() 
    436  
    437         self.infoLabel.setText("%i genes\n%i matched NCBI's IDs" % (len(genes), len(cells))) 
    438         self.matchedInfo = len(genes), len(cells) 
     486 
     487        self.infoLabel.setText("%i genes\n%i matched NCBI's IDs" % 
     488                               (len(self.genes), len(cells))) 
     489        self.matchedInfo = len(self.genes), len(cells) 
    439490 
    440491    def clear(self): 
     
    591642             
    592643    def onAltSourceChange(self): 
    593         self.setItems() 
    594          
     644        self.updateInfoItems() 
     645 
     646    def onDeleteWidget(self): 
     647        OWWidget.onDeleteWidget(self) 
     648 
     649        # try to cancel pending tasks 
     650        if self.initfuture: 
     651            self.initfuture.cancel() 
     652        if self.itemsfuture: 
     653            self.itemsfuture.cancel() 
     654 
     655        self.executor.shutdown() 
     656 
     657 
    595658def reportItemView(view): 
    596659    model = view.model() 
     
    618681    w = OWGeneInfo() 
    619682    w.show() 
    620     w.initialize() 
    621683 
    622684    w.setData(data) 
Note: See TracChangeset for help on using the changeset viewer.