Example #1
0
    def set_backend(self, backend):
        """ Set the backend to the new value (implies setting a new layer). """
        if self.backend != backend:
            Signals.disconnect_list(self.backend_signals)

            self.backend = backend

            if self.backend is not None:
                # If no active layer is set, even though there are layers,
                # then we should set the first layer as being active.
                if self.backend.layer is None and len(self.backend.plot.layers) > 0:
                    self.backend.layer = self.backend.plot.layers[0]
                self.layer = self.backend.layer

                # make sure we keep track of changes to the active layer
                self.backend_signals.append(
                    Signals.connect(backend, "notify::layer",
                                    (lambda sender, layer: self.set_layer(layer)))
                    )
            else:
                self.layer = None

            # propagate the new backend to all tools
            self.dock.foreach((lambda tool: tool.set_backend(self.backend)))
            
            # Adjust the active index of the combobox so that the new
            # backend is displayed.
            if self.backend is None:
                index = -1
            else:
                model = self.combobox.get_model()
                index = self.project.backends.index(backend)
            self.combobox.set_active(index)
    def __init__(self, project=None):
	" 'project' may be a Project object or a filename. "

        
        self.eConfig = config.read_configfile(self, const.CONFIG_FILE)
        Signals.connect(self, "write-config",
                        (lambda sender: self.write_recentfiles()))
        
        self.plugins = dict()

        self.recent_files = list()
        self.read_recentfiles()

        # init() is a good place for initialization of derived class
        self.init()
        
        # Set up the Project...
        self._project = None
	if isinstance(project, basestring):
	    try:
		self.load_project(project)
	    except IOError:
                logger.error("Failed to load project '%s'\nSetting up an empty project instead." % project)                
		self.set_project(Project())
        else:
            self.set_project(project)

        self.init_plugins()
    def new_dataset(self, key='dataset', undolist=None):
        """
        Add a new Dataset object to the Project.

        The `data` field contains a nearly empty numarray (1 row, 2
        columns, all zero).

        If no key is given, then one is created.  If the key already
        exists, then the method assures that it is unique within the
        Project.

        Returns newly created Dataset.
        """
        if undolist is None:
            undolist = self.journal
        
        key = pdict.unique_key(self.datasets, key)
        ds = Dataset()
        pdict.setitem(self.datasets, key, ds)
        ds.data = Table(nrows=1,ncols=2)
        ds.data.column(0).designation = 'X'
        ds.data.column(1).designation = 'Y'        
        Signals.emit(self, "notify::datasets")

        ui = UndoInfo(self.remove_objects, [ds], False)
        ui.describe("Create new Dataset '%s'" % key)
        undolist.append(ui)
        
        return ds
    def cb_interpolate(self, action):
        plugin = self.app.get_plugin('pygsl')
        pygsl = plugin.pygsl
        
        table = self.dataset.get_data()
        x, y = table[0], table[1]
        
        steps = table.nrows * 3
        start, end = x[0], x[-1]
        stepwidth = (end - start) / steps
        new_x = Numeric.arange(start=start, stop=end+stepwidth, step=stepwidth)

        new_table = Table(nrows=steps, ncols=2,
                          typecodes=[table.get_typecode(0),
                                     table.get_typecode(1)])

        sp = pygsl.spline.cspline(table.nrows)
        sp.init(x, y)

        iter = new_table.row(0)
        for xi in new_x:
            iter.set( (xi, sp.eval(xi)) )
            try:
                iter = iter.next()
            except StopIteration:
                print "Iteration stopped"
            
        # set new Dataset
        self.project.datasets.append( Dataset(key="Niklas", data=new_table) )
        Signals.emit(self.project.datasets, "changed")        
Example #5
0
def set(container, *args, **kwargs):
    undolist = kwargs.pop('undolist', UndoList())
    olditems = dict()
    changeset = []

    arglist = list(args)
    while len(arglist) > 1:
        key = arglist.pop(0)
        value = arglist.pop(0)
        olditems[key] = container.get_value(key, None)
        setattr(container, key, value)
        changeset.append(key)

    for (key, value) in kwargs.iteritems():
        olditems[key] = container.get_value(key, None)            
        setattr(container, key, value)
        changeset.append(key)

    undolist.append( UndoInfo(set, container, **olditems) )      

    if len(changeset) > 0:
        Signals.emit(container, "notify", changeset)

        # TODO: remove, it's deprecated
        Signals.emit(container, "prop-changed", changeset) 
