def addGeneLabels(fig, sourceData): labels = LabelSet(x='x_label', y='y_label', text='label', source=sourceData, render_mode='canvas', text_font_size="18px") slider_font = Slider(start=0, end=64, value=16, step=1, title="Gene label font size in px") slider_angle = Slider(start=0, end=pi / 2, value=0, step=0.01, title="Gene label angle in radian") radio_label_type = RadioGroup(labels=[ "name", "product", "family", "local identifier", "gene ID", "none" ], active=0) slider_angle.js_link('value', labels, 'angle') slider_font.js_on_change( 'value', CustomJS(args=dict(other=labels), code="other.text_font_size = this.value+'px';")) radio_label_type.js_on_click( CustomJS(args=dict(other=labels, source=sourceData), code=""" if(this.active == 5){ source.data['label'] = []; for(var i=0;i<source.data['name'].length;i++){ source.data['label'].push(''); } }else if(this.active == 3){ source.data['label'] = source.data['gene_local_ID']; }else if(this.active == 4){ source.data['label'] = source.data['gene_ID']; } else{ source.data['label'] = source.data[this.labels[this.active]]; } other.source = source; source.change.emit(); """)) label_header = Div(text="<b>Gene labels:</b>") radio_title = Div(text="""Gene labels to use:""", width=200, height=100) labels_block = column(label_header, row(slider_font, slider_angle), column(radio_title, radio_label_type)) fig.add_layout(labels) return labels_block, labels
def sliderPlot(): plot = figure( title="Adjustable Radius Slider Plot", sizing_mode="fixed", plot_width=400, plot_height=400, ) r = plot.circle( [ 1, 2, 3, 4, 5, ], [3, 2, 5, 6, 4], radius=0.2, alpha=0.5, ) slider = Slider(start=0.1, end=2, step=0.01, value=0.2) slider.js_link("value", r.glyph, "radius") return column(plot, slider)
def create(): doc = curdoc() det_data = {} cami_meta = {} def proposal_textinput_callback(_attr, _old, new): nonlocal cami_meta proposal = new.strip() for zebra_proposals_path in pyzebra.ZEBRA_PROPOSALS_PATHS: proposal_path = os.path.join(zebra_proposals_path, proposal) if os.path.isdir(proposal_path): # found it break else: raise ValueError(f"Can not find data for proposal '{proposal}'.") file_list = [] for file in os.listdir(proposal_path): if file.endswith(".hdf"): file_list.append((os.path.join(proposal_path, file), file)) file_select.options = file_list cami_meta = {} proposal_textinput = TextInput(title="Proposal number:", width=210) proposal_textinput.on_change("value", proposal_textinput_callback) def upload_button_callback(_attr, _old, new): nonlocal cami_meta with io.StringIO(base64.b64decode(new).decode()) as file: cami_meta = pyzebra.parse_h5meta(file) file_list = cami_meta["filelist"] file_select.options = [(entry, os.path.basename(entry)) for entry in file_list] upload_div = Div(text="or upload .cami file:", margin=(5, 5, 0, 5)) upload_button = FileInput(accept=".cami", width=200) upload_button.on_change("value", upload_button_callback) def update_image(index=None): if index is None: index = index_spinner.value current_image = det_data["data"][index] proj_v_line_source.data.update(x=np.arange(0, IMAGE_W) + 0.5, y=np.mean(current_image, axis=0)) proj_h_line_source.data.update(x=np.mean(current_image, axis=1), y=np.arange(0, IMAGE_H) + 0.5) image_source.data.update( h=[np.zeros((1, 1))], k=[np.zeros((1, 1))], l=[np.zeros((1, 1))], ) image_source.data.update(image=[current_image]) if main_auto_checkbox.active: im_min = np.min(current_image) im_max = np.max(current_image) display_min_spinner.value = im_min display_max_spinner.value = im_max image_glyph.color_mapper.low = im_min image_glyph.color_mapper.high = im_max if "mf" in det_data: metadata_table_source.data.update(mf=[det_data["mf"][index]]) else: metadata_table_source.data.update(mf=[None]) if "temp" in det_data: metadata_table_source.data.update(temp=[det_data["temp"][index]]) else: metadata_table_source.data.update(temp=[None]) gamma, nu = calculate_pol(det_data, index) omega = np.ones((IMAGE_H, IMAGE_W)) * det_data["omega"][index] image_source.data.update(gamma=[gamma], nu=[nu], omega=[omega]) def update_overview_plot(): h5_data = det_data["data"] n_im, n_y, n_x = h5_data.shape overview_x = np.mean(h5_data, axis=1) overview_y = np.mean(h5_data, axis=2) overview_plot_x_image_source.data.update(image=[overview_x], dw=[n_x], dh=[n_im]) overview_plot_y_image_source.data.update(image=[overview_y], dw=[n_y], dh=[n_im]) if proj_auto_checkbox.active: im_min = min(np.min(overview_x), np.min(overview_y)) im_max = max(np.max(overview_x), np.max(overview_y)) proj_display_min_spinner.value = im_min proj_display_max_spinner.value = im_max overview_plot_x_image_glyph.color_mapper.low = im_min overview_plot_y_image_glyph.color_mapper.low = im_min overview_plot_x_image_glyph.color_mapper.high = im_max overview_plot_y_image_glyph.color_mapper.high = im_max frame_range.start = 0 frame_range.end = n_im frame_range.reset_start = 0 frame_range.reset_end = n_im frame_range.bounds = (0, n_im) scan_motor = det_data["scan_motor"] overview_plot_y.axis[1].axis_label = f"Scanning motor, {scan_motor}" var = det_data[scan_motor] var_start = var[0] var_end = var[-1] + (var[-1] - var[0]) / (n_im - 1) scanning_motor_range.start = var_start scanning_motor_range.end = var_end scanning_motor_range.reset_start = var_start scanning_motor_range.reset_end = var_end # handle both, ascending and descending sequences scanning_motor_range.bounds = (min(var_start, var_end), max(var_start, var_end)) def file_select_callback(_attr, old, new): nonlocal det_data if not new: # skip empty selections return # Avoid selection of multiple indicies (via Shift+Click or Ctrl+Click) if len(new) > 1: # drop selection to the previous one file_select.value = old return if len(old) > 1: # skip unnecessary update caused by selection drop return det_data = pyzebra.read_detector_data(new[0]) if cami_meta and "crystal" in cami_meta: det_data["ub"] = cami_meta["crystal"]["UB"] index_spinner.value = 0 index_spinner.high = det_data["data"].shape[0] - 1 index_slider.end = det_data["data"].shape[0] - 1 zebra_mode = det_data["zebra_mode"] if zebra_mode == "nb": metadata_table_source.data.update(geom=["normal beam"]) else: # zebra_mode == "bi" metadata_table_source.data.update(geom=["bisecting"]) update_image(0) update_overview_plot() file_select = MultiSelect(title="Available .hdf files:", width=210, height=250) file_select.on_change("value", file_select_callback) def index_callback(_attr, _old, new): update_image(new) index_slider = Slider(value=0, start=0, end=1, show_value=False, width=400) index_spinner = Spinner(title="Image index:", value=0, low=0, width=100) index_spinner.on_change("value", index_callback) index_slider.js_link("value_throttled", index_spinner, "value") index_spinner.js_link("value", index_slider, "value") plot = Plot( x_range=Range1d(0, IMAGE_W, bounds=(0, IMAGE_W)), y_range=Range1d(0, IMAGE_H, bounds=(0, IMAGE_H)), plot_height=IMAGE_PLOT_H, plot_width=IMAGE_PLOT_W, toolbar_location="left", ) # ---- tools plot.toolbar.logo = None # ---- axes plot.add_layout(LinearAxis(), place="above") plot.add_layout(LinearAxis(major_label_orientation="vertical"), place="right") # ---- grid lines plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- rgba image glyph image_source = ColumnDataSource( dict( image=[np.zeros((IMAGE_H, IMAGE_W), dtype="float32")], h=[np.zeros((1, 1))], k=[np.zeros((1, 1))], l=[np.zeros((1, 1))], gamma=[np.zeros((1, 1))], nu=[np.zeros((1, 1))], omega=[np.zeros((1, 1))], x=[0], y=[0], dw=[IMAGE_W], dh=[IMAGE_H], )) h_glyph = Image(image="h", x="x", y="y", dw="dw", dh="dh", global_alpha=0) k_glyph = Image(image="k", x="x", y="y", dw="dw", dh="dh", global_alpha=0) l_glyph = Image(image="l", x="x", y="y", dw="dw", dh="dh", global_alpha=0) gamma_glyph = Image(image="gamma", x="x", y="y", dw="dw", dh="dh", global_alpha=0) nu_glyph = Image(image="nu", x="x", y="y", dw="dw", dh="dh", global_alpha=0) omega_glyph = Image(image="omega", x="x", y="y", dw="dw", dh="dh", global_alpha=0) plot.add_glyph(image_source, h_glyph) plot.add_glyph(image_source, k_glyph) plot.add_glyph(image_source, l_glyph) plot.add_glyph(image_source, gamma_glyph) plot.add_glyph(image_source, nu_glyph) plot.add_glyph(image_source, omega_glyph) image_glyph = Image(image="image", x="x", y="y", dw="dw", dh="dh") plot.add_glyph(image_source, image_glyph, name="image_glyph") # ---- projections proj_v = Plot( x_range=plot.x_range, y_range=DataRange1d(), plot_height=150, plot_width=IMAGE_PLOT_W, toolbar_location=None, ) proj_v.add_layout(LinearAxis(major_label_orientation="vertical"), place="right") proj_v.add_layout(LinearAxis(major_label_text_font_size="0pt"), place="below") proj_v.add_layout(Grid(dimension=0, ticker=BasicTicker())) proj_v.add_layout(Grid(dimension=1, ticker=BasicTicker())) proj_v_line_source = ColumnDataSource(dict(x=[], y=[])) proj_v.add_glyph(proj_v_line_source, Line(x="x", y="y", line_color="steelblue")) proj_h = Plot( x_range=DataRange1d(), y_range=plot.y_range, plot_height=IMAGE_PLOT_H, plot_width=150, toolbar_location=None, ) proj_h.add_layout(LinearAxis(), place="above") proj_h.add_layout(LinearAxis(major_label_text_font_size="0pt"), place="left") proj_h.add_layout(Grid(dimension=0, ticker=BasicTicker())) proj_h.add_layout(Grid(dimension=1, ticker=BasicTicker())) proj_h_line_source = ColumnDataSource(dict(x=[], y=[])) proj_h.add_glyph(proj_h_line_source, Line(x="x", y="y", line_color="steelblue")) # add tools hovertool = HoverTool(tooltips=[ ("intensity", "@image"), ("gamma", "@gamma"), ("nu", "@nu"), ("omega", "@omega"), ("h", "@h"), ("k", "@k"), ("l", "@l"), ]) box_edit_source = ColumnDataSource(dict(x=[], y=[], width=[], height=[])) box_edit_glyph = Rect(x="x", y="y", width="width", height="height", fill_alpha=0, line_color="red") box_edit_renderer = plot.add_glyph(box_edit_source, box_edit_glyph) boxedittool = BoxEditTool(renderers=[box_edit_renderer], num_objects=1) def box_edit_callback(_attr, _old, new): if new["x"]: h5_data = det_data["data"] x_val = np.arange(h5_data.shape[0]) left = int(np.floor(new["x"][0])) right = int(np.ceil(new["x"][0] + new["width"][0])) bottom = int(np.floor(new["y"][0])) top = int(np.ceil(new["y"][0] + new["height"][0])) y_val = np.sum(h5_data[:, bottom:top, left:right], axis=(1, 2)) else: x_val = [] y_val = [] roi_avg_plot_line_source.data.update(x=x_val, y=y_val) box_edit_source.on_change("data", box_edit_callback) wheelzoomtool = WheelZoomTool(maintain_focus=False) plot.add_tools( PanTool(), BoxZoomTool(), wheelzoomtool, ResetTool(), hovertool, boxedittool, ) plot.toolbar.active_scroll = wheelzoomtool # shared frame ranges frame_range = Range1d(0, 1, bounds=(0, 1)) scanning_motor_range = Range1d(0, 1, bounds=(0, 1)) det_x_range = Range1d(0, IMAGE_W, bounds=(0, IMAGE_W)) overview_plot_x = Plot( title=Title(text="Projections on X-axis"), x_range=det_x_range, y_range=frame_range, extra_y_ranges={"scanning_motor": scanning_motor_range}, plot_height=400, plot_width=IMAGE_PLOT_W - 3, ) # ---- tools wheelzoomtool = WheelZoomTool(maintain_focus=False) overview_plot_x.toolbar.logo = None overview_plot_x.add_tools( PanTool(), BoxZoomTool(), wheelzoomtool, ResetTool(), ) overview_plot_x.toolbar.active_scroll = wheelzoomtool # ---- axes overview_plot_x.add_layout(LinearAxis(axis_label="Coordinate X, pix"), place="below") overview_plot_x.add_layout(LinearAxis(axis_label="Frame", major_label_orientation="vertical"), place="left") # ---- grid lines overview_plot_x.add_layout(Grid(dimension=0, ticker=BasicTicker())) overview_plot_x.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- rgba image glyph overview_plot_x_image_source = ColumnDataSource( dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_W], dh=[1])) overview_plot_x_image_glyph = Image(image="image", x="x", y="y", dw="dw", dh="dh") overview_plot_x.add_glyph(overview_plot_x_image_source, overview_plot_x_image_glyph, name="image_glyph") det_y_range = Range1d(0, IMAGE_H, bounds=(0, IMAGE_H)) overview_plot_y = Plot( title=Title(text="Projections on Y-axis"), x_range=det_y_range, y_range=frame_range, extra_y_ranges={"scanning_motor": scanning_motor_range}, plot_height=400, plot_width=IMAGE_PLOT_H + 22, ) # ---- tools wheelzoomtool = WheelZoomTool(maintain_focus=False) overview_plot_y.toolbar.logo = None overview_plot_y.add_tools( PanTool(), BoxZoomTool(), wheelzoomtool, ResetTool(), ) overview_plot_y.toolbar.active_scroll = wheelzoomtool # ---- axes overview_plot_y.add_layout(LinearAxis(axis_label="Coordinate Y, pix"), place="below") overview_plot_y.add_layout( LinearAxis( y_range_name="scanning_motor", axis_label="Scanning motor", major_label_orientation="vertical", ), place="right", ) # ---- grid lines overview_plot_y.add_layout(Grid(dimension=0, ticker=BasicTicker())) overview_plot_y.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- rgba image glyph overview_plot_y_image_source = ColumnDataSource( dict(image=[np.zeros((1, 1), dtype="float32")], x=[0], y=[0], dw=[IMAGE_H], dh=[1])) overview_plot_y_image_glyph = Image(image="image", x="x", y="y", dw="dw", dh="dh") overview_plot_y.add_glyph(overview_plot_y_image_source, overview_plot_y_image_glyph, name="image_glyph") roi_avg_plot = Plot( x_range=DataRange1d(), y_range=DataRange1d(), plot_height=150, plot_width=IMAGE_PLOT_W, toolbar_location="left", ) # ---- tools roi_avg_plot.toolbar.logo = None # ---- axes roi_avg_plot.add_layout(LinearAxis(), place="below") roi_avg_plot.add_layout(LinearAxis(major_label_orientation="vertical"), place="left") # ---- grid lines roi_avg_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) roi_avg_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) roi_avg_plot_line_source = ColumnDataSource(dict(x=[], y=[])) roi_avg_plot.add_glyph(roi_avg_plot_line_source, Line(x="x", y="y", line_color="steelblue")) cmap_dict = { "gray": Greys256, "gray_reversed": Greys256[::-1], "plasma": Plasma256, "cividis": Cividis256, } def colormap_callback(_attr, _old, new): image_glyph.color_mapper = LinearColorMapper(palette=cmap_dict[new]) overview_plot_x_image_glyph.color_mapper = LinearColorMapper( palette=cmap_dict[new]) overview_plot_y_image_glyph.color_mapper = LinearColorMapper( palette=cmap_dict[new]) colormap = Select(title="Colormap:", options=list(cmap_dict.keys()), width=210) colormap.on_change("value", colormap_callback) colormap.value = "plasma" STEP = 1 def main_auto_checkbox_callback(state): if state: display_min_spinner.disabled = True display_max_spinner.disabled = True else: display_min_spinner.disabled = False display_max_spinner.disabled = False update_image() main_auto_checkbox = CheckboxGroup(labels=["Main Auto Range"], active=[0], width=145, margin=[10, 5, 0, 5]) main_auto_checkbox.on_click(main_auto_checkbox_callback) def display_max_spinner_callback(_attr, _old_value, new_value): display_min_spinner.high = new_value - STEP image_glyph.color_mapper.high = new_value display_max_spinner = Spinner( low=0 + STEP, value=1, step=STEP, disabled=bool(main_auto_checkbox.active), width=100, height=31, ) display_max_spinner.on_change("value", display_max_spinner_callback) def display_min_spinner_callback(_attr, _old_value, new_value): display_max_spinner.low = new_value + STEP image_glyph.color_mapper.low = new_value display_min_spinner = Spinner( low=0, high=1 - STEP, value=0, step=STEP, disabled=bool(main_auto_checkbox.active), width=100, height=31, ) display_min_spinner.on_change("value", display_min_spinner_callback) PROJ_STEP = 0.1 def proj_auto_checkbox_callback(state): if state: proj_display_min_spinner.disabled = True proj_display_max_spinner.disabled = True else: proj_display_min_spinner.disabled = False proj_display_max_spinner.disabled = False update_overview_plot() proj_auto_checkbox = CheckboxGroup(labels=["Projections Auto Range"], active=[0], width=145, margin=[10, 5, 0, 5]) proj_auto_checkbox.on_click(proj_auto_checkbox_callback) def proj_display_max_spinner_callback(_attr, _old_value, new_value): proj_display_min_spinner.high = new_value - PROJ_STEP overview_plot_x_image_glyph.color_mapper.high = new_value overview_plot_y_image_glyph.color_mapper.high = new_value proj_display_max_spinner = Spinner( low=0 + PROJ_STEP, value=1, step=PROJ_STEP, disabled=bool(proj_auto_checkbox.active), width=100, height=31, ) proj_display_max_spinner.on_change("value", proj_display_max_spinner_callback) def proj_display_min_spinner_callback(_attr, _old_value, new_value): proj_display_max_spinner.low = new_value + PROJ_STEP overview_plot_x_image_glyph.color_mapper.low = new_value overview_plot_y_image_glyph.color_mapper.low = new_value proj_display_min_spinner = Spinner( low=0, high=1 - PROJ_STEP, value=0, step=PROJ_STEP, disabled=bool(proj_auto_checkbox.active), width=100, height=31, ) proj_display_min_spinner.on_change("value", proj_display_min_spinner_callback) def hkl_button_callback(): index = index_spinner.value h, k, l = calculate_hkl(det_data, index) image_source.data.update(h=[h], k=[k], l=[l]) hkl_button = Button(label="Calculate hkl (slow)", width=210) hkl_button.on_click(hkl_button_callback) def events_list_callback(_attr, _old, new): doc.events_list_spind.value = new events_list = TextAreaInput(rows=7, width=830) events_list.on_change("value", events_list_callback) doc.events_list_hdf_viewer = events_list def add_event_button_callback(): diff_vec = [] p0 = [1.0, 0.0, 1.0] maxfev = 100000 wave = det_data["wave"] ddist = det_data["ddist"] gamma = det_data["gamma"][0] omega = det_data["omega"][0] nu = det_data["nu"][0] chi = det_data["chi"][0] phi = det_data["phi"][0] scan_motor = det_data["scan_motor"] var_angle = det_data[scan_motor] x0 = int(np.floor(det_x_range.start)) xN = int(np.ceil(det_x_range.end)) y0 = int(np.floor(det_y_range.start)) yN = int(np.ceil(det_y_range.end)) fr0 = int(np.floor(frame_range.start)) frN = int(np.ceil(frame_range.end)) data_roi = det_data["data"][fr0:frN, y0:yN, x0:xN] cnts = np.sum(data_roi, axis=(1, 2)) coeff, _ = curve_fit(gauss, range(len(cnts)), cnts, p0=p0, maxfev=maxfev) m = cnts.mean() sd = cnts.std() snr_cnts = np.where(sd == 0, 0, m / sd) frC = fr0 + coeff[1] var_F = var_angle[math.floor(frC)] var_C = var_angle[math.ceil(frC)] frStep = frC - math.floor(frC) var_step = var_C - var_F var_p = var_F + var_step * frStep if scan_motor == "gamma": gamma = var_p elif scan_motor == "omega": omega = var_p elif scan_motor == "nu": nu = var_p elif scan_motor == "chi": chi = var_p elif scan_motor == "phi": phi = var_p intensity = coeff[1] * abs( coeff[2] * var_step) * math.sqrt(2) * math.sqrt(np.pi) projX = np.sum(data_roi, axis=(0, 1)) coeff, _ = curve_fit(gauss, range(len(projX)), projX, p0=p0, maxfev=maxfev) x_pos = x0 + coeff[1] projY = np.sum(data_roi, axis=(0, 2)) coeff, _ = curve_fit(gauss, range(len(projY)), projY, p0=p0, maxfev=maxfev) y_pos = y0 + coeff[1] ga, nu = pyzebra.det2pol(ddist, gamma, nu, x_pos, y_pos) diff_vector = pyzebra.z1frmd(wave, ga, omega, chi, phi, nu) d_spacing = float(pyzebra.dandth(wave, diff_vector)[0]) diff_vector = diff_vector.flatten() * 1e10 dv1, dv2, dv3 = diff_vector diff_vec.append(diff_vector) if events_list.value and not events_list.value.endswith("\n"): events_list.value = events_list.value + "\n" events_list.value = ( events_list.value + f"{x_pos} {y_pos} {intensity} {snr_cnts} {dv1} {dv2} {dv3} {d_spacing}" ) add_event_button = Button(label="Add spind event") add_event_button.on_click(add_event_button_callback) metadata_table_source = ColumnDataSource( dict(geom=[""], temp=[None], mf=[None])) num_formatter = NumberFormatter(format="0.00", nan_format="") metadata_table = DataTable( source=metadata_table_source, columns=[ TableColumn(field="geom", title="Geometry", width=100), TableColumn(field="temp", title="Temperature", formatter=num_formatter, width=100), TableColumn(field="mf", title="Magnetic Field", formatter=num_formatter, width=100), ], width=300, height=50, autosize_mode="none", index_position=None, ) # Final layout import_layout = column(proposal_textinput, upload_div, upload_button, file_select) layout_image = column( gridplot([[proj_v, None], [plot, proj_h]], merge_tools=False)) colormap_layout = column( colormap, main_auto_checkbox, row(display_min_spinner, display_max_spinner), proj_auto_checkbox, row(proj_display_min_spinner, proj_display_max_spinner), ) layout_controls = column( row(metadata_table, index_spinner, column(Spacer(height=25), index_slider)), row(add_event_button, hkl_button), row(events_list), ) layout_overview = column( gridplot( [[overview_plot_x, overview_plot_y]], toolbar_options=dict(logo=None), merge_tools=True, toolbar_location="left", ), ) tab_layout = row( column(import_layout, colormap_layout), column(layout_overview, layout_controls), column(roi_avg_plot, layout_image), ) return Panel(child=tab_layout, title="hdf viewer")
# Create our Bokeh figure p = figure(plot_height=800, plot_width=800, title = "Protocol bytes vs packets", tools="pan,wheel_zoom,box_zoom,reset,hover", tooltips="Bytes = @dst_bytes - Packets = @dst_packets, Port = @dst_port", toolbar_location="below") # Add scatter object to our figure s = p.scatter("dst_bytes", "dst_packets", source=ColumnDataSource(scatter_data), legend_field="dst_port", fill_alpha=0.8, size=7, fill_color='colors', line_color='colors') # Format axes p.xaxis.axis_label = 'Bytes' p.yaxis.axis_label = 'Packets' # Link the value of our slider to the size value in our scatter object slider.js_link('value', s.glyph, 'size') # Display the slider and plot togeher in a column layout show(column(slider, p)) Bokeh also has a number of integrations to make plotting simple. One of these that is particularly useful when investigating network data is [integration with Networkx]("https://docs.bokeh.org/en/latest/docs/user_guide/graph.html?highlight=networkx").</br> Bokeh can take a Networkx graph and plot it on a figure, in addition you can apply a number of Bokeh's interactive options to this allowing for interactive networkx plots. # Create a edgelist from our dataset edgelist= pd.DataFrame({"source": clean_data['src_ip'].to_list(), "target": clean_data['dst_ip'].to_list(), "weight":clean_data['total_bytes'].to_list()}) # Create networkx graph from our edgelist G = nx.from_pandas_edgelist(edgelist) # Create our Bokeh figure p = figure(title="Network node communication graph", x_range=(-2.5,2.5), y_range=(-2.5,2.5)) # Set our hover items and add it to the plot node_hover_tool = HoverTool(tooltips=[("IP address", "@index")])
start=0, end=90, step=10) # plotting widgets row_color_widget = ColorPicker(title="Row Color") column_color_widget = ColorPicker(title="Column Color") row_color_widget.js_link('color', horizontal_lines.glyph, 'line_color') column_color_widget.js_link('color', vertical_lines.glyph, 'line_color') line_thickness = Slider(title="Line Thickness", value=1, start=0, end=10, step=1) line_thickness.js_link('value', vertical_lines.glyph, 'line_width') line_thickness.js_link('value', horizontal_lines.glyph, 'line_width') # Set up callbacks def update_data(attrname, old, new): # Get the current slider values ll = line_length.value lg = line_gap.value rd = row_density.value cd = column_density.value lines.make_lines(ll, lg, rd, cd) horizontal_source.data = dict(
# create another new plot and add a renderer right = figure(tools=TOOLS, plot_width=300, plot_height=300, title=None) right.circle('x', 'y1', source=source) p = gridplot([[left, right]]) show(p) # Linked properties - Link values of Bokeh model properties together, so they # remain synchronzed, using js_link. output_file("JS_link.html") plot = figure(plot_width=400, plot_height=400) r = plot.circle([1, 2, 3, 4, 5], [3, 2, 5, 6, 4], radius=0.2, alpha=0.5) slider = Slider(start=0.1, end=2, step=0.01, value=0.2) # method js_link(attr, other, other_attr) # @brief Link 2 Bokeh model properties using JavaScript. # @details This is a convenience method that simplifies adding a CustomJS # callback to update 1 Bokeh model property whenever another changes value. # Parameters * attr(str) - The name of a Bokeh property on this model # * other (Model) - A Bokeh model to link to self.attr # * other_attr(str) - The property on other to link together. slider.js_link('value', r.glyph, 'radius') show(column(plot, slider))
def mast_bokeh(eph, mast_results, stcs=None, display=False): # Function to produce a Bokeh plot of MAST results with the target path p = figure(plot_width=700, x_axis_label="RA (deg)", y_axis_label="Dec (deg)") # Target path eph_data = { 'eph_x': eph['RA'], 'eph_y': eph['DEC'], 'Date': eph['datetime_str'] } eph_plot1 = p.line(x='eph_x', y='eph_y', source=eph_data, line_width=2, line_color='black', legend=eph['targetname'][0]) eph_plot2 = p.circle(x='eph_x', y='eph_y', source=eph_data, fill_color="black", size=12, legend=eph['targetname'][0]) p.add_tools( HoverTool(renderers=[eph_plot1, eph_plot2], tooltips=[('Date', "@Date")])) # Target footprint patch_xs = parse_s_region(stcs)['ra'] patch_ys = parse_s_region(stcs)['dec'] stcs_data = {'stcs_x': [patch_xs], 'stcs_y': [patch_ys]} p.patches('stcs_x', 'stcs_y', source=stcs_data, fill_alpha=0., line_color="grey", line_width=0.8, line_dash='dashed', legend='Search Area') # Prepare MAST footprints obsDF = mast_results.to_pandas() obsDF['coords'] = obsDF.apply(lambda x: parse_s_region(x['s_region']), axis=1) for col in mast_results.colnames: if isinstance(obsDF[col][0], bytes): obsDF[col] = obsDF[col].str.decode('utf-8') # Loop over missions, coloring each separately mast_plots = [] for mission, color in zip(obsDF['obs_collection'].unique(), palette): ind = obsDF['obs_collection'] == mission # Some missions have very complex STCS and need to be treated separately if mission in ('Kepler', 'K2', 'K2FFI'): plot_data = _individual_plot_data(obsDF[ind]) for data in plot_data: mast_plots.append( p.patches('x', 'y', source=data, legend=mission, fill_color=color, fill_alpha=0.3, line_color="white", line_width=0.5)) else: # Add patches with the observation footprings patch_xs = [c['ra'] for c in obsDF['coords'][ind]] patch_ys = [c['dec'] for c in obsDF['coords'][ind]] data = { 'x': patch_xs, 'y': patch_ys, 'obs_collection': obsDF['obs_collection'][ind], 'instrument_name': obsDF['instrument_name'][ind], 'obs_id': obsDF['obs_id'][ind], 'target_name': obsDF['target_name'][ind], 'proposal_pi': obsDF['proposal_pi'][ind], 'obs_mid_date': obsDF['obs_mid_date'][ind], 'filters': obsDF['filters'][ind] } mast_plots.append( p.patches('x', 'y', source=data, legend=mission, fill_color=color, fill_alpha=0.3, line_color="white", line_width=0.5)) # Add hover tooltip for MAST observations tooltip = [("obs_id", "@obs_id"), ("target_name", "@target_name"), ("instrument_name", "@instrument_name"), ("filters", "@filters"), ('obs_mid_date', '@obs_mid_date')] p.add_tools(HoverTool(renderers=mast_plots, tooltips=tooltip)) # Additional settings p.legend.click_policy = "hide" p.x_range.flipped = True # Slider for alpha settings slider = Slider(start=0, end=1, step=0.01, value=0.3, title="Footprint opacity") for i in range(len(mast_plots)): slider.js_link('value', mast_plots[i].glyph, 'fill_alpha') final = column(p, slider) if display: output_notebook() show(final) else: return final
r_by_station = plot_by_station.circle( grouped_data_by_start_station['Station'], grouped_data_by_start_station['Tripduration'] % 60, line_color=mapper_y, color=mapper_y, alpha=0.5) plot_by_station.xaxis.major_label_orientation = 1.2 plot_by_station.toolbar_location = None hover = HoverTool() hover.tooltips = [('Duration', '@y')] plot_by_station.add_tools(hover) slider = Slider(start=0.1, end=2, step=0.01, value=0.3) slider.js_link('value', r_by_station.glyph, 'radius') color_bar = ColorBar(color_mapper=mapper_y['transform'], width=8, location=(0, 0)) plot_by_station.add_layout(color_bar, 'right') # The amount of trips by station amount_of_trips = df.groupby('Station').size().to_frame().reset_index() amount_of_trips.columns = ["Station", "Trips"] plot_trips_by_stations = figure( plot_width=900, plot_height=800, x_range=amount_of_trips['Station'], title="Amount of trips done in December 2019 from stations")
# create another new plot and add a renderer right = figure(tools=TOOLS, plot_width=300, plot_height=300, title=None) right.circle('x', 'y1', source=source) p = gridplot([[left, right]]) show(p) # Linked properties - Link values of Bokeh model properties together, so they # remain synchronzed, using js_link. output_file("JS_link.html") plot = figure(plot_width=400, plot_height=400) r = plot.circle([1,2,3,4,5], [3,2,5,6,4], radius=0.2, alpha=0.5) slider = Slider(start=0.1, end=2, step=0.01, value=0.2) # method js_link(attr, other, other_attr) # @brief Link 2 Bokeh model properties using JavaScript. # @details This is a convenience method that simplifies adding a CustomJS # callback to update 1 Bokeh model property whenever another changes value. # Parameters * attr(str) - The name of a Bokeh property on this model # * other (Model) - A Bokeh model to link to self.attr # * other_attr(str) - The property on other to link together. slider.js_link('value', r.glyph, 'radius') show(column(plot, slider))
m.circle(x=-9754910, y=5142738, size=10, color='orange') show(m) Interactive Widgets In [91]: # change size of scatter plot circles from bokeh.layouts import column from bokeh.models import Slider # create figure and plot change_plot_size = figure(plot_width=600, plot_height=300) change_plot_size_r = change_plot_size.circle([1,2,3,4,5], [3,2,5,6,4], radius=0.1, alpha=0.5) # create widget and link slider = Slider(start=0.1, end=1, step=0.01, value=0.2) slider.js_link('value', change_plot_size_r.glyph, 'radius') show(column(change_plot_size, slider)) In [86]: from sklearn import linear_model from bokeh.layouts import layout from bokeh.models import Toggle import numpy as np output_notebook() # data x = [1,2,3,4,5,6,7,8,9,10] X = np.array(x).reshape(-1, 1) y = [2,2,4,1,5,6,8,2,3,7] Y = np.array(y).reshape(-1, 1)
def addGenomeTools(fig, geneRecs, genomeRecs, geneSource, genomeSource, nb, geneLabels): # add genome labels genomeLabels = LabelSet(x='x_label', y='y', x_offset=-20, text='name', text_align="right", source=genomeSource, render_mode='canvas', text_font_size="16px") fig.add_layout(genomeLabels) slider_font = Slider(start=0, end=64, value=16, step=1, title="Genome label font size in px") slider_font.js_on_change( 'value', CustomJS(args=dict(other=genomeLabels), code="other.text_font_size = this.value+'px';")) slider_offset = Slider(start=-400, end=0, value=-20, step=1, title="Genome label offset") slider_offset.js_link('value', genomeLabels, 'x_offset') slider_spacing = Slider(start=1, end=40, value=10, step=1, title="Genomes spacing") slider_spacing.js_on_change( 'value', CustomJS(args=dict(geneRecs=geneRecs, geneSource=geneSource, genomeRecs=genomeRecs, genomeSource=genomeSource, nb_elements=nb, genomeLabels=genomeLabels, geneLabels=geneLabels), code=""" var current_val = genomeSource.data['y'][genomeSource.data['y'].length - 1] / (nb_elements-1); for (let i=0 ; i < genomeSource.data['y'].length ; i++){ genomeSource.data['y'][i] = (genomeSource.data['y'][i] * this.value) / current_val; } for (let i=0 ; i < geneSource.data['y'].length ; i++){ if((geneSource.data['ordered'][i] == 'True' && geneSource.data['strand'][i] == '+') || (geneSource.data['ordered'][i] == 'False' && geneSource.data['strand'][i] == '-') ){ geneSource.data['y'][i] = (((geneSource.data['y'][i]-1) * this.value) / current_val) +1; geneSource.data['y_label'][i] = (((geneSource.data['y_label'][i]-1-1.5) * this.value) / current_val) + 1 + 1.5; }else{ geneSource.data['y'][i] = (((geneSource.data['y'][i]+1) * this.value) / current_val) -1; geneSource.data['y_label'][i] = (((geneSource.data['y_label'][i]+1-1.5) * this.value) / current_val) -1 + 1.5; } } geneRecs.source = geneSource; genomeRecs.source = genomeSource; geneLabels.source = geneSource; genomeLabels.source = genomeSource; geneSource.change.emit(); genomeSource.change.emit(); """)) genome_header = Div(text="<b>Genomes:</b>") return column(genome_header, slider_spacing, slider_font, slider_offset)