diff --git a/system/dataset.py b/system/dataset.py index 6f6db4e..7caa82f 100644 --- a/system/dataset.py +++ b/system/dataset.py @@ -57,8 +57,8 @@ class Dataset: else: raise ValueError, "Array input must be of ArrayType" - def __str__(self): - return self._name + ":\n" + "Dim names: " + self._dims.__str__() + #def __str__(self): + # return self._name + ":\n" + "Dim names: " + self._dims.__str__() def __iter__(self): """Returns an iterator over dimensions of dataset.""" @@ -181,7 +181,7 @@ class Dataset: if idents==None: index = array_sort(self._map[dim].values()) else: - index = [self._map[dim][key] for key in idents] + index = [self._map[dim][key] for key in idents if self._map[dim].has_key(key)] return asarray(index) class CategoryDataset(Dataset): @@ -236,7 +236,7 @@ class GraphDataset(Dataset): def asnetworkx(self,nx_type='graph'): dim = self.get_dim_name()[0] - ids = self.get_identifiers(dim) + ids = self.get_identifiers(dim,sorted=True) adj_mat = self.asarray() G = self._graph_from_adj_matrix(adj_mat,labels=ids) self.has_graph = True @@ -271,11 +271,6 @@ class GraphDataset(Dataset): return G Dataset._all_dims=set() - -class Selection: - """Handles selected identifiers along each dimension of a dataset""" - def __init__(self): - self.current_selection={} class ReverseDict(dict): """ @@ -300,7 +295,7 @@ def to_file(filepath,dataset,name=None): """ if not name: name = dataset._name - data = shelve.open(filepath,protocol=2) + data = shelve.open(filepath,flag='c',protocol=2) if data: #we have an append names = data.keys() if name in names: @@ -311,7 +306,7 @@ def to_file(filepath,dataset,name=None): def from_file(filepath): """Read dataset from file """ - data = shelve.open(filepath) + data = shelve.open(filepath,flag='r') out_data = [] for name in data.keys(): sub_data = data[name] @@ -324,3 +319,7 @@ def from_file(filepath): return out_data +class Selection: + """Handles selected identifiers along each dimension of a dataset""" + def __init__(self): + self.current_selection={} diff --git a/system/fluents.py b/system/fluents.py index 39baab5..9bddfbd 100755 --- a/system/fluents.py +++ b/system/fluents.py @@ -80,6 +80,8 @@ class FluentApp: self.init_gui() def change_plot(self, plot): + # add current selection to new plot + plot.selection_changed(self.project.get_selection()) pt = self.widget_tree.get_widget('main_view') pt.insert_view(plot) diff --git a/system/navigator.py b/system/navigator.py index 5ecc79b..fb996cf 100644 --- a/system/navigator.py +++ b/system/navigator.py @@ -18,7 +18,6 @@ class NavigatorView (gtk.TreeView): # various properties self.set_headers_visible(False) - # Selection Mode self.get_selection().set_mode(gtk.SELECTION_MULTIPLE) self.get_selection().set_select_function(self.is_selectable) @@ -29,11 +28,11 @@ class NavigatorView (gtk.TreeView): # self.connect('cursor_changed', self.cursor_changed_handler) self.connect('row_activated', self.row_activated_handler) - textrenderer = gtk.CellRendererText() - + self.textrenderer = textrenderer = gtk.CellRendererText() + textrenderer.set_property('foreground_set',True) self.object_col = gtk.TreeViewColumn('Object') - self.object_col.pack_start(textrenderer) - self.object_col.set_attributes(textrenderer, cell_background=3, foreground = 4, text=0) + self.object_col.pack_start(textrenderer,expand=False) + self.object_col.set_attributes(textrenderer, cell_background=3, foreground=4, text=0) self.append_column(self.object_col) # send events to plots / itself @@ -46,12 +45,11 @@ class NavigatorView (gtk.TreeView): # sets data for drag event. def slot_drag_data(self,treeview,context,selection,target_id,etime): - treeselection = treeview.get_selection() - model, paths = treeselection.get_selected_rows() - if paths: + treeselection = treeview.get_selection() + model, paths = treeselection.get_selected_rows() + if paths: self.data_tree.drag_data_get(paths[0], selection) - def add_project(self, project): self.project = project self.data_tree = project.data_tree @@ -69,12 +67,13 @@ class NavigatorView (gtk.TreeView): # selection changed, setting current_data ojbects def selection_changed_handler(self, selection): - # update prev selection right away in case of multiple events model, paths = selection.get_selected_rows() - tmp = self._previous_selection + if not paths: # a plot is marked: do nothing + return + + tmp = self._previous_selection self._previous_selection = paths - # set timestamp on newly selected objects [self.data_tree.set_value(self.data_tree.get_iter(path),5,time.time()) for path in paths if path not in tmp] @@ -99,7 +98,6 @@ class NavigatorView (gtk.TreeView): if not (treestore.get_value(iter,2) or treestore.get_value(iter,1)): return - self.expand_to_path(pos) if isinstance(obj,dataset.Dataset): @@ -121,7 +119,7 @@ class NavigatorView (gtk.TreeView): d.set_default_response(gtk.BUTTONS_OK) d.run() d.destroy() - + def row_activated_handler(self, widget, path, column): tree_iter = self.data_tree.get_iter(path) obj = self.data_tree.get_value(tree_iter, 2) diff --git a/system/plots.py b/system/plots.py index 4306f6d..83c2c1f 100644 --- a/system/plots.py +++ b/system/plots.py @@ -238,6 +238,7 @@ class Plot (gtk.Frame): self.fig = Figure(figsize=(5,4), dpi=72) self.canvas = FigureCanvas(self.fig) self.fig.set_facecolor('white') + def get_title(self): return self.title @@ -394,6 +395,8 @@ class LineViewPlot(Plot): ps: slow (cant get linecollection and blit to work) """ def __init__(self, dataset,major_axis=1,minor_axis=None, name="Line view"): + self.use_blit = False + self._last_index = [] self._data = dataset.asarray() self.dataset = dataset Plot.__init__(self, name) @@ -407,7 +410,10 @@ class LineViewPlot(Plot): x_axis = scipy.arrayrange(self._data.shape[minor_axis]) for i in range(self._data.shape[major_axis]): yi = scipy.take(self._data,[i],axis=major_axis) - l, = self.ax.plot(x_axis,yi,'k',alpha=.05,animated=True) + if self.use_blit: + l,=self.ax.plot(x_axis,yi,'k',alpha=.05,animated=True) + else: + l,=self.ax.plot(x_axis,yi,'k',alpha=.05) self.line_collection[i] = l self.add(self.canvas) @@ -427,18 +433,33 @@ class LineViewPlot(Plot): def selection_changed(self, selection): ids = selection[self.current_dim] # current identifiers index = self.dataset.get_indices(self.current_dim, ids) - if self._background is None: - print "background needs copy" - self._background = self.canvas.copy_from_bbox(self.ax.bbox) - print self.ax.bbox.get_bounds() - self.canvas.restore_region(self._background) + if self.use_blit: + if self._background is None: + self._last_index = None + self._background = self.canvas.copy_from_bbox(self.ax.bbox) + + self.canvas.restore_region(self._background) if index: + if self._last_index: + for i in self._last_index: + # if not using blit: reset last selection + self.ax.lines[i].set_color('k') + self.ax.lines[i].set_alpha(.05) + self.ax.lines[i].set_zorder(1) for i in index: - self.line_collection[i].set_visible(True) - self.line_collection[i].set_color('r') - self.line_collection[i].set_alpha(1.0) - self.ax.draw_artist(self.line_collection[i]) - self.canvas.blit() + self.ax.lines[i].set_color('r') + self.ax.lines[i].set_alpha(1.0) + self.ax.lines[i].set_visible(True) + self.ax.lines[i].set_zorder(3) + if self.use_blit: + self.ax.draw_artist(self.ax.lines[i]) + #else: + # self.ax.add_line(self.line_collection[i]) + self._last_index = index + if self.use_blit: + self.canvas.blit() + else: + self.canvas.draw() class ScatterMarkerPlot(Plot): """The ScatterMarkerPlot is faster than regular scatterplot, but @@ -446,9 +467,14 @@ has no color and size options.""" def __init__(self, dataset_1, dataset_2, id_dim, sel_dim, id_1, id_2, name="Scatter plot"): Plot.__init__(self, name) self.ax = ax = self.fig.add_subplot(111) + #self.ax.set_position([0.01,0.01,.99,.99]) + self.ax.set_xticks([]) + self.ax.set_yticks([]) + self.ax.axhline(0,color='k',lw=1.5,zorder=0) + self.ax.axvline(0,color='k',lw=1.5,zorder=0) self.current_dim = id_dim self.dataset_1 = dataset_1 - + self._selection_line = None x_index = dataset_1[sel_dim][id_1] y_index = dataset_2[sel_dim][id_2] @@ -493,9 +519,9 @@ has no color and size options.""" xdata_new = scipy.take(self.xaxis_data, index) #take data ydata_new = scipy.take(self.yaxis_data, index) #remove old selection - if len(self.ax.lines)>1: - del self.ax.lines[-1] - self.ax.plot(xdata_new,ydata_new,'ok') + if self._selection_line: + self.ax.lines.remove(self._selection_line) + self._selection_line, = self.ax.plot(xdata_new,ydata_new,'or') self._toolbar.forward() #update data lims before draw self.canvas.draw() @@ -505,6 +531,7 @@ has no color and size options.""" def __init__(self, dataset_1, dataset_2, id_dim, sel_dim, id_1, id_2,c='b',s=30, name="Scatter plot"): Plot.__init__(self, name) self.ax = ax = self.fig.add_subplot(111) + #self.ax.set_position([0.01,0.01,.99,.99]) self.current_dim = id_dim self.dataset_1 = dataset_1 @@ -516,8 +543,8 @@ has no color and size options.""" ax.scatter(self.xaxis_data,self.yaxis_data,s=s,c=c,faceted=False,edgecolor='k') ax.set_title(self.get_title()) - ax.set_xlabel("%s - %s" % (sel_dim, id_1)) - ax.set_ylabel("%s - %s" % (sel_dim, id_2)) + #ax.set_xlabel("%s - %s" % (sel_dim, id_1)) + #ax.set_ylabel("%s - %s" % (sel_dim, id_2)) # collection self.coll = ax.collections[0] @@ -553,8 +580,10 @@ has no color and size options.""" ids = selection[self.current_dim] # current identifiers index = self.dataset_1.get_indices(self.current_dim, ids) lw = scipy.zeros(self.xaxis_data.shape,'f') + zo = lw.copy() + 1 #z-order scipy.put(lw,index,2.) self.coll.set_linewidth(lw) + self.coll.set_zorder(zo) self._toolbar.forward() #update data lims before draw self.canvas.draw() @@ -598,6 +627,9 @@ class NetworkPlot(Plot): kw.pop('node_color') self.ax = self.fig.add_subplot(111) + self.ax.set_position([0.01,0.01,.99,.99]) + self.ax.set_xticks([]) + self.ax.set_yticks([]) # FIXME: ax shouldn't be in kw at all if kw.has_key('ax'): kw.pop('ax') @@ -659,7 +691,7 @@ class NetworkPlot(Plot): self.ax.clear() networkx.draw_networkx_edges(self.graph, edge_list=self.graph.edges(), \ ax=self.ax, **self.keywords) - + networkx.draw_networkx_labels(self.graph,**self.keywords) if unselected_nodes: networkx.draw_networkx_nodes(self.graph, nodelist=unselected_nodes, \ node_color='r', node_size=unselected_sizes, ax=self.ax, **self.keywords) diff --git a/system/project.py b/system/project.py index 5fa7f99..30bac90 100644 --- a/system/project.py +++ b/system/project.py @@ -2,6 +2,7 @@ import scipy import gobject import gtk +import logger from system import dataset, plots class Project: @@ -70,11 +71,17 @@ class Project: it = self.data_tree_insert(parent_iter, fun, None, "grey","black") for d in data: - if isinstance(d, dataset.Dataset): + if isinstance(d, dataset.GraphDataset): self.add_dataset(d) - self.data_tree_insert(it, d.get_name(), d, "white", "blue") + self.data_tree_insert(it, d.get_name(), d, "LightPink", "black") + elif isinstance(d,dataset.CategoryDataset): + self.add_dataset(d) + self.data_tree_insert(it, d.get_name(), d, "LightSalmon", "black") + elif isinstance(d, dataset.Dataset): + self.add_dataset(d) + self.data_tree_insert(it, d.get_name(), d, "LightSkyBlue", "black") elif isinstance(d, plots.Plot): - self.data_tree_insert(it, d.get_title(), d, "white", "dark green") + self.data_tree_insert(it, d.get_title(), d, "PaleGreen", "black") d.set_selection_listener(self.set_selection) self._selection_observers.append(d) @@ -91,6 +98,7 @@ class Project: def add_dataset(self,dataset): """Appends a new Dataset to the project.""" + logger.log('debug','Adding dataset: %s' %dataset.get_name()) self.datasets.append(dataset) for dim_name in dataset.get_all_dims(): if dim_name not in self.dim_names: diff --git a/system/workflow.py b/system/workflow.py index b993a2d..18568a0 100644 --- a/system/workflow.py +++ b/system/workflow.py @@ -41,7 +41,7 @@ def workflow_list(): except Exception, e: logger.log('warning', 'Cannot load workflow: %s' % fn) logger.log('warning', e) - + return retval class Workflow: diff --git a/workflows/pca_workflow.py b/workflows/pca_workflow.py index 05018a6..50f9458 100644 --- a/workflows/pca_workflow.py +++ b/workflows/pca_workflow.py @@ -6,6 +6,8 @@ from scipy import log2,transpose,dot,divide,shape,mean,resize,zeros from scipy.linalg import svd,inv,norm,get_blas_funcs,eig from system import dataset, logger, plots + + class PCAWorkflow(wf.Workflow): name = 'PCA Workflow' ident = 'pca' @@ -96,9 +98,9 @@ class PCAFunction(Function): row_ids = data.get_identifiers('genes') col_ids = data.get_identifiers('samples') - T = dataset.Dataset(T,[('samples',col_ids) ,comp_def]) - P = dataset.Dataset(P,[('genes',row_ids),comp_def]) - E = dataset.Dataset(E,[('samples',col_ids),('genes',row_ids)]) + T = dataset.Dataset(T,[('samples',col_ids) ,comp_def],name='T2') + P = dataset.Dataset(P,[('genes',row_ids),comp_def],name='P') + E = dataset.Dataset(E,[('samples',col_ids),('genes',row_ids)],name='E') #tsq = dataset.Dataset(tsq,[singel_def,data_ids[1]) ## plots