Changeset 1561:4769cbf80eca in orange-bioinformatics


Ignore:
Timestamp:
02/13/12 16:35:05 (2 years ago)
Author:
ales_erjavec
Branch:
default
Message:

Added caching of computed distances. Can now change the base for each group individually and the base can be from the background.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • widgets/OWQualityControl.py

    r1560 r1561  
    99 
    1010from OWWidget import * 
    11 from OWItemModels import PyListModel 
     11from OWItemModels import PyListModel, safe_text 
    1212from OWGraphics import GraphicsSimpleTextLayoutItem, GtI 
    1313import OWGUI 
     
    6767    except ValueError: 
    6868        return val 
     69     
     70def experiment_description(feature): 
     71    text = "" 
     72    if feature.attributes: 
     73        items = feature.attributes.items() 
     74        items = [(safe_text(key), safe_text(value)) for key, value in items] 
     75        labels = map("%s = %s".__mod__, items) 
     76        text += "Experiment Labels:<br/>" 
     77        text += "<br/>".join(labels) 
     78    return text 
    6979 
    7080class OWQualityControl(OWWidget): 
     
    145155 
    146156        self._disable_updates = False 
     157        self._cached_distances = {} 
     158        self._base_index_hints = {} 
    147159        self.main_widget = None 
    148160         
     
    163175        self.scene.clear() 
    164176        self.info_box.setText("\n") 
     177        self._cached_distances = {} 
    165178 
    166179    def set_data(self, data=None): 
     
    223236        return self.DISTANCE_FUNCTIONS[self.selected_distance_index][1] 
    224237     
    225     def selected_base_index(self): 
    226         """Return the selected base index 
     238    def selected_base_group_index(self): 
     239        """Return the selected base group index 
    227240        """ 
    228241        return self.base_index 
     242     
     243    def selected_base_indices(self, base_group_index=None): 
     244        indices = [] 
     245        for g, ind in self.groups: 
     246            if base_group_index is None: 
     247                label = group_label(self.selected_split_by_labels(), g) 
     248                ind = filter(None, ind) 
     249                i = self._base_index_hints.get(label, ind[0] if ind else None) 
     250            else: 
     251                i = ind[base_group_index] 
     252            indices.append(i) 
     253        return indices 
    229254 
    230255    def on_new_data(self): 
     
    285310        with widget_disable(self): 
    286311            if not self._disable_updates: 
     312                self.base_index = 0 
    287313                context = self.currentContexts[""] 
    288314                context.sort_by_labels = self.selected_sort_by_labels() 
     
    308334        """An ``item`` in the quality plot has been clicked. 
    309335        """ 
    310         base = item.index 
    311         if base != self.base_index: 
    312             self.base_index = base 
     336        update = False 
     337        sort_by_labels = self.selected_sort_by_labels() 
     338        if sort_by_labels and item.in_group: 
     339            ## The item is part of the group 
     340            if item.group_index != self.base_index: 
     341                self.base_index = item.group_index 
     342                update = True 
     343             
     344        else: 
     345            if sort_by_labels: 
     346                # If the user clicked on an background item it 
     347                # invalidates the sorted labels selection 
     348                with disable_updates(self): 
     349                    self.sort_by_view.selectionModel().clear() 
     350                    update = True 
     351                     
     352            index = item.index 
     353            group = item.group 
     354            label = group_label(self.selected_split_by_labels(), group) 
     355             
     356            if self._base_index_hints.get(label, 0) != index: 
     357                self._base_index_hints[label] = index 
     358                update = True 
     359             
     360        if update: 
    313361            self.split_and_update() 
    314362         
     
    319367         
    320368        """ 
     369        split_labels = self.selected_split_by_labels() 
     370        sort_labels = self.selected_sort_by_labels() 
    321371        self.groups, self.unique_pos = \ 
    322                 exp.separate_by(self.data, 
    323                                 self.selected_split_by_labels(), 
    324                                 consider=self.selected_sort_by_labels(), 
     372                exp.separate_by(self.data, split_labels, 
     373                                consider=sort_labels, 
    325374                                add_empty=True) 
    326375         
     
    331380                                 key=lambda t: map(float_if_posible, t[0])) 
    332381         
    333         pprint(self.groups) 
    334         pprint(self.unique_pos) 
     382#        pprint(self.groups) 
     383#        pprint(self.unique_pos) 
     384         
    335385        if self.groups: 
    336             # TODO: Check if the groups of base experiment have changed 
    337             self.update_distances() 
     386            if sort_labels: 
     387                group_base = self.selected_base_group_index() 
     388                base_indices = self.selected_base_indices(group_base) 
     389            else: 
     390                base_indices = self.selected_base_indices() 
     391            self.update_distances(base_indices) 
    338392            self.replot_experiments() 
    339393 
    340     def update_distances(self): 
     394    def get_cached_distances(self, measure): 
     395        if measure not in self._cached_distances: 
     396            attrs = self.data.domain.attributes 
     397            mat = Orange.misc.SymMatrix(len(attrs)) 
     398            self._cached_distances[measure] = \ 
     399                (mat, set(zip(range(len(attrs)), range(len(attrs))))) 
     400             
     401        return self._cached_distances[measure] 
     402             
     403             
     404    def get_cached_distance(self, measure, i, j): 
     405        matrix, computed = self.get_cached_distances(measure) 
     406        key = (i, j) if i < j else (j, i)  
     407        if key in computed: 
     408            return matrix[i, j] 
     409        else: 
     410            return None 
     411         
     412    def get_distance(self, measure, i, j): 
     413        d = self.get_cached_distance(measure, i, j) 
     414        if d is None: 
     415            vec_i = exp.linearize(self.data, [i]) 
     416            vec_j = exp.linearize(self.data, [j]) 
     417            d = distance(vec_i, vec_j) 
     418            mat, computed = self.get_cached_distances(measure) 
     419            mat[i, j] = d 
     420            key = key = (i, j) if i < j else (j, i) 
     421            computed.add(key) 
     422        return d 
     423     
     424    def store_distance(self, measure, i, j, dist): 
     425        matrix, computed = self.get_cached_distances(measure) 
     426        key = key = (i, j) if i < j else (j, i) 
     427        matrix[i, j] = dist 
     428        computed.add(key) 
     429         
     430             
     431    def update_distances(self, base_indices=()): 
    341432        """Recompute the experiment distances. 
    342433        """ 
    343434        distance = self.selected_distance() 
    344         base_index = self.base_index 
     435        if base_indices == (): 
     436            base_group_index = self.selected_base_group_index() 
     437            base_indices = [ind[base_group_index] \ 
     438                            for _, ind in self.groups] 
     439         
     440        assert(len(base_indices) == len(self.groups))  
     441         
    345442        base_distances = [] 
     443        attributes = self.data.domain.attributes 
    346444        pb = OWGUI.ProgressBar(self, len(self.groups) * \ 
    347                                len(self.data.domain.attributes)) 
    348         for group, indices in self.groups: 
     445                               len(attributes)) 
     446         
     447        cached_distances, filled_set = self.get_cached_distances(distance) 
     448         
     449        for (group, indices), base_index in zip(self.groups, base_indices): 
    349450            # Base column of the group 
    350             if indices[base_index] is not None: 
    351                 base_vec = exp.linearize(self.data, [indices[base_index]]) 
     451            if base_index is not None: 
     452                base_vec = exp.linearize(self.data, [base_index]) 
    352453                distances = [] 
    353                 # Compute the distances between base replicate  
     454                # Compute the distances between base column  
    354455                # and all the rest data columns. 
    355                 for i in range(len(self.data.domain.attributes)): 
    356                     if i == indices[base_index]: 
     456                for i in range(len(attributes)): 
     457                    if i == base_index: 
    357458                        distances.append(0.0) 
     459                    elif self.get_cached_distance(distance, i, base_index) is not None: 
     460                        distances.append(self.get_cached_distance(distance, i, base_index)) 
    358461                    else: 
    359462                        vec_i = exp.linearize(self.data, [i]) 
    360                         distances.append(distance(base_vec, vec_i)) 
     463                        dist = distance(base_vec, vec_i) 
     464                        self.store_distance(distance, i, base_index, dist) 
     465                        distances.append(dist) 
    361466                    pb.advance() 
    362467                     
     
    364469            else: 
    365470                base_distances.append(None) 
     471                 
    366472        pb.finish() 
    367473        self.distances = base_distances 
    368474 
    369475    def replot_experiments(self): 
    370         """Replot the whole quality plot 
     476        """Replot the whole quality plot. 
    371477        """ 
    372478        self.scene.clear() 
    373479        labels = [] 
    374         ## Base replicate=1 TODO: the index should be set 
    375         base_index = self.base_index 
     480#        ## Base replicate=1 TODO: the index should be set 
     481#        if self.selected_sort_by_labels(): 
     482#            base_indices = self.selected_base_indices() 
     483#        else: 
     484#            base_indices = self.selected_base_indices(\ 
     485#                                self.selected_base_group_index() 
     486#                                ) 
     487#             
    376488        max_dist = numpy.max(filter(None, self.distances)) 
    377         print max_dist 
    378489        rug_widgets = [] 
    379490         
     
    392503        if self.data: 
    393504            for (group, indices), dist_vec in zip(self.groups, self.distances): 
    394                 base = indices[base_index] 
    395505                indices_set = set(indices) 
    396506                rug_items = [] 
     
    403513                                           1.0, self.on_rug_item_clicked) 
    404514                            rug_item.setPen(group_pen) 
    405                             tooltip = sort_label(split_by, attr) 
    406                             tooltip += "\n" + sort_label(sort_by, attr) 
     515#                            tooltip = sort_label(split_by, attr) 
     516#                            tooltip += "\n" + sort_label(sort_by, attr) 
     517                            tooltip = experiment_description(attr) 
    407518                            rug_item.setToolTip(tooltip) 
    408                             rug_item.setToolTip(sort_label(sort_by, attr)) 
    409                             rug_item.index = indices.index(i) 
     519                            rug_item.group_index = indices.index(i) 
    410520                        else: 
    411 #                            rug_item = RugItem(dist_vec[i] / max_dist, 0.85) 
    412521                            rug_item = ClickableRugItem(dist_vec[i] / max_dist, 
    413                                            0.85, None)#self.on_rug_item_clicked) 
    414                             tooltip = sort_label(split_by, attr) 
    415                             tooltip += "\n" + sort_label(sort_by, attr) 
     522                                           0.85, self.on_rug_item_clicked) 
     523                            rug_item.setPen(background_pen) 
     524#                            tooltip = sort_label(split_by, attr) 
     525#                            tooltip += "\n" + sort_label(sort_by, attr) 
     526                            tooltip = experiment_description(attr) 
    416527                            rug_item.setToolTip(tooltip) 
    417                             rug_item.setPen(background_pen) 
     528                             
     529                        rug_item.group = group 
     530                        rug_item.index = i 
     531                        rug_item.in_group = in_group 
     532                         
    418533                        rug_items.append(rug_item) 
    419534                     
Note: See TracChangeset for help on using the changeset viewer.