Example #6
0
def smart_set(container, *args, **kwargs):

    """ Like 'set', but only add undo information, if the values have
    actually changed. """
    
    undolist = kwargs.pop('undolist', UndoList())
    olditems = dict()
    changed_props = []

    def do_set(key, value):
        old_value = container.get_value(key, None)
        setattr(container, key, value)
        if old_value != container.get_value(key, None):
            olditems[key] = old_value
            changed_props.append(key)
            print "Prop '%s' has changed from '%s' to '%s'." % (key, container.get_value(key, None), old_value)

    arglist = list(args)
    while len(arglist) > 1:
        do_set(arglist.pop(0), arglist.pop(0))
        
    for (key, value) in kwargs.iteritems():
        do_set(key, value)


    if len(changed_props) > 0:
        undolist.append( UndoInfo(smart_set, container, **olditems) )      
        Signals.emit(container, "prop-changed", changed_props)
    else:
        undolist.append( NullUndo() )
    def _construct_toolwindow(self):

        window = tools.ToolWindow(self.app, None)
        window.set_transient_for(self)
        window.set_destroy_with_parent(True)
        window.hide()

        def cb_toggle_window(action, window):
            if action.get_active() is True: window.show()
            else: window.hide()        
        t = gtk.ToggleAction('ToggleToolWindow', 'Show tools window', None, None)
        t.connect("toggled", cb_toggle_window, window)
        uihelper.get_action_group(self.uimanager, 'Application').add_action(t)

        def cb_window_hideshow(window):
            action = self.uimanager.get_action('/MainMenu/ViewMenu/ToggleToolWindow')
            action.set_active(window.get_property('visible'))
        window.connect('hide', cb_window_hideshow)
        window.connect('show', cb_window_hideshow)

        def on_notify_project(sender, project, toolwin):
            print "==> project = ", project
            print "==> toolwin = ", toolwin
            toolwin.set_project(project)
        Signals.connect(self.app, 'notify::project', on_notify_project, window)
        
        return window
    def set_dataset(self, dataset):
        
        if dataset is None:
            self.set_title("(no dataset)")
        else:
            self.set_title("DS: %s" % dataset.key)

        # FIXME
        # this is inconsistent: we expect 'table' to be fixed,
        # even though we argued before that the dataset.data field
        # is not necessarily fixed, only the Dataset.
        table = dataset.get_data()
        if not isinstance(table, Table):
            raise TypeError("TableWindow can only use Datasets with a Table as data.")
        self.tableview.set_table(table)

        for signal in self._signals:
            Signals.disconnect(signal)

        self._signals += [
            Signals.connect(table, 'update-columns',
                            (lambda sender: self.tableview.setup_columns())),
            Signals.connect(dataset,'notify',
                            (lambda sender: self.tableview.queue_draw()))
            ]

        # TODO: set metadata widget       
            
        self._dataset = dataset
    def set_plot(self, plot):

        Signals.disconnect_list(self._signals)
        self.backend is not None and self.backend.disconnect()

        if plot is None:
            return

        
        self.plot = plot
        self.set_title( "Plot: %s" % plot.key )
        
        self.backend = project.new_backend('gnuplot/x11', plot=plot)

        # connect signals for treeview
        # these are disconnect by the backend if it closes
        Signals.connect(self.backend, 'gnuplot-send-cmd', self.on_send_cmd)
        Signals.connect(self.backend, 'gnuplot-finish-cmd', self.on_finish_cmd)
        Signals.connect(self.backend, 'gnuplot-start-plotting', self.on_start_plotting)

        # connect signal for plot
        # these should be disconnected before the plot needs to do it.
        self._signals += [
            Signals.connect(plot, "plot-changed", (lambda sender: self.backend.draw())),
            Signals.connect(plot, "closed", (lambda sender: self.destroy()))
            ]

        self.backend.draw()
    def __call__(self, cmd):
        """Send string to gnuplot"""

        encoded_cmd = cmd.encode( self.encoding )
        #encoded_cmd = cmd
        self.gpout.flush()
        Signals.emit(self, 'gnuplot-send-cmd', cmd=cmd)
        self.gpwrite.write(encoded_cmd + "\n")
        self.gpwrite.write("print '<--END-->'\n")
        self.gpwrite.flush()

        result = []
        while result[-1:] != ["<--END-->\n"]:
            if self.process.poll() is not None:                
                break
            result.append( self.gpout.readline() )

        if len(result) == 0:
            result = None
        elif result[-1:] == ["<--END-->\n"]:
            result = result[:-1]
            
        self.history.append( (encoded_cmd, result) )
        Signals.emit(self, 'gnuplot-finish-cmd', cmd=cmd, result=result)
        return result
    def mouse_move(self, event):
        if not event.inaxes:
            return
        ax = event.inaxes
        minx, maxx = ax.get_xlim()
        miny, maxy = ax.get_ylim()

        x, y = event.xdata, event.ydata
        Signals.emit(self, "move", x, y)
 def request_backend(self, key, plot=None):
     matches = self.find_backends(key=key, plot=plot)
     if len(matches) > 0:
         return matches[0]
     else:
         backend = BackendRegistry[key](project=self, plot=plot)
         self.backends.append(backend)
         Signals.emit(self, "notify::backends")
         return backend
    def _cb_select_line(self, action):
            
        def finish_select_line(sender):
            print "FINISHED SELECT LINE", sender.line

        s = mpl_selector.SelectLine(self.backend.figure,mode=mpl_selector.SELECTLINE_VERTICAL)
        Signals.connect(s, "finished", finish_select_line)
        
        self.select(s)
    def add_plotwidget(self, widget):
        n = self.plotbook.append_page(widget)
        self.plotbook.set_tab_label_text(widget, "Plot")
        # TODO: this signal should be a gobject signal
        Signals.connect(widget, "closed", self.detach_plotwidget)

        for ag in widget.get_actiongroups():
            self.uimanager.insert_action_group(ag, 0)
        self.add_accel_group(self.uimanager.get_accel_group())
        self.uimanager.add_ui_from_string(widget.get_uistring())
 def load_project(self, filename):
     # load new project and if it is sucessfully loaded,
     # detach the old project
     new_project = load_project(filename)
     if new_project:
         self.set_project(new_project)
         self.recent_files.insert(0, os.path.abspath(filename))
         if len(self.recent_files) > 10:
             self.recent_files.pop(-1)
         Signals.emit(self, "update-recent-files")
    def __init__(self, app, project, plot):
        gtk.Window.__init__(self)
        self.set_size_request(width=360,height=400)
        
        self.app = app
        self.project = project
        self.plot = None # will be set after everything else is set up
        self.backend = None
        self._signals = list()
        
        # some icons are not right at all....
        groups = {
            'Common':
            [('Replot', gtk.STOCK_REFRESH, 'Replot',
              '<control>R', 'Replot everything', '_cb_replot'),
             ('Edit', gtk.STOCK_PROPERTIES, 'Edit Plot',
              None, 'Edit Plot', '_cb_edit_plot'),
             ('ZoomSelection', gtk.STOCK_ZOOM_FIT, 'use current range',
              None, 'Use Current Range', '_cb_zoom_selection'),
             ('ZoomAutoscale', gtk.STOCK_ZOOM_100, 'do not limit range',
              None, 'Do not limit Range', '_cb_zoom_autoscale'),
             ('ExportPostscript', gtk.STOCK_SAVE, 'export as postscript',
              None, 'Export as Postscript file', '_cb_export_postscript')
             ]
            }
        
        ui = \
        """
        <ui>
          <toolbar name='Toolbar'>
            <toolitem action='Replot'/>            
            <separator/>
            <toolitem action='Edit'/>
            <toolitem action='ZoomSelection'/>
            <toolitem action='ZoomAutoscale'/>
            <separator/>
            <toolitem action='ExportPostscript'/>
          </toolbar>
        </ui>
        """
        
        self.uimanager = self._construct_uimanager(groups,ui)
        self.toolbar = self._construct_toolbar()

        # vbox 
        self.vbox = gtk.VBox(False)
        self.vbox.pack_start(self.toolbar, expand=False, fill=True)
        self.vbox.pack_start(self._construct_history(), expand=True, fill=True)
        self.vbox.show()
        self.add(self.vbox)

        self.connect("destroy", (lambda sender: self.destroy()))

        Signals.connect(self.project, "close", (lambda sender: self.destroy()))        
        self.set_plot(plot)
