def _draw_markers(self, plot, element, marks, axis='x'): if marks is None: return style = self.style[self.cyclic_index] mark_opts = {k[7:]: v for k, v in style.items() if axis+'mark' in k} mark_opts = {'line_'+k if k in ('color', 'alpha') else k: v for k, v in mpl_to_bokeh(mark_opts).items()} categories = list(element.dimension_values(0 if axis == 'x' else 1, expanded=False)) if callable(marks): positions = [i for i, x in enumerate(categories) if marks(x)] elif isinstance(marks, int): nth_mark = np.ceil(len(categories) / marks).astype(int) positions = np.arange(len(categories)+1)[::nth_mark] elif isinstance(marks, tuple): positions = [categories.index(m) for m in marks if m in categories] else: positions = [m for m in marks if isinstance(m, int) and m < len(categories)] if axis == 'y': positions = [len(categories)-p for p in positions] prev_markers = self.handles.get(axis+'marks', []) new_markers = [] for i, p in enumerate(positions): if i < len(prev_markers): span = prev_markers[i] span.update(**dict(mark_opts, location=p)) else: dimension = 'height' if axis == 'x' else 'width' span = Span(level='annotation', dimension=dimension, location=p, **mark_opts) plot.renderers.append(span) span.visible = True new_markers.append(span) for pm in prev_markers: if pm not in new_markers: pm.visible = False new_markers.append(pm) self.handles[axis+'marks'] = new_markers
def bokeh_plot(dataF, cat, n_since, tickers, n_top=15, format_axes=False): ''' Customizations for the Bokeh plots ''' # cat = {'confirmed', 'deaths', 'recoveries'} # n_since = number of cases since we start counting # n_top = number of top countries to show # tickers = customized tickers for the logy axis. It is simpler to manually define # them than to compute them for each case. from bokeh.io import output_notebook, output_file, show, reset_output from bokeh.plotting import figure, save from bokeh.models import ColumnDataSource, NumeralTickFormatter, HoverTool, Span from bokeh.palettes import Category20 # Specify the selection tools to be made available select_tools = [ 'box_zoom', 'pan', 'wheel_zoom', 'reset', 'crosshair', 'save' ] # Format the tooltip tooltips = [('', '$name'), ('Days since', '$x{(0)}'), ('{}'.format(cat), '$y{(0)}')] if format_axes: y_range = [0.49, 4000] else: y_range = None p = figure(y_range=y_range, y_axis_type="log", plot_width=840, plot_height=600, x_axis_label='Days since average daily {} passed {}'.format(cat, n_since), y_axis_label='', title= 'Daily {} ({}-day rolling average) by number of days ' \ 'since {} cases - top {} countries ' \ '(as of {})'.format(cat, roll, n_since, n_top, today_date), toolbar_location='above',tools=select_tools, toolbar_sticky=False) for i in range(n_top): p.line(dataF.index[:], dataF.iloc[:, i], line_width=2, color=Category20[20][i], alpha=0.8, legend_label=dataF.columns[i], name=dataF.columns[i]) p.line(1) p.circle(dataF.index[:], dataF.iloc[:, i], color=Category20[20][i], fill_color='white', size=3, alpha=0.8, legend_label=dataF.columns[i], name=dataF.columns[i]) hline = Span(location=1, dimension='width', line_width=2, line_dash='dashed', line_color='gray') p.renderers.extend([hline]) p.yaxis.ticker = tickers p.legend.location = 'top_right' p.legend.click_policy = 'hide' p.add_tools(HoverTool(tooltips=tooltips)) output_file('Daily_{}.html'.format(cat)) return save(p, 'Daily_{}.html'.format(cat))
def scatterCI(x, ci=None, label=None, hoverlabel=None, hline=0, sort_abs=False, col_hline=True, col_palette=None, title="Scatter CI Plot", xlabel="Peak", ylabel="Value", width=200, height=300, legend=True, font_size="20pt", label_font_size="13pt", linkrange=None): """Creates a scatterCI plot using Bokeh. Required Parameters ------------------- X : array-like, shape = [n_samples] Inpute data """ # If label is None, give an index based on input order if label is None: label_copy = [] for i in range(len(x)): label_copy.append(str(i)) else: label_copy = deepcopy(label) # Ensure label_copy is unique and under 60 characters until supported by Bokeh label_copy = [elem[:59] for elem in label_copy] # Limit Label characters limit to 59 label_copy = np.array(label_copy).tolist() label_unique = set(label_copy) label_indices = { value: [i for i, v in enumerate(label_copy) if v == value] for value in label_unique } for key, value in label_indices.items(): if len(value) > 1: for i in range(len(value)): label_copy[value[i]] = (str(" ") * i) + label_copy[value[i]] # Make sure height accounts for the max length of label height = height + 5 * len(max(label_copy, key=len)) # If colour palette is None (default): if col_palette is None: col_palette = ["blue", "red", "green"] # if col_hline is True, color depends on if error bar overlaps hline if col_hline is False: col = [] for i in range(len(x)): col.append(col_palette[2]) else: col = [] if ci is None: for i in range(len(x)): if x[i] < hline < x[i]: col.append(col_palette[0]) else: col.append(col_palette[1]) else: for i in range(len(x)): if ci[:, 0][i] < hline < ci[:, 1][i]: col.append(col_palette[0]) else: col.append(col_palette[1]) # Sort data (absolute) if sort_abs is True: sorted_idx = np.argsort(abs(x))[::-1] x = x[sorted_idx] label_copy = np.array(label_copy) label_copy = label_copy[sorted_idx] col = np.array(col) col = col[sorted_idx] # Sort ci if it exists if ci is not None: ci_low = ci[:, 0][sorted_idx] ci_high = ci[:, 1][sorted_idx] ci = [] for i in range(len(ci_low)): ci.append([ci_low[i], ci_high[i]]) ci = np.array(ci) hoverlabel = hoverlabel.copy() # hoverlabel = hoverlabel.reset_index() # hoverlabel = hoverlabel.reindex(sorted_idx).drop('index', axis=1) elif sort_abs is False: pass if hoverlabel is None: hoverlabel_copy = {} hoverlabel_copy["Idx"] = list(range(len(x))) else: try: hoverlabel2 = hoverlabel.copy() hoverlabel2_dict = hoverlabel2.to_dict("series") hoverlabel_copy = hoverlabel2_dict except TypeError: hoverlabel2 = label.copy() hoverlabel_copy = {} hoverlabel_copy[label2.name] = hoverlabel2.values.tolist() # Linking to another plot if linkrange is None: xrange = label_copy else: xrange = linkrange.x_range # Bokeh data source if ci is None: data = {"x": x, "col": col, "label": label_copy} else: data = { "x": x, "lowci": ci[:, 0], "uppci": ci[:, 1], "col": col, "label": label_copy } data_label = {} for name, val in hoverlabel_copy.items(): data_label[name] = val data.update(data_label) source = ColumnDataSource(data=data) # Tool-tip TOOLTIPS = [] for name, val in data_label.items(): TOOLTIPS.append((str(name), "@" + str(name))) TOOLTIPS.append(("Value", "@x{1.111}")) TOOLTIPS.append(("Upper", "@uppci{1.111}")) TOOLTIPS.append(("Lower", "@lowci{1.111}")) if ci is None: y_range_max = max(abs(np.min(x)), abs(np.max(x)), abs(np.min(x)), abs(np.max(x))) * 0.1 y_range = (min(np.min(x) - y_range_max, np.min(x) - y_range_max), max(np.max(x) + y_range_max, np.max(x) + y_range_max)) else: y_range_max = max(abs(np.min(ci[:, 0])), abs(np.max(ci[:, 0])), abs(np.min(ci[:, 1])), abs(np.max(ci[:, 1]))) * 0.1 y_range = (min( np.min(ci[:, 0]) - y_range_max, np.min(ci[:, 0]) - y_range_max), max( np.max(ci[:, 1]) + y_range_max, np.max(ci[:, 0]) + y_range_max)) # Base figure fig = figure(title=title, x_axis_label=xlabel, y_axis_label=ylabel, x_range=xrange, y_range=y_range, plot_width=int(len(x) / 10 * width), plot_height=height, tooltips=TOOLTIPS, toolbar_location="left", toolbar_sticky=False) # Add circles fig.circle("label", "x", size=10, alpha=0.6, color="col", source=source) # Add hline hline = Span(location=hline, dimension="width", line_color="black", line_width=2, line_alpha=0.3) fig.add_layout(hline) # Add error bars if ci is not None: fig.add_layout( Whisker(base="label", lower="lowci", upper="uppci", line_color="col", line_width=1.5, source=source)) # Font-sizes fig.title.text_font_size = font_size fig.xaxis.axis_label_text_font_size = label_font_size fig.yaxis.axis_label_text_font_size = label_font_size # X-axis orientation fig.xaxis.major_label_orientation = np.pi / 2 # Extra padding fig.min_border_left = 20 fig.min_border_right = 20 fig.min_border_top = 20 fig.min_border_bottom = 20 return fig
def plot_pair( ax, infdata_group, numvars, figsize, textsize, kind, kde_kwargs, hexbin_kwargs, contour, # pylint: disable=unused-argument plot_kwargs, # pylint: disable=unused-argument fill_last, # pylint: disable=unused-argument divergences, diverging_mask, flat_var_names, backend_kwargs, diagonal, marginal_kwargs, point_estimate, point_estimate_kwargs, reference_values, reference_values_kwargs, show, ): """Bokeh pair plot.""" if backend_kwargs is None: backend_kwargs = {} backend_kwargs = { **backend_kwarg_defaults(("dpi", "plot.bokeh.figure.dpi"), ), **backend_kwargs, } if hexbin_kwargs is None: hexbin_kwargs = {} hexbin_kwargs.setdefault("size", 0.5) if kind != "kde": kde_kwargs.setdefault("contourf_kwargs", {"fill_alpha": 0}) kde_kwargs.setdefault("contour_kwargs", {}) kde_kwargs["contour_kwargs"].setdefault("line_color", "black") kde_kwargs["contour_kwargs"].setdefault("line_alpha", 1) if reference_values: reference_values_copy = {} label = [] for variable in list(reference_values.keys()): if " " in variable: variable_copy = variable.replace(" ", "\n", 1) else: variable_copy = variable label.append(variable_copy) reference_values_copy[variable_copy] = reference_values[variable] difference = set(flat_var_names).difference(set(label)) for dif in difference: reference_values_copy[dif] = None if difference: warn = [dif.replace("\n", " ", 1) for dif in difference] warnings.warn( "Argument reference_values does not include reference value for: {}" .format(", ".join(warn)), UserWarning, ) if reference_values_kwargs is None: reference_values_kwargs = {} reference_values_kwargs.setdefault("line_color", "red") reference_values_kwargs.setdefault("line_width", 5) dpi = backend_kwargs.pop("dpi") max_plots = (numvars**2 if rcParams["plot.max_subplots"] is None else rcParams["plot.max_subplots"]) vars_to_plot = np.sum(np.arange(numvars).cumsum() < max_plots) if vars_to_plot < numvars: warnings.warn( "rcParams['plot.max_subplots'] ({max_plots}) is smaller than the number " "of resulting pair plots with these variables, generating only a " "{side}x{side} grid".format(max_plots=max_plots, side=vars_to_plot), UserWarning, ) numvars = vars_to_plot (figsize, _, _, _, _, _) = _scale_fig_size(figsize, textsize, numvars - 2, numvars - 2) tmp_flat_var_names = None if len(flat_var_names) == len(list(set(flat_var_names))): source_dict = dict( zip(flat_var_names, [list(post) for post in infdata_group])) else: tmp_flat_var_names = [ "{}__{}".format(name, str(uuid4())) for name in flat_var_names ] source_dict = dict( zip(tmp_flat_var_names, [list(post) for post in infdata_group])) if divergences: divergenve_name = "divergences_{}".format(str(uuid4())) source_dict[divergenve_name] = np.array(diverging_mask).astype( bool).astype(int).astype(str) source = ColumnDataSource(data=source_dict) if divergences: source_nondiv = CDSView( source=source, filters=[GroupFilter(column_name=divergenve_name, group="0")]) source_div = CDSView( source=source, filters=[GroupFilter(column_name=divergenve_name, group="1")]) def get_width_and_height(jointplot, rotate): """Compute subplots dimensions for two or more variables.""" if jointplot: if rotate: width = int(figsize[0] / (numvars - 1) + 2 * dpi) height = int(figsize[1] / (numvars - 1) * dpi) else: width = int(figsize[0] / (numvars - 1) * dpi) height = int(figsize[1] / (numvars - 1) + 2 * dpi) else: width = int(figsize[0] / (numvars - 1) * dpi) height = int(figsize[1] / (numvars - 1) * dpi) return width, height if diagonal: var = 0 else: var = 1 if ax is None: ax = [] backend_kwargs.setdefault("width", int(figsize[0] / (numvars - 1) * dpi)) backend_kwargs.setdefault("height", int(figsize[1] / (numvars - 1) * dpi)) for row in range(numvars - var): row_ax = [] var1 = (flat_var_names[row + var] if tmp_flat_var_names is None else tmp_flat_var_names[row + var]) for n, col in enumerate(range(numvars - var)): var2 = (flat_var_names[col] if tmp_flat_var_names is None else tmp_flat_var_names[col]) backend_kwargs_copy = backend_kwargs.copy() if "scatter" in kind: tooltips = [ (var2, "@{{{}}}".format(var2)), (var1, "@{{{}}}".format(var1)), ] backend_kwargs_copy.setdefault("tooltips", tooltips) else: tooltips = None if row < col: row_ax.append(None) else: jointplot = row == col and numvars == 2 and diagonal rotate = n == 1 width, height = get_width_and_height(jointplot, rotate) if jointplot: ax_ = bkp.figure(width=width, height=height, tooltips=tooltips) else: ax_ = bkp.figure(**backend_kwargs_copy) row_ax.append(ax_) ax.append(row_ax) ax = np.array(ax) else: assert ax.shape == (numvars - var, numvars - var) # pylint: disable=too-many-nested-blocks for i in range(0, numvars - var): var1 = flat_var_names[ i] if tmp_flat_var_names is None else tmp_flat_var_names[i] for j in range(0, numvars - var): var2 = (flat_var_names[j + var] if tmp_flat_var_names is None else tmp_flat_var_names[j + var]) if j == i and diagonal: rotate = numvars == 2 and j == 1 var1_dist = infdata_group[i] plot_dist( var1_dist, ax=ax[j, i], show=False, backend="bokeh", rotated=rotate, **marginal_kwargs, ) ax[j, i].xaxis.axis_label = flat_var_names[i] ax[j, i].yaxis.axis_label = flat_var_names[j + var] elif j + var > i: if "scatter" in kind: if divergences: ax[j, i].circle(var1, var2, source=source, view=source_nondiv) else: ax[j, i].circle(var1, var2, source=source) if "kde" in kind: var1_kde = infdata_group[i] var2_kde = infdata_group[j + var] plot_kde( var1_kde, var2_kde, ax=ax[j, i], backend="bokeh", backend_kwargs={}, show=False, **kde_kwargs, ) if "hexbin" in kind: var1_hexbin = infdata_group[i] var2_hexbin = infdata_group[j + var] ax[j, i].grid.visible = False ax[j, i].hexbin( var1_hexbin, var2_hexbin, **hexbin_kwargs, ) if divergences: ax[j, i].circle( var1, var2, line_color="black", fill_color="orange", line_width=1, size=10, source=source, view=source_div, ) if point_estimate: var1_pe = infdata_group[i] var2_pe = infdata_group[j] pe_x = calculate_point_estimate(point_estimate, var1_pe) pe_y = calculate_point_estimate(point_estimate, var2_pe) ax[j, i].square(pe_x, pe_y, line_width=figsize[0] + 1, **point_estimate_kwargs) ax_hline = Span( location=pe_y, dimension="width", line_dash="solid", line_width=3, **point_estimate_kwargs, ) ax_vline = Span( location=pe_x, dimension="height", line_dash="solid", line_width=3, **point_estimate_kwargs, ) ax[j, i].add_layout(ax_hline) ax[j, i].add_layout(ax_vline) if diagonal: ax[j - 1, i].add_layout(ax_vline) pe_last = calculate_point_estimate( point_estimate, infdata_group[-1]) ax_pe_vline = Span( location=pe_last, dimension="height", line_dash="solid", line_width=3, **point_estimate_kwargs, ) ax[-1, -1].add_layout(ax_pe_vline) if numvars == 2: ax_pe_hline = Span( location=pe_last, dimension="width", line_dash="solid", line_width=3, **point_estimate_kwargs, ) ax[-1, -1].add_layout(ax_pe_hline) if reference_values: x = reference_values_copy[flat_var_names[j + var]] y = reference_values_copy[flat_var_names[i]] if x and y: ax[j, i].circle(y, x, **reference_values_kwargs) ax[j, i].xaxis.axis_label = flat_var_names[i] ax[j, i].yaxis.axis_label = flat_var_names[j + var] show_layout(ax, show) return ax
], x_axis_label="Season", y_axis_label="Deaths", toolbar_location="right", title='COVID-19 vs. Past Influenzas in Canada') # HOVERTOOLS p.add_tools( HoverTool(tooltips=[ ("Strain", "@info"), ("Deaths", "@deaths{(0,0)}"), ("Population", "@pop{(0,0)}"), ])) # MEAN LINE SPAN span = Span(location=np.nanmean(data['Deaths']), dimension='width', line_color='firebrick', line_width=3, line_alpha=0.43) p.add_layout(span) my_label = Label(x=5, y=np.nanmean(data['Deaths']) + 10, text='MEAN LINE', text_color='firebrick', text_alpha=0.43, text_font_style='bold') p.add_layout(my_label) source = ColumnDataSource( data={ 'x': data['Season'], 'info': data['Strain'],
# set up static line and annotations plot.line(x_line, y_line, line_width=5, color='blue', line_alpha=0.3) plot.circle(x_points, y_points, size=10, color='blue', line_alpha=0.3) mytext = Label(x=-6.5, y=105, text='Top=100, Bottom=0, pEC50=6, Hill=1', text_color="blue", text_alpha=0.5) plot.add_layout(mytext) # add axes lines vline = Span(location=0, dimension='height', line_color='black', line_width=1, line_alpha=0.3) hline = Span(location=0, dimension='width', line_color='black', line_width=1, line_alpha=0.3) plot.renderers.extend([vline, hline]) # set up java script callback function to make plot interactive top_slider = Slider(start=0, end=200, value=100, step=5, title="Top Response (%)")
def create(palm): doc = curdoc() # Calibration averaged waveforms per photon energy waveform_plot = Plot( title=Title(text="eTOF calibration waveforms"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=760, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools waveform_plot.toolbar.logo = None waveform_plot_hovertool = HoverTool( tooltips=[("energy, eV", "@en"), ("eTOF bin", "$x{0.}")]) waveform_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool(), waveform_plot_hovertool) # ---- axes waveform_plot.add_layout(LinearAxis(axis_label="eTOF time bin"), place="below") waveform_plot.add_layout(LinearAxis(axis_label="Intensity", major_label_orientation="vertical"), place="left") # ---- grid lines waveform_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) waveform_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- multiline glyphs waveform_ref_source = ColumnDataSource(dict(xs=[], ys=[], en=[])) waveform_ref_multiline = waveform_plot.add_glyph( waveform_ref_source, MultiLine(xs="xs", ys="ys", line_color="blue")) waveform_str_source = ColumnDataSource(dict(xs=[], ys=[], en=[])) waveform_str_multiline = waveform_plot.add_glyph( waveform_str_source, MultiLine(xs="xs", ys="ys", line_color="red")) # ---- legend waveform_plot.add_layout( Legend(items=[( "reference", [waveform_ref_multiline]), ("streaked", [waveform_str_multiline])])) waveform_plot.legend.click_policy = "hide" # ---- vertical spans photon_peak_ref_span = Span(location=0, dimension="height", line_dash="dashed", line_color="blue") photon_peak_str_span = Span(location=0, dimension="height", line_dash="dashed", line_color="red") waveform_plot.add_layout(photon_peak_ref_span) waveform_plot.add_layout(photon_peak_str_span) # Calibration fit plot fit_plot = Plot( title=Title(text="eTOF calibration fit"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools fit_plot.toolbar.logo = None fit_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes fit_plot.add_layout(LinearAxis(axis_label="Photoelectron peak shift"), place="below") fit_plot.add_layout(LinearAxis(axis_label="Photon energy, eV", major_label_orientation="vertical"), place="left") # ---- grid lines fit_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) fit_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- circle glyphs fit_ref_circle_source = ColumnDataSource(dict(x=[], y=[])) fit_ref_circle = fit_plot.add_glyph( fit_ref_circle_source, Circle(x="x", y="y", line_color="blue")) fit_str_circle_source = ColumnDataSource(dict(x=[], y=[])) fit_str_circle = fit_plot.add_glyph(fit_str_circle_source, Circle(x="x", y="y", line_color="red")) # ---- line glyphs fit_ref_line_source = ColumnDataSource(dict(x=[], y=[])) fit_ref_line = fit_plot.add_glyph(fit_ref_line_source, Line(x="x", y="y", line_color="blue")) fit_str_line_source = ColumnDataSource(dict(x=[], y=[])) fit_str_line = fit_plot.add_glyph(fit_str_line_source, Line(x="x", y="y", line_color="red")) # ---- legend fit_plot.add_layout( Legend(items=[ ("reference", [fit_ref_circle, fit_ref_line]), ("streaked", [fit_str_circle, fit_str_line]), ])) fit_plot.legend.click_policy = "hide" # Calibration results datatables def datatable_ref_source_callback(_attr, _old_value, new_value): for en, ps, use in zip(new_value["energy"], new_value["peak_pos_ref"], new_value["use_in_fit"]): palm.etofs["0"].calib_data.loc[ en, "calib_tpeak"] = ps if ps != "NaN" else np.nan palm.etofs["0"].calib_data.loc[en, "use_in_fit"] = use calib_res = {} for etof_key in palm.etofs: calib_res[etof_key] = palm.etofs[etof_key].fit_calibration_curve() update_calibration_plot(calib_res) datatable_ref_source = ColumnDataSource( dict(energy=["", "", ""], peak_pos_ref=["", "", ""], use_in_fit=[True, True, True])) datatable_ref_source.on_change("data", datatable_ref_source_callback) datatable_ref = DataTable( source=datatable_ref_source, columns=[ TableColumn(field="energy", title="Photon Energy, eV", editor=IntEditor()), TableColumn(field="peak_pos_ref", title="Reference Peak", editor=IntEditor()), TableColumn(field="use_in_fit", title=" ", editor=CheckboxEditor(), width=80), ], index_position=None, editable=True, height=300, width=250, ) def datatable_str_source_callback(_attr, _old_value, new_value): for en, ps, use in zip(new_value["energy"], new_value["peak_pos_str"], new_value["use_in_fit"]): palm.etofs["1"].calib_data.loc[ en, "calib_tpeak"] = ps if ps != "NaN" else np.nan palm.etofs["1"].calib_data.loc[en, "use_in_fit"] = use calib_res = {} for etof_key in palm.etofs: calib_res[etof_key] = palm.etofs[etof_key].fit_calibration_curve() update_calibration_plot(calib_res) datatable_str_source = ColumnDataSource( dict(energy=["", "", ""], peak_pos_str=["", "", ""], use_in_fit=[True, True, True])) datatable_str_source.on_change("data", datatable_str_source_callback) datatable_str = DataTable( source=datatable_str_source, columns=[ TableColumn(field="energy", title="Photon Energy, eV", editor=IntEditor()), TableColumn(field="peak_pos_str", title="Streaked Peak", editor=IntEditor()), TableColumn(field="use_in_fit", title=" ", editor=CheckboxEditor(), width=80), ], index_position=None, editable=True, height=350, width=250, ) # eTOF calibration folder path text input def path_textinput_callback(_attr, _old_value, _new_value): path_periodic_update() update_load_dropdown_menu() path_textinput = TextInput(title="eTOF calibration path:", value=os.path.join(os.path.expanduser("~")), width=510) path_textinput.on_change("value", path_textinput_callback) # eTOF calibration eco scans dropdown def scans_dropdown_callback(event): scans_dropdown.label = event.item scans_dropdown = Dropdown(label="ECO scans", button_type="default", menu=[]) scans_dropdown.on_click(scans_dropdown_callback) # ---- etof scans periodic update def path_periodic_update(): new_menu = [] if os.path.isdir(path_textinput.value): for entry in os.scandir(path_textinput.value): if entry.is_file() and entry.name.endswith(".json"): new_menu.append((entry.name, entry.name)) scans_dropdown.menu = sorted(new_menu, reverse=True) doc.add_periodic_callback(path_periodic_update, 5000) path_tab = Panel(child=column( path_textinput, scans_dropdown, ), title="Path") upload_div = Div(text="Upload ECO scan (top) and all hdf5 files (bottom):") # ECO scan upload FileInput def eco_fileinput_callback(_attr, _old, new): with io.BytesIO(base64.b64decode(new)) as eco_scan: data = json.load(eco_scan) print(data) eco_fileinput = FileInput(accept=".json", disabled=True) eco_fileinput.on_change("value", eco_fileinput_callback) # HDF5 upload FileInput def hdf5_fileinput_callback(_attr, _old, new): for base64_str in new: with io.BytesIO(base64.b64decode(base64_str)) as hdf5_file: with h5py.File(hdf5_file, "r") as h5f: print(h5f.keys()) hdf5_fileinput = FileInput(accept=".hdf5,.h5", multiple=True, disabled=True) hdf5_fileinput.on_change("value", hdf5_fileinput_callback) upload_tab = Panel(child=column(upload_div, eco_fileinput, hdf5_fileinput), title="Upload") # Calibrate button def calibrate_button_callback(): try: palm.calibrate_etof_eco(eco_scan_filename=os.path.join( path_textinput.value, scans_dropdown.label)) except Exception: palm.calibrate_etof(folder_name=path_textinput.value) datatable_ref_source.data.update( energy=palm.etofs["0"].calib_data.index.tolist(), peak_pos_ref=palm.etofs["0"].calib_data["calib_tpeak"].tolist(), use_in_fit=palm.etofs["0"].calib_data["use_in_fit"].tolist(), ) datatable_str_source.data.update( energy=palm.etofs["0"].calib_data.index.tolist(), peak_pos_str=palm.etofs["1"].calib_data["calib_tpeak"].tolist(), use_in_fit=palm.etofs["1"].calib_data["use_in_fit"].tolist(), ) def update_calibration_plot(calib_res): etof_ref = palm.etofs["0"] etof_str = palm.etofs["1"] shift_val = 0 etof_ref_wf_shifted = [] etof_str_wf_shifted = [] for wf_ref, wf_str in zip(etof_ref.calib_data["waveform"], etof_str.calib_data["waveform"]): shift_val -= max(wf_ref.max(), wf_str.max()) etof_ref_wf_shifted.append(wf_ref + shift_val) etof_str_wf_shifted.append(wf_str + shift_val) waveform_ref_source.data.update( xs=len(etof_ref.calib_data) * [list(range(etof_ref.internal_time_bins))], ys=etof_ref_wf_shifted, en=etof_ref.calib_data.index.tolist(), ) waveform_str_source.data.update( xs=len(etof_str.calib_data) * [list(range(etof_str.internal_time_bins))], ys=etof_str_wf_shifted, en=etof_str.calib_data.index.tolist(), ) photon_peak_ref_span.location = etof_ref.calib_t0 photon_peak_str_span.location = etof_str.calib_t0 def plot_fit(time, calib_a, calib_b): time_fit = np.linspace(np.nanmin(time), np.nanmax(time), 100) en_fit = (calib_a / time_fit)**2 + calib_b return time_fit, en_fit def update_plot(calib_results, circle, line): (a, c), x, y = calib_results x_fit, y_fit = plot_fit(x, a, c) circle.data.update(x=x, y=y) line.data.update(x=x_fit, y=y_fit) update_plot(calib_res["0"], fit_ref_circle_source, fit_ref_line_source) update_plot(calib_res["1"], fit_str_circle_source, fit_str_line_source) calib_const_div.text = f""" a_str = {etof_str.calib_a:.2f}<br> b_str = {etof_str.calib_b:.2f}<br> <br> a_ref = {etof_ref.calib_a:.2f}<br> b_ref = {etof_ref.calib_b:.2f} """ calibrate_button = Button(label="Calibrate eTOF", button_type="default", width=250) calibrate_button.on_click(calibrate_button_callback) # Photon peak noise threshold value text input def phot_peak_noise_thr_spinner_callback(_attr, old_value, new_value): if new_value > 0: for etof in palm.etofs.values(): etof.photon_peak_noise_thr = new_value else: phot_peak_noise_thr_spinner.value = old_value phot_peak_noise_thr_spinner = Spinner(title="Photon peak noise threshold:", value=1, step=0.1) phot_peak_noise_thr_spinner.on_change( "value", phot_peak_noise_thr_spinner_callback) # Electron peak noise threshold value text input def el_peak_noise_thr_spinner_callback(_attr, old_value, new_value): if new_value > 0: for etof in palm.etofs.values(): etof.electron_peak_noise_thr = new_value else: el_peak_noise_thr_spinner.value = old_value el_peak_noise_thr_spinner = Spinner(title="Electron peak noise threshold:", value=10, step=0.1) el_peak_noise_thr_spinner.on_change("value", el_peak_noise_thr_spinner_callback) # Save calibration button def save_button_callback(): palm.save_etof_calib(path=path_textinput.value) update_load_dropdown_menu() save_button = Button(label="Save", button_type="default", width=250) save_button.on_click(save_button_callback) # Load calibration button def load_dropdown_callback(event): new_value = event.item if new_value: palm.load_etof_calib(os.path.join(path_textinput.value, new_value)) datatable_ref_source.data.update( energy=palm.etofs["0"].calib_data.index.tolist(), peak_pos_ref=palm.etofs["0"].calib_data["calib_tpeak"].tolist( ), use_in_fit=palm.etofs["0"].calib_data["use_in_fit"].tolist(), ) datatable_str_source.data.update( energy=palm.etofs["0"].calib_data.index.tolist(), peak_pos_str=palm.etofs["1"].calib_data["calib_tpeak"].tolist( ), use_in_fit=palm.etofs["1"].calib_data["use_in_fit"].tolist(), ) def update_load_dropdown_menu(): new_menu = [] calib_file_ext = ".palm_etof" if os.path.isdir(path_textinput.value): for entry in os.scandir(path_textinput.value): if entry.is_file() and entry.name.endswith((calib_file_ext)): new_menu.append( (entry.name[:-len(calib_file_ext)], entry.name)) load_dropdown.button_type = "default" load_dropdown.menu = sorted(new_menu, reverse=True) else: load_dropdown.button_type = "danger" load_dropdown.menu = new_menu doc.add_next_tick_callback(update_load_dropdown_menu) doc.add_periodic_callback(update_load_dropdown_menu, 5000) load_dropdown = Dropdown(label="Load", menu=[], width=250) load_dropdown.on_click(load_dropdown_callback) # eTOF fitting equation fit_eq_div = Div( text="""Fitting equation:<br><br><img src="/palm/static/5euwuy.gif">""" ) # Calibration constants calib_const_div = Div(text=f""" a_str = {0}<br> b_str = {0}<br> <br> a_ref = {0}<br> b_ref = {0} """) # assemble tab_layout = column( row( column(waveform_plot, fit_plot), Spacer(width=30), column( Tabs(tabs=[path_tab, upload_tab]), calibrate_button, phot_peak_noise_thr_spinner, el_peak_noise_thr_spinner, row(save_button, load_dropdown), row(datatable_ref, datatable_str), calib_const_div, fit_eq_div, ), )) return Panel(child=tab_layout, title="eTOF Calibration")
def plot(self, canvas, transform=None, bins=None, title="Pers Diag"): r""" Plot the persistence diagram using `matplotlib` or `bokeh`. Parameters ---------- canvas An instance of :class:`bokeh.plotting.figure.Figure` invoked as `canvas = bokeh.plotting.figure()`, or a an instance of :class:`matplotlib.axes._subplots.AxesSubplot` invoked as `fig,canvas = matplotlib.pyplot.subplots()` or similar. Notes ----- You have to save or show the canvas after running this call. """ if type(canvas).__module__ == 'bokeh.plotting.figure': canvas_type = "bokeh" import bokeh.plotting from bokeh.models import Span elif type(canvas).__module__ == 'matplotlib.axes._subplots': canvas_type = "pyplot" import matplotlib.pyplot as plt else: raise NotImplementedError( """canvas must be a bokeh.plotting.figure() or a matplotlib.pyplot.subplots()[1]. You gave me {}""".format(type(canvas))) if canvas_type == "bokeh": canvas.title = title elif canvas_type == "pyplot": canvas.set_title(title) if bins is not None: if canvas_type == "bokeh": for edge in bins: if np.isfinite(edge): canvas.renderers.append( Span(location=edge, dimension='height', line_color='purple', line_alpha=0.8)) canvas.renderers.append( Span(location=edge, dimension='width', line_color='purple', line_alpha=0.8)) elif canvas_type == "pyplot": for edge in bins: if np.isfinite(edge): canvas.axhline(edge, color='purple', alpha=0.8) canvas.axvline(edge, color='purple', alpha=0.8) absmin = self.diagram['birth'].min() absmax = self.diagram['death'].max() boundary = np.array([[absmin, absmin], [absmin, absmax], [absmax, absmax]]) boundary = self.transform(transform, boundary) if canvas_type == "bokeh": canvas.line(boundary[:, 0], boundary[:, 1], color='orange') elif canvas_type == "pyplot": canvas.plot(boundary[:, 0], boundary[:, 1], color='orange') diagonal = np.array([[absmin, absmin], [absmax, absmax]]) diagonal = self.transform(transform, diagonal) if canvas_type == "bokeh": canvas.line(diagonal[:, 0], diagonal[:, 1], color='red') elif canvas_type == "pyplot": canvas.plot(diagonal[:, 0], diagonal[:, 1], color='red') rectified = self.transform(transform) if canvas_type == "bokeh": canvas.circle(rectified[:, 0], rectified[:, 1], color='blue', alpha=0.5, size=3) elif canvas_type == "pyplot": canvas.scatter(rectified[:, 0], rectified[:, 1], color='blue', alpha=0.5) pass
def graph(bitcoin_data, tweet_data): bitcoin_time_array = [ parse_and_localize_utc(x["time_period_start"]) for x in bitcoin_data ] bitcoin_price_array = [y["price_close"] for y in bitcoin_data] bitcoin_min = min(bitcoin_price_array) bitcoin_max = max(bitcoin_price_array) curdoc().theme = 'dark_minimal' p = figure(title='BitCoin x Elon Musk', x_axis_label='date', x_axis_type='datetime', y_axis_label='Price (USD)', y_range=(round(bitcoin_min, -4), round(bitcoin_max, -4))) p.line(bitcoin_time_array, bitcoin_price_array, legend_label="BitCoin Price", line_width=2, line_color='gray') trades_count_array = [x['trades_count'] for x in bitcoin_data] trades_count_min = min(trades_count_array) trades_count_max = max(trades_count_array) p.extra_y_ranges = { "trades_count": Range1d(start=round(trades_count_min, -3), end=round(trades_count_max, -3)) } p.add_layout( LinearAxis(y_range_name="trades_count", axis_label="Trades Count"), 'right') p.vbar(x=bitcoin_time_array, top=trades_count_array, width=0.4, bottom=0, y_range_name="trades_count", line_color='purple', line_alpha=0.8, legend_label="BitCoin Trades Count", fill_color='purple') x_tweet = [] bitcoin_average = statistics.mean(bitcoin_price_array) y_tweet = [bitcoin_average for x in range(0, len(tweet_data))] desc_tweet = [] for tweet in tweet_data: created_at_parsed = parse_and_localize_utc(tweet.created_at) x_tweet.append(created_at_parsed) desc_tweet.append(tweet.text) tweet_line = Span(location=created_at_parsed, dimension='height', line_color='deepskyblue', line_dash='dashed', line_width=0.8) p.add_layout(tweet_line) source = ColumnDataSource(data=dict( x=x_tweet, y=y_tweet, desc=desc_tweet, )) circle = p.circle(source=source, size=1, alpha=1) tweet_hovertool = HoverTool( renderers=[circle], mode='vline', tooltips=[("@elonmusk:", "@desc")], ) p.tools.append(tweet_hovertool) curdoc().add_root(p)
top='CE_OI_Change', source=source, color="#e84d60", width=20) p.vbar(x=dodge('strikePrice', 10, range=p.x_range), top='PE_OI_Change', source=source, color="#718dbf", width=20) p.background_fill_color = "black" p.xgrid.grid_line_color = None p.ygrid.grid_line_color = None nifty = df['Nifty'].iloc[1] ltp = Span(location=nifty, dimension='height', line_color='green', line_dash='dashed', line_width=3) p.add_layout(ltp) my_label = Label(x=nifty, y=max_oi_change, text=str(nifty), border_line_color='green', border_line_alpha=1.0, y_offset=3, x_offset=-38, text_color='white', text_font_size='8pt', background_fill_color='green', background_fill_alpha=1.0) p.add_layout(my_label)
def modify_doc(): # collect all the names of .npz files in the folder lfpca_all_names = glob.glob("*.npz") lfpca_all_names.sort() # loading the npz files lfpca_all = {} for ind, lf in enumerate(lfpca_all_names): lfpca_all[lf[:-4]] = lfpca.lfpca_load_spec(lf) # initialize with the first lfpca object lf = lfpca_all[lfpca_all_names[0][:-4]] # grabbing channel count from psd chan_count, freq = lf.psd.shape # mapping all the channels DEFAULT_TICKERS = list(map(str, range(chan_count))) LF_TICKERS = [key for key in lfpca_all.keys()] # initializing values for frequency, psd, scv, histogram plot chan = 0 select_freq = 10 select_bin = 20 freq_vals = lf.f_axis[1:] psd_vals = lf.psd[chan].T[1:] scv_vals = lf.scv[chan].T[1:] # creating a selector and slider lf_ticker = Select(value=lfpca_all_names[0][:-4], title='lf_condition', options=LF_TICKERS) ticker = Select(value=str(chan), title='channel', options=DEFAULT_TICKERS) freq_slider = Slider(start=1, end=199, value=select_freq, step=1, title="Frequency", callback_policy="mouseup") bin_slider = Slider(start=10, end=55, value=select_bin, step=5, title="Number of bins", callback_policy="mouseup") # create data and selection tools source = ColumnDataSource( data=dict(freq_vals=freq_vals, psd_vals=psd_vals, scv_vals=scv_vals)) TOOLS = "help" #tapTool work in progress # setting up plots psd_plot = figure(tools=TOOLS, title='PSD', x_axis_type='log', y_axis_type='log') psd_plot.legend.location = 'top_left' psd_plot.xaxis.axis_label = 'Frequency (Hz)' psd_plot.yaxis.axis_label = 'Power/Frequency (dB/Hz)' psd_plot.grid.grid_line_alpha = 0.3 scv_plot = figure(tools=TOOLS, title='SCV', x_axis_type='log', y_axis_type='log') scv_plot.legend.location = 'top_left' scv_plot.xaxis.axis_label = 'Frequency (Hz)' scv_plot.yaxis.axis_label = '(Unitless)' scv_plot.grid.grid_line_alpha = 0.3 # create histogram frame hist_source = ColumnDataSource({'top': [], 'left': [], 'right': []}) fit_hist_source = ColumnDataSource({'x': [], 'y': []}) hist, edges = np.histogram(lf.spg[chan, select_freq, :], bins=select_bin, density=True) hist_source.data = {'top': hist, 'left': edges[:-1], 'right': edges[1:]} # create fit line for the histogram rv = expon(scale=sp.stats.expon.fit(lf.spg[chan, select_freq, :], floc=0)[1]) hist_source.data = {'top': hist, 'left': edges[:-1], 'right': edges[1:]} fit_hist_source.data = {'x': edges, 'y': rv.pdf(edges)} hist_fig = figure(x_axis_label='Power', y_axis_label='Probability', background_fill_color="#E8DDCB") hist_fig.axis.visible = False hist_fig.title.text = 'Freq = %.1fHz, p-value = %.4f' % ( select_freq, lf.ks_pvals[chan, select_freq]) # customize plot to psd def create_psd_plot(psd_plot, source): psd_plot.line('freq_vals', 'psd_vals', source=source, color='navy') psd_plot.circle( 'freq_vals', 'psd_vals', source=source, size=5, color='darkgrey', alpha=0.2, # set visual properties for selected glyphs selection_color="firebrick", # set visual properties for non-selected glyphs nonselection_fill_alpha=0.2, nonselection_fill_color="darkgrey", name='psd_circ') # customize plot to psd def create_scv_plot(scv_plot, source): scv_plot.line('freq_vals', 'scv_vals', source=source, color='navy') scv_plot.circle( 'freq_vals', 'scv_vals', source=source, size=5, color='darkgrey', alpha=0.2, # set visual properties for selected glyphs selection_color="firebrick", # set visual properties for non-selected glyphs nonselection_fill_alpha=0.2, nonselection_fill_color="darkgrey", name='scv_circ') # customize histogram def create_hist(hist_fig, hist_source): hist_fig.quad(top='top', bottom=0, left='left', right='right', fill_color="#036564", line_color="#033649", source=hist_source) # initializing plots create_psd_plot(psd_plot, source) create_scv_plot(scv_plot, source) vline_psd = Span(location=select_freq, dimension='height', line_color='red', line_dash='dashed', line_width=3) vline_scv = Span(location=select_freq, dimension='height', line_color='red', line_dash='dashed', line_width=3) psd_plot.add_layout(vline_psd) scv_plot.add_layout(vline_scv) create_hist(hist_fig, hist_source) fit_line = bokeh.models.glyphs.Line(x='x', y='y', line_width=8, line_alpha=0.7, line_color="#D95B43") hist_fig.add_glyph(fit_hist_source, fit_line) all_plots = gridplot([[psd_plot, scv_plot, hist_fig]], plot_width=300, plot_height=300) # set up connector spans freq_slider.callback = CustomJS(args=dict(span1=vline_psd, span2=vline_scv, slider=freq_slider), code="""span1.location = slider.value; span2.location = slider.value""" ) def update(attrname, old, new): # get current slider values chan = int(ticker.value) lf = lfpca_all[lf_ticker.value] select_freq = freq_slider.value select_bin = bin_slider.value # update data psd_vals = lf.psd[chan].T[1:] scv_vals = lf.scv[chan].T[1:] data = dict(freq_vals=freq_vals, psd_vals=psd_vals, scv_vals=scv_vals) # create a column data source for the plots to share source.data = data # update histogram and fit line hist, edges = np.histogram(lf.spg[chan, select_freq, :], bins=select_bin, density=True) rv = expon( scale=sp.stats.expon.fit(lf.spg[chan, select_freq, :], floc=0)[1]) hist_source.data = { 'top': hist, 'left': edges[:-1], 'right': edges[1:] } fit_hist_source.data = {'x': edges, 'y': rv.pdf(edges)} create_psd_plot(psd_plot=psd_plot, source=source) create_scv_plot(scv_plot=scv_plot, source=source) hist_fig.title.text = 'Freq = %.1fHz, p-value = %.4f' % ( select_freq, lf.ks_pvals[chan, select_freq]) create_hist(hist_fig=hist_fig, hist_source=hist_source) fit_line = bokeh.models.glyphs.Line(x='x', y='y', line_width=8, line_alpha=0.7, line_color="#D95B43") hist_fig.add_glyph(fit_hist_source, fit_line) # whenever a widget changes, the changes are tracked and histogram always updated for widget in [lf_ticker, ticker, bin_slider, freq_slider]: widget.on_change('value', update) # when selected value changes, take the following methods of actions # lf_ticker.on_change('value', lf_selection_change) # ticker.on_change('value', selection_change) # what to do when freq slider value changes def freq_change(attr, old, new): select_freq = source.selected.indices[0] # update histogram and fit line hist, edges = np.histogram(lf.spg[chan, select_freq, :], bins=select_bin, density=True) rv = expon( scale=sp.stats.expon.fit(lf.spg[chan, select_freq, :], floc=0)[1]) hist_source.data = { 'top': hist, 'left': edges[:-1], 'right': edges[1:] } fit_hist_source.data = {'x': edges, 'y': rv.pdf(edges)} hist_fig.title.text = 'Freq = %.1fHz, p-value = %.4f' % ( select_freq, lf.ks_pvals[chan, select_freq]) create_hist(hist_fig=hist_fig, hist_source=hist_source) fit_line = bokeh.models.glyphs.Line(x='x', y='y', line_width=8, line_alpha=0.7, line_color="#D95B43") hist_fig.add_glyph(fit_hist_source, fit_line) # organize layout widgets = row(lf_ticker, ticker) sliders = row(freq_slider, bin_slider) layout = column(widgets, sliders, all_plots) # doc.add_root(layout) return layout # In the notebook, just pass the function that defines the app to show # show(modify_doc, notebook_handle=True) # curdoc().add_root(layout) - for .py file # curdoc().add_root(layout) # h = show(layout, notebook_handle=True) # In the notebook, just pass the function that defines the app to show # show(modify_doc) # curdoc().add_root(layout) # for .py file
def plot(df, start=None, end=None, **kwargs): ''' plot candle chart with 'df'(DataFrame) from 'start' to 'end' * df: DataFrame to plot * start(default: None) * end(default: None) * recent_high: display recent high price befre n-days (if recent_high == -1 plot plot recent high yesterday) ''' try: from bokeh.plotting import figure, gridplot from bokeh.models import NumeralTickFormatter, DatetimeTickFormatter, Span from bokeh.io import output_notebook, show, export_png from bokeh.palettes import d3 except ModuleNotFoundError as e: raise ModuleNotFoundError(bokeh_install_msg) params = dict(__plot_params) for key, value in kwargs.items(): if key == 'config': for key, value in kwargs.items(): params[key] = value else: params[key] = value df = df.loc[start:end].copy() ma_type = params['moving_average_type'] weights = np.arange(240) + 1 for n in params['moving_average_lines']: # moving average lines if ma_type.upper() == 'SMA': df[f'MA_{n}'] = df.Close.rolling(window=n).mean() elif ma_type.upper() == 'WMA': df[f'MA_{n}'] = df.Close.rolling(n).apply( lambda prices: np.dot(prices, weights[:n]) / weights[:n].sum()) elif ma_type.upper() == 'EMA': df[f'MA_{n}'] = df.Close.ewm(span=n).mean() elif ma_type.upper() == 'None': pass else: raise ValueError(f"moving_average_type '{ma_type}' is invalid") inc = df.Close > df.Open dec = df.Open > df.Close output_notebook() # plot price OHLC candles x = np.arange(len(df)) height = params['height'] if params['volume']: height = int(params['height'] - params['height'] * params['volume_height']) pp = figure(plot_width=params['width'], plot_height=height, x_range=(-1, min(120, len(df))), y_range=(df.Low.min(), df.High.max()), title=params['title'], y_axis_label=params['ylabel']) pp.segment(x[inc], df.High[inc], x[inc], df.Low[inc], color=params['color_up']) pp.segment(x[dec], df.High[dec], x[dec], df.Low[dec], color=params['color_down']) pp.vbar(x[inc], 0.8, df.Open[inc], df.Close[inc], fill_color=params['color_up'], line_color=params['color_up']) pp.vbar(x[dec], 0.8, df.Open[dec], df.Close[dec], fill_color=params['color_down'], line_color=params['color_down']) pp.yaxis[0].formatter = NumeralTickFormatter(format='0,0') if params['volume']: pp.xaxis.visible = False else: x_labels = { i: dt.strftime('%Y-%m-%d') for i, dt in enumerate(df.index) } x_labels.update({len(df): ''}) pp.xaxis.major_label_overrides = x_labels pp.xaxis.formatter = DatetimeTickFormatter(hours=["%H:%M"], days=["%Y-%m-%d"]) pp.xaxis.major_label_orientation = np.pi / 5 for ix, n in enumerate(params['moving_average_lines']): pal = d3['Category10'][10] pp.line(x, df[f'MA_{n}'], line_color=pal[ix % len(pal)]) if params['recent_high']: to = df.index.max() + timedelta(days=params['recent_high']) hline = Span(location=df.Close[:to].max(), dimension='width', line_dash='dashed', line_color='gray', line_width=2) pp.renderers.extend([hline]) # plot volume if params['volume']: inc = df.Volume.diff() >= 0 dec = df.Volume.diff() < 0 height = int(params['height'] * params['volume_height']) pv = figure(plot_width=params['width'], plot_height=height, x_range=pp.x_range) pv.vbar(x[inc], 0.8, df.Volume[inc], fill_color=params['color_volume_up'], line_color="black") pv.vbar(x[dec], 0.8, df.Volume[dec], fill_color=params['color_volume_down'], line_color="black") pv.yaxis[0].formatter = NumeralTickFormatter(format='0,0') x_labels = { i: dt.strftime('%Y-%m-%d') for i, dt in enumerate(df.index) } x_labels.update({len(df): ''}) pv.xaxis.major_label_overrides = x_labels pv.xaxis.formatter = DatetimeTickFormatter(hours=["%H:%M"], days=["%Y-%m-%d"]) pv.xaxis.major_label_orientation = np.pi / 5 pv.y_range.range_padding = 0 # 가격(pp)과 거래량(pv) 함께 그리기 p = gridplot([[pp], [pv]]) else: p = gridplot([[pp]]) show(p) if 'save' in kwargs: export_png(p, filename=kwargs['save'])
y_axis_label="Relative Profit of Attacking (Millions of USD)") plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6) # Set up widgets text = TextInput(title="Title", value='mighty bitcoin') mining_power = Slider(title="Mining Power", start=min_mining_power, end=max_mining_power, value=default_mining_power, step=mining_power_step) discount_rate = Slider(title="Discount Rate", start=min_discount, end=max_discount, value=default_discount, step=discount_step) btc_stolen = Slider(title="Amount of BTC Stolen", start=min_btc_stolen, end=max_btc_stolen, value=default_btc_stolen, step=btc_stolen_step) btc_owned_0 = Slider(title="BTC Owned At Time 0", start=min_btc_owned_0, end=max_btc_owned_0, value=default_btc_owned_0, step=btc_owned_0_step) exchange_rate = Slider(title="BTC-USD Exchange Rate", start=min_rate, end=max_rate, value=default_rate, step=rate_step) btc_f_stolen = Slider(title="Fraction Amount of BTC Stolen", start=min_btc_f_stolen, end=max_btc_f_stolen, value=default_btc_f_stolen, step=btc_f_stolen_step) btc_f_owned_0 = Slider(title="Fraction BTC Owned At Time 0", start=min_btc_f_owned_0, end=max_btc_f_owned_0, value=default_btc_f_owned_0, step=btc_f_owned_0_step) hline = Span(location=0, dimension='width', line_color='green', line_width=1.5) plot.renderers.extend([hline]) # Set up callbacks def update_title(attrname, old, new): plot.title.text = text.value text.on_change('value', update_title) def update_data(): # Get the current slider values alpha = mining_power.value gamma = discount_rate.value f_owned = btc_f_owned_0.value f_stolen = btc_f_stolen.value
def plot_population_size(self, timestep=None): # 'self' will be 'network' """ Plots a graph of the population size throughout the model run, regardless of timestep specified. The timestep just draws a vertical line indicating the current timestep relative to the plotted data.""" history = self.network.history source = ColumnDataSource({ 'time': np.array([history_step['step'] for history_step in history]) / time_settings['WEEKS_PER_YEAR'], 'total population': [ history_step['anad pop'] + history_step['res pop'] for history_step in history ], 'anadromous population': [history_step['anad pop'] for history_step in history], 'resident population': [history_step['res pop'] for history_step in history], 'anadromous redds': [history_step['anad redds'] for history_step in history], 'resident redds': [history_step['res redds'] for history_step in history], 'total redds': [ history_step['anad redds'] + history_step['res redds'] for history_step in history ] }) fig = figure(tools=[], plot_width=500, plot_height=300) fig.yaxis.axis_label = 'Population size' fig.line('time', 'total population', source=source, line_width=2, legend='Total fish', line_color='lightgray') fig.line('time', 'anadromous population', source=source, line_width=2, legend='Anadromous', line_color='forestgreen') fig.line('time', 'resident population', source=source, line_width=2, legend='Resident', line_color='slateblue') rfig = figure(tools=[], plot_width=500, plot_height=300) rfig.yaxis.axis_label = 'Redds' rfig.line('time', 'total redds', source=source, line_width=2, legend='Total redds', line_color='lightgray') rfig.line('time', 'anadromous redds', source=source, line_width=2, legend='Anadromous', line_color='forestgreen') rfig.line('time', 'resident redds', source=source, line_width=2, legend='Resident', line_color='slateblue') for f in (fig, rfig): fig.xaxis.axis_label = 'Time (years)' f.legend.location = 'top_left' f.toolbar.logo = None f.select(dict(type=Axis, layout="left"))[0].formatter.use_scientific = False if timestep is not None: f.add_layout( Span(location=timestep / time_settings['WEEKS_PER_YEAR'], dimension='height', line_color='red', line_dash='dashed', line_width=1)) return row([fig, rfig])
f = figure(plot_height=300, x_range=aparelhos, title='Cozinha - Campo magnético', toolbar_location='above') f.vbar(x=aparelhos, top=campo, width=0.9) source = ColumnDataSource( dict(x=aparelhos, y=[2.069, 30.06, 3.754, 22.45, 6.521])) labels = LabelSet(x='x', y='y', text='y', level='glyph', x_offset=-13.5, y_offset=0, source=source, render_mode='canvas') f.add_layout(labels) f.y_range = Range1d(0, 210, bounds=(0, None)) span = Span(location=200, dimension='width', line_color='red', line_dash='dashed', line_width=1) f.xaxis.axis_label = 'Aparelhos' f.yaxis.axis_label = 'B (uT)' f.xgrid.grid_line_color = None f.y_range.start = 0 f.add_layout(span) show(f)
tools=TOOLS) p.xaxis.axis_label_text_font_size = "32pt" p.yaxis.axis_label_text_font_size = "32pt" p.xaxis.major_label_text_font_size = "24pt" p.yaxis.major_label_text_font_size = "24pt" # add a line renderer with legend and line thickness p.circle(range(len(data_out)), data_out, fill_color="red", line_color="red", size=6) hline = Span(location=np.mean(data_out), dimension='width', line_color='green', line_width=1) p.renderers.extend([hline]) hline = Span(location=np.mean(data_out) + np.std(data_out), dimension='width', line_color='blue', line_width=1, line_dash='dashed') p.renderers.extend([hline]) hline = Span(location=np.mean(data_out) - np.std(data_out), dimension='width', line_color='blue', line_width=1, line_dash='dashed')
title="Scale Slider", callback=callback) callback.args["scale"] = slider1 slider2 = Slider( start=0, end=len(ch2_data[0]), value=1, step=1, title="Peak Slider") peak_start = Span( location=slider2.value, dimension='height', line_color='red', line_dash='dashed', line_width=1) p.add_layout(peak_start) slider2.callback = CustomJS(args=dict(span=peak_start, slider=slider2), code=""" span.location = slider.value; """) cb_up = CustomJS(args=dict(span=peak_start, slider=slider2), code=""" span.location = span.location + 1; slider.value = span.location; """) cb_down = CustomJS(args=dict(span=peak_start, slider=slider2), code=""" span.location = span.location - 1; slider.value = span.location;
num_offenses.line(x='year_month', y='num_offenses', source=line_source, color=RED, line_width=1.5) num_offenses.add_tools(offenses_tooltip) num_offenses.circle(x='year_month', y='num_offenses', source=line_source, color="black", size=4) num_offenses.yaxis.axis_label = 'Number of Offenses' num_offenses.xaxis.axis_label = 'Date' mean_line = Span(location=0, dimension='width', line_color=RED, line_dash=[8, 3]) num_offenses.add_layout(mean_line) shootings_tooltip = HoverTool(tooltips=[('Date', '@year_month{%b %Y}'), ('Number of Shootings', '@num_shootings')], formatters={'year_month': 'datetime'}, mode="vline") num_shootings = figure(x_axis_type="datetime", title="Number of Shootings per Month", active_drag="xbox_select", tools=tools) num_shootings.add_tools(shootings_tooltip)
def add_graph(self, field_names, colors, legends, use_downsample=True, mark_nan=False, use_step_lines=False): """ add 1 or more lines to a graph field_names can be a list of fields from the data set, or a list of functions with the data set as argument and returning a tuple of (field_name, data) :param mark_nan: if True, add an indicator to the plot when one of the graphs is NaN :param use_step_lines: if True, render step lines (after each point) instead of rendering a straight line to the next point """ if self._had_error: return try: p = self._p data_set = {} data_set['timestamp'] = self._cur_dataset.data['timestamp'] field_names_expanded = self._expand_field_names(field_names, data_set) if mark_nan: # look through the data to find NaN's and store their timestamps nan_timestamps = set() for key in field_names_expanded: nan_indexes = np.argwhere(np.isnan(data_set[key])) last_index = -2 for ind in nan_indexes: if last_index + 1 != ind: # store only timestamps at the start of NaN nan_timestamps.add(data_set['timestamp'][ind][0]) last_index = ind nan_color = 'black' for nan_timestamp in nan_timestamps: nan_line = Span(location=nan_timestamp, dimension='height', line_color=nan_color, line_dash='dashed', line_width=3) p.add_layout(nan_line) if len(nan_timestamps) > 0: y_values = [30] * len(nan_timestamps) # NaN label: add a space to separate it from the line names = [' NaN'] * len(nan_timestamps) source = ColumnDataSource(data=dict(x=np.array(list(nan_timestamps)), names=names, y=y_values)) # plot as text with a fixed screen-space y offset labels = LabelSet(x='x', y='y', text='names', y_units='screen', level='glyph', text_color=nan_color, source=source, render_mode='canvas') p.add_layout(labels) if use_downsample: # we directly pass the data_set, downsample and then create the # ColumnDataSource object, which is much faster than # first creating ColumnDataSource, and then downsample downsample = DynamicDownsample(p, data_set, 'timestamp') data_source = downsample.data_source else: data_source = ColumnDataSource(data=data_set) for field_name, color, legend in zip(field_names_expanded, colors, legends): if use_step_lines: p.step(x='timestamp', y=field_name, source=data_source, legend=legend, line_width=2, line_color=color, mode="after") else: p.line(x='timestamp', y=field_name, source=data_source, legend=legend, line_width=2, line_color=color) except (KeyError, IndexError, ValueError) as error: print(type(error), "("+self._data_name+"):", error) self._had_error = True
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, labeller, 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, isel, 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 = labeller.make_label_vert(var_name, selection, isel) 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
fill_color='color', line_color='black', size='size', line_width=0.3, source=s1, hover_line_color='black', hover_color='red', legend='mesh_term') p.grid.visible = False # hover message p.hover.tooltips = tooltips significant_line = Span(location=-np.log10(5e-8), dimension='width', line_color='grey', line_dash='dashed', line_width=2, line_alpha=0.5) p.add_layout(significant_line) p.axis.minor_tick_line_color = None p.axis.major_tick_in = 0 snp_columns = [ TableColumn(field="rsid", title="rsID"), TableColumn(field="maf", title="MAF"), TableColumn(field="ea", title="Effect Allele"), TableColumn(field="nea", title="Non-effect Allele"), TableColumn(field="beta", title="BETA"), TableColumn(field="se", title="SE"), TableColumn(field="p", title="P Value"), TableColumn(field="zscore", title="Zscore"),
def generate_sentiment_ts_plot(sentiment_ts_data, sentiment_ts_sample_count): tooltips = [ ("Date", "@date{%F}"), ("Mentions", "@Count"), ("Nett Sentiment (7 day mean)", "@NettSentiment{0.0%}"), ] line_plot = figure(title=None, width=None, height=None, sizing_mode="scale_both", x_range=(sentiment_ts_data["date"].min(), sentiment_ts_data["date"].max()), x_axis_type='datetime', y_axis_label="Nett Sentiment (7 day mean)", tools=[], toolbar_location=None) # Setting range of y range line_plot.y_range = Range1d(-1, 1) # Adding Count range on the right line_plot.extra_y_ranges = { "count_range": Range1d(start=0, end=sentiment_ts_sample_count.max() * 1.1) } secondary_axis = LinearAxis(y_range_name="count_range", axis_label="Mentions") line_plot.add_layout(secondary_axis, 'right') sentiment_count_bars = line_plot.vbar(x="date", top="Count", width=pandas.Timedelta(days=0.75), color="orange", source=sentiment_ts_data, y_range_name="count_range") sentiment_line = line_plot.line(x="date", y="NettSentiment", color="blue", source=sentiment_ts_data, line_width=5) # Long Term sentiment baseline long_term_sentiment_span = Span( location=LONG_TERM_SENTIMENT, name="LongTermSentiment", dimension='width', line_color='red', line_dash='dashed', line_width=3, ) line_plot.add_layout(long_term_sentiment_span) start_timestamp = sentiment_ts_data["date"].min() long_term_sentiment_label = Label(x=start_timestamp, y=LONG_TERM_SENTIMENT, x_offset=-10, y_offset=10, text='Sentiment Baseline', render_mode='css', border_line_color='white', border_line_alpha=0.0, angle=0, angle_units='deg', background_fill_color='white', background_fill_alpha=0.0, text_color='red', text_font_size='12pt') line_plot.add_layout(long_term_sentiment_label) hover_tool = HoverTool(renderers=[sentiment_line, sentiment_count_bars], tooltips=tooltips, formatters={ '@date': 'datetime', 'NettSentiment': 'printf' }) line_plot.add_tools(hover_tool) line_plot.xaxis.formatter = DatetimeTickFormatter(days="%Y-%m-%d") line_plot.yaxis.formatter = NumeralTickFormatter(format="0.[0]%") secondary_axis.formatter = NumeralTickFormatter(format="0.[0] a") line_plot.axis.axis_label_text_font_size = "12pt" line_plot.axis.major_label_text_font_size = "12pt" plot_html = file_html(line_plot, CDN, "Behavioural Sentiment Timeseries") return plot_html
def _plot_indicators(): """Strategy indicators""" def _too_many_dims(value): assert value.ndim >= 2 if value.ndim > 2: warnings.warn("Can't plot indicators with >2D ('{}')".format( value.name), stacklevel=5) return True return False class LegendStr(str): # The legend string is such a string that only matches # itself if it's the exact same object. This ensures # legend items are listed separately even when they have the # same string contents. Otherwise, Bokeh would always consider # equal strings as one and the same legend item. def __eq__(self, other): return self is other ohlc_colors = colorgen() for i, value in enumerate(indicators): value = np.atleast_2d(value) # Use .get()! A user might have assigned a Strategy.data-evolved # _Array without Strategy.I() if not value._opts.get('plot') or _too_many_dims(value): continue is_overlay = value._opts['overlay'] is_scatter = value._opts['scatter'] if is_overlay: fig = fig_ohlc else: fig = new_indicator_figure() figs_below_ohlc.append(fig) tooltips = [] colors = value._opts['color'] colors = colors and cycle(_as_list(colors)) or (cycle( [next(ohlc_colors)]) if is_overlay else colorgen()) legend_label = LegendStr(value.name) for j, arr in enumerate(value, 1): color = next(colors) source_name = '{}_{}_{}'.format(legend_label, i, j) if arr.dtype == bool: arr = arr.astype(int) source.add(arr, source_name) tooltips.append('@{{{}}}{{0,0.0[0000]}}'.format(source_name)) if is_overlay: ohlc_extreme_values[source_name] = arr if is_scatter: fig.scatter('index', source_name, source=source, legend_label=legend_label, color=color, line_color='black', fill_alpha=.8, marker='circle', radius=bar_width / 2 * 1.5) else: fig.line('index', source_name, source=source, legend_label=legend_label, line_color=color, line_width=1.3) else: if is_scatter: r = fig.scatter('index', source_name, source=source, legend_label=LegendStr(legend_label), color=color, marker='circle', radius=bar_width / 2 * .9) else: r = fig.line('index', source_name, source=source, legend_label=LegendStr(legend_label), line_color=color, line_width=1.3) # Add dashed centerline just because mean = float(pd.Series(arr).mean()) if not np.isnan(mean) and ( abs(mean) < .1 or round(abs(mean), 1) == .5 or round(abs(mean), -1) in (50, 100, 200)): fig.add_layout( Span(location=float(mean), dimension='width', line_color='#666666', line_dash='dashed', line_width=.5)) if is_overlay: ohlc_tooltips.append((legend_label, NBSP.join(tooltips))) else: set_tooltips(fig, [(legend_label, NBSP.join(tooltips))], vline=True, renderers=[r]) # If the sole indicator line on this figure, # have the legend only contain text without the glyph if len(value) == 1: fig.legend.glyph_width = 0
def make_bls_figure_elements(result, bls_source, help_source): """Make a line plot of a BLS result. Parameters ---------- result : BLS.model result BLS model result to plot bls_source : bokeh.plotting.ColumnDataSource Bokeh style source object for plotting BLS source help_source : bokeh.plotting.ColumnDataSource Bokeh style source object for rendering help button Returns ------- fig : bokeh.plotting.figure Bokeh figure object vertical_line : bokeh.models.Span Vertical line to highlight current selected period """ # Build Figure fig = figure(title='BLS Periodogram', plot_height=340, plot_width=450, tools="pan,box_zoom,tap,reset", toolbar_location="below", border_fill_color="#FFFFFF", x_axis_type='log', active_drag="box_zoom") fig.title.offset = -10 fig.yaxis.axis_label = 'Power' fig.xaxis.axis_label = 'Period [days]' fig.y_range = Range1d(start=result.power.min() * 0.95, end=result.power.max() * 1.05) fig.x_range = Range1d(start=result.period.min(), end=result.period.max()) # Add circles for the selection of new period. These are always hidden circ = fig.circle('period', 'power', source=bls_source, fill_alpha=0., size=6, line_color=None, selection_color="white", nonselection_fill_alpha=0.0, nonselection_fill_color='white', nonselection_line_color=None, nonselection_line_alpha=0.0, fill_color=None, hover_fill_color="white", hover_alpha=0., hover_line_color="white") # Add line for the BLS power fig.line('period', 'power', line_width=1, color='#191919', source=bls_source, nonselection_line_color='#191919', nonselection_line_alpha=1.0) # Vertical line to indicate the current period vertical_line = Span(location=0, dimension='height', line_color='firebrick', line_width=3, line_alpha=0.5) fig.add_layout(vertical_line) # Help button question_mark = Text(x="period", y="power", text="helpme", text_color="grey", text_align='center', text_baseline="middle", text_font_size='12px', text_font_style='bold', text_alpha=0.6) fig.add_glyph(help_source, question_mark) help = fig.circle('period', 'power', alpha=0.0, size=15, source=help_source, line_width=2, line_color='grey', line_alpha=0.6) tooltips = help_source.data['help'][0] fig.add_tools( HoverTool(tooltips=tooltips, renderers=[help], mode='mouse', point_policy="snap_to_data")) return fig, vertical_line
def __init__(self, **params): super(ufloat, self).__init__(**params) # will mirror data in dicts: self.D = {i: {} for i in _items} self.D['total'] = {} # hull material #self.D['hull'].update(alu_6061) # constraints self.constraints = {} # init figures self.renderers = { v: {} for v in ['volume', 'length', 'mass', 'constraints', 'speed'] } _tools = 'pan,wheel_zoom,box_zoom,hover,crosshair,reset' TOOLTIPS = [ ("(radius, y)", "($x, $y)"), ] # for linked crosshair: # https://stackoverflow.com/questions/37965669/how-do-i-link-the-crosshairtool-in-bokeh-over-several-plots f_volume = figure( y_axis_label='[liters]', tools=_tools, tooltips=TOOLTIPS, ) f, r = f_volume, self.renderers['volume'] for i in ['hull', 'piston', 'battery', 'electronics', 'total']: r[i] = f.line([], [], color=_colors[i], line_width=3, legend_label=i) f.legend.background_fill_alpha = 0.1 # f_length = figure(y_axis_label='[cm]', tools=_tools, tooltips=TOOLTIPS, x_range=f_volume.x_range) f, r = f_length, self.renderers['length'] for i in ['hull', 'piston']: r[i + '_radius'] = f.line( [], [], color=_colors[i], line_width=2, legend_label=i + ' radius', ) r[i + '_length'] = f.line( [], [], color=_colors[i], line_width=4, legend_label=i + ' length', ) r['hull_radius_gamma'] = f.line([], [], color=_colors['hull'], line_width=3, line_dash='4 4', legend_label='h radius/Gamma^{1/2}') #f.xaxis.axis_label = 'hull radius [cm]' f.legend.background_fill_alpha = 0.1 # f_mass = figure(y_axis_label='[kg]', y_axis_location='right', tools=_tools, tooltips=TOOLTIPS, x_range=f_volume.x_range) f, r = f_mass, self.renderers['mass'] for i in ['battery', 'hull', 'total']: r[i] = f.line([], [], color=_colors[i], line_width=3, legend_label=i) f.legend.background_fill_alpha = 0.1 # f_constraints = figure( y_axis_label='[1]', y_axis_location='right', tools=_tools, tooltips=TOOLTIPS, x_range=f_volume.x_range, y_range=(0, 5), ) f, r = f_constraints, self.renderers['constraints'] r['stress'] = line(f, _colors['hull'], 'stress') r['buckling'] = line(f, _colors['hull'], 'buckling', line_dash='dashed') r['compressibility'] = line(f, 'green', '1/compressibility') r['piston_length'] = line(f, _colors['piston'], 'piston length') r['piston_radius'] = line(f, _colors['piston'], 'piston radius', line_dash='dashed') f.xaxis.axis_label = 'hull radius [cm]' f.add_layout( Span(location=1, dimension='width', line_color='black', line_width=1)) f.legend.background_fill_alpha = 0.1 # f_speed = figure( y_axis_label='[cm/s]', tools=_tools, tooltips=TOOLTIPS, x_range=f_volume.x_range, ) f, r = f_speed, self.renderers['speed'] r['maxspeed'] = line(f, 'black', 'max speed') f.legend.background_fill_alpha = 0.1 # self.figures = gridplot( [[f_volume, f_mass], [f_length, f_constraints], [f_speed, None]], plot_width=500, plot_height=300, ) # self.update()
def assembly_chart(df, complements): """function to assembly the chart""" print('starting the plot...') # specify the output file name output_file("movigrama_chart.html") # force to show only one plot when multiples executions of the code occur # otherwise the plots will append each time one new calling is done reset_output() # create ColumnDataSource objects directly from Pandas data frames source = ColumnDataSource(df) # use the column DT as index df.set_index('DT', inplace=True) ########################################################################### # # Movigrama Plot # ########################################################################### # build figure of the plot p = figure(x_axis_type='datetime', x_axis_label='days of moviment', y_axis_label='unities movimented', plot_width=1230, plot_height=500, active_scroll='wheel_zoom') # TODO Specify X range (not all plots have 365 days of moviment) # build the Stock Level bar r1 = p.vbar(x='DT', bottom=0, top='STOCK', width=pd.Timedelta(days=1), fill_alpha=0.4, color='paleturquoise', source=source) # build the OUT bar p.vbar(x='DT', bottom=0, top='SOMA_SAI', width=pd.Timedelta(days=1), fill_alpha=0.8, color='crimson', source=source) # build the IN bar p.vbar(x='DT', bottom=0, top='SOMA_ENTRA', width=pd.Timedelta(days=1), fill_alpha=0.8, color='seagreen', source=source) # edit title # adds warehouse title p.add_layout( Title(text=complements['warehouse'], text_font='helvetica', text_font_size='10pt', text_color='orangered', text_alpha=0.5, align='center', text_font_style="italic"), 'above') # adds product title p.add_layout( Title(text=complements['product'], text_font='helvetica', text_font_size='10pt', text_color='orangered', text_alpha=0.5, align='center', text_font_style="italic"), 'above') # adds main title p.add_layout( Title(text='Movigrama Endicon', text_font='helvetica', text_font_size='16pt', text_color='orangered', text_alpha=0.9, align='center', text_font_style="bold"), 'above') # adds horizontal line hline = Span(location=0, line_alpha=0.4, dimension='width', line_color='gray', line_width=3) p.renderers.extend([hline]) # adapt the range to the plot p.x_range.range_padding = 0.1 p.y_range.range_padding = 0.1 # format the plot's outline p.outline_line_width = 4 p.outline_line_alpha = 0.1 p.outline_line_color = 'orangered' # format major labels p.axis.major_label_text_color = 'gray' p.axis.major_label_text_font_style = 'bold' # format labels p.axis.axis_label_text_color = 'gray' p.axis.axis_label_text_font_style = 'bold' # p.xgrid.grid_line_color = None # disable vertical bars # p.ygrid.grid_line_color = None # disable horizontal bars # change placement of minor and major ticks in the plot p.axis.major_tick_out = 10 p.axis.minor_tick_in = -3 p.axis.minor_tick_out = 6 p.axis.minor_tick_line_color = 'gray' # format properly the X datetime axis p.xaxis.formatter = DatetimeTickFormatter(days=['%d/%m'], months=['%m/%Y'], years=['%Y']) # initiate hover object hover = HoverTool() hover.mode = "vline" # activate hover by vertical line hover.tooltips = [("SUM-IN", "@SOMA_ENTRA"), ("SUM-OUT", "@SOMA_SAI"), ("COUNT-IN", "@TRANSACT_ENTRA"), ("COUNT-OUT", "@TRANSACT_SAI"), ("STOCK", "@STOCK"), ("DT", "@DT{%d/%m/%Y}")] # use 'datetime' formatter for 'DT' field hover.formatters = {"DT": 'datetime'} hover.renderers = [r1] # display tooltip only to one render p.add_tools(hover) ########################################################################### # # Demand analysis # ########################################################################### # change to positive values df['out_invert'] = df['SOMA_SAI'] * -1 # moving average with n=30 days df['MA30'] = df['out_invert'].rolling(30).mean().round(0) # moving standard deviation with n=30 days df['MA30_std'] = df['out_invert'].rolling(30).std().round(0) # lower control limit for 1 sigma deviation df['lcl_1sigma'] = (df['MA30'] - df['MA30_std']) # upper control limit for 1 sigma deviation df['ucl_1sigma'] = (df['MA30'] + df['MA30_std']) source = ColumnDataSource(df) p1 = figure(plot_width=1230, plot_height=500, x_range=p.x_range, x_axis_type="datetime", active_scroll='wheel_zoom') # build the Sum_out bar r1 = p1.vbar(x='DT', top='out_invert', width=pd.Timedelta(days=1), color='darkred', line_color='salmon', fill_alpha=0.4, source=source) # build the moving average line p1.line(x='DT', y='MA30', source=source) # build the confidence interval band = Band(base='DT', lower='lcl_1sigma', upper='ucl_1sigma', source=source, level='underlay', fill_alpha=1.0, line_width=1, line_color='black') p1.renderers.extend([band]) # adds title p1.add_layout( Title(text='Demand Variability', text_font='helvetica', text_font_size='16pt', text_color='orangered', text_alpha=0.5, align='center', text_font_style="bold"), 'above') # adds horizontal line hline = Span(location=0, line_alpha=0.4, dimension='width', line_color='gray', line_width=3) p1.renderers.extend([hline]) # format the plot's outline p1.outline_line_width = 4 p1.outline_line_alpha = 0.1 p1.outline_line_color = 'orangered' # format major labels p1.axis.major_label_text_color = 'gray' p1.axis.major_label_text_font_style = 'bold' # format labels p1.axis.axis_label_text_color = 'gray' p1.axis.axis_label_text_font_style = 'bold' # change placement of minor and major ticks in the plot p1.axis.major_tick_out = 10 p1.axis.minor_tick_in = -3 p1.axis.minor_tick_out = 6 p1.axis.minor_tick_line_color = 'gray' # format properly the X datetime axis p1.xaxis.formatter = DatetimeTickFormatter(days=['%d/%m'], months=['%m/%Y'], years=['%Y']) # initiate hover object hover = HoverTool() hover.mode = "vline" # activate hover by vertical line hover.tooltips = [("DEMAND", '@out_invert'), ("UCL 1σ", "@ucl_1sigma"), ("LCL 1σ", "@lcl_1sigma"), ("M AVG 30d", "@MA30"), ("DT", "@DT{%d/%m/%Y}")] # use 'datetime' formatter for 'DT' field hover.formatters = {"DT": 'datetime'} hover.renderers = [r1] # display tooltip only to one render p1.add_tools(hover) ########################################################################### # # Demand grouped by month # ########################################################################### resample_M = df.iloc[:, 0:6].resample('M').sum() # resample to month # create column date as string resample_M['date'] = resample_M.index.strftime('%b/%y').values # moving average with n=3 months resample_M['MA3'] = resample_M['out_invert'].rolling(3).mean() resample_M['MA3'] = np.ceil(resample_M.MA3) # round up the column MA3 # resample to month with mean resample_M['mean'] = np.ceil(resample_M['out_invert'].mean()) # resample to month with standard deviation resample_M['std'] = np.ceil(resample_M['out_invert'].std()) # moving standard deviation with n=30 days resample_M['MA3_std'] = np.ceil(resample_M['out_invert'].rolling(3).std()) # lower control limit for 1 sigma deviation resample_M['lcl_1sigma'] = resample_M['MA3'] - resample_M['MA3_std'] # upper control limit for 1 sigma deviation resample_M['ucl_1sigma'] = resample_M['MA3'] + resample_M['MA3_std'] source = ColumnDataSource(resample_M) p2 = figure(plot_width=1230, plot_height=500, x_range=FactorRange(factors=list(resample_M.date)), title='demand groupped by month') colors = factor_cmap('date', palette=Category20_20, factors=list(resample_M.date)) p2.vbar(x='date', top='out_invert', width=0.8, fill_color=colors, fill_alpha=0.8, source=source, legend=value('OUT')) p2.line(x='date', y='MA3', color='red', line_width=3, line_dash='dotted', source=source, legend=value('MA3')) p2.line(x='date', y='mean', color='blue', line_width=3, line_dash='dotted', source=source, legend=value('mean')) band = Band(base='date', lower='lcl_1sigma', upper='ucl_1sigma', source=source, level='underlay', fill_alpha=1.0, line_width=1, line_color='black') labels1 = LabelSet(x='date', y='MA3', text='MA3', level='glyph', y_offset=5, source=source, render_mode='canvas', text_font_size="8pt", text_color='darkred') labels2 = LabelSet(x='date', y='out_invert', text='out_invert', level='glyph', y_offset=5, source=source, render_mode='canvas', text_font_size="8pt", text_color='gray') low_box = BoxAnnotation( top=resample_M['mean'].iloc[0] - resample_M['std'].iloc[0], # analysis:ignore fill_alpha=0.1, fill_color='red') mid_box = BoxAnnotation( bottom=resample_M['mean'].iloc[0] - resample_M['std'].iloc[0], # analysis:ignore top=resample_M['mean'].iloc[0] + resample_M['std'].iloc[0], # analysis:ignore fill_alpha=0.1, fill_color='green') high_box = BoxAnnotation( bottom=resample_M['mean'].iloc[0] + resample_M['std'].iloc[0], # analysis:ignore fill_alpha=0.1, fill_color='red') p2.renderers.extend([band, labels1, labels2, low_box, mid_box, high_box]) p2.legend.click_policy = "hide" p2.legend.background_fill_alpha = 0.4 p2.add_layout( Title(text='Demand Grouped by Month', text_font='helvetica', text_font_size='16pt', text_color='orangered', text_alpha=0.5, align='center', text_font_style="bold"), 'above') # adds horizontal line hline = Span(location=0, line_alpha=0.4, dimension='width', line_color='gray', line_width=3) p2.renderers.extend([hline]) # format the plot's outline p2.outline_line_width = 4 p2.outline_line_alpha = 0.1 p2.outline_line_color = 'orangered' # format major labels p2.axis.major_label_text_color = 'gray' p2.axis.major_label_text_font_style = 'bold' # format labels p2.axis.axis_label_text_color = 'gray' p2.axis.axis_label_text_font_style = 'bold' # change placement of minor and major ticks in the plot p2.axis.major_tick_out = 10 p2.axis.minor_tick_in = -3 p2.axis.minor_tick_out = 6 p2.axis.minor_tick_line_color = 'gray' # initiate hover object # TODO develop hoverTool # hover = HoverTool() # hover.mode = "vline" # activate hover by vertical line # hover.tooltips = [("SUM-IN", "@SOMA_ENTRA"), # ("SUM-OUT", "@SOMA_SAI"), # ("COUNT-IN", "@TRANSACT_ENTRA"), # ("COUNT-OUT", "@TRANSACT_SAI"), # ("STOCK", "@STOCK")] # hover.renderers = [r1] # display tooltip only to one render # p2.add_tools(hover) ########################################################################### # # Plot figures # ########################################################################### # put the results in a column and show show(column(p, p1, p2)) # show(p) # plot action print('plot finished')
def test_add_annotation(self): """""" v = self.cls(self.data, x="sample") v.add_annotation(Span(location=500, dimension="height")) v.make_layout()
def nepal_cases_with_events(cases_dataframe): """ This function, creates a plot showing number of cases vs date (time), with vertical lines and annotation blocks showing major festivals and events """ # create a figure object with width and height cases_with_events_plot = figure(x_axis_type="datetime", width=1000, height=400, sizing_mode='fixed') # creating columnDataSource object, for the dataframes cases_source = ColumnDataSource(cases_dataframe) init_value = (cases_dataframe['Date'].min(), cases_dataframe['Date'].max()) # configuring date range slider with start date end date and value date_range_slider = DateRangeSlider(start=init_value[0], end=init_value[1], value=init_value) date_filter = BooleanFilter(booleans=[True] * cases_dataframe.shape[0]) # not use scientific numbers on Y-axis cases_with_events_plot.yaxis.formatter = BasicTickFormatter( use_scientific=False) # whenever a slider value updates. The date range sliders, value changes. date_range_slider.js_on_change( "value", CustomJS(args=dict(f=date_filter, cases_source=cases_source), code="""\ const [start, end] = cb_obj.value; f.booleans = Array.from(cases_source.data['Date']).map(d => (d >= start && d <= end)); // Needed because of https://github.com/bokeh/bokeh/issues/7273 cases_source.change.emit(); """)) # name and field pairs for the Hover tool tooltips = [('Date', '@Date{%F}'), ('Nepal', "@Nepal")] # formatting scheme of date column formatters = {'@Date': 'datetime'} # create a Hover tool for the figure with the tooltips and specify the formatting scheme cases_with_events_plot.add_tools( HoverTool(tooltips=tooltips, formatters=formatters, mode='vline')) cases_with_events_plot.title.text = 'Confirmed covid Cases' cases_with_events_plot.title.text_color = "midnightblue" cases_with_events_plot.title.text_font_size = "25px" cases_with_events_plot.xaxis.axis_label = 'Date' cases_with_events_plot.yaxis.axis_label = 'Confirmed Casees' # add a line renderer using the cases_source's two columns with a label, color and line cases_with_events_plot.circle(x='Date', y='Nepal', source=cases_source, view=CDSView(source=cases_source, filters=[date_filter]), color='purple', line_width=0.5) # create a box annotation between the left date to the right date. first_lockdown_mid = BoxAnnotation( top=400000, left=datetime(2020, 3, 24).timestamp() * 1000, right=datetime(2020, 7, 21).timestamp() * 1000, fill_alpha=0.1, fill_color='gray') # add the box annotation to the plot cases_with_events_plot.renderers.extend([first_lockdown_mid]) # label the box annotation in the legend cases_with_events_plot.square(legend_label="Lockdown", color='gray') # create a box annotation between the left date to the right date. tihar = BoxAnnotation(top=400000, left=datetime(2020, 11, 13).timestamp() * 1000, right=datetime(2020, 11, 17).timestamp() * 1000, fill_alpha=0.1, fill_color='blue') # add the box annotation to the plot cases_with_events_plot.renderers.extend([tihar]) # label the box annotation in the legend cases_with_events_plot.square(legend_label="Tihar", color='blue') # create a box annotation between the left date to the right date. dashain = BoxAnnotation(top=400000, left=datetime(2020, 10, 23).timestamp() * 1000, right=datetime(2020, 10, 27).timestamp() * 1000, fill_alpha=0.1, fill_color='red') # add the box annotation to the plot cases_with_events_plot.renderers.extend([dashain]) # label the box annotation in the legend cases_with_events_plot.square(legend_label="Dashain", color='pink') # create a span indra_jatra = Span(location=date(2020, 9, 1), dimension='height', line_color='Yellow', line_dash='dashed', line_width=1.5) # label the span in the legend cases_with_events_plot.line(legend_label="Indra Jatra", line_dash=[4, 4], line_color="yellow", line_width=2) # add the span to the plot cases_with_events_plot.add_layout(indra_jatra) # create a span wedding_season = Span(location=date(2021, 3, 23), dimension='height', line_color='orange', line_dash='dashed', line_width=1.5) # label the span in the legend cases_with_events_plot.line(legend_label="Wedding season begins", line_dash=[4, 4], line_color="orange", line_width=2) # add the span to the plot cases_with_events_plot.add_layout(wedding_season) cases_with_events_plot.line(legend_label="Beginning of Pahachare", line_dash=[4, 4], line_color="Blue", line_width=2) pahachare = Span(location=date(2021, 4, 10), dimension='height', line_color='blue', line_dash='dashed', line_width=1.5) cases_with_events_plot.add_layout(pahachare) cases_with_events_plot.line(legend_label="Holi", line_dash=[4, 4], line_color="brown", line_width=2) holi = Span(location=date(2021, 3, 28), dimension='height', line_color='brown', line_dash='dashed', line_width=1.5) cases_with_events_plot.add_layout(holi) cases_with_events_plot.line(legend_label="Biska Jatra", line_dash=[4, 4], line_color="purple", line_width=2) biska_jatra = Span(location=date(2021, 4, 13), dimension='height', line_color='purple', line_dash='dashed', line_width=1.5) cases_with_events_plot.add_layout(biska_jatra) cases_with_events_plot.line(legend_label="Nepali New Year", line_dash=[4, 4], line_color="Green", line_width=2) nepali_new_year = Span(location=date(2021, 4, 14), dimension='height', line_color='Green', line_dash='dashed', line_width=1.5) cases_with_events_plot.add_layout(nepali_new_year) cases_with_events_plot.line(legend_label="Machendranath Jatra", line_dash=[4, 4], line_color="red", line_width=2) machendranath = Span(location=date(2021, 4, 20), dimension='height', line_color='red', line_dash='dashed', line_width=1.5) cases_with_events_plot.add_layout(machendranath) cases_with_events_plot.line(legend_label="Inauguration of Dharahara", line_dash=[4, 4], line_color="black", line_width=2) inauguration = Span(location=date(2021, 4, 24), dimension='height', line_color='black', line_dash='dashed', line_width=1.5) cases_with_events_plot.add_layout(inauguration) # remove the toolbar cases_with_events_plot.toolbar_location = None cases_with_events_plot.legend.location = "left" return column(cases_with_events_plot, date_range_slider)
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)): 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)[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) 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 = 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_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, ): 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) trace_kwargs.setdefault("line_width", linewidth) plot_kwargs.setdefault("line_width", linewidth) if backend_kwargs is None: backend_kwargs = dict() backend_kwargs.setdefault("tools", rcParams["plot.bokeh.tools"]) backend_kwargs.setdefault("output_backend", rcParams["plot.bokeh.output_backend"]) backend_kwargs.setdefault( "height", int(figsize[1] * rcParams["plot.bokeh.figure.dpi"] // len(plotters))) backend_kwargs.setdefault( "width", int(figsize[0] * rcParams["plot.bokeh.figure.dpi"] // 2)) 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
scatters.append(out) legend = Legend(items=legend_it, location=(0, ymax)) legend.click_policy = "hide" scatter_fig.add_layout(legend, "right") scatter_fig.xgrid.visible = False scatter_fig.ygrid.visible = False # span_kws = dict(line_color="black", line_dash="dashed", line_width=0.5) for b in borders: s = Span(location=b, dimension="height", **span_kws) scatter_fig.add_layout(s) s = Span(location=b, dimension="width", **span_kws) scatter_fig.add_layout(s) # legend = Legend(items=edge_type, location=(0, -60)) # legend.click_policy = "mute" # scatter_fig.add_layout(legend, "right") show(scatter_fig) from bokeh.resources import CDN html = file_html(scatter_fig, CDN, "mb_adj") with open("mb_adj.html", "w") as f: