From 48165d1aed5d3d852ff4fd021659032243e3f8ed Mon Sep 17 00:00:00 2001 From: flatberg Date: Wed, 21 Feb 2007 12:41:37 +0000 Subject: [PATCH] Updated the selection controller with sorting ++ --- fluents/selections.py | 114 +++++++++++++++++++++++++++++++++--------- 1 file changed, 91 insertions(+), 23 deletions(-) diff --git a/fluents/selections.py b/fluents/selections.py index 7194e13..043b10f 100644 --- a/fluents/selections.py +++ b/fluents/selections.py @@ -1,7 +1,3 @@ - -import logger, dataset -import annotations - import pygtk import gtk import gtk.gdk @@ -10,6 +6,11 @@ import gnome import gnome.ui import gobject +import logger, dataset +import annotations +from lib import hypergeom + + class SimpleMenu(gtk.Menu): def __init__(self): gtk.Menu.__init__(self) @@ -166,22 +167,43 @@ class SelectionListController: self._dimension = None self._idlist_controller = idlist_controller + # Selection renderers renderer = gtk.CellRendererText() sel_column = gtk.TreeViewColumn('Selection', renderer, text=0) seltree.insert_column(sel_column, 0) + + intersect_cs_col = gtk.TreeViewColumn('In curr.sel.', renderer, text=3) + seltree.insert_column(intersect_cs_col, 1) + + n_all_col = gtk.TreeViewColumn('# All', renderer, text=4) + seltree.insert_column(n_all_col, 2) + + rank_col = gtk.TreeViewColumn('Rank', renderer, text=5) + seltree.insert_column(rank_col, 3) + # Signals seltree.connect('row-activated', self._on_row_activated) seltree.connect('cursor-changed', self._on_cursor_changed) - + seltree.connect('button-press-event', self._on_button_pressed) seltree.drag_dest_set(gtk.DEST_DEFAULT_ALL, [("GTK_TREE_MODEL_ROW", gtk.TARGET_SAME_APP, 7)], gtk.gdk.ACTION_LINK) seltree.connect('drag-data-received', self._drag_data_received) - ## - ## Public interface - ## + # Selections context menu + self._seltree_menu = SimpleMenu() + self._seltree_menu.add_simple_item('Sort by selection', self._on_seltree_sort) + # self._seltree_menu.add_simple_item('Copy selection', self._on_seltree_copy_selection) + # + # Public interface + # + + def set_project(self, project): + """Dependency injection.""" + self.project = project + project.add_selection_observer(self) + def set_dimlist_controller(self, dimlist_controller): self._dimlist_controller = dimlist_controller @@ -199,19 +221,26 @@ class SelectionListController: store = self._sel_stores[dim] if not self._get_current_selection_iter(selection, dim): - values = (selection.title, selection, dim) + n = len(selection[dim]) + values = (selection.title, selection, dim, n, n, 2) store.insert_after(None, None, values) def add_dataset(self, dataset): - self._ensure_selection_store(dataset.get_dim_name(0)) - store = self._sel_stores[dataset.get_dim_name(0)] + dim_name = dataset.get_dim_name(0) + self._ensure_selection_store(dim_name) + store = self._sel_stores[dim_name] di = self._get_dataset_iter(dataset) if not di: - values = (dataset.get_name(), dataset, dataset.get_dim_name(0)) + n_tot = dataset.shape[0] + selection = self.project.get_selection().get(dim_name) + ds_idents = dataset.get_identifiers(dim_name) + n_cs = len(selection.intersection(ds_idents)) + values = (dataset.get_name(), dataset, dim_name, n_cs, n_tot, 2) i = store.insert_after(None, None, values) for selection in dataset.as_selections(): - values = (selection.title, selection, dataset.get_dim_name(0)) + n_sel = len(selection[dim_name]) + values = (selection.title, selection, dim_name, 0, n_sel, 0) store.insert_after(i, None, values) @@ -221,12 +250,16 @@ class SelectionListController: def _add_selection_store(self, dim): """Add a new gtk.TreeStore for the selections on a dimension.""" # Create new store - ## Two types of lines, one for CategoryDatasets and one for - ## Selections. The elements are title, link to dataset or selection - ## and the name of the dimension. + # Two types of lines, one for CategoryDatasets and one for + # Selections. The elements are title, link to dataset or selection, + # name of dimension, num. members in selection, num. in + # intersection with current selection and the rank of selection. store = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT, - gobject.TYPE_STRING) + gobject.TYPE_STRING, + gobject.TYPE_INT, + gobject.TYPE_INT, + gobject.TYPE_FLOAT) # Set selection store for this dimension self._sel_stores[dim] = store @@ -264,10 +297,33 @@ class SelectionListController: return i i = store.iter_next(i) return None - - ## - ## GTK callbacks - ## + + def _sort_selections(self, dataset): + """Ranks selections by intersection with current selection. + Ranks determined by the hypergeometric distribution. + """ + dim_name = dataset.get_dim_name(0) + sel_store = self._sel_stores[dim_name] + selection_obj = self.project.get_selection() + current_selection = selection_obj.get(dim_name) + if current_selection==None: return + + pvals = hypergeom.gene_hypergeo_test(current_selection, dataset) + + for row in sel_store: + if row[1]==dataset: + for child in row.iterchildren(): + name = child[0] + child[3] = pvals[name][0] + child[4] = pvals[name][1] + child[5] = pvals[name][2] + + sel_store.set_sort_column_id(5, gtk.SORT_ASCENDING) + + # + # GTK callbacks + # + def _drag_data_received(self, widget, drag_context, x, y, selection, info, timestamp): @@ -305,7 +361,20 @@ class SelectionListController: elif isinstance(obj, dataset.Selection): self.project.set_selection(self._dimension, obj[self._dimension]) - + + def _on_button_pressed(self, widget, event): + """Button press callbak.""" + if event.button == 3: + self._seltree_menu.popup(None, None, None, event.button, event.time) + + def _on_seltree_sort(self, menuitem): + """Sort selection tree if row is category dataset.""" + store = self._sel_stores[self._dimension] + p = self._seltree.get_cursor()[0] + i = store.get_iter(p) + obj = store.get_value(i, 1) + if isinstance(obj, dataset.CategoryDataset): + self._sort_selections(obj) class DimListController: def __init__(self, dimlist, seltree_controller): @@ -337,7 +406,6 @@ class DimListController: self.project = project self.dim_names = project.dim_names self.update_dims() - project.add_selection_observer(self._seltree_controller) project.add_dataset_observer(self) def get_dimension(self, dim):