Example #17
0
 def set_layer(self, layer):
     if layer == self.layer:
         return
     
     Signals.disconnect_list(self.layer_signals)
     self.layer = layer
     
     if layer is not None:
         # maybe connect to layer properties: is it visible, position, ...
         pass
     self.update_layer()
 def set_current_layer(self, layer):
     """
     Set the current layer.
     The layer must be either None or a Layer instance that is
     contained in self.layers.
     """
     if layer is None or layer in self.layers:
         self._current_layer = layer
         Signals.emit(self, "notify::current_layer", layer)
     else:
         raise ValueError("Layer %s can't be set as current, because it is not part of the Plot!" % layer)
Example #19
0
 def set_backend(self, backend):
     if backend == self.backend:
         return
     
     Signals.disconnect_list(self.backend_signals)
     self.backend = backend
     self.update_backend()
     
     if backend is not None:            
         self.set_layer(backend.layer)
     else:
         self.set_layer(None)            
    def _cb_zoom_axes(self, action):

        def finish_moving(sender):
            ul = UndoList().describe("Zoom")
            layer = self.backend.axes_to_layer[sender.axes]
            self.zoom_to_region(layer, sender.region, undolist=ul)
            self.project.journal.add_undo(ul)           
           
        s = mpl_selector.ZoomAxes(self.backend.figure)
        Signals.connect(s, "finished", finish_moving)

        self.select(s)
    def on_action_SelectLine(self, action):
            
        def finish_select_line(sender):
            print "FINISHED SELECT LINE", sender.line

        layer = self.backend.layer
        axes = self.backend.layer_to_axes[layer]
        s = mpl_selector.SelectLine(self.backend.figure, axes,
                                    mode=mpl_selector.SELECTLINE_VERTICAL)
        Signals.connect(s, "finished", finish_select_line)
        
        self.select(s)
