def _create_loss_figure(self, df: pd.DataFrame, width: int = 1000, height: int = 300): colors = itertools.cycle(palette) df.columns = [str(i) for i in df.columns] ds = ColumnDataSource(df) fig = Figure(y_axis_type="log", width=width, height=height) fig.below[0].formatter.use_scientific = False for column, color in zip(df.columns, colors): glyph = fig.line(x='index', y=column, source=ds, color=color) fig.add_tools( HoverTool(tooltips=[("epoch", "@index")] + [(f"loss_{column}", f"@{column}")], mode='vline', renderers=[glyph])) def update_epoch(self: App, event): epoch = reduce(lambda a, b: a if a[0] < b[0] else b, [(abs(e - event.x), e) for e in self.state.epochs])[1] self.widget_epoch_select.value = str(epoch) fig.on_event(DoubleTap, partial(update_epoch, self)) return fig
def init_time_series_plot(hover): """ Defaults for time series plot """ plot = Figure( plot_height=300, plot_width=900, responsive=True, tools="xpan,xwheel_zoom,xbox_zoom,reset,tap", x_axis_type='datetime', min_border_top=0, min_border_right=10, min_border_bottom=50, min_border_left=50, outline_line_color=None, ) plot.add_tools(hover) plot.x_range.follow = "end" plot.x_range.range_padding = 0 plot.xaxis.axis_label = "Time" plot.xaxis.major_label_orientation = pi/4 plot.xaxis.formatter = DatetimeTickFormatter(formats=dict( hours=["%d %B"], days=["%d %B"], months=["%d %B"], years=["%d %B"], )) return plot
def __plot_control_chart(self, index): plot_args = self.__conf.plot_args[index] annotations = self.__conf.annotations[index] if not annotations: annotations = PlotAnnotationContainer() plot = Figure(plot_height=500, plot_width=600, x_range=FactorRange(factors=self.__factors, name='x_factors')) plot.toolbar.logo = None plot.title.text = 'Control chart' hover_tool = self.__create_tooltips() plot.add_tools(hover_tool) plot.xaxis.major_label_orientation = pi / 4 plot.xaxis.major_label_standoff = 10 if not self.__values['_calc_value'].empty: if 'color' not in plot_args: plot_args['color'] = 'navy' if 'alpha' not in plot_args: plot_args['alpha'] = 0.5 self.__values['s_fac'] = self.__factors col_ds = ColumnDataSource(self.__values, name='control_data') col_ds.js_on_change('data', CustomJS(code="refresh_maps();")) plot.circle('s_fac', '_calc_value', source=col_ds, name='circle', **plot_args) plot.line('s_fac', '_calc_value', source=col_ds, name='line', **plot_args) min_anno, max_anno = annotations.calc_min_max_annotation( self.__values['_calc_value']) annotations.plot(plot, self.__values['_calc_value']) anno_range = max_anno - min_anno if anno_range and not isnan(anno_range): plot.y_range.start = min_anno - anno_range plot.y_range.end = max_anno + anno_range return plot
def createPlot(df, boundaryDF): p = Figure(plot_height=900, plot_width=PLOT_WIDTH, title="", y_range=[], title_text_font_size=TITLE_FONT_SIZE) p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None quad = p.quad( top="top", bottom="bottom", left="left", right="right", source=blockSource, fill_color="grey", hover_fill_color="firebrick", fill_alpha=0.05, hover_alpha=0.3, line_color=None, hover_line_color="white", ) p.multi_line(xs="xs", ys="ys", source=blockSource, color="black", line_width=2, line_alpha=0.4, line_dash="dotted") p.multi_line(xs="xs", ys="ys", source=source, color="color", line_width="width", line_alpha="line_alpha") p.add_tools( HoverTool( tooltips=[("chromosome", "@chromosome"), ("exon", "@exon"), ("start", "@start"), ("end", "@end")], renderers=[quad], ) ) return p
def plot_bar_stack( p: Figure, source: ColumnDataSource, df: pd.DataFrame ) -> List[GlyphRenderer]: # Plot bar stack. measurements = list(df["Measurement"].unique()) n_measurements = len(measurements) color = list((Category20_20 * 2)[:n_measurements]) if "None" in measurements: color[measurements.index("None")] = "black" bar_stack = p.vbar_stack( **BAR_STACK_KWARGS, stackers=measurements, color=color, source=source, ) stack_hover = HoverTool( renderers=bar_stack, tooltips=STACK_HOVER_TOOLTIPS, ) p.add_tools(stack_hover) # Customize left y-axis range. p.y_range.start = 0 max_count = bar_stack[0].data_source.data["total"].max() + 1 p.y_range.end = max_count # Create a legend. kwargs = LEGEND_KWARGS.copy() if len(measurements) == 1: kwargs["location"] = (0, 250) legend = Legend( items=[ (measurement, [bar_stack[i]]) for i, measurement in enumerate(measurements) ], **kwargs, ) p.add_layout(legend, "right") return bar_stack
def init_time_series_plot(hover): """ Defaults for time series plot """ plot = Figure( plot_height=400, plot_width=1000, sizing_mode="scale_width", toolbar_location="above", tools="pan, wheel_zoom, xbox_zoom, reset, tap", active_scroll='wheel_zoom', x_axis_type="datetime", min_border_top=0, min_border_right=10, min_border_bottom=50, min_border_left=50, outline_line_color=None, ) plot.add_tools(hover) plot.x_range.follow = "end" plot.x_range.range_padding = 0 plot.xaxis.axis_label = "Time" plot.xaxis.axis_label_text_font_style = "normal" plot.xaxis.axis_label_text_font_size = "14pt" plot.yaxis.axis_label_text_font_style = "normal" plot.yaxis.axis_label_text_font_size = "14pt" return plot
def plot_df(df: pd.DataFrame, legend: Optional[List[str]] = None, width: int = 1200, height: int = 700, title: str = 'loss', x_label: str = 'epoch') -> Figure: colors = itertools.cycle(palette) df = df.copy() df.columns = [str(i) for i in df.columns] if legend is None: legend = df.columns df.columns = [BokehPlot._sanitize_column_name(i) for i in df.columns] ds = ColumnDataSource(df) fig = Figure(y_axis_type="log", width=width, height=height, title=title, x_axis_label=x_label) fig.below[0].formatter.use_scientific = False for column, color, legend in zip(df.columns, colors, legend): glyph = fig.line(x='index', y=column, source=ds, color=color, legend_label=legend) # fig.add_tools(HoverTool(tooltips=[(f"{column} - {legend}", f"@{column}")], mode='vline', renderers=[glyph])) fig.add_tools(HoverTool(tooltips=[(f"{legend}", f"@{column}")], mode='vline', renderers=[glyph])) fig.legend.location = 'bottom_left' fig.legend.click_policy = "hide" fig.legend.label_text_font_size = '12px' fig.legend.spacing = -4 fig.legend.background_fill_alpha = 0.6 return fig
def plot_prices(df, template_name='stock', notebook=False, x='Date', y='Adj. Close', title="Stock prices", xlabel="Date", ylabel="Price"): """ Bokeh Plot for stock prices with a custom title and meaningful axis labels. template_name: output file name of plot notebook: boolean for showing plot on jupyter notebook """ source = ColumnDataSource(df) # create a new plot with a title and axis labels p = Figure( title=title, x_axis_label=xlabel, y_axis_label=ylabel, x_axis_type='datetime', plot_height=500, plot_width=950, tools=['pan', 'wheel_zoom'], toolbar_location='below', ) # configure so that Bokeh chooses what (if any) scroll tool is active p.toolbar.active_scroll = "auto" # add a line renderer with legend and line thickness p.line(x=x, y=y, line_width=2, legend='Adj Close', source=source) p.legend.location = "top_left" p.legend.click_policy = "hide" hover = HoverTool( tooltips=[ ('Date', '@Date{%F}'), ('Close', '$@{Adj. Close}{%0.2f}'), # use @{ } for field names with spaces ('Volume', '@Volume{0.00 a}'), ], formatters={ 'Date': 'datetime', # use 'datetime' formatter for 'date' field 'Adj. Close': 'printf', # use 'printf' formatter for 'adj close' field # use default 'numeral' formatter for other fields }, # display a tooltip whenever the cursor is vertically in line with a glyph mode='vline') p.add_tools(hover) if notebook: # show the results show(p, notebook_handle=True) push_notebook() else: # output the results output_file('%s.html' % template_name) save(p)
def buildVendorsTab(): defaultGfxVendors = [ gfxVendors.index('NVIDIA Corporation'), gfxVendors.index('Advanced Micro Devices, Inc. [AMD/ATI]'), gfxVendors.index('Intel Corporation') ] gfxVendorCheckbox = CheckboxGroup(labels=gfxVendors, active=defaultGfxVendors) source_release = ColumnDataSource(data=dict(x=[], y=[], height=[])) source_beta = ColumnDataSource(data=dict(x=[], y=[], height=[])) fig = Figure(title="GFX Vendors", x_range=[], y_range=[0, 0], plot_width=1000, plot_height=650) hover = HoverTool(tooltips=[ ('Users', '@height %') ]) fig.add_tools(hover) fig.rect(x='x', y='y', height='height', source=source_release, width=0.4, color='orange', legend='Release') fig.rect(x='x', y='y', height='height', source=source_beta, width=0.4, color='blue', legend='Beta') fig.xaxis.major_label_orientation = np.pi / 3 def update(selected): vendors = [gfxVendors[i] for i in range(len(gfxVendors)) if i in selected] releaseUsers = 100 * getUsersForVendors('release', vendors) / gfxTotalReleaseUsers betaUsers = 100 * getUsersForVendors('beta', vendors) / gfxTotalBetaUsers fig.x_range.factors = vendors fig.y_range.end = max([releaseUsers.max(), betaUsers.max()]) source_release.data = dict( x=[c + ':0.3' for c in vendors], y=releaseUsers / 2, height=releaseUsers, ) source_beta.data = dict( x=[c + ':0.7' for c in vendors], y=betaUsers / 2, height=betaUsers, ) gfxVendorCheckbox.on_click(update) update(gfxVendorCheckbox.active) vendorComparison = HBox(HBox(VBoxForm(*[gfxVendorCheckbox]), width=300), fig, width=1100) return Panel(child=vendorComparison, title="GFX Vendor Comparison")
def init_xy_plot(hover): """ Defaults for xy plots """ plot = Figure(tools="pan,wheel_zoom,box_zoom,reset,tap") plot.add_tools(hover) return plot
def dt_line_viz( df: pd.DataFrame, x: str, timeunit: str, yscale: str, plot_width: int, plot_height: int, show_yticks: bool, miss_pct: Optional[float] = None, y: Optional[str] = None, ) -> Figure: """ Render a line chart """ # pylint: disable=too-many-arguments if miss_pct is not None: title = f"{x} ({miss_pct}% missing)" if miss_pct > 0 else f"{x}" tooltips = [(timeunit, "@lbl"), ("Frequency", "@freq"), ("Percent", "@pct%")] agg = "freq" else: title = title = f"{df.columns[1]} of {y} by {x}" agg = f"{df.columns[1]}" tooltips = [(timeunit, "@lbl"), (agg, f"@{df.columns[1]}")] fig = Figure( plot_width=plot_width, plot_height=plot_height, toolbar_location=None, title=title, tools=[], y_axis_type=yscale, x_axis_type="datetime", ) fig.line( source=df, x=x, y=agg, line_width=2, line_alpha=0.8, color="#7e9ac8", ) hover = HoverTool( tooltips=tooltips, mode="vline", ) fig.add_tools(hover) tweak_figure(fig, "line", show_yticks) if show_yticks and yscale == "linear": _format_axis(fig, 0, df[agg].max(), "y") if y: fig.yaxis.axis_label = f"{df.columns[1]} of {y}" fig.xaxis.axis_label = x return Panel(child=fig, title="line chart") fig.yaxis.axis_label = "Frequency" return fig
def performance(): plot = Figure(x_axis_type="datetime", tools="save", toolbar_location=None, plot_width=1000, plot_height=300) l1 = plot.line(x="time", y="power_out", source=source_perfomance, line_color="green", name="local") plot.add_tools(HoverTool(renderers=[l1])) plot.select(dict(type=HoverTool)).tooltips = [("Date", "@hover_time"), ("Performance", "@power_out")] l2 = plot.line(x="time", y="avg_perf", source=source_perfomance, line_color="red", name="global") plot.x_range = DataRange1d(range_padding=0.0, bounds=None) plot.title = "Plant Performance" return plot
def render_scatter( itmdt: Intermediate, plot_width: int, plot_height: int, palette: Sequence[str] ) -> Figure: """ Render scatter plot with a regression line and possible most influencial points """ # pylint: disable=too-many-locals df = itmdt["data"] xcol, ycol, *maybe_label = df.columns tooltips = [(xcol, f"@{{{xcol}}}"), (ycol, f"@{{{ycol}}}")] fig = Figure( plot_width=plot_width, plot_height=plot_height, toolbar_location=None, title=Title(text="Scatter Plot & Regression Line", align="center"), tools=[], x_axis_label=xcol, y_axis_label=ycol, ) # Scatter scatter = fig.scatter(x=df.columns[0], y=df.columns[1], source=df) if maybe_label: assert len(maybe_label) == 1 mapper = CategoricalColorMapper(factors=["=", "+", "-"], palette=palette) scatter.glyph.fill_color = {"field": maybe_label[0], "transform": mapper} scatter.glyph.line_color = {"field": maybe_label[0], "transform": mapper} # Regression line coeff_a, coeff_b = itmdt["coeffs"] line_x = np.asarray([df.iloc[:, 0].min(), df.iloc[:, 0].max()]) line_y = coeff_a * line_x + coeff_b fig.line(x=line_x, y=line_y, line_width=3) # Not adding the tooltips before because we only want to apply tooltip to the scatter hover = HoverTool(tooltips=tooltips, renderers=[scatter]) fig.add_tools(hover) # Add legends if maybe_label: nidx = df.index[df[maybe_label[0]] == "-"][0] pidx = df.index[df[maybe_label[0]] == "+"][0] legend = Legend( items=[ LegendItem(label="Most Influential (-)", renderers=[scatter], index=nidx), LegendItem(label="Most Influential (+)", renderers=[scatter], index=pidx), ], margin=0, padding=0, ) fig.add_layout(legend, place="right") return fig
def dt_line_viz( df: List[pd.DataFrame], x: str, timeunit: str, yscale: str, plot_width: int, plot_height: int, show_yticks: bool, orig: List[str], df_labels: List[str], ) -> Figure: """ Render a line chart """ # pylint: disable=too-many-arguments tooltips = [(timeunit, "@lbl"), ("Frequency", "@freq"), ("Source", "@orig")] for i, _ in enumerate(df): df[i]["orig"] = orig[i] fig = Figure( plot_width=plot_width, plot_height=plot_height, toolbar_location=None, title=x, tools=[], y_axis_type=yscale, x_axis_type="datetime", ) for i, _ in enumerate(df): fig.line( source=df[i], x=x, y="freq", line_width=2, line_alpha=0.8, color=CATEGORY10[i], ) hover = HoverTool( tooltips=tooltips, mode="vline", ) fig.add_tools(hover) tweak_figure(fig, "line", show_yticks) if show_yticks and yscale == "linear": _format_axis(fig, 0, max([d["freq"].max() for d in df]), "y") if orig != df_labels: fig.xaxis.axis_label = f"This variable is only in {','.join(orig)}" fig.xaxis.axis_label_standoff = 0 fig.yaxis.axis_label = "Frequency" return fig
def hist_kde_viz( df: pd.DataFrame, pts_rng: np.ndarray, pdf: np.ndarray, col: str, yscale: str, plot_width: int, plot_height: int, ) -> Panel: """ Render histogram with overlayed kde """ # pylint: disable=too-many-arguments fig = Figure( plot_width=plot_width, plot_height=plot_height, title=f"{col}", tools=[], toolbar_location=None, y_axis_type=yscale, ) bottom = 0 if yscale == "linear" or df.empty else df["freq"].min() / 2 hist = fig.quad( source=df, left="left", right="right", bottom=bottom, alpha=0.5, top="freq", fill_color="#6baed6", ) hover_hist = HoverTool( renderers=[hist], tooltips=[("Bin", "@intervals"), ("Density", "@freq")], mode="vline", ) line = fig.line( # pylint: disable=too-many-function-args pts_rng, pdf, line_color="#9467bd", line_width=2, alpha=0.5) hover_dist = HoverTool(renderers=[line], tooltips=[("x", "@x"), ("y", "@y")]) fig.add_tools(hover_hist) fig.add_tools(hover_dist) tweak_figure(fig, "kde") fig.yaxis.axis_label = "Density" fig.xaxis.axis_label = col _format_axis(fig, df.iloc[0]["left"], df.iloc[-1]["right"], "x") if yscale == "linear": _format_axis(fig, 0, df["freq"].max(), "y") return Panel(child=fig, title="KDE plot")
def createPlots(): ######################################## BS Pressure Plot ######################################## sourceBuySell, sourceVolume = requestHoseData() pBuySell = Figure(plot_width=PLOT_WIDTH, plot_height=BUYSELL_PLOT_HEIGHT, name="pltBuySell") pBuySell.xaxis.ticker = [8.75, 9, 9.5, 10, 10.5, 11, 11.5, 13, 13.5, 14, 14.5, 14.75] pBuySell.xaxis.major_label_overrides = { 8.5: "8:30", 8.75: "8:45", 9: "9:00", 9.5: "9:30", 10: "10:00", 10.5: "10:30", 11: "11:00", 11.5: "11:30", 13: "13:00", 13.5: "13:30", 14: "14:00", 14.5: "14:30", 14.75: "14:45"} pBuySell.line(x='index', y='buyPressure', source=sourceBuySell, color='green', legend_label="Tổng đặt mua", name="glyphSellPressure") pBuySell.line(x='index', y='sellPressure', source=sourceBuySell, color='red', legend_label="Tổng đặt bán", name="glyphBuyPressure") wz = WheelZoomTool(dimensions="width"); pBuySell.add_tools(wz); pBuySell.toolbar.active_scroll = wz pBuySell.toolbar.logo = None pBuySell.axis[0].visible = False pBuySell.legend.location = "top_left" pBuySell.legend.click_policy = "hide" pBuySell.legend.background_fill_alpha = 0.0 ######################################## Volume Plot ######################################## pVolume = Figure(width=PLOT_WIDTH, height=VOLUME_PLOT_HEIGHT, tools="pan, reset", name="pltVolume") pVolume.toolbar.logo = None wz = WheelZoomTool(dimensions="height"); pVolume.add_tools(wz); pVolume.toolbar.active_scroll = wz pVolume.vbar(x='index', top='totalValue', width=1 /60, color='blue', source=sourceVolume, fill_alpha=LIQUIDITY_ALPHA, line_alpha=LIQUIDITY_ALPHA, name="glyphTotalValue", legend_label="Thanh khoản toàn tt") pVolume.vbar(x='index', top='nnBuy', width=1/1.2/60, color='green', source=sourceVolume ,name="glyphNNBuy", legend_label="NN mua",) pVolume.vbar(x='index', top='nnSell', width=1/1.2/60, color='red', source=sourceVolume ,name="glyphNNSell", legend_label="NN bán",) pVolume.x_range = pBuySell.x_range pVolume.y_range=Range1d(-10, 45) pVolume.legend.location = "top_left" pVolume.legend.click_policy = "hide" pVolume.legend.background_fill_alpha = 0.0 ######################################### OHLC plot ######################################### orders, source, pressure = requestPSData() plotOhlc = createOhlcPlot(source) pCandle, divCandle = hookupFigure(plotOhlc) # "divCustomJS" "pltOHLC" "glyphOHLCSegment" pDebug = Paragraph(text=f"""["num_ps_orders": "{len(orders['index'])}"]\n""" """""", width=DIV_TEXT_WIDTH, height=100, name="pDebug") ################################# Putting all plots together ################################ def activation_function(): pBuySell._document.add_periodic_callback(lambda: updateDoc(pBuySell._document), 500) print("Document activated !") return pCandle, pBuySell, pVolume, divCandle , activation_function, sourceBuySell, sourceVolume, pDebug
def hist_viz( df: pd.DataFrame, miss_pct: float, col: str, yscale: str, plot_width: int, plot_height: int, show_yaxis: bool, ) -> Figure: """ Render a histogram """ # pylint: disable=too-many-arguments title = f"{col} ({miss_pct}% missing)" if miss_pct > 0 else f"{col}" tooltips = [ ("Bin", "@intervals"), ("Frequency", "@freq"), ("Percent", "@pct{0.2f}%"), ] fig = Figure( plot_width=plot_width, plot_height=plot_height, toolbar_location=None, title=title, tools=[], y_axis_type=yscale, ) bottom = 0 if yscale == "linear" or df.empty else df["freq"].min() / 2 fig.quad( source=df, left="left", right="right", bottom=bottom, alpha=0.5, top="freq", fill_color="#6baed6", ) hover = HoverTool( tooltips=tooltips, mode="vline", ) fig.add_tools(hover) tweak_figure(fig, "hist", show_yaxis) fig.yaxis.axis_label = "Frequency" if not df.empty: _format_axis(fig, df.iloc[0]["left"], df.iloc[-1]["right"], "x") if show_yaxis and yscale == "linear": _format_axis(fig, 0, df["freq"].max(), "y") return fig
def buildOSesTab(): osesCheckbox = CheckboxGroup(labels=oses, active=[i for i in range(len(oses))]) source_release = ColumnDataSource(data=dict(x=[], y=[], height=[])) source_beta = ColumnDataSource(data=dict(x=[], y=[], height=[])) fig = Figure(title='OS', x_range=[], y_range=[0, 0], plot_width=1000, plot_height=650) hover = HoverTool(tooltips=[ ('Users', '@height %') ]) fig.add_tools(hover) fig.rect(x='x', y='y', height='height', source=source_release, width=0.4, color='orange', legend='Release') fig.rect(x='x', y='y', height='height', source=source_beta, width=0.4, color='blue', legend='Beta') fig.xaxis.major_label_orientation = np.pi / 3 def update(selected): cur_oses = [oses[i] for i in range(len(oses)) if i in selected] releaseUsers = 100 * getUsersForOses('release', cur_oses) / osTotalReleaseUsers betaUsers = 100 * getUsersForOses('beta', cur_oses) / osTotalBetaUsers fig.x_range.factors = cur_oses fig.y_range.end = max([releaseUsers.max(), betaUsers.max()]) source_release.data = dict( x=[c + ':0.3' for c in cur_oses], y=releaseUsers / 2, height=releaseUsers, ) source_beta.data = dict( x=[c + ':0.7' for c in cur_oses], y=betaUsers / 2, height=betaUsers, ) osesCheckbox.on_click(update) update(osesCheckbox.active) osesComparison = HBox(HBox(VBoxForm(*[osesCheckbox]), width=300), fig, width=1100) return Panel(child=osesComparison, title="OS Comparison")
def render_dendrogram(dend: Dict["str", Any], plot_width: int, plot_height: int) -> Figure: """ Render a missing dendrogram. """ # list of lists of dcoords and icoords from scipy.dendrogram xs, ys, cols = dend["icoord"], dend["dcoord"], dend["ivl"] # if the number of columns is greater than 20, make the plot wider if len(cols) > 20: plot_width = 28 * len(cols) fig = Figure( plot_width=plot_width, plot_height=plot_height, toolbar_location=None, tools="", title=" ", ) # round the coordinates to integers, and plot the dendrogram xs = [[round(coord) for coord in coords] for coords in xs] ys = [[round(coord, 2) for coord in coords] for coords in ys] fig.multi_line(xs=xs, ys=ys, line_color="#8073ac") # extract the horizontal lines for the hover tooltip h_lns_x = [coords[1:3] for coords in xs] h_lns_y = [coords[1:3] for coords in ys] null_mismatch_vals = [coord[0] for coord in h_lns_y] source = ColumnDataSource(dict(x=h_lns_x, y=h_lns_y, n=null_mismatch_vals)) h_lns = fig.multi_line(xs="x", ys="y", source=source, line_color="#8073ac") hover_pts = HoverTool( renderers=[h_lns], tooltips=[("Average distance", "@n{0.1f}")], line_policy="interp", ) fig.add_tools(hover_pts) # shorten column labels if necessary, and override coordinates with column names cols = [f"{col[:16]}..." if len(col) > 18 else col for col in cols] axis_coords = list(range(5, 10 * len(cols) + 1, 10)) axis_overrides = dict(zip(axis_coords, cols)) fig.xaxis.ticker = axis_coords fig.xaxis.major_label_overrides = axis_overrides fig.xaxis.major_label_orientation = np.pi / 3 fig.yaxis.axis_label = "Average Distance Between Clusters" fig.grid.visible = False fig.frame_width = plot_width return fig
def cmatrix_plot_format(plot: Figure, format_cols: List, hover_code: str) -> Figure: plot.toolbar.logo = None plot.yaxis.axis_label_text_font_size = "16px" plot.yaxis.axis_label_text_color = '#003566' plot.xaxis.major_label_text_color = '#003566' plot.y_range.range_padding = 0 plot.hover.point_policy = "follow_mouse" plot.hover.attachment = "above" cust_formatters = {} for f in format_cols: code_ref = dashboard_constants.bucket_cust_format.format(field_name=f) if f == 'max_percentile_conf' else \ dashboard_constants.scale_format_code.format(field_name=f) cust_formatters[f] = CustomJSHover(args=dict(source=plot.renderers[0].data_source), code=code_ref) custom_hover_format = CustomJS(code=hover_code) format_dict = {f'@{c}': cust_formatters[c] for c in format_cols} plot.add_tools(HoverTool(tooltips=None, callback=custom_hover_format, formatters=format_dict)) someargs = dict(yaxis=plot.yaxis[0], xaxis=plot.xaxis[0], legend=plot.legend[0]) fig_resize_callback = CustomJS(args=someargs, code=dashboard_constants.fig_resize_callback_code) plot.js_on_change('inner_width', fig_resize_callback) return plot
def render(df: pd.DataFrame) -> Figure: from bokeh.models import HoverTool from bokeh.palettes import Category10_10 from bokeh.plotting import ColumnDataSource p = Figure(plot_width=1200, plot_height=600, x_axis_type='datetime') names = [x for x in df.columns.tolist() if x not in ('date', 'zeros')] source = ColumnDataSource(df) p.varea_stack(stackers=names, x='date', color=Category10_10[:len(names)], legend_label=names, source=source) p.line(x='date', y='zeros', line_alpha=0, source=source) p.legend.location = 'top_left' p.add_tools( HoverTool(tooltips=[('date', '@date{%Y-%m-%d}')] + [(x, f'@{x}') for x in names], formatters={'@date': 'datetime'}, mode='vline')) return p
def _add_tools(plot: Figure, on_click: str, nodes_glyph: GlyphRenderer, renderer: GlyphRenderer, **kw): """Add hover and tap tools to the plot. Args: plot (Figure): Plot to add these tools to. on_click (str): JS code to be run when the renderer is clicked. nodes_glyph (GlyphRenderer): Glyph for the nodes on this plot. renderer (GlyphRenderer): Renderer that should call on_click code. """ on_hover_code = "source.data['last_index'] = cb_data.index.indices[0]" plot.add_tools( HoverTool(tooltips=[("Index", "$index"), ("Name", "@name")], renderers=[nodes_glyph]), HoverTool(tooltips=None, callback=CustomJS(args=dict(source=kw['source']), code=on_hover_code), renderers=[renderer]), TapTool(callback=CustomJS(args=kw, code=on_click), renderers=[renderer]))
def _add_hover_tool(cls, chart_layers: [Layer], plot: Figure) -> None: """ Add hover tool to a bokeh plot. Method iterates through chart layers to create a hover tool tooltip for each of them based on axis of the layer. :param chart_layers: list(Layer) list of layers to prepare tooltips for. :param plot: (Figure) bokeh figure to create hover tool for. :return: None """ tooltips = [] for layer in chart_layers: axis = layer.axis cls._prepare_tooltip(tooltips=tooltips, axis=axis) if len(tooltips) > 0: hover_tool = HoverTool(tooltips=tooltips, mode="mouse", point_policy="follow_mouse") plot.add_tools(hover_tool)
def render_crossfilter(itmdt: Intermediate, plot_width: int, plot_height: int) -> column: """ Render crossfilter scatter plot with a regression line. """ # pylint: disable=too-many-locals, too-many-function-args df = itmdt["data"] df["__x__"] = df[df.columns[0]] df["__y__"] = df[df.columns[0]] source_scatter = ColumnDataSource(df) source_xy_value = ColumnDataSource({ "x": [df.columns[0]], "y": [df.columns[0]] }) var_list = list(df.columns[:-2]) xcol = source_xy_value.data["x"][0] ycol = source_xy_value.data["y"][0] tooltips = [("X-Axis: ", "@__x__"), ("Y-Axis: ", "@__y__")] fig = Figure( plot_width=plot_width, plot_height=plot_height, toolbar_location=None, title=Title(text="Scatter Plot", align="center"), tools=[], x_axis_label=xcol, y_axis_label=ycol, ) scatter = fig.scatter("__x__", "__y__", source=source_scatter) hover = HoverTool(tooltips=tooltips, renderers=[scatter]) fig.add_tools(hover) x_select = Select(title="X-Axis", value=xcol, options=var_list, width=150) y_select = Select(title="Y-Axis", value=ycol, options=var_list, width=150) x_select.js_on_change( "value", CustomJS( args=dict( scatter=source_scatter, xy_value=source_xy_value, x_axis=fig.xaxis[0], ), code=""" let currentSelect = this.value; let xyValueData = xy_value.data; let scatterData = scatter.data; xyValueData['x'][0] = currentSelect; scatterData['__x__'] = scatterData[currentSelect]; x_axis.axis_label = currentSelect; scatter.change.emit(); xy_value.change.emit(); """, ), ) y_select.js_on_change( "value", CustomJS( args=dict( scatter=source_scatter, xy_value=source_xy_value, y_axis=fig.yaxis[0], ), code=""" let currentSelect = this.value; let xyValueData = xy_value.data; let scatterData = scatter.data; xyValueData['y'][0] = currentSelect; scatterData['__y__'] = scatterData[currentSelect]; y_axis.axis_label = currentSelect; scatter.change.emit(); xy_value.change.emit(); """, ), ) fig = column(row(x_select, y_select, align="center"), fig, sizing_mode="stretch_width") return fig
def buildDevicesTab(): gfxVendorSelect = Select(title='Vendor', options=gfxVendors, value=gfxVendors[0]) gfxDeviceCheckbox = CheckboxGroup() source_release = ColumnDataSource(data=dict(x=[], y=[], height=[])) source_beta = ColumnDataSource(data=dict(x=[], y=[], height=[])) fig = Figure(title="GFX Devices", x_range=[], y_range=[0, 0], plot_width=1000, plot_height=650) hover = HoverTool(tooltips=[ ('Users', '@height %') ]) fig.add_tools(hover) fig.rect(x='x', y='y', height='height', source=source_release, width=0.4, color='orange', legend='Release') fig.rect(x='x', y='y', height='height', source=source_beta, width=0.4, color='blue', legend='Beta') fig.xaxis.major_label_orientation = np.pi / 3 def update_view(): vendor = gfxVendorSelect.value deviceNames = getDeviceNames('release', vendor, True) gfxDeviceCheckbox.labels = deviceNames devices = [deviceNames[i] for i in range(len(deviceNames)) if i in gfxDeviceCheckbox.active] releaseUsers = 100 * getUsersForDevices('release', vendor, devices) / gfxTotalReleaseUsers betaUsers = 100 * getUsersForDevices('beta', vendor, devices) / gfxTotalBetaUsers fig.x_range.factors = devices fig.y_range.end = max([releaseUsers.max(), betaUsers.max()]) source_release.data = dict( x=[c + ':0.3' for c in devices], y=releaseUsers / 2, height=releaseUsers, ) source_beta.data = dict( x=[c + ':0.7' for c in devices], y=betaUsers / 2, height=betaUsers, ) def update(attrname, old, new): gfxDeviceCheckbox.active = [i for i in range(5)] update_view() def click(selected): update_view() gfxVendorSelect.on_change('value', update) gfxDeviceCheckbox.on_click(click) update('value', '', gfxVendorSelect.value) deviceComparison = HBox(HBox(VBoxForm(*[gfxVendorSelect, gfxDeviceCheckbox]), width=300), fig, width=1100) return Panel(child=deviceComparison, title="GFX Device Comparison")
class DynamicPlotHandler(Handler): def __init__(self, network): self._network = weakref.ref(network) self.sources = {} self._last_time_list = None self._update_complete = False self._recurring_update = RecurringTask(self.plan_update_data, delay=5) self._pcb = None # Periodic callback self._ntcb = None # Next Tick callback super().__init__() @property def network(self): return self._network() def organize_data(self): self._log.debug("Organize Data") self.s = {} for point in self.network.trends: self.s[point.history.name] = (point.history, point.history.units) self.lst_of_trends = [his[0] for name, his in self.s.items()] def build_data_sources(self): sources = {} self.organize_data() for each in self.lst_of_trends: df = pd.DataFrame(each) df = df.reset_index() df["name"] = each.name df["units"] = str(each.units) df["time_s"] = df["index"].apply(str) df.states = each.states try: df = ( df.fillna(method="ffill") .fillna(method="bfill") .replace(["inactive", "active"], [0, 1]) ) except TypeError: df = df.fillna(method="ffill").fillna(method="bfill") sources[each.name] = ColumnDataSource( data=dict( x=df["index"], y=df[each.name], time=df["time_s"], name=df["name"], units=df["units"], ) ) return sources def build_plot(self): self._log.debug("Build Plot") self.stop_update_data() self.sources = self.build_data_sources() TOOLS = "pan,box_zoom,wheel_zoom,save,reset" self.p = Figure( x_axis_type="datetime", x_axis_label="Time", y_axis_label="Numeric Value", title="BAC0 Trends", tools=TOOLS, plot_width=800, plot_height=600, toolbar_location="above", ) self.p.background_fill_color = "#f4f3ef" self.p.border_fill_color = "#f4f3ef" self.p.extra_y_ranges = { "bool": Range1d(start=0, end=1.1), "enum": Range1d(start=0, end=10), } self.p.add_layout(LinearAxis(y_range_name="bool", axis_label="Binary"), "left") self.p.add_layout( LinearAxis(y_range_name="enum", axis_label="Enumerated"), "right" ) hover = HoverTool( tooltips=[ ("name", "@name"), ("value", "@y"), ("units", "@units"), ("time", "@time"), ] ) self.p.add_tools(hover) length = len(self.s.keys()) if length <= 10: if length < 3: length = 3 color_mapper = dict(zip(self.s.keys(), d3["Category10"][length])) else: # This would be a very loaded trend... color_mapper = dict(zip(self.s.keys(), Spectral6[:length])) for each in self.lst_of_trends: if each.states == "binary": self.p.circle( "x", "y", source=self.sources[each.name], name=each.name, color=color_mapper[each.name], legend=("%s | %s (OFF-ON)" % (each.name, each.description)), y_range_name="bool", size=10, ) elif each.states == "multistates": self.p.diamond( "x", "y", source=self.sources[each.name], name=each.name, color=color_mapper[each.name], legend=("%s | %s (%s)" % (each.name, each.description, each.units)), y_range_name="enum", size=20, ) else: self.p.line( "x", "y", source=self.sources[each.name], name=each.name, color=color_mapper[each.name], legend=("%s | %s (%s)" % (each.name, each.description, each.units)), line_width=2, ) self.p.legend.location = "bottom_right" self.p.legend.click_policy = "hide" self.plots = [self.p] def update_data(self): self._log.debug("Update Data") doc = curdoc() # self.organize_data() if self._last_time_list: if self._last_time_list != self.s.keys(): self._list_have_changed = True self.stop_update_data() # doc.add_next_tick_callback(self.modify_document) self.modify_document(doc) else: self._list_have_changed = False l = [] for each in self.p.renderers: l.append(each.name) # for each in self.lst_of_trends: # df = pd.DataFrame(each) # df = df.reset_index() # df['name'] = each.name # df['units'] = str(each.units) # df['time_s'] = df['index'].apply(str) # try: # df = df.fillna(method='ffill').fillna( # method='bfill').replace(['inactive', 'active'], [0, 1]) # except TypeError: # df = df.fillna(method='ffill').fillna(method='bfill') index = l.index(each.name) # renderer = self.p.renderers[index] # new_data = {} # new_data['name'] = df['name'] # new_data['x'] = df['index'] # new_data['y'] = df[each.name] # if each.states == 'binary': # new_data['units'] = [each.units[int(x)] for x in df[each.name]] # elif each.states == 'multistates': # new_data['units'] = [ # each.units[int(math.fabs(x-1))] for x in df[each.name]] # else: # new_data['units'] = df['units'] # new_data['time'] = df['time_s'] # renderer.data_source.data = new_data try: new_data = self.build_data_sources() for each in self.lst_of_trends: self.sources[each.name].data = new_data[each.name].data except KeyError: self._log.warning( "Problem updating {} on chart, will try again next time.".format( each.name ) ) else: self._last_time_list = self.s.keys() # self.start_update_data() self._update_complete = True def modify_document(self, doc): curdoc().clear() # doc = curdoc() try: curdoc().remove_periodic_callback(self._pcb) except: pass doc.clear() self.build_plot() layout = gridplot(self.plots, ncols=2) doc.add_root(layout) self._pcb = doc.add_periodic_callback(self.update_data, 10000) return doc def plan_update_data(self): doc = curdoc() if self._update_complete == True: self._update_complete = False self._ntcb = doc.add_next_tick_callback(self.update_data) def stop_update_data(self): doc = curdoc() if self._recurring_update.is_running: self._recurring_update.stop() while self._recurring_update.is_running: pass try: doc.remove_next_tick_callback(self._ntcb) except (ValueError, RuntimeError): pass # Already gone def start_update_data(self): if not self._recurring_update.is_running: try: self._recurring_update.start() while not self._recurring_update.is_running: pass except RuntimeError: pass
tt = [ ("Source ID", "@src"), ("Epoch (" + catalog[entry]['photometry'][0]['timeunit'] + ")", "@x{1.11}"), ("Magnitude", "@y{1.111}"), ("Error", "@err{1.111}"), ("Band", "@desc") ] if len(list(filter(None, photoinstru))): tt += [("Instrument", "@instr")] hover = HoverTool(tooltips = tt) p1 = Figure(title='Photometry for ' + eventname, x_axis_label='Time (' + catalog[entry]['photometry'][0]['timeunit'] + ')', y_axis_label='AB Magnitude', x_range = x_range, tools = tools, y_range = (0.5 + max([x + y for x, y in list(zip(photoAB, photoerrs))]), -0.5 + min([x - y for x, y in list(zip(photoAB, photoerrs))]))) p1.add_tools(hover) err_xs = [] err_ys = [] for x, y, yerr in list(zip(phototime, photoAB, photoerrs)): err_xs.append((x, x)) err_ys.append((y - yerr, y + yerr)) bandset = set(photoband) bandset = [i for (j, i) in sorted(list(zip(list(map(bandaliasf, bandset)), bandset)))] for band in bandset: bandname = bandaliasf(band) indb = [i for i, j in enumerate(photoband) if j == band] indt = [i for i, j in enumerate(phototype) if not j]
tcolor = 'black' falpha = 0.0 else: tcolor = colors[ci] falpha = 1.0 glyphs.append( p1.circle('x', 'y', source=source, color=tcolor, fill_alpha=falpha, legend=ct, size=glsize)) hover = HoverTool(tooltips=tt, renderers=glyphs) p1.add_tools(hover) p1.legend.location = "bottom_center" p1.legend.orientation = "horizontal" p1.legend.label_text_font_size = '7pt' p1.legend.label_width = 20 p1.legend.label_height = 8 p1.legend.glyph_height = 8 p1.legend.spacing = 0 html = file_html(p1, CDN, 'Supernova locations').replace('width: 90%;', 'width: inherit;') with open(outdir + modulename + "-locations.html", "w") as f: f.write(html)
def correlation(): "the scatter plot" args = flask.request.args xattr = args.get("x", "atomic_number") yattr = args.get("y", "covalent_radius_pyykko") categ = args.get("categ", "name_series") data = get_data() properties = get_property_names(data) categories = get_category_names() fig = Figure(title="{} vs {}".format(properties[xattr], properties[yattr]), plot_width=PLOT_WIDTH, plot_height=PLOT_HEIGHT, tools="box_zoom,pan,resize,save,reset", toolbar_location="above", toolbar_sticky=False, ) fig.xaxis.axis_label = properties[xattr] fig.yaxis.axis_label = properties[yattr] ccm = get_color_mapper(categ, data) if categ == "None": legend = None color_dict = "#1F77B4" else: legend = categ color_dict = {"field": categ, "transform": ccm} fig.circle(x=xattr, y=yattr, fill_alpha=0.7, size=10, source=ColumnDataSource(data=data), fill_color=color_dict, line_color=color_dict, legend=legend) if categ != "None": fig.legend.location = (0, 0) fig.legend.plot = None fig.add_layout(fig.legend[0], "right") hover = HoverTool(tooltips=HOVER_TOOLTIPS) fig.add_tools(hover) script, div = components(fig) js_resources = INLINE.render_js() css_resources = INLINE.render_css() html = render_template( "correlations.html", plot_script=script, plot_div=div, properties=properties, categories=categories, xselected=xattr, yselected=yattr, catselected=categ, js_resources=js_resources, css_resources=css_resources, ) return encode_utf8(html)
state_drunk=state_drunk, state_percent=state_percent, state_percent_sp=state_percent_sp)) patches = fig.patches(xs="borders_x", ys="borders_y", source=patch_source, fill_alpha="alpha", fill_color="colors", line_alpha=0, hover_alpha=.3, line_width=5) fig.add_tools( HoverTool(renderers=[patches], tooltips=[("State", "@state_names"), ("Total", "@state_totals"), ("Drunk%", "@state_percent{1.11}" + "%"), ("Speeding%", "@state_percent_sp{1.11}" + "%")])) select = Select(title="Color States By:", value="None", options=["None", "Drunk%", "Speeding%"]) def update_color(attrname, old, new): if select.value == "Drunk%": patch_source.data["colors"] = drunk_colors patch_source.data["alpha"] = [.3] * len(state_names) elif select.value == "Speeding%": patch_source.data["colors"] = speeding_colors patch_source.data["alpha"] = [.3] * len(state_names) else:
x=speeding_accidents['x'], y=speeding_accidents['y'] )) drinking_source = ColumnDataSource(dict( x=drinking_accidents['x'], y=drinking_accidents['y'] )) other_source = ColumnDataSource(dict( x=other_accidents['x'], y=other_accidents['y'] )) fig.circle('x', 'y', source=speeding_source, fill_color="red", size=3) fig.circle('x', 'y', source=drinking_source, fill_color="green", size=3) fig.circle('x', 'y', source=other_source, fill_color="blue", size=3) fig.add_tools(HoverTool(renderers=[states], tooltips=[("State", "@state"), ("Total", "@total"), ("Drunk Percent", "@perc_drunk"), ("Speeding Percent", "@perc_speeding")])) # ------------------------------------------------- from bokeh.io import output_file, show from bokeh.layouts import column from bokeh.models.widgets import Select from bokeh.palettes import Reds9 output_file("final_bokeh.html") select = Select(title="Option:", value="Default", options=["Other", "Speeding", "Drunk", "Default"]) border_source.add("white", name="color")
# temporarily ignoring bad types from import sntypes.append(ctv) sntypes = sorted(sntypes) snoffs = [[] for x in range(len(sntypes))] tt = [ ("Type", "@ct") ] hover = HoverTool(tooltips=tt, line_policy='interp') p = Figure(x_range=[0., 100.], y_range=[0., 1.], title='Supernova Host Offsets', x_axis_label='Offset (kpc)', y_axis_label='CDF', plot_width=980, plot_height=500, title_text_font='futura', title_text_font_size='14pt') p.add_tools(hover) for si, sntype in enumerate(tq(sntypes)): for event in meta: if ('hostoffsetdist' in event and event['hostoffsetdist'] and is_number(event['hostoffsetdist'][0]['value']) and 'claimedtype' in event and event['claimedtype'] and sntype in [x['value'] for x in event['claimedtype']]): snoffs[si].append(float(event['hostoffsetdist'][0]['value'])) snoffs[si] = sorted(snoffs[si]) colors = sns.color_palette("hls", n_colors=sum( [1 if len(snoffs[i]) >= mincnt else 0 for i, x in enumerate(snoffs)])).as_hex() cnt = 0
# coding=utf-8 from bokeh.io import output_file, show from bokeh.models import ColumnDataSource, TapTool, HoverTool, CustomJS from bokeh.plotting import Figure from bokeh.layouts import row output_file("layout.html") source = ColumnDataSource( data=dict(x=[2,3,5], y=[8,5,2]), name='source' ) p1 = Figure(plot_width=550, plot_height=550, sizing_mode="fixed", title="With inspect behavior") p1.circle(x='x', y='y', source=source, size=50) p1.add_tools(TapTool(behavior='inspect', callback=CustomJS(code="alert('foo');"))) p1.add_tools(HoverTool()) p2 = Figure(plot_width=550, plot_height=550, sizing_mode="fixed", title="With select behavior") p2.circle(x='x', y='y', source=source, size=50) p2.add_tools(TapTool(behavior='select', callback=CustomJS(code="alert('foo');"))) p2.add_tools(HoverTool()) layout = row(p1, p2) show(layout)
def freq_plot(freq_array, date_array, plot_name, init_key1='tea', init_key2='coffee'): """ create frequency plot :param freq_array: columns: dates, rows: keywords :param date_array: dates :param plot_name: """ def get_dataset(key1, key2): return ColumnDataSource(data=dict(dates=date_array, freq1=freq_array[key2index(key1), :].tolist(), freq2=freq_array[key2index(key2), :].tolist(), )) source = get_dataset(init_key1, init_key2) freq_list = freq_array.tolist() freq = ColumnDataSource(data=dict(freq_list=freq_list)) callback1 = CustomJS(args=dict(source=source, freq=freq), code=""" var data = source.get('data'); var freq = freq.get('data'); var freq_list = freq['freq_list']; var option = cb_obj.get('value'); var index = option.split(':')[0]; for (var i = 0; i < freq_list[0].length; i++) {data['freq1'][i] = freq_list[index][i] }; source.trigger('change'); """) callback2 = CustomJS(args=dict(source=source, freq=freq), code=""" var data = source.get('data'); var freq = freq.get('data'); var freq_list = freq['freq_list']; var option = cb_obj.get('value'); var index = option.split(':')[0]; for (var i = 0; i < freq_list[0].length; i++) {data['freq2'][i] = freq_list[index][i] }; source.trigger('change'); """) # set up plot plot = Figure(plot_width=1000, tools="pan,reset," "resize,save,wheel_zoom", responsive=True, x_axis_type='datetime') plot.min_border = 0 colormap = Spectral9 keys = get_keys() for i in range(len(keys)): plot.line(x=date_array, y=freq_array[i, :].tolist(), line_color=colormap[4], line_alpha=0.5, line_width=1) plot.line(x='dates', y='freq1', line_width=4, line_alpha=1, source=source, line_color=colormap[0], legend='keyword 1', ) plot.line(x='dates', y='freq2', line_width=4, line_alpha=1, source=source, line_color=colormap[1], legend='keyword 2', ) plot.xaxis.axis_label = 'Date [Month/Day/Year]' plot.yaxis.axis_label = 'Variation relative to mean' plot.legend.location = 'top_right' # show events m, d, y, e = get_events() all_dates = [datetime.datetime(y[i], m[i], d[i]) for i in range(y.shape[0])] event_source = ColumnDataSource(data=dict(date_x=all_dates, date_y=[10 for x in all_dates], event=e, date=[x.strftime('%m-%d-%Y') for x in all_dates])) event_points = plot.circle(x='date_x', y='date_y', size=20, color=colormap[8], source=event_source, alpha=.5) hover = HoverTool(renderers=[event_points], tooltips=[("date", "@date"), ("event", "@event")], ) plot.add_tools(hover) # set up widgets options = [str(x) + ': ' + get_keys()[x] for x in range(len(get_keys()))] first_key1 = str(key2index(init_key1)) + ': ' + init_key1 first_key2 = str(key2index(init_key2)) + ': ' + init_key2 key1_select = Select(value=first_key1, title='keyword 1', options=options, callback=callback1) key2_select = Select(value=first_key2, title='keyword 2', options=options, callback=callback2) inputs = HBox(key1_select, key2_select, width=400) layout = VBox(inputs, plot) # for website script, html = components(layout) print (html) # curdoc().add_root(HBox(inputs, plot)) # save output file output_file(plot_name + '.html', title=plot_name) # save js file for website js_file = open(plot_name + '.js', 'w') js_file.write(script) js_file.close() show(layout)
plot.yaxis.axis_label = "Frequency" plot.yaxis.axis_line_color = None plot.yaxis.major_tick_line_color = None plot.yaxis.minor_tick_line_color = None plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = None plot.outline_line_color = None plot.logo = None bar_hover = HoverTool(renderers=[freq_bars], tooltips=[("Range", '@left_edge to @right_edge'), ("Frequency", '@hist'), ("Total # Samples", '@samples')]) plot.add_tools(bar_hover) # Dropdown and interactive UI elements selectable_years = ["All Years"] + list(map(str, compdata['Year'].unique())) selectable_events = ["All Events"] + [event.replace(' Score', '') for event in compdata.columns.values.tolist()[5:13]] select_year = Select(title="Year", value="All Years", options=selectable_years) select_event = Select(title="Event", value="All Events", options=selectable_events) # Interactive callbacks def update_histogram_data(year='All Years', event='All Events'): # TODO: Properly sanitize input data event_index_name = EVENT_CONSTANTS[event]['fullname'] event_max_points = EVENT_CONSTANTS[event]['points']
source = ColumnDataSource(data=dict(x=[], y=[], color=[], raw=[], wikidataID=[], counts=[])) selected, new_x_factors, new_y_factors = get_subset(dictionary_selector.value, dictionary_selector.value) TOOLS="tap, reset" hover = HoverTool(names = ["glyphs"], tooltips=[("Cooccurring", "@x, @y"), ("Counts", "@counts"), ("wikidataID for this item (x-axis)", "@wikidataID")]) fig = Figure(plot_height=700, plot_width=700, title="", tools=TOOLS, toolbar_location="above", x_range=new_x_factors[:top_n.value], y_range=new_y_factors[:top_n.value]) fig.add_tools(hover) update(None, None, None) # initial load of the data rects = fig.rect(x="x", y="y", source=source, color="color", width=0.95, height=0.95, name="glyphs") fig.xaxis.major_label_orientation = np.pi/4 fig.yaxis.major_label_orientation = np.pi/4 fig.xgrid.visible = False fig.ygrid.visible = False url = "https://www.wikidata.org/wiki/@wikidataID" taptool = fig.select(type=TapTool) taptool.callback = OpenURL(url=url) renderer = fig.select(name="glyphs")[0] renderer.selection_glyph = renderer.glyph renderer.nonselection_glyph = renderer.glyph
def __init__(self, fig: Figure): """ Constructs a new PassGeneratorPlotter associated to fig. :param fig: A Bokeh figure """ self.fig = fig self.zones_source = ColumnDataSource( dict(center_xs=[], center_ys=[], widths=[], heights=[])) self.fig.rect( source=self.zones_source, x="center_xs", y="center_ys", width="widths", height="heights", fill_alpha=0, line_color="blue", line_width=1.2, legend_label="Pass Generator zones", ) self.passes_source = ColumnDataSource( dict( receiver_xs=[], receiver_ys=[], pass_line_xs=[], pass_line_ys=[], pass_rating=[], line_width=[], )) self.pass_color_mapper = LinearColorMapper(palette=mpl["Plasma"][256], low=0, high=1) color_bar = ColorBar( color_mapper=self.pass_color_mapper, width=8, height=400, location="bottom_right", title="Pass rating", ) self.fig.add_layout(color_bar, "right") self.fig.multi_line( source=self.passes_source, xs="pass_line_xs", ys="pass_line_ys", line_width="line_width", line_color=dict(field="pass_rating", transform=self.pass_color_mapper), ) receiver_point_glyph = self.fig.circle_cross( source=self.passes_source, x="receiver_xs", y="receiver_ys", size=10, fill_alpha=0.0, legend_label="Receiver points", ) pass_rating_tooltip = ("Pass rating", "@pass_rating") hover_tool = HoverTool(tooltips=[pass_rating_tooltip], renderers=[receiver_point_glyph]) fig.add_tools(hover_tool)
def periodic_plot(cds, title="Periodic Table", width=PLOT_WIDTH, height=PLOT_HEIGHT, cmap="viridis", showfblock=True, long_version=False, color_mapper=None): """ Create the periodic plot Args: df : DataFrame Pandas DataFrame with the data on elements tile : str Title to appear above the periodic table colorby : str Name of the column containig the colors width : int Width of the figure in pixels height : int Height of the figure in pixels cmap : str Colormap to use, see matplotlib colormaps long_version : bool Show the long version of the periodic table with the f block between the s and d blocks showfblock : bool Show the elements from the f block .. note:: `property` attribute holds the current property to be displayed """ fig = Figure(title=title, x_axis_location="above", x_range=(0.5, 18.5), y_range=(10.0, 0.5), plot_width=width, plot_height=height, tools="box_zoom,pan,resize,save,reset", toolbar_location="above", toolbar_sticky=False, ) if color_mapper is None: color_dict = "#1F77B4" else: color_dict = {"field": "value", "transform": color_mapper} fig.rect("x", "y", 0.9, 0.9, source=cds, fill_alpha=0.6, fill_color=color_dict, line_color=color_dict) # adjust the ticks and axis bounds fig.yaxis.bounds = (1, 7) fig.axis[1].ticker.num_minor_ticks = 0 fig.axis[0].ticker = FixedTicker(ticks=list(range(1, 19))) text_props = { "source": cds, "angle": 0, "color": "black", "text_align": "center", "text_baseline": "middle" } fig.text(x="x", y="y_symbol", text="symbol", text_font_style="bold", text_font_size="15pt", **text_props) fig.text(x="x", y="y_anumber", text="atomic_number", text_font_size="9pt", **text_props) fig.text(x="x", y="y_name", text="name", text_font_size="7pt", **text_props) fig.text(x="x", y="y_prop", text="value_str", text_font_size="8pt", **text_props) fig.grid.grid_line_color = None hover = HoverTool(tooltips=HOVER_TOOLTIPS) fig.add_tools(hover) return fig
def plot_carto_single(self, data, frente, palette, path=FILE_OUT, name_file="", low=0, high=100, show_plot=True): """ :param data: df loaded by data_load :param frente: string, name of "partido" lowercase: diff, mas, cc, creemos, fpv, pan_bol :param palette: ej: P_GRAD_CC :param name_file: default:test :param low: cmap low limit: default: -80 :param high: cmap high limit: defauilt: +80. :param path: file out :return: df """ da_col = ['HAB','PAIS','MUN','REC','X','Y','LAT','LON','x','y', 'r','r2','GX','GY' ] cart_init_val = self.CART_SLIDER_INIT # add slider self.process_data(cart_init_val, data) if frente == "diff": low = self.C_BAR_LOW high = self.C_BAR_HIGH frente = "d_mas_cc" f1 = 'mas_o_cc' f2 = 'ad_mas_cc' _p = 'mas' _p1 = 'cc' da_col.append(frente) da_col.append(f1) da_col.append(f2) da_col.append(_p) da_col.append(_p1) if frente == "d_mas_creemos": low = self.C_BAR_LOW high = self.C_BAR_HIGH f1 = 'mas_o_creemos' f2 = 'ad_mas_creemos' da_col.append(frente) da_col.append(f1) da_col.append(f2) da_col.append('mas') da_col.append('creemos') da_col.append(frente) cm = linear_cmap(frente, palette=palette, low=low, high=high) data = data[da_col] source_master = ColumnDataSource(data) source_red_map = ColumnDataSource({'gx': [], 'gy': []}) # la, lo = ebu.get_la_lo_bolivia() # source_bol = ColumnDataSource({'la': la, 'lo': lo}) # source_red_car = ColumnDataSource({'lo': [], 'la': []}) # JS CODE code_draw_red_map = """ const data = {'gx': [], 'gy': []} const indices = cb_data.index.indices for (var i = 0; i < indices.length; i++ ) { data['gx'].push(source_master.data.GX[indices[i]]) data['gy'].push(source_master.data.GY[indices[i]]) } source_red_map.data = data """ code_slider = """ var data = source.data; var f = cb_obj.value var x = data['x'] var y = data['y'] var Y = data['Y'] var X = data['X'] var lat = data['LAT'] var lon = data['LON'] for (var i = 0; i < x.length; i++) { y[i] = (1-f)*lat[i] + f*Y[i] x[i] = (1-f)*lon[i] + f*X[i] } source.change.emit(); """ # FIGURES curr_time = ebu.get_bolivian_time(-3) pw = self.FIG_WIDTH callback_red_map = CustomJS( args={'source_master': source_master, 'source_red_map': source_red_map, }, code=code_draw_red_map) hover_cart = bokeh.models.HoverTool( tooltips=self.TOOL_TIP_DIC[frente], callback=callback_red_map, # renderers = [red_scat_car] ) cart_fig = Figure(plot_width=pw, plot_height=pw, output_backend="webgl", ) cart_fig.background_fill_color = "grey" cart_fig.background_fill_alpha = .5 cart_fig.scatter('x', 'y', source=source_master, radius='r', color=cm) cart_fig.add_tools(hover_cart, ) title = "Última actualización: " + curr_time["datetime_val"].strftime( "%Y-%m-%d %H:%M") + "BOT" map_fig = Figure(plot_width=pw, plot_height=pw, x_axis_type='mercator', y_axis_type='mercator', output_backend="webgl", title=title, ) # cb_fig = bokeh.plotting.Figure(plot_height=pw,plot_width=) # cb_fig.toolbar.logo = None # cb_fig.toolbar_location = None # SCATTER # noinspection PyUnresolvedReferences # add tiles tile_provider = bokeh.tile_providers.get_provider( bokeh.tile_providers.Vendors.CARTODBPOSITRON) map_fig.add_tile(tile_provider) # scatter in map map_fig.scatter( 'GX', 'GY', source=source_master, size='r2', color=cm ) # todo if we wont use map then we nee to delete the source # cart_fig.line('lo', 'la', source=source_bol, color='black') # noinspection PyUnusedLocal red_scat_map = map_fig.circle_cross('gx', 'gy', source=source_red_map, fill_color=None, size=20, line_color="white", line_width=4 ) # noinspection PyUnusedLocal red_scat_map = map_fig.circle_cross('gx', 'gy', source=source_red_map, fill_color=None, size=20, line_color="red", line_width=1 ) # red_scat_car = cart_fig.scatter('lo', 'la', # source=source_red_car, color='green') # add a hover tool that sets the link data for a hovered circle # callbacks # code = code_merged) # callback_red_car = CustomJS( # args={'source_master': source_master, 'source_red_car': source_red_car}, # code=code_draw_red_car) # tools hover_map = bokeh.models.HoverTool( tooltips=self.TOOL_TIP_DIC[frente], # callback=callback_red_car, # renderers = [red_scat_map] ) map_fig.add_tools(hover_map, ) # slider callback_slider = CustomJS(args=dict(source=source_master), code=code_slider) slider = Slider(start=0, end=1, value=cart_init_val, step=.02, title="carto") slider.js_on_change('value', callback_slider) # COLOR BAR ml = {int(i): str(np.abs(i)) for i in np.arange(-80, 81, 20)} cb = bokeh.models.ColorBar( color_mapper=cm['transform'], # width=int(.9 * 450), width='auto', location=(0, 0), # title="DEN (N/km^2)", # title=(BAR_TITLE), # margin=0,padding=0, title_standoff=10, # ticker=bokeh.models.LogTicker(), orientation='horizontal', major_label_overrides=ml ) cart_fig.add_layout(cb, 'above') # cb.title_text_align = 'left' cart_fig.title.text = self.BAR_TITLE_DIC[frente] cart_fig.title.align = 'center' # layout = row(column(slider, cart_f),map_f) layout = bokeh.layouts.gridplot( [[slider, None], [cart_fig, map_fig]], sizing_mode='scale_width', merge_tools=False) layout.max_width = 1400 # layout = bokeh.layouts.column([slider, cart_fig]) cart_fig.x_range.start = self.CXS cart_fig.x_range.end = self.CXE cart_fig.y_range.start = self.CYS cart_fig.y_range.end = self.CYE _ll = ebu.lola_to_cart(lo=[self.MXS, self.MXE], la=[self.MYS, self.MYE]) map_fig.x_range.start = _ll[0][0] map_fig.x_range.end = _ll[0][1] map_fig.y_range.start = _ll[1][0] map_fig.y_range.end = _ll[1][1] cart_fig.xaxis.major_tick_line_color = None # turn off x-axis major ticks cart_fig.xaxis.minor_tick_line_color = None # turn off x-axis minor ticks cart_fig.yaxis.major_tick_line_color = None # turn off y-axis major ticks cart_fig.yaxis.minor_tick_line_color = None cart_fig.xaxis.major_label_text_font_size = '0pt' # turn off x-axis tick labels cart_fig.yaxis.major_label_text_font_size = '0pt' # turn off y-axis tick labels nam = 'z037_' + frente + '_' + name_file + '.html' nam_lat = 'z037_' + frente + '_' + 'latest' + '.html' nam1 = os.path.join(path, nam) nam2 = os.path.join(os.path.dirname(ebu.DIR), 'docs', 'graficas_htmls', nam_lat) # bokeh.plotting.output_file(nam2) if show_plot: bokeh.plotting.show(layout) bokeh.plotting.save(layout, nam1) bokeh.plotting.save(layout, nam2) return data
# tools ebu.TOOL_TIPS1 = [('Inscritos', '@HAB'), ('PAIS', '@PAIS'), ('Municipalidad', '@MUN'), ('Recinto', '@REC'), ('MAS-CC%', '@d_mas_cc{0.0}') # ('DEN %', '@DEN') # ('PAIS', '@PAIS'), ] hover_cart = bokeh.models.HoverTool( tooltips=ebu.TOOL_TIPS1, callback=callback_red_map, # renderers = [red_scat_car] ) cart_fig.add_tools(hover_cart, ) hover_map = bokeh.models.HoverTool( tooltips=ebu.TOOL_TIPS1, # callback=callback_red_car, # renderers = [red_scat_map] ) map_fig.add_tools(hover_map, ) # slider callback_slider = CustomJS(args=dict(source=source_master), code=code_slider) slider = Slider(start=0, end=1, value=cart_init_val, step=.01, title="carto") slider.js_on_change('value', callback_slider) # %%
# rank chart 그리는 부분임 ranksource = ColumnDataSource( data={ 'crop': list(rank.keys()), 'rank': list(rank.values()), 'year': [db.column_names] * len(rank), 'color': Category20[14] }) p = Figure(plot_width=1000, plot_height=300, x_axis_label='Year', y_axis_label='Rank', toolbar_location='above', title='재배면적 상위 10개종목 순위변화') p.multi_line('year', 'rank', alpha=1, color='color', source=ranksource) p.add_tools(HoverTool(tooltips=[('Crop', '@crop')])) # 작물 select 하면 맞춰서 그래프 움직이는 부분 select = Select(title="Crop", value="감자", options=crops) def update_crop(attr, old, new): source.data = get_data(str(select.value)) select.on_change('value', update_crop) seconddiv = Div(text="""<h1>읍면동별 작물 시계열 차트</h1>""", width=1000) rankwidget = WidgetBox(titlediv, data_table, para, cums_table)
sntypes = sorted(sntypes) snoffs = [[] for x in range(len(sntypes))] tt = [("Type", "@ct")] hover = HoverTool(tooltips=tt, line_policy='interp') p = Figure(x_range=[0., 100.], y_range=[0., 1.], title='Supernova Host Offsets', x_axis_label='Offset (kpc)', y_axis_label='CDF', plot_width=980, plot_height=500, title_text_font='futura', title_text_font_size='14pt') p.add_tools(hover) for si, sntype in enumerate(sntypes): for event in meta: if 'hostoffkpc' in event and is_number(event['hostoffkpc']) \ and 'claimedtype' in event and event['claimedtype'] and sntype in [x['value'] for x in event['claimedtype']]: snoffs[si].append(float(event['hostoffkpc'])) snoffs[si] = sorted(snoffs[si]) colors = sns.color_palette("hls", n_colors=sum([ 1 if len(snoffs[i]) >= mincnt else 0 for i, x in enumerate(snoffs) ])).as_hex() cnt = 0
class DynamicPlotHandler(Handler): def __init__(self, network): self._network = weakref.ref(network) self.sources = {} self._last_time_list = None self._update_complete = False self._recurring_update = RecurringTask(self.plan_update_data, delay=5) self._pcb = None # Periodic callback self._ntcb = None # Next Tick callback super().__init__() @property def network(self): return self._network() def organize_data(self): self._log.debug("Organize Data") self.s = {} for point in self.network.trends: self.s[point.history.name] = (point.history, point.history.units) self.lst_of_trends = [his[0] for name, his in self.s.items()] def build_data_sources(self): sources = {} self.organize_data() for each in self.lst_of_trends: df = pd.DataFrame(each) df = df.reset_index() df["name"] = each.name df["units"] = str(each.units) df["time_s"] = df["index"].apply(str) df.states = each.states try: df = ( df.fillna(method="ffill") .fillna(method="bfill") .replace(["inactive", "active"], [0, 1]) ) except TypeError: df = df.fillna(method="ffill").fillna(method="bfill") sources[each.name] = ColumnDataSource( data=dict( x=df["index"], y=df[each.name], time=df["time_s"], name=df["name"], units=df["units"], ) ) return sources def build_plot(self): self._log.debug("Build Plot") self.stop_update_data() self.sources = self.build_data_sources() TOOLS = "pan,box_zoom,wheel_zoom,save,reset" self.p = Figure( x_axis_type="datetime", x_axis_label="Time", y_axis_label="Numeric Value", title="BAC0 Trends", tools=TOOLS, plot_width=800, plot_height=600, toolbar_location="above", ) self.p.background_fill_color = "#f4f3ef" self.p.border_fill_color = "#f4f3ef" self.p.extra_y_ranges = { "bool": Range1d(start=0, end=1.1), "enum": Range1d(start=0, end=10), } self.p.add_layout(LinearAxis(y_range_name="bool", axis_label="Binary"), "left") self.p.add_layout( LinearAxis(y_range_name="enum", axis_label="Enumerated"), "right" ) hover = HoverTool( tooltips=[ ("name", "@name"), ("value", "@y"), ("units", "@units"), ("time", "@time"), ] ) self.p.add_tools(hover) self.legends_list = [] length = len(self.s.keys()) if length <= 10: if length < 3: length = 3 color_mapper = dict(zip(self.s.keys(), d3["Category10"][length])) else: # This would be a very loaded trend... color_mapper = dict(zip(self.s.keys(), Spectral6[:length])) for each in self.lst_of_trends: if each.states == "binary": self.p.circle( "x", "y", source=self.sources[each.name], name=each.name, color=color_mapper[each.name], legend=("{} | {} (OFF-ON)".format(each.name, each.description)), y_range_name="bool", size=10, ) # self.legends_list.append( # (("{} | {} (OFF-ON)".format(each.name, each.description)), [c]) # ) elif each.states == "multistates": self.p.diamond( "x", "y", source=self.sources[each.name], name=each.name, color=color_mapper[each.name], legend=( "{} | {} ({})".format(each.name, each.description, each.units) ), y_range_name="enum", size=20, ) else: self.p.line( "x", "y", source=self.sources[each.name], name=each.name, color=color_mapper[each.name], legend=( "{} | {} ({})".format(each.name, each.description, each.units) ), line_width=2, ) self.p.legend.location = "top_left" # legend = Legend(items=self.legends_list, location=(0, -60)) self.p.legend.click_policy = "hide" # self.p.add_layout(legend, "right") self.plots = [self.p] def update_data(self): self._log.debug("Update Data") doc = curdoc() # self.organize_data() if self._last_time_list: if self._last_time_list != self.s.keys(): self._list_have_changed = True self.stop_update_data() # doc.add_next_tick_callback(self.modify_document) self.modify_document(doc) else: self._list_have_changed = False l = [] for each in self.p.renderers: l.append(each.name) # for each in self.lst_of_trends: # df = pd.DataFrame(each) # df = df.reset_index() # df['name'] = each.name # df['units'] = str(each.units) # df['time_s'] = df['index'].apply(str) # try: # df = df.fillna(method='ffill').fillna( # method='bfill').replace(['inactive', 'active'], [0, 1]) # except TypeError: # df = df.fillna(method='ffill').fillna(method='bfill') index = l.index(each.name) # renderer = self.p.renderers[index] # new_data = {} # new_data['name'] = df['name'] # new_data['x'] = df['index'] # new_data['y'] = df[each.name] # if each.states == 'binary': # new_data['units'] = [each.units[int(x)] for x in df[each.name]] # elif each.states == 'multistates': # new_data['units'] = [ # each.units[int(math.fabs(x-1))] for x in df[each.name]] # else: # new_data['units'] = df['units'] # new_data['time'] = df['time_s'] # renderer.data_source.data = new_data try: new_data = self.build_data_sources() for each in self.lst_of_trends: self.sources[each.name].data = new_data[each.name].data except KeyError: self._log.warning( "Problem updating {} on chart, will try again next time.".format( each.name ) ) else: self._last_time_list = self.s.keys() # self.start_update_data() self._update_complete = True def modify_document(self, doc): doc.clear() self.build_plot() layout = gridplot(self.plots, ncols=2) doc.add_root(layout) self._pcb = doc.add_periodic_callback(self.update_data, 10000) return doc def plan_update_data(self): doc = curdoc() if self._update_complete == True: self._update_complete = False self._ntcb = doc.add_next_tick_callback(self.update_data) def stop_update_data(self): doc = curdoc() try: doc.remove_periodic_callback(self._pcb) except: pass if self._recurring_update.is_running: self._recurring_update.stop() while self._recurring_update.is_running: pass try: doc.remove_next_tick_callback(self._ntcb) except (ValueError, RuntimeError): pass # Already gone def start_update_data(self): if not self._recurring_update.is_running: try: self._recurring_update.start() while not self._recurring_update.is_running: pass except RuntimeError: pass
max_x_range = x_buffer + \ max([x + y for x, y in list(zip(phototime, phototimelowererrs))]) p1 = Figure(title='Average Photometry for Type ' + averagetype + ' SNe', x_axis_label='Time (MJD)', # responsive = True, y_axis_label='Absolute Magnitude', tools=tools, plot_width=1000, plot_height=1000, x_range=(min_x_range, max_x_range), y_range=(0.5 + max([x + y for x, y in list(zip(photoAB, photoABerrs))]), -0.5 + min([x - y for x, y in list(zip(photoAB, photoABerrs))])), title_text_font_size='20pt', webgl=True) p1.xaxis.axis_label_text_font_size = '16pt' p1.yaxis.axis_label_text_font_size = '16pt' p1.xaxis.major_label_text_font_size = '12pt' p1.yaxis.major_label_text_font_size = '12pt' p1.add_tools(hover) xs = [] ys = [] err_xs = [] err_ys = [] for x, y, xlowerr, xupperr, yerr in list(zip(phototime, photoAB, phototimelowererrs, phototimeuppererrs, photoABerrs)): xs.append(x) ys.append(y) err_xs.append((x - xlowerr, x + xupperr)) err_ys.append((y - yerr, y + yerr)) for band in bandset: bandname = bandaliasf(band) indb = [i for i, j in enumerate(photoband) if j == band]
borders_y=b["y"], colors=no_colors, alpha=alpha, state_names=state_names, state_totals=state_totals, state_drunk=state_drunk, state_percent=state_percent, state_percent_sp=state_percent_sp ) ) patches = fig.patches(xs="borders_x", ys="borders_y", source=patch_source, fill_alpha="alpha", fill_color="colors", line_alpha=0, hover_alpha=.3, line_width=5) fig.add_tools(HoverTool(renderers=[patches], tooltips=[("State", "@state_names"), ("Total", "@state_totals"), ("Drunk%", "@state_percent{1.11}" + "%"), ("Speeding%", "@state_percent_sp{1.11}" + "%")])) select = Select(title="Color States By:", value="None", options=["None", "Drunk%", "Speeding%"]) def update_color(attrname, old, new): if select.value == "Drunk%": patch_source.data["colors"] = drunk_colors patch_source.data["alpha"] = [.3]*len(state_names) elif select.value == "Speeding%": patch_source.data["colors"] = speeding_colors patch_source.data["alpha"] = [.3]*len(state_names) else: patch_source.data["colors"] = no_colors patch_source.data["alpha"] = [0]*len(state_names) select.on_change('value', update_color)
def build_local_uk_tab(): s3_root = 'https://covid19-bokeh-app.s3.eu-west-2.amazonaws.com' la_boundaries_gdf = gpd.read_file( f'{s3_root}/data/_geo_data/la_districts_dec19.zip' ).loc[:, ['lad19cd', 'lad19nm', 'geometry']] # Importing uk local authority data la_cases_df = pd.read_csv(f'{s3_root}/data/local_uk.csv') # Filter for latest date la_cases_latest_df = la_cases_df.loc[la_cases_df.date == la_cases_df.date.max()] # Import local authority population data la_pop_df = pd.read_csv(f'{s3_root}/data/local_authority_populations.csv' ).loc[:, ['code', 'population']] # Remove commas and convert to numeric dtype la_pop_df['population'] = pd.to_numeric( (la_pop_df['population'].str.replace(",", ""))) # Merge cases and population datasets la_cases_latest_df = la_cases_latest_df.merge(la_pop_df, left_on="area_code", right_on="code", how="left") # Merge geo-boundaries GeoDataFrame with cases, pop dataset la_cases_gdf = la_boundaries_gdf.merge(la_cases_latest_df, left_on="lad19cd", right_on="area_code", how="left") # Calculate weekly cases per 100,000 la_cases_gdf['cases_per_pop'] = ( 100000 * la_cases_gdf['weekly_cases'] / la_cases_gdf['population']).fillna(0).astype(int) # Convert dataset to GeoJSONDataSource to feed geo-plot geosource = GeoJSONDataSource(geojson=la_cases_gdf.to_json()) # Adding figure and geographical patches from shapefile local_uk_geo_plot = Figure(title="Weekly Cases per 100,000", plot_height=500, plot_width=500, name="local_uk_geo_plot", output_backend="webgl") # Add linear colour mapper for case density mapper = linear_cmap(field_name='cases_per_pop', palette=brewer['YlOrRd'][9][:7][::-1], low=min(la_cases_gdf['cases_per_pop']), high=max(la_cases_gdf['cases_per_pop'])) # Add local authority patches to figure geo_patches = local_uk_geo_plot.patches('xs', 'ys', source=geosource, alpha=0.8, color=mapper) # Adding hover tool and tap tool hover = HoverTool( tooltips=[('Local Authority', '@lad19nm'), ( 'Daily Cases', '@new_cases'), ('Population', '@population{0,0}' ), ('Weekly Cases per 100,000', '@cases_per_pop')]) local_uk_geo_plot.add_tools(hover) local_uk_geo_plot.add_tools(TapTool()) # Adding color bar color_bar = ColorBar(color_mapper=mapper['transform'], location=(0, 0)) local_uk_geo_plot.add_layout(color_bar, 'right') # Adding recent trend figure area_name = "Wandsworth" cases_trend_df = la_cases_df.loc[la_cases_df.area_name == area_name] cases_trend_df.date = pd.to_datetime(cases_trend_df.date, format="%Y-%m-%d") ninety_days_back = cases_trend_df.date.max() - timedelta(days=90) cases_trend_df = cases_trend_df.loc[ cases_trend_df.date >= ninety_days_back] cases_trend_cds = ColumnDataSource(cases_trend_df) cases_trend_plot = Figure(title=f"New Cases in {area_name}", plot_height=500, plot_width=500, name="cases_trend_plot", x_axis_type="datetime") cases_trend_plot.line(x='date', y='new_cases', legend="New Cases", source=cases_trend_cds) cases_trend_plot.line(x='date', y='weekly_average', line_color="orange", legend="Weekly Average", source=cases_trend_cds) cases_trend_hover = HoverTool(tooltips=[('Date', '@date{%F}'), ('Daily Cases', '@new_cases'), ('Weekly Average', '@weekly_average{int}')], formatters={"@date": "datetime"}) cases_trend_plot.add_tools(cases_trend_hover) def callback(attr, old, new): index = geosource.selected.indices[0] geojson = json.loads(geosource.geojson) area_name = geojson['features'][index]['properties']['area_name'] # Adding recent trend figure cases_trend_df = la_cases_df.loc[la_cases_df.area_name == area_name] cases_trend_df.date = pd.to_datetime(cases_trend_df.date, format="%Y-%m-%d") ninety_days_back = cases_trend_df.date.max() - timedelta(days=90) cases_trend_df = cases_trend_df.loc[ cases_trend_df.date >= ninety_days_back] cases_trend_cds.data = cases_trend_df cases_trend_plot.title.text = f"New Cases in {area_name}" geosource.selected.on_change('indices', callback) # Add the plots to the current document curdoc().add_root(local_uk_geo_plot) curdoc().add_root(cases_trend_plot)
class AppView(object): def __init__(self, app_model): self.model = app_model self.create_layout() def create_layout(self): # create figure self.x_range = Range1d(start=self.model.map_extent[0], end=self.model.map_extent[2], bounds=None) self.y_range = Range1d(start=self.model.map_extent[1], end=self.model.map_extent[3], bounds=None) self.fig = Figure(tools='wheel_zoom,pan', x_range=self.x_range, lod_threshold=None, plot_width=self.model.plot_width, plot_height=self.model.plot_height, y_range=self.y_range) self.fig.min_border_top = 0 self.fig.min_border_bottom = 10 self.fig.min_border_left = 0 self.fig.min_border_right = 0 self.fig.axis.visible = False self.fig.xgrid.grid_line_color = None self.fig.ygrid.grid_line_color = None # add tiled basemap self.tile_source = WMTSTileSource(url=self.model.basemap) self.tile_renderer = TileRenderer(tile_source=self.tile_source) self.fig.renderers.append(self.tile_renderer) # add datashader layer self.image_source = ImageSource(url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) self.image_renderer = DynamicImageRenderer(image_source=self.image_source) self.fig.renderers.append(self.image_renderer) # add label layer self.label_source = WMTSTileSource(url=self.model.labels_url) self.label_renderer = TileRenderer(tile_source=self.label_source) self.fig.renderers.append(self.label_renderer) # Add a hover tool hover_layer = HoverLayer() hover_layer.field_name = self.model.field_title hover_layer.is_categorical = self.model.field in self.model.categorical_fields self.fig.renderers.append(hover_layer.renderer) self.fig.add_tools(hover_layer.tool) self.model.hover_layer = hover_layer self.model.legend_side_vbox = VBox() self.model.legend_bottom_vbox = VBox() # add ui components controls = [] axes_select = Select.create(name='Axes', options=self.model.axes) axes_select.on_change('value', self.on_axes_change) controls.append(axes_select) self.field_select = Select.create(name='Field', options=self.model.fields) self.field_select.on_change('value', self.on_field_change) controls.append(self.field_select) self.aggregate_select = Select.create(name='Aggregate', options=self.model.aggregate_functions) self.aggregate_select.on_change('value', self.on_aggregate_change) controls.append(self.aggregate_select) transfer_select = Select.create(name='Transfer Function', options=self.model.transfer_functions) transfer_select.on_change('value', self.on_transfer_function_change) controls.append(transfer_select) color_ramp_select = Select.create(name='Color Ramp', options=self.model.color_ramps) color_ramp_select.on_change('value', self.on_color_ramp_change) controls.append(color_ramp_select) spread_size_slider = Slider(title="Spread Size (px)", value=0, start=0, end=10, step=1) spread_size_slider.on_change('value', self.on_spread_size_change) controls.append(spread_size_slider) hover_size_slider = Slider(title="Hover Size (px)", value=8, start=4, end=30, step=1) hover_size_slider.on_change('value', self.on_hover_size_change) controls.append(hover_size_slider) controls.append(self.model.legend_side_vbox) # add map components basemap_select = Select.create(name='Basemap', value='Imagery', options=self.model.basemaps) basemap_select.on_change('value', self.on_basemap_change) image_opacity_slider = Slider(title="Opacity", value=100, start=0, end=100, step=1) image_opacity_slider.on_change('value', self.on_image_opacity_slider_change) basemap_opacity_slider = Slider(title="Basemap Opacity", value=100, start=0, end=100, step=1) basemap_opacity_slider.on_change('value', self.on_basemap_opacity_slider_change) show_labels_chk = CheckboxGroup(labels=["Show Labels"], active=[0]) show_labels_chk.on_click(self.on_labels_change) map_controls = [basemap_select, basemap_opacity_slider, image_opacity_slider, show_labels_chk] self.controls = VBox(width=200, height=600, children=controls) self.map_controls = HBox(width=self.fig.plot_width, children=map_controls) self.map_area = VBox(width=self.fig.plot_width, children=[self.map_controls, self.fig, self.model.legend_bottom_vbox]) self.layout = HBox(width=1366, children=[self.controls, self.map_area]) def update_image(self): self.model.shader_url_vars['cachebust'] = str(uuid.uuid4()) self.image_renderer.image_source = ImageSource(url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) def on_field_change(self, attr, old, new): self.model.field_title = new self.model.field = self.model.fields[new] self.model.hover_layer.field_name = new self.model.hover_layer.is_categorical = self.model.field in self.model.categorical_fields self.update_image() if not self.model.field: self.aggregate_select.options = [dict(name="No Aggregates Available", value="")] elif self.model.field in self.model.categorical_fields: self.model.hover_layer.is_categorical = True self.aggregate_select.options = [dict(name="Categorical", value="count_cat")] else: opts = [dict(name=k, value=k) for k in self.model.aggregate_functions.keys()] self.aggregate_select.options = opts self.model.hover_layer.is_categorical = False def on_basemap_change(self, attr, old, new): self.model.basemap = self.model.basemaps[new] self.tile_renderer.tile_source = WMTSTileSource(url=self.model.basemap) def on_hover_size_change(self, attr, old, new): self.model.hover_layer.size = int(new) def on_spread_size_change(self, attr, old, new): self.model.spread_size = int(new) self.update_image() def on_axes_change(self, attr, old, new): self.model.active_axes = self.model.axes[new] self.update_image() def on_aggregate_change(self, attr, old, new): self.model.agg_function_name = new self.update_image() def on_transfer_function_change(self, attr, old, new): self.model.transfer_function = self.model.transfer_functions[new] self.update_image() def on_color_ramp_change(self, attr, old, new): self.model.color_ramp = self.model.color_ramps[new] self.update_image() def on_image_opacity_slider_change(self, attr, old, new): self.image_renderer.alpha = new / 100 def on_basemap_opacity_slider_change(self, attr, old, new): self.tile_renderer.alpha = new / 100 def on_labels_change(self, new): self.label_renderer.alpha = 1 if new else 0