def build_stmt_table( pred_stmt_dict: Dict, tnt_grp: RadioButtonGroup, b_grp: RadioButtonGroup, cc_grp: RadioButtonGroup ) -> Tuple[DataTable, ColumnDataSource, CDSView]: stmttable_cds = ColumnDataSource(pred_stmt_dict) stmtcolumn = [ TableColumn(field="statement_text", title="Statement", width=4000) ] js_filter = CustomJSFilter(args=dict(stmttable_cds=stmttable_cds, tnt_grp=tnt_grp, b_grp=b_grp, cc_grp=cc_grp), code=dashboard_constants.cdsview_jsfilter_code) stmt_view = CDSView(source=stmttable_cds, filters=[js_filter]) stmttable = DataTable(source=stmttable_cds, columns=stmtcolumn, header_row=False, index_position=None, view=stmt_view, height_policy='max', width_policy='max', fit_columns=False, scroll_to_selection=False, margin=(5, 5, 5, 5), width=300, height=300, min_height=50, css_classes=['box', 'stmt_table']) return stmttable, stmttable_cds, stmt_view
def getTimeSeries_newish(df_tws): df_tws['date'] = pd.to_datetime(df_tws['date'], format='%m/%d/%Y') grouped = df_tws.groupby( [pd.Grouper(key='date', freq='M'), 'keyword'])['sentiment'].count().to_frame(name='count').reset_index() print(grouped) source = ColumnDataSource(grouped) p = figure(plot_height=400, x_axis_type='datetime') p.line(x='date', y='count', line_width=2, source=source, legend='Music') p.line(x='date', y='count', line_width=2, source=source, legend='Art') p.yaxis.axis_label = 'Number of Tweets' s = Select(title="test", value="music", options=['art', 'music']) w2 = CheckboxGroup(labels=["One", "Two", "Three"], active=[1, 1, 1]) callback = CustomJS(args=dict(src=source), code=''' src.change.emit(); ''') js_filter = CustomJSFilter(code=''' var indices = []; for (var i = 0; i < src.get_length(); i++){ if (src.data['keyword'][i] == select.value){ indices.push(true); } else { indices.push(false); } } return indices; ''') s.js_on_change('value', callback) return p, s, w2
def get_checkboxes_with_filter(labels: List[str], column_label: str, source, select_all_btn=True, clear_all_btn=True): """ :param labels: names for checkbox labels as list (dataframe must contain it as value to filter) :param column_label: name of column in dataframe :param source: dataframe :return: checkboxes and filter for graph """ # routes checkboxes checkboxes = CheckboxGroup(labels=labels, active=list(range(len(labels)))) filter = CustomJSFilter(code=''' var selected = checkboxes.active.map(i=>checkboxes.labels[i]); var indices = []; var column = source.data[column_label]; // iterate through rows of data source and see if each satisfies some constraint for (var i = 0; i < column.length; i++){ if(selected.includes(column[i])){ indices.push(true); } else { indices.push(false); } } console.log("filter completed"); return indices; ''', args=dict(checkboxes=checkboxes, column_label=column_label)) checkboxes.js_on_change( "active", CustomJS(code="source.change.emit();", args=dict(source=source))) widgets = [checkboxes] if select_all_btn: select_all = Button(label="выбрать все", width=65, height=30) select_all.js_on_click( CustomJS(args=dict(checkboxes=checkboxes, all_active=list(range(len(labels)))), code=""" checkboxes.active = all_active """)) widgets.append(select_all) if clear_all_btn: clear_all = Button(label="отчистить все", width=65, height=30) clear_all.js_on_click( CustomJS(args=dict(checkboxes=checkboxes), code=""" checkboxes.active = [] """)) widgets.append(clear_all) return Column(*widgets), filter
def js_filter(modifier, slider): code = ''' var indices = []; for (var i = 0; i <= source.data['word_length'].length; i++){{ if (source.data['word_length'][i] == slider.value-{0}) {{ indices.push(i) }} }} return indices '''.format(modifier) return CustomJSFilter(args=dict(slider=slider), code=code)
def build_autocomplete_grph_driver(rtplot: Figure, plots: List, ms_plot: Figure, patchsources: Dict[str, Tuple], source: ColumnDataSource, default_county: str, counties: pd.Index) -> Tuple[CDSView, AutocompleteInput]: choices = AutocompleteInput(completions=counties.tolist(), case_sensitive=False, value=default_county, title='Search for county or select from table:', name="county_input", width_policy='fit', css_classes=['autocomplete_input'], min_width=250, align="start") someargs = dict(source=source, rtplot=rtplot, rtxaxis=rtplot.xaxis[0], rtyaxis=rtplot.yaxis[0], ms_plot=ms_plot, ms_plot_xaxis=ms_plot.xaxis[0], ms_plot_yaxis0=ms_plot.yaxis[0], plots=plots, choices=choices, patchsources=patchsources) someargs['xaxes'], someargs['yaxes'], someargs['plots'] = [], [], [] for p in plots: someargs['xaxes'].append(p['plot'].xaxis[0]) someargs['yaxes'].append(p['plot'].yaxis[0]) someargs['plots'].append(p['plot']) callback = CustomJS(args=someargs, code=constants.autocomplete_input_code) choices.js_on_change('value', callback) js_filter = CustomJSFilter(args=dict(choices=choices), code=constants.cdsview_jsfilter_code) view = CDSView(source=source, filters=[js_filter]) return view, choices
def get_checkbox_btn_with_filter(labels: List[str], column_label: str, source): """ :param labels: names for checkbox labels as list (dataframe must contain it as value to filter) :param column_label: name of column in dataframe :param source: dataframe :return: checkboxes and filter for graph """ # routes checkboxes checkboxes = CheckboxButtonGroup(labels=labels, width=65) filter = CustomJSFilter(code=''' var selected = checkboxes.active.map(i=>true); var indices = []; var column = source.data[column_label]; // iterate through rows of data source and see if each satisfies some constraint if(!selected.length){ return Array(column.length).fill(true) } for (var i = 0; i < column.length; i++){ if(selected.includes(column[i])){ indices.push(true); } else { indices.push(false); } } console.log("filter completed"); return indices; ''', args=dict(checkboxes=checkboxes, column_label=column_label)) checkboxes.js_on_change( "active", CustomJS(code="source.change.emit();", args=dict(source=source))) widgets = [checkboxes] return Column(*widgets), filter
start=min_speed, # end=max_speed, end=55, step=1, value=(min_speed, 55), ) speed_filter = CustomJSFilter(code=''' var min_speed = speed_slider.value[0] var max_speed = speed_slider.value[1] var indices = []; var column = source.data['speed']; // iterate through rows of data source and see if each satisfies some constraint for (var i = 0; i < column.length; i++){ if(column[i]>min_speed && column[i]<max_speed){ indices.push(true); } else { indices.push(false); } } console.log("filter completed"); return indices; ''', args={'speed_slider': speed_slider}) speed_slider.js_on_change( "value", CustomJS(code="source.change.emit();", args=dict(source=source_visible))) # range slider for time start = datetime.datetime.fromtimestamp(df.timestamp.min())
filteredDataSource[i] = false; } } source.change.emit(); sel.change.emit(); """) food_search = TextInput(value="", name='foodSearchTxtInput', title="Food Search:", callback=callback, width=200) custom_filter = CustomJSFilter(args=dict(source=unfilt_source, sel=filtered_source), code=''' return sel.data['x']; ''') view = CDSView(source=unfilt_source, filters=[custom_filter]) # Colorblind toggle clr_callback = CustomJS(args=dict(source=unfilt_source, color_source=legend_c, leg_source=legend_source), code=""" var state = cb_obj.active var data = source.data var leg = leg_source.data if (state){ data['color'] = data['cb_colors']; leg['colors'] = color_source['cb'];
def make_cbd_plot(session, current_user, flight_id, width, height, return_plot=False, pageref=0, dataset='antarctica', flight_date=None): if flight_date is None: df = pd.read_sql(FilmSegment.query_visible_to_user(current_user, session=session).filter(FilmSegment.dataset == dataset) \ .filter(FilmSegment.flight == flight_id).statement, session.bind) else: df = pd.read_sql(FilmSegment.query_visible_to_user(current_user, session=session).filter(FilmSegment.dataset == dataset) \ .filter(and_(FilmSegment.flight == flight_id, FilmSegment.raw_date == flight_date)).statement, session.bind) # Add colormaps to plot unique_reels = df['reel'].unique() reel_map = {r: idx for idx, r in enumerate(unique_reels)} reel_cm = plt.cm.get_cmap('viridis', len(unique_reels)) df['Color by Reel'] = df['reel'].apply( lambda x: mcolors.to_hex(reel_cm.colors[reel_map[x]])) df['Color by Verified'] = df['is_verified'].apply(lambda x: app.config[ 'COLOR_ACCENT'] if x else app.config['COLOR_GRAY']) df['Color by Review'] = df['needs_review'].apply(lambda x: app.config[ 'COLOR_ACCENT'] if x else app.config['COLOR_GRAY']) df['Color by Frequency'] = df['instrument_type'].apply( lambda x: app.config['COLOR_REDWOOD'] if x == FilmSegment.RADAR_60MHZ else (app.config['COLOR_PALO_ALOT'] if x == FilmSegment.RADAR_300MHZ else app.config['COLOR_GRAY'])) # source = ColumnDataSource(df) toggle_verified = Toggle(label="Show only verified") toggle_junk = Toggle(label="Hide junk", active=True) toggle_z = Toggle(label="Show Z Scopes", active=True) toggle_a = Toggle(label="Show A Scopes", active=True) toggle_verified.js_on_change( 'active', CustomJS(args=dict(source=source), code="source.change.emit()")) toggle_junk.js_on_change( 'active', CustomJS(args=dict(source=source), code="source.change.emit()")) toggle_z.js_on_change( 'active', CustomJS(args=dict(source=source), code="source.change.emit()")) toggle_a.js_on_change( 'active', CustomJS(args=dict(source=source), code="source.change.emit()")) filter_verified = CustomJSFilter(args=dict(tog=toggle_verified), code=''' var indices = []; for (var i = 0; i < source.get_length(); i++){ if ((!tog.active) || source.data['is_verified'][i]){ indices.push(true); } else { indices.push(false); } } return indices; ''') filter_junk = CustomJSFilter(args=dict(tog=toggle_junk), code=''' var indices = []; for (var i = 0; i < source.get_length(); i++){ if (tog.active && source.data['is_junk'][i]){ indices.push(false); } else { indices.push(true); } } console.log(indices); return indices; ''') filter_scope = CustomJSFilter(args=dict(tog_a=toggle_a, tog_z=toggle_z), code=''' console.log('filter_scope'); var indices = []; for (var i = 0; i < source.get_length(); i++){ if (tog_a.active && (source.data['scope_type'][i] == 'a')){ indices.push(true); } else if (tog_z.active && (source.data['scope_type'][i] == 'z')) { indices.push(true); } else { indices.push(false); } } console.log(indices); return indices; ''') view = CDSView(source=source, filters=[filter_verified, filter_junk, filter_scope]) p = figure( tools=['pan,box_zoom,wheel_zoom,box_select,lasso_select,reset,tap'], active_scroll='wheel_zoom') segs = p.segment(y0='first_frame', y1='last_frame', x0='first_cbd', x1='last_cbd', color=app.config["COLOR_GRAY"], source=source, view=view) scat_first = p.scatter('first_cbd', 'first_frame', color='Color by Verified', source=source, view=view, nonselection_fill_color=app.config["COLOR_GRAY"]) scat_last = p.scatter('last_cbd', 'last_frame', color='Color by Verified', source=source, view=view, nonselection_fill_color=app.config["COLOR_GRAY"]) p.add_tools( HoverTool(renderers=[segs], tooltips=[("Reel", "@reel"), ("Scope", "@scope_type"), ("Verified", "@is_verified")])) p.xaxis.axis_label = "CBD" p.yaxis.axis_label = "Frame" p.sizing_mode = "stretch_both" if (width is not None) and (height is not None): p.width = width p.height = height p.title.text = "Film Segments" # Select matching code from https://stackoverflow.com/questions/54768576/python-bokeh-customjs-debugging-a-javascript-callback-for-the-taping-tool cb_cselect = CustomJS(args=dict(s1=scat_first, s2=scat_last, csource=source), code=""" var selected_color = cb_obj.value; s1.glyph.line_color.field = selected_color; s1.glyph.fill_color.field = selected_color; s2.glyph.line_color.field = selected_color; s2.glyph.fill_color.field = selected_color; csource.change.emit(); """) color_select = Select(value="Color by Verified", options=[ "Color by Verified", "Color by Reel", "Color by Review", "Color by Frequency" ]) color_select.js_on_change('value', cb_cselect) p.toolbar.active_scroll = p.select_one(WheelZoomTool) if return_plot: return p, column(toggle_verified, toggle_junk, toggle_z, toggle_a, color_select), source else: layout = row( p, column(toggle_verified, toggle_junk, toggle_z, toggle_a, color_select)) script, div = components(layout) return f'\n{script}\n\n{div}\n'
if (source.data['word_length'][i] == slider.value) { columns.push(source.data['y'][i]); } } var uniqueItems = Array.from(new Set(columns)); text.text = "<font size=40>" + uniqueItems.length+ "</font>"; source.change.emit(); """) slider.js_on_change('value', callback) # Define the custom filter to return the indices from 0 to the desired percentage of total data rows. You could also compare against values in source.data js_filter = CustomJSFilter(args=dict(slider=slider, text = text), code=''' var indices = []; for (var i = 0; i <= source.data['word_length'].length; i++){ if (source.data['word_length'][i] == slider.value) { indices.push(i) } } return indices ''') # Use the filter in a view long_filter = Filter([item == 'long' for item in data['type']]) long_view = CDSView(source=source, filters=[long_filter, js_filter]) short_filter = Filter([item == 'short' for item in data['type']]) short_view = CDSView(source=source, filters=[short_filter, js_filter]) fig = figure(toolbar_location=None) fig.axis.visible = False fig.xgrid.visible = False fig.ygrid.visible = False fig.outline_line_color = None
def bokeh_xy_sliders(outputMatrix): # outputArray is a 2d array composed of # a transposed array of unique group names, competitiveness scores, # comp p-values, lottery scores, and lottery p-values. # Scatterplot with sliders to filter significance output_file("scatterplot.html") TOOLS = ("hover,pan,wheel_zoom,zoom_in,zoom_out,box_zoom,reset, save, tap") TOOLTIPS = [ # Displays on hover ("group", "@groups"), ("Comp P-value", "@compP{0.0000}"), ("Lottery P-value", "@lotP{0.0000}"), ("(x,y)", "(@x, @y)") ] # create a new plot with a title and axis labels p = figure(tools=TOOLS, title="Scatterplot", x_axis_label='Lottery Score', y_axis_label='Competitiveness', tooltips=TOOLTIPS, output_backend="webgl", toolbar_location="above") # Making sliders slider = Slider(start=0., end=1., value=1., step=.01, title="Comp P-value Filter") slider2 = Slider(start=0., end=1., value=1., step=.01, title="Lottery P-value Filter") try: colors = viridis(len(outputMatrix.uniqueGroups)) except ValueError: print("Error: Bokeh can only display 256 colors. You requested ", len(outputMatrix.uniqueGroups), " Please try chart style 2 instead.") for i in range(len(outputMatrix.uniqueGroups)): # Assigning data to each point dx = [outputMatrix.lotScores[i]] dy = [outputMatrix.compScores[i]] dcompP = [outputMatrix.compPValues[i]] dlotP = [outputMatrix.lotPValues[i]] dgroup = [outputMatrix.uniqueGroups[i]] dcolor = colors[i] source = ColumnDataSource(data=dict(x=dx, y=dy, groups=dgroup, compP=dcompP, lotP=dlotP, size=[15], color=[dcolor])) # Callback for when the slider is changed callback = CustomJS(args=dict(source=source), code=""" source.change.emit(); """) slider.js_on_change('value', callback) slider2.js_on_change('value', callback) # Custom Javascript boolean filters js_filter = CustomJSFilter(args=dict(slider=slider, source=source), code=""" bools = [] for (i = 0; i < source.data.x.length; i++) { if (source.data.compP[i] < slider.value) { bools.push(true); } else { bools.push(false); } } return bools; """) js_filter2 = CustomJSFilter(args=dict(slider=slider2, source=source), code=""" bools = [] for (i = 0; i < source.data.x.length; i++) { if (source.data.lotP[i] < slider.value) { bools.push(true); } else { bools.push(false); } } return bools; """) # Using those filters to change what data is displayed view = CDSView(source=source, filters=[js_filter, js_filter2]) p.circle(x="x", y="y", source=source, size="size", legend="groups", color="color", view=view) p.legend.click_policy = "hide" # Click legend entry to hide that point sliders = column(slider, slider2) layout = row(p, sliders) show(layout)
def make_plot(emperor, df, column=None, value=None): df = df[df['Emperor'] == emperor] source = ColumnDataSource(df) select_den = Select(title="Denomination", value="All", options=["All", "Aureus", "Denarius"]) select_grd = Select(title="Grade", value="All", options=[ 'All', 'Fine', 'Good Fine', 'Near VF', 'VF', 'Good VF', 'Near EF', 'EF', 'Superb EF', 'Choice EF', 'FDC' ]) check_attractive = CheckboxGroup(labels=["Attractively Toned"], active=[]) check_cabinet = CheckboxGroup(labels=["Cabinet Toning"], active=[]) check_lusterous = CheckboxGroup(labels=["Lusterous"], active=[]) check_centered = CheckboxGroup(labels=["Well Centered"], active=[]) check_portrait = CheckboxGroup(labels=["Artistic Portrait"], active=[]) # This callback is crucial, otherwise the filter will # not be triggered when the select changes callback = CustomJS(args=dict(source=source), code=""" source.change.emit(); """) select_den.js_on_change('value', callback) select_grd.js_on_change('value', callback) check_attractive.js_on_change('active', callback) check_cabinet.js_on_change('active', callback) check_lusterous.js_on_change('active', callback) check_centered.js_on_change('active', callback) check_portrait.js_on_change('active', callback) custom_filter_grd = CustomJSFilter(args=dict(select=select_grd, source=source), code=''' var indices = []; console.log(select.value); // no select cuts applied if (select.value == 'All') { for (var i = 0; i < source.get_length(); i++){ indices.push(true); } return indices; } // iterate through rows of data source and see if each satisfies some constraint for (var i = 0; i < source.get_length(); i++){ if (source.data['Grade'][i] == select.value){ indices.push(true); } else { indices.push(false) } } return indices; ''') custom_filter_den = CustomJSFilter(args=dict(select=select_den, source=source), code=''' var indices = []; console.log(select.value); // no select cuts applied if (select.value == 'All') { for (var i = 0; i < source.get_length(); i++){ indices.push(true); } return indices; } // iterate through rows of data source and see if each satisfies some constraint for (var i = 0; i < source.get_length(); i++){ if (source.data['Denomination'][i] == select.value){ indices.push(true); } else { indices.push(false) } } //console.log(indices) return indices; ''') custom_filter_attractive = CustomJSFilter(args=dict( checkbox=check_attractive, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Attractively Toned'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') custom_filter_cabinet = CustomJSFilter(args=dict(checkbox=check_cabinet, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Cabinet Toning'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') custom_filter_lusterous = CustomJSFilter(args=dict( checkbox=check_lusterous, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Lusterous'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') custom_filter_centered = CustomJSFilter(args=dict(checkbox=check_centered, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Cabinet Toning'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') custom_filter_portrait = CustomJSFilter(args=dict(checkbox=check_portrait, source=source), code=''' var indices = []; //console.log(checkbox.active); if (checkbox.active.includes(0)) { //console.log('0 on') //console.log(checkbox.active.includes(0)); for (var i = 0; i < source.get_length(); i++) { if (source.data['Quality Portrait'][i] == 1) { indices.push(true); } else { indices.push(false) } } } else { //console.log('0 off') for (var i = 0; i < source.get_length(); i++) { indices.push(true); } } return indices; ''') view = CDSView(source=source, filters=[ custom_filter_grd, custom_filter_den, custom_filter_attractive, custom_filter_cabinet, custom_filter_lusterous, custom_filter_centered, custom_filter_portrait ]) TOOLS = ["pan, wheel_zoom, box_zoom, reset, save"] TOOLTIPS = [("Auction", "@AuctionID"), ("Lot", "@LotNumber"), ("Emperor", "@Emperor"), ("RIC Number", "@RIC"), ("Estimate [USD]", "@Estimate"), ("Sale [USD]", "@Sale")] plot = figure( title='CNG Auctions through 2019 for Coins of Emperor ' + emperor, plot_width=500, plot_height=300, tools=TOOLS, tooltips=TOOLTIPS, x_range=Range1d(start=20, end=80000, bounds=(None, None)), y_range=[ 'Fine', 'Good Fine', 'Near VF', 'VF', 'Good VF', 'Near EF', 'EF', 'Superb EF', 'Choice EF', 'FDC' ], x_axis_type='log') color_mapper = CategoricalColorMapper(factors=['Aureus', 'Denarius'], palette=['#FFD700', '#C0C0C0']) plot.circle(x='Sale', y=jitter('Grade', 0.4, range=plot.y_range), source=source, view=view, fill_alpha=0.8, size=5, legend='data', line_color=None, color={ 'field': 'Denomination', 'transform': color_mapper }, hover_color='red') plot.xaxis.axis_label = "Sale Price (USD)" plot.yaxis.axis_label = "Grade" plot.xaxis.formatter = BasicTickFormatter(use_scientific=False) plot.xaxis.formatter = NumeralTickFormatter(format='$0,0') plot.legend.visible = False return row( plot, widgetbox([ select_den, select_grd, check_attractive, check_cabinet, check_lusterous, check_centered, check_portrait ]))
def add_widget(self, source_label, widget_type, reference, widget_name=None, custom_js=None, **kwargs): """ Add widgets to subset the data displayed in the plot. Parameters: source_label (str): the label for the data source to be used for the widget widget_type (str): a widget that is a valid key from `bokeh_utils.WIDGETS`. widget_name (str): an arbitrary name that can be used to identify the widget (necessary if `custom_js` is not None). reference (str): a column name from `self.sources[source_label]` that the widget should look at to filter the data source custom_js (str): custom javascript code for defining the filtering fuunction kwargs: all keyword arguments will be fed the instantiation of the widget to define the look and content of the interaction (ranges, initial values, etc.) """ self._validate_workflow('add_widget') if widget_type == 'Animation': widget_type = 'Slider' animate = True else: animate = False if widget_name is None: widget_name = widget_type if reference not in self.sources[source_label].columns: raise ValueError("Reference '{}' not in data source '{}'.".format( reference, source_label)) source = self.sources[source_label] ref_array = source[reference].tolist() animation_kwargs = { 'button_type': 'primary', 'label': 'Start', 'ms_delay': 500 } remove_kw = list() for k, v in kwargs.items(): if k.startswith('animation'): remove_kw.append(k) k = k.replace('animation_', '') animation_kwargs[k] = v for k in remove_kw: _ = kwargs.pop(k) for k, v in bokeh_utils.DEFAULT_KWARGS[widget_type].items(): if k not in kwargs: kwargs[k] = v widget = bokeh_utils.WIDGETS[widget_type]( name=widget_name, **{ k: v if v != 'auto' else bokeh_utils.auto_widget_kwarg( widget_type, k, ref_array) for k, v in kwargs.items() }) # This callback is crucial to trigger changes when the widget changes callback = CustomJS(args=dict(source=None), code=""" source.change.emit(); console.log() """) use_active = widget_type in ('CheckboxButtonGroup', 'CheckboxGroup', 'RadioButtonGroup') widget.js_on_change('active' if use_active else 'value', callback) if custom_js is None: if self.custom_js is not None: raise ValueError( 'Either all widgets or no widgets must use custom_js.') if source_label in self.views: raise ValueError( 'Multiple widgets can only be used with custom_js.') js_filter = CustomJSFilter(args=dict(widget=widget, reference=reference), code=bokeh_utils.FILTERS[widget_type]) else: if self.custom_js is None: self.custom_js = CustomJSFilter(args={}, code=custom_js) js_filter = self.custom_js js_filter.args.update({ widget_name: widget, widget_name + '_ref': reference }) self.widgets[widget_name] = { 'widget': widget, 'filter': js_filter, 'source': source_label } if animate: ms_delay = animation_kwargs.pop('ms_delay') button = bokeh_utils.Button(**animation_kwargs) button.js_on_event(bokeh_utils.ButtonClick, bokeh_utils.auto_advance(widget, ms_delay)) self.widgets['animation'] = { 'widget': button, 'filter': None, 'source': None } if source_label not in self.views: self.views[source_label] = CDSView(filters=[js_filter]) self.validation['add_widget'] = True return self
# Make a slider object to toggle the month shown slider = Slider(title = 'Month',start = 1, end = 12, step = 1, value = 1) # This callback triggers the filter when the slider changes callback = CustomJS(args=dict(source=sitesource), code=""" source.change.emit(); """) slider.js_on_change('value', callback) # Creates custom filter that selects the rows of the month based on the value in the slider custom_filter = CustomJSFilter(args=dict(slider=slider, source=sitesource), code=''' var indices = []; // iterate through rows of data source and see if each satisfies some constraint for (var i = 0; i < source.get_length(); i++){ if (source.data['Month'][i] == slider.value){ indices.push(true); } else { indices.push(false); } } return indices; ''') view = CDSView(source=sitesource, filters=[custom_filter]) # Plots the water sampling sites based on month in slider sites = p.circle('x', 'y', source = sitesource, color = 'red', size = 5, alpha = 0.3, view = view) # Create hover tool p.add_tools(HoverTool(renderers = [states], tooltips = [('State','@NAME'),('Population', '@POPESTIMATE2018')]))
def show_projection(alg, selected_ids, dim_red, directionality): filename = "static/data/anchs_" title = "2D Projection - Key Features" samples = 7468 if (not alg): samples = 3114 filename = "static/data/changes_" title = "2D Projection - Changes" filename += dim_red if (not directionality): filename += "_dir_False" filename += ".csv" fp = open(filename, 'r', encoding='utf-8') X = np.zeros((samples, 2)) ids = [] category = [] ft_selected_ids = [] for i in range(samples): roww = fp.readline().split(',') # print(roww) ids.append(int(roww[0])) X[i][0] = float(roww[3]) X[i][1] = float(roww[4]) if int(roww[0]) in selected_ids: ft_selected_ids.append(1) else: ft_selected_ids.append(0) if roww[2] == "TP": category.append(0) elif roww[2] == "TN": category.append(1) elif roww[2] == "FP": category.append(2) elif roww[2] == "FN": category.append(3) # percentage.append(float(roww[4])) fp.close() for p in range(1, 2): x = [] y = [] for i in range(samples): x.append(X[i][0]) y.append(X[i][1]) ################# ################# ##### bokeh ##### ################# ################# color_opt = [ "rgb(27, 158, 119)", "rgb(217, 95, 2)", "rgb(27, 158, 119)", "rgb(217, 95, 2)", "gray" ] alpha_opt = [0.6, 0.05] line_opt = [ "rgb(27, 158, 119)", "rgb(217, 95, 2)", "black", "black", "gray" ] if (len(ft_selected_ids) > 0): alpha_opt = [0.7, 0.02] colors = [] line_color = [] fill_alpha = [] line_alpha = [] for k in range(samples): if ft_selected_ids[k]: colors.append(color_opt[category[k]]) line_color.append(line_opt[category[k]]) fill_alpha.append(alpha_opt[0]) line_alpha.append(alpha_opt[0]) else: colors.append(color_opt[-1]) line_color.append(line_opt[-1]) fill_alpha.append(alpha_opt[-1]) line_alpha.append(alpha_opt[-1]) output_file('2d_changes_map.html') s1 = ColumnDataSource(data=dict(x=x, y=y, ids=ids, category=category, colors=colors, fill_alpha=fill_alpha, line_alpha=line_alpha, line_color=line_color, ft_selected_ids=ft_selected_ids)) hover = HoverTool(tooltips=""" """) # help_b = HelpTool(help_tooltip = """ """) wheel_zoom = WheelZoomTool() lasso_select = LassoSelectTool() p1 = figure( tools=[hover, lasso_select, "reset", "tap", wheel_zoom, "pan"], toolbar_location="right", toolbar_sticky=False, title=title, width=390, height=390) # p1.circle('x', 'y', source=s1, size=7.3, fill_alpha = 'fill_alpha', line_alpha = 'line_alpha', fill_color = 'colors', line_color = 'line_color', # nonselection_fill_alpha=alpha_opt[-1], # nonselection_fill_color=color_opt[-1], # nonselection_line_color=color_opt[-1], # nonselection_line_alpha=alpha_opt[-1] # ) p1.title.text_font_size = '10pt' p1.title.align = 'center' p1.toolbar.active_scroll = wheel_zoom p1.toolbar.active_drag = lasso_select p1.axis.visible = False lasso_select.select_every_mousemove = False # CheckboxGroup to select categories category_selection = CheckboxGroup(labels=["TP", "TN", "FP", "FN"], active=[0, 1, 2, 3]) selection_callback = CustomJS(args=dict(source=s1), code=""" source.change.emit(); """) category_selection.js_on_change('active', selection_callback) # Define the custom filter to return the indices, compare against values in source.data js_filter = CustomJSFilter(args=dict( category_selection=category_selection, source=s1), code=""" var indices = []; for (var i = 0; i <= source.data['category'].length; i++){ if (category_selection.active.includes(source.data['category'][i])) { indices.push(i) } } return indices; """) s1.callback = CustomJS(code=""" var lasso_ids = cb_obj.selected['1d'].indices; //console.log(lasso_ids); var ft_selected_ids = cb_obj.data['ft_selected_ids']; var ids = cb_obj.data['ids']; //console.log(ft_selected_ids); var aggregation_ids = []; for (i=0; i<ft_selected_ids.length; i++){ if (ft_selected_ids[i] == 1 && lasso_ids.includes(i)){ //console.log(ids[i]); aggregation_ids.push(ids[i]); } } if (!(aggregation_ids && aggregation_ids.length)) { aggregation_ids = [-1]; } console.log(aggregation_ids); //parent.makeBokehRequest(aggregation_ids); parent.makeBokehRequest2(aggregation_ids); """) # Use the filter in a view view = CDSView(source=s1, filters=[js_filter]) p1.circle('x', 'y', source=s1, view=view, size=7.3, fill_alpha='fill_alpha', line_alpha='line_alpha', fill_color='colors', line_color='line_color', nonselection_fill_alpha=alpha_opt[-1], nonselection_fill_color=color_opt[-1], nonselection_line_color=color_opt[-1], nonselection_line_alpha=alpha_opt[-1]) layout = column(p1, category_selection) # show(layout) # grid = gridplot([[p1, None]], merge_tools=False) # # show(grid) html = file_html(layout, CDN, "my_plot") html = html.replace("auto;", "0px;") fp = open("static/html/projection_file_raw.html", 'w') fp.write(html) fp.close() # show_projection(False, list(range(7468)), "pca", True )
def bokeh_plot(node, link, name='NetworkMap'): from bokeh.plotting import figure, from_networkx, save from bokeh.models import ColumnDataSource, HoverTool from bokeh.io import export_png from bokeh.models import CustomJS, TextInput, CustomJSFilter, CDSView, TapTool from bokeh.layouts import column from bokeh.plotting import output_file, show from bokeh.tile_providers import get_provider, Vendors from bokeh.models import Circle, MultiLine, LabelSet, Toggle, CheckboxGroup from bokeh.models.graphs import NodesAndLinkedEdges text_input = TextInput(value="", title="Filter Nodes:") wgs84_to_web_mercator(node) node_source_data = ColumnDataSource( data=dict(x=node['MX'], y=node['MY'], desc=node['id'])) # link G = nx.from_pandas_edgelist(link, source='id', target='anode') nx.set_node_attributes(G, dict(zip(link.id, link.id)), 'desc') n_loc = {k: (x, y) for k, x, y in zip(node['id'], node['MX'], node['MY'])} nx.set_node_attributes(G, n_loc, 'pos') n_color = {k: 'orange' if 'C' in k else 'green' for k in node['id']} nx.set_node_attributes(G, n_color, 'color') n_alpha = {k: 1 if 'C' in k else 0 for k in node['id']} nx.set_node_attributes(G, n_alpha, 'alpha') e_color = {(s, t): 'red' if 'C' in s else 'black' for s, t in zip(link['id'], link['anode'])} nx.set_edge_attributes(G, e_color, 'color') e_line_type = {(s, t): 'dashed' if 'C' in s else 'solid' for s, t in zip(link['id'], link['anode'])} nx.set_edge_attributes(G, e_line_type, 'line_type') tile_provider = get_provider(Vendors.CARTODBPOSITRON) bokeh_plot = figure(title="%s network map" % name.split('/')[-1].split('.')[0], sizing_mode="scale_height", plot_width=1300, x_range=(min(node['MX']), max(node['MX'])), tools='pan,wheel_zoom', active_drag="pan", active_scroll="wheel_zoom") bokeh_plot.add_tile(tile_provider) # This callback is crucial, otherwise the filter will not be triggered when the slider changes callback = CustomJS(args=dict(source=node_source_data), code=""" source.change.emit(); """) text_input.js_on_change('value', callback) # Define the custom filter to return the indices from 0 to the desired percentage of total data rows. You could # also compare against values in source.data js_filter = CustomJSFilter(args=dict(text_input=text_input), code=f""" const z = source.data['desc']; var indices = ((() => {{ var result = []; for (let i = 0, end = source.get_length(), asc = 0 <= end; asc ? i < end : i > end; asc ? i++ : i--) {{ if (z[i].includes(text_input.value.toString(10))) {{ result.push(i); }} }} return result; }})()); return indices;""") # Use the filter in a view view = CDSView(source=node_source_data, filters=[js_filter]) callback2 = CustomJS(args=dict(x_range=bokeh_plot.x_range, y_range=bokeh_plot.y_range, text_input=text_input, source=node_source_data), code=f""" const z = source.data['desc']; const x = source.data['x']; const y = source.data['y']; var result = []; for (let i = 0, end = source.get_length(), asc = 0 <= end; asc ? i < end : i > end; asc ? i++ : i--) {{ if (z[i].includes(text_input.value.toString(10))) {{ result.push(i); }} }} var indices = result[0]; var Xstart = x[indices]; var Ystart = y[indices]; y_range.setv({{"start": Ystart-280, "end": Ystart+280}}); x_range.setv({{"start": Xstart-500, "end": Xstart+500}}); x_range.change.emit(); y_range.change.emit(); """) text_input.js_on_change('value', callback2) graph = from_networkx(G, nx.get_node_attributes(G, 'pos'), scale=2, center=(0, 0)) graph.node_renderer.glyph = Circle(radius=15, fill_color='color', fill_alpha='alpha') graph.node_renderer.hover_glyph = Circle(radius=15, fill_color='red') graph.edge_renderer.glyph = MultiLine( line_alpha=1, line_color='color', line_width=1, line_dash='line_type') # zero line alpha graph.edge_renderer.hover_glyph = MultiLine(line_color='#abdda4', line_width=5) graph.inspection_policy = NodesAndLinkedEdges() bokeh_plot.circle('x', 'y', source=node_source_data, radius=10, color='green', alpha=0.7, view=view) labels = LabelSet(x='x', y='y', text='desc', text_font_size="8pt", text_color='black', x_offset=5, y_offset=5, source=node_source_data, render_mode='canvas') code = '''\ if (toggle.active) { box.text_alpha = 0.0; console.log('enabling box'); } else { box.text_alpha = 1.0; console.log('disabling box'); } ''' callback3 = CustomJS(code=code, args={}) toggle = Toggle(label="Annotation", button_type="success") toggle.js_on_click(callback3) callback3.args = {'toggle': toggle, 'box': labels} bokeh_plot.add_tools(HoverTool(tooltips=[("id", "@desc")]), TapTool()) # Output filepath bokeh_plot.renderers.append(graph) bokeh_plot.add_layout(labels) layout = column(toggle, text_input, bokeh_plot) # export_png(p, filename="plot.png") output_file(name) show(layout)