Example #22
0
 def set_layer(self, layer):
     if layer == self.layer:
         return
     
     Signals.disconnect_list(self.layer_signals)
     self.layer = layer
     
     if layer is not None:
         self.layer_signals.append(
             Signals.connect(self.layer, "notify::labels", self.on_notify_labels)
             )
     self.update_layer()
    def mouse_move(self, event):
        if not event.inaxes:
            return
        ax = event.inaxes
        minx, maxx = ax.get_xlim()
        miny, maxy = ax.get_ylim()

        x, y = event.xdata, event.ydata
        Signals.emit("newcoords", x, y)

        # return value
        self.point = (x, y)
    def button_press(self, event):
        ax = event.inaxes

        if event.button == 3:
            Signals.emit(self, "picked-axes", ax)

        elif event.button == 1:
            if ax is not None:
                obj = ax.pick(event.x, event.y)
            else:
                obj = None
            print "RMB, you picked", obj
Example #25
0
    def update_cols(self):
        """
        Call this whenever you add/remove a column or when you change
        the type of a column.
        """
        self._colcount = len(self._columns)
        self._typecodes = map(lambda x: x.typecode(), self._columns)

        type_map = {'d': float, 'f': float, 'O': str}
        self._converters = map(lambda tc: type_map[tc], self._typecodes)

        Signals.emit(self, 'update-columns') # FIXME
Example #26
0
    def update_cols(self):
        """
        Call this whenever you add/remove a column or when you change
        the type of a column.
        """
        self._ncols = len(self._columns)
        self._typecodes = map(lambda x: x.typecode(), self._columns)

        # TODO: move to types.h
        type_map = {'d': float, 'f': float, 'O': str, 'l': long, 'i': int}
        self._converters = map(lambda tc: type_map[tc], self._typecodes)

        Signals.emit(self, 'update-columns') # FIXME
Example #27
0
    def update_cols(self):
        """
        Call this whenever you add/remove a column or when you change
        the type of a column.
        """
        self._ncols = len(self._columns)
        self._typecodes = map(lambda x: x.typecode(), self._columns)

        # TODO: move to types.h
        type_map = {"d": float, "f": float, "O": str, "l": long}
        self._converters = map(lambda tc: type_map[tc], self._typecodes)

        Signals.emit(self, "update-columns")  # FIXME
    def new_plot(self, undolist=None):
        " Returns a new Plot. "
        if undolist is None:
            undolist = self.journal
        
        new_plot = new_lineplot2d()
        new_plot.key = pdict.unique_key(self.plots, "new lineplot2d")
        self.add_plot(new_plot)
        ui = UndoInfo(self.remove_plot, new_plot).describe("New Plot")
        undolist.append(ui)

        Signals.emit(self, "notify::plots")
        
        return new_plot    
    def set_new_index(self, index):
        " Sets the new index (but keeps the line). "

        if index >= self.bounds[0] and index <= self.bounds[1]:
            self.index = index

            xdata = self.line.get_xdata()[index]
            ydata = self.line.get_ydata()[index]
            self.point = (xdata, ydata)

            self.coords = self.axes.transData.xy_tup((xdata, ydata))

            Signals.emit(self, "update-position", self.line, self.index, self.point)
            self.draw()
    def on_action_MoveAxes(self, action):

        def finish_moving(sender):
            ul = UndoList().describe("Move Graph")
            layer = self.backend.axes_to_layer[sender.axes]
            self.zoom_to_region(layer, sender.region, undolist=ul)
            self.project.journal.add_undo(ul)           

        layer = self.backend.layer
        axes = self.backend.layer_to_axes[layer]
        s = mpl_selector.MoveAxes(self.backend.figure, axes)
        Signals.connect(s, "finished", finish_moving)

        self.select(s)