def create_lines_chart(data, title, x_name, y_name, y2_name, hover_tool=None, width=1100, height=400): """Creates a bar chart plot with the exact styling for the centcom dashboard. Pass in data as a dictionary, desired plot title, name of x axis, y axis and the hover tool HTML. """ source = ColumnDataSource(data) xdr = FactorRange(factors=list(data[x_name])) ydr = Range1d(start=0, end=max(max(data[y_name]), max(data[y2_name])) * 1.05) tools = [] if hover_tool: tools = [ hover_tool, ] plot = figure(title=title, x_range=xdr, y_range=ydr, plot_width=width, plot_height=height, min_border=0, toolbar_location="above", tools=tools, outline_line_color="#666666") glyph = Line(x=x_name, y=y_name, line_width=6, line_alpha=0.6, line_color="#ffc0cb") glyph2 = Line(x=x_name, y=y2_name, line_width=6, line_alpha=0.6, line_color="#013220") glyph1a = Scatter(x=x_name, y=y_name, size=7, marker="square", fill_color="#ffc0cb") glyph2a = Scatter(x=x_name, y=y2_name, size=7, marker="square", fill_color="#013220") plot.add_glyph(source, glyph) plot.add_glyph(source, glyph2) plot.add_glyph(source, glyph1a) plot.add_glyph(source, glyph2a) plot.add_tools(WheelZoomTool()) plot.add_tools(BoxZoomTool()) plot.add_tools(ZoomOutTool()) xaxis = LinearAxis() yaxis = LinearAxis() plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) plot.toolbar.logo = None plot.min_border_top = 0 plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = "#999999" plot.yaxis.axis_label = "Observed and Fitted" plot.ygrid.grid_line_alpha = 0.1 plot.xaxis.axis_label = "" plot.xaxis.major_label_orientation = 1 return plot
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(_attr, _old_value, new_value): scans_dropdown.label = new_value scans_dropdown = Dropdown(label="ECO scans", button_type="default", menu=[]) scans_dropdown.on_change("value", 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) # Calibrate button def calibrate_button_callback(): try: palm.calibrate_etof_eco(eco_scan_filename=os.path.join( path_textinput.value, scans_dropdown.value)) 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(_attr, _old_value, new_value): 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(), ) # Drop selection, so that this callback can be triggered again on the same dropdown menu # item from the user perspective load_dropdown.value = "" 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_change("value", 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( path_textinput, scans_dropdown, 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 create(): det_data = [] fit_params = {} js_data = ColumnDataSource(data=dict(content=["", ""], fname=["", ""])) def proposal_textinput_callback(_attr, _old, new): 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((".ccl", ".dat")): file_list.append((os.path.join(proposal_path, file), file)) file_select.options = file_list file_open_button.disabled = False file_append_button.disabled = False proposal_textinput = TextInput(title="Proposal number:", width=210) proposal_textinput.on_change("value", proposal_textinput_callback) def _init_datatable(): scan_list = [s["idx"] for s in det_data] file_list = [] for scan in det_data: file_list.append(os.path.basename(scan["original_filename"])) scan_table_source.data.update( file=file_list, scan=scan_list, param=[None] * len(scan_list), fit=[0] * len(scan_list), export=[True] * len(scan_list), ) scan_table_source.selected.indices = [] scan_table_source.selected.indices = [0] scan_motor_select.options = det_data[0]["scan_motors"] scan_motor_select.value = det_data[0]["scan_motor"] param_select.value = "user defined" file_select = MultiSelect(title="Available .ccl/.dat files:", width=210, height=250) def file_open_button_callback(): nonlocal det_data det_data = [] for f_name in file_select.value: with open(f_name) as file: base, ext = os.path.splitext(f_name) if det_data: append_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(append_data, monitor_spinner.value) det_data.extend(append_data) else: det_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(det_data, monitor_spinner.value) js_data.data.update( fname=[base + ".comm", base + ".incomm"]) _init_datatable() append_upload_button.disabled = False file_open_button = Button(label="Open New", width=100, disabled=True) file_open_button.on_click(file_open_button_callback) def file_append_button_callback(): for f_name in file_select.value: with open(f_name) as file: _, ext = os.path.splitext(f_name) append_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(append_data, monitor_spinner.value) det_data.extend(append_data) _init_datatable() file_append_button = Button(label="Append", width=100, disabled=True) file_append_button.on_click(file_append_button_callback) def upload_button_callback(_attr, _old, new): nonlocal det_data det_data = [] for f_str, f_name in zip(new, upload_button.filename): with io.StringIO(base64.b64decode(f_str).decode()) as file: base, ext = os.path.splitext(f_name) if det_data: append_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(append_data, monitor_spinner.value) det_data.extend(append_data) else: det_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(det_data, monitor_spinner.value) js_data.data.update( fname=[base + ".comm", base + ".incomm"]) _init_datatable() append_upload_button.disabled = False upload_div = Div(text="or upload new .ccl/.dat files:", margin=(5, 5, 0, 5)) upload_button = FileInput(accept=".ccl,.dat", multiple=True, width=200) upload_button.on_change("value", upload_button_callback) def append_upload_button_callback(_attr, _old, new): for f_str, f_name in zip(new, append_upload_button.filename): with io.StringIO(base64.b64decode(f_str).decode()) as file: _, ext = os.path.splitext(f_name) append_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(append_data, monitor_spinner.value) det_data.extend(append_data) _init_datatable() append_upload_div = Div(text="append extra files:", margin=(5, 5, 0, 5)) append_upload_button = FileInput(accept=".ccl,.dat", multiple=True, width=200, disabled=True) append_upload_button.on_change("value", append_upload_button_callback) def monitor_spinner_callback(_attr, _old, new): if det_data: pyzebra.normalize_dataset(det_data, new) _update_plot() monitor_spinner = Spinner(title="Monitor:", mode="int", value=100_000, low=1, width=145) monitor_spinner.on_change("value", monitor_spinner_callback) def scan_motor_select_callback(_attr, _old, new): if det_data: for scan in det_data: scan["scan_motor"] = new _update_plot() scan_motor_select = Select(title="Scan motor:", options=[], width=145) scan_motor_select.on_change("value", scan_motor_select_callback) def _update_table(): fit_ok = [(1 if "fit" in scan else 0) for scan in det_data] scan_table_source.data.update(fit=fit_ok) def _update_plot(): _update_single_scan_plot(_get_selected_scan()) _update_overview() def _update_single_scan_plot(scan): scan_motor = scan["scan_motor"] y = scan["counts"] x = scan[scan_motor] plot.axis[0].axis_label = scan_motor plot_scatter_source.data.update(x=x, y=y, y_upper=y + np.sqrt(y), y_lower=y - np.sqrt(y)) fit = scan.get("fit") if fit is not None: x_fit = np.linspace(x[0], x[-1], 100) plot_fit_source.data.update(x=x_fit, y=fit.eval(x=x_fit)) x_bkg = [] y_bkg = [] xs_peak = [] ys_peak = [] comps = fit.eval_components(x=x_fit) for i, model in enumerate(fit_params): if "linear" in model: x_bkg = x_fit y_bkg = comps[f"f{i}_"] elif any(val in model for val in ("gaussian", "voigt", "pvoigt")): xs_peak.append(x_fit) ys_peak.append(comps[f"f{i}_"]) plot_bkg_source.data.update(x=x_bkg, y=y_bkg) plot_peak_source.data.update(xs=xs_peak, ys=ys_peak) fit_output_textinput.value = fit.fit_report() else: plot_fit_source.data.update(x=[], y=[]) plot_bkg_source.data.update(x=[], y=[]) plot_peak_source.data.update(xs=[], ys=[]) fit_output_textinput.value = "" def _update_overview(): xs = [] ys = [] param = [] x = [] y = [] par = [] for s, p in enumerate(scan_table_source.data["param"]): if p is not None: scan = det_data[s] scan_motor = scan["scan_motor"] xs.append(scan[scan_motor]) x.extend(scan[scan_motor]) ys.append(scan["counts"]) y.extend([float(p)] * len(scan[scan_motor])) param.append(float(p)) par.extend(scan["counts"]) if det_data: scan_motor = det_data[0]["scan_motor"] ov_plot.axis[0].axis_label = scan_motor ov_param_plot.axis[0].axis_label = scan_motor ov_plot_mline_source.data.update(xs=xs, ys=ys, param=param, color=color_palette(len(xs))) if y: mapper["transform"].low = np.min([np.min(y) for y in ys]) mapper["transform"].high = np.max([np.max(y) for y in ys]) ov_param_plot_scatter_source.data.update(x=x, y=y, param=par) if y: interp_f = interpolate.interp2d(x, y, par) x1, x2 = min(x), max(x) y1, y2 = min(y), max(y) image = interp_f( np.linspace(x1, x2, ov_param_plot.inner_width // 10), np.linspace(y1, y2, ov_param_plot.inner_height // 10), assume_sorted=True, ) ov_param_plot_image_source.data.update(image=[image], x=[x1], y=[y1], dw=[x2 - x1], dh=[y2 - y1]) else: ov_param_plot_image_source.data.update(image=[], x=[], y=[], dw=[], dh=[]) def _update_param_plot(): x = [] y = [] fit_param = fit_param_select.value for s, p in zip(det_data, scan_table_source.data["param"]): if "fit" in s and fit_param: x.append(p) y.append(s["fit"].values[fit_param]) param_plot_scatter_source.data.update(x=x, y=y) # Main plot plot = Plot( x_range=DataRange1d(), y_range=DataRange1d(only_visible=True), plot_height=450, plot_width=700, ) plot.add_layout(LinearAxis(axis_label="Counts"), place="left") plot.add_layout(LinearAxis(axis_label="Scan motor"), place="below") plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) plot_scatter_source = ColumnDataSource( dict(x=[0], y=[0], y_upper=[0], y_lower=[0])) plot_scatter = plot.add_glyph( plot_scatter_source, Scatter(x="x", y="y", line_color="steelblue")) plot.add_layout( Whisker(source=plot_scatter_source, base="x", upper="y_upper", lower="y_lower")) plot_fit_source = ColumnDataSource(dict(x=[0], y=[0])) plot_fit = plot.add_glyph(plot_fit_source, Line(x="x", y="y")) plot_bkg_source = ColumnDataSource(dict(x=[0], y=[0])) plot_bkg = plot.add_glyph( plot_bkg_source, Line(x="x", y="y", line_color="green", line_dash="dashed")) plot_peak_source = ColumnDataSource(dict(xs=[[0]], ys=[[0]])) plot_peak = plot.add_glyph( plot_peak_source, MultiLine(xs="xs", ys="ys", line_color="red", line_dash="dashed")) fit_from_span = Span(location=None, dimension="height", line_dash="dashed") plot.add_layout(fit_from_span) fit_to_span = Span(location=None, dimension="height", line_dash="dashed") plot.add_layout(fit_to_span) plot.add_layout( Legend( items=[ ("data", [plot_scatter]), ("best fit", [plot_fit]), ("peak", [plot_peak]), ("linear", [plot_bkg]), ], location="top_left", click_policy="hide", )) plot.add_tools(PanTool(), WheelZoomTool(), ResetTool()) plot.toolbar.logo = None # Overview multilines plot ov_plot = Plot(x_range=DataRange1d(), y_range=DataRange1d(), plot_height=450, plot_width=700) ov_plot.add_layout(LinearAxis(axis_label="Counts"), place="left") ov_plot.add_layout(LinearAxis(axis_label="Scan motor"), place="below") ov_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) ov_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) ov_plot_mline_source = ColumnDataSource( dict(xs=[], ys=[], param=[], color=[])) ov_plot.add_glyph(ov_plot_mline_source, MultiLine(xs="xs", ys="ys", line_color="color")) hover_tool = HoverTool(tooltips=[("param", "@param")]) ov_plot.add_tools(PanTool(), WheelZoomTool(), hover_tool, ResetTool()) ov_plot.add_tools(PanTool(), WheelZoomTool(), ResetTool()) ov_plot.toolbar.logo = None # Overview perams plot ov_param_plot = Plot(x_range=DataRange1d(), y_range=DataRange1d(), plot_height=450, plot_width=700) ov_param_plot.add_layout(LinearAxis(axis_label="Param"), place="left") ov_param_plot.add_layout(LinearAxis(axis_label="Scan motor"), place="below") ov_param_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) ov_param_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) ov_param_plot_image_source = ColumnDataSource( dict(image=[], x=[], y=[], dw=[], dh=[])) ov_param_plot.add_glyph( ov_param_plot_image_source, Image(image="image", x="x", y="y", dw="dw", dh="dh")) ov_param_plot_scatter_source = ColumnDataSource(dict(x=[], y=[], param=[])) mapper = linear_cmap(field_name="param", palette=Turbo256, low=0, high=50) ov_param_plot.add_glyph( ov_param_plot_scatter_source, Scatter(x="x", y="y", line_color=mapper, fill_color=mapper, size=10), ) ov_param_plot.add_tools(PanTool(), WheelZoomTool(), ResetTool()) ov_param_plot.toolbar.logo = None # Parameter plot param_plot = Plot(x_range=DataRange1d(), y_range=DataRange1d(), plot_height=400, plot_width=700) param_plot.add_layout(LinearAxis(axis_label="Fit parameter"), place="left") param_plot.add_layout(LinearAxis(axis_label="Parameter"), place="below") param_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) param_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) param_plot_scatter_source = ColumnDataSource(dict(x=[], y=[])) param_plot.add_glyph(param_plot_scatter_source, Scatter(x="x", y="y")) param_plot.add_tools(PanTool(), WheelZoomTool(), ResetTool()) param_plot.toolbar.logo = None def fit_param_select_callback(_attr, _old, _new): _update_param_plot() fit_param_select = Select(title="Fit parameter", options=[], width=145) fit_param_select.on_change("value", fit_param_select_callback) # Plot tabs plots = Tabs(tabs=[ Panel(child=plot, title="single scan"), Panel(child=ov_plot, title="overview"), Panel(child=ov_param_plot, title="overview map"), Panel(child=column(param_plot, row(fit_param_select)), title="parameter plot"), ]) # Scan select def scan_table_select_callback(_attr, old, new): 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 scan_table_source.selected.indices = old return if len(old) > 1: # skip unnecessary update caused by selection drop return _update_plot() def scan_table_source_callback(_attr, _old, _new): _update_preview() scan_table_source = ColumnDataSource( dict(file=[], scan=[], param=[], fit=[], export=[])) scan_table_source.on_change("data", scan_table_source_callback) scan_table = DataTable( source=scan_table_source, columns=[ TableColumn(field="file", title="file", width=150), TableColumn(field="scan", title="scan", width=50), TableColumn(field="param", title="param", editor=NumberEditor(), width=50), TableColumn(field="fit", title="Fit", width=50), TableColumn(field="export", title="Export", editor=CheckboxEditor(), width=50), ], width=410, # +60 because of the index column editable=True, autosize_mode="none", ) def scan_table_source_callback(_attr, _old, _new): if scan_table_source.selected.indices: _update_plot() scan_table_source.selected.on_change("indices", scan_table_select_callback) scan_table_source.on_change("data", scan_table_source_callback) def _get_selected_scan(): return det_data[scan_table_source.selected.indices[0]] def param_select_callback(_attr, _old, new): if new == "user defined": param = [None] * len(det_data) else: param = [scan[new] for scan in det_data] scan_table_source.data["param"] = param _update_param_plot() param_select = Select( title="Parameter:", options=["user defined", "temp", "mf", "h", "k", "l"], value="user defined", width=145, ) param_select.on_change("value", param_select_callback) def fit_from_spinner_callback(_attr, _old, new): fit_from_span.location = new fit_from_spinner = Spinner(title="Fit from:", width=145) fit_from_spinner.on_change("value", fit_from_spinner_callback) def fit_to_spinner_callback(_attr, _old, new): fit_to_span.location = new fit_to_spinner = Spinner(title="to:", width=145) fit_to_spinner.on_change("value", fit_to_spinner_callback) def fitparams_add_dropdown_callback(click): # bokeh requires (str, str) for MultiSelect options new_tag = f"{click.item}-{fitparams_select.tags[0]}" fitparams_select.options.append((new_tag, click.item)) fit_params[new_tag] = fitparams_factory(click.item) fitparams_select.tags[0] += 1 fitparams_add_dropdown = Dropdown( label="Add fit function", menu=[ ("Linear", "linear"), ("Gaussian", "gaussian"), ("Voigt", "voigt"), ("Pseudo Voigt", "pvoigt"), # ("Pseudo Voigt1", "pseudovoigt1"), ], width=145, ) fitparams_add_dropdown.on_click(fitparams_add_dropdown_callback) def fitparams_select_callback(_attr, old, new): # Avoid selection of multiple indicies (via Shift+Click or Ctrl+Click) if len(new) > 1: # drop selection to the previous one fitparams_select.value = old return if len(old) > 1: # skip unnecessary update caused by selection drop return if new: fitparams_table_source.data.update(fit_params[new[0]]) else: fitparams_table_source.data.update( dict(param=[], value=[], vary=[], min=[], max=[])) fitparams_select = MultiSelect(options=[], height=120, width=145) fitparams_select.tags = [0] fitparams_select.on_change("value", fitparams_select_callback) def fitparams_remove_button_callback(): if fitparams_select.value: sel_tag = fitparams_select.value[0] del fit_params[sel_tag] for elem in fitparams_select.options: if elem[0] == sel_tag: fitparams_select.options.remove(elem) break fitparams_select.value = [] fitparams_remove_button = Button(label="Remove fit function", width=145) fitparams_remove_button.on_click(fitparams_remove_button_callback) def fitparams_factory(function): if function == "linear": params = ["slope", "intercept"] elif function == "gaussian": params = ["amplitude", "center", "sigma"] elif function == "voigt": params = ["amplitude", "center", "sigma", "gamma"] elif function == "pvoigt": params = ["amplitude", "center", "sigma", "fraction"] elif function == "pseudovoigt1": params = ["amplitude", "center", "g_sigma", "l_sigma", "fraction"] else: raise ValueError("Unknown fit function") n = len(params) fitparams = dict( param=params, value=[None] * n, vary=[True] * n, min=[None] * n, max=[None] * n, ) if function == "linear": fitparams["value"] = [0, 1] fitparams["vary"] = [False, True] fitparams["min"] = [None, 0] elif function == "gaussian": fitparams["min"] = [0, None, None] return fitparams fitparams_table_source = ColumnDataSource( dict(param=[], value=[], vary=[], min=[], max=[])) fitparams_table = DataTable( source=fitparams_table_source, columns=[ TableColumn(field="param", title="Parameter"), TableColumn(field="value", title="Value", editor=NumberEditor()), TableColumn(field="vary", title="Vary", editor=CheckboxEditor()), TableColumn(field="min", title="Min", editor=NumberEditor()), TableColumn(field="max", title="Max", editor=NumberEditor()), ], height=200, width=350, index_position=None, editable=True, auto_edit=True, ) # start with `background` and `gauss` fit functions added fitparams_add_dropdown_callback(types.SimpleNamespace(item="linear")) fitparams_add_dropdown_callback(types.SimpleNamespace(item="gaussian")) fitparams_select.value = ["gaussian-1"] # add selection to gauss fit_output_textinput = TextAreaInput(title="Fit results:", width=750, height=200) def proc_all_button_callback(): for scan, export in zip(det_data, scan_table_source.data["export"]): if export: pyzebra.fit_scan(scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value) pyzebra.get_area( scan, area_method=AREA_METHODS[area_method_radiobutton.active], lorentz=lorentz_checkbox.active, ) _update_plot() _update_table() for scan in det_data: if "fit" in scan: options = list(scan["fit"].params.keys()) fit_param_select.options = options fit_param_select.value = options[0] break _update_param_plot() proc_all_button = Button(label="Process All", button_type="primary", width=145) proc_all_button.on_click(proc_all_button_callback) def proc_button_callback(): scan = _get_selected_scan() pyzebra.fit_scan(scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value) pyzebra.get_area( scan, area_method=AREA_METHODS[area_method_radiobutton.active], lorentz=lorentz_checkbox.active, ) _update_plot() _update_table() for scan in det_data: if "fit" in scan: options = list(scan["fit"].params.keys()) fit_param_select.options = options fit_param_select.value = options[0] break _update_param_plot() proc_button = Button(label="Process Current", width=145) proc_button.on_click(proc_button_callback) area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5)) area_method_radiobutton = RadioGroup(labels=["Function", "Area"], active=0, width=145) lorentz_checkbox = CheckboxGroup(labels=["Lorentz Correction"], width=145, margin=(13, 5, 5, 5)) export_preview_textinput = TextAreaInput(title="Export file preview:", width=450, height=400) def _update_preview(): with tempfile.TemporaryDirectory() as temp_dir: temp_file = temp_dir + "/temp" export_data = [] for s, export in zip(det_data, scan_table_source.data["export"]): if export: export_data.append(s) # pyzebra.export_1D(export_data, temp_file, "fullprof") exported_content = "" file_content = [] for ext in (".comm", ".incomm"): fname = temp_file + ext if os.path.isfile(fname): with open(fname) as f: content = f.read() exported_content += f"{ext} file:\n" + content else: content = "" file_content.append(content) js_data.data.update(content=file_content) export_preview_textinput.value = exported_content save_button = Button(label="Download File(s)", button_type="success", width=220) save_button.js_on_click( CustomJS(args={"js_data": js_data}, code=javaScript)) fitpeak_controls = row( column(fitparams_add_dropdown, fitparams_select, fitparams_remove_button), fitparams_table, Spacer(width=20), column(fit_from_spinner, lorentz_checkbox, area_method_div, area_method_radiobutton), column(fit_to_spinner, proc_button, proc_all_button), ) scan_layout = column(scan_table, row(monitor_spinner, scan_motor_select, param_select)) import_layout = column( proposal_textinput, file_select, row(file_open_button, file_append_button), upload_div, upload_button, append_upload_div, append_upload_button, ) export_layout = column(export_preview_textinput, row(save_button)) tab_layout = column( row(import_layout, scan_layout, plots, Spacer(width=30), export_layout), row(fitpeak_controls, fit_output_textinput), ) return Panel(child=tab_layout, title="param study")
def create(self): manufacturers = sorted(mpg["manufacturer"].unique()) models = sorted(mpg["model"].unique()) transmissions = sorted(mpg["trans"].unique()) drives = sorted(mpg["drv"].unique()) classes = sorted(mpg["class"].unique()) manufacturer_select = Select(title="Manufacturer:", value="All", options=["All"] + manufacturers) manufacturer_select.on_change('value', self.on_manufacturer_change) model_select = Select(title="Model:", value="All", options=["All"] + models) model_select.on_change('value', self.on_model_change) transmission_select = Select(title="Transmission:", value="All", options=["All"] + transmissions) transmission_select.on_change('value', self.on_transmission_change) drive_select = Select(title="Drive:", value="All", options=["All"] + drives) drive_select.on_change('value', self.on_drive_change) class_select = Select(title="Class:", value="All", options=["All"] + classes) class_select.on_change('value', self.on_class_change) columns = [ TableColumn(field="manufacturer", title="Manufacturer", editor=SelectEditor(options=manufacturers), formatter=StringFormatter(font_style="bold")), TableColumn(field="model", title="Model", editor=StringEditor(completions=models)), TableColumn(field="displ", title="Displacement", editor=NumberEditor(step=0.1), formatter=NumberFormatter(format="0.0")), TableColumn(field="year", title="Year", editor=IntEditor()), TableColumn(field="cyl", title="Cylinders", editor=IntEditor()), TableColumn(field="trans", title="Transmission", editor=SelectEditor(options=transmissions)), TableColumn(field="drv", title="Drive", editor=SelectEditor(options=drives)), TableColumn(field="class", title="Class", editor=SelectEditor(options=classes)), TableColumn(field="cty", title="City MPG", editor=IntEditor()), TableColumn(field="hwy", title="Highway MPG", editor=IntEditor()), ] data_table = DataTable(source=self.source, columns=columns, editable=True) plot = Plot(title=None, x_range= DataRange1d(), y_range=DataRange1d(), plot_width=1000, plot_height=300) # Set up x & y axis plot.add_layout(LinearAxis(), 'below') yaxis = LinearAxis() plot.add_layout(yaxis, 'left') plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) # Add Glyphs cty_glyph = Circle(x="index", y="cty", fill_color="#396285", size=8, fill_alpha=0.5, line_alpha=0.5) hwy_glyph = Circle(x="index", y="hwy", fill_color="#CE603D", size=8, fill_alpha=0.5, line_alpha=0.5) cty = plot.add_glyph(self.source, cty_glyph) hwy = plot.add_glyph(self.source, hwy_glyph) # Add the tools tooltips = [ ("Manufacturer", "@manufacturer"), ("Model", "@model"), ("Displacement", "@displ"), ("Year", "@year"), ("Cylinders", "@cyl"), ("Transmission", "@trans"), ("Drive", "@drv"), ("Class", "@class"), ] cty_hover_tool = HoverTool(renderers=[cty], tooltips=tooltips + [("City MPG", "@cty")]) hwy_hover_tool = HoverTool(renderers=[hwy], tooltips=tooltips + [("Highway MPG", "@hwy")]) select_tool = BoxSelectTool(renderers=[cty, hwy], dimensions=['width']) plot.add_tools(cty_hover_tool, hwy_hover_tool, select_tool) controls = VBox(children=[ manufacturer_select, model_select, transmission_select, drive_select, class_select]) top_panel = HBox(children=[controls, plot]) layout = VBox(children=[top_panel, data_table]) return layout
from bokeh.embed import file_html from bokeh.models import (Circle, ColumnDataSource, CrosshairTool, CustomJS, Grid, HoverTool, Legend, LegendItem, Line, LinearAxis, Plot, Range1d, TapTool, WheelZoomTool) from bokeh.resources import INLINE from bokeh.util.browser import view plot = Plot(x_range=Range1d(-10, 10), y_range=Range1d(-10, 10), plot_width=600, plot_height=600, toolbar_sticky=False) xaxis = LinearAxis() yaxis = LinearAxis() xgrid = Grid(dimension=0, ticker=xaxis.ticker) ygrid = Grid(dimension=1, ticker=yaxis.ticker) plot.add_layout(xaxis, "below") plot.add_layout(yaxis, "left") plot.add_layout(xgrid) plot.add_layout(ygrid) def fds(x, y, e, n): d = [ (x + 0 * e, y + 0 * e, 1, "red", "%s00" % n), (x + 1 * e, y + 1 * e, 1, "blue", "%s01" % n), (x + 2 * e, y + 2 * e, 1, "green", "%s02" % n), (x + 3 * e, y + 3 * e, 1, "violet", "%s03" % n), (x + 4 * e, y + 4 * e, 1, "pink", "%s04" % n),
def large_plot(n): from bokeh.models import (Plot, LinearAxis, Grid, GlyphRenderer, ColumnDataSource, DataRange1d, PanTool, ZoomInTool, ZoomOutTool, WheelZoomTool, BoxZoomTool, BoxSelectTool, SaveTool, ResetTool) from bokeh.models.layouts import Column from bokeh.models.glyphs import Line col = Column() objects = set([col]) for i in xrange(n): source = ColumnDataSource(data=dict(x=[0, i + 1], y=[0, i + 1])) xdr = DataRange1d() ydr = DataRange1d() plot = Plot(x_range=xdr, y_range=ydr) xaxis = LinearAxis(plot=plot) yaxis = LinearAxis(plot=plot) xgrid = Grid(plot=plot, dimension=0) ygrid = Grid(plot=plot, dimension=1) tickers = [ xaxis.ticker, xaxis.formatter, yaxis.ticker, yaxis.formatter ] glyph = Line(x='x', y='y') renderer = GlyphRenderer(data_source=source, glyph=glyph) plot.renderers.append(renderer) pan = PanTool() zoom_in = ZoomInTool() zoom_out = ZoomOutTool() wheel_zoom = WheelZoomTool() box_zoom = BoxZoomTool() box_select = BoxSelectTool() save = SaveTool() reset = ResetTool() tools = [ pan, zoom_in, zoom_out, wheel_zoom, box_zoom, box_select, save, reset ] plot.add_tools(*tools) col.children.append(plot) objects |= set([ xdr, ydr, xaxis, yaxis, xgrid, ygrid, renderer, renderer.view, glyph, source, source.selected, source.selection_policy, plot, plot.x_scale, plot.y_scale, plot.toolbar, plot.title, box_zoom.overlay, box_select.overlay, ] + tickers + tools) return col, objects
def create_bar_chart(data, title, hover_tool, colors): """Creates a bar chart plot with the exact styling for the centcom dashboard. Pass in data as a dictionary, desired plot title, name of x axis, y axis and the hover tool HTML. """ xdr = DataRange1d(bounds='auto') ydr = DataRange1d(bounds='auto') hover = HoverTool(tooltips=""" <div> <p><span style="font-weight: bold;">%s</span> - %s</p> <p>%s million %s passengers</p> </div> """ % ("@airline", "@date{%b %Y}", "$y", "$name"), formatters={'date': 'datetime'}, names=['domestic', 'international', 'total']) tools = [ hover, 'pan', 'box_zoom', 'zoom_in', 'zoom_out', 'wheel_zoom', 'reset' ] plot = figure(title=title, x_range=xdr, y_range=ydr, plot_width=1200, plot_height=800, h_symmetry=False, v_symmetry=False, min_border=0, toolbar_location="above", tools=tools, outline_line_color="#666666", x_axis_type='datetime', border_fill_color='#DBECFC') plot.left[0].formatter.use_scientific = False legendItems = [] for airline in data: color = colors[airline] source = ColumnDataSource(data=data[airline]) legendItems.append(([airline, "Domestic"], (plot.line(x='date', y='domestic', line_color=color, line_width=2, line_alpha=0.6, line_dash='dashed', source=source)))) legendItems.append(([airline, "Domestic"], plot.circle(x='date', y='domestic', size=5, fill_color=color, source=source, name='domestic', line_color=color))) legendItems[-1][1].hover_glyph = Circle(line_width=6, line_color=color, line_alpha=0.2, fill_color=color) source = ColumnDataSource(data=data[airline]) legendItems.append(([airline, "Total"], plot.line(x='date', y='total', line_color=color, line_width=2, line_alpha=0.6, source=source))) legendItems.append(([airline, "Total"], plot.circle(x='date', y='total', size=8, fill_color=color, line_color=color, source=source, name='total'))) legendItems[-1][1].hover_glyph = Circle(line_width=9, line_color=color, line_alpha=0.2, fill_color=color) source = ColumnDataSource(data=data[airline]) legendItems.append(([airline, "International"], plot.line(x='date', y='international', line_color=color, line_width=2, line_alpha=0.6, line_dash='dotted', source=source))) legendItems.append(([airline, "International"], plot.circle(x='date', y='international', size=5, fill_color=color, line_color=color, source=source, name='international'))) legendItems[-1][1].hover_glyph = Circle(line_width=6, line_color=color, line_alpha=0.2, fill_color=color) #Create legend for airline legendAirlines = CategorialLegend(items=legendItems, click_policy='hide') plot.add_layout(legendAirlines, 'right') xaxis = LinearAxis() yaxis = LinearAxis() plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) plot.toolbar.logo = None plot.min_border_top = 0 plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = "#999999" plot.ygrid.grid_line_alpha = 0.1 #Style Y axis plot.yaxis.axis_label = "Number of Passengers (Millions)" plot.yaxis.axis_label_text_font_size = '12pt' plot.yaxis.axis_label_text_font_style = 'normal' #Style X axis plot.xaxis.axis_label = "Year" plot.xaxis.major_label_orientation = 1 plot.xaxis.axis_label_text_font_size = '12pt' plot.xaxis.axis_label_text_font_style = 'normal' plot.xaxis[0].formatter.days = '%b %Y' return plot
def generate_stacked_chart(data: dict, text: dict, width=1200, height=800, chart_type: str = 'Column'): months = data['months'] energy_types = [key for key in sorted(data.keys()) if key != "months"] if len(energy_types) == 2: colors = ["red", "green"] elif len(energy_types) == 4: colors = ["orange", "red", "blue", "green"] else: colors = ['red'] tools = ["pan", "wheel_zoom,save,reset"] plot = figure(title=text['title'], x_range=months, plot_height=height, plot_width=width, h_symmetry=False, v_symmetry=False, min_border=0, toolbar_location="above", tools=tools, sizing_mode='scale_width', outline_line_color="#666666", active_scroll='wheel_zoom', active_drag='pan') if chart_type == 'Column': source = ColumnDataSource(data) renderers = plot.vbar_stack(energy_types, x='months', width=0.8, color=colors, source=source, legend=[item for item in text['legend']] if text.get('legend') else None) for r in renderers: item = r.name tooltips = [("Koszt: ", "@%s{0.00} zł" % item), ("Miesiąc: ", "@months")] if text.get("tooltip", None): additional_tooltips = [ ("{}: ".format(text["tooltip"]["energy_type"]["label"]), text["tooltip"]["energy_type"]["value"]), ("{}: ".format(text["tooltip"]["building"]["label"]), text["tooltip"]["building"]["value"]) ] for t in additional_tooltips: tooltips.insert(0, t) hover = HoverTool(tooltips=tooltips, renderers=[r]) plot.add_tools(hover) elif chart_type == 'Line': r = plot.multi_line( [[month for month in months] for item in energy_types], [data[type_energy] for type_energy in energy_types], color=colors, line_width=4) if text.get('legend', None): legend = Legend(items=[ LegendItem(label=item, renderers=[r], index=index) for index, item in enumerate(text['legend']) ]) plot.add_layout(legend) xaxis = LinearAxis() yaxis = LinearAxis() plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) plot.title.text_font_size = '12pt' plot.toolbar.logo = None plot.min_border_top = 0 plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = "#999999" plot.yaxis.axis_label = text['title'] plot.ygrid.grid_line_alpha = 0.1 plot.xaxis.axis_label = "Miesiąc" plot.xaxis.axis_label_text_font_size = "11pt" plot.xaxis.major_label_orientation = 1 return plot
def create(): det_data = {} fit_params = {} js_data = ColumnDataSource( data=dict(content=["", ""], fname=["", ""], ext=["", ""])) def proposal_textinput_callback(_attr, _old, new): 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((".ccl", ".dat")): file_list.append((os.path.join(proposal_path, file), file)) file_select.options = file_list file_open_button.disabled = False file_append_button.disabled = False proposal_textinput = TextInput(title="Proposal number:", width=210) proposal_textinput.on_change("value", proposal_textinput_callback) def _init_datatable(): scan_list = [s["idx"] for s in det_data] hkl = [f'{s["h"]} {s["k"]} {s["l"]}' for s in det_data] export = [s.get("active", True) for s in det_data] scan_table_source.data.update( scan=scan_list, hkl=hkl, fit=[0] * len(scan_list), export=export, ) scan_table_source.selected.indices = [] scan_table_source.selected.indices = [0] merge_options = [(str(i), f"{i} ({idx})") for i, idx in enumerate(scan_list)] merge_from_select.options = merge_options merge_from_select.value = merge_options[0][0] file_select = MultiSelect(title="Available .ccl/.dat files:", width=210, height=250) def file_open_button_callback(): nonlocal det_data det_data = [] for f_name in file_select.value: with open(f_name) as file: base, ext = os.path.splitext(f_name) if det_data: append_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(append_data, monitor_spinner.value) pyzebra.merge_datasets(det_data, append_data) else: det_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(det_data, monitor_spinner.value) pyzebra.merge_duplicates(det_data) js_data.data.update(fname=[base, base]) _init_datatable() append_upload_button.disabled = False file_open_button = Button(label="Open New", width=100, disabled=True) file_open_button.on_click(file_open_button_callback) def file_append_button_callback(): for f_name in file_select.value: with open(f_name) as file: _, ext = os.path.splitext(f_name) append_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(append_data, monitor_spinner.value) pyzebra.merge_datasets(det_data, append_data) _init_datatable() file_append_button = Button(label="Append", width=100, disabled=True) file_append_button.on_click(file_append_button_callback) def upload_button_callback(_attr, _old, new): nonlocal det_data det_data = [] for f_str, f_name in zip(new, upload_button.filename): with io.StringIO(base64.b64decode(f_str).decode()) as file: base, ext = os.path.splitext(f_name) if det_data: append_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(append_data, monitor_spinner.value) pyzebra.merge_datasets(det_data, append_data) else: det_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(det_data, monitor_spinner.value) pyzebra.merge_duplicates(det_data) js_data.data.update(fname=[base, base]) _init_datatable() append_upload_button.disabled = False upload_div = Div(text="or upload new .ccl/.dat files:", margin=(5, 5, 0, 5)) upload_button = FileInput(accept=".ccl,.dat", multiple=True, width=200) upload_button.on_change("value", upload_button_callback) def append_upload_button_callback(_attr, _old, new): for f_str, f_name in zip(new, append_upload_button.filename): with io.StringIO(base64.b64decode(f_str).decode()) as file: _, ext = os.path.splitext(f_name) append_data = pyzebra.parse_1D(file, ext) pyzebra.normalize_dataset(append_data, monitor_spinner.value) pyzebra.merge_datasets(det_data, append_data) _init_datatable() append_upload_div = Div(text="append extra files:", margin=(5, 5, 0, 5)) append_upload_button = FileInput(accept=".ccl,.dat", multiple=True, width=200, disabled=True) append_upload_button.on_change("value", append_upload_button_callback) def monitor_spinner_callback(_attr, old, new): if det_data: pyzebra.normalize_dataset(det_data, new) _update_plot(_get_selected_scan()) monitor_spinner = Spinner(title="Monitor:", mode="int", value=100_000, low=1, width=145) monitor_spinner.on_change("value", monitor_spinner_callback) def _update_table(): fit_ok = [(1 if "fit" in scan else 0) for scan in det_data] scan_table_source.data.update(fit=fit_ok) def _update_plot(scan): scan_motor = scan["scan_motor"] y = scan["counts"] x = scan[scan_motor] plot.axis[0].axis_label = scan_motor plot_scatter_source.data.update(x=x, y=y, y_upper=y + np.sqrt(y), y_lower=y - np.sqrt(y)) fit = scan.get("fit") if fit is not None: x_fit = np.linspace(x[0], x[-1], 100) plot_fit_source.data.update(x=x_fit, y=fit.eval(x=x_fit)) x_bkg = [] y_bkg = [] xs_peak = [] ys_peak = [] comps = fit.eval_components(x=x_fit) for i, model in enumerate(fit_params): if "linear" in model: x_bkg = x_fit y_bkg = comps[f"f{i}_"] elif any(val in model for val in ("gaussian", "voigt", "pvoigt")): xs_peak.append(x_fit) ys_peak.append(comps[f"f{i}_"]) plot_bkg_source.data.update(x=x_bkg, y=y_bkg) plot_peak_source.data.update(xs=xs_peak, ys=ys_peak) fit_output_textinput.value = fit.fit_report() else: plot_fit_source.data.update(x=[], y=[]) plot_bkg_source.data.update(x=[], y=[]) plot_peak_source.data.update(xs=[], ys=[]) fit_output_textinput.value = "" # Main plot plot = Plot( x_range=DataRange1d(), y_range=DataRange1d(only_visible=True), plot_height=470, plot_width=700, ) plot.add_layout(LinearAxis(axis_label="Counts"), place="left") plot.add_layout(LinearAxis(axis_label="Scan motor"), place="below") plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) plot_scatter_source = ColumnDataSource( dict(x=[0], y=[0], y_upper=[0], y_lower=[0])) plot_scatter = plot.add_glyph( plot_scatter_source, Scatter(x="x", y="y", line_color="steelblue")) plot.add_layout( Whisker(source=plot_scatter_source, base="x", upper="y_upper", lower="y_lower")) plot_fit_source = ColumnDataSource(dict(x=[0], y=[0])) plot_fit = plot.add_glyph(plot_fit_source, Line(x="x", y="y")) plot_bkg_source = ColumnDataSource(dict(x=[0], y=[0])) plot_bkg = plot.add_glyph( plot_bkg_source, Line(x="x", y="y", line_color="green", line_dash="dashed")) plot_peak_source = ColumnDataSource(dict(xs=[[0]], ys=[[0]])) plot_peak = plot.add_glyph( plot_peak_source, MultiLine(xs="xs", ys="ys", line_color="red", line_dash="dashed")) fit_from_span = Span(location=None, dimension="height", line_dash="dashed") plot.add_layout(fit_from_span) fit_to_span = Span(location=None, dimension="height", line_dash="dashed") plot.add_layout(fit_to_span) plot.add_layout( Legend( items=[ ("data", [plot_scatter]), ("best fit", [plot_fit]), ("peak", [plot_peak]), ("linear", [plot_bkg]), ], location="top_left", click_policy="hide", )) plot.add_tools(PanTool(), WheelZoomTool(), ResetTool()) plot.toolbar.logo = None # Scan select def scan_table_select_callback(_attr, old, new): 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 scan_table_source.selected.indices = old return if len(old) > 1: # skip unnecessary update caused by selection drop return _update_plot(det_data[new[0]]) def scan_table_source_callback(_attr, _old, _new): _update_preview() scan_table_source = ColumnDataSource( dict(scan=[], hkl=[], fit=[], export=[])) scan_table_source.on_change("data", scan_table_source_callback) scan_table = DataTable( source=scan_table_source, columns=[ TableColumn(field="scan", title="Scan", width=50), TableColumn(field="hkl", title="hkl", width=100), TableColumn(field="fit", title="Fit", width=50), TableColumn(field="export", title="Export", editor=CheckboxEditor(), width=50), ], width=310, # +60 because of the index column height=350, autosize_mode="none", editable=True, ) scan_table_source.selected.on_change("indices", scan_table_select_callback) def _get_selected_scan(): return det_data[scan_table_source.selected.indices[0]] merge_from_select = Select(title="scan:", width=145) def merge_button_callback(): scan_into = _get_selected_scan() scan_from = det_data[int(merge_from_select.value)] if scan_into is scan_from: print("WARNING: Selected scans for merging are identical") return pyzebra.merge_scans(scan_into, scan_from) _update_plot(_get_selected_scan()) merge_button = Button(label="Merge into current", width=145) merge_button.on_click(merge_button_callback) def restore_button_callback(): pyzebra.restore_scan(_get_selected_scan()) _update_plot(_get_selected_scan()) restore_button = Button(label="Restore scan", width=145) restore_button.on_click(restore_button_callback) def fit_from_spinner_callback(_attr, _old, new): fit_from_span.location = new fit_from_spinner = Spinner(title="Fit from:", width=145) fit_from_spinner.on_change("value", fit_from_spinner_callback) def fit_to_spinner_callback(_attr, _old, new): fit_to_span.location = new fit_to_spinner = Spinner(title="to:", width=145) fit_to_spinner.on_change("value", fit_to_spinner_callback) def fitparams_add_dropdown_callback(click): # bokeh requires (str, str) for MultiSelect options new_tag = f"{click.item}-{fitparams_select.tags[0]}" fitparams_select.options.append((new_tag, click.item)) fit_params[new_tag] = fitparams_factory(click.item) fitparams_select.tags[0] += 1 fitparams_add_dropdown = Dropdown( label="Add fit function", menu=[ ("Linear", "linear"), ("Gaussian", "gaussian"), ("Voigt", "voigt"), ("Pseudo Voigt", "pvoigt"), # ("Pseudo Voigt1", "pseudovoigt1"), ], width=145, ) fitparams_add_dropdown.on_click(fitparams_add_dropdown_callback) def fitparams_select_callback(_attr, old, new): # Avoid selection of multiple indicies (via Shift+Click or Ctrl+Click) if len(new) > 1: # drop selection to the previous one fitparams_select.value = old return if len(old) > 1: # skip unnecessary update caused by selection drop return if new: fitparams_table_source.data.update(fit_params[new[0]]) else: fitparams_table_source.data.update( dict(param=[], value=[], vary=[], min=[], max=[])) fitparams_select = MultiSelect(options=[], height=120, width=145) fitparams_select.tags = [0] fitparams_select.on_change("value", fitparams_select_callback) def fitparams_remove_button_callback(): if fitparams_select.value: sel_tag = fitparams_select.value[0] del fit_params[sel_tag] for elem in fitparams_select.options: if elem[0] == sel_tag: fitparams_select.options.remove(elem) break fitparams_select.value = [] fitparams_remove_button = Button(label="Remove fit function", width=145) fitparams_remove_button.on_click(fitparams_remove_button_callback) def fitparams_factory(function): if function == "linear": params = ["slope", "intercept"] elif function == "gaussian": params = ["amplitude", "center", "sigma"] elif function == "voigt": params = ["amplitude", "center", "sigma", "gamma"] elif function == "pvoigt": params = ["amplitude", "center", "sigma", "fraction"] elif function == "pseudovoigt1": params = ["amplitude", "center", "g_sigma", "l_sigma", "fraction"] else: raise ValueError("Unknown fit function") n = len(params) fitparams = dict( param=params, value=[None] * n, vary=[True] * n, min=[None] * n, max=[None] * n, ) if function == "linear": fitparams["value"] = [0, 1] fitparams["vary"] = [False, True] fitparams["min"] = [None, 0] elif function == "gaussian": fitparams["min"] = [0, None, None] return fitparams fitparams_table_source = ColumnDataSource( dict(param=[], value=[], vary=[], min=[], max=[])) fitparams_table = DataTable( source=fitparams_table_source, columns=[ TableColumn(field="param", title="Parameter"), TableColumn(field="value", title="Value", editor=NumberEditor()), TableColumn(field="vary", title="Vary", editor=CheckboxEditor()), TableColumn(field="min", title="Min", editor=NumberEditor()), TableColumn(field="max", title="Max", editor=NumberEditor()), ], height=200, width=350, index_position=None, editable=True, auto_edit=True, ) # start with `background` and `gauss` fit functions added fitparams_add_dropdown_callback(types.SimpleNamespace(item="linear")) fitparams_add_dropdown_callback(types.SimpleNamespace(item="gaussian")) fitparams_select.value = ["gaussian-1"] # add selection to gauss fit_output_textinput = TextAreaInput(title="Fit results:", width=750, height=200) def proc_all_button_callback(): for scan, export in zip(det_data, scan_table_source.data["export"]): if export: pyzebra.fit_scan(scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value) pyzebra.get_area( scan, area_method=AREA_METHODS[area_method_radiobutton.active], lorentz=lorentz_checkbox.active, ) _update_plot(_get_selected_scan()) _update_table() proc_all_button = Button(label="Process All", button_type="primary", width=145) proc_all_button.on_click(proc_all_button_callback) def proc_button_callback(): scan = _get_selected_scan() pyzebra.fit_scan(scan, fit_params, fit_from=fit_from_spinner.value, fit_to=fit_to_spinner.value) pyzebra.get_area( scan, area_method=AREA_METHODS[area_method_radiobutton.active], lorentz=lorentz_checkbox.active, ) _update_plot(scan) _update_table() proc_button = Button(label="Process Current", width=145) proc_button.on_click(proc_button_callback) area_method_div = Div(text="Intensity:", margin=(5, 5, 0, 5)) area_method_radiobutton = RadioGroup(labels=["Function", "Area"], active=0, width=145) lorentz_checkbox = CheckboxGroup(labels=["Lorentz Correction"], width=145, margin=(13, 5, 5, 5)) export_preview_textinput = TextAreaInput(title="Export file preview:", width=500, height=400) def _update_preview(): with tempfile.TemporaryDirectory() as temp_dir: temp_file = temp_dir + "/temp" export_data = [] for s, export in zip(det_data, scan_table_source.data["export"]): if export: export_data.append(s) pyzebra.export_1D( export_data, temp_file, export_target_select.value, hkl_precision=int(hkl_precision_select.value), ) exported_content = "" file_content = [] for ext in EXPORT_TARGETS[export_target_select.value]: fname = temp_file + ext if os.path.isfile(fname): with open(fname) as f: content = f.read() exported_content += f"{ext} file:\n" + content else: content = "" file_content.append(content) js_data.data.update(content=file_content) export_preview_textinput.value = exported_content def export_target_select_callback(_attr, _old, new): js_data.data.update(ext=EXPORT_TARGETS[new]) _update_preview() export_target_select = Select(title="Export target:", options=list(EXPORT_TARGETS.keys()), value="fullprof", width=80) export_target_select.on_change("value", export_target_select_callback) js_data.data.update(ext=EXPORT_TARGETS[export_target_select.value]) def hkl_precision_select_callback(_attr, _old, _new): _update_preview() hkl_precision_select = Select(title="hkl precision:", options=["2", "3", "4"], value="2", width=80) hkl_precision_select.on_change("value", hkl_precision_select_callback) save_button = Button(label="Download File(s)", button_type="success", width=200) save_button.js_on_click( CustomJS(args={"js_data": js_data}, code=javaScript)) fitpeak_controls = row( column(fitparams_add_dropdown, fitparams_select, fitparams_remove_button), fitparams_table, Spacer(width=20), column(fit_from_spinner, lorentz_checkbox, area_method_div, area_method_radiobutton), column(fit_to_spinner, proc_button, proc_all_button), ) scan_layout = column( scan_table, row(monitor_spinner, column(Spacer(height=19), restore_button)), row(column(Spacer(height=19), merge_button), merge_from_select), ) import_layout = column( proposal_textinput, file_select, row(file_open_button, file_append_button), upload_div, upload_button, append_upload_div, append_upload_button, ) export_layout = column( export_preview_textinput, row(export_target_select, hkl_precision_select, column(Spacer(height=19), row(save_button))), ) tab_layout = column( row(import_layout, scan_layout, plot, Spacer(width=30), export_layout), row(fitpeak_controls, fit_output_textinput), ) return Panel(child=tab_layout, title="ccl integrate")
TOOLBAR_STICKY = True #1 plot1 = figure(title="Streaming data at %.1f Hz" % (1e3 / g.DATA_FREQ_VAL), x_axis_type=None, plot_height=120, plot_width=800, tools=g.TOOLS1, toolbar_location=TOOLBAR_LOCATION, toolbar_sticky=TOOLBAR_STICKY, active_drag='xbox_select', active_tap=None, active_scroll='xwheel_zoom') xaxis1 = TimeAxis() plot1.add_layout(xaxis1, 'below') plot1.add_layout(Grid(dimension=0, ticker=xaxis1.ticker)) plot1.x_range.update(follow='end', follow_interval=FOLLOW_INTERVAL, range_padding=0.0, min_interval=2 * xaxis1.ticker.tickers[0].min_interval) color = brewer['Paired'][4][1] line1 = plot1.line(x='t', y='f', source=source1, color=color) circle1 = plot1.circle(x='t', y='f', source=source1, color=color) plot1.add_tools( CustomHover( tooltips=[ ("force", "$~y{0.000}"), ("time", "$xaxis_f"), ],
def create_bar_chart(data, title, x_name, y_name, hover_tool=None, width=1200, height=300): """Creates a bar chart plot, uses centcom dashboard styling. Parameters: - data, dict - title, str - names of x and y axes, str - hover tool, html""" source = ColumnDataSource(data) # Gets the data for the plot # From the data gets the axis names xdr = FactorRange(factors=data[x_name]) ydr = Range1d(start=0, end=max(data[y_name]) * 1.5) tools = [] if hover_tool: # turns on the over tool if exists tools = [ hover_tool, ] # Defines the plot main figure plot = figure( title=title, x_range=xdr, # value ranges y_range=ydr, plot_width=width, plot_height=height, h_symmetry=False, v_symmetry=False, min_borders=0, toolbar_location="above", tools=tools, responsive=True, outline_line_color="#666666") # Defines the plot's shape as a vertical bar and sets its parameters glyph = VBar(x=x_name, top=y_name, bottom=0, width=.8, fill_color="#e12127") # Adds the glyph to the plot with the data plot.add_glyph(source, glyph) # Defines the x, y axes xaxis = LinearAxis() yaxis = LinearAxis() plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) plot.toolbar.logo = None plot.min_border_top = 0 plot.xaxis.axis_label = "Days after app deployment" plot.yaxis.axis_label = "Bugs found" plot.xaxis.major_label_orientation = 1 plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = "#999999" plot.ygrid.grid_line_alpha = 0.1 return plot
def create(palm): connected = False current_message = None stream_t = 0 doc = curdoc() # Streaked and reference waveforms plot waveform_plot = Plot( title=Title(text="eTOF waveforms"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools waveform_plot.toolbar.logo = None waveform_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes waveform_plot.add_layout(LinearAxis(axis_label="Photon energy, eV"), 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())) # ---- line glyphs waveform_source = ColumnDataSource( dict(x_str=[], y_str=[], x_ref=[], y_ref=[])) waveform_ref_line = waveform_plot.add_glyph( waveform_source, Line(x="x_ref", y="y_ref", line_color="blue")) waveform_str_line = waveform_plot.add_glyph( waveform_source, Line(x="x_str", y="y_str", line_color="red")) # ---- legend waveform_plot.add_layout( Legend(items=[("reference", [waveform_ref_line]), ("streaked", [waveform_str_line])])) waveform_plot.legend.click_policy = "hide" # Cross-correlation plot xcorr_plot = Plot( title=Title(text="Waveforms cross-correlation"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools xcorr_plot.toolbar.logo = None xcorr_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes xcorr_plot.add_layout(LinearAxis(axis_label="Energy shift, eV"), place="below") xcorr_plot.add_layout(LinearAxis(axis_label="Cross-correlation", major_label_orientation="vertical"), place="left") # ---- grid lines xcorr_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) xcorr_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs xcorr_source = ColumnDataSource(dict(lags=[], xcorr=[])) xcorr_plot.add_glyph(xcorr_source, Line(x="lags", y="xcorr", line_color="purple")) # ---- vertical span xcorr_center_span = Span(location=0, dimension="height") xcorr_plot.add_layout(xcorr_center_span) # Delays plot pulse_delay_plot = Plot( title=Title(text="Pulse delays"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools pulse_delay_plot.toolbar.logo = None pulse_delay_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes pulse_delay_plot.add_layout(LinearAxis(axis_label="Pulse number"), place="below") pulse_delay_plot.add_layout( LinearAxis(axis_label="Pulse delay (uncalib), eV", major_label_orientation="vertical"), place="left", ) # ---- grid lines pulse_delay_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) pulse_delay_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs pulse_delay_source = ColumnDataSource(dict(x=[], y=[])) pulse_delay_plot.add_glyph(pulse_delay_source, Line(x="x", y="y", line_color="steelblue")) # Pulse lengths plot pulse_length_plot = Plot( title=Title(text="Pulse lengths"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools pulse_length_plot.toolbar.logo = None pulse_length_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes pulse_length_plot.add_layout(LinearAxis(axis_label="Pulse number"), place="below") pulse_length_plot.add_layout( LinearAxis(axis_label="Pulse length (uncalib), eV", major_label_orientation="vertical"), place="left", ) # ---- grid lines pulse_length_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) pulse_length_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs pulse_length_source = ColumnDataSource(dict(x=[], y=[])) pulse_length_plot.add_glyph(pulse_length_source, Line(x="x", y="y", line_color="steelblue")) # Image buffer slider def buffer_slider_callback(_attr, _old, new): message = receiver.data_buffer[new] doc.add_next_tick_callback(partial(update, message=message)) buffer_slider = Slider( start=0, end=59, value=0, step=1, title="Buffered Image", callback_policy="throttle", callback_throttle=500, ) buffer_slider.on_change("value", buffer_slider_callback) # Connect toggle button def connect_toggle_callback(state): nonlocal connected if state: connected = True connect_toggle.label = "Connecting" connect_toggle.button_type = "default" else: connected = False connect_toggle.label = "Connect" connect_toggle.button_type = "default" connect_toggle = Toggle(label="Connect", button_type="default", width=250) connect_toggle.on_click(connect_toggle_callback) # Intensity stream reset button def reset_button_callback(): nonlocal stream_t stream_t = 1 # keep the latest point in order to prevent full axis reset reset_button = Button(label="Reset", button_type="default", width=250) reset_button.on_click(reset_button_callback) # Stream update coroutine async def update(message): nonlocal stream_t if connected and receiver.state == "receiving": y_ref = message[receiver.reference].value[np.newaxis, :] y_str = message[receiver.streaked].value[np.newaxis, :] delay, length, debug_data = palm.process({ "0": y_ref, "1": y_str }, debug=True) prep_data, lags, corr_res_uncut, _ = debug_data waveform_source.data.update( x_str=palm.energy_range, y_str=prep_data["1"][0, :], x_ref=palm.energy_range, y_ref=prep_data["0"][0, :], ) xcorr_source.data.update(lags=lags, xcorr=corr_res_uncut[0, :]) xcorr_center_span.location = delay[0] pulse_delay_source.stream({ "x": [stream_t], "y": [delay] }, rollover=120) pulse_length_source.stream({ "x": [stream_t], "y": [length] }, rollover=120) stream_t += 1 # Periodic callback to fetch data from receiver async def internal_periodic_callback(): nonlocal current_message if waveform_plot.inner_width is None: # wait for the initialization to finish, thus skip this periodic callback return if connected: if receiver.state == "polling": connect_toggle.label = "Polling" connect_toggle.button_type = "warning" elif receiver.state == "stopped": connect_toggle.label = "Not available" connect_toggle.button_type = "danger" elif receiver.state == "receiving": connect_toggle.label = "Receiving" connect_toggle.button_type = "success" # Set slider to the right-most position if len(receiver.data_buffer) > 1: buffer_slider.end = len(receiver.data_buffer) - 1 buffer_slider.value = len(receiver.data_buffer) - 1 if receiver.data_buffer: current_message = receiver.data_buffer[-1] doc.add_next_tick_callback(partial(update, message=current_message)) doc.add_periodic_callback(internal_periodic_callback, 1000) # assemble tab_layout = column( row( column(waveform_plot, xcorr_plot), Spacer(width=30), column(buffer_slider, row(connect_toggle, reset_button)), ), row(pulse_delay_plot, Spacer(width=10), pulse_length_plot), ) return Panel(child=tab_layout, title="Stream")
def create(): det_data = {} roi_selection = {} upload_div = Div(text="Open .cami file:") def upload_button_callback(_attr, _old, new): with io.StringIO(base64.b64decode(new).decode()) as file: h5meta_list = pyzebra.parse_h5meta(file) file_list = h5meta_list["filelist"] filelist.options = file_list filelist.value = file_list[0] upload_button = FileInput(accept=".cami") 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 auto_toggle.active: im_max = int(np.max(current_image)) im_min = int(np.min(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 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]) overview_plot_y_image_source.data.update(image=[overview_y], dw=[n_y]) if frame_button_group.active == 0: # Frame overview_plot_x.axis[1].axis_label = "Frame" overview_plot_y.axis[1].axis_label = "Frame" overview_plot_x_image_source.data.update(y=[0], dh=[n_im]) overview_plot_y_image_source.data.update(y=[0], dh=[n_im]) elif frame_button_group.active == 1: # Omega overview_plot_x.axis[1].axis_label = "Omega" overview_plot_y.axis[1].axis_label = "Omega" om = det_data["rot_angle"] om_start = om[0] om_end = (om[-1] - om[0]) * n_im / (n_im - 1) overview_plot_x_image_source.data.update(y=[om_start], dh=[om_end]) overview_plot_y_image_source.data.update(y=[om_start], dh=[om_end]) def filelist_callback(_attr, _old, new): nonlocal det_data det_data = pyzebra.read_detector_data(new) index_spinner.value = 0 index_spinner.high = det_data["data"].shape[0] - 1 update_image(0) update_overview_plot() filelist = Select() filelist.on_change("value", filelist_callback) def index_spinner_callback(_attr, _old, new): update_image(new) index_spinner = Spinner(title="Image index:", value=0, low=0) index_spinner.on_change("value", index_spinner_callback) 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_H * 3, plot_width=IMAGE_W * 3, 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))], 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) plot.add_glyph(image_source, h_glyph) plot.add_glyph(image_source, k_glyph) plot.add_glyph(image_source, l_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=200, plot_width=IMAGE_W * 3, 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_H * 3, plot_width=200, 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"), ("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 range frame_range = DataRange1d() det_x_range = DataRange1d() overview_plot_x = Plot( title=Title(text="Projections on X-axis"), x_range=det_x_range, y_range=frame_range, plot_height=400, plot_width=400, toolbar_location="left", ) # ---- 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=[1], 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 = DataRange1d() overview_plot_y = Plot( title=Title(text="Projections on Y-axis"), x_range=det_y_range, y_range=frame_range, plot_height=400, plot_width=400, toolbar_location="left", ) # ---- 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(axis_label="Frame", major_label_orientation="vertical"), place="left") # ---- 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=[1], 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") def frame_button_group_callback(_active): update_overview_plot() frame_button_group = RadioButtonGroup(labels=["Frames", "Omega"], active=0) frame_button_group.on_click(frame_button_group_callback) roi_avg_plot = Plot( x_range=DataRange1d(), y_range=DataRange1d(), plot_height=IMAGE_H * 3, plot_width=IMAGE_W * 3, 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())) colormap.on_change("value", colormap_callback) colormap.value = "plasma" radio_button_group = RadioButtonGroup(labels=["nb", "nb_bi"], active=0) STEP = 1 # ---- colormap auto toggle button def auto_toggle_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() auto_toggle = Toggle(label="Auto Range", active=True, button_type="default") auto_toggle.on_click(auto_toggle_callback) # ---- colormap display max value 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( title="Maximal Display Value:", low=0 + STEP, value=1, step=STEP, disabled=auto_toggle.active, ) display_max_spinner.on_change("value", display_max_spinner_callback) # ---- colormap display min value 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( title="Minimal Display Value:", high=1 - STEP, value=0, step=STEP, disabled=auto_toggle.active, ) display_min_spinner.on_change("value", display_min_spinner_callback) def hkl_button_callback(): index = index_spinner.value setup_type = "nb_bi" if radio_button_group.active else "nb" h, k, l = calculate_hkl(det_data, index, setup_type) image_source.data.update(h=[h], k=[k], l=[l]) hkl_button = Button(label="Calculate hkl (slow)") hkl_button.on_click(hkl_button_callback) selection_list = TextAreaInput(rows=7) def selection_button_callback(): nonlocal roi_selection selection = [ int(np.floor(det_x_range.start)), int(np.ceil(det_x_range.end)), int(np.floor(det_y_range.start)), int(np.ceil(det_y_range.end)), int(np.floor(frame_range.start)), int(np.ceil(frame_range.end)), ] filename_id = filelist.value[-8:-4] if filename_id in roi_selection: roi_selection[f"{filename_id}"].append(selection) else: roi_selection[f"{filename_id}"] = [selection] selection_list.value = str(roi_selection) selection_button = Button(label="Add selection") selection_button.on_click(selection_button_callback) # Final layout layout_image = column( gridplot([[proj_v, None], [plot, proj_h]], merge_tools=False), row(index_spinner)) colormap_layout = column(colormap, auto_toggle, display_max_spinner, display_min_spinner) hkl_layout = column(radio_button_group, hkl_button) layout_overview = column( gridplot( [[overview_plot_x, overview_plot_y]], toolbar_options=dict(logo=None), merge_tools=True, ), frame_button_group, ) tab_layout = row( column( upload_div, upload_button, filelist, layout_image, row(colormap_layout, hkl_layout), ), column( roi_avg_plot, layout_overview, row(selection_button, selection_list), ), ) return Panel(child=tab_layout, title="Data Viewer")
def make_scatter_plot(source, data, country, xname, yname, xax=False, yax=False): # sets range and borders for plot xdr = DataRange1d(bounds=None) ydr = DataRange1d(bounds=None) mbl = 40 if yax else 0 mbb = 40 if xax else 0 plot = figure(x_range=xdr, y_range=ydr, background_fill_color="#efe8e2", border_fill_color='white', plot_width=200 + mbl, plot_height=200 + mbb, min_border_left=2 + mbl, min_border_right=2, min_border_top=2, min_border_bottom=2 + mbb, title=country) # plots points circle = Circle(x=xname, y=yname, fill_color="blue", fill_alpha=0.2, size=4, line_color="blue") plot.add_glyph(source, circle) # calculates and plots regression line a, b, mse = make_regression_line(data, xname, yname) mse_mean = mse.mean() print(xname, yname, mse_mean) x = data[xname] plot.line(x, a * x + b, color='red') plot.axis.visible = False # makes axis according to place in matrix xticker = BasicTicker() if xax: xaxis = LinearAxis() xaxis.axis_label = xname plot.add_layout(xaxis, 'below') xticker = xaxis.ticker plot.add_layout(Grid(dimension=0, ticker=xticker)) yticker = BasicTicker() if yax: yaxis = LinearAxis() yaxis.axis_label = yname yaxis.major_label_orientation = 'vertical' plot.add_layout(yaxis, 'left') yticker = yaxis.ticker plot.add_layout(Grid(dimension=1, ticker=yticker)) return plot
def __init__(self, n_rectangles=1000, clear_interval=20000, **kwargs): """ kwargs are applied to the bokeh.models.plots.Plot constructor """ self.n_rectangles = n_rectangles self.clear_interval = clear_interval self.last = 0 self.source = ColumnDataSource(data=dict(start=[], duration=[], key=[], name=[], color=[], worker=[], y=[], worker_thread=[], alpha=[])) x_range = DataRange1d() y_range = DataRange1d(range_padding=0) self.root = Plot(title=Title(text="Task Stream"), id='bk-task-stream-plot', x_range=x_range, y_range=y_range, toolbar_location="above", min_border_right=35, **kwargs) self.root.add_glyph( self.source, Rect(x="start", y="y", width="duration", height=0.8, fill_color="color", line_color="color", line_alpha=0.6, fill_alpha="alpha", line_width=3)) self.root.add_layout(DatetimeAxis(axis_label="Time"), "below") ticker = BasicTicker(num_minor_ticks=0) self.root.add_layout( LinearAxis(axis_label="Worker Core", ticker=ticker), "left") self.root.add_layout( Grid(dimension=1, grid_line_alpha=0.4, ticker=ticker)) hover = HoverTool(point_policy="follow_mouse", tooltips=""" <div> <span style="font-size: 12px; font-weight: bold;">@name:</span> <span style="font-size: 10px; font-family: Monaco, monospace;">@duration</span> <span style="font-size: 10px;">ms</span> </div> """) # export = ExportTool() # export.register_plot(self.root) self.root.add_tools( hover, # export, BoxZoomTool(), ResetTool(reset_size=False), PanTool(dimensions="width"), WheelZoomTool(dimensions="width")) # Required for update callback self.task_stream_index = [0]
def create_bar_chart(data, title, x_name, y_name, x_label, y_label, hover_tool=None, width=1200, height=500): """Creates a bar chart plot with the exact styling for the centcom dashboard. Pass in data as a dictionary, desired plot title, name of x axis, y axis and the hover tool HTML. """ source = ColumnDataSource(data) xdr = FactorRange(factors=data[x_name]) ydr = Range1d(start=0, end=max(data[y_name]) * 1.5) tools = [] if hover_tool: tools = [ hover_tool, ] plot = figure(title=title, x_range=xdr, y_range=ydr, plot_width=width, plot_height=height, h_symmetry=False, v_symmetry=False, min_border=0, toolbar_location="above", tools=tools, sizing_mode='scale_width', outline_line_color="#666666") glyph = VBar(x=x_name, top=y_name, bottom=0, width=.8, fill_color="#141d99") plot.add_glyph(source, glyph) xaxis = LinearAxis() yaxis = LinearAxis() plot.title.text_font_size = '15pt' plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) plot.toolbar.logo = None plot.min_border_top = 0 plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = "#999999" plot.yaxis.axis_label = y_label plot.yaxis.axis_label_text_font_size = '15pt' plot.yaxis.major_label_text_font_size = '12pt' plot.ygrid.grid_line_alpha = 0.1 plot.xaxis.axis_label = x_label plot.xaxis.major_label_orientation = 1 plot.xaxis.axis_label_text_font_size = '15pt' plot.xaxis.major_label_text_font_size = '12pt' return plot
def create(palm): fit_max = 1 fit_min = 0 doc = curdoc() # THz calibration plot scan_plot = Plot( title=Title(text="THz calibration"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools scan_plot.toolbar.logo = None scan_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes scan_plot.add_layout(LinearAxis(axis_label="Stage delay motor"), place="below") scan_plot.add_layout(LinearAxis(axis_label="Energy shift, eV", major_label_orientation="vertical"), place="left") # ---- grid lines scan_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) scan_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- circle cluster glyphs scan_circle_source = ColumnDataSource(dict(x=[], y=[])) scan_plot.add_glyph(scan_circle_source, Circle(x="x", y="y", line_alpha=0, fill_alpha=0.5)) # ---- circle glyphs scan_avg_circle_source = ColumnDataSource(dict(x=[], y=[])) scan_plot.add_glyph( scan_avg_circle_source, Circle(x="x", y="y", line_color="purple", fill_color="purple")) # ---- line glyphs fit_line_source = ColumnDataSource(dict(x=[], y=[])) scan_plot.add_glyph(fit_line_source, Line(x="x", y="y", line_color="purple")) # THz calibration folder path text input def path_textinput_callback(_attr, _old_value, _new_value): update_load_dropdown_menu() path_periodic_update() path_textinput = TextInput(title="THz calibration path:", value=os.path.join(os.path.expanduser("~")), width=510) path_textinput.on_change("value", path_textinput_callback) # THz calibration eco scans dropdown def scans_dropdown_callback(_attr, _old_value, new_value): scans_dropdown.label = new_value scans_dropdown = Dropdown(label="ECO scans", button_type="default", menu=[]) scans_dropdown.on_change("value", scans_dropdown_callback) # ---- eco 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) # Calibrate button def calibrate_button_callback(): palm.calibrate_thz( path=os.path.join(path_textinput.value, scans_dropdown.value)) fit_max_spinner.value = np.ceil(palm.thz_calib_data.index.values.max()) fit_min_spinner.value = np.floor( palm.thz_calib_data.index.values.min()) update_calibration_plot() def update_calibration_plot(): scan_plot.xaxis.axis_label = f"{palm.thz_motor_name}, {palm.thz_motor_unit}" scan_circle_source.data.update( x=np.repeat(palm.thz_calib_data.index, palm.thz_calib_data["peak_shift"].apply(len)).tolist(), y=np.concatenate( palm.thz_calib_data["peak_shift"].values).tolist(), ) scan_avg_circle_source.data.update( x=palm.thz_calib_data.index.tolist(), y=palm.thz_calib_data["peak_shift_mean"].tolist()) x = np.linspace(fit_min, fit_max, 100) y = palm.thz_slope * x + palm.thz_intersect fit_line_source.data.update(x=np.round(x, decimals=5), y=np.round(y, decimals=5)) calib_const_div.text = f""" thz_slope = {palm.thz_slope} """ calibrate_button = Button(label="Calibrate THz", button_type="default", width=250) calibrate_button.on_click(calibrate_button_callback) # THz fit maximal value text input def fit_max_spinner_callback(_attr, old_value, new_value): nonlocal fit_max if new_value > fit_min: fit_max = new_value palm.calibrate_thz( path=os.path.join(path_textinput.value, scans_dropdown.value), fit_range=(fit_min, fit_max), ) update_calibration_plot() else: fit_max_spinner.value = old_value fit_max_spinner = Spinner(title="Maximal fit value:", value=fit_max, step=0.1) fit_max_spinner.on_change("value", fit_max_spinner_callback) # THz fit maximal value text input def fit_min_spinner_callback(_attr, old_value, new_value): nonlocal fit_min if new_value < fit_max: fit_min = new_value palm.calibrate_thz( path=os.path.join(path_textinput.value, scans_dropdown.value), fit_range=(fit_min, fit_max), ) update_calibration_plot() else: fit_min_spinner.value = old_value fit_min_spinner = Spinner(title="Minimal fit value:", value=fit_min, step=0.1) fit_min_spinner.on_change("value", fit_min_spinner_callback) # Save calibration button def save_button_callback(): palm.save_thz_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(_attr, _old_value, new_value): palm.load_thz_calib(os.path.join(path_textinput.value, new_value)) update_calibration_plot() def update_load_dropdown_menu(): new_menu = [] calib_file_ext = ".palm_thz" 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_change("value", load_dropdown_callback) # Calibration constants calib_const_div = Div(text=f""" thz_slope = {0} """) # assemble tab_layout = column( row( scan_plot, Spacer(width=30), column( path_textinput, scans_dropdown, calibrate_button, fit_max_spinner, fit_min_spinner, row(save_button, load_dropdown), calib_const_div, ), )) return Panel(child=tab_layout, title="THz Calibration")
def plotprotein(sequence, other_binding, dna_binding, metal_binding, active, variant_location): sequence = [i for i in sequence] print(len(sequence)) sequence += [''] * (3000 - len(sequence)) print(sequence) print(variant_location) if variant_location > 50: start_seq = variant_location - 50 else: start_seq = 0 if variant_location + 50 < len(sequence): end_seq = variant_location + 50 else: end_seq = 3000 x_values = range(0, 3000) #x_values = range(starting_value, value) source1 = ColumnDataSource( dict(x=x_values[start_seq:end_seq], y=other_binding[start_seq:end_seq], names=sequence[start_seq:end_seq])) source2 = ColumnDataSource( dict(x=x_values[start_seq:end_seq], y=dna_binding[start_seq:end_seq], names=sequence[start_seq:end_seq])) source3 = ColumnDataSource( dict(x=x_values[start_seq:end_seq], y=metal_binding[start_seq:end_seq], names=sequence[start_seq:end_seq])) source4 = ColumnDataSource( dict(x=x_values[start_seq:end_seq], y=active[start_seq:end_seq], names=sequence[start_seq:end_seq])) glyph1 = Line(x="x", y="y", line_color="red", line_width=3, line_alpha=0.6) glyph2 = Line(x="x", y="y", line_color="blue", line_width=3, line_alpha=0.6) glyph3 = Line(x="x", y="y", line_color="green", line_width=3, line_alpha=0.6) glyph4 = Line(x="x", y="y", line_color="orange", line_width=3, line_alpha=0.6) plot = Plot(title=None, plot_height=150, plot_width=1000, min_border=0, toolbar_location=None) plot.add_glyph(source1, glyph1) plot.add_glyph(source2, glyph2) plot.add_glyph(source3, glyph3) plot.add_glyph(source4, glyph4) plot.add_layout( Span(location=variant_location, dimension='height', line_color='black')) xaxis = LinearAxis() #YOUR_FONT_SIZE = 10 labels = LabelSet(x='x', y=1, text='names', level='glyph', x_offset=-1, y_offset=5, source=source1, render_mode='canvas', text_font_size='5pt') plot.add_layout(labels) yaxis = LinearAxis() plot.add_layout(yaxis, 'left') plot.yaxis.bounds = (0, 1) plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) plot.y_range = Range1d(-0.1, 1.5) show(plot)
def create(palm): energy_min = palm.energy_range.min() energy_max = palm.energy_range.max() energy_npoints = palm.energy_range.size current_results = (0, 0, 0, 0) doc = curdoc() # Streaked and reference waveforms plot waveform_plot = Plot( title=Title(text="eTOF waveforms"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location='right', ) # ---- tools waveform_plot.toolbar.logo = None waveform_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes waveform_plot.add_layout(LinearAxis(axis_label='Photon energy, eV'), 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())) # ---- line glyphs waveform_source = ColumnDataSource( dict(x_str=[], y_str=[], x_ref=[], y_ref=[])) waveform_ref_line = waveform_plot.add_glyph( waveform_source, Line(x='x_ref', y='y_ref', line_color='blue')) waveform_str_line = waveform_plot.add_glyph( waveform_source, Line(x='x_str', y='y_str', line_color='red')) # ---- legend waveform_plot.add_layout( Legend(items=[("reference", [waveform_ref_line]), ("streaked", [waveform_str_line])])) waveform_plot.legend.click_policy = "hide" # Cross-correlation plot xcorr_plot = Plot( title=Title(text="Waveforms cross-correlation"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location='right', ) # ---- tools xcorr_plot.toolbar.logo = None xcorr_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes xcorr_plot.add_layout(LinearAxis(axis_label='Energy shift, eV'), place='below') xcorr_plot.add_layout(LinearAxis(axis_label='Cross-correlation', major_label_orientation='vertical'), place='left') # ---- grid lines xcorr_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) xcorr_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs xcorr_source = ColumnDataSource(dict(lags=[], xcorr1=[], xcorr2=[])) xcorr_plot.add_glyph( xcorr_source, Line(x='lags', y='xcorr1', line_color='purple', line_dash='dashed')) xcorr_plot.add_glyph(xcorr_source, Line(x='lags', y='xcorr2', line_color='purple')) # ---- vertical span xcorr_center_span = Span(location=0, dimension='height') xcorr_plot.add_layout(xcorr_center_span) # Delays plot pulse_delay_plot = Plot( title=Title(text="Pulse delays"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location='right', ) # ---- tools pulse_delay_plot.toolbar.logo = None pulse_delay_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes pulse_delay_plot.add_layout(LinearAxis(axis_label='Pulse number'), place='below') pulse_delay_plot.add_layout( LinearAxis(axis_label='Pulse delay (uncalib), eV', major_label_orientation='vertical'), place='left', ) # ---- grid lines pulse_delay_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) pulse_delay_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs pulse_delay_source = ColumnDataSource(dict(pulse=[], delay=[])) pulse_delay_plot.add_glyph( pulse_delay_source, Line(x='pulse', y='delay', line_color='steelblue')) # ---- vertical span pulse_delay_plot_span = Span(location=0, dimension='height') pulse_delay_plot.add_layout(pulse_delay_plot_span) # Pulse lengths plot pulse_length_plot = Plot( title=Title(text="Pulse lengths"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location='right', ) # ---- tools pulse_length_plot.toolbar.logo = None pulse_length_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes pulse_length_plot.add_layout(LinearAxis(axis_label='Pulse number'), place='below') pulse_length_plot.add_layout( LinearAxis(axis_label='Pulse length (uncalib), eV', major_label_orientation='vertical'), place='left', ) # ---- grid lines pulse_length_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) pulse_length_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs pulse_length_source = ColumnDataSource(dict(x=[], y=[])) pulse_length_plot.add_glyph(pulse_length_source, Line(x='x', y='y', line_color='steelblue')) # ---- vertical span pulse_length_plot_span = Span(location=0, dimension='height') pulse_length_plot.add_layout(pulse_length_plot_span) # Folder path text input def path_textinput_callback(_attr, _old, new): save_textinput.value = new path_periodic_update() path_textinput = TextInput(title="Folder Path:", value=os.path.join(os.path.expanduser('~')), width=510) path_textinput.on_change('value', path_textinput_callback) # Saved runs dropdown menu def h5_update(pulse, delays, debug_data): prep_data, lags, corr_res_uncut, corr_results = debug_data waveform_source.data.update( x_str=palm.energy_range, y_str=prep_data['1'][pulse, :], x_ref=palm.energy_range, y_ref=prep_data['0'][pulse, :], ) xcorr_source.data.update(lags=lags, xcorr1=corr_res_uncut[pulse, :], xcorr2=corr_results[pulse, :]) xcorr_center_span.location = delays[pulse] pulse_delay_plot_span.location = pulse pulse_length_plot_span.location = pulse # this placeholder function should be reassigned in 'saved_runs_dropdown_callback' h5_update_fun = lambda pulse: None def saved_runs_dropdown_callback(_attr, _old, new): if new != "Saved Runs": nonlocal h5_update_fun, current_results saved_runs_dropdown.label = new filepath = os.path.join(path_textinput.value, new) tags, delays, lengths, debug_data = palm.process_hdf5_file( filepath, debug=True) current_results = (new, tags, delays, lengths) if autosave_checkbox.active: save_button_callback() pulse_delay_source.data.update(pulse=np.arange(len(delays)), delay=delays) pulse_length_source.data.update(x=np.arange(len(lengths)), y=lengths) h5_update_fun = partial(h5_update, delays=delays, debug_data=debug_data) pulse_slider.end = len(delays) - 1 pulse_slider.value = 0 h5_update_fun(0) saved_runs_dropdown = Dropdown(label="Saved Runs", button_type='primary', menu=[]) saved_runs_dropdown.on_change('value', saved_runs_dropdown_callback) # ---- saved run 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(('.hdf5', '.h5')): new_menu.append((entry.name, entry.name)) saved_runs_dropdown.menu = sorted(new_menu, reverse=True) doc.add_periodic_callback(path_periodic_update, 5000) # Pulse number slider def pulse_slider_callback(_attr, _old, new): h5_update_fun(pulse=new) pulse_slider = Slider( start=0, end=99999, value=0, step=1, title="Pulse ID", callback_policy='throttle', callback_throttle=500, ) pulse_slider.on_change('value', pulse_slider_callback) # Energy maximal range value text input def energy_max_textinput_callback(_attr, old, new): nonlocal energy_max try: new_value = float(new) if new_value > energy_min: energy_max = new_value palm.energy_range = np.linspace(energy_min, energy_max, energy_npoints) saved_runs_dropdown_callback('', '', saved_runs_dropdown.label) else: energy_max_textinput.value = old except ValueError: energy_max_textinput.value = old energy_max_textinput = TextInput(title='Maximal Energy, eV:', value=str(energy_max)) energy_max_textinput.on_change('value', energy_max_textinput_callback) # Energy minimal range value text input def energy_min_textinput_callback(_attr, old, new): nonlocal energy_min try: new_value = float(new) if new_value < energy_max: energy_min = new_value palm.energy_range = np.linspace(energy_min, energy_max, energy_npoints) saved_runs_dropdown_callback('', '', saved_runs_dropdown.label) else: energy_min_textinput.value = old except ValueError: energy_min_textinput.value = old energy_min_textinput = TextInput(title='Minimal Energy, eV:', value=str(energy_min)) energy_min_textinput.on_change('value', energy_min_textinput_callback) # Energy number of interpolation points text input def energy_npoints_textinput_callback(_attr, old, new): nonlocal energy_npoints try: new_value = int(new) if new_value > 1: energy_npoints = new_value palm.energy_range = np.linspace(energy_min, energy_max, energy_npoints) saved_runs_dropdown_callback('', '', saved_runs_dropdown.label) else: energy_npoints_textinput.value = old except ValueError: energy_npoints_textinput.value = old energy_npoints_textinput = TextInput( title='Number of interpolation points:', value=str(energy_npoints)) energy_npoints_textinput.on_change('value', energy_npoints_textinput_callback) # Save location save_textinput = TextInput(title="Save Folder Path:", value=os.path.join(os.path.expanduser('~'))) # Autosave checkbox autosave_checkbox = CheckboxButtonGroup(labels=["Auto Save"], active=[], width=250) # Save button def save_button_callback(): if current_results[0]: filename, tags, delays, lengths = current_results save_filename = os.path.splitext(filename)[0] + '.csv' df = pd.DataFrame({ 'pulse_id': tags, 'pulse_delay': delays, 'pulse_length': lengths }) df.to_csv(os.path.join(save_textinput.value, save_filename), index=False) save_button = Button(label="Save Results", button_type='default', width=250) save_button.on_click(save_button_callback) # assemble tab_layout = column( row( column(waveform_plot, xcorr_plot), Spacer(width=30), column( path_textinput, saved_runs_dropdown, pulse_slider, Spacer(height=30), energy_min_textinput, energy_max_textinput, energy_npoints_textinput, Spacer(height=30), save_textinput, autosave_checkbox, save_button, ), ), row(pulse_delay_plot, Spacer(width=10), pulse_length_plot), ) return Panel(child=tab_layout, title="HDF5 File")
def large_plot(n: int) -> Tuple[Model, Set[Model]]: from bokeh.models import ( BoxSelectTool, BoxZoomTool, Column, ColumnDataSource, DataRange1d, GlyphRenderer, Grid, Line, LinearAxis, PanTool, Plot, ResetTool, SaveTool, WheelZoomTool, ZoomInTool, ZoomOutTool, ) col = Column() objects: Set[Model] = {col} for i in range(n): source = ColumnDataSource(data=dict(x=[0, i + 1], y=[0, i + 1])) xdr = DataRange1d() ydr = DataRange1d() plot = Plot(x_range=xdr, y_range=ydr) xaxis = LinearAxis() plot.add_layout(xaxis, "below") yaxis = LinearAxis() plot.add_layout(yaxis, "left") xgrid = Grid(dimension=0) plot.add_layout(xgrid, "center") ygrid = Grid(dimension=1) plot.add_layout(ygrid, "center") tickers = [ xaxis.ticker, xaxis.formatter, yaxis.ticker, yaxis.formatter ] glyph = Line(x='x', y='y') renderer = GlyphRenderer(data_source=source, glyph=glyph) plot.renderers.append(renderer) pan = PanTool() zoom_in = ZoomInTool() zoom_out = ZoomOutTool() wheel_zoom = WheelZoomTool() box_zoom = BoxZoomTool() box_select = BoxSelectTool() save = SaveTool() reset = ResetTool() tools = [ pan, zoom_in, zoom_out, wheel_zoom, box_zoom, box_select, save, reset ] plot.add_tools(*tools) col.children.append(plot) objects |= set([ xdr, ydr, xaxis, xaxis.major_label_policy, yaxis, yaxis.major_label_policy, xgrid, ygrid, renderer, renderer.view, glyph, source, source.selected, source.selection_policy, plot, plot.x_scale, plot.y_scale, plot.toolbar, plot.title, box_zoom.overlay, box_select.overlay, ] + tickers + tools) return col, objects
def create_bar_chart(data, title, x_name, y_name, hover_tool=None, width=1200, height=300): """Creates a bar chart plot with the exact styling for the centcom dashboard. Pass in data as a dictionary, desired plot title, name of x axis, y axis and the hover tool HTML. """ source = ColumnDataSource(data) xdr = FactorRange(factors=data[x_name]) ydr = Range1d(start=0, end=max(data[y_name]) * 1.5) callback = CustomJS(args=dict(source=source), code=""" var data = source.data; console.log("data[bugs] : " +data['bugs']); console.log("source data : " + data); var geometry = cb_data['geometries']; /// calculate x and y var x = geometry[0].x var y = geometry[0].y console.log("geometry : " + geometry[0]); console.log("x : " + x); console.log("y : " + y); var b = cb_obj.data; console.log("cb_obj-data : "+ b); console.log("cb_obj selected : " + cb_obj.selected); console.log("cb_obj selected indices : " + cb_obj.selected.indices); //This one works to give indices from 0-last console.log(cb_obj.selected['1d'].indices) if ($(".hover_bkgr_fricc").length){ document.getElementById('id_index').value= parseInt(cb_obj.selected['1d'].indices) + 1 ; $('.hover_bkgr_fricc').show(); } """) tap_tool = TapTool(callback=callback) plot = figure(title=title, x_range=xdr, y_range=ydr, plot_width=width, plot_height=height, h_symmetry=False, v_symmetry=False, min_border=0, toolbar_location="above", tools=[hover_tool, tap_tool, CrosshairTool()], responsive=True, outline_line_color="#666666") glyph = VBar(x=x_name, top=y_name, bottom=0, width=.8, fill_color="#e12127") plot.add_glyph(source, glyph) xaxis = LinearAxis() yaxis = LinearAxis() plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) plot.toolbar.logo = None plot.min_border_top = 0 plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = "#999999" plot.yaxis.axis_label = "Bugs found" plot.ygrid.grid_line_alpha = 0.1 plot.xaxis.axis_label = "Days after app deployment" plot.xaxis.major_label_orientation = 1 return plot
def __init__( self, plot_height=894, plot_width=854, image_height=100, image_width=100, x_start=None, x_end=None, y_start=None, y_end=None, ): """Initialize image view plot. Args: plot_height (int, optional): Height of plot area in screen pixels. Defaults to 894. plot_width (int, optional): Width of plot area in screen pixels. Defaults to 854. image_height (int, optional): Image height in pixels. Defaults to 100. image_width (int, optional): Image width in pixels. Defaults to 100. x_start (int, optional): Initial x-axis start value. If None, then equals to 0. Defaults to None. x_end (int, optional): Initial x-axis end value. If None, then equals to image_width. Defaults to None. y_start (int, optional): Initial y-axis start value. If None, then equals to 0. Defaults to None. y_end (int, optional): Initial y-axis end value. If None, then equals to image_height. Defaults to None. """ if x_start is None: x_start = 0 if x_end is None: x_end = image_width if y_start is None: y_start = 0 if y_end is None: y_end = image_height self.zoom_views = [] plot = Plot( x_range=Range1d(x_start, x_end, bounds=(0, image_width)), y_range=Range1d(y_start, y_end, bounds=(0, image_height)), plot_height=plot_height, plot_width=plot_width, toolbar_location="left", ) self.plot = plot # ---- tools plot.toolbar.logo = None hovertool = HoverTool(tooltips=[("intensity", "@image")], names=["image_glyph"]) plot.add_tools(PanTool(), WheelZoomTool(maintain_focus=False), SaveTool(), ResetTool(), hovertool) plot.toolbar.active_scroll = plot.tools[1] # ---- 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 self._image_source = ColumnDataSource( dict( image=[np.zeros((1, 1), dtype="float32")], x=[x_start], y=[y_start], dw=[x_end - x_start], dh=[y_end - y_start], )) self.image_glyph = Image(image="image", x="x", y="y", dw="dw", dh="dh") image_renderer = plot.add_glyph(self._image_source, self.image_glyph, name="image_glyph") # This avoids double update of image values on a client, see # https://github.com/bokeh/bokeh/issues/7079 # https://github.com/bokeh/bokeh/issues/7299 image_renderer.view.source = ColumnDataSource() # ---- pixel value text glyph self._pvalue_source = ColumnDataSource(dict(x=[], y=[], text=[])) plot.add_glyph( self._pvalue_source, Text( x="x", y="y", text="text", text_align="center", text_baseline="middle", text_color="white", ), ) # ---- horizontal and vertical projection line glyphs self._hproj_source = ColumnDataSource(dict(x=[], y=[])) plot.add_glyph(self._hproj_source, Line(x="x", y="y", line_color="greenyellow")) self._vproj_source = ColumnDataSource(dict(x=[], y=[])) plot.add_glyph(self._vproj_source, Line(x="x", y="y", line_color="greenyellow")) proj_toggle = CheckboxGroup(labels=["Inner Projections"], default_size=145) self.proj_toggle = proj_toggle
plot.add_tools( PanTool(), BoxZoomTool(), WheelZoomTool(maintain_focus=False), SaveTool(), ResetTool(), ) plot.add_layout( LinearAxis(axis_label="pulse_id", formatter=BasicTickFormatter(use_scientific=False)), place="below", ) plot.add_layout(LinearAxis(), place="left") plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) step_source = ColumnDataSource(dict(x=[], y=[])) step = plot.add_glyph( step_source, Step(x="x", y="y", mode="after", line_color="steelblue", line_width=2)) step_nobkg_source = ColumnDataSource(dict(x=[], y=[])) step_nobkg = plot.add_glyph( step_nobkg_source, Step(x="x", y="y", mode="after", line_color="firebrick", line_width=2)) plot.add_layout( Legend( items=[("ROI Pump-probe", [step]),
TableColumn(field="cty", title="City MPG", editor=IntEditor()), TableColumn(field="hwy", title="Highway MPG", editor=IntEditor()), ] data_table = DataTable(source=source, columns=columns, editable=True) xdr = DataRange1d() ydr = DataRange1d() plot = Plot(title=None, x_range=xdr, y_range=ydr, plot_width=1000, plot_height=300) xaxis = LinearAxis(plot=plot) plot.below.append(xaxis) yaxis = LinearAxis(plot=plot) ygrid = Grid(plot=plot, dimension=1, ticker=yaxis.ticker) plot.left.append(yaxis) cty_glyph = Circle(x="index", y="cty", fill_color="#396285", size=8, fill_alpha=0.5, line_alpha=0.5) hwy_glyph = Circle(x="index", y="hwy", fill_color="#CE603D", size=8, fill_alpha=0.5, line_alpha=0.5) cty = GlyphRenderer(data_source=source, glyph=cty_glyph) hwy = GlyphRenderer(data_source=source, glyph=hwy_glyph)
# "Emmigrants Men / Women[2014-2017] plot1 = Plot(title=None, plot_width=700, plot_height=600, min_border=0, toolbar_location=None) glyph_m = HBar(y="years", right="men", left=1000, height=0.31, fill_color=Category20[10][0]) plot1.add_glyph(source_m, glyph_m) glyph_w = HBar(y="years", left="women", right=-1000, height=0.31, fill_color=Category20[10][1]) plot1.add_glyph(source_w, glyph_w) xaxis = LinearAxis() plot1.add_layout(xaxis, 'below') yaxis = LinearAxis() plot1.add_layout(yaxis, 'left') plot1.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) #plot1.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) show(gridplot([[plot1]])) export_png(plot1, filename=filepath + "__4-B.png")
def make_correlation_datatable(correl_df): """ the input datframe must have columns ['Target (as string)', 'Hedge (as string)', 'Correlation ( as float )'] :param correl_df: :return: """ correl_df.reset_index(inplace=True) source = ColumnDataSource(correl_df) target_ts_asset = sorted(correl_df["Target"].unique()) hedge_ts_asset = sorted(correl_df["Hedge"].unique()) columns = [ TableColumn(field="Target", title="Target Timeseries", formatter=StringFormatter(font_style="bold", text_color='red')), TableColumn(field="Hedge", title="Hedge Timeseries", formatter=StringFormatter(font_style="bold", text_color='blue')), TableColumn(field="Correlation", title="Correlation", formatter=StringFormatter(font_style="bold", text_color='darkgreen')) ] data_table = DataTable(source=source, columns=columns, editable=False, width=1000) plot = Plot(title=Title( text="Correlations, Target vs. Hedge Timeseries)", align="center"), x_range=DataRange1d(), y_range=DataRange1d(), plot_width=1000, plot_height=300) # Set up x & y axis plot.add_layout(LinearAxis(), 'below') yaxis = LinearAxis() plot.add_layout(yaxis, 'left') plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) # Add Glyphs correlation_glyph = Circle(x="index", y="Correlation", fill_color="#396285", size=8, fill_alpha=0.5, line_alpha=0.5) target_glyph = Circle(x="index", y="Target", fill_color="#396285", size=8, fill_alpha=0.5, line_alpha=0.5) hedge_glyph = Circle(x="index", y="Hedge", fill_color="#396285", size=8, fill_alpha=0.5, line_alpha=0.5) correlation = plot.add_glyph(source, correlation_glyph) target = plot.add_glyph(source, target_glyph) hedge = plot.add_glyph(source, hedge_glyph) # Add the tools tooltips = [("Correlation", "@Correlation"), ("Target", "@Target"), ("Hedge", "@Hedge")] correlation_hover_tool = HoverTool(renderers=[correlation], tooltips=tooltips) target_hover_tool = HoverTool(renderers=[target], tooltips=tooltips) hedge_hover_tool = HoverTool(renderers=[hedge], tooltips=tooltips) select_tool = BoxSelectTool(renderers=[target, hedge, correlation], dimensions='width') plot.add_tools(target_hover_tool, hedge_hover_tool, correlation_hover_tool, select_tool) layout = Column(plot, data_table) the_doc = Document() the_doc.add_root(layout) return the_doc
sprint["MedalLine"] = sprint.Medal.map(lambda medal: line_color[medal]) sprint["SelectedName"] = sprint[["Name", "Medal", "Year"]].apply(tuple, axis=1).map(lambda args: selected_name(*args)) source = ColumnDataSource(sprint) xdr = Range1d(start=sprint.MetersBack.max()+2, end=0) # XXX: +2 is poor-man's padding (otherwise misses last tick) ydr = DataRange1d(range_padding=0.05) # XXX: should be 2 years (both sides) plot = Plot(x_range=xdr, y_range=ydr, plot_width=1000, plot_height=600, toolbar_location=None, outline_line_color=None) plot.title.text = "Usain Bolt vs. 116 years of Olympic sprinters" xticker = SingleIntervalTicker(interval=5, num_minor_ticks=0) xaxis = LinearAxis(ticker=xticker, axis_line_color=None, major_tick_line_color=None, axis_label="Meters behind 2012 Bolt", axis_label_text_font_size="10pt", axis_label_text_font_style="bold") plot.add_layout(xaxis, "below") xgrid = Grid(dimension=0, ticker=xaxis.ticker, grid_line_dash="dashed") plot.add_layout(xgrid) yticker = SingleIntervalTicker(interval=12, num_minor_ticks=0) yaxis = LinearAxis(ticker=yticker, major_tick_in=-5, major_tick_out=10) plot.add_layout(yaxis, "right") radius = dict(value=5, units="screen") medal_glyph = Circle(x="MetersBack", y="Year", radius=radius, fill_color="MedalFill", line_color="MedalLine", fill_alpha=0.5) medal = plot.add_glyph(source, medal_glyph) athlete_glyph = Text(x="MetersBack", y="Year", x_offset=10, text="SelectedName", text_align="left", text_baseline="middle", text_font_size="9pt") athlete = plot.add_glyph(source, athlete_glyph) no_olympics_glyph = Text(x=7.5, y=1942, text=["No Olympics in 1940 or 1944"], text_align="center", text_baseline="middle",
def make_example_datatable(): source = ColumnDataSource(mpg) print(source.column_names) manufacturers = sorted(mpg["manufacturer"].unique()) models = sorted(mpg["model"].unique()) transmissions = sorted(mpg["trans"].unique()) drives = sorted(mpg["drv"].unique()) classes = sorted(mpg["class"].unique()) columns = [ TableColumn(field="manufacturer", title="Manufacturer", editor=SelectEditor(options=manufacturers), formatter=StringFormatter(font_style="bold")), TableColumn(field="model", title="Model", editor=StringEditor(completions=models)), TableColumn(field="displ", title="Displacement", editor=NumberEditor(step=0.1), formatter=NumberFormatter(format="0.0")), TableColumn(field="year", title="Year", editor=IntEditor()), TableColumn(field="cyl", title="Cylinders", editor=IntEditor()), TableColumn(field="trans", title="Transmission", editor=SelectEditor(options=transmissions)), TableColumn(field="drv", title="Drive", editor=SelectEditor(options=drives)), TableColumn(field="class", title="Class", editor=SelectEditor(options=classes)), TableColumn(field="cty", title="City MPG", editor=IntEditor()), TableColumn(field="hwy", title="Highway MPG", editor=IntEditor()), ] data_table = DataTable(source=source, columns=columns, editable=True, width=1000) plot = Plot(title=None, x_range=DataRange1d(), y_range=DataRange1d(), plot_width=1000, plot_height=300) # Set up x & y axis plot.add_layout(LinearAxis(), 'below') yaxis = LinearAxis() plot.add_layout(yaxis, 'left') plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) # Add Glyphs cty_glyph = Circle(x="index", y="cty", fill_color="#396285", size=8, fill_alpha=0.5, line_alpha=0.5) hwy_glyph = Circle(x="index", y="hwy", fill_color="#CE603D", size=8, fill_alpha=0.5, line_alpha=0.5) cty = plot.add_glyph(source, cty_glyph) hwy = plot.add_glyph(source, hwy_glyph) # Add the tools tooltips = [ ("Manufacturer", "@manufacturer"), ("Model", "@model"), ("Displacement", "@displ"), ("Year", "@year"), ("Cylinders", "@cyl"), ("Transmission", "@trans"), ("Drive", "@drv"), ("Class", "@class"), ] cty_hover_tool = HoverTool(renderers=[cty], tooltips=tooltips + [("City MPG", "@cty")]) hwy_hover_tool = HoverTool(renderers=[hwy], tooltips=tooltips + [("Highway MPG", "@hwy")]) select_tool = BoxSelectTool(renderers=[cty, hwy], dimensions='width') plot.add_tools(cty_hover_tool, hwy_hover_tool, select_tool) layout = Column(plot, data_table) doc = Document() doc.add_root(layout) return doc
)) xdr = DataRange1d() ydr = DataRange1d() plot = Plot(title=None, x_range=xdr, y_range=ydr, plot_width=300, plot_height=300, h_symmetry=False, v_symmetry=False, min_border=0, toolbar_location=None) glyph = HexTile(q="q", r="r", size=1, fill_color="#fb9a99", line_color="white") plot.add_glyph(source, glyph) xaxis = LinearAxis() plot.add_layout(xaxis, 'below') yaxis = LinearAxis() plot.add_layout(yaxis, 'left') plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) curdoc().add_root(plot) show(plot)
def create_bar_chart(data, title, x_name, y_name, hover_tool=None, width=100, height=100): """Creates a bar chart plot with the exact styling for the centcom dashboard. Pass in data as a dictionary, desired plot title, name of x axis, y axis and the hover tool HTML. """ # import ipdb; ipdb.set_trace() vid = deepcopy(data) video_id = vid.pop('video_id', None) data_sorted = sort_dict(vid, x_name, y_name) title = "ID " + video_id + " " + title source = ColumnDataSource(data_sorted) xdr = FactorRange(factors=[str(i) for i in data_sorted[x_name]]) ydr = Range1d(start=0, end=1.01) tools = [] if hover_tool: tools = [ hover_tool, ] plot = figure(title=title, x_range=xdr, y_range=ydr, plot_width=width, plot_height=height, h_symmetry=False, v_symmetry=False, min_border=0, toolbar_location="above", tools=tools, responsive=True, outline_line_color="#666666") glyph = VBar(x=x_name, top=y_name, bottom=0, width=.8, fill_color="#e12127") plot.add_glyph(source, glyph) xaxis = LinearAxis() yaxis = LinearAxis() plot.add_layout(Grid(dimension=0, ticker=xaxis.ticker)) plot.add_layout(Grid(dimension=1, ticker=yaxis.ticker)) plot.toolbar.logo = None plot.min_border_top = 0 plot.xgrid.grid_line_color = None plot.ygrid.grid_line_color = "#999999" plot.yaxis.axis_label = "Probability" plot.ygrid.grid_line_alpha = 0.1 plot.xaxis.axis_label = "Class" plot.xaxis.major_label_orientation = 1 return plot