def scatterplot_tab(): #File input record_dict = SeqIO.index( join(dirname(__file__), "data/protein_sequences.fasta"), "fasta") df = pd.read_csv(join(dirname(__file__), 'data/input_data.csv'), sep="\t", header=0) df = df.fillna(0.0) cut_off = 2.0 output_backend = "webgl" def create_figure(cut_off, df, output_backend): columns = sorted(df.columns[2:]) #Initialize variables for data input xs = df[x.value].values ys = df[y.value].values geneid = df['AlternateID'].values desc = df['Annotation'].values x_title = x.value.lower() y_title = y.value.lower() #create a new column in df named seq storing protein sequences result = {} for i in geneid: if i in record_dict.keys(): result[i] = str(record_dict[i].seq) else: result[i] = str('*') df['seq'] = result.values() seq = df['seq'].values data = { 'x_values': xs, 'y_values': ys, 'fold_change': [(-x / y) if (x > y and y != 0) else (y / x) if (y >= x and x != 0) else 'NaN' for x, y in zip(xs, ys)], 'GeneID': geneid, 'Annotation': desc, 'seq': seq } mysource = ColumnDataSource(data=data) #use CDSView function to determine a subset of significant genes for visualization significant_xy_view = CDSView( source=mysource, filters=[ BooleanFilter([ True if ((geneX > 0 and geneY > 0 and (abs(geneX / geneY) > cut_off)) or (geneX > 0 and geneY > 0 and abs(geneY / geneX) > cut_off) and (geneX + geneY) > 10) else False for geneX, geneY in zip(mysource.data['x_values'], mysource.data['y_values']) ]) ]) # create a plot and style its properties kw = dict() kw['title'] = "%s vs %s" % (x_title, y_title) #make a plot p = figure(plot_height=500, plot_width=700, output_backend=output_backend, tools='pan,box_zoom,wheel_zoom,reset,save,tap', **kw) #make sure WheelZoomTool is activated by default p.toolbar.active_scroll = p.select_one(WheelZoomTool) p.xaxis.axis_label = x_title p.yaxis.axis_label = y_title p.yaxis.axis_label_text_font_size = '10pt' p.xaxis.axis_label_text_font_size = '10pt' p.yaxis.major_label_text_font_size = '10pt' p.xaxis.major_label_text_font_size = '10pt' p.title.text_font_size = '12pt' common_circle_kwargs = { 'x': 'x_values', 'y': 'y_values', 'source': mysource, 'hover_color': 'black' } p.circle(**common_circle_kwargs, color="skyblue", alpha=0.7, size=9, line_color="white") p.circle(**common_circle_kwargs, view=significant_xy_view, color="red", muted_alpha=0.1, legend_label='sig. genes', size=9, line_color="black") # Highlighting of genes using a substring in the gene annotation, if it is provided in the Textfield if desc_sel.value != "": selected = df[df.Annotation.str.contains(desc_sel.value, case=False) == True] p.circle(x=selected[x.value].values, y=selected[y.value].values, color="yellow", alpha=1.0, muted_alpha=0.1, legend_label='sel. genes', size=8, line_color="black") # Set autohide to true to only show the toolbar when mouse is over plot p.toolbar.autohide = True p.legend.title = 'Click to hide' p.legend.location = "bottom_right" p.legend.border_line_width = 1 p.legend.border_line_color = "black" p.legend.border_line_alpha = 0.5 # use the "seq" column of mysource to complete the URL # e.g. if the glyph at index 1 is selected, then @seq # will be replaced with mysource.data['seq'][1] url = "http://papers.genomics.lbl.gov/cgi-bin/litSearch.cgi?query=@seq&Search=Search" taptool = p.select(type=TapTool) taptool.callback = OpenURL(url=url) # Format the tooltip tooltips = [('GeneID', '@GeneID'), ('Annotation', '@Annotation{safe}'), ('fold change', '@fold_change'), ('FPKM (%s)' % (x_title), '@x_values'), ('FPKM (%s)' % (y_title), '@y_values')] # Configure a renderer to be used upon hover hover_glyph = p.circle(**common_circle_kwargs, size=15, alpha=0, hover_fill_color='black', hover_alpha=0.5) # Add the custom HoverTool to the figure p.add_tools(HoverTool(tooltips=tooltips, renderers=[hover_glyph])) # Add the custom CrosshairTool to the figure p.add_tools(CrosshairTool(line_width=1)) # Add interactivity to the legend p.legend.click_policy = "hide" return p def update_data(attr, old, new): cut_off = float(sl.value) layout.children[1] = create_figure(cut_off, df, output_backend) x = Select(title='X-Axis: condition A', value='wt_0min', options=sorted(list(df.iloc[:, 2:].columns))) x.on_change('value', update_data) y = Select(title='Y-Axis: condition B', value='wt_25min', options=sorted(list(df.iloc[:, 2:].columns))) y.on_change('value', update_data) sl = Slider(start=0.0, end=10.0, value=cut_off, step=0.5, title='|fold change| \u003E') sl.callback_policy = 'mouseup' sl.on_change('value_throttled', update_data) desc_sel = TextInput(title="Gene annotation contains:") desc_sel.on_change('value', update_data) div = Div(text=""" Interact with the widgets below to query a list of significant genes to plot. Hover over the circles to see more information about each gene. Click on the circle to get information from PaperBlast""") #add button for saving plot as .svg def button_handler(): timestr = time.strftime("%Y%m%d-%H%M%S") p.output_backend = 'svg' export_svgs(p, filename="scatterplot{}.svg".format(timestr)) p.output_backend = 'webgl' button = Button(label="Save as .svg", button_type="success") button.on_click(button_handler) p = create_figure(cut_off, df, output_backend) # Make a tab with the layout controls = column(x, y, sl, desc_sel, button, width=200) layout = row(column(div, controls), p) tab = pn.pane.Bokeh(layout) return tab
def slider_cb(attr, old, new): # call draw function and put the new figure in the layout p = illusion.draw(permMap[variation_selector.active], distortion_slider.value) pBox.children[0] = p submit_button.on_click(submit_button_cb) variation_selector.on_change('active', selector_cb) save_button.on_click(save_button_cb) #slider.on_change('value', cb) # hack to throttle slider callback (https://stackoverflow.com/questions/38375961/throttling-in-bokeh-application/38379136#38379136) distortion_slider.callback_policy = 'mouseup' #call only on mouseup #slider.callback_throttle = 50 #call max every x ms source = ColumnDataSource(data=dict(value=[])) source.on_change('data', slider_cb) distortion_slider.callback = CustomJS(args=dict(source=source), code=""" source.data = { value: [cb_obj.value] } """) # ## some CSS to center layout # header = Div(text=""" # <style> # body { width: 1150px; margin: 0 auto; } # </style> # """) # curdoc().add_root(header)