From 179a2f88a9bfd3e068d81bf0a40e3da49c08870a Mon Sep 17 00:00:00 2001 From: einarr Date: Mon, 24 Apr 2006 14:52:21 +0000 Subject: [PATCH] The navigator now displays the plots and data in a tree that shows the ancestry information. --- fluent | 1 + system/logger.py | 5 ++- system/plots.py | 18 +++++++---- system/project.py | 28 ++++++++++++----- system/workflow.py | 5 ++- workflows/go_workflow.py | 67 +++++++++++++++++++++++----------------- 6 files changed, 80 insertions(+), 44 deletions(-) diff --git a/fluent b/fluent index 509a02c..7162098 100755 --- a/fluent +++ b/fluent @@ -53,6 +53,7 @@ class FluentApp: def create_logview(self, str1, str2, int1, int2): # Set up log view self.log_view = logger.LogView(logger.logger) + self.log_view.set_level('notice') self.log_view.show() return self.log_view diff --git a/system/logger.py b/system/logger.py index 5f04fb4..b4f2c76 100644 --- a/system/logger.py +++ b/system/logger.py @@ -58,7 +58,10 @@ class LogView(gtk.TreeView): #self.connect('button_release_event', None) # Make sure tree view displays bottom entry when entered - self.model.connect('row-changed', lambda model, path, iter : self.scroll_to_cell(path)) + def scroll_to_last(model, path, it): + if path: + self.scroll_to_cell(path) + self.model.connect('row-changed', scroll_to_last) def set_level(self, level): self.level = level diff --git a/system/plots.py b/system/plots.py index b229b79..d427fc4 100644 --- a/system/plots.py +++ b/system/plots.py @@ -161,13 +161,17 @@ class LargeView (gtk.Frame): class Plot (gtk.Frame): - def __init__(self): + def __init__(self, title): gtk.Frame.__init__(self) self.mark_active(False) self.connect('button_press_event', self.on_button_press) self.sel_obj = None self.active = False - + self.title = title + + def get_title(self): + return self.title + def on_button_press(self, *rest): # logger.log('debug', 'button pressed in plot') self.mark_active(True) @@ -188,7 +192,7 @@ class Plot (gtk.Frame): class EmptyView (Plot): def __init__(self): - Plot.__init__(self) + Plot.__init__(self, 'Empty view') label = gtk.Label('No view') ebox = gtk.EventBox() @@ -213,20 +217,22 @@ class EmptyView (Plot): class SinePlot(Plot): def __init__(self): - Plot.__init__(self) + Plot.__init__(self, 'Sine plot') + fig = Figure(figsize=(5,4), dpi=72) ax = fig.add_subplot(111) t = arange(0.0,3.0,0.01) s = sin(2*pi*t) ax.plot(t,s) + self.canvas = FigureCanvas(fig) self.add(self.canvas) self.canvas.show() class ScatterPlot(Plot): - def __init__(self, dataset, id_dim, sel_dim, id_1, id_2): - Plot.__init__(self) + def __init__(self, dataset,id_dim, sel_dim,id_1,id_2): + Plot.__init__(self, 'Scatter plot') fig = Figure(figsize=(5,4), dpi=72) self.ax = ax = fig.add_subplot(111) self.current_dim = id_dim diff --git a/system/project.py b/system/project.py index 3a0dc40..f3ff054 100644 --- a/system/project.py +++ b/system/project.py @@ -45,28 +45,42 @@ class Project: def get_selection(self): """Returns the current selection object""" return self.sel_obj.current_selection - + + def get_data_iter(self, obj): + """Retuns an iterator to data.""" + retval = [None] + def is_obj(m, p, i, d): + if obj == m.get_value(i, 2): + d.append(i) + return True + + self.data_tree.foreach(is_obj, retval) + return retval[-1] + def add_data(self, parent, data): """Adds a set of data and plots to the navigator. This method is usually called after a Function in a workflow has finished and returns its output.""" + + parent_iter = self.get_data_iter(parent) + for d in data: if isinstance(d, dataset.Dataset): self.add_dataset(d) - self.data_tree_insert(None, d.get_name(), d) + self.data_tree_insert(parent_iter, d.get_name(), d) elif isinstance(d, plots.Plot): # self.add_view(d) - self.data_tree_insert(None, 'view', d) + self.data_tree_insert(parent_iter, d.get_title(), d) d.set_project(self) self.attach(d, 'selection_update') def data_tree_insert(self, parent, text, data): tree = self.data_tree - iter = tree.append(parent) - tree.set_value(iter, 0, text) - tree.set_value(iter, 1, type(data)) - tree.set_value(iter, 2, data) + it = tree.append(parent) + tree.set_value(it, 0, text) + tree.set_value(it, 1, type(data)) + tree.set_value(it, 2, data) def add_dataset(self,dataset): """Appends a new Dataset to the project.""" diff --git a/system/workflow.py b/system/workflow.py index 4c9e0b8..582cac9 100644 --- a/system/workflow.py +++ b/system/workflow.py @@ -116,9 +116,12 @@ class WorkflowView (gtk.VBox): def run_function(self, function): logger.log('debug', 'Starting function: %s' % function.name) project = self.workflow.app.project + parent_data = project.current_data + new_data = function.run(project.current_data) if new_data != None: - project.add_data(None, new_data) + project.add_data(parent_data, new_data) + logger.log('debug', 'Function ended: %s' % function.name) def button_click_handler(self, button): diff --git a/workflows/go_workflow.py b/workflows/go_workflow.py index ee2eaa5..82df27e 100644 --- a/workflows/go_workflow.py +++ b/workflows/go_workflow.py @@ -1,55 +1,55 @@ import gtk import logger from annotations import Annotations -from workflow import * +import workflow import plots import dataset #import geneontology #import gostat -from scipy import array,randn +from scipy import array,randn,log import cPickle -class EinarsWorkflow (Workflow): +class EinarsWorkflow (workflow.Workflow): name = 'Test Workflow' description = 'Gene Ontology Workflow. This workflow currently serves as a general testing workflow.' def __init__(self, app): - Workflow.__init__(self, app) + workflow.Workflow.__init__(self, app) - load = Stage('load', 'Load Data') - load.add_function(Function('load', 'Load Microarrays')) + load = workflow.Stage('load', 'Load Data') load.add_function(CelFileImportFunction()) load.add_function(TestDataFunction()) load.add_function(DatasetLoadFunction()) self.add_stage(load) - preproc = Stage('preprocess', 'Preprocessing') - preproc.add_function(Function('rma', 'RMA')) + preproc = workflow.Stage('preprocess', 'Preprocessing') + preproc.add_function(DatasetLog()) + preproc.add_function(workflow.Function('rma', 'RMA')) self.add_stage(preproc) - go = Stage('go', 'Gene Ontology Data') + go = workflow.Stage('go', 'Gene Ontology Data') go.add_function(LoadAnnotationsFunction()) go.add_function(GODistanceFunction()) self.add_stage(go) - regression = Stage('regression', 'Regression') - regression.add_function(Function('pls', 'PLS')) + regression = workflow.Stage('regression', 'Regression') + regression.add_function(workflow.Function('pls', 'PLS')) self.add_stage(regression) - explore = Stage('explore', 'Explorative analysis') + explore = workflow.Stage('explore', 'Explorative analysis') explore.add_function(PCAFunction(self)) self.add_stage(explore) - save = Stage('save', 'Save Data') + save = workflow.Stage('save', 'Save Data') save.add_function(DatasetSaveFunction()) self.add_stage(save) logger.log('debug', '\tEinar\'s workflow is now active') -class LoadAnnotationsFunction(Function): +class LoadAnnotationsFunction(workflow.Function): def __init__(self): - Function.__init__(self, 'load-go-ann', 'Load Annotations') + workflow.Function.__init__(self, 'load-go-ann', 'Load Annotations') self.annotations = None def load_file(self, filename): @@ -80,10 +80,10 @@ class LoadAnnotationsFunction(Function): dialog.destroy() return [self.annotations] -class GODistanceFunction(Function): +class GODistanceFunction(workflow.Function): def __init__(self): - Function.__init__(self, 'go_diatance', 'GO Distances') + workflow.Function.__init__(self, 'go_diatance', 'GO Distances') self.output = None def run(self, data): @@ -99,9 +99,9 @@ class GODistanceFunction(Function): return gene_distances -class TestDataFunction(Function): +class TestDataFunction(workflow.Function): def __init__(self): - Function.__init__(self, 'test_data', 'Generate Test Data') + workflow.Function.__init__(self, 'test_data', 'Generate Test Data') def run(self, data): logger.log('notice', 'Injecting foo test data') @@ -109,11 +109,20 @@ class TestDataFunction(Function): X = dataset.Dataset(x) return [X, plots.SinePlot()] +class DatasetLog(workflow.Function): + def __init__(self): + workflow.Function.__init__(self, 'log', 'Log') -class DatasetLoadFunction(Function): + def run(self, data): + logger.log('notice', 'Taking the log of dataset %s' % data.get_name()) + d = data.asarray() + d = log(d) + return [dataset.Dataset(d)] + +class DatasetLoadFunction(workflow.Function): """Loader for previously pickled Datasets.""" def __init__(self): - Function.__init__(self, 'load_data', 'Load Pickled Dataset') + workflow.Function.__init__(self, 'load_data', 'Load Pickled Dataset') def run(self, data): chooser = gtk.FileChooserDialog(title="Select cel files...", parent=None, @@ -136,10 +145,10 @@ class DatasetLoadFunction(Function): chooser.destroy() -class DatasetSaveFunction(Function): +class DatasetSaveFunction(workflow.Function): """QND way to save data to file for later import to this program.""" def __init__(self): - Function.__init__(self, 'save_data', 'Save Pickled Dataset') + workflow.Function.__init__(self, 'save_data', 'Save Pickled Dataset') def run(self, data): if not data: @@ -168,10 +177,10 @@ class DatasetSaveFunction(Function): chooser.destroy() -class CelFileImportFunction(Function): +class CelFileImportFunction(workflow.Function): """Loads AffyMetrix .CEL-files into matrix.""" def __init__(self): - Function.__init__(self, 'cel_import', 'Import Affy') + workflow.Function.__init__(self, 'cel_import', 'Import Affy') def run(self, data): import rpy @@ -214,11 +223,11 @@ class CelFileImportFunction(Function): chooser.destroy() -class PCAFunction(Function): +class PCAFunction(workflow.Function): """Generic PCA function.""" - def __init__(self, workflow): - Function.__init__(self, 'pca', 'PCA') - self._workflow = workflow + def __init__(self, wf): + workflow.Function.__init__(self, 'pca', 'PCA') + self._workflow = wf def run(self, data): import rpy