def test_callback_property_executes(self, bokeh_model_page): group = CheckboxGroup(labels=LABELS, css_classes=["foo"]) group.callback = CustomJS(code=RECORD("active", "cb_obj.active")) page = bokeh_model_page(group) el = page.driver.find_element_by_css_selector('.foo input[value="2"]') el.click() results = page.results assert results['active'] == [2] el = page.driver.find_element_by_css_selector('.foo input[value="0"]') el.click() results = page.results assert results['active'] == [0, 2] el = page.driver.find_element_by_css_selector('.foo input[value="2"]') el.click() results = page.results assert results['active'] == [0] assert page.has_no_console_errors()
def modify_doc(doc): source = ColumnDataSource(dict(x=[1, 2], y=[1, 1], val=["a", "b"])) plot = Plot(plot_height=400, plot_width=400, x_range=Range1d(0, 1), y_range=Range1d(0, 1), min_border=0) plot.add_glyph(source, Circle(x='x', y='y', size=20)) plot.add_tools(CustomAction(callback=CustomJS(args=dict(s=source), code=RECORD("data", "s.data")))) group = CheckboxGroup(labels=LABELS, css_classes=["foo"]) def cb(active): source.data['val'] = (active + [0, 0])[:2] # keep col length at 2, padded with zero group.on_click(cb) doc.add_root(column(group, plot))
def render_mask(img_path, document_objs, document_name='Default_Document', output_path='./outputs/', save_html=False): img = load_img(img_path) bokeh.plotting.reset_output() hover = HoverTool( tooltips=[ ("Name", "@name"), ("(x,y)", "($x, $y)"), ] ) fig = figure(tools=[hover, bokeh.models.WheelZoomTool(), bokeh.models.PanTool()]) fig.hover.point_policy = "follow_mouse" fig.sizing_mode='scale_width' fig.image_url(url=[os.path.basename(img_path)], x=0, y=img.shape[0], w=img.shape[1], h=img.shape[0]) script = "active = cb_obj.active;" labels = list(document_objs.keys()) color_map = bp.magma(len(labels)) args = dict() total_objs = 0 for key_id, key in enumerate(labels): xs = [] ys = [] for box in document_objs[key]: _ = np.array(box).reshape(-1,2).T xs.append(_[0]) ys.append(_[1]) ys=doccoor2planecoor(ys, img.shape[0]) data_source = dict(x=xs, y=ys, name=["%s %d"%(key, idx) for idx in range(len(xs))]) falpha = 0.5*int('table' not in key.lower()) lcolor = 'blue' if 'table' in key.lower() else 'red' lwidth = 3 if 'table' in key.lower() else 1 total_objs += len(document_objs[key]) args[key] = fig.patches('x', 'y', source=data_source, fill_color=color_map[key_id], fill_alpha=falpha, line_color=lcolor, line_width=lwidth, legend=key+': %d'%len(document_objs[key])) r = args[key] script += "\n%s.visible = active.includes(%d);"%(key, key_id) fig.patch([],[], fill_color='red', fill_alpha=0, line_color='white', legend='Total region: %d'%total_objs) fig.legend.click_policy="hide" fig.legend.location = "top_left" checkbox = CheckboxGroup(labels=labels, active=[])#active=[*range(len(labels))]) checkbox.callback = CustomJS(args=args, code=script) plt_obj = [fig] html = file_html(plt_obj, CDN, title=document_name) if save_html: base = os.path.join(output_path, document_name) if os.path.exists(base): shutil.rmtree(base) os.makedirs(base) shutil.copy(img_path, base) with open(os.path.join(base, 'main.html'),'w') as g: g.write(html) return html
if 3 in toggle_checkbox.active: source.data = pdict['source.data'] else: source.data = dict( x=[], y=[], x1=[], y1=[], cx=[], cy=[], ) toggle_checkbox = CheckboxGroup(labels=[ "Toggle Start Points", "Toggle End Points", "Toggle Hexes", "Toggle Path" ], active=[0, 1, 2, 3]) toggle_checkbox.on_change("active", toggle_checkbox_handler) weekday_checkbox = CheckboxGroup(labels=[ 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday' ], active=[0, 1, 2, 3, 4, 5, 6]) cid_filter = CheckboxGroup(labels=["Filter Customers"], active=[]) #cid_filter.on_change('active',cid_filter_handler) CID = list(set(df['customer_id'].astype('str')))
def main_gui_fnc(doc): # Make widgets plottype_list = ['Trends', '1D Distribution', '2D Distribution'] plottype_dropdown = Select(title='Plot Type', value=plottype_list[0], options=plottype_list) trend_x_list = ['z', 't'] trend_y_list = [ 'Beam Size', 'Bunch Length', 'Emittance (x,y)', 'Emittance (4D)', 'Slice emit. (x,y)', 'Slice emit. (4D)', 'Charge', 'Energy', 'Trajectory' ] trend_x_dropdown = Select(title='X axis', options=trend_x_list, value=trend_x_list[0]) trend_y_dropdown = Select(title='Y axis', options=trend_y_list, value=trend_y_list[0]) dist_list = ['t', 'x', 'y', 'px', 'py', 'pz'] trend_slice_var_dropdown = Select(title='Slice variable', options=dist_list, value=dist_list[0]) trend_slice_nslices_text = make_text_input(text_input_params, 'Number of slices', min=5, max=500, value=50, step=1) screen_z_dropdown = Select(title='Screen z (m)', options=screen_z_str_list, value=screen_z_str_list[0]) dist_x_1d_dropdown = Select(title='X axis', options=dist_list, value=dist_list[0]) dist_type_1d_list = [ 'Charge Density', 'Emittance X', 'Emittance Y', 'Emittance 4D', 'Sigma X', 'Sigma Y' ] dist_type_1d_dropdown = Select(title='Y axis', options=dist_type_1d_list, value=dist_type_1d_list[0]) nbin_1d_text = make_text_input(text_input_params, 'Histogram bins', min=5, max=500, value=50, step=1) screen_z_dropdown_copy = Select(title='Screen z (m)', options=screen_z_str_list, value=screen_z_str_list[0]) screen_z_dropdown_copy.js_link('value', screen_z_dropdown, 'value') screen_z_dropdown.js_link('value', screen_z_dropdown_copy, 'value') dist_x_dropdown = Select(title='X axis', options=dist_list, value=dist_list[1]) dist_y_dropdown = Select(title='Y axis', options=dist_list, value=dist_list[2]) dist_2d_type_list = ['Scatter', 'Histogram'] dist2d_type_dropdown = Select(title='Plot method', options=dist_2d_type_list, value=dist_2d_type_list[1]) scatter_color_list = [ 'density', 't', 'x', 'y', 'r', 'px', 'py', 'pz', 'pr' ] scatter_color_dropdown = Select(title='Scatter color variable', options=scatter_color_list, value=scatter_color_list[0]) axis_equal_checkbox = CheckboxGroup(labels=['Enabled'], active=[]) nbin_x_text = make_text_input(text_input_params, 'Histogram bins, X', min=5, max=500, value=50, step=1) nbin_y_text = make_text_input(text_input_params, 'Histogram bins, Y', min=5, max=500, value=50, step=1) cyl_copies_checkbox = CheckboxGroup(labels=['Enabled'], active=[]) cyl_copies_text = make_text_input(text_input_params, 'Number of copies', min=5, max=500, value=50, step=1) remove_correlation_checkbox = CheckboxGroup(labels=['Enabled'], active=[]) remove_correlation_n_text = make_text_input(text_input_params, 'Max polynomial power', min=0, max=10, value=1, step=1) remove_correlation_var1_dropdown = Select(title='Independent var (x)', options=dist_list, value=dist_list[1]) remove_correlation_var2_dropdown = Select(title='Dependent var (y)', options=dist_list, value=dist_list[3]) take_slice_checkbox = CheckboxGroup(labels=['Enabled'], active=[]) take_slice_var_dropdown = Select(title='Slice variable', options=dist_list, value=dist_list[0]) take_slice_nslices_text = make_text_input(text_input_params, 'Number of slices', min=5, max=500, value=50, step=1) take_slice_index_text = make_text_input( text_input_params, 'Slice index', min=0, max=int(take_slice_nslices_text.value) - 1, value=0, step=1) trends_tab = column(add_label(trend_x_dropdown, widget_width), add_label(trend_y_dropdown, widget_width), add_label(trend_slice_var_dropdown, widget_width), add_label(trend_slice_nslices_text, widget_width)) dist_1d_tab = column(add_label(screen_z_dropdown, widget_width), add_label(dist_x_1d_dropdown, widget_width), add_label(dist_type_1d_dropdown, widget_width), add_label(nbin_1d_text, widget_width)) dist_2d_tab = column( add_label(screen_z_dropdown_copy, widget_width), add_label(dist2d_type_dropdown, widget_width), add_label(scatter_color_dropdown, widget_width), add_label(dist_x_dropdown, widget_width), add_label(dist_y_dropdown, widget_width), add_label(axis_equal_checkbox, widget_width, label='Equal scale axes'), add_label(nbin_x_text, widget_width), add_label(nbin_y_text, widget_width)) postprocess_tab = column( add_label(cyl_copies_checkbox, widget_width, label='Cylindrical copies'), add_label(cyl_copies_text, widget_width), add_label(remove_correlation_checkbox, widget_width, label='Remove Correlation'), add_label(remove_correlation_n_text, widget_width), add_label(remove_correlation_var1_dropdown, widget_width), add_label(remove_correlation_var2_dropdown, widget_width), add_label(take_slice_checkbox, widget_width, label='Take slice of data'), add_label(take_slice_var_dropdown, widget_width), add_label(take_slice_index_text, widget_width), add_label(take_slice_nslices_text, widget_width)) tab1 = Panel(child=trends_tab, title='Trends') tab2 = Panel(child=dist_1d_tab, title='1D Dist.') tab3 = Panel(child=dist_2d_tab, title='2D Dist.') tab4 = Panel(child=postprocess_tab, title='Postprocess') tabs = Tabs(tabs=[tab1, tab2, tab3, tab4]) main_panel = column(row(add_label(plottype_dropdown, widget_width)), tabs) # Main plotting function def create_plot(): #Get current GUI settings plottype = plottype_dropdown.value.lower() trend_x = 'mean_' + trend_x_dropdown.value.lower() trend_y = get_trend_vars(trend_y_dropdown.value.lower()) trend_slice_var = trend_slice_var_dropdown.value trend_slice_nslices = int( trend_slice_nslices_text.value ) #constrain_text_input(trend_slice_nslices_text, text_input_params) screen_z = float(screen_z_dropdown.value) dist_x_1d = dist_x_1d_dropdown.value dist_y_1d = dist_type_1d_dropdown.value.lower() nbins_1d = int( nbin_1d_text.value ) # constrain_text_input(nbin_1d_text, text_input_params) dist_x = dist_x_dropdown.value dist_y = dist_y_dropdown.value ptype = dist2d_type_dropdown.value.lower() scatter_color_var = scatter_color_dropdown.value.lower() is_trend = (plottype == 'trends') is_slice_trend = any(['slice' in yy for yy in trend_y]) is_dist1d = (plottype == '1d distribution') is_dist2d = (plottype == '2d distribution') nbins = [int(nbin_x_text.value), int(nbin_y_text.value)] axis_equal = (0 in axis_equal_checkbox.active) cyl_copies_on = (0 in cyl_copies_checkbox.active) and (plottype != 'trends') cyl_copies = int(cyl_copies_text.value) remove_correlation = (0 in remove_correlation_checkbox.active ) and (plottype != 'trends') remove_correlation_n = int(remove_correlation_n_text.value) remove_correlation_var1 = remove_correlation_var1_dropdown.value remove_correlation_var2 = remove_correlation_var2_dropdown.value take_slice = (0 in take_slice_checkbox.active) and (plottype != 'trends') take_slice_var = take_slice_var_dropdown.value take_slice_nslices = int(take_slice_nslices_text.value) text_input_params[ take_slice_index_text.id]['max'] = take_slice_nslices - 1 take_slice_index = int(take_slice_index_text.value) # Disable widgets trend_x_dropdown.disabled = not is_trend trend_y_dropdown.disabled = not is_trend trend_slice_var_dropdown.disabled = not is_slice_trend trend_slice_nslices_text.disabled = not is_slice_trend screen_z_dropdown.disabled = not is_dist1d dist_x_1d_dropdown.disabled = not is_dist1d dist_type_1d_dropdown.disabled = not is_dist1d nbin_1d_text.disabled = not is_dist1d screen_z_dropdown_copy.disabled = not is_dist2d dist2d_type_dropdown.disabled = not is_dist2d scatter_color_dropdown.disabled = not (is_dist2d and ptype == 'scatter') dist_x_dropdown.disabled = not is_dist2d dist_y_dropdown.disabled = not is_dist2d axis_equal_checkbox.disabled = not is_dist2d nbin_x_text.disabled = not is_dist2d nbin_y_text.disabled = not is_dist2d if (is_trend): params = {} if (is_slice_trend): params['slice_key'] = trend_slice_var params['n_slices'] = trend_slice_nslices p = gpt_plot(gpt_data, trend_x, trend_y, show_plot=False, format_input_data=False, **params) if (is_dist1d): ptype_1d = get_dist_plot_type(dist_y_1d) params = {} if (cyl_copies_on): params['cylindrical_copies'] = cyl_copies if (remove_correlation): params['remove_correlation'] = (remove_correlation_var1, remove_correlation_var2, remove_correlation_n) if (take_slice): params['take_slice'] = (take_slice_var, take_slice_index, take_slice_nslices) p = gpt_plot_dist1d(gpt_data, dist_x_1d, screen_z=screen_z, plot_type=ptype_1d, nbins=nbins_1d, show_plot=False, format_input_data=False, **params) if (is_dist2d): params = {} params['color_var'] = scatter_color_var if (axis_equal): params['axis'] = 'equal' if (cyl_copies_on): params['cylindrical_copies'] = cyl_copies if (remove_correlation): params['remove_correlation'] = (remove_correlation_var1, remove_correlation_var2, remove_correlation_n) if (take_slice): params['take_slice'] = (take_slice_var, take_slice_index, take_slice_nslices) p = gpt_plot_dist2d(gpt_data, dist_x, dist_y, screen_z=screen_z, plot_type=ptype, nbins=nbins, show_plot=False, format_input_data=False, **params) p.width = plot_area_width return p gui = row(main_panel, create_plot()) doc.add_root(gui) #callback functions def just_redraw(attr, old, new): gui.children[1] = create_plot() def change_tab(attr, old, new): new_index = plottype_list.index(new) if (tabs.active < 3): tabs.active = new_index gui.children[1] = create_plot() # Assign callbacks plottype_dropdown.on_change('value', change_tab) trend_x_dropdown.on_change('value', just_redraw) trend_y_dropdown.on_change('value', just_redraw) trend_slice_var_dropdown.on_change('value', just_redraw) trend_slice_nslices_text.on_change('value', just_redraw) screen_z_dropdown.on_change('value', just_redraw) dist_x_1d_dropdown.on_change('value', just_redraw) dist_type_1d_dropdown.on_change('value', just_redraw) nbin_1d_text.on_change('value', just_redraw) dist_x_dropdown.on_change('value', just_redraw) dist_y_dropdown.on_change('value', just_redraw) dist2d_type_dropdown.on_change('value', just_redraw) scatter_color_dropdown.on_change('value', just_redraw) nbin_x_text.on_change('value', just_redraw) nbin_y_text.on_change('value', just_redraw) axis_equal_checkbox.on_change('active', just_redraw) cyl_copies_checkbox.on_change('active', just_redraw) cyl_copies_text.on_change('value', just_redraw) remove_correlation_checkbox.on_change('active', just_redraw) remove_correlation_n_text.on_change('value', just_redraw) remove_correlation_var1_dropdown.on_change('value', just_redraw) remove_correlation_var2_dropdown.on_change('value', just_redraw) take_slice_checkbox.on_change('active', just_redraw) take_slice_var_dropdown.on_change('value', just_redraw) take_slice_index_text.on_change('value', just_redraw) take_slice_nslices_text.on_change('value', just_redraw)
source_1_hom520.data = dict(x=temp_range, y=SellarsTegart_1_hom520) source_10_hom520.data = dict(x=temp_range, y=SellarsTegart_10_hom520) # update the title values_string = ('Homogenisation 520: ' + 'SigmaR = ' + "{0:.3}".format(SigmaR_hom520) + ', SigmaP = ' + "{0:.3}".format(SigmaP_hom520) + ', Q = ' + "{0:.2E}".format(ST_values[2]) + ', A = ' + "{0:.2E}".format(ST_values[3]) + ', n = ' + "{0:.3}".format(ST_values[4])) fig_hom520.title.text = values_string # Set checkboxes LABELS = ["SigmaR", "SigmaP", "Q", "A", "n"] checkbox_group = CheckboxGroup(labels=LABELS) checkbox_group.on_change('active', callback) # insert sliders for the max and min values SigmaR_range_slider = RangeSlider(start=0, end=100, value=(0, 50), step=.1, title="SigmaR") SigmaP_range_slider = RangeSlider(start=0, end=100, value=(0, 50), step=.1, title="SigmaP") Q_range_slider = RangeSlider(start=0.5e5, end=3e5,
def _show_graph(self, data_frame): #create the plot panels for the Agent_Tasks panels = self._create_task_panels(data_frame) top_left_x_range = panels[list(panels.keys())[0]]['panel1'].x_range #Altitude over ground pAltitude = figure(plot_width=800, plot_height=300, x_range=top_left_x_range) alti_legend = [] # Setting the second y axis range name and range pAltitude.extra_y_ranges = {"speed": Range1d(50, 120)} # Adding the second axis to the plot. pAltitude.add_layout( LinearAxis(y_range_name="speed", axis_label="IAS, TAS [Knots]"), 'right') altitudeLine = pAltitude.line(data_frame.index * self.step_time, data_frame['position_h_sl_ft'], line_width=2, color=Viridis4[2]) alti_legend.append(("Altitude [ftsl]", [altitudeLine])) kiasLine = pAltitude.line(data_frame.index * self.step_time, data_frame['velocities_vc_kts'], line_width=2, y_range_name="speed", color=Viridis4[1]) alti_legend.append(("Indicated Airspeed [KIAS]", [kiasLine])) tasLine = pAltitude.line(data_frame.index * self.step_time, data_frame['velocities_vtrue_kts'], line_width=2, y_range_name="speed", color=Viridis4[0]) alti_legend.append(("True Airspeed [KAS]", [tasLine])) pAltitude.extra_y_ranges.renderers = [ kiasLine, tasLine ] #this does not quite work: https://stackoverflow.com/questions/48631530/bokeh-twin-axes-with-datarange1d-not-well-scaling pAltitude.y_range.renderers = [altitudeLine] lg_alti = Legend(items=alti_legend, location=(0, 10), glyph_width=25, label_width=190) lg_alti.click_policy = "hide" pAltitude.add_layout(lg_alti, 'right') tAlti = Title() tAlti.text = 'Altitude and Speed [IAS, TAS] over Timesteps' pAltitude.title = tAlti pAltitude.xaxis.axis_label = 'timestep [s]' pAltitude.yaxis[0].axis_label = 'Altitude [ftsl]' pAltitude.legend.location = "center_right" pSideslip = figure(plot_width=800, plot_height=300, x_range=top_left_x_range) slip_legend = [] slip_skid_line = pSideslip.line(data_frame.index * self.step_time, data_frame['aero_beta_deg'], line_width=2, color=Viridis4[2]) slip_legend.append(("Sideslip", [slip_skid_line])) pSideslip.y_range.renderers = [slip_skid_line] lg_slip = Legend(items=slip_legend, location=(0, 10), glyph_width=25, label_width=190) lg_slip.click_policy = "hide" pSideslip.add_layout(lg_slip, 'right') tSlip = Title() tSlip.text = 'Sideslip' pSideslip.title = tSlip pSideslip.xaxis.axis_label = 'timestep [s]' pSideslip.yaxis[0].axis_label = 'Sideslip [deg]' pSideslip.legend.location = "center_right" #activate the zooming on all plots #this is not nice, but this not either: https://stackoverflow.com/questions/49282688/how-do-i-set-default-active-tools-for-a-bokeh-gridplot pAltitude.toolbar.active_scroll = pAltitude.toolbar.tools[ 1] #this selects the WheelZoomTool instance pSideslip.toolbar.active_scroll = pSideslip.toolbar.tools[ 1] #this selects the WheelZoomTool instance reset_output() # if self.env.meta_dict['model_type'] == 'trained': # discriminator = self.env.meta_dict['model_base_name']+"_%+.2f" % (data_frame['reward'].sum()) # self.env.meta_dict['model_discriminator'] = discriminator # else: # discriminator = self.env.meta_dict['model_discriminator'] ts = time.time() overshoot_frames_per_task = self._analyze_overshoot(data_frame) overshoot_divs = [ Div(text=ovs_fr.round(3).to_html(), width=600) for ovs_fr in overshoot_frames_per_task ] print("Overshoot analysis done in %.2f sec" % (time.time() - ts)) ts = time.time() settlement_times_per_task = self._analyze_settle_times(data_frame) settlement_divs = [ Div(text=settle_fr.round(3).to_html(), width=600) for settle_fr in settlement_times_per_task ] print("Settlement analysis done in %.2f sec" % (time.time() - ts)) panel_grid = [] panel_grid.append([ Div(text='<h3>' + t.name + '</h3>', id='div_' + t.name) for t in self.env.task_list ]) # to switch on and off the statistics panels, this is unfortuntely the best, I could achive # https://stackoverflow.com/a/52416676/2682209 cols = [] checkbox = CheckboxGroup( labels=["show stats"], active=[], width=100) #checkbox is added to header_col later on for i, t in enumerate(self.env.task_list): # overshoot_stat = overshoot_divs[i] c = column(Div()) #empty for the beginning cols.append(c) callback = CustomJS(args=dict(overshoot_divs=overshoot_divs, settlement_divs=settlement_divs, cols=cols, checkbox=checkbox), code=""" for (var j = 0; j < cols.length; j++) { console.log('col', j) const children = [] for (const i of checkbox.active) { console.log('active', i) children.push(overshoot_divs[j]) children.push(settlement_divs[j]) } console.log('children', children) cols[j].children = children } """) checkbox.js_on_change('active', callback) # show_stats_btn = [Div(text=""" # <button onclick="display_event(%s)">Try it</button> # """ %t.name for t in self.env.task_list] # for t, b in zip(self.env.task_list, show_stats_btn): # b.tags = ['id', 'btn_'+t.name] # panel_grid.append(show_stats_btn) # [b.js_on_event(events.ButtonClick, display_event(b, t.name)) for t, b in zip(self.env.task_list, show_stats_btn)] # panel_grid.append(chkbxs) panel_grid.append(cols) panel_grid_t = [[ panels[name]['panel1'], panels[name]['panel2'], panels[name]['panel3'] ] for name in self.task_names] [panel_grid.append(fig) for fig in list(zip(*panel_grid_t))] # add the additional plots panel_grid.append([pAltitude, pSideslip]) panel_grid_plot = gridplot(panel_grid, toolbar_location='right', sizing_mode='stretch_width') #for string formatting look here: https://pyformat.info/ titleString = '' if 'experiment_name' in self.env.meta_dict: titleString += "{}: ".format(self.env.meta_dict['experiment_name']) titleString += "Run Date: {}; ".format( datetime.datetime.now().strftime("%c")) if 'train_step' in self.env.meta_dict: titleString += "Training Step: {}; ".format( self.env.meta_dict['train_step']) if 'episode_number' in self.env.meta_dict: titleString += "Episode: {}; ".format( self.env.meta_dict['episode_number']) if 'csv_line_nr' in self.env.meta_dict: titleString += "Env in CSV line: {}; ".format( self.env.meta_dict['csv_line_nr']) # titleString += "Total Reward: {:.2f}; ".format(data_frame['reward'].sum()) # titleString += "Model Discriminator: {};".format(self.env.meta_dict['model_discriminator']) header_col = column( Div(text="<h1>" + self.env.unwrapped.spec.id + (" - " + self.env.meta_dict['env_info']) if 'env_info' in self.meta_dict else "" + "</h1>"), row(Div(text="<h2>" + titleString + "</h2>", width=1200), checkbox)) webpage = gridplot([[header_col], [panel_grid_plot]], toolbar_location=None, sizing_mode='stretch_width') base_filename = 'Run_' + '_'.join([tsk.name for tsk in self.task_list]) html_output_name = os.path.join(self.save_path, 'plots', base_filename + '_latest.html') os.makedirs(os.path.dirname(html_output_name), exist_ok=True) if self.showNextPlotFlag: output_file( html_output_name, mode='inline' ) #mode='absolute') #use mode='absolute' to make it work offline with the js and css installed in the bokeh package locally if self.firstRun: show(webpage) #opens up a new browser window self.firstRun = False else: save( webpage ) #just updates the HTML; Manual F5 in browser required :-(, (There must be a way to push...) if self.exportNextPlotFlag and self.save_path: #build the filename including the individual rewards task_rewards = [ self.reward_variables[i].get_legal_name() for i in range(len(self.task_list)) ] task_names_with_rewards = [ t.name + '_' + f'{data_frame[task_rewards[i]].sum():.2f}' for i, t in enumerate(self.task_list) ] name_with_rewards = 'Run_' + '_'.join( task_names_with_rewards) + 'time_{}'.format( datetime.datetime.now().strftime("%H-%M-%S")) base_filename = os.path.join( self.save_path, 'plots', name_with_rewards ) # 'glideAngle_Elevator_Reward_{:.2f}_time_{}'.format(data_frame['reward'].sum(), datetime.datetime.now().strftime("%H-%M-%S"))) if self.showNextPlotFlag: #we keep the html as well for easy exploration shutil.copyfile(html_output_name, base_filename + '.html') def export(webpage): png_filename = base_filename + '.png' webpage.width = 1800 #set the width of the page instead of passing a width parameter to the export; https://stackoverflow.com/a/61563173/2682209 export_png( webpage, filename=png_filename ) #TODO: the width parameter is ignored in bokeh/io/export.py get_layout_html() as webpage isn't a Plot export( gridplot([[header_col], [panel_grid_plot]], toolbar_location=None)) self.showNextPlotFlag = False #only show the plot once and then reset self.exportNextPlotFlag = False print("Output Plot generated: " + titleString)
from bokeh.plotting import figure x = [3, 4, 6, 12, 10, 1] y = [7, 1, 3, 4, 1, 6] source = ColumnDataSource(data=dict(x=x, y=y)) plot_figure = figure(title='Checkbox', plot_height=450, plot_width=600, tools="save,reset", toolbar_location="below") plot_figure.scatter('x', 'y', source=source, size=10) checkbox = CheckboxGroup(labels=['Show x-axis label', 'Show y-axis label']) def checkbox_click(attr, old, new): active_checkbox = checkbox.active ##Getting checkbox value in list ## Get first checkbox value and show x-axis label if len(active_checkbox) != 0 and (0 in active_checkbox): plot_figure.xaxis.axis_label = 'X-Axis' else: plot_figure.xaxis.axis_label = None ## Get second checkbox value and show y-axis label if len(active_checkbox) != 0 and (1 in active_checkbox):
d3['y'].push(d2['y'][i]) d3['time'].push(d2['time'][i]) d3['ann'].push(d2['ann'][i]) d3['noise'].push(d2['noise'][i]) d3['change'].push(0) } } } s3.change.emit(); s4.change.emit(); """) checkboxes = CheckboxGroup(name="Select beats to display",labels=['N','V','Q'], active=[0, 1,2],callback = callback3,height = 120) checkboxes.active = [] checkboxes.js_on_click(callback3) div = Div(text="""<b>Select annotations to change: </b>""", width=200, height=0) div2 = Div(text="""<b>Change annotations to : </b>""", width=200, height=0) div3 = Div(text="""<b>Select noise level : </b>""", width=200, height=0)
def __init__( self, plot_height=894, plot_width=854, image_height=100, image_width=100, x_start=None, x_end=None, y_start=None, y_end=None, ): """Initialize image view plot. Args: plot_height (int, optional): Height of plot area in screen pixels. Defaults to 894. plot_width (int, optional): Width of plot area in screen pixels. Defaults to 854. image_height (int, optional): Image height in pixels. Defaults to 100. image_width (int, optional): Image width in pixels. Defaults to 100. x_start (int, optional): Initial x-axis start value. If None, then equals to 0. Defaults to None. x_end (int, optional): Initial x-axis end value. If None, then equals to image_width. Defaults to None. y_start (int, optional): Initial y-axis start value. If None, then equals to 0. Defaults to None. y_end (int, optional): Initial y-axis end value. If None, then equals to image_height. Defaults to None. """ if x_start is None: x_start = 0 if x_end is None: x_end = image_width if y_start is None: y_start = 0 if y_end is None: y_end = image_height self.zoom_views = [] plot = Plot( x_range=Range1d(x_start, x_end, bounds=(0, image_width)), y_range=Range1d(y_start, y_end, bounds=(0, image_height)), plot_height=plot_height, plot_width=plot_width, toolbar_location="left", ) self.plot = plot # ---- tools plot.toolbar.logo = None hovertool = HoverTool(tooltips=[("intensity", "@image")], names=["image_glyph"]) plot.add_tools(PanTool(), WheelZoomTool(maintain_focus=False), SaveTool(), ResetTool(), hovertool) plot.toolbar.active_scroll = plot.tools[1] # ---- axes plot.add_layout(LinearAxis(), place="above") plot.add_layout(LinearAxis(major_label_orientation="vertical"), place="right") # ---- grid lines plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- rgba image glyph self._image_source = ColumnDataSource( dict( image=[np.zeros((1, 1), dtype="float32")], x=[x_start], y=[y_start], dw=[x_end - x_start], dh=[y_end - y_start], )) self.image_glyph = Image(image="image", x="x", y="y", dw="dw", dh="dh") image_renderer = plot.add_glyph(self._image_source, self.image_glyph, name="image_glyph") # This avoids double update of image values on a client, see # https://github.com/bokeh/bokeh/issues/7079 # https://github.com/bokeh/bokeh/issues/7299 image_renderer.view.source = ColumnDataSource() # ---- pixel value text glyph self._pvalue_source = ColumnDataSource(dict(x=[], y=[], text=[])) plot.add_glyph( self._pvalue_source, Text( x="x", y="y", text="text", text_align="center", text_baseline="middle", text_color="white", ), ) # ---- horizontal and vertical projection line glyphs self._hproj_source = ColumnDataSource(dict(x=[], y=[])) plot.add_glyph(self._hproj_source, Line(x="x", y="y", line_color="greenyellow")) self._vproj_source = ColumnDataSource(dict(x=[], y=[])) plot.add_glyph(self._vproj_source, Line(x="x", y="y", line_color="greenyellow")) proj_toggle = CheckboxGroup(labels=["Inner Projections"], default_size=145) self.proj_toggle = proj_toggle
p.xaxis.major_label_text_font_size = '12pt' p.yaxis.axis_label_text_font_size = '12pt' p.yaxis.major_label_text_font_size = '12pt' return p def get_dataset(carrier_list): subset = by_carrier[by_carrier['name'].isin(carrier_list)] new_src = ColumnDataSource(subset) return new_src def update(attr, old, new): carrier_list = [available_carriers[i] for i in carrier_select.active] new_src = get_dataset(carrier_list) src.data.update(new_src.data) carrier_select = CheckboxGroup(labels=available_carriers, active=[0]) carrier_select.on_change('active', update) src = get_dataset([available_carriers[i] for i in carrier_select.active]) p = make_plot(src) layout = row(carrier_select, p) tab = Panel(child=layout, title='Histogram') tabs = Tabs(tabs=[tab]) curdoc().add_root(tabs)
def show_cells_on_stack(data, stack, X='X', Y='Y', channelNames=None, group='group', hue='hue', palette='Spectral11', default=0, alpha=.5, plot_width=500, plot_height=500, vmin=0, vmax=3, znorm=True): ''' stack: np. array of shape (nchannels,height,width) ''' from bokeh.models import CheckboxGroup, RadioButtonGroup, Legend, LegendItem if not channelNames: channelNames = ['Channel ' + str(i) for i in range(len(stack))] print(channelNames) s1 = ColumnDataSource(data=data) p1 = figure(plot_width=plot_width, plot_height=plot_height, tools="pan,wheel_zoom,reset") channels = {} for i, channel in enumerate(channelNames): img = stack[i] if znorm: img = (img - img.mean()) / img.std() channels[i] = p1.image(image=[img], x=[0], y=[0], dw=[plot_width], dh=[plot_height], color_mapper=LogColorMapper(palette=palette, low=vmin, high=vmax), global_alpha=alpha, visible=(i == default)) plots = {} #scaled_coordinates to fit in stack_dw,stack_dh dh_ratio = plot_height / img.shape[0] dw_ratio = plot_width / img.shape[1] data['warped_X'] = data[X] * dw_ratio data['warped_Y'] = data[Y] * dh_ratio groups = list(data[group].unique()) for g_id in groups: s2 = ColumnDataSource(data=data[data[group] == g_id]) scatter = p1.circle('warped_X', 'warped_Y', source=s2, alpha=1, color='hue') #,legend_label = str(g_id)) scatter.visible = False plots[g_id] = scatter select_celltype = CheckboxGroup(labels=groups, active=[], width=100) select_channel = RadioButtonGroup(labels=channelNames, active=default, width=100, orientation='horizontal') select_celltype.callback = CustomJS(args={ 'plots': plots, 'groups': groups, 'msel': select_celltype, 'fig': p1 }, code=""" //fig.title.text = 'new Title' for (var i =0; i<groups.length;i++){ plots[groups[i]].visible = msel.active.indexOf(i)>-1 } """) select_channel.callback = CustomJS(args={ 'channels': channels, 'sel': select_channel, 'fig': p1 }, code=""" //fig.title.text = Object.keys(channels).length.toString() for (var i =0; i<Object.keys(channels).length;i++){ channels[i].visible = false } var val = sel.active channels[val].visible = true /** if (val==0){ fig.title.text = 'confirm upper' chan1.visible = true chan2.visible = false //bg_channel = [z[0]] }else if (val==1){ fig.title.text = 'confirm lower' chan1.visible = false chan2.visible = true //bg_channel = [z[1]] } **/ """) layout = column(p1, select_celltype, select_channel) show(layout)
def create_layout(self): # create figure self.x_range = Range1d(start=self.model.map_extent[0], end=self.model.map_extent[2], bounds=None) self.y_range = Range1d(start=self.model.map_extent[1], end=self.model.map_extent[3], bounds=None) self.fig = Figure(tools='wheel_zoom,pan', x_range=self.x_range, lod_threshold=None, plot_width=self.model.plot_width, plot_height=self.model.plot_height, y_range=self.y_range) self.fig.min_border_top = 0 self.fig.min_border_bottom = 10 self.fig.min_border_left = 0 self.fig.min_border_right = 0 self.fig.axis.visible = False self.fig.xgrid.grid_line_color = None self.fig.ygrid.grid_line_color = None # add tiled basemap self.tile_source = WMTSTileSource(url=self.model.basemap) self.tile_renderer = TileRenderer(tile_source=self.tile_source) self.fig.renderers.append(self.tile_renderer) # add datashader layer self.image_source = ImageSource( url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) self.image_renderer = DynamicImageRenderer( image_source=self.image_source) self.fig.renderers.append(self.image_renderer) # add label layer self.label_source = WMTSTileSource(url=self.model.labels_url) self.label_renderer = TileRenderer(tile_source=self.label_source) self.fig.renderers.append(self.label_renderer) # Add a hover tool hover_layer = HoverLayer() hover_layer.field_name = self.model.field_title hover_layer.is_categorical = self.model.field in self.model.categorical_fields self.fig.renderers.append(hover_layer.renderer) self.fig.add_tools(hover_layer.tool) self.model.hover_layer = hover_layer self.model.legend_side_vbox = VBox() self.model.legend_bottom_vbox = VBox() # add ui components controls = [] axes_select = Select.create(name='Axes', options=self.model.axes) axes_select.on_change('value', self.on_axes_change) controls.append(axes_select) self.field_select = Select.create(name='Field', options=self.model.fields) self.field_select.on_change('value', self.on_field_change) controls.append(self.field_select) self.aggregate_select = Select.create( name='Aggregate', options=self.model.aggregate_functions) self.aggregate_select.on_change('value', self.on_aggregate_change) controls.append(self.aggregate_select) transfer_select = Select.create(name='Transfer Function', options=self.model.transfer_functions) transfer_select.on_change('value', self.on_transfer_function_change) controls.append(transfer_select) color_ramp_select = Select.create(name='Color Ramp', options=self.model.color_ramps) color_ramp_select.on_change('value', self.on_color_ramp_change) controls.append(color_ramp_select) spread_size_slider = Slider(title="Spread Size (px)", value=0, start=0, end=10, step=1) spread_size_slider.on_change('value', self.on_spread_size_change) controls.append(spread_size_slider) hover_size_slider = Slider(title="Hover Size (px)", value=8, start=4, end=30, step=1) hover_size_slider.on_change('value', self.on_hover_size_change) controls.append(hover_size_slider) controls.append(self.model.legend_side_vbox) # add map components basemap_select = Select.create(name='Basemap', value='Imagery', options=self.model.basemaps) basemap_select.on_change('value', self.on_basemap_change) image_opacity_slider = Slider(title="Opacity", value=100, start=0, end=100, step=1) image_opacity_slider.on_change('value', self.on_image_opacity_slider_change) basemap_opacity_slider = Slider(title="Basemap Opacity", value=100, start=0, end=100, step=1) basemap_opacity_slider.on_change('value', self.on_basemap_opacity_slider_change) show_labels_chk = CheckboxGroup(labels=["Show Labels"], active=[0]) show_labels_chk.on_click(self.on_labels_change) map_controls = [ basemap_select, basemap_opacity_slider, image_opacity_slider, show_labels_chk ] self.controls = VBox(width=200, height=600, children=controls) self.map_controls = HBox(width=self.fig.plot_width, children=map_controls) self.map_area = VBox(width=self.fig.plot_width, children=[ self.map_controls, self.fig, self.model.legend_bottom_vbox ]) self.layout = HBox(width=1366, children=[self.controls, self.map_area])
sports_choice = [ 'No preference', 'Dance and fitness', 'Outdoor', 'Water sports ', 'Martial arts ', 'Racquet sports', 'Ball team sports' ] div51 = Div(text="<i> Choose Sport </i>") select51 = Select(options=sports_choice, value=sports_choice[0]) select51.on_change('value', update) elect_choice = ['No preference', 'Technology', 'Creativity', 'Society'] div52 = Div(text="<i> Choose Elective </i>") select52 = Select(options=elect_choice, value=elect_choice[0]) select52.on_change('value', update) div53 = Div(text="<i> Additional Choices</i>") offer = ['Uniform', 'Extended day', 'Summer session', 'Weekend program'] checkbox52 = CheckboxGroup(labels=offer, active=[]) checkbox52.on_change('active', update) # 6) Gender div6 = Div(text="<b> Gender Rate </b>") slider61 = RangeSlider(start=0, end=100, value=(0, 100), step=1, title="% Male") slider61.on_change('value', update) slider62 = RangeSlider(start=0, end=100, value=(0, 100), step=1, title="% Female")
x_range=FactorRange(factors=source_bar.data['x']), plot_width=480, plot_height=400, y_range=(0, 1) ) #plot2.vbar(x=demography_age, top=list(demography_data.loc[demography_data['Location'] == state].values[0][1:-2]), width=0.7) glyph = VBar(x='x', top='y', bottom=0, width=.8, fill_color="#6599ed") plot2.add_glyph(source_bar, glyph) print(list(demography_data.loc[demography_data['Location'] == state].values[0][1:-2])) div_head = Div(text="""<h2>US vs states covid-19 spread plots</h2>""", width=500, height=50) div_explain = Div(text="""<h3>US plots(thinner lines and smaller dots) are normalized according to the population of the compared state</h3>""", width=300, height=50) div_us_pop = Div(text="""<br><br><br>Total population of US: """+f"{total_us_population:,d}", width=300, height=50) div_state_pop = Div(text="""<br>Total population of """+state+" : "+f"{state_population_dict[state]:,d}", width=300, height=50) checkbox_group = CheckboxGroup(labels=["positive", "recovered", "death", "positive increase", "death increase"], active=[0,1,2,3,4]) select_state = Select(title="Select State", value="Minnesota", options=states_fullname) #list(list(gp.groups.keys()))) def callbackselect_state(attr, old, new): try: div_state_pop.text = """<br>Total population of """+select_state.value+": "+f"{state_population_dict[select_state.value]:,d}" except: div_state_pop.text = """<br>Total population of """ + select_state.value + ": Not Available" try: #plot2.vbar(x=demography_age, top=list(demography_data.loc[demography_data['Location'] == select_state.value].values[0][1:-2]), width=0.7) source_bar.data={ 'x': demography_age, 'y': list(demography_data.loc[demography_data['Location'] == select_state.value].values[0][1:-2]) } glyph = VBar(x='x', top='y', bottom=0, width=.8, fill_color="#6599ed") plot2.add_glyph(source_bar, glyph)
def create_charts(cur, include_8888=False): " Create chart on each tab for 5 regions + super DC " tables = create_tables(cur, for_div=True, include_8888=include_8888) tabs = [] for title, code, seats in regions: # chart components p = figure(x_axis_label='滾動日期', y_axis_label='支持%' if include_8888 else '有效支持%', x_axis_type="datetime") candids = [] earliest_date, latest_date = None, None for n in range(1, 30): candid, redness, trend = get_trend(cur, code, n, include_8888) if not trend: continue earliest_date, latest_date = trend[0][0], trend[-1][0] colour = getcolour(redness) line = p.line([d for d, _ in trend], [p for _, p in trend], color=colour, line_width=2, line_alpha=0.9) label = p.text([trend[-1][0]], [trend[-1][1]], text=[candid.rsplit(None, 1)[-1]], text_align='right', text_alpha=0.9, text_baseline='bottom', text_color=colour, text_font_size="9pt", y_offset=0.25) candids.append([n, candid, colour, trend[-1][1], line, label]) if include_8888: candid, redness, trend = get_trend(cur, code, 8888, True) if not trend: continue earliest_date, latest_date = trend[0][0], trend[-1][0] line = p.line([d for d, _ in trend], [p for _, p in trend], color="#707070", line_width=2, line_alpha=0.9) label = p.text([trend[-1][0]], [trend[-1][1]], text=["未決定"], text_align='right', text_alpha=0.9, text_baseline='bottom', text_color="#707070", text_font_size="9pt", y_offset=0.25) candids.append([8888, "未決定", "#707070", trend[-1][1], line, label]) p.line([earliest_date, latest_date], [100.0 / seats, 100.0 / seats], line_dash=[6, 3], color="black", line_width=2, line_alpha=0.5) # control all_lines = [n for n, _ in enumerate(candids)] top_5 = [ n for _, n in sorted([(c[3], n) for n, c in enumerate(candids)], reverse=True)[:5] ] for n in all_lines: if n not in top_5: candids[n][-1].visible = candids[n][-2].visible = False customjs_params = [("line%d"%n, candid[-2]) for n,candid in enumerate(candids)] + \ [("label%d"%n, candid[-1]) for n,candid in enumerate(candids)] jscode = ''' var lines = [%s]; var labels = [%s]; for (var n=0; n<lines.length; n++) { lines[n].visible = (cb_obj.active.indexOf(n) >= 0); labels[n].visible = (cb_obj.active.indexOf(n) >= 0); };''' % (",".join("line%d" % n for n in all_lines), ",".join( "label%d" % n for n in all_lines)) checkbox = CheckboxGroup(labels=[ str(800 + c[0] if code == 'SuperDC' else c[0]) + ' ' + c[1] + ' ' + ("%.2f%%" % c[3]) for c in candids ], active=top_5) checkbox.callback = CustomJS(args=dict(customjs_params), code=jscode) # ranking table div = Div(text=tables[code], width=600) # layout and show layout = row(checkbox, p, div) tab = Panel(child=layout, title=title + "民調(" + str(seats) + '席)') tabs.append(tab) # build and return return Tabs(tabs=tabs)
def create_layout(self): # create figure self.x_range = Range1d(start=self.model.map_extent[0], end=self.model.map_extent[2], bounds=None) self.y_range = Range1d(start=self.model.map_extent[1], end=self.model.map_extent[3], bounds=None) self.fig = Figure(tools='wheel_zoom,pan', x_range=self.x_range, lod_threshold=None, plot_width=self.model.plot_width, plot_height=self.model.plot_height, y_range=self.y_range) self.fig.min_border_top = 0 self.fig.min_border_bottom = 10 self.fig.min_border_left = 0 self.fig.min_border_right = 0 self.fig.axis.visible = False self.fig.xgrid.grid_line_color = None self.fig.ygrid.grid_line_color = None # add tiled basemap self.tile_source = WMTSTileSource(url=self.model.basemap) self.tile_renderer = TileRenderer(tile_source=self.tile_source) self.fig.renderers.append(self.tile_renderer) # add datashader layer self.image_source = ImageSource(url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) self.image_renderer = DynamicImageRenderer(image_source=self.image_source) self.fig.renderers.append(self.image_renderer) # add label layer self.label_source = WMTSTileSource(url=self.model.labels_url) self.label_renderer = TileRenderer(tile_source=self.label_source) self.fig.renderers.append(self.label_renderer) # Add a hover tool hover_layer = HoverLayer() hover_layer.field_name = self.model.field_title hover_layer.is_categorical = self.model.field in self.model.categorical_fields self.fig.renderers.append(hover_layer.renderer) self.fig.add_tools(hover_layer.tool) self.model.hover_layer = hover_layer self.model.legend_side_vbox = VBox() self.model.legend_bottom_vbox = VBox() # add ui components controls = [] axes_select = Select.create(name='Axes', options=self.model.axes) axes_select.on_change('value', self.on_axes_change) controls.append(axes_select) self.field_select = Select.create(name='Field', options=self.model.fields) self.field_select.on_change('value', self.on_field_change) controls.append(self.field_select) self.aggregate_select = Select.create(name='Aggregate', options=self.model.aggregate_functions) self.aggregate_select.on_change('value', self.on_aggregate_change) controls.append(self.aggregate_select) transfer_select = Select.create(name='Transfer Function', options=self.model.transfer_functions) transfer_select.on_change('value', self.on_transfer_function_change) controls.append(transfer_select) color_ramp_select = Select.create(name='Color Ramp', options=self.model.color_ramps) color_ramp_select.on_change('value', self.on_color_ramp_change) controls.append(color_ramp_select) spread_size_slider = Slider(title="Spread Size (px)", value=0, start=0, end=10, step=1) spread_size_slider.on_change('value', self.on_spread_size_change) controls.append(spread_size_slider) hover_size_slider = Slider(title="Hover Size (px)", value=8, start=4, end=30, step=1) hover_size_slider.on_change('value', self.on_hover_size_change) controls.append(hover_size_slider) controls.append(self.model.legend_side_vbox) # add map components basemap_select = Select.create(name='Basemap', value='Imagery', options=self.model.basemaps) basemap_select.on_change('value', self.on_basemap_change) image_opacity_slider = Slider(title="Opacity", value=100, start=0, end=100, step=1) image_opacity_slider.on_change('value', self.on_image_opacity_slider_change) basemap_opacity_slider = Slider(title="Basemap Opacity", value=100, start=0, end=100, step=1) basemap_opacity_slider.on_change('value', self.on_basemap_opacity_slider_change) show_labels_chk = CheckboxGroup(labels=["Show Labels"], active=[0]) show_labels_chk.on_click(self.on_labels_change) map_controls = [basemap_select, basemap_opacity_slider, image_opacity_slider, show_labels_chk] self.controls = VBox(width=200, height=600, children=controls) self.map_controls = HBox(width=self.fig.plot_width, children=map_controls) self.map_area = VBox(width=self.fig.plot_width, children=[self.map_controls, self.fig, self.model.legend_bottom_vbox]) self.layout = HBox(width=1366, children=[self.controls, self.map_area])
class Scatter: # X axis choices AXIS_MAP = { "Tempo": "tempo", "Duration (sec)": "duration_s", "Danceability": "danceability", "Energy": "energy", "Loudness": "loudness", "Speechiness": "speechiness", "Acousticness": "acousticness", "Instrumentalness": "instrumentalness", "Liveness": "liveness", "Valence": "valence" } # Tooltips for circle glyphs CIRC_TOOLTIPS = [("Track", "@track_name"), ("Artist", "@artist_name"), ("Times Played", "@count")] def __init__(self, df: pd.DataFrame): # Initialize data sources for scatter plot and regression line self.backing_df = df self.circ_source = ColumnDataSource({ 'x': [], 'y': [], 'track_name': [], 'artist_name': [], 'count': [], 'circle_size': [] }) self.line_source = ColumnDataSource({'x': [], 'y_pred': []}) # Initialize widgets self.x_axis = Select(title="X Axis", options=list(self.AXIS_MAP.keys()), value="Tempo") self.y_axis = Select(title="Y Axis", options=list(self.AXIS_MAP.keys()), value="Duration (sec)") time_start = datetime.datetime(1970, 1, 1, hour=0, minute=0, second=0) time_end = datetime.datetime(1970, 1, 1, hour=23, minute=59, second=59) start_date = min(self.backing_df['date_played']) start_dt = datetime.datetime(year=start_date.year, month=start_date.month, day=start_date.day, hour=0, minute=0, second=0) end_date = max(self.backing_df['date_played']) end_dt = datetime.datetime(year=end_date.year, month=end_date.month, day=end_date.day, hour=23, minute=59, second=59) date_step_size = 1000 * 60 * 60 * 24 # Step size of 1 day in ms self.date_slider = DateRangeSlider(title="Date Range", start=start_dt, end=end_dt, value=(start_dt, end_dt), format="%d %b %Y", step=date_step_size) time_step_size = 1000 * 60 * 30 # 30 minues in ms self.time_slider = DateRangeSlider(title="Time Range", value=(time_start, time_end), start=time_start, end=time_end, format="%X", step=time_step_size) self.track_name = TextInput(title="Song name includes") self.artist_name = TextInput(title="Artist name includes") self.reg_line_check = CheckboxGroup(labels=["Add Regression Line"], active=[]) # Create the hover tools self.points_hover = HoverTool(tooltips=self.CIRC_TOOLTIPS, names=["circles"]) self.line_hover = HoverTool(tooltips=[], names=["reg_line"]) # Create the scatter plot and regression line self.plot = figure(title="Scatter", plot_height=450, plot_width=800, tools=[self.points_hover, self.line_hover]) self.plot.circle(x="x", y="y", source=self.circ_source, size="circle_size", fill_alpha=0.6, name="circles") self.reg_line = self.plot.line(x='x', y='y_pred', source=self.line_source, color='#FFAF87', name="reg_line") self.layout = row( column(self.x_axis, self.y_axis, self.date_slider, self.time_slider, self.track_name, self.artist_name, self.reg_line_check), self.plot) # Fill data and create events for on change self.update() self.on_change() def on_change(self): """ Creates on change events for all widgets in the scatter plot. """ widgets = [ self.x_axis, self.y_axis, self.date_slider, self.time_slider, self.track_name, self.artist_name ] for control in widgets: control.on_change("value", lambda attr, old, new: self.update()) self.reg_line_check.on_change("active", lambda attr, old, new: self.update()) def update(self): """ Updates the data source and regression line based on current values of all widgets. """ new_df = self.get_selected() # Get number of individual plays and then remove duplicate tracks for plotting num_plays = len(new_df) new_df.drop_duplicates(subset='track_id', inplace=True) # Choose the x and y axis x_name = self.AXIS_MAP[self.x_axis.value] y_name = self.AXIS_MAP[self.y_axis.value] self.plot.xaxis.axis_label = self.x_axis.value self.plot.yaxis.axis_label = self.y_axis.value # Calculate correlation coefficient between x and y axis corr = np.corrcoef(new_df[x_name], new_df[y_name])[0, 1] if not new_df.empty else 0 self.plot.title.text = f"{num_plays} track plays selected, correlation: {round(corr, 2)}" # Provide the new selected data to the Data Source data_dict = { 'x': new_df[x_name], 'y': new_df[y_name], 'track_name': new_df['song_name'], 'artist_name': new_df['artist_name'], 'count': new_df['counts'], 'circle_size': new_df['circle_size'] } self.circ_source.data = data_dict # Update the regression line if more than one track is selected if len(new_df) <= 1: self.reg_line.visible = False else: x = sm.add_constant(new_df[x_name]) reg_model = sm.OLS(new_df[y_name], x) results = reg_model.fit() y_pred = list( map( lambda x: results.params.iloc[1] * x + results.params.iloc[ 0], new_df[x_name])) reg_data_dict = {'x': new_df[x_name], 'y_pred': y_pred} self.line_source.data = reg_data_dict # Update hover tool for regression line self.line_hover.tooltips = [( "Y=", f"{round(results.params.iloc[1], 2)}x + {round(results.params.iloc[0], 2)}" ), ("R\u00b2", str(round(results.rsquared, 2)))] self.reg_line.visible = (len(self.reg_line_check.active) > 0) def get_selected(self): """ Filter data based on widget values. Returns filtered DataFrame """ df = self.backing_df if not self.track_name.value.isspace(): df = df[df['song_name'].str.lower().str.contains( self.track_name.value.strip().lower())] if not self.artist_name.value.isspace(): df = df[df['artist_name'].str.lower().str.contains( self.artist_name.value.strip().lower())] # Filter by date played date_begin = pd.to_datetime(self.date_slider.value[0], unit='ms') date_end = pd.to_datetime(self.date_slider.value[1], unit='ms') df = df[(date_begin <= df['date_played']) & (df['date_played'] <= date_end)] # Filter by time played time_begin = pd.to_datetime(self.time_slider.value[0], unit='ms').time() time_end = pd.to_datetime(self.time_slider.value[1], unit='ms').time() df = df[(time_begin <= df['time_played']) & (df['time_played'] <= time_end)] # Join the counts and circle size columns to the df df = self.get_selected_counts(df) return df def get_selected_counts(self, df): """ If no tracks are selected, simply join empty columns for counts and circle_size. Otherwise, compute the counts and circle sizes, and join those columns to the df. Arguemnts: -df : filtered DataFrame Returns filtered DataFrame with additional columns for counts and circle_size. """ if df.empty: df['counts'] = pd.Series([]) df['circle_size'] = pd.Series([]) return df df_counts = df.groupby(['song_name', 'artist_name' ]).size().reset_index(name='counts') df_counts = df_counts.apply(self.apply_circle_sizes, axis=1) return pd.merge(df, df_counts, on=['song_name', 'artist_name'], how='left') def apply_circle_sizes(self, row): """ Determines the size of each circle based on the number of times that track has been played. """ if row['counts'] == 1: row['circle_size'] = 5 elif 1 < row['counts'] <= 5: row['circle_size'] = 7 elif row['counts'] > 5: row['circle_size'] = 10 return row
disabled_button = Button(label="Button (disabled) - still has click event", button_type="primary", disabled=True) toggle = Toggle(label="Toggle button", button_type="success") menu = [("Item 1", "item_1_value"), ("Item 2", "item_2_value"), None, ("Item 3", "item_3_value")] dropdown = Dropdown(label="Dropdown button", button_type="warning", menu=menu) dropdown_split = Dropdown(label="Split button", button_type="danger", menu=menu, split=True) checkbox_group = CheckboxGroup(labels=["Option 1", "Option 2", "Option 3"], active=[0, 1]) radio_group = RadioGroup(labels=["Option 1", "Option 2", "Option 3"], active=0) checkbox_button_group = CheckboxButtonGroup( labels=["Option 1", "Option 2", "Option 3"], active=[0, 1]) radio_button_group = RadioButtonGroup( labels=["Option 1", "Option 2", "Option 3"], active=0) checkbox_button_group_vertical = CheckboxButtonGroup( labels=["Option 1", "Option 2", "Option 3"], active=[0, 1], orientation="vertical") radio_button_group_vertical = RadioButtonGroup( labels=["Option 1", "Option 2", "Option 3"], active=0, orientation="vertical")
def create_layout(self): # create figure self.x_range = Range1d(start=self.model.map_extent[0], end=self.model.map_extent[2], bounds=None) self.y_range = Range1d(start=self.model.map_extent[1], end=self.model.map_extent[3], bounds=None) self.fig = Figure(tools='wheel_zoom,pan', x_range=self.x_range, y_range=self.y_range) self.fig.plot_height = 560 self.fig.plot_width = 800 self.fig.axis.visible = False # add tiled basemap self.tile_source = WMTSTileSource(url=self.model.basemap) self.tile_renderer = TileRenderer(tile_source=self.tile_source) self.fig.renderers.append(self.tile_renderer) # add datashader layer self.image_source = ImageSource( url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) self.image_renderer = DynamicImageRenderer( image_source=self.image_source) self.fig.renderers.append(self.image_renderer) # add label layer self.label_source = WMTSTileSource(url=self.model.labels_url) self.label_renderer = TileRenderer(tile_source=self.label_source) self.fig.renderers.append(self.label_renderer) # add ui components axes_select = Select.create(name='Axes', options=self.model.axes) axes_select.on_change('value', self.on_axes_change) field_select = Select.create(name='Field', options=self.model.fields) field_select.on_change('value', self.on_field_change) aggregate_select = Select.create( name='Aggregate', options=self.model.aggregate_functions) aggregate_select.on_change('value', self.on_aggregate_change) transfer_select = Select.create(name='Transfer Function', options=self.model.transfer_functions) transfer_select.on_change('value', self.on_transfer_function_change) basemap_select = Select.create(name='Basemap', value='Toner', options=self.model.basemaps) basemap_select.on_change('value', self.on_basemap_change) image_opacity_slider = Slider(title="Opacity", value=100, start=0, end=100, step=1) image_opacity_slider.on_change('value', self.on_image_opacity_slider_change) basemap_opacity_slider = Slider(title="Basemap Opacity", value=100, start=0, end=100, step=1) basemap_opacity_slider.on_change('value', self.on_basemap_opacity_slider_change) show_labels_chk = CheckboxGroup(labels=["Show Labels"], active=[0]) show_labels_chk.on_click(self.on_labels_change) controls = [ axes_select, field_select, aggregate_select, transfer_select ] map_controls = [ basemap_select, basemap_opacity_slider, image_opacity_slider, show_labels_chk ] self.controls = VBox(width=200, height=600, children=controls) self.map_controls = HBox(width=self.fig.plot_width, children=map_controls) self.map_area = VBox(width=self.fig.plot_width, children=[self.map_controls, self.fig]) self.layout = HBox(width=1024, children=[self.controls, self.map_area])
line_width=3) layout.children[0] = p kjonnselect = Select(title="Kjønn", value="Begge kjønn", options=sorted(set(df['kjonn']))) fullfselect = Select(title="Fullføringsgrad", value="I alt", options=sorted(set(df['fullforingsgrad']))) studretnselect = Select(title="Studieretning", value="Alle studieretninger/utdanningsprogram", options=sorted( set(df['studieretning_utdanningsprogram']))) prosent = CheckboxGroup(labels=["Vis prosent"], active=[]) kjonnselect.on_change('value', callback) fullfselect.on_change('value', callback) studretnselect.on_change('value', callback) prosent.on_change('active', callback) p = figure(plot_height=400, plot_width=950, tooltips=TOOLTIPS, sizing_mode='scale_width') p.xaxis.axis_label = "Skoleår" p.yaxis.axis_label = andelprosent_label(prosent) # Apply list on grouped dataframe returns list of lists - must be run on each variable. df2 = df.loc[(df['kjonn'] == kjonnselect.value)
def create_layout(self): # create figure self.x_range = Range1d(start=self.model.map_extent[0], end=self.model.map_extent[2], bounds=None) self.y_range = Range1d(start=self.model.map_extent[1], end=self.model.map_extent[3], bounds=None) self.fig = Figure( tools="wheel_zoom,pan", x_range=self.x_range, lod_threshold=None, plot_width=self.model.plot_width, plot_height=self.model.plot_height, background_fill_color="black", y_range=self.y_range, ) self.fig.min_border_top = 0 self.fig.min_border_bottom = 10 self.fig.min_border_left = 0 self.fig.min_border_right = 0 self.fig.axis.visible = False self.fig.xgrid.grid_line_color = None self.fig.ygrid.grid_line_color = None # add tiled basemap self.tile_source = WMTSTileSource(url=self.model.basemap) self.tile_renderer = TileRenderer(tile_source=self.tile_source) self.fig.renderers.append(self.tile_renderer) # add datashader layer self.image_source = ImageSource(url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) self.image_renderer = DynamicImageRenderer(image_source=self.image_source) self.fig.renderers.append(self.image_renderer) # add label layer self.label_source = WMTSTileSource(url=self.model.labels_url) self.label_renderer = TileRenderer(tile_source=self.label_source) self.fig.renderers.append(self.label_renderer) # Add placeholder for legends (temporarily disabled) # self.model.legend_side_vbox = VBox() # self.model.legend_bottom_vbox = VBox() # add ui components controls = [] axes_select = Select.create(name="Axes", options=self.model.axes) axes_select.on_change("value", self.on_axes_change) controls.append(axes_select) self.field_select = Select.create(name="Field", options=self.model.fields) self.field_select.on_change("value", self.on_field_change) controls.append(self.field_select) self.aggregate_select = Select.create(name="Aggregate", options=self.model.aggregate_functions) self.aggregate_select.on_change("value", self.on_aggregate_change) controls.append(self.aggregate_select) transfer_select = Select.create(name="Transfer Function", options=self.model.transfer_functions) transfer_select.on_change("value", self.on_transfer_function_change) controls.append(transfer_select) color_ramp_select = Select.create(name="Color Ramp", options=self.model.color_ramps) color_ramp_select.on_change("value", self.on_color_ramp_change) controls.append(color_ramp_select) spread_size_slider = Slider(title="Spread Size (px)", value=0, start=0, end=10, step=1) spread_size_slider.on_change("value", self.on_spread_size_change) controls.append(spread_size_slider) hover_size_slider = Slider(title="Hover Size (px)", value=8, start=4, end=30, step=1) hover_size_slider.on_change("value", self.on_hover_size_change) controls.append(hover_size_slider) # legends (temporarily disabled) # controls.append(self.model.legend_side_vbox) # add map components basemap_select = Select.create(name="Basemap", value="Imagery", options=self.model.basemaps) basemap_select.on_change("value", self.on_basemap_change) image_opacity_slider = Slider(title="Opacity", value=100, start=0, end=100, step=1) image_opacity_slider.on_change("value", self.on_image_opacity_slider_change) basemap_opacity_slider = Slider(title="Basemap Opacity", value=100, start=0, end=100, step=1) basemap_opacity_slider.on_change("value", self.on_basemap_opacity_slider_change) show_labels_chk = CheckboxGroup(labels=["Show Labels"], active=[0]) show_labels_chk.on_click(self.on_labels_change) map_controls = [basemap_select, basemap_opacity_slider, image_opacity_slider, show_labels_chk] self.controls = VBox(height=600, children=controls) self.map_controls = HBox(width=self.fig.plot_width, children=map_controls) # legends (temporarily disabled) self.map_area = VBox(width=900, height=600, children=[self.map_controls, self.fig]) self.layout = HBox(width=1300, height=600, children=[self.controls, self.map_area]) self.model.fig = self.fig self.model.update_hover()
def __init__(self, df: pd.DataFrame): # Initialize data sources for scatter plot and regression line self.backing_df = df self.circ_source = ColumnDataSource({ 'x': [], 'y': [], 'track_name': [], 'artist_name': [], 'count': [], 'circle_size': [] }) self.line_source = ColumnDataSource({'x': [], 'y_pred': []}) # Initialize widgets self.x_axis = Select(title="X Axis", options=list(self.AXIS_MAP.keys()), value="Tempo") self.y_axis = Select(title="Y Axis", options=list(self.AXIS_MAP.keys()), value="Duration (sec)") time_start = datetime.datetime(1970, 1, 1, hour=0, minute=0, second=0) time_end = datetime.datetime(1970, 1, 1, hour=23, minute=59, second=59) start_date = min(self.backing_df['date_played']) start_dt = datetime.datetime(year=start_date.year, month=start_date.month, day=start_date.day, hour=0, minute=0, second=0) end_date = max(self.backing_df['date_played']) end_dt = datetime.datetime(year=end_date.year, month=end_date.month, day=end_date.day, hour=23, minute=59, second=59) date_step_size = 1000 * 60 * 60 * 24 # Step size of 1 day in ms self.date_slider = DateRangeSlider(title="Date Range", start=start_dt, end=end_dt, value=(start_dt, end_dt), format="%d %b %Y", step=date_step_size) time_step_size = 1000 * 60 * 30 # 30 minues in ms self.time_slider = DateRangeSlider(title="Time Range", value=(time_start, time_end), start=time_start, end=time_end, format="%X", step=time_step_size) self.track_name = TextInput(title="Song name includes") self.artist_name = TextInput(title="Artist name includes") self.reg_line_check = CheckboxGroup(labels=["Add Regression Line"], active=[]) # Create the hover tools self.points_hover = HoverTool(tooltips=self.CIRC_TOOLTIPS, names=["circles"]) self.line_hover = HoverTool(tooltips=[], names=["reg_line"]) # Create the scatter plot and regression line self.plot = figure(title="Scatter", plot_height=450, plot_width=800, tools=[self.points_hover, self.line_hover]) self.plot.circle(x="x", y="y", source=self.circ_source, size="circle_size", fill_alpha=0.6, name="circles") self.reg_line = self.plot.line(x='x', y='y_pred', source=self.line_source, color='#FFAF87', name="reg_line") self.layout = row( column(self.x_axis, self.y_axis, self.date_slider, self.time_slider, self.track_name, self.artist_name, self.reg_line_check), self.plot) # Fill data and create events for on change self.update() self.on_change()
def __init__( self, options, name, data, data_types, type_categories, ): """ Configuration options: - default/X Axis: name - default/Y Axis: name - default/Group by: name - default/Exclude: name1;name2;...;nameN - default/discard_axis_x: name1;name2;...;nameN - default/discard_axis_y: name1;name2;...;nameN - default/discard_group_by: name1;name2;...;nameN - default/discard_exclude_max_values: number. the maximum number of excluded values for a category to be shown. If an exclusion category has more values, no values added for this category - default/number_of_columns: int Args: options: name: data: data_types: type_categories: """ self.discard_group_by = safe_lookup(options.config, name, 'default', 'discard_group_by', default='').split(';') self.discard_axis_x = safe_lookup(options.config, name, 'default', 'discard_axis_x', default='').split(';') self.discard_axis_y = safe_lookup(options.config, name, 'default', 'discard_axis_y', default='').split(';') self.discard_exclude_max_values = int(safe_lookup(options.config, name, 'default', 'discard_exclude_max_values', default='15')) self.group_by = CheckboxGroup() self.y_axis = CheckboxGroup() self.x_axis = RadioGroup() self.exclude = CheckboxGroup() controls_list = [ PreText(text='Group by:'), self.group_by, PreText(text='Y Axis:'), self.y_axis, PreText(text='X Axis:'), self.x_axis, PreText(text='Exclude:'), self.exclude, ] controls = column(controls_list, name='PanelDataGraph_controls') controls.sizing_mode = "fixed" self.update_controls(options, name, data, data_types, type_categories) self.options = options self.layout = row(controls, sizing_mode='stretch_both') self.last_data = data self.last_data_types = data_types self.last_type_categories = type_categories self.last_figs_by_group = {} self.number_of_columns = int(safe_lookup(options.config, name, 'default', 'number_of_columns', default='2')) for control in controls_list: if hasattr(control, 'active'): control.on_change('active', lambda attr, old, new: self._update_and_clear_plots()) self._update() super().__init__(ui=Panel(child=self.layout, title=name))
# Import CheckboxGroup, RadioGroup, Toggle from bokeh.models from bokeh.models import CheckboxGroup, RadioGroup, Toggle from bokeh.io import curdoc from bokeh.plotting import figure from bokeh.layouts import widgetbox # Add a Toggle: toggle toggle = Toggle(label='Toggle button', button_type='success') # Add a CheckboxGroup: checkbox checkbox = CheckboxGroup(labels=['Option 1', 'Option 2', 'Option 3']) # Add a RadioGroup: radio radio = RadioGroup(labels=['Option 1', 'Option 2', 'Option 3']) # Add widgetbox(toggle, checkbox, radio) to the current document curdoc().add_root(widgetbox(toggle, checkbox, radio))
def candlestick_plot(): def obv_indicator(data): res = talib.OBV(data.close.values, data.volume.values) return res def rsi_indicator(data): res = talib.RSI(data.close.values, timeperiod=14) return res def cci_indicator(data): res = talib.CCI(data.high.values, data.low.values, data.close.values, timeperiod=14) return res def technical_indicator(data, indicator): if indicator == 'CCI': data['tech'] = cci_indicator(data) elif indicator == 'RSI': data['tech'] = rsi_indicator(data) else: data['tech'] = obv_indicator(data) return data def load_data(obid, start, end, freq='1d'): print('running....') data = get_price(obid, start, end, freqency=freq).reset_index() data['pct_change'] = data['close'].pct_change() # data.dropna(inplace=True) data['pct_change'] = data['pct_change'].apply(lambda x: str(round(x * 100, 2)) + '%') data['index'] = list(np.arange(len(data))) data['date'] = data['date'].apply(lambda x: x.strftime("%Y%m%d")) return data def moving_average(data, selection): selection_mapping = {k: int(k.split('_')[-1]) for k in selection} for k, v in selection_mapping.items(): data[k] = data['close'].rolling(window=v).mean() return data def update_lines(attr, old, new): line_0.visible = 0 in average_selection.active line_1.visible = 1 in average_selection.active line_2.visible = 2 in average_selection.active line_3.visible = 3 in average_selection.active line_4.visible = 4 in average_selection.active line_5.visible = 5 in average_selection.active def update_plot(attr, old, new): indicator = indicator_selection.value new_data = technical_indicator(data, indicator) new_source = ColumnDataSource(new_data) source.data.update(new_source.data) def update_data(): # global obid, start, end obid = order_book_id.value start = start_date.value end = end_date.value # 提取数据,均线根据选取与否进行添加 new_data = load_data(obid, start, end) new_data_1 = moving_average(new_data, average_labels) new_data_2 = technical_indicator(new_data, indicator_selection.value) new_source = ColumnDataSource(new_data_2) new_source_1 = ColumnDataSource(new_data_1) source.data.update(new_source.data) source_1.data.update(new_source_1.data) inc = new_data.close >= new_data.open dec = new_data.close < new_data.open inc_source.data = inc_source.from_df(new_data_2.loc[inc]) dec_source.data = dec_source.from_df(new_data_2.loc[dec]) p.title.text = instruments(obid).symbol p.x_range.end = len(new_data) + 1 p2.xaxis.major_label_overrides = {i: date for i, date in enumerate(new_data['date'])} today = datetime.now().date() average_labels = ["MA_5", "MA_10", "MA_20", 'MA_30', 'MA_60', 'MA_120'] average_selection = CheckboxGroup(labels=average_labels, active=[0, 1, 2, 3, 4, 5, 6]) indicator_selection = Select(title='TechnicalIndicator', value='RSI', options=['OBV', 'RSI', 'CCI']) order_book_id = TextInput(title='StockCode', value='002916.XSHE') symbol = instruments(order_book_id.value).symbol start_date = DatePicker(title="StartDate", value='2018-01-01', min_date='2015-01-01', max_date=today) end_date = DatePicker(title="EndDate", value=today, min_date=start_date.value, max_date=today) # labels = [average_selection.labels[i] for i in average_selection.active] data = load_data(order_book_id.value, start_date.value, end_date.value) # 均线计算 data_1 = moving_average(data, average_labels) # 计算各种长度的均线 # 技术指标计算 data_2 = technical_indicator(data, indicator_selection.value) source = ColumnDataSource(data_2) source_1 = ColumnDataSource(data_1) inc = data.close >= data.open dec = data.open > data.close inc_source = ColumnDataSource(data_2.loc[inc]) dec_source = ColumnDataSource(data_2.loc[dec]) TOOLS = 'save, pan, box_zoom, reset, wheel_zoom' hover = HoverTool(tooltips=[('date', '@date'), ('open', '@open'), ('high', '@high'), ('low', '@low'), ('close', '@close'), ('pct_change', "@pct_change") ] ) length = len(data) p = figure(plot_width=1000, plot_height=500, title='{}'.format(symbol), tools=TOOLS, x_range=(0, length + 1)) p.xaxis.visible = False # 隐藏x-axis p.min_border_bottom = 0 # 均线图 line_0 = p.line(x='index', y='MA_5', source=source_1, color=Spectral6[5]) line_1 = p.line(x='index', y='MA_10', source=source_1, color=Spectral6[4]) line_2 = p.line(x='index', y='MA_20', source=source_1, color=Spectral6[3]) line_3 = p.line(x='index', y='MA_30', source=source_1, color=Spectral6[2]) line_4 = p.line(x='index', y='MA_60', source=source_1, color=Spectral6[1]) line_5 = p.line(x='index', y='MA_120', source=source_1, color=Spectral6[0]) p.segment(x0='index', y0='high', x1='index', y1='low', color='red', source=inc_source) p.segment(x0='index', y0='high', x1='index', y1='low', color='green', source=dec_source) p.vbar('index', 0.5, 'open', 'close', fill_color='red', line_color='red', source=inc_source, hover_fill_alpha=0.5) p.vbar('index', 0.5, 'open', 'close', fill_color='green', line_color='green', source=dec_source, hover_fill_alpha=0.5) p.add_tools(hover) p1 = figure(plot_width=p.plot_width, plot_height=200, x_range=p.x_range, toolbar_location=None) p1.vbar('index', 0.5, 0, 'volume', color='red', source=inc_source) p1.vbar('index', 0.5, 0, 'volume', color='green', source=dec_source) p1.xaxis.visible = False p2 = figure(plot_width=p.plot_width, plot_height=p1.plot_height, x_range=p.x_range, toolbar_location=None) p2.line(x='index', y='tech', source=source) p2.xaxis.major_label_overrides = {i: date for i, date in enumerate(data['date'])} p2.xaxis.major_label_orientation = pi / 4 p2.min_border_bottom = 0 button = Button(label="ClickToChange", button_type="success") button.on_click(update_data) average_selection.inline = True average_selection.width = 500 average_selection.on_change('active', update_lines) indicator_selection.on_change('value', update_plot) widgets = column(row(order_book_id, start_date, end_date, button), row(indicator_selection, average_selection)) layouts = column(widgets, p, p1, p2) # doc.add_root(pp) # make a layout tab = Panel(child=layouts, title='StockPrice') return tab
def create_layout(self): # create figure self.x_range = Range1d(start=self.model.map_extent[0], end=self.model.map_extent[2], bounds=None) self.y_range = Range1d(start=self.model.map_extent[1], end=self.model.map_extent[3], bounds=None) self.fig = Figure(tools='wheel_zoom,pan', x_range=self.x_range, lod_threshold=None, plot_width=self.model.plot_width, plot_height=self.model.plot_height, background_fill_color='black', y_range=self.y_range) self.fig.min_border_top = 0 self.fig.min_border_bottom = 10 self.fig.min_border_left = 0 self.fig.min_border_right = 0 self.fig.axis.visible = False self.fig.xgrid.grid_line_color = None self.fig.ygrid.grid_line_color = None # add tiled basemap self.tile_source = WMTSTileSource(url=self.model.basemap) self.tile_renderer = TileRenderer(tile_source=self.tile_source) self.fig.renderers.append(self.tile_renderer) # add datashader layer self.image_source = ImageSource( url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) self.image_renderer = DynamicImageRenderer( image_source=self.image_source) self.fig.renderers.append(self.image_renderer) # add label layer self.label_source = WMTSTileSource(url=self.model.labels_url) self.label_renderer = TileRenderer(tile_source=self.label_source) self.fig.renderers.append(self.label_renderer) # Add placeholder for legends (temporarily disabled) # self.model.legend_side_vbox = Column() # self.model.legend_bottom_vbox = Column() # add ui components controls = [] axes_select = Select(name='Axes', options=list(self.model.axes.keys())) axes_select.on_change('value', self.on_axes_change) controls.append(axes_select) self.field_select = Select(name='Field', options=list(self.model.fields.keys())) self.field_select.on_change('value', self.on_field_change) controls.append(self.field_select) self.aggregate_select = Select( name='Aggregate', options=list(self.model.aggregate_functions.keys())) self.aggregate_select.on_change('value', self.on_aggregate_change) controls.append(self.aggregate_select) transfer_select = Select(name='Transfer Function', options=list( self.model.transfer_functions.keys())) transfer_select.on_change('value', self.on_transfer_function_change) controls.append(transfer_select) color_ramp_select = Select(name='Color Ramp', options=list(self.model.color_ramps.keys())) color_ramp_select.on_change('value', self.on_color_ramp_change) controls.append(color_ramp_select) spread_size_slider = Slider(title="Spread Size (px)", value=0, start=0, end=10, step=1) spread_size_slider.on_change('value', self.on_spread_size_change) controls.append(spread_size_slider) # hover (temporarily disabled) #hover_size_slider = Slider(title="Hover Size (px)", value=8, start=4, # end=30, step=1) #hover_size_slider.on_change('value', self.on_hover_size_change) #controls.append(hover_size_slider) # legends (temporarily disabled) # controls.append(self.model.legend_side_vbox) # add map components basemap_select = Select(name='Basemap', value='Imagery', options=list(self.model.basemaps.keys())) basemap_select.on_change('value', self.on_basemap_change) image_opacity_slider = Slider(title="Opacity", value=100, start=0, end=100, step=1) image_opacity_slider.on_change('value', self.on_image_opacity_slider_change) basemap_opacity_slider = Slider(title="Basemap Opacity", value=100, start=0, end=100, step=1) basemap_opacity_slider.on_change('value', self.on_basemap_opacity_slider_change) show_labels_chk = CheckboxGroup(labels=["Show Labels"], active=[0]) show_labels_chk.on_click(self.on_labels_change) map_controls = [ basemap_select, basemap_opacity_slider, image_opacity_slider, show_labels_chk ] self.controls = Column(height=600, children=controls) self.map_controls = Row(width=self.fig.plot_width, children=map_controls) # legends (temporarily disabled) self.map_area = Column(width=900, height=600, children=[self.map_controls, self.fig]) self.layout = Row(width=1300, height=600, children=[self.controls, self.map_area]) self.model.fig = self.fig self.model.update_hover()
def create_layout(self): # create figure self.x_range = Range1d(start=self.model.map_extent[0], end=self.model.map_extent[2], bounds=None) self.y_range = Range1d(start=self.model.map_extent[1], end=self.model.map_extent[3], bounds=None) self.fig = Figure(tools='wheel_zoom,pan', x_range=self.x_range, lod_threshold=None, plot_width=self.model.plot_width, plot_height=self.model.plot_height, y_range=self.y_range) self.fig.min_border_top = 0 self.fig.min_border_bottom = 10 self.fig.min_border_left = 0 self.fig.min_border_right = 0 self.fig.axis.visible = False self.fig.xgrid.grid_line_color = None self.fig.ygrid.grid_line_color = None # add tiled basemap self.tile_source = WMTSTileSource(url=self.model.basemap) self.tile_renderer = TileRenderer(tile_source=self.tile_source) self.fig.renderers.append(self.tile_renderer) # add datashader layer self.image_source = ImageSource(url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) self.image_renderer = DynamicImageRenderer(image_source=self.image_source) self.fig.renderers.append(self.image_renderer) # add label layer self.label_source = WMTSTileSource(url=self.model.labels_url) self.label_renderer = TileRenderer(tile_source=self.label_source) self.fig.renderers.append(self.label_renderer) # Add a hover tool self.invisible_square = Square(x='x', y='y', fill_color=None, line_color=None, size=self.model.hover_size) self.visible_square = Square(x='x', y='y', fill_color='#79DCDE', fill_alpha=.5, line_color='#79DCDE', line_alpha=1, size=self.model.hover_size) cr = self.fig.add_glyph(self.model.hover_source, self.invisible_square, selection_glyph=self.visible_square, nonselection_glyph=self.invisible_square) code = "source.set('selected', cb_data['index']);" callback = CustomJS(args={'source': self.model.hover_source}, code=code) self.model.hover_tool = HoverTool(tooltips=[(self.model.fields.keys()[0], "@value")], callback=callback, renderers=[cr], mode='mouse') self.fig.add_tools(self.model.hover_tool) self.model.legend_side_vbox = VBox() self.model.legend_bottom_vbox = VBox() # add ui components controls = [] axes_select = Select.create(name='Axes', options=self.model.axes) axes_select.on_change('value', self.on_axes_change) controls.append(axes_select) self.field_select = Select.create(name='Field', options=self.model.fields) self.field_select.on_change('value', self.on_field_change) controls.append(self.field_select) self.aggregate_select = Select.create(name='Aggregate', options=self.model.aggregate_functions) self.aggregate_select.on_change('value', self.on_aggregate_change) controls.append(self.aggregate_select) transfer_select = Select.create(name='Transfer Function', options=self.model.transfer_functions) transfer_select.on_change('value', self.on_transfer_function_change) controls.append(transfer_select) color_ramp_select = Select.create(name='Color Ramp', options=self.model.color_ramps) color_ramp_select.on_change('value', self.on_color_ramp_change) controls.append(color_ramp_select) spread_size_slider = Slider(title="Spread Size (px)", value=0, start=0, end=10, step=1) spread_size_slider.on_change('value', self.on_spread_size_change) controls.append(spread_size_slider) hover_size_slider = Slider(title="Hover Size (px)", value=8, start=4, end=30, step=1) hover_size_slider.on_change('value', self.on_hover_size_change) controls.append(hover_size_slider) controls.append(self.model.legend_side_vbox) # add map components basemap_select = Select.create(name='Basemap', value='Imagery', options=self.model.basemaps) basemap_select.on_change('value', self.on_basemap_change) image_opacity_slider = Slider(title="Opacity", value=100, start=0, end=100, step=1) image_opacity_slider.on_change('value', self.on_image_opacity_slider_change) basemap_opacity_slider = Slider(title="Basemap Opacity", value=100, start=0, end=100, step=1) basemap_opacity_slider.on_change('value', self.on_basemap_opacity_slider_change) show_labels_chk = CheckboxGroup(labels=["Show Labels"], active=[0]) show_labels_chk.on_click(self.on_labels_change) map_controls = [basemap_select, basemap_opacity_slider, image_opacity_slider, show_labels_chk] self.controls = VBox(width=200, height=600, children=controls) self.map_controls = HBox(width=self.fig.plot_width, children=map_controls) self.map_area = VBox(width=self.fig.plot_width, children=[self.map_controls, self.fig, self.model.legend_bottom_vbox]) self.layout = HBox(width=1366, children=[self.controls, self.map_area])
import numpy as np from bokeh.io import curdoc from bokeh.layouts import row from bokeh.palettes import Viridis3 from bokeh.plotting import figure from bokeh.models import CheckboxGroup p = figure() props = dict(line_width=4, line_alpha=0.7) x = np.linspace(0, 4 * np.pi, 100) l0 = p.line(x, np.sin(x), color=Viridis3[0], legend="Line 0", **props) l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], legend="Line 1", **props) l2 = p.line(x, np.tan(x), color=Viridis3[2], legend="Line 2", **props) checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"], active=[0, 1, 2], width=100) def update(attr, old, new): l0.visible = 0 in checkbox.active l1.visible = 1 in checkbox.active l2.visible = 2 in checkbox.active checkbox.on_change('active', update) layout = row(checkbox, p) curdoc().add_root(layout)
def setup_widgets(self): # Generation of selectable items # Dict contains all inspectable runs (maps display strings to timestamps) # The dict structure allows to get the timestamp from the display string # in O(1) self.runs_dict = helper.gen_runs_selection(self.metadata) # Dict maps display strings to column names for the different factors # (var, backend, test) self.factors_dict = { "Variables": "variable", "Backends": "vfc_backend", "Tests": "test" } # Run selection # Contains all options strings runs_display = list(self.runs_dict.keys()) # Will be used when updating plots (contains actual number) self.current_run = self.runs_dict[runs_display[-1]] # Contains the selected option string, used to update current_n_runs current_run_display = runs_display[-1] # This contains only entries matching the run self.run_data = self.data[self.data["timestamp"] == self.current_run] change_run_callback_js = "updateRunMetadata(cb_obj.value, \"\");" self.widgets["select_run"] = Select(name="select_run", title="Run :", value=current_run_display, options=runs_display) self.doc.add_root(self.widgets["select_run"]) self.widgets["select_run"].on_change("value", self.update_run) self.widgets["select_run"].js_on_change( "value", CustomJS( code=change_run_callback_js, args=(dict(metadata=helper.metadata_to_dict( helper.get_metadata(self.metadata, self.current_run)))))) # Factors selection # "Group by" radio self.widgets["groupby_radio"] = RadioButtonGroup( name="groupby_radio", labels=list(self.factors_dict.keys()), active=0) self.doc.add_root(self.widgets["groupby_radio"]) # The functions are defined inside the template to avoid writing too # much JS server side self.widgets["groupby_radio"].on_change("active", self.update_groupby) # "Filter by" radio # Get all possible factors, and remove the one selected in "Group by" filterby_list = list(self.factors_dict.keys()) del filterby_list[self.widgets["groupby_radio"].active] self.widgets["filterby_radio"] = RadioButtonGroup( name="filterby_radio", labels=filterby_list, active=0) self.doc.add_root(self.widgets["filterby_radio"]) # The functions are defined inside the template to avoid writing too # much JS server side self.widgets["filterby_radio"].on_change("active", self.update_filterby) # Filter selector filterby = self.widgets["filterby_radio"].labels[ self.widgets["filterby_radio"].active] filterby = self.factors_dict[filterby] if not self.run_data.empty: options = self.run_data.index\ .get_level_values(filterby).drop_duplicates().tolist() else: options = ["None"] self.widgets["select_filter"] = Select( # We need a different name to avoid collision in the template with # the runs comparison's widget name="select_filter", title="Select a filter :", value=options[0], options=options) self.doc.add_root(self.widgets["select_filter"]) self.widgets["select_filter"]\ .on_change("value", self.update_filter) # Toggle for outliers filtering self.widgets["outliers_filtering_inspect"] = CheckboxGroup( name="outliers_filtering_inspect", labels=["Filter outliers"], active=[]) self.doc.add_root(self.widgets["outliers_filtering_inspect"]) self.widgets["outliers_filtering_inspect"]\ .on_change("active", self.update_outliers_filtering)
def __init__(self, type): self.test = False self.report_type = type self.utc = TimezoneInfo() self.kp_zone = TimezoneInfo(utc_offset=-7*u.hour) self.zones = [self.utc, self.kp_zone] self.datefmt = DateFormatter(format="%m/%d/%Y %H:%M:%S") self.inst_style = {'font-size':'150%'} self.subt_style = {'font-size':'200%','font-style':'bold'} self.title_style = {'font-size':'250%','font-style':'bold'} self.alert_style = {'font-size':'150%','color':'red'} self.nl_file = None self.intro_subtitle = Div(text="Connect to Night Log",css_classes=['subt-style']) self.time_note = Div(text="<b> Note: </b> Enter all times as HHMM (1818 = 18:18 = 6:18pm) in Kitt Peak local time. Either enter the time or hit the <b> Now </b> button if it just occured.", css_classes=['inst-style']) hostname = socket.gethostname() ip_address = socket.gethostbyname(hostname) if 'desi' in hostname: self.location = 'kpno' #self.conn = psycopg2.connect(host="desi-db", port="5442", database="desi_dev", user="******", password="******") elif 'app' in hostname: #this is not true. Needs to change. self.location = 'nersc' else: self.location = 'other' nw_dirs = {'nersc':'/global/cfs/cdirs/desi/spectro/nightwatch/nersc/', 'kpno':'/exposures/nightwatch/', 'other':None} self.nw_dir = nw_dirs[self.location] self.nl_dir = os.environ['NL_DIR'] self.your_name = TextInput(title ='Your Name', placeholder = 'John Smith') self.os_name_1 = TextInput(title ='Observing Scientist 1', placeholder = 'Ruth Bader Ginsberg') self.os_name_2 = TextInput(title ='Observing Scientist 2', placeholder = "Sandra Day O'Connor") self.lo_names = ['None ','Liz Buckley-Geer','Ann Elliott','Parker Fagrelius','Satya Gontcho A Gontcho','James Lasker','Martin Landriau','Claire Poppett','Michael Schubnell','Luke Tyas','Other '] self.oa_names = ['None ','Karen Butler','Amy Robertson','Anthony Paat','Dave Summers','Doug Williams','Other '] self.intro_txt = Div(text=' ') self.comment_txt = Div(text=" ", css_classes=['inst-style'], width=1000) self.date_init = Select(title="Existing Night Logs") self.time_title = Paragraph(text='Time* (Kitt Peak local time)', align='center') self.now_btn = Button(label='Now', css_classes=['now_button'], width=50) days = [d for d in os.listdir(self.nl_dir) if os.path.isdir(os.path.join(self.nl_dir, d))] init_nl_list = np.sort([day for day in days if 'nightlog_meta.json' in os.listdir(os.path.join(self.nl_dir,day))])[::-1][0:10] self.date_init.options = list(init_nl_list) self.date_init.value = init_nl_list[0] self.connect_txt = Div(text=' ', css_classes=['alert-style']) self.connect_bt = Button(label="Connect to Existing Night Log", css_classes=['connect_button']) self.exp_info = Div(text="Fill In Only Relevant Data. Mandatory fields have an asterisk*.", css_classes=['inst-style'],width=500) self.exp_comment = TextAreaInput(title ='Comment/Remark', placeholder = 'Humidity high for calibration lamps',value=None,rows=10, cols=5,width=800,max_length=5000) self.exp_time = TextInput(placeholder = '20:07',value=None, width=100) #title ='Time in Kitt Peak local time*', self.exp_btn = Button(label='Add', css_classes=['add_button']) self.exp_type = Select(title="Exposure Type", value = None, options=['None','Zero','Focus','Dark','Arc','FVC','DESI']) self.exp_alert = Div(text=' ', css_classes=['alert-style']) self.exp_exposure_start = TextInput(title='Exposure Number: First', placeholder='12345', value=None) self.exp_exposure_finish = TextInput(title='Exposure Number: Last', placeholder='12346', value=None) self.nl_subtitle = Div(text="Current DESI Night Log: {}".format(self.nl_file), css_classes=['subt-style']) self.nl_btn = Button(label='Get Current DESI Night Log', css_classes=['connect_button']) self.nl_text = Div(text=" ", css_classes=['inst-style'], width=1000) self.nl_alert = Div(text='You must be connected to a Night Log', css_classes=['alert-style'], width=500) self.nl_info = Div(text="Night Log Info:", css_classes=['inst-style'], width=500) self.exptable_alert = Div(text=" ",css_classes=['alert-style'], width=500) self.checklist = CheckboxGroup(labels=[]) self.check_time = TextInput(placeholder = '20:07', value=None) #title ='Time in Kitt Peak local time*', self.check_alert = Div(text=" ", css_classes=['alert-style']) self.check_btn = Button(label='Submit', css_classes=['add_button']) self.check_comment = TextAreaInput(title='Comment', placeholder='comment if necessary', rows=3, cols=3) self.prob_subtitle = Div(text="Problems", css_classes=['subt-style']) self.prob_inst = Div(text="Describe problems as they come up and at what time they occur. If there is an Alarm ID associated with the problem, include it, but leave blank if not. If possible, include a description of the remedy.", css_classes=['inst-style'], width=1000) self.prob_time = TextInput(placeholder = '20:07', value=None, width=100) #title ='Time in Kitt Peak local time*', self.prob_input = TextAreaInput(placeholder="NightWatch not plotting raw data", rows=10, cols=3, title="Problem Description*:") self.prob_alarm = TextInput(title='Alarm ID', placeholder='12', value=None, width=100) self.prob_action = TextAreaInput(title='Resolution/Action',placeholder='description',rows=10, cols=3) self.prob_btn = Button(label='Add', css_classes=['add_button']) self.prob_alert = Div(text=' ', css_classes=['alert-style']) self.img_subtitle = Div(text="Images", css_classes=['subt-style']) self.img_upinst = Div(text="Include images in the Night Log by uploading a png image from your local computer. Select file, write a comment and click Add", css_classes=['inst-style'], width=1000) self.img_upinst2 = Div(text=" Choose image to include with comment: ", css_classes=['inst-style']) self.img_upload = FileInput(accept=".png") self.img_upload.on_change('value', self.upload_image) self.img_upload_comments = FileInput(accept=".png") self.img_upload_comments.on_change('value', self.upload_image_comments) self.img_upload_comments_os = FileInput(accept=".png") self.img_upload_comments_os.on_change('value', self.upload_image_comments_os) self.img_upload_problems = FileInput(accept=".png") self.img_upload_problems.on_change('value', self.upload_image_problems) self.img_inst = Div(text="Include images in the Night Log by entering the location of the images on the desi cluster", css_classes=['inst-style'], width=1000) self.img_input = TextInput(title='image file location on desi cluster', placeholder='/n/home/desiobserver/image.png',value=None) self.img_comment = TextAreaInput(placeholder='comment about image', rows=8, cols=3, title='Image caption') self.img_btn = Button(label='Add', css_classes=['add_button']) self.img_alert = Div(text=" ",width=1000) self.plot_subtitle = Div(text="Telemetry Plots", css_classes=['subt-style']) self.DESI_Log = None self.save_telem_plots = False
#plot.title.text = "The Shanghai city has been evaluated by %d blocks for tessllation" % (length*width) slider = Slider(title="size", start=5, end=20, step=1, value=10) factors = [ "FAR (Floor Area Ratio)", "Building Type Mix Diversity", "Heating/Cooling Degree Days", "Urban Heating/Cooling Loads", "Electricy Tariff", "Population and Urban Compactness", "GDP per Capita", "Ratio of Street Surface to Building Area", "Vegetation Coverage", "Building Shading and Urban Context", "Roof Color and Albedo", "Building Materials", "Vehicles and Transportation", "Percentage of Water Body" ] checkbox = CheckboxGroup(labels=factors, active=[]) source = get_dataset() plot = make_plot(source) p = Div( text= """<h><b>The Shanghai city is now being evaluated by __ districts for tessellation</b></h>""", width=600, height=10) img = Div( text= """<img src="myapp/static/images/icon.png" alt="Engie Lab China" height="50" width="85">""", width=85, height=50) slider.on_change("value", update_plot) checkbox.on_change("active", update_plot)
def make_document(doc): frame_ratio = 320 / 180 # Frames from Pipelines raw_image_win = init_image_win("Raw Image") motion_mask_win = init_image_win("Motion Mask") cv_mask_win = init_image_win("CV Mask") new_alert_win = init_image_win("New Alert Snapshot") pipeline_win_height = 225 pipeline_grid_plot = gridplot( [ raw_image_win, motion_mask_win, cv_mask_win, new_alert_win, ], ncols=1, plot_width=int(pipeline_win_height * frame_ratio), plot_height=pipeline_win_height, toolbar_location=None, ) pipeline_col = column(pipeline_grid_plot) # Frames from Motion h264_win = init_image_win("H.264") fd_win = init_image_win("FD") mog2_win = init_image_win("MOG2") amf_win = init_image_win("AMF") display_detection_win = init_image_win("Motion Detection") motion_win_height = 225 motion_grid_plot = gridplot( children=[ [h264_win, fd_win], [mog2_win, amf_win], ], plot_width=int(motion_win_height * frame_ratio), plot_height=motion_win_height, toolbar_location=None, ) motion_col = column(display_detection_win, motion_grid_plot) # Motion Control Panel motion_checkbox_group = CheckboxGroup( labels=["H.264", "FD", "MOG2", "AMF", "Show Motion Detections"]) motion_select = Select(title="Motion Filter Type", value="h264", options=["h264", "fd", "mog2", "amf"]) motion_interval_slider = Slider(start=0.05, end=30, value=1.5, step=0.01, title="Motion Interval") motion_threshold_slider = Slider(start=0, end=200, value=50, step=1, title="Motion Threshold(H.264 only)") motion_bbx_area_threshold_slider = Slider( start=25, end=200, value=200, step=1, title="Motion BBX Area Threshold(OpenCV only)", ) # AMF only configs variance_threshold_slider = Slider(start=10, end=500, value=500, step=1, title="Variance Threshold(AMF only)") amf_checkbox_group = CheckboxGroup( labels=["History Variance(AMF only)", "Frame Reduction(AMF only)"], active=[1]) # Config Control Panel show_configs_checkbox_group = CheckboxGroup( labels=["Show CV Config", "Show Event Config"]) override_cv_config_input = TextInput(value=json.dumps({}), title="Override CV Config") override_event_config_input = TextInput(value=json.dumps({}), title="Override Event Config") env_select = Select(title="Environment", value="staging", options=["staging", "rc", "production"]) jumbo_id_input = TextInput(value="", title="Jumbo ID") api_token_input = TextInput(value="", title="API Token") panel_col = column( Div(text="<h4> Config Control Panel </h4>"), show_configs_checkbox_group, override_cv_config_input, override_event_config_input, env_select, jumbo_id_input, api_token_input, Div(text="<h4> Motion Control Panel </h4>"), motion_checkbox_group, motion_select, motion_interval_slider, motion_threshold_slider, motion_bbx_area_threshold_slider, variance_threshold_slider, amf_checkbox_group, sizing_mode="scale_width", ) main_row = row( pipeline_col, panel_col, motion_col, ) doc.title = "StreamDebugger" doc.add_root(main_row)
def plot_benchmarks_as_lines(title, *bm, transform=None, line_title_transform=None, logx=True, logy=True): import bokeh from bokeh.plotting import figure, output_file, show from bokeh.palettes import Dark2_5 as palette from bokeh.layouts import row, column from bokeh.models import (Legend, LegendItem, CheckboxGroup, CustomJS, Div, RadioGroup, Toggle, ColumnDataSource, DataTable, TableColumn) from bokeh.models.markers import marker_types # ids = entry_ids(*bm, transform=transform) colors = itertools.cycle(palette) markers = itertools.cycle(marker_types) p = figure( title=title, x_axis_type="log" if logx else "linear", y_axis_type="log" if logy else "linear", #background_fill_color="#fafafa", plot_width=1000, x_axis_label="Number of pixels", y_axis_label="Throughput (MB/s)", ) p.toolbar.autohide = True #p.toolbar.active_inspect = [hover_tool, crosshair_tool] p.toolbar.active_drag = "auto" p.toolbar.active_scroll = "auto" # def dft(v): return v if v else (lambda n: n) tr = dft(transform) lttr = dft(line_title_transform) # for results in bm: x = [ids[name] for name in results.names] y = [bps / 1e6 for bps in results.bytes_per_second] c = next(colors) marker = next(markers) next(markers) # advance two line_name = lttr(results.first) #legends.append(LegendItem(name=c, label=line_name)) p.scatter(x, y, marker=marker, size=8, color=c, legend_label=line_name) p.line( x, y, color=c, alpha=0.9, #muted_color=c, muted_alpha=0.05, legend_label=line_name) p.legend.click_policy = "hide" p.legend.label_text_font_size = "10px" # def input_title(title): return Div(text=f"<h3>{title}</h3>") inputs = [] first = bm[0].first.meta for k, g in first.checkbox_groups().items(): cb = CheckboxGroup(labels=[str(v) for v in g], active=[i for i in range(len(g))], inline=True) inputs.append(input_title(k)) inputs.append(cb) # # https://github.com/bokeh/bokeh/blob/branch-2.3/examples/app/export_csv/main.py x_axis_values = [f"{m.num_pixels}px" for m in bm[0].meta] table_sources = [] for i, px in enumerate(x_axis_values): c = ColumnDataSource( data={ 'name': [nth(results.filtered_names, i) for results in bm], 'bytes_per_second': [nth(results.bytes_per_second, i) for results in bm], 'items_per_second': [nth(results.items_per_second, i) for results in bm], 'cpu_time': [nth(results.real_time, i) for results in bm], 'real_time': [nth(results.real_time, i) for results in bm], 'iterations': [nth(results.iterations, i) for results in bm], 'threads': [nth(results.threads, i) for results in bm], }) table_sources.append(c) selected_x_index = 8 # FIXME (currently 2000 pixels) table_source = copy.deepcopy(table_sources[selected_x_index]) relvalues = Toggle(label="Table: Relative values") px_title = input_title("Table: number of pixels") px_radiogroup = RadioGroup(labels=x_axis_values, active=selected_x_index) table_inputs = [relvalues, px_title, px_radiogroup] # table_cols = [ TableColumn(field='name', title='Name'), TableColumn(field='bytes_per_second', title='Bytes/second'), TableColumn(field='items_per_second', title='Items/second'), TableColumn(field='cpu_time', title='CPU time'), TableColumn(field='real_time', title='Real time'), TableColumn(field='iterations', title='Iterations'), TableColumn(field='threads', title='Threads'), ] data_table = DataTable(source=table_source, columns=table_cols, width=1200) callback = CustomJS(args=dict(radiogroup=px_radiogroup, source=table_source, table=table_sources), code=""" console.log(`active=${radiogroup.active}`); /*source.data=table[radiogroup.active];*/ var nrows = source.data['name'].length; var ts = table[radiogroup.active].data; var names = ["name", "bytes_per_second", "items_per_second", "cpu_time", "real_time", "iterations", "threads"]; var ncols = names.length; console.log(`names=${names} nrows=${nrows} ncols=${ncols}`); for(var i = 0; i < nrows; i++) { for(var j = 0; j < ncols; ++j) { var name = names[j]; /*console.log(`i=${i} j=${j} name=${name}`);*/ source.data[name][i] = ts[name][i]; } } source.change.emit(); """) px_radiogroup.js_on_change('active', callback) # lambda attr, old, new: log(f"attr={attr} old={old} new={new} active={px_radiogroup.active}")) # layout = column(row(column(*inputs), p), row(column(*table_inputs), data_table)) show(layout)
""" import numpy as np from bokeh.io import output_file, show from bokeh.layouts import row from bokeh.palettes import Viridis3 from bokeh.plotting import figure from bokeh.models import CheckboxGroup, CustomJS output_file("line_on_off.html", title="line_on_off.py example") p = figure() props = dict(line_width=4, line_alpha=0.7) x = np.linspace(0, 4 * np.pi, 100) l0 = p.line(x, np.sin(x), color=Viridis3[0], legend="Line 0", **props) l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], legend="Line 1", **props) l2 = p.line(x, np.tan(x), color=Viridis3[2], legend="Line 2", **props) checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"], active=[0, 1, 2], width=100) checkbox.callback = CustomJS(args=dict(l0=l0, l1=l1, l2=l2, checkbox=checkbox), lang="coffeescript", code=""" l0.visible = 0 in checkbox.active; l1.visible = 1 in checkbox.active; l2.visible = 2 in checkbox.active; """) layout = row(checkbox, p) show(layout)
def bkapp(doc): def createDataSet(): ''' Charge les données d'entrées dans un dataFrame geopandas Données d'entrées : - shapefile contenant le traçé des communes au format geojson - fichier texte contenant les données aui nous interesse au format csv Tâches réalisées : - chargement des fichiers - reprojection de wgs84 vers webmercator - tri des données inutiles - calcul de données à partir des données existantes - assemblage des données dans un geodataframe - tri des NaN/inf Sortie : - un geoDataFrame ''' # Fichier contenant le tracé des communes (format geojson) city_shapefile = "DATA/communes-20190101.json" # Fichiers de données taxe_hab = "DATA/taux_taxe_habitation.xlsx" taxe_fon = "DATA/taux_taxe_fonciere.xlsx" ########## Gestion de la géométrie des communes ############ # import de la geometrie des communes df_shape = gpd.read_file(city_shapefile) # Suppression des colonnes "wiki" et "surface", inutiles df_shape.drop(columns=["wikipedia", "surf_ha"], inplace=True) # reprojection en webmercator df_shape["geometry"] = df_shape["geometry"].to_crs("EPSG:3857") df_shape.crs = "EPSG:3857" ########## Gestion des stats sur les communes ############ # Taxe habitation # Import des taux d'imposition par commune dans la dataframe dfTH = pd.read_excel(taxe_hab, sheet_name="COM", header=2, usecols="A:B,E:G", converters={ 'Code commune': str, 'Code DEP': str }) # Mise en forme des libelles des colonnes dfTH.columns = dfTH.columns.str.replace(' ', '_') dfTH.columns = dfTH.columns.str.replace('Taux_communal_TH*', 'TauxTH').str.replace( 'Taux_communal_voté_TH*', 'TauxTH') # On crée le code INSEE en concatenant le code departement et commune # Le code Insee sera la clé commune entre les dataframe de géométrie et de data. # Création du code Insee dans une nouvelle colonne de la df dfTH["insee"] = dfTH["Code_DEP"] + dfTH["Code_commune"] # Suppression de la colonne code commune qui ne sert plus à rien dfTH.drop(columns=["Code_commune"], inplace=True) # On converti les valeurs non numériques de la colonnes TauxTH en NaN pour les filtrer dfTH["TauxTH_2018"] = pd.to_numeric(dfTH["TauxTH_2018"], errors='coerce') dfTH["TauxTH_2017"] = pd.to_numeric(dfTH["TauxTH_2017"], errors='coerce') # Taxe foncière dfTF = pd.read_excel(taxe_fon, sheet_name="COM", header=2, usecols="A:B,D:F", converters={ 'Code commune': str, 'Code DEP': str }) dfTF.columns = dfTF.columns.str.replace(' ', '_') dfTF.columns = dfTF.columns.str.replace('Taux_communal_TFB*', 'TauxTF').str.replace( 'Taux_communal_voté_TFB*', 'TauxTF') dfTF["insee"] = dfTF["Code_DEP"] + dfTF["Code_commune"] dfTF.drop(columns=["Code_commune"], inplace=True) dfTF.drop(columns=["Code_DEP"], inplace=True) # On converti les valeurs non numériques de la colonnes TauxTH en NaN pour les filtrer dfTF["TauxTF_2018"] = pd.to_numeric(dfTF["TauxTF_2018"], errors='coerce') dfTF["TauxTF_2017"] = pd.to_numeric(dfTF["TauxTF_2017"], errors='coerce') # Assemblage de la géométrie et des taux d'imposition. dataCities = pd.merge(df_shape, dfTH, left_on="insee", right_on="insee", how='left') dataCities = pd.merge(dataCities, dfTF, left_on="insee", right_on="insee", how='left') return dataCities ### Fonctions de traitement ### def select_data(df, ogCity, dist): """ Fonction qui permet de sélectionner les données à afficher Sélectionnées en fonction de la distance autour de la ville : On prend toutes les villes dont le contour est intersecté par le contour de la ville originale augmenté de dist Entrées : - df : dataframe qui contient toutes les données - ogCity : extract de la commune sélectionnée - dist : distance à l'origine (l'unité dépend du CRS, le EPSG:3857 est en m) Sortie : - dataFrame ne contenant que les données retenues """ # La fonction renvoie les communes qui sont intersectées par le cercle de centre ogCity # et de rayon dist*1000 (le rayon est entré en km) return df[df.intersects(other=ogCity.geometry.buffer(dist * 1000))] def create_choropleth(displaySet, displayParam, palette, ogCity): """ Fonction qui met à jour la coloration des communes affichées Entrées : - displaySet : dataFrame contenant les données affichées - displayParam : paramètres que l'on souhaite aficher - palette : liste de couleurs (identique à celle de la choroplèthe) - ogCity : extract de la commune sélectionnée Sorties : - Figure contenant la carte. """ # On récupère les limites géographiques pour initialiser la carte displayBounds = displaySet.total_bounds # conversion du tracé des communes en json pour interpretation par Bokeh geosource = GeoJSONDataSource(geojson=displaySet.to_json()) # Creation de la figure de la carte choroPlot = figure(title='Taux ' + select_imp.value + " " + str(slider_yr.value), x_range=(displayBounds[0], displayBounds[2]), y_range=(displayBounds[1], displayBounds[3]), x_axis_type="mercator", y_axis_type="mercator", plot_height=500, plot_width=850, sizing_mode="scale_width", toolbar_location='below', tools="pan, wheel_zoom, box_zoom, reset", x_axis_location=None, y_axis_location=None) choroPlot.xgrid.grid_line_color = None choroPlot.ygrid.grid_line_color = None # Ajout d'un évèmenent de type clic, pour sélectionnr la commune de référence choroPlot.on_event(Tap, update_loc) #outil de zoom molette activé par défaut choroPlot.toolbar.active_scroll = choroPlot.select_one(WheelZoomTool) # ajout du fond de carte tile_provider = get_provider(Vendors.CARTODBPOSITRON) choroPlot.add_tile(tile_provider) # On détermine les vals min et max du jeu de test pour la gestion des couleurs mini = displaySet[displayParam].min() maxi = displaySet[displayParam].max() # Création d'une échelle de couleur évoulant linéairement avec le paramètre à afficher color_mapper = LinearColorMapper(palette=defaultPalette, low=mini, high=maxi, nan_color='#808080') # Ajout du tracé des communes sur la carte citiesPatch = choroPlot.patches('xs', 'ys', source=geosource, line_color='gray', line_width=0.25, fill_alpha=0.5, fill_color={ 'field': displayParam, 'transform': color_mapper }) # création de la legende # color_bar = ColorBar(color_mapper=color_mapper, label_standoff=8, location=(0, 0), orientation='vertical') choroPlot.add_layout(color_bar, 'right') # ajout d'une flèche sur la commune de reférence start = ogCity.geometry.centroid pin_point = Arrow(end=VeeHead(size=15), line_color="red", x_start=start.x, y_start=start.y, x_end=start.x, y_end=start.y - 0.001) choroPlot.add_layout(pin_point) # Ajout d'un tooltip au survol de la carte choroHover = HoverTool(renderers=[citiesPatch], tooltips=[('Commune', '@nom'), (displayParam, '@' + displayParam)]) toolTip = choroPlot.add_tools(choroHover) return choroPlot # Fonction de création de l'histogramme def createHisto(displaySet, displayParam, palette, ogCity): """ L'histogramme permet de visualiser la répartition des taux des communes affichées Entrées : - displaySet : dataFrame contenant les données affichées - displayParam : paramètres que l'on souhaite aficher - palette : liste de couleurs (identique à celle de la choroplèthe) - ogCity : extract de la commune sélectionnée Sorties : - figure contenant l'histogramme. """ # On crée autant de regroupement que de couleurs passées à la fct° nBins = len(palette) # Calcul de l'histogramme hist, edges = np.histogram(displaySet[displayParam].dropna(), bins=nBins) # Nombre de lignes dans displaySet (vectorisé pour passage à datasource) total = displaySet[displayParam].size * np.ones(nBins, np.int8) # Normalisation de l'histogramme (affichage en % du total d'éléments) hist_pct = 100 * hist / total[0] # Calcul de l'étendue l'échelle verticale hmax = max(hist_pct) * 1.1 hmin = -0.1 * hmax # Calcul de la moyenne et médiane de l'échantillon mean = displaySet[displayParam].mean() med = displaySet[displayParam].quantile(0.5) # Création de la figure contenant l'histogramme histoPlot = figure(title='Répartition du taux de ' + select_imp.value + " " + str(slider_yr.value), y_range=(hmin, hmax), plot_height=300, plot_width=400, sizing_mode="scale_width", y_axis_location='right', toolbar_location=None) histoPlot.xgrid.grid_line_color = None histoPlot.xaxis.axis_label = displayParam histoPlot.xaxis.axis_line_color = None histoPlot.ygrid.grid_line_color = "white" histoPlot.yaxis.axis_label = '% de l\'échantillon' histoPlot.yaxis.axis_line_color = None # Source de données data = dict(right=edges[1:], left=edges[:-1], top=hist_pct, nb=hist, total=total, color=palette) histoSource = ColumnDataSource(data=data) # Tracé de l'histogramme histoDraw = histoPlot.quad(bottom=0, left="left", right="right", top="top", fill_color="color", line_color=None, source=histoSource) # Ajout d'un tooltip au survol de la carte histoHover = HoverTool(renderers=[histoDraw], mode="vline", tooltips=[ ('Taille', '@nb'), ('Fourchette', '@left - ' + '@right'), ]) histoTooltip = histoPlot.add_tools(histoHover) # Ajout d'un repère vertical pour la commune sélectionnée if ~np.isnan(ogCity[displayParam]): ogCityDraw = histoPlot.quad(bottom=hmin, top=hmax, left=ogCity[displayParam] - 0.05, right=ogCity[displayParam] + 0.05, fill_color="pink", line_color=None, legend_label=ogCity["nom"] + ' (' + ogCity["Code_DEP"] + ')') # Ajout d'un tooltip au survol de la commune d'orginie displayName = ogCity["nom"] + " (" + ogCity["Code_DEP"] + ")" ogCityHover = HoverTool(renderers=[ogCityDraw], mode="vline", tooltips=[ ('Commune sélectionnée', displayName), (displayParam, str(ogCity[displayParam])), ]) histoTooltip = histoPlot.add_tools(ogCityHover) # Ajout d'un repère vertical pour la moyenne de l'échantillon ogCityDraw = histoPlot.quad(bottom=hmin, top=hmax, left=mean - 0.05, right=mean + 0.05, fill_color="blue", line_color=None, legend_label="Moyenne ") # Ajout d'un repère vertical pour la mediane de l'échantillon ogCityDraw = histoPlot.quad(bottom=hmin, top=hmax, left=med - 0.05, right=med + 0.05, fill_color="purple", line_color=None, legend_label="Mediane ") # On rend la légende interactive histoPlot.legend.click_policy = "hide" # On oriente horizontalement la légende histoPlot.legend.orientation = "vertical" # Réduction de la police histoPlot.legend.label_text_font_size = "8px" # On place la légende hors de la zone de tracé histoLegend = histoPlot.legend[0] histoPlot.legend[0] = None histoPlot.add_layout(histoLegend, 'right') return histoPlot def create_info(displaySet, displayParam, ogCity): """ Affiche un panneau textuel contenant des infomations sur le jeu de données affiché et la commune sélectionnée. Entrées : - displaySet : dataFrame contenant les données affichées - displayParam : paramètres que l'on souhaite aficher - ogCity : extract de la commune sélectionnée Sorties : - figure contenant le texte à afficher. """ stats = displaySet[displayParam].dropna().describe( percentiles=[0.5]).round(decimals=2) stats = stats[stats.index != 'count'] #On supprime la variable "count" deja affichée # Modification de l'intitulé des colonnes stats.columns = ["Taux " + str(elt) for elt in data_yr] # Creation du texte infoText = [ f"<b>Communes affichées</b> : {len(displaySet)}", f"<b>Commune sélectionnée</b> : {ogCity['nom']} ({ogCity['Code_DEP']})", "</br><b>Statistiques</b> : " + select_imp.value ] return [Div(text="</br>".join(infoText)), PreText(text=str(stats))] def update_layout(displaySet, displayParam, ogCity, palette): """ Fonction permettant de mettre à jour toutes les figures du layout Entrées : - displaySet : dataFrame contenant les données affichées - displayParam : paramètres que l'on souhaite aficher - ogCity : extract de la commune sélectionnée - palette : liste de couleurs Sorties : - rien """ # Mise à jour de la chroplèthe appLayout.children[0].children[0] = create_choropleth( displaySet, displayParam, palette, ogCity) # Mise à jour de l'histogramme appLayout.children[1].children[0] = createHisto( displaySet, displayParam, palette, ogCity) # Mise à jour des infos appLayout.children[1].children[1:] = create_info( displaySet, infoParam, ogCity) def create_displayParam(impot='TauxTH_', year=2018): """ Fonction qui retourne le paramètre à afficher dans la dataframe, à partir de l'impôt et de l'année désirée. Entrées : - impot : l'impot que l'ont souhaite afficher (str) - année (int) : l'année que l'on souhait afficher (int) Sortie : - displayParam : le paramètre d'affichge (str) """ return impot + str(year) ### Fonction callback ### # Callback fonction (met à jour le graphique) def update_yr(attr, old, new): """ Fonction callback appelée au changement du slider des années. Permet de modifier l'année du taux affiché. """ # Création du paramètre à afficher en fonction de l'année sélectionnée : displayParam = create_displayParam(impot, slider_yr.value) # Mise à jour du layout update_layout(displaySet, displayParam, ogCity, defaultPalette) def update_dst(attr, old, new): """ Fonction callback appelée au changement de la distance d'affichage Modifie le jeu de données afiché et recalcule les couleurs de nouveau jeu """ # Utilisation de variables globales (nécessaire car utilisée par plusieurs callback) global displaySet # Création du paramètre à afficher en fonction de l'année sélectionnée : displayParam = create_displayParam(impot, slider_yr.value) # Mise à jour du jeu d'affichage displaySet = select_data(dataCities, ogCity, slider_dst.value) # Mise à jour du layout update_layout(displaySet, displayParam, ogCity, defaultPalette) def update_loc(event): """ Fonction callback activé au clic sur la map Permet de changer la commune sélectionnée Maj la carte avec la nouvelle commune de référence """ # Utilisation de variables globales (nécessaire car utilisée par plusieurs callback) global ogCity global displaySet ### Identification de la commune sous le point cliqué ### # Création d'un objet shapely de type Point aux coords du clic : clicPoint = gpd.points_from_xy([event.x], [event.y]) # Creation d'une geoserie contenant le point : # Rem : utilisation de iloc[0] pour ne pas avoir d'index # cf issue https://github.com/geopandas/geopandas/issues/317 pointSerie = gpd.GeoSeries(crs='epsg:3857', data=clicPoint).iloc[0] # On recherche la commune qui contient le point : clicCity = dataCities[dataCities.contains(other=pointSerie)] # On vérifie avant maj que le clic a bien retourné une géométrie if not clicCity.empty: ogCity = clicCity.iloc[0] ### Mise à jour de la carte avec la commune cliquée pour référence ### # Calcul du nouveau jeu de données à afficher displaySet = select_data(dataCities, ogCity, slider_dst.value) # Création du paramètre à afficher en fonction de l'année sélectionnée : displayParam = create_displayParam(impot, slider_yr.value) # Mise à jour du layout update_layout(displaySet, displayParam, ogCity, defaultPalette) def update_colormap(attr, old, new): """ Change la palette de couleurs utilisée à l'action sur le toggle idoine """ global defaultPalette # Création du paramètre à afficher en fonction de l'année sélectionnée : displayParam = create_displayParam(impot, slider_yr.value) if len(new) > 0: print('Mode Daltonien') defaultPalette = Colorblind[7] else: print('Mode Normal') defaultPalette = brewer['RdYlGn'][7] # Mise à jour du layout update_layout(displaySet, displayParam, ogCity, defaultPalette) def update_impot(attr, old, new): global impot dict_imp = {"Taxe d'habitation": "TauxTH_", "Taxe foncière": "TauxTF_"} impot = dict_imp[new] # Création du paramètre à afficher en fonction de l'année sélectionnée : displayParam = create_displayParam(impot, slider_yr.value) # Mise à jour du layout update_layout(displaySet, displayParam, ogCity, defaultPalette) #%% # Chargement du jeu de test try: dataCities = gpd.read_file("DATA/dataCities.json") except: print("fichier dataCities.json non trouvé, génération en cours") dataCities = createDataSet() # Sauvegarde du dataSet dataCities.to_file("DATA/dataCities.json", driver='GeoJSON') # %% ### Main Code #### ### Constrution de la carte et légende #### global displaySet global impot global defaultPalette global ogCity # Paramètres par défaut ogCity = dataCities[dataCities["nom"] == 'Paris'].iloc[ 0] # Paris sélectionnée par défaut # paramètre affiché par défaut = taxe d'habitation la plus récente defaultParam = impot + str(data_yr[-1]) infoParam = [impot + str(elt) for elt in data_yr] # Création du set de donnée à afficher displaySet = select_data(dataCities, ogCity, dist) ### Construction du front-end ### # Ajout d'un slider pour choisir l'année slider_yr = Slider(title='Année', start=data_yr[0], end=data_yr[-1], step=1, value=data_yr[-1], default_size=250) slider_yr.on_change('value', update_yr) # Ajout d'un slider pour choisir la distance d'affichage slider_dst = Slider(title='Distance d\'affichage (km)', start=0, end=100, step=5, value=dist, default_size=250) slider_dst.on_change('value', update_dst) # Ajout d'un sélecteur pour choisir l'impot à afficher select_imp = Select(title="Impôt:", value="Taxe d'habitation", options=["Taxe d'habitation", "Taxe foncière"]) select_imp.on_change('value', update_impot) # Ajout d'un mode daltonien checkbox_dalto = CheckboxGroup(labels=["Mode Daltonien"]) checkbox_dalto.on_change('active', update_colormap) # Creation de la choropleth choroPlot = create_choropleth(displaySet, defaultParam, defaultPalette, ogCity) # Creation de l'historamme histoPlot = createHisto(displaySet, defaultParam, defaultPalette, ogCity) # Creation des figures infos infoTitle, infoDisplaySet = create_info(displaySet, infoParam, ogCity) # Organisation colones/lignes Col1 = column(slider_yr, slider_dst) Col2 = column(select_imp, checkbox_dalto) row_wgt = row(Col1, Col2) Col3 = column(choroPlot, row_wgt) Col4 = column(histoPlot, infoTitle, infoDisplaySet) appLayout = row(Col3, Col4) doc.add_root(appLayout) doc.title = "VizImpôts" doc.theme = Theme(filename="theme.yaml")
""" Example demonstrating turning lines on and off - with bokeh server """ import numpy as np from bokeh.io import curdoc from bokeh.layouts import row from bokeh.palettes import Viridis3 from bokeh.plotting import figure from bokeh.models import CheckboxGroup p = figure() props = dict(line_width=4, line_alpha=0.7) x = np.linspace(0, 4 * np.pi, 100) l0 = p.line(x, np.sin(x), color=Viridis3[0], legend="Line 0", **props) l1 = p.line(x, 4 * np.cos(x), color=Viridis3[1], legend="Line 1", **props) l2 = p.line(x, np.tan(x), color=Viridis3[2], legend="Line 2", **props) checkbox = CheckboxGroup(labels=["Line 0", "Line 1", "Line 2"], active=[0, 1, 2], width=100) def update(attr, old, new): l0.visible = 0 in checkbox.active l1.visible = 1 in checkbox.active l2.visible = 2 in checkbox.active checkbox.on_change('active', update) layout = row(checkbox, p) curdoc().add_root(layout)
def plot(tables, output_filename, xmin, xmax, ymin, ymax, superterm): ''' This is the plot function that uses Bokeh functions and widgets to make an interactive hexagon plot. This function recieves: - tables: dictionary with tables used to create arrays of repeated x, y coordinates (depending on the counts) for the hexagon plot. - output_filename: filename of .html output in the plots folder The coordinate arrays are used to create a pandas dataframe with Bokeh functions. This dataframe contains the q, r coordinates and counts used to plot the hexagons. To this dataframe, extra information is added (e.g. most common chemicals), which is displayed in the hover tooltip. Gaussian blur is added to copies of this dataframe and given as input to the Bokeh slider widget. Other widgets are added as well, for saturation, normalization etc. Bokeh allows to customize these widges with javascript code. The hexagon plot is saved as a .html file and also shown in the browser. ''' file_name = 'plots/' + str(output_filename) + '.html' output_file(file_name) # Blur and saturation values BLUR_MAX = 4 BLUR_STEP_SIZE = 0.25 SATURATION_MAX = 5 SATURATION_STEP_SIZE = 0.25 # Hexagon plot properties SIZE_HEXAGONS = 10 orientation = 'flattop' #bokeh alows 2 different hexagon orientations which also influences hexagon size calculations, but we currently have only calculated blur distances for this orientation ratio = ((ymax - ymin) / (xmax - xmin)) size = SIZE_HEXAGONS / ratio hexagon_height = sqrt(3) * size hexagon_height = hexagon_height * ratio # make figure p = figure(x_range=[xmin, xmax], y_range=[ymin - (hexagon_height / 2), ymax], tools="wheel_zoom,reset,save", background_fill_color='#440154') p.grid.visible = False p.xaxis.axis_label = "log(P)" p.yaxis.axis_label = "mass in Da" p.xaxis.axis_label_text_font_style = 'normal' p.yaxis.axis_label_text_font_style = 'normal' # term_to_source, term_to_metadata, options = make_plot_sources(tables, size, ratio, orientation, BLUR_MAX, BLUR_STEP_SIZE) # source for widgets term_to_source = dict() term_to_class = dict() term_to_metadata = dict() options = [] for term in tables.keys(): options.append((term, term)) table = tables[term]['table'] if superterm: source = create_class_source(table, term, size, ratio, orientation, superterm) term_to_class[term] = {} term_to_class[term]['show_class'] = True term_to_class[term]['source'] = source else: term_to_class[term] = {'show_class': False} source, title = create_data_source(table, term, size, ratio, orientation, BLUR_MAX, BLUR_STEP_SIZE) metadata = return_html(tables[term]['metadata']) term_to_source[term] = {'source': source, 'title': title} term_to_metadata[term] = metadata # hex = p.hex_tile(q='q', r="r", size=size, line_color=None, source=source, aspect_scale=ratio,orientation=orientation, # fill_color='pink' ) # show(p) # make default souce for plot, this is the first source shown in the plot, and also works like a container. Old data is thrown out and new data is thrown in. default_term = list(tables.keys())[0] # pick the first one metadata = tables[default_term]['metadata'] metadata = return_html(metadata) table = tables[default_term]['table'] source, title = create_data_source(table, default_term, size, ratio, orientation, BLUR_MAX, BLUR_STEP_SIZE) p.title.text = title # color mapper mapper = linear_cmap('scaling', 'Viridis256', 0, max(source.data['scaling'])) # plot hex = p.hex_tile(q="q", r="r", size=size, line_color=None, source=source, aspect_scale=ratio, orientation=orientation, fill_color=mapper) if superterm: source_class = term_to_class[default_term]['source'] class_hex = p.hex_tile(q='q', r="r", size=size, line_color=None, source=source_class, aspect_scale=ratio, orientation=orientation, fill_color='pink', fill_alpha=0.7) class_hex.visible = False # HOVER TOOLTIPS = return_JS_code('tooltips') TOOLTIPS_tfidf = return_JS_code('tooltips_tfidf') code_callback_hover = return_JS_code('hover') callback_hover = CustomJS(code=code_callback_hover) hover = HoverTool(tooltips=TOOLTIPS, callback=callback_hover, show_arrow=False) p.add_tools(hover) # WIDGETS slider1 = Slider(start=1, end=SATURATION_MAX, value=1, step=SATURATION_STEP_SIZE, title="Saturation", width=100) slider2 = Slider(start=0, end=BLUR_MAX, value=0, step=BLUR_STEP_SIZE, title="Blur", width=100) checkbox = CheckboxGroup(labels=["TFIDF"], active=[]) radio_button_group = RadioGroup(labels=["Viridis256", "Greys256"], active=0) button = Button(label="Metadata", button_type="default", width=100) multi_select = MultiSelect(title=output_filename, value=[default_term], options=options, width=100, height=300) if superterm: label = "Show " + str(superterm) checkbox_class = CheckboxGroup(labels=[label], active=[]) # WIDGETS CODE FOR CALLBACK code_callback_slider1 = return_JS_code('slider1') code_callback_slider2 = return_JS_code('slider2') code_callback_checkbox = return_JS_code('checkbox') code_callback_rbg = return_JS_code('rbg') code_callback_button = return_JS_code('button') code_callback_ms = return_JS_code('multi_select') if superterm: code_callback_class = return_JS_code('class') # WIDGETS CALLBACK callback_slider1 = CustomJS(args={ 'source': source, 'mapper': mapper, 'slider2': slider2, 'checkbox': checkbox }, code=code_callback_slider1) callback_slider2 = CustomJS(args={ 'source': source, 'mapper': mapper, 'slider1': slider1, 'checkbox': checkbox }, code=code_callback_slider2) callback_checkbox = CustomJS(args={ 'source': source, 'slider1': slider1, 'slider2': slider2, 'mapper': mapper, 'hover': hover, 'tooltips': TOOLTIPS, 'tooltips_tfidf': TOOLTIPS_tfidf }, code=code_callback_checkbox) callback_radio_button_group = CustomJS(args={ 'p': p, 'multi_select': multi_select, 'mapper': mapper, 'term_to_class': term_to_class, 'Viridis256': Viridis256, 'Greys256': Greys256 }, code=code_callback_rbg) callback_button = CustomJS(args={ 'term_to_metadata': term_to_metadata, 'multi_select': multi_select }, code=code_callback_button) callback_ms = CustomJS(args={ 'source': source, 'term_to_source': term_to_source, 'term_to_class': term_to_class, 'checkbox': checkbox, 'slider2': slider2, 'slider1': slider1, 'p': p, 'mapper': mapper }, code=code_callback_ms) if superterm: callback_radio_button_group = CustomJS(args={ 'p': p, 'multi_select': multi_select, 'class_hex': class_hex, 'term_to_class': term_to_class, 'mapper': mapper, 'Viridis256': Viridis256, 'Greys256': Greys256 }, code=code_callback_rbg) callback_class = CustomJS(args={ 'multi_select': multi_select, 'term_to_class': term_to_class, 'class_hex': class_hex }, code=code_callback_class) callback_ms = CustomJS(args={ 'source': source, 'term_to_source': term_to_source, 'checkbox': checkbox, 'slider2': slider2, 'slider1': slider1, 'p': p, 'mapper': mapper, 'checkbox_class': checkbox_class, 'class_hex': class_hex, 'term_to_class': term_to_class }, code=code_callback_ms) # WIDGETS INTERACTION slider1.js_on_change('value', callback_slider1) slider2.js_on_change('value', callback_slider2) checkbox.js_on_change('active', callback_checkbox) radio_button_group.js_on_change('active', callback_radio_button_group) button.js_on_event(events.ButtonClick, callback_button) multi_select.js_on_change("value", callback_ms) if superterm: checkbox_class.js_on_change('active', callback_class) # LAYOUT if superterm: layout = row( multi_select, p, column(slider1, slider2, checkbox, checkbox_class, radio_button_group, button)) else: layout = row( multi_select, p, column(slider1, slider2, checkbox, radio_button_group, button)) show(layout)
#sdate_range_slider = DateRangeSlider(title="Date Range: ", start=datetime.datetime(2017, 1, 1,1), end=datetime.datetime(2017, 2, 7,2), value=(datetime.datetime(2017, 9, 7,1), datetime.datetime(2017, 9, 7,2)),step=1) #sdate_range_slider.on_change("value", my_slider_handler) #sdate_range_slider = DateSlider(title="Date Range: ", start=datetime.datetime(2017, 1, 1,1), end=datetime.datetime(2019, 9, 7,2), value=(datetime.datetime(2017, 9, 7,1), datetime.datetime(2017, 9, 7,2)), step=1) date_range_radio = RadioButtonGroup( name='Date Range Filter', labels=["Date Range Filter On", "Date Range Filter Off"], active=0) idle_range_radio = RadioButtonGroup( name='Idle Range Filter', labels=["Idle Range Filte On", "Idle Range Filte Off"], active=1) checkbox_group = CheckboxGroup( labels=["Cumulative Date Filter", "Fine Date Filter"], active=[0]) hour_range_slider = RangeSlider(start=0, end=360, value=(0, 150), step=1, title="Idle time for a vehicle (hours)") alpha_range_slider = Slider(start=0, end=1, value=0.4, step=.1, title="Spot Transparency") size_range_slider = Slider(start=4, end=50, value=4, step=1, title="Spot Size")
def create_layout(self): # create figure self.x_range = Range1d(start=self.model.map_extent[0], end=self.model.map_extent[2], bounds=None) self.y_range = Range1d(start=self.model.map_extent[1], end=self.model.map_extent[3], bounds=None) self.fig = Figure(tools='wheel_zoom,pan', x_range=self.x_range, y_range=self.y_range) self.fig.plot_height = 560 self.fig.plot_width = 800 self.fig.axis.visible = False # add tiled basemap self.tile_source = WMTSTileSource(url=self.model.basemap) self.tile_renderer = TileRenderer(tile_source=self.tile_source) self.fig.renderers.append(self.tile_renderer) # add datashader layer self.image_source = ImageSource(url=self.model.service_url, extra_url_vars=self.model.shader_url_vars) self.image_renderer = DynamicImageRenderer(image_source=self.image_source) self.fig.renderers.append(self.image_renderer) # add label layer self.label_source = WMTSTileSource(url=self.model.labels_url) self.label_renderer = TileRenderer(tile_source=self.label_source) self.fig.renderers.append(self.label_renderer) # add ui components axes_select = Select.create(name='Axes', options=self.model.axes) axes_select.on_change('value', self.on_axes_change) field_select = Select.create(name='Field', options=self.model.fields) field_select.on_change('value', self.on_field_change) aggregate_select = Select.create(name='Aggregate', options=self.model.aggregate_functions) aggregate_select.on_change('value', self.on_aggregate_change) transfer_select = Select.create(name='Transfer Function', options=self.model.transfer_functions) transfer_select.on_change('value', self.on_transfer_function_change) basemap_select = Select.create(name='Basemap', value='Toner', options=self.model.basemaps) basemap_select.on_change('value', self.on_basemap_change) image_opacity_slider = Slider(title="Opacity", value=100, start=0, end=100, step=1) image_opacity_slider.on_change('value', self.on_image_opacity_slider_change) basemap_opacity_slider = Slider(title="Basemap Opacity", value=100, start=0, end=100, step=1) basemap_opacity_slider.on_change('value', self.on_basemap_opacity_slider_change) show_labels_chk = CheckboxGroup(labels=["Show Labels"], active=[0]) show_labels_chk.on_click(self.on_labels_change) controls = [axes_select, field_select, aggregate_select, transfer_select] map_controls = [basemap_select, basemap_opacity_slider, image_opacity_slider, show_labels_chk] self.controls = VBox(width=200, height=600, children=controls) self.map_controls = HBox(width=self.fig.plot_width, children=map_controls) self.map_area = VBox(width=self.fig.plot_width, children=[self.map_controls, self.fig]) self.layout = HBox(width=1024, children=[self.controls, self.map_area])