def make_document(doc: Document): doc.title = "Backtrader Optimization Result" env = Environment( loader=PackageLoader('backtrader_plotting.bokeh', 'templates')) doc.template = env.get_template("basic.html.j2") model = self.generate_optresult_model(result, columns) doc.add_root(model)
def go(self): """Displays the application""" document = Document() document.title = "UT330 UI" document.add_root(self.tabs) session = push_session(document) session.show() session.loop_until_closed()
def make_document(doc: Document): doc.title = "Backtrader Optimization Result" env = Environment( loader=PackageLoader('backtrader_plotting.bokeh', 'templates')) doc.template = env.get_template("basic.html.j2") doc.template_variables['stylesheet'] = utils.generate_stylesheet( self._bokeh.params.scheme) model = self._build_optresult_model() doc.add_root(model)
def get_bokeh_script(user, plot, suffix): from .models import UserSession document = Document() document.add_root(plot) document.title = suffix with closing(push_session(document)) as session: # Save the session id to a UserSession UserSession.objects.create(user=user, bokeh_session_id=session.id) # Get the script to pass into the template script = autoload_server(None, session_id=session.id) return script
def make_document(doc: Document): if self._on_session_destroyed is not None: doc.on_session_destroyed(self._on_session_destroyed) # set document title doc.title = self._title # set document template env = Environment(loader=PackageLoader('backtrader_plotting.bokeh', 'templates')) doc.template = env.get_template(self._html_template) doc.template_variables['stylesheet'] = utils.generate_stylesheet(self._scheme) # get root model model = self._model_factory_fnc(doc) doc.add_root(model)
def make_document(doc: Document): if self._on_session_destroyed is not None: doc.on_session_destroyed(self._on_session_destroyed) # set document title doc.title = self._title # set document template now = datetime.now() env = Environment(loader=PackageLoader('btplotting', 'templates')) templ = env.get_template(self._html_template) templ.globals['now'] = now.strftime('%Y-%m-%d %H:%M:%S') doc.template = templ doc.template_variables['stylesheet'] = generate_stylesheet( self._scheme) model = self._model_factory_fnc(doc) doc.add_root(model)
def plot_code_iterator(self): """ Iterator over the single bokeh plot :return: Tuple of js-script code for the plot and number of invalid values """ for index, dummy in enumerate(self.__conf.filter_args): if self.__index is not None and self.__index != index: continue document = Document() document.title = self.__conf.description self.__factors, self.__values, num_invalid = \ self.create_x_y_values(index) plot = self.__create_control_chart_hist(index) document.add_root(plot) session_id = self.__save_user_session(document, index) script = autoload_server(None, session_id=session_id) yield script, num_invalid
def density_handler(doc: Document) -> None: """ Handler function for the density application. """ task_id = doc.session_context.request.arguments.get('task_id') username = doc.session_context.request.arguments.get('username') user_dir = os.path.join(settings.USER_DATA, username) path_to_db = os.path.join(user_dir, task_id) try: conn = os.path.join(path_to_db, task_id + '.csv') df = pd.read_csv(conn) proteins = list(df.Protein.unique()) lipids = list(df.Lipids.unique()) except: proteins, lipids = [], [] for o in os.listdir(path_to_db): key = o.split('/')[-1] if key.endswith('.npy'): if key.startswith('prot_'): proteins.append('Protein(s)') else: lipid = key.split('_')[0] lipids.append(lipid) all_mpl_cmaps = [ 'viridis', 'plasma', 'inferno', 'cividis', 'Greys', 'Purples', 'Blues', 'Greens', 'Oranges', 'Reds', 'RdYlBu', 'RdYlGn', 'Spectral', 'Spectral_r', 'coolwarm', 'coolwarm_r', 'seismic', 'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu', 'GnBu', 'PuBu', 'YlGnBu', 'PuBuGn', 'BuGn', 'YlGn', 'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGy', 'RdBu', ] #TODO: globals declaration should not be necessary anymore. global prot_xyz prot_xyz = np.load(os.path.join(path_to_db, "prot_" + task_id + '.npy')) global l_xyz global x_min, x_max, y_min, y_max, z_min, z_max l_xyz = np.load( os.path.join(path_to_db, lipids[0] + "_" + task_id + '.npy')) x_min, x_max = l_xyz[:, 0].min(), l_xyz[:, 0].max() y_min, y_max = l_xyz[:, 1].min(), l_xyz[:, 1].max() z_min, z_max = l_xyz[:, 2].min(), l_xyz[:, 2].max() # widgets color_map = Select(title="Colormap", value="viridis", options=all_mpl_cmaps, width=120) lipid = Select(title="Lipids", value=lipids[0], options=lipids, width=100) denstype = Select(title="Density Type", value="All Proteins", options=["All Proteins", "Average"], width=120) number = Slider(title="Number of Bins", value=380, start=80, end=500, step=10, width=200) protein = Select(title="Show Protein", value="No", options=["Yes", "No"], width=90) gpcr = Select(title="Protein", value=proteins[0], options=proteins, width=130) zrange = RangeSlider(start=z_min, end=z_max, value=(z_min, z_max), step=0.2, title="Z-Axis Range", callback_policy='mouseup', width=352) cbar_range = Slider(value=256, start=0, end=256, step=1, height=600, orientation='vertical', callback_policy='mouseup', margin=(15, 0), tooltips=False, show_value=False) # colorschemes colormap = cm.get_cmap(color_map.value) bokehpalette = [ mpl.colors.rgb2hex(m) for m in colormap(np.arange(colormap.N)) ] def lipid_density(array, bins=160): """Given a 2D array, containing the x, y values of a lipid, return its histogram with edges.""" x = array[:, 0] y = array[:, 1] lipid, e1, e2 = np.histogram2d(x, y, density=True, bins=bins) return lipid, e1, e2 # Plot histogram image H, xe, ye = lipid_density(l_xyz, number.value) minx = np.abs(xe.min()) miny = np.abs(ye.min()) p1 = figure(plot_height=640, plot_width=640, tools='') image_source = ColumnDataSource(data=dict(image=[])) img = p1.image(image="image", x=xe[0], y=ye[0], dw=xe[-1] + minx, dh=ye[-1] + miny, palette=bokehpalette, source=image_source) circle_prot_source = ColumnDataSource( data=dict(x1=prot_xyz[:, 0], y1=prot_xyz[:, 1])) p1.circle(x="x1", y="y1", source=circle_prot_source, size=2, fill_alpha=0.2) cb_palette = LinearColorMapper(palette=bokehpalette, low=H.min(), high=H.max()) color_bar = ColorBar(color_mapper=cb_palette, width=8, location=(0, 0), label_standoff=10) color_bar.formatter = BasicTickFormatter(use_scientific=False) p1.add_layout(color_bar, 'right') # Make graph pretty p1.xgrid.grid_line_color = None p1.ygrid.grid_line_color = None p1.xaxis.major_tick_line_color = None p1.xaxis.minor_tick_line_color = None p1.yaxis.major_tick_line_color = None p1.yaxis.minor_tick_line_color = None p1.xaxis.major_label_text_font_size = '0pt' p1.yaxis.major_label_text_font_size = '0pt' p1.grid.visible = False p1.toolbar.logo = None p1.toolbar_location = None def update_all(cond=False, cmap=False): """ Update the image showing all proteins. """ if cond: # For efficiency execute only if GPCR structure changes global l_xyz global x_min, x_max, y_min, y_max, z_min, z_max l_xyz = np.load( os.path.join(path_to_db, str(lipid.value) + "_" + task_id + '.npy')) x_min, x_max = l_xyz[:, 0].min(), l_xyz[:, 0].max() y_min, y_max = l_xyz[:, 1].min(), l_xyz[:, 1].max() z_min, z_max = l_xyz[:, 2].min(), l_xyz[:, 2].max() zrange.start = z_min zrange.end = z_max index = np.where((l_xyz[:, 2] > zrange.value[0]) & (l_xyz[:, 2] < zrange.value[1])) l_xyz_new = l_xyz[index] else: l_xyz_new = l_xyz if cmap: # For efficiency execute only if image colormap changes cb_cut_value = 256 - cbar_range.value cmap = color_map.value colormap = cm.get_cmap(cmap) bokehpalette = [ mpl.colors.rgb2hex(m) for m in colormap(np.arange(colormap.N)) ] bp_i = 0 while bp_i < len(bokehpalette[:cb_cut_value]): bokehpalette[bp_i] = '#ffffff' bp_i += 1 img.glyph.color_mapper.palette = bokehpalette color_bar.color_mapper.palette = bokehpalette # Update histogram image H, xe, ye = lipid_density(l_xyz_new, number.value) minx = np.abs(xe.min()) miny = np.abs(ye.min()) img.glyph.dw = xe[-1] + minx img.glyph.dh = ye[-1] + miny # update image source image_source.data = dict(image=[H]) def update_protein(cond=False): """ Update the protein representation. """ if cond: # For efficiency execute only if GPCR structure changes global prot_xyz if protein.value == "Yes": circle_prot_source.data = dict(x1=prot_xyz[:, 0], y1=prot_xyz[:, 1]) elif protein.value == "No": circle_prot_source.data = dict(x1=[], y1=[]) def update_cbar(): cb_cut_value = 256 - cbar_range.value cmap = color_map.value colormap = cm.get_cmap(cmap) bokehpalette = [ mpl.colors.rgb2hex(m) for m in colormap(np.arange(colormap.N)) ] bp_i = 0 while bp_i < len(bokehpalette[:cb_cut_value]): bokehpalette[bp_i] = '#ffffff' bp_i += 1 img.glyph.color_mapper.palette = bokehpalette color_bar.color_mapper.palette = bokehpalette # event listeners controls = [lipid, zrange, gpcr] for control in controls: control.on_change('value', lambda attr, old, new: update_denstype(cond=True)) number.on_change('value', lambda attr, old, new: update_denstype()) color_map.on_change('value', lambda attr, old, new: update_denstype(cmap=True)) protein.on_change('value', lambda attr, old, new: update_protein()) denstype.on_change('value', lambda attr, old, new: update_denstype()) cbar_range.on_change('value', lambda attr, old, new: update_cbar()) # deal with what gets updated and what not. def update_denstype(cond=False, cmap=False): update_all(cond, cmap) update_protein(cond) update_denstype() input1 = row([gpcr, lipid, color_map, protein]) input2 = row([p1, cbar_range]) input3 = row([number, zrange]) input3 = column([input1, input2, input3]) l = layout([input3]) doc.add_root(l) doc.title = "Density App"
def scatter_handler(doc: Document) -> None: """ Handler function for the scatter application. """ # Load data task_id = doc.session_context.request.arguments.get('task_id') username = doc.session_context.request.arguments.get('username') user_dir = os.path.join(settings.USER_DATA, username) path_to_db = os.path.join(user_dir, task_id) conn = os.path.join(path_to_db, task_id + '.csv') df = pd.read_csv(conn) for col in df.columns: if col.endswith('Error'): if df[col].max() == 0: del df[col] # widgets radii = [str(x) for x in df.Radius.unique()] number = Slider(title="Value Cutoff", value=0, start=0, end=4, step=0.1, width=150) residue = TextInput(title="Residue name (3 letter code):", width=200) gpcr = Select(title="Proteins", value=list(df.Protein.unique())[0], options=list(df.Protein.unique()), width=100) lipid = Select(title="Lipids", value=list(df.Lipids.unique())[0], options=list(df.Lipids.unique()), width=100) radius = Select(title="Radius", value=radii[-1], options=radii, width=100) options = list(df.columns)[:-5] + ['ResID'] x_axis = Select(title="X Axis", options=options, value="ResID", width=150) y_axis = Select(title="Y Axis", options=options, value=options[0], width=150) # colors and plotting cc_colors = [x for x in cc.all_original_names() if x.startswith('linear') or x.startswith('rainbow')] cmap = Select(title="Colormap", options=cc_colors, value='linear_kryw_0_100_c71', width=150) # Create Column Data Source that will be used by the plot source = ColumnDataSource(data=dict(x=[], y=[], ResName=[], ResID=[], Protein=[])) TOOLTIPS=[ ("ResName", "@ResName"), ("ResID", "@ResID"), ("Value", "@y") ] point_color_mapper = linear_cmap(field_name='y', palette=cc.CET_L19, low=df[df.Protein == gpcr.value][y_axis.value].min(), high=df[df.Protein == gpcr.value][y_axis.value].max()) p = figure(plot_height=400, plot_width=800, tooltips=TOOLTIPS,) circle_plot = p.circle(x="x", y="y", source=source, line_color='black', fill_color=point_color_mapper, size=7) circle_object = {'circle': circle_plot} # make plot pretty p.toolbar.autohide = True p.axis.axis_label_text_font_size = "12pt" p.axis.axis_label_text_font_style = "bold" p.title.align = 'center' def update(df): y_value = y_axis.value x_value = x_axis.value df = df[ (df[y_value] >= number.value) & (df['Protein'] == gpcr.value) & (df['Lipids'] == lipid.value) & (df['Radius'] == float(radius.value)) ] if (residue.value != ""): df = df[df.ResName.str.contains(residue.value.upper())==True] point_color_mapper = linear_cmap(field_name='y', palette=cc.palette[cmap.value], low=df[df.Protein == gpcr.value][y_value].min(), high=df[df.Protein == gpcr.value][y_value].max()) circle_object['circle'].glyph.fill_color = point_color_mapper p.xaxis.axis_label = x_value p.yaxis.axis_label = y_value p.title.text = "Showing %d Data Points " % len(df) source.data = dict( x=df[x_value], y=df[y_value], ResName=df["ResName"], ResID=df["ResID"], Protein=df["Protein"], ) # add controls controls = [number, gpcr, lipid, radius, y_axis, x_axis, residue, cmap] for control in controls: control.on_change('value', lambda attr, old, new: update(df)) # build layout # TODO: this should be made easier to read sizing_mode = 'scale_width' inputs2 = row([gpcr, lipid, radius, residue], sizing_mode=sizing_mode) inputs3 = row([number, x_axis, y_axis, cmap], sizing_mode=sizing_mode) layout1 = layout([[inputs2]], sizing_mode=sizing_mode) layout2 = layout([p], sizing_mode=sizing_mode) layout3 = layout([inputs3], sizing_mode="scale_width") # render update(df) doc.add_root(layout1) doc.add_root(layout2) doc.add_root(layout3) doc.title = "Point Application"
def radar_handler(doc: Document) -> None: """ Handler function for the radar application. """ # Load data. task_id = doc.session_context.request.arguments.get('task_id') username = doc.session_context.request.arguments.get('username') user_dir = os.path.join(settings.USER_DATA, username) path_to_db = os.path.join(user_dir, task_id) conn = os.path.join(path_to_db, task_id + '.csv') df = pd.read_csv(conn) for col in df.columns: if col.endswith('Error'): del df[col] # NOTE: How does this fare with multiple different proteins? And should we care? gpcrs = list(df.Protein.unique()) lipids = list(df.Lipids.unique()) radius = list(df.Radius.unique()) radius = [str(r) for r in radius] # NOTE: every metric is normalized with respect to itself! # Normalize [0-1] all contact parameters with respect to each other. # TODO: There are better ways of doing this! This app needs to be improved. for cmn in list(df.columns)[:6]: for lipid in lipids: for radius_value in radius: radius_value = float(radius_value) dfmin = df[(df.Lipids == lipid) & (df.Radius == radius_value)][cmn].min() dfmax = df[(df.Lipids == lipid) & (df.Radius == radius_value)][cmn].max() lip_index = list(df[(df.Lipids == lipid) & (df.Radius == radius_value)].index) df.loc[lip_index, cmn] = df[(df.Lipids == lipid) & (df.Radius == radius_value)][cmn].apply( lambda x: (x - dfmin) / (dfmax - dfmin)) df = df.fillna(0) # TODO: It is better to simply remove residues with zero contacts so they do not overcrowd the selection box. # 1 unique set of residues - works also if there's only 1 set available. resname = df[(df.Protein == gpcrs[0]) & (df.Lipids == lipids[0]) & (df.Radius == float(radius[0]))].ResName.to_list() resid = df[(df.Protein == gpcrs[0]) & (df.Lipids == lipids[0]) & (df.Radius == float(radius[0]))].ResID.to_list() residues = [] for rn, ri in zip(resname, resid): residues.append("{}-{}".format(rn, ri)) # random starting values import random # Create Input controls gpcr1 = Select(title="Protein", value=gpcrs[0], options=gpcrs, width=100) gpcr2 = Select(title="Protein", value=gpcrs[0], options=gpcrs, width=100) lipid1 = Select(title="Lipids", value=lipids[0], options=lipids, width=100) lipid2 = Select(title="Lipids", value=lipids[0], options=lipids, width=100) residue1 = Select(title="Residue", value=random.choice(residues), options=residues, width=120) residue2 = Select(title="Residue", value=random.choice(residues), options=residues, width=120) radius1 = Select(title="Radius", value=radius[0], options=radius, width=100) radius2 = Select(title="Radius", value=radius[0], options=radius, width=100) def unit_poly_verts(theta, centre): """Return vertices of polygon for subplot axes. This polygon is circumscribed by a unit circle centered at (0.5, 0.5) """ x0, y0, r = [centre] * 3 verts = [(r * np.cos(t) + x0, r * np.sin(t) + y0) for t in theta] return verts def radar_patch(r, theta, centre): """ Returns the x and y coordinates corresponding to the magnitudes of each variable displayed in the radar plot """ # offset from centre of circle offset = 0 yt = (r * centre + offset) * np.sin(theta) + centre xt = (r * centre + offset) * np.cos(theta) + centre return list(xt), list(yt) # We need to make the plot pretty! def star_curv(old_x, old_y): """ Interpolates every point by a star-shaped curv. It does so by adding "fake" data points in-between every two data points, and pushes these "fake" points towards the center of the graph (roughly 1/4 of the way). """ try: points = np.array([old_x, old_y]).reshape(7, 2) hull = ConvexHull(points) x_mid = np.mean(hull.points[hull.vertices, 0]) y_mid = np.mean(hull.points[hull.vertices, 1]) except: x_mid = 0.5 y_mid = 0.5 c = 1 x, y = [], [] for i, j in zip(old_x, old_y): x.append(i) y.append(j) try: xm_i, ym_i = midpoint((i, j), midpoint((i, j), (x_mid, y_mid))) xm_j, ym_j = midpoint((old_x[c], old_y[c]), midpoint((old_x[c], old_y[c]), (x_mid, y_mid))) xm, ym = midpoint((xm_i, ym_i), (xm_j, ym_j)) x.append(xm) y.append(ym) c += 1 except IndexError: break orig_len = len(x) x = x[-3:-1] + x + x[1:3] y = y[-3:-1] + y + y[1:3] t = np.arange(len(x)) ti = np.linspace(2, orig_len + 1, 10 * orig_len) kind = 'quadratic' xi = interp1d(t, x, kind=kind)(ti) yi = interp1d(t, y, kind=kind)(ti) return xi, yi def midpoint(p1, p2, sf=1): xm = ((p1[0] + p2[0]) / 2) * sf ym = ((p1[1] + p2[1]) / 2) * sf return (xm, ym) num_vars = 6 centre = 0.5 theta = np.linspace(0, 2 * np.pi, num_vars, endpoint=False) theta += np.pi / 2 verts = unit_poly_verts(theta, centre) xv = [v[0] for v in verts] yv = [v[1] for v in verts] f1 = df[(df.Protein == str(gpcr1.value)) & (df.Lipids == str(lipid1.value)) & (df.ResID == int(str(residue1.value).split("-")[1])) & (df.Radius == float( radius1.value))].loc[:, list(df.columns)[:6]].to_numpy().reshape( 6, ) f2 = df[(df.Protein == str(gpcr2.value)) & (df.Lipids == str(lipid2.value)) & (df.ResID == int(str(residue2.value).split("-")[1])) & (df.Radius == float( radius2.value))].loc[:, list(df.columns)[:6]].to_numpy().reshape( 6, ) flist = [f1, f2] p = figure(plot_height=600, plot_width=600, x_range=(-0.3, 1.3), y_range=(-0.3, 1.3), tools="") cmap = RdBu[6] colors = cmap[:1] + cmap[-1:] patch1 = ColumnDataSource(data=dict(xi=[], yi=[])) circle1 = ColumnDataSource(data=dict(xt=[], yt=[])) xt, yt = radar_patch(f1, theta, centre) xi, yi = star_curv(xt + xt[:1], yt + yt[:1]) patch = p.patch(x="xi", y="yi", fill_alpha=0.15, fill_color=colors[0], line_color=colors[0], source=patch1) circle = p.circle(x='xt', y='yt', size=10, alpha=0.5, line_color=colors[0], fill_color=colors[0], source=circle1) patch2 = ColumnDataSource(data=dict(xi=[], yi=[])) circle2 = ColumnDataSource(data=dict(xt=[], yt=[])) xt, yt = radar_patch(f2, theta, centre) xi, yi = star_curv(xt + xt[:1], yt + yt[:1]) patch = p.patch(x="xi", y="yi", fill_alpha=0.15, fill_color=colors[1], line_color=colors[1], source=patch2) circle = p.circle(x='xt', y='yt', size=10, alpha=0.5, line_color=colors[1], fill_color=colors[1], source=circle2) # Draw grid so the plot looks like a polar graph. text_label = list(df.columns)[:6] + [''] p.circle(x=0.5, y=0.5, size=20, fill_alpha=0, line_color='black', line_dash='dashed', line_alpha=0.2) for size in [x * 100 for x in range(1, 10)]: p.circle(x=0.5, y=0.5, size=size, fill_alpha=0, line_color='black', line_dash='dashed', line_alpha=0.2) line = np.linspace(-2, 2, 100) p.line(line, (line * 0.58) + 0.21, line_color='black', line_dash='dashed', line_alpha=0.2) p.line(line, (line * (-0.58)) + 0.79, line_color='black', line_dash='dashed', line_alpha=0.2) p.line([0.5] * 100, line, line_color='black', line_dash='dashed', line_alpha=0.2) # Hide axes. p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None p.xaxis.major_tick_line_color = None p.xaxis.minor_tick_line_color = None p.yaxis.major_tick_line_color = None p.yaxis.minor_tick_line_color = None p.xaxis.major_label_text_font_size = '0pt' p.yaxis.major_label_text_font_size = '0pt' p.axis.visible = None p.toolbar.logo = None p.toolbar_location = None # Draw the hexagon with labels attached. p.line(x=xv + [centre], y=yv + [1], color='black') xv[1] = xv[1] - 0.13 xv[2] = xv[2] - 0.1 xv[-2] = xv[-2] + 0.16 xv[-1] = xv[-1] + 0.1 yv[3] = yv[3] - 0.06 label_source = ColumnDataSource({ 'x': xv + [centre], 'y': yv + [1], 'text': text_label }) labels = LabelSet(x="x", y="y", text="text", source=label_source, level='glyph', text_align="center") p.add_layout(labels) def select_dfGPCR(): gpcr1_val, gpcr2_val = gpcr1.value, gpcr2.value lipid1_val, lipid2_val = lipid1.value, lipid2.value res1_val, res2_val = str(residue1.value).split("-")[1], str( residue2.value).split("-")[1] f1 = df[(df.Protein == str(gpcr1_val)) & (df.Lipids == str(lipid1_val)) & (df.ResID == int(res1_val)) & (df.Radius == float(radius1.value) )].loc[:, list(df.columns)[:6]].to_numpy().reshape(6, ) f2 = df[(df.Protein == str(gpcr2_val)) & (df.Lipids == str(lipid2_val)) & (df.ResID == int(res2_val)) & (df.Radius == float(radius2.value) )].loc[:, list(df.columns)[:6]].to_numpy().reshape(6, ) return (f1, f2) def update1(): gpcr_val = gpcr1.value lipid1_val = lipid1.value radius1_val = radius1.value resname = df[(df.Protein == str(gpcr_val)) & (df.Lipids == str(lipid1_val)) & (df.Radius == float(radius1_val))].ResName.to_list() resid = df[(df.Protein == str(gpcr_val)) & (df.Lipids == str(lipid1_val)) & (df.Radius == float(radius1_val))].ResID.to_list() residues = [] for rn, ri in zip(resname, resid): residues.append("{}-{}".format(rn, ri)) residue1.options = residues if residue1.value not in residues: residue1.value = residues[0] f1 = select_dfGPCR()[0] xt, yt = radar_patch(f1, theta, centre) xi, yi = star_curv(xt + xt[:1], yt + yt[:1]) circle1.data = dict(xt=xt, yt=yt) patch1.data = dict(xi=xi, yi=yi) def update2(): gpcr_val = gpcr1.value lipid2_val = lipid2.value radius2_val = radius2.value resname = df[(df.Protein == str(gpcr_val)) & (df.Lipids == str(lipid2_val)) & (df.Radius == float(radius2_val))].ResName.to_list() resid = df[(df.Protein == str(gpcr_val)) & (df.Lipids == str(lipid2_val)) & (df.Radius == float(radius2_val))].ResID.to_list() residues = [] for rn, ri in zip(resname, resid): residues.append("{}-{}".format(rn, ri)) # options = [str(x) for x in options] residue2.options = residues if residue2.value not in residues: residue2.value = residues[0] f2 = select_dfGPCR()[1] xt, yt = radar_patch(f2, theta, centre) xi, yi = star_curv(xt + xt[:1], yt + yt[:1]) circle2.data = dict(xt=xt, yt=yt) patch2.data = dict(xi=xi, yi=yi) controls1 = [gpcr1, lipid1, residue1, radius1] controls2 = [gpcr2, lipid2, residue2, radius2] for control1 in controls1: control1.on_change('value', lambda attr, old, new: update1()) for control2 in controls2: control2.on_change('value', lambda attr, old, new: update2()) inputs1 = column([gpcr1, lipid1, residue1, radius1]) inputs2 = column([gpcr2, lipid2, residue2, radius2]) l = layout([[inputs1, p, inputs2]]) update1() update2() doc.add_root(l) doc.title = "Radar App"
def distanceApp(doc: Document) -> None: distances = lipid_residue_distances[0] time = lipid_residue_distances[1]['time'] proteins = lipid_residue_distances[1]['protein'] lipids = list(distances.keys()) residues = list(distances[lipids[0]].keys()) protein_id = list(distances[lipids[0]][residues[0]].keys()) residues = [str(x) for x in residues] protein_id = [str(x) for x in protein_id] source = ColumnDataSource(data=dict(x=[], y=[])) protein_name = Select(title="Protein", value=proteins[0], options=proteins, width=100) pc = Select(title="Protein Copy", value=protein_id[0], options=protein_id, width=100) res = Select(title="Residue Selection", value=residues[0], options=residues, width=100) lip = Select(title="Lipid Selection", value=lipids[0], options=lipids, width=100) p = figure(plot_width=1500, plot_height=400, tools='pan, box_zoom, ywheel_zoom, save, reset, help') color = '#%02x%02x%02x' % tuple(np.random.choice(range(256), size=3)) p.line(x='x', y='y', line_color=color, source=source, line_width=4) p.y_range = Range1d(0, 4) p.x_range = Range1d(time[0], time[-1]) p.toolbar.autohide = True p.axis.axis_label_text_font_size = "12pt" p.axis.axis_label_text_font_style = "bold" p.title.align = 'center' p.xaxis.axis_label = "Trajectory Time" p.yaxis.axis_label = "Distance (nm)" def update(): protein_selected = protein_name.value copy_selected = pc.value residue_selected = res.value lipid_selected = lip.value residues = list(distances[lipid_selected].keys()) if int(residue_selected) not in residues: residue_selected = residues[0] res.options = [str(x) for x in residues] y = distances[lipid_selected][int(residue_selected)][int( copy_selected)] source.data = dict(x=time, y=y) controls = [protein_name, pc, res, lip] for control in controls: control.on_change('value', lambda attr, old, new: update()) inputs2 = row([*controls]) layout1 = layout([[inputs2]]) layout2 = layout([p]) update() doc.add_root(layout1) doc.add_root(layout2) doc.title = "Distance Calculations" doc.theme = Theme(json=yaml.load(""" attrs: Figure: toolbar_location: above height: 500 width: 1000 Grid: grid_line_dash: [6, 4] grid_line_color: black """, Loader=yaml.FullLoader))
def define_plot( doc: Document, rt_client: _StreamingClient, channels: list, tribe: RealTimeTribe, inventory: Inventory, detections: list, map_options: dict, plot_options: dict, plot_length: float, update_interval: int, data_color: str = "grey", lowcut: float = 1.0, highcut: float = 10.0, offline: bool = False, ): """ Set up a bokeh plot for real-time plotting. Defines a moving data stream and a map. Parameters ---------- doc Bokeh document to edit - usually called as a partial rt_client RealTimeClient streaming data channels Channels to plot tribe Tribe to plot inventory Inventory to plot detections Detections to plot - should be a list that is updated in place. map_options Dictionary of options for the map plot_options Dictionary of options for plotting in general plot_length Length of data plot update_interval Update frequency in seconds data_color Colour to data stream lowcut Lowcut for filtering data stream highcut Highcut for filtering data stream offline Flag to set time-stamps to data time-stamps if True, else timestamps will be real-time """ # Set up the data source Logger.info("Getting stream to define plot") stream = rt_client.stream.copy().split().detrend() if lowcut and highcut: stream.filter("bandpass", freqmin=lowcut, freqmax=highcut) title = "Streaming data: {0}-{1} Hz bandpass".format(lowcut, highcut) elif lowcut: stream.filter("highpass", lowcut) title = "Streaming data: {0} Hz highpass".format(lowcut) elif highcut: stream.filter("lowpass", highcut) title = "Streaming data: {0} Hz lowpass".format(highcut) else: title = "Raw streaming data" stream.merge() Logger.info(f"Have the stream: \n{stream}") template_lats, template_lons, template_alphas, template_ids = ( [], [], [], []) for template in tribe: try: origin = (template.event.preferred_origin() or template.event.origins[0]) except IndexError: continue template_lats.append(origin.latitude) template_lons.append(origin.longitude % 360) template_alphas.append(0) template_ids.append(template.event.resource_id.id.split("/")[-1]) station_lats, station_lons, station_ids = ([], [], []) for network in inventory: for station in network: station_lats.append(station.latitude) station_lons.append(station.longitude % 360) station_ids.append(station.code) # Get plot bounds in web mercator Logger.info("Defining map") transformer = Transformer.from_crs( "epsg:4326", "epsg:3857", always_xy=True) try: min_lat, min_lon, max_lat, max_lon = ( min(template_lats + station_lats), min(template_lons + station_lons), max(template_lats + station_lats), max(template_lons + station_lons)) except ValueError as e: Logger.error(e) Logger.info("Setting map bounds to NZ") min_lat, min_lon, max_lat, max_lon = (-47., 165., -34., 179.9) Logger.info(f"Map bounds: {min_lon}, {min_lat} - {max_lon}, {max_lat}") bottom_left = transformer.transform(min_lon, min_lat) top_right = transformer.transform(max_lon, max_lat) map_x_range = (bottom_left[0], top_right[0]) map_y_range = (bottom_left[1], top_right[1]) template_x, template_y = ([], []) for lon, lat in zip(template_lons, template_lats): _x, _y = transformer.transform(lon, lat) template_x.append(_x) template_y.append(_y) station_x, station_y = ([], []) for lon, lat in zip(station_lons, station_lats): _x, _y = transformer.transform(lon, lat) station_x.append(_x) station_y.append(_y) template_source = ColumnDataSource({ 'y': template_y, 'x': template_x, 'lats': template_lats, 'lons': template_lons, 'template_alphas': template_alphas, 'id': template_ids}) station_source = ColumnDataSource({ 'y': station_y, 'x': station_x, 'lats': station_lats, 'lons': station_lons, 'id': station_ids}) Logger.info("Allocated data sources") trace_sources = {} trace_data_range = {} # Allocate empty arrays for channel in channels: tr = stream.select(id=channel)[0] times = np.arange( tr.stats.starttime.datetime, (tr.stats.endtime + tr.stats.delta).datetime, step=dt.timedelta(seconds=tr.stats.delta)) data = tr.data trace_sources.update( {channel: ColumnDataSource({'time': times, 'data': data})}) trace_data_range.update({channel: (data.min(), data.max())}) # Set up the map to go on the left side Logger.info("Adding features to map") map_plot = figure( title="Template map", x_range=map_x_range, y_range=map_y_range, x_axis_type="mercator", y_axis_type="mercator", **map_options) url = 'http://a.basemaps.cartocdn.com/rastertiles/voyager/{Z}/{X}/{Y}.png' attribution = "Tiles by Carto, under CC BY 3.0. Data by OSM, under ODbL" map_plot.add_tile(WMTSTileSource(url=url, attribution=attribution)) map_plot.circle( x="x", y="y", source=template_source, fill_color="firebrick", line_color="grey", line_alpha=.2, fill_alpha="template_alphas", size=10) map_plot.triangle( x="x", y="y", size=10, source=station_source, color="blue", alpha=1.0) # Set up the trace plots Logger.info("Setting up streaming plot") trace_plots = [] if not offline: now = dt.datetime.utcnow() else: now = max([tr.stats.endtime for tr in stream]).datetime p1 = figure( y_axis_location="right", title=title, x_range=[now - dt.timedelta(seconds=plot_length), now], plot_height=int(plot_options["plot_height"] * 1.2), **{key: value for key, value in plot_options.items() if key != "plot_height"}) p1.yaxis.axis_label = None p1.xaxis.axis_label = None p1.min_border_bottom = 0 p1.min_border_top = 0 if len(channels) != 1: p1.xaxis.major_label_text_font_size = '0pt' p1_line = p1.line( x="time", y='data', source=trace_sources[channels[0]], color=data_color, line_width=1) legend = Legend(items=[(channels[0], [p1_line])]) p1.add_layout(legend, 'right') datetick_formatter = DatetimeTickFormatter( days=["%m/%d"], months=["%m/%d"], hours=["%m/%d %H:%M:%S"], minutes=["%m/%d %H:%M:%S"], seconds=["%m/%d %H:%M:%S"], hourmin=["%m/%d %H:%M:%S"], minsec=["%m/%d %H:%M:%S"]) p1.xaxis.formatter = datetick_formatter # Add detection lines Logger.info("Adding detection artists") detection_source = _get_pick_times(detections, channels[0]) detection_source.update( {"pick_values": [[ int(min(stream.select(id=channels[0])[0].data) * .9), int(max(stream.select(id=channels[0])[0].data) * .9)] for _ in detection_source['picks']]}) detection_sources = {channels[0]: ColumnDataSource(detection_source)} detection_lines = MultiLine( xs="picks", ys="pick_values", line_color="red", line_dash="dashed", line_width=1) p1.add_glyph(detection_sources[channels[0]], detection_lines) trace_plots.append(p1) if len(channels) > 1: for i, channel in enumerate(channels[1:]): p = figure( x_range=p1.x_range, y_axis_location="right", **plot_options) p.yaxis.axis_label = None p.xaxis.axis_label = None p.min_border_bottom = 0 # p.min_border_top = 0 p_line = p.line( x="time", y="data", source=trace_sources[channel], color=data_color, line_width=1) legend = Legend(items=[(channel, [p_line])]) p.add_layout(legend, 'right') p.xaxis.formatter = datetick_formatter # Add detection lines detection_source = _get_pick_times(detections, channel) detection_source.update( {"pick_values": [[ int(min(stream.select(id=channel)[0].data) * .9), int(max(stream.select(id=channel)[0].data) * .9)] for _ in detection_source['picks']]}) detection_sources.update({ channel: ColumnDataSource(detection_source)}) detection_lines = MultiLine( xs="picks", ys="pick_values", line_color="red", line_dash="dashed", line_width=1) p.add_glyph(detection_sources[channel], detection_lines) trace_plots.append(p) if i != len(channels) - 2: p.xaxis.major_label_text_font_size = '0pt' plots = gridplot([[map_plot, column(trace_plots)]]) previous_timestamps = { channel: stream.select(id=channel)[0].stats.endtime for channel in channels} def update(): Logger.debug("Plot updating") _stream = rt_client.stream.split().detrend() if lowcut and highcut: _stream.filter("bandpass", freqmin=lowcut, freqmax=highcut) elif lowcut: _stream.filter("highpass", lowcut) elif highcut: _stream.filter("lowpass", highcut) _stream.merge() for _i, _channel in enumerate(channels): try: _tr = _stream.select(id=_channel)[0] except IndexError: Logger.debug("No channel for {0}".format(_channel)) continue new_samples = int(_tr.stats.sampling_rate * ( previous_timestamps[_channel] - _tr.stats.endtime)) if new_samples == 0: Logger.debug("No new data for {0}".format(_channel)) continue _new_data = _tr.slice( starttime=previous_timestamps[_channel]) new_times = np.arange( _new_data.stats.starttime.datetime, (_tr.stats.endtime + _tr.stats.delta).datetime, step=dt.timedelta(seconds=_tr.stats.delta)) new_data = {'time': new_times[1:], 'data': _new_data.data[1:]} Logger.debug("Channl: {0}\tNew times: {1}\t New data: {2}".format( _tr.id, new_data["time"].shape, new_data["data"].shape)) trace_sources[_channel].stream( new_data=new_data, rollover=int(plot_length * _tr.stats.sampling_rate)) new_picks = _get_pick_times(detections, _channel) new_picks.update({ 'pick_values': [ [int(np.nan_to_num( trace_sources[_channel].data['data']).max() * .9), int(np.nan_to_num( trace_sources[_channel].data['data']).min() * .9)] for _ in new_picks['picks']]}) detection_sources[_channel].data = new_picks previous_timestamps.update({_channel: _tr.stats.endtime}) Logger.debug("New data plotted for {0}".format(_channel)) if not offline: now = dt.datetime.utcnow() else: try: now = max([tr.stats.endtime for tr in _stream]).datetime except ValueError: return trace_plots[0].x_range.start = now - dt.timedelta(seconds=plot_length) trace_plots[0].x_range.end = now _update_template_alphas( detections, tribe, decay=plot_length, now=now, datastream=template_source) Logger.info("Adding callback") doc.add_periodic_callback(update, update_interval) doc.title = "EQcorrscan Real-time plotter" doc.add_root(plots) Logger.info("Plot defined")
def line_handler(doc: Document) -> None: task_id = doc.session_context.request.arguments.get('task_id') username = doc.session_context.request.arguments.get('username') user_dir = os.path.join(settings.USER_DATA, username) path_to_db = os.path.join(user_dir, task_id) conn = os.path.join(path_to_db, 'distances.p') with open(conn, 'rb') as fp: lipid_residue_distances = pickle.load(fp) # variables distances = lipid_residue_distances[0] time = lipid_residue_distances[1]['time'] proteins = lipid_residue_distances[1]['protein'] lipids = list(distances.keys()) residues = list(distances[lipids[0]].keys()) protein_id = list(distances[lipids[0]][residues[0]].keys()) residues = [str(x) for x in residues] protein_id = [str(x) for x in protein_id] # columndatasource source = ColumnDataSource(data=dict(x=[], y=[])) #widgets protein_name = Select(title="Protein", value=proteins[0], options=proteins, width=100) pc = Select(title="Protein Copy", value=protein_id[0], options=protein_id, width=100) res = Select(title="Residue Selection", value=residues[0], options=residues, width=100) lip = Select(title="Lipid Selection", value=lipids[0], options=lipids, width=100) p = figure(plot_width=1500, plot_height=400, tools='pan, box_zoom, ywheel_zoom, save, reset, help') # line with random color color = '#%02x%02x%02x' % tuple(np.random.choice(range(256), size=3)) p.line(x='x', y='y', line_color=color, source=source, line_width=2) # make pretty p.y_range = Range1d(0, 4) p.x_range = Range1d(time[0], time[-1]) p.toolbar.autohide = True p.axis.axis_label_text_font_size = "12pt" p.axis.axis_label_text_font_style = "bold" p.title.align = 'center' p.xaxis.axis_label = "Trajectory Time" p.yaxis.axis_label = "Distance (nm)" def update(): protein_selected = protein_name.value copy_selected = pc.value residue_selected = res.value lipid_selected = lip.value residues = list(distances[lipid_selected].keys()) if int(residue_selected) not in residues: residue_selected = residues[0] res.options = [str(x) for x in residues] y = distances[lipid_selected][int(residue_selected)][int( copy_selected)] source.data = dict(x=time, y=y) # add controls controls = [protein_name, pc, res, lip] for control in controls: control.on_change('value', lambda attr, old, new: update()) # align plot elements inputs2 = row([*controls]) layout1 = layout([[inputs2]]) layout2 = layout([p]) # render update() doc.add_root(layout1) doc.add_root(layout2) doc.title = "Distance Calculations" doc.theme = Theme(json=yaml.load(""" attrs: Figure: toolbar_location: above height: 500 width: 1000 Grid: grid_line_dash: [6, 4] grid_line_color: black """, Loader=yaml.FullLoader))