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 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)
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 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 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")
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 disconnect(self): """ Close the connection to the backend. """ if self.project is not None: self.project.remove_backend(self) self.set(None,None) self.connected = False Signals.emit(self, 'backend-closed') Signals.disconnect(sender=self) Signals.disconnect(receiver=self)
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 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)
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
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
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
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 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 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 save_project_as(self, filename = None): """ Save project under another filename. """ pj = self._check_project() if not filename: # allow user to choose a filename chooser = gtk.FileChooserDialog( title="Save Project As", action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) chooser.set_default_response(gtk.RESPONSE_OK) chooser.set_current_folder( const.internal_path(const.PATH_EXAMPLE) ) chooser.set_select_multiple(False) chooser.set_filename(pj.filename or "unnamed.spj") filter = gtk.FileFilter() filter.set_name("All files") filter.add_pattern("*") chooser.add_filter(filter) chooser.set_filter(filter) # default filter shortcut_folder = const.internal_path(const.PATH_EXAMPLE) if os.path.exists(shortcut_folder): chooser.add_shortcut_folder(shortcut_folder) response = chooser.run() try: if response == gtk.RESPONSE_OK: filename = chooser.get_filename() else: raise error.UserCancel finally: chooser.destroy() # add extension if not yet there if filename.lower().endswith('.spj') is False: filename = filename + ".spj" self._project.filename = filename self.window.set_title(basename(self._project.filename)) save_project(self._project) self._project.journal.clear() self.recent_files.append(os.path.abspath(filename)) Signals.emit(self, 'update-recent-files')
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) # Add filename to list of recent_files __unless__ # it is identical with the most recent file. new_filename = os.path.abspath(filename) if len(self.recent_files) == 0 or \ self.recent_files[0] != new_filename: self.recent_files.insert(0, new_filename) if len(self.recent_files) > 10: self.recent_files.pop(-1) Signals.emit(self, "update-recent-files")
def close(self): " Close project properly. " for dataset in self.datasets: dataset.close() for plot in self.plots: plot.close() if self._archive is not None: self._archive.close() # disconnect all opened backends for backend in self.backends: backend.disconnect() Signals.emit(self, 'close') self.app = None # TODO: this should be unnecessary if the app catches the signal
def rename_plot(self, xn_plot, new_key, undolist=None): " Analogon to `rename_dataset`. " if undolist is None: undolist = self.journal plotlist = [plot for plot in self.plots] plot = self.get_plot(xn_plot) plotlist.remove(plot) new_key = pdict.unique_key(plotlist, new_key) ui = UndoInfo(self.rename_plot, plot, plot.key) ui.describe("Rename Plot") plot.key = new_key undolist.append(ui) Signals.emit(self, "notify::plots") return plot
def set_project(self, project, confirm=True): has_changed = (id(self._project) != id(project)) if self._project is not None and has_changed: self._project.close() self._project = project if project is not None: project.app = self def detach_project(project): if id(self._project) == id(project): self._project.app = None self._project = None # TODO: connect_once would be nice. Signals.connect(project, 'close', detach_project) if has_changed is True: Signals.emit(self, 'notify::project', self._project)
def redraw(self, rebuild_cache=True): # All commands for gnuplot are appended to the cmd_list, # so that they can be executed at the very end. cmd_list = [] cmd_list.append('cd "%s"' % self.tmpdir) cmd_list.append( "set encoding %s" % self.encoding ) cmd_list += self.terminal.build(self) # multiplot ? if len(self.plot.layers) > 1: cmd_list.append( "set multiplot" ) for layer in self.plot.layers: group_info = {} x, y = uwrap.get(layer, 'x'), uwrap.get(layer, 'y') width, height = uwrap.get(layer, 'width'), uwrap.get(layer, 'height') cmd_list.append("set origin %.2f,%.2f" % (x,y)) cmd_list.append("set size %.2f,%.2f" % (width, height)) cmd_list += self.build_layer(layer, group_info) cmd_list.append( "unset multiplot" ) else: # Single plot! # create plotting commands from the Layer information group_info = {} cmd_list += self.build_layer(self.plot.layers[0], group_info) self.export_datasets() # Now execute all collected commands. print "cmd list is: " for cmd in cmd_list: print " ", cmd print Signals.emit(self, 'gnuplot-start-plotting') logger.info("Gnuplot command list:\n\n%s" % "\n".join(cmd_list)) for cmd in cmd_list: self(cmd) Signals.emit(self,'gnuplot-after-plot', window_title=self.window_title)
def close_project(self, confirm=True): pj = self._check_project() print "Closing Project" for dataset in pj.datasets: dataset.close() for plot in pj.plots: plot.close() if pj._archive is not None: pj._archive.close() pj.app = None # disconnect all opened backends for backend in pj.backends: backend.disconnect() print "Emitting Signal" Signals.emit(pj, "close") self._project = None
def rename_dataset(self, xn_dataset, new_key, undolist=None): """ Rename a Dataset and make sure that its key is unique. The name might be modified so if the key is important to you, you might want to check it afterwards. Returns the Dataset. """ if undolist is None: undolist = self.journal dataset = self.get_dataset(xn_dataset) dslist = [ds for ds in self.datasets] dslist.remove(dataset) new_key = pdict.unique_key(dslist, new_key) ui = UndoInfo(self.rename_dataset, dataset, dataset.key) ui.describe("Rename Dataset") dataset.key = new_key undolist.append(ui) Signals.emit(self, "notify::datasets") return dataset
def set_plot(self, plot): # TODO: remove old plot # TODO: connect to plot's title if plot is not None: backend = self.project.request_backend('matplotlib', plot=plot) #backend.canvas.set_size_request(800, 600) sw = uihelper.add_scrollbars(backend.canvas, viewport=True) sw.show() self.vbox.pack_start(sw) else: backend = None # disconnect old stuff if self.backend is not None and self.backend != backend: self.backend.disconnect() for signal in self._signals: Signals.disconnect(signal) self._signals = [] if self.cursor is not None: self.cursor.finish() # connect new backend self.plot = plot self.backend = backend if backend is not None: self._signals.extend( [Signals.connect(plot, "plot-changed", (lambda sender: backend.draw())), Signals.connect(plot, "closed", (lambda sender: Signals.emit(self, 'closed')))] ) try: backend.draw() except: #gtkutils.info_msg("Nothing to plot.") raise # Cursor self.cursor = mpl_selector.Cursor(self.backend.figure) Signals.connect(self.cursor, "move", (lambda sender,x,y: self.set_coords(x,y))) self.cursor.init()
def emit_last(sender, name, *args, **kwargs): ul = kwargs.pop('undolist', []) Signals.emit(sender, name, *args, **kwargs) ul.insert(0, UndoInfo(emit_last, sender, name, *args, **kwargs))
def emit(sender, name, *args, **kwargs): " undo wrapper around emit. " undolist = kwargs.pop('undolist', []) Signals.emit(sender, name, *args, **kwargs) undolist.append(UndoInfo(emit, sender, name, *args, **kwargs))
def detach(self): Signals.emit(self, 'closed')
def close(self): Signals.emit(self, 'closed')