source: orange-bioinformatics/orangecontrib/bio/widgets/OWGEODatasets.py @ 1874:b3e32cc5cf6f

Revision 1874:b3e32cc5cf6f, 23.8 KB checked in by Ales Erjavec <ales.erjavec@…>, 6 months ago (diff)

Added new style widget meta descriptions.

RevLine 
[1397]1"""<name>GEO Data Sets</name>
[752]2<description>Access to Gene Expression Omnibus data sets.</description>
[1051]3<priority>20</priority>
[738]4<contact>Ales Erjavec (ales.erjavec(@at@)fri.uni-lj.si)</contact>
[1726]5<icon>icons/GEODataSets.svg</icon>
[738]6"""
7
[1632]8from __future__ import absolute_import, with_statement
[1113]9
[890]10from collections import defaultdict
11from functools import partial
[1632]12import sys, os, glob
13
14from Orange.orng import orngServerFiles
15from Orange.orng.orngDataCaching import data_hints
16from Orange.OrangeWidgets import OWGUI, OWGUIEx
17from Orange.OrangeWidgets.OWWidget import *
18
19from .. import obiGEO
[890]20
[1874]21NAME = "GEO Data Sets"
22DESCRIPTION = "Access to Gene Expression Omnibus data sets."
23ICON = "icons/GEODataSets.svg"
24PRIORITY = 20
25
26INPUTS = []
27OUTPUTS = [("Expression Data", Orange.data.Table)]
28
29REPLACES = ["_bioinformatics.widgets.OWGEODatasets.OWGEODatasets"]
30
31
[819]32LOCAL_GDS_COLOR = Qt.darkGreen
[818]33
[1374]34TextFilterRole = OWGUI.OrangeUserRole.next()
35
[890]36class TreeModel(QAbstractItemModel):
37    def __init__(self, data, header, parent):
38        QAbstractItemModel.__init__(self, parent)
39        self._data = [[QVariant(s) for s in row] for row in data]
40        self._dataDict = {}
[1013]41        self._header = {Qt.Horizontal: dict([(i, {Qt.DisplayRole: h}) for i, h in enumerate(header)])}
[890]42        self._roleData = {Qt.DisplayRole:self._data}
[1013]43        dataStore = partial(defaultdict, partial(defaultdict, partial(defaultdict, QVariant)))
44        self._roleData = dataStore(self._roleData)
45        self._header = dataStore(self._header)
[741]46   
[890]47    def setColumnLinks(self, column, links):
48        font =QFont()
49        font.setUnderline(True)
50        font = QVariant(font)
51        for i, link in enumerate(links):
52            self._roleData[LinkRole][i][column] = QVariant(link)
53            self._roleData[Qt.FontRole][i][column] = font
54            self._roleData[Qt.ForegroundRole][i][column] = QVariant(QColor(Qt.blue))
55   
56    def setRoleData(self, role, row, col, data):
57        self._roleData[role][row][col] = data
58       
[1113]59    def setData(self, index, value, role=Qt.EditRole):
60        self._roleData[role][index.row()][index.column()] = value
61        self.emit(SIGNAL("dataChanged(QModelIndex, QModelIndex)"), index, index)
62       
[890]63    def data(self, index, role):
64        row, col = index.row(), index.column()
65        return self._roleData[role][row][col]
66       
67    def index(self, row, col, parent=QModelIndex()):
68        return self.createIndex(row, col, 0)
69   
70    def parent(self, index):
71        return QModelIndex()
72   
[982]73    def rowCount(self, index=QModelIndex()):
[890]74        if index.isValid():
75            return 0
[739]76        else:
[890]77            return len(self._data)
78       
79    def columnCount(self, index):
[1013]80        return len(self._header[Qt.Horizontal])
[890]81
82    def headerData(self, section, orientation, role):
[1013]83        try:
84            return QVariant(self._header[orientation][section][role])
85        except KeyError, er:
86#            print >> sys.stderr, er
87            return QVariant()
88       
89    def setHeaderData(self, section, orientation, value, role=Qt.EditRole):
90        self._header[orientation][section][role] = value
[1374]91       
[1601]92from Orange.utils import lru_cache
[1397]93
[1374]94class MySortFilterProxyModel(QSortFilterProxyModel):   
95    def __init__(self, parent=None):
96        QSortFilterProxyModel.__init__(self, parent)
97        self._filter_strings = []
98        self._cache = {}
99        self._cache_fixed = {}
100        self._cache_prefix = {}
101        self._row_text = {}
[1397]102       
103        # Create a cached version of _filteredRows
104        self._filteredRows = lru_cache(100)(self._filteredRows) 
[1374]105
106    def setSourceModel(self, model):
[1397]107        """ Set the source model for the filter
108        """ 
[1374]109        self._filter_strings = []
110        self._cache = {}
111        self._cache_fixed = {}
112        self._cache_prefix = {}
113        self._row_text = {}
114        QSortFilterProxyModel.setSourceModel(self, model)
115       
116    def addFilterFixedString(self, string, invalidate=True):
[1397]117        """ Add `string` filter to the list of filters. If invalidate is
118        True the filter cache will be recomputed.
119        """
[1374]120        self._filter_strings.append(string)
121        all_rows = range(self.sourceModel().rowCount())
122        row_text = [self.rowFilterText(row) for row in all_rows]
123        self._cache[string] = [string in text for text in row_text]
124        if invalidate:
125            self.updateCached()
[1397]126            self.invalidateFilter()
[1374]127       
128    def removeFilterFixedString(self, index=-1, invalidate=True):
[1397]129        """ Remove the `index`-th filter string. If invalidate is True the
130        filter cache will be recomputed.
131        """
132        string = self._filter_strings.pop(index) 
133        del self._cache[string] 
[1374]134        if invalidate:
135            self.updateCached()
[1397]136            self.invalidateFilter()
[1374]137           
138    def setFilterFixedStrings(self, strings):
[1397]139        """ Set a list of string to be the new filters.
140        """
[1374]141        s_time = time.time()
142        to_remove = set(self._filter_strings) - set(strings)
143        to_add = set(strings) - set(self._filter_strings)
144        for str in to_remove:
145            self.removeFilterFixedString(self._filter_strings.index(str), invalidate=False)
146       
147        for str in to_add:
148            self.addFilterFixedString(str, invalidate=False)
149        self.updateCached()
[1397]150        self.invalidateFilter()
[1374]151           
[1397]152    def _filteredRows(self, filter_strings):
153        """ Return a dictionary mapping row indexes to True False values.
154        .. note:: This helper function is wrapped in the __init__ method.
155        """
156        all_rows = range(self.sourceModel().rowCount())
157        cache = self._cache
158        return dict([(row, all([cache[str][row] for str in filter_strings])) for row in all_rows])
159   
[1374]160    def updateCached(self):
[1397]161        """ Update the combined filter cache.
162        """
163        self._cache_fixed = self._filteredRows(tuple(sorted(self._filter_strings))) 
[1374]164       
165    def setFilterFixedString(self, string):
[1397]166        """Should this raise an error? It is not being used.
167        """
[1374]168        QSortFilterProxyModel.setFilterFixedString(self, string)
169       
170    def rowFilterText(self, row):
[1397]171        """ Return text for `row` to filter on.
172        """
[1374]173        f_role = self.filterRole()
174        f_column = self.filterKeyColumn()
175        s_model = self.sourceModel()
176        data = s_model.data(s_model.index(row, f_column), f_role)
177        if isinstance(data, QVariant):
178            data = unicode(data.toString(), errors="ignore")
179        else:
180            data = unicode(data, errors="ignore")
181        return data
182       
[1397]183    def filterAcceptsRow(self, row, parent): 
184        return self._cache_fixed.get(row, True)
[890]185   
[1460]186    def lessThan(self, left, right):
187        if left.column() == 1 and right.column(): # TODO: Remove fixed column handling
188            left_gds = str(left.data(Qt.DisplayRole).toString())
189            right_gds = str(right.data(Qt.DisplayRole).toString())
190            left_gds = left_gds.lstrip("GDS")
191            right_gds = right_gds.lstrip("GDS")
192            try:
193                return int(left_gds) < int(right_gds)
194            except Exception, ex:
195                pass
196        return QSortFilterProxyModel.lessThan(self, left, right)
197   
[1632]198from Orange.OrangeWidgets.OWGUI import LinkStyledItemDelegate, LinkRole
[1140]199
[1346]200def childiter(item):
201    """ Iterate over the children of an QTreeWidgetItem instance.
202    """
203    for i in range(item.childCount()):
204        yield item.child(i)
205               
[738]206class OWGEODatasets(OWWidget):
[982]207    settingsList = ["outputRows", "mergeSpots", "gdsSelectionStates", "splitterSettings", "currentGds", "autoCommit"]
[738]208
[1397]209    def __init__(self, parent=None ,signalManager=None, name=" GEO Data Sets"):
[738]210        OWWidget.__init__(self, parent ,signalManager, name)
211
[896]212        self.outputs = [("Expression Data", ExampleTable)]
[738]213
214        ## Settings
[906]215#        self.selectedSubsets = []
216#        self.sampleSubsets = []
217        self.selectedAnnotation = 0
[738]218        self.includeIf = False
219        self.minSamples = 3
220        self.autoCommit = False
221        self.outputRows = 0
222        self.mergeSpots = True
223        self.filterString = ""
[982]224        self.currentGds = None
225        self.selectionChanged = False
226        self.autoCommit = False
[945]227        self.gdsSelectionStates = {}
228        self.splitterSettings = ['\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xea\x00\x00\x00\xd7\x01\x00\x00\x00\x07\x01\x00\x00\x00\x02',
229                                 '\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x01\xb5\x00\x00\x02\x10\x01\x00\x00\x00\x07\x01\x00\x00\x00\x01']
[738]230
231        self.loadSettings()
232
233        ## GUI
[1222]234        self.infoBox = OWGUI.widgetLabel(OWGUI.widgetBox(self.controlArea, "Info", addSpace=True), "\n\n")
[738]235
[1222]236        box = OWGUI.widgetBox(self.controlArea, "Output", addSpace=True)
[982]237        OWGUI.radioButtonsInBox(box, self, "outputRows", ["Genes or spots", "Samples"], "Rows", callback=self.commitIf)
238        OWGUI.checkBox(box, self, "mergeSpots", "Merge spots of same gene", callback=self.commitIf)
[738]239
[1222]240        box = OWGUI.widgetBox(self.controlArea, "Output", addSpace=True)
[922]241        self.commitButton = OWGUI.button(box, self, "Commit", callback=self.commit)
[982]242        cb = OWGUI.checkBox(box, self, "autoCommit", "Commit on any change")
243        OWGUI.setStopper(self, self.commitButton, cb, "selectionChanged", self.commit)
[738]244        OWGUI.rubber(self.controlArea)
245
[1373]246        self.filterLineEdit = OWGUIEx.lineEditHint(self.mainArea, self, "filterString", "Filter",
247                                   caseSensitive=False, matchAnywhere=True, 
[1405]248                                   #listUpdateCallback=self.filter, callbackOnType=False,
[1373]249                                   callback=self.filter,  delimiters=" ")
250       
[945]251        splitter = QSplitter(Qt.Vertical, self.mainArea)
252        self.mainArea.layout().addWidget(splitter)
253        self.treeWidget = QTreeView(splitter)
254       
[738]255        self.treeWidget.setSelectionMode(QAbstractItemView.SingleSelection)
256        self.treeWidget.setRootIsDecorated(False)
[741]257        self.treeWidget.setSortingEnabled(True)
[1013]258        self.treeWidget.setAlternatingRowColors(True)
[1374]259        self.treeWidget.setUniformRowHeights(True)
[890]260        self.treeWidget.setItemDelegate(LinkStyledItemDelegate(self.treeWidget))
[1013]261        self.treeWidget.setItemDelegateForColumn(0, OWGUI.IndicatorItemDelegate(self.treeWidget, role=Qt.DisplayRole))
262       
[738]263        self.connect(self.treeWidget, SIGNAL("itemSelectionChanged ()"), self.updateSelection)
[890]264        self.treeWidget.viewport().setMouseTracking(True)
[1373]265       
[945]266        splitterH = QSplitter(Qt.Horizontal, splitter) 
[1373]267       
[945]268        box = OWGUI.widgetBox(splitterH, "Description")
269        self.infoGDS = OWGUI.widgetLabel(box, "")
[738]270        self.infoGDS.setWordWrap(True)
[945]271        OWGUI.rubber(box)
272       
273        box = OWGUI.widgetBox(splitterH, "Sample Annotations")
274        self.annotationsTree = QTreeWidget(box)
275        self.annotationsTree.setHeaderLabels(["Type (Sample annotations)", "Sample count"])
276        self.annotationsTree.setRootIsDecorated(True)
277        box.layout().addWidget(self.annotationsTree)
278        self.connect(self.annotationsTree, SIGNAL("itemChanged(QTreeWidgetItem * , int)"), self.annotationSelectionChanged)
279        self._annotationsUpdating = False
280        self.splitters = splitter, splitterH
281        self.connect(splitter, SIGNAL("splitterMoved(int, int)"), self.splitterMoved)
282        self.connect(splitterH, SIGNAL("splitterMoved(int, int)"), self.splitterMoved)
283       
284        for sp, setting in zip(self.splitters, self.splitterSettings):
285            sp.restoreState(setting)
286           
[897]287        self.searchKeys = ["dataset_id", "title", "platform_organism", "description"]
[890]288        self.cells = []
[1373]289       
[738]290        QTimer.singleShot(50, self.updateTable)
[900]291        self.resize(1000, 600)
[738]292
293    def updateInfo(self):
[1374]294        gds_info = self.gds_info #obiGEO.GDSInfo()
[945]295        text = "%i datasets\n%i datasets cached\n" % (len(gds_info), len(glob.glob(orngServerFiles.localpath("GEO") + "/GDS*")))
[1374]296        filtered = self.treeWidget.model().rowCount()
[890]297        if len(self.cells) != filtered:
[847]298            text += ("%i after filtering") % filtered
299        self.infoBox.setText(text)
[738]300       
301    def updateTable(self):
302        self.treeItems = []
[754]303        self.progressBarInit()
[859]304        with orngServerFiles.DownloadProgress.setredirect(self.progressBarSet):
[1374]305            self.gds_info = info = obiGEO.GDSInfo()
[754]306        milestones = set(range(0, len(info), max(len(info)/100, 1)))
[890]307        self.cells = cells = []
308        gdsLinks = []
309        pmLinks = []
310        localGDS = []
[1374]311        full_text_search_data = []
312       
[890]313        self.gds = []
[754]314        for i, (name, gds) in enumerate(info.items()):
[1013]315            local = os.path.exists(orngServerFiles.localpath(obiGEO.DOMAIN, gds["dataset_id"] + ".soft.gz"))
316            cells.append([" " if local else "", gds["dataset_id"], gds["title"], gds["platform_organism"], len(gds["samples"]), gds["feature_count"],
[890]317                          gds["gene_count"], len(gds["subsets"]), gds.get("pubmed_id", "")])
318
319            gdsLinks.append("http://www.ncbi.nlm.nih.gov/sites/GDSbrowser?acc=%s" % gds["dataset_id"])
320            pmLinks.append("http://www.ncbi.nlm.nih.gov/pubmed/%s" % gds.get("pubmed_id") if gds.get("pubmed_id") else QVariant())
321
[1013]322            if local:
[890]323                localGDS.append(i)
324            self.gds.append(gds)
325           
[1374]326            full_text_search_data.append(unicode(" | ".join([gds.get(key, "").lower() for key in self.searchKeys]), errors="ignore"))
327           
[754]328            if i in milestones:
[890]329                self.progressBarSet(100.0*i/len(info))
[754]330
[1013]331        model = TreeModel(cells, ["", "ID", "Title", "Organism", "Samples", "Features", "Genes", "Subsets", "PubMedID"], self.treeWidget)
332        model.setColumnLinks(1, gdsLinks)
333        model.setColumnLinks(8, pmLinks)
[1374]334       
335        for i, text in enumerate(full_text_search_data):
336            model.setData(model.index(i, 0), QVariant(text), TextFilterRole)
337       
338        proxyModel = MySortFilterProxyModel(self.treeWidget)
339#        proxyModel = QSortFilterProxyModel(self.treeWidget)
[890]340        proxyModel.setSourceModel(model)
[1374]341        proxyModel.setFilterKeyColumn(0)
342        proxyModel.setFilterRole(TextFilterRole)
343        proxyModel.setFilterCaseSensitivity(False)
344        proxyModel.setFilterFixedString(self.filterString)
[890]345        self.treeWidget.setModel(proxyModel)
346        self.connect(self.treeWidget.selectionModel(), SIGNAL("selectionChanged(QItemSelection , QItemSelection )"), self.updateSelection)
[897]347        filterItems = " ".join([self.gds[i][key] for i in range(len(self.gds)) for key in self.searchKeys])
[1397]348        filterItems = reduce(lambda s, d: s.replace(d, " "),
349                             [",", ".", ":", ";", "!", "?", "(", ")", "{", "}"
350                              "[", "]", "_", "-", "+", "\\", "|", "/", "%", "#",
351                              "@", "$", "^", "&", "*", "<", ">", "~", "`"],
352                             filterItems.lower())
[897]353        filterItems = sorted(set(filterItems.split(" ")))
[1380]354        filterItems = [item for item in filterItems if len(filterItems) > 3]
[897]355        self.filterLineEdit.setItems(filterItems)
[900]356       
357        for i in range(8):
358            self.treeWidget.resizeColumnToContents(i)
359        self.treeWidget.setColumnWidth(1, min(self.treeWidget.columnWidth(1), 300))
360        self.treeWidget.setColumnWidth(2, min(self.treeWidget.columnWidth(2), 200))
[890]361        self.progressBarFinished()
[738]362
[982]363        if self.currentGds:
[1262]364            gdss = [(i, model.data(model.index(i,1), Qt.DisplayRole)) for i in range(model.rowCount())]
365            current = [i for i, variant in gdss if variant.isValid() and str(variant.toString()) == self.currentGds["dataset_id"]]
[982]366            if current:
367                mapFromSource = self.treeWidget.model().mapFromSource
368                self.treeWidget.selectionModel().select(mapFromSource(model.index(current[0], 0)), QItemSelectionModel.Select | QItemSelectionModel.Rows)
369           
[738]370        self.updateInfo()
371
[890]372    def updateSelection(self, *args):
373        current = self.treeWidget.selectedIndexes()
374        mapToSource = self.treeWidget.model().mapToSource
375        current = [mapToSource(index).row() for index in current]
[738]376        if current:
[890]377            self.currentGds = self.gds[current[0]]
[906]378            self.setAnnotations(self.currentGds)
[890]379            self.infoGDS.setText(self.currentGds.get("description", ""))
[738]380        else:
[890]381            self.currentGds = None
[982]382#        self.commitButton.setDisabled(not bool(self.currentGds))
383        self.commitIf()
[738]384       
[945]385   
[906]386    def setAnnotations(self, gds):
[945]387        self._annotationsUpdating = True
388        self.annotationsTree.clear()
389        annotations = reduce(lambda d, info: d[info["type"]].add(info["description"]) or d, gds["subsets"], defaultdict(set))
390        subsetscount = dict([(s["description"], str(len(s["sample_id"]))) for s in gds["subsets"]])
391        for type, subsets in annotations.items():
392            key = (gds["dataset_id"], type)
393            subsetItem = QTreeWidgetItem(self.annotationsTree, [type])
394            subsetItem.setFlags(subsetItem.flags() | Qt.ItemIsUserCheckable | Qt.ItemIsTristate)
395            subsetItem.setCheckState(0, self.gdsSelectionStates.get(key, Qt.Checked))
396            subsetItem.key = key
397            for subset in subsets:
398                key = (gds["dataset_id"], type, subset)
399                item = QTreeWidgetItem(subsetItem, [subset, subsetscount.get(subset, "")])
400                item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
401                item.setCheckState(0, self.gdsSelectionStates.get(key, Qt.Checked))
402                item.key = key
403        self._annotationsUpdating = False
404        self.annotationsTree.expandAll()
405        for i in range(self.annotationsTree.columnCount()):
406            self.annotationsTree.resizeColumnToContents(i)
407               
408    def annotationSelectionChanged(self, item, column):
409        if self._annotationsUpdating:
410            return 
411        for i in range(self.annotationsTree.topLevelItemCount()):
412            item = self.annotationsTree.topLevelItem(i)
413            self.gdsSelectionStates[item.key] = item.checkState(0)
414            for j in range(item.childCount()):
415                child = item.child(j)
416                self.gdsSelectionStates[child.key] = child.checkState(0)
[890]417       
418    def rowFiltered(self, row):
419        filterStrings = self.filterString.lower().split()
420        try:
[897]421            string = " ".join([self.gds[row].get(key, "").lower() for key in self.searchKeys])
[895]422            return not all([s in string for s in filterStrings])
423        except UnicodeDecodeError:
[897]424            string = " ".join([unicode(self.gds[row].get(key, "").lower(), errors="ignore") for key in self.searchKeys])
[895]425            return not all([s in string for s in filterStrings])
[890]426   
[738]427    def filter(self):
[1374]428        filter_string = unicode(self.filterLineEdit.text(), errors="ignore")
429        proxyModel = self.treeWidget.model()
[1426]430        if proxyModel:
431            strings = filter_string.lower().strip().split()
432            proxyModel.setFilterFixedStrings(strings)
433            self.updateInfo()
[738]434
[1346]435    def selectedSamples(self):
436        """ Return the currently selected sample annotations (list of
437        sample type, sample value tuples).
438       
439        .. note:: if some Sample annotation type has no selected values.
440                  this method will return all values for it.
441       
442        """
443        samples = []
444        unused_types = []
[1374]445        for stype in childiter(self.annotationsTree.invisibleRootItem()): 
[1346]446            selected_values = []
447            all_values = []
448            for sval in childiter(stype):
449                value = (str(stype.text(0)), str(sval.text(0)))
450                if self.gdsSelectionStates.get(sval.key, True):
451                    selected_values.append(value)
452                all_values.append(value)
453            if selected_values:
454                samples.extend(selected_values)
455            else:
456                # If no sample of sample type is selected we don't filter on it.
457                samples.extend(all_values)
458                unused_types.append(str(stype.text(0)))
459               
460        return samples
461   
[982]462    def commitIf(self):
463        if self.autoCommit:
464            self.commit()
465        else:
466            self.selectionChanged = True
[1346]467   
[1272]468    def commit(self):
[1343]469        if self.currentGds:
470            self.error(0) 
[1272]471            sample_type = None
472            self.progressBarInit()
473            self.progressBarSet(10)
[1262]474           
[1272]475            def getdata(gds_id, **kwargs):
476                gds = obiGEO.GDS(gds_id)
477                data = gds.getdata(**kwargs)
478                return data
479           
480            self.setEnabled(False)
481            call = self.asyncCall(getdata, (self.currentGds["dataset_id"],), dict(report_genes=self.mergeSpots,
482                                           transpose=self.outputRows,
483                                           sample_type=sample_type if sample_type!="Include all" else None),
[1343]484                                  onResult=self.onData,
485                                  onFinished=lambda: self.setEnabled(True),
486                                  onError=self.onAsyncError,
[1272]487                                  threadPool=QThreadPool.globalInstance()
488                                 )
489            call.__call__() #invoke
[1343]490
491    def onAsyncError(self, (exctype, value, tb)):
492        import ftplib
493        if issubclass(exctype, ftplib.error_temp):
494            self.error(0, "Can not download dataset from NCBI ftp server! Try again later.")
495        elif issubclass(exctype, ftplib.all_errors):
496            self.error(0, "Error while connecting to the NCBI ftp server! %s" % str(value))
497        else:
498            sys.excepthook(exctype, value, tb)
499           
500        self.progressBarFinished()
501
[1262]502    def onData(self, data):
503        self.progressBarSet(50)
504       
[1346]505        samples = self.selectedSamples()
506       
[1373]507        self.warning(0)
[1346]508        message = None
[1262]509        if self.outputRows:
[1346]510            samples = set(s[1] for s in samples) # dont have info on sample types in the data class variable
511            select = [1 if samples.issuperset(str(ex.getclass()).split("|")) else 0 for ex in data]
[1262]512            data = data.select(select)
[1346]513            # TODO: add sample types as separate features 
[1262]514            data.domain.classVar.values = ["|".join([cl for cl in val.split("|") if cl in samples]) for val in data.domain.classVar.values]
[1346]515            if len(data) == 0:
[1373]516                message = "No samples with selected sample annotations."
[1262]517        else:
[1346]518            samples = set(samples)
519            domain = orange.Domain([attr for attr in data.domain.attributes if samples.issuperset(attr.attributes.items())], data.domain.classVar)
[1262]520            domain.addmetas(data.domain.getmetas())
[1373]521            if len(domain.attributes) == 0:
522                message = "No samples with selected sample annotations."
[1346]523            stypes = set(s[0] for s in samples)
[1262]524            for attr in domain.attributes:
[1346]525                attr.attributes = dict([(key, value) for key, value in attr.attributes.items() if key in stypes])
[1262]526            data = orange.ExampleTable(domain, data)
[1373]527       
528        if message is not None:
529            self.warning(0, message)
530           
[1262]531        data_hints.set_hint(data, "taxid", self.currentGds.get("taxid", ""), 10.0)
532        data_hints.set_hint(data, "genesinrows", self.outputRows, 10.0)
533       
534        self.progressBarFinished()
535        self.send("Expression Data", data)
[890]536
[1262]537        model = self.treeWidget.model().sourceModel()
538        row = self.gds.index(self.currentGds)
[1113]539#            model._roleData[Qt.ForegroundRole][row].update(zip(range(1, 7), [QVariant(QColor(LOCAL_GDS_COLOR))] * 6))
[1262]540        model.setData(model.index(row, 0),  QVariant(" "), Qt.DisplayRole) 
[1113]541#            model.emit(SIGNAL("dataChanged(const QModelIndex &, const QModelIndex &)"), model.index(row, 0), model.index(row, 0))
[1262]542        self.updateInfo()
[982]543        self.selectionChanged = False
[945]544       
545    def splitterMoved(self, *args):
546        self.splitterSettings = [str(sp.saveState()) for sp in self.splitters]
[738]547
548if __name__ == "__main__":
549    app = QApplication(sys.argv)
550    w = OWGEODatasets()
551    w.show()
552    app.exec_()
[752]553    w.saveSettings()
Note: See TracBrowser for help on using the repository browser.