def to_html(self, dir_plot_destination): from .p3b_chisquared_detailed import figures_chisq_detailed init_group = '- World' # 'Lebanon' source_chisq, c_a1a, grid_chisq = figures_chisq_detailed( init_group, self.df_chisq) fn_dest = join(dir_plot_destination, "t11d-chisquared_dashboard-detailed.html") output_file(fn_dest) # link dropdown to filter data # from https://docs.bokeh.org/en/latest/docs/user_guide/interaction/widgets.html#select callback = CustomJS(args=dict(vf=c_a1a.view.filters[0], source_chisq=source_chisq), code=""" console.log(vf.group); console.log(cb_obj.value); vf.group = cb_obj.value; source_chisq.change.emit(); """) from bokeh.models import Select select = Select(title="Country/State:", value=init_group, options=sorted(list( self.df_chisq.CountryProv.unique()))) select.js_on_change('value', callback) # create layout of everything layout = column(select, grid_chisq) save(layout) print(f"Saved to {fn_dest}")
def build_choropleth_doc(cpleth_df_instances: List[pd.DataFrame], county_date_instances: List, debug_mode: bool = False) -> None: df_instances, states = build_cpleth_df(cpleth_df_instances) curdoc().clear() national_cpleth_sources, cpleth_sources, stateplot, nationalplots = build_cpleth_plot_df(states, df_instances) ttldiv = Div(text="""Effective Reproduction Number ( R<sub>t</sub> )""", orientation='vertical', height_policy='min', width_policy='min', css_classes=['cbar_title'], align='center') ttldiv.visible = True menu = [] for full_name, state in zip(constants.full_names, states): menu.append((state, full_name)) select = Select(title="", value="Choose", options=menu, name='state_select', css_classes=['bk_select'], width_policy='min', background=None) someargs = dict(plot=stateplot, select=select, ttldiv=ttldiv, cpleth_sources=cpleth_sources) select_callback = CustomJS(args=someargs, code=constants.select_callback_code) select.js_on_change('value', select_callback) row_layout = row(stateplot, ttldiv) gridlayout = grid([ [select], [row_layout] ]) if not debug_mode: for i, natp in enumerate(nationalplots): gen_national_imgs(i, natp, county_date_instances) script, div = components([gridlayout]) covid_utils.save_bokeh_tags([div[0], script], config.choro_covid_explorer_tags) else: show(gridlayout)
def ajax(): x = [1, 2, 3] source = ColumnDataSource(data=dict(x=x, y=my_data['one'])) plot = figure(height=250, width=300) plot.line('x', 'y', source=source, line_width=3, line_alpha=0.8) callback = CustomJS(args=dict(source=source), code=""" var selected_value = cb_obj.value; var plot_data = source.data; jQuery.ajax({ type: 'POST', url: '/new_option', data: {"value": selected_value}, dataType: 'json', success: function (response) { plot_data['y'] = response["option"]; source.change.emit(); }, error: function() { alert("An error occured!"); } }); """) select = Select(value='one', options=['one', 'two', 'three']) select.js_on_change('value', callback) layout = column(widgetbox(select, width=100), plot) script, div = components(layout, INLINE) return jsonify(script=script, div=div, js_resources=INLINE.render_js(), css_resources=INLINE.render_css())
def make_comparison_controls(source, track_sources, p1, p2, pars_dict, select_options): calbackcode = """ var data = source.data; var parname = cb_obj.value; data[axisname+'1'] = data[parname+'_1']; data[axisname+'2'] = data[parname+'_2']; axis1.axis_label = parname; axis2.axis_label = parname; source.change.emit(); """ x1 = Select(title='X-Axis', value=pars_dict['x1'], options=select_options) x1.js_on_change( 'value', CustomJS(args=dict(source=source, axisname='x', axis1=p1.xaxis[0], axis2=p2.xaxis[0], suffix='_1'), code=calbackcode)) y1 = Select(title='Y-Axis', value=pars_dict['y1'], options=select_options) y1.js_on_change( 'value', CustomJS(args=dict(source=source, axisname='y', axis1=p1.yaxis[0], axis2=p2.yaxis[0], suffix='_1'), code=calbackcode)) update_source = CustomJS(args=dict( summary_source=source, track_sources=track_sources, ), code=""" update_source(summary_source, track_sources[0], grid1, '_1') update_source(summary_source, track_sources[1], grid2, '_2') """) button = Button(label="Plot selected tracks", button_type="success", sizing_mode="stretch_width") button.js_on_click(update_source) controls = row([x1, y1, button]) control_dict = { "x1": x1, "y1": y1, } return controls, control_dict
def create_dropdown(self, name, source_daily, source_total): # get options for dropdown # dates can't be sorted like this, so it has to be removed self.df_dict_total.pop("dates") self.df_dict_total.pop("dates_str") key = lambda x: x[1][-1] sort_options = sorted(self.df_dict_total.items(), key=key, reverse=True) options = [] for tpl in sort_options: total_cases_list = list(str(tpl[1][-1])) total_cases_str_sep = "" for i, num in enumerate(total_cases_list): total_cases_str_sep += num if i == len(total_cases_list) - 1: continue elif len(total_cases_list) % 3 == 0: if i % 3 == 2: total_cases_str_sep += "," elif len(total_cases_list) % 3 == 1: if i % 3 == 0: total_cases_str_sep += "," elif len(total_cases_list) % 3 == 2: if i % 3 == 1: total_cases_str_sep += "," if tpl[0] == name: selected_total_cases_sep = total_cases_str_sep options.append(f"{tpl[0]}: {total_cases_str_sep} total cases") options.remove(f"selected: {selected_total_cases_sep} total cases") # add dates again since they were removed for sorting the options self.df_dict_total["dates"] = self.dates self.df_dict_total["dates_str"] = self.dates_str # create dropdown select = Select( title="Select a country", value=f"{name}: {selected_total_cases_sep} total cases", options=options, sizing_mode="scale_width") with open("main.js", "r") as f: JS_function = CustomJS(args=dict(source_d=source_daily, source_t=source_total, df_dict_t=self.df_dict_total, df_dict_d=self.df_dict_daily), code=f.read()) select.js_on_change("value", JS_function) return select
def doBokehViz(self): try: dic=self.data menus=[k for k in dic] colors=[] for c in self.categ: if c==1: colors.append('black') elif c==-1: colors.append('red') dic['categ']=colors dic['bokeh_plt_x']=dic[menus[0]] if len(menus)==1: dic['bokeh_plt_y']=dic[menus[0]] else: dic['bokeh_plt_y']=dic[menus[1]] data=ColumnDataSource(dic) self.bokeh_fig.xaxis.axis_label=menus[0] if len(menus)==1: self.bokeh_fig.yaxis.axis_label=menus[0] else: self.bokeh_fig.yaxis.axis_label=menus[1] self.bokeh_fig.circle('bokeh_plt_x','bokeh_plt_y',source=data,color='categ',fill_alpha=0.2,size=10) self.bokeh_fig.add_tools( HoverTool(tooltips = [('X,Y', '@bokeh_plt_x,@bokeh_plt_y')]) ) callbackX = CustomJS(args=dict(source=data,axis=self.bokeh_fig.xaxis[0]), code=""" var data=source.data var f = cb_obj.value data['bokeh_plt_x']=data[f] axis.axis_label=f source.change.emit(); """) callbackY = CustomJS(args=dict(source=data,axis=self.bokeh_fig.yaxis[0]), code=""" var data=source.data var f = cb_obj.value data['bokeh_plt_y']=data[f] axis.axis_label=f source.change.emit(); """) #dp1 = Dropdown(label="X value",menu=x_menu,default_value=x_menu[0]) dp1=Select(title="X-coordinate:",value=menus[0],options=menus) dp1.js_on_change('value', callbackX) #dp2 = Dropdown(label="Y value",menu=y_menu,default_value=y_menu[0]) if len(menus)==1: dp2=Select(title="Y-coordinate:",value=menus[0],options=menus) else: dp2=Select(title="Y-coordinate:",value=menus[1],options=menus) dp2.js_on_change('value', callbackY) self.bokeh_fig = column(row(dp1,dp2), self.bokeh_fig) except Exception as e: raise Exception(f'[{self.algoInfo["algoname"]}][do_bokeh_viz]{e}')
def depth_graph(self, references, depth_file): """Create depth vs position graph.""" # create list of graphs graphs = [] # create dictionary of {ref: depths} if str(depth_file) == 'None': return None depth_file.columns = ['ref', 'start', 'end', 'depth'] all_ref = dict(tuple(depth_file.groupby(['ref']))) ref_keys = list(all_ref.keys()) for name, isoforms in references.items(): refs_present = list(set(isoforms).intersection(ref_keys)) graph_dic = {} for entry in refs_present: v = all_ref[entry] graph_dic[entry] = {'x': v['start'], 'y': v['depth']} if len(graph_dic) > 0: drop_down = list(graph_dic.keys()) first_plot = graph_dic[drop_down[0]] plot = figure() source = ColumnDataSource(data=first_plot) select = Select(title="Select reference for " + name + ':', value=drop_down[0], options=drop_down) plot = figure(plot_height=350, y_range=None, x_range=None, x_axis_label='Position along reference', y_axis_label='Sequencing depth / Bases', title=str(name)) plot.step(x='x', y='y', source=source) plot.xaxis.formatter.use_scientific = False select.js_on_change( 'value', CustomJS(args=dict(source=source, source_graph=graph_dic, select=select), code=""" const new_data = Object.assign({}, source.data) source.data = source_graph[select.value] """)) drop_down_plot = layout([select, plot]) graphs.append(drop_down_plot) alignment_grid = gridplot(graphs, ncols=2, sizing_mode="stretch_width") text = ("This tab contains visualisations of " "the depth of coverage of alignments across the reference." " If there are no Depth graphs for" " a particular reference" " it is likely to mean no alignments were found.") plots = [[self.get_description(text)], [alignment_grid]] main = layout(plots, sizing_mode="scale_width") return Panel(child=main, title="Depth")
def test_js_on_change_executes(self, bokeh_model_page): select = Select(options=["Option 1", "Option 2", "Option 3"], css_classes=["foo"]) select.js_on_change('value', CustomJS(code=RECORD("value", "cb_obj.value"))) page = bokeh_model_page(select) el = page.driver.find_element_by_css_selector('.foo select') el.click() el = page.driver.find_element_by_css_selector('.foo select option[value="Option 3"]') el.click() results = page.results assert results['value'] == 'Option 3' assert page.has_no_console_errors()
def test_js_on_change_executes(self, bokeh_model_page: BokehModelPage) -> None: select = Select(options=["Option 1", "Option 2", "Option 3"]) select.js_on_change('value', CustomJS(code=RECORD("value", "cb_obj.value"))) page = bokeh_model_page(select) el = find_element_for(page.driver, select, "select") el.click() el = find_element_for(page.driver, select, 'select option[value="Option 3"]') el.click() results = page.results assert results['value'] == 'Option 3' assert page.has_no_console_errors()
def view_database_file(_id, file_type): ds = load_file(_id, file_type) d = {} for data_var in ds.data_vars: d[data_var] = [ds[data_var].values] d["to_plot"] = [ds[list(ds.data_vars)[0]].values] source = ColumnDataSource(d) callback = CustomJS( args=dict(source=source), code=""" var data = source.data; data['to_plot'] = data[cb_obj.value]; source.change.emit(); """, ) select = Select(title="Variable:", options=list(ds.data_vars)) select.js_on_change("value", callback) p = Figure( x_range=(-180, 180), y_range=(-90, 90), aspect_ratio=2.5, tools="pan,wheel_zoom,box_zoom,reset, hover", ) p.sizing_mode = "scale_width" p.image( image="to_plot", x=-180, y=-90, dw=360, dh=180, source=source, palette="Viridis11", ) script, div = components( column(column(select), p, sizing_mode="stretch_width")) return render_template( "app/bokeh_plot.html", script=script, div=div, data_file_id=_id, title=file_type.capitalize(), )
def plot(input_data): df = pandas.DataFrame(input_data) df['one-rep-max'] = df.apply(calculate_one_rep_max, axis=1) df = df.drop(['avg_reps', 'avg_weight'], axis=1) df['workout__date'] = pandas.to_datetime(df.workout__date) df = df.set_index(keys='workout__date') data = ColumnDataSource(data=df) menu = list(df.exercise__name.unique()) cur_data = ColumnDataSource(data=dict(x=[], y=[], z=[])) callback = CustomJS(args=dict(source=data, ss=cur_data), code=""" var f = cb_obj.value var d2 = ss.data d2['x'] = [] d2['y'] = [] d2['z'] = [] for(var i = 0; i <= source.get_length(); i++){ if (source.data['exercise__name'][i] == f){ d2['x'].push(source.data['workout__date'][i]) d2['y'].push(source.data['one-rep-max'][i]) d2['z'].push(source.data['exercise__name'][i]) } } ss.change.emit(); """) exercise_chooser = Select(title="Exercise", options=menu) exercise_chooser.sizing_mode = 'scale_width' exercise = '' if cur_data.data['z'] == [] else cur_data.data['z'][0] fig = figure(title=f"Estimated One Rep Max - {exercise}", x_axis_label="Date", x_axis_type='datetime', y_axis_label="Estimated One Rep Max") fig.sizing_mode = "scale_both" fig.line(x='x', y='y', source=cur_data) exercise_chooser.js_on_change("value", callback) layout = column(exercise_chooser, fig) layout.sizing_mode = "scale_width" script, div = components(layout) return script, div
def plot_selected_country(self, name, output, module="bokeh"): if self.selected is None: raise ValueError("no country selected") # create dictionary out of df that can be put into JS function grouped_df_d = self.df_daily.groupby("Country/Region", sort=False) grouped_df_t = self.df_total.groupby("Country/Region", sort=False) grouped_list_d = grouped_df_d.apply(lambda x: x.to_dict(orient="list")) grouped_list_t = grouped_df_t.apply(lambda x: x.to_dict(orient="list")) df_dict_nested_d = grouped_list_d.to_dict() df_dict_nested_t = grouped_list_t.to_dict() df_dict_daily = {} df_dict_total = {} keys_to_ignore = ["Province/State", "Country/Region", "Lat", "Long"] for key, value in df_dict_nested_d.items(): helper_list = [] for key_two, value_two in value.items(): if key_two in keys_to_ignore: continue else: # sums up countries that occur multiple times helper_list.append(sum(value_two)) df_dict_daily[key] = helper_list for key, value in df_dict_nested_t.items(): helper_list = [] for key_two, value_two in value.items(): if key_two in keys_to_ignore: continue else: # sums up countries that occur multiple times helper_list.append(sum(value_two)) df_dict_total[key] = helper_list dates = [] dates_str = [] for date_str in self.selected.index: date_obj = datetime.strptime(date_str, '%m/%d/%y') dates.append(date_obj) date_str_new = datetime.strptime(date_str, '%m/%d/%y').strftime('%d %b %Y') dates_str.append(date_str_new) df_dict_daily["dates"] = dates df_dict_total["dates"] = dates df_dict_daily["dates_str"] = dates_str df_dict_total["dates_str"] = dates_str if module == "bokeh": # also necessary to make it compatible with JS function df_dict_daily["selected"] = df_dict_daily[name] df_dict_total["selected"] = df_dict_total[name] source_daily = ColumnDataSource(data=df_dict_daily) source_total = ColumnDataSource(data=df_dict_total) # create two plots XAXIS_LABEL = "Date" YAXIS_LABEL = "Death Cases" LEGEND_LOC = "top_left" TOOLTIPS = [("Date", "@dates_str"), ("Cases of selected country", "@selected"), ("Cases worldwide", "@World")] TOOLS = [ HoverTool(tooltips=TOOLTIPS), "pan", "wheel_zoom", "box_zoom", "reset" ] HEIGHT = 600 WIDTH = 760 SIZE = 1 CIRCLE_SIZE = 12 colors = ["lightgray", "red"] pd = figure(x_axis_type="datetime", title="Daily Infections", plot_height=HEIGHT, tools=TOOLS, width=WIDTH, css_classes=["we-need-this-for-manip"], name="d_infections") pt = figure(x_axis_type="datetime", title="Total Infections", plot_height=HEIGHT, tools=TOOLS, width=WIDTH, css_classes=["we-need-this-for-manip-total"], name="t_infections") # pd.vbar(x='dates', top="World", color=colors[0], line_width=SIZE, # source=source_daily, legend_label="Worldwide") pd.vbar(x='dates', top="selected", color=colors[1], line_width=SIZE, source=source_daily, legend_label="Selected Country") # HoverTool does not work for vbar so invisible circles are necessary # pd.circle(x='dates', y="World", color=colors[0], size=CIRCLE_SIZE, # source=source_daily, legend_label="Worldwide", fill_alpha=0, # line_alpha=0) pd.circle(x='dates', y="selected", color=colors[1], size=CIRCLE_SIZE, source=source_daily, legend_label="Selected Country", fill_alpha=0, line_alpha=0) pd.legend.location = LEGEND_LOC pd.yaxis.axis_label = YAXIS_LABEL pd.xaxis.axis_label = XAXIS_LABEL # pt.vbar(x='dates', top="World", color=colors[0], line_width=SIZE, # source=source_total, legend_label="Worldwide") pt.vbar(x='dates', top="selected", color=colors[1], line_width=SIZE, source=source_total, legend_label="Selected Country") # pt.circle(x='dates', y="World", color=colors[0], size=CIRCLE_SIZE, # source=source_total, legend_label="Worldwide", fill_alpha=0, # line_alpha=0) pt.circle(x='dates', y="selected", color=colors[1], size=CIRCLE_SIZE, source=source_total, legend_label="Selected Country", fill_alpha=0, line_alpha=0) pt.legend.location = LEGEND_LOC pt.yaxis.axis_label = YAXIS_LABEL pt.xaxis.axis_label = XAXIS_LABEL output_file(output) # dropdown menu # dates can't be sorted like this, so it has to be removed for this step df_dict_total.pop("dates") df_dict_total.pop("dates_str") sort_options = sorted(df_dict_total.items(), key=lambda x: x[1][-1], reverse=True) options = [] for tpl in sort_options: total_cases_list = list(str(tpl[1][-1])) total_cases_str_sep = "" for i, num in enumerate(total_cases_list): total_cases_str_sep += num if i == len(total_cases_list) - 1: continue elif len(total_cases_list) % 3 == 0: if i % 3 == 2: total_cases_str_sep += "," elif len(total_cases_list) % 3 == 1: if i % 3 == 0: total_cases_str_sep += "," elif len(total_cases_list) % 3 == 2: if i % 3 == 1: total_cases_str_sep += "," if tpl[0] == name: selected_total_cases_sep = total_cases_str_sep options.append(f"{tpl[0]}: {total_cases_str_sep} total cases") options.remove(f"selected: {selected_total_cases_sep} total cases") df_dict_total["dates"] = dates df_dict_total["dates_str"] = dates_str select = Select( title="Select a country", value=f"{name}: {selected_total_cases_sep} total cases", options=options, sizing_mode="scale_width") with open("main.js", "r") as f: select.js_on_change( "value", CustomJS(args=dict( source_d=source_daily, source_t=source_total, df_dict_t=df_dict_total, df_dict_d=df_dict_daily, ), code=f.read())) plots = column(pd, pt) # show(column(select, plots)) with open("template.html", "r") as f: template = f.read() save(column(select, plots), template=template) view(output) if module == "mpl": confirmed_cases = [] confirmed_cases_world = [] # cave: only for daily for sub_arr in self.selected.values: confirmed_cases.append(sub_arr[0]) for sub_arr in self.world_data_daily.values: confirmed_cases_world.append(sub_arr[0]) fig, ax = plt.subplots() date_format = DateFormatter("%d %b %Y") world_plot = ax.bar(dates, confirmed_cases_world, bottom=0, color="lightgray") country_plot = ax.bar(dates, confirmed_cases, bottom=0) ax.set(xlabel="Date", ylabel="Death Cases") ax.xaxis.set_major_formatter(date_format) fig.subplots_adjust(bottom=0.175) plt.xticks(rotation=35, fontsize=7) plt.legend((world_plot[0], country_plot[0]), ("Worldwide", "{}".format(name))) plt.show()
0].axis_label = 'Total number of edits on the Wikipedia article of the namesake of the spacerock' p.yaxis[0].axis_label = 'Absolute magnitude of the piece of spacerock' opts = list(set(ds.data['namesakeLabel'])) callback_select = CustomJS(args=dict(ds=ds), code=""" var namesakes = ds.data['namesakeLabel']; var ind = namesakes .map((n, i) => n === cb_obj.value ? i : -1) .filter(index => index !== -1);; ds.selected.indices = ind; """) s = Select(options=['Select person...'] + opts) s.js_on_change('value', callback_select) callback_ti = CustomJS(args=dict(ds=ds, s=s, opts=opts), code=f""" s.options = opts .filter(i => i.toLowerCase().includes(cb_obj.value.toLowerCase())); s.value = s.options[0] var namesakes = ds.data['namesakeLabel']; var ind = namesakes .map((n, i) => n === s.value ? i : -1) .filter(index => index !== -1);; ds.selected.indices = ind; """) ti = TextInput(title="Select to view a specific person", placeholder='Enter filter',
plot = figure(sizing_mode="stretch_both") plot.xaxis.axis_label = "total_cases" plot.yaxis.axis_label = "total_deaths" scatter = plot.circle(x="total_cases", y="total_deaths", source=source,) xfeature = Select(title="Select X axis Feature", options=options, value="total_cases") yfeature = Select(title="Select Y axis Feature", options=options, value="total_deaths") xfeature.js_on_change( "value", CustomJS( args=dict(xaxis=plot.xaxis[0], scatter=scatter, source=source), code=""" scatter.glyph.x.field = cb_obj.value xaxis.axis_label = cb_obj.value source.change.emit() """, ), ) yfeature.js_on_change( "value", CustomJS( args=dict(yaxis=plot.yaxis[0], scatter=scatter, source=source), code=""" scatter.glyph.y.field = cb_obj.value yaxis.axis_label = cb_obj.value source.change.emit() """,
options=hOptions, #list of options value="KO Counts per Player" #default value ) vSelect = Select( title="Vertical Data", options=vOptions, #list of options value="Win Counts per Player" #default value ) #layout widgets = row(hSelect, vSelect) layout = column(widgets, p) curdoc().add_root(layout) curdoc().title = "Player Plot" #interactivity p.js_on_event(MouseEnter, callbackPlot) #plot whichever axes are currently selected hSelect.js_on_change('value', callbackUpdateHAxis) vSelect.js_on_change('value', callbackUpdateVAxis) hSelect.js_on_change('value', callbackPlot) vSelect.js_on_change('value', callbackPlot) #show(layout) save(layout)
def to_html(self, dir_plot_destination): from .p3a_chisquared_simple import figures_chisq_simple init_group = '- World' # 'Lebanon' source_chisq, c_b1b, fig_chisq1, fig_chisq2 = figures_chisq_simple( init_group, self.df_chisq) from .p4_slopes import figures_slopes source_slopes, fig_slopes = figures_slopes(self.df_slopes, self.df_pop) fn_dest = join(dir_plot_destination, "t11d-chisquared_dashboard-simple.html") output_file(fn_dest) # link dropdown to filter data # from https://docs.bokeh.org/en/latest/docs/user_guide/interaction/widgets.html#select callback = CustomJS(args=dict(vf=c_b1b.view.filters[0], source_chisq=source_chisq, source_slopes=source_slopes), code=""" console.log(vf.group); console.log(cb_obj.value); console.log(source_slopes.data['CountryProv'].indexOf(cb_obj.value)) if(source_slopes.data['CountryProv'].indexOf(cb_obj.value)!=-1) source_slopes.selected.indices[0]=source_slopes.data['CountryProv'].indexOf(cb_obj.value) else source_slopes.selected.indices=[]; source_slopes.change.emit(); vf.group = cb_obj.value; source_chisq.change.emit(); """) from bokeh.models import Select, Div, Paragraph select = Select(title="Country/State:", value=init_group, options=sorted(list( self.df_chisq.CountryProv.unique())), width=200) select.js_on_change('value', callback) callback2 = CustomJS(args=dict(source_slopes=source_slopes, select=select), code=""" console.log(source_slopes.selected) var selectedIndex = source_slopes.selected.indices; console.log("x:", source_slopes.data['CountryProv'][selectedIndex[0]]); if(selectedIndex[0]>=0) select.value=source_slopes.data['CountryProv'][selectedIndex[0]]; """) taptool = fig_slopes.select(type=TapTool) source_slopes.selected.js_on_change('indices', callback2) fn_css = ("t11d-layout.css") header = Div(text="<link rel='stylesheet' type='text/css' href='" + fn_css + "'>") desc = Div( height_policy="min", sizing_mode="stretch_width", style={'color': 'whitesmoke'}, text= "<p><b>Plots Descrition </b><br/> The scatterplot shows the rate of change in daily number of tests and daily positive cases in the last week. <br/>The excess cases are calculated from the 7-day average of actual cases minus expected values based on previous 14 days. Negative values indicate that actual cases are lower than expected, while positive values indicate that actual cases are more than expected.</p>" ) # create layout of everything column1 = column( [row(select), row([fig_slopes], sizing_mode="stretch_both")], sizing_mode="stretch_width") column2 = column([fig_chisq1, fig_chisq2], sizing_mode='stretch_both') rowMain = row([header, column1, column2], sizing_mode='stretch_height') layout = column([ rowMain, Div(style={'color': 'whitesmoke'}, text="Last Updated on " + str(pd.to_datetime( source_chisq.data['Date']).max()).split(" ")[0]) ], sizing_mode='stretch_width') #layout = row(header,select,fig_slopes,column( fig_chisq1,fig_chisq2)) save(layout) print(f"Saved to {fn_dest}")
def plot(df, plot_file="plot.html", ais="Carter", bis="Kyle"): """ takes in a df that includes scores, cart's guess, and Kyle's guess for away and home teams plots (x - away, y - home) and draws a line for the final score must handle having or not having results score :param df: :return: """ # TODO: # show who won # say what dot is who # plot line # scale bounds to match score? # display score # plot game win line # add title # make better hover ''' def x_point(x1, x2): return (x2 - x1) / 2 + x1 def y_point(y1, y2): return (y2 - y1) / 2 + y1 def div_slope(x1, y1, x2, y2): # m return -1 * (x2 - x1) / (y2 - y1) def mid_point(x1, y1, x2, y2): # mx - y return div_slope(x1, y1, x2, y2) * x_point(x1, x2) - y_point(y1, y2) div_lines = pd.DataFrame() div_lines['Game'] = df['Game'] div_lines['m'] = div_slope(df['AAwayGuess'].values, df['AHomeGuess'].values, df['BAwayGuess'].values, df['BHomeGuess'].values) ''' output_file(plot_file) plot_tools = "hover,pan,wheel_zoom,zoom_in,zoom_out,undo,redo,reset,tap,save,box_select,poly_select,lasso_select," p = figure( tools=plot_tools, plot_width=7, plot_height=3, match_aspect=True, x_axis_label="Away", y_axis_label="Home", ) p.add_tools(BoxZoomTool(match_aspect=True)) p.sizing_mode = "scale_width" max_away = max([ df['AwayResult'].max(), df['AAwayGuess'].max(), df['BAwayGuess'].max() ]) max_home = max([ df['HomeResult'].max(), df['AHomeGuess'].max(), df['BHomeGuess'].max() ]) p.x_range = Range1d(0, max_away + 5) p.y_range = Range1d(0, max_home + 5) dareas = dict() curr_dareas = dict() target_game = df['Game'].iloc[0] for aag, ahg, bag, bhg, game in zip(df['AAwayGuess'], df['AHomeGuess'], df['BAwayGuess'], df['BHomeGuess'], df['Game']): for x in range(max_away): for y in range(max_home): if abs(x - aag) + abs(y - ahg) < abs(x - bag) + abs(y - bhg): w = 'A' elif abs(x - aag) + abs(y - ahg) > abs(x - bag) + abs(y - bhg): w = 'B' else: w = 'Tie' dareas['xs'] = dareas.get( 'xs', []) + [[x - 0.5, x - 0.5, x + 0.5, x + 0.5]] dareas['ys'] = dareas.get( 'ys', []) + [[y - 0.5, y + 0.5, y + 0.5, y - 0.5]] dareas['game'] = dareas.get('game', []) + [game] dareas['winner'] = dareas.get('winner', []) + [w] if game == target_game: curr_dareas['xs'] = curr_dareas.get( 'xs', []) + [[x - 0.5, x - 0.5, x + 0.5, x + 0.5]] curr_dareas['ys'] = curr_dareas.get( 'ys', []) + [[y - 0.5, y + 0.5, y + 0.5, y - 0.5]] curr_dareas['game'] = curr_dareas.get('game', []) + [game] curr_dareas['winner'] = curr_dareas.get('winner', []) + [w] patch_color_map = factor_cmap('winner', palette=Spectral3, factors=['A', 'B', 'Tie']) p_areas = ColumnDataSource(dareas) curr_areas = ColumnDataSource(curr_dareas) p.patches('xs', 'ys', source=curr_areas, color=patch_color_map) # ColumnDataSource(df) data = ColumnDataSource(df) curr = ColumnDataSource( df[df['Game'] == df['Game'].iloc[0]]) # select to game # gonna go simple first p.scatter("AwayResult", "HomeResult", source=curr, color="Black", radius=0.5) p.scatter("AAwayGuess", "AHomeGuess", source=curr, color="Orange", radius=0.5) p.scatter("BAwayGuess", "BHomeGuess", source=curr, color="Teal", radius=0.5) p_callback = CustomJS(args=dict( source=data, sc=curr, p_sc=p_areas, p_curr=curr_areas, ), code=""" var f = cb_obj.value; // this should be the column selection sc.data['AwayResult']=[] sc.data['HomeResult']=[] sc.data['AAwayGuess']=[] sc.data['AHomeGuess']=[] sc.data['BAwayGuess']=[] sc.data['BHomeGuess']=[] p_curr.data['xs'] = [] p_curr.data['ys'] = [] p_curr.data['winner'] = [] for(var i = 0; i <= source.get_length(); i++){ if (source.data['Game'][i] == f){ sc.data['AwayResult'].push(source.data['AwayResult'][i]) sc.data['HomeResult'].push(source.data['HomeResult'][i]) sc.data['AAwayGuess'].push(source.data['AAwayGuess'][i]) sc.data['AHomeGuess'].push(source.data['AHomeGuess'][i]) sc.data['BAwayGuess'].push(source.data['BAwayGuess'][i]) sc.data['BHomeGuess'].push(source.data['BHomeGuess'][i]) } } for( var i = 0; i <= p_sc.get_length(); i++){ if(p_sc.data['game'][i] == f) { p_curr.data['xs'] = p_sc.data['xs'] p_curr.data['ys'] = p_sc.data['ys'] p_curr.data['winner'] = p_sc.data['winner'] } } sc.change.emit(); p_curr.change.emit(); """) # drop down menu menu = Select(options=list(df['Game']), value=list(df['Game'])[0], title='Game') menu.js_on_change('value', p_callback) # show(p) show(layout(column(p, menu), sizing_mode='scale_width'))
def make_bokeh_map(width, height, flight_id=None, dataset='antarctica', title="", flight_lines=None, flight_date=None, return_plot=False, return_components=False): if flight_lines is None: raise (Exception("Providing flight lines is now required.")) # print("Warning: Recommend pre-loading positioning files to speedup page load.") # flight_lines = load_flight_lines('../original_positioning/') if not flight_id: flight_lines = list(flight_lines.values()) else: if flight_date is None: flight_identifier = (flight_id, None) else: flight_identifier = (flight_id, flight_date % 100 ) # only year part if flight_identifier in flight_lines: flight_lines = [flight_lines[flight_identifier]] else: not_found_html = "<div class='plot_error'>Couldn't find the requested flight ID.</div>" if return_components: return None elif return_plot: return not_found_html, None else: return not_found_html p = figure(match_aspect=True, tools=['pan,wheel_zoom,box_zoom,reset,tap']) data_sources = [] flight_glyphs = [] for df in flight_lines: data_source = ColumnDataSource(data=df) l_b = p.line(x='X', y='Y', source=data_source, color='white', line_width=2) for df in flight_lines: data_source = ColumnDataSource(data=df) data_sources.append(data_source) l = p.line(x='X', y='Y', source=data_source, color=app.config["COLOR_PRIMARY"], line_width=1) flight_glyphs.append(l) highlight_source = ColumnDataSource(data={'X': [], 'Y': []}) p.scatter(x='X', y='Y', source=highlight_source, line_width=3, color=app.config["COLOR_ACCENT"]) if dataset == 'antarctica': p.xaxis.axis_label = "ESPG:3031 X" p.yaxis.axis_label = "ESPG:3031 Y" elif dataset == 'greenland': p.xaxis.axis_label = "ESPG:3413 X" p.yaxis.axis_label = "ESPG:3413 Y" else: raise (Exception( f"Unexpected dataset {dataset} - should be antarctica or greenland" )) p.add_tools( HoverTool(renderers=flight_glyphs, tooltips=[('Track', '@{Track}'), ('CBD', '@CBD')])) map_tile_sources = map_tile_sources_all[ dataset] # select greenland or antarctica data tiles tile_options = {} tile_options['url'] = map_tile_sources[0]['url'] tile_options['attribution'] = map_tile_sources[0]['attribution'] tile_source = BBoxTileSource(**tile_options) ts_glyph = p.add_tile(tile_source) ts_glyph.level = 'underlay' # Create tile change code tile_select_code = "" first = True for ts in map_tile_sources: if not first: tile_select_code += " else " else: first = False tile_select_code += f"""if (cb_obj.value == "{ts["name"]}") {{ tile_source.url = "{ts["url"]}"; tile_source.attribution = "{ts["attribution"]}"; $(".bk-tile-attribution").html("{ts["attribution"]}"); }}""" # Manually setting the tile attribution div is a bit of a hack. Updating the attribution in the tile source does not # cause a change in what is displayed, so this is a workaround for now. cb_tile_select = CustomJS(args=dict(tile_source=tile_source), code=tile_select_code) tile_select = Select(value=map_tile_sources[0]['name'], options=[ts['name'] for ts in map_tile_sources]) tile_select.js_on_change('value', cb_tile_select) if len(flight_lines) > 1: url = f"@url" taptool = p.select(type=TapTool) taptool.callback = OpenURL(url=url, same_tab=True) p.sizing_mode = 'stretch_both' if (width is not None) and (height is not None): p.width = width p.height = height p.title.text = title if return_components: return { 'map': p, 'tile_select': tile_select, 'flight_lines': flight_lines, 'data_sources': data_sources, 'highlight_source': highlight_source } elif return_plot: return p, flight_lines else: script, div = components(p) return f'\n{script}\n\n{div}\n'
def make_urg_performance_plot(urg_data): source = ColumnDataSource(data=urg_data) mapper = LinearColorMapper(palette=Viridis256, low=0, high=urg_data['true'].max()) color_bar = ColorBar(color_mapper=mapper, location=(0, 0)) TOOLTIPS = [("(Pred., True)", "(@x, @y)"), ("Raw Count", "@raw"), ("Norm. by True", "@true{1.111}"), ("Norm. by Pred.", "@pred{1.111}"), ("Norm. by Total", "@all{1.111}")] labels = ['stable', 'questionable', 'urgent', 'immediate'] fig = figure(title="Confusion Matrix", tooltips=TOOLTIPS, toolbar_location=None, x_range=labels, y_range=labels[-1::-1], plot_height=500, plot_width=600) rect = fig.rect('y', 'x', source=source, fill_color={ 'field': 'color', 'transform': mapper }, line_color='black', width=1, height=1) fig.add_layout(color_bar, 'right') fig.xaxis.axis_label = 'Predicted' fig.yaxis.axis_label = 'True' fig.title.text_font_size = '16pt' fig.yaxis.axis_label_text_font_size = '14pt' fig.xaxis.axis_label_text_font_size = '14pt' fig.yaxis.major_label_text_font_size = '11pt' fig.xaxis.major_label_text_font_size = '11pt' opts = [ 'Raw Counts', 'Normalize by True Labels', 'Normalize by Predicted Labels', 'Normalize by Total' ] select = Select(title="Plot Options:", value=opts[1], options=opts) codec = """ var data = source.data; var f = select.value; const {transform} = rect.glyph.fill_color; switch(f) { case "Raw Counts": data['color'] = data['raw']; break; case "Normalize by True Labels": data['color'] = data['true']; break; case "Normalize by Predicted Labels": data['color'] = data['pred']; break; case "Normalize by Total": data['color'] = data['all']; break; default: data['color'] = data['true']; } transform.low = 0; transform.high = Math.max.apply(Math,data['color']); rect.glyph.fill_color = {field: 'color', transform: transform}; // necessary becasue we mutated source.data in-place source.change.emit(); p.reset.emit() """ update_cm = CustomJS(args=dict(source=source, select=select, rect=rect, fig=fig), code=codec) select.js_on_change('value', update_cm) return fig, select
code = """ var death = document.getElementById("total-Region-Death"); var recovered = document.getElementById("total-Region-Recovered"); var confirmed = document.getElementById("total-Region-Confirmed"); var region = cb_obj.value death.innerHTML = death_case[region].toLocaleString('id') recovered.innerHTML = recovered_case[region].toLocaleString('id') confirmed.innerHTML = confirmed_case[region].toLocaleString('id') """ js_on_change_region = CustomJS(args=dict(source=source, death_case=total_death_case, confirmed_case=total_confirmed_case, recovered_case=total_recovered_case), code=code) region_select.js_on_change('value', js_on_change_region) case_select.on_change('active', handle_case_change) range_slider.on_change('value', handle_range_change) button.on_click(change_theme) plt = make_plot(source, case.capitalize() + " case in " + region, case, sizing_mode="stretch_both") # Layouting about_text = """ <div style="width:300px;"> <ul class="list-group"> <li class="list-group-item">Anvaqta Tangguh Wisesa</li> <li class="list-group-item">Rachma Indira</li>
def geoplot( # noqa C901 gdf_in, geometry_column="geometry", figure=None, figsize=None, title="", xlabel="Longitude", ylabel="Latitude", xlim=None, ylim=None, color="blue", colormap=None, colormap_uselog=False, colormap_range=None, category=None, dropdown=None, slider=None, slider_range=None, slider_name="", show_colorbar=True, colorbar_tick_format=None, xrange=None, yrange=None, hovertool=True, hovertool_columns=[], hovertool_string=None, simplify_shapes=None, tile_provider="CARTODBPOSITRON_RETINA", tile_provider_url=None, tile_attribution="", tile_alpha=1, panning=True, zooming=True, toolbar_location="right", show_figure=True, return_figure=True, return_html=False, legend=True, webgl=True, **kwargs, ): """Doc-String: TODO""" # Imports: import bokeh.plotting from bokeh.layouts import column, row from bokeh.models import ( BasicTicker, BoxZoomTool, ColorBar, ColumnDataSource, GeoJSONDataSource, HoverTool, LinearColorMapper, LogColorMapper, LogTicker, Select, Slider, WheelZoomTool, ) from bokeh.models.callbacks import CustomJS from bokeh.models.widgets import Dropdown from bokeh.palettes import all_palettes from bokeh.plotting import show # Make a copy of the input geodataframe: gdf = gdf_in.copy() # Check layertypes: if type(gdf) != pd.DataFrame: layertypes = [] if "Point" in str(gdf.geom_type.unique()): layertypes.append("Point") if "Line" in str(gdf.geom_type.unique()): layertypes.append("Line") if "Polygon" in str(gdf.geom_type.unique()): layertypes.append("Polygon") if len(layertypes) > 1: raise Exception( f"Can only plot GeoDataFrames/Series with single type of geometry (either Point, Line or Polygon). Provided is a GeoDataFrame/Series with types: {layertypes}" ) else: layertypes = ["Point"] # Get and check provided parameters for geoplot: figure_options = { "title": title, "x_axis_label": xlabel, "y_axis_label": ylabel, "plot_width": 600, "plot_height": 400, "toolbar_location": toolbar_location, "active_scroll": "wheel_zoom", "x_axis_type": "mercator", "y_axis_type": "mercator", "match_aspect": True, } if figsize is not None: width, height = figsize figure_options["plot_width"] = width figure_options["plot_height"] = height if webgl: figure_options["output_backend"] = "webgl" if type(gdf) != pd.DataFrame: # Convert GeoDataFrame to Web Mercator Projection: gdf.to_crs(epsg=3857, inplace=True) # Simplify shapes if wanted: if isinstance(simplify_shapes, numbers.Number): if layertypes[0] in ["Line", "Polygon"]: gdf[geometry_column] = gdf[geometry_column].simplify( simplify_shapes) elif simplify_shapes is not None: raise ValueError( "<simplify_shapes> parameter only accepts numbers or None.") # Check for category, dropdown or slider (choropleth map column): category_options = 0 if category is not None: category_options += 1 category_columns = [category] if dropdown is not None: category_options += 1 category_columns = dropdown if slider is not None: category_options += 1 category_columns = slider if category_options > 1: raise ValueError( "Only one of <category>, <dropdown> or <slider> parameters is allowed to be used at once." ) # Check for category (single choropleth plot): if category is None: pass elif isinstance(category, (list, tuple)): raise ValueError( "For <category>, please provide an existing single column of the GeoDataFrame." ) elif category in gdf.columns: pass else: raise ValueError( f"Could not find column '{category}' in GeoDataFrame. For <category>, please provide an existing single column of the GeoDataFrame." ) # Check for dropdown (multiple choropleth plots via dropdown selection): if dropdown is None: pass elif not isinstance(dropdown, (list, tuple)): raise ValueError( "For <dropdown>, please provide a list/tuple of existing columns of the GeoDataFrame." ) else: for col in dropdown: if col not in gdf.columns: raise ValueError( f"Could not find column '{col}' for <dropdown> in GeoDataFrame. " ) # Check for slider (multiple choropleth plots via slider selection): if slider is None: pass elif not isinstance(slider, (list, tuple)): raise ValueError( "For <slider>, please provide a list/tuple of existing columns of the GeoDataFrame." ) else: for col in slider: if col not in gdf.columns: raise ValueError( f"Could not find column '{col}' for <slider> in GeoDataFrame. " ) if slider_range is not None: if not isinstance(slider_range, Iterable): raise ValueError( "<slider_range> has to be a type that is iterable like list, tuple, range, ..." ) else: slider_range = list(slider_range) if len(slider_range) != len(slider): raise ValueError( "The number of elements in <slider_range> has to be the same as in <slider>." ) steps = [] for i in range(len(slider_range) - 1): steps.append(slider_range[i + 1] - slider_range[i]) if len(set(steps)) > 1: raise ValueError( "<slider_range> has to have equal step size between each elements (like a range-object)." ) else: slider_step = steps[0] slider_start = slider_range[0] slider_end = slider_range[-1] # Check colormap if either <category>, <dropdown> or <slider> is choosen: if category_options == 1: if colormap is None: colormap = blue_colormap elif isinstance(colormap, (tuple, list)): if len(colormap) > 1: pass else: raise ValueError( f"<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}" ) elif isinstance(colormap, str): if colormap in all_palettes: colormap = all_palettes[colormap] colormap = colormap[max(colormap.keys())] else: raise ValueError( f"Could not find <colormap> with name {colormap}. The following predefined colormaps are supported (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}" ) else: raise ValueError( f"<colormap> only accepts a list/tuple of at least two colors or the name of one of the following predefined colormaps (see also https://bokeh.pydata.org/en/latest/docs/reference/palettes.html ): {list(all_palettes.keys())}" ) else: if isinstance(color, str): colormap = [color] elif color is None: colormap = ["blue"] else: raise ValueError( "<color> has to be a string specifying the fill_color of the map glyph." ) # Check xlim & ylim: if xlim is not None: if isinstance(xlim, (tuple, list)): if len(xlim) == 2: xmin, xmax = xlim for _ in [xmin, xmax]: if not -180 < _ <= 180: raise ValueError( "Limits for x-axis (=Longitude) have to be between -180 and 180." ) if not xmin < xmax: raise ValueError("xmin has to be smaller than xmax.") from pyproj import Transformer transformer = Transformer.from_crs("epsg:4326", "epsg:3857") xmin = transformer.transform(0, xmin)[0] xmax = transformer.transform(0, xmax)[0] figure_options["x_range"] = (xmin, xmax) else: raise ValueError( "Limits for x-axis (=Longitude) have to be of form [xmin, xmax] with values between -180 and 180." ) else: raise ValueError( "Limits for x-axis (=Longitude) have to be of form [xmin, xmax] with values between -180 and 180." ) if ylim is not None: if isinstance(ylim, (tuple, list)): if len(ylim) == 2: ymin, ymax = ylim for _ in [ymin, ymax]: if not -90 < _ <= 90: raise ValueError( "Limits for y-axis (=Latitude) have to be between -90 and 90." ) if not ymin < ymax: raise ValueError("ymin has to be smaller than ymax.") from pyproj import Transformer transformer = Transformer.from_crs("epsg:4326", "epsg:3857") ymin = transformer.transform(ymin, 0)[1] ymax = transformer.transform(ymax, 0)[1] figure_options["y_range"] = (ymin, ymax) else: raise ValueError( "Limits for y-axis (=Latitude) have to be of form [ymin, ymax] with values between -90 and 90." ) else: raise ValueError( "Limits for y-axis (=Latitude) have to be of form [ymin, ymax] with values between -90 and 90." ) # Create Figure to draw: old_layout = None if figure is None: figure_options["x_axis_label"] = (figure_options["x_axis_label"] if figure_options["x_axis_label"] is not None else "Longitute") figure_options["y_axis_label"] = (figure_options["y_axis_label"] if figure_options["y_axis_label"] is not None else "Latitude") p = bokeh.plotting.figure(**figure_options) # Add Tile Source as Background: p = _add_backgroundtile(p, tile_provider, tile_provider_url, tile_attribution, tile_alpha) elif isinstance(figure, type(bokeh.plotting.figure())): p = figure elif isinstance(figure, type(column())): old_layout = figure p = _get_figure(old_layout) else: raise ValueError( "Parameter <figure> has to be of type bokeh.plotting.figure or bokeh.layouts.column." ) for t in p.tools: # Get ridd of zoom on axes: if isinstance(t, WheelZoomTool): t.zoom_on_axis = False # Make sure that box zoom matches aspect: if isinstance(t, BoxZoomTool): t.match_aspect = True # Hide legend if wanted: legend_input = legend if isinstance(legend, str): pass else: legend = "GeoLayer" # Define colormapper: if len(colormap) == 1: kwargs["fill_color"] = colormap[0] elif category is not None: # Check if category column is numerical: if not issubclass(gdf[category].dtype.type, np.number): raise NotImplementedError( f"<category> plot only yet implemented for numerical columns. Column '{category}' is not numerical." ) field = category colormapper_options = {"palette": colormap} if colormap_range is not None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[field].min() colormapper_options["high"] = gdf[field].max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} if not isinstance(legend, str): legend = str(field) elif dropdown is not None: # Check if all columns in dropdown selection are numerical: for col in dropdown: if not issubclass(gdf[col].dtype.type, np.number): raise NotImplementedError( f"<dropdown> plot only yet implemented for numerical columns. Column '{col}' is not numerical." ) field = dropdown[0] colormapper_options = {"palette": colormap} if colormap_range is not None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[dropdown].min().min() colormapper_options["high"] = gdf[dropdown].max().max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} legend = " " + field elif slider is not None: # Check if all columns in dropdown selection are numerical: for col in slider: if not issubclass(gdf[col].dtype.type, np.number): raise NotImplementedError( f"<slider> plot only yet implemented for numerical columns. Column '{col}' is not numerical." ) field = slider[0] colormapper_options = {"palette": colormap} if colormap_range is not None: if not isinstance(colormap_range, (tuple, list)): raise ValueError( "<colormap_range> can only be 'None' or a tuple/list of form (min, max)." ) elif len(colormap_range) == 2: colormapper_options["low"] = colormap_range[0] colormapper_options["high"] = colormap_range[1] else: colormapper_options["low"] = gdf[slider].min().min() colormapper_options["high"] = gdf[slider].max().max() if colormap_uselog: colormapper = LogColorMapper(**colormapper_options) else: colormapper = LinearColorMapper(**colormapper_options) kwargs["fill_color"] = {"field": "Colormap", "transform": colormapper} if not isinstance(legend, str): legend = "Geolayer" # Check that only hovertool_columns or hovertool_string is used: if isinstance(hovertool_columns, (list, tuple, str)): if len(hovertool_columns) > 0 and hovertool_string is not None: raise ValueError( "Either <hovertool_columns> or <hovertool_string> can be used, but not both at the same time." ) else: raise ValueError( "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) if hovertool_string is not None: hovertool_columns = "all" # Check for Hovertool columns: if hovertool: if not isinstance(hovertool_columns, (list, tuple)): if hovertool_columns == "all": hovertool_columns = list( filter(lambda col: col != geometry_column, gdf.columns)) else: raise ValueError( "<hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) elif len(hovertool_columns) == 0: if category is not None: hovertool_columns = [category] elif dropdown is not None: hovertool_columns = dropdown elif slider is not None: hovertool_columns = slider else: hovertool_columns = [] else: for col in hovertool_columns: if col not in gdf.columns: raise ValueError( f"Could not find columns '{col}' in GeoDataFrame. <hovertool_columns> has to be a list of columns of the GeoDataFrame or the string 'all'." ) else: if category is None: hovertool_columns = [] else: hovertool_columns = [category] # Reduce DataFrame to needed columns: if type(gdf) == pd.DataFrame: gdf["Geometry"] = 0 additional_columns = ["x", "y"] else: additional_columns = [geometry_column] for kwarg, value in kwargs.items(): if isinstance(value, Hashable): if value in gdf.columns: additional_columns.append(value) if category_options == 0: gdf = gdf[list(set(hovertool_columns) | set(additional_columns))] else: gdf = gdf[list( set(hovertool_columns) | set(category_columns) | set(additional_columns))] gdf["Colormap"] = gdf[field] field = "Colormap" # Create GeoJSON DataSource for Plot: if type(gdf) != pd.DataFrame: geo_source = GeoJSONDataSource(geojson=gdf.to_json()) else: geo_source = gdf # Draw Glyph on Figure: layout = None if "Point" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = kwargs["fill_color"] glyph = p.scatter(x="x", y="y", source=geo_source, legend_label=legend, **kwargs) if "Line" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = kwargs["fill_color"] del kwargs["fill_color"] glyph = p.multi_line(xs="xs", ys="ys", source=geo_source, legend_label=legend, **kwargs) if "Polygon" in layertypes: if "line_color" not in kwargs: kwargs["line_color"] = "black" # Creates from a geoDataFrame with Polygons and Multipolygons a Pandas DataFrame # with x any y columns specifying the geometry of the Polygons: geo_source = ColumnDataSource( convert_geoDataFrame_to_patches(gdf, geometry_column)) # Plot polygons: glyph = p.multi_polygons(xs="__x__", ys="__y__", source=geo_source, legend_label=legend, **kwargs) # Add hovertool: if hovertool and (category_options == 1 or len(hovertool_columns) > 0): my_hover = HoverTool(renderers=[glyph]) if hovertool_string is None: my_hover.tooltips = [(str(col), "@{%s}" % col) for col in hovertool_columns] else: my_hover.tooltips = hovertool_string p.add_tools(my_hover) # Add colorbar: if show_colorbar and category_options == 1: colorbar_options = { "color_mapper": colormapper, "label_standoff": 12, "border_line_color": None, "location": (0, 0), } if colormap_uselog: colorbar_options["ticker"] = LogTicker() if colorbar_tick_format: colorbar_options["formatter"] = get_tick_formatter( colorbar_tick_format) colorbar = ColorBar(**colorbar_options) p.add_layout(colorbar, "right") # Add Dropdown Widget: if dropdown is not None: # Define Dropdown widget: dropdown_widget = Select(title="Select Choropleth Layer", options=list(zip(dropdown, dropdown))) # Define Callback for Dropdown widget: callback = CustomJS( args=dict( dropdown_widget=dropdown_widget, geo_source=geo_source, legend=p.legend[0].items[0], ), code=""" //Change selection of field for Colormapper for choropleth plot: geo_source.data["Colormap"] = geo_source.data[dropdown_widget.value]; geo_source.change.emit(); //Change label of Legend: legend.label["value"] = " " + dropdown_widget.value; """, ) dropdown_widget.js_on_change("value", callback) # Add Dropdown widget above the plot: if old_layout is None: layout = column(dropdown_widget, p) else: layout = column(dropdown_widget, old_layout) # Add Slider Widget: if slider is not None: if slider_range is None: slider_start = 0 slider_end = len(slider) - 1 slider_step = 1 value2name = ColumnDataSource({ "Values": np.arange(slider_start, slider_end + slider_step, slider_step), "Names": slider, }) # Define Slider widget: slider_widget = Slider( start=slider_start, end=slider_end, value=slider_start, step=slider_step, title=slider_name, ) # Define Callback for Slider widget: callback = CustomJS( args=dict( slider_widget=slider_widget, geo_source=geo_source, value2name=value2name, ), code=""" //Change selection of field for Colormapper for choropleth plot: var slider_value = slider_widget.value; var i; for(i=0; i<value2name.data["Names"].length; i++) { if (value2name.data["Values"][i] == slider_value) { var name = value2name.data["Names"][i]; } } geo_source.data["Colormap"] = geo_source.data[name]; geo_source.change.emit(); """, ) slider_widget.js_on_change("value", callback) # Add Slider widget above the plot: if old_layout is None: layout = column(slider_widget, p) else: layout = column(slider_widget, old_layout) # Hide legend if user wants: if legend_input is False: p.legend.visible = False # Set click policy for legend: p.legend.click_policy = "hide" # Set panning option: if panning is False: p.toolbar.active_drag = None # Set zooming option: if zooming is False: p.toolbar.active_scroll = None # Display plot and if wanted return plot: if layout is None: if old_layout is None: layout = p else: layout = old_layout # Display plot if wanted if show_figure: show(layout) # Return as (embeddable) HTML if wanted: if return_html: return embedded_html(layout) # Return plot: if return_figure: return layout
def modify_doc(cls): TOOLS = "pan,wheel_zoom,box_zoom,reset,save" season = Season() seasons_1990_on = season.seasons_1990_on data_dict = seasons_1990_on.to_dict('list') source = ColumnDataSource(data=data_dict) years = seasons_1990_on["Year"].unique().tolist() years = ["ALL"] + [str(int(year)) for year in years][::-1] slider = Slider(title="Year", start=1990, end=2017, step=1, value=2006) menu_options_list = ["ALL"] + seasons_1990_on["Tm"].unique().tolist() team_menu = Select(options=menu_options_list, value="ALL", title="Team") columns = list(seasons_1990_on.columns) x_axis_menu = Select(options=columns, value="3PA", title="X Axis") y_axis_menu = Select(options=columns, value="3P", title="Y Axis") y_axis_menu = Select(options=columns, value="3P", title="Y Axis") season_menu = Select(options=years, value="ALL", title="Season") TOOLS = "pan,wheel_zoom,box_zoom,reset,save" p1 = figure( tools=TOOLS ) p1.xaxis.visible = None p1.yaxis.visible = None ################### p1.circle( "X", "Y", source=source, alpha=0.8, nonselection_alpha=0.1, ) p1.legend.location = "bottom_right" #################### #################### ####################### cls.add_tooltips(p1, x_label='3PA', y_label='3P') widgetboxes = [ widgetbox(team_menu), widgetbox(season_menu), widgetbox(x_axis_menu), widgetbox(y_axis_menu) ] column1 = column(widgetboxes) layout = row(column1, p1) xaxis = LinearAxis(axis_label="3 Pointers Attempted") yaxis = LinearAxis(axis_label="3 Pointers Made") p1.add_layout(xaxis, 'below') p1.add_layout(yaxis, 'left') args = { 'source': source, 'data_dict': data_dict, 'team_menu': team_menu, 'slider': slider, 'x_axis_menu': x_axis_menu, 'y_axis_menu': y_axis_menu, 'season_menu': season_menu, 'p': p1, 'xaxis': xaxis, 'yaxis': yaxis, 'hover': p1.hover, } callback = CustomJS(args=args, code=""" data_copy = JSON.parse(JSON.stringify(data_dict)) console.log(data_copy, "<-- Here is data copy"); console.log(p, "<--- Here is the plot") console.log(hover, "<--- Here is the hover") keys = Object.keys(data_copy) selected_team = team_menu.value selected_season = season_menu.value all_seasons = data_copy['Year'] all_teams = data_copy['Tm'] x_axis_menu.value y_hover = '@' + y_axis_menu.value x_hover = '@' + x_axis_menu.value console.log(y_hover); console.log(x_hover); hover[0].tooltips = [ ['Player', '@Player'], ['Team', '@Tm'], ['Position', '@Pos'], ['Year', '@Year'], [x_axis_menu.value, x_hover], [y_axis_menu.value, y_hover], ] // remove_row removes a row of data // for all lists. function remove_row(index) { for (j = 0; j < keys.length; j++) { column = data_copy[keys[j]] value = column[index] data_copy[keys[j]].splice(index, 1) } } // Filter Year if (selected_season !== "ALL") { for (var i = all_seasons.length - 1; i >= 0; i--) { season = all_seasons[i]; if (season != selected_season) { remove_row(i) } } } // Filter Team if (selected_team !== "ALL") { for (var i = all_teams.length - 1; i >= 0; i--) { team_name = all_teams[i]; if (team_name !== selected_team) { remove_row(i) } } console.log(data_copy['Tm'].length, "<--- End Length") } console.log("Here are the keys -->", keys) console.log("Here are team menu -->", team_menu) console.log("Here are slider -->", slider) console.log("Here are x_axis_menu menu -->", x_axis_menu) console.log("Here are y_axis_menu menu -->", y_axis_menu) if (team_menu.value === "ALL") { console.log("What's up. I am ALL"); } // Add X & Y data_copy['X'] = data_copy[x_axis_menu.value] data_copy['Y'] = data_copy[y_axis_menu.value] source.data = data_copy xaxis.attributes.axis_label = x_axis_menu.value yaxis.attributes.axis_label = y_axis_menu.value xaxis.change.emit(); yaxis.change.emit(); source.change.emit(); """) x_axis_menu.js_on_change('value', callback) y_axis_menu.js_on_change('value', callback) slider.js_on_change('value', callback) team_menu.js_on_change('value', callback) season_menu.js_on_change('value', callback) resources = INLINE.render() script, div = components({'p': layout}) return {'script': script, 'div': div, 'resources': resources} def callback(attr, old, new): if menu.value == "ALL": new_df = seasons_1990_on[seasons_1990_on['Year'] == slider.value] new_x = new_df[x_axis_menu.value] new_y = new_df[y_axis_menu.value] else: new_df = seasons_1990_on[ (seasons_1990_on['Year'] == slider.value) & (seasons_1990_on['Tm'] == menu.value) ] new_x = new_df[x_axis_menu.value] new_y = new_df[y_axis_menu.value] source.data['X'] = new_x source.data['Y'] = new_y new_df['X'] = new_x new_df['Y'] = new_y tooltips = [ ("Players", "@Player"), (x_axis_menu.value, "@{}".format(x_axis_menu.value)) (y_axis_menu.value, "@{}".format(y_axis_menu.value)) ] source.data = new_df cls.add_tooltips(plot=p1, tooltips=tooltips) print("Here is x", new_x) print("Here is y", new_y) print("Here is y name", new_y.name) p1.xaxis.axis_label = new_x.name p1.yaxis.axis_label = new_y.name slider.on_change("value", callback) menu.on_change("value", callback) x_axis_menu.on_change("value", callback) y_axis_menu.on_change("value", callback)
code=""" const t = cb_obj.value; // make the selected item's marks blue and the rest gray for (let i in lines) { if (i == t) { lines[i].glyph.line_color = '""" + color_selected + """'; circles[i].glyph.fill_color = '""" + color_selected + """'; } else { lines[i].glyph.line_color = '""" + color_deselected + """'; circles[i].glyph.fill_color = '""" + color_deselected + """'; } } """) menu.js_on_change('value', callback) # display the layout chart_layout = row(p, menu) show(chart_layout) #--------------------------------------------------------------------------------------------------- # check results #--------------------------------------------------------------------------------------------------- solution_files = ['PD 2020 Wk 9 Output.csv'] my_files = ['output-2020-09.csv'] unique_cols = [['Candidate', 'Poll', 'End Date', 'Sample Type']] col_order_matters = True round_dec = 8
plot_height=600) # x轴是Categorical Data时需指明x_range=? p.vbar(x=name, top=attribute, width=0.5, bottom=0) p.xaxis.major_label_orientation = 1 # x轴label斜着显示 # source.stream(new_data) return p # 数据更新函数 def update(attr, old, new): layout.children[1] = get_figure(df) # 将第二子图更新 select_club = Select(title="Club:", value=list_club[0], options=list_club) select_club.js_on_change( "value", CustomJS( code="""console.log('select: value=' + this.value, this.toString())""") ) select_attribute = Select(title="Attribute:", value=list_attribute[0], options=list_attribute) select_attribute.js_on_change( "value", CustomJS( code="""console.log('select: value=' + this.value, this.toString())""") ) select_attribute.on_change("value", update) select = row(select_club, select_attribute) # 小部件和图横向排列 layout = Column(select, get_figure(df)) # 小部件和图横向排列
def render_crossfilter(itmdt: Intermediate, plot_width: int, plot_height: int) -> column: """ Render crossfilter scatter plot with a regression line. """ # pylint: disable=too-many-locals, too-many-function-args df = itmdt["data"] df["__x__"] = df[df.columns[0]] df["__y__"] = df[df.columns[0]] source_scatter = ColumnDataSource(df) source_xy_value = ColumnDataSource({ "x": [df.columns[0]], "y": [df.columns[0]] }) var_list = list(df.columns[:-2]) xcol = source_xy_value.data["x"][0] ycol = source_xy_value.data["y"][0] tooltips = [("X-Axis: ", "@__x__"), ("Y-Axis: ", "@__y__")] fig = Figure( plot_width=plot_width, plot_height=plot_height, toolbar_location=None, title=Title(text="Scatter Plot", align="center"), tools=[], x_axis_label=xcol, y_axis_label=ycol, ) scatter = fig.scatter("__x__", "__y__", source=source_scatter) hover = HoverTool(tooltips=tooltips, renderers=[scatter]) fig.add_tools(hover) x_select = Select(title="X-Axis", value=xcol, options=var_list, width=150) y_select = Select(title="Y-Axis", value=ycol, options=var_list, width=150) x_select.js_on_change( "value", CustomJS( args=dict( scatter=source_scatter, xy_value=source_xy_value, x_axis=fig.xaxis[0], ), code=""" let currentSelect = this.value; let xyValueData = xy_value.data; let scatterData = scatter.data; xyValueData['x'][0] = currentSelect; scatterData['__x__'] = scatterData[currentSelect]; x_axis.axis_label = currentSelect; scatter.change.emit(); xy_value.change.emit(); """, ), ) y_select.js_on_change( "value", CustomJS( args=dict( scatter=source_scatter, xy_value=source_xy_value, y_axis=fig.yaxis[0], ), code=""" let currentSelect = this.value; let xyValueData = xy_value.data; let scatterData = scatter.data; xyValueData['y'][0] = currentSelect; scatterData['__y__'] = scatterData[currentSelect]; y_axis.axis_label = currentSelect; scatter.change.emit(); xy_value.change.emit(); """, ), ) fig = column(row(x_select, y_select, align="center"), fig, sizing_mode="stretch_width") return fig
def create_vp_plot(data): ds = ColumnDataSource(data) # tools_to_show = "box_zoom, pan,save, hover, reset, wheel_zoom" var_label = '@{' + str(data.columns[0] + '}') try: var_tooltip_label = str(data.variable_metadata['long_name']) except KeyError: var_tooltip_label = str(data.variable_metadata['standard_name']) try: units = list({'unit', 'units'}.intersection(data.variable_metadata))[0] x_axis_label = " ".join( [var_tooltip_label, '[', data.variable_metadata[units], ']']) except IndexError: print('no units found') x_axis_label = var_tooltip_label p = figure(toolbar_location="above", tools="crosshair,box_zoom, pan,save, reset, wheel_zoom", x_axis_type="linear", x_axis_label=x_axis_label) p.sizing_mode = 'stretch_width' if len(data.dataset_metadata['dimension']) == 2: try: vertical_level, time_level = data.dataset_metadata['dimension'] except KeyError: vertical_level, time_level = ('obsdepth', 'time') else: vertical_level = data.dataset_metadata['dimension'][0] try: var_tooltip_label = str(data.variable_metadata['long_name']) except KeyError: var_tooltip_label = str(data.variable_metadata['standard_name']) # if " " in var_label: # var_label = '@{' + var_label + '}' # else: # var_label = var_label # var_label = var_label hover = HoverTool(tooltips=[("Depth", "@" + vertical_level), (var_tooltip_label, var_label)]) p.add_tools(hover) p.y_range.flipped = True p.min_border_left = 80 p.min_border_right = 80 p.background_fill_color = "SeaShell" p.background_fill_alpha = 0.5 line_renderer = p.line(data.columns[0], vertical_level, source=ds, line_alpha=0.6, color='RoyalBlue', ) point_renderer = p.circle(data.columns[0], vertical_level, source=ds, color='RoyalBlue', size=3, fill_alpha=0.5, fill_color='white', legend_label=data.columns[0], ) p.legend.location = "top_left" p.legend.click_policy = "hide" if len(list(data.columns)) >= 2: # Div html_text = get_datetime_string(list(data.columns)[0]) par = Div(text=html_text) # Slider Labels end_label = Div(text=list(data.columns)[-1]) start_label = Div(text=list(data.columns)[0]) # Buttons left_btn = Button(label='<', width=30) right_btn = Button(label='>', width=30) # Spacer sp = Spacer(width=50) # Slider Labels end_label = Div(text=list(data.columns)[-1].split('T')[0] + \ '<br>' \ + list(data.columns)[-1].split('T')[1], style={'text-align': 'right'}) start_label = Div(text=list(data.columns)[0].split('T')[0] + \ '<br>' \ + list(data.columns)[0].split('T')[1], style={'text-align': 'left'}) select = Select(title="Profile-record:", options=list(data.columns), value=list(data.columns)[0]) slider = Slider(title="Profile #", value=0, start=0, end=len(data.columns) - 1, step=1, show_value=True, tooltips=False) # select_handler = CustomJS(args=dict(line_renderer=line_renderer, point_renderer=point_renderer, slider=slider, par=par), code=""" line_renderer.glyph.x = {field: cb_obj.value}; point_renderer.glyph.x = {field: cb_obj.value}; slider.value = cb_obj.options.indexOf(cb_obj.value); var date_time = cb_obj.value.split("T"); var date = date_time[0]; var time = date_time[1]; par.text = `<ul style="text-align:left;"><li>Date: <b>`+date+`</b></li><li>Time: <b>`+time+`</b></li></ul>`; """) select.js_on_change('value', select_handler) slider_handler = CustomJS(args=dict(select=select), code=""" select.value = select.options[cb_obj.value]; """) slider.js_on_change('value', slider_handler) # Left button cb left_btn_args = dict(slider=slider) left_btn_handler = """ if(slider.value > slider.start) { slider.value = slider.value - 1; slider.change.emit(); } """ left_btn_callback = CustomJS(args=left_btn_args, code=left_btn_handler) left_btn.js_on_click(left_btn_callback) # Right button cb right_btn_args = dict(slider=slider) right_btn_handler = """ if(slider.value <= slider.end - 1) { slider.value = slider.value + 1; slider.change.emit(); } """ right_btn_callback = CustomJS(args=right_btn_args, code=right_btn_handler) right_btn.js_on_click(right_btn_callback) # buttons = row(left_btn, right_btn) # inputs = row(sp,slider,buttons, par) # return column(select, slider, p, par, sizing_mode="stretch_width") # return column(p, select, inputs, sizing_mode="stretch_width") # Set up layouts and add to document # slider_wrapper = layout([ # [slider], # [start_label, Spacer(sizing_mode="stretch_width"), end_label] # ]) slider_wrapper = layout([ [sp, sp, slider, left_btn, right_btn, par], [sp, start_label, sp, sp, end_label, sp, sp], ]) # buttons = row(left_btn, right_btn) # inputs = row(sp, start_label, left_btn, sp, slider, sp, right_btn, end_label, par) return column(select, p, slider_wrapper, sizing_mode="stretch_width") else: return column(p, sizing_mode="stretch_width")
opts = [ k for k in init_map.keys() if isinstance(init_map[k][0], int) or isinstance(init_map[k][0], float) ] select = Select(title="Data Options:", value="positiveActiveMAVPerMil", options=opts) select.js_on_change( "value", CustomJS(args={ 'mpoly': map_mpolys[k], 'ext_datafiles': ext_datafiles, 'graph_lines': graph_lines, }, code=""" console.log('select: value=' + this.value, this.toString()) mpoly.glyph.fill_color.field = this.value mpoly.data_source.change.emit() console.log(mpoly.glyph.fill_color.transform) console.log(mpoly.glyph.fill_color.transform.low) console.log(mpoly.glyph.fill_color.transform.high) """)) with open(javascript_path + 'graph_callback.js', 'r') as f: graph_callback = f.read() graph_fig.js_on_event( 'tap', CustomJS(args={ 'mpoly': map_mpolys[k], 'ext_datafiles': ext_datafiles,
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'
feature_selection_dict = {} for j in range(axis_threshold): feature_selection_dict[str(j + 1)] = j feature_axis_x_select = Select(value=default_x_index, title='X-axis', options=sorted(feature_selection_dict.keys())) feature_axis_y_select = Select(value=default_y_index, title='Y-axis', options=sorted(feature_selection_dict.keys())) feature_axis_x_select.js_on_change( 'value', CustomJS(args=dict(key='x', labels=feature_selection_dict, source=feature_source, projection_pool=xx_feature_projection_list, correlation_pool=xx_feature_correlation_list, axis=[feature_left.xaxis[0], feature_right.xaxis[0]]), code=code)) feature_axis_y_select.js_on_change( 'value', CustomJS(args=dict(key='y', labels=feature_selection_dict, source=feature_source, projection_pool=xx_feature_projection_list, correlation_pool=xx_feature_correlation_list, axis=[feature_left.yaxis[0], feature_right.yaxis[0]]), code=code)) feature_controls = column(feature_axis_x_select, feature_axis_y_select)
def __init__(self, data, deterministic_data, metadata): curdoc().title = "Verificarlo Report" self.data = data self.deterministic_data = deterministic_data self.metadata = metadata # Initialize repository selection # Generate display names for repositories remote_urls = self.metadata["remote_url"].drop_duplicates().to_list() branches = self.metadata["branch"].drop_duplicates().to_list() repo_names_dict = helper.gen_repo_names(remote_urls, branches) self.metadata["repo_name"] = self.metadata["remote_url"].apply( lambda x: repo_names_dict[x] ) # Add the repository selection widget select_repo = Select( name="select_repo", title="", value=list(repo_names_dict.values())[0], options=list(repo_names_dict.values()) ) curdoc().add_root(select_repo) select_repo.on_change("value", self.change_repo) change_repo_callback_js = "changeRepository(cb_obj.value);" select_repo.js_on_change( "value", CustomJS(code=change_repo_callback_js) ) # Invert key/values for repo_names_dict and pass it to the template as # a JSON string repo_names_dict = { value: key for key, value in repo_names_dict.items()} curdoc().template_variables["repo_names_dict"] = json.dumps( repo_names_dict) # Pass metadata to the template as a JSON string curdoc().template_variables["metadata"] = self.metadata.to_json( orient="index") # Show the first repository by default repo_name = list(repo_names_dict.keys())[0] # Filter metadata by repository filtered_metadata = self.metadata[ self.metadata["repo_name"] == repo_name ] # Filter data and deterministic_data by repository if not data.empty: filtered_data = self.data[ helper.filterby_repo( self.metadata, repo_name, self.data["timestamp"] ) ] else: filtered_data = data if not deterministic_data.empty: filtered_deterministic_data = self.deterministic_data[ helper.filterby_repo( self.metadata, repo_name, self.deterministic_data["timestamp"] ) ] else: filtered_deterministic_data = deterministic_data # Initialize views # Initialize runs comparison self.compare = compare_runs.CompareRuns( master=self, doc=curdoc(), data=filtered_data, metadata=filtered_metadata ) # Initialize deterministic runs comparison self.deterministic = deterministic_compare.DeterministicCompare( master=self, doc=curdoc(), data=filtered_deterministic_data, metadata=filtered_metadata ) # Initialize runs inspection self.inspect = inspect_runs.InspectRuns( master=self, doc=curdoc(), data=filtered_data, metadata=filtered_metadata ) # Initialize checks table view self.checks = checks.Checks( master=self, doc=curdoc(), data=filtered_data, deterministic_data=filtered_deterministic_data, metadata=filtered_metadata )