def plot_config(ptype: str, data_source: ColumnDataSource) -> Figure: mapper = LinearColorMapper(palette=constants.cust_rg_palette, low=0.8, high=1.2, low_color='#33FF33', high_color='#FF3333', nan_color='#33FF33') color_bar = ColorBar(color_mapper=mapper, ticker=BasicTicker(), label_standoff=12, border_line_color=None, location=(0, 0), background_fill_alpha=0, background_fill_color=None, major_tick_line_alpha=0) custom_hover_format = CustomJS(args=dict( cust_tooltip_above=constants.cust_tooltip_above, cust_tooltip_below=constants.cust_tooltip_below), code=constants.custom_hover_code) national_args = dict(toolbar_location=None, plot_width=900, plot_height=600, frame_height=700, frame_width=1050) min_width, min_height, max_width, max_height = constants.base_dims state_args = { 'width_policy': 'fit', 'height_policy': 'fit', 'min_height': min_height, 'min_width': min_width, 'max_height': max_height, 'max_width': max_width, 'min_border_left': 25, 'tools': 'pan,wheel_zoom,reset' } plot_tools_config = { 'x_axis_location': None, 'y_axis_location': None, 'border_fill_alpha': 0, 'background_fill_alpha': 0, 'background_fill_color': None, 'border_fill_color': None, 'outline_line_alpha': 0, 'outline_line_width': 0 } t = None if ptype == 'national': p = figure(**plot_tools_config, **national_args) else: p = figure(**plot_tools_config, **state_args) t = Title() t.text = 'Default' p.title = t p.title.text_font_size = "20pt" p.title.text_color = '#003566' p.add_tools( HoverTool(tooltips=None, callback=custom_hover_format, formatters={ '@2nd_order_growth': 'numeral', '@confirmed_infected': 'numeral', '@Rt': 'numeral' })) p.grid.grid_line_color = None p.hover.point_policy = "follow_mouse" p.hover.attachment = "above" p.toolbar.logo = None p.patches('lons', 'lats', source=data_source, fill_color=transform('Rt', mapper), fill_alpha=0.7, line_color='#003566', line_width=0.5, hover_color='#003566') if ptype != 'national': p.add_layout(color_bar, 'right') t.visible = False return p
def plot_bpv( ax, length_plotters, rows, cols, obs_plotters, pp_plotters, total_pp_samples, kind, t_stat, bpv, plot_mean, reference, n_ref, hdi_prob, color, figsize, textsize, plot_ref_kwargs, backend_kwargs, show, ): """Bokeh bpv plot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(), **backend_kwargs, } color = vectorized_to_hex(color) if plot_ref_kwargs is None: plot_ref_kwargs = {} if kind == "p_value" and reference == "analytical": plot_ref_kwargs.setdefault("line_color", "black") plot_ref_kwargs.setdefault("line_dash", "dashed") else: plot_ref_kwargs.setdefault("alpha", 0.1) plot_ref_kwargs.setdefault("line_color", color) (figsize, ax_labelsize, _, _, linewidth, markersize) = _scale_fig_size( figsize, textsize, rows, cols ) if ax is None: axes = create_axes_grid( length_plotters, rows, cols, figsize=figsize, backend_kwargs=backend_kwargs, ) else: axes = np.atleast_2d(ax) if len([item for item in axes.ravel() if not None]) != length_plotters: raise ValueError( "Found {} variables to plot but {} axes instances. They must be equal.".format( length_plotters, len(axes) ) ) for i, ax_i in enumerate((item for item in axes.flatten() if item is not None)): var_name, _, obs_vals = obs_plotters[i] pp_var_name, _, pp_vals = pp_plotters[i] obs_vals = obs_vals.flatten() pp_vals = pp_vals.reshape(total_pp_samples, -1) if kind == "p_value": tstat_pit = np.mean(pp_vals <= obs_vals, axis=-1) x_s, tstat_pit_dens = kde(tstat_pit) ax_i.line(x_s, tstat_pit_dens, line_width=linewidth, line_color=color) # ax_i.set_yticks([]) if reference is not None: dist = stats.beta(obs_vals.size / 2, obs_vals.size / 2) if reference == "analytical": lwb = dist.ppf((1 - 0.9999) / 2) upb = 1 - lwb x = np.linspace(lwb, upb, 500) dens_ref = dist.pdf(x) ax_i.line(x, dens_ref, **plot_ref_kwargs) elif reference == "samples": x_ss, u_dens = sample_reference_distribution( dist, (n_ref, tstat_pit_dens.size,) ) for x_ss_i, u_dens_i in zip(x_ss.T, u_dens.T): ax_i.line(x_ss_i, u_dens_i, line_width=linewidth, **plot_ref_kwargs) elif kind == "u_value": tstat_pit = np.mean(pp_vals <= obs_vals, axis=0) x_s, tstat_pit_dens = kde(tstat_pit) ax_i.line(x_s, tstat_pit_dens, line_color=color) if reference is not None: if reference == "analytical": n_obs = obs_vals.size hdi = stats.beta(n_obs / 2, n_obs / 2).ppf((1 - hdi_prob) / 2) hdi_odds = (hdi / (1 - hdi), (1 - hdi) / hdi) ax_i.add_layout( BoxAnnotation( bottom=hdi_odds[1], top=hdi_odds[0], fill_alpha=plot_ref_kwargs.pop("alpha"), fill_color=plot_ref_kwargs.pop("line_color"), **plot_ref_kwargs, ) ) elif reference == "samples": dist = stats.uniform(0, 1) x_ss, u_dens = sample_reference_distribution(dist, (tstat_pit_dens.size, n_ref)) for x_ss_i, u_dens_i in zip(x_ss.T, u_dens.T): ax_i.line(x_ss_i, u_dens_i, line_width=linewidth, **plot_ref_kwargs) # ax_i.set_ylim(0, None) # ax_i.set_xlim(0, 1) else: if t_stat in ["mean", "median", "std"]: if t_stat == "mean": tfunc = np.mean elif t_stat == "median": tfunc = np.median elif t_stat == "std": tfunc = np.std obs_vals = tfunc(obs_vals) pp_vals = tfunc(pp_vals, axis=1) elif hasattr(t_stat, "__call__"): obs_vals = t_stat(obs_vals.flatten()) pp_vals = t_stat(pp_vals) elif is_valid_quantile(t_stat): t_stat = float(t_stat) obs_vals = np.quantile(obs_vals, q=t_stat) pp_vals = np.quantile(pp_vals, q=t_stat, axis=1) else: raise ValueError(f"T statistics {t_stat} not implemented") plot_kde(pp_vals, ax=ax_i, plot_kwargs={"color": color}, backend="bokeh", show=False) # ax_i.set_yticks([]) if bpv: p_value = np.mean(pp_vals <= obs_vals) ax_i.line(0, 0, legend_label=f"bpv={p_value:.2f}", alpha=0) if plot_mean: ax_i.circle( obs_vals.mean(), 0, fill_color=color, line_color="black", size=markersize ) if var_name != pp_var_name: xlabel = "{} / {}".format(var_name, pp_var_name) else: xlabel = var_name _title = Title() _title.text = xlabel ax_i.title = _title size = str(int(ax_labelsize)) ax_i.title.text_font_size = f"{size}pt" show_layout(axes, show) return axes
def _d_helper( vec, vname, color, bw, line_width, markersize, credible_interval, point_estimate, hpd_markers, outline, shade, ax, ): extra = dict() plotted = [] if vec.dtype.kind == "f": if credible_interval != 1: hpd_ = hpd(vec, credible_interval, multimodal=False) new_vec = vec[(vec >= hpd_[0]) & (vec <= hpd_[1])] else: new_vec = vec density, xmin, xmax = _fast_kde(new_vec, bw=bw) density *= credible_interval x = np.linspace(xmin, xmax, len(density)) ymin = density[0] ymax = density[-1] if outline: plotted.append( ax.line(x, density, line_color=color, line_width=line_width, **extra)) plotted.append( ax.line( [xmin, xmin], [-ymin / 100, ymin], line_color=color, line_dash="solid", line_width=line_width, muted_color=color, muted_alpha=0.2, )) plotted.append( ax.line( [xmax, xmax], [-ymax / 100, ymax], line_color=color, line_dash="solid", line_width=line_width, muted_color=color, muted_alpha=0.2, )) if shade: plotted.append( ax.patch(np.r_[x[::-1], x, x[-1:]], np.r_[np.zeros_like(x), density, [0]], fill_color=color, fill_alpha=shade, muted_color=color, muted_alpha=0.2, **extra)) else: xmin, xmax = hpd(vec, credible_interval, multimodal=False) bins = get_bins(vec) _, hist, edges = histogram(vec, bins=bins) if outline: plotted.append( ax.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:], line_color=color, fill_color=None, muted_color=color, muted_alpha=0.2, **extra)) else: plotted.append( ax.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:], line_color=color, fill_color=color, fill_alpha=shade, muted_color=color, muted_alpha=0.2, **extra)) if hpd_markers: plotted.append( ax.diamond(xmin, 0, line_color="black", fill_color=color, size=markersize)) plotted.append( ax.diamond(xmax, 0, line_color="black", fill_color=color, size=markersize)) if point_estimate is not None: est = calculate_point_estimate(point_estimate, vec, bw) plotted.append( ax.circle(est, 0, fill_color=color, line_color="black", size=markersize)) _title = Title() _title.text = vname ax.title = _title ax.title.text_font_size = "13pt" return plotted
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 source_scatter = ColumnDataSource(itmdt["data"]) source_coeffs = ColumnDataSource(itmdt["coeffs"]) source_xy_value = ColumnDataSource({ "x": [itmdt["data"].columns[0]], "y": [itmdt["data"].columns[0]] }) var_list = list(itmdt["data"].columns)[0:-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 & Regression Line", align="center"), tools=[], x_axis_label=xcol, y_axis_label=ycol, ) scatter = fig.scatter("__x__", "__y__", source=source_scatter) fig.line("__x__", "__y__", source=source_coeffs, 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) 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, coeffs=source_coeffs, xy_value=source_xy_value, x_axis=fig.xaxis[0], ), code=""" let currentSelect = this.value; let xyValueData = xy_value.data; let scatterData = scatter.data; let coeffsData = coeffs.data; xyValueData['x'][0] = currentSelect; scatterData['__x__'] = scatterData[currentSelect]; coeffsData['__x__'] = coeffsData[`${currentSelect}${xyValueData['y'][0]}x`]; coeffsData['__y__'] = coeffsData[`${currentSelect}${xyValueData['y'][0]}y`]; x_axis.axis_label = currentSelect; scatter.change.emit(); coeffs.change.emit(); xy_value.change.emit(); """, ), ) y_select.js_on_change( "value", CustomJS( args=dict( scatter=source_scatter, coeffs=source_coeffs, xy_value=source_xy_value, y_axis=fig.yaxis[0], ), code=""" let currentSelect = this.value; let xyValueData = xy_value.data; let scatterData = scatter.data; let coeffsData = coeffs.data; xyValueData['y'][0] = currentSelect; scatterData['__y__'] = scatterData[currentSelect]; coeffsData['__x__'] = coeffsData[`${xyValueData['x'][0]}${currentSelect}x`]; coeffsData['__y__'] = coeffsData[`${xyValueData['x'][0]}${currentSelect}y`]; y_axis.axis_label = currentSelect; scatter.change.emit(); coeffs.change.emit(); xy_value.change.emit(); """, ), ) fig = column(row(x_select, y_select, align="center"), fig, sizing_mode="stretch_width") return fig
def plot_trace( data, var_names, divergences, kind, figsize, rug, lines, compact, compact_prop, combined, chain_prop, legend, plot_kwargs, fill_kwargs, rug_kwargs, hist_kwargs, trace_kwargs, rank_kwargs, plotters, divergence_data, axes, backend_kwargs, backend_config, show, ): """Bokeh traceplot.""" # If divergences are plotted they must be provided if divergences is not False: assert divergence_data is not None if backend_config is None: backend_config = {} backend_config = { **backend_kwarg_defaults(("bounds_y_range", "plot.bokeh.bounds_y_range"), ), **backend_config, } # Set plot default backend kwargs if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(("dpi", "plot.bokeh.figure.dpi"), ), **backend_kwargs, } dpi = backend_kwargs.pop("dpi") if figsize is None: figsize = (12, len(plotters) * 2) figsize, _, _, _, linewidth, _ = _scale_fig_size(figsize, 10, rows=len(plotters), cols=2) backend_kwargs.setdefault("height", int(figsize[1] * dpi // len(plotters))) backend_kwargs.setdefault("width", int(figsize[0] * dpi // 2)) if lines is None: lines = () num_chain_props = len(data.chain) + 1 if combined else len(data.chain) if not compact: chain_prop = ({ "line_color": plt.rcParams["axes.prop_cycle"].by_key()["color"] } if chain_prop is None else chain_prop) else: chain_prop = ({ "line_dash": ("solid", "dotted", "dashed", "dashdot"), } if chain_prop is None else chain_prop) compact_prop = ({ "line_color": plt.rcParams["axes.prop_cycle"].by_key()["color"] } if compact_prop is None else compact_prop) if isinstance(chain_prop, str): chain_prop = { chain_prop: plt.rcParams["axes.prop_cycle"].by_key()[chain_prop] } if isinstance(chain_prop, tuple): warnings.warn( "chain_prop as a tuple will be deprecated in a future warning, use a dict instead", FutureWarning, ) chain_prop = {chain_prop[0]: chain_prop[1]} chain_prop = { prop_name: [prop for _, prop in zip(range(num_chain_props), cycle(props))] for prop_name, props in chain_prop.items() } if isinstance(compact_prop, str): compact_prop = { compact_prop: plt.rcParams["axes.prop_cycle"].by_key()[compact_prop] } if isinstance(compact_prop, tuple): warnings.warn( "compact_prop as a tuple will be deprecated in a future warning, use a dict instead", FutureWarning, ) compact_prop = {compact_prop[0]: compact_prop[1]} trace_kwargs = {} if trace_kwargs is None else trace_kwargs trace_kwargs.setdefault("alpha", 0.35) if hist_kwargs is None: hist_kwargs = {} hist_kwargs.setdefault("alpha", 0.35) if plot_kwargs is None: plot_kwargs = {} if fill_kwargs is None: fill_kwargs = {} if rug_kwargs is None: rug_kwargs = {} if rank_kwargs is None: rank_kwargs = {} trace_kwargs.setdefault("line_width", linewidth) plot_kwargs.setdefault("line_width", linewidth) if rank_kwargs is None: rank_kwargs = {} if axes is None: axes = [] for i in range(len(plotters)): if i != 0: _axes = [ bkp.figure(**backend_kwargs), bkp.figure(x_range=axes[0][1].x_range, **backend_kwargs), ] else: _axes = [ bkp.figure(**backend_kwargs), bkp.figure(**backend_kwargs) ] axes.append(_axes) axes = np.atleast_2d(axes) cds_data = {} cds_var_groups = {} draw_name = "draw" for var_name, selection, value in list( xarray_var_iter(data, var_names=var_names, combined=True)): if selection: cds_name = "{}_ARVIZ_CDS_SELECTION_{}".format( var_name, "_".join( str(item) for key, value in selection.items() for item in ([key, value] if ( isinstance(value, str) or not isinstance(value, Iterable)) else [key, *value])), ) else: cds_name = var_name if var_name not in cds_var_groups: cds_var_groups[var_name] = [] cds_var_groups[var_name].append(cds_name) for chain_idx, _ in enumerate(data.chain.values): if chain_idx not in cds_data: cds_data[chain_idx] = {} _data = value[chain_idx] cds_data[chain_idx][cds_name] = _data while any(key == draw_name for key in cds_data[0]): draw_name += "w" for chain_idx in cds_data: cds_data[chain_idx][draw_name] = data.draw.values cds_data = { chain_idx: ColumnDataSource(cds) for chain_idx, cds in cds_data.items() } for idx, (var_name, selection, value) in enumerate(plotters): value = np.atleast_2d(value) if len(value.shape) == 2: y_name = (var_name if not selection else "{}_ARVIZ_CDS_SELECTION_{}".format( var_name, "_".join( str(item) for key, value in selection.items() for item in ((key, value) if ( isinstance(value, str) or not isinstance(value, Iterable)) else ( key, *value))), )) if rug: rug_kwargs["y"] = y_name _plot_chains_bokeh( ax_density=axes[idx, 0], ax_trace=axes[idx, 1], data=cds_data, x_name=draw_name, y_name=y_name, chain_prop=chain_prop, combined=combined, rug=rug, kind=kind, legend=legend, trace_kwargs=trace_kwargs, hist_kwargs=hist_kwargs, plot_kwargs=plot_kwargs, fill_kwargs=fill_kwargs, rug_kwargs=rug_kwargs, rank_kwargs=rank_kwargs, ) else: for y_name in cds_var_groups[var_name]: if rug: rug_kwargs["y"] = y_name _plot_chains_bokeh( ax_density=axes[idx, 0], ax_trace=axes[idx, 1], data=cds_data, x_name=draw_name, y_name=y_name, chain_prop=chain_prop, combined=combined, rug=rug, kind=kind, legend=legend, trace_kwargs=trace_kwargs, hist_kwargs=hist_kwargs, plot_kwargs=plot_kwargs, fill_kwargs=fill_kwargs, rug_kwargs=rug_kwargs, rank_kwargs=rank_kwargs, ) for col in (0, 1): _title = Title() _title.text = make_label(var_name, selection) axes[idx, col].title = _title axes[idx, col].y_range = DataRange1d( bounds=backend_config["bounds_y_range"], min_interval=0.1) for _, _, vlines in (j for j in lines if j[0] == var_name and j[1] == selection): if isinstance(vlines, (float, int)): line_values = [vlines] else: line_values = np.atleast_1d(vlines).ravel() for line_value in line_values: vline = Span( location=line_value, dimension="height", line_color="black", line_width=1.5, line_alpha=0.75, ) hline = Span( location=line_value, dimension="width", line_color="black", line_width=1.5, line_alpha=trace_kwargs["alpha"], ) axes[idx, 0].renderers.append(vline) axes[idx, 1].renderers.append(hline) if legend: for col in (0, 1): axes[idx, col].legend.location = "top_left" axes[idx, col].legend.click_policy = "hide" else: for col in (0, 1): if axes[idx, col].legend: axes[idx, col].legend.visible = False if divergences: div_density_kwargs = {} div_density_kwargs.setdefault("size", 14) div_density_kwargs.setdefault("line_color", "red") div_density_kwargs.setdefault("line_width", 2) div_density_kwargs.setdefault("line_alpha", 0.50) div_density_kwargs.setdefault("angle", np.pi / 2) div_trace_kwargs = {} div_trace_kwargs.setdefault("size", 14) div_trace_kwargs.setdefault("line_color", "red") div_trace_kwargs.setdefault("line_width", 2) div_trace_kwargs.setdefault("line_alpha", 0.50) div_trace_kwargs.setdefault("angle", np.pi / 2) div_selection = { k: v for k, v in selection.items() if k in divergence_data.dims } divs = divergence_data.sel(**div_selection).values divs = np.atleast_2d(divs) for chain, chain_divs in enumerate(divs): div_idxs = np.arange(len(chain_divs))[chain_divs] if div_idxs.size > 0: values = value[chain, div_idxs] tmp_cds = ColumnDataSource({"y": values, "x": div_idxs}) if divergences == "top": y_div_trace = value.max() else: y_div_trace = value.min() glyph_density = Dash(x="y", y=0.0, **div_density_kwargs) glyph_trace = Dash(x="x", y=y_div_trace, **div_trace_kwargs) axes[idx, 0].add_glyph(tmp_cds, glyph_density) axes[idx, 1].add_glyph(tmp_cds, glyph_trace) show_layout(axes, show) return axes
def _plot_trace_bokeh( data, var_names=None, coords=None, divergences="bottom", figsize=None, rug=False, lines=None, compact=False, combined=False, legend=False, plot_kwargs=None, fill_kwargs=None, rug_kwargs=None, hist_kwargs=None, trace_kwargs=None, backend_kwargs=None, show=True, ): """Plot distribution (histogram or kernel density estimates) and sampled values. Parameters ---------- data : obj Any object that can be converted to an az.InferenceData object Refer to documentation of az.convert_to_dataset for details var_names : string, or list of strings One or more variables to be plotted. coords : mapping, optional Coordinates of var_names to be plotted. Passed to `Dataset.sel` divergences : {"bottom", "top", None, False} NOT IMPLEMENTED Plot location of divergences on the traceplots. Options are "bottom", "top", or False-y. figsize : figure size tuple If None, size is (12, variables * 2) rug : bool If True adds a rugplot. Defaults to False. Ignored for 2D KDE. Only affects continuous variables. lines : tuple Tuple of (var_name, {'coord': selection}, [line, positions]) to be overplotted as vertical lines on the density and horizontal lines on the trace. compact : bool Plot multidimensional variables in a single plot. combined : bool Flag for combining multiple chains into a single line. If False (default), chains will be plotted separately. legend : bool Add a legend to the figure with the chain color code. plot_kwargs : dict Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables. fill_kwargs : dict Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables. rug_kwargs : dict Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables. hist_kwargs : dict Extra keyword arguments passed to `arviz.plot_dist`. Only affects discrete variables. trace_kwargs : dict Extra keyword arguments passed to `bokeh.plotting.lines` backend_kwargs : dict Extra keyword arguments passed to `bokeh.plotting.figure` show : bool Call `bokeh.plotting.show` for gridded plots `bokeh.layouts.gridplot(axes.tolist())` Returns ------- ndarray axes (bokeh figures) Examples -------- Plot a subset variables .. plot:: :context: close-figs >>> import arviz as az >>> data = az.load_arviz_data('non_centered_eight') >>> coords = {'school': ['Choate', 'Lawrenceville']} >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords) Show all dimensions of multidimensional variables in the same plot .. plot:: :context: close-figs >>> az.plot_trace(data, compact=True) Combine all chains into one distribution .. plot:: :context: close-figs >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, combined=True) Plot reference lines against distribution and trace .. plot:: :context: close-figs >>> lines = (('theta_t',{'school': "Choate"}, [-1]),) >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, lines=lines) """ if divergences: try: divergence_data = convert_to_dataset( data, group="sample_stats").diverging except (ValueError, AttributeError): # No sample_stats, or no `.diverging` divergences = False if coords is None: coords = {} data = get_coords(convert_to_dataset(data, group="posterior"), coords) var_names = _var_names(var_names, data) if divergences: divergence_data = get_coords( divergence_data, {k: v for k, v in coords.items() if k in ("chain", "draw")}) if lines is None: lines = () num_colors = len(data.chain) + 1 if combined else len(data.chain) colors = [ prop for _, prop in zip( range(num_colors), cycle(plt.rcParams["axes.prop_cycle"].by_key()["color"])) ] if compact: skip_dims = set(data.dims) - {"chain", "draw"} else: skip_dims = set() plotters = list( xarray_var_iter(data, var_names=var_names, combined=True, skip_dims=skip_dims)) max_plots = rcParams["plot.max_subplots"] max_plots = len(plotters) if max_plots is None else max_plots if len(plotters) > max_plots: warnings.warn( "rcParams['plot.max_subplots'] ({max_plots}) is smaller than the number " "of variables to plot ({len_plotters}), generating only {max_plots} " "plots".format(max_plots=max_plots, len_plotters=len(plotters)), SyntaxWarning, ) plotters = plotters[:max_plots] if figsize is None: figsize = (12, len(plotters) * 2) if trace_kwargs is None: trace_kwargs = {} trace_kwargs.setdefault("alpha", 0.35) if hist_kwargs is None: hist_kwargs = {} if plot_kwargs is None: plot_kwargs = {} if fill_kwargs is None: fill_kwargs = {} if rug_kwargs is None: rug_kwargs = {} hist_kwargs.setdefault("alpha", 0.35) figsize, _, _, _, linewidth, _ = _scale_fig_size(figsize, 10, rows=len(plotters), cols=2) figsize = int(figsize[0] * 90 // 2), int(figsize[1] * 90 // len(plotters)) trace_kwargs.setdefault("line_width", linewidth) plot_kwargs.setdefault("line_width", linewidth) if backend_kwargs is None: backend_kwargs = dict() backend_kwargs.setdefault( "tools", ",".join([ "pan", "wheel_zoom", "box_zoom", "lasso_select", "poly_select", "undo", "redo", "reset", "save,hover", ]), ) backend_kwargs.setdefault("output_backend", "webgl") backend_kwargs.setdefault("height", figsize[1]) backend_kwargs.setdefault("width", figsize[0]) axes = [] for i in range(len(plotters)): if i != 0: _axes = [ bkp.figure(**backend_kwargs), bkp.figure(x_range=axes[0][1].x_range, **backend_kwargs), ] else: _axes = [ bkp.figure(**backend_kwargs), bkp.figure(**backend_kwargs) ] axes.append(_axes) axes = np.array(axes) cds_data = {} cds_var_groups = {} draw_name = "draw" for var_name, selection, value in list( xarray_var_iter(data, var_names=var_names, combined=True)): if selection: cds_name = "{}_ARVIZ_CDS_SELECTION_{}".format( var_name, "_".join( str(item) for key, value in selection.items() for item in ([key, value] if ( isinstance(value, str) or not isinstance(value, Iterable)) else [key, *value])), ) else: cds_name = var_name if var_name not in cds_var_groups: cds_var_groups[var_name] = [] cds_var_groups[var_name].append(cds_name) for chain_idx, _ in enumerate(data.chain.values): if chain_idx not in cds_data: cds_data[chain_idx] = {} _data = value[chain_idx] cds_data[chain_idx][cds_name] = _data while any(key == draw_name for key in cds_data[0]): draw_name += "w" for chain_idx in cds_data: cds_data[chain_idx][draw_name] = data.draw.values cds_data = { chain_idx: ColumnDataSource(cds) for chain_idx, cds in cds_data.items() } for idx, (var_name, selection, value) in enumerate(plotters): value = np.atleast_2d(value) if len(value.shape) == 2: y_name = (var_name if not selection else "{}_ARVIZ_CDS_SELECTION_{}".format( var_name, "_".join( str(item) for key, value in selection.items() for item in ((key, value) if ( isinstance(value, str) or not isinstance(value, Iterable)) else ( key, *value))), )) if rug: rug_kwargs["y"] = y_name _plot_chains_bokeh( ax_density=axes[idx, 0], ax_trace=axes[idx, 1], data=cds_data, x_name=draw_name, y_name=y_name, colors=colors, combined=combined, rug=rug, legend=legend, trace_kwargs=trace_kwargs, hist_kwargs=hist_kwargs, plot_kwargs=plot_kwargs, fill_kwargs=fill_kwargs, rug_kwargs=rug_kwargs, ) else: for y_name in cds_var_groups[var_name]: if rug: rug_kwargs["y"] = y_name _plot_chains_bokeh( ax_density=axes[idx, 0], ax_trace=axes[idx, 1], data=cds_data, x_name=draw_name, y_name=y_name, colors=colors, combined=combined, rug=rug, legend=legend, trace_kwargs=trace_kwargs, hist_kwargs=hist_kwargs, plot_kwargs=plot_kwargs, fill_kwargs=fill_kwargs, rug_kwargs=rug_kwargs, ) for col in (0, 1): _title = Title() _title.text = make_label(var_name, selection) axes[idx, col].title = _title for _, _, vlines in (j for j in lines if j[0] == var_name and j[1] == selection): if isinstance(vlines, (float, int)): line_values = [vlines] else: line_values = np.atleast_1d(vlines).ravel() for line_value in line_values: vline = Span( location=line_value, dimension="height", line_color="black", line_width=1.5, line_alpha=0.75, ) hline = Span( location=line_value, dimension="width", line_color="black", line_width=1.5, line_alpha=trace_kwargs["alpha"], ) axes[idx, 0].renderers.append(vline) axes[idx, 1].renderers.append(hline) if legend: for col in (0, 1): axes[idx, col].legend.location = "top_left" axes[idx, col].legend.click_policy = "hide" else: for col in (0, 1): if axes[idx, col].legend: axes[idx, col].legend.visible = False if divergences: div_density_kwargs = {} div_density_kwargs.setdefault("size", 14) div_density_kwargs.setdefault("line_color", "red") div_density_kwargs.setdefault("line_width", 2) div_density_kwargs.setdefault("line_alpha", 0.50) div_density_kwargs.setdefault("angle", np.pi / 2) div_trace_kwargs = {} div_trace_kwargs.setdefault("size", 14) div_trace_kwargs.setdefault("line_color", "red") div_trace_kwargs.setdefault("line_width", 2) div_trace_kwargs.setdefault("line_alpha", 0.50) div_trace_kwargs.setdefault("angle", np.pi / 2) div_selection = { k: v for k, v in selection.items() if k in divergence_data.dims } divs = divergence_data.sel(**div_selection).values divs = np.atleast_2d(divs) for chain, chain_divs in enumerate(divs): div_idxs = np.arange(len(chain_divs))[chain_divs] if div_idxs.size > 0: values = value[chain, div_idxs] tmp_cds = ColumnDataSource({"y": values, "x": div_idxs}) if divergences == "top": y_div_trace = value.max() else: y_div_trace = value.min() glyph_density = Dash(x="y", y=0.0, **div_density_kwargs) glyph_trace = Dash(x="x", y=y_div_trace, **div_trace_kwargs) axes[idx, 0].add_glyph(tmp_cds, glyph_density) axes[idx, 1].add_glyph(tmp_cds, glyph_trace) if show: grid = gridplot([list(item) for item in axes], toolbar_location="above") bkp.show(grid) return axes
def plot_autocorr( axes, plotters, max_lag, figsize, rows, cols, line_width, combined, backend_config, backend_kwargs, show, ): """Bokeh autocorrelation plot.""" if backend_config is None: backend_config = {} len_y = plotters[0][2].size backend_config.setdefault("bounds_x_range", (0, len_y)) backend_config = { **backend_kwarg_defaults(("bounds_y_range", "plot.bokeh.bounds_y_range"), ), **backend_config, } if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(("dpi", "plot.bokeh.figure.dpi"), ), **backend_kwargs, } if axes is None: _, axes = _create_axes_grid( len(plotters), rows, cols, figsize=figsize, squeeze=False, sharex=True, sharey=True, backend="bokeh", backend_kwargs=backend_kwargs, ) else: axes = np.atleast_2d(axes) data_range_x = DataRange1d(start=0, end=max_lag, bounds=backend_config["bounds_x_range"], min_interval=5) data_range_y = DataRange1d(start=-1, end=1, bounds=backend_config["bounds_y_range"], min_interval=0.1) for (var_name, selection, x), ax in zip(plotters, (item for item in axes.flatten() if item is not None)): x_prime = x if combined: x_prime = x.flatten() y = autocorr(x_prime) ax.segment( x0=np.arange(len(y)), y0=0, x1=np.arange(len(y)), y1=y, line_width=line_width, line_color="black", ) ax.line([0, 0], [0, max_lag], line_color="steelblue") title = Title() title.text = make_label(var_name, selection) ax.title = title ax.x_range = data_range_x ax.y_range = data_range_y show_layout(axes, show) return axes
def plot(): from pandas_datareader import data import datetime from bokeh.plotting import figure, show, output_file from bokeh.models.annotations import Title from bokeh.embed import components from bokeh.resources import CDN start = datetime.datetime(2020, 5, 18) end = datetime.datetime(2020, 8, 25) df = data.DataReader(name="GOOG", data_source="yahoo", start=start, end=end) #date_increase=df.index[df.Close > df.Open] #date_decrease=df.index[df.Close < df.Open] def inc_dec(c, o): if c > o: value = "Increase" elif c < o: value = "Decrease" else: value = "Equal" return value df["Status"] = [inc_dec(c, o) for c, o in zip(df.Close, df.Open)] df["Middle"] = (df.Close + df.Open) / 2 df["Height"] = abs(df.Close - df.Open) p = figure(x_axis_type='datetime', width=1000, height=300, sizing_mode="scale_width") t = Title() t.text = 'Candlestick Chart' p.title = t p.grid.grid_line_alpha = 0.3 #p.title = "Candlestick Chart" hours_12 = 12 * 60 * 60 * 1000 p.segment(df.index, df.High, df.index, df.Low, color="Black") p.rect(df.index[df.Status == "Increase"], df.Middle[df.Status == "Increase"], hours_12, df.Height[df.Status == "Increase"], fill_color="#CCFFFF", line_color="black") p.rect(df.index[df.Status == "Decrease"], df.Middle[df.Status == "Decrease"], hours_12, df.Height[df.Status == "Decrease"], fill_color="#FF3333", line_color="black") script, div = components(p) cdn_js = CDN.js_files[0] #cdn_css=CDN.css_files return render_template("plot.html", script=script, div=div, cdn_js=cdn_js)
def _plot_violin( ax, plotters, figsize, rows, cols, sharey, kwargs_shade, shade, bw, credible_interval, linewidth, quartiles, show, ): if ax is None: _, ax = _create_axes_grid( len(plotters), rows, cols, sharey=sharey, figsize=figsize, squeeze=False, backend="bokeh", ) ax = np.atleast_1d(ax) for (var_name, selection, x), ax_ in zip(plotters, ax.flatten()): val = x.flatten() if val[0].dtype.kind == "i": cat_hist(val, shade, ax_, **kwargs_shade) else: _violinplot(val, shade, bw, ax_, **kwargs_shade) per = np.percentile(val, [25, 75, 50]) hpd_intervals = hpd(val, credible_interval, multimodal=False) if quartiles: ax_.line([0, 0], per[:2], line_width=linewidth * 3, line_color="black") ax_.line([0, 0], hpd_intervals, line_width=linewidth, line_color="black") ax_.circle(0, per[-1]) _title = Title() _title.text = make_label(var_name, selection) ax_.title = _title ax_.xaxis.major_tick_line_color = None ax_.xaxis.minor_tick_line_color = None ax_.xaxis.major_label_text_font_size = "0pt" if show: grid = gridplot([list(item) for item in ax], toolbar_location="above") bkp.show(grid) return ax
def _create_task_panels(self, data_frame): panels = {} top_left_x_range = None for i, t in enumerate(self.env.task_list): panels[t.name] = {} # Panel 1: Setpoint and command panel pCtrl = figure(plot_width=800, plot_height=300) ctrl_legend = [] # Setting the second y axis range name and range pCtrl.extra_y_ranges = { t.name + '_cmd': Range1d(start=-1, end=1) } # this should query the action space # Adding the second axis to the plot. pCtrl.add_layout( LinearAxis(y_range_name=t.name + '_cmd', axis_label=t.name + '_cmd [norm.]'), 'right') try: name = self.panel_contents[ t.name]['panel1']['action_prop'].get_legal_name( ) #maybe there are more entries in the future action_Line = pCtrl.line(data_frame.index * self.step_time, data_frame[name], line_width=1, y_range_name=t.name + '_cmd', color=Viridis4[1]) ctrl_legend.append((t.name + ' Cmd.', [action_Line])) except KeyError: #we have no action prop, only setpoints to be evaluated pass try: name = self.panel_contents[ t.name]['panel1']['current_value_prop'].get_legal_name() current_value_line = pCtrl.line(data_frame.index * self.step_time, data_frame[name], line_width=2, color=Viridis4[0]) ctrl_legend.append((name, [current_value_line])) name = self.panel_contents[ t.name]['panel1']['setpoint_value_prop'].get_legal_name() setpoint_value_line = pCtrl.line(data_frame.index * self.step_time, data_frame[name], line_width=2, color=Viridis4[3]) ctrl_legend.append((name, [setpoint_value_line])) except KeyError: #there is no setpoint to be displayed, only actuations pass ctrl_lg = Legend(items=ctrl_legend, location=(0, 10), glyph_width=25, label_width=190) ctrl_lg.click_policy = "hide" pCtrl.add_layout(ctrl_lg, 'right') pCtrl.toolbar.active_scroll = pCtrl.toolbar.tools[ 1] #this selects the WheelZoomTool instance # Add the title... tCtrl = Title() tCtrl.text = 'Controlled Value over Time' pCtrl.title = tCtrl pCtrl.xaxis.axis_label = 'timestep [s]' pCtrl.yaxis[0].axis_label = 'Controlled Value' if not top_left_x_range: top_left_x_range = pCtrl.x_range else: pCtrl.x_range = top_left_x_range panels[t.name].update({'panel1': pCtrl}) #Panel 2: Rewards and reward components pRwd = figure(plot_width=1057, plot_height=300, x_range=top_left_x_range) rwd_cmp_lines = [] reward_legend = [] cmp_names = self.panel_contents[ t.name]['panel2']['reward_component_names'] for idx, rwd_component in enumerate(cmp_names): rwd_cmp_lines.append( pRwd.line(data_frame.index * self.step_time, data_frame[rwd_component], line_width=2, color=Viridis7[idx % 6])) reward_legend.append((rwd_component, [rwd_cmp_lines[-1]])) name = self.panel_contents[ t.name]['panel2']['reward_prop'].get_legal_name() reward_line = pRwd.line(data_frame.index * self.step_time, data_frame[name], line_width=2, color=Viridis7[6]) reward_legend.append((name, [reward_line])) reward_lg = Legend(items=reward_legend, location=(48, 10), glyph_width=25, label_width=190) reward_lg.click_policy = "hide" pRwd.add_layout(reward_lg, 'right') pRwd.toolbar.active_scroll = pRwd.toolbar.tools[ 1] #this selects the WheelZoomTool instance #Add the title tReward = Title() tReward.text = f'{t.name}: last Reward over {data_frame[name].size-1} Timesteps (∑ = {data_frame[name].sum():.2f})' pRwd.title = tReward pRwd.xaxis.axis_label = 'timestep [s]' pRwd.yaxis[0].axis_label = 'actual Reward [norm.]' panels[t.name].update({'panel2': pRwd}) #Panel 3: Presented Observations pState = figure(plot_width=1057, plot_height=300, x_range=top_left_x_range) # Setting the second y axis range name and range norm_state_extents = 10 pState.extra_y_ranges = { "normalized_data": Range1d(start=-norm_state_extents, end=norm_state_extents) } # Adding the second axis to the plot. pState.add_layout( LinearAxis(y_range_name="normalized_data", axis_label="normalized data"), 'right') state_lines = [] state_legend = [] normalized_state_lines = [] obs_props_names = [ o_prp.get_legal_name() for o_prp in self.panel_contents[t.name]['panel3']['obs_props'] ] for idx, state_name in enumerate(obs_props_names): if (data_frame[state_name].max() <= norm_state_extents and data_frame[state_name].min() >= -norm_state_extents): normalized_state_lines.append( pState.line(data_frame.index * self.step_time, data_frame[state_name], line_width=2, y_range_name="normalized_data", color=Inferno7[idx % 7], visible=False)) state_legend.append( ("norm_" + state_name, [normalized_state_lines[-1]])) else: state_lines.append( pState.line(data_frame.index * self.step_time, data_frame[state_name], line_width=2, color=Inferno7[idx % 7], visible=False)) state_legend.append((state_name, [state_lines[-1]])) pState.y_range.renderers = state_lines pState.extra_y_ranges.renderers = normalized_state_lines #this does not quite work: https://stackoverflow.com/questions/48631530/bokeh-twin-axes-with-datarange1d-not-well-scaling lg_state = Legend(items=state_legend, location=(0, 10), glyph_width=25, label_width=190) lg_state.click_policy = "hide" pState.add_layout(lg_state, 'right') pState.toolbar.active_scroll = pState.toolbar.tools[ 1] #this selects the WheelZoomTool instance #Add the title tState = Title() tState.text = 'Actual Observation presented to Agent' pState.title = tState pState.xaxis.axis_label = 'timestep [s]' pState.yaxis[0].axis_label = 'state data' panels[t.name].update({'panel3': pState}) return panels
def _show_graph(self, data_frame): #create the plot panels for the Agent_Tasks panels = self._create_task_panels(data_frame) top_left_x_range = panels[list(panels.keys())[0]]['panel1'].x_range #Altitude over ground pAltitude = figure(plot_width=800, plot_height=300, x_range=top_left_x_range) alti_legend = [] # Setting the second y axis range name and range pAltitude.extra_y_ranges = {"speed": Range1d(50, 120)} # Adding the second axis to the plot. pAltitude.add_layout( LinearAxis(y_range_name="speed", axis_label="IAS, TAS [Knots]"), 'right') altitudeLine = pAltitude.line(data_frame.index * self.step_time, data_frame['position_h_sl_ft'], line_width=2, color=Viridis4[2]) alti_legend.append(("Altitude [ftsl]", [altitudeLine])) kiasLine = pAltitude.line(data_frame.index * self.step_time, data_frame['velocities_vc_kts'], line_width=2, y_range_name="speed", color=Viridis4[1]) alti_legend.append(("Indicated Airspeed [KIAS]", [kiasLine])) tasLine = pAltitude.line(data_frame.index * self.step_time, data_frame['velocities_vtrue_kts'], line_width=2, y_range_name="speed", color=Viridis4[0]) alti_legend.append(("True Airspeed [KAS]", [tasLine])) pAltitude.extra_y_ranges.renderers = [ kiasLine, tasLine ] #this does not quite work: https://stackoverflow.com/questions/48631530/bokeh-twin-axes-with-datarange1d-not-well-scaling pAltitude.y_range.renderers = [altitudeLine] lg_alti = Legend(items=alti_legend, location=(0, 10), glyph_width=25, label_width=190) lg_alti.click_policy = "hide" pAltitude.add_layout(lg_alti, 'right') tAlti = Title() tAlti.text = 'Altitude and Speed [IAS, TAS] over Timesteps' pAltitude.title = tAlti pAltitude.xaxis.axis_label = 'timestep [s]' pAltitude.yaxis[0].axis_label = 'Altitude [ftsl]' pAltitude.legend.location = "center_right" pSideslip = figure(plot_width=800, plot_height=300, x_range=top_left_x_range) slip_legend = [] slip_skid_line = pSideslip.line(data_frame.index * self.step_time, data_frame['aero_beta_deg'], line_width=2, color=Viridis4[2]) slip_legend.append(("Sideslip", [slip_skid_line])) pSideslip.y_range.renderers = [slip_skid_line] lg_slip = Legend(items=slip_legend, location=(0, 10), glyph_width=25, label_width=190) lg_slip.click_policy = "hide" pSideslip.add_layout(lg_slip, 'right') tSlip = Title() tSlip.text = 'Sideslip' pSideslip.title = tSlip pSideslip.xaxis.axis_label = 'timestep [s]' pSideslip.yaxis[0].axis_label = 'Sideslip [deg]' pSideslip.legend.location = "center_right" #activate the zooming on all plots #this is not nice, but this not either: https://stackoverflow.com/questions/49282688/how-do-i-set-default-active-tools-for-a-bokeh-gridplot pAltitude.toolbar.active_scroll = pAltitude.toolbar.tools[ 1] #this selects the WheelZoomTool instance pSideslip.toolbar.active_scroll = pSideslip.toolbar.tools[ 1] #this selects the WheelZoomTool instance reset_output() # if self.env.meta_dict['model_type'] == 'trained': # discriminator = self.env.meta_dict['model_base_name']+"_%+.2f" % (data_frame['reward'].sum()) # self.env.meta_dict['model_discriminator'] = discriminator # else: # discriminator = self.env.meta_dict['model_discriminator'] ts = time.time() overshoot_frames_per_task = self._analyze_overshoot(data_frame) overshoot_divs = [ Div(text=ovs_fr.round(3).to_html(), width=600) for ovs_fr in overshoot_frames_per_task ] print("Overshoot analysis done in %.2f sec" % (time.time() - ts)) ts = time.time() settlement_times_per_task = self._analyze_settle_times(data_frame) settlement_divs = [ Div(text=settle_fr.round(3).to_html(), width=600) for settle_fr in settlement_times_per_task ] print("Settlement analysis done in %.2f sec" % (time.time() - ts)) panel_grid = [] panel_grid.append([ Div(text='<h3>' + t.name + '</h3>', id='div_' + t.name) for t in self.env.task_list ]) # to switch on and off the statistics panels, this is unfortuntely the best, I could achive # https://stackoverflow.com/a/52416676/2682209 cols = [] checkbox = CheckboxGroup( labels=["show stats"], active=[], width=100) #checkbox is added to header_col later on for i, t in enumerate(self.env.task_list): # overshoot_stat = overshoot_divs[i] c = column(Div()) #empty for the beginning cols.append(c) callback = CustomJS(args=dict(overshoot_divs=overshoot_divs, settlement_divs=settlement_divs, cols=cols, checkbox=checkbox), code=""" for (var j = 0; j < cols.length; j++) { console.log('col', j) const children = [] for (const i of checkbox.active) { console.log('active', i) children.push(overshoot_divs[j]) children.push(settlement_divs[j]) } console.log('children', children) cols[j].children = children } """) checkbox.js_on_change('active', callback) # show_stats_btn = [Div(text=""" # <button onclick="display_event(%s)">Try it</button> # """ %t.name for t in self.env.task_list] # for t, b in zip(self.env.task_list, show_stats_btn): # b.tags = ['id', 'btn_'+t.name] # panel_grid.append(show_stats_btn) # [b.js_on_event(events.ButtonClick, display_event(b, t.name)) for t, b in zip(self.env.task_list, show_stats_btn)] # panel_grid.append(chkbxs) panel_grid.append(cols) panel_grid_t = [[ panels[name]['panel1'], panels[name]['panel2'], panels[name]['panel3'] ] for name in self.task_names] [panel_grid.append(fig) for fig in list(zip(*panel_grid_t))] # add the additional plots panel_grid.append([pAltitude, pSideslip]) panel_grid_plot = gridplot(panel_grid, toolbar_location='right', sizing_mode='stretch_width') #for string formatting look here: https://pyformat.info/ titleString = '' if 'experiment_name' in self.env.meta_dict: titleString += "{}: ".format(self.env.meta_dict['experiment_name']) titleString += "Run Date: {}; ".format( datetime.datetime.now().strftime("%c")) if 'train_step' in self.env.meta_dict: titleString += "Training Step: {}; ".format( self.env.meta_dict['train_step']) if 'episode_number' in self.env.meta_dict: titleString += "Episode: {}; ".format( self.env.meta_dict['episode_number']) if 'csv_line_nr' in self.env.meta_dict: titleString += "Env in CSV line: {}; ".format( self.env.meta_dict['csv_line_nr']) # titleString += "Total Reward: {:.2f}; ".format(data_frame['reward'].sum()) # titleString += "Model Discriminator: {};".format(self.env.meta_dict['model_discriminator']) header_col = column( Div(text="<h1>" + self.env.unwrapped.spec.id + (" - " + self.env.meta_dict['env_info']) if 'env_info' in self.meta_dict else "" + "</h1>"), row(Div(text="<h2>" + titleString + "</h2>", width=1200), checkbox)) webpage = gridplot([[header_col], [panel_grid_plot]], toolbar_location=None, sizing_mode='stretch_width') base_filename = 'Run_' + '_'.join([tsk.name for tsk in self.task_list]) html_output_name = os.path.join(self.save_path, 'plots', base_filename + '_latest.html') os.makedirs(os.path.dirname(html_output_name), exist_ok=True) if self.showNextPlotFlag: output_file( html_output_name, mode='inline' ) #mode='absolute') #use mode='absolute' to make it work offline with the js and css installed in the bokeh package locally if self.firstRun: show(webpage) #opens up a new browser window self.firstRun = False else: save( webpage ) #just updates the HTML; Manual F5 in browser required :-(, (There must be a way to push...) if self.exportNextPlotFlag and self.save_path: #build the filename including the individual rewards task_rewards = [ self.reward_variables[i].get_legal_name() for i in range(len(self.task_list)) ] task_names_with_rewards = [ t.name + '_' + f'{data_frame[task_rewards[i]].sum():.2f}' for i, t in enumerate(self.task_list) ] name_with_rewards = 'Run_' + '_'.join( task_names_with_rewards) + 'time_{}'.format( datetime.datetime.now().strftime("%H-%M-%S")) base_filename = os.path.join( self.save_path, 'plots', name_with_rewards ) # 'glideAngle_Elevator_Reward_{:.2f}_time_{}'.format(data_frame['reward'].sum(), datetime.datetime.now().strftime("%H-%M-%S"))) if self.showNextPlotFlag: #we keep the html as well for easy exploration shutil.copyfile(html_output_name, base_filename + '.html') def export(webpage): png_filename = base_filename + '.png' webpage.width = 1800 #set the width of the page instead of passing a width parameter to the export; https://stackoverflow.com/a/61563173/2682209 export_png( webpage, filename=png_filename ) #TODO: the width parameter is ignored in bokeh/io/export.py get_layout_html() as webpage isn't a Plot export( gridplot([[header_col], [panel_grid_plot]], toolbar_location=None)) self.showNextPlotFlag = False #only show the plot once and then reset self.exportNextPlotFlag = False print("Output Plot generated: " + titleString)
def plot_ess( ax, plotters, xdata, ess_tail_dataset, mean_ess, sd_ess, idata, data, text_x, text_va, kind, extra_methods, rows, cols, figsize, kwargs, extra_kwargs, text_kwargs, _linewidth, _markersize, n_samples, relative, min_ess, xt_labelsize, titlesize, ax_labelsize, ylabel, rug, rug_kind, rug_kwargs, hline_kwargs, backend_kwargs, show, ): """Bokeh essplot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(), **backend_kwargs, } if ax is None: _, ax = _create_axes_grid( len(plotters), rows, cols, figsize=figsize, squeeze=False, constrained_layout=True, backend="bokeh", backend_kwargs=backend_kwargs, ) else: ax = np.atleast_2d(ax) for (var_name, selection, x), ax_ in zip(plotters, (item for item in ax.flatten() if item is not None)): ax_.circle(np.asarray(xdata), np.asarray(x), size=6) if kind == "evolution": ax_.line(np.asarray(xdata), np.asarray(x), legend_label="bulk") ess_tail = ess_tail_dataset[var_name].sel(**selection) ax_.line(np.asarray(xdata), np.asarray(ess_tail), color="orange", legend_label="tail") ax_.circle(np.asarray(xdata), np.asarray(ess_tail), size=6, color="orange") elif rug: if rug_kwargs is None: rug_kwargs = {} if not hasattr(idata, "sample_stats"): raise ValueError( "InferenceData object must contain sample_stats for rug plot" ) if not hasattr(idata.sample_stats, rug_kind): raise ValueError( "InferenceData does not contain {} data".format(rug_kind)) rug_kwargs.setdefault("space", 0.1) _rug_kwargs = {} _rug_kwargs.setdefault("size", 8) _rug_kwargs.setdefault("line_color", rug_kwargs.get("line_color", "black")) _rug_kwargs.setdefault("line_width", 1) _rug_kwargs.setdefault("line_alpha", 0.35) _rug_kwargs.setdefault("angle", np.pi / 2) values = data[var_name].sel(**selection).values.flatten() mask = idata.sample_stats[rug_kind].values.flatten() values = rankdata(values)[mask] rug_space = np.max(x) * rug_kwargs.pop("space") rug_x, rug_y = values / (len(mask) - 1), np.zeros_like(values) - rug_space glyph = Dash(x="rug_x", y="rug_y", **_rug_kwargs) cds_rug = ColumnDataSource({ "rug_x": np.asarray(rug_x), "rug_y": np.asarray(rug_y) }) ax_.add_glyph(cds_rug, glyph) hline = Span( location=0, dimension="width", line_color="black", line_width=_linewidth, line_alpha=0.7, ) ax_.renderers.append(hline) if extra_methods: mean_ess_i = mean_ess[var_name].sel(**selection).values.item() sd_ess_i = sd_ess[var_name].sel(**selection).values.item() hline = Span( location=mean_ess_i, dimension="width", line_color="black", line_width=2, line_dash="dashed", line_alpha=1.0, ) ax_.renderers.append(hline) hline = Span( location=sd_ess_i, dimension="width", line_color="black", line_width=1, line_dash="dashed", line_alpha=1.0, ) ax_.renderers.append(hline) hline = Span( location=400 / n_samples if relative else min_ess, dimension="width", line_color="red", line_width=3, line_dash="dashed", line_alpha=1.0, ) ax_.renderers.append(hline) title = Title() title.text = make_label(var_name, selection) ax_.title = title ax_.xaxis.axis_label = "Total number of draws" if kind == "evolution" else "Quantile" ax_.yaxis.axis_label = ylabel.format( "Relative ESS" if relative else "ESS") if backend_show(show): grid = gridplot(ax.tolist(), toolbar_location="above") bkp.show(grid) return ax
def plot_actions(folder, memory, long_actions, short_actions, title='agent_actions', trades=None, save_only=True): """ Plot the financial positions of the agent in respect to the time series of the exchange rate. """ output_file(folder + '\\' + title + '.html') p = figure(plot_width=1000, plot_height=600) data_len = len(memory) x_axis = [x[0] for x in memory] y_axis = [x[1] for x in memory] x_axis_l = [x[0] for x in long_actions] y_axis_l = [y[1] for y in long_actions] x_axis_s = [x[0] for x in short_actions] y_axis_s = [y[1] for y in short_actions] p.line(x_axis, y_axis, line_width=2) p.scatter(x_axis_l, y_axis_l, marker="triangle", line_color="#6666ee", fill_color="#00FF00", fill_alpha=0.5, size=16) p.scatter(x_axis_s, y_axis_s, marker="inverted_triangle", line_color="#ee6666", fill_color="#FF0000", fill_alpha=0.5, size=16) if trades is not None: # Plot the time steps where a trade was made as well (long<->short) x_axis_tr = [x[0] for x in trades] y_axis_tr = [y[1] for y in trades] p.scatter(x_axis_tr, y_axis_tr, marker="diamond", line_color="#FFA500", fill_color="#FFFF00", fill_alpha=0.5, size=16) p.xaxis.axis_label = 'Epochs' p.yaxis.axis_label = 'Reward' t = Title() t.text = 'Agent Actions' p.title = t if save_only: save(p) else: show(p)
def plot_posterior( ax, length_plotters, rows, cols, figsize, plotters, bw, circular, bins, kind, point_estimate, round_to, hdi_prob, multimodal, skipna, textsize, ref_val, rope, ref_val_color, rope_color, labeller, kwargs, backend_kwargs, show, ): """Bokeh posterior plot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults( ("dpi", "plot.bokeh.figure.dpi"), ), **backend_kwargs, } (figsize, ax_labelsize, *_, linewidth, _) = _scale_fig_size(figsize, textsize, rows, cols) if ax is None: ax = create_axes_grid( length_plotters, rows, cols, figsize=figsize, backend_kwargs=backend_kwargs, ) else: ax = np.atleast_2d(ax) idx = 0 for (var_name, selection, isel, x), ax_ in zip( plotters, (item for item in ax.flatten() if item is not None) ): _plot_posterior_op( idx, x.flatten(), var_name, selection, ax=ax_, bw=bw, circular=circular, bins=bins, kind=kind, point_estimate=point_estimate, round_to=round_to, hdi_prob=hdi_prob, multimodal=multimodal, skipna=skipna, linewidth=linewidth, ref_val=ref_val, rope=rope, ref_val_color=ref_val_color, rope_color=rope_color, ax_labelsize=ax_labelsize, **kwargs, ) idx += 1 _title = Title() _title.text = labeller.make_label_vert(var_name, selection, isel) ax_.title = _title show_layout(ax, show) return ax
def _plot_trace_bokeh( data, var_names=None, coords=None, divergences="bottom", figsize=None, textsize=None, lines=None, compact=False, combined=False, legend=False, plot_kwargs=None, fill_kwargs=None, rug_kwargs=None, hist_kwargs=None, trace_kwargs=None, backend_kwargs=None, show=True, ): """Plot distribution (histogram or kernel density estimates) and sampled values. NOTE: EXPERIMENTAL CODE Not implemented: If `divergences` data is available in `sample_stats`, will plot the location of divergences as dashed vertical lines. Parameters ---------- data : obj Any object that can be converted to an az.InferenceData object Refer to documentation of az.convert_to_dataset for details var_names : string, or list of strings One or more variables to be plotted. coords : mapping, optional Coordinates of var_names to be plotted. Passed to `Dataset.sel` divergences : {"bottom", "top", None, False} NOT IMPLEMENTED Plot location of divergences on the traceplots. Options are "bottom", "top", or False-y. figsize : figure size tuple If None, size is (12, variables * 2) textsize: float Text size scaling factor for labels, titles and lines. If None it will be autoscaled based on figsize. lines : tuple Tuple of (var_name, {'coord': selection}, [line, positions]) to be overplotted as vertical lines on the density and horizontal lines on the trace. compact : bool Plot multidimensional variables in a single plot. combined : bool Flag for combining multiple chains into a single line. If False (default), chains will be plotted separately. legend : bool Add a legend to the figure with the chain color code. plot_kwargs : dict Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables. fill_kwargs : dict Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables. rug_kwargs : dict Extra keyword arguments passed to `arviz.plot_dist`. Only affects continuous variables. hist_kwargs : dict Extra keyword arguments passed to `arviz.plot_dist`. Only affects discrete variables. trace_kwargs : dict Extra keyword arguments passed to `bokeh.plotting.lines` backend_kwargs : dict Extra keyword arguments passed to `bokeh.plotting.figure` show : bool Call `bokeh.plotting.show` for gridded plots `bokeh.layouts.gridplot(axes.tolist())` Returns ------- ndarray axes (bokeh figures) Examples -------- Plot a subset variables .. plot:: :context: close-figs >>> import arviz as az >>> data = az.load_arviz_data('non_centered_eight') >>> coords = {'school': ['Choate', 'Lawrenceville']} >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords) Show all dimensions of multidimensional variables in the same plot .. plot:: :context: close-figs >>> az.plot_trace(data, compact=True) Combine all chains into one distribution .. plot:: :context: close-figs >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, combined=True) Plot reference lines against distribution and trace .. plot:: :context: close-figs >>> lines = (('theta_t',{'school': "Choate"}, [-1]),) >>> az.plot_trace(data, var_names=('theta_t', 'theta'), coords=coords, lines=lines) """ if divergences: try: divergence_data = convert_to_dataset(data, group="sample_stats").diverging except (ValueError, AttributeError): # No sample_stats, or no `.diverging` divergences = False if coords is None: coords = {} data = get_coords(convert_to_dataset(data, group="posterior"), coords) var_names = _var_names(var_names, data) if divergences: divergence_data = get_coords( divergence_data, {k: v for k, v in coords.items() if k in ("chain", "draw")} ) if lines is None: lines = () num_colors = len(data.chain) + 1 if combined else len(data.chain) colors = [ prop for _, prop in zip( range(num_colors), cycle(plt.rcParams["axes.prop_cycle"].by_key()["color"]) ) ] if compact: skip_dims = set(data.dims) - {"chain", "draw"} else: skip_dims = set() plotters = list(xarray_var_iter(data, var_names=var_names, combined=True, skip_dims=skip_dims)) max_plots = rcParams["plot.max_subplots"] max_plots = len(plotters) if max_plots is None else max_plots if len(plotters) > max_plots: warnings.warn( "rcParams['plot.max_subplots'] ({max_plots}) is smaller than the number " "of variables to plot ({len_plotters}), generating only {max_plots} " "plots".format(max_plots=max_plots, len_plotters=len(plotters)), SyntaxWarning, ) plotters = plotters[:max_plots] if figsize is None: figsize = (12, len(plotters) * 2) if trace_kwargs is None: trace_kwargs = {} trace_kwargs.setdefault("alpha", 0.35) if hist_kwargs is None: hist_kwargs = {} if plot_kwargs is None: plot_kwargs = {} if fill_kwargs is None: fill_kwargs = {} if rug_kwargs is None: rug_kwargs = {} hist_kwargs.setdefault("alpha", 0.35) figsize, _, titlesize, xt_labelsize, linewidth, _ = _scale_fig_size( figsize, textsize, rows=len(plotters), cols=2 ) figsize = int(figsize[0] * 90 // 2), int(figsize[1] * 90 // len(plotters)) trace_kwargs.setdefault("line_width", linewidth) plot_kwargs.setdefault("line_width", linewidth) if backend_kwargs is None: backend_kwargs = dict() backend_kwargs.setdefault( "tools", ("pan,wheel_zoom,box_zoom," "lasso_select,poly_select," "undo,redo,reset,save,hover"), ) backend_kwargs.setdefault("output_backend", "webgl") backend_kwargs.setdefault("height", figsize[1]) backend_kwargs.setdefault("width", figsize[0]) axes = [] for i in range(len(plotters)): if i != 0: _axes = [ bkp.figure(**backend_kwargs), bkp.figure(x_range=axes[0][1].x_range, **backend_kwargs), ] else: _axes = [bkp.figure(**backend_kwargs), bkp.figure(**backend_kwargs)] axes.append(_axes) axes = np.array(axes) # THIS IS BROKEN --> USE xarray_sel_iter cds_data = {} draw_name = "draw" for var_name, _, value in plotters: for chain_idx, _ in enumerate(data.chain.values): if chain_idx not in cds_data: cds_data[chain_idx] = {} cds_data[chain_idx][var_name] = data[var_name][chain_idx].values while any(key == draw_name for key in cds_data[0]): draw_name += "w" for chain_idx in cds_data: cds_data[chain_idx][draw_name] = data.draw.values cds_data = {chain_idx: ColumnDataSource(cds) for chain_idx, cds in cds_data.items()} for idx, (var_name, selection, value) in enumerate(plotters): value = np.atleast_2d(value) if len(value.shape) == 2: _plot_chains_bokeh( axes[idx, 0], axes[idx, 1], cds_data, draw_name, var_name, colors, combined, legend, xt_labelsize, trace_kwargs, hist_kwargs, plot_kwargs, fill_kwargs, rug_kwargs, ) else: value = value.reshape((value.shape[0], value.shape[1], -1)) for sub_idx in range(value.shape[2]): _plot_chains_bokeh( axes[idx, 0], axes[idx, 1], cds_data, draw_name, var_name, colors, combined, legend, xt_labelsize, trace_kwargs, hist_kwargs, plot_kwargs, fill_kwargs, rug_kwargs, ) for col in (0, 1): _title = Title() _title.text = make_label(var_name, selection) axes[idx, col].title = _title for _, _, vlines in (j for j in lines if j[0] == var_name and j[1] == selection): if isinstance(vlines, (float, int)): line_values = [vlines] else: line_values = np.atleast_1d(vlines).ravel() for line_value in line_values: vline = Span( location=line_value, dimension="height", line_color="black", line_width=1.5, line_alpha=0.75, ) hline = Span( location=line_value, dimension="width", line_color="black", line_width=1.5, line_alpha=trace_kwargs["alpha"], ) axes[idx, 0].renderers.append(vline) axes[idx, 1].renderers.append(hline) if legend: for col in (0, 1): axes[idx, col].legend.location = "top_left" axes[idx, col].legend.click_policy = "hide" else: for col in (0, 1): axes[idx, col].legend.visible = False if show: grid = gridplot([list(item) for item in axes], toolbar_location="above") bkp.show(grid) return axes
def plot_violin( ax, plotters, figsize, rows, cols, sharex, sharey, shade_kwargs, shade, rug, rug_kwargs, bw, textsize, circular, hdi_prob, quartiles, backend_kwargs, show, ): """Bokeh violin plot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(("dpi", "plot.bokeh.figure.dpi"), ), **backend_kwargs, } (figsize, *_, linewidth, _) = _scale_fig_size(figsize, textsize, rows, cols) shade_kwargs = {} if shade_kwargs is None else shade_kwargs rug_kwargs = {} if rug_kwargs is None else rug_kwargs rug_kwargs.setdefault("fill_alpha", 0.1) rug_kwargs.setdefault("line_alpha", 0.1) if ax is None: ax = create_axes_grid( len(plotters), rows, cols, sharex=sharex, sharey=sharey, figsize=figsize, backend_kwargs=backend_kwargs, ) else: ax = np.atleast_2d(ax) for (var_name, selection, x), ax_ in zip(plotters, (item for item in ax.flatten() if item is not None)): val = x.flatten() if val[0].dtype.kind == "i": dens = cat_hist(val, rug, shade, ax_, **shade_kwargs) else: dens = _violinplot(val, rug, shade, bw, circular, ax_, **shade_kwargs) if rug: rug_x = -np.abs( np.random.normal(scale=max(dens) / 3.5, size=len(val))) ax_.scatter(rug_x, val, **rug_kwargs) per = np.nanpercentile(val, [25, 75, 50]) hdi_probs = hdi(val, hdi_prob, multimodal=False, skipna=True) if quartiles: ax_.line([0, 0], per[:2], line_width=linewidth * 3, line_color="black", line_cap="round") ax_.line([0, 0], hdi_probs, line_width=linewidth, line_color="black", line_cap="round") ax_.circle( 0, per[-1], line_color="white", fill_color="white", size=linewidth * 1.5, line_width=linewidth, ) _title = Title() _title.align = "center" _title.text = make_label(var_name, selection) ax_.title = _title ax_.xaxis.major_tick_line_color = None ax_.xaxis.minor_tick_line_color = None ax_.xaxis.major_label_text_font_size = "0pt" show_layout(ax, show) return ax
def make_block_example_grid(aoi_gdf, total_height, total_width, block_list, add_reblock=False, region=None): ''' Start by assuming a 2x2 grid of examples ''' if add_reblock: assert region is not None, "If adding reblocking must also provide region, i.e. 'Africa' " # Add other figs r = 2 c = 2 height = total_height // r width = total_width // c flat_l = [] for i, block in enumerate(block_list): cur_r = i // r cur_c = i % c print("Plotting block {} index {} at ({},{})".format( block, i, cur_r, cur_c)) is_block = aoi_gdf['block_id'] == block cur_gdf = aoi_gdf.loc[is_block] cur_density = cur_gdf['bldg_density'].iloc[0] cur_complexity = cur_gdf['complexity'].iloc[0] cur_count = cur_gdf['bldg_count'].iloc[0] #fig = make_bokeh(cur_gdf, plot_height=height, plot_width=width, bldg_alpha=1.0) fig, new_road_length = make_bokeh(cur_gdf, plot_height=height, plot_width=width, bldg_alpha=1.0, add_reblock=add_reblock, region=region) t = Title() if add_reblock: if new_road_length is None: new_road_length = "???" t.text = "Complexity = {} New road len (m) = {}".format( cur_complexity, new_road_length) else: t.text = "Complexity = {} New road len (m) = {:,}".format( cur_complexity, new_road_length) else: t.text = "Complexity = {} Bldg. density = {}% Bldg. count = {:,}".format( cur_complexity, np.round(cur_density * 100), int(cur_count)) fig.title = t fig.xaxis.visible = False fig.yaxis.visible = False fig.title.text_color = 'black' # Add the plot to the below flat_l.append(fig) return flat_l
def color_plot_bokeh(source, TOOLS, uniformity_method): """ NAME: color_plot PURPOSE: Given result of dot product and cluster, plot all possible 2 dimensional projection scatter plot with color corresponding to dot product values. Save all the graph in the corresponding folder. INPUT: source = dictionary-like data struction in Bokeh to update selected values in real-time TOOLS = list of tools used in bokeh plots uniformity method = dot product/projection, projection refers to fractional length OUTPUT: None HISTORY: 2018-07-30 - Written - Michael Poon """ # Go through all combinations of axis projection and plot them counter = 0 all_proj = [None] * 16 for i in range(6): for j in range(i + 1, 6): color_plot_ij_bokeh(source, TOOLS, i, j, all_proj, counter, uniformity_method) counter += 1 # Create frequency histogram if uniformity_method == 'projection': all_proj[15] = figure(tools=TOOLS, plot_width=350, plot_height=300) hist, edges = np.histogram(result, bins='auto', density=True, range=(0, 1)) all_proj[15].quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:]) all_proj[15].xaxis.axis_label = 'Fractional Length of Projection' all_proj[15].yaxis.axis_label = 'Frequency' t = Title() t.text = 'Fractional Length Frequency Histogram' all_proj[15].title = t elif uniformity_method == 'dot product': all_proj[15] = figure(tools=TOOLS, plot_width=350, plot_height=300) hist, edges = np.histogram(result, bins='auto', density=True, range=(0, 1)) all_proj[15].quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:]) all_proj[15].xaxis.axis_label = 'Maximum Absolute Dot Product' all_proj[15].yaxis.axis_label = 'Frequency' t = Title() t.text = 'Dot Product Frequency Histogram' all_proj[15].title = t # Adding titles and adjusting graph spacing t1 = Title() t1.text = 'Position Space Projections' all_proj[0].title = t1 t2 = Title() t2.text = 'Velocity Space Projections' all_proj[12].title = t2 t3 = Title() t3.text = 'Position-Velocity Space Projections' all_proj[6].title = t3 t4 = Title() if uniformity_method == "dot product": t4.text = "Maximum Dot Product" else: t4.text = "Fractional Length of Proj." all_proj[2].title = t4 all_proj[2].title.text_font_size = "14pt" # add button to show average dot product/projection if uniformity_method == "dot product": button = Button(label='Dot Product Method', button_type='warning', width=350) else: button = Button(label='Projection Method', button_type='warning', width=350) button.callback = CustomJS(args=dict(source=source), code=""" var inds = source.selected['1d'].indices; var data = source.data; var selected_dp = 0.; var total_dp = 0.; if (inds.length != 0) { for (i = 0; i < inds.length; i++) { selected_dp += data['result'][inds[i]]; } window.alert(inds.length + " of " + data['result'].length + " points chosen. Average Result = " + (selected_dp/inds.length).toFixed(2)); } else { for (i = 0; i < data['result'].length; i++) { total_dp += data['result'][i]; } window.alert("No points chosen. Average Result (of all points) = " + (total_dp/data['result'].length).toFixed(2)); } """) show( gridplot([[all_proj[0], button, all_proj[2], all_proj[6], all_proj[9]], [ all_proj[1], all_proj[5], all_proj[3], all_proj[7], all_proj[10] ], [all_proj[12], None, all_proj[4], all_proj[8], all_proj[11]], [all_proj[13], all_proj[14], all_proj[15], None, None]])) # Show twice to compare when selecting regions show( gridplot([[all_proj[0], button, all_proj[2], all_proj[6], all_proj[9]], [ all_proj[1], all_proj[5], all_proj[3], all_proj[7], all_proj[10] ], [all_proj[12], None, all_proj[4], all_proj[8], all_proj[11]], [all_proj[13], all_proj[14], all_proj[15], None, None]]))
def forestplot(self, hdi_prob, quartiles, linewidth, markersize, ax, rope): """Draw forestplot for each plotter. Parameters ---------- hdi_prob : float Probability for the highest density interval. Width of each line. quartiles : bool Whether to mark quartiles linewidth : float Width of forestplot line markersize : float Size of marker in center of forestplot line ax : Axes Axes to draw on """ if rope is None or isinstance(rope, dict): pass elif len(rope) == 2: cds = ColumnDataSource({ "x": rope, "lower": [-2 * self.y_max(), -2 * self.y_max()], "upper": [self.y_max() * 2, self.y_max() * 2], }) band = Band( base="x", lower="lower", upper="upper", fill_color=[ color for _, color in zip( range(4), cycle(plt.rcParams["axes.prop_cycle"].by_key() ["color"])) ][2], line_alpha=0.5, source=cds, ) ax.renderers.append(band) else: raise ValueError("Argument `rope` must be None, a dictionary like" '{"var_name": {"rope": (lo, hi)}}, or an ' "iterable of length 2") # Quantiles to be calculated endpoint = 100 * (1 - hdi_prob) / 2 if quartiles: qlist = [endpoint, 25, 50, 75, 100 - endpoint] else: qlist = [endpoint, 50, 100 - endpoint] for plotter in self.plotters.values(): for y, selection, values, color in plotter.treeplot( qlist, hdi_prob): if isinstance(rope, dict): self.display_multiple_ropes(rope, ax, y, linewidth, plotter.var_name, selection) mid = len(values) // 2 param_iter = zip( np.linspace(2 * linewidth, linewidth, mid, endpoint=True)[-1::-1], range(mid)) for width, j in param_iter: ax.line([values[j], values[-(j + 1)]], [y, y], line_width=width, line_color=color) ax.circle( x=values[mid], y=y, size=markersize * 0.75, fill_color=color, ) _title = Title() _title.text = "{:.1%} HDI".format(hdi_prob) ax.title = _title return ax
def plot(): from bokeh.models.annotations import Title from pandas_datareader import data import datetime from bokeh.plotting import figure, show, output_file from bokeh.embed import components from bokeh.resources import CDN start = datetime.datetime(2021, 1, 1) end = datetime.datetime(2021, 4, 1) df = data.DataReader(name="AAPL", data_source="yahoo", start=start, end=end) def inc_dec(c, o): """ define the days when the indexes increased or dereased """ if c > o: value = "Increase" elif c < o: value = "Decrease" else: value = "Equal" return value df["Status"] = [inc_dec(c, o) for c, o in zip(df.Close, df.Open)] df["Middle"] = (df.Open + df.Close) / 2 df["Height"] = abs(df.Open - df.Close) p = figure(x_axis_type="datetime", width=1000, height=300, sizing_mode="scale_width") t = Title() t.text = 'Candlestick Chart of AAPL from 01.01.2021 till 01.04.2021' p.title = t p.grid.grid_line_alpha = 0.3 p.segment(df.index, df.High, df.index, df.Low, color="Black") hours_12 = 12 * 60 * 60 * 1000 # color the charts to red when the index increased p.rect(df.index[df.Status == "Increase"], df.Middle[df.Status == "Increase"], hours_12, df.Height[df.Status == "Increase"], fill_color="#008B8B", line_color="black") # color the chart to cyjana when the index decreased p.rect(df.index[df.Status == "Decrease"], df.Middle[df.Status == "Decrease"], hours_12, df.Height[df.Status == "Decrease"], fill_color="#A52A2A", line_color="black") # putting on live webpage # send these two components to html templates script1, div1 = components(p) cdn_js = CDN.js_files[0] cdn_css = CDN.css_files return render_template("plot.html", script1=script1, div1=div1, cdn_js=cdn_js)
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
import datetime #The time period for which you need the data. starttime = datetime.datetime(2018, 5, 2) endttime = datetime.datetime(2018, 5, 20) #pandas_datareader imports data from a number of online sources. #Parameters: Stock symbol, Data source, Start time and End time. stock_data = data.DataReader(name="AAPL", data_source="yahoo", start=starttime, end=endttime) #Setting properties of the plot. plot = figure(x_axis_type='datetime', width=1000, height=300) t = Title() t.text = 'Candlestick chart' plot.title = t plot.grid.grid_line_alpha = 0.3 #Twelve horus in milliseconds. twelve_hours = 12 * 60 * 60 * 1000 #Updating status of the stock. def status_update(open_price, close_price): if close_price > open_price: value = "Increase" elif open_price > close_price: value = "Decrease" else:
def plot_posterior( ax, length_plotters, rows, cols, figsize, plotters, bw, bins, kind, point_estimate, round_to, hdi_prob, multimodal, ref_val, rope, ax_labelsize, kwargs, backend_kwargs, show, ): """Bokeh posterior plot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(("dpi", "plot.bokeh.figure.dpi"), ), **backend_kwargs, } if ax is None: _, ax = _create_axes_grid( length_plotters, rows, cols, figsize=figsize, squeeze=False, backend="bokeh", backend_kwargs=backend_kwargs, ) else: ax = np.atleast_2d(ax) idx = 0 for (var_name, selection, x), ax_ in zip(plotters, (item for item in ax.flatten() if item is not None)): _plot_posterior_op(idx, x.flatten(), var_name, selection, ax=ax_, bw=bw, bins=bins, kind=kind, point_estimate=point_estimate, round_to=round_to, hdi_prob=hdi_prob, multimodal=multimodal, ref_val=ref_val, rope=rope, ax_labelsize=ax_labelsize, **kwargs) idx += 1 _title = Title() _title.text = make_label(var_name, selection) ax_.title = _title show_layout(ax, show) return ax
def plot_violin( ax, plotters, figsize, rows, cols, sharex, sharey, shade_kwargs, shade, rug, rug_kwargs, bw, credible_interval, linewidth, quartiles, backend_kwargs, show, ): """Bokeh violin plot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(), **backend_kwargs, } if ax is None: _, ax = _create_axes_grid( len(plotters), rows, cols, sharex=sharex, sharey=sharey, figsize=figsize, squeeze=False, backend="bokeh", backend_kwargs=backend_kwargs, ) else: ax = np.atleast_2d(ax) for (var_name, selection, x), ax_ in zip( plotters, (item for item in ax.flatten() if item is not None) ): val = x.flatten() if val[0].dtype.kind == "i": dens = cat_hist(val, rug, shade, ax_, **shade_kwargs) else: dens = _violinplot(val, rug, shade, bw, ax_, **shade_kwargs) if rug: rug_x = -np.abs(np.random.normal(scale=max(dens) / 3.5, size=len(val))) ax_.scatter(rug_x, val, **rug_kwargs) per = np.percentile(val, [25, 75, 50]) hpd_intervals = hpd(val, credible_interval, multimodal=False) if quartiles: ax_.line( [0, 0], per[:2], line_width=linewidth * 3, line_color="black", line_cap="round" ) ax_.line([0, 0], hpd_intervals, line_width=linewidth, line_color="black", line_cap="round") ax_.circle( 0, per[-1], line_color="white", fill_color="white", size=linewidth * 1.5, line_width=linewidth, ) _title = Title() _title.text = make_label(var_name, selection) ax_.title = _title ax_.xaxis.major_tick_line_color = None ax_.xaxis.minor_tick_line_color = None ax_.xaxis.major_label_text_font_size = "0pt" if backend_show(show): grid = gridplot(ax.tolist(), toolbar_location="above") bkp.show(grid) return ax
def plot_mcse( ax, plotters, length_plotters, rows, cols, figsize, errorbar, rug, data, probs, kwargs, # pylint: disable=unused-argument extra_methods, mean_mcse, sd_mcse, textsize, text_kwargs, # pylint: disable=unused-argument rug_kwargs, extra_kwargs, idata, rug_kind, backend_kwargs, show, ): """Bokeh mcse plot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(), **backend_kwargs, } (figsize, *_, _linewidth, _markersize) = _scale_fig_size(figsize, textsize, rows, cols) extra_kwargs = {} if extra_kwargs is None else extra_kwargs extra_kwargs.setdefault("linewidth", _linewidth / 2) extra_kwargs.setdefault("color", "black") extra_kwargs.setdefault("alpha", 0.5) if ax is None: ax = create_axes_grid( length_plotters, rows, cols, figsize=figsize, backend_kwargs=backend_kwargs, ) else: ax = np.atleast_2d(ax) for (var_name, selection, x), ax_ in zip(plotters, (item for item in ax.flatten() if item is not None)): if errorbar or rug: values = data[var_name].sel(**selection).values.flatten() if errorbar: quantile_values = _quantile(values, probs) ax_.dash(probs, quantile_values) ax_.multi_line( list(zip(probs, probs)), [(quant - err, quant + err) for quant, err in zip(quantile_values, x)], ) else: ax_.circle(probs, x) if extra_methods: mean_mcse_i = mean_mcse[var_name].sel( **selection).values.item() sd_mcse_i = sd_mcse[var_name].sel(**selection).values.item() hline_mean = Span( location=mean_mcse_i, dimension="width", line_color=extra_kwargs["color"], line_width=extra_kwargs["linewidth"] * 2, line_alpha=extra_kwargs["alpha"], ) ax_.renderers.append(hline_mean) hline_sd = Span( location=sd_mcse_i, dimension="width", line_color="black", line_width=extra_kwargs["linewidth"], line_alpha=extra_kwargs["alpha"], ) ax_.renderers.append(hline_sd) if rug: if rug_kwargs is None: rug_kwargs = {} if not hasattr(idata, "sample_stats"): raise ValueError( "InferenceData object must contain sample_stats for rug plot" ) if not hasattr(idata.sample_stats, rug_kind): raise ValueError( "InferenceData does not contain {} data".format(rug_kind)) rug_kwargs.setdefault("space", 0.1) _rug_kwargs = {} _rug_kwargs.setdefault("size", 8) _rug_kwargs.setdefault("line_color", rug_kwargs.get("line_color", "black")) _rug_kwargs.setdefault("line_width", 1) _rug_kwargs.setdefault("line_alpha", 0.35) _rug_kwargs.setdefault("angle", np.pi / 2) mask = idata.sample_stats[rug_kind].values.flatten() values = rankdata(values, method="average")[mask] if errorbar: rug_x, rug_y = ( values / (len(mask) - 1), np.full_like( values, min( 0, min(quantile_values) - (max(quantile_values) - min(quantile_values)) * 0.05, ), ), ) hline = Span( location=min( 0, min(quantile_values) - (max(quantile_values) - min(quantile_values)) * 0.05, ), dimension="width", line_color="black", line_width=_linewidth, line_alpha=0.7, ) else: rug_x, rug_y = ( values / (len(mask) - 1), np.full_like( values, 0, ), ) hline = Span( location=0, dimension="width", line_color="black", line_width=_linewidth, line_alpha=0.7, ) ax_.renderers.append(hline) glyph = Dash(x="rug_x", y="rug_y", **_rug_kwargs) cds_rug = ColumnDataSource({ "rug_x": np.asarray(rug_x), "rug_y": np.asarray(rug_y) }) ax_.add_glyph(cds_rug, glyph) title = Title() title.text = make_label(var_name, selection) ax_.title = title ax_.xaxis.axis_label = "Quantile" ax_.yaxis.axis_label = (r"Value $\pm$ MCSE for quantiles" if errorbar else "MCSE for quantiles") if not errorbar: ax_.y_range._property_values["start"] = -0.05 # pylint: disable=protected-access ax_.y_range._property_values["end"] = 1 # pylint: disable=protected-access show_layout(ax, show) return ax
def plot_trace( data, var_names, divergences, figsize, rug, lines, combined, legend, plot_kwargs: [Dict], fill_kwargs: [Dict], rug_kwargs: [Dict], hist_kwargs: [Dict], trace_kwargs: [Dict], plotters, divergence_data, colors, backend_kwargs: [Dict], show, ): """Bokeh traceplot.""" # If divergences are plotted they must be provided if divergences is not False: assert divergence_data is not None # Set plot default backend kwargs if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults( ("tools", "plot.bokeh.tools"), ("output_backend", "plot.bokeh.output_backend"), ("dpi", "plot.bokeh.figure.dpi"), ), **backend_kwargs, } dpi = backend_kwargs.pop("dpi") backend_kwargs.setdefault("height", int(figsize[1] * dpi // len(plotters))) backend_kwargs.setdefault("width", int(figsize[0] * dpi // 2)) figsize, _, _, _, linewidth, _ = _scale_fig_size(figsize, 10, rows=len(plotters), cols=2) trace_kwargs.setdefault("line_width", linewidth) plot_kwargs.setdefault("line_width", linewidth) axes = [] for i in range(len(plotters)): if i != 0: _axes = [ bkp.figure(**backend_kwargs), bkp.figure(x_range=axes[0][1].x_range, **backend_kwargs), ] else: _axes = [ bkp.figure(**backend_kwargs), bkp.figure(**backend_kwargs) ] axes.append(_axes) axes = np.array(axes) cds_data = {} cds_var_groups = {} draw_name = "draw" for var_name, selection, value in list( xarray_var_iter(data, var_names=var_names, combined=True)): if selection: cds_name = "{}_ARVIZ_CDS_SELECTION_{}".format( var_name, "_".join( str(item) for key, value in selection.items() for item in ([key, value] if ( isinstance(value, str) or not isinstance(value, Iterable)) else [key, *value])), ) else: cds_name = var_name if var_name not in cds_var_groups: cds_var_groups[var_name] = [] cds_var_groups[var_name].append(cds_name) for chain_idx, _ in enumerate(data.chain.values): if chain_idx not in cds_data: cds_data[chain_idx] = {} _data = value[chain_idx] cds_data[chain_idx][cds_name] = _data while any(key == draw_name for key in cds_data[0]): draw_name += "w" for chain_idx in cds_data: cds_data[chain_idx][draw_name] = data.draw.values cds_data = { chain_idx: ColumnDataSource(cds) for chain_idx, cds in cds_data.items() } for idx, (var_name, selection, value) in enumerate(plotters): value = np.atleast_2d(value) if len(value.shape) == 2: y_name = (var_name if not selection else "{}_ARVIZ_CDS_SELECTION_{}".format( var_name, "_".join( str(item) for key, value in selection.items() for item in ((key, value) if ( isinstance(value, str) or not isinstance(value, Iterable)) else ( key, *value))), )) if rug: rug_kwargs["y"] = y_name _plot_chains_bokeh( ax_density=axes[idx, 0], ax_trace=axes[idx, 1], data=cds_data, x_name=draw_name, y_name=y_name, colors=colors, combined=combined, rug=rug, legend=legend, trace_kwargs=trace_kwargs, hist_kwargs=hist_kwargs, plot_kwargs=plot_kwargs, fill_kwargs=fill_kwargs, rug_kwargs=rug_kwargs, ) else: for y_name in cds_var_groups[var_name]: if rug: rug_kwargs["y"] = y_name _plot_chains_bokeh( ax_density=axes[idx, 0], ax_trace=axes[idx, 1], data=cds_data, x_name=draw_name, y_name=y_name, colors=colors, combined=combined, rug=rug, legend=legend, trace_kwargs=trace_kwargs, hist_kwargs=hist_kwargs, plot_kwargs=plot_kwargs, fill_kwargs=fill_kwargs, rug_kwargs=rug_kwargs, ) for col in (0, 1): _title = Title() _title.text = make_label(var_name, selection) axes[idx, col].title = _title for _, _, vlines in (j for j in lines if j[0] == var_name and j[1] == selection): if isinstance(vlines, (float, int)): line_values = [vlines] else: line_values = np.atleast_1d(vlines).ravel() for line_value in line_values: vline = Span( location=line_value, dimension="height", line_color="black", line_width=1.5, line_alpha=0.75, ) hline = Span( location=line_value, dimension="width", line_color="black", line_width=1.5, line_alpha=trace_kwargs["alpha"], ) axes[idx, 0].renderers.append(vline) axes[idx, 1].renderers.append(hline) if legend: for col in (0, 1): axes[idx, col].legend.location = "top_left" axes[idx, col].legend.click_policy = "hide" else: for col in (0, 1): if axes[idx, col].legend: axes[idx, col].legend.visible = False if divergences: div_density_kwargs = {} div_density_kwargs.setdefault("size", 14) div_density_kwargs.setdefault("line_color", "red") div_density_kwargs.setdefault("line_width", 2) div_density_kwargs.setdefault("line_alpha", 0.50) div_density_kwargs.setdefault("angle", np.pi / 2) div_trace_kwargs = {} div_trace_kwargs.setdefault("size", 14) div_trace_kwargs.setdefault("line_color", "red") div_trace_kwargs.setdefault("line_width", 2) div_trace_kwargs.setdefault("line_alpha", 0.50) div_trace_kwargs.setdefault("angle", np.pi / 2) div_selection = { k: v for k, v in selection.items() if k in divergence_data.dims } divs = divergence_data.sel(**div_selection).values divs = np.atleast_2d(divs) for chain, chain_divs in enumerate(divs): div_idxs = np.arange(len(chain_divs))[chain_divs] if div_idxs.size > 0: values = value[chain, div_idxs] tmp_cds = ColumnDataSource({"y": values, "x": div_idxs}) if divergences == "top": y_div_trace = value.max() else: y_div_trace = value.min() glyph_density = Dash(x="y", y=0.0, **div_density_kwargs) glyph_trace = Dash(x="x", y=y_div_trace, **div_trace_kwargs) axes[idx, 0].add_glyph(tmp_cds, glyph_density) axes[idx, 1].add_glyph(tmp_cds, glyph_trace) if backend_show(show): grid = gridplot(axes.tolist(), toolbar_location="above") bkp.show(grid) return axes
def plot_posterior( ax, length_plotters, rows, cols, figsize, plotters, bw, bins, kind, point_estimate, round_to, credible_interval, multimodal, ref_val, rope, ax_labelsize, kwargs, backend_kwargs, show, ): """Bokeh posterior plot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(), **backend_kwargs, } if ax is None: _, ax = _create_axes_grid( length_plotters, rows, cols, figsize=figsize, squeeze=False, backend="bokeh", backend_kwargs=backend_kwargs, ) else: ax = np.atleast_2d(ax) idx = 0 for (var_name, selection, x), ax_ in zip(plotters, (item for item in ax.flatten() if item is not None)): _plot_posterior_op(idx, x.flatten(), var_name, selection, ax=ax_, bw=bw, bins=bins, kind=kind, point_estimate=point_estimate, round_to=round_to, credible_interval=credible_interval, multimodal=multimodal, ref_val=ref_val, rope=rope, ax_labelsize=ax_labelsize, **kwargs) idx += 1 _title = Title() _title.text = make_label(var_name, selection) ax_.title = _title if backend_show(show): grid = gridplot(ax.tolist(), toolbar_location="above") bkp.show(grid) return ax
from opcua import Client import time import csv from datetime import datetime import sqlite3 import bokeh from bokeh.io import curdoc from bokeh.layouts import gridplot from bokeh.models import ColumnDataSource from bokeh.plotting import figure from bokeh.models.annotations import Title import numpy as np source = ColumnDataSource(dict(vibx=[], viby=[], vibz=[], tim=[])) t1 = Title() t2 = Title() t3 = Title() fig1 = figure(width=250, height=250, x_axis_type='datetime') fig1.line(source=source, x='tim', y='vibx', line_width=2, alpha=0.85, color='red') t1.text = "Vibration-X" fig1.title = t1 fig2 = figure(width=250, height=250, x_axis_type='datetime') fig2.line(source=source,
def plot_ess( ax, plotters, xdata, ess_tail_dataset, mean_ess, sd_ess, idata, data, kind, extra_methods, textsize, rows, cols, figsize, kwargs, extra_kwargs, text_kwargs, n_samples, relative, min_ess, labeller, ylabel, rug, rug_kind, rug_kwargs, hline_kwargs, backend_kwargs, show, ): """Bokeh essplot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(), **backend_kwargs, } (figsize, *_, _linewidth, _markersize) = _scale_fig_size(figsize, textsize, rows, cols) if ax is None: ax = create_axes_grid( len(plotters), rows, cols, figsize=figsize, backend_kwargs=backend_kwargs, ) else: ax = np.atleast_2d(ax) for (var_name, selection, isel, x), ax_ in zip(plotters, (item for item in ax.flatten() if item is not None)): bulk_points = ax_.circle(np.asarray(xdata), np.asarray(x), size=6) if kind == "evolution": bulk_line = ax_.line(np.asarray(xdata), np.asarray(x)) ess_tail = ess_tail_dataset[var_name].sel(**selection) tail_points = ax_.line(np.asarray(xdata), np.asarray(ess_tail), color="orange") tail_line = ax_.circle(np.asarray(xdata), np.asarray(ess_tail), size=6, color="orange") elif rug: if rug_kwargs is None: rug_kwargs = {} if not hasattr(idata, "sample_stats"): raise ValueError( "InferenceData object must contain sample_stats for rug plot" ) if not hasattr(idata.sample_stats, rug_kind): raise ValueError( "InferenceData does not contain {} data".format(rug_kind)) rug_kwargs.setdefault("space", 0.1) _rug_kwargs = {} _rug_kwargs.setdefault("size", 8) _rug_kwargs.setdefault("line_color", rug_kwargs.get("line_color", "black")) _rug_kwargs.setdefault("line_width", 1) _rug_kwargs.setdefault("line_alpha", 0.35) _rug_kwargs.setdefault("angle", np.pi / 2) values = data[var_name].sel(**selection).values.flatten() mask = idata.sample_stats[rug_kind].values.flatten() values = rankdata(values, method="average")[mask] rug_space = np.max(x) * rug_kwargs.pop("space") rug_x, rug_y = values / (len(mask) - 1), np.zeros_like(values) - rug_space glyph = Scatter(x="rug_x", y="rug_y", marker="dash", **_rug_kwargs) cds_rug = ColumnDataSource({ "rug_x": np.asarray(rug_x), "rug_y": np.asarray(rug_y) }) ax_.add_glyph(cds_rug, glyph) hline = Span( location=0, dimension="width", line_color="black", line_width=_linewidth, line_alpha=0.7, ) ax_.renderers.append(hline) if extra_methods: mean_ess_i = mean_ess[var_name].sel(**selection).values.item() sd_ess_i = sd_ess[var_name].sel(**selection).values.item() hline = Span( location=mean_ess_i, dimension="width", line_color="black", line_width=2, line_dash="dashed", line_alpha=1.0, ) ax_.renderers.append(hline) hline = Span( location=sd_ess_i, dimension="width", line_color="black", line_width=1, line_dash="dashed", line_alpha=1.0, ) ax_.renderers.append(hline) hline = Span( location=400 / n_samples if relative else min_ess, dimension="width", line_color="red", line_width=3, line_dash="dashed", line_alpha=1.0, ) ax_.renderers.append(hline) if kind == "evolution": legend = Legend( items=[("bulk", [bulk_points, bulk_line]), ("tail", [tail_line, tail_points])], location="center_right", orientation="horizontal", ) ax_.add_layout(legend, "above") ax_.legend.click_policy = "hide" title = Title() title.text = labeller.make_label_vert(var_name, selection, isel) ax_.title = title ax_.xaxis.axis_label = "Total number of draws" if kind == "evolution" else "Quantile" ax_.yaxis.axis_label = ylabel.format( "Relative ESS" if relative else "ESS") show_layout(ax, show) return ax
data=result).set(xlabel='Month/ Day', ylabel='Temperature') import pandas as pd from bokeh.plotting import figure, output_file, show from bokeh.models import ColumnDataSource from bokeh.palettes import Spectral3 from bokeh.models.annotations import Title output_file('temp_lineplot.html') source1 = ColumnDataSource(apriltemp_df) source2 = ColumnDataSource(junetemp_df) source3 = ColumnDataSource(julytemp_df) p = figure(x_axis_type='datetime') t = Title() t.text = 'Change in Temperature' p.title = t p.line(x='datetime', y='temp', line_width=2, source=source1, legend='April-June Temp', color='red') p.line(x='datetime', y='temp', line_width=2, source=source2, legend='June-July Temp', color='blue') p.line(x='datetime',