def __init__(self, x, y, title="Graph", parent=None): gtk.Window.__init__(self) try: self.set_screen(parent.get_screen()) except: self.connect('destroy', lambda *w: self.destroy()) self.set_title(title) self.set_default_size(800, 600) self.set_border_width(2) self.set_position(gtk.WIN_POS_CENTER) box = gtk.VBox() self.add(box) fig = Fig(figsize=(5,4), dpi=100) ax = fig.add_subplot(111) ax.plot(x, y) canvas = FigCan(fig) canvas.mpl_connect('key_press_event', self.on_key_event) box.pack_start(canvas) toolbar = NavBar(canvas, self) box.pack_start(toolbar, False, False) self.show_all() del box, fig, ax, canvas, toolbar
class PowerGraph(gtk.Window): def __init__(self, powers, step=0.5, title="Power Graph", parent=None): x = [] y = [] for power, next_power in itertools.izip(powers, powers[1:]): u = float(power[0]) u1 = float(next_power[0]) while u < u1: x.append(u) y.append(float(eval(power[1]))) u += step*(u1-u) x.append(float(powers[-1][0])) y.append(float(eval(powers[-1][1]))) gtk.Window.__init__(self) try: self.set_screen(parent.get_screen()) except AttributeError: self.connect('destroy', lambda *w: self.destroy()) if parent is not None: self.set_parent(parent) self.set_title(title) self.set_destroy_with_parent(True) self.set_default_size(600, 400) vbox = gtk.VBox() self.add(vbox) figure = Figure(figsize=(5,4), dpi=100) subplot = figure.add_subplot(111) subplot.plot(x, y) subplot.set_title("Power Graph") subplot.set_xlabel("Speed (u) [m/s]") subplot.set_ylabel("Power [kW]") subplot.grid(True) self.canvas = FigureCanvas(figure) self.canvas.mpl_connect('key_press_event', self.on_key_event) vbox.pack_start(self.canvas) self.toolbar = NavigationToolbar(self.canvas, self) vbox.pack_start(self.toolbar, False, False) self.show_all() def on_key_event(self, event): key_press_handler(event, self.canvas, self.toolbar)
def __init__(self, toolBoxWidgets=None, title="GTK Gui Plot", scaling=True, *args, **kwargs): if not toolBoxWidgets: toolBoxWidgets = [] super(GuiWithCanvasAndToolbar, self).__init__(*args, **kwargs) self.connect("destroy", lambda x: gtk.main_quit()) self.set_default_size(1100, 600) self.set_title(title) table = gtk.Table(1, 2, False) self.figures = [] self.y_max = float("-inf") self.x_max = float("-inf") self.y_min = float("inf") self.x_min = float("inf") self.fig = Figure(figsize=(8, 6), dpi=100) self.ax = self.fig.add_subplot(111) canvas = FigureCanvas(self.fig) canvas.set_size_request(800, 600) canvas.mpl_connect('button_press_event', self.handle_click) table.attach(canvas, 0, 1, 0, 1) toolbox = gtk.Table(len(toolBoxWidgets) + 1, 1, False) i = 0 for widget in toolBoxWidgets: toolbox.attach(widget, 0, 1, i, i + 1) i += 1 label = gtk.Label("SimGUI") toolbox.attach(label, 0, 1, i, i + 1) table.attach(toolbox, 1, 2, 0, 1) self.canvas = canvas canvas.draw() self.update_figures() self.add(table) self.scaling = scaling
def __init__(self, wTree, widget): figure = Figure(figsize=(6,4), dpi=72) axes = figure.add_subplot(1,1,1) canvas = FigureCanvasGTKAgg(figure) canvas.show() canvas.mpl_connect('pick_event', self.pick_handler) canvas.mpl_connect('motion_notify_event', self.motion_handler) canvas.mpl_connect('button_release_event', self.release_handler) canvas.mpl_connect('button_press_event', self.press_handler) graphview = wTree.get_widget(widget) graphview.add_with_viewport(canvas) self.figure = figure self.canvas = canvas self.axes = axes self.plot_line = self.axes.plot([], [], 'b-', animated=True)[0] self.cursors = [] self.picked = None self.data = []
class GenomeBrowser(object): def __init__(self): """ 2008-01-30 """ program_path = os.path.dirname(sys.argv[0]) xml = gtk.glade.XML(os.path.join(program_path, 'GenomeBrowser.glade')) xml.signal_autoconnect(self) self.xml = xml self.app1 = xml.get_widget("app1") self.app1.connect("delete_event", gtk.main_quit) #self.app1.set_default_size(1200, 800) self.vbox_matplotlib = xml.get_widget('vbox_matplotlib') # matplotlib canvas fig = Figure(figsize=(8,8)) self.canvas_matplotlib = FigureCanvas(fig) # a gtk.DrawingArea self.canvas_matplotlib.set_size_request(600,400) self.canvas_matplotlib.mpl_connect('pick_event', self.on_canvas_pick) self.vbox_matplotlib.pack_start(self.canvas_matplotlib) #matplotlib axes #self.ax = fig.add_subplot(111) axe_y_offset1 = 0.05 #y_offset for axe_LD, axe_strain_pca, axe_phenotype, axe_map axe_height1 = 0.15 #height of axe_LD or axe_snp_matrix axe_y_offset2 = axe_y_offset1+axe_height1 axe_height2 = 0.75 #height of axe_gene_model axe_y_offset3 = axe_y_offset2+axe_height2 axe_x_offset1 = 0.1 # axe_width1 = 0.85 axe_x_offset2 = axe_x_offset1 + axe_width1 self.ax = fig.add_axes([axe_x_offset1, axe_y_offset2, axe_width1, axe_height2], frameon=False) self.ax.grid(True, alpha=0.3) #self.ax.set_xticklabels([]) #remove xtick labels on ax1 because axe_LD's xtick labels cover this. self.axe_gene_model = fig.add_axes([axe_x_offset1, axe_y_offset1, axe_width1, axe_height1], frameon=False, sharex=self.ax) #axe_gene_model.set_xticks([]) #this will set ax1's xticks off as well because the x-axis is shared. self.axe_gene_model.set_yticks([]) # matplotlib toolbar self.toolbar = NavigationToolbar(self.canvas_matplotlib, self.app1) self.vbox_matplotlib.pack_start(self.toolbar, False, False) self.textview_output = xml.get_widget('textview_output') self.textbuffer_output = self.textview_output.get_buffer() #redirect stdout/stderr to textbuffer_output t_table=self.textbuffer_output.get_tag_table() tag_err=gtk.TextTag("error") tag_err.set_property("foreground","red") #tag_err.set_property("font","monospace 10") t_table.add(tag_err) tag_out=gtk.TextTag("output") tag_out.set_property("foreground","blue") #tag_out.set_property("font","monospace 10") t_table.add(tag_out) self.dummy_out = yh_gnome.Dummy_File(self.textbuffer_output, tag_out) self.dummy_err = yh_gnome.Dummy_File(self.textbuffer_output, tag_err) sys.stdout = self.dummy_out sys.stderr = self.dummy_err self.app1.show_all() self.filechooserdialog1 = xml.get_widget("filechooserdialog1") self.entry_min_value_cutoff = xml.get_widget('entry_min_value_cutoff') self.entry_max_value_cutoff = xml.get_widget('entry_max_value_cutoff') self.filechooserdialog1.connect("delete_event", yh_gnome.subwindow_hide) self.dialog_db_connect = xml.get_widget("dialog_db_connect") self.dialog_db_connect.connect("delete_event", yh_gnome.subwindow_hide) self.entry_mysql_hostname = xml.get_widget("entry_mysql_hostname") self.entry_mysql_dbname = xml.get_widget("entry_mysql_dbname") self.entry_postgres_hostname = xml.get_widget("entry_postgres_hostname") self.entry_postgres_dbname = xml.get_widget("entry_postgres_dbname") self.entry_postgres_schema = xml.get_widget("entry_postgres_schema") self.entry_gene_annotation_picklef = xml.get_widget("entry_gene_annotation_picklef") self.filechooserbutton_gene_annot = xml.get_widget("filechooserbutton_gene_annot") self.dialog_preferences = xml.get_widget("dialog_preferences") self.dialog_preferences.connect("delete_event", yh_gnome.subwindow_hide) self.checkbutton_debug = xml.get_widget("checkbutton_debug") self.checkbutton_stdout = xml.get_widget("checkbutton_stdout") self.checkbutton_stderr = xml.get_widget("checkbutton_stderr") self.entry_gene_width = xml.get_widget("entry_gene_width") self.checkbutton_draw_gene_symbol = xml.get_widget("checkbutton_draw_gene_symbol") self.aboutdialog1 = xml.get_widget("aboutdialog1") self.aboutdialog1.connect("delete_event", yh_gnome.subwindow_hide) self.dialog_cnvqc_db = xml.get_widget("dialog_cnvqc_db") self.filechooserdialog_cnv_gada = xml.get_widget("filechooserdialog_cnv_gada") self.mysql_conn = self.mysql_curs = self.postgres_conn = self.postgres_curs = self.db = None self.gene_annotation = None self.candidate_gene_set = None self.chr_id2size = None self.chr_id2cumu_size = None self.chr_gap = None self.chr_id_ls = [] self.genome_wide_results = GenomeWideResults(gap=1.0) self.genome_wide_results.genome_wide_result_ls = [] self.genome_wide_results.genome_wide_result_obj_id2index = {} self.artist_obj_id2data_obj_key = {} self.yticks = [] self.yticklabels = [] self.gene_id2artist_object_id = {} self.chr_id2gene_id_ls = {} #chr_id here is str type (db is varchar type) self.gene_id2model = {} self.artist_obj_id2artist_gene_id_ls = {} self.gene_id2vspan_obj_id = {} #for the axvspan()'s drawn on the canvas self.gene_width = 1.0 self.draw_gene_symbol_when_clicked = 0 self.debug = 0 def load_data(self, mysql_curs, postgres_curs): """ 2008-02-04 update the info related to chromosome , position in toolbar 2008-02-01 read the input data chr_id2cumu_size has an extra fake chromosome (0) compared to chr_id2size chr_id is all changed into str type """ from variation.src.common import get_chr_id2size, get_chr_id2cumu_size chr_id_int2size = get_chr_id2size(mysql_curs) self.chr_id2size = {} #change the type of chr_id into string type for chr_id_int, size in chr_id_int2size.iteritems(): self.chr_id2size[str(chr_id_int)] = size #chr_id2cumu_size has an extra fake chromosome (0) compared to chr_id2size data_ls = get_chr_id2cumu_size(self.chr_id2size) self.chr_id2cumu_size, self.chr_gap, self.chr_id_ls = data_ls[:3] #2008-02-04 update the info related to chromosome , position in toolbar if self.debug: print 'self.chr_id2size', self.chr_id2size for chr_id in self.chr_id2size: print type(chr_id) print 'self.chr_id2cumu_size', self.chr_id2cumu_size for chr_id in self.chr_id2cumu_size: print type(chr_id) print 'self.chr_id_ls', self.chr_id_ls for chr_id in self.chr_id_ls: print type(chr_id) self.toolbar.update_chr_info(self.chr_id2size, self.chr_id2cumu_size, self.chr_gap, self.chr_id_ls) def getXposition(self, chr, pos): chr = str(chr) if getattr(self, 'chr_id2cumu_size', None) is None: self.load_data(self.mysql_curs, self.postgres_curs) this_chr_starting_pos_on_plot = self.chr_id2cumu_size[chr]-self.chr_id2size[chr]-self.chr_gap x = this_chr_starting_pos_on_plot + pos return x def plot(self, ax, canvas, genome_wide_result, draw_line_as_point=True, draw_cnv_block=True): """ 2008-05-28 input is genome_wide_result chr_id2cumu_size, chr_id2size, chr_gap hidden from arguments 2008-02-04 chromosome is converted to str type 2008-02-01 draw the p-value, snp position, and chromosome boundary """ sys.stderr.write("Plotting %s ..."%genome_wide_result.name) #ax.clear() genome_wide_result_id = id(genome_wide_result) x_ls = [] y_ls = [] plot_together = True for data_obj in genome_wide_result.data_obj_ls: y_pos = genome_wide_result.base_value - genome_wide_result.min_value + data_obj.value x_pos = self.getXposition(data_obj.chromosome, data_obj.position) if data_obj.stop_position is not None and draw_cnv_block==True: x_stop_pos = self.getXposition(data_obj.chromosome, data_obj.stop_position) xs = [x_pos, x_stop_pos, x_stop_pos, x_pos] y_base_pos = genome_wide_result.base_value - genome_wide_result.min_value + 0 ys = [y_pos, y_pos, y_base_pos, y_base_pos] artist_obj = Polygon(zip(xs,ys), facecolor='g', alpha=0.8, linewidth=0.5) #linewidth=0.7 ax.add_patch(artist_obj) artist_obj_id = id(artist_obj) plot_together = False if data_obj.stop_position is not None and draw_line_as_point==False: #bigger than 100k, then a line x_stop_pos = self.getXposition(data_obj.chromosome, data_obj.stop_position) x_ls.append([(x_pos, y_pos), (x_stop_pos, y_pos)]) #artist_obj = Line2D([x_pos, y_pos], [x_stop_pos, y_pos], picker=True) else: if draw_line_as_point and data_obj.stop_position is not None: x_stop_pos = self.getXposition(data_obj.chromosome, data_obj.stop_position) x_pos = (x_pos+x_stop_pos)/2.0 x_ls.append(x_pos) y_ls.append(y_pos) #artist_obj = Circle((x_pos, y_pos), picker=True) if plot_together: if len(y_ls)>0: artist_obj = ax.scatter(x_ls, y_ls, s=10, faceted=False, picker=True) else: artist_obj = LineCollection(x_ls, picker=True) ax.add_artist(artist_obj) artist_obj_id = id(artist_obj) self.artist_obj_id2data_obj_key[artist_obj_id] = [genome_wide_result_id, None] y_base_value = genome_wide_result.base_value y_top_value = genome_wide_result.base_value + genome_wide_result.max_value - genome_wide_result.min_value if self.debug: print "y_base_value", y_base_value print 'y_top_value', y_top_value self.yticks.append(y_base_value) self.yticks.append(y_top_value) ax.set_yticks(self.yticks) self.yticklabels.append('%s %.2f'%(genome_wide_result.name, genome_wide_result.min_value)) self.yticklabels.append('%s %.2f'%(genome_wide_result.name, genome_wide_result.max_value)) ax.set_yticklabels(self.yticklabels) """ ax.add_artist(g_artist) artist_obj_id = id(g_artist) self.artist_obj_id2artist_gene_id_ls[artist_obj_id] = [g_artist, gene_id] self.gene_id2artist_object_id[gene_id] = artist_obj_id x_ls = [] y_ls = [] max_pvalue = 0 for i in range(len(snp_pos_ls)): chr, pos = snp_pos_ls[i] chr = str(chr) this_chr_starting_pos_on_plot = chr_id2cumu_size[chr]-chr_id2size[chr]-chr_gap x = this_chr_starting_pos_on_plot + pos x_ls.append(x) pvalue = pvalue_ls[i] if pvalue > max_pvalue: max_pvalue = pvalue y_ls.append(pvalue) ax.plot(x_ls, y_ls, '.', picker=3) #3 points tolerance """ #draw the chromosome boundary for chr_id, cumu_size in self.chr_id2cumu_size.iteritems(): ax.vlines(cumu_size, y_base_value, y_top_value, color='k') canvas.draw() sys.stderr.write("Done.\n") def respond2GeneObjPicker(self, event, artist_obj_id, artist_obj_id2artist_gene_id_ls, gene_annotation,\ ax=None, draw_gene_symbol_when_clicked=False, canvas_matplotlib=None): """ 2008-12-17 a common function specifying how to respond to picker events of both gene models in axe_gene_model and vertical gene spans in ax called by on_canvas_pick() """ gene_id = artist_obj_id2artist_gene_id_ls[artist_obj_id][1] gene_model = gene_annotation.gene_id2model[gene_id] if len(gene_model.gene_commentaries)==0: gene_commentary = gene_model #fake one here else: gene_commentary = gene_model.gene_commentaries[0] protein_label = getattr(gene_commentary, 'protein_label', None) if not protein_label: protein_label = getattr(gene_commentary, 'label', '') protein_comment = getattr(gene_commentary, 'protein_comment', None) if not protein_comment: protein_comment = getattr(gene_commentary, 'comment', '') if getattr(gene_commentary, 'protein_label', None) is not None: #true gene_commentary is available type_of_gene = getattr(gene_model, 'type_of_gene', '') else: #it doesn't have protein, get gene_commentary_type type_of_gene = getattr(gene_commentary, 'gene_commentary_type', '') print '%s (gene id=%s) type_of_gene: %s. chromosome: %s. start: %s. stop: %s. strand: %s.'%\ (gene_model.gene_symbol, gene_id, type_of_gene, gene_model.chromosome, \ gene_model.start, gene_model.stop, gene_model.strand) print '\t protein_label: %s.'%protein_label print '\t protein_comment: %s.'%protein_comment if draw_gene_symbol_when_clicked: if ax: ax.text(event.mouseevent.xdata, event.mouseevent.ydata, gene_model.gene_symbol, size=8) if canvas_matplotlib: canvas_matplotlib.draw() def on_canvas_pick(self, event): """ 2008-11-12 display more information (maf, genotype_var_perc, comment) of data_obj (SNP) if they exist 2008-05-28 pick from collection 2008-01-31 copied from examples/pick_event_demo.py from matplotlib source code """ if self.debug: print dir(event) print event.artist print dir(event.artist) print type(event.artist) """ if isinstance(event.artist, Line2D): thisline = event.artist xdata = thisline.get_xdata() ydata = thisline.get_ydata() ind = event.ind if self.debug: print "indices:", ind print 'onpick1 line:', zip(numpy.take(xdata, ind), numpy.take(ydata, ind)) for i in ind: print "snp chromosome: %s, position: %s, pvalue: %s"%(self.snp_pos_ls[i][0], self.snp_pos_ls[i][1], self.pvalue_ls[i]) """ if isinstance(event.artist, ExonIntronCollection): #ExonIntronCollection is also a kind of Collection artist_obj_id = id(event.artist) if artist_obj_id in self.artist_obj_id2artist_gene_id_ls: self.respond2GeneObjPicker(event, artist_obj_id, self.artist_obj_id2artist_gene_id_ls, self.gene_annotation,\ ax=self.axe_gene_model, draw_gene_symbol_when_clicked=self.draw_gene_symbol_when_clicked, \ canvas_matplotlib=self.canvas_matplotlib) else: sys.stderr.write("%s not in artist_obj_id2artist_gene_id_ls.\n"%(artist_obj_id)) elif isinstance(event.artist, Collection) or isinstance(event.artist, LineCollection): # artist_obj_id = id(event.artist) if artist_obj_id in self.artist_obj_id2data_obj_key: genome_wide_result_id, data_obj_id = self.artist_obj_id2data_obj_key[artist_obj_id] genome_wide_result = self.genome_wide_results.get_genome_wide_result_by_obj_id(genome_wide_result_id) for obj_index in event.ind: if isinstance(obj_index, tuple) or isinstance(obj_index, list): obj_index = obj_index[0] data_obj = genome_wide_result.get_data_obj_by_obj_index(obj_index) output_str = "genome result: %s, chromosome: %s, position: %s, "%(genome_wide_result.name, data_obj.chromosome, data_obj.position) if data_obj.stop_position is not None: output_str += "stop position: %s, "%(data_obj.stop_position) output_str += '\n' output_str += "\tscore: %s\n"%(data_obj.value) if data_obj.maf: output_str += "\tmaf: %s\n"%(data_obj.maf) if data_obj.genotype_var_perc: output_str += "\tgenotype_var_perc: %s\n"%(data_obj.genotype_var_perc) if data_obj.comment: output_str += "\tcomment: %s\n"%(data_obj.comment) print output_str else: sys.stderr.write("%s not in artist_obj_id2data_obj_key.\n"%(artist_obj_id)) elif isinstance(event.artist, Polygon): #ExonIntronCollection is also a kind of Collection artist_obj_id = id(event.artist) print 'artist ID:', artist_obj_id patch = event.artist print 'onpick1 patch:', patch.get_verts() if artist_obj_id in self.artist_obj_id2artist_gene_id_ls: self.respond2GeneObjPicker(event, artist_obj_id, self.artist_obj_id2artist_gene_id_ls, self.gene_annotation,\ ax=self.ax, draw_gene_symbol_when_clicked=self.draw_gene_symbol_when_clicked, \ canvas_matplotlib=self.canvas_matplotlib) else: sys.stderr.write("%s not in artist_obj_id2artist_gene_id_ls.\n"%(artist_obj_id)) elif isinstance(event.artist, Rectangle): patch = event.artist print 'onpick1 patch:', patch.get_verts() elif isinstance(event.artist, Text): text = event.artist print 'onpick1 text:', text.get_text() def on_imagemenuitem_quit_activate(self, data=None): """ 2008-02-01 program quits """ gtk.main_quit() def on_imagemenuitem_open_activate(self, event, data=None): self.filechooserdialog1.show_all() def on_imagemenuitem_db_connect_activate(self, event, data=None): self.dialog_db_connect.show_all() def on_imagemenuitem_cnvqc_db_activate(self, event, data=None): """ 2009-10-30 """ self.dialog_cnvqc_db.show_all() def on_imagemenuitem_cnv_file_activate(self, event, data=None): """ 2009-10-30 """ self.filechooserdialog_cnv_gada.show_all() def on_button_filechooser_ok_clicked(self, widget, data=None): """ 2008-12-16 allow gwr name to be specified add function to get gwr from db based on call_method_id, analysis_method_id, phenotype_method_id 2008-10-12 add checkbutton_draw_line_as_point add checkbutton_4th_col_stop_pos 2008-08-03 restrict the data by (chromosome, start, stop) 2008-05-31 add check button to handle log10 transformation 2008-05-28 use GenomeWideResult and etc 2008-02-14 set the window title by the input filename """ input_fname = self.filechooserdialog1.get_filename() self.filechooserdialog1.hide() if not self.mysql_conn or not self.mysql_curs: self.db_connect() self.app1.set_title("Genome Browser: %s"%input_fname) checkbutton_log10_transformation = self.xml.get_widget("checkbutton_log10_transformation") if checkbutton_log10_transformation.get_active(): do_log10_transformation = True else: do_log10_transformation = False if self.entry_min_value_cutoff.get_text(): min_value_cutoff = float(self.entry_min_value_cutoff.get_text()) else: min_value_cutoff = None #2008-08-03 pdata = PassingData() entry_chromosome = self.xml.get_widget("entry_chromosome") if entry_chromosome.get_text(): pdata.chromosome = int(entry_chromosome.get_text()) entry_start = self.xml.get_widget("entry_start") if entry_start.get_text(): pdata.start = int(entry_start.get_text()) entry_stop = self.xml.get_widget("entry_stop") if entry_stop.get_text(): pdata.stop = int(entry_stop.get_text()) # 2009-10-27 if self.entry_max_value_cutoff.get_text(): pdata.max_value_cutoff = float(self.entry_max_value_cutoff.get_text()) else: pdata.max_value_cutoff = None # 2009-10-27 checkbutton_OR_min_max = self.xml.get_widget("checkbutton_OR_min_max") if checkbutton_OR_min_max.get_active(): pdata.OR_min_max = True else: pdata.OR_min_max = False checkbutton_4th_col_stop_pos = self.xml.get_widget("checkbutton_4th_col_stop_pos") if checkbutton_4th_col_stop_pos.get_active(): pdata.is_4th_col_stop_pos = True else: pdata.is_4th_col_stop_pos = False checkbutton_draw_line_as_point = self.xml.get_widget("checkbutton_draw_line_as_point") if checkbutton_draw_line_as_point.get_active(): draw_line_as_point= True else: draw_line_as_point = False entry_gwr_name = self.xml.get_widget("entry_gwr_name") if entry_gwr_name.get_text(): pdata.gwr_name = entry_gwr_name.get_text() else: pdata.gwr_name = None entry_call_method_id = self.xml.get_widget("entry_call_method_id") call_method_id = entry_call_method_id.get_text() entry_analysis_method_id = self.xml.get_widget("entry_analysis_method_id") analysis_method_id = entry_analysis_method_id.get_text() entry_phenotype_method_id = self.xml.get_widget("entry_phenotype_method_id") phenotype_method_id = entry_phenotype_method_id.get_text() if call_method_id and analysis_method_id and phenotype_method_id: call_method_id = int(call_method_id) analysis_method_id = int(analysis_method_id) phenotype_method_id = int(phenotype_method_id) rows = Stock_250kDB.ResultsMethod.query.filter_by(call_method_id=call_method_id).filter_by(analysis_method_id=analysis_method_id).\ filter_by(phenotype_method_id=phenotype_method_id).filter_by(results_method_type_id=1) if rows.count()==1: rm = rows.first() elif rows.count()==0: sys.stderr.write("No result fetched from db based on call_method_id=%s, analysis_method_id=%s, phenotype_method_id=%s.\n"%\ (call_method_id, analysis_method_id, phenotype_method_id)) rm = None else: sys.stderr.write("First result out of %s results fetched from db based on call_method_id=%s, analysis_method_id=%s, phenotype_method_id=%s.\n"%\ (rows.count(), call_method_id, analysis_method_id, phenotype_method_id)) rm = rows.first() if rm: input_fname = rm.filename pdata.gwr_name = '%s_%s_%s'%(rm.analysis_method.short_name, rm.phenotype_method_id, rm.phenotype_method.short_name) genome_wide_result = getGenomeWideResultFromFile(input_fname, min_value_cutoff, do_log10_transformation, pdata) if len(genome_wide_result.data_obj_ls)>0: self.genome_wide_results.add_genome_wide_result(genome_wide_result) #self.load_data(input_fname, self.mysql_curs, self.postgres_curs) self.plot(self.ax, self.canvas_matplotlib, self.genome_wide_results.genome_wide_result_ls[-1], draw_line_as_point=draw_line_as_point) else: sys.stderr.write("No data in %s under min_value_cutoff=%s. Maybe min_value_cutoff is too high.\n"%(input_fname, min_value_cutoff)) def on_button_filechooser_cancel_clicked(self, widget, data=None): self.filechooserdialog1.hide() def on_button_dialog_db_connect_cancel_clicked(self, widget, data=None): self.dialog_db_connect.hide() def on_button_dialog_db_connect_clicked(self, widget, data=None): self.dialog_db_connect.hide() self.db_connect() def on_button_cnvqc_ok_clicked(self, widget, data=None): """ 2009-10-30 """ self.dialog_cnvqc_db.hide() if not self.mysql_conn or not self.mysql_curs: self.db_connect() entry_cnv_qc_accession_id = self.xml.get_widget("entry_cnv_qc_accession_id") cnv_qc_accession_id = entry_cnv_qc_accession_id.get_text() if cnv_qc_accession_id: cnv_qc_accession_id = int(cnv_qc_accession_id) else: sys.stderr.write("Accession id is not given.\n") return entry_cnv_type_id = self.xml.get_widget("entry_cnv_type_id") cnv_type_id = entry_cnv_type_id.get_text() if cnv_type_id: cnv_type_id = int(cnv_type_id) else: cnv_type_id = None entry_cnv_qc_min_size = self.xml.get_widget("entry_cnv_qc_min_size") cnv_qc_min_size = entry_cnv_qc_min_size.get_text() if cnv_qc_min_size: cnv_qc_min_size = int(cnv_qc_min_size) else: cnv_qc_min_size = None entry_cnv_qc_min_no_of_probes = self.xml.get_widget("entry_cnv_qc_min_no_of_probes") cnv_qc_min_no_of_probes = entry_cnv_qc_min_no_of_probes.get_text() if cnv_qc_min_no_of_probes: cnv_qc_min_no_of_probes = int(cnv_qc_min_no_of_probes) else: cnv_qc_min_no_of_probes = None genome_wide_result = self.db.getCNVQCInGWA(cnv_qc_accession_id, cnv_type_id=cnv_type_id, min_size=cnv_qc_min_size,\ min_no_of_probes=cnv_qc_min_no_of_probes) if len(genome_wide_result.data_obj_ls)>0: self.genome_wide_results.add_genome_wide_result(genome_wide_result) #self.load_data(input_fname, self.mysql_curs, self.postgres_curs) self.plot(self.ax, self.canvas_matplotlib, self.genome_wide_results.genome_wide_result_ls[-1], draw_cnv_block=True) else: sys.stderr.write("No CNV QC data for accession_id=%s, cnv_type=%s, min_size=%s, min_no_of_probes=%s.\n"%\ (cnv_qc_accession_id, cnv_type_id, cnv_qc_min_size, cnv_qc_min_no_of_probes)) def on_button_cnvqc_cancel_clicked(self, widget, data=None): """ 2009-10-30 """ self.dialog_cnvqc_db.hide() def on_button_cnv_gada_ok_clicked(self, widget, data=None): """ 2009-10-30 get CNVs from GADA output file """ input_fname = self.filechooserdialog_cnv_gada.get_filename() self.filechooserdialog_cnv_gada.hide() if not self.mysql_conn or not self.mysql_curs: self.db_connect() entry_cnv_array_id = self.xml.get_widget("entry_cnv_array_id") array_id = entry_cnv_array_id.get_text() if array_id: array_id = int(array_id) else: sys.stderr.write("Array id is not given.\n") return entry_cnv_max_amp = self.xml.get_widget("entry_cnv_max_amp") max_amp = entry_cnv_max_amp.get_text() if max_amp: max_amp = float(max_amp) else: max_amp = None entry_cnv_min_amp = self.xml.get_widget("entry_cnv_min_amp") min_amp = entry_cnv_min_amp.get_text() if min_amp: min_amp = float(min_amp) else: min_amp = None entry_cnv_min_size = self.xml.get_widget("entry_cnv_min_size") min_size = entry_cnv_min_size.get_text() if min_size: min_size = int(min_size) else: min_size = None entry_cnv_min_no_of_probes = self.xml.get_widget("entry_cnv_min_no_of_probes") min_no_of_probes = entry_cnv_min_no_of_probes.get_text() if min_no_of_probes: min_no_of_probes = int(min_no_of_probes) else: min_no_of_probes = None input_fname_ls = [input_fname] genome_wide_result = getCNVDataFromFileInGWA(input_fname_ls, array_id, max_amp=max_amp, min_amp=min_amp, min_size=min_size,\ min_no_of_probes=min_no_of_probes) if len(genome_wide_result.data_obj_ls)>0: self.genome_wide_results.add_genome_wide_result(genome_wide_result) #self.load_data(input_fname, self.mysql_curs, self.postgres_curs) self.plot(self.ax, self.canvas_matplotlib, self.genome_wide_results.genome_wide_result_ls[-1], draw_cnv_block=True) else: sys.stderr.write("No CNV data for array_id=%s, max_amp=%s, min_amp=%s, min_size=%s, min_no_of_probes=%s.\n"%\ (array_id, max_amp, min_amp, min_size, min_no_of_probes)) def on_button_cnv_gada_cancel_clicked(self, widget, data=None): """ 2009-10-30 """ self.filechooserdialog_cnv_gada.hide() def db_connect(self): """ 2010-1-15 pass "cls_with_db_args=self" to DrawSNPRegion.dealWithGeneAnnotation() 2009-12-09 add db_user, db_passwd to MySQLdb.connect() 2008-12-16 add gene_annotation_picklef 2008-02-01 read the data in dialog_db_connect and establish the connections to two databases """ sys.stderr.write("Database Connecting ...") self.drivername = 'mysql' self.hostname = self.entry_mysql_hostname.get_text() self.dbname = self.entry_mysql_dbname.get_text() self.db_user = self.xml.get_widget("entry_db_user").get_text() self.db_passwd = self.xml.get_widget("entry_db_passwd").get_text() import MySQLdb try: self.mysql_conn = MySQLdb.connect(db=self.dbname, host=self.hostname, user=self.db_user, passwd=self.db_passwd) self.mysql_curs = self.mysql_conn.cursor() self.db = Stock_250kDB.Stock_250kDB(drivername=self.drivername, username=self.db_user, password=self.db_passwd, hostname=self.hostname, database=self.dbname) self.db.setup(create_tables=False) self.session = self.db.session except: sys.stderr.write('DB connection error: %s\n'%repr(sys.exc_info())) traceback.print_exc() if not self.gene_annotation: gene_annotation_picklef = self.entry_gene_annotation_picklef.get_text() self.gene_annotation = DrawSNPRegion.dealWithGeneAnnotation(gene_annotation_picklef, cls_with_db_args=self) #2010-1-13 for postgresql. commented out #hostname = self.entry_postgres_hostname.get_text() #dbname = self.entry_postgres_dbname.get_text() #schema = self.entry_postgres_schema.get_text() #from annot.bin.codense.common import db_connect #2008-12-16 don't need postgres conn anymore #self.postgres_conn, self.postgres_curs = db_connect(hostname, dbname, schema) sys.stderr.write("Done.\n") def get_gene_id2model(cls, curs, entrezgene_mapping_table='genome.entrezgene_mapping', \ annot_assembly_table = 'genome.annot_assembly', gene_table='genome.gene', \ gene2go_table='genome.gene2go', tax_id=3702): """ 2008-09-24 turn gene_id into integer 2008-08-03 schema where tables about genes are from is renamed from 'sequence' to 'genome' 2008-02-02 get all the necessary info for genes. watch, chromosome here is varchar type (because of chromosome X, Y etc) """ sys.stderr.write("Getting gene_id2model and chr_id2gene_id_ls...") from annot.bin.codense.common import pg_1d_array2python_ls gene_id2model = {} chr_id2gene_id_ls = {} curs.execute("DECLARE gene_crs CURSOR FOR select e.gene_id, a.chromosome, e.start, e.stop, e.mrna_start, e.mrna_stop, e.cds_start, e.cds_stop, e.strand, g.gene_symbol, g.description, g.type_of_gene \ from %s e, %s a, %s g where e.gene_id=g.gene_id and e.genomic_gi=a.gi and e.tax_id=%s order by chromosome, start, stop"%\ (entrezgene_mapping_table, annot_assembly_table, gene_table, tax_id)) curs.execute("fetch 5000 from gene_crs") rows = curs.fetchall() while rows: for row in rows: #gene_id is integer. chromosome is varchar. gene_id, chromosome, start, stop, mrna_start, mrna_stop, cds_start, cds_stop, strand, symbol, description, type_of_gene = row gene_id = int(gene_id) #2008-09-24 if cds_start and cds_stop: if type(cds_start)!=list: cds_start = pg_1d_array2python_ls(cds_start, int) cds_stop = pg_1d_array2python_ls(cds_stop, int) else: cds_start = cds_stop = None if mrna_start and mrna_stop: if type(mrna_stop)!=list: mrna_start = pg_1d_array2python_ls(mrna_start, int) mrna_stop = pg_1d_array2python_ls(mrna_stop, int) else: mrna_start = mrna_stop = None if chromosome not in chr_id2gene_id_ls: chr_id2gene_id_ls[chromosome] = [] chr_id2gene_id_ls[chromosome].append(gene_id) if gene_id not in gene_id2model: gene_id2model[gene_id] = GeneModel(gene_id, chromosome, symbol, description, type_of_gene, \ start, stop, mrna_start, mrna_stop, cds_start, cds_stop, strand) curs.execute("fetch 5000 from gene_crs") rows = curs.fetchall() curs.execute("close gene_crs") sys.stderr.write("Done.\n") return gene_id2model, chr_id2gene_id_ls get_gene_id2model = classmethod(get_gene_id2model) def plot_one_gene(self, ax, gene_id, gene_id2model, chr_id2cumu_size, chr_id2size, chr_gap, y_value=1, gene_width=1.0): """ 2008-12-16 defunct. DrawSNPRegion.drawGeneModel() is used in on_button_draw_annotation_clicked() 2008-02-02 draw a single gene on the canvas, """ gene_model = gene_id2model.get(gene_id) if gene_model: c_start_ls = None c_end_ls = None if gene_model.cds_start!=None and gene_model.cds_stop!=None: c_start_ls = gene_model.cds_start c_end_ls = gene_model.cds_stop elif gene_model.mrna_start!=None and gene_model.mrna_stop!=None: c_start_ls = gene_model.mrna_start c_end_ls = gene_model.mrna_stop elif gene_model.start!=None and gene_model.stop!=None: c_start_ls = [gene_model.start] c_end_ls = [gene_model.stop] if c_start_ls and c_end_ls: chromosome = gene_model.chromosome this_chr_starting_pos_on_plot = chr_id2cumu_size[chromosome]-chr_id2size[chromosome]-chr_gap if gene_model.strand=="1": g_artist = Gene(c_start_ls, c_end_ls, y=y_value, x_offset=this_chr_starting_pos_on_plot, width=gene_width, alpha=0.3, facecolor='r', picker=True) elif gene_model.strand=="-1": #to draw opposite strand, 1st is to order c_start_ls and c_end_ls in descending order. 2nd is to swap c_start_ls and c_end_ls. #c_start_ls.reverse() #2008-02-04 it's already in descending order in db. #c_end_ls.reverse() #2008-02-04 it's already in descending order in db. g_artist = Gene(c_end_ls, c_start_ls, y=y_value, x_offset=this_chr_starting_pos_on_plot, width=gene_width, alpha=0.3, facecolor='r', picker=True) else: #no arrow g_artist = Gene(c_start_ls, c_end_ls, y=y_value, is_arrow=False, x_offset=this_chr_starting_pos_on_plot, width=gene_width, alpha=0.3, facecolor='r', picker=True) ax.add_artist(g_artist) artist_obj_id = id(g_artist) self.artist_obj_id2artist_gene_id_ls[artist_obj_id] = [g_artist, gene_id] self.gene_id2artist_object_id[gene_id] = artist_obj_id def on_button_draw_annotation_clicked(self, widget, data=None): """ 2008-12-16 use DrawSNPRegion.drawGeneModel() to draw gene models 2008-02-02 """ if not self.chr_id2size: sys.stderr.write("No genome-wide pvalue plot has been drawn yet. Do it first!\n") return #if not self.gene_id2model: # self.gene_id2model, self.chr_id2gene_id_ls = self.get_gene_id2model(self.postgres_curs, tax_id=3702) if not self.gene_annotation: self.db_connect() xlim = self.axe_gene_model.get_xlim() left_chr, left_pos = get_chr_pos_from_x_axis_pos(xlim[0], self.chr_gap, self.chr_id2cumu_size, self.chr_id_ls) right_chr, right_pos = get_chr_pos_from_x_axis_pos(xlim[1], self.chr_gap, self.chr_id2cumu_size, self.chr_id_ls) #fake a snps_within_this_region for drawGeneModel() snps_within_this_region = PassingData(chr_pos_ls=[[left_chr, left_pos],[right_chr, right_pos]]) base_y_value = 1 gene_width = 0.8 gene_position_cycle = 5 return_data = DrawSNPRegion.drawGeneModel(self.axe_gene_model, snps_within_this_region, self.gene_annotation, candidate_gene_set=None,\ gene_width=gene_width, gene_position_cycle=gene_position_cycle, base_y_value=base_y_value, \ gene_box_text_gap=20, label_gene=0, rotate_xy=False,\ chr_id2cumu_size=self.chr_id2cumu_size, chr_id2size=self.chr_id2size, chr_gap=self.chr_gap,\ artist_obj_id2artist_gene_id_ls=self.artist_obj_id2artist_gene_id_ls, \ gene_id2artist_object_id=self.gene_id2artist_object_id, drawGeneOnTheBoundary=False) #set drawGeneOnTheBoundary to False because later adding text to these genes would corrupt the running program. self.axe_gene_model.set_ylim([base_y_value-gene_width, gene_position_cycle+gene_width*2]) """ for gene_id in self.chr_id2gene_id_ls[left_chr]: gene_model = self.gene_id2model[gene_id] if gene_model.start!=None and gene_model.stop!=None and gene_model.stop>left_pos and gene_id not in self.gene_id2artist_object_id: if left_chr==right_chr: #same chromosome if gene_model.start>right_pos: #totally out of range, skip it continue y_value = len(self.gene_id2artist_object_id)%4 #cycling through the y position to avoid clogging self.plot_one_gene(self.ax, gene_id, self.gene_id2model, self.chr_id2cumu_size, self.chr_id2size, self.chr_gap, y_value=-1-y_value, gene_width=self.gene_width) if left_chr!=right_chr: for gene_id in self.chr_id2gene_id_ls[right_chr]: gene_model = self.gene_id2model[gene_id] if gene_model.start!=None and gene_model.stop!=None and gene_model.start<right_pos and gene_id not in self.gene_id2artist_object_id: y_value = len(self.gene_id2artist_object_id)%4 #cycling through the y position to avoid clogging self.plot_one_gene(self.ax, gene_id, self.gene_id2model, self.chr_id2cumu_size, self.chr_id2size, self.chr_gap, y_value=-1-y_value, gene_width=self.gene_width) """ self.canvas_matplotlib.draw() def on_imagemenuitem_preferences_activate(self, event, data=None): """ 2008-02-04 """ self.dialog_preferences.show_all() def on_button_dialog_preferences_ok_clicked(self, widget, data=None): """ 2008-02-04 change some preferences """ self.dialog_preferences.hide() if self.checkbutton_debug.get_active(): self.debug = 1 else: self.debug = 0 if self.checkbutton_stderr.get_active(): sys.stderr = self.dummy_err else: sys.stderr = sys.__stderr__ if self.checkbutton_stdout.get_active(): sys.stdout = self.dummy_out else: sys.stdout = sys.__stdout__ if self.checkbutton_draw_gene_symbol.get_active(): self.draw_gene_symbol_when_clicked = 1 else: self.draw_gene_symbol_when_clicked = 0 self.gene_width = float(self.entry_gene_width.get_text()) def on_button_dialog_preferences_cancel_clicked(self, widget, data=None): """ 2008-02-04 don't change any preferences """ self.dialog_preferences.hide() def on_imagemenuitem_about_activate(self, widget): """ 2008-02-04 """ self.aboutdialog1.show_all() def on_imagemenuitem_cleanup_output_activate(self, widget): """ 2008-02-04 clean up output buffer """ self.textbuffer_output.set_text('') def on_checkbutton_debug_toggled(self, widget): """ 2008-05-28 """ if self.checkbutton_debug.get_active(): self.debug = 1 else: self.debug = 0 def on_checkbutton_stdout_toggled(self, widget): """ 2008-05-28 """ if self.checkbutton_stdout.get_active(): sys.stdout = self.dummy_out else: sys.stdout = sys.__stdout__ def on_checkbutton_stderr_toggled(self, widget): """ 2008-05-28 """ if self.checkbutton_stderr.get_active(): sys.stderr = self.dummy_err else: sys.stderr = sys.__stderr__ def on_checkbutton_draw_gene_symbol_toggled(self, widget): """ 2008-05-28 """ if self.checkbutton_draw_gene_symbol.get_active(): self.draw_gene_symbol_when_clicked = 1 else: self.draw_gene_symbol_when_clicked = 0 def on_entry_gene_width_changed(self, widget): """ 2008-05-28 """ self.gene_width = float(self.entry_gene_width.get_text()) def on_filechooserbutton_gene_annot_file_set(self, widget): """ 2008-12-16 """ self.entry_gene_annotation_picklef.set_text(self.filechooserbutton_gene_annot.get_filename()) def on_button_draw_gene_list_bars_clicked(self, widget): """ 2008-12-16 draw vertical spans to denote the locations of genes from a candidate list """ if self.db is None: self.db_connect() if not self.chr_id2size: sys.stderr.write("No genome-wide pvalue plot has been drawn yet. Do it first!\n") return entry_gene_list_id = self.xml.get_widget("entry_gene_list_id") list_type_id = entry_gene_list_id.get_text() comboboxentry_bar_color = self.xml.get_widget("comboboxentry_bar_color") bar_color = comboboxentry_bar_color.get_active_text() if not bar_color: #default is black bar_color = 'k' if list_type_id: list_type_id = int(list_type_id) self.candidate_gene_set = GeneListRankTest.dealWithCandidateGeneList(list_type_id, return_set=True) for gene_id in self.candidate_gene_set: gene_model = self.gene_annotation.gene_id2model[gene_id] if gene_id in self.gene_id2vspan_obj_id: artist_obj_id = self.gene_id2vspan_obj_id[gene_id] artist = self.artist_obj_id2artist_gene_id_ls[artist_obj_id][0] if artist.get_edgecolor()!=bar_color: artist.set_edgecolor(bar_color) if artist.get_facecolor()!=bar_color: artist.set_facecolor(bar_color) #artist.remove() else: this_chr_starting_pos_on_plot = self.chr_id2cumu_size[gene_model.chromosome]-\ self.chr_id2size[gene_model.chromosome]-self.chr_gap xmin = this_chr_starting_pos_on_plot + gene_model.start xmax = this_chr_starting_pos_on_plot + gene_model.stop artist = self.ax.axvspan(xmin, xmax, edgecolor=bar_color, facecolor=bar_color, alpha=0.3, picker=6) artist_obj_id = id(artist) self.artist_obj_id2artist_gene_id_ls[artist_obj_id] = [artist, gene_id] self.gene_id2vspan_obj_id[gene_id] = artist_obj_id self.canvas_matplotlib.draw() def on_button_adjust_gene_axis_clicked(self, widget): """ 2008-12-19 sometimes after zoom-in/out, axe_gene_model loses track of its y-range and the gene models in it float into ax. this function would bring the y-range of axe_gene_model into normal range. """ base_y_value = 1 gene_width = 0.8 gene_position_cycle = 5 self.axe_gene_model.set_ylim([base_y_value-gene_width, gene_position_cycle+gene_width*2]) self.canvas_matplotlib.draw()
class SensorWindow(object): def __init__(self, mainThread, gladefile='sensor_window.glade'): self.builder = gtk.Builder() self.builder.add_from_file(gladefile) self.builder.connect_signals(self) self._stopped = False self.mainThread = mainThread self.fig = plt.figure() self.numLines = 1 # lines plot self.ax = self.fig.add_subplot(111) self.ax.set_xlabel('Time') self.ax.set_ylabel('Power') self.ax.xaxis.set_animated(True) self.ax.yaxis.set_animated(True) self.ax.set_title('Light Intensity') self.ax.grid(True) self.start = time.time() self.background1 = None self.prev_time = self.start self.prev_pixel_offset = 0 self.x0 = 0 self.value = [0] * self.numLines self.ax.set_ylim(-1, 256) self.lines = [] for i in range(self.numLines): line, = self.ax.plot([], [], animated=True, lw=2) self.lines.append(line) self.canvas = FigureCanvas(self.fig) self.graphview = self.builder.get_object("box2") self.graphview.pack_start(self.canvas) self.graphview.reorder_child(self.canvas, 0) self.img = self.builder.get_object("image1") self.img.set_from_file("off.svg") self.lamp = False self.canvas.show() gobject.idle_add(self.update_line) self.canvas.mpl_connect('draw_event', self.on_draw) self.barpath = [] def close_window(self, obj): print "closing window" self.builder.get_object("window1").destroy() def destroy_callback(self, obj): print "destroying window" self.mainThread.stop() self._stopped = True def close_from_mainthread(self): print "close from mainthread" self.builder.get_object("window1").destroy() def toggle_lamp(self): print "toggle lamp!!" self.img = self.builder.get_object("image1") if (self.lamp): self.lamp = False self.img.set_from_file("off.svg") else: self.lamp = True self.img.set_from_file("on.svg") def update_line(self, *args): if self._stopped: self.destroy_callback(None) return False if self.background1 is None: return True cur_time = time.time() pixel_offset = int((cur_time - self.start) * 40.) dx_pixel = pixel_offset - self.prev_pixel_offset self.prev_pixel_offset = pixel_offset dx_data = self.get_dx_data(dx_pixel) #cur_time - self.prev_time) x0 = self.x0 self.x0 += dx_data self.prev_time = cur_time self.ax.set_xlim(self.x0 - 2, self.x0 + 0.1) # restore background which will plot lines from previous plots self.restore_background_shifted(dx_pixel) #x0, self.x0) # now plot line segment within [x0, x0+dx_data], # Note that we're only plotting a line between [x0, x0+dx_data]. xx = np.array([x0, self.x0]) for i in range(len(self.lines)): line = self.lines[i] line.set_xdata(xx) # the for loop below could be improved by using collection. line.set_ydata(np.array([self.value[i], self.value[i]])) self.ax.draw_artist(line) self.background2 = self.canvas.copy_from_bbox(self.get_bg_bbox()) self.ax.draw_artist(self.ax.xaxis) self.ax.draw_artist(self.ax.yaxis) self.canvas.blit(self.ax.get_figure().bbox) return True def get_dx_data(self, dx_pixel): tp = self.ax.transData.inverted().transform_point x0, y0 = tp((0, 0)) x1, y1 = tp((dx_pixel, 0)) return (x1 - x0) def get_bg_bbox(self): return self.ax.bbox.padded(-3) def save_bg(self): self.background1 = self.canvas.copy_from_bbox( self.ax.get_figure().bbox) self.background2 = self.canvas.copy_from_bbox(self.get_bg_bbox()) def on_draw(self, *args): self.save_bg() return False def restore_background_shifted(self, dx_pixel): """ restore bacground shifted by dx in data coordinate. This only works if the data coordinate system is linear. """ # restore the clean slate background self.canvas.restore_region(self.background1) # restore subregion (x1+dx, y1, x2, y2) of the second bg # in a offset position (x1-dx, y1) x1, y1, x2, y2 = self.background2.get_extents() self.canvas.restore_region(self.background2, bbox=(x1 + dx_pixel, y1, x2, y2), xy=(x1 - dx_pixel, y1)) return dx_pixel def update(self, data): if type(data) == ListType: assert (len(self.lines) == len(data)) self.value = data else: assert (len(self.lines) == 1) self.value = [data]
class Figure(gtk.VBox): def __init__(self): print "Starting up SamFigure!" gtk.VBox.__init__(self) self.figure = MPLFigure() self.canvas = FigureCanvas(self.figure) self.canvas.mpl_connect("button_press_event", self.on_click) self.ax = self.figure.add_subplot(111) self.ax2 = None self.mode = TWODPLOT self.new_data() self.xlabel = '' self.y1label = '' self.y2label = '' self.xsize = 0 self.ysize = 0 self.packed = False self.count_since_replot=0 self.set_colors() def on_click(self,event): # If left button, if event.button==1: # screen coordinates of click xclick,yclick= event.x, event.y top_ax=event.inaxes if top_ax is None: return # display coordinates of nearest point in ax data1=self.ax.transData.transform(\ zip(self.listing.getX(),self.listing.getY(1))) distances1=\ [(x-xclick)**2+(y-yclick)**2 \ for (x,y) in data1] ind_sel1=numpy.argmin(distances1) dist1 = distances1[ind_sel1] xsel,ysel= data1[ind_sel1] label_ax=self.ax label_color='b' # if DUAL, then also check ax2 for nearer points if self.mode==DUALTWODPLOT: data2=self.ax2.transData.transform(\ zip(self.listing.getX(),self.listing.getY(2))) distances2=\ [(x-xclick)**2+(y-yclick)**2 \ for (x,y) in data2] ind_sel2=numpy.argmin(distances2) dist2 = distances2[ind_sel2] if dist2<dist1: xsel,ysel= data2[ind_sel2] label_color='g' label_ax=self.ax2 # Clear off old labels if hasattr(self,"label_text"): self.label_text.remove() self.label_point.remove() del(self.label_text) # Coordinates to show ( data coordinates of the selected axes) xlabel,ylabel=label_ax.transData.inverted().transform((xsel,ysel)) # Coordinates to place label (on top set of axes) xloc,yloc=top_ax.transData.inverted().transform((xsel,ysel)) # Label the point if (xloc > sum(self.ax.get_xlim())/2): h_align='right' else: h_align='left' self.label_text=\ top_ax.text(xloc,yloc,'({0:.3g},{1:.3g})'\ .format(xlabel,ylabel),\ backgroundcolor='white', color=label_color,\ verticalalignment='bottom', horizontalalignment=h_align,\ bbox={'facecolor': 'white', 'boxstyle': 'round'},zorder=100 ) self.label_point,=\ top_ax.plot(xloc,yloc,'ro',\ zorder=self.label_text.get_zorder()+1) self.repaint() # Otherwise, just clear off old labels else: self.label_text.remove() self.label_point.remove() del(self.label_text) self.repaint() def replot(self): if self.mode == TWODPLOT: self.ax.clear() self.ax.plot(self.listing.getX(),self.listing.getY(1),self.color1+'.-') self.count_since_replot=0 elif self.mode == DUALTWODPLOT: self.ax.clear() self.ax2.clear() self.ax.plot(self.listing.getX(),self.listing.getY(1),self.color1+'.-') self.ax2.plot(self.listing.getX(),self.listing.getY(2),self.color2+'.-') self.count_since_replot=0 def show(self): try: if not self.packed: self.pack_start(self.canvas, expand=True) toolbar = NavigationToolbar(self.canvas, self.get_parent_window()) next = 8 button = gtk.Button('Lin y') button.show() button2 = gtk.Button('Lin x') button2.show() # linear/log def clicked(button): self.adjust_axis_margins() self.set_axis_labels() self.color_labels() self.canvas.draw_idle() self.canvas.show() if self.ax.get_yscale() == 'log': button.set_label('Lin y') self.ax.set_yscale('linear') else: button.set_label('Log y') self.ax.set_yscale('log') self.show() def clicked2(button): self.adjust_axis_margins() self.set_axis_labels() self.color_labels() self.canvas.draw_idle() self.canvas.show() if self.ax.get_xscale() == 'log': button.set_label('Lin x') self.ax.set_xscale('linear') else: button.set_label('Log x') self.ax.set_xscale('log') self.show() button.connect('clicked', clicked) button2.connect('clicked', clicked2) toolitem=gtk.ToolItem() toolitem.show() toolitem.add(button) toolbar.insert(toolitem, next) next +=1 toolitem2=gtk.ToolItem() toolitem2.show() toolitem2.add(button2) toolbar.insert(toolitem2, next) self.pack_start(toolbar, expand=False) self.packed = True super(Figure, self).show() except Exception, e: print 'Exception: ', e raise
class DataMatrixGuiXYProbe(gtk.Window): """ 2009-3-13 migrated from QCVisualize.py. now become a standalone program and able to read data from a file and plot ... QCVisualize.py inherits from here 2008-02-05 embed it into a bigger gnome app, add more buttons, and change the __init__() 2008-01-01 class to visualize the results from QualityControl.py """ def __init__(self, plot_title='', id_is_strain=1, header=None, strain_acc_list=None, category_list=None, data_matrix=None): """ 2008-01-10 use a paned window to wrap the scrolledwindow and the canvas so that the relative size of canvas to the scrolledwindow could be adjusted by the user. """ prog = gnome.program_init('DataMatrixGuiXYProbe', '0.1') #this must be called before any initialization for gnome app program_path = os.path.dirname(__init__.__file__) #sys.argv[0]) xml = gtk.glade.XML(os.path.join(program_path, 'DataMatrixGuiXYProbe.glade')) xml.signal_autoconnect(self) self.app1 = xml.get_widget("app1") self.app1.connect("delete_event", gtk.main_quit) self.app1.set_default_size(800, 1000) self.app1.set_title(plot_title) self.plot_title = plot_title self.id_is_strain = id_is_strain self.header = header self.strain_acc_list = strain_acc_list self.category_list = category_list self.data_matrix = data_matrix self.column_types = None self.column_header = None self.column_editable_flag_ls = None self.list_2d = None self.column_types = None self.list_2d = None self.column_header = None self.editable_flag_ls = None self.vbox1 = xml.get_widget("vbox1") self.treeview_matrix = xml.get_widget("treeview_matrix") # matplotlib stuff fig = Figure(figsize=(8,8)) self.canvas = FigureCanvas(fig) # a gtk.DrawingArea self._idClick = self.canvas.mpl_connect('button_press_event', self.onUserClickCanvas) self.vpaned1 = xml.get_widget("vpaned1") self.vpaned1.add2(self.canvas) #vbox.pack_start(self.canvas, True, True) self.ax = fig.add_subplot(111) self.treeview_matrix.connect('row-activated', self.plot_row) toolbar = NavigationToolbar(self.canvas, self.app1) self.vbox1.pack_start(toolbar, False, False) self.checkbutton_label_dot = xml.get_widget('checkbutton_label_dot') self.entry_dot_label_column = xml.get_widget('entry_dot_label_column') self.entry_x_na = xml.get_widget('entry_x_na') self.entry_y_na = xml.get_widget('entry_y_na') self.entry_multiply_x = xml.get_widget('entry_multiply_x') self.entry_multiply_y = xml.get_widget('entry_multiply_y') self.entry_add_x = xml.get_widget('entry_add_x') self.entry_add_y = xml.get_widget('entry_add_y') self.entry_x_error = xml.get_widget("entry_x_error") self.entry_y_error = xml.get_widget("entry_y_error") self.checkbutton_logX = xml.get_widget('checkbutton_logX') #2014.06.09 self.checkbutton_logY = xml.get_widget('checkbutton_logY') self.entry_x_column = xml.get_widget('entry_x_column') self.entry_y_column = xml.get_widget('entry_y_column') #self.checkbutton_histLogX = xml.get_widget('checkbutton_histLogX') #2014.06.09 #self.checkbutton_histLogY = xml.get_widget('checkbutton_histLogY') self.entry_hist_column = xml.get_widget('entry_hist_column') self.entry_no_of_bins = xml.get_widget('entry_no_of_bins') #2009-5-20 self.entry_plot_title = xml.get_widget('entry_plot_title') self.entry_plot_title.set_text(self.plot_title) self.filechooserdialog_save = xml.get_widget("filechooserdialog_save") self.filechooserdialog_save.connect("delete_event", yh_gnome.subwindow_hide) self.entry_sampling_probability = xml.get_widget("entry_sampling_probability") self.filechooserdialog_open = xml.get_widget("filechooserdialog_open") self.filechooserdialog_open.connect("delete_event", yh_gnome.subwindow_hide) self.app1_appbar1 = xml.get_widget('app1_appbar1') self.app1_appbar1.push('Status Message.') #import gnome.ui has to be executed. self.treeview_matrix.connect('cursor-changed', self.update_no_of_selected, self.app1_appbar1) self.app1.show_all() self.xValuePreProcessor = None self.yValuePreProcessor = None self.x_error_column_index = None self.y_error_column_index = None #self.add_events(gdk.BUTTON_PRESS_MASK|gdk.KEY_PRESS_MASK|gdk.KEY_RELEASE_MASK) def onUserClickCanvas(self, event): """ 2009-3-13 use (x_lim[1]-x_lim[0])/200. as the resolution for a dot to be called identical to a data point. similar for the y_data 2009-3-13 deal with checkbutton_label_dot, entry_dot_label_column, entry_x_column, entry_y_column 2008-01-01 derived from on_click_row() of QualityControl.py reaction when user clicked in the plot """ # get the x and y coords, flip y from top to bottom x, y = event.x, event.y to_label_dot = self.checkbutton_label_dot.get_active() dot_label_column = int(self.entry_dot_label_column.get_text()) x_column = int(self.entry_x_column.get_text()) y_column = int(self.entry_y_column.get_text()) x_lim = self.ax.get_xlim() x_grain_size = (x_lim[1]-x_lim[0])/200. y_lim = self.ax.get_ylim() y_grain_size = (y_lim[1]-y_lim[0])/200. if event.button==1: if event.inaxes is not None: print 'data coords', event.xdata, event.ydata if self.list_2d is None: return for row in self.list_2d: if row[x_column] and row[y_column]: #not empty try: x_data = float(row[x_column]) y_data = float(row[y_column]) x = self.processDataValue(x_data, self.xValuePreProcessor) if x is None: continue y = self.processDataValue(y_data, self.yValuePreProcessor) if y is None: continue if abs(x-event.xdata)<x_grain_size and abs(y-event.ydata)<y_grain_size: info = row[dot_label_column] if to_label_dot: self.ax.text(event.xdata, event.ydata, info, size=8) self.canvas.draw() sys.stderr.write("%s: %s, %s: %s, raw xy=(%s, %s), scaled xy=(%s,%s), info: %s.\n"%\ (self.column_header[0], row[0], self.column_header[1], row[1], row[x_column], row[y_column], x,y, info)) except: sys.stderr.write("Column %s, %s of row (%s), could not be converted to float. skip.\n"%\ (x_column, y_column, repr(row))) def setUserDataPreprocessingFlags(self): """ 2014.07.25 """ self.xValuePreProcessor = ValuePreProcessor(na = self.entry_x_na.get_text()) self.yValuePreProcessor = ValuePreProcessor(na = self.entry_y_na.get_text()) if self.entry_multiply_x.get_text(): self.xValuePreProcessor.scalar = float(self.entry_multiply_x.get_text()) if self.entry_multiply_y.get_text(): self.yValuePreProcessor.scalar = float(self.entry_multiply_y.get_text()) if self.entry_add_x.get_text(): self.xValuePreProcessor.addition = float(self.entry_add_x.get_text()) if self.entry_add_y.get_text(): self.yValuePreProcessor.addition = float(self.entry_add_y.get_text()) if self.entry_x_error.get_text(): self.xValuePreProcessor.errorColumnIndex = int(self.entry_x_error.get_text()) if self.entry_y_error.get_text(): self.yValuePreProcessor.errorColumnIndex = int(self.entry_y_error.get_text()) if self.checkbutton_logX.get_active(): self.xValuePreProcessor.logScale = True if self.checkbutton_logY.get_active(): self.yValuePreProcessor.logScale = True def processDataValue(self, value=None, valuePreProcessor=None): """ 2014.07.31 """ if valuePreProcessor.na is not None and (value==valuePreProcessor.na or float(value)==float(valuePreProcessor.na)): return None value = float(value) if valuePreProcessor.scalar is not None: value = value*valuePreProcessor.scalar if valuePreProcessor.addition is not None: value = value + valuePreProcessor.addition return value def decorateAxisLabel(self, label=None, valuePreProcessor=None): """ 2014.07.31 """ if valuePreProcessor.scalar is not None: label = "%s*%s"%(valuePreProcessor.scalar, label) if valuePreProcessor.addition: label = "%s+%s"%(label, valuePreProcessor.addition) return label def plotXY(self, ax, canvas, liststore, plot_title='', chosen_index_ls=[]): """ 2015.01.28 add summary stats to title 2014.04.29 add error bars 2009-3-13 rename plot_NA_mismatch_rate to plotXY() 2008-02-05 chosen_index => chosen_index_ls 2007-12-14 """ x_column = int(self.entry_x_column.get_text()) y_column = int(self.entry_y_column.get_text()) self.setUserDataPreprocessingFlags() plot_title = self.entry_plot_title.get_text() min_x = 1 min_y = 1 max_x = 0 max_y = 0 x_ls = [] x_error_ls = [] y_ls = [] y_error_ls = [] x_chosen_ls = [] x_chosen_error_ls = [] y_chosen_ls = [] y_chosen_error_ls = [] chosen_index_set = set(chosen_index_ls) for i in range(len(liststore)): row = liststore[i] x = row[x_column] y = row[y_column] if not x or not y: #2013.07.12 skip if empty cells continue x = self.processDataValue(x, self.xValuePreProcessor) if x is None: continue y = self.processDataValue(y, self.yValuePreProcessor) if y is None: continue if self.xValuePreProcessor.errorColumnIndex is not None: x_error = row[self.xValuePreProcessor.errorColumnIndex] else: x_error = 0 if self.yValuePreProcessor.errorColumnIndex is not None: y_error = row[self.yValuePreProcessor.errorColumnIndex] else: y_error = 0 if x<min_x: min_x = x if x>max_x: max_x = x if y<min_y: min_y = y if y>max_y: max_y = y if i in chosen_index_set: x_chosen_ls.append(x) y_chosen_ls.append(y) x_chosen_error_ls.append(x_error) y_chosen_error_ls.append(y_error) else: x_ls.append(x) y_ls.append(y) x_error_ls.append(x_error) y_error_ls.append(y_error) ax.clear() if self.xValuePreProcessor.logScale: ax.set_xscale('log') if self.yValuePreProcessor.logScale: ax.set_yscale('log') if self.x_error_column_index is not None and self.y_error_column_index is not None: ax.errorbar(x_ls, y_ls, xerr=x_error_ls, yerr=y_error_ls, ecolor='g', fmt='o') else: ax.plot(x_ls, y_ls, '.') """ #diagonal line give a rough feeling about the notion, more NA, worse calling diagonal_start = min(min_x, min_y)-0.1 diagonal_end = max(max_x, max_x)+0.1 ax.plot([diagonal_start, diagonal_end],[diagonal_start, diagonal_end]) """ if x_chosen_ls and y_chosen_ls: #highlight titleWithStats = "Highlighted data\n" + yh_matplotlib.constructTitleFromTwoDataSummaryStat(x_chosen_ls, y_chosen_ls) ax.plot(x_chosen_ls, y_chosen_ls, '.', c='r') if self.x_error_column_index is not None and self.y_error_column_index is not None: ax.errorbar(x_chosen_ls, y_chosen_ls, xerr=x_chosen_error_ls, yerr=y_chosen_error_ls, ecolor='r', color='r', fmt='o') else: #take all data titleWithStats = yh_matplotlib.constructTitleFromTwoDataSummaryStat(x_ls+x_chosen_ls, y_ls+y_chosen_ls) if plot_title: ax.set_title("%s %s"%(plot_title, titleWithStats)) else: ax.set_title(titleWithStats) xlabel = "(%s)"%self.column_header[x_column] xlabel = self.decorateAxisLabel(xlabel, self.xValuePreProcessor) ax.set_xlabel(xlabel) ylabel = "(%s)"%self.column_header[y_column] ylabel = self.decorateAxisLabel(ylabel, self.yValuePreProcessor) ax.set_ylabel(ylabel) canvas.draw() def plot_row(self, treeview, path, view_column): if self._idClick==None: self._idClick = self.canvas.mpl_connect('button_press_event', self.onUserClickCanvas) self.plotXY(self.ax, self.canvas, self.liststore, self.plot_title, path) def setupColumns(self, treeview): """ 2009-3-13 """ if not getattr(self, 'column_header', None): sys.stderr.write("Nothing in columns yet.\n") return self.liststore = gtk.ListStore(*self.column_types) #self.add_columns(self.treeview_matrix) yh_gnome.create_columns(self.treeview_matrix, self.column_header, self.editable_flag_ls, self.liststore) yh_gnome.fill_treeview(self.treeview_matrix, self.liststore, self.list_2d, reorderable=True) self.treeselection = self.treeview_matrix.get_selection() def on_button_PlotXY_clicked(self, widget, data=None): """ 2008-02-12 to update the no_of_selected rows (have to double click a row to change a cursor if it's multiple selection) 2008-02-05 """ if self._idClick==None: self._idClick = self.canvas.mpl_connect('button_press_event', self.onUserClickCanvas) pathlist_strains1 = [] self.treeselection.selected_foreach(yh_gnome.foreach_cb, pathlist_strains1) index_ls = [] for path in pathlist_strains1: index_ls.append(path[0]) self.app1_appbar1.push("%s rows selected."%len(pathlist_strains1)) self.plotXY(self.ax, self.canvas, self.liststore, self.plot_title, index_ls) def on_button_save_clicked(self, widget, data=None): """ 2008-02-05 """ self.filechooserdialog_save.show_all() def on_button_filechooserdialog_cancel_ok_clicked(self, widget, data=None): """ 2008-02-05 """ self.filechooserdialog_save.hide() def on_button_filechooserdialog_save_ok_clicked(self, widget, data=None): """ 2008-02-12 to update the no_of_selected rows (have to double click a row to change a cursor if it's multiple selection) 2008-02-05 """ output_fname = self.filechooserdialog_save.get_filename() self.filechooserdialog_save.hide() pathlist_strains1 = [] self.treeselection.selected_foreach(yh_gnome.foreach_cb, pathlist_strains1) self.app1_appbar1.push("%s rows selected."%len(pathlist_strains1)) if self.header and self.strain_acc_list and self.category_list and self.data_matrix: selected_index_set = set() for path in pathlist_strains1: row = self.liststore[path[0]] id = row[0] index_in_data_matrix = row[-1] selected_index_set.add(index_in_data_matrix) if self.id_is_strain: id = id[1:-1].split(',') #id is a tuple of (ecotypeid,duplicate) self.strain_acc_list[index_in_data_matrix] = id[0].strip() #remove extra space self.category_list[index_in_data_matrix] = id[1].strip() #else: # self.header[index_in_data_matrix+2] = id FilterStrainSNPMatrix_instance = FilterStrainSNPMatrix() if self.id_is_strain: rows_to_be_tossed_out = set(range(len(self.strain_acc_list))) - selected_index_set FilterStrainSNPMatrix_instance.write_data_matrix(self.data_matrix, output_fname, self.header, self.strain_acc_list, self.category_list,\ rows_to_be_tossed_out, cols_to_be_tossed_out=set(), nt_alphabet=0) else: cols_to_be_tossed_out = set(range(len(self.header)-2)) - selected_index_set FilterStrainSNPMatrix_instance.write_data_matrix(self.data_matrix, output_fname, self.header, self.strain_acc_list, self.category_list,\ rows_to_be_tossed_out=set(), cols_to_be_tossed_out=cols_to_be_tossed_out, nt_alphabet=0) def show_all(self): """ 2008-02-05 preserve the old interface. in order not to change anything in plot_col_NA_mismatch_rate() and plot_row_NA_mismatch_rate() of QualityControl.py """ self.app1.show_all() def on_button_PlotHistogram_clicked(self, widget, data=None): """ 2015.01.28 add summary stats to title 2009-5-20 get the number of bins from entry_no_of_bins 2009-3-13 draw histogram of specific hist_column 2008-02-06 """ if not getattr(self, 'column_header', None): sys.stderr.write("Nothing in columns yet.\n") return self.setUserDataPreprocessingFlags() self.ax.clear() self.canvas.mpl_disconnect(self._idClick) #drop the signal handler self._idClick = None #reset the _idClick hist_ls = [] hist_column = int(self.entry_hist_column.get_text()) for i in range(len(self.liststore)): x = self.liststore[i][hist_column] if not x: continue x = self.processDataValue(x, self.xValuePreProcessor) if x is None: continue if self.xValuePreProcessor.logScale: if x>0: x = math.log10(x) else: sys.stderr.write("x value %s, not good for log10.\n"%(x)) continue hist_ls.append(x) title = "%s %s %s"%(self.plot_title, self.column_header[hist_column], yh_matplotlib.constructTitleFromDataSummaryStat(hist_ls)) self.ax.set_title(title); #"Histogram of %s %s"%(self.plot_title, self.column_header[hist_column])) no_of_bins = int(self.entry_no_of_bins.get_text()) #if self.x_logScale: # self.ax.set_xscale('log') if self.yValuePreProcessor.logScale: self.ax.set_yscale('log') xlabel = "(%s)"%self.column_header[hist_column] xlabel = self.decorateAxisLabel(xlabel, self.xValuePreProcessor) if self.xValuePreProcessor.logScale: xlabel = "log10(%s)"%(xlabel) self.ax.set_xlabel(xlabel) self.ax.hist(hist_ls, no_of_bins) self.canvas.draw() def update_no_of_selected(self, treeview, app1_appbar1): """ 2008-02-12 to update the no_of_selected rows (have to double click a row to change a cursor if it's multiple selection) """ pathlist_strains1 = [] self.treeselection.selected_foreach(yh_gnome.foreach_cb, pathlist_strains1) app1_appbar1.push("%s rows selected."%len(pathlist_strains1)) return True def readInDataToPlot(self, input_fname, sampling_probability=1.0): """ 2015.01.23 added argument sampling_probability to sub-sample data 2013.07.11 use MatrixFile to read in the file 2009-5-20 add the column index into the column header for easy picking 2009-3-13 wrap the float conversion part into try...except to report what goes wrong 2009-3-13 """ if sampling_probability>1 or sampling_probability<0: sampling_probability=1.0 reader = MatrixFile(inputFname=input_fname) self.column_header=reader.next() for i in range(len(self.column_header)): self.column_header[i] = '%s %s'%(i, self.column_header[i]) no_of_cols = len(self.column_header) self.column_types = [str]*2 + [float]*(no_of_cols-2) self.column_editable_flag_ls = [True, True] + [False]*(no_of_cols-2) self.list_2d = [] for row in reader: if sampling_probability>0 and sampling_probability<1: if random.random()>sampling_probability: #skip continue float_part = row[2:] try: float_part = map(float, float_part) except: sys.stderr.write('Except type: %s\n'%repr(sys.exc_info())) traceback.print_exc() new_row = row[:2]+float_part self.list_2d.append(new_row) reader.close() self.setupColumns(self.treeview_matrix) #update status to reflect the input filename self.app1.set_title(os.path.basename(input_fname)) self.app1_appbar1.push(input_fname) self.plotXY(self.ax, self.canvas, self.liststore, self.plot_title) def readInRawMatrixData(self, input_fname): """ 2009-3-13 """ delimiter = figureOutDelimiter(input_fname) self.header, self.strain_acc_list, self.category_list, self.data_matrix = read_data(input_fname, delimiter=delimiter) def on_imagemenuitem_open_activate(self, widget, data=None): """ 2009-3-13 """ self.filechooserdialog_open.show_all() def on_button_fileopen_cancel_clicked(self, widget, data=None): """ 2015.01.23 """ self.filechooserdialog_open.hide() def on_button_fileopen_ok_clicked(self, widget, data=None): """ 2009-3-13 """ input_fname = self.filechooserdialog_open.get_filename() sampling_probability = float(self.entry_sampling_probability.get_text()) self.filechooserdialog_open.hide() self.readInDataToPlot(input_fname, sampling_probability) def on_entry_plot_title_change(self, widget, data=None): """ 2009-3-13 upon any change in the entry_plot_title """ self.plot_title = self.entry_plot_title.get_text()
def __init__(self, cube, parent_window, cmap=None): gtk.VBox.__init__(self, False) self.cube = cube self._x, self._y, self._z = 0,0,0 # Coordinates of our current view in the cube. Read/write via the .x .y and .z properties self.last_drawn_x,self.last_drawn_y, self.last_drawn_z = 0,0,0 # what the coordinates were last time we drew fig = matplotlib.figure.Figure() self.fig = fig # Save a reference to the figure self.axes = fig.add_subplot(111) if cmap is None: # Use the default color map: #cmap = "spectral" cmap = CubeViewWidget.default_cmap self.imgplot = self.axes.imshow(cube.data[:,:,self._z].transpose(1,0), cmap=cmap,vmin=0, vmax=np.nanmax(cube.data)) self._colorbar = fig.colorbar(self.imgplot) # Add a color scale at the right-hand side self.axes.set_xlabel(u"Right Ascension \u03b1") self.axes.xaxis.set_major_formatter(self._AxisFormatter(self.cube)) self.axes.set_ylabel(u"Declination \u03b4") self.axes.yaxis.set_major_formatter(self._AxisFormatter(self.cube)) self.axes.set_ylim(0,cube.data.shape[1]) self._imgplot_highlight = None # An imshow plot of a highlight mask, if any self._highlight_mask = None self.xline = self.axes.axvline(x=self._x, linewidth=4, color="white", alpha=0.5) self.yline = self.axes.axhline(y=self._y, linewidth=4, color="white", alpha=0.5) canvas = FigureCanvasGTKAgg(fig) # a gtk.DrawingArea self.pack_start(canvas) # The toolbar: self.pack_start(gtk.HSeparator(), False,False) self.toolbar = self._NavigationToolbar(cube, canvas, parent_window) # parent_window is needed for the "Save image..." file chooser dialog self.toolbar.remove(self.toolbar.get_nth_item(6)) # Remove the "Configure subplots" button which causes rendering issues if used self.pack_start(self.toolbar, False, False) canvas.mpl_connect('button_press_event', self._figure_mousedown) canvas.mpl_connect('button_release_event', self._figure_mouseup) canvas.mpl_connect('motion_notify_event', self._figure_mousemoved) self._is_mouse_down = False # is the mouse button currently pressed? # A list of methods to call when the user clicks on a point. Passes an (x,y,z) tuple and a flux value to each function self.click_notify = [] # The velocity navigation: self.pack_start(gtk.HSeparator(), False,False) scale = gtk.HScale() self.scale = scale scale.set_digits(0) self._initialize_scale_element() # Set up the range and marks on the Z slider scale scale.set_value(self._z) scale.set_draw_value(False)# Hide the built in display of the current value since it's not in real units (not in km/s) self.pack_start(scale, False, False) scale.connect("value-changed", self._update_velocity) self.needs_redraw = False # Set this to True if you want the canvas to be repainted gtk.idle_add(CubeViewWidget._check_redraw, self) # we only want to re re-drawing when the GUI is idle, for maximum interactivity self.toolbar.update_mouseout_message() # A list of "highlighters" that can be used to color in specific # areas of the plot: self._highlighters = []
def _get_canvas(self): canvas = FigureCanvas(self.figure) canvas.mpl_connect("pick_event", self.on_pick) return canvas
class DataMatrixGuiXYProbe(gtk.Window): """ 2009-3-13 migrated from QCVisualize.py. now become a standalone program and able to read data from a file and plot ... QCVisualize.py inherits from here 2008-02-05 embed it into a bigger gnome app, add more buttons, and change the __init__() 2008-01-01 class to visualize the results from QualityControl.py """ def __init__(self, plot_title='', id_is_strain=1, header=None, strain_acc_list=None, category_list=None, data_matrix=None): """ 2008-01-10 use a paned window to wrap the scrolledwindow and the canvas so that the relative size of canvas to the scrolledwindow could be adjusted by the user. """ prog = gnome.program_init('DataMatrixGuiXYProbe', '0.1') #this must be called before any initialization for gnome app program_path = os.path.dirname(__init__.__file__) #sys.argv[0]) xml = gtk.glade.XML(os.path.join(program_path, 'DataMatrixGuiXYProbe.glade')) xml.signal_autoconnect(self) self.app1 = xml.get_widget("app1") self.app1.connect("delete_event", gtk.main_quit) self.app1.set_default_size(800, 1000) self.app1.set_title(plot_title) self.plot_title = plot_title self.id_is_strain = id_is_strain self.header = header self.strain_acc_list = strain_acc_list self.category_list = category_list self.data_matrix = data_matrix self.column_types = None self.column_header = None self.column_editable_flag_ls = None self.list_2d = None self.column_types = None self.list_2d = None self.column_header = None self.editable_flag_ls = None self.vbox1 = xml.get_widget("vbox1") self.treeview_matrix = xml.get_widget("treeview_matrix") # matplotlib stuff fig = Figure(figsize=(8,8)) self.canvas = FigureCanvas(fig) # a gtk.DrawingArea self._idClick = self.canvas.mpl_connect('button_press_event', self.on_click) self.vpaned1 = xml.get_widget("vpaned1") self.vpaned1.add2(self.canvas) #vbox.pack_start(self.canvas, True, True) self.ax = fig.add_subplot(111) self.treeview_matrix.connect('row-activated', self.plot_row) toolbar = NavigationToolbar(self.canvas, self.app1) self.vbox1.pack_start(toolbar, False, False) self.checkbutton_label_dot = xml.get_widget('checkbutton_label_dot') self.entry_dot_label_column = xml.get_widget('entry_dot_label_column') self.entry_x_column = xml.get_widget('entry_x_column') self.entry_y_column = xml.get_widget('entry_y_column') self.entry_hist_column = xml.get_widget('entry_hist_column') self.entry_no_of_bins = xml.get_widget('entry_no_of_bins') #2009-5-20 self.entry_plot_title = xml.get_widget('entry_plot_title') self.entry_plot_title.set_text(self.plot_title) self.filechooserdialog_save = xml.get_widget("filechooserdialog_save") self.filechooserdialog_save.connect("delete_event", yh_gnome.subwindow_hide) self.filechooserdialog_open = xml.get_widget("filechooserdialog_open") self.filechooserdialog_open.connect("delete_event", yh_gnome.subwindow_hide) self.app1_appbar1 = xml.get_widget('app1_appbar1') self.app1_appbar1.push('Status Message.') #import gnome.ui has to be executed. self.treeview_matrix.connect('cursor-changed', self.update_no_of_selected, self.app1_appbar1) self.app1.show_all() #self.add_events(gdk.BUTTON_PRESS_MASK|gdk.KEY_PRESS_MASK|gdk.KEY_RELEASE_MASK) def on_click(self, event): """ 2009-3-13 use (x_lim[1]-x_lim[0])/200. as the resolution for a dot to be called identical to a data point. similar for the y_data 2009-3-13 deal with checkbutton_label_dot, entry_dot_label_column, entry_x_column, entry_y_column 2008-01-01 derived from on_click_row() of QualityControl.py reaction when user clicked in the plot """ # get the x and y coords, flip y from top to bottom x, y = event.x, event.y to_label_dot = self.checkbutton_label_dot.get_active() dot_label_column = int(self.entry_dot_label_column.get_text()) x_column = int(self.entry_x_column.get_text()) y_column = int(self.entry_y_column.get_text()) x_lim = self.ax.get_xlim() x_grain_size = (x_lim[1]-x_lim[0])/200. y_lim = self.ax.get_ylim() y_grain_size = (y_lim[1]-y_lim[0])/200. if event.button==1: if event.inaxes is not None: print 'data coords', event.xdata, event.ydata for row in self.list_2d: x_data = row[x_column] y_data = row[y_column] if abs(x_data-event.xdata)<x_grain_size and abs(y_data-event.ydata)<y_grain_size: info = row[dot_label_column] if to_label_dot: self.ax.text(event.xdata, event.ydata, info, size=8) self.canvas.draw() sys.stderr.write("%s: %s, %s: %s, xy=(%s, %s), info: %s.\n"%(self.column_header[0], row[0], self.column_header[1], row[1], x_data, y_data, info)) def plotXY(self, ax, canvas, liststore, plot_title='', chosen_index_ls=[]): """ 2009-3-13 rename plot_NA_mismatch_rate to plotXY() 2008-02-05 chosen_index => chosen_index_ls 2007-12-14 """ x_column = int(self.entry_x_column.get_text()) y_column = int(self.entry_y_column.get_text()) plot_title = self.entry_plot_title.get_text() min_x = 1 min_y = 1 max_x = 0 max_y = 0 x_ls = [] y_ls = [] x_chosen_ls = [] y_chosen_ls = [] from sets import Set chosen_index_set = Set(chosen_index_ls) for i in range(len(liststore)): row = liststore[i] x = row[x_column] y = row[y_column] if x<min_x: min_x = x if x>max_x: max_x = x if y<min_y: min_y = y if y>max_y: max_y = y if i in chosen_index_set: x_chosen_ls.append(x) y_chosen_ls.append(y) else: x_ls.append(x) y_ls.append(y) ax.clear() ax.plot(x_ls, y_ls, '.') """ #diagonal line give a rough feeling about the notion, more NA, worse calling diagonal_start = min(min_x, min_y)-0.1 diagonal_end = max(max_x, max_x)+0.1 ax.plot([diagonal_start, diagonal_end],[diagonal_start, diagonal_end]) """ if x_chosen_ls and y_chosen_ls: #highlight ax.plot(x_chosen_ls, y_chosen_ls, '.', c='r') if plot_title: ax.set_title(plot_title) ax.set_xlabel(self.column_header[x_column]) ax.set_ylabel(self.column_header[y_column]) canvas.draw() def plot_row(self, treeview, path, view_column): if self._idClick==None: self._idClick = self.canvas.mpl_connect('button_press_event', self.on_click) self.plotXY(self.ax, self.canvas, self.liststore, self.plot_title, path) def setupColumns(self, treeview): """ 2009-3-13 """ if not getattr(self, 'column_header', None): sys.stderr.write("Nothing in columns yet.\n") return self.liststore = gtk.ListStore(*self.column_types) #self.add_columns(self.treeview_matrix) yh_gnome.create_columns(self.treeview_matrix, self.column_header, self.editable_flag_ls, self.liststore) yh_gnome.fill_treeview(self.treeview_matrix, self.liststore, self.list_2d, reorderable=True) self.treeselection = self.treeview_matrix.get_selection() def on_button_highlight_clicked(self, widget, data=None): """ 2008-02-12 to update the no_of_selected rows (have to double click a row to change a cursor if it's multiple selection) 2008-02-05 """ if self._idClick==None: self._idClick = self.canvas.mpl_connect('button_press_event', self.on_click) pathlist_strains1 = [] self.treeselection.selected_foreach(yh_gnome.foreach_cb, pathlist_strains1) index_ls = [] for path in pathlist_strains1: index_ls.append(path[0]) self.app1_appbar1.push("%s rows selected."%len(pathlist_strains1)) self.plotXY(self.ax, self.canvas, self.liststore, self.plot_title, index_ls) def on_button_save_clicked(self, widget, data=None): """ 2008-02-05 """ self.filechooserdialog_save.show_all() def on_button_filechooserdialog_cancel_ok_clicked(self, widget, data=None): """ 2008-02-05 """ self.filechooserdialog_save.hide() def on_button_filechooserdialog_save_ok_clicked(self, widget, data=None): """ 2008-02-12 to update the no_of_selected rows (have to double click a row to change a cursor if it's multiple selection) 2008-02-05 """ output_fname = self.filechooserdialog_save.get_filename() self.filechooserdialog_save.hide() pathlist_strains1 = [] self.treeselection.selected_foreach(yh_gnome.foreach_cb, pathlist_strains1) self.app1_appbar1.push("%s rows selected."%len(pathlist_strains1)) if self.header and self.strain_acc_list and self.category_list and self.data_matrix: selected_index_set = Set() for path in pathlist_strains1: row = self.liststore[path[0]] id = row[0] index_in_data_matrix = row[-1] selected_index_set.add(index_in_data_matrix) if self.id_is_strain: id = id[1:-1].split(',') #id is a tuple of (ecotypeid,duplicate) self.strain_acc_list[index_in_data_matrix] = id[0].strip() #remove extra space self.category_list[index_in_data_matrix] = id[1].strip() #else: # self.header[index_in_data_matrix+2] = id from variation.src.FilterStrainSNPMatrix import FilterStrainSNPMatrix FilterStrainSNPMatrix_instance = FilterStrainSNPMatrix() if self.id_is_strain: rows_to_be_tossed_out = Set(range(len(self.strain_acc_list))) - selected_index_set FilterStrainSNPMatrix_instance.write_data_matrix(self.data_matrix, output_fname, self.header, self.strain_acc_list, self.category_list,\ rows_to_be_tossed_out, cols_to_be_tossed_out=Set(), nt_alphabet=0) else: cols_to_be_tossed_out = Set(range(len(self.header)-2)) - selected_index_set FilterStrainSNPMatrix_instance.write_data_matrix(self.data_matrix, output_fname, self.header, self.strain_acc_list, self.category_list,\ rows_to_be_tossed_out=Set(), cols_to_be_tossed_out=cols_to_be_tossed_out, nt_alphabet=0) def show_all(self): """ 2008-02-05 preserve the old interface. in order not to change anything in plot_col_NA_mismatch_rate() and plot_row_NA_mismatch_rate() of QualityControl.py """ self.app1.show_all() def on_button_histogram_clicked(self, widget, data=None): """ 2009-5-20 get the number of bins from entry_no_of_bins 2009-3-13 draw histogram of specific hist_column 2008-02-06 """ if not getattr(self, 'column_header', None): sys.stderr.write("Nothing in columns yet.\n") return self.ax.clear() self.canvas.mpl_disconnect(self._idClick) #drop the signal handler self._idClick = None #reset the _idClick hist_ls = [] hist_column = int(self.entry_hist_column.get_text()) for i in range(len(self.liststore)): hist_ls.append(self.liststore[i][hist_column]) self.ax.set_title("Histogram of %s %s"%(self.plot_title, self.column_header[hist_column])) no_of_bins = int(self.entry_no_of_bins.get_text()) self.ax.hist(hist_ls, no_of_bins) self.canvas.draw() def update_no_of_selected(self, treeview, app1_appbar1): """ 2008-02-12 to update the no_of_selected rows (have to double click a row to change a cursor if it's multiple selection) """ pathlist_strains1 = [] self.treeselection.selected_foreach(yh_gnome.foreach_cb, pathlist_strains1) app1_appbar1.push("%s rows selected."%len(pathlist_strains1)) return True def readInDataToPlot(self, input_fname): """ 2009-5-20 add the column index into the column header for easy picking 2009-3-13 wrap the float conversion part into try...except to report what goes wrong 2009-3-13 """ reader = csv.reader(open(input_fname), delimiter=figureOutDelimiter(input_fname)) self.column_header=reader.next() for i in range(len(self.column_header)): self.column_header[i] = '%s %s'%(i, self.column_header[i]) no_of_cols = len(self.column_header) self.column_types = [str]*2 + [float]*(no_of_cols-2) self.column_editable_flag_ls = [True, True] + [False]*(no_of_cols-2) self.list_2d = [] for row in reader: float_part = row[2:] try: float_part = map(float, float_part) except: sys.stderr.write('Except type: %s\n'%repr(sys.exc_info())) traceback.print_exc() new_row = row[:2]+float_part self.list_2d.append(new_row) self.setupColumns(self.treeview_matrix) self.plotXY(self.ax, self.canvas, self.liststore, self.plot_title) def readInRawMatrixData(self, input_fname): """ 2009-3-13 """ delimiter = figureOutDelimiter(input_fname) self.header, self.strain_acc_list, self.category_list, self.data_matrix = read_data(input_fname, delimiter=delimiter) def on_imagemenuitem_open_activate(self, widget, data=None): """ 2009-3-13 """ self.filechooserdialog_open.show_all() def on_button_fileopen_ok_clicked(self, widget, data=None): """ 2009-3-13 """ input_fname = self.filechooserdialog_open.get_filename() self.filechooserdialog_open.hide() self.readInDataToPlot(input_fname) def on_entry_plot_title_change(self, widget, data=None): """ 2009-3-13 upon any change in the entry_plot_title """ self.plot_title = self.entry_plot_title.get_text()
class TesiDogs: """This is the application main class - there is only one class because socialists don't believe in the class system.""" def __init__(self): self.builder = gtk.Builder() self.builder.add_from_file("tesidog.glade") dic = {"mainwindowdestroy" : gtk.main_quit, "fwdbtnclicked" : self.LoadNextFrame, "backbtnclicked" : self.LoadPreviousFrame, "file1fileset":self.FileLoad, "zoomoutbtnclicked": self.ZoomOut, "zoominbtnclicked":self.ZoomIn, "panleftbtnclicked":self.PanLeft, "panrightbtnclicked":self.PanRight, "pandownbtnclicked":self.PanDown, "panupbtnclicked":self.PanUp, "mainwindowkeypress":self.GetKeyPress, "basebtnclicked":self.BaseButtonClicked, "tailbtnclicked":self.TailButtonClicked, "nolinebtnclicked":self.NoLineButtonClicked, "drawtailendbtnclicked":self.DrawTailEndButtonClicked, "autorunbtnclicked":self.AutorunButtonClicked, "pklchoosefileset":self.PickleFileSet, "imagesavebtnclicked":self.ShowImageSaveDialog, "imagesaveokbtnclicked":self.SaveImageOkButtonClicked, "imagesavecancelbtnclicked":self.SaveImageCancelButtonClicked, "copytailbasepointbtnclicked":self.ShowCopyDialog, "copybaselinebtnclicked":self.ShowCopyDialog, "copyokbtnclicked":self.CopyOkButtonClicked, "copycancelbtnclicked":self.CopyCancelButtonClicked} self.builder.connect_signals(dic) self.conid=self.builder.get_object("statusbar").get_context_id("maps") self.curid=None self.copybtn=None filterplot2 = gtk.FileFilter() filterplot2.set_name("PKL") filterplot2.add_pattern("*.pkl") filterplot2.add_pattern("*.PKL") self.builder.get_object("pklchoose").add_filter(filterplot2) self.images=[] self.clickstate="none" self.linewidth=3. self.circleradius=2 self.circlealpha=0.4 self.taillinealpha=0.7 self.points=[] self.currentbase1=None self.currentbase2=None self.currenttail1=None self.baseline=None self.hoverline=None self.tailline=None self.paraline=None self.autorun=True self.datafile=None self.datastr=None self.builder.get_object("autorunbtn").set_sensitive(0) self.builder.get_object("toolbar1").set_sensitive(0) self.builder.get_object("pklchoose").set_sensitive(0) self.origin="lower" now = datetime.datetime.now() self.timestr=now.strftime("%d_%m_%H%M") self.textbuffer=gtk.TextBuffer() self.builder.get_object("dataview").set_buffer(self.textbuffer) def ClearLines(self): self.axis.clear() self.hoverline=None self.tailline=None def FileLoad(self, widget): self.points=[] self.folder=widget.get_filenames()[0] #get full path self.filenames = os.listdir(self.folder) i=0 while i<len(self.filenames): if self.filenames[i][-3:]!="BMP" and self.filenames[i][-3:]!="bmp": self.filenames.pop(i) else: self.filenames[i]=self.folder+"/"+self.filenames[i] i+=1 if len(self.filenames)==0: if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, "Error: No BMPs in given folder!") return 0 self.filenames.sort() try: self.datafilename=self.filenames[0].split("/")[-1].split("_")[0]+self.timestr+".dat" except: self.datafilename=self.filenames[0].split("/")[-1].split(".")[0]+self.timestr+".dat" self.builder.get_object("toolbar1").set_sensitive(1) if (self.filenames[0].split(".")[-1]=="bmp") or (self.filenames[0].split(".")[-1]=="BMP"): self.origin="lower" else: self.origin="upper" #Reset other data here - TODO for filen in self.filenames: #no faster self.images.append(mpimg.imread(filen)) self.figure=Figure() self.axis=self.figure.add_subplot(111) img=mpimg.imread(self.filenames[0]) self.frame=0 self.points.append({"base1":None, "base2":None, "tail1":None, "tail2":None, "angle":None, "side":None, "topbottom":None, "length":None}) self.axis.imshow(img, origin=self.origin) self.canvas=FigureCanvasGTKAgg(self.figure) self.canvas.show() self.canvas.mpl_connect('motion_notify_event', self.HoverOnImage) self.canvas.mpl_connect('button_release_event', self.CaptureClick) self.builder.get_object("npbox").pack_start(self.canvas, True, True) self.builder.get_object("pklchoose").set_sensitive(1) self.SetClickState("base1") self.UpdateInstructions("Zoom in and click two points along the dog's feet to draw the base line") def LoadNextFrame(self, widget): xlims=self.axis.get_xlim() ylims=self.axis.get_ylim() #Load next frame self.ClearLines() self.frame+=1 if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, 'Click mode: "'+self.clickstate+'". Autorun: ' + str(self.autorun) + '. Frame: '+ str(self.frame+1) + "/" + str(len(self.filenames)) +".") if (self.frame >= len(self.points)): #if image unseen, prepare dictionary - this code disallows skipping, assumption is the mother of all fuckups self.points.append({"base1":self.currentbase1, "base2":self.currentbase2, "tail1":self.currenttail1, "tail2":None, "angle":None, "side":None, "topbottom":None, "length":None}) img=self.images[self.frame] self.axis.imshow(img, origin=self.origin) self.axis.set_xlim(left=xlims[0], right=xlims[1]) self.axis.set_ylim(top=ylims[1], bottom=ylims[0]) if self.points[self.frame]["base2"] != None: #if already line, draw that one self.baseline = lines.Line2D(np.array([self.points[self.frame]["base1"][0],self.points[self.frame]["base2"][0]]), np.array([self.points[self.frame]["base1"][1],self.points[self.frame]["base2"][1]]), lw=self.linewidth, color='r', alpha=0.9) self.currentbase1=(self.points[self.frame]["base1"][0], self.points[self.frame]["base1"][1]) self.currentbase2=(self.points[self.frame]["base2"][0], self.points[self.frame]["base2"][1]) self.axis.add_line(self.baseline) self.DrawParallelLine() elif (self.points[self.frame]["base2"] == None) and (self.currentbase2!=None): #if not line, use previous one, don't think this is ever run self.baseline = lines.Line2D(np.array([self.currentbase1[0],self.currentbase2[0]]), np.array([self.currentbase1[1],self.currentbase2[1]]), lw=self.linewidth, color='r', alpha=0.9) self.axis.add_line(self.baseline) self.DrawParallelLine() if self.clickstate=="none": self.UpdateInstructions("Browsing mode. Use toolbar buttons to edit points. Autorun disabled. Frame " + str(self.frame+1) + "/" + str(len(self.filenames))) if self.points[self.frame]["tail2"] != None: #if already line, draw that one self.tailline = lines.Line2D(np.array([self.points[self.frame]["tail1"][0],self.points[self.frame]["tail2"][0]]), np.array([self.points[self.frame]["tail1"][1],self.points[self.frame]["tail2"][1]]), lw=self.linewidth, color='b', alpha=self.taillinealpha) self.axis.add_line(self.tailline) self.currenttail1=(self.points[self.frame]["tail1"][0], self.points[self.frame]["tail1"][1]) #bad hack to fix parallel line if (self.frame-1>=0): self.builder.get_object("backbtn").set_sensitive(1) else: self.builder.get_object("backbtn").set_sensitive(0) if (len(self.filenames)<=self.frame+1): self.builder.get_object("fwdbtn").set_sensitive(0) else: self.builder.get_object("fwdbtn").set_sensitive(1) self.canvas.draw() def LoadPreviousFrame(self, widget): xlims=self.axis.get_xlim() ylims=self.axis.get_ylim() #Load next frame self.ClearLines() self.frame-=1 img=self.images[self.frame] self.axis.imshow(img, origin=self.origin) self.axis.set_xlim(left=xlims[0], right=xlims[1]) self.axis.set_ylim(top=ylims[1], bottom=ylims[0]) if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, 'Click mode: "'+self.clickstate+'". Autorun: ' + str(self.autorun) + '. Frame: '+ str(self.frame+1) + "/" + str(len(self.filenames)) +".") if self.points[self.frame]["base2"] != None: #if already line, draw that one self.baseline = lines.Line2D(np.array([self.points[self.frame]["base1"][0],self.points[self.frame]["base2"][0]]), np.array([self.points[self.frame]["base1"][1],self.points[self.frame]["base2"][1]]), lw=self.linewidth, color='r', alpha=0.9) self.axis.add_line(self.baseline) self.currentbase1=(self.points[self.frame]["base1"][0], self.points[self.frame]["base1"][1]) self.currentbase2=(self.points[self.frame]["base2"][0], self.points[self.frame]["base2"][1]) self.DrawParallelLine() if self.clickstate=="none": self.UpdateInstructions("Browsing mode. Use toolbar buttons to edit points. Autorun disabled. Frame " + str(self.frame+1) + "/" + str(len(self.filenames))) if self.points[self.frame]["tail2"] != None: #if already line, draw that one self.tailline = lines.Line2D(np.array([self.points[self.frame]["tail1"][0],self.points[self.frame]["tail2"][0]]), np.array([self.points[self.frame]["tail1"][1],self.points[self.frame]["tail2"][1]]), lw=self.linewidth, color='b', alpha=self.taillinealpha) self.axis.add_line(self.tailline) self.currenttail1=(self.points[self.frame]["tail1"][0], self.points[self.frame]["tail1"][1]) #bad hack to fix parallel line if (len(self.filenames)<=self.frame+1): self.builder.get_object("fwdbtn").set_sensitive(0) else: self.builder.get_object("fwdbtn").set_sensitive(1) if (self.frame-1<0): self.builder.get_object("backbtn").set_sensitive(0) else: self.builder.get_object("backbtn").set_sensitive(1) self.canvas.draw() def HoverOnImage(self, event): if event.x!=None and event.y!=None and event.xdata!=None and event.ydata!=None: if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, 'Click mode: "'+self.clickstate+'", Autorun: ' + str(self.autorun) + '. Frame: '+ str(self.frame+1) + "/" + str(len(self.filenames)) + '. x=%d, y=%d'%(int(round(event.xdata)), int(round(event.ydata)))) if self.clickstate=="base2": if self.hoverline==None: self.hoverline = lines.Line2D(np.array([self.points[self.frame]["base1"][0],int(round(event.xdata))]), np.array([self.points[self.frame]["base1"][1],int(round(event.ydata))]), lw=self.linewidth, color='y', alpha=0.5) self.axis.add_line(self.hoverline) else: self.hoverline.set_data(np.array([self.points[self.frame]["base1"][0],int(round(event.xdata))]), np.array([self.points[self.frame]["base1"][1],int(round(event.ydata))])) self.canvas.draw() if self.clickstate=="tail2": if self.hoverline==None: self.hoverline = lines.Line2D(np.array([self.points[self.frame]["tail1"][0],int(round(event.xdata))]), np.array([self.points[self.frame]["tail1"][1],int(round(event.ydata))]), lw=self.linewidth, color='y', alpha=0.5) self.axis.add_line(self.hoverline) else: self.hoverline.set_data(np.array([self.points[self.frame]["tail1"][0],int(round(event.xdata))]), np.array([self.points[self.frame]["tail1"][1],int(round(event.ydata))])) self.canvas.draw() def ZoomIn(self, widget): xlims=self.axis.get_xlim() ylims=self.axis.get_ylim() xchange=abs(xlims[1]-xlims[0])*0.1 ychange=abs(ylims[1]-ylims[0])*0.1 self.axis.set_xlim(left=xlims[0]+xchange, right=xlims[1]-xchange) self.axis.set_ylim(top=ylims[1]-ychange, bottom=ylims[0]+ychange) self.builder.get_object("npbox").remove(self.canvas) self.builder.get_object("npbox").pack_start(self.canvas, True, True) def ZoomOut(self, widget): xlims=self.axis.get_xlim() ylims=self.axis.get_ylim() xchange=abs(xlims[1]-xlims[0])*0.111 ychange=abs(ylims[1]-ylims[0])*0.111 self.axis.set_xlim(left=xlims[0]-xchange, right=xlims[1]+xchange) self.axis.set_ylim(top=ylims[1]+ychange, bottom=ylims[0]-ychange) self.builder.get_object("npbox").remove(self.canvas) self.builder.get_object("npbox").pack_start(self.canvas, True, True) def PanLeft(self, widget): xlims=self.axis.get_xlim() xchange=abs(xlims[1]-xlims[0])*0.1 self.axis.set_xlim(left=xlims[0]-xchange, right=xlims[1]-xchange) self.builder.get_object("npbox").remove(self.canvas) self.builder.get_object("npbox").pack_start(self.canvas, True, True) def PanRight(self, widget): xlims=self.axis.get_xlim() xchange=abs(xlims[1]-xlims[0])*0.1 self.axis.set_xlim(left=xlims[0]+xchange, right=xlims[1]+xchange) self.builder.get_object("npbox").remove(self.canvas) self.builder.get_object("npbox").pack_start(self.canvas, True, True) def PanUp(self, widget): ylims=self.axis.get_ylim() ychange=abs(ylims[1]-ylims[0])*0.1 self.axis.set_ylim(top=ylims[1]+ychange, bottom=ylims[0]+ychange) self.builder.get_object("npbox").remove(self.canvas) self.builder.get_object("npbox").pack_start(self.canvas, True, True) def PanDown(self, widget): ylims=self.axis.get_ylim() ychange=abs(ylims[1]-ylims[0])*0.1 self.axis.set_ylim(top=ylims[1]-ychange, bottom=ylims[0]-ychange) self.builder.get_object("npbox").remove(self.canvas) self.builder.get_object("npbox").pack_start(self.canvas, True, True) def UpdateInstructions(self, message): self.builder.get_object("instructions").set_label(message) def CaptureClick(self, event): #self.clickstate can be "none", "base1", "base2", "tail1", "tail2" #Datastructure is list of dicts - one list for each frame #dict contains base1 point, base2 point, tail1 point, tail2 point #base can be changed per frame but is assumed from previous frame by default if self.clickstate=="none": return 0 elif event.x==None or event.y==None or event.xdata==None or event.ydata==None: return 0 elif self.clickstate=="base1": self.currentbase1=(int(round(event.xdata)), int(round(event.ydata))) self.points[self.frame]["base1"]=(int(round(event.xdata)), int(round(event.ydata))) self.SetClickState("base2") elif self.clickstate=="base2": self.currentbase2=(int(round(event.xdata)), int(round(event.ydata))) self.points[self.frame]["base2"]=(int(round(event.xdata)), int(round(event.ydata))) self.baseline = lines.Line2D(np.array([self.points[self.frame]["base1"][0],self.points[self.frame]["base2"][0]]), np.array([self.points[self.frame]["base1"][1],self.points[self.frame]["base2"][1]]), lw=self.linewidth, color='r', alpha=0.9) self.axis.add_line(self.baseline) if self.points[self.frame]["tail1"]!=None: self.DrawParallelLine() self.canvas.draw() if self.points[self.frame]["tail2"]!=None: self.CalculateAngle() if self.autorun==True: self.SetClickState("tail1") elif self.autorun==False: self.SetClickState("none") elif self.clickstate=="tail1": if self.points[self.frame]["tail1"]!=None: #point already there, must clear already=True else: already=False self.currenttail1=(int(round(event.xdata)), int(round(event.ydata))) self.points[self.frame]["tail1"]=(int(round(event.xdata)), int(round(event.ydata))) self.DrawParallelLine() if self.points[self.frame]["tail2"]!=None: self.CalculateAngle() if already==True: self.SetClickState("none") self.frame=self.frame-1 self.LoadNextFrame(None) if self.autorun==True: self.SetClickState("tail2") else: self.SetClickState("none") #Draw parallel line and circle elif self.clickstate=="tail2": self.points[self.frame]["tail2"]=(int(round(event.xdata)), int(round(event.ydata))) self.tailline = lines.Line2D(np.array([self.points[self.frame]["tail1"][0],self.points[self.frame]["tail2"][0]]), np.array([self.points[self.frame]["tail1"][1],self.points[self.frame]["tail2"][1]]), lw=self.linewidth, color='b', alpha=0.9) self.axis.add_line(self.tailline) self.canvas.draw() self.CalculateAngle() if (len(self.filenames)<=self.frame+1): self.SetClickState("none") self.UpdateInstructions("Finished") else: if self.autorun==True: self.UpdateInstructions("Click the end of the tail. Frame " + str(self.frame+2) + "/" + str(len(self.filenames))) self.LoadNextFrame(None) elif self.autorun==False: self.SetClickState("none") def DrawParallelLine(self): if self.currenttail1==None and self.points[self.frame]["tail1"]==None: return 0 if self.currenttail1==None: if self.points[self.frame]["tail1"]==None: return 0; else: self.currenttail1=self.points[self.frame]["tail1"] if self.points[self.frame]["base2"]!=None: #draw actual line if self.points[self.frame]["tail1"]!=None: circle=Circle(self.points[self.frame]["tail1"], radius=self.circleradius, alpha=self.circlealpha, color="yellow") #put here because here has check for tail1 basem=(float(self.points[self.frame]["base2"][1]-self.points[self.frame]["base1"][1]))/(float(self.points[self.frame]["base2"][0]-self.points[self.frame]["base1"][0])) c=self.points[self.frame]["base2"][1]-(basem*self.points[self.frame]["base2"][0]) ydiff=self.points[self.frame]["tail1"][1]-((basem*self.points[self.frame]["tail1"][0])+c) #fails if points[self.frame]["tail1"]==None - should never be called in this case self.paraline = lines.Line2D(np.array([self.points[self.frame]["base1"][0], self.points[self.frame]["base2"][0]]), np.array([self.points[self.frame]["base1"][1]+ydiff, self.points[self.frame]["base2"][1]+ydiff]), lw=self.linewidth, color='r', alpha=0.3) else: circle=Circle(self.currenttail1, radius=self.circleradius, alpha=self.circlealpha, color="yellow") #put here because here has check for tail1 basem=(float(self.points[self.frame]["base2"][1]-self.points[self.frame]["base1"][1]))/(float(self.points[self.frame]["base2"][0]-self.points[self.frame]["base1"][0])) c=self.points[self.frame]["base2"][1]-(basem*self.points[self.frame]["base2"][0]) ydiff=self.currenttail1[1]-((basem*self.currenttail1[0])+c) #fails if currenttail1==None - should never be called in this case self.paraline = lines.Line2D(np.array([self.points[self.frame]["base1"][0], self.points[self.frame]["base2"][0]]), np.array([self.points[self.frame]["base1"][1]+ydiff, self.points[self.frame]["base2"][1]+ydiff]), lw=self.linewidth, color='r', alpha=0.3) elif self.points[self.frame]["base2"] == None: if self.points[self.frame]["tail1"]!=None: circle=Circle(self.points[self.frame]["tail1"], radius=self.circleradius, alpha=self.circlealpha, color="yellow") #put here because here has check for tail1 basem=(float(self.currentbase2[1]-self.currentbase1[1]))/(float(self.currentbase2[0]-self.currentbase1[0])) c=self.currentbase2[1]-(basem*self.currentbase2[0]) ydiff=self.points[self.frame]["tail1"][1]-((basem*self.points[self.frame]["tail1"][0])+c) #fails if points[self.frame]["tail1"]==None - should never be called in this case self.paraline = lines.Line2D(np.array([self.currentbase1[0], self.currentbase2[0]]), np.array([self.currentbase1[1]+ydiff, self.currentbase2[1]+ydiff]), lw=self.linewidth, color='r', alpha=0.3) else: circle=Circle(self.currenttail1, radius=self.circleradius, alpha=self.circlealpha, color="yellow") #put here because here has check for tail1 basem=(float(self.currentbase2[1]-self.currentbase1[1]))/(float(self.currentbase2[0]-self.currentbase1[0])) c=self.currentbase2[1]-(basem*self.currentbase2[0]) ydiff=self.currenttail1[1]-((basem*self.currenttail1[0])+c) #fails if currenttail1==None - should never be called in this case self.paraline = lines.Line2D(np.array([self.currentbase1[0], self.currentbase2[0]]), np.array([self.currentbase1[1]+ydiff, self.currentbase2[1]+ydiff]), lw=self.linewidth, color='r', alpha=0.3) self.axis.add_line(self.paraline) self.axis.add_patch(circle) self.canvas.draw() def GetKeyPress(self, widget, event): if event.keyval==65307: #ESC key pressed self.SetClickState("none") def SetClickState(self, clickstate): if clickstate=="none": self.UpdateInstructions("Browsing mode. Use toolbar buttons to edit points. Autorun disabled. Frame " + str(self.frame+1) + "/" + str(len(self.filenames))) if self.hoverline!=None: #Remove hover line self.hoverline.set_data(np.array([0,0]),np.array([0,0])) self.canvas.draw() self.hoverline=None self.builder.get_object("nolinebtn").set_sensitive(0) #Make noline button insensitive self.builder.get_object("basebtn").set_sensitive(1) self.builder.get_object("tailbtn").set_sensitive(1) self.builder.get_object("tailendbtn").set_sensitive(1) self.builder.get_object("copytailbasepointbtn").set_sensitive(1) self.builder.get_object("copybaselinebtn").set_sensitive(1) self.builder.get_object("tailendbtn").set_sensitive(1) #Attempt to make next/prev buttons sensitive if (self.frame-1>=0): self.builder.get_object("backbtn").set_sensitive(1) if (len(self.filenames)>self.frame+1): self.builder.get_object("fwdbtn").set_sensitive(1) self.autorun=False self.builder.get_object("autorunbtn").set_sensitive(1) elif clickstate=="base1": self.UpdateInstructions("Click the first base point. Frame " + str(self.frame+1) + "/" + str(len(self.filenames))) if self.baseline!=None: self.baseline.set_data(np.array([0,0]),np.array([0,0])) self.canvas.draw() if self.paraline!=None: self.paraline.set_data(np.array([0,0]),np.array([0,0])) self.canvas.draw() self.builder.get_object("nolinebtn").set_sensitive(1) self.builder.get_object("basebtn").set_sensitive(0) self.builder.get_object("tailbtn").set_sensitive(0) self.builder.get_object("tailendbtn").set_sensitive(0) self.builder.get_object("backbtn").set_sensitive(0) self.builder.get_object("fwdbtn").set_sensitive(0) self.builder.get_object("copytailbasepointbtn").set_sensitive(0) self.builder.get_object("copybaselinebtn").set_sensitive(0) elif clickstate=="base2": self.UpdateInstructions("Click the second base point. Frame " + str(self.frame+1) + "/" + str(len(self.filenames))) elif clickstate=="tail1": self.UpdateInstructions("Click the base of the tail on the dog. Frame " + str(self.frame+1) + "/" + str(len(self.filenames))) self.builder.get_object("nolinebtn").set_sensitive(1) self.builder.get_object("basebtn").set_sensitive(0) self.builder.get_object("tailbtn").set_sensitive(0) self.builder.get_object("tailendbtn").set_sensitive(0) self.builder.get_object("backbtn").set_sensitive(0) self.builder.get_object("fwdbtn").set_sensitive(0) self.builder.get_object("copytailbasepointbtn").set_sensitive(0) self.builder.get_object("copybaselinebtn").set_sensitive(0) elif clickstate=="tail2": if self.points[self.frame]["tail1"]==None: self.SetClickState("none") if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, "Error: First tail point not set!") return None else: self.UpdateInstructions("Click the end of the tail. Frame " + str(self.frame+1) + "/" + str(len(self.filenames))) if self.tailline!=None: self.tailline.set_data(np.array([0,0]),np.array([0,0])) self.canvas.draw() self.builder.get_object("nolinebtn").set_sensitive(1) self.builder.get_object("basebtn").set_sensitive(0) self.builder.get_object("tailbtn").set_sensitive(0) self.builder.get_object("tailendbtn").set_sensitive(0) self.builder.get_object("backbtn").set_sensitive(0) self.builder.get_object("fwdbtn").set_sensitive(0) self.builder.get_object("copytailbasepointbtn").set_sensitive(0) self.builder.get_object("copybaselinebtn").set_sensitive(0) #Push changed message to statusbar self.clickstate=clickstate if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, 'Changed click mode to "'+clickstate+'". Autorun: ' + str(self.autorun) + '. Frame: '+ str(self.frame+1) + "/" + str(len(self.filenames)) +".") def BaseButtonClicked(self, widget): self.SetClickState("base1") def TailButtonClicked(self, widget): self.SetClickState("tail1") def DrawTailEndButtonClicked(self, widget): self.SetClickState("tail2") def NoLineButtonClicked(self, widget): self.SetClickState("none") def AutorunButtonClicked(self, widget): self.autorun=True self.builder.get_object("autorunbtn").set_sensitive(0) def CalculateAngle(self): #Angle always measured from normal, above and below #Find line between tail2 and tail1 graderror=False try: tailm=(float(self.points[self.frame]["tail2"][1]-self.points[self.frame]["tail1"][1]))/(float(self.points[self.frame]["tail2"][0]-self.points[self.frame]["tail1"][0])) tailc=self.points[self.frame]["tail2"][1]-(tailm*self.points[self.frame]["tail2"][0]) except: #Assume divide by zero error poix=self.points[self.frame]["tail2"][0] graderror=True try: basem=(float(self.points[self.frame]["base2"][1]-self.points[self.frame]["base1"][1]))/(float(self.points[self.frame]["base2"][0]-self.points[self.frame]["base1"][0])) basec=self.points[self.frame]["base2"][1]-(basem*self.points[self.frame]["base2"][0]) except: poix=self.points[self.frame]["base2"][0] graderror=True if graderror==False: poix=((tailc-basec)/(basem-tailm)) try: poiy=(basem*poix)+basec except: poiy=(tailm*poix)+tailc #if both fail then divergent self.points[self.frame]["angle"]=abs(90-math.degrees(math.acos((((self.points[self.frame]["tail2"][0] - poix)*(self.points[self.frame]["base1"][0] - poix)) + ((self.points[self.frame]["tail2"][1] - poiy)*(self.points[self.frame]["base1"][1] - poiy)))/(math.sqrt( ((math.pow(self.points[self.frame]["tail2"][0] - poix,2)) + (math.pow(self.points[self.frame]["tail2"][1] - poiy,2))) * ( ((math.pow(self.points[self.frame]["base1"][0] - poix,2)) + (math.pow(self.points[self.frame]["base1"][1] - poiy,2))))) )))) if ((self.points[self.frame]["tail2"][0]-self.points[self.frame]["tail1"][0])>=0): self.points[self.frame]["side"]="R" else: self.points[self.frame]["side"]="L" if ((self.points[self.frame]["tail2"][1]-self.points[self.frame]["tail1"][1])>=0): self.points[self.frame]["topbottom"]="T" else: self.points[self.frame]["topbottom"]="B" self.points[self.frame]["length"]=math.sqrt(pow(self.points[self.frame]["tail2"][1]-self.points[self.frame]["tail1"][1],2) + pow(self.points[self.frame]["tail2"][0]-self.points[self.frame]["tail1"][0],2) ) self.SaveData() def SaveData(self): #get datastr from dictionary #save that, pickle dictionary base1xlist=[] base1ylist=[] base2xlist=[] base2ylist=[] tail1xlist=[] tail1ylist=[] tail2xlist=[] tail2ylist=[] anglelist=[] sidelist=[] topbottomlist=[] lengthlist=[] for item in self.points: try: base1xlist.append(item["base1"][0]) except: base1xlist.append("NA") try: base1ylist.append(item["base1"][1]) except: base1ylist.append("NA") try: base2xlist.append(item["base2"][0]) except: base2xlist.append("NA") try: base2ylist.append(item["base2"][1]) except: base2ylist.append("NA") try: tail1xlist.append(item["tail1"][0]) except: tail1xlist.append("NA") try: tail1ylist.append(item["tail1"][1]) except: tail1ylist.append("NA") try: tail2xlist.append(item["tail2"][0]) except: tail2xlist.append("NA") try: tail2ylist.append(item["tail2"][1]) except: tail2ylist.append("NA") try: if item["angle"]!=None: anglelist.append(item["angle"]) else: anglelist.append("NA") except: anglelist.append("NA") try: if item["side"]!=None: sidelist.append(item["side"]) else: sidelist.append("NA") except: sidelist.append("NA") try: if item["topbottom"]!=None: topbottomlist.append(item["topbottom"]) else: topbottomlist.append("NA") except: topbottomlist.append("NA") try: if item["length"]!=None: lengthlist.append(item["length"]) else: lengthlist.append("NA") except: lengthlist.append("NA") for i in range(len(self.filenames)-len(self.points)): base1xlist.append("NA") base1ylist.append("NA") base2xlist.append("NA") base2ylist.append("NA") tail1xlist.append("NA") tail1ylist.append("NA") tail2xlist.append("NA") tail2ylist.append("NA") anglelist.append("NA") sidelist.append("NA") topbottomlist.append("NA") lengthlist.append("NA") self.datastr="id,base1x,base1y,base2x,base2y,tail1x,tail1y,tail2x,tail2y,angle,length,side,topbottom\n" for i in range(len(base1xlist)): self.datastr+=str(i+1) +","+str(base1xlist[i])+ ","+str(base1ylist[i]) + "," +str(base2xlist[i]) +"," +str(base2ylist[i]) + "," + str(tail1xlist[i]) + "," + str(tail1ylist[i]) + "," + str(tail2xlist[i]) + "," + str(tail2ylist[i]) + "," + str(anglelist[i]) + "," + str(lengthlist[i]) + "," + str(sidelist[i]) + "," + str(topbottomlist[i]) +"\n" self.textbuffer.set_text(self.datastr) self.datafile=open(self.datafilename, "w") self.datafile.write(self.datastr) self.datafile.close() picklefile=open(self.datafilename[:-3]+"pkl", "w") pickle.dump(self.points,picklefile) picklefile.close() def PickleFileSet(self, widget): self.SetClickState("none") pklfilename=widget.get_filenames()[0] try: picklefile=open(pklfilename, "r") temppoints=pickle.load(picklefile) picklefile.close() except: return 0 if len(temppoints)>len(self.filenames): if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, "Error: PKL file had more frames than frames loaded!") return 0 self.points=temppoints self.datafilename=pklfilename[:-3]+"dat" self.SaveData() i=0 while i < len(self.points): #hopefully this works, might need to initialise full list if self.points[i]["tail2"]==None: self.frame=i break i+=1 if i == len(self.points): if len(self.filenames)>len(self.points): self.frame = len(self.points) else: self.frame=0 #redraw canvas, load data self.frame=self.frame-1 self.LoadNextFrame(None) if self.frame==0: self.SetClickState("none") else: #assumes these are defined self.currentbase1=(self.points[self.frame-1]["base1"][0], self.points[self.frame-1]["base1"][1]) self.currentbase2=(self.points[self.frame-1]["base2"][0], self.points[self.frame-1]["base2"][1]) self.currenttail1=(self.points[self.frame-1]["tail1"][0], self.points[self.frame-1]["tail1"][1]) if self.points[self.frame]["base1"]==None: self.points[self.frame]["base1"]=self.currentbase1 if self.points[self.frame]["base2"]==None: self.points[self.frame]["base2"]=self.currentbase2 if self.points[self.frame]["tail1"]==None: self.points[self.frame]["tail1"]=self.currenttail1 self.frame=self.frame-1 self.LoadNextFrame(None) self.AutorunButtonClicked(None) self.SetClickState("tail2") def ShowImageSaveDialog(self, widget): self.builder.get_object("imagesavedialog").set_visible(1) def SaveImageCancelButtonClicked(self, widget): self.builder.get_object("imagesavedialog").set_visible(0) def SaveImageOkButtonClicked(self, widget): filename=self.builder.get_object("imagesavedialog").get_filenames()[0] if filename[-4:]!=".png" and filename[-4:]!=".PNG": filename=filename+".png" self.figure.savefig(filename, format="png") self.builder.get_object("imagesavedialog").set_visible(0) def ShowCopyDialog(self, widget): self.SetClickState("none") if gtk.Buildable.get_name(widget) == "copybaselinebtn": self.builder.get_object("copylabel").set_label("From which frame number (1-" + str(len(self.points))+") do you wish to copy the base line?") self.copybtn="base" else: self.builder.get_object("copylabel").set_label("From which frame number (1-" + str(len(self.points))+") do you wish to copy the tail basepoint?") self.copybtn="tail" self.builder.get_object("copydialog").set_visible(1) def CopyCancelButtonClicked(self, widget): self.builder.get_object("copydialog").set_visible(0) def CopyOkButtonClicked(self, widget): try: number=int(self.builder.get_object("entry1").get_text()) except: self.builder.get_object("copydialog").set_visible(0) if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, "Error: Frame number given was not an integer!") return 0 if number>len(self.points) or number<1: self.builder.get_object("copydialog").set_visible(0) if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, "Error: Frame number was not within valid range!") return 0 if self.copybtn=="base": if self.points[number-1]["base2"]==None: self.builder.get_object("copydialog").set_visible(0) if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, "Error: Frame does not have valid base line!") return 0 else: self.builder.get_object("copydialog").set_visible(0) self.points[self.frame]["base1"]=self.points[number-1]["base1"] self.currentbase1=self.points[number-1]["base1"] self.points[self.frame]["base2"]=self.points[number-1]["base2"] self.currentbase2=self.points[number-1]["base2"] self.frame=self.frame-1 self.LoadNextFrame(None) if self.points[self.frame]["tail2"]!=None: self.CalculateAngle() if self.copybtn=="tail": if self.points[number-1]["tail1"]==None: self.builder.get_object("copydialog").set_visible(0) if self.curid!=None: self.builder.get_object("statusbar").remove_message(self.conid, self.curid) self.curid=self.builder.get_object("statusbar").push(self.conid, "Error: Frame does not have valid tail basepoint!") return 0 else: self.builder.get_object("copydialog").set_visible(0) self.points[self.frame]["tail1"]=self.points[number-1]["tail1"] self.currenttail1=self.points[number-1]["tail1"] self.frame=self.frame-1 self.LoadNextFrame(None) if self.points[self.frame]["tail2"]!=None: self.CalculateAngle() return 0
class XratersWindow(gtk.Window): __gtype_name__ = "XratersWindow" def __init__(self): """__init__ - This function is typically not called directly. Creation a XratersWindow requires redeading the associated ui file and parsing the ui definition extrenally, and then calling XratersWindow.finish_initializing(). Use the convenience function NewXratersWindow to create XratersWindow object. """ self._acc_cal = ((128, 128, 128), (255, 255, 255)) self._acc = [0, 0, 0] self._connected = False self._wiiMote = None self._resetData() self._dataLock = threading.Lock() isConnected = property(lambda self: self._connected) def callback(funct): """A decorator used to require connection to the Wii Remote This decorator is used to implement the precondition that the Wii Remote must be connected. """ def _callback(cls, *args, **kwds): if cls.isConnected: funct(cls, *args, **kwds) return True else: return False return _callback def _connectCallback(self, connectionMaker): """Callback function called upon successful connection to the Wiimote """ if connectionMaker.connected: self._connected = True self._wiiMote = connectionMaker.wiiMote self._resetData() gobject.timeout_add(45, self._drawAcc) self.widget('actionDisconnect').set_sensitive(True) self.widget('actionSave').set_sensitive(True) self.widget('actionReset').set_sensitive(True) self.widget('actionPause').set_sensitive(True) self.widget('toolbutton1').set_related_action(self.widget('actionDisconnect')) self._acc_cal = connectionMaker.acc_cal self._wiiMote.mesg_callback = self._getAcc self._updBatteryLevel() gobject.timeout_add_seconds(60, self._updBatteryLevel) else: self.widget('actionWiiConnect').set_sensitive(True) @callback def _upd_background(self, event): """Keep a copy of the figure background """ self.__background = self._accCanvas.copy_from_bbox(self._accAxis.bbox) def _getAcc(self, messages, theTime=0): """Process acceleration messages from the Wiimote This function is intended to be set as cwiid.mesg_callback """ if self._Paused: return for msg in messages: if msg[0] == cwiid.MESG_ACC: # Normalize data using calibration info for i, axisAcc in enumerate(msg[1]): self._acc[i] = float(axisAcc-self._acc_cal[0][i]) self._acc[i] /=(self._acc_cal[1][i]\ -self._acc_cal[0][i]) with self._dataLock: # Store time and acceleration in the respective arrays self._time.append(theTime-self._startTime) [self._accData[i].append(self._acc[i]) for i in threeAxes] # We only keep about 6 seconds worth of data if (self._time[-1] - self._time[0] > 6): with self._dataLock: self._time.pop(0) [self._accData[i].pop(0) for i in threeAxes] @callback def _drawAcc(self): """Update the acceleration graph """ # Do nothing while paused or there's no data available if self._Paused or len(self._time)==0: return draw_flag = False # Update axes limits if the data fall out of range lims = self._accAxis.get_xlim() if self._time[-1] > lims[1]: self._accAxis.set_xlim(lims[0], lims[1]+2) lims = self._accAxis.get_xlim() draw_flag = True if (self._time[-1] - lims[0] > 6): self._accAxis.set_xlim(lims[0]+2, lims[1]) draw_flag = True if draw_flag: gobject.idle_add(self._accCanvas.draw) # Do the actual update of the background if self.__background != None: self._accCanvas.restore_region(self.__background) # Do the actual update of the lines with self._dataLock: [self._lines[i].set_data(self._time, self._accData[i]) for i in threeAxes] [self._accAxis.draw_artist(self._lines[i]) for i in threeAxes] self._accCanvas.blit(self._accAxis.bbox) @callback def _updBatteryLevel(self): """Callback to update the battery indicator in the status bar """ self._wiiMote.request_status() self._setBatteryIndicator(float(self._wiiMote.state['battery']) / cwiid.BATTERY_MAX) def _setBatteryIndicator(self, level): """Actually update the battery indicator in the status bar """ progressBar = self.widget("progressbarBattery") progressBar.set_fraction(level) progressBar.set_text("Battery: %.0f%%" % (level * 100)) def _resetData(self): """Reset stored data and status flags to their defaults """ self._accData = [list(), list(), list()] self._time = list() self._startTime = time.time() self._moveTime = self._startTime self._Paused = False def widget(self, name): """Helper function to retrieve widget handlers """ return self.builder.get_object(name) def finish_initializing(self, builder): """finish_initalizing should be called after parsing the ui definition and creating a XratersWindow object with it in order to finish initializing the start of the new XratersWindow instance. """ #get a reference to the builder and set up the signals self.builder = builder self.builder.connect_signals(self) #uncomment the following code to read in preferences at start up dlg = PreferencesXratersDialog.NewPreferencesXratersDialog() self.preferences = dlg.get_preferences() #code for other initialization actions should be added here self._accFigure = Figure(figsize=(8,6), dpi=72) self._accAxis = self._accFigure.add_subplot(111) self._accAxis.set_xlabel("time (s)") self._accAxis.set_ylabel("acceleration (g)") self._lines = self._accAxis.plot(self._time, self._accData[X], self._time, self._accData[Y], self._time, self._accData[Z], animated=True) self._accFigure.legend(self._lines, ("X", "Y", "Z"), 'upper center', ncol=3) self._accAxis.set_xlim(0, 2) self._accAxis.set_ylim(-3, 3) self._accCanvas = FigureCanvas(self._accFigure) self._accCanvas.mpl_connect("draw_event", self._upd_background) self.__background = self._accCanvas.copy_from_bbox(self._accAxis.bbox) self._accCanvas.show() self._accCanvas.set_size_request(600, 400) vbMain = self.widget("vboxMain") vbMain.pack_start(self._accCanvas, True, True) vbMain.show() vbMain.reorder_child(self._accCanvas, 2) self._setBatteryIndicator(0) def about(self, widget, data=None): """about - display the about box for xraters """ about = AboutXratersDialog.NewAboutXratersDialog() response = about.run() about.destroy() def preferences(self, widget, data=None): """preferences - display the preferences window for xraters """ prefs = PreferencesXratersDialog.NewPreferencesXratersDialog() response = prefs.run() if response == gtk.RESPONSE_OK: #make any updates based on changed preferences here self.preferences = prefs.get_preferences() prefs.destroy() def quit(self, widget, data=None): """quit - signal handler for closing the XratersWindow""" self.destroy() def on_destroy(self, widget, data=None): """on_destroy - called when the XratersWindow is close. """ #clean up code for saving application state should be added here if self.isConnected: self.on_wiiDisconnect(widget, data) gtk.main_quit() def on_wiiConnect(self, widget, data=None): """Signal handler for the WiiConnect action """ self.widget('actionWiiConnect').set_sensitive(False) connectionMaker = WiiConnectionMaker(self.preferences['wiiAddress'], self.widget("statusbar"), self._connectCallback) self._accAxis.set_xlim(0, 2) gobject.idle_add(self._accCanvas.draw) connectionMaker.start() def on_wiiDisconnect(self, widget, data=None): """Signal handler for the WiiDisconnect action """ self._wiiMote.close() self._connected = False self.widget('actionDisconnect').set_sensitive(False) self.widget('actionWiiConnect').set_sensitive(True) self.widget('actionReset').set_sensitive(False) self.widget('actionPause').set_sensitive(False) self.widget('toolbutton1').set_related_action(self.widget('actionWiiConnect')) self.widget('actionSave').set_sensitive(True) self.widget('statusbar').pop(self.widget("statusbar").get_context_id('')) self._setBatteryIndicator(0) def on_Reset(self, widget, data=None): """Signal handler for the reset action """ self._resetData() self._accAxis.set_xlim(0, 2) gobject.idle_add(self._accCanvas.draw) def on_Pause(self, widge, data=None): """Signal handler for the pause action """ if not self._Paused: self.widget('actionPause').set_short_label("Un_pause") else: self.widget('actionPause').set_short_label("_Pause") self._Paused = not (self._Paused) def save(self, widget, data=None): """Signal handler for the save action """ fileName = os.sep.join([self.preferences['outputDir'], "acceleration_" + time.strftime("%Y-%m-%d_%H-%M-%S") + ".dat"]) try: with open(fileName, 'wb') as outFile: writer = csv.writer(outFile, 'excel-tab') outFile.write(writer.dialect.delimiter.join(("#time", "Ax", "Ay", "Az"))) outFile.write(writer.dialect.lineterminator) outFile.write(writer.dialect.delimiter.join(("#s", "g", "g", "g"))) outFile.write(writer.dialect.lineterminator) with self._dataLock: writer.writerows(zip(self._time, *self._accData)) except IOError as error: dialog = gtk.MessageDialog(parent = None, flags = gtk.DIALOG_DESTROY_WITH_PARENT, type = gtk.MESSAGE_ERROR, buttons = gtk.BUTTONS_OK, message_format = str(error)) dialog.set_title(error[1]) dialog.connect('response', lambda dialog, response: dialog.destroy()) dialog.show()
class PlotWindow: def __init__(self, plot, title="", lines=[], shown=False): self.plot=plot self.window=None self.vbox=None self.figure=None self.canvas=None self.axes=None self.legend=None self.show_cursors=False self.plot.shown=shown if shown: self.show() def show(self): self.vbox = gtk.VBox() self.figure = Figure(figsize=(5,4)) self.figure.set_size_inches(self.plot.figwidth, self.plot.figheight) self.window = gtk.Window() self.window.connect("destroy", self.destroy_cb) # self.window.connect("set-focus", self.set_focus_cb) self.window.connect("notify::is-active", self.window_focus_cb) self.window.add(self.vbox) self.canvas = FigureCanvas(self.figure) # a gtk.DrawingArea self.draw() self.update(limits=True) self.vbox.pack_start(self.canvas) toolbar = NavigationToolbar(self.canvas, self.window) self.vbox.pack_start(toolbar, False, False) if self.plot.window_size != (0,0): self.window.resize(self.plot.window_size[0], self.plot.window_size[1]) else: self.window.resize(400, 300) if self.plot.window_pos != (0,0): self.window.move(self.plot.window_pos[0], self.plot.window_pos[1]) self.window.set_title(self.plot.title) self.cursors, = self.axes.plot(self.plot.lines[0].get_data()[0], self.plot.lines[0].get_data()[1]) self.cursors.set_linestyle("None") self.cursors.set_markersize(10) self.cursors.set_markeredgewidth(2) self.cursors.set_markeredgecolor("k") self.cursors.set_antialiased(False) self.window.show_all() # self.plot.figwidth=self.figure.get_figwidth() # self.plot.figheight=self.figure.get_figheight() # self.pos=self.window.get_position() self.plot.shown=True def set_focus_cb(self,window,data): print "Hej!" def window_focus_cb(self,window,data): print self.plot.window_size, self.plot.window_pos print "window_focus_cb:", self.plot.title if window.get_property('is-active'): #self.plot.parent.notebook.set_current_page(1) print "is-active" if self.plot.parent.plt_combo.get_selected_data() != self.plot: print "selecting item..." self.plot.parent.plt_combo.select_item_by_data(self.plot) self.plot.window_size=self.window.get_size() self.plot.window_pos=self.window.get_position() self.plot.figwidth=self.figure.get_figwidth() self.plot.figheight=self.figure.get_figheight() def draw(self, items=None, sources=None): legend=[] print "drawing "+self.plot.title def myfmt(x,y): return 'x=%1.6g\ny=%1.6g'%(x,y) self.figure.clf() self.axes = self.figure.add_subplot(111) #self.axes = self.figure.add_axes([0.10,0.10,0.85,0.85]) #self.figure.subplots_adjust(bottom=0.15, left=0.15) self.axes.set_autoscale_on(False) self.axes.format_coord = myfmt # self.btn_axes=self.figure.add_axes([0,0,0.1,0.05], frameon=True) # self.cursor_a_btn=Button(self.btn_axes,"A") #self.selector=RectangleSelector(self.axes, self.rectangle_cb, useblit=True) self.canvas.mpl_connect('button_release_event', self.button_up_cb) #self.axes.callbacks.connect("xlim_changed",self.xlim_cb) #self.axes.callbacks.connect("ylim_changed",self.ylim_cb) self.figure.canvas.mpl_connect('pick_event',self.pick_cb) # xaxis=self.axes.get_xaxis() # yaxis=self.axes.get_yaxis() # xaxis.set_picker(axis_picker) # yaxis.set_picker(axis_picker) legend=[] for line in self.plot.lines: self.draw_line(line, draw_canvas=False) #source=line.source # if line.source is not None: # x_data, y_data=line.get_data() # line.handle, = self.axes.plot(x_data, y_data, # color=line.color, ls=line.style, # linewidth=line.width, picker=5.0) # #data_clipping=True) # line.handle.parent=line # legend.append(line.label) # #line.handle.set_label(line.label) #self.update() self.update_legend(draw_canvas=False) self.update_ticks(draw_canvas=False) self.canvas.draw() def draw_line(self, line, draw_canvas=True): #source=line.source if line.source is not None: x_data, y_data=line.get_data() line.handle, = self.axes.plot(x_data, y_data, color=line.color, ls=line.style, marker= line.marker, mew=0, linewidth=line.width, picker=5.0, label=line.label) #data_clipping=True) line.handle.parent=line #legend.append(line.label) #line.handle.set_label(line.label) #self.update() if draw_canvas: self.canvas.draw() def update_ticks(self, draw_canvas=True): xMajorFormatter = ScalarFormatter() yMajorFormatter = ScalarFormatter() xMajorFormatter.set_powerlimits((-3,4)) yMajorFormatter.set_powerlimits((-3,4)) xaxis=self.axes.get_xaxis() yaxis=self.axes.get_yaxis() xaxis.set_major_formatter(xMajorFormatter) yaxis.set_major_formatter(yMajorFormatter) if self.plot.x_majorticks_enable: xMajorLocator = MaxNLocator(self.plot.x_majorticks_maxn) xaxis.set_major_locator(xMajorLocator) else: xaxis.set_major_locator(NullLocator()) if self.plot.y_majorticks_enable: yMajorLocator = MaxNLocator(self.plot.y_majorticks_maxn) yaxis.set_major_locator(yMajorLocator) else: yaxis.set_major_locator(NullLocator()) if self.plot.x_minorticks_enable: xMinorLocator = MaxNLocator(self.plot.x_minorticks_maxn) xaxis.set_minor_locator(xMinorLocator) else: xaxis.set_minor_locator(NullLocator()) if self.plot.y_minorticks_enable: yMinorLocator = MaxNLocator(self.plot.y_minorticks_maxn) yaxis.set_minor_locator(yMinorLocator) else: yaxis.set_minor_locator(NullLocator()) self.update_margins(draw_canvas=False) if draw_canvas: self.canvas.draw() def update_margins(self, draw_canvas=True): margins={"left":0.05, "bottom":0.05} if self.plot.x_axis_label_enable: margins["bottom"]+=0.05 if self.plot.y_axis_label_enable: margins["left"]+=0.05 if self.plot.x_majorticks_enable: margins["bottom"]+=0.05 if self.plot.y_majorticks_enable: margins["left"]+=0.05 print margins self.figure.subplots_adjust(**margins) if draw_canvas: self.canvas.draw() def update_legend(self, draw_canvas=True): if self.plot.legend_enable: print "update_legend()" lines=[] labels=[] for line in self.plot.lines: labels.append(line.label) lines.append(line.handle) #line.handle.set_label(line.label) self.legend=self.axes.legend(lines, labels, loc=self.plot.legend_loc, prop=FontProperties(size=self.plot.legend_size)) self.legend.draw_frame(self.plot.legend_border) self.legend.set_picker(legend_picker) else: self.legend=None self.axes.legend_=None if draw_canvas: self.canvas.draw() def gupdate(self, source=None): """Takes care of updating relevant parts""" self.redraw(sources=[source]) for part in parts: if part == "all": self.draw() elif part == "legend": self.update_legend() elif part == "margins": self.update_margins() elif part == "rest": self.update() def update(self, limits=True, draw_canvas=True): """Updates everything but the Lines and legend""" # if self.plot.shown: #self.draw() #if self.plot.legend_enable: # self.update_legend() if self.plot.x_axis_label_enable: self.axes.set_xlabel(self.plot.x_axis_label) else: self.axes.set_xlabel("") if self.plot.y_axis_label_enable: self.axes.set_ylabel(self.plot.y_axis_label) else: self.axes.set_ylabel("") if self.plot.x_log_enable: self.axes.set_xscale("log") else: self.axes.set_xscale("linear") if self.plot.y_log_enable: self.axes.set_yscale("log") else: self.axes.set_yscale("linear") xaxis=self.axes.get_xaxis() xaxis.grid(self.plot.x_grid_enable, which="major") yaxis=self.axes.get_yaxis() yaxis.grid(self.plot.y_grid_enable, which="major") if limits: extr=self.plot.get_extremes() print "sxtr:", extr if len(extr) == 4: print "extr:", extr y_pad=(extr[3]-extr[2])*0.05 #self.axes.set_xlim(extr[0], extr[1]) #self.axes.set_ylim(extr[2]-y_pad, extr[3]+y_pad) if self.plot.xlim_enable: print "xlim" self.axes.set_xlim(self.plot.xlim_min, self.plot.xlim_max, emit=False) else: self.axes.set_xlim(#map(lambda x: round_to_n(x, 5), extr[0], extr[1]) #) if self.plot.ylim_enable: self.axes.set_ylim(self.plot.ylim_min, self.plot.ylim_max, emit=False) else: y_limits=(extr[2], extr[3])#)#map(lambda y: round_to_n(y, 5), y_pad=(y_limits[1]-y_limits[0])/20 self.axes.set_ylim(y_limits[0]-y_pad, y_limits[1]+y_pad) try: mpl_code=compile(self.plot.mpl_commands,'<string>','exec') eval(mpl_code, None, {"figure": self.figure, "axes": self.axes, "legend": self.legend, "s": self.plot.parent.source_list[:], "p": self.plot.parent.plt_combo.get_model_items().values(), "plot": self.plot}) except: print "Invalid MPL code!" if draw_canvas: self.canvas.draw() def redraw(self, sources, draw_canvas=True): if sources != []: lines=[] for line in self.plot.lines: if line.source in sources and line not in lines: lines.append(line) #legend=[] for line in lines: print("Redraw: "+line.source.name) source=line.source if source: x_data, y_data=line.get_data() #print x_data, y_data # if source.norm_enable: # print "NORMALIZE!" # y_data=(source.y_data-source.y_data[source.norm_min_pt])/\ # (source.y_data[source.norm_max_pt]-\ # source.y_data[source.norm_min_pt])*\ # (source.norm_max_y-source.norm_min_y)+source.norm_min_y # if line.x_scale_enable: # x_data=x_data*line.x_scale # if line.y_scale_enable: # y_data=y_data*line.y_scale # if line.x_shift_enable: # x_data=x_data+line.x_shift # if line.y_shift_enable: # y_data=y_data+line.y_shift # if source.shift_enable: # x_data=source.x_data+source.shift line.handle.set_data(x_data, y_data) line.update_extremes() line.handle.set_color(line.color) line.handle.set_linewidth(line.width) line.handle.set_marker(line.marker) try: s=self.plot.parent.source_list.get_selected_rows()[0] except: pass else: if self.show_cursors and s.norm_enable: self.cursors.set_data( #s.x_data, s.y_data) [s.x_data[s.norm_min_pt], s.x_data[s.norm_max_pt]], [s.norm_min_y, s.norm_max_y]) self.cursors.set_marker('+') else: self.cursors.set_marker("None") #print "getting axis limits" extr=self.plot.get_extremes() if not self.plot.xlim_enable: self.axes.set_xlim(extr[0], extr[1]) if not self.plot.ylim_enable: y_pad=(extr[3]-extr[2])*0.05 self.axes.set_ylim(extr[2]-y_pad, extr[3]+y_pad) #self.axes.redraw_in_frame() #???? if draw_canvas: self.canvas.draw() def destroy_cb(self, widget): self.plot.shown=False #TreeDisplay.update_plot_state() #self.pos=self.window.get_position() #self.size=self.window.get_size() #print self.pos self.window.destroy() #self.plot.shown=False self.plot.parent.shown.update(False) #self.plot.parent.shown=False #self.plot.update_plot_info() #callbacks def rectangle_cb(self, event1, event2): print event1.xdata, event1.ydata, event2.xdata, event2.ydata self.plot.x_lim_min=event1.xdata self.plot.x_lim_max=event2.xdata self.plot.y_lim_min=event1.ydata self.plot.y_lim_max=event2.ydata self.axes.set_xlim(min(event1.xdata,event2.xdata), max(event1.xdata,event2.xdata)) self.axes.set_ylim(min(event1.ydata,event2.ydata), max(event1.ydata,event2.ydata)) self.canvas.draw() def button_up_cb(self,event): self.plot.xlim_min, self.plot.xlim_max=self.axes.get_xlim() self.plot.ylim_min, self.plot.ylim_max=self.axes.get_ylim() if not self.plot.xlim_enable: self.plot.parent.xlim_min.update(self.plot.xlim_min) self.plot.parent.xlim_max.update(self.plot.xlim_max) if not self.plot.ylim_enable: self.plot.parent.ylim_min.update(self.plot.ylim_min) self.plot.parent.ylim_max.update(self.plot.ylim_max) def xlim_cb(self,event): #print "xlim changed to: "+str(self.axes.get_xlim()) self.plot.xlim_min, self.plot.xlim_max=self.axes.get_xlim() if not self.plot.xlim_enable: self.plot.parent.xlim_min.update(self.plot.xlim_min) self.plot.parent.xlim_max.update(self.plot.xlim_max) #pass def ylim_cb(self,event): #print "ylim changed to: "+str(self.axes.get_ylim()) self.plot.ylim_min, self.plot.ylim_max=self.axes.get_ylim() if not self.plot.ylim_enable: self.plot.parent.ylim_min.update(self.plot.ylim_min) self.plot.parent.ylim_max.update(self.plot.ylim_max) #pass def pick_cb (self, event ) : print event.artist if isinstance(event.artist, Line2D): print event.artist.parent.label xdata=event.artist.get_xdata() ydata=event.artist.get_ydata() print event.ind[0] print xdata[event.ind[0]], ydata[event.ind[0]] axes_h=self.axes.get_ylim() print axes_h self.plot.parent.plot_notebook.set_current_page(0) self.plot.parent.lines_list.select(event.artist.parent) # arrow_h=0.1*(axes_h[1]-axes_h[0]) # self.axes.arrow(xdata[event.ind[0]],ydata[event.ind[0]],0,arrow_h,label="A", visible=True) # self.canvas.draw() #self.axes.arrow(0.5,0.5,0.1,0.1) if isinstance(event.artist, Legend): print "legend clicked" self.plot.parent.plot_notebook.set_current_page(2) else: print event
new_y = 0 if new_y > 100: new_y = 100 y_data.append(new_y) global frames, start_time frames += 1 if frames % 50 == 0: print frames / float(time.time() - start_time) return True pressed = False def press(event): global pressed, y_val pressed = True y_val = event.ydata canvas.mpl_connect('button_press_event', press) def release(event): global pressed, y_val pressed = False y_val = event.ydata canvas.mpl_connect('button_release_event', release) def motion(event): if pressed and event.inaxes == ax: global y_val y_val = event.ydata canvas.mpl_connect('motion_notify_event', motion) win.add(canvas) win.show_all()
class Plotter(): def __init__(self, context, data, fitfunction): self.context = context self.data = data self.fitfunction = fitfunction self.fig = Figure(figsize=(6, 4)) # create fig self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea self.canvas.set_size_request(600, 400) # set min size self.markers = [ '.', ',', '+', 'x', '|', '_', 'o', 'v', '^', '<', '>', '8', 's', 'p', '*', 'h', 'H', 'D', 'd' ] self.colors = [ 'black', 'blue', 'green', 'red', 'cyan', 'magenta', 'yellow', 'purple', 'white' ] self.pstyle = [ 'bmh', 's', '6', 'red', '0.8', 'black', '2', 'black', '0.3', '', '25', '', '', '20', '15', '', '', '20', '15' ] self.styledict = {} self.styledict["style"] = 'bmh' self.styledict["point_style"] = 's' self.styledict["point_size"] = '6' self.styledict["point_color"] = 'red' self.styledict["point_alpha"] = '0.8' self.styledict["line_color"] = 'black' self.styledict["line_width"] = '2' self.styledict["band_color"] = 'black' self.styledict["band_alpha"] = '0.3' self.styledict["title_size"] = '25' self.styledict["xtitle_size"] = '20' self.styledict["xlabel_size"] = '15' self.styledict["ytitle_size"] = '20' self.styledict["ylabel_size"] = '15' self.nselec = [1, 12, 5, 3, -1, 0, -1, 0, -1, -1, -1, -1, -1, -1] self.plot_labels = [] self.plot_labels.append(data.labels[3] + " vs " + data.labels[0]) # plot title self.plot_labels.append(data.labels[0]) # x-axis title self.plot_labels.append(data.labels[3]) # y-axis title self.plot_labels.append("[Gy]") # x-axis unit self.plot_labels.append(" ") # y-axis unit #print plt.style.available self.fit_toggle = 'active' self.points_toggle = 1 self.function_toggle = 1 self.err_toggle = 1 self.ci_func_toggle = 1 self.ci_points_toggle = 1 toolbar = NavigationToolbar(self.canvas, self) toolbarbox = gtk.HBox() image = gtk.Image() image.set_from_stock(gtk.STOCK_PROPERTIES, gtk.ICON_SIZE_LARGE_TOOLBAR) options_button = gtk.Button() options_button.add(image) image2 = gtk.Image() image2.set_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_LARGE_TOOLBAR) refresh_button = gtk.Button() refresh_button.add(image2) toolbarbox.pack_start(toolbar, True, True) toolbarbox.pack_end(options_button, False, True) toolbarbox.pack_end(refresh_button, False, True) self.vbox = gtk.VBox() self.vbox.pack_start(toolbarbox, False, False) self.vbox.pack_start(self.canvas, True, True) # signals self.canvas.mpl_connect('pick_event', self.on_pick) options_button.connect('clicked', self.mpl_options) refresh_button.connect('clicked', self.on_refresh_clicked) def on_pick(self, event): artist = event.artist xmouse, ymouse = event.mouseevent.xdata, event.mouseevent.ydata x, y = artist.get_xdata(), artist.get_ydata() ind = event.ind print 'Artist picked:', event.artist print '{} vertices picked'.format(len(ind)) print 'Pick between vertices {} and {}'.format(min(ind), max(ind)) print 'x, y of mouse: {:.2f},{:.2f}'.format(xmouse, ymouse) print 'Data point:', x[ind[0]], y[ind[0]] print self.context.log('Data point:\t ' + str(x[ind[0]]) + '\t' + str(y[ind[0]])) self.context.treeview.treeview.set_cursor(min(ind)) self.context.treeview.treeview.grab_focus() def mpl_options(self, button): """Create GTKDialog containing options for plotting and connect signals.""" mpl_options_dialog = MPLOptions(self.context, self) def on_refresh_clicked(self, button): """Refresh canvas - plot everything again""" self.plotting() def plotvline(self, **kwargs): self.ax1.axvline(**kwargs) def plothline(self, **kwargs): self.ax1.axhline(**kwargs) def replot(self): self.canvas.draw() def plotting(self): """Generating matplotlib canvas""" plt.style.use(self.pstyle[0]) self.ax1 = self.fig.add_subplot(111) self.ax1.clear() if self.points_toggle == 1: self.ax1.errorbar(self.data.get_xdata(), self.data.get_ydata(), self.data.get_yerr(), fmt='none', ecolor='black', elinewidth=0.5, capsize=0.5, capthick=0.5) self.ax1.plot(self.data.get_xdata(), self.data.get_ydata(), color=self.pstyle[3], label=self.data.labels[3], marker=self.pstyle[1], alpha=float(self.pstyle[4]), linestyle='None', markersize=float(self.pstyle[2]), picker=float(self.pstyle[2])) self.ax1.set_title(self.plot_labels[0], fontsize=self.pstyle[10]) self.ax1.set_xlabel(self.plot_labels[1] + self.plot_labels[3], fontsize=int(self.pstyle[13])) self.ax1.set_ylabel(self.plot_labels[2] + self.plot_labels[4], fontsize=int(self.pstyle[17])) self.ax1.tick_params(axis='x', which='both', labelsize=int(self.pstyle[14])) self.ax1.tick_params(axis='y', which='both', labelsize=int(self.pstyle[18])) x = np.arange(-0.1, max(20, max(self.data.get_xdata())) * 1.1, 0.05) if (self.fit_toggle == 'active'): if len(self.data.get_xdata()) >= 3: print "before fit", self.fitfunction.params print "before fit", self.fitfunction.params print "xdata", self.data.get_xdata() print "ydata", self.data.get_ydata() self.fitfunction.fit_function(self.data.get_xdata(), self.data.get_ydata(), self.data.get_yerr()) print "after fit", self.fitfunction.params print "after fit", self.fitfunction.params self.context.functiontab.function_changed() else: self.context.log("Too few data to fit the function!") if self.function_toggle == 1: y = self.fitfunction.func(x, self.fitfunction.params) self.ax1.plot(x, y, color=self.pstyle[5], marker='.', linestyle='None', markersize=float(self.pstyle[6])) if self.ci_func_toggle == 1 and self.fit_toggle == 'active': conf = confidence(x, self.data.get_xdata(), len(x), np.mean(self.data.get_xdata()), self.fitfunction.dof, self.fitfunction.rmse) upper = self.fitfunction.func(x, self.fitfunction.params) + conf lower = self.fitfunction.func(x, self.fitfunction.params) - conf self.ax1.fill_between(x, lower, upper, facecolor=self.pstyle[7], alpha=float(self.pstyle[8])) if self.ci_points_toggle == 1: upper = self.fitfunction.func( x, self.fitfunction.params) + confidence_points( x, self.fitfunction.std_err) lower = self.fitfunction.func( x, self.fitfunction.params) - confidence_points( x, self.fitfunction.std_err) self.ax1.fill_between(x, lower, upper, facecolor='blue', alpha=float(self.pstyle[8])) if self.err_toggle == 1: upper = self.fitfunction.func( x, self.fitfunction.params) + uncertainty( x, self.fitfunction.std_err) lower = self.fitfunction.func( x, self.fitfunction.params) - uncertainty( x, self.fitfunction.std_err) self.ax1.fill_between(x, lower, upper, facecolor='green', alpha=float(self.pstyle[8])) self.fig.subplots_adjust(left=0.13, right=0.96, top=0.91, bottom=0.13, hspace=0.04) self.canvas.draw() print self.fitfunction.params print self.fitfunction.std_err
def __init__(self): # assign gtk-Layout builder = gtk.Builder() builder.add_from_file("panoptikum.glade") builder.connect_signals(self) self.window = builder.get_object("window1") self.windowMessage = builder.get_object("messagedialog1") self.filechooserProject = builder.get_object("filechooserdialog1") self.filefilter = builder.get_object("filefilter1") self.filefilter.add_pattern("*.cfg") self.large_atom_check_button = builder.get_object("large_atom_check_button") self.live_mode_check_button = builder.get_object("live_mode_check_button") self.roiOnly_check_button = builder.get_object("roiOnly_check_button") self.sameID_check_button = builder.get_object("sameID_check_button") self.radio_buttons_imageCategory = builder.get_object("action1") self.window.connect("destroy", self.__del__) self.statusbar = builder.get_object("statusbar1") self.hbox_Rb = builder.get_object("hboxRb") self.vbox_Rb = builder.get_object("vboxRb") self.vbox_RbLast10 = builder.get_object("vboxRbLast10") self.hbox_Li = builder.get_object("hboxLi") self.vbox_Li = builder.get_object("vboxLi") self.www_Rb = builder.get_object("togglebuttonRbWww") self.www_Li = builder.get_object("togglebuttonLiWww") # global Variables self.MessageType = "N_Li" self.maxImageSize = array([0, 1392, 0, 1040]) ######### TODO ############ """ self.TEST = builder.get_object('filechooserbutton1Rb') self.TEST2 = builder.get_object('entry1') #import time #self.time_start = 0 #self.time_end = 0 try: print p['pixelSizeTextField'].get_value() print self.TEST.get_filename() self.TEST.set_filename('rb_recenta.fit') self.TEST2.set_text(str(p['part'])[1:-1]) except: pass """ """ self.time_start = time.clock() self.time_end = time.clock() print self.time_end - self.time_start """ ######### TODO ############ # matplotlib self.whiteCMap = loadColormap.whiteCMap() self.initNav() self.shiftPressed = False # Rb __init__ self.figure_Rb = plt.figure() gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1]) ax1 = plt.subplot(gs[0]) ax1.set_xlabel(u"\u00b5m") ax1.set_ylabel(u"\u00b5m") ax1.xaxis.set_label_coords(0.97, -0.06) ax3 = plt.subplot(gs[1]) ax3.xaxis.set_label_coords(0.97, -0.16) canvas_Rb = FigCanvas(self.figure_Rb) plt.subplots_adjust(hspace=0.25, bottom=0.05, right=0.95) nav_Rb = Nav(canvas_Rb, self.window) self.vbox_Rb.pack_start(nav_Rb, False, False) self.vbox_Rb.pack_start(canvas_Rb) self.figure_RbLast10 = plt.figure() self.ax1Last10 = plt.subplot(111) self.canvas_RbLast10 = FigCanvas(self.figure_RbLast10) self.vbox_RbLast10.pack_start(self.canvas_RbLast10) RbValues2calc = [ "N_Rb", "T_Rb", "fwhmV_Rb", "fwhmH_Rb", "PosV_Rb", "PosH_Rb", "AmpV_Rb", "AmpH_Rb", "OffV_Rb", "OffH_Rb", "______AUTOMATISIERUNG_", "AUTO_N_POS", "AUTO_STEP_POS", "AUTO_START", "AUTO_STEP", "AUTO_BREAK", "ABB_TOF_RB", ] RbIndexLst = [s.lower().strip("_" + "rb") for s in RbValues2calc] self.RbParameters = { "pixelSize": 6.57e-6, "pixelSizeTextField": builder.get_object("spinbutton1"), "axScale": 1e6, "species": "Rb", "folder": "F:\\INBOX\\Apogee\\", "filenames": ["rb_recenta.fit", "rb_recentb.fit", "rb_recentc.fit"], "adwinfile": "..\\ADwin\\adwin_code_recent.acm", "savefilename": "rb_result.png", "fullFrame": zeros(2), "partAtomCount": array([550, 750, 500, 800]), "partLumCorr": array([550, 750, 800, 950]), "part": self.maxImageSize, "xylim": [(0, 6826), (9138, 0)], "Marker1Pos": (0, 0), "Marker2Pos": (0, 0), "imageAx": ax1, "linescanAx": ax3, "canvasObj": canvas_Rb, "ODmaxAuto": builder.get_object("checkbuttonRbAutoOD"), "ODmaxLabel": builder.get_object("labelRbOD"), "ODmax": builder.get_object("hscaleRbOD"), "adwinID": builder.get_object("adwinIDRb"), "imageCategory": "opt. Dichte", "values2calc": RbValues2calc, "indexLst": RbIndexLst, "last10": pd.DataFrame(index=RbIndexLst), } # Li __init__ self.figure_Li = plt.figure() gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1]) ax0 = plt.subplot(gs[0]) ax0.set_xlabel(u"\u00b5m") ax0.set_ylabel(u"\u00b5m") ax0.xaxis.set_label_coords(0.97, -0.06) ax2 = plt.subplot(gs[1]) ax2.xaxis.set_label_coords(0.97, -0.16) canvas_Li = FigCanvas(self.figure_Li) plt.subplots_adjust(hspace=0.25, bottom=0.05, right=0.95) nav_Li = Nav(canvas_Li, self.window) self.vbox_Li.pack_start(nav_Li, False, False) self.vbox_Li.pack_start(canvas_Li) LiValues2calc = [ "N_Li", "T_Li", "fwhmV_Li", "fwhmH_Li", "PosV_Li", "PosH_Li", "AmpV_Li", "AmpH_Li", "OffV_Li", "OffH_Li", "______AUTOMATISIERUNG_", "AUTO_N_POS", "AUTO_STEP_POS", "AUTO_START", "AUTO_STEP", "AUTO_BREAK", "ABB_TOF_LI", ] LiIndexLst = [s.lower().strip("_" + "li") for s in LiValues2calc] self.LiParameters = { "pixelSize": 6.57e-6, "axScale": 1e6, "species": "Li", "folder": "F:\\INBOX\\Apogee\\", "filenames": ["li_recenta.fit", "li_recentb.fit", "li_recentc.fit"], "adwinfile": "..\\ADwin\\adwin_code_recent.acm", "savefilename": "li_result.png", "fullFrame": zeros(2), "partAtomCount": array([550, 750, 500, 800]), "partLumCorr": array([550, 750, 800, 950]), "part": self.maxImageSize, "xylim": [(0, 6826), (9138, 0)], "Marker1Pos": (0, 0), "Marker2Pos": (0, 0), "imageAx": ax0, "linescanAx": ax2, "canvasObj": canvas_Li, "ODmaxAuto": builder.get_object("checkbuttonLiAutoOD"), "ODmaxLabel": builder.get_object("labelLiOD"), "ODmax": builder.get_object("hscaleLiOD"), "adwinID": builder.get_object("adwinIDLi"), "imageCategory": "opt. Dichte", "values2calc": LiValues2calc, "indexLst": LiIndexLst, "last10": pd.DataFrame(index=LiIndexLst), } # reload Parameters of last Session try: with open("restoreLastSession.pickle", "rb") as infile: parameterFromStorage = pickle.load(infile) self.RbParameters["part"] = parameterFromStorage[0] self.RbParameters["partAtomCount"] = parameterFromStorage[1] self.RbParameters["partLumCorr"] = parameterFromStorage[2] self.RbParameters["xylim"] = parameterFromStorage[3] self.RbParameters["Marker1Pos"] = parameterFromStorage[4] self.RbParameters["Marker2Pos"] = parameterFromStorage[5] self.LiParameters["part"] = parameterFromStorage[6] self.LiParameters["partAtomCount"] = parameterFromStorage[7] self.LiParameters["partLumCorr"] = parameterFromStorage[8] self.LiParameters["xylim"] = parameterFromStorage[9] self.LiParameters["Marker1Pos"] = parameterFromStorage[10] self.LiParameters["Marker2Pos"] = parameterFromStorage[11] except: print "Cannot load last Session!" # set working directory os.chdir(self.RbParameters["folder"]) # draw matplotlib stuff self.initLines(self.RbParameters) self.initLines(self.LiParameters) self.updateFullFrameImage(self.RbParameters) self.updateFullFrameImage(self.LiParameters) self.last10Rb = self.drawImageArea(self.RbParameters) self.last10Li = self.drawImageArea(self.LiParameters) # show gtk-window self.window.set_default_size(1024, 800) self.window.set_size_request(600, 800) self.window.set_title("Panoptikum - LiRb-Lab Image Analyse") self.window.show_all() # self.statusbar1_text_pushed('Li image updated... waiting for images...') # GTK-event handlers self.window.connect("key_press_event", self.on_key_press) self.window.connect("key_release_event", self.on_key_released) # matplotlib-event handlers canvas_Rb.mpl_connect("button_press_event", self.mouse_press_callback_Rb) canvas_Rb.mpl_connect("button_release_event", self.mouse_release_callback_Rb) canvas_Rb.mpl_connect("scroll_event", self.mouse_scrolled_callback_Rb) canvas_Li.mpl_connect("button_press_event", self.mouse_press_callback_Li) canvas_Li.mpl_connect("button_release_event", self.mouse_release_callback_Li) canvas_Li.mpl_connect("scroll_event", self.mouse_scrolled_callback_Li) rectprops = dict(facecolor="black", edgecolor="black", alpha=0.1, fill=True) self.RS_Rb = RectangleSelector( ax1, self.RectangleSelector_callback_Rb, drawtype="box", useblit=True, button=[1, 3], minspanx=10, minspany=10, spancoords="pixels", rectprops=rectprops, ) self.RS_Li = RectangleSelector( ax0, self.RectangleSelector_callback_Li, drawtype="box", useblit=True, button=[1, 3], minspanx=10, minspany=10, spancoords="pixels", rectprops=rectprops, ) # GIO-event handlers fileRb = gio.File(self.RbParameters["filenames"][-1]) self.monitorRb = fileRb.monitor_file() self.monitorRbID = self.monitorRb.connect("changed", self.file_changedRb) fileLi = gio.File("li_recentc.fit") self.monitorLi = fileLi.monitor_file() self.monitorLiID = self.monitorLi.connect("changed", self.file_changedLi)
class WindGraph(gtk.Window): def table(self, winds, subplot, step): x = [] y = [] for wind, next_wind in itertools.izip(winds, winds[1:]): u = float(wind[0]) u1 = float(next_wind[0]) while u < u1: x.append(u) y.append(float(eval(wind[1]))) u += step*(u1-u) x.append(float(winds[-1][0])) y.append(float(eval(winds[-1][1]))) subplot.plot(x, y) def weibull(self, weibull, subplot, step): shape = weibull[0] scale = weibull[1] stop = weibull[2] numargs = exponweib.numargs [a, c] = [weibull[0]] * numargs rv = exponweib(a, c, scale=weibull[1]) x = arange(start=0, stop=weibull[2], step=step/2) subplot.plot(x, rv.pdf(x)*100) def __init__(self, winds=None, weibull=None, step=0.5, title="Wind Graph", parent=None): gtk.Window.__init__(self) try: self.set_screen(parent.get_screen()) except AttributeError: self.connect('destroy', lambda *w: self.destroy()) if parent is not None: self.set_parent(parent) self.set_title(title) self.set_destroy_with_parent(True) self.set_default_size(600, 400) vbox = gtk.VBox() self.add(vbox) figure = Figure(figsize=(5,4), dpi=100) subplot = figure.add_subplot(111) subplot.set_title("Wind Distribution") subplot.set_xlabel("Speed (u) [m/s]") subplot.set_ylabel("Probability density [%]") subplot.grid(True) if winds is not None: self.table(winds, subplot, step) elif weibull is not None: self.weibull(weibull, subplot, step/2) self.canvas = FigureCanvas(figure) self.canvas.mpl_connect('key_press_event', self.on_key_event) vbox.pack_start(self.canvas) self.toolbar = NavigationToolbar(self.canvas, self) vbox.pack_start(self.toolbar, False, False) self.show_all() def on_key_event(self, event): key_press_handler(event, self.canvas, self.toolbar)
class spectrum_plotter: def __init__(self, xs, ys): self.xs=xs self.ys=ys self.win = gtk.Window() self.win.connect("destroy", lambda x: gtk.main_quit()) self.win.set_default_size(800,600) self.win.set_title("openSpectrometer") self.vbox = gtk.VBox() self.win.add(self.vbox) self.fig = Figure(figsize=(5,4), dpi=100) self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea self.ax = self.fig.add_subplot(111) self.canvas.mpl_connect('pick_event', self.onpick) self.vbox.pack_start(self.canvas) self.toolbar = NavigationToolbar(self.canvas, self.win) self.hbox = gtk.HBox() self.button=gtk.Button('Select this point as lambda max') self.button.connect("clicked", self.buttonClick) self.hbox.pack_start(self.toolbar) self.hbox.pack_start(self.button) self.vbox.pack_start(self.hbox, False, False) self.lastind = 0 self.text = self.ax.text(0.05, 0.95, 'Datapoint index selected: none', transform=self.ax.transAxes, va='top') def plot(self, *args, **kwargs): self.ax.plot(*args, **kwargs) def plotSelectable(self, *args, **kwargs): self.line=self.ax.plot(*args, **kwargs) def selectPoint(self, x, y): self.selected = self.ax.plot([x],[y], 'o', ms=20, alpha=0.4, color='yellow', visible=False) def show(self): self.win.show_all() gtk.main() def buttonClick(self): return self.lastind def onpick(self, event): if event.artist!=self.line[0]: return True N = len(event.ind) if not N: return True print 'here' if N > 1: print '%i points found!' % N print event.ind # the click locations x = event.mouseevent.xdata y = event.mouseevent.ydata dx = numpy.array(x-self.xs[event.ind],dtype=float) dy = numpy.array(y-self.ys[event.ind],dtype=float) distances = numpy.hypot(dx,dy) indmin = distances.argmin() dataind = event.ind[indmin] self.lastind = dataind self.update() def update(self): if self.lastind is None: return dataind = self.lastind self.selected[0].set_visible(True) self.selected[0].set_data(self.xs[dataind], self.ys[dataind]) # put a user function in here! self.userfunc(dataind) self.fig.canvas.draw() def userfunc(self,dataind): self.text.set_text('datapoint index selected: %d'%dataind) print 'No userfunc defined' pass
class MainView(BasePlotView, gtk.Frame): """ A Gtk Frame based plotting widget for dreampy that contains additional tool bar items for printing and adding notes """ def __init__(self, win, **kwargs): gtk.Frame.__init__(self) BasePlotView.__init__(self, **kwargs) self.win = win self.title = None #Put some stuff # self.suppress_header = kwargs.get('suppress_header', False) # self.suppress_title = kwargs.get('suppress_title', False) # self.suppress_legend = kwargs.get('suppress_legend', False) self.vbox = gtk.VBox(False, 0) self.add(self.vbox) self.sw = gtk.ScrolledWindow() self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.vbox.pack_start(self.sw, True, True, 0) self.sw.show() self.f = Figure(figsize=(5,4), dpi=100) self.canvas = FigureCanvas(self.f) # a gtk.DrawingArea self.canvas.set_size_request(400,300) self.sw.add_with_viewport (self.canvas) self.canvas.show_all() self.toolbar = NavToolBar(self.canvas, self.win) self.vbox.pack_start(self.toolbar, False, False) self.toolbar.show() self.vbox.show() # self.autoscale = True # self.xmin = None # self.xmax = None # self.ymin = None # self.ymax = None # self.image = None # self.hold_plot = False # self.keyid = None # self.filter = None # self.labelsize = 8 # self.titlesize = 10 # self.ticklabelsize = 8 # self.ticklabelweight = 'normal' # self.labelweight = 'bold' # self.titleweight = 'bold' # self.legendsize = 8 # self.legendweight = 'normal' # self.hdrlabelsize = 9 # self.hdrlabelweight = 'normal' # self.cur_axname = None self.refresh_canvas() self.show_all() #self.gtk_catchup() def gtk_catchup(self): gtk.gdk.threads_enter() while gtk.events_pending(): gtk.main_iteration() gtk.gdk.threads_leave() def create_arrow_button(self, arrow_type, shadow_type): button = gtk.Button() self.arrow = gtk.Arrow(arrow_type, shadow_type) button.add(self.arrow) button.show() self.arrow.show() return button def list_widgets_turnoff(self): self.left_button.set_sensitive(False) self.right_button.set_sensitive(False) self.ignore_button.set_sensitive(False) #if self.keyid: # self.canvas.disconnect(self.keyid) def disconnect_event(self, sig): if self.canvas: self.canvas.mpl_disconnect(sig) def connect_event(self, eventname, eventfunc): if self.canvas: self.canvas.set_flags(gtk.CAN_FOCUS) #to grab focus for keystrokes self.canvas.grab_focus() #to grab focus for keystrokes return self.canvas.mpl_connect(eventname, eventfunc) def redraw_plot(self): if self.hold_plot is False: if hasattr(self.canvas, 'show_all'): self.canvas.show_all() self.canvas.draw() self.gtk_catchup()
class Graph_viewer: def __init__(self, graph, actions=['nothing'], callback=None): """ weights : dictionary mapping name to weight kmers will be colored in rank order of weight """ self.graph = graph self.callback = callback self.window = gtk.Window() self.window.connect('destroy', lambda x: gtk.main_quit()) self.window.set_default_size(800, 600) self.window.set_title('Graph viewer') vbox = gtk.VBox() self.window.add(vbox) self.figure = Figure(figsize=(8, 6), dpi=50) self.axes = self.figure.add_subplot(111) colors = numpy.empty((len(graph.names), 3)) sizes = numpy.empty(len(graph.names)) sizes[:] = 2.0 #if weights is None: # #self.axes.plot(graph.positions[:,0], graph.positions[:,1], ',') # # colors[:,:] = [[0.0,0.0,0.0]] # #else: #names = weights.keys() #values = weights.values() ##names.sort(key=lambda x: weights[x]) #idents = numpy.array([ graph.name_to_ident[name] for name in names ]) #x = numpy.array(values, dtype='float64') x = numpy.array(graph.weights, dtype='float64') x = numpy.log(x) x -= numpy.minimum.reduce(x) x /= numpy.average(x) * 2.0 #x /= numpy.sum(x*x)*2.0/numpy.sum(x) xx = numpy.minimum(x, 1.0) #x = numpy.arange(len(graph.names)) / float(len(graph.names)) colors[:, 0] = 0.5 - xx * 0.5 colors[:, 1] = 0.75 - xx * 0.5 colors[:, 2] = 1.0 - xx * 0.5 sizes[:] = numpy.maximum(x, 1.0)**2 #*2.0 #n = 20 #for i in xrange(n): # start = i*len(names)//n # end = (i+1)*len(names)//n # if start == end: continue # # x = (1.0-float(i)/(n-1)) # position_block = graph.positions[idents[start:end]] # self.axes.scatter(position_block[:,0], # position_block[:,1], # linewidths=0, # marker='s', # s=10.0, # c=(0.0,x,x*0.5+0.5), # zorder=i) dots = Dots(graph.positions[:, 1], graph.positions[:, 0], colors, sizes) self.axes.add_artist(dots) #if len(graph.links) < 1000: # for i, (other, other_sign, other_travel) in enumerate(graph.links): # for j in other: # if j > i: # self.axes.plot([graph.positions[i,0],graph.positions[j,0]], # [graph.positions[i,1],graph.positions[j,1]], # 'k-') self.axes.axis('scaled') self.axes.set_xlim(0.0, numpy.maximum.reduce(graph.positions[:, 0]) * 1.1) self.axes.set_ylim(0.0, numpy.maximum.reduce(graph.positions[:, 1]) * 1.1) self.figure.subplots_adjust(top=0.99, bottom=0.05, right=0.99, left=0.05) #pylab.connect('button_press_event', self._on_click) self.annotation_pylab = [] self.clear_annotation() self.canvas = FigureCanvas(self.figure) # a gtk.DrawingArea self.canvas.mpl_connect('button_press_event', self._on_down) self.canvas.mpl_connect('button_release_event', self._on_up) vbox.pack_start(self.canvas) hbox = gtk.HBox() vbox.pack_start(hbox, False, False, 10) label = gtk.Label('Middle click:') hbox.pack_start(label, False, False, 5) self.radios = {} last = None for action in actions: radio = gtk.RadioButton(group=last, label=action) last = radio self.radios[action] = radio hbox.pack_start(radio, False, False, 5) label = gtk.Label('Right click: clear') hbox.pack_end(label, False, False, 5) self.radios[actions[0]].set_active(True) toolbar = NavigationToolbar(self.canvas, self.window) vbox.pack_start(toolbar, False, False) def run(self): self.window.show_all() gtk.main() def clear_annotation(self): self.annotation = {} def label(self, name, label): ident = self.graph.name_to_ident[name] self.axes.text(self.graph.positions[ident, 0], self.graph.positions[ident, 1], label, horizontalalignment='center', verticalalignment='bottom', zorder=100000) def arrow(self, names, label): positions = [ self.graph.positions[self.graph.name_to_ident[name]] for name in names if self.graph.has(name) ] if not positions: return #Error? max_positions = max(4, (len(positions) + 29) // 30) #20 if len(positions) > max_positions: positions = [ positions[i * (len(positions) - 1) // (max_positions - 1)] for i in xrange(max_positions) ] arrow = Arrow(positions, label, True) #names = [ name for name in names if self.graph.has(name) ] # #if len(names) < 2: return #Error? # #ident1 = self.graph.name_to_ident[names[0]] #ident2 = self.graph.name_to_ident[names[-1]] # #arrow = Arrow(self.graph.positions[ident1], # self.graph.positions[ident2], # label, # True) self.axes.add_artist(arrow) def annotate(self, name, mass, r, g, b): r *= mass g *= mass b *= mass old_mass, old_r, old_g, old_b = self.annotation.get( name, (0.0, 0.0, 0.0, 0.0)) self.annotation[name] = (old_mass + mass, old_r + r, old_g + g, old_b + b) def refresh_annotation(self): while self.annotation_pylab: item = self.annotation_pylab.pop(-1) item.remove() xs = [] ys = [] colors = [] sizes = [] for name in self.annotation: mass, r, g, b = self.annotation[name] if not mass: continue ident = self.graph.name_to_ident[name] xs.append(self.graph.positions[ident, 0]) ys.append(self.graph.positions[ident, 1]) colors.append((r / mass, g / mass, b / mass)) sizes.append(mass) if xs: #thing = self.axes.scatter( # xs, # ys, # s=sizes, # c=colors, # linewidths=0, # marker='s', # zorder=10000) thing = Dots(numpy.array(ys), numpy.array(xs), numpy.array(colors), numpy.array(sizes), zorder=2) self.axes.add_artist(thing) self.annotation_pylab.append(thing) self.canvas.draw() def name_from_position(self, x, y): xoff = self.graph.positions[:, 0] - x yoff = self.graph.positions[:, 1] - y dist2 = xoff * xoff + yoff * yoff best = numpy.argmin(dist2) return self.graph.names[best] def _on_down(self, event): self.down_name = self.name_from_position(event.xdata, event.ydata) def _on_up(self, event): if event.inaxes and event.button == 3: self.clear_annotation() self.refresh_annotation() elif event.inaxes and event.button == 2: name = self.name_from_position(event.xdata, event.ydata) if self.callback: action = None for item in self.radios: if self.radios[item].get_active(): action = item self.callback(self, action, self.down_name, name) self.refresh_annotation() del self.down_name
class SensorWindow(object): def __init__(self, mainThread, gladefile = 'sensor_window.glade'): self.builder = gtk.Builder() self.builder.add_from_file(gladefile) self.builder.connect_signals(self) self._stopped = False self.mainThread = mainThread self.fig = plt.figure() self.numLines = 1 # lines plot self.ax = self.fig.add_subplot(111) self.ax.set_xlabel('Time') self.ax.set_ylabel('Power') self.ax.xaxis.set_animated(True) self.ax.yaxis.set_animated(True) self.ax.set_title('Light Intensity') self.ax.grid(True) self.start = time.time() self.background1 = None self.prev_time = self.start self.prev_pixel_offset = 0 self.x0 = 0 self.value = [0] * self.numLines self.ax.set_ylim(-1, 256) self.lines = [] for i in range(self.numLines): line, = self.ax.plot([], [], animated = True, lw = 2) self.lines.append(line) self.canvas = FigureCanvas(self.fig) self.graphview = self.builder.get_object("box2") self.graphview.pack_start(self.canvas) self.graphview.reorder_child(self.canvas, 0) self.img = self.builder.get_object("image1") self.img.set_from_file("off.svg") self.lamp = False self.canvas.show() gobject.idle_add(self.update_line) self.canvas.mpl_connect('draw_event', self.on_draw) self.barpath = [] def close_window(self, obj): print "closing window" self.builder.get_object("window1").destroy() def destroy_callback(self, obj): print "destroying window" self.mainThread.stop() self._stopped = True def close_from_mainthread(self): print "close from mainthread" self.builder.get_object("window1").destroy() def toggle_lamp(self): print "toggle lamp!!" self.img = self.builder.get_object("image1") if(self.lamp): self.lamp = False self.img.set_from_file("off.svg") else: self.lamp = True self.img.set_from_file("on.svg") def update_line(self, *args): if self._stopped: self.destroy_callback(None) return False if self.background1 is None: return True cur_time = time.time() pixel_offset = int((cur_time - self.start) * 40.) dx_pixel = pixel_offset - self.prev_pixel_offset self.prev_pixel_offset = pixel_offset dx_data = self.get_dx_data(dx_pixel) #cur_time - self.prev_time) x0 = self.x0 self.x0 += dx_data self.prev_time = cur_time self.ax.set_xlim(self.x0-2, self.x0+0.1) # restore background which will plot lines from previous plots self.restore_background_shifted(dx_pixel) #x0, self.x0) # now plot line segment within [x0, x0+dx_data], # Note that we're only plotting a line between [x0, x0+dx_data]. xx = np.array([x0, self.x0]) for i in range(len(self.lines)): line = self.lines[i] line.set_xdata(xx) # the for loop below could be improved by using collection. line.set_ydata(np.array([self.value[i], self.value[i]])) self.ax.draw_artist(line) self.background2 = self.canvas.copy_from_bbox(self.get_bg_bbox()) self.ax.draw_artist(self.ax.xaxis) self.ax.draw_artist(self.ax.yaxis) self.canvas.blit(self.ax.get_figure().bbox) return True def get_dx_data(self, dx_pixel): tp = self.ax.transData.inverted().transform_point x0, y0 = tp((0, 0)) x1, y1 = tp((dx_pixel, 0)) return (x1 - x0) def get_bg_bbox(self): return self.ax.bbox.padded(-3) def save_bg(self): self.background1 = self.canvas.copy_from_bbox(self.ax.get_figure().bbox) self.background2 = self.canvas.copy_from_bbox(self.get_bg_bbox()) def on_draw(self, *args): self.save_bg() return False def restore_background_shifted(self, dx_pixel): """ restore bacground shifted by dx in data coordinate. This only works if the data coordinate system is linear. """ # restore the clean slate background self.canvas.restore_region(self.background1) # restore subregion (x1+dx, y1, x2, y2) of the second bg # in a offset position (x1-dx, y1) x1, y1, x2, y2 = self.background2.get_extents() self.canvas.restore_region(self.background2, bbox=(x1+dx_pixel, y1, x2, y2), xy=(x1-dx_pixel, y1)) return dx_pixel def update(self, data): if type(data) == ListType: assert(len(self.lines) == len(data)) self.value = data else: assert(len(self.lines) == 1) self.value = [data]
class spectrum_plotter: def __init__(self, xs, ys): self.xs=xs self.ys=ys self.win = gtk.Window() self.win.connect("destroy", lambda x: gtk.main_quit()) self.win.set_default_size(800,600) self.win.set_title("openSpectrometer") self.vbox = gtk.VBox() self.win.add(self.vbox) self.fig = Figure(figsize=(5,4), dpi=100) self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea self.ax = self.fig.add_subplot(111) self.canvas.mpl_connect('pick_event', self.onpick) self.vbox.pack_start(self.canvas) self.toolbar = NavigationToolbar(self.canvas, self.win) self.hbox = gtk.HBox() self.button=gtk.Button('Select this point as lambda max') self.button.connect("clicked", self.buttonClick) self.hbox.pack_start(self.toolbar) self.hbox.pack_start(self.button) self.vbox.pack_start(self.hbox, False, False) self.lastind = 0 self.text = self.ax.text(0.05, 0.95, 'Datapoint index selected: none', transform=self.ax.transAxes, va='top') def plot(self, *args, **kwargs): self.ax.plot(*args, **kwargs) def plotSelectable(self, *args, **kwargs): self.line=self.ax.plot(*args, **kwargs) def selectPoint(self, x, y): self.selected = self.ax.plot([x],[y], 'o', ms=20, alpha=0.4, color='yellow', visible=False) def show(self): self.win.show_all() gtk.main() return self.lastind def buttonClick(self, event): self.win.hide_all() gtk.main_quit() def onpick(self, event): if event.artist!=self.line[0]: return True N = len(event.ind) if not N: return True if N > 1: print '%i points found!' % N # the click locations x = event.mouseevent.xdata y = event.mouseevent.ydata dx = numpy.array(x-self.xs[event.ind],dtype=float) dy = numpy.array(y-self.ys[event.ind],dtype=float) distances = numpy.hypot(dx,dy) indmin = distances.argmin() dataind = event.ind[indmin] self.lastind = dataind self.update() def update(self): if self.lastind is None: return dataind = self.lastind self.selected[0].set_visible(True) self.selected[0].set_data(self.xs[dataind], self.ys[dataind]) # put a user function in here! self.userfunc(dataind) self.fig.canvas.draw() def userfunc(self,dataind): self.text.set_text('datapoint index selected: %d'%dataind) print 'No userfunc defined' pass
class PopUpImage(object): def __init__(self, xdata, ydata, xlabel, ylabel, title): self.popupwin=gtk.Window() self.popupwin.set_size_request(600,550) self.popupwin.set_position(gtk.WIN_POS_CENTER) self.popupwin.set_border_width(10) self.xdata = xdata self.ydata = ydata vbox = gtk.VBox() self.fig=Figure(dpi=100) self.ax = self.fig.add_subplot(111) self.canvas = FigureCanvas(self.fig) self.main_figure_navBar = NavigationToolbar(self.canvas, self) self.cursor = Cursor(self.ax, color='k', linewidth=1, useblit=True) self.canvas.mpl_connect("button_press_event",self.on_press) self.ax.set_xlabel(xlabel, fontsize = 18) self.ax.set_ylabel(ylabel, fontsize = 18) self.ax.set_title(title, fontsize = 18) self.ax.plot(self.xdata, self.ydata, 'b-', lw=2) self.textes = [] self.plots = [] vbox.pack_start(self.main_figure_navBar, False, False, 0) vbox.pack_start(self.canvas, True, True, 2) self.popupwin.add(vbox) self.popupwin.connect("destroy", self.dest) self.popupwin.show_all() def dest(self,widget): self.popupwin.destroy() def on_press(self, event): if event.inaxes == self.ax and event.button==3: self.clear_notes() xc = event.xdata #***** Find the closest x value ***** residuel = self.xdata - xc residuel = N.abs(residuel) j = N.argmin(residuel) #y = self.ydata[i-1:i+1] #yc= y.max() #j = N.where(self.ydata == yc) #j = j[0][0] xc= self.xdata[j] x_fit = self.xdata[j-3:j+3] y_fit = self.ydata[j-3:j+3] fitted_param, fitted_data = fit(x_fit, y_fit, xc, True) x_fit = N.linspace(x_fit.min(), x_fit.max(), 200) y_fit = psdVoigt(fitted_param, x_fit) period = fitted_param['xc'].value std_err= fitted_param['xc'].stderr p = self.ax.plot(x_fit, y_fit,'r-') p2 = self.ax.axvline(period,color='green',lw=2) txt=self.ax.text(0.05, 0.9, 'Period = %.4f +- %.4f (nm)'%(period, std_err), transform = self.ax.transAxes, color='red') self.textes.append(txt) self.plots.append(p[0]) self.plots.append(p2) elif event.inaxes == self.ax and event.button==2: dif = N.diff(self.ydata) dif = dif/dif.max() p3 = self.ax.plot(dif,'r-') self.plots.append(p3[0]) self.canvas.draw() def clear_notes(self): if len(self.textes)>0: for t in self.textes: t.remove() if len(self.plots)>0: for p in self.plots: p.remove() self.textes = [] self.plots = []
class gui: """Main application class.""" def __init__(self): self.builder=gtk.Builder() self.dsizes=[] self.builder.add_from_file("gladeb.glade") myscreen=gtk.gdk.Screen() self.screensize=(myscreen.get_width(),myscreen.get_height()) print self.screensize dic={"mainwindowdestroy" : gtk.main_quit,"openwindow":self.openWindow, "closewindow":self.closeWindow, "devicenumchanged":self.changeDeviceNumber, "btnclicked":self.btnclicked, "fileset":self.fileSet, "mctoolbarbtn":self.mctoolbarClicked, "trkeypress":self.getKeyPress} self.builder.connect_signals(dic) #Initialise defaults #Camera config window self.devicenumcb = gtk.combo_box_new_text() self.builder.get_object("combospace").add(self.devicenumcb) self.builder.get_object("combospace").show_all() self.devicenumcb.append_text('0') self.devicenumcb.append_text('1') self.devicenumcb.set_active(0) self.devicenumcb.connect("changed", self.changeDeviceNumber) self.figurecc=Figure() self.axiscc=self.figurecc.add_subplot(111) try: self.cap = cv2.VideoCapture(self.devicenumcb.get_active()) except: pass self.pixelthreshold=0 #Monitor config window self.tolerance=25 self.blocksize=7 self.d1size=(80,50) self.d2size=None self.builder.get_object("tolerance").set_text("25") self.builder.get_object("blocksize").set_text("7") self.builder.get_object("d1x").set_text("50") self.builder.get_object("d1y").set_text("80") self.figuremc=Figure() self.axismc=self.figuremc.add_subplot(111) self.figuretmc=Figure() self.axistmc=self.figuretmc.add_subplot(111) self.mcflipx=False self.mcflipy=False self.clickstate="none" self.crop1=None self.crop2=None self.builder.get_object("tolerance").set_editable(True) self.builder.get_object("blocksize").set_editable(True) self.builder.get_object("d1x").set_editable(True) self.builder.get_object("d1y").set_editable(True) self.builder.get_object("d2x").set_editable(True) self.builder.get_object("d2y").set_editable(True) self.contours=[] self.dlist=[] self.trdlist=[] self.figuretr=Figure() self.axistr=self.figuretr.add_subplot(111) self.trframe=0 self.trtotal=0 self.traindict={} self.solsdict={} #General functions def fileSet(self, widget): call=gtk.Buildable.get_name(widget) if call=="monitorconfigloadfile": self.loadMonitorImage(widget.get_filename()) elif call=="trainingfilechooser": self.loadTrainingImage(widget.get_filename()) elif call=="testmcfile": self.loadMonitorImage(widget.get_filename(), testmc=True) def btnclicked(self, widget): call=gtk.Buildable.get_name(widget) if call=="resbtn": self.setResolution() elif call=="imagesavebtn": fname=self.builder.get_object("imagesavetext").get_text() if fname!="" and fname!=None: self.saveImage(fname) elif call=="videosavebtn": fname=self.builder.get_object("videosavefile").get_text() if fname!="" and fname!=None: self.saveVideo(fname) elif call=="setparameters": self.setParameters() elif call=="setdigits": self.setDigitSizes() elif call=="mcflipx": if self.mcflipx==False: self.mcflipx=True else: self.mcflipx=False self.loadMonitorImage(self.builder.get_object("monitorconfigloadfile").get_filename()) elif call=="mcflipy": if self.mcflipy==False: self.mcflipy=True else: self.mcflipy=False self.loadMonitorImage(self.builder.get_object("monitorconfigloadfile").get_filename()) elif call=="addtag": self.setClickMode("tag") elif call=="cleartags": #TODO Clear tags pass elif call=="addcontour": self.setClickMode("addcontour1") elif call=="rmcontour": self.setClickMode("rmcontour") elif call=="splitcontour": self.setClickMode("splitcontour") elif call=="cropimage": self.setClickMode("crop1") elif call=="getdigitsize": self.setClickMode("getdigit1") elif call=="tagokbtn": self.curtag=self.builder.get_object("tagname").get_text() self.builder.get_object("tagwindow").set_visible(0) self.contours.append(Contour(self.tempditem,self.tempitem,self.curtag)) if not (self.d1size in self.dsizes): self.dsizes.append(self.d1size) elif call=="tagcancelbtn": self.setClickMode("none") self.builder.get_object("tagwindow").set_visible(0) elif call=="trnext": self.trNext() elif call=="trprev": if self.trframe>0: self.trframe-=1 self.updateTrainingDataWindow() elif call=="savetrdata": fn=self.builder.get_object("trfile").get_text() f=open(fn, "w") pickle.dump(self.traindict, f) f.close() elif call=="allconts": #show all contours in monitor config window self.loadMonitorImage(self.builder.get_object("monitorconfigloadfile").get_filename(), allconts=True) elif call=="clearunsaved": #redraw only those ritems in self.contours self.drawMonitor(clearunsaved=True) elif call=="liverecord": #TODO test? Fix all parameters here #start loop to get data fn=self.builder.get_object("livefile").get_text() f=open(fn,"r") #log to f while True: self.livelist=[] #get image using current camera config ret,im=self.cap.read() #run contour detection (self.monimage,self.dlist,self.rlist)=self.getContours(a,self.d1size) #take only labelled ones for i in range(len(self.rlist)): for j in range(len(self.contours)): #if self.rlist[i]==cont.ritem: #TODO remove hidden parameters here cont=self.contours[j] if np.abs(self.rlist[i][0][0]-cont.ritem[0][0])<=4 and np.abs(self.rlist[i][0][1]-cont.ritem[0][1])<=4: #Need to append x position, label self.livelist.append((self.dlist[i],j)) #could add width, height check as well #run digit analysis #TODO - modify this for known number of digits? for item2 in self.livelist: item=item2[0][0] q=False #data = np.zeros((esize), dtype=np.uint8) esize1=self.d1size[0]*self.d1size[1] #results=[] #err=[] data=item.flatten() boolarray=(data>self.pixelthreshold) resultd=[] #print self.traindict.keys() for j in range(len(self.traindict.keys())): result=np.sum(self.traindict[j][boolarray]) #penalisation factor result-=4*np.sum(self.traindict[j][data<=self.pixelthreshold]) resultd.append(result/float(esize1)) #print resultd # sr=reversed(sorted(resultd)) # srlist=[] # for j in sr: # srlist.append(j) # err.append(srlist[0]-srlist[1]) resultf=(resultd.index(max(resultd))) #print resultf if max(resultd)<-0.1: #print "IGNORE!" q=True #print "---" #cv2.imshow("newtest",item) #cv2.waitKey(0) #Append digit to correct place #rl = {mlabel:{x:(1,q)}} #use label instead of y co-ordinate as constant if self.contours[item2[1]].label in rl.keys(): rl[self.contours[item2[1]].label][item2[0][1]]=(resultf, q) else: rl[self.contours[item2[1]].label]={item2[0][1]:(resultf,q)} #Want data structure instead of string for key in sorted(rl.iterkeys()): #print "%s: %s" % (key, mydict[key]) for key2 in sorted(rl[key].iterkeys()): string+=str(rl[key][key2][0]) #if rl[key][key2][1]==False: #create solutions dictionary #string+=str(rl[key][key2][0]) #if rl[key][key2][1]==True: #string+="?" solsdict[self.contours[item2[1]].label]=string #reconstruct labelled data for item in solsdict.keys(): f.write(item +":" + solsdict[item]) f.write("\n") #log to f def trNext(self): if self.trframe<(self.trtotal-1): self.trframe+=1 self.updateTrainingDataWindow() def openWindow(self, widget): #Make dict of widgets to functions call=gtk.Buildable.get_name(widget) if call=="opencameraconfig": self.openCameraConfig() elif call=="openimagesave": self.builder.get_object("imagesavewindow").set_visible(1) elif call=="openrecordvideo": self.builder.get_object("videosavewindow").set_visible(1) elif call=="openmonitorconfig": self.builder.get_object("monitorconfig").set_visible(1) elif call=="opentrainingdatawindow": self.builder.get_object("trainingdatawindow").set_visible(1) elif call=="openlive": self.builder.get_object("livewindow").set_visible(1) elif call=="opentmc": self.builder.get_object("testmcwindow").set_visible(1) def closeWindow(self,widget): call=gtk.Buildable.get_name(widget) if call=="closecameraconfig": self.applyCameraConfig() elif call=="imagesaveclosebtn": self.builder.get_object("imagesavewindow").set_visible(0) elif call=="closevideowindow": self.builder.get_object("videosavewindow").set_visible(0) elif call=="closemonitorconfig": self.builder.get_object("monitorconfig").set_visible(0) elif call=="closetrainingwindow": self.builder.get_object("trainingdatawindow").set_visible(0) elif call=="closelive": self.builder.get_object("livewindow").set_visible(0) elif call=="closetc": self.builder.get_object("testmcwindow").set_visible(0) #Camera config functions def openCameraConfig(self): try: self.builder.get_object("ccimgbox").remove(self.canvascc) except: pass ret,img = self.cap.read() try: img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #cv2.imshow("newtest",img) except: img=np.zeros((100,100)) self.builder.get_object("resx").set_text(str(img.shape[1])) self.builder.get_object("resy").set_text(str(img.shape[0])) self.resolution=(img.shape[1], img.shape[0]) if img.shape[1]<self.screensize[0] and img.shape[0]<self.screensize[1]: pass else: img=imresize(img, (img.shape[0]/2, img.shape[1]/2)) self.axiscc.imshow(img, cmap=cm.gray) #set scale to 0,255 somehow self.canvascc=FigureCanvasGTKAgg(self.figurecc) self.canvascc.draw() self.canvascc.show() self.builder.get_object("ccimgbox").pack_start(self.canvascc, True, True) self.builder.get_object("cameraconfig").set_visible(1) def applyCameraConfig(self): self.builder.get_object("cameraconfig").set_visible(0) def changeDeviceNumber(self, widget): self.cap = cv2.VideoCapture(self.devicenumcb.get_active()) self.openCameraConfig() def setResolution(self): x=self.builder.get_object("resx").get_text() y=self.builder.get_object("resy").get_text() self.cap.set(3,int(x)) self.cap.set(4,int(y)) self.resolution=(int(x),int(y)) self.openCameraConfig() #Image saving def saveImage(self,fname): if fname!="" or None: ret,im=self.cap.read() cv2.imwrite(fname,im) #Video saving def saveVideo(self,fname): try: if fname.lower()[-4:]!=".avi": fname=fname+".avi" except: fname=fname+".avi" video = cv2.VideoWriter(fname,CV_FOURCC(ord("D"),ord("I"),ord("V"),ord("X")), 25, self.resolution) ret,im = self.cap.read() for i in range(1000): ret,im = self.cap.read() video.write(im) video.release() #TODO: May want to chuck away last frame - perhaps do this in analysis #Monitor configuration def loadMonitorImage(self,fname, allconts=False, testmc=False): if fname[-4:].lower()==".avi": #TODO get first frame - look this up pass elif fname[-4:].lower()==".png" or fname[-4:].lower()==".jpg": a=cv2.imread(fname, 0) #note 0 implies grayscale #getcontours else: #Error pass if self.mcflipx==True and self.mcflipy==True: a=cv2.flip(a,-1) elif self.mcflipx==True and self.mcflipy==False: a=cv2.flip(a,0) if self.mcflipy==True and self.mcflipx==False: a=cv2.flip(a,1) if self.crop1!=None and self.crop2!=None: #print str(self.crop1) #print str(self.crop2) a=a[np.min([self.crop1[1],self.crop2[1]]):np.max([self.crop1[1],self.crop2[1]]),np.min([self.crop1[0],self.crop2[0]]):np.max([self.crop1[0],self.crop2[0]])] #TODO add other digit sizes if testmc==True: self.trlist=[] for dsize in self.dsizes: (self.tmonimage,self.dlist,rlist)=self.getContours(a,dsize) self.trlist+=rlist self.drawMonitorTest() else: if allconts==False: (self.monimage,self.dlist,self.rlist)=self.getContours(a,self.d1size) self.drawMonitor() else: (self.monimage,self.rlist1,self.rlist2)=self.getAllContours(a) self.drawMonitor(allconts=True) def setParameters(self): self.tolerance=int(self.builder.get_object("tolerance").get_text()) self.blocksize=int(self.builder.get_object("blocksize").get_text()) self.loadMonitorImage(self.builder.get_object("monitorconfigloadfile").get_filename()) def setDigitSizes(self): if (self.builder.get_object("d1y").get_text()!=None and self.builder.get_object("d1y").get_text()!="") and (self.builder.get_object("d1x").get_text()!="" and self.builder.get_object("d1x").get_text()!=None): self.d1size=(int(self.builder.get_object("d1y").get_text()),int(self.builder.get_object("d1x").get_text())) else: self.d1size=None if (self.builder.get_object("d2y").get_text()!=None and self.builder.get_object("d2y").get_text()!="") and (self.builder.get_object("d2x").get_text()!="" and self.builder.get_object("d2x").get_text()!=None): self.d2size=(int(self.builder.get_object("d2y").get_text()),int(self.builder.get_object("d2x").get_text())) else: self.d2size=None #Redo contours, etc. self.loadMonitorImage(self.builder.get_object("monitorconfigloadfile").get_filename()) def getContours(self,a,dsize): a=cv2.GaussianBlur(a,(3,3), 0) orig=a.copy() a=cv2.adaptiveThreshold(a, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, self.tolerance, self.blocksize) b=a.copy() contours, hierarchy = cv2.findContours(a, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS) mask = np.zeros(a.shape, dtype=np.uint8) dlist=[] output=np.zeros(b.shape,dtype=np.uint8) rlist=[] for cont in contours: br=cv2.boundingRect(cont) charray=np.zeros(dsize, dtype=np.uint8) temp=b[br[1]:br[1]+br[3], br[0]:br[0]+br[2]] if temp.shape[0]>10 and temp.shape[1]>10: temp=cv2.bitwise_not(temp) temp2=temp.copy() contours2, hierarchy = cv2.findContours(temp2, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) for cont2 in contours2: br2=cv2.boundingRect(cont2) #important hidden parameters if br2[3]<dsize[0]+20 and br2[3]>dsize[0]-20 and br2[2]<dsize[1]+20 and br2[2]>dsize[1]-60: #After cropping, edge constrains not necessary # and br2[0]>0+(temp.shape[1]/40.0) and br2[0]<temp.shape[1]-(temp.shape[1]/40.0) mask = np.zeros(temp2.shape, dtype=np.uint8) cv2.drawContours(mask,[cont2],0,255,-1) temp2=temp.copy() temp2[mask==0]=0 temp3=temp2[br2[1]:br2[1]+br2[3], br2[0]:br2[0]+br2[2]] charray=temp3.copy() charray=imresize(charray, dsize) #dlist.append((charray, br[0]+br2[0], br[1])) if br2[2]>5 and br2[3]>5: #cv2.rectangle(b, (br[0]+br2[0],br[1]+br2[1]), (br[0]+br2[0]+br2[2],br[1]+br2[1]+br2[3]), 100) dlist.append((charray, br[0]+br2[0], br[1])) rlist.append(((br[0]+br2[0], br[1]+br2[1]), br2[2], br2[3])) return (b,dlist,rlist) def getAllContours(self,a): a=cv2.GaussianBlur(a,(3,3), 0) orig=a.copy() a=cv2.adaptiveThreshold(a, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, self.tolerance, self.blocksize) b=a.copy() contours, hierarchy = cv2.findContours(a, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_KCOS) mask = np.zeros(a.shape, dtype=np.uint8) output=np.zeros(b.shape,dtype=np.uint8) rlist1=[] rlist2=[] for cont in contours: br=cv2.boundingRect(cont) rlist1.append(((br[0], br[1]), br[2], br[3])) temp=b[br[1]:br[1]+br[3], br[0]:br[0]+br[2]] if temp.shape[0]>5 and temp.shape[1]>5: temp=cv2.bitwise_not(temp) temp2=temp.copy() contours2, hierarchy = cv2.findContours(temp2, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) for cont2 in contours2: br2=cv2.boundingRect(cont2) #if br2[3]<dsize[0]+10 and br2[3]>dsize[0]-10 and br2[2]<dsize[1]+10 and br2[2]>dsize[1]-50 and br2[0]>0+(temp.shape[1]/30) and br2[0]<temp.shape[1]-(temp.shape[1]/5): mask = np.zeros(temp2.shape, dtype=np.uint8) cv2.drawContours(mask,[cont2],0,255,-1) temp2=temp.copy() temp2[mask==0]=0 temp3=temp2[br2[1]:br2[1]+br2[3], br2[0]:br2[0]+br2[2]] #dlist.append((charray, br[0]+br2[0], br[1])) if br2[2]>3 and br2[3]>3: #cv2.rectangle(b, (br[0]+br2[0],br[1]+br2[1]), (br[0]+br2[0]+br2[2],br[1]+br2[1]+br2[3]), 100) #dlist.append((charray, br[0]+br2[0], br[1])) rlist2.append(((br[0]+br2[0], br[1]+br2[1]), br2[2], br2[3])) return (b,rlist1, rlist2) def drawMonitor(self, allconts=False, clearunsaved=False): try: self.builder.get_object("monitorconfigspace").remove(self.canvasmc) self.axismc.clear() #self.builder.get_object("mctoolbar").remove(self.mctoolbar) except: pass #Add cropping self.axismc.imshow(self.monimage, cmap=cm.gray) #set scale to 0,255 somehow #Maybe this needn't be redefined for every draw - only need draw() but not drawn often anyway self.canvasmc=FigureCanvasGTKAgg(self.figuremc) self.canvasmc.draw() self.canvasmc.show() self.canvasmc.mpl_connect('motion_notify_event', self.mcHoverOnImage) self.canvasmc.mpl_connect('button_release_event', self.mcCaptureClick) self.builder.get_object("monitorconfigspace").pack_start(self.canvasmc, True, True) #TODO stop this getting so complicated if clearunsaved==False: if allconts==False: for item in self.rlist: #Structure of rlist: #rlist.append(((br[0]+br2[0], br[1]+br2[1]), br2[2], br2[3])) r=Rectangle(item[0], item[1], item[2], fill=False, color="red") #Rectangle has (lowerleft, width, height) self.axismc.add_patch(r) elif allconts==True: #allcontours for item in self.rlist1: #Structure of rlist: #rlist.append(((br[0]+br2[0], br[1]+br2[1]), br2[2], br2[3])) r=Rectangle(item[0], item[1], item[2], fill=False, color="blue") #Rectangle has (lowerleft, width, height) self.axismc.add_patch(r) for item in self.rlist2: #Structure of rlist: #rlist.append(((br[0]+br2[0], br[1]+br2[1]), br2[2], br2[3])) r=Rectangle(item[0], item[1], item[2], fill=False, color="green") #Rectangle has (lowerleft, width, height) self.axismc.add_patch(r) #Always draw saved contours in blue for ditem in self.contours: item=ditem.ritem r=Rectangle(item[0], item[1], item[2], fill=False, color="blue") self.axismc.add_patch(r) def drawMonitorTest(self): try: self.builder.get_object("tmcspace").remove(self.canvastmc) self.axistmc.clear() except: pass #Add cropping self.axistmc.imshow(self.tmonimage, cmap=cm.gray) #set scale to 0,255 somehow #Maybe this needn't be redefined for every draw - only need draw() but not drawn often anyway self.canvastmc=FigureCanvasGTKAgg(self.figuretmc) self.canvastmc.draw() self.canvastmc.show() self.builder.get_object("tmcspace").pack_start(self.canvastmc, True, True) for i in range(len(self.trlist)): for cont in self.contours: #if self.rlist[i]==cont.ritem: #TODO remove hidden parameters here if np.abs(self.trlist[i][0][0]-cont.ritem[0][0])<=4 and np.abs(self.trlist[i][0][1]-cont.ritem[0][1])<=4: item=self.trlist[i] r=Rectangle(item[0], item[1], item[2], fill=False, color="blue") self.axistmc.add_patch(r) #could add width, height check as well #Always draw saved contours in blue for ditem in self.contours: item=ditem.ritem def mcHoverOnImage(self, event): #add contour stuff here if not too expensive #find innermost contour #Cannot afford to redraw, must work out how to remove rectangle afterwards since only one at a time #TODO if event.x!=None and event.y!=None and event.xdata!=None and event.ydata!=None: pass def mcCaptureClick(self, event): #print "click" if self.clickstate=="none": pass #elif not(event.x==None or event.y==None or event.xdata==None or event.ydata==None): else: if self.clickstate=="crop1": self.crop1=(int(round(event.xdata)), int(round(event.ydata))) self.setClickMode("crop2") elif self.clickstate=="getdigit1": self.getdigit1=(int(round(event.xdata)), int(round(event.ydata))) self.setClickMode("getdigit2") elif self.clickstate=="crop2": self.crop2=(int(round(event.xdata)), int(round(event.ydata))) self.setClickMode("none") self.loadMonitorImage(self.builder.get_object("monitorconfigloadfile").get_filename()) elif self.clickstate=="getdigit2": self.getdigit2=(int(round(event.xdata)), int(round(event.ydata))) #apply stuff self.d1size=(np.abs(self.getdigit2[1]-self.getdigit1[1]),np.abs(self.getdigit2[0]-self.getdigit1[0])) self.builder.get_object("d1x").set_text(str(np.abs(self.getdigit2[0]-self.getdigit1[0]))) self.builder.get_object("d1y").set_text(str(np.abs(self.getdigit2[1]-self.getdigit1[1]))) self.setClickMode("none") self.loadMonitorImage(self.builder.get_object("monitorconfigloadfile").get_filename()) elif self.clickstate=="tag": #Check if we are inside contour, if so present label window, if not, ignore #Contours checked by rlist? coords=(int(round(event.xdata)), int(round(event.ydata))) #found=False #Find innermost not just first contour fitem=None fi=None for i in range(len(self.rlist)): item=self.rlist[i] if (coords[0] >= item[0][0]) and (coords[0] <= (item[0][0]+item[1])) and (coords[1] >= item[0][1]) and (coords[1] <= item[0][1]+item[2]): #Found contour, create contour object for final contour list if fitem==None: fitem=item fi=i else: if (item[0][0] >= fitem[0][0]) and (item[0][0]+item[1] <= (fitem[0][0]+fitem[1])) and (item[0][1] >= fitem[0][1]) and (item[0][1]+item[2] <= fitem[0][1]+fitem[2]): fitem=item fi=i if fitem!=None: self.tempitem=fitem self.tempditem=self.rlist[fi] self.builder.get_object("tagwindow").set_visible(1) #self.contours.append(Contour(item,self.curtag)) def mctoolbarClicked(self,widget): call=gtk.Buildable.get_name(widget) if call=="mczoomin": self.mcZoomIn() elif call=="mczoomout": self.mcZoomOut() elif call=="mcpanleft": self.mcPanLeft() elif call=="mcpanright": self.mcPanRight() elif call=="mcpanup": self.mcPanUp() elif call=="mcpandown": self.mcPanDown() elif call=="mcresetzoom": self.mcResetZoom() def mcZoomIn(self): xlims=self.axismc.get_xlim() ylims=self.axismc.get_ylim() xchange=abs(xlims[1]-xlims[0])*0.1 ychange=abs(ylims[1]-ylims[0])*0.1 self.axismc.set_xlim(left=xlims[0]+xchange, right=xlims[1]-xchange) self.axismc.set_ylim(top=ylims[1]+ychange, bottom=ylims[0]-ychange) self.builder.get_object("monitorconfigspace").remove(self.canvasmc) self.builder.get_object("monitorconfigspace").pack_start(self.canvasmc, True, True) def mcZoomOut(self): xlims=self.axismc.get_xlim() ylims=self.axismc.get_ylim() xchange=abs(xlims[1]-xlims[0])*0.111 ychange=abs(ylims[1]-ylims[0])*0.111 self.axismc.set_xlim(left=xlims[0]-xchange, right=xlims[1]+xchange) self.axismc.set_ylim(top=ylims[1]-ychange, bottom=ylims[0]+ychange) self.builder.get_object("monitorconfigspace").remove(self.canvasmc) self.builder.get_object("monitorconfigspace").pack_start(self.canvasmc, True, True) def mcPanLeft(self): xlims=self.axismc.get_xlim() xchange=abs(xlims[1]-xlims[0])*0.1 self.axismc.set_xlim(left=xlims[0]-xchange, right=xlims[1]-xchange) self.builder.get_object("monitorconfigspace").remove(self.canvasmc) self.builder.get_object("monitorconfigspace").pack_start(self.canvasmc, True, True) def mcPanRight(self): xlims=self.axismc.get_xlim() xchange=abs(xlims[1]-xlims[0])*0.1 self.axismc.set_xlim(left=xlims[0]+xchange, right=xlims[1]+xchange) self.builder.get_object("monitorconfigspace").remove(self.canvasmc) self.builder.get_object("monitorconfigspace").pack_start(self.canvasmc, True, True) def mcPanDown(self): ylims=self.axismc.get_ylim() ychange=abs(ylims[1]-ylims[0])*0.1 self.axismc.set_ylim(top=ylims[1]+ychange, bottom=ylims[0]+ychange) self.builder.get_object("monitorconfigspace").remove(self.canvasmc) self.builder.get_object("monitorconfigspace").pack_start(self.canvasmc, True, True) def mcPanUp(self): ylims=self.axismc.get_ylim() ychange=abs(ylims[1]-ylims[0])*0.1 self.axismc.set_ylim(top=ylims[1]-ychange, bottom=ylims[0]-ychange) self.builder.get_object("monitorconfigspace").remove(self.canvasmc) self.builder.get_object("monitorconfigspace").pack_start(self.canvasmc, True, True) def mcResetZoom(self): #Reset view to original somehow - fit entire image pass def setClickMode(self,mode): #none, crop1, crop2, tag, addcontour1, addcontour2, rmcontour, splitcontour, getdigit1, getdigit2 self.builder.get_object("mcclickmode").set_label("Mode:" + str(mode)) self.clickstate=mode def loadTrainingImage(self,fname): if fname[-4:].lower()==".avi": #get first frame - look this up pass elif fname[-4:].lower()==".png" or fname[-4:].lower()==".jpg": a=cv2.imread(fname, 0) #note 0 implies grayscale #getcontours else: #Error pass if self.mcflipx==True and self.mcflipy==True: a=cv2.flip(a,-1) elif self.mcflipx==True and self.mcflipy==False: a=cv2.flip(a,0) if self.mcflipy==True and self.mcflipx==False: a=cv2.flip(a,1) if self.crop1!=None and self.crop2!=None: #print str(self.crop1) #print str(self.crop2) a=a[np.min([self.crop1[1],self.crop2[1]]):np.max([self.crop1[1],self.crop2[1]]),np.min([self.crop1[0],self.crop2[0]]):np.max([self.crop1[0],self.crop2[0]])] (self.monimage,self.dlist,self.rlist)=self.getContours(a,self.d1size) #for cont in self.contours: #add individual digits to list, then tag list #self.dlist.append(self.monimage[cont.ritem[0][1]:cont.ritem[0][1]+cont.ritem[2],cont.ritem[0][0]:cont.ritem[0][0]+cont.ritem[1]]) #TODO FIX THIS - need to take ditem of new image, not config one, where the coords are the same #for cont in self.contours: #self.dlist.append(cont.ditem[0]) for i in range(len(self.rlist)): for cont in self.contours: #if self.rlist[i]==cont.ritem: #TODO remove hidden parameters here if np.abs(self.rlist[i][0][0]-cont.ritem[0][0])<=4 and np.abs(self.rlist[i][0][1]-cont.ritem[0][1])<=4: self.trdlist.append(self.dlist[i]) self.trtotal+=1 #could add width, height check as well #update display self.updateTrainingDataWindow() def updateTrainingDataWindow(self): #Use curframe number, like TesiDogs program try: self.builder.get_object("bvbox3").remove(self.canvastr) self.axistr.clear() except: pass self.axistr.imshow(self.trdlist[self.trframe][0], cmap=cm.gray) #set scale to 0,255 somehow self.canvastr=FigureCanvasGTKAgg(self.figuretr) self.canvastr.draw() self.canvastr.show() self.builder.get_object("bvbox3").pack_start(self.canvastr, True, True) self.builder.get_object("trframecount").set_label(str(self.trframe+1) + "/" + str(self.trtotal)) #self.builder.get_object("trcursol").set_label(str(self.trframe+1) + "/" + str(self.trtotal)) #TODO update labels #bvbox3 #trframecount #trcursol def getKeyPress(self, widget, event): #TODO training #GTKwidget keyreleaseevent ci=event.keyval ci=ci-48 if event.keyval==45: #set to not a number self.trNext() elif ci in [0,1,2,3,4,5,6,7,8,9]: data=self.trdlist[self.trframe][0].flatten() if ci in self.traindict.keys(): self.traindict[ci]+=data self.traindict[ci]/=2.0 self.trNext() else: self.traindict[ci]=data self.trNext() def sumpmtestlive(self): rl={} for item2 in dlist: item=item2[0] q=False data = np.zeros((esize1), dtype=np.uint8) #results=[] #err=[] data=item.flatten() boolarray=(data>self.pixelthreshold) resultd=[] #print tdict.keys() for j in range(len(tdict.keys())): result=np.sum(tdict[j][boolarray]) #penalisation factor result-=4*np.sum(tdict[j][data<=self.pixelthreshold]) resultd.append(result/float(esize1)) #print resultd # sr=reversed(sorted(resultd)) # srlist=[] # for j in sr: # srlist.append(j) # err.append(srlist[0]-srlist[1]) resultf=(resultd.index(max(resultd))) #print resultf if max(resultd)<-0.1: #print "IGNORE!" q=True #print "---" #cv2.imshow("newtest",item) #cv2.waitKey(0) #Append digit to correct place #rl = {y:{x:(1,q)}} if item2[2] in rl.keys(): rl[item2[2]][item2[1]]=(resultf, q) else: rl[item2[2]]={item2[1]:(resultf,q)} string="" for key in sorted(rl.iterkeys()): #print "%s: %s" % (key, mydict[key]) for key2 in sorted(rl[key].iterkeys()): if rl[key][key2][1]==False: string+=str(rl[key][key2][0]) #if rl[key][key2][1]==True: #string+="?" string+=" " print string
class DataManager(gtk.Window): # read default data from a file into the list view read_data_csv() # global variables needed to share among classes global labels global data # dimensions of data numRows=len(data[0]) numCols=len(labels) ########################################################################################### def __init__(self): # init gtk::Window gtk.Window.__init__(self) self.set_default_size(600, 800) self.connect('destroy', lambda win: gtk.main_quit()) # load data for plots self.data=data self.xdata=self.data[0] self.ydata=self.data[3] self.set_title('DOSEMATIC v0.1') # variable name -- TODO self.xvariable="Dose" self.xvar="D" self.xunits="Gy" self.yvariable="Yield" self.yvar="Y" self.yunits="" # main layout container main_eb = gtk.EventBox() # horizontal box hbox = gtk.HBox(False, 8) # vertical box VBOX = gtk.VBox(False, 0) main_eb.add(VBOX) #main_eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(red=60000,green=60000,blue=60000)) self.add(main_eb) vbox1 = gtk.VBox(False,8) vbox2 = gtk.VBox(False,8) hbox.pack_start(vbox1, True, True) hbox.pack_start(vbox2, True, True) top_band = gtk.HBox() bottom_band = gtk.HBox() top_eb = gtk.EventBox() bottom_eb = gtk.EventBox() top_eb.add(top_band) bottom_eb.add(bottom_band) top_eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0,0,0)) bottom_eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(0,0,0)) l1 = gtk.Label('DOSEMATIC v1.0 --- beta testing --- module 1, basic view') l2 = gtk.Label('author: Maciej Lewicki [email protected], [email protected]') top_band.add(l1) bottom_band.add(l2) hruler = gtk.HSeparator() hruler2 = gtk.HSeparator() VBOX.pack_start(top_eb,False,False) VBOX.pack_start(hruler,False,True,5) VBOX.pack_start(hbox,True,True) VBOX.pack_start(hruler2,False,True,5) VBOX.pack_end(bottom_eb,False,False) # TREE VIEW________________________________________________________ self.model = self.create_model() # MODEL self.treeview = gtk.TreeView(self.model) # TREE VIEW self.treeview.set_rules_hint(True) self.add_columns() # FILL COLUMNS # -> TREE VIEW BUTTONS button_add1 = gtk.Button('Add row') # ADD 1 ROW button_add10 = gtk.Button('Add 10 rows') # ADD 10 ROWS button_load = gtk.Button("Load data") # LOAD FILE button_save = gtk.Button("Save data") # LOAD FILE hbox_buttons = gtk.HBox(False,5) # layout packaging hbox_buttons2 = gtk.HBox(False,5) # layout packaging hbox_buttons.pack_start(button_add1, True, True) hbox_buttons.pack_start(button_add10, True, True) hbox_buttons2.pack_start(button_load, True, True) hbox_buttons2.pack_start(button_save, True, True) vbox2.pack_start(hbox_buttons2, False, False) vbox2.pack_end(hbox_buttons, False, False) button_add1.connect('clicked',self.add_rows,1) # SIGNALS HANDLING button_add10.connect('clicked',self.add_rows,10) button_load.connect('clicked',self.on_load_file) button_save.connect('clicked',self.on_save_file) # -> INTO SCROLABLE WINDOW self.sw = gtk.ScrolledWindow() self.sw.set_shadow_type(gtk.SHADOW_ETCHED_IN) self.sw.set_policy(gtk.POLICY_NEVER,gtk.POLICY_AUTOMATIC) self.sw.add(self.treeview) # ADD TO SW vbox2.pack_start(self.sw, True, True) #__________________________________________________________________ # TEXT SCREEN______________________________________________________ self.text = gtk.TextView() # TEXT VIEW self.text.set_wrap_mode(gtk.WRAP_WORD) # wrap words self.scroll_text = gtk.ScrolledWindow() # into scrollable env self.scroll_text.set_shadow_type(gtk.SHADOW_ETCHED_IN) self.scroll_text.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) self.scroll_text.add(self.text) text_view_box = gtk.VBox(False,5) text_view_box.pack_start(self.scroll_text,True,True) #__________________________________________________________________ # ESTIMATOR________________________________________________________ estimator_box = gtk.HBox(False,5) self.estxt = gtk.TextView() self.estxt.set_wrap_mode(gtk.WRAP_WORD) self.scroll_estxt = gtk.ScrolledWindow() self.scroll_estxt.set_shadow_type(gtk.SHADOW_ETCHED_IN) self.scroll_estxt.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) self.scroll_estxt.add(self.estxt) label = gtk.Label(self.yvariable+' = ') entry = gtk.Entry() entry.set_text("0.00") button = gtk.Button('Estimate '+self.xvariable) button.connect('clicked',self.y_estimate,entry) combo = gtk.combo_box_new_text() combo.append_text("Method A") combo.append_text("Method B") combo.append_text("Method C-original") combo.append_text("Method C-simplified") self.method="Method C-simplified" combo.set_active(3) combo.connect('changed', self.on_method_changed) ruler = gtk.HSeparator() grid = gtk.Table(2,4) grid.attach(label, 0,1,0,1) grid.attach(entry, 1,2,0,1) grid.attach(button, 0,2,1,2) grid.attach(ruler,0,2,2,3) grid.attach(combo,0,2,3,4) estimator_box.pack_start(grid,False,False) estimator_box.pack_start(self.scroll_estxt,True,True) #__________________________________________________________________ # FUNCTION TAB_____________________________________________________ function_box = gtk.HBox(False,5) self.ftxt = gtk.TextView() self.ftxt.set_wrap_mode(gtk.WRAP_WORD) self.scroll_ftxt = gtk.ScrolledWindow() self.scroll_ftxt.set_shadow_type(gtk.SHADOW_ETCHED_IN) self.scroll_ftxt.set_policy(gtk.POLICY_AUTOMATIC,gtk.POLICY_AUTOMATIC) self.scroll_ftxt.add(self.ftxt) label_Y = gtk.Label() label_Y.set_use_markup(True) label_Y.set_markup('Y = c + αD + βD<sup>2</sup>') self.entry_c = gtk.Entry() self.entry_c.set_width_chars(5) label_c = gtk.Label('c: ') self.entry_alpha = gtk.Entry() self.entry_alpha.set_width_chars(5) label_alpha = gtk.Label() label_alpha.set_use_markup(True) label_alpha.set_markup('α: ') self.entry_beta = gtk.Entry() self.entry_beta.set_width_chars(5) label_beta = gtk.Label() label_beta.set_use_markup(True) label_beta.set_markup('β: ') self.entry_sc = gtk.Entry() self.entry_sc.set_width_chars(5) label_sc = gtk.Label() label_sc.set_use_markup(True) label_sc.set_markup('σ(c): ') self.entry_salpha = gtk.Entry() self.entry_salpha.set_width_chars(5) label_salpha = gtk.Label() label_salpha.set_use_markup(True) label_salpha.set_markup('σ(α): ') self.entry_sbeta = gtk.Entry() self.entry_sbeta.set_width_chars(5) label_sbeta = gtk.Label() label_sbeta.set_use_markup(True) label_sbeta.set_markup('σ(β): ') table_f = gtk.Table(6,3) #table_f.attach(label_Y, False, False) table_f.attach(label_c,0,1,0,1) table_f.attach(self.entry_c,1,2,0,1) table_f.attach(label_alpha,0,1,1,2) table_f.attach(self.entry_alpha,1,2,1,2) table_f.attach(label_beta,0,1,2,3) table_f.attach(self.entry_beta,1,2,2,3) table_f.attach(label_sc,4,5,0,1) table_f.attach(self.entry_sc,5,6,0,1) table_f.attach(label_salpha,4,5,1,2) table_f.attach(self.entry_salpha,5,6,1,2) table_f.attach(label_sbeta,4,5,2,3) table_f.attach(self.entry_sbeta,5,6,2,3) vruler = gtk.VSeparator() table_f.attach(vruler,3,4,0,3,xpadding=10) check_function = gtk.CheckButton("Plot function") check_points = gtk.CheckButton("Plot data points") check_err = gtk.CheckButton("Plot uncertainty band") check_ci_curve = gtk.CheckButton("Plot CI95% band (curve)") check_ci_points = gtk.CheckButton("Plot CI95% band (points)") check_function.set_active(True) check_points.set_active(True) check_err.set_active(True) check_ci_curve.set_active(True) check_ci_points.set_active(True) vbox_checks = gtk.VBox(False, 5) vbox_checks.pack_start(check_function, False, False) vbox_checks.pack_start(check_points, False, False) vbox_checks.pack_start(check_err, False, False) vbox_checks.pack_start(check_ci_curve, False, False) vbox_checks.pack_start(check_ci_points, False, False) check_function.connect('toggled',self.on_toggled, 'function') check_points.connect('toggled',self.on_toggled, 'points') check_err.connect('toggled',self.on_toggled, 'err') check_ci_curve.connect('toggled',self.on_toggled, 'ci_curve') check_ci_points.connect('toggled',self.on_toggled, 'ci_points') hbox_buttons = gtk.HBox(True,5) button_save_f = gtk.Button("Save Funtion") button_load_f = gtk.Button("Load Funtion") hbox_buttons.pack_start(button_save_f,True,True) hbox_buttons.pack_start(button_load_f,True,True) button_save_f.connect('clicked',self.save_function) button_load_f.connect('clicked',self.load_function) left_box = gtk.VBox(False,5) ruler_f1 = gtk.HSeparator() ruler_f2 = gtk.HSeparator() left_box.pack_start(label_Y, False, False) left_box.pack_start(table_f, False, False) left_box.pack_start(ruler_f1, False, True, 5) left_box.pack_start(vbox_checks, False, False) left_box.pack_start(ruler_f2, False, True, 5) left_box.pack_start(hbox_buttons, False, True) function_box.pack_start(left_box, False, False) function_box.pack_start(self.scroll_ftxt, True, True) #__________________________________________________________________ # NOTEBOOK WRAP____________________________________________________ self.notebook = gtk.Notebook() self.notebook.append_page(text_view_box, gtk.Label('Log console')) self.notebook.append_page(estimator_box, gtk.Label('Estimator')) self.notebook.append_page(function_box, gtk.Label('Calibration function')) vbox1.pack_end(self.notebook,True,True) #__________________________________________________________________ # MAT-PLOT-LIB_____________________________________________________ self.fig = Figure(figsize=(6, 4)) # create fig self.canvas = FigureCanvas(self.fig) # a gtk.DrawingArea self.canvas.set_size_request(600,400) # set min size self.markers = ['.',',','+','x','|','_','o', 'v', '^', '<', '>', '8', 's', 'p', '*', 'h', 'H', 'D', 'd'] self.colors = ['black','blue','green','red','cyan','magenta','yellow','purple','white'] self.pstyle = ['bmh','s','6','red','0.8','black','2','black','0.3','','25','','','20','15','','','20','15'] self.styledict = {} self.styledict["style"]='bmh' self.styledict["point_style"]='s' self.styledict["point_size"]='6' self.styledict["point_color"]='red' self.styledict["point_alpha"]='0.8' self.styledict["line_color"]='black' self.styledict["line_width"]='2' self.styledict["band_color"]='black' self.styledict["band_alpha"]='0.3' self.styledict["title_size"]='25' self.styledict["xtitle_size"]='20' self.styledict["xlabel_size"]='15' self.styledict["ytitle_size"]='20' self.styledict["ylabel_size"]='15' self.nselec = [1,12,5,3,-1,0,-1,0,-1,-1,-1,-1,-1,-1] self.plot_labels = ["Foci per cell vs Dose", "Dose", "Foci per cell", " [Gy]", " []"] #print plt.style.available self.mode='quadratic' self.function = None if self.mode=='linear' : self.function = self.linear elif self.mode=='quadratic' : self.function = self.quadratic self.fit_toggle='active' self.points_toggle=1 self.function_toggle=1 self.err_toggle=1 self.ci_func_toggle=1 self.ci_points_toggle=1 self.plotting() # --- CORE plotting function --- self.canvas.mpl_connect('pick_event', self.on_pick) toolbar = NavigationToolbar(self.canvas, self) toolbarbox = gtk.HBox() image = gtk.Image() image.set_from_stock(gtk.STOCK_PROPERTIES, gtk.ICON_SIZE_LARGE_TOOLBAR) options_button = gtk.Button() options_button.add(image) options_button.connect('clicked',self.mpl_options) image2 = gtk.Image() image2.set_from_stock(gtk.STOCK_REFRESH, gtk.ICON_SIZE_LARGE_TOOLBAR) refresh_button = gtk.Button() refresh_button.add(image2) refresh_button.connect('clicked',self.on_refresh_clicked) toolbarbox.pack_start(toolbar, True, True) toolbarbox.pack_end(options_button, False, True) toolbarbox.pack_end(refresh_button, False, True) vbox1.pack_start(toolbarbox, False, False) vbox1.pack_start(self.canvas, True, True) # into box layout #__________________________________________________________________ def plotting(self): plt.style.use(self.pstyle[0]) self.xdata=self.data[0] self.ydata=self.data[3] self.ax1 = self.fig.add_subplot(111) self.ax1.clear() if self.points_toggle==1: self.ax1.plot(self.xdata,self.ydata, color=self.pstyle[3], label=labels[3], marker=self.pstyle[1], alpha=float(self.pstyle[4]), linestyle='None', markersize=float(self.pstyle[2]), picker=float(self.pstyle[2])) self.ax1.set_title(self.plot_labels[0], fontsize=self.pstyle[10]) self.ax1.set_xlabel(self.plot_labels[1]+self.plot_labels[3], fontsize=int(self.pstyle[13])) self.ax1.set_ylabel(self.plot_labels[2]+self.plot_labels[4], fontsize=int(self.pstyle[17])) self.ax1.tick_params(axis='x', which='both', labelsize=int(self.pstyle[14])) self.ax1.tick_params(axis='y', which='both', labelsize=int(self.pstyle[18])) x = np.arange(-0.1, max(20,max(self.xdata))*1.1, 0.05) if (self.fit_toggle=='active'): self.params, self.rmse, self.p_value, self.std_err, self.dof, self.rss, self.cov_mtx = self.fit_function(self.xdata,self.ydata) self.function_changed() if self.function_toggle==1: y = self.function(x,self.params) self.ax1.plot(x,y, color=self.pstyle[5], marker='.', linestyle='None', markersize=float(self.pstyle[6])) if self.ci_func_toggle==1 and self.fit_toggle=='active': conf = self.confidence(x,self.xdata,len(x),np.mean(self.xdata),self.dof,self.rmse) upper = self.function(x,self.params) + conf lower = self.function(x,self.params) - conf self.ax1.fill_between(x, lower, upper, facecolor=self.pstyle[7], alpha=float(self.pstyle[8])) if self.ci_points_toggle==1: upper = self.function(x,self.params) + self.confidence_points(x,self.std_err) lower = self.function(x,self.params) - self.confidence_points(x,self.std_err) self.ax1.fill_between(x, lower, upper, facecolor='blue', alpha=float(self.pstyle[8])) if self.err_toggle==1: upper = self.function(x,self.params) + self.uncertainty(x,self.std_err) lower = self.function(x,self.params) - self.uncertainty(x,self.std_err) self.ax1.fill_between(x, lower, upper, facecolor='green', alpha=float(self.pstyle[8])) self.canvas.draw() def on_refresh_clicked(self,button) : self.plotting() def on_pick(self,event): artist = event.artist xmouse, ymouse = event.mouseevent.xdata, event.mouseevent.ydata x, y = artist.get_xdata(), artist.get_ydata() ind = event.ind print 'Artist picked:', event.artist print '{} vertices picked'.format(len(ind)) print 'Pick between vertices {} and {}'.format(min(ind), max(ind)) print 'x, y of mouse: {:.2f},{:.2f}'.format(xmouse, ymouse) print 'Data point:', x[ind[0]], y[ind[0]] print self.log('Data point:\t ' + str(x[ind[0]]) + '\t' + str(y[ind[0]])) self.treeview.set_cursor(min(ind)) self.treeview.grab_focus() def log(self,txt): end_iter = self.text.get_buffer().get_end_iter() self.text.get_buffer().insert(end_iter, txt+'\n') adj = self.scroll_text.get_vadjustment() adj.set_value( adj.upper - adj.page_size ) self.notebook.set_current_page(0) def loges(self,txt): end_iter = self.estxt.get_buffer().get_end_iter() self.estxt.get_buffer().insert(end_iter, txt+'\n') adj = self.scroll_estxt.get_vadjustment() adj.set_value( adj.upper - adj.page_size ) self.notebook.set_current_page(1) def logf(self,txt): end_iter = self.ftxt.get_buffer().get_end_iter() self.ftxt.get_buffer().insert(end_iter, txt+'\n') adj = self.scroll_ftxt.get_vadjustment() adj.set_value( adj.upper - adj.page_size ) self.notebook.set_current_page(2) def add_columns(self): for i in range(self.numCols): renderer = gtk.CellRendererText() renderer.props.wrap_width = 100 if i==0 or i==1 or i==2: renderer.set_property('editable', True) renderer.connect('edited',self.edited_cb, i) else : renderer.set_property('editable', False) column = gtk.TreeViewColumn(labels[i], renderer, text=i) column.set_resizable(True) column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) column.set_min_width(50) column.set_fixed_width(100) column.set_expand(False) self.treeview.append_column(column) def edited_cb(self, cell, path, new_content, user_data): column = user_data liststore=self.model print 'edited_cb', self.model print 'edited_cb', len(self.model) print path, int(path) if isfloat(new_content) and float(new_content)>=0.0 : liststore[path][column] = float(new_content) self.data[int(column)][int(path)] = float(new_content) if liststore[path][1] != 0: liststore[path][3] = liststore[path][2] / liststore[path][1] self.data[3][int(path)] = self.data[2][int(path)] / self.data[1][int(path)] else: liststore[path][3]=0.0 self.data[3][int(path)]=0.0 print "data[", column, "][", path, "] = ", self.data[int(column)][int(path)] self.plotting() else : self.log("___Wrong input format!___") def add_rows(self,button,n): self.log('n of rows to add: ' + str(n)) print 'add_rows', self.model print 'add_rows', len(self.model) for i in range(0,n) : self.model.append([0,0,0,0,0]) self.data = np.insert( self.data, len(self.xdata), values=0, axis=1 ) adj = self.sw.get_vadjustment() adj.set_value( adj.upper - adj.page_size ) print 'add_rows', self.model print 'add_rows', len(self.model) def create_model(self): types = [float]*self.numCols store = None store = gtk.ListStore(*types) temp=zip(*self.data) for row in temp: store.append(row) return store def linear(self, x, params): return params[0]*x + params[1] def quadratic(self, x, params): return params[0]*x*x + params[1]*x + params[2] def fit_linear(self, x, a, b): return a*x + b def fit_quadratic(self, x, a, b, c): return a*x*x + b*x + c def confidence(self, x, xdata, n, mean_x, dof, RMSE): alpha=0.05 t = stats.t.isf(alpha/2., df=dof) #conf = t * np.sqrt((RSS/(n-2))*(1.0/n + ( (x-mean_x)**2 / ((np.sum(x**2)) - n*(mean_x**2))))) Sxx = np.sum(xdata**2) - np.sum(xdata)**2/n se_a = RMSE / np.sqrt(Sxx) se_b = RMSE * np.sqrt(np.sum(xdata**2)/(n*Sxx)) conf = t * RMSE * np.sqrt( 1./n + (x-mean_x)**2/Sxx) #pred = t * RMSE * np.sqrt(1+1./n + (x-mean_x)**2/Sxx) return conf def uncertainty(self, x, std_err) : return std_err[2] + x*std_err[1] + x*x*std_err[0] def confidence_points(self, x, std_err) : return 1.96*self.uncertainty(x, std_err) def fit_function(self,x,y): # fit the model if self.mode=='linear' : popt, pcov = curve_fit(self.fit_linear, x, y) elif self.mode=='quadratic' : popt, pcov = curve_fit(self.fit_quadratic, x, y) # parameters standard error std_err = np.sqrt(np.diag(pcov)) # degrees of freedom ndata = len(y) npar = len(popt) dof = max(0, ndata - npar) # root mean squared error residuals = y - self.function(x,popt) RSS = sum(residuals**2) MSE = RSS/dof RMSE = np.sqrt(MSE) # t-value t_value = popt/std_err # p-value P(>|t|) p_value=(1 - stats.t.cdf( abs(t_value), dof))*2 return popt, RMSE, p_value, std_err, dof, RSS, pcov def function_changed(self): if self.mode=='quadratic' : self.entry_c.set_text('%.3f' % self.params[2]) self.entry_alpha.set_text('%.3f' % self.params[1]) self.entry_beta.set_text('%.3f' % self.params[0]) self.entry_sc.set_text('%.3f' % self.std_err[2]) self.entry_salpha.set_text('%.3f' % self.std_err[1]) self.entry_sbeta.set_text('%.3f' % self.std_err[0]) self.logf("params:\t[beta\talpha\tc ]") self.logf("values\t\t" + str(self.params)) self.logf("std_err\t" + str(self.std_err)) self.logf("p-value\t" + str(self.p_value)) self.logf("RSS\t" + str(self.rss)) self.logf("RMSE\t" + str(self.rmse)) self.logf("---------------------------------------------------------------------------") def on_load_file(self, button) : file_chooser = gtk.FileChooserDialog("Open...", self, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) response = file_chooser.run() path='' if response == gtk.RESPONSE_OK : path = file_chooser.get_filename() self.log('Loaded data file: ' + path) if ".csv" in path: read_data_csv(path) self.data=data self.model = self.create_model() self.treeview.set_model(self.model) self.fit_toggle = 'active' self.points_toggle=True self.plotting() else : self.log("___Wrong file format!___") file_chooser.destroy() def on_save_file(self, button) : file_chooser = gtk.FileChooserDialog("Open...", self, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) response = file_chooser.run() path='' if response == gtk.RESPONSE_OK : path = file_chooser.get_filename() self.log('Data saved in file: ' + path) if ".csv" not in path: path = path + '.csv' ofile = open(path,"wb") writer = csv.writer(ofile, delimiter=',') writer.writerow(labels) for row in zip(*self.data): print row writer.writerow(row) ofile.close() file_chooser.destroy() else : file_chooser.destroy() def y_estimate(self, button, entry): if not isfloat(entry.get_text()): self.loges("___Not a number!___") return Y = float(entry.get_text()) plist = self.get_fit_params() u = uncer.UCER(Y=Y,par_list=plist) D = u.D if self.method=="Method A": DL, DU = u.method_a() elif self.method=="Method B": DL, DU = u.method_b() elif self.method=="Method C-original": DL, DU = u.method_c1() elif self.method=="Method C-simplified": DL, DU = u.method_c2() xlab=self.xvar ylab=self.yvar self.loges( xlab + " estimation for " + ylab + " = " + str(Y) + " using " + self.method + ":") self.loges( "D = " + str(D) + "; DL = " + str(DL) + "; DU = " + str(DU)) self.loges("-----------------------------------------------------------------") self.ax1.axhline(y=Y,linewidth=1,linestyle='-',color='red') self.ax1.axvline(x=D,linewidth=1,linestyle='-',color='blue') self.ax1.axvline(x=DL,linewidth=1,linestyle='--',color='green') self.ax1.axvline(x=DU,linewidth=1,linestyle='--',color='green') self.canvas.draw() def mpl_options(self,button) : dialog = gtk.Dialog("My Dialog",self,0,(gtk.STOCK_OK, gtk.RESPONSE_OK)) box = dialog.get_content_area() table = gtk.Table(2,18) table.set_row_spacings(5) table.set_col_spacings(5) l=[] l.append(gtk.Label("Canvas Style")) l.append(gtk.Label("Marker Style")) l.append(gtk.Label("Marker Size")) l.append(gtk.Label("Marker Color")) l.append(gtk.Label("Marker Alpha")) l.append(gtk.Label("Line Color")) l.append(gtk.Label("Line Width")) l.append(gtk.Label("CI Band Color")) l.append(gtk.Label("CI Band Alpha")) l.append(gtk.Label("Title")) l.append(gtk.Label("Title size")) l.append(gtk.Label("X-axis title")) l.append(gtk.Label("X-axis unit")) l.append(gtk.Label("X-axis title size")) l.append(gtk.Label("X-axis labels size")) l.append(gtk.Label("Y-axis title")) l.append(gtk.Label("Y-axis unit")) l.append(gtk.Label("Y-axis title size")) l.append(gtk.Label("Y-axis labels size")) hbox=[] hlines=[] for i in range(0,len(l)) : l[i].set_alignment(xalign=0,yalign=0.5) hbox.append(gtk.HBox(False,5)) hlines.append(gtk.HSeparator()) table.attach(l[i],0,1,2*i,2*i+1) table.attach(hbox[i],1,2,2*i,2*i+1) table.attach(hlines[i],0,2,2*i+1,2*i+2) combo_cs = self.create_combobox(plt.style.available,hbox,0) combo_mst = self.create_combobox(self.markers,hbox,1) spin_msz = self.create_spinbutton(hbox,float(self.pstyle[2]), 1.0,20.0,1.0,2, 2) combo_mc = self.create_combobox(self.colors,hbox,3) spin_ma = self.create_spinbutton(hbox,float(self.pstyle[4]), 0.0,1.0,0.05,2, 4) combo_lc = self.create_combobox(self.colors,hbox,5) spin_lw = self.create_spinbutton(hbox,float(self.pstyle[6]), 0.0,10.0,0.5,2, 6) combo_bc = self.create_combobox(self.colors,hbox,7) spin_ba = self.create_spinbutton(hbox,float(self.pstyle[8]), 0.0,1.0,0.05,2, 8) entry_title = self.create_entry(hbox,0, 9) entry_xaxis = self.create_entry(hbox,1, 11) entry_xunit = self.create_entry(hbox,3, 12) entry_yaxis = self.create_entry(hbox,2, 15) entry_yunit = self.create_entry(hbox,4, 16) spin_title_size = self.create_spinbutton(hbox,float(self.pstyle[10]), 10.0,40.0,1.0,1 , 10) spin_xtile_size = self.create_spinbutton(hbox,float(self.pstyle[13]), 10.0,40.0,1.0,1 , 13) spin_xlabels_size = self.create_spinbutton(hbox,float(self.pstyle[14]), 10.0,40.0,1.0,1 , 14) spin_ytile_size = self.create_spinbutton(hbox,float(self.pstyle[17]), 10.0,40.0,1.0,1 , 17) spin_ylabels_size = self.create_spinbutton(hbox,float(self.pstyle[18]), 10.0,40.0,1.0,1 , 18) box.add(table) dialog.show_all() response = dialog.run() if response == gtk.RESPONSE_OK : dialog.destroy() else : dialog.destroy() def create_combobox(self,slist,whereto,n) : combo = gtk.combo_box_new_text() whereto[n].pack_start(combo) for style in slist : combo.append_text(str(style)) combo.set_active(self.nselec[n]) combo.connect('changed', self.on_combo_changed, n) def create_spinbutton(self,whereto,val,mini,maxi,step,digits,n) : adj = gtk.Adjustment(val,mini,maxi,step,0.5,0.0) spin = gtk.SpinButton(adj,step,digits) whereto[n].pack_start(spin) spin.connect('changed',self.on_spin_changed,n) def create_entry(self,whereto,m,n) : entry_title = gtk.Entry() entry_title.set_text(self.plot_labels[m]) whereto[n].pack_start(entry_title) entry_title.connect("activate",self.on_entry_changed,m) def on_combo_changed(self,cb,n): model = cb.get_model() index = cb.get_active() cb.set_active(index) self.pstyle[n] = model[index][0] self.nselec[n]=index self.plotting() def on_spin_changed(self,spin,n) : self.pstyle[n] = spin.get_value() self.plotting() def on_entry_changed(self,entry,n) : self.plot_labels[n] = entry.get_text() self.plotting() def on_toggled(self,button,s) : if(s=='ci_points'): self.ci_points_toggle*=-1 elif(s=='ci_curve'): self.ci_func_toggle*=-1 elif(s=='function'): self.function_toggle*=-1 elif(s=='points'): self.points_toggle*=-1 elif(s=='err'): self.err_toggle*=-1 self.plotting() def save_function(self,button) : file_chooser = gtk.FileChooserDialog("Open...", self, gtk.FILE_CHOOSER_ACTION_SAVE, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK)) response = file_chooser.run() path='' if response == gtk.RESPONSE_OK : path = file_chooser.get_filename() self.logf('Curve saved in file: ' + path) self.logf("---------------------------------------------------------------------------") if ".csv" not in path: path = path + '.csv' file_chooser.destroy() ofile = open(path,"wb") writer = csv.writer(ofile, delimiter=',') writer.writerow(self.params) writer.writerow(self.std_err) writer.writerow(self.p_value) writer.writerow(self.cov_mtx[0]) writer.writerow(self.cov_mtx[1]) writer.writerow(self.cov_mtx[2]) writer.writerow((self.rss, self.rmse, 0.0)) ofile.close() else : file_chooser.destroy() def get_fit_params(self): l=[self.params,self.std_err,self.p_value,self.cov_mtx[0],self.cov_mtx[1],self.cov_mtx[2],[self.rss,self.rmse,0.0]] return l def load_function(self,button) : file_chooser = gtk.FileChooserDialog("Open...", self, gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) response = file_chooser.run() path='' if response == gtk.RESPONSE_OK : path = file_chooser.get_filename() self.logf('Loaded curve from file: ' + path) self.logf("---------------------------------------------------------------------------") f = open(path, 'rt') try: reader = csv.reader(f) l=list(reader) print l self.params=[float(i) for i in l[0]] self.std_err=[float(i) for i in l[1]] self.p_value=[float(i) for i in l[2]] self.cov_mtx=[[float(i) for i in l[3]],[float(i) for i in l[4]],[float(i) for i in l[5]]] self.rss=float(l[6][0]) self.rmse=float(l[6][1]) self.function_changed() self.fit_toggle='inactive' self.points_toggle=False read_data_csv('zeros.csv') self.data=data self.model = self.create_model() self.treeview.set_model(self.model) self.plotting() finally: f.close() #self.plotting() file_chooser.destroy() else : file_chooser.destroy() def on_method_changed(self,cb): model = cb.get_model() index = cb.get_active() cb.set_active(index) self.method = model[index][0]
def __init__(self, cube, parent_window): """ A Dendrogram Plot Widget. Designed as a companion to an astrocube.cubeview.CubeViewWidget which should be passed as cube_view """ gtk.VBox.__init__(self, False) # Main data structures: self.cube = cube # The cube that this widget's dendrogram represents self._data = cube.data # Save a reference to the cube's original data, as we may replace it... self.dendrogram = None # The Dendrogram for the cube. To be built later # The plot: self.fig = matplotlib.figure.Figure() self.axes = self.fig.add_subplot(111) self.dendro_plot = None # Gets set to a DendrogramPlot object self.highlighter_clicked = None # a Highlighter object to color the clicked item self.highlighter_hover = None # a Highlighter object to color an item on mouseover # UI structure: canvas = FigureCanvasGTKAgg(self.fig) # a gtk.DrawingArea self.pack_start(canvas) self.pack_start(gtk.HSeparator(), False,False) # # The matplotlib plot toolbar: self._plot_toolbar = self._NavigationToolbar(self.cube, canvas, parent_window) # parent_window is needed for the "Save image..." file chooser dialog self._plot_toolbar.remove(self._plot_toolbar.get_nth_item(6)) # Remove the "Configure subplots" button which causes rendering issues if used self.pack_start(self._plot_toolbar, False, False) self.pack_start(gtk.HSeparator(), False,False) # # the dendrogram parameters toolbar: self._dendro_toolbar = gtk.HBox() # # # Minimum flux: self._dendro_toolbar.pack_start(gtk.Label("Min flux: ")) self._min_flux_widget = gtk.SpinButton(digits=1) self._min_flux_widget.set_range(np.nanmin(self._data)-0.1,np.nanmax(self._data)) self._min_flux_widget.set_increments(0.1,1) self._min_flux_widget.set_value(np.nanmin(self._data)) self._dendro_toolbar.pack_start(self._min_flux_widget) # # # Minimum npix: self._dendro_toolbar.pack_start(gtk.Label("Min # pix: ")) self._min_npix_widget = gtk.SpinButton() self._min_npix_widget.set_range(0,999) self._min_npix_widget.set_increments(1,5) self._min_npix_widget.set_value(0) self._dendro_toolbar.pack_start(self._min_npix_widget) # # # Minimum delta: self._dendro_toolbar.pack_start(gtk.Label("Min delta: ")) self._min_delta_widget = gtk.SpinButton(digits=2) self._min_delta_widget.set_range(0,np.nanmax(self._data)) self._min_delta_widget.set_increments(0.05,0.3) self._min_delta_widget.set_value(0) self._dendro_toolbar.pack_start(self._min_delta_widget) # # # Compute button: self._compute_button = gtk.Button("Compute") self._compute_button.connect("button-press-event", self._compute_btn_clicked) self._dendro_toolbar.pack_start(self._compute_button) # # # Plot style: self._dendro_toolbar.pack_start(gtk.Label("Plot style: ")) self._plot_style_widget = gtk.combo_box_new_text() plot_styles = ['rfmax', 'x_mean', 'y_mean', 'z_mean'] for s in plot_styles: self._plot_style_widget.append_text(s) self._plot_style_widget.set_active(0) self._plot_style_widget.connect("changed", self.setup_plot) self._dendro_toolbar.pack_start(self._plot_style_widget) self.pack_start(self._dendro_toolbar, False, False) # Set up event handling: self._is_mouse_down = False # is the mouse button currently pressed? self._redraw_all = False # Set this to True to trigger a complete re-draw of the canvas when idle self._redraw_highlights = False # Set this True to re-draw only the highlighted (clicked or hovered) leaves canvas.mpl_connect('button_press_event', self._figure_mousedown) canvas.mpl_connect('button_release_event', self._figure_mouseup) canvas.mpl_connect('motion_notify_event', self._figure_mousemoved) canvas.mpl_connect('resize_event', self._figure_resized) gtk.idle_add(DendrogramViewWidget._check_redraw, self) # we only want to re re-drawing when the GUI is idle, for maximum interactivity self._click_notify = [] self._compute_notify = []
class GUI: # # Main Window # # menu item activation signals def on_imagemenuitem_file_save_as_activate(self, widget): self.fcdialog_save.set_current_folder(self.folder) self.fcdialog_save.show() def on_imagemenuitem_export_activate(self, widget): self.fcdialog_export.set_current_folder(self.folder) self.fcdialog_export.show() def on_imagemenuitem_quit_activate(self, widget): self._quit() # View menu def on_checkmenuitem_function_intersections_toggled(self, widget): self.fg.point_type_enabled[1] = \ self.checkmenuitem_function_intersections.\ get_active() self.fg.update_xylimits() self.graph_update() def on_checkmenuitem_x_intercepts_toggled(self, widget): self.fg.point_type_enabled[2] = \ self.checkmenuitem_x_intercepts.get_active() self.fg.update_xylimits() self.graph_update() def on_checkmenuitem_y_intercepts_toggled(self, widget): self.fg.point_type_enabled[3] = \ self.checkmenuitem_y_intercepts.get_active() self.fg.update_xylimits() self.graph_update() def on_checkmenuitem_extrema_toggled(self, widget): self.fg.point_type_enabled[4] = \ self.checkmenuitem_extrema.get_active() self.fg.update_xylimits() self.graph_update() def on_checkmenuitem_inflection_toggled(self, widget): self.fg.point_type_enabled[5] = \ self.checkmenuitem_inflection.get_active() self.fg.update_xylimits() self.graph_update() def on_checkmenuitem_vertical_asym_toggled(self, widget): self.fg.point_type_enabled[6] = \ self.checkmenuitem_vertical_asym.get_active() self.fg.update_xylimits() self.graph_update() def on_checkmenuitem_horizontal_asym_toggled(self, widget): self.fg.point_type_enabled[7] = \ self.checkmenuitem_horizontal_asym.get_active() self.fg.update_xylimits() self.graph_update() def on_checkmenuitem_slope45_toggled(self, widget): self.fg.point_type_enabled[8] = \ self.checkmenuitem_slope45.get_active() self.fg.update_xylimits() self.graph_update() def on_checkmenuitem_outliers_toggled(self, widget): self.fg.outliers = self.checkmenuitem_outliers.get_active() self.fg.update_xylimits() self.graph_update() def on_checkmenuitem_show_poi_toggled(self, widget): self.fg.show_poi = self.checkmenuitem_show_poi.get_active() self.graph_update() def on_checkmenuitem_grouped_toggled(self, widget): self.fg.grouped = self.checkmenuitem_grouped.get_active() self.graph_update() def on_checkmenuitem_legend_toggled(self, widget): self.fg.show_legend = self.checkmenuitem_legend.get_active() self.graph_update() def on_checkmenuitem_logscale_toggled(self, widget): self.fg.logscale = self.checkmenuitem_logscale.get_active() self.graph_update() def on_menuitem_legend_lower_right_toggled(self, widget): if widget.active: self.fg.legend_location = 4 if self.fg.show_legend: self.graph_update() def on_menuitem_legend_upper_right_toggled(self, widget): if widget.active: self.fg.legend_location = 1 if self.fg.show_legend: self.graph_update() def on_menuitem_legend_lower_left_toggled(self, widget): if widget.active: self.fg.legend_location = 3 if self.fg.show_legend: self.graph_update() def on_menuitem_legend_upper_left_toggled(self, widget): if widget.active: self.fg.legend_location = 2 if self.fg.show_legend: self.graph_update() # help menu def on_imagemenuitem_about_activate(self, widget): self.aboutdialog.show() # toolbar button activation signals def on_btn_new_clicked(self, widget): if self.changed: self.dialog_confirm_new.show() else: self.changed = False self.filename = None self.export_filename = None self.fg.new() self._restore_state() self.update_function_list() self.graph_update() def on_btn_open_clicked(self, widget): if self.changed: self.dialog_confirm_open.show() else: self.fcdialog_open.set_current_folder(self.folder) self.fcdialog_open.show() def on_btn_save_clicked(self, widget): if self.filename is None: self.fcdialog_save.set_current_folder(self.folder) self.fcdialog_save.show() else: self._save() self.changed = False def on_btn_add_clicked(self, widget): self.changed = True self.entry_function.set_text('') self.dialog_add_function.show() self.entry_function.grab_focus() def on_btn_remove_clicked(self, widget): selected_line = self.treeview_functions.get_selection() self.ls_functions, iter = selected_line.get_selected() if iter is not None: index = self.ls_functions.get_value(iter, 3) self.fg.functions.pop(index) self.fg.calc_intersections() self.update_function_list() self.graph_update() self.changed = True def on_btn_zoom_x_in_clicked(self, widget): self.changed = True self.fg.zoom_x_in() self.graph_update() def on_btn_zoom_x_out_clicked(self, widget): self.changed = True self.fg.zoom_x_out() self.graph_update() def on_btn_zoom_y_in_clicked(self, widget): self.changed = True self.fg.zoom_y_in() self.graph_update() def on_btn_zoom_y_out_clicked(self, widget): self.changed = True self.fg.zoom_y_out() self.graph_update() def on_btn_zoomin_clicked(self, widget): self.changed = True self.fg.zoom_in() self.graph_update() def on_btn_zoomout_clicked(self, widget): self.changed = True self.fg.zoom_out() self.graph_update() def on_btn_auto_toggled(self, widget): self.changed = True self.fg.auto = self.btn_auto.get_active() if self.fg.auto: self.fg.zoom_default() self.graph_update() # toggle visibility in function list def on_cr_toggle_visible_toggled(self, widget, event): self.changed = True i = int(event) visible = self.fg.functions[i].visible if visible: self.fg.functions[i].visible = False else: self.fg.functions[i].visible = True self.update_function_list() self.graph_update() # about dialog close def on_aboutdialog_response(self, widget, event): self.aboutdialog.hide() def on_aboutdialog_delete_event(self, widget, event): self.aboutdialog.hide() return True # zoom in/out with the mouse wheel def wheel_zoom(self, event): self.changed = True if event.button == 'down': self.fg.zoom_out() elif event.button == 'up': self.fg.zoom_in() self.graph_update() # pan handling # when pressing down the mouse button on the graph, record # the current mouse coordinates def pan_press(self, event): self.changed = True if event.inaxes != self.ax: return self.mousebutton_press = event.xdata, event.ydata # when releasing the mouse button, stop recording the # mouse coordinates and redraw def pan_release(self, event): self.mousebutton_press = None self.graph_update() # when moving the mouse, while holding down the mouse button (any # mouse button - that makes nice middle-click pan and zoom # possible) calculate how much the mouse has travelled and adjust # the graph accordingly def pan_motion(self, event): if self.mousebutton_press is None: return if event.inaxes != self.ax: return self.fg.auto = False old_x, old_y = self.mousebutton_press dx = event.xdata - old_x dy = event.ydata - old_y self.fg.x_min -= dx self.fg.x_max -= dx self.fg.y_min -= dy self.fg.y_max -= dy self.fg.update_graph_points() self.graph_update() # update the graph def graph_update(self): self.ax.clear() if self.fg.auto: self.fg.update_xylimits() x_min, x_max = self.fg.x_min, self.fg.x_max y_min, y_max = self.fg.y_min, self.fg.y_max self.ax.grid(True) if self.fg.logscale: self.ax.set_xscale('log') self.ax.set_yscale('log') else: self.ax.set_xscale('linear') self.ax.set_yscale('linear') # put axes in center instead of the sides # when axes are off screen, put them on the edges if x_min < 0 and x_max > 0: self.ax.spines['left'].set_color('black') self.ax.spines['left'].set_position(('data', 0)) self.ax.spines['left'].set_smart_bounds(False) self.ax.spines['right'].set_color('none') self.ax.yaxis.set_ticks_position('left') elif x_min >= 0: self.ax.spines['left'].set_color('black') self.ax.spines['left'].set_position(('data', x_min)) self.ax.spines['left'].set_smart_bounds(False) self.ax.spines['right'].set_color('none') self.ax.yaxis.set_ticks_position('left') else: self.ax.spines['right'].set_color('black') self.ax.spines['right'].set_position(('data', x_max)) self.ax.spines['right'].set_smart_bounds(False) self.ax.spines['left'].set_color('none') self.ax.yaxis.set_ticks_position('right') if y_min < 0 and y_max > 0: self.ax.spines['bottom'].set_color('black') self.ax.spines['bottom'].set_position(('data', 0)) self.ax.spines['bottom'].set_smart_bounds(False) self.ax.spines['top'].set_color('none') self.ax.xaxis.set_ticks_position('bottom') elif y_min >= 0: self.ax.spines['bottom'].set_color('black') self.ax.spines['bottom'].set_position(('data', y_min)) self.ax.spines['bottom'].set_smart_bounds(False) self.ax.spines['top'].set_color('none') self.ax.xaxis.set_ticks_position('bottom') else: self.ax.spines['top'].set_color('black') self.ax.spines['top'].set_position(('data', y_max)) self.ax.spines['top'].set_smart_bounds(False) self.ax.spines['bottom'].set_color('none') self.ax.xaxis.set_ticks_position('top') # we don't need the origin annotated in both axes if x_min < 0 and x_max > 0 and y_min < 0 and y_max > 0: formatter = CenteredFormatter(useMathText=True) formatter.center = 0 self.ax.xaxis.set_major_formatter(formatter) self.ax.yaxis.set_major_formatter(formatter) self.ax.annotate('(0,0)', (0, 0), xytext=(-4, -4), textcoords='offset points', ha='right', va='top') self.ax.set_xlim(float(x_min), float(x_max)) self.ax.set_ylim(float(y_min), float(y_max)) legend = [] # draw the functions for f in self.fg.functions: x, y = f.graph_points if f.visible: color = self.color[len(legend) % len(self.color)] self.ax.plot(x, y, linewidth=2, color=color) # add function to legend legend.append(f.mathtex_expr) # create a list of ungrouped POI color_index = 0 ungrouped_poi = [] for f in self.fg.functions: if f.visible: color = self.color[color_index % len(self.color)] # function POI for p in f.poi: if self.fg.point_type_enabled[p.point_type]: p.color = color ungrouped_poi.append(p) color_index += 1 # add function intercepts POI to ungrouped list for p in self.fg.poi: if self.fg.point_type_enabled[p.point_type]: p.color = 'black' ungrouped_poi.append(p) # group POI if self.fg.show_poi: if self.fg.grouped: grouped_poi = self.fg.grouped_poi(ungrouped_poi) else: grouped_poi = ungrouped_poi # draw POI for p in grouped_poi: if p.point_type > 1 and p.point_type < 9: if p.function.visible: # don't plot vertical or horizontal # asymptotes here. We'll do it later if p.point_type < 6 or p.point_type > 7: if self.fg.point_type_enabled\ [p.point_type]: self.ax.scatter([p.x], [p.y], s=80, c=p.color, linewidths=0) # plot asymptotes now elif p.point_type == 6: if self.fg.point_type_enabled\ [p.point_type]: # vertical asymptotes are plotted # as 'x' self.ax.scatter([p.x], [0], s=80, marker='x', c=p.color, linewidths=2) elif p.point_type == 7: if self.fg.point_type_enabled\ [p.point_type]: # horizontal asymptotes are plotted # as '+' self.ax.scatter([0], [p.y], s=80, marker='+', c=p.color, linewidths=2) elif p.point_type == 1: if p.function[0].visible \ and p.function[1].visible \ and self.fg.point_type_enabled[p.point_type]: # plot function intercepts self.ax.scatter([p.x], [p.y], s=80, alpha=0.5, c='black', linewidths=0) elif p.point_type == 9: if self.fg.point_type_enabled[p.point_type]: # plot grouped poi self.ax.scatter([p.x], [p.y], s=p.size * 80, alpha=0.8, c='orange', linewidths=0) # show legend if self.fg.show_legend: if self.fg.legend_location == 1: anchor = (1, 1) elif self.fg.legend_location == 2: anchor = (0, 1) elif self.fg.legend_location == 3: anchor = (0, 0) else: anchor = (1, 0) self.ax.legend(legend, loc=self.fg.legend_location, bbox_to_anchor=anchor, fontsize=18) # show canvas self.ax.figure.canvas.draw() # check/uncheck the toolbutton for auto-adjustment self.btn_auto.set_active(self.fg.auto) def update_function_list(self): self.ls_functions.clear() visible_functions = 0 index = 0 for f in self.fg.functions: if f.visible: color = self.color[visible_functions % len(self.color)] visible_functions += 1 else: color = '#999999' self.ls_functions.append([f.visible, f.expr.lower() + '', gtk.gdk.Color(color), index]) index += 1 def gtk_main_quit(self, widget, data=None): self._quit() def _quit(self): if self.changed: self.dialog_confirm_quit.show() else: gtk.main_quit() # # Add function dialog # def on_dialog_add_function_delete_event(self, widget, event): self.dialog_add_function.hide() return True def _entry_function_append_text(self, text): t = self.entry_function.get_text() t = t + text l = len(t) self.entry_function.set_text(t) self.entry_function.grab_focus() self.entry_function.set_position(l) def on_button_1_clicked(self, widget): self._entry_function_append_text('1') def on_button_2_clicked(self, widget): self._entry_function_append_text('2') def on_button_3_clicked(self, widget): self._entry_function_append_text('3') def on_button_4_clicked(self, widget): self._entry_function_append_text('4') def on_button_5_clicked(self, widget): self._entry_function_append_text('5') def on_button_6_clicked(self, widget): self._entry_function_append_text('6') def on_button_7_clicked(self, widget): self._entry_function_append_text('7') def on_button_8_clicked(self, widget): self._entry_function_append_text('8') def on_button_9_clicked(self, widget): self._entry_function_append_text('9') def on_button_0_clicked(self, widget): self._entry_function_append_text('0') def on_button_left_paren_clicked(self, widget): self._entry_function_append_text('(') def on_button_right_paren_clicked(self, widget): self._entry_function_append_text(')') def on_button_x_clicked(self, widget): self._entry_function_append_text('x') def on_button_plus_clicked(self, widget): self._entry_function_append_text('+') def on_button_minus_clicked(self, widget): self._entry_function_append_text('-') def on_button_times_clicked(self, widget): self._entry_function_append_text('*') def on_button_div_clicked(self, widget): self._entry_function_append_text('/') def on_button_sin_clicked(self, widget): self._entry_function_append_text('sin(x)') def on_button_cos_clicked(self, widget): self._entry_function_append_text('cos(x)') def on_button_tan_clicked(self, widget): self._entry_function_append_text('tan(x)') def on_button_cot_clicked(self, widget): self._entry_function_append_text('cot(x)') def on_button_sec_clicked(self, widget): self._entry_function_append_text('sec(x)') def on_button_csc_clicked(self, widget): self._entry_function_append_text('csc(x)') def on_button_log_clicked(self, widget): self._entry_function_append_text('log(x)') def on_button_ln_clicked(self, widget): self._entry_function_append_text('ln(x)') def on_button_10p_x_clicked(self, widget): self._entry_function_append_text('10^x') def on_button_ep_x_clicked(self, widget): self._entry_function_append_text('exp(x)') def on_button_sqrt_clicked(self, widget): self._entry_function_append_text('sqrt(x)') def on_button_abs_clicked(self, widget): self._entry_function_append_text('abs(x)') def on_button_power2_clicked(self, widget): self._entry_function_append_text('x^2') def on_button_power3_clicked(self, widget): self._entry_function_append_text('x^3') def on_button_pi_clicked(self, widget): self._entry_function_append_text('pi') def on_button_e_clicked(self, widget): self._entry_function_append_text('e') def on_button_addf_cancel_clicked(self, widget): self.dialog_add_function.hide() @threaded def on_button_addf_ok_clicked(self, widget): gobject.idle_add(self.window_calculating.show) expr = self.entry_function.get_text() f = self.fg.add_function(expr) if f: gobject.idle_add(self.dialog_add_function.hide) gobject.idle_add(self.window_calculating.hide) gobject.idle_add(self.update_function_list) gobject.idle_add(self.graph_update) else: gobject.idle_add(self.window_calculating.hide) gobject.idle_add(self.dialog_add_error.show) # Error while adding function dialog def on_dialog_add_error_delete_event(self, widget, event): self.dialog_add_error.hide() return True def on_button_add_error_close_clicked(self, widget): self.dialog_add_error.hide() # # file new/open/save dialogs # def on_button_confirm_new_yes_clicked(self, widget): self.dialog_confirm_new.hide() self.changed = False self.filename = None self.fg.new() self.update_function_list() self.graph_update() def on_button_confirm_new_cancel_clicked(self, widget): self.dialog_confirm_new.hide() def on_dialog_confirm_new_delete_event(self, widget, event): self.dialog_confirm_new.hide() return True def on_button_fileopen_open_clicked(self, widget): filename = self.fcdialog_open.get_filename() filename = filename.encode(sys.getfilesystemencoding()) folder = self.fcdialog_open.get_current_folder() logging.debug('Loading file: ' + filename) try: filehandler = open(filename, "rb") try: self.fg = pickle.load(filehandler) filehandler.close() self.folder = folder self.fg.update_xylimits() self._restore_state() self.update_function_list() self.graph_update() self.fcdialog_open.hide() self.changed = False self.filename = filename except: self.label_open_error.\ set_text( _("File doesn't look like a FunctionPlot file.")) self.dialog_file_open_error.show() except: self.label_open_error.set_text(_('Error reading file.')) self.dialog_file_open_error.show() def on_button_fileopen_cancel_clicked(self, widget): self.fcdialog_open.hide() def on_filechooserdialog_open_delete_event(self, widget, event): self.fcdialog_open.hide() return True def on_button_file_open_error_close_clicked(self, widget): self.dialog_file_open_error.hide() def on_dialog_file_open_error_delete_event(self, widget, event): self.dialog_file_open_error.hide() return True def on_button_filesave_save_clicked(self, widget): filename = self.fcdialog_save.get_filename() filename = filename.encode(sys.getfilesystemencoding()) try: if os.path.isdir(filename): self.fcdialog_save.set_current_folder(filename) self.folder = filename else: if not filename.lower().endswith('.functionplot'): filename = filename + '.functionplot' folder = self.fcdialog_save.get_current_folder() self.filename = filename self.folder = folder if os.path.isfile(filename): logging.debug('File already exists: ' + filename) self.dialog_overwrite.show() else: saved = self._save() # TypeError is raised if the filename is empty, or only # spaces, or has invalid characters. except TypeError: pass def on_button_filesave_cancel_clicked(self, widget): self.fcdialog_save.hide() def on_filechooserdialog_save_delete_event(self, widget, event): self.fcdialog_save.hide() return True def on_button_save_error_close_clicked(self, widget): self.dialog_file_save_error.hide() def on_dialog_file_save_error_delete_event(self, widget, event): self.dialog_file_save_error.hide() return True def on_button_overwrite_yes_clicked(self, widget): self.dialog_overwrite.hide() self._save() def on_button_overwrite_cancel_clicked(self, widget): self.dialog_overwrite.hide() self.fcdialog_save.hide() def on_button_overwrite_no_clicked(self, widget): self.dialog_overwrite.hide() def on_dialog_overwrite_delete_event(self, widget, event): self.dialog_overwrite.hide() return True def on_button_confirm_open_yes_clicked(self, widget): self.fcdialog_open.set_current_folder(self.folder) self.dialog_confirm_open.hide() self.fcdialog_open.show() def on_button_confirm_open_cancel_clicked(self, widget): self.dialog_confirm_open.hide() def on_dialog_confirm_open_delete_event(self, widget, event): self.dialog_confirm_open.hide() return True def on_button_export_yes_clicked(self, widget): filename = self.fcdialog_export.get_filename() filename = filename.encode(sys.getfilesystemencoding()) try: if os.path.isdir(filename): self.fcdialog_export.set_current_folder(filename) self.folder = filename else: if not filename.lower().endswith('.png'): filename = filename + '.png' self.export_filename = filename folder = self.fcdialog_export.get_current_folder() self.folder = folder if os.path.isfile(filename): logging.debug('File already exists: ' + filename) self.dialog_export_overwrite.show() else: saved = self._export() # TypeError is raised if the filename is empty, or only # spaces, or has invalid characters. except TypeError: pass def on_button_export_cancel_clicked(self, widget): self.fcdialog_export.hide() def on_button_confirm_quit_yes_clicked(self, widget): gtk.main_quit() def on_button_confirm_quit_cancel_clicked(self, widget): self.dialog_confirm_quit.hide() def on_dialog_confirm_quit_delete_event(self, widget, event): self.dialog_confirm_quit.hide() return True def on_filechooserdialog_export_delete_event(self, widget, event): self.fcdialog_export.hide() return True def on_button_export_overwrite_yes_clicked(self, widget): self.dialog_export_overwrite.hide() self._export() def on_button_export_overwrite_cancel_clicked(self, widget): self.dialog_export_overwrite.hide() self.fcdialog_export.hide() def on_button_export_overwrite_no_clicked(self, widget): self.dialog_export_overwrite.hide() def on_dialog_export_overwrite_delete_event(self, widget, event): self.dialog_export_overwrite.hide() return True def on_button_export_error_close_clicked(self, widget): self.dialog_file_export_error.hide() def on_dialog_file_export_error_delete_event(self, widget, event): self.dialog_file_export_error.hide() return True def on_functionplot_delete_event(self, widget, event): self._quit() return True # example functions @threaded def _add_example_function(self, expr): self.changed = True gobject.idle_add(self.window_calculating.show) f = self.fg.add_function(expr) gobject.idle_add(self.window_calculating.hide) gobject.idle_add(self.update_function_list) gobject.idle_add(self.graph_update) def on_button_add_2_clicked(self, widget): self._add_example_function('2') def on_button_abs_xp2_m1_clicked(self, widget): self._add_example_function('abs(x+2)-1') def on_button_abs_x_p2_clicked(self, widget): self._add_example_function('abs(x)+2') def on_button_add_x_clicked(self, widget): self._add_example_function('x') def on_button_add_2x_clicked(self, widget): self._add_example_function('2x') def on_button_add_mx_clicked(self, widget): self._add_example_function('-x') def on_button_add_xm1_clicked(self, widget): self._add_example_function('x-1') def on_button_add_mxp3_clicked(self, widget): self._add_example_function('-x+3') def on_button_add_abs_x_clicked(self, widget): self._add_example_function('abs(x)') def on_button_abs_xp2_clicked(self, widget): self._add_example_function('abs(x+2)') def on_button_add_x_square_clicked(self, widget): self._add_example_function('x^2') def on_button_add_quad1_clicked(self, widget): self._add_example_function('2x^2') def on_button_add_quad2_clicked(self, widget): self._add_example_function('-x^2') def on_button_add_quad3_clicked(self, widget): self._add_example_function('3x^2+2x-4') def on_button_add_quad4_clicked(self, widget): self._add_example_function('(x-1)^2') def on_button_add_quad5_clicked(self, widget): self._add_example_function('(x+2)(x-1)') def on_button_add_quad6_clicked(self, widget): self._add_example_function('(x-2)^2') def on_button_add_x_cube_clicked(self, widget): self._add_example_function('x^3') def on_button_add_poly1_clicked(self, widget): self._add_example_function('2x^3') def on_button_add_poly2_clicked(self, widget): self._add_example_function('-x^3') def on_button_add_poly3_clicked(self, widget): self._add_example_function('3x^3-8x^2+2x-1') def on_button_add_poly4_clicked(self, widget): self._add_example_function('-(x-2)^3') def on_button_add_poly5_clicked(self, widget): self._add_example_function('(x+2)(x-1)(x-3)') def on_button_add_poly6_clicked(self, widget): self._add_example_function('x^4') def on_button_add_poly7_clicked(self, widget): self._add_example_function('x^4-3x^2+5x-3') def on_button_add_poly8_clicked(self, widget): self._add_example_function('x^5') def on_button_add_poly9_clicked(self, widget): self._add_example_function('-(x-5)^3 x^2') def on_button_add_poly10_clicked(self, widget): self._add_example_function('(x-1)^12') def on_button_add_poly11_clicked(self, widget): self._add_example_function('-(x+3)^13') def on_button_add_poly12_clicked(self, widget): self._add_example_function('abs(x^3)') def on_button_add_rat1_clicked(self, widget): self._add_example_function('1/x') def on_button_add_rat2_clicked(self, widget): self._add_example_function('-1/x') def on_button_add_rat3_clicked(self, widget): self._add_example_function('1/(x+2)') def on_button_add_rat4_clicked(self, widget): self._add_example_function('2/x') def on_button_add_rat5_clicked(self, widget): self._add_example_function('x/(2x+3)') def on_button_add_rat6_clicked(self, widget): self._add_example_function('(2x+1)/(x+1)') def on_button_add_rat7_clicked(self, widget): self._add_example_function('(x^2+1)/(x-1)') def on_button_add_rat8_clicked(self, widget): self._add_example_function('(x-1)/(x^2+1)') def on_button_add_rat9_clicked(self, widget): self._add_example_function('1/x^2') def on_button_add_rat10_clicked(self, widget): self._add_example_function('4/(x^2+1)') def on_button_add_pow1_clicked(self, widget): self._add_example_function('2^x') def on_button_add_pow2_clicked(self, widget): self._add_example_function('2^(-x)') def on_button_add_pow3_clicked(self, widget): self._add_example_function('-2^x') def on_button_add_pow4_clicked(self, widget): self._add_example_function('-2^(-x)') def on_button_add_pow5_clicked(self, widget): self._add_example_function('2^(x-1)') def on_button_add_pow6_clicked(self, widget): self._add_example_function('2^(x+1)') def on_button_add_pow7_clicked(self, widget): self._add_example_function('exp(x)') def on_button_add_pow8_clicked(self, widget): self._add_example_function('3^x') def on_button_add_pow9_clicked(self, widget): self._add_example_function('10^x') def on_button_add_pow10_clicked(self, widget): self._add_example_function('x^x') def on_button_add_log1_clicked(self, widget): self._add_example_function('log(x)') def on_button_add_log2_clicked(self, widget): self._add_example_function('log(x-1)') def on_button_add_log3_clicked(self, widget): self._add_example_function('log(x+1)') def on_button_add_log4_clicked(self, widget): self._add_example_function('log(2x)') def on_button_add_log5_clicked(self, widget): self._add_example_function('log(x)-2') def on_button_add_log6_clicked(self, widget): self._add_example_function('xlog(x)') def on_button_add_log7_clicked(self, widget): self._add_example_function('ln(x)') def on_button_add_log8_clicked(self, widget): self._add_example_function('log(x)ln(x)') def on_button_add_log9_clicked(self, widget): self._add_example_function('log(abs(x))') def on_button_add_trig1_clicked(self, widget): self._add_example_function('sin(x)') def on_button_add_trig2_clicked(self, widget): self._add_example_function('sin(2x)') def on_button_add_trig3_clicked(self, widget): self._add_example_function('-sin(x)') def on_button_add_trig4_clicked(self, widget): self._add_example_function('sin(x-1)') def on_button_add_trig5_clicked(self, widget): self._add_example_function('sin(x+1)') def on_button_add_trig6_clicked(self, widget): self._add_example_function('cos(x)') def on_button_add_trig7_clicked(self, widget): self._add_example_function('tan(x)') def on_button_add_trig8_clicked(self, widget): self._add_example_function('cot(x)') def on_button_add_trig9_clicked(self, widget): self._add_example_function('sec(x)') def on_button_add_trig10_clicked(self, widget): self._add_example_function('csc(x)') def on_button_add_root1_clicked(self, widget): self._add_example_function('sqrt(x)') def on_button_add_root2_clicked(self, widget): self._add_example_function('sqrt(2x)') def on_button_add_root3_clicked(self, widget): self._add_example_function('-sqrt(x)') def on_button_add_root4_clicked(self, widget): self._add_example_function('sqrt(-x)') def on_button_add_root5_clicked(self, widget): self._add_example_function('sqrt(x-1)') def on_button_add_root6_clicked(self, widget): self._add_example_function('sqrt(x^2+3)') def on_button_add_root7_clicked(self, widget): self._add_example_function('sqrt(1-x^2)') def on_button_add_root8_clicked(self, widget): self._add_example_function('xsqrt(x^2-4)') def on_button_add_comb1_clicked(self, widget): self._add_example_function('x-cos(x)') def on_button_add_comb2_clicked(self, widget): self._add_example_function('x^2/log(x)') def on_button_add_comb3_clicked(self, widget): self._add_example_function('x^3/abs(x(x-1))') def on_button_add_comb4_clicked(self, widget): self._add_example_function('x2^x') def on_button_add_comb5_clicked(self, widget): self._add_example_function('-4^x+x^4') def on_button_add_comb6_clicked(self, widget): self._add_example_function('(x^2+3)/sqrt(x-2)') def on_button_add_comb7_clicked(self, widget): self._add_example_function('sin(log(x))') # save the graph def _save(self): try: filehandler = open(self.filename, "wb") pickle.dump(self.fg, filehandler) filehandler.close() logging.debug('File saved: ' + self.filename) self.changed = False self.fcdialog_save.hide() return True except: self.dialog_file_save_error.show() return False # export the graph to png def _export(self): try: filename = self.export_filename self.fig.savefig(filename, dpi=300) self.fcdialog_export.hide() except: self.dialog_file_export_error.show() # restores the status of checkboxes when loading a graph # from a file or creating a new graph def _restore_state(self): self.checkmenuitem_function_intersections.\ set_active(self.fg.point_type_enabled[1]) self.checkmenuitem_x_intercepts.\ set_active(self.fg.point_type_enabled[2]) self.checkmenuitem_y_intercepts.\ set_active(self.fg.point_type_enabled[3]) self.checkmenuitem_extrema.\ set_active(self.fg.point_type_enabled[4]) self.checkmenuitem_inflection.\ set_active(self.fg.point_type_enabled[5]) self.checkmenuitem_vertical_asym.\ set_active(self.fg.point_type_enabled[6]) self.checkmenuitem_horizontal_asym.\ set_active(self.fg.point_type_enabled[7]) self.checkmenuitem_slope45.\ set_active(self.fg.point_type_enabled[8]) self.checkmenuitem_outliers.set_active(self.fg.outliers) self.checkmenuitem_show_poi.set_active(self.fg.show_poi) self.checkmenuitem_grouped.set_active(self.fg.grouped) self.checkmenuitem_legend.set_active(self.fg.show_legend) self.menuitem_legend_upper_right.set_active(False) self.menuitem_legend_upper_left.set_active(False) self.menuitem_legend_lower_right.set_active(False) self.menuitem_legend_lower_left.set_active(False) if self.fg.legend_location == 2: self.menuitem_legend_upper_left.set_active(True) elif self.fg.legend_location == 3: self.menuitem_legend_lower_left.set_active(True) elif self.fg.legend_location == 4: self.menuitem_legend_lower_right.set_active(True) else: self.menuitem_legend_upper_right.set_active(True) self.checkmenuitem_logscale.set_active(self.fg.logscale) self.btn_auto.set_active(self.fg.auto) def __init__(self): # Only a few colors defined. Hard to find more that will # stand out. If there are more functions, colors will cycle # from the start. # colors were taken mostly from http://latexcolor.com/ self.color = ['#4F81BD', # blue '#C0504D', # red '#9BBB59', # green '#8064A2', # purple '#F79646', # orange '#00B7EB', # cyan '#3B444B', # charcoal '#F0E130', # yellow '#DE5D83', # pink (blush) '#B87333', # copper '#0047AB', # cobalt '#614051', # eggplant ] # filenames to save to/open from and export to self.filename = None self.export_filename = None # create a FunctionGraph object self.fg = FunctionGraph() # we need this to keep track if the file has changed since # last save self.changed = False # we'll need this for panning self.mousebutton_press = None # Load GUI from glade file builder = gtk.Builder() builder.add_from_file(os.path.join(here, 'functionplot.glade')) # # Main Window # self.window = builder.get_object('functionplot') # on win32 just maximize the window. _NetWORKAREA # doesn't work anyway if win32: self.window.maximize() else: # on non-win32 systems, get the size of the # working area (if supported by the window # manager) and set the window dimensions to # 80% of that try: w = gtk.gdk.get_default_root_window() p = gtk.gdk.atom_intern('_NET_WORKAREA') workarea_width, workarea_height = \ w.property_get(p)[2][2:4] width = int(workarea_width * 0.8) height = int(workarea_height * 0.8) except TypeError: width = 700 height = 500 self.window.set_default_size(width, height) # menus self.imagemenuitem_quit = \ builder.get_object('imagemenuitem_quit') self.checkmenuitem_function_intersections = builder.\ get_object('checkmenuitem_function_intersections') self.checkmenuitem_x_intercepts = \ builder.get_object('checkmenuitem_x_intercepts') self.checkmenuitem_y_intercepts = \ builder.get_object('checkmenuitem_y_intercepts') self.checkmenuitem_extrema = \ builder.get_object('checkmenuitem_extrema') self.checkmenuitem_inflection = \ builder.get_object('checkmenuitem_inflection') self.checkmenuitem_vertical_asym = \ builder.get_object('checkmenuitem_vertical_asym') self.checkmenuitem_horizontal_asym = \ builder.get_object('checkmenuitem_horizontal_asym') self.checkmenuitem_slope45 = \ builder.get_object('checkmenuitem_slope45') self.checkmenuitem_outliers = \ builder.get_object('checkmenuitem_outliers') self.checkmenuitem_show_poi = \ builder.get_object('checkmenuitem_show_poi') self.checkmenuitem_grouped = \ builder.get_object('checkmenuitem_grouped') self.checkmenuitem_legend = \ builder.get_object('checkmenuitem_legend') self.menuitem_legend_upper_left = \ builder.get_object('menuitem_legend_upper_left') self.menuitem_legend_upper_right = \ builder.get_object('menuitem_legend_upper_right') self.menuitem_legend_lower_left = \ builder.get_object('menuitem_legend_lower_left') self.menuitem_legend_lower_right = \ builder.get_object('menuitem_legend_lower_right') self.checkmenuitem_logscale = \ builder.get_object('checkmenuitem_logscale') # main toolbar self.btn_auto = builder.get_object('btn_auto') # restore state of GUI widgets self._restore_state() # graph in main window self.table = builder.get_object('table_graph') self.fig = Figure(facecolor='w', tight_layout=True) self.ax = self.fig.add_subplot(111) self.canvas = FigureCanvas(self.fig) self.table.attach(self.canvas, 0, 1, 0, 1) # function list self.ls_functions = \ builder.get_object('liststore_functions') self.ls_functions.clear() self.treeview_functions = \ builder.get_object('treeview_functions') self.cr_toggle_visible = \ builder.get_object('cr_toggle_visible') # catch mouse wheel scroll self.canvas.mpl_connect('scroll_event', self.wheel_zoom) # catch click and pan self.canvas.mpl_connect('button_press_event', self.pan_press) self.canvas.mpl_connect('button_release_event', self.pan_release) self.canvas.mpl_connect('motion_notify_event', self.pan_motion) self.graph_update() # # file open/save dialogs # self.fcdialog_open = \ builder.get_object('filechooserdialog_open') self.fcdialog_save = \ builder.get_object('filechooserdialog_save') filefilter = gtk.FileFilter() filefilter.set_name(_('FunctionPlot files')) filefilter.add_pattern('*.functionplot') filefilter.add_pattern('*.FUNCTIONPLOT') self.fcdialog_open.add_filter(filefilter) self.fcdialog_save.add_filter(filefilter) self.dialog_file_open_error = \ builder.get_object('dialog_file_open_error') self.label_open_error = \ builder.get_object('label_open_error') self.dialog_file_save_error = \ builder.get_object('dialog_file_save_error') # use the "My documents" dir in windows if win32: self.folder = winshell.my_documents() else: self.folder = os.path.expanduser("~") # overwrite dialog self.dialog_overwrite = \ builder.get_object('dialog_overwrite') self.label_overwrite = builder.get_object('label_overwrite') # confirm open dialog self.dialog_confirm_open = \ builder.get_object('dialog_confirm_open') # confirm new dialog self.dialog_confirm_new = \ builder.get_object('dialog_confirm_new') # confirm quit dialog self.dialog_confirm_quit = \ builder.get_object('dialog_confirm_quit') # export dialogs self.fcdialog_export = \ builder.get_object('filechooserdialog_export') exportfilter = gtk.FileFilter() exportfilter.set_name(_('PNG image files')) exportfilter.add_pattern('*.png') exportfilter.add_pattern('*.PNG') self.fcdialog_export.add_filter(exportfilter) self.dialog_export_overwrite = \ builder.get_object('dialog_export_overwrite') self.dialog_file_export_error = \ builder.get_object('dialog_file_export_error') # # Add function dialog # self.dialog_add_function = \ builder.get_object('dialog_add_function') self.entry_function = builder.get_object('entry_function') self.dialog_add_error = \ builder.get_object('dialog_add_error') # Calculating... window self.window_calculating = \ builder.get_object('window_calculating') # About dialog self.aboutdialog = \ builder.get_object('aboutdialog') self.logo = gtk.gdk.pixbuf_new_from_file('img/functionplot.png') self.aboutdialog.set_logo(self.logo) # Connect all signals builder.connect_signals(self) self.window.show_all()
win = gtk.Window() win.connect("destroy", lambda x: gtk.main_quit()) win.set_default_size(400,300) win.set_title("Embedding in GTK") vbox = gtk.VBox() win.add(vbox) fig = Figure(figsize=(5,4), dpi=100) ax = fig.add_subplot(111) t = arange(0.0,3.0,0.01) s = sin(2*pi*t) ax.plot(t,s) canvas = FigureCanvas(fig) # a gtk.DrawingArea vbox.pack_start(canvas) toolbar = NavigationToolbar(canvas, win) vbox.pack_start(toolbar, False, False) def on_key_event(event): print('you pressed %s'%event.key) key_press_handler(event, canvas, toolbar) canvas.mpl_connect('key_press_event', on_key_event) win.show_all() gtk.main()
class Figure(gtk.VBox): def __init__(self): print "Starting up SamFigure!" gtk.VBox.__init__(self) self.figure = MPLFigure() self.canvas = FigureCanvas(self.figure) self.canvas.mpl_connect("button_press_event", self.on_click) self.ax = self.figure.add_subplot(111) self.ax2 = None self.mode = TWODPLOT self.new_data() self.xlabel = '' self.y1label = '' self.y2label = '' self.xsize = 0 self.ysize = 0 self.packed = False self.count_since_replot = 0 self.set_colors() def on_click(self, event): # If left button, if event.button == 1: # screen coordinates of click xclick, yclick = event.x, event.y top_ax = event.inaxes if top_ax is None: return # display coordinates of nearest point in ax data1=self.ax.transData.transform(\ zip(self.listing.getX(),self.listing.getY(1))) distances1=\ [(x-xclick)**2+(y-yclick)**2 \ for (x,y) in data1] ind_sel1 = numpy.argmin(distances1) dist1 = distances1[ind_sel1] xsel, ysel = data1[ind_sel1] label_ax = self.ax label_color = 'b' # if DUAL, then also check ax2 for nearer points if self.mode == DUALTWODPLOT: data2=self.ax2.transData.transform(\ zip(self.listing.getX(),self.listing.getY(2))) distances2=\ [(x-xclick)**2+(y-yclick)**2 \ for (x,y) in data2] ind_sel2 = numpy.argmin(distances2) dist2 = distances2[ind_sel2] if dist2 < dist1: xsel, ysel = data2[ind_sel2] label_color = 'g' label_ax = self.ax2 # Clear off old labels if hasattr(self, "label_text"): self.label_text.remove() self.label_point.remove() del (self.label_text) # Coordinates to show ( data coordinates of the selected axes) xlabel, ylabel = label_ax.transData.inverted().transform( (xsel, ysel)) # Coordinates to place label (on top set of axes) xloc, yloc = top_ax.transData.inverted().transform((xsel, ysel)) # Label the point if (xloc > sum(self.ax.get_xlim()) / 2): h_align = 'right' else: h_align = 'left' self.label_text=\ top_ax.text(xloc,yloc,'({0:.3g},{1:.3g})'\ .format(xlabel,ylabel),\ backgroundcolor='white', color=label_color,\ verticalalignment='bottom', horizontalalignment=h_align,\ bbox={'facecolor': 'white', 'boxstyle': 'round'},zorder=100 ) self.label_point,=\ top_ax.plot(xloc,yloc,'ro',\ zorder=self.label_text.get_zorder()+1) self.repaint() # Otherwise, just clear off old labels else: self.label_text.remove() self.label_point.remove() del (self.label_text) self.repaint() def replot(self): if self.mode == TWODPLOT: self.ax.clear() self.ax.plot(self.listing.getX(), self.listing.getY(1), self.color1 + '.-') self.count_since_replot = 0 elif self.mode == DUALTWODPLOT: self.ax.clear() self.ax2.clear() self.ax.plot(self.listing.getX(), self.listing.getY(1), self.color1 + '.-') self.ax2.plot(self.listing.getX(), self.listing.getY(2), self.color2 + '.-') self.count_since_replot = 0 def show(self): try: if not self.packed: self.pack_start(self.canvas, expand=True) toolbar = NavigationToolbar(self.canvas, self.get_parent_window()) next = 8 button = gtk.Button('Lin y') button.show() button2 = gtk.Button('Lin x') button2.show() # linear/log def clicked(button): self.adjust_axis_margins() self.set_axis_labels() self.color_labels() self.canvas.draw_idle() self.canvas.show() if self.ax.get_yscale() == 'log': button.set_label('Lin y') self.ax.set_yscale('linear') else: button.set_label('Log y') self.ax.set_yscale('log') self.show() def clicked2(button): self.adjust_axis_margins() self.set_axis_labels() self.color_labels() self.canvas.draw_idle() self.canvas.show() if self.ax.get_xscale() == 'log': button.set_label('Lin x') self.ax.set_xscale('linear') else: button.set_label('Log x') self.ax.set_xscale('log') self.show() button.connect('clicked', clicked) button2.connect('clicked', clicked2) toolitem = gtk.ToolItem() toolitem.show() toolitem.add(button) toolbar.insert(toolitem, next) next += 1 toolitem2 = gtk.ToolItem() toolitem2.show() toolitem2.add(button2) toolbar.insert(toolitem2, next) self.pack_start(toolbar, expand=False) self.packed = True super(Figure, self).show() except Exception, e: print 'Exception: ', e raise
win = gtk.Window() win.connect("destroy", lambda x: gtk.main_quit()) win.set_default_size(400, 300) win.set_title("Embedding in GTK") vbox = gtk.VBox() win.add(vbox) fig = Figure(figsize=(5, 4), dpi=100) ax = fig.add_subplot(111) t = arange(0.0, 3.0, 0.01) s = sin(2 * pi * t) ax.plot(t, s) canvas = FigureCanvas(fig) # a gtk.DrawingArea vbox.pack_start(canvas) toolbar = NavigationToolbar(canvas, win) vbox.pack_start(toolbar, False, False) def on_key_event(event): print('you pressed %s' % event.key) key_press_handler(event, canvas, toolbar) canvas.mpl_connect('key_press_event', on_key_event) win.show_all() gtk.main()
class XratersWindow(gtk.Window): __gtype_name__ = "XratersWindow" def __init__(self): """__init__ - This function is typically not called directly. Creation a XratersWindow requires redeading the associated ui file and parsing the ui definition extrenally, and then calling XratersWindow.finish_initializing(). Use the convenience function NewXratersWindow to create XratersWindow object. """ self._acc_cal = ((128, 128, 128), (255, 255, 255)) self._acc = [0, 0, 0] self._connected = False self._wiiMote = None self._resetData() self._dataLock = threading.Lock() isConnected = property(lambda self: self._connected) def callback(funct): """A decorator used to require connection to the Wii Remote This decorator is used to implement the precondition that the Wii Remote must be connected. """ def _callback(cls, *args, **kwds): if cls.isConnected: funct(cls, *args, **kwds) return True else: return False return _callback def _connectCallback(self, connectionMaker): """Callback function called upon successful connection to the Wiimote """ if connectionMaker.connected: self._connected = True self._wiiMote = connectionMaker.wiiMote self._resetData() gobject.timeout_add(45, self._drawAcc) self.widget('actionDisconnect').set_sensitive(True) self.widget('actionSave').set_sensitive(True) self.widget('actionReset').set_sensitive(True) self.widget('actionPause').set_sensitive(True) self.widget('toolbutton1').set_related_action( self.widget('actionDisconnect')) self._acc_cal = connectionMaker.acc_cal self._wiiMote.mesg_callback = self._getAcc self._updBatteryLevel() gobject.timeout_add_seconds(60, self._updBatteryLevel) else: self.widget('actionWiiConnect').set_sensitive(True) @callback def _upd_background(self, event): """Keep a copy of the figure background """ self.__background = self._accCanvas.copy_from_bbox(self._accAxis.bbox) def _getAcc(self, messages, theTime=0): """Process acceleration messages from the Wiimote This function is intended to be set as cwiid.mesg_callback """ if self._Paused: return for msg in messages: if msg[0] == cwiid.MESG_ACC: # Normalize data using calibration info for i, axisAcc in enumerate(msg[1]): self._acc[i] = float(axisAcc - self._acc_cal[0][i]) self._acc[i] /=(self._acc_cal[1][i]\ -self._acc_cal[0][i]) with self._dataLock: # Store time and acceleration in the respective arrays self._time.append(theTime - self._startTime) [self._accData[i].append(self._acc[i]) for i in threeAxes] # We only keep about 6 seconds worth of data if (self._time[-1] - self._time[0] > 6): with self._dataLock: self._time.pop(0) [self._accData[i].pop(0) for i in threeAxes] @callback def _drawAcc(self): """Update the acceleration graph """ # Do nothing while paused or there's no data available if self._Paused or len(self._time) == 0: return draw_flag = False # Update axes limits if the data fall out of range lims = self._accAxis.get_xlim() if self._time[-1] > lims[1]: self._accAxis.set_xlim(lims[0], lims[1] + 2) lims = self._accAxis.get_xlim() draw_flag = True if (self._time[-1] - lims[0] > 6): self._accAxis.set_xlim(lims[0] + 2, lims[1]) draw_flag = True if draw_flag: gobject.idle_add(self._accCanvas.draw) # Do the actual update of the background if self.__background != None: self._accCanvas.restore_region(self.__background) # Do the actual update of the lines with self._dataLock: [ self._lines[i].set_data(self._time, self._accData[i]) for i in threeAxes ] [self._accAxis.draw_artist(self._lines[i]) for i in threeAxes] self._accCanvas.blit(self._accAxis.bbox) @callback def _updBatteryLevel(self): """Callback to update the battery indicator in the status bar """ self._wiiMote.request_status() self._setBatteryIndicator( float(self._wiiMote.state['battery']) / cwiid.BATTERY_MAX) def _setBatteryIndicator(self, level): """Actually update the battery indicator in the status bar """ progressBar = self.widget("progressbarBattery") progressBar.set_fraction(level) progressBar.set_text("Battery: %.0f%%" % (level * 100)) def _resetData(self): """Reset stored data and status flags to their defaults """ self._accData = [list(), list(), list()] self._time = list() self._startTime = time.time() self._moveTime = self._startTime self._Paused = False def widget(self, name): """Helper function to retrieve widget handlers """ return self.builder.get_object(name) def finish_initializing(self, builder): """finish_initalizing should be called after parsing the ui definition and creating a XratersWindow object with it in order to finish initializing the start of the new XratersWindow instance. """ #get a reference to the builder and set up the signals self.builder = builder self.builder.connect_signals(self) #uncomment the following code to read in preferences at start up dlg = PreferencesXratersDialog.NewPreferencesXratersDialog() self.preferences = dlg.get_preferences() #code for other initialization actions should be added here self._accFigure = Figure(figsize=(8, 6), dpi=72) self._accAxis = self._accFigure.add_subplot(111) self._accAxis.set_xlabel("time (s)") self._accAxis.set_ylabel("acceleration (g)") self._lines = self._accAxis.plot(self._time, self._accData[X], self._time, self._accData[Y], self._time, self._accData[Z], animated=True) self._accFigure.legend(self._lines, ("X", "Y", "Z"), 'upper center', ncol=3) self._accAxis.set_xlim(0, 2) self._accAxis.set_ylim(-3, 3) self._accCanvas = FigureCanvas(self._accFigure) self._accCanvas.mpl_connect("draw_event", self._upd_background) self.__background = self._accCanvas.copy_from_bbox(self._accAxis.bbox) self._accCanvas.show() self._accCanvas.set_size_request(600, 400) vbMain = self.widget("vboxMain") vbMain.pack_start(self._accCanvas, True, True) vbMain.show() vbMain.reorder_child(self._accCanvas, 2) self._setBatteryIndicator(0) def about(self, widget, data=None): """about - display the about box for xraters """ about = AboutXratersDialog.NewAboutXratersDialog() response = about.run() about.destroy() def preferences(self, widget, data=None): """preferences - display the preferences window for xraters """ prefs = PreferencesXratersDialog.NewPreferencesXratersDialog() response = prefs.run() if response == gtk.RESPONSE_OK: #make any updates based on changed preferences here self.preferences = prefs.get_preferences() prefs.destroy() def quit(self, widget, data=None): """quit - signal handler for closing the XratersWindow""" self.destroy() def on_destroy(self, widget, data=None): """on_destroy - called when the XratersWindow is close. """ #clean up code for saving application state should be added here if self.isConnected: self.on_wiiDisconnect(widget, data) gtk.main_quit() def on_wiiConnect(self, widget, data=None): """Signal handler for the WiiConnect action """ self.widget('actionWiiConnect').set_sensitive(False) connectionMaker = WiiConnectionMaker(self.preferences['wiiAddress'], self.widget("statusbar"), self._connectCallback) self._accAxis.set_xlim(0, 2) gobject.idle_add(self._accCanvas.draw) connectionMaker.start() def on_wiiDisconnect(self, widget, data=None): """Signal handler for the WiiDisconnect action """ self._wiiMote.close() self._connected = False self.widget('actionDisconnect').set_sensitive(False) self.widget('actionWiiConnect').set_sensitive(True) self.widget('actionReset').set_sensitive(False) self.widget('actionPause').set_sensitive(False) self.widget('toolbutton1').set_related_action( self.widget('actionWiiConnect')) self.widget('actionSave').set_sensitive(True) self.widget('statusbar').pop( self.widget("statusbar").get_context_id('')) self._setBatteryIndicator(0) def on_Reset(self, widget, data=None): """Signal handler for the reset action """ self._resetData() self._accAxis.set_xlim(0, 2) gobject.idle_add(self._accCanvas.draw) def on_Pause(self, widge, data=None): """Signal handler for the pause action """ if not self._Paused: self.widget('actionPause').set_short_label("Un_pause") else: self.widget('actionPause').set_short_label("_Pause") self._Paused = not (self._Paused) def save(self, widget, data=None): """Signal handler for the save action """ fileName = os.sep.join([ self.preferences['outputDir'], "acceleration_" + time.strftime("%Y-%m-%d_%H-%M-%S") + ".dat" ]) try: with open(fileName, 'wb') as outFile: writer = csv.writer(outFile, 'excel-tab') outFile.write( writer.dialect.delimiter.join(("#time", "Ax", "Ay", "Az"))) outFile.write(writer.dialect.lineterminator) outFile.write( writer.dialect.delimiter.join(("#s", "g", "g", "g"))) outFile.write(writer.dialect.lineterminator) with self._dataLock: writer.writerows(zip(self._time, *self._accData)) except IOError as error: dialog = gtk.MessageDialog(parent=None, flags=gtk.DIALOG_DESTROY_WITH_PARENT, type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK, message_format=str(error)) dialog.set_title(error[1]) dialog.connect('response', lambda dialog, response: dialog.destroy()) dialog.show()
class DataMatrixGUI(gtk.Window): """ 2009-3-13 migrated from QCVisualize.py. now become a standalone program and able to read data from a file and plot ... QCVisualize.py inherits from here 2008-02-05 embed it into a bigger gnome app, add more buttons, and change the __init__() 2008-01-01 class to visualize the results from QualityControl.py """ def __init__(self, plot_title='', id_is_strain=1, header=None, strain_acc_list=None, category_list=None, data_matrix=None): """ 2008-01-10 use a paned window to wrap the scrolledwindow and the canvas so that the relative size of canvas to the scrolledwindow could be adjusted by the user. """ prog = gnome.program_init('DataMatrixGUI', '0.1') #this must be called before any initialization for gnome app program_path = os.path.dirname(__init__.__file__) xml = gtk.glade.XML(os.path.join(program_path, 'DataMatrixGUI.glade')) xml.signal_autoconnect(self) self.app1 = xml.get_widget("app1") self.app1.connect("delete_event", gtk.main_quit) self.app1.set_default_size(800, 1000) self.app1.set_title(plot_title) self.plot_title = plot_title self.id_is_strain = id_is_strain self.header = header self.strain_acc_list = strain_acc_list self.category_list = category_list self.data_matrix = data_matrix self.inputDataHeaders = None self.columnTypes = None self.columnHeaders = None self.columnEditableFlagList = None self.list2D = None self.vbox1 = xml.get_widget("vbox1") self.treeview_matrix = xml.get_widget("treeview_matrix") # matplotlib stuff fig = Figure(figsize=(8,8)) self.canvas = FigureCanvas(fig) # a gtk.DrawingArea self._idClick = self.canvas.mpl_connect('button_press_event', self.onUserClickCanvas) self.vpaned1 = xml.get_widget("vpaned1") self.vpaned1.add2(self.canvas) #self.vbox1.pack_start(self.canvas, True, True) self.ax = fig.add_subplot(111) self.treeview_matrix.connect('row-activated', self.plot_row) toolbar = NavigationToolbar(self.canvas, self.app1) self.vbox1.pack_start(toolbar, False, False) self.checkbutton_label_dot = xml.get_widget('checkbutton_label_dot') self.entry_dot_label_column = xml.get_widget('entry_dot_label_column') self.dataLabelColumnIndexAndSeparatorList = None self.dataLabelNumericItemIndexList = None self.entry_x_na = xml.get_widget('entry_x_na') self.entry_y_na = xml.get_widget('entry_y_na') self.entry_multiply_x = xml.get_widget('entry_multiply_x') self.entry_multiply_y = xml.get_widget('entry_multiply_y') self.entry_add_x = xml.get_widget('entry_add_x') self.entry_add_y = xml.get_widget('entry_add_y') self.entry_x_error = xml.get_widget("entry_x_error") self.entry_y_error = xml.get_widget("entry_y_error") self.checkbutton_logX = xml.get_widget('checkbutton_logX') self.checkbutton_logY = xml.get_widget('checkbutton_logY') self.checkButtonPlotOnlySelected = xml.get_widget('checkButtonPlotOnlySelected') self.entry_x_column = xml.get_widget('entry_x_column') self.entry_y_column = xml.get_widget('entry_y_column') self.entry_filters = xml.get_widget("entry_filters") #self.checkbutton_histLogX = xml.get_widget('checkbutton_histLogX') #self.checkbutton_histLogY = xml.get_widget('checkbutton_histLogY') self.entry_hist_column = xml.get_widget('entry_hist_column') self.entry_no_of_bins = xml.get_widget('entry_no_of_bins') self.entry_plot_title = xml.get_widget('entry_plot_title') self.entry_plot_title.set_text(self.plot_title) self.filechooserdialog_save = xml.get_widget("filechooserdialog_save") self.filechooserdialog_save.connect("delete_event", yh_gnome.subwindow_hide) self.entry_sampling_probability = xml.get_widget("entry_sampling_probability") self.filechooserdialog_open = xml.get_widget("filechooserdialog_open") self.filechooserdialog_open.connect("delete_event", yh_gnome.subwindow_hide) self.app1_appbar1 = xml.get_widget('app1_appbar1') self.app1_appbar1.push('Status Message.') #import gnome.ui has to be executed. self.treeview_matrix.connect('cursor-changed', self.update_no_of_selected, self.app1_appbar1) self.app1.show_all() self.xValuePreProcessor = None self.yValuePreProcessor = None self.x_error_column_index = None self.y_error_column_index = None self.typeName2PythonType = { "str": str, "string": str, "numeric":float, "number":float, "double":float, "float":float, "integer":int, "int":int} #self.add_events(gdk.BUTTON_PRESS_MASK|gdk.KEY_PRESS_MASK|gdk.KEY_RELEASE_MASK) def parseDataLabelColumns(self, inputText): """ 2015.04.16 """ splitP= re.compile(r'([,/|\.\-_=\?:;"\'^%$@+])') #any single character included could be used as splitter self.dataLabelColumnIndexAndSeparatorList = splitP.split(inputText) self.dataLabelNumericItemIndexList = [] for i in range(len(self.dataLabelColumnIndexAndSeparatorList)): if not splitP.match(self.dataLabelColumnIndexAndSeparatorList[i]): #it's a column index self.dataLabelColumnIndexAndSeparatorList[i] = int(self.dataLabelColumnIndexAndSeparatorList[i]) self.dataLabelNumericItemIndexList.append(i) return self.dataLabelColumnIndexAndSeparatorList, self.dataLabelNumericItemIndexList def getDataPointLabel(self, dataRow): """ 2015.04.16 """ dataLabelInList = copy.deepcopy(self.dataLabelColumnIndexAndSeparatorList) for i in self.dataLabelNumericItemIndexList: dataLabelInList[i] = str(dataRow[self.dataLabelColumnIndexAndSeparatorList[i]]) return ''.join(dataLabelInList) def onUserClickCanvas(self, event): """ 2016.06.07 bugfix. zero(0) generates false condition while only empty string or None should generate false. 2009-3-13 use (x_lim[1]-x_lim[0])/200. as the resolution for a dot to be called identical to a data point. similar for the y_data 2009-3-13 deal with checkbutton_label_dot, entry_dot_label_column, entry_x_column, entry_y_column 2008-01-01 derived from on_click_row() of QualityControl.py reaction when user clicked in the plot """ # get the x and y coords, flip y from top to bottom x, y = event.x, event.y toLabelDataPoint = self.checkbutton_label_dot.get_active() self.parseDataLabelColumns(self.entry_dot_label_column.get_text()) x_column = int(self.entry_x_column.get_text()) y_column = int(self.entry_y_column.get_text()) x_lim = self.ax.get_xlim() x_grain_size = abs(x_lim[1]-x_lim[0])/200. y_lim = self.ax.get_ylim() y_grain_size = abs(y_lim[1]-y_lim[0])/200. if event.button==1: if event.inaxes is not None: sys.stderr.write("x_grain_size: %s, y_grain_size: %s\n"%(x_grain_size, y_grain_size)) sys.stderr.write("data coords: %s, %s\n"%(event.xdata, event.ydata)) if self.list2D is None: return for row in self.list2D: if row[x_column] is not None and row[x_column]!="" and \ row[y_column] is not None and row[y_column]!="" : #not empty #2016.06.07 try: x_data = float(row[x_column]) y_data = float(row[y_column]) x = self.processDataValue(x_data, self.xValuePreProcessor) if x is None: continue y = self.processDataValue(y_data, self.yValuePreProcessor) if y is None: continue if abs(x-event.xdata)<x_grain_size and abs(y-event.ydata)<y_grain_size: dataLabel = self.getDataPointLabel(row) if toLabelDataPoint: self.ax.text(event.xdata, event.ydata, dataLabel, size=8) self.canvas.draw() sys.stderr.write("%s: %s, %s: %s, raw xy=(%s, %s), scaled xy=(%s,%s), dataLabel: %s.\n"%\ (self.columnHeaders[0], row[0], self.columnHeaders[1], row[1], row[x_column], row[y_column], x,y, dataLabel)) except: sys.stderr.write("Column %s, %s of row (%s), could not be converted to float. skip.\n"%\ (x_column, y_column, repr(row))) def setUserDataPreprocessingFlags(self): """ 2014.07.25 """ self.xValuePreProcessor = ValuePreProcessor(na = self.entry_x_na.get_text()) self.yValuePreProcessor = ValuePreProcessor(na = self.entry_y_na.get_text()) if self.entry_multiply_x.get_text(): self.xValuePreProcessor.scalar = float(self.entry_multiply_x.get_text()) if self.entry_multiply_y.get_text(): self.yValuePreProcessor.scalar = float(self.entry_multiply_y.get_text()) if self.entry_add_x.get_text(): self.xValuePreProcessor.addition = float(self.entry_add_x.get_text()) if self.entry_add_y.get_text(): self.yValuePreProcessor.addition = float(self.entry_add_y.get_text()) if self.entry_x_error.get_text(): self.xValuePreProcessor.errorColumnIndex = int(self.entry_x_error.get_text()) if self.entry_y_error.get_text(): self.yValuePreProcessor.errorColumnIndex = int(self.entry_y_error.get_text()) if self.checkbutton_logX.get_active(): self.xValuePreProcessor.logScale = True if self.checkbutton_logY.get_active(): self.yValuePreProcessor.logScale = True def processDataValue(self, value=None, valuePreProcessor=None): """ 2014.07.31 """ if valuePreProcessor.na is not None and (value==valuePreProcessor.na or \ float(value)==float(valuePreProcessor.na)): return None value = float(value) if valuePreProcessor.scalar is not None: value = value*valuePreProcessor.scalar if valuePreProcessor.addition is not None: value = value + valuePreProcessor.addition return value def decorateAxisLabel(self, label=None, valuePreProcessor=None): """ 2014.07.31 """ if valuePreProcessor.scalar is not None: label = "%s*%s"%(valuePreProcessor.scalar, label) if valuePreProcessor.addition: label = "%s+%s"%(label, valuePreProcessor.addition) return label def filterDataRow(self, dataRow): """ 2015.4.16 unfinished """ logicSplitP= re.compile(r'(AND|OR)') equationSplitP = re.compile(r'>=|>|=|<|<=') filtersText = self.entry_filters.get_text() logicSplitP.split(filtersText) self.dataLabelColumnIndexAndSeparatorList = splitP.split(inputText) self.dataLabelNumericItemIndexList = [] for i in range(len(self.dataLabelColumnIndexAndSeparatorList)): if not splitP.match(self.dataLabelColumnIndexAndSeparatorList[i]): #it's a column index self.dataLabelColumnIndexAndSeparatorList[i] = \ int(self.dataLabelColumnIndexAndSeparatorList[i]) self.dataLabelNumericItemIndexList.append(i) def plotXY(self, ax, canvas, liststore, plot_title='', chosen_index_ls=[]): """ 2015.01.28 add summary stats to title 2014.04.29 add error bars 2009-3-13 rename plot_NA_mismatch_rate to plotXY() 2008-02-05 chosen_index => chosen_index_ls 2007-12-14 """ x_column = int(self.entry_x_column.get_text()) y_column = int(self.entry_y_column.get_text()) self.setUserDataPreprocessingFlags() plot_title = self.entry_plot_title.get_text() min_x = 1 min_y = 1 max_x = 0 max_y = 0 x_ls = [] x_error_ls = [] y_ls = [] y_error_ls = [] x_chosen_ls = [] x_chosen_error_ls = [] y_chosen_ls = [] y_chosen_error_ls = [] noOfValuesDiscarded = 0 chosen_index_set = set(chosen_index_ls) for i in range(len(liststore)): row = liststore[i] x = row[x_column] y = row[y_column] if x=='' or y=='': continue noOfValuesDiscarded += 1 x = self.processDataValue(x, self.xValuePreProcessor) if x is None: continue noOfValuesDiscarded += 1 y = self.processDataValue(y, self.yValuePreProcessor) if y is None: continue noOfValuesDiscarded += 1 #self.filterDataRow() if self.xValuePreProcessor.errorColumnIndex is not None: x_error = row[self.xValuePreProcessor.errorColumnIndex] else: x_error = 0 if self.yValuePreProcessor.errorColumnIndex is not None: y_error = row[self.yValuePreProcessor.errorColumnIndex] else: y_error = 0 if x<min_x: min_x = x if x>max_x: max_x = x if y<min_y: min_y = y if y>max_y: max_y = y if i in chosen_index_set: x_chosen_ls.append(x) y_chosen_ls.append(y) x_chosen_error_ls.append(x_error) y_chosen_error_ls.append(y_error) else: x_ls.append(x) y_ls.append(y) x_error_ls.append(x_error) y_error_ls.append(y_error) sys.stderr.write("WARNING: %s values were discarded.\n"%(noOfValuesDiscarded)) ax.clear() if self.xValuePreProcessor.logScale: ax.set_xscale('log') if self.yValuePreProcessor.logScale: ax.set_yscale('log') #plot unselected data only if if not self.checkButtonPlotOnlySelected.get_active(): if self.x_error_column_index is not None and self.y_error_column_index is not None: ax.errorbar(x_ls, y_ls, xerr=x_error_ls, yerr=y_error_ls, ecolor='g', fmt='o') else: ax.plot(x_ls, y_ls, 'o', alpha=0.7, linewidth=0, linestyle="None") """ #diagonal line give a rough feeling about the notion, more NA, worse calling diagonal_start = min(min_x, min_y)-0.1 diagonal_end = max(max_x, max_x)+0.1 ax.plot([diagonal_start, diagonal_end],[diagonal_start, diagonal_end]) """ if x_chosen_ls and y_chosen_ls: #highlight titleWithStats = "Highlighted data\n" + \ yh_matplotlib.constructTitleFromTwoDataSummaryStat(x_chosen_ls, y_chosen_ls) ax.plot(x_chosen_ls, y_chosen_ls, 'o', alpha=0.6, c='r') if self.x_error_column_index is not None and self.y_error_column_index is not None: ax.errorbar(x_chosen_ls, y_chosen_ls, xerr=x_chosen_error_ls, yerr=y_chosen_error_ls, ecolor='r', color='r', fmt='o') else: #take all data titleWithStats = yh_matplotlib.\ constructTitleFromTwoDataSummaryStat(x_ls+x_chosen_ls, y_ls+y_chosen_ls) if plot_title: ax.set_title("%s %s"%(plot_title, titleWithStats)) else: ax.set_title(titleWithStats) xlabel = "(%s)"%self.columnHeaders[x_column] xlabel = self.decorateAxisLabel(xlabel, self.xValuePreProcessor) ax.set_xlabel(xlabel) ylabel = "(%s)"%self.columnHeaders[y_column] ylabel = self.decorateAxisLabel(ylabel, self.yValuePreProcessor) ax.set_ylabel(ylabel) canvas.draw() def plot_row(self, treeview, path, view_column): if self._idClick==None: self._idClick = self.canvas.mpl_connect('button_press_event', self.onUserClickCanvas) self.plotXY(self.ax, self.canvas, self.liststore, self.plot_title, path) def setupColumns(self, treeview): """ 2009-3-13 """ if not getattr(self, 'columnHeaders', None): sys.stderr.write("Nothing in columns yet.\n") return self.liststore = gtk.ListStore(*self.columnTypes) #self.add_columns(self.treeview_matrix) yh_gnome.create_columns(self.treeview_matrix, self.columnHeaders, self.columnEditableFlagList, self.liststore) yh_gnome.fill_treeview(self.treeview_matrix, self.liststore, self.list2D, reorderable=True) self.treeselection = self.treeview_matrix.get_selection() def on_button_PlotXY_clicked(self, widget, data=None): """ 2008-02-12 to update the no_of_selected rows (have to double click a row to change a cursor if it's multiple selection) """ if self._idClick==None: self._idClick = self.canvas.mpl_connect('button_press_event', self.onUserClickCanvas) pathlist_strains1 = [] self.treeselection.selected_foreach(yh_gnome.foreach_cb, pathlist_strains1) index_ls = [] for path in pathlist_strains1: index_ls.append(path[0]) self.app1_appbar1.push("%s rows selected."%len(pathlist_strains1)) self.plotXY(self.ax, self.canvas, self.liststore, self.plot_title, index_ls) def on_button_UnSelectAll_clicked(self, widget, data=None): """ 2015.04.16 """ self.treeselection = self.treeview_matrix.get_selection() self.treeselection.unselect_all() def on_button_save_clicked(self, widget, data=None): """ 2008-02-05 """ self.filechooserdialog_save.show_all() def on_button_filechooserdialog_cancel_ok_clicked(self, widget, data=None): """ 2008-02-05 """ self.filechooserdialog_save.hide() def on_button_filechooserdialog_save_ok_clicked(self, widget, data=None): """ 2008-02-12 to update the no_of_selected rows (have to double click a row to change a cursor if it's multiple selection) 2008-02-05 """ output_fname = self.filechooserdialog_save.get_filename() self.filechooserdialog_save.hide() pathlist_strains1 = [] self.treeselection.selected_foreach(yh_gnome.foreach_cb, pathlist_strains1) self.app1_appbar1.push("%s rows selected."%len(pathlist_strains1)) if self.header and self.strain_acc_list and self.category_list and self.data_matrix: selected_index_set = set() for path in pathlist_strains1: row = self.liststore[path[0]] id = row[0] index_in_data_matrix = row[-1] selected_index_set.add(index_in_data_matrix) if self.id_is_strain: id = id[1:-1].split(',') #id is a tuple of (ecotypeid,duplicate) self.strain_acc_list[index_in_data_matrix] = id[0].strip() self.category_list[index_in_data_matrix] = id[1].strip() #else: # self.header[index_in_data_matrix+2] = id if self.id_is_strain: rows_to_be_tossed_out = set(range(len(self.strain_acc_list))) - selected_index_set write_data_matrix(self.data_matrix, output_fname, self.header, self.strain_acc_list, self.category_list,\ rows_to_be_tossed_out, cols_to_be_tossed_out=set(), nt_alphabet=0) else: cols_to_be_tossed_out = set(range(len(self.header)-2)) - selected_index_set write_data_matrix(self.data_matrix, output_fname, self.header, self.strain_acc_list, self.category_list, rows_to_be_tossed_out=set(), cols_to_be_tossed_out=cols_to_be_tossed_out, nt_alphabet=0) def show_all(self): """ 2008-02-05 preserve the old interface. in order not to change anything in plot_col_NA_mismatch_rate() and plot_row_NA_mismatch_rate() of QualityControl.py """ self.app1.show_all() def on_button_PlotHistogram_clicked(self, widget, data=None): """ 2016.04.14 bugfix: skip "" /empty cells 2015.01.28 add summary stats to title 2009-5-20 get the number of bins from entry_no_of_bins 2009-3-13 draw histogram of specific hist_column 2008-02-06 """ if not getattr(self, 'columnHeaders', None): sys.stderr.write("Nothing in columns yet.\n") return self.setUserDataPreprocessingFlags() self.ax.clear() self.canvas.mpl_disconnect(self._idClick) #drop the signal handler self._idClick = None #reset the _idClick hist_ls = [] hist_column = int(self.entry_hist_column.get_text()) noOfValuesDiscarded = 0 for i in range(len(self.liststore)): x = self.liststore[i][hist_column] if x=='': #2016.04.14 bugfix skip if empty cells #if not x: noOfValuesDiscarded += 1 continue x = self.processDataValue(x, self.xValuePreProcessor) if x is None: continue noOfValuesDiscarded += 1 if self.xValuePreProcessor.logScale: if x>0: x = math.log10(x) else: sys.stderr.write("x value %s, not good for log10.\n"%(x)) continue noOfValuesDiscarded += 1 hist_ls.append(x) sys.stderr.write("WARNING: %s values were discarded.\n"%(noOfValuesDiscarded)) title = "%s %s %s"%(self.plot_title, self.columnHeaders[hist_column], yh_matplotlib.constructTitleFromDataSummaryStat(hist_ls)) self.ax.set_title(title); #"Histogram of %s %s"%(self.plot_title, self.columnHeaders[hist_column])) no_of_bins = int(self.entry_no_of_bins.get_text()) #if self.x_logScale: # self.ax.set_xscale('log') if self.yValuePreProcessor.logScale: self.ax.set_yscale('log') xlabel = "(%s)"%self.columnHeaders[hist_column] xlabel = self.decorateAxisLabel(xlabel, self.xValuePreProcessor) if self.xValuePreProcessor.logScale: xlabel = "log10(%s)"%(xlabel) self.ax.set_xlabel(xlabel) self.ax.hist(hist_ls, no_of_bins) self.canvas.draw() def update_no_of_selected(self, treeview, app1_appbar1): """ 2008-02-12 to update the no_of_selected rows (have to double click a row to change a cursor if it's multiple selection) """ pathlist_strains1 = [] self.treeselection.selected_foreach(yh_gnome.foreach_cb, pathlist_strains1) app1_appbar1.push("%s rows selected."%len(pathlist_strains1)) return True def parseDataHeader(self, dataHeaders=None): """ 2016.04.15 inserted a first column to denote order of data """ no_of_cols = len(dataHeaders) self.columnHeaders = ['']*(no_of_cols+1) self.columnHeaders[0] = "0 Order" self.columnTypes = [str]*(no_of_cols+1) self.columnTypes[0] = int self.columnEditableFlagList = [False]*(no_of_cols+1) print("columnHeaders: ", self.columnHeaders) print("columnTypes: ", self.columnTypes) print("columnEditableFlagList: ", self.columnEditableFlagList) for i in range(no_of_cols): header = dataHeaders[i] tmp_ls = header.split('|') columnHeader = tmp_ls[0] if len(tmp_ls)>1: columnTypeName = tmp_ls[1] elif i<2: #by default first two columns are of string type columnTypeName = "string" else: #by default columns after first two are of numeric type columnTypeName = 'number' column_type = self.typeName2PythonType.get(columnTypeName, str) self.columnHeaders[i+1] = '%s %s'%(i+1, columnHeader) self.columnTypes[i+1] = column_type if column_type==str: self.columnEditableFlagList[i+1] = True print("columnHeaders: ", self.columnHeaders) print("columnTypes: ", self.columnTypes) print("columnEditableFlagList: ", self.columnEditableFlagList) def readInDataToPlot(self, input_fname, sampling_probability=1.0): """ 2016.04.15 report summary of data and inserted a first column to denote order of data 2015.04.16 use parseDataHeader() convert each column data according to self.columnTypes 2015.01.23 added argument sampling_probability to sub-sample data 2013.07.11 use MatrixFile to read in the file 2009-5-20 add the column index into the column header for easy picking 2009-3-13 wrap the float conversion part into try...except to report what goes wrong 2009-3-13 """ if sampling_probability>1 or sampling_probability<0: sampling_probability=1.0 reader = MatrixFile(path=input_fname) self.inputDataHeaders = reader.__next__() print("delimiter: ", reader.delimiter) print("inputDataHeaders: ", self.inputDataHeaders) self.parseDataHeader(self.inputDataHeaders) self.list2D = [] dimOfRawData = [0,0] dimOfList2D = [0,0] for row in reader: dimOfRawData[0] += 1 dimOfRawData[1] = len(row) if sampling_probability>0 and sampling_probability<1: if random.random()>sampling_probability: #skip continue new_row = ['']*(len(row)+1) #first column is the order of data for i in range(len(row)): try: new_row[i+1] = self.columnTypes[i+1](row[i]) except: sys.stderr.write("Error in converting column %s data %s (row=%s) to type %s.\n"%\ (i, row[i], repr(row), self.columnTypes[i+1])) sys.stderr.write('Except type: %s\n'%repr(sys.exc_info())) traceback.print_exc() dimOfList2D[0] += 1 dimOfList2D[1] = len(new_row) new_row[0] = dimOfList2D[0] #order of this data self.list2D.append(new_row) reader.close() sys.stderr.write("Dimension of raw data: %s. Dimension of displayed data: %s."%\ (dimOfRawData, dimOfList2D)) self.setupColumns(self.treeview_matrix) #update status to reflect the input filename self.app1.set_title(os.path.basename(input_fname)) self.app1_appbar1.push(input_fname) self.plotXY(self.ax, self.canvas, self.liststore, self.plot_title) def readInRawMatrixData(self, input_fname): """ 2009-3-13 """ delimiter = figureOutDelimiter(input_fname) self.header, self.strain_acc_list, self.category_list, \ self.data_matrix = read_data(input_fname, delimiter=delimiter) def on_imagemenuitem_open_activate(self, widget, data=None): """ 2009-3-13 """ self.filechooserdialog_open.show_all() def on_button_fileopen_cancel_clicked(self, widget, data=None): """ 2015.01.23 """ self.filechooserdialog_open.hide() def on_button_fileopen_ok_clicked(self, widget, data=None): """ 2009-3-13 """ input_fname = self.filechooserdialog_open.get_filename() sampling_probability = float(self.entry_sampling_probability.get_text()) self.filechooserdialog_open.hide() self.readInDataToPlot(input_fname, sampling_probability) def on_entry_plot_title_change(self, widget, data=None): """ 2009-3-13 upon any change in the entry_plot_title """ self.plot_title = self.entry_plot_title.get_text()
class Graph_viewer: def __init__(self, graph, actions=['nothing'], callback=None): """ weights : dictionary mapping name to weight kmers will be colored in rank order of weight """ self.graph = graph self.callback = callback self.window = gtk.Window() self.window.connect('destroy', lambda x: gtk.main_quit()) self.window.set_default_size(800,600) self.window.set_title('Graph viewer') vbox = gtk.VBox() self.window.add(vbox) self.figure = Figure(figsize=(8,6), dpi=50) self.axes = self.figure.add_subplot(111) colors = numpy.empty((len(graph.names), 3)) sizes = numpy.empty(len(graph.names)) sizes[:] = 2.0 #if weights is None: # #self.axes.plot(graph.positions[:,0], graph.positions[:,1], ',') # # colors[:,:] = [[0.0,0.0,0.0]] # #else: #names = weights.keys() #values = weights.values() ##names.sort(key=lambda x: weights[x]) #idents = numpy.array([ graph.name_to_ident[name] for name in names ]) #x = numpy.array(values, dtype='float64') x = numpy.array(graph.weights, dtype='float64') x = numpy.log(x) x -= numpy.minimum.reduce(x) x /= numpy.average(x) * 2.0 #x /= numpy.sum(x*x)*2.0/numpy.sum(x) xx = numpy.minimum(x,1.0) #x = numpy.arange(len(graph.names)) / float(len(graph.names)) colors[:,0] = 0.5-xx*0.5 colors[:,1] = 0.75-xx*0.5 colors[:,2] = 1.0-xx*0.5 sizes[:] = numpy.maximum(x,1.0)**2 #*2.0 #n = 20 #for i in xrange(n): # start = i*len(names)//n # end = (i+1)*len(names)//n # if start == end: continue # # x = (1.0-float(i)/(n-1)) # position_block = graph.positions[idents[start:end]] # self.axes.scatter(position_block[:,0], # position_block[:,1], # linewidths=0, # marker='s', # s=10.0, # c=(0.0,x,x*0.5+0.5), # zorder=i) dots = Dots(graph.positions[:,1], graph.positions[:,0], colors, sizes) self.axes.add_artist(dots) #if len(graph.links) < 1000: # for i, (other, other_sign, other_travel) in enumerate(graph.links): # for j in other: # if j > i: # self.axes.plot([graph.positions[i,0],graph.positions[j,0]], # [graph.positions[i,1],graph.positions[j,1]], # 'k-') self.axes.axis('scaled') self.axes.set_xlim(0.0, numpy.maximum.reduce(graph.positions[:,0]) * 1.1) self.axes.set_ylim(0.0, numpy.maximum.reduce(graph.positions[:,1]) * 1.1) self.figure.subplots_adjust(top=0.99,bottom=0.05,right=0.99,left=0.05) #pylab.connect('button_press_event', self._on_click) self.annotation_pylab = [ ] self.clear_annotation() self.canvas = FigureCanvas(self.figure) # a gtk.DrawingArea self.canvas.mpl_connect('button_press_event', self._on_down) self.canvas.mpl_connect('button_release_event', self._on_up) vbox.pack_start(self.canvas) hbox = gtk.HBox() vbox.pack_start(hbox, False, False, 10) label = gtk.Label('Middle click:') hbox.pack_start(label, False, False, 5) self.radios = { } last = None for action in actions: radio = gtk.RadioButton(group=last, label=action) last = radio self.radios[action] = radio hbox.pack_start(radio, False, False, 5) label = gtk.Label('Right click: clear') hbox.pack_end(label, False, False, 5) self.radios[actions[0]].set_active(True) toolbar = NavigationToolbar(self.canvas, self.window) vbox.pack_start(toolbar, False, False) def run(self): self.window.show_all() gtk.main() def clear_annotation(self): self.annotation = { } def label(self, name, label): ident = self.graph.name_to_ident[name] self.axes.text( self.graph.positions[ident,0], self.graph.positions[ident,1], label, horizontalalignment='center', verticalalignment='bottom', zorder=100000) def arrow(self, names, label): positions = [ self.graph.positions[self.graph.name_to_ident[name]] for name in names if self.graph.has(name) ] if not positions: return #Error? max_positions = max(4, (len(positions)+29)//30) #20 if len(positions) > max_positions: positions = [ positions[i*(len(positions)-1)//(max_positions-1)] for i in xrange(max_positions) ] arrow = Arrow(positions, label, True) #names = [ name for name in names if self.graph.has(name) ] # #if len(names) < 2: return #Error? # #ident1 = self.graph.name_to_ident[names[0]] #ident2 = self.graph.name_to_ident[names[-1]] # #arrow = Arrow(self.graph.positions[ident1], # self.graph.positions[ident2], # label, # True) self.axes.add_artist(arrow) def annotate(self, name, mass,r,g,b): r *= mass g *= mass b *= mass old_mass, old_r, old_g, old_b = self.annotation.get(name,(0.0,0.0,0.0,0.0)) self.annotation[name] = (old_mass+mass,old_r+r,old_g+g,old_b+b) def refresh_annotation(self): while self.annotation_pylab: item = self.annotation_pylab.pop(-1) item.remove() xs = [ ] ys = [ ] colors = [ ] sizes = [ ] for name in self.annotation: mass,r,g,b = self.annotation[name] if not mass: continue ident = self.graph.name_to_ident[name] xs.append(self.graph.positions[ident,0]) ys.append(self.graph.positions[ident,1]) colors.append((r/mass,g/mass,b/mass)) sizes.append(mass) if xs: #thing = self.axes.scatter( # xs, # ys, # s=sizes, # c=colors, # linewidths=0, # marker='s', # zorder=10000) thing = Dots(numpy.array(ys), numpy.array(xs), numpy.array(colors), numpy.array(sizes), zorder=2) self.axes.add_artist(thing) self.annotation_pylab.append(thing) self.canvas.draw() def name_from_position(self, x,y): xoff = self.graph.positions[:,0] - x yoff = self.graph.positions[:,1] - y dist2 = xoff*xoff+yoff*yoff best = numpy.argmin(dist2) return self.graph.names[best] def _on_down(self, event): self.down_name = self.name_from_position(event.xdata, event.ydata) def _on_up(self, event): if event.inaxes and event.button == 3: self.clear_annotation() self.refresh_annotation() elif event.inaxes and event.button == 2: name = self.name_from_position(event.xdata, event.ydata) if self.callback: action = None for item in self.radios: if self.radios[item].get_active(): action = item self.callback(self, action, self.down_name, name) self.refresh_annotation() del self.down_name