def unrestricted_input(doc): input_box = AutocompleteInput(css_classes=["foo"], completions=["100001", "12344556"], restrict=False) input_box.on_change('value', counter.increment) plot = Plot() doc.add_root(column(input_box, plot))
def modify_doc(doc): source = ColumnDataSource(dict(x=[1, 2], y=[1, 1], val=["a", "b"])) plot = Plot( plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0, ) plot.add_glyph(source, Circle(x="x", y="y", size=20)) plot.add_tools( CustomAction( callback=CustomJS(args=dict(s=source), code=RECORD("data", "s.data")) ) ) input_box = AutocompleteInput(css_classes=["foo"]) input_box.title = "title" input_box.value = "400" input_box.completions = [ "100001", "12344556", "12344557", "3194567289", "209374209374", ] def cb(attr, old, new): source.data["val"] = [old, new] input_box.on_change("value", cb) doc.add_root(column(input_box, plot))
def create_document(directory, chat_titles): (message_df, reacts, title, participants) = parse_json_messages(directory) # ------------------------------------------------------------------------- # Plot Message Timeseries: # ------------------------------------------------------------------------- # Create a color palette to use in plotting: """ Might raise an error when number of people in the group chat is > 20""" colour_palette = Category20[20][0:len(participants)] message_panel = create_message_timeseries_panel(message_df, title, participants, colour_palette) # --------------------------------------------------------------------------+ # Plot Reaction Panel: # --------------------------------------------------------------------------+ reacts_panel = create_react_breakdown_panel(reacts, title, participants, colour_palette) # --------------------------------------------------------------------------+ # Create Panel to Summarise Individual Statistics: # --------------------------------------------------------------------------+ message_log_panel = create_message_log_panel(message_df, title, participants, colour_palette) # --------------------------------------------------------------------------+ # Compile Bokeh Application: # --------------------------------------------------------------------------+ tabs = Tabs(tabs=[message_panel, reacts_panel, message_log_panel]) directory_search = AutocompleteInput(completions = list(chat_titles.keys()), width = 400, height = 30, sizing_mode = "fixed", align = 'end') directory_search.on_change("value", update_data) search_text = Div( text = "<i>Search Chats:</i>", height_policy = "max", sizing_mode = "scale_both", align = "end", style = {"font-family": 'Verdana', "font-size": "17px"} ) # A title which could be included in the top left of the document title = Div( text = "<b>Messenger Analysis</b>", height_policy = "max", sizing_mode = "fixed", align = "start", style = {"font-family": 'Verdana', "font-size": "16px"} ) layout = column(row(search_text,directory_search, Spacer( width=35, height=40, sizing_mode="fixed"), align = "end"), tabs, sizing_mode = "scale_width") return layout
def modify_doc(doc): source = ColumnDataSource(dict(x=[1, 2], y=[1, 1], val=["a", "b"])) plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) plot.add_glyph(source, Circle(x='x', y='y', size=20)) plot.add_tools(CustomAction(callback=CustomJS(args=dict(s=source), code=RECORD("data", "s.data")))) input_box = AutocompleteInput(css_classes=["foo"]) input_box.title = "title" input_box.value = "400" input_box.completions = ["100001", "12344556", "12344557", "3194567289", "209374209374"] def cb(attr, old, new): source.data['val'] = [old, new] input_box.on_change('value', cb) doc.add_root(column(input_box, plot))
def generateAutocompleteWidget(destination_number=1, initial_value="", name=None, placeholder=None): if name is None: name = f'Destination {destination_number}' if placeholder is None: placeholder = 'Enter Location' autocomplete = AutocompleteInput(name=name, completions=['test'], title=name, min_characters=3, value=initial_value, placeholder=placeholder) def autocomplete_callback(attr, old, new): if (len(new) > 0): pass autocomplete.on_change('value_input', autocomplete_callback) return autocomplete
def modify_doc(doc): #callback function def autocomplete_update(attrname, old, new): stream.event(gene=new) print(autocomplete.value) #callback function def dropdown_update(attrname, old, new): streamSet.event(set=new) stream.event(set=new) print(dropdown.value) #initialize dropdown to select cell type dropdown = Select(title="Cell Set", value="all", options=['all', 'microglia']) #initialize autocomplete field for querying genes autocomplete = AutocompleteInput( title="Type in a gene and select from the dropdown", value="", completions=getGenes()) #callbacks dropdown.on_change('value', dropdown_update) autocomplete.on_change('value', autocomplete_update) #get graphs and store in variables hvplot = renderer.get_plot(dmap_query, doc) hvplot_full = renderer.get_plot(dmap_cluster, doc) #create view for HTML plot = gridplot([[autocomplete, dropdown], [hvplot.state, hvplot_full.state]]) #add view to HTML doc doc.add_root(plot)
def bkapp(doc): # global variables global flag_control_global global serial_info # local variables flag_control_local = {"start": False} # the period function @gen.coroutine def update(x, y, flag): global flag_control_global # source.stream(dict(x=[x], y=[y])) if (flag_control_local["start"]): source.data = dict(x=x, y=y) if (flag_control_global["status"]): button_open.disabled = True button_close.disabled = False else: button_open.disabled = False button_close.disabled = True if (flag): select_port.options = refresh_com() def blocking_task(): global data # global flag_control_global count = 0 flag_update = False while True: # do some blocking computation time.sleep(0.05) flag_update = False count = count + 1 if (count >= 50): flag_update = True count = 0 yin = data[:-1] xin = range(len(yin)) # but update the document from callback doc.add_next_tick_callback( partial(update, x=xin, y=yin, flag=flag_update)) def refresh_com(): available_port = ['COM1'] com_available = myserial.SerialConnect.Get_Used_Com() if (len(com_available) > 0): for com in com_available: available_port.append(com["device"]) return available_port # callback event of the button_open def callback_button_open(): serial_info["portx"] = select_port.value serial_info["bps"] = int(text_bps.value) flag_control_global["connect"] = True # flag_control_global["disconnect"] = False button_open.disabled = True button_close.disabled = False print("button open successful") # callback event of the button_close def callback_button_close(): button_open.disabled = False button_close.disabled = True # flag_control_global["connect"] = False flag_control_global["disconnect"] = True print("button close successful") # callback event of the button_start def callback_button_start(): button_start.disabled = True button_stop.disabled = False flag_control_local["start"] = True print("button start successful") # callback event of the button_stop def callback_button_stop(): button_start.disabled = False button_stop.disabled = True flag_control_local["start"] = False print("button stop successful") # def update_text_port(attrname, old, new): # pass def update_select_port(attrnaem, old, new): pass def update_text_bps(attrname, old, new): pass #------------------- data plot --------------------------- source = ColumnDataSource(data=dict(x=[], y=[])) plot = figure( plot_height=300, plot_width=1100, title="serial data wave", tools="crosshair,pan,reset,save,wheel_zoom", ) plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6) # text_port = AutocompleteInput(title="PORT", value='COM1', completions=completions_port) # text_port.on_change('value', update_text_port) #------------------- port selector ----------------------- select_port = Select(title="PORT", value='COM1', options=["COM1", "COM2"]) select_port.on_change('value', update_select_port) #------------------- bps input --------------------------- completions_bps = ["9600", "115200", "4800"] text_bps = AutocompleteInput(title="bps", value='9600', placeholder="Enter value (auto-complete) ...", completions=completions_bps) text_bps.on_change('value', update_text_bps) #------------------- button on --------------------------- button_open = Button(label='Open', button_type="success") button_open.on_click(callback_button_open) #------------------- button close ------------------------ button_close = Button(label='Close', button_type="success", disabled=True) button_close.on_click(callback_button_close) #------------------- button start ------------------------ button_start = Button(label='Start', button_type="success") button_start.on_click(callback_button_start) # button_start.js_on_click(CustomJS(code="alert('button: click!')")) #------------------- button stop ------------------------ button_stop = Button(label='Stop', button_type="success", disabled=True) button_stop.on_click(callback_button_stop) #------------------- widgets column --------------------- serial_control = column(select_port, text_bps, button_open, button_close, button_start, button_stop) #-------------------------------------------------------- #------------------- set-parm layout -------------------- #-------------------------------------------------------- text_set_param_1 = TextInput(title="进样时间(s)", value='10') text_set_param_2 = TextInput(title="分离时间(s)", value='300') text_set_param_3 = TextInput(title="电极电位(伏)", value='214') text_set_param_4 = TextInput(title="采样频率(Hz)", value='20') text_set_param_5 = RadioGroup(labels=["循环伏安扫描", "电泳实验"], active=0) set_param = column(text_set_param_1, text_set_param_2, text_set_param_3, text_set_param_4, text_set_param_5) plot_slider_1 = Slider(title="基线位置", value=10, start=0, end=100, step=0.5) plot_slider_2 = Slider(title="幅度相调", value=20, start=0, end=100, step=0.5) plot_slider_3 = Slider(title="幅度粗调", value=60, start=0, end=100, step=0.5) plot_slider_4 = Slider(title="时间调节", value=40, start=0, end=100, step=0.5) plot_button_1 = Button(label="滤波", button_type="success") plot_slider = column(plot_slider_1, plot_slider_2, plot_slider_3, plot_slider_4, plot_button_1) ctr_button_0 = Button(label="使用说明", height=30, width=100, button_type="success") ctr_button_1 = Button(label="保存数据", height=30, width=100, button_type="success") ctr_button_2 = Button(label="清除数据", height=30, width=100, button_type="success") ctr_button_3 = Button(label="载入数据", height=30, width=100, button_type="success") ctr_button_4 = Button(label="加载参数", height=30, width=100, button_type="success") ctr_button_5 = Button(label="保存图像", height=30, width=100, button_type="success") ctr_button_6 = Button(label="指令交互", height=30, width=100, button_type="success") ctr_button_7 = Button(label="配置仪器", height=30, width=100, button_type="success") ctr_button = column(ctr_button_1, ctr_button_2, ctr_button_3, ctr_button_4, ctr_button_5, ctr_button_6, ctr_button_7) #-------------------------------------------------------- #-------------------- Top layout ------------------------ #-------------------------------------------------------- layout_1 = row(plot) layout_2 = row(ctr_button, serial_control, set_param, plot_slider) # layout_3 = column(layout_1, layout_2) # layout_top = row(ctr_button,layout_3) layout_top = column(layout_1, layout_2) doc.add_root(layout_top) thread_update_data = Thread(target=blocking_task) thread_update_data.start()
'x': xlist, 'y': ylist, 'colors': colors, 'labels': new_ngrams } main_line.visible = True p.legend.visible = True def clear_lines(): global new_ngrams, lookup_list, box new_ngrams = [] main_line.visible = False p.legend.visible = False lookup_list = list(group.columns) # set up autocomplete box and trigger box = AutocompleteInput(completions=lookup_list, placeholder='Enter text') #box = TextInput(placeholder='Enter text') box.on_change('value', update_plot) clear = Button(label='clear all lines') clear.on_click(clear_lines) # create layout box_widget = widgetbox(box) clear_widget = widgetbox(clear) layout = column(p, row(box_widget, clear_widget)) curdoc().add_root(layout)
def prepare_server(doc, input_data, cell_stack, cell_markers=None, default_cell_marker=None): @lru_cache() def image_markers(lower=False, mapping=False): if mapping: return { y: j for j, y in sorted( ((i, x) for i, x in enumerate( image_markers(lower=lower, mapping=False))), key=lambda x: x[1].lower(), ) } if lower: return [ x.lower() for x in image_markers(lower=False, mapping=False) ] return (cell_markers if cell_markers is not None else [f"Marker {i + 1}" for i in range(cell_stack.shape[1])]) # Data sources ########################################################################### def prepare_data(input_data): data = input_data.copy() if "contour" in data and not all(x in data for x in ["contour_x", "contour_y"]): contour = parse_contour(data["contour"]) data["contour_x"] = contour[0] data["contour_y"] = contour[1] if "marked" not in data: data["marked"] = np.full(data.shape[0], "") source.data = data source = ColumnDataSource(data={}) prepare_data(input_data) image_source = ColumnDataSource( data=dict(image=[], dw=[], dh=[], contour_x=[], contour_y=[])) # Cell picture plot ########################################################################### def add_outline(): data = source.data if all(x in data for x in ["contour_x", "contour_y"]): cell_outline = cell_figure.patches( xs="contour_x", ys="contour_y", fill_color=None, line_color="red", name="cell_outline", source=image_source, ) cell_outline.level = "overlay" else: cell_outline = cell_figure.select(name="cell_outline") for x in cell_outline: cell_figure.renderers.remove(x) default_cell_marker = (0 if default_cell_marker is None else image_markers( mapping=True)[default_cell_marker]) cell_markers_select = Select( value=str(default_cell_marker), options=list( (str(i), x) for x, i in image_markers(mapping=True).items()), title="Marker cell image", ) cell_marker_input = AutocompleteInput( completions=list(image_markers()) + list(image_markers(lower=True)), min_characters=1, placeholder="Search for marker", ) cell_slider = RangeSlider(start=0, end=1, value=(0, 1), orientation="vertical", direction="rtl") metric_select = RadioButtonGroup(active=0, labels=CELL_IMAGE_METRICS[0]) stats = PreText(text="", width=100) cell_mapper = bokeh.models.mappers.LinearColorMapper(viridis(20), low=0, high=1000, high_color=None) cell_color_bar = ColorBar(color_mapper=cell_mapper, width=12, location=(0, 0)) cell_figure = figure( plot_width=450, plot_height=350, tools="pan,wheel_zoom,reset", toolbar_location="left", ) cell_image = cell_figure.image( image="image", color_mapper=cell_mapper, x=0, y=0, dw="dw", dh="dh", source=image_source, ) add_outline() cell_figure.add_layout(cell_color_bar, "right") # Edit data of selected cells ########################################################################### marker_edit_container = column() marker_edit_instances = [] def add_marker_edit_callback(): editor = ColumnEditor( source, marker_edit_container, log_widget=edit_selecton_log, editor_delete_callback=delete_marker_edit_callback, external_edit_callback=edit_selection_callback, ) marker_edit_instances.append(editor) def delete_marker_edit_callback(editor): idx = next(i for i, x in enumerate(marker_edit_instances) if x is editor) del marker_edit_instances[idx] file_name_text = Div() add_marker_edit_button = Button(label="+", button_type="success", align=("start", "end"), width=50) add_marker_edit_button.on_click(add_marker_edit_callback) edit_selection_submit = Button(label="Submit change", button_type="primary", align=("start", "end")) download_button = Button(label="Download edited data", button_type="success", align=("start", "end")) download_button.js_on_click( CustomJS(args=dict(source=source), code=DOWNLOAD_JS)) edit_selecton_log = TextAreaInput(value="", disabled=True, css_classes=["edit_log"], cols=30, rows=10) upload_file_input = FileInput(accept="text/csv", align=("end", "end")) # Cell table ########################################################################### default_data_table_cols = [ TableColumn(field="marked", title="Seen", width=20) ] data_table = DataTable(source=source, columns=default_data_table_cols, width=800) # Callbacks for buttons and widgets ########################################################################### def cell_slider_change(attrname, old, new): cell_mapper.low = new[0] cell_mapper.high = new[1] def selection_change(attrname, old, new): selected = source.selected.indices data = source.data if not selected: return mean_image = CELL_IMAGE_METRICS[1][metric_select.active]( cell_stack[selected, int(cell_markers_select.value), :, :], axis=0) image_data = { "image": [mean_image], "dw": [cell_stack.shape[2]], "dh": [cell_stack.shape[3]], } for coord in ["contour_x", "contour_y"]: try: image_data[coord] = list(data[coord][selected]) except KeyError: pass image_source.data = image_data image_extr = round_signif(mean_image.min()), round_signif( mean_image.max()) cell_slider.start = image_extr[0] cell_slider.end = image_extr[1] cell_slider.step = round_signif((image_extr[1] - image_extr[0]) / 50) cell_slider.value = image_extr stats.text = "n cells: " + str(len(selected)) def autocomplete_cell_change(attrname, old, new): try: idx = image_markers(mapping=True)[new] except KeyError: try: idx = image_markers(lower=True, mapping=True)[new] except KeyError: return cell_markers_select.value = str(idx) cell_marker_input.value = None def data_change(attrname, old, new): new_keys = [n for n in new.keys() if n not in set(old.keys())] for n in new_keys: data_table.columns.append(TableColumn(field=n, title=n)) def edit_selection_submit_click(): for x in marker_edit_instances: x.edit_callback() def edit_selection_callback(): idx = source.selected.indices try: if len(idx) == 1 and all( source.data[x.widgets["input_col"].value][idx] != "NA" for x in marker_edit_instances): source.selected.indices = [idx[0] + 1] except KeyError: pass def upload_file_callback(attrname, old, new): try: data_text = b64decode(new) data = pd.read_csv(BytesIO(data_text)) except Exception: file_name_text.text = f"Error loading file {upload_file_input.filename}" return file_name_text.text = f"Editing file {upload_file_input.filename}" # Have to regenerate contours try: del data["contour_x"] del data["contour_y"] except KeyError: pass data_table.columns = default_data_table_cols prepare_data(data) add_outline() source.selected.on_change("indices", selection_change) source.on_change("data", data_change) cell_slider.on_change("value", cell_slider_change) metric_select.on_change("active", selection_change) cell_markers_select.on_change("value", selection_change) cell_marker_input.on_change("value", autocomplete_cell_change) edit_selection_submit.on_click(edit_selection_submit_click) upload_file_input.on_change("value", upload_file_callback) style_div = Div(text=CUSTOM_CSS) # set up layout layout = column( row( column(data_table), column( cell_markers_select, cell_marker_input, metric_select, row(cell_figure, cell_slider), stats, ), ), file_name_text, marker_edit_container, add_marker_edit_button, row(edit_selection_submit, download_button, upload_file_input), edit_selecton_log, style_div, ) doc.add_root(layout) doc.title = "Cell classifier"
value='', case_sensitive=False, completions=autocomplete_names, css_classes=['autocomplete'], placeholder='Search for director, writer, actor') def update_name(attr, old, new): global name if (new != old): name = new.split(' (')[0] update_data() search_bar.on_change('value', update_name) search_bar_button = Button(name='filter_name_button', label='Clear', width=80) def clear_name(): global name if (name != ''): name = '' search_bar.value = '' update_data() search_bar_button.on_click(clear_name)
def bkapp(doc): # global variables global flag_control_global global serial_info global Data # local variables flag_control_local = { "start": False, "exit": False, "clear": False, "load": False } filename_control = ColumnDataSource(data=dict( save_flag=[False], save_name=["data0.csv"], load_name=["data0.csv"])) # { "save" : False, # "save_name" : "data.csv", # "load_name" : "data.csv"} # widegs toolbar TOOLS = "hover,crosshair,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,undo,redo,reset,tap,save,box_select,poly_select,lasso_select" # the period function @gen.coroutine def update(flag): global flag_control_global if (flag_control_local["clear"]): flag_control_local["clear"] = False print("Clearing !!!") source.data = dict(x=[], y=[]) if (flag_control_local["load"]): flag_control_local["load"] = False Data.load_data("data.csv") y = Data.container.copy() x = list(range(len(y))) source.data = dict(x=x, y=y) if (flag_control_local["start"]): y, base_len = Data.get_buffer() x = list(range(base_len - len(y), base_len, 1)) if (len(y) > 0): source.stream(dict(x=x, y=y)) # source.data = dict(x=x, y=y) if (flag_control_global["status"]): button_open.disabled = True button_close.disabled = False else: button_open.disabled = False button_close.disabled = True if (flag): select_port.options = refresh_com() def blocking_task(): count = 0 flag_update = False while True: time.sleep(0.05) flag_update = False count = count + 1 if (flag_control_local["exit"]): print("Exiting !!!!!!!") os._exit(0) # if(filename_control.data['save_flag'][0]): # filename_control.data['save_flag'][0] = False # print("save the data!!!") if (count >= 40): print(filename_control.data['save_flag'][0], "\t", filename_control.data['save_name'][0]) flag_update = True count = 0 # if (count>=50): # flag_update = True # count = 0 # update the document from callback doc.add_next_tick_callback(partial(update, flag=flag_update)) def refresh_com(): available_port = [] com_available = myserial.SerialConnect.Get_Used_Com() if (len(com_available) > 0): for com in com_available: available_port.append(com["device"]) return available_port # callback event of the button_open def callback_button_open(): serial_info["portx"] = select_port.value serial_info["bps"] = int(text_bps.value) flag_control_global["connect"] = True # flag_control_global["disconnect"] = False button_open.disabled = True button_close.disabled = False print("button open") # callback event of the button_close def callback_button_close(): button_open.disabled = False button_close.disabled = True # flag_control_global["connect"] = False flag_control_global["disconnect"] = True print("button close") # callback event of the button_start def callback_button_start(): button_start.disabled = True button_stop.disabled = False flag_control_local["start"] = True print("button start") # callback event of the button_stop def callback_button_stop(): button_start.disabled = False button_stop.disabled = True flag_control_local["start"] = False print("button stop") customjs_button_1 = CustomJS(args=dict(source=filename_control), code=""" var file = window.prompt("Input the file name","data.csv"); var flag = [true]; var name = [file]; source.data['save_flag'] = flag; source.data['save_name'] = name; // source.change.emit(); window.alert("Saving !!!"); """) def callback_ctr_button_1(): Data.save_data("data.csv") print("save the data") pass def callback_ctr_button_2(): flag_control_local["clear"] = True print("clear the data") pass def callback_ctr_button_3(): flag_control_local["load"] = True print("load local data") pass def callback_ctr_button_5(): ctr_button_5.disabled = True print("Exit the system") flag_control_local["exit"] = True def update_select_port(attrnaem, old, new): pass def update_text_bps(attrname, old, new): pass def mk_tab(type): plot_tab = figure( plot_height=300, plot_width=1100, tools=TOOLS, toolbar_location="above") # background_fill_color="lightgrey" # toolbar_location : "below" "above" "left" "right" if type == "line": plot_tab.line('x', 'y', source=source, line_width=2, line_alpha=0.6) elif type == "scatter": plot_tab.scatter('x', 'y', source=source, fill_alpha=0.6, size=1) return Panel(title=type, child=plot_tab) #------------------- data plot --------------------------- source = ColumnDataSource(data=dict(x=[], y=[])) # plot = figure(plot_height=300, plot_width=1100,tools=TOOLS,toolbar_location="above") # title="serial data wave", # plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6) #------------------- Plot Tab --------------------------- tabs = Tabs(tabs=[mk_tab("scatter"), mk_tab("line")]) #------------------- port selector ----------------------- select_port = Select(title="PORT", value='COM1', options=["COM1", "COM2"]) select_port.on_change('value', update_select_port) #------------------- bps input --------------------------- completions_bps = ["9600", "115200", "4800"] text_bps = AutocompleteInput(title="bps", value='9600', placeholder="Enter value (auto-complete) ...", completions=completions_bps) text_bps.on_change('value', update_text_bps) #------------------- button on --------------------------- button_open = Button(label='Open', button_type="success") button_open.on_click(callback_button_open) #------------------- button close ------------------------ button_close = Button(label='Close', button_type="success", disabled=True) button_close.on_click(callback_button_close) #------------------- button start ------------------------ button_start = Button(label='Start', button_type="success") button_start.on_click(callback_button_start) # button_start.js_on_click(CustomJS(code="alert('button: click!')")) #------------------- button stop ------------------------ button_stop = Button(label='Stop', button_type="success", disabled=True) button_stop.on_click(callback_button_stop) #------------------- widgets column --------------------- serial_control = column(select_port, text_bps, button_open, button_close, button_start, button_stop) #-------------------------------------------------------- #------------------- set-parm layout -------------------- #-------------------------------------------------------- text_set_param_1 = TextInput(title="进样时间(s)", value='10') text_set_param_2 = TextInput(title="分离时间(s)", value='300') text_set_param_3 = TextInput(title="电极电位(伏)", value='214') text_set_param_4 = TextInput(title="采样频率(Hz)", value='20') text_set_param_5 = RadioGroup(labels=["循环伏安扫描", "电泳实验"], active=0) set_param = column(text_set_param_1, text_set_param_2, text_set_param_3, text_set_param_4, text_set_param_5) plot_slider_1 = Slider(title="基线位置", value=10, start=0, end=100, step=0.5) plot_slider_2 = Slider(title="幅度相调", value=20, start=0, end=100, step=0.5) plot_slider_3 = Slider(title="幅度粗调", value=60, start=0, end=100, step=0.5) plot_slider_4 = Slider(title="时间调节", value=40, start=0, end=100, step=0.5) plot_button_1 = Button(label="滤波", button_type="success") plot_slider = column(plot_slider_1, plot_slider_2, plot_slider_3, plot_slider_4, plot_button_1) ctr_button_0 = Button(label="使用说明", height=30, width=100, button_type="success") ctr_button_1 = Button(label="保存数据", height=30, width=100, button_type="success") ctr_button_2 = Button(label="清除数据", height=30, width=100, button_type="success") ctr_button_3 = Button(label="载入数据", height=30, width=100, button_type="success") ctr_button_4 = Button(label="加载参数", height=30, width=100, button_type="success") ctr_button_5 = Button(label="退出系统", height=30, width=100, button_type="success") ctr_button_6 = Button(label="指令交互", height=30, width=100, button_type="success") ctr_button_7 = Button(label="配置仪器", height=30, width=100, button_type="success") ctr_button_1.on_click(callback_ctr_button_1) # ctr_button_1.js_on_click(customjs_button_1) # ctr_button_1.js_on_event(events.ButtonClick, customjs_button_1) ctr_button_2.on_click(callback_ctr_button_2) ctr_button_3.on_click(callback_ctr_button_3) ctr_button_5.on_click(callback_ctr_button_5) ctr_button = column(ctr_button_1, ctr_button_2, ctr_button_3, ctr_button_4, ctr_button_5, ctr_button_6, ctr_button_7) #-------------------------------------------------------- #-------------------- Top layout ------------------------ #-------------------------------------------------------- layout_1 = column(tabs) layout_2 = row(ctr_button, serial_control, plot_slider, set_param) layout_top = column(layout_1, layout_2) doc.add_root(layout_top) thread_update_data = Thread(target=blocking_task) thread_update_data.start()
def create_plot(doc): """Creat a bokeh plot.""" # create a plot and style its properties # doc = curdoc() doc.theme = Theme(filename=join(dirname(__file__), 'theme.yaml')) doc.title = 'Sample bokeh plot' sp = StockPrices() plot_width = 600 plot_height = 600 # elements symbol_selector = AutocompleteInput(completions=list(sp.get_symbols()), width=150) period_selector = RadioButtonGroup(labels=[ "Today" if datetime.today().weekday() < 5 else "Friday", "5 days", "1 month", "6 months", "1 year", "5 years" ], active=5, width=400) selected = ['GOOGL', 'AMZN'] spinner = Div(text='') overlay = Div(text='') layout = column(Div(text='<header><h1>Stock Closing Prices</h1></header>', width=plot_width), row(column( widgetbox(Div(text='<h3>Period</h3>'), period_selector, width=400)), column( widgetbox(Div(text='<h3>Symbols</h3>'), symbol_selector, width=plot_width - 400)), height=95), plot(period_selector.active, plot_width, plot_height, get_data(sp, selected, period_selector.active)), spinner, overlay, width=plot_width + 20, height=plot_height + 120, sizing_mode='fixed') # layout.css_classes = ['wrapper'] doc.add_root(layout) # Set up callbacks # symbol selector def update_symbol_list(attr, old, new): """Update selected symobls.""" spinner.css_classes = ['loader-spinner'] overlay.css_classes = ['loader-overlay'] if symbol_selector.value is None: return if symbol_selector.value in selected: selected.remove(symbol_selector.value) else: selected.append(symbol_selector.value) if selected is None: _data = None else: _data = get_data(sp, selected, period_selector.active) layout.children[2] = plot(period_selector.active, plot_width, plot_height, _data) symbol_selector.value = None spinner.css_classes = [] overlay.css_classes = [] symbol_selector.on_change('value', update_symbol_list) # period selector def update_period(attr, old, new): """Update selected period.""" spinner.css_classes = ['loader-spinner'] overlay.css_classes = ['loader-overlay'] _data = get_data(sp, selected, period_selector.active) layout.children[2] = plot(period_selector.active, plot_width, plot_height, _data) spinner.css_classes = [] overlay.css_classes = [] period_selector.on_change('active', update_period)
def create_message_log_panel(message_df, title, participants, colour_palette): def filter_for_user(attr, old, new): df = deepcopy(message_df) df = df[df['Type'] == 'Message'] if new in participants: df = df[df['Name'] == new] message_CDS.data = df elif new == 'all': message_CDS.data = df # Old version, probably not so relevant anymore type_counts = message_df.groupby(['Name', 'Type']).count().reset_index() type_counts = ColumnDataSource(type_counts) type_bar_graph = figure(x_range=[*message_df['Type'].unique()], plot_height=350, title="Distribution of Types", toolbar_location=None, tools="") type_bar_graph.vbar(source=type_counts, x='Type', top='Message', width=0.9) type_bar_graph.xgrid.grid_line_color = None type_bar_graph.y_range.start = 0 # Create DataTable Widget: columns = [ TableColumn(field="Message", title="Message"), TableColumn(field="Name", title="Name", width=10), TableColumn(field="Date", title="Date", formatter=DateFormatter(format="%d/%m/%Y"), width=10) ] message_CDS = ColumnDataSource(message_df[message_df['Type'] == 'Message']) data_table = DataTable(source=message_CDS, columns=columns, fit_columns=True, width=700, height=350) directory_search = AutocompleteInput(completions=participants, width=400, height=30, sizing_mode="fixed", align='start') directory_search.on_change("value", filter_for_user) filter_text = Div(text="Filter for a Particular User:"******"max", sizing_mode="scale_both", align="end", style={ "font-family": 'Verdana', "font-size": "17px" }) filter_input = row(filter_text, directory_search) message_log_panel = layout( [column(filter_input, data_table, sizing_mode="scale_both")], sizing_mode="scale_both") message_log_panel = Panel(child=message_log_panel, title='Message Log') return message_log_panel
def prepare_server( doc, input_data, cell_stack, cell_markers=None, default_umap_marker=None, default_cell_marker=None, ): @lru_cache() def get_data(m=None): d = input_data if m is not None: m_v = d[m] if np.issubdtype(m_v.dtype, np.number): d["marker_val_num"] = m_v else: d["marker_val_cat"] = m_v if "marker_val_num" not in d: d["marker_val_num"] = np.arange(d.shape[0]) if "marker_val_cat" not in d: d["marker_val_cat"] = np.full(d.shape[0], "a") return d @lru_cache() def get_cat_colors(n): return Colorblind[max(3, n)][:n] @lru_cache() def marker_cols(lower=False): markers = list(sorted(input_data.columns, key=lambda x: x.lower())) if lower: return {x.lower(): x for x in markers} return markers @lru_cache() def image_markers(lower=False, mapping=False): if mapping: return { y: j for j, y in sorted( ( (i, x) for i, x in enumerate(image_markers(lower=lower, mapping=False)) ), key=lambda x: x[1].lower(), ) } if lower: return [x.lower() for x in image_markers(lower=False, mapping=False)] return ( cell_markers if cell_markers is not None else [f"Marker {i + 1}" for i in range(cell_stack.shape[1])] ) input_data = input_data.copy() # Marker selection for UMAP plots ########################################################################### if default_umap_marker is None: default_umap_marker = marker_cols()[0] marker_select = Select( value=default_umap_marker, options=marker_cols(), title="Color UMAP by" ) marker_input = AutocompleteInput( completions=marker_cols() + list(marker_cols(lower=True).keys()), min_characters=1, placeholder="Search for marker", ) marker_slider = RangeSlider( start=0, end=1, value=(0, 1), step=0.1, orientation="vertical", direction="rtl" ) # Data sources ########################################################################### source = ColumnDataSource(data=get_data(None)) image_source = ColumnDataSource(data=dict(image=[], dw=[], dh=[])) # UMAP scatter plot for numeric data ########################################################################### umap_figure = figure( plot_width=800, plot_height=500, tools="pan,wheel_zoom,lasso_select,box_select,tap,reset", active_scroll="wheel_zoom", active_drag="box_select", active_tap="tap", toolbar_location="left", ) marker_mapper = linear_cmap( field_name="marker_val_num", palette=inferno(10)[:-1], low=0, high=500, high_color=None, ) umap_scatter_renderer = umap_figure.circle( "d1", "d2", size=8, source=source, fill_alpha=0.5, line_alpha=0.9, fill_color=marker_mapper, line_color=marker_mapper, selection_fill_alpha=0.8, selection_line_alpha=1, selection_line_color="black", nonselection_alpha=0.2, hover_line_color="black", ) umap_color_bar = ColorBar( color_mapper=marker_mapper["transform"], width=12, location=(0, 0) ) umap_figure.add_layout(umap_color_bar, "right") umap_figure.add_tools( HoverTool(tooltips=None, renderers=[umap_scatter_renderer], mode="mouse") ) # UMAP scatter plot for categorical data ########################################################################### umap_figure_cat = figure( plot_width=800, plot_height=500, tools="pan,wheel_zoom,lasso_select,box_select,tap,reset", active_scroll="wheel_zoom", active_drag="box_select", active_tap="tap", x_range=umap_figure.x_range, y_range=umap_figure.y_range, toolbar_location="left", ) marker_mapper_cat = factor_cmap( field_name="marker_val_cat", palette=["#000000"], factors=["a"] ) umap_figure_cat.circle( "d1", "d2", size=8, source=source, legend_field="marker_val_cat", alpha=0.7, fill_color=marker_mapper_cat, line_color=None, selection_alpha=0.9, selection_line_color="black", nonselection_alpha=0.5, ) umap_figure_cat.legend.location = "top_right" umap_figure_cat.legend.orientation = "vertical" # Cell picture plot ########################################################################### default_cell_marker = ( 0 if default_cell_marker is None else image_markers(mapping=True)[default_cell_marker] ) cell_markers_select = Select( value=str(default_cell_marker), options=list((str(i), x) for x, i in image_markers(mapping=True).items()), title="Marker cell image", ) cell_marker_input = AutocompleteInput( completions=list(image_markers()) + list(image_markers(lower=True)), min_characters=1, placeholder="Search for marker", ) cell_slider = RangeSlider( start=0, end=1, value=(0, 1), orientation="vertical", direction="rtl" ) metric_select = RadioButtonGroup(active=0, labels=CELL_IMAGE_METRICS[0]) stats = PreText(text="", width=100) cell_mapper = bokeh.models.mappers.LinearColorMapper( viridis(20), low=0, high=1000, high_color=None ) cell_color_bar = ColorBar(color_mapper=cell_mapper, width=12, location=(0, 0)) cell_figure = figure( plot_width=450, plot_height=350, tools="pan,wheel_zoom,reset", toolbar_location="left", ) cell_image = cell_figure.image( image="image", color_mapper=cell_mapper, x=0, y=0, dw="dw", dh="dh", source=image_source, ) cell_figure.add_layout(cell_color_bar, "right") # Edit data of selected cells ########################################################################### edit_selection_col = TextInput(title="Column") edit_selection_val = TextInput(title="Value") edit_selection_submit = Button( label="Submit change", button_type="primary", align=("start", "end") ) edit_selecton_log = PreText(text="") download_button = Button( label="Download cell data", button_type="success", align=("start", "end") ) download_button.js_on_click(CustomJS(args=dict(source=source), code=DOWNLOAD_JS)) # Callbacks for buttons and widgets ########################################################################### def marker_change(attrname, old, new): update() def cell_slider_change(attrname, old, new): cell_mapper.low = new[0] cell_mapper.high = new[1] def marker_slider_change(attrname, old, new): marker_mapper["transform"].low = new[0] marker_mapper["transform"].high = new[1] def update(update_range=True): m = marker_select.value d = get_data(m) source.data = d numeric_marker = np.issubdtype(d[m].dtype, np.number) if not numeric_marker: levels = list(sorted(set(d["marker_val_cat"]))) marker_mapper_cat["transform"].palette = get_cat_colors(len(levels)) marker_mapper_cat["transform"].factors = levels elif update_range and numeric_marker: marker_max = round_signif(d["marker_val_num"].max()) marker_min = round_signif(d["marker_val_num"].min()) marker_slider.start = marker_min marker_slider.end = marker_max marker_slider.step = round_signif((marker_max - marker_min) / 50) marker_slider.value = tuple( map(round_signif, np.percentile(d["marker_val_num"], [5, 95])) ) umap_figure.visible = numeric_marker umap_figure_cat.visible = not numeric_marker marker_slider.visible = numeric_marker def selection_change(attrname, old, new): m = marker_select.value data = get_data(m) selected = source.selected.indices if not selected: return data = data.iloc[selected, :] mean_image = CELL_IMAGE_METRICS[1][metric_select.active]( cell_stack[selected, int(cell_markers_select.value), :, :], axis=0 ) image_source.data = { "image": [mean_image], "dw": [cell_stack.shape[1]], "dh": [cell_stack.shape[2]], } image_extr = round_signif(mean_image.min()), round_signif(mean_image.max()) cell_slider.start = image_extr[0] cell_slider.end = image_extr[1] cell_slider.step = round_signif((image_extr[1] - image_extr[0]) / 50) cell_slider.value = image_extr stats.text = "n cells: " + str(len(selected)) def mark_selection(): get_data.cache_clear() col = edit_selection_col.value if col is None or col == "": return if col not in input_data: input_data[col] = np.full(input_data.shape[0], "NA") col_type = input_data[col].dtype idx = source.selected.indices try: val = np.full(len(idx), edit_selection_val.value).astype(col_type) input_data.loc[input_data.index[idx], col] = val except Exception as e: edit_selecton_log.text = ( f'Failed to edit cells. Exception: "{e}"\n' + edit_selecton_log.text ) else: edit_selecton_log.text = ( f'Edited {len(source.selected.indices)} cells. {col}="{edit_selection_val.value}"\n' + edit_selecton_log.text ) update(update_range=False) old_marker_cols = set(marker_cols()) marker_cols.cache_clear() if old_marker_cols != set(marker_cols()): marker_select.options = marker_cols() marker_input.completions = marker_cols() + list( marker_cols(lower=True).keys() ) def autocomplete_change(attrname, old, new): if new not in marker_cols(): try: new = marker_cols(lower=True)[new] except KeyError: return marker_select.value = new marker_input.value = None def autocomplete_cell_change(attrname, old, new): try: idx = image_markers(mapping=True)[new] except KeyError: try: idx = image_markers(lower=True, mapping=True)[new] except KeyError: return cell_markers_select.value = str(idx) cell_marker_input.value = None source.selected.on_change("indices", selection_change) marker_select.on_change("value", marker_change) marker_slider.on_change("value", marker_slider_change) cell_slider.on_change("value", cell_slider_change) metric_select.on_change("active", selection_change) cell_markers_select.on_change("value", selection_change) edit_selection_submit.on_click(mark_selection) marker_input.on_change("value", autocomplete_change) cell_marker_input.on_change("value", autocomplete_cell_change) # set up layout layout = column( row( column( marker_select, marker_input, row(umap_figure, marker_slider), umap_figure_cat, ), column( cell_markers_select, cell_marker_input, metric_select, row(cell_figure, cell_slider), stats, ), ), Div(text="Change data for selected cells"), row( edit_selection_col, edit_selection_val, edit_selection_submit, download_button, ), edit_selecton_log, ) # initialize update() doc.add_root(layout) doc.title = "UMAP projection"