class GuiApp(object): def __init__(self): global unit self.filename=None self.gladefile="/usr/share/freeceilo-%s/ceilo.glade" % VERSION self.wTree=gtk.glade.XML(self.gladefile) self.window=self.wTree.get_widget("FreeCeilo") self.window.maximize() self.threadvar=0 #--------buttons---------# self.Open=self.wTree.get_widget("Open") #-----cloud detection plotting button------# self.first_cld_plot_button=self.wTree.get_widget("first_cld_plot_button") self.second_cld_plot_button=self.wTree.get_widget("second_cld_plot_button") self.third_cld_plot_button=self.wTree.get_widget("third_cld_plot_button") self.cld_det_clear_button=self.wTree.get_widget("cld_det_clear_button") self.cld_det_save_button=self.wTree.get_widget("cld_det_save_button") #------------ gnuplot buttons -------------# self.gnu_plot_button=self.wTree.get_widget("gnu_plot_button") self.gnuplot_zoom_in_button=self.wTree.get_widget("gnuplot_zoom_in_button") self.gnuplot_zoom_normal_button=self.wTree.get_widget("gnuplot_zoom_normal_button") self.gnuplot_zoom_out_button=self.wTree.get_widget("gnuplot_zoom_out_button") self.gnuplot_save_button=self.wTree.get_widget("gnuplot_save_button") #--------buttons ends---------# #------progressbars------# self.progressbar1=self.wTree.get_widget("progressbar1") self.progressbar2=self.wTree.get_widget("progressbar2") self.progressbar1.set_fraction(0.0) self.datpbar=0 self.progressbar2.set_fraction(0.0) self.gnupbar=0 self.timer = gobject.timeout_add (100, progress_timeout, self) #------gnu plot image normal size ----# self.imagex= 810 self.imagey=540 self.gnuplot_image=self.wTree.get_widget("gnuplot_image") self.x=0 #--------Handles events dic={"on_FreeCeilo_destroy":self.quitprogram,"on_Open_activate":self.openfile, "on_first_cld_plot_button_clicked":self.firstcloudshow,"on_second_cld_plot_button_clicked" :self.secondcloudshow,"on_third_cld_plot_button_clicked":self.thirdcloudshow, "on_zoom_in_x_activate":self.clouddetectzoominx,"on_zoom_out_x_activate": self.clouddetectzoomoutx,"on_zoom_in_y_activate":self.clouddetectzoominy, "on_zoom_out_y_activate":self.clouddetectzoomouty,"on_cld_det_save_button_clicked" :self.clouddetectsave,"on_cld_det_clear_button_clicked":self.clouddetectgraphclear, "on_gnu_plot_button_clicked":self.gnuplotshow,"on_gnuplot_zoom_in_button_clicked": self.gnuplotzoomin,"on_gnuplot_zoom_normal_button_clicked":self.gnuplotzoomnormal, "on_gnuplot_zoom_out_button_clicked":self.gnuplotzoomout,"on_gnuplot_save_button_clicked" :self.gnuplotsave} self.wTree.signal_autoconnect(dic) #-----plotting area for graphs self.graphview = self.wTree.get_widget("hbox7") #-----plotting area for cloud detection graph self.figure1 = Figure(figsize=(12,6),facecolor='y',dpi=55,edgecolor='black',linewidth=5.0) self.axis1 = self.figure1.add_subplot(111) self.axis1.grid(True) self.canvas1 = FigureCanvasGTK(self.figure1) self.graphview.pack_start(self.canvas1,True,True) self.canvas1.show() self.axis1.set_autoscale_on(True) #-----plotting area for back scatterprofile self.figure2 = Figure(figsize=(12,6),facecolor='y', dpi=55,edgecolor='black',linewidth=4.0) self.axis2 = self.figure2.add_subplot(111) self.axis2.grid(True) self.canvas2 = FigureCanvasGTK(self.figure2) self.graphview.pack_end(self.canvas2,True,True) self.canvas2.show() ################################# File Openning and dataprocessing ####################### def openfile(self,obj): self.filename=None if(self.threadvar==1): os.system("killall -9 gnuplot > /dev/zero") self.datpbar=0 self.gnupbar=0 self.datadecode_thread_obj.stop() dialog = gtk.FileChooserDialog("Open..", None, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) dialog.set_default_response(gtk.RESPONSE_OK) filter = gtk.FileFilter() filter.set_name("DATA FILES") filter.add_pattern("*.dat") dialog.add_filter(filter) response=dialog.run() if response == gtk.RESPONSE_OK: self.filename=dialog.get_filename() self.window.set_title("Free Ceilo 0.1 ( "+self.filename+")") self.datpbar=1 self.gnupbar=1 #---- Threads for datadecoding ,gnuplot ---# cond=Condition() self.datadecode_thread_obj=datadecodethreadlib.DataDecodeThread(cond,self.filename) self.datadecode_thread_obj.start() self.threadvar=1 #---- Threads ends ------# elif response == gtk.RESPONSE_CANCEL: print 'Closed, no files selected' dialog.destroy() ###############################Cloud Detection Graph Plotting ####################### ##### Show the first cloud ###### def firstcloudshow(self,obj): self.x= getstatusobj.getdataobj() self.axis1.set_xlabel('Time') self.axis1.set_ylabel('Altitude'+","+unit) self.axis1.set_title('Cloud Detection Graph') self.axis1.grid(True) self.axis1.plot_date(self.x.lwst_time_index,self.x.lwst_cldbse_hgt,'b.',label=" First") self.axis1.xaxis.set_major_locator(MaxNLocator(6)) ####-------for rotating the xticks------------------########### #labels = self.axis1.get_xticklabels() #setp(labels, rotation=90, fontsize=10) self.axis1.legend() self.canvas1.draw() ##### Show the second cloud ###### def secondcloudshow(self,obj): self.x= getstatusobj.getdataobj() self.axis1.set_xlabel('Time') self.axis1.set_ylabel('Altitude'+","+unit) self.axis1.set_title('Cloud Detection Graph') self.axis1.grid(True) self.axis1.plot_date(self.x.sec_time_index,self.x.sec_lwst_cldbse_hgt,'g.',label="Second") self.axis1.xaxis.set_major_locator(MaxNLocator(6)) self.axis1.legend() self.canvas1.draw() ##### Show the third cloud ###### def thirdcloudshow(self,obj): self.x= getstatusobj.getdataobj() self.axis1.set_xlabel('Time') self.axis1.set_ylabel('Altitude'+","+unit) self.axis1.set_title('Cloud Detection Graph') self.axis1.grid(True) self.axis1.plot_date(self.x.higst_time_index,self.x.higst_cldbse_hgt,'r.',label="Third") self.axis1.xaxis.set_major_locator(MaxNLocator(6)) self.axis1.legend() self.canvas1.draw() ####---------Zooming the figure--------######## def clouddetectzoominx(self,obj): self.axis1.zoomx(2) self.canvas1.draw() def clouddetectzoomoutx(self,obj): self.axis1.zoomx(-2) self.canvas1.draw() def clouddetectzoominy(self,obj): self.axis1.zoomy(2) self.canvas1.draw() def clouddetectzoomouty(self,obj): self.axis1.zoomy(-2) self.canvas1.draw() def clouddetectgraphclear(self,obj): self.axis1.clear() self.axis1.set_xlabel('Time') self.axis1.set_ylabel('Altitude'+","+unit) self.axis1.set_title('Cloud Detection Graph') self.axis1.grid(True) self.canvas1.draw() #############SAVE CLD DETECT######### def clouddetectsave(self,obj): dialog= gtk.FileChooserDialog("Save Cloud Detection Graph ", None, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) dialog.set_default_response(gtk.RESPONSE_OK) dialog.set_current_folder(os.curdir) dialog.set_do_overwrite_confirmation(True) filter = gtk.FileFilter() filter.set_name("image(png) file") filter.add_pattern("*.png") dialog.add_filter(filter) response=dialog.run() if response == gtk.RESPONSE_OK: plotimagefile=dialog.get_filename() dialog.destroy() #self.canvas1.print_figure1(plotimagefile, 72,'w', 'w','portrait') self.figure1.savefig(plotimagefile) self.canvas1.destroy() self.canvas1 = FigureCanvasGTK(self.figure1) self.graphview.pack_start(self.canvas1, True,True) self.canvas1.show() elif response == gtk.RESPONSE_CANCEL: print "no file is selected" dialog.destroy() self.canvas1.show() ##########################################GNUPLOT#################################### #--------- The Functions to display Gnuplot image and zoom the images and save------# def gnuplotshow(self,obj): self.gnuplot_image.set_from_file("/tmp/FreeCeilo/.gnu.png") #----Functions to zoom the images----# def gnuplotzoomin(self,obj): self.imagex+=30 self.imagey+=20 self.gnuplotzoom() def gnuplotzoomout(self,obj): self.imagex-=30 self.imagey-=20 self.gnuplotzoom() def gnuplotzoomnormal(self,obj): self.imagex=810 self.imagey=540 self.gnuplotzoom() def gnuplotzoom(self): self.gnuplot_image.set_from_pixbuf(gtk.gdk.pixbuf_new_from_file("/tmp/FreeCeilo/.gnu.png").scale_simple(self.imagex,self.imagey,gtk.gdk.INTERP_BILINEAR)) #---Function to save the gnuplot image in another location using save as option---# def gnuplotsave(self,obj): dialog= gtk.FileChooserDialog("Save as..", None, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) dialog.set_default_response(gtk.RESPONSE_OK) dialog.set_do_overwrite_confirmation(True) filter = gtk.FileFilter() filter.set_name("image(png) file") filter.add_pattern("*.png") dialog.add_filter(filter) response=dialog.run() if response == gtk.RESPONSE_OK: plotimagefile=dialog.get_filename() if not plotimagefile.endswith(".png"): k=plotimagefile.find(".") plotimagefile=plotimagefile[0:k] plotimagefile=plotimagefile.__add__(".png") shutil.copyfile("/tmp/FreeCeilo/.gnu.png",plotimagefile) elif response == gtk.RESPONSE_CANCEL: print "no file is selected" dialog.destroy() ################################# Quit the Program ######################### def quitprogram(self,obj): self.id1=os.getpid() gobject.source_remove(self.timer) self.timer = 0 gtk.main_quit() os.system("killall -9 gnuplot > /dev/zero") os.popen("kill -9 "+str(self.id1)) sys.exit(0)
class Backend( backend.Plotter ): def init(self): # line_cache: key = id(Curve), value=mpl line object self.line_cache = dict() self.layer_to_axes = dict() self.axes_to_layer = dict() self.layers_cache = list() # copy of self.plot.layers def connect(self): logger.debug("Opening matplotlib session.") self.figure = Figure(dpi=100, facecolor="white") # figsize=(5,4), dpi=100) self.canvas = FigureCanvas(self.figure) self.canvas.show() self.line_cache.clear() self.layer_to_axes.clear() self.axes_to_layer.clear() backend.Plotter.connect(self) logger.debug("Init finished") def disconnect(self): logger.debug("Closing matplotlib session.") if not self.canvas is None: self.canvas.destroy() self.canvas = None if not self.figure is None: self.figure = None backend.Plotter.disconnect(self) #---------------------------------------------------------------------- def arrange(self, rows=1, cols=1): layers = self.plot.layers n = len(layers) if n > (rows*cols): rows = int((rows*cols) / n) + 1 cols = rows * n #raise ValueError("Not enough rows and cols for all layers!") self.figure.clear() self.figure.axes = [] self.layer_to_axes.clear() self.axes_to_layer.clear() self.layers_cache = list() j = 1 for layer in layers: print "Setting up layer", layer axes = self.figure.add_subplot("%d%d%d" % (rows,cols,j)) self.layer_to_axes[layer] = axes self.axes_to_layer[axes] = layer self.layers_cache.append(layer) j += 1 def draw_layer(self, layer, group_info): ax = self.layer_to_axes[layer] print "DRAWING AXES ", ax ax.lines = [] line_cache = [] line_count = 0 last_cx = -1 # Default values come in two flavors: # group-wise and single default values group_colors = uwrap.get(layer, 'group_colors') group_styles = uwrap.get(layer, 'group_styles') group_markers = uwrap.get(layer, 'group_markers') #default_color = 'r' default_color = None default_style = 'solid' default_marker = 'None' #:layer.visible if uwrap.get(layer, 'visible') is False: return #:layer.title title = uwrap.get(layer, 'title', None) if title is not None: ax.set_title(title) #:layer.grid grid = uwrap.get(layer, 'grid') ax.grid(grid) #:layer.lines for line in layer.lines: data_to_plot = [] #:line.visible if uwrap.get(line, 'visible') is False: if line in ax.lines: ax.lines.remove(line) continue #:line.source if line.source is None: logger.warn("No Dataset specified for Line!") continue else: ds = line.source if ds.is_empty() is True: logger.warn("No data for Line!") continue table = ds.get_data() if not isinstance(table, Table): raise TypeError("Matplotlib Backend currently only supports data of type Table, while this is of %s" % type(table)) #:line.cx if line.cx is None or line.cy is None: logger.error("No x or y source given for Line. Line skipped.") continue else: cx, cy = line.cx, line.cy try: xdata = table[cx] except IndexError: logger.error("X-Index out of range (%s). Line skipped." % cx) continue #:line.cy try: ydata = table[cy] except IndexError: logger.error("Y-Index out of range (%s). Line skipped." % cy) continue #:line.style global linestyle_mappings default = default_style or group_styles[line_count % len(group_styles)] style = uwrap.get(line, 'style', default) style = linestyle_mappings[style] #:line.marker global linemarker_mappings default = default_marker or group_markers[line_count % len(group_markers)] marker = uwrap.get(line, 'marker', default) marker = linemarker_mappings[marker] #:line.width width = uwrap.get(line, 'width') #:line.color default = default_color or group_colors[line_count % len(group_colors)] color = uwrap.get(line, 'color', default) #--- PLOT LINE --- l, = ax.plot( xdata, ydata, linewidth=width, linestyle=style, marker=marker, color=color) line_cache.append(l) # TODO: if we set the label afterwards, don't we then have a redraw? #:line.label label = line.label if label is None: column = table.column(cy) label = column.label or column.key or uwrap.get(line, 'label') l.set_label(label) line_count += 1 # # # # additional lines # # # p = len(xdata) # if p > 2: p = p/2 # atpoint = xdata[max(p-1,0)] # print "Printing vertical line at ", atpoint # ax.axvline(atpoint) #:layer.legend legend = uwrap.get(layer, 'legend') if legend is not None and line_count > 0: visible = uwrap.get(legend, 'visible') if visible is True: #:legend.label TODO label = uwrap.get(legend, 'visible') if label is not None: pass #:legend.border TODO border = uwrap.get(legend, 'border') #:legend.position TODO position = uwrap.get(legend, 'position', 'best') if position == 'at position': position = (uwrap.get(legend, 'x'), uwrap.get(legend, 'y')) # create legend entries from line labels labels = [l.get_label() for l in line_cache] ax.legend(line_cache, labels, loc=position) else: ax.legend_ = None else: ax.legend_ = None #:layer.axes for (key, axis) in layer.axes.iteritems(): #:axis.label #:axis.scale #:axis.start #:axis.end label = uwrap.get(axis, 'label') scale = uwrap.get(axis, 'scale') start = uwrap.get(axis, 'start') end = uwrap.get(axis, 'end') print "START = %s, END = %s" % (str(start), str(end)) if key == 'x': set_label = ax.set_xlabel set_scale = ax.set_xscale set_start = (lambda l: ax.set_xlim(xmin=l)) set_end = (lambda l: ax.set_xlim(xmax=l)) elif key == 'y': set_label = ax.set_ylabel set_scale = ax.set_yscale set_start = (lambda l: ax.set_ylim(ymin=l)) set_end = (lambda l: ax.set_ylim(ymax=l)) else: raise RuntimeError("Invalid axis key '%s'" % key) if label is not None: set_label(label) if scale is not None: set_scale(scale) if start is not None: set_start(start) if end is not None: set_end(end) def draw(self): logger.debug("Matplotlib: draw()") self.check_connection() # plot all curves together in one plot legend_list = [] # for legend later on curve_count = 0 # if self.plot.layers != self.layers_cache: self.arrange() for layer in self.plot.layers: group_info = {} self.draw_layer(layer, group_info) self.canvas.draw()
class Graphic: def __init__(self, widget): self.figure = Figure(figsize=(4,3), dpi=64) self.axes = self.figure.add_subplot(111) self.axes.grid(True) self.widget = widget self.canvas = FigureCanvasGTK(self.figure) self.graphview = widget self.graphview.pack_start(self.canvas, True, True) #self.cursor = None #self.on_press_cb = None #self.on_release_cb = None #self.on_motion_cb = None self.lx_min = None self.lx_max = None #self.rec = None self.axes2 = None self.span = None self.ticklines = self.axes.get_xticklines() self.ticklines.extend( self.axes.get_yticklines() ) self.gridlines = self.axes.get_xgridlines() self.gridlines.extend( self.axes.get_ygridlines() ) self.ticklabels = self.axes.get_xticklabels() self.ticklabels.extend( self.axes.get_yticklabels() ) for line in self.ticklines: line.set_linewidth(2) for line in self.gridlines: line.set_linestyle('-') for label in self.ticklabels: label.set_fontsize('small') self.canvas.show() #button_ax = axes([0.7, 0.5, 0.1, 0.75]) #button = Button(button_ax, 'Press Me') #button.on_clicked(self.on_button_clicked) def plot(self, x, y): self.axes.clear() self.axes.plot(x, y) self.axes.grid(True) self.canvas.destroy() self.canvas = FigureCanvasGTK(self.figure) self.canvas.show() self.widget.pack_start(self.canvas, True, True) def semilogy(self, x, y): self.axes.clear() self.axes.grid(True) self.axes.semilogy(x, y) self.canvas.destroy() self.canvas = FigureCanvasGTK(self.figure) self.canvas.show() self.widget.pack_start(self.canvas, True, True) def autocor(self, x): self.axes.clear() self.axes.grid(True) self.axes.acorr(x) self.canvas.destroy() self.canvas = FigureCanvasGTK(self.figure) self.canvas.show() self.widget.pack_start(self.canvas, True, True) def power_spectrum(self, x, n, fs): self.axes.clear() self.axes.grid(True) self.axes.psd(x, NFFT = n, Fs = fs) self.canvas.destroy() self.canvas = FigureCanvasGTK(self.figure) self.canvas.show() self.widget.pack_start(self.canvas, True, True) def clear_figure(self): self.axes.clear() self.canvas.destroy() self.axes.grid(True) self.canvas = FigureCanvasGTK(self.figure) self.canvas.show() self.widget.pack_start(self.canvas, True, True) def enable_span(self): #self.rec = RectangleSelector(self.axes, self.line_select_callback, # drawtype='box',useblit=True, # minspanx=5,minspany=5) # Unref original sublot #xmin, xmax = self.axes.get_xlim() #self.lx_min = xmin #self.lx_max = xmax self.span = SpanSelector(self.axes, self.on_select, 'horizontal', useblit=False, rectprops=dict(alpha=0.5, facecolor='red')) self.span.visible = True #self.lx = self.axes.plot((0,0), (0,0), 'k-') #self.ly = self.axes.plot((0,0), (0,0), 'k-') #self.lx = Line2D([],[], 'k-') #self.ly = Line2D([],[], 'k-') #self.lx.set_axes(self.axes) #self.ly.set_axes(self.axes) #self.lx.visible = True #self.ly.visible = True #self.on_press_cb = self.canvas.mpl_connect('button_press_event', self.on_press) #self.on_release_cb = self.canvas.mpl_connect('button_release_event', self.on_release) #self.on_motion_cb = self.canvas.mpl_connect('motion_notify_event', self.on_motion) #self.canvas.show() def on_select(self, xmin, xmax): #indmin, indmax = npy.searchsorted(x, (xmin, xmax)) #indmax = min(len(x)-1, indmax) #print xmin #print xmax #thisx = x[indmin:indmax] #thisy = y[indmin:indmax] #self.figure.set_data(thisx, thisy) self.lx_min = xmin self.lx_max = xmax self.axes.set_xlim(xmin, xmax) #self.axes.set_ylim(thisy.min(), thisy.max()) self.figure.canvas.draw() def disable_span(self): self.span.visible = False #self.on_press_cb = None #self.on_release_cb = None #self.on_motion_cb = None def line_select_callback(self, event1, event2): x1, y1 = event1.xdata, event1.ydata x2, y2 = event2.xdata, event2.ydata print "(%3.2f, %3.2f) --> (%3.2f, %3.2f)"%(x1,y1,x2,y2) print " The button you used were: ",event1.button, event2.button def destroy(self): self.canvas.destroy()
class Backend( backend.Backend ): def init(self): self.layer_to_axes = {} self.axes_to_layer = {} self.layers_cache = [] # copy of self.plot.layers self.layer_signals = {} self.line_caches = {} self.omaps = {} def connect(self): logger.debug("Opening matplotlib session.") self.figure = Figure(dpi=100, facecolor="white") # figsize=(5,4), dpi=100) self.canvas = FigureCanvas(self.figure) self.canvas.show() self.line_caches = {} self.layer_to_axes.clear() self.axes_to_layer.clear() backend.Backend.connect(self) logger.debug("Init finished") def set(self, project,plot): backend.Backend.set(self, project, plot) if self.project is not None: # TODO: connect to notify::layers of Plot pass def disconnect(self): logger.debug("Closing matplotlib session.") if not self.canvas is None: self.canvas.destroy() self.canvas = None if not self.figure is None: self.figure = None backend.Backend.disconnect(self) #---------------------------------------------------------------------- def arrange(self, rows=1, cols=1): layers = self.plot.layers n = len(layers) if n > (rows*cols): rows = int((rows*cols) / n) + 1 cols = rows * n #raise ValueError("Not enough rows and cols for all layers!") self.figure.clear() self.figure.axes = [] self.layer_to_axes.clear() self.axes_to_layer.clear() self.layers_cache = [] for signal_list in self.layer_signals.itervalues(): for signal in signal_list: Signals.disconnect(signal) self.layer_signals = {} j = 1 for layer in layers: print "Setting up layer", layer axes = self.figure.add_subplot("%d%d%d" % (rows,cols,j)) self.layer_to_axes[layer] = axes self.axes_to_layer[axes] = layer self.layers_cache.append(layer) print "Connecting to notify of ", layer self.layer_signals[layer] = \ [Signals.connect(layer, 'notify', self.on_update_layer), Signals.connect(layer, 'notify::labels', self.on_update_labels)] j += 1 def draw(self): self.check_connection() logger.debug("Matplotlib: draw()") if self.plot.layers != self.layers_cache: self.arrange() self.omaps = {} for layer in self.plot.layers: self.update_layer(layer) self.draw_canvas() def draw_canvas(self): self.canvas.draw() #---------------------------------------------------------------------- # Layer # def on_update_layer(self, sender, updateinfo={}): # updateinfo is ignored self.update_layer(sender) self.canvas.draw() def update_layer(self, layer, updateinfo={}): # updateinfo is ignored self.omaps[layer] = {} self.line_caches[layer] = {} axes = self.layer_to_axes[layer] axes.lines = [] line_cache = self.line_caches[layer] = [] #:layer.lines:OK for line in layer.lines: self.update_line(line, layer, axes=axes) #:layer.axes for (key, axis) in layer.axes.iteritems(): #:axis.label #:axis.scale #:axis.start #:axis.end label = axis.label scale = axis.scale start = axis.start end = axis.end logger.debug("start = %s; end = %s" % (start, end)) if key == 'x': set_label = axes.set_xlabel set_scale = axes.set_xscale set_start = (lambda l: axes.set_xlim(xmin=l)) set_end = (lambda l: axes.set_xlim(xmax=l)) elif key == 'y': set_label = axes.set_ylabel set_scale = axes.set_yscale set_start = (lambda l: axes.set_ylim(ymin=l)) set_end = (lambda l: axes.set_ylim(ymax=l)) else: raise RuntimeError("Invalid axis key '%s'" % key) if label is not None: set_label(label) if scale is not None: set_scale(scale) if start is not None: set_start(start) if end is not None: set_end(end) #:layer.visible if layer.visible is False: return # TODO #:layer.title title = layer.title if title is not None: axes.set_title(title) #:layer.grid axes.grid(layer.grid) #:layer.legend:OK self.update_legend(layer) #:layer.labels:OK axes.texts = [] for label in layer.labels: self.update_textlabel(label, layer) #---------------------------------------------------------------------- # Line # def update_line(self, line, layer, axes=None, updateinfo={}): # updateinfo is ignored axes = axes or self.layer_to_axes[layer] omap = self.omaps[layer] line_cache = self.line_caches[layer] data_to_plot = [] #:line.visible if line.visible is False: if line in axes.lines: axes.lines.remove(line) line_cache.remove(line) omap[line] = None return ds = self.get_line_source(line) table = self.get_table(ds) cx, cy = self.get_column_indices(line) xdata, ydata = self.get_table_data(table, cx, cy) #:line.row_first #:line.row_last def limit_data(data, start, end): try: return data[start:end] except IndexError: backend.BackendError("Index range '%s'out of bounds!" % (start,end) ) start, end = line.row_first, line.row_last xdata = limit_data(xdata, start, end) ydata = limit_data(ydata, start, end) #:line.style global linestyle_mappings style = linestyle_mappings[line.style] #:line.marker global linemarker_mappings marker = linemarker_mappings[line.marker] #:line.width:OK #:line.color N = len(layer.group_colors) index = layer.lines.index(line) color = line.rget('color', layer.group_colors[index%N]) #--- PLOT LINE --- l, = axes.plot( xdata, ydata, linewidth=line.width, linestyle=style, marker=marker, color=color) line_cache.append(l) omap[line] = l label = self.get_line_label(line, table=table, cy=cy) if label is not None: l.set_label(label) #---------------------------------------------------------------------- # TextLabel # def on_update_labels(self, layer, updateinfo={}): # updateinfo is ignored # clear existing labels and their corresponding mappings axes = self.layer_to_axes[layer] axes.texts = [] for label in layer.labels: try: self.omaps[layer].pop(label) except KeyError: pass # create new labels for label in layer.labels: self.update_textlabel(label, layer) self.canvas.draw() def update_textlabel(self, label, layer, axes=None, updateinfo={}): # updateinfo is ignored axes = axes or self.layer_to_axes[layer] kwargs = self.label_kwargs(axes, label) if kwargs is None: return transform = kwargs.pop('transform') try: mpl_label = self.omaps[layer][label] except KeyError: mpl_label = Text(**kwargs) self.omaps[layer][label] = mpl_label axes.texts.append(mpl_label) else: mpl_label.update(kwargs) mpl_label.set_transform(transform) def label_kwargs(self, axes, label): if label.x is None or label.y is None: logger.info("Label coordinates contains empty value. Skipped.") return None if label.system == 0: transform = axes.transData elif label.system == 1: transform = axes.transAxes elif label.system == 2: transform = self.figure.transFigure elif label.system == 3: transform = matplotlib.transforms.identity_transform() return {'x': label.x, 'y': label.y, 'text' : label.text, 'horizontalalignment': 'center', 'verticalalignment' : 'center', 'transform' : transform} #---------------------------------------------------------------------- # Legend # def update_legend(self, layer, axes=None, updateinfo={}): # updateinfo is ignored axes = axes or self.layer_to_axes[layer] legend = layer.legend if legend is None: if axes.legend_ is not None: axes.legend_ = None self.omaps[layer][legend] = None else: kw = self.legend_kwargs(legend, layer) border = kw.pop('border') visible = kw.pop('visible') handles, labels = kw.pop('handles'), kw.pop('labels') _legend = axes.legend(handles, labels, **kw) self.omaps[layer][legend] = _legend _legend.draw_frame(border) _legend.set_visible(visible) self.omaps[layer][legend] = axes.legend_ def legend_kwargs(self, legend, layer): """ 'border' must be popped and set via legend.draw_frame 'visible' must be popped and set via set_visible """ visible = legend.visible #:legend.label:TODO label = legend.label if label is not None: pass #:legend.border:OK # (see below but keep it here!) border = legend.border #:legend.position TODO position = legend.position if position == 'at position': position = (legend.x, legend.y) # create legend entries from line labels line_cache = self.line_caches[layer] labels = [l.get_label() for l in line_cache] rv = {'handles' : line_cache, 'labels' : labels, 'loc' : position, 'border' : border, 'visible' : visible} print "LEGEND" print rv return rv
class appGui: def __init__(self): gladefile = "project2.glade" self.windowname = "gtkbench" self.wTree = gtk.glade.XML(gladefile, self.windowname) self.win = self.wTree.get_widget("gtkbench") self.win.maximize() dic = { "on_window1_destroy": gtk.main_quit, "on_button1_clicked": self.submitDB, "on_button3_clicked": self.fillTree, "on_notebook1_switch_page": self.selectNotebookPage, "on_treeview1_button_press_event": self.clickTree, "on_button2_clicked": self.createProjectGraph } self.wTree.signal_autoconnect(dic) # start with database selection self.wDialog = gtk.glade.XML("project2.glade", "dbSelector") # setup matplotlib stuff on first notebook page (empty graph) self.figure = Figure(figsize=(6, 4), dpi=72) self.axis = self.figure.add_subplot(111) self.axis.set_xlabel('Yepper') self.axis.set_ylabel('Flabber') self.axis.set_title('An Empty Graph') self.axis.grid(True) self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea self.canvas.show() self.graphview = self.wTree.get_widget("vbox1") self.graphview.pack_start(self.canvas, True, True) # setup listview for database self.listview = self.wTree.get_widget("treeview1") self.listmodel = gtk.ListStore(str, int, int, str, str) self.listview.set_model(self.listmodel) renderer = gtk.CellRendererText() column = gtk.TreeViewColumn("Name", renderer, text=0) column.set_clickable(True) column.set_sort_column_id(0) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) #renderer = gtk.CellRendererText() column = gtk.TreeViewColumn("Age", renderer, text=1) column.set_clickable(True) column.set_sort_column_id(1) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) #self.listview.show() column = gtk.TreeViewColumn("Shoesize", renderer, text=2) column.set_clickable(True) column.set_sort_column_id(2) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) #self.listview.show() column = gtk.TreeViewColumn("Created", renderer, text=3) column.set_clickable(True) column.set_sort_column_id(3) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) #self.listview.show() #renderer = gtk.CellRendererText() column = gtk.TreeViewColumn("Updated", renderer, text=4) column.set_clickable(True) column.set_sort_column_id(4) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) return # callbacks. def submitDB(self, widget): while True: try: name = self.wTree.get_widget("entry1").get_text() age = self.wTree.get_widget("entry2").get_text() size = self.wTree.get_widget("entry3").get_text() assert name != "" assert age != "" assert size != "" dataUsr = name, age, size sd = DBStuff.Eb_db(host, user, passwd, db) sd.subMit(dataUsr) break except AssertionError: self.wDialog = gtk.glade.XML("project2.glade", "dbWarningEmpty") close = self.wDialog.get_widget("dbWarningEmpty") response = close.run() if response == gtk.RESPONSE_CLOSE: close.destroy() break except DBStuff.MySQLdb.IntegrityError: def callback(): self.wDialog = gtk.glade.XML("project2.glade", "dbWarningOverwrite") close = self.wDialog.get_widget("dbWarningOverwrite") response = close.run() if response == gtk.RESPONSE_CANCEL: close.destroy() if response == gtk.RESPONSE_OK: sd.delRow(name) wd = DBStuff.Eb_db(host, user, passwd, db) wd.subMit(dataUsr) close.destroy() callback() break def fillTree(self, widget): model = self.listmodel self.listmodel.clear() fg = DBStuff.Eb_db(host, user, passwd, db) fg.getData("Age") for i in range(len(fg.data)): # note: all data from table "bench" is appended, but that is something you don't want # possible solution: create a seperate table for the listbox (eg. ommit Timestamp, keep it in another table) self.listmodel.append(fg.data[i]) self.createDBGraph(self) def selectNotebookPage(self, widget, notebookpage, page_number): # if database page is selected (nr. 1 for now!), retrieve data if page_number == 1: self.fillTree(self) if page_number == 0: print "clicked first tab" def clickTree(self, treeview, event): if event.button == 3: x = int(event.x) y = int(event.y) time = event.time pthinfo = treeview.get_path_at_pos(x, y) if pthinfo != None: path, col, cellx, celly = pthinfo treeview.grab_focus() treeview.set_cursor(path, col, 0) self.wDialog = gtk.glade.XML("project2.glade", "treeRightClick") close = self.wDialog.get_widget("treeRightClick") response = close.run() if response == gtk.RESPONSE_OK: close.destroy() print x print y print pthinfo #self.popup.popup( None, None, None, event.button, time) return 1 def createProjectGraph(self, widget): while True: try: # empty axis if neccesary, and reset title and stuff self.axis.clear() self.axis.set_xlabel('Yepper') self.axis.set_ylabel('Flabber') self.axis.set_title('A Graph') self.axis.grid(True) # get data age = self.wTree.get_widget("entry2").get_text() size = self.wTree.get_widget("entry3").get_text() age != "" size != "" N = 1 ind = arange(N) # the x locations for the groups width = 0.35 # the width of the bars p1 = self.axis.bar(ind, int(age), width, color='r') p2 = self.axis.bar(ind + width, int(size), width, color='y') self.axis.legend((p1[0], p2[0]), ("Age", "Size"), shadow=True) #self.axis.set_xticks(ind+width, ('G1') ) self.axis.set_xlim(-width, len(ind)) self.canvas.destroy() self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea self.canvas.show() self.grahview = self.wTree.get_widget("vbox1") self.grahview.pack_start(self.canvas, True, True) break except ValueError: self.wDialog = gtk.glade.XML("project2.glade", "cannotCreateProjGraph") close = self.wDialog.get_widget("cannotCreateProjGraph") response = close.run() if response == gtk.RESPONSE_OK: close.destroy() break def createDBGraph(self, widget): self.axis.clear() self.axis.set_xlabel('Samples (n)') self.axis.set_ylabel('Value (-)') self.axis.set_title( 'Another Graph (click on the columnheader to sort)') self.axis.grid(True) # get columns from listmodel age = [] for row in self.listmodel: age.append(row[1]) size = [] for row in self.listmodel: size.append(row[2]) # get number of rows N = len(age) ind = arange(N) # the x locations for the groups width = 0.35 # the width of the bars p1 = self.axis.bar(ind, age, width, color='b') p2 = self.axis.bar(ind + width, size, width, color='r') # destroy graph if it already exists while True: try: self.canvas2.destroy() break except: print "nothing to destroy" break self.canvas2 = FigureCanvasGTK(self.figure) # a gtk.DrawingArea self.canvas2.show() self.grahview = self.wTree.get_widget("vbox2") self.grahview.pack_start(self.canvas2, True, True)
class appGui: def __init__(self): gladefile = "project2.glade" self.windowname = "gtkbench" self.wTree = gtk.glade.XML(gladefile, self.windowname) self.win = self.wTree.get_widget("gtkbench") self.win.maximize() dic = {"on_window1_destroy" : gtk.main_quit, "on_button1_clicked" : self.submitDB, "on_button3_clicked" : self.fillTree, "on_notebook1_switch_page" : self.selectNotebookPage, "on_treeview1_button_press_event" : self.clickTree, "on_button2_clicked" : self.createProjectGraph } self.wTree.signal_autoconnect(dic) # start with database selection self.wDialog = gtk.glade.XML("project2.glade", "dbSelector") # setup matplotlib stuff on first notebook page (empty graph) self.figure = Figure(figsize=(6,4), dpi=72) self.axis = self.figure.add_subplot(111) self.axis.set_xlabel('Yepper') self.axis.set_ylabel('Flabber') self.axis.set_title('An Empty Graph') self.axis.grid(True) self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea self.canvas.show() self.graphview = self.wTree.get_widget("vbox1") self.graphview.pack_start(self.canvas, True, True) # setup listview for database self.listview = self.wTree.get_widget("treeview1") self.listmodel = gtk.ListStore(str, int, int, str, str) self.listview.set_model(self.listmodel) renderer = gtk.CellRendererText() column = gtk.TreeViewColumn("Name",renderer, text=0) column.set_clickable(True) column.set_sort_column_id(0) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) #renderer = gtk.CellRendererText() column = gtk.TreeViewColumn("Age",renderer, text=1) column.set_clickable(True) column.set_sort_column_id(1) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) #self.listview.show() column = gtk.TreeViewColumn("Shoesize",renderer, text=2) column.set_clickable(True) column.set_sort_column_id(2) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) #self.listview.show() column = gtk.TreeViewColumn("Created",renderer, text=3) column.set_clickable(True) column.set_sort_column_id(3) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) #self.listview.show() #renderer = gtk.CellRendererText() column = gtk.TreeViewColumn("Updated",renderer, text=4) column.set_clickable(True) column.set_sort_column_id(4) column.connect("clicked", self.createDBGraph) column.set_resizable(True) self.listview.append_column(column) return # callbacks. def submitDB(self, widget): while True: try: name = self.wTree.get_widget("entry1").get_text() age = self.wTree.get_widget("entry2").get_text() size = self.wTree.get_widget("entry3").get_text() assert name != "" assert age != "" assert size != "" dataUsr = name, age, size sd = DBStuff.Eb_db(host, user, passwd, db) sd.subMit(dataUsr) break except AssertionError: self.wDialog = gtk.glade.XML("project2.glade", "dbWarningEmpty") close = self.wDialog.get_widget("dbWarningEmpty") response = close.run() if response == gtk.RESPONSE_CLOSE: close.destroy() break except DBStuff.MySQLdb.IntegrityError: def callback(): self.wDialog = gtk.glade.XML("project2.glade", "dbWarningOverwrite") close = self.wDialog.get_widget("dbWarningOverwrite") response = close.run() if response == gtk.RESPONSE_CANCEL: close.destroy() if response == gtk.RESPONSE_OK: sd.delRow(name) wd = DBStuff.Eb_db(host, user, passwd, db) wd.subMit(dataUsr) close.destroy() callback() break def fillTree(self, widget): model = self.listmodel self.listmodel.clear() fg = DBStuff.Eb_db(host, user, passwd, db) fg.getData("Age") for i in range(len(fg.data)): # note: all data from table "bench" is appended, but that is something you don't want # possible solution: create a seperate table for the listbox (eg. ommit Timestamp, keep it in another table) self.listmodel.append(fg.data[i]) self.createDBGraph(self) def selectNotebookPage(self, widget, notebookpage, page_number): # if database page is selected (nr. 1 for now!), retrieve data if page_number == 1: self.fillTree(self) if page_number == 0: print "clicked first tab" def clickTree(self, treeview, event): if event.button == 3: x = int(event.x) y = int(event.y) time = event.time pthinfo = treeview.get_path_at_pos(x, y) if pthinfo != None: path, col, cellx, celly = pthinfo treeview.grab_focus() treeview.set_cursor( path, col, 0) self.wDialog = gtk.glade.XML("project2.glade", "treeRightClick") close = self.wDialog.get_widget("treeRightClick") response = close.run() if response == gtk.RESPONSE_OK: close.destroy() print x print y print pthinfo #self.popup.popup( None, None, None, event.button, time) return 1 def createProjectGraph(self, widget): while True: try: # empty axis if neccesary, and reset title and stuff self.axis.clear() self.axis.set_xlabel('Yepper') self.axis.set_ylabel('Flabber') self.axis.set_title('A Graph') self.axis.grid(True) # get data age = self.wTree.get_widget("entry2").get_text() size = self.wTree.get_widget("entry3").get_text() age != "" size != "" N = 1 ind = arange(N) # the x locations for the groups width = 0.35 # the width of the bars p1 = self.axis.bar(ind, int(age), width, color='r') p2 = self.axis.bar(ind+width, int(size), width, color='y') self.axis.legend((p1[0], p2[0]), ("Age", "Size"), shadow = True) #self.axis.set_xticks(ind+width, ('G1') ) self.axis.set_xlim(-width,len(ind)) self.canvas.destroy() self.canvas = FigureCanvasGTK(self.figure) # a gtk.DrawingArea self.canvas.show() self.grahview = self.wTree.get_widget("vbox1") self.grahview.pack_start(self.canvas, True, True) break except ValueError: self.wDialog = gtk.glade.XML("project2.glade", "cannotCreateProjGraph") close = self.wDialog.get_widget("cannotCreateProjGraph") response = close.run() if response == gtk.RESPONSE_OK: close.destroy() break def createDBGraph(self, widget): self.axis.clear() self.axis.set_xlabel('Samples (n)') self.axis.set_ylabel('Value (-)') self.axis.set_title('Another Graph (click on the columnheader to sort)') self.axis.grid(True) # get columns from listmodel age = [] for row in self.listmodel: age.append(row[1]) size = [] for row in self.listmodel: size.append(row[2]) # get number of rows N = len(age) ind = arange(N) # the x locations for the groups width = 0.35 # the width of the bars p1 = self.axis.bar(ind, age, width, color='b') p2 = self.axis.bar(ind+width, size, width, color='r') # destroy graph if it already exists while True: try: self.canvas2.destroy() break except: print "nothing to destroy" break self.canvas2 = FigureCanvasGTK(self.figure) # a gtk.DrawingArea self.canvas2.show() self.grahview = self.wTree.get_widget("vbox2") self.grahview.pack_start(self.canvas2, True, True)
class appgui: def __init__(self): self.gladefile = "attenuation_calc.glade" windowname = "MainWindow" self.wTree=gtk.glade.XML(self.gladefile, windowname) dic = { "on_GetDataButton_clicked" : self.button1_clicked, "on_SaveImageMenuItem_activate" : self.save_image, "on_ExportMenuItem_activate" : self.save_data, "on_MainWindow_destroy" : (gtk.main_quit) , "on_QuitMenuItem_activate" : (gtk.main_quit), "on_about_menuitem_activate" : self.about } self.wTree.signal_autoconnect(dic) self.figure = Figure(figsize=(6,4), dpi=72) self.axis = self.figure.add_subplot(111) self.axis.set_xlabel('Energies') self.axis.set_ylabel('Attenuation Length (microns)') self.axis.set_title('Attenuation Lengths vs Energy') self.axis.grid(True) self.canvas = FigureCanvasGTK(self.figure) self.canvas.show() self.graphview = self.wTree.get_widget("vbox1") self.graphview.pack_start(self.canvas,True,True) #self.graphview.pack_start(self.canvas,True,True) self.wTree.get_widget(windowname).maximize() self.E = {} self.attlen = {} return def about(self,widget): print 'Hello World' t = gtk.glade.XML(self.gladefile, "aboutdialog1") about = t.get_widget("aboutdialog1") about.run() about.hide() return def button1_clicked(self,widget): self.graphview.remove(self.canvas) # important else they just get inserted again each time (not replaced) self.axis.cla() eltext = self.wTree.get_widget("ElementText").get_text() if eltext.find(',') == -1: el = self.wTree.get_widget("ElementText").get_text().split() else: el = self.wTree.get_widget("ElementText").get_text().split(',') [self.E,self.attlen] = nx.calclengths(el) for e in self.attlen.keys(): self.axis.loglog(self.E[e],self.attlen[e],label=e); self.axis.set_xlabel('Energy (MeV)') self.axis.set_ylabel('Attenuation Length (cm)') self.axis.set_title('Attenuation Lengths vs Energy') self.axis.legend(loc='lower right') self.axis.grid(True) self.canvas.destroy() self.canvas = FigureCanvasGTK(self.figure) self.canvas.show() self.graphview = self.wTree.get_widget("vbox1") self.graphview.pack_end(self.canvas, True, True) #self.graphview.pack_start(self.canvas, True, True) #print dir(self.canvas) def save_image(self,widget): chooser = gtk.FileChooserDialog(title='Save File',action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) chooser.set_default_response(gtk.RESPONSE_OK) response = chooser.run() if response == gtk.RESPONSE_OK: print chooser.get_filename() self.figure.savefig(chooser.get_filename()) else: print 'No files selected' chooser.destroy() def save_data(self,widget): chooser = gtk.FileChooserDialog(title='Save File',action=gtk.FILE_CHOOSER_ACTION_SAVE, buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) chooser.set_default_response(gtk.RESPONSE_OK) response = chooser.run() if response == gtk.RESPONSE_OK: print chooser.get_filename() filename = chooser.get_filename() Eint = [] # ==Interpolate data== # Find unique energies for e in self.E.keys(): Eint = Eint + self.E[e] # Uniquify list Eint = list(set(Eint)) Eint.sort() att_ints = [] # Interpolate the data for e in self.attlen.keys(): buff = interpolate.interp1d(self.E[e], self.attlen[e], kind='linear', bounds_error=False) att_ints.append(buff(Eint)) print 'Writing data to file:',filename fout = open(filename,'w') fout.write('# Data output from attenuation calculator\n') fout.write('Energy,'+ ','.join(self.E.keys())+'\n') print len(Eint), len(self.attlen.keys()) for i in range(len(Eint)): fout.write(str(Eint[i])) for j in range(len(self.attlen.keys())): fout.write(',' + str(att_ints[j][i])) fout.write('\n') #fout.write(str(energy)+','+','.join([i(energy) for i in att_ints])+'\n') print 'Done' else: print 'No files selected' chooser.destroy()
class Backend( backend.Backend ): def init(self): # line_cache: key = id(Curve), value=mpl line object self.line_cache = dict() self.layer_to_axes = dict() self.axes_to_layer = dict() self.layers_cache = list() # copy of self.plot.layers def connect(self): logger.debug("Opening matplotlib session.") self.figure = Figure(dpi=100, facecolor="white") # figsize=(5,4), dpi=100) self.canvas = FigureCanvas(self.figure) self.canvas.show() self.line_cache.clear() self.layer_to_axes.clear() self.axes_to_layer.clear() backend.Backend.connect(self) logger.debug("Init finished") def disconnect(self): logger.debug("Closing matplotlib session.") if not self.canvas is None: self.canvas.destroy() self.canvas = None if not self.figure is None: self.figure = None backend.Backend.disconnect(self) #---------------------------------------------------------------------- def arrange(self, rows=1, cols=1): layers = self.plot.layers n = len(layers) if n > (rows*cols): rows = int((rows*cols) / n) + 1 cols = rows * n #raise ValueError("Not enough rows and cols for all layers!") self.figure.clear() self.figure.axes = [] self.layer_to_axes.clear() self.axes_to_layer.clear() self.layers_cache = list() j = 1 for layer in layers: print "Setting up layer", layer axes = self.figure.add_subplot("%d%d%d" % (rows,cols,j)) self.layer_to_axes[layer] = axes self.axes_to_layer[axes] = layer self.layers_cache.append(layer) j += 1 def draw_layer(self, layer, group_info): ax = self.layer_to_axes[layer] print "DRAWING AXES ", ax ax.lines = [] line_cache = [] line_count = 0 last_cx = -1 # Default values come in two flavors: # group-wise and single default values group_colors = uwrap.get(layer, 'group_colors') group_styles = uwrap.get(layer, 'group_styles') group_markers = uwrap.get(layer, 'group_markers') #default_color = 'r' default_color = None default_style = 'solid' default_marker = 'None' #:layer.visible if uwrap.get(layer, 'visible') is False: return #:layer.title title = uwrap.get(layer, 'title', None) if title is not None: ax.set_title(title) #:layer.grid grid = uwrap.get(layer, 'grid') ax.grid(grid) #:layer.lines for line in layer.lines: data_to_plot = [] #:line.visible if uwrap.get(line, 'visible') is False: if line in ax.lines: ax.lines.remove(line) continue ds = self.get_line_source(line) table = self.get_table(ds) cx, cy = self.get_column_indices(line) xdata, ydata = self.get_table_data(table, cx, cy) #:line.row_first #:line.row_last def limit_data(data, start, end): try: return data[start:end] except IndexError: backend.BackendError("Index range '%s'out of bounds!" % (start,end) ) start, end = line.row_first, line.row_last xdata = limit_data(xdata, start, end) ydata = limit_data(ydata, start, end) #:line.style global linestyle_mappings default = default_style or group_styles[line_count % len(group_styles)] style = uwrap.get(line, 'style', default) style = linestyle_mappings[style] #:line.marker global linemarker_mappings default = default_marker or group_markers[line_count % len(group_markers)] marker = uwrap.get(line, 'marker', default) marker = linemarker_mappings[marker] #:line.width width = uwrap.get(line, 'width') #:line.color default = default_color or group_colors[line_count % len(group_colors)] color = uwrap.get(line, 'color', default) #--- PLOT LINE --- l, = ax.plot( xdata, ydata, linewidth=width, linestyle=style, marker=marker, color=color) line_cache.append(l) label = self.get_line_label(line, table=table, cy=cy) l.set_label(label) line_count += 1 # # # # additional lines # # # p = len(xdata) # if p > 2: p = p/2 # atpoint = xdata[max(p-1,0)] # print "Printing vertical line at ", atpoint # ax.axvline(atpoint) #:layer.legend legend = uwrap.get(layer, 'legend') if legend is not None and line_count > 0: visible = uwrap.get(legend, 'visible') if visible is True: #:legend.label:TODO label = uwrap.get(legend, 'visible') if label is not None: pass #:legend.border:OK # (see below but keep it here!) border = uwrap.get(legend, 'border') #:legend.position TODO position = uwrap.get(legend, 'position', 'best') if position == 'at position': position = (uwrap.get(legend, 'x'), uwrap.get(legend, 'y')) # create legend entries from line labels labels = [l.get_label() for l in line_cache] legend = ax.legend(line_cache, labels, loc=position) legend.draw_frame(border) else: ax.legend_ = None else: ax.legend_ = None #:layer.axes for (key, axis) in layer.axes.iteritems(): #:axis.label #:axis.scale #:axis.start #:axis.end label = uwrap.get(axis, 'label') scale = uwrap.get(axis, 'scale') start = uwrap.get(axis, 'start') end = uwrap.get(axis, 'end') print "START = %s, END = %s" % (str(start), str(end)) if key == 'x': set_label = ax.set_xlabel set_scale = ax.set_xscale set_start = (lambda l: ax.set_xlim(xmin=l)) set_end = (lambda l: ax.set_xlim(xmax=l)) elif key == 'y': set_label = ax.set_ylabel set_scale = ax.set_yscale set_start = (lambda l: ax.set_ylim(ymin=l)) set_end = (lambda l: ax.set_ylim(ymax=l)) else: raise RuntimeError("Invalid axis key '%s'" % key) if label is not None: set_label(label) if scale is not None: set_scale(scale) if start is not None: set_start(start) if end is not None: set_end(end) def draw(self): logger.debug("Matplotlib: draw()") self.check_connection() # plot all curves together in one plot legend_list = [] # for legend later on curve_count = 0 # if self.plot.layers != self.layers_cache: self.arrange() for layer in self.plot.layers: group_info = {} self.draw_layer(layer, group_info) self.canvas.draw()
class Backend( backend.Backend ): def init(self): self.layer_to_axes = {} self.axes_to_layer = {} self.layers_cache = [] # copy of self.plot.layers self.layer_signals = {} self.line_caches = {} self.omaps = {} def connect(self): logger.debug("Opening matplotlib session.") self.figure = Figure(dpi=100, facecolor="white") # figsize=(5,4), dpi=100) self.canvas = FigureCanvas(self.figure) self.canvas.show() self.line_caches = {} self.layer_to_axes.clear() self.axes_to_layer.clear() backend.Backend.connect(self) logger.debug("Init finished") def set(self, project,plot): backend.Backend.set(self, project, plot) if self.project is not None: # TODO: connect to notify::layers of Plot pass def disconnect(self): logger.debug("Closing matplotlib session.") if not self.canvas is None: self.canvas.destroy() self.canvas = None if not self.figure is None: self.figure = None backend.Backend.disconnect(self) #---------------------------------------------------------------------- def arrange(self, rows=1, cols=1): layers = self.plot.layers n = len(layers) if n > (rows*cols): rows = int((rows*cols) / n) + 1 cols = rows * n #raise ValueError("Not enough rows and cols for all layers!") self.figure.clear() self.figure.axes = [] self.layer_to_axes.clear() self.axes_to_layer.clear() self.layers_cache = [] for signal_list in self.layer_signals.itervalues(): for signal in signal_list: Signals.disconnect(signal) self.layer_signals = {} j = 1 for layer in layers: print "Setting up layer", layer axes = self.figure.add_subplot("%d%d%d" % (rows,cols,j)) self.layer_to_axes[layer] = axes self.axes_to_layer[axes] = layer self.layers_cache.append(layer) print "Connecting to notify of ", layer self.layer_signals[layer] = \ [Signals.connect(layer, 'notify', self.on_update_sobject), Signals.connect(layer, 'notify::labels', self.on_update_labels)] j += 1 def draw_layer(self, layer, group_info): ax = self.layer_to_axes[layer] logger.info ("drawing layer %s (axes %s)" % (layer, ax)) omap = self.omaps[layer] ax.lines = [] line_cache = self.line_caches[layer] = [] last_cx = -1 # Default values come in two flavors: # group-wise and single default values group_styles = uwrap.get(layer, 'group_styles') group_markers = uwrap.get(layer, 'group_markers') # def update_layer(self, layer): #:layer.axes for (key, axis) in layer.axes.iteritems(): #:axis.label #:axis.scale #:axis.start #:axis.end label = uwrap.get(axis, 'label') scale = uwrap.get(axis, 'scale') start = uwrap.get(axis, 'start') end = uwrap.get(axis, 'end') print "START = %s, END = %s" % (str(start), str(end)) if key == 'x': set_label = ax.set_xlabel set_scale = ax.set_xscale set_start = (lambda l: ax.set_xlim(xmin=l)) set_end = (lambda l: ax.set_xlim(xmax=l)) elif key == 'y': set_label = ax.set_ylabel set_scale = ax.set_yscale set_start = (lambda l: ax.set_ylim(ymin=l)) set_end = (lambda l: ax.set_ylim(ymax=l)) else: raise RuntimeError("Invalid axis key '%s'" % key) if label is not None: set_label(label) if scale is not None: set_scale(scale) if start is not None: set_start(start) if end is not None: set_end(end) #:layer.visible if uwrap.get(layer, 'visible') is False: return # TODO #:layer.title title = uwrap.get(layer, 'title', None) if title is not None: ax.set_title(title) # TODO #:layer.grid grid = uwrap.get(layer, 'grid') ax.grid(grid) #:layer.lines:OK for line in layer.lines: self.update_line(line, layer, axes=ax) #:layer.legend:OK self.update_legend(layer.legend, layer) #:layer.labels:OK ax.texts = [] for label in layer.labels: self.update_textlabel(label, layer) def draw(self): self.check_connection() logger.debug("Matplotlib: draw()") if self.plot.layers != self.layers_cache: self.arrange() self.omaps = {} for layer in self.plot.layers: self.omaps[layer] = {} self.line_caches[layer] = {} group_info = {} self.draw_layer(layer, group_info) self.canvas.draw() #---------------------------------------------------------------------- def on_update_sobject(self, sender, sobject, **kwargs): logger.debug("Updating %s with args %s" % (sobject,str(kwargs))) return try: if isinstance(sobject, objects.TextLabel): self.update_textlabel(sobject, sender, **kwargs) elif isinstance(sobject, objects.Legend): self.update_legend(sobject, **kwargs) elif isinstance(sobject, objects.Line): self.update_line(sobject, **kwargs) self.update_legend(sobject, **kwargs) except Exception, msg: logger.info("Exception raised during sobject update.") logger.info(str(inspect.trace())) else: