def test_callback_property_executes(self, bokeh_model_page): group = CheckboxButtonGroup(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 .bk-btn:nth-child(3)') el.click() results = page.results assert results['active'] == [2] el = page.driver.find_element_by_css_selector('.foo .bk-btn:nth-child(1)') el.click() results = page.results assert results['active'] == [0, 2] el = page.driver.find_element_by_css_selector('.foo .bk-btn:nth-child(3)') 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 = CheckboxButtonGroup(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 create(palm): energy_min = palm.energy_range.min() energy_max = palm.energy_range.max() energy_npoints = palm.energy_range.size current_results = (0, 0, 0, 0) doc = curdoc() # Streaked and reference waveforms plot waveform_plot = Plot( title=Title(text="eTOF waveforms"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools waveform_plot.toolbar.logo = None waveform_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes waveform_plot.add_layout(LinearAxis(axis_label="Photon energy, eV"), place="below") waveform_plot.add_layout(LinearAxis(axis_label="Intensity", major_label_orientation="vertical"), place="left") # ---- grid lines waveform_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) waveform_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs waveform_source = ColumnDataSource( dict(x_str=[], y_str=[], x_ref=[], y_ref=[])) waveform_ref_line = waveform_plot.add_glyph( waveform_source, Line(x="x_ref", y="y_ref", line_color="blue")) waveform_str_line = waveform_plot.add_glyph( waveform_source, Line(x="x_str", y="y_str", line_color="red")) # ---- legend waveform_plot.add_layout( Legend(items=[("reference", [waveform_ref_line]), ("streaked", [waveform_str_line])])) waveform_plot.legend.click_policy = "hide" # Cross-correlation plot xcorr_plot = Plot( title=Title(text="Waveforms cross-correlation"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools xcorr_plot.toolbar.logo = None xcorr_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes xcorr_plot.add_layout(LinearAxis(axis_label="Energy shift, eV"), place="below") xcorr_plot.add_layout(LinearAxis(axis_label="Cross-correlation", major_label_orientation="vertical"), place="left") # ---- grid lines xcorr_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) xcorr_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs xcorr_source = ColumnDataSource(dict(lags=[], xcorr1=[], xcorr2=[])) xcorr_plot.add_glyph( xcorr_source, Line(x="lags", y="xcorr1", line_color="purple", line_dash="dashed")) xcorr_plot.add_glyph(xcorr_source, Line(x="lags", y="xcorr2", line_color="purple")) # ---- vertical span xcorr_center_span = Span(location=0, dimension="height") xcorr_plot.add_layout(xcorr_center_span) # Delays plot pulse_delay_plot = Plot( title=Title(text="Pulse delays"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools pulse_delay_plot.toolbar.logo = None pulse_delay_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes pulse_delay_plot.add_layout(LinearAxis(axis_label="Pulse number"), place="below") pulse_delay_plot.add_layout( LinearAxis(axis_label="Pulse delay (uncalib), eV", major_label_orientation="vertical"), place="left", ) # ---- grid lines pulse_delay_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) pulse_delay_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs pulse_delay_source = ColumnDataSource(dict(pulse=[], delay=[])) pulse_delay_plot.add_glyph( pulse_delay_source, Line(x="pulse", y="delay", line_color="steelblue")) # ---- vertical span pulse_delay_plot_span = Span(location=0, dimension="height") pulse_delay_plot.add_layout(pulse_delay_plot_span) # Pulse lengths plot pulse_length_plot = Plot( title=Title(text="Pulse lengths"), x_range=DataRange1d(), y_range=DataRange1d(), plot_height=PLOT_CANVAS_HEIGHT, plot_width=PLOT_CANVAS_WIDTH, toolbar_location="right", ) # ---- tools pulse_length_plot.toolbar.logo = None pulse_length_plot.add_tools(PanTool(), BoxZoomTool(), WheelZoomTool(), ResetTool()) # ---- axes pulse_length_plot.add_layout(LinearAxis(axis_label="Pulse number"), place="below") pulse_length_plot.add_layout( LinearAxis(axis_label="Pulse length (uncalib), eV", major_label_orientation="vertical"), place="left", ) # ---- grid lines pulse_length_plot.add_layout(Grid(dimension=0, ticker=BasicTicker())) pulse_length_plot.add_layout(Grid(dimension=1, ticker=BasicTicker())) # ---- line glyphs pulse_length_source = ColumnDataSource(dict(x=[], y=[])) pulse_length_plot.add_glyph(pulse_length_source, Line(x="x", y="y", line_color="steelblue")) # ---- vertical span pulse_length_plot_span = Span(location=0, dimension="height") pulse_length_plot.add_layout(pulse_length_plot_span) # Folder path text input def path_textinput_callback(_attr, _old_value, new_value): save_textinput.value = new_value path_periodic_update() path_textinput = TextInput(title="Folder Path:", value=os.path.join(os.path.expanduser("~")), width=510) path_textinput.on_change("value", path_textinput_callback) # Saved runs dropdown menu def h5_update(pulse, delays, debug_data): prep_data, lags, corr_res_uncut, corr_results = debug_data waveform_source.data.update( x_str=palm.energy_range, y_str=prep_data["1"][pulse, :], x_ref=palm.energy_range, y_ref=prep_data["0"][pulse, :], ) xcorr_source.data.update(lags=lags, xcorr1=corr_res_uncut[pulse, :], xcorr2=corr_results[pulse, :]) xcorr_center_span.location = delays[pulse] pulse_delay_plot_span.location = pulse pulse_length_plot_span.location = pulse # this placeholder function should be reassigned in 'saved_runs_dropdown_callback' h5_update_fun = lambda pulse: None def update_saved_runs(saved_run): new_value = saved_run if new_value != "Saved Runs": nonlocal h5_update_fun, current_results saved_runs_dropdown.label = new_value filepath = os.path.join(path_textinput.value, new_value) tags, delays, lengths, debug_data = palm.process_hdf5_file( filepath, debug=True) current_results = (new_value, tags, delays, lengths) if autosave_checkbox.active: save_button_callback() pulse_delay_source.data.update(pulse=np.arange(len(delays)), delay=delays) pulse_length_source.data.update(x=np.arange(len(lengths)), y=lengths) h5_update_fun = partial(h5_update, delays=delays, debug_data=debug_data) pulse_slider.end = len(delays) - 1 pulse_slider.value = 0 h5_update_fun(0) def saved_runs_dropdown_callback(event): update_saved_runs(event.item) saved_runs_dropdown = Dropdown(label="Saved Runs", button_type="primary", menu=[]) saved_runs_dropdown.on_click(saved_runs_dropdown_callback) # ---- saved run periodic update def path_periodic_update(): new_menu = [] if os.path.isdir(path_textinput.value): for entry in os.scandir(path_textinput.value): if entry.is_file() and entry.name.endswith((".hdf5", ".h5")): new_menu.append((entry.name, entry.name)) saved_runs_dropdown.menu = sorted(new_menu, reverse=True) doc.add_periodic_callback(path_periodic_update, 5000) # Pulse number slider def pulse_slider_callback(_attr, _old_value, new_value): h5_update_fun(pulse=new_value) pulse_slider = Slider( start=0, end=99999, value_throttled=0, step=1, title="Pulse ID", ) pulse_slider.on_change("value_throttled", pulse_slider_callback) # Energy maximal range value text input def energy_max_spinner_callback(_attr, old_value, new_value): nonlocal energy_max if new_value > energy_min: energy_max = new_value palm.energy_range = np.linspace(energy_min, energy_max, energy_npoints) update_saved_runs(saved_runs_dropdown.label) else: energy_max_spinner.value = old_value energy_max_spinner = Spinner(title="Maximal Energy, eV:", value=energy_max, step=0.1) energy_max_spinner.on_change("value", energy_max_spinner_callback) # Energy minimal range value text input def energy_min_spinner_callback(_attr, old_value, new_value): nonlocal energy_min if new_value < energy_max: energy_min = new_value palm.energy_range = np.linspace(energy_min, energy_max, energy_npoints) update_saved_runs(saved_runs_dropdown.label) else: energy_min_spinner.value = old_value energy_min_spinner = Spinner(title="Minimal Energy, eV:", value=energy_min, step=0.1) energy_min_spinner.on_change("value", energy_min_spinner_callback) # Energy number of interpolation points text input def energy_npoints_spinner_callback(_attr, old_value, new_value): nonlocal energy_npoints if new_value > 1: energy_npoints = new_value palm.energy_range = np.linspace(energy_min, energy_max, energy_npoints) update_saved_runs(saved_runs_dropdown.label) else: energy_npoints_spinner.value = old_value energy_npoints_spinner = Spinner(title="Number of interpolation points:", value=energy_npoints) energy_npoints_spinner.on_change("value", energy_npoints_spinner_callback) # Save location save_textinput = TextInput(title="Save Folder Path:", value=os.path.join(os.path.expanduser("~"))) # Autosave checkbox autosave_checkbox = CheckboxButtonGroup(labels=["Auto Save"], active=[], width=250) # Save button def save_button_callback(): if current_results[0]: filename, tags, delays, lengths = current_results save_filename = os.path.splitext(filename)[0] + ".csv" df = pd.DataFrame({ "pulse_id": tags, "pulse_delay": delays, "pulse_length": lengths }) df.to_csv(os.path.join(save_textinput.value, save_filename), index=False) save_button = Button(label="Save Results", button_type="default", width=250) save_button.on_click(save_button_callback) # assemble tab_layout = column( row( column(waveform_plot, xcorr_plot), Spacer(width=30), column( path_textinput, saved_runs_dropdown, pulse_slider, Spacer(height=30), energy_min_spinner, energy_max_spinner, energy_npoints_spinner, Spacer(height=30), save_textinput, autosave_checkbox, save_button, ), ), row(pulse_delay_plot, Spacer(width=10), pulse_length_plot), ) return Panel(child=tab_layout, title="HDF5 File")
# Radio buttons to choose time scale radioLabels = ['day','week','month'] radio = RadioGroup(labels=radioLabels,active=1) def radioCallback(active): timerange = radioLabels[active] print(timerange) global slot global space tooltips,slot, space = updateToolTips(timerange) data161subset = data161.iloc[startPt:startPt+slot:space,:] dataSource.data.update(ColumnDataSource(data161subset).data) radio.on_click(radioCallback) # Buttons to choose which sources are shown checkbuttons = CheckboxButtonGroup(labels=zlist, active=[0,1,2]) def checkboxCallback(active): global showcols showcols=[] print(active) for activeItem in active: showcols.append(' '+zlist[activeItem].lower()) print(showcols) for colRef,line in enumerate(ylist,1): if line in showcols: dictOfLines[line].visible = True else: dictOfLines[line].visible = False checkbuttons.on_click(checkboxCallback) # Button to update axis
plot_figure = figure(title='Checkbox Button Group', height=450, width=600, tools="save,reset", toolbar_location="below") plot_figure.scatter('x', 'y', source=source, size=10, color={ 'field': 'z', 'transform': color_mapper }) checkbox_button = CheckboxButtonGroup( labels=['Show x-axis label', 'Show y-axis label']) def checkbox_button_click(attr, old, new): active_checkbox = checkbox_button.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):
conso_source = ColumnDataSource(data=dict(date=[], conso=[], diff=[])) datetime_source = ColumnDataSource(data=dict(date=[], conso=[])) # Inputs print("Building page") button = Button(label="Close") sector_select = Select(title="Secteur", value="1", options=list(map(str, range(1, n_sectors)))) date_slider = Slider(title="Date", start=dates.min().day, end=dates.max().day, step=1, value=dates.min().day) time_slider = Slider(title="Heure", start=0, end=23, step=1, value=0) type_button = CheckboxButtonGroup(labels=["Secteur", "Signal"], active=[0]) # Plots class MapPlot(object): def __init__(self): self.map_plot = Figure( tools="pan,wheel_zoom,tap", toolbar_location="right", logo=None, min_border=0, min_border_left=0, **get_paris_extent(0.6), # x_range & y_range plot_width=1100, plot_height=650) self.map_plot.add_tile(tile_source=OSM_TILE_SOURCE) self.map_plot_renderer = self.map_plot.patches( source=geo_source, xs="xs", ys="ys",
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") text_input = TextInput(placeholder="Enter value ...") completions = ["aaa", "aab", "aac", "baa", "caa"]
click_button = Button(label="Button still has click event", button_type="success") 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) text_input = TextInput(placeholder="Enter value ...") completions = ["aaa", "aab", "aac", "baa", "caa"] autocomplete_input = AutocompleteInput(placeholder="Enter value (auto-complete) ...", completions=completions) select = Select(options=["Option 1", "Option 2", "Option 3"]) multi_select = MultiSelect(options=["Option %d" % (i+1) for i in range(16)], size=6) slider = Slider(value=10, start=0, end=100, step=0.5) range_slider = RangeSlider(value=[10, 90], start=0, end=100, step=0.5)
else: af_button.button_type = 'success' if not animating: pc_id_f = doc.add_periodic_callback(unlocked_task, 200) animating = True else: doc.remove_periodic_callback(pc_id_f) animating = False af_button.on_click(af_callback) LABELS = ["legend", "symbols"] checkbox_button_group = CheckboxButtonGroup(labels=LABELS, active=[0]) labels.visible = False def check_btn_callback(attr): if 1 in attr: print("SYMBOLS ON") labels.visible = True else: print("SYMBOLS OFF") labels.visible = False if 0 in attr: print("LEGEND ON") plot.legend.visible = True else: print("LEGEND OFF")
def TabParcialesPausas(df): """ PREPARACION DE DATOS """ # Calculo de los valores agregados AVG_Altitud, MAX_Altitud, MIN_Altitud, \ AVG_Velocidad, MAX_Velocidad, MIN_Velocidad, \ AVG_Ritmo, MAX_Ritmo, MIN_Ritmo, \ AVG_FrecuenciaCardiaca, MAX_FrecuenciaCardiaca, MIN_FrecuenciaCardiaca, \ AVG_Cadencia, MAX_Cadencia, MIN_Cadencia, \ AVG_Temperatura, MAX_Temperatura, MIN_Temperatura, \ AVG_LongitudZancada, MAX_LongitudZancada, MIN_LongitudZancada, \ AVG_Pendiente, MAX_Pendiente , MIN_Pendiente = CalculosVectoresAgregados(df) # Calculo de desniveles finales DesnivelPositivo = df['DesnivelPositivoAcumulado'].max() DesnivelNegativo = df['DesnivelNegativoAcumulado'].max() DesnivelAcumulado = DesnivelPositivo + DesnivelNegativo DesnivelPorKilometro = (DesnivelAcumulado / df['Distancia'].max()) * 1000 # Factor de achatamiento de la altitud if DesnivelPorKilometro > 40: OffsetSuperiorAltitud = 0.1 OffsetInferiorAltitud = 0.03 else: OffsetSuperiorAltitud = 2.5 OffsetInferiorAltitud = 0.5 dfTramosPausas = TablaParcialesPausas(df) dfTramosPausas['Ritmo_STR'] = dfTramosPausas.Ritmo.apply( lambda x: FormateoTiempos(x, 'R')) # Seleccion de un subconjunto de datos para visualizar dfBokehParcialesPausas = df[[ 'Bloque', 'Distancia', 'Altitud', 'FrecuenciaCardiaca', 'Cadencia' ]].copy() dfBokehParcialesPausas['AltitudEscalada'] = Reescalado( dfBokehParcialesPausas['Altitud'], [ MIN_Altitud[0] - (MAX_Altitud[0] - MIN_Altitud[0]) * OffsetInferiorAltitud, MAX_Altitud[0] + (MAX_Altitud[0] - MIN_Altitud[0]) * OffsetSuperiorAltitud ], [0, dfTramosPausas.Velocidad.max()]) dfBokehParcialesPausas['FrecuenciaCardiacaEscalada'] = Reescalado( dfBokehParcialesPausas['FrecuenciaCardiaca'], [MIN_FrecuenciaCardiaca[0], MAX_FrecuenciaCardiaca[0]], [0, dfTramosPausas.Velocidad.max()]) dfBokehParcialesPausas['CadenciaEscalada'] = Reescalado( dfBokehParcialesPausas['Cadencia'], [MIN_Cadencia[0], MAX_Cadencia[0]], [0, dfTramosPausas.Velocidad.max()]) OrigenTramosPausa = ColumnDataSource(dfBokehParcialesPausas) # Reducion de la frecuencia de muestreo dfBokehParcialesPausas_Agg = dfBokehParcialesPausas.groupby( 'Bloque').resample('10S').agg({ 'Distancia': np.max, 'Cadencia': np.mean }) dfBokehParcialesPausas_Agg['Cadencia'] = dfBokehParcialesPausas_Agg[ 'Cadencia'].round() dfBokehParcialesPausas_Agg['CadenciaEscalada'] = Reescalado( dfBokehParcialesPausas_Agg['Cadencia'], [MIN_Cadencia[0], MAX_Cadencia[0]], [0, dfTramosPausas.Velocidad.max()]) # Creacion de los ColumnDataSource de origen de Bokeh OrigenParcialesPausa = ColumnDataSource(dfBokehParcialesPausas) OrigenParcialesPausa_Agg = ColumnDataSource(dfBokehParcialesPausas_Agg) OrigenTramosPausa = ColumnDataSource(dfTramosPausas) # Asignacion de tamaño segun el total de puntos if df['Distancia'].max() < 5: SizeCircle = 10 elif df['Distancia'].max() < 10: SizeCircle = 8 else: SizeCircle = 5 # Definicion de la paleta de colores por cadencia MapaColorCadencia = LinearColorMapper(palette=paleta_cadencia, low=110, high=190) """ TRAMOS POR PAUSAS """ PLT_TramosPausas = figure(plot_width=900, plot_height=500, x_range=(0, df['Distancia'].max()), y_range=(0, dfTramosPausas.Velocidad.max() + dfTramosPausas.Velocidad.max() * 0.1), tools='', toolbar_location=None) PLT_TramosPausas.add_layout( Span(location=AVG_Velocidad[0], dimension='width', line_color=BlueJeans[2], line_dash='dashed', line_width=1, line_alpha=0.7)) PLT_TramosPausas.rect(x='x', y='y', width='Distancia', height='Velocidad', source=OrigenTramosPausa, line_width=1, line_color=BlueJeans[2], fill_color=BlueJeans[1]) PLT_TramosPausas.add_tools( HoverTool(tooltips=[('', '@Ritmo_STR')], mode='mouse')) PropiedadesLineas = dict(line_width=2, line_alpha=0.7, line_cap='round', visible=False) PLT_TramosPausas_Altitud = PLT_TramosPausas.line( 'Distancia', 'AltitudEscalada', source=OrigenParcialesPausa, color=paleta_verde[6], **PropiedadesLineas) PLT_TramosPausas_FC = PLT_TramosPausas.line('Distancia', 'FrecuenciaCardiacaEscalada', source=OrigenParcialesPausa, color=paleta_rojo[6], **PropiedadesLineas) PLT_TramosPausas_Cadencia = PLT_TramosPausas.circle( 'Distancia', 'CadenciaEscalada', source=OrigenParcialesPausa_Agg, size=SizeCircle, line_color=transform('Cadencia', MapaColorCadencia), color=transform('Cadencia', MapaColorCadencia), fill_alpha=1, visible=False) # Atributos PLT_TramosPausas.title.text = 'RITMO MEDIO POR BLOQUES' PLT_TramosPausas.xaxis.axis_label = 'Distancia' PLT_TramosPausas.xaxis.formatter = NumeralTickFormatter(format='0 a') PLT_TramosPausas.yaxis.axis_label = 'Ritmo [min/km]' PLT_TramosPausas.grid.visible = False PLT_TramosPausas.yaxis.major_label_overrides = { 1: '16:40', 1.5: '16:06', 2: '8:20', 2.5: '6:40', 3: '5:33', 3.5: '4:45', 4: '4:10', 4.5: '3:42', 5: '3:20', 5.5: '3:01', 6: '2:46', 6.5: '2:34', 7: '2:22' } PLT_TramosPausas.xaxis.ticker = SingleIntervalTicker(interval=1000) PLT_TramosPausas.xaxis.major_label_overrides = FormateoEjes( OrigenParcialesPausa.data['Distancia'], 1000, 1000, 0, 0) """ DATOS EN FORMA DE TABLA POR PAUSAS """ TablaPausas = [ TableColumn(field='TramoKm', title='Km', width=40, default_sort='ascending', sortable=False, formatter=StringFormatter(font_style='normal', text_align='center', text_color='black')), TableColumn(field='Ritmo_STR', title='Ritmo[min/Km]', width=80, default_sort='ascending', sortable=False, formatter=StringFormatter(font_style='normal', text_align='center', text_color='black')), TableColumn(field='FrecuenciaCardiaca', title='FC[ppm]', width=80, default_sort='ascending', sortable=False, formatter=NumberFormatter(format='0,0', language='es', rounding='round', font_style='normal', text_align='center', text_color='black')), TableColumn(field='Cadencia', title='Cadencia[ppm]', width=80, default_sort='ascending', sortable=False, formatter=NumberFormatter(format='0,0', language='es', rounding='round', font_style='normal', text_align='center', text_color='black')), TableColumn(field='DesnivelAcumulado', title='Desnivel', width=80, default_sort='ascending', sortable=False, formatter=NumberFormatter(format='0,0', language='es', rounding='round', font_style='normal', text_align='center', text_color='black')) ] PLT_TablaPausas = DataTable(source=OrigenTramosPausa, columns=TablaPausas, width=360, height=550, fit_columns=False, sortable=False, reorderable=False, selectable=True, editable=False, index_position=None, header_row=True, row_height=25) """ BOTONES """ CodigoJS = """ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; l0.visible = indexOf.call(checkbox.active,0)>=0; l1.visible = indexOf.call(checkbox.active,1)>=0; l2.visible = indexOf.call(checkbox.active,2)>=0; """ BotonesTramosPausas = CheckboxButtonGroup( labels=["Altitud", "Frecuencia Cardiaca", "Cadencia"], active=[], width=300, height=30) CodigoJSTramosPausas = CustomJS(code=CodigoJS, args=dict(l0=PLT_TramosPausas_Altitud, l1=PLT_TramosPausas_FC, l2=PLT_TramosPausas_Cadencia, checkbox=BotonesTramosPausas)) BotonesTramosPausas.js_on_click(CodigoJSTramosPausas) """ LAYOUT """ GridGraficaTramosPausas = layout([ Column(PLT_TramosPausas, width=900, height=500), [ Spacer(width=300, height=30), Column(BotonesTramosPausas, width=300, height=30), Spacer(width=300, height=30) ] ], sizing_mode='stretch_width', width=900, height=570) GridTablaTramosPausas = layout([ Spacer(width=360, height=25), Column(PLT_TablaPausas, width=360, height=550) ], sizing_mode='stretch_width', width=360, height=570) GridAnalisisPausas = gridplot( [GridGraficaTramosPausas, GridTablaTramosPausas], ncols=2, sizing_mode='stretch_width', toolbar_location=None, plot_width=1000, plot_height=570) return GridAnalisisPausas
'Dead' ]) init_measure_s = options_s[MEASURES.index(init_measure)] #select = Select(title="Measure", options=list(df.columns.values)[2:11], value=init_measure) select = Select(title="Measure", options=options_s, value=init_measure_s, width=320) select.on_change('value', update_plot) slider = Slider(title='Day', start=0, end=max_time, step=1, value=init_period) slider.on_change('value', update_plot) labels_age = [i.split('Age_')[1].replace('_', ' - ') for i in list(AGEGROUPS)] checkbox_button_group = CheckboxButtonGroup(labels=labels_age, active=[0, 1, 2, 3, 4, 5, 6, 7, 8]) checkbox_button_group.on_change('active', update_plot) ############################################################################## #################################### MAP ##################################### new_data, new_json_data = json_data(init_period, init_agegroups, init_measure) geosource = GeoJSONDataSource(geojson=new_json_data) a, b = new_data.Infected_plus.min(), new_data.Infected_plus.max() #Define a color palette. palette = brewer['YlOrRd'][8] palette = palette[::-1] #Create color bar. #color_mapper = LinearColorMapper(palette = palette, low = a, high = b, nan_color = '#d9d9d9') color_mapper = LogColorMapper(palette=palette,
class WarmUpWidget: def __init__(self, parent=None): self.parent = parent self.fs = main_config['fs'] self.n_channels = main_config['n_channels'] self.t0 = 0 self.last_ts = 0 self.game_is_on = False # Chronogram self.chrono_source = ColumnDataSource(dict(ts=[], y_pred=[])) self.pred_decoding = main_config['pred_decoding'] # LSL stream reader self.lsl_reader = None self.lsl_start_time = None self._lsl_data = (None, None) self.thread_lsl = QtCore.QThreadPool() self.channel_source = ColumnDataSource(dict(ts=[], eeg=[])) self.buffer_size_s = 10 # LSL stream recorder if not os.path.isdir(main_config['record_path']): os.mkdir(main_config['record_path']) self.record_path = main_config['record_path'] self.record_name = warmup_config['record_name'] self.lsl_recorder = None # Predictor self.models_path = main_config['models_path'] self.input_signal = np.zeros((self.n_channels, 4 * self.fs)) self.predictor = None self.thread_pred = QtCore.QThreadPool() self._pred_action = (0, 'Rest') # Feedback images self.static_folder = warmup_config['static_folder'] self.action2image = warmup_config['action2image'] @property def pred_action(self): return self._pred_action @pred_action.setter def pred_action(self, val_tuple): self._pred_action = val_tuple self.parent.add_next_tick_callback(self.update_prediction) @property def lsl_data(self): return self._lsl_data @lsl_data.setter def lsl_data(self, data): self._lsl_data = data self.parent.add_next_tick_callback(self.update_signal) @property def available_models(self): ml_models = [p.name for p in self.models_path.glob('*.pkl')] dl_models = [p.name for p in self.models_path.glob('*.h5')] return [''] + ml_models + dl_models @property def selected_settings(self): active = self.checkbox_settings.active return [self.checkbox_settings.labels[i] for i in active] @property def modelfile(self): return self.models_path / self.select_model.value @property def model_name(self): return self.select_model.value @property def is_convnet(self): return self.select_model.value.split('.')[-1] == 'h5' @property def channel_idx(self): return int(self.select_channel.value.split('-')[0]) def reset_lsl(self): if self.lsl_reader: self.lsl_reader.should_stream = False self.lsl_reader = None self.lsl_start_time = None self.thread_lsl.clear() def reset_predictor(self): self.model_info.text = f'<b>Model:</b> None' self.pred_info.text = f'<b>Prediction:</b> None' self.image.text = '' if self.predictor: self.predictor.should_predict = False self.predictor = None self.thread_pred.clear() def reset_recorder(self): if self.lsl_recorder: self.lsl_recorder.close_h5() self.lsl_recorder = None def on_settings_change(self, attr, old, new): self.plot_stream.visible = 0 in new def on_model_change(self, attr, old, new): logging.info(f'Select new pre-trained model {new}') self.select_model.options = self.available_models # Delete existing predictor thread if self.predictor is not None: self.reset_predictor() if new == '': return try: self.predictor = ActionPredictor(self, self.modelfile, self.is_convnet) self.thread_pred.start(self.predictor) self.model_info.text = f'<b>Model:</b> {new}' except Exception as e: logging.error(f'Failed loading model {self.modelfile} - {e}') self.reset_predictor() def on_channel_change(self, attr, old, new): logging.info(f'Select new channel {new}') self.channel_source.data = dict(ts=[], eeg=[]) self.plot_stream.yaxis.axis_label = f'Amplitude ({new})' def reset_plots(self): self.chrono_source.data = dict(ts=[], y_pred=[]) self.channel_source.data = dict(ts=[], eeg=[]) def update_prediction(self): # Update chronogram source action_idx = self.pred_action[0] if self.lsl_start_time is not None: ts = time.time() - self.lsl_start_time self.chrono_source.stream(dict(ts=[ts], y_pred=[action_idx])) # Update information display (might cause delay) self.pred_info.text = f'<b>Prediction:</b> {self.pred_action}' src = self.static_folder / \ self.action2image[self.pred_decoding[action_idx]] self.image.text = f"<img src={src} width='200' height='200' text-align='center'>" # Save prediction as event if self.lsl_recorder is not None: self.lsl_recorder.save_event(copy.deepcopy(self.last_ts), copy.deepcopy(action_idx)) def on_lsl_connect_toggle(self, active): if active: # Connect to LSL stream self.button_lsl.label = 'Seaching...' self.button_lsl.button_type = 'warning' self.reset_plots() self.parent.add_next_tick_callback(self.start_lsl_thread) else: self.reset_lsl() self.reset_predictor() self.button_lsl.label = 'LSL Disconnected' self.button_lsl.button_type = 'danger' def start_lsl_thread(self): try: self.lsl_reader = LSLClient(self) self.fs = self.lsl_reader.fs if self.lsl_reader is not None: self.select_channel.options = [ f'{i+1} - {ch}' for i, ch in enumerate(self.lsl_reader.ch_names) ] self.thread_lsl.start(self.lsl_reader) self.button_lsl.label = 'Reading LSL stream' self.button_lsl.button_type = 'success' except Exception: logging.info(f'No LSL stream - {traceback.format_exc()}') self.button_lsl.label = 'Can\'t find stream' self.button_lsl.button_type = 'danger' self.reset_lsl() def on_lsl_record_toggle(self, active): if active: try: self.lsl_recorder = LSLRecorder(self.record_path, self.record_name, self.lsl_reader.ch_names) self.lsl_recorder.open_h5() self.button_record.label = 'Stop recording' self.button_record.button_type = 'success' except Exception as e: logging.info(f'Failed creating LSLRecorder - {e}') self.reset_recorder() self.button_record.label = 'Recording failed' self.button_record.button_type = 'danger' else: self.reset_recorder() self.button_record.label = 'Start recording' self.button_record.button_type = 'primary' def update_signal(self): ts, eeg = self.lsl_data self.last_ts = ts[-1] if ts.shape[0] != eeg.shape[-1]: logging.info('Skipping data points (bad format)') return # Local LSL start time if self.lsl_start_time is None: self.lsl_start_time = time.time() self.t0 = ts[0] # Update source display ch = self.channel_idx self.channel_source.stream(dict(ts=(ts - self.t0) / self.fs, eeg=eeg[ch, :]), rollover=int(self.buffer_size_s * self.fs)) # Update signal chunk_size = eeg.shape[-1] self.input_signal = np.roll(self.input_signal, -chunk_size, axis=-1) self.input_signal[:, -chunk_size:] = eeg # Record signal if self.lsl_recorder is not None: self.lsl_recorder.save_data(copy.deepcopy(ts), copy.deepcopy(eeg)) def create_widget(self): # Toggle - Connect to LSL stream self.button_lsl = Toggle(label='Connect to LSL') self.button_lsl.on_click(self.on_lsl_connect_toggle) # Toggle - Start/stop LSL stream recording self.button_record = Toggle(label='Start Recording', button_type='primary') self.button_record.on_click(self.on_lsl_record_toggle) # Select - Choose pre-trained model self.select_model = Select(title="Select pre-trained model") self.select_model.options = self.available_models self.select_model.on_change('value', self.on_model_change) # Checkbox - Choose settings self.div_settings = Div(text='<b>Settings</b>', align='center') self.checkbox_settings = CheckboxButtonGroup(labels=['Show signal']) self.checkbox_settings.on_change('active', self.on_settings_change) # Select - Channel to visualize self.select_channel = Select(title='Select channel', value='1 - Fp1') self.select_channel.on_change('value', self.on_channel_change) # Plot - LSL EEG Stream self.plot_stream = figure(title='Temporal EEG signal', x_axis_label='Time [s]', y_axis_label='Amplitude', plot_height=500, plot_width=800, visible=False) self.plot_stream.line(x='ts', y='eeg', source=self.channel_source) # Plot - Chronogram prediction vs results self.plot_chronogram = figure(title='Chronogram', x_axis_label='Time [s]', y_axis_label='Action', plot_height=300, plot_width=800) self.plot_chronogram.cross(x='ts', y='y_pred', color='red', source=self.chrono_source, legend_label='Prediction') self.plot_chronogram.legend.background_fill_alpha = 0.6 self.plot_chronogram.yaxis.ticker = list(self.pred_decoding.keys()) self.plot_chronogram.yaxis.major_label_overrides = self.pred_decoding # Div - Display useful information self.model_info = Div(text=f'<b>Model:</b> None') self.pred_info = Div(text=f'<b>Prediction:</b> None') self.image = Div() # Create layout column1 = column(self.button_lsl, self.button_record, self.select_model, self.select_channel, self.div_settings, self.checkbox_settings) column2 = column(self.plot_stream, self.plot_chronogram) column3 = column(self.model_info, self.pred_info, self.image) return row(column1, column2, column3)
source.data = dict(source2.data) table = result4.copy() table["Date_reported"] = table["Date_reported"].dt.strftime('%d/%m/%Y') table = table[[ 'Date_reported', ' Country', ' Country_code', ' New_cases', ' Cumulative_cases', ' New_deaths', ' Cumulative_deaths', ' WHO_region', 'udzial_w_populacji' ]] Columns = [TableColumn(field=Ci, title=Ci) for Ci in table.columns] data_table_source2 = ColumnDataSource(table) data_table_source.data = dict(data_table_source2.data) # 1. europa / świat opcje = ["Europa", "poza Europa"] checkbox_button_group = CheckboxButtonGroup(labels=opcje, active=[]) checkbox_button_group.on_change('active', update_x) # 2. button - najwięcej zgonów button = Button(label='The highest number of deaths') button.on_click(deaths) # 3. slider po liczebności slider = Slider(start=0, end=10, step=1, value=0, title='Change the range of the x axis') slider.on_change('value', x_range) # 4.select okres
source=d2) renderer['lines'] = p2.line(x="xs", y="ys", line_width=2, source=d2) def callback_glyphs(new): print("Active Checkboxes:", new) renderer['circles'].visible = False renderer['lines'].visible = False if 0 in new: renderer['circles'].visible = True if 1 in new: renderer['lines'].visible = True btn_glyphs = CheckboxButtonGroup(labels=["Circles", "Lines"], active=[0, 1]) btn_glyphs.on_click(callback_glyphs) """ ======================= Two Axes ======================= """ d_axis_1 = ColumnDataSource(dict(xs=np.arange(0, 10), ys=np.random.rand(10))) d_axis_2 = ColumnDataSource( dict(xs=np.arange(0, 10), ys=np.random.rand(10) * 100)) p_axis = figure(plot_width=400, plot_height=400, y_range=(0.0, 1.0)) p_axis.line(x="xs", y="ys", line_width=2, source=d_axis_1)
TableColumn(field='cage baffle', title='cage baffle', width=63, editor=SelectEditor(options=['on', 'off', '?'])), TableColumn(field='barrel insulation', title='barrel insulation', width=85, editor=SelectEditor(options=['on', 'off', '?'])), TableColumn(field='operator', title='operator', width=70, editor=SelectEditor(options=sorted(fpa_experts)+['?'])), TableColumn(field='data path', title='data path', width=700)] table = DataTable(source=source, columns=columns, editable=True, sortable=False, reorderable=False, fit_columns=False, default_size=1300, height=min(27*pcm.len+30, 600), min_width=1300, sizing_mode='stretch_width') plot_bt = Button(label="Plot Selected Calibration", button_type='primary', width=300) ptls_bt_group = CheckboxButtonGroup(labels=[f'PC{i:02}' for i in range(10)], active=pcm.pcids, width=300) def change_selected_calibration(attr, old, new): pcm.i_selected = new[0] print('selection changed', attr, old, pcm.i_selected) def on_change_source_data(attr, old, new): # old, new, source.data are all the same print('Source changed, updating manager data and saving to disk') pcm.table = new pcm.table_dict_to_df() def change_ptls(attr, old, new):
dropdown_disabled = Dropdown(label="Dropdown button (disabled)", button_type="warning", disabled=True, menu=menu) dropdown_disabled.js_on_event("button_click", CustomJS(code="console.log('dropdown(disabled): click ' + this.toString())")) dropdown_disabled.js_on_event("menu_item_click", CustomJS(code="console.log('dropdown(disabled): ' + this.item, this.toString())")) dropdown_split = Dropdown(label="Split button", split=True, button_type="danger", menu=menu) dropdown_split.js_on_event("button_click", CustomJS(code="console.log('dropdown(split): click ' + this.toString())")) dropdown_split.js_on_event("menu_item_click", CustomJS(code="console.log('dropdown(split): ' + this.item, this.toString())")) checkbox_group = CheckboxGroup(labels=["Option 1", "Option 2", "Option 3"], active=[0, 1]) checkbox_group.js_on_change('active', CustomJS(code="console.log('checkbox_group: active=' + this.active, this.toString())")) radio_group = RadioGroup(labels=["Option 1", "Option 2", "Option 3"], active=0) radio_group.js_on_change('active', CustomJS(code="console.log('radio_group: active=' + this.active, this.toString())")) checkbox_button_group = CheckboxButtonGroup(labels=["Option 1", "Option 2", "Option 3"], active=[0, 1]) checkbox_button_group.js_on_event("button_click", CustomJS(code="console.log('checkbox_button_group: active=' + this.origin.active, this.toString())")) radio_button_group = RadioButtonGroup(labels=["Option 1", "Option 2", "Option 3"], active=0) radio_button_group.js_on_event("button_click", CustomJS(code="console.log('radio_button_group: active=' + this.origin.active, this.toString())")) widget_box = Column(children=[ button, button_disabled, toggle_inactive, toggle_active, dropdown, dropdown_disabled, dropdown_split, checkbox_group, radio_group, checkbox_button_group, radio_button_group, ]) doc = Document() doc.add_root(widget_box)
def plot_time_series(activity: models.Activity): """ Plotting function to create the time series plots shown in tha activity page. Depending on what data is available this creates the following plots: - Altitude - Heart Rate - Speed - Cadence - Temperature All plots share a connected vertical cross hair tools. Parameters ---------- activity : models.Activity Activity model containing the required activity for which the plots should be generated Returns ------- script, div : tuple(str, str) the html script and div elements used to render the plots in the html templates """ attributes = activity.trace_file.__dict__ coordinates = json.loads(attributes["coordinates_list"]) initial_list_of_distances = [] list_of_distances = [] if coordinates: initial_list_of_distances = convert_list_to_km( json.loads(attributes['distance_list'])) list_of_distances = extend_list_to_have_length( length=len(coordinates), input_list=initial_list_of_distances) lap_data = models.Lap.objects.filter(trace=activity.trace_file) plots = [] lap_lines = [] for attribute, values in attributes.items(): if attribute in attributes_to_create_time_series_plot_for: values = json.loads(values) if values: attribute = attribute.replace("_list", "") if activity.distance: x_axis = extend_list_to_have_length( length=len(values), input_list=initial_list_of_distances) p = figure(plot_height=int(settings.PLOT_HEIGHT / 2.5), sizing_mode='stretch_width', y_axis_label=plot_matrix[attribute]["axis"], x_range=(0, x_axis[-1])) lap = _add_laps_to_plot(laps=lap_data, plot=p, y_values=values) x_hover = ("Distance", "@x km") else: # activity has no distance data, use time for x-axis instead timestamps_list = json.loads(attributes["timestamps_list"]) start = timestamp_to_local_time(timestamps_list[0]) x_axis = [ timestamp_to_local_time(t) - start for t in timestamps_list ] x_axis, values = cut_list_to_have_same_length( x_axis, values) p = figure(x_axis_type='datetime', plot_height=int(settings.PLOT_HEIGHT / 2.5), sizing_mode='stretch_width', y_axis_label=plot_matrix[attribute]["axis"]) lap = _add_laps_to_plot(laps=lap_data, plot=p, y_values=values, x_start_value=x_axis[0], use_time=True) x_hover = ("Time", "@x") lap_lines += lap p.toolbar.logo = None p.toolbar_location = None p.xgrid.grid_line_color = None if attribute == 'cadence': p.scatter(x_axis, values, radius=0.01, fill_alpha=1, color=plot_matrix[attribute]["color"], legend_label=plot_matrix[attribute]["title"]) elif attribute == 'altitude': p.varea(x_axis, values, [min(values) for i in range(len(values))], color=plot_matrix[attribute]["second_color"], fill_alpha=0.5) p.line(x_axis, values, line_width=2, color=plot_matrix[attribute]["color"], legend_label=plot_matrix[attribute]["title"]) else: p.line(x_axis, values, line_width=2, color=plot_matrix[attribute]["color"], legend_label=plot_matrix[attribute]["title"]) hover = HoverTool(tooltips=[ (plot_matrix[attribute]['title'], f"@y {plot_matrix[attribute]['axis']}"), x_hover ], mode='vline') p.add_tools(hover) cross = CrosshairTool(dimensions="height") p.add_tools(cross) p.legend.location = "top_left" p.legend.label_text_font = "ubuntu" p.legend.background_fill_alpha = 0.9 plots.append(p) _link_all_plots_with_each_other(all_plots=plots, x_values=list_of_distances) # TODO # connect all plots and share hovering line # add hover info for each lap line with lap data info all_plots = column(*plots) all_plots.sizing_mode = "stretch_width" if lap_data: log.debug(f"found some Lap data for {activity}: {lap_data}") checkbox = CheckboxButtonGroup(labels=["Show Laps"], active=[0], width=100) js = """ for (line in laps) { laps[line].visible = false; if (typeof markerGroup != "undefined") { markerGroup.removeFrom(map); } } for (i in cb_obj.active) { if (cb_obj.active[i] == 0) { for (line in laps) { laps[line].visible = true; if (typeof markerGroup != "undefined") { markerGroup.addTo(map); } } } } """ callback = CustomJS(args=dict(laps=lap_lines, checkbox=checkbox), code=js) checkbox.js_on_change('active', callback) layout = column(all_plots, checkbox) layout.sizing_mode = 'stretch_width' script, div = components(layout) else: script, div = components(all_plots) return script, div
# define the selection widgets for code, exchange, # TODO: enable widgets that support multi-selection # Elements selection widget from a periodic table code = Select(title='Code', value=codes[0], options=codes) code.on_change('value', lambda attr, old, new: CF.update_code()) exchange = Select(title='ExchangeCorrelation', value=exchanges[0], options=exchanges) exchange.on_change('value', lambda attr, old, new: CF.update_exchange()) struct = Select(title='Structure', value=structures[0], options=structures) struct.on_change('value', lambda attr, old, new: CF.update_struct()) element = CheckboxButtonGroup(labels=_elements, active=[1]) element.on_click(CF.update_element) prop = Select(title='Property', value=properties[0], options=properties) prop.on_change('value', lambda attr, old, new: CF.update_prop()) apply_crossfilter = Button(label='CrossFilter and Plot') apply_crossfilter.on_click(CF.update_crossfilter) clean_crossfilter = Button(label='Clear') clean_crossfilter.on_click(CF.clear_crossfilter) x_select.on_change('value', lambda attr, old, new: CF.update_x()) y_select.on_change('value', lambda attr, old, new: CF.update_y())
def Mapa(dfBokeh, DatosBokeh): """ PREPARACION DE DATOS """ # Calculo de los valores agregados AVG_Altitud, MAX_Altitud, MIN_Altitud, \ AVG_Velocidad, MAX_Velocidad, MIN_Velocidad, \ AVG_Ritmo, MAX_Ritmo, MIN_Ritmo, \ AVG_FrecuenciaCardiaca, MAX_FrecuenciaCardiaca, MIN_FrecuenciaCardiaca, \ AVG_Cadencia, MAX_Cadencia, MIN_Cadencia, \ AVG_Temperatura, MAX_Temperatura, MIN_Temperatura, \ AVG_LongitudZancada, MAX_LongitudZancada, MIN_LongitudZancada, \ AVG_Pendiente, MAX_Pendiente , MIN_Pendiente = CalculosVectoresAgregados(dfBokeh) AltitudInicio, AltitudFin = dfBokeh.loc[dfBokeh.index.min() == dfBokeh.index, ['Altitud']].min()[0], dfBokeh.loc[dfBokeh.index.max() == dfBokeh.index, ['Altitud']].min()[0] # Calculo de desniveles finales DesnivelPositivo = dfBokeh['DesnivelPositivoAcumulado'].max() DesnivelNegativo = dfBokeh['DesnivelNegativoAcumulado'].max() DesnivelAcumulado = DesnivelPositivo + DesnivelNegativo DesnivelPorKilometro = (DesnivelAcumulado/dfBokeh['Distancia'].max())*1000 """ MAPA CARTODBPOSITRON CARTODBPOSITRON_RETINA STAMEN_TERRAIN STAMEN_TERRAIN_RETINA STAMEN_TONER STAMEN_TONER_BACKGROUND STAMEN_TONER_LABELS """ # Creacion de un grafica PLT_Mapa = figure(width=900, height=430, x_range=(DatosBokeh.data['LongitudMercator'].min()-100, DatosBokeh.data['LongitudMercator'].max()+100), y_range=(DatosBokeh.data['LatitudMercator'].min()-100, DatosBokeh.data['LatitudMercator'].max()+100), x_axis_type= 'mercator', y_axis_type= 'mercator', tools= 'wheel_zoom, reset, hover') PLT_Mapa.add_tile(get_provider('STAMEN_TERRAIN')) # Inclusion de datos PLT_MP_Linea = PLT_Mapa.line(x= 'LongitudMercator', y= 'LatitudMercator', source= DatosBokeh, line_color= Grapefruit[2], line_width= 3, line_cap= 'round') """ #PLT_Mapa.circle(x= 'LongitudMercator', y= 'LatitudMercator', source= DatosBokeh, size= 5, line_color= None, fill_color= None, fill_alpha= 0, hover_fill_color= 'yellow', hover_line_color = 'black', hover_alpha= 1) #PLT_Mapa.add_tools(HoverTool(tooltips=None, mode='mouse')) """ CoordenadasHitosKm, TiempoTotalKm, TiempoActividadKm, MinDistanciaKm = HitosKilometricos(dfBokeh) CoordenadasPausas, TiempoTotalPausas, TiempoActividadPausas, DistanciasPausas = HitosPausas(dfBokeh) # Ubicacion de puntos de inicio, fin y kilometros LongitudKm =[] LatitudKm =[] PuntoKilometrico = [] for i, Km in enumerate(CoordenadasHitosKm): if i == 0: PLT_Mapa_Inicio = PLT_Mapa.circle(ConversorCoordenadasMercator(Km[1], Km[0])[0], ConversorCoordenadasMercator(Km[1], Km[0])[1], size= 8, line_color= 'black', fill_color= Spectral[2], visible= True) elif i == len(CoordenadasHitosKm)-1: PLT_Mapa_Fin = PLT_Mapa.circle(ConversorCoordenadasMercator(Km[1], Km[0])[0], ConversorCoordenadasMercator(Km[1], Km[0])[1], size= 8, line_color= 'black', fill_color= Spectral[7], visible= True) else: LongitudKm.append(ConversorCoordenadasMercator(Km[1], Km[0])[0]) LatitudKm.append(ConversorCoordenadasMercator(Km[1], Km[0])[1]) PuntoKilometrico.append(str(i)) CDS_PuntosKm = ColumnDataSource(data= dict(Longitud= LongitudKm, Latitud= LatitudKm, PuntoKilometrico= PuntoKilometrico)) PLT_Mapa_PuntoKm = PLT_Mapa.circle(x= 'Longitud', y= 'Latitud', source= CDS_PuntosKm, color= 'white', size= 8, line_color= 'black', fill_color= 'white', visible= True) PLT_Mapa_PuntoKm_TXT = LabelSet(x= 'Longitud', y= 'Latitud', text='PuntoKilometrico', level='glyph', x_offset= 5, y_offset= 0, source= CDS_PuntosKm, render_mode='canvas', text_font_size= '10pt', text_color= 'black', text_align= 'left', text_baseline= 'middle', text_font_style= 'bold', visible= True) PLT_Mapa.add_layout(PLT_Mapa_PuntoKm_TXT) # Ubicacion de pausas LongitudPausa =[] LatitudPausa =[] for i, Km in enumerate(CoordenadasPausas): LongitudPausa.append(ConversorCoordenadasMercator(Km[1], Km[0])[0]) LatitudPausa.append(ConversorCoordenadasMercator(Km[1], Km[0])[1]) PLT_Mapa_Pausas = PLT_Mapa.x(LongitudPausa, LatitudPausa, line_color= 'black', line_width= 2, fill_color= None, visible= False) # Identificacion de pico y valle en trails for index, row in dfBokeh.iterrows(): LongitudMercator, LatitudMercator = ConversorCoordenadasMercator(row.Longitud, row.Latitud) dfBokeh.at[index,'LongitudMercator'] = LongitudMercator dfBokeh.at[index,'LatitudMercator'] = LatitudMercator if (DesnivelPorKilometro > 40) and (MAX_Altitud[0] >= (AltitudInicio + 50) and MAX_Altitud[0] >= (AltitudFin + 50)): PLT_Mapa_Cima = PLT_Mapa.triangle(dfBokeh[dfBokeh['Altitud']==MAX_Altitud[0]]['LongitudMercator'].min(), dfBokeh[dfBokeh['Altitud']==MAX_Altitud[0]]['LatitudMercator'].min(), size= 10, line_color= 'black', line_width= 2, fill_color= Spectral[4], visible= False) PLT_Mapa_Cima_TXT = Label(x= dfBokeh[dfBokeh['Altitud']==MAX_Altitud[0]]['LongitudMercator'].min(), y= dfBokeh[dfBokeh['Altitud']==MAX_Altitud[0]]['LatitudMercator'].min(), text= str(round(MAX_Altitud[0])), x_offset= 5, y_offset= 0, text_font_size= '10pt', text_color= 'black', text_align= 'left', text_baseline= 'middle', text_font_style= 'bold', visible= False) PLT_Mapa.add_layout(PLT_Mapa_Cima_TXT) else: PLT_Mapa_Cima = PLT_Mapa.triangle(0, 0, size= 0, line_alpha= 0, visible= False) PLT_Mapa_Cima_TXT = Label(x= 0, y= 0, text= '', text_font_size= '0pt', text_alpha= 0, visible= False) if (DesnivelPorKilometro > 40) and (MIN_Altitud[0] <= (AltitudInicio - 50) and MIN_Altitud[0] <= (AltitudFin - 50)): PLT_Mapa_Valle = PLT_Mapa.inverted_triangle(dfBokeh[dfBokeh['Altitud']==MIN_Altitud[0]]['LongitudMercator'].min(), dfBokeh[dfBokeh['Altitud']==MIN_Altitud[0]]['LatitudMercator'].min(), size= 10, line_color= 'black', line_width= 2, fill_color= Spectral[0], visible= False) PLT_Mapa_Valle_TXT = Label(x= dfBokeh[dfBokeh['Altitud']==MIN_Altitud[0]]['LongitudMercator'].min(), y= dfBokeh[dfBokeh['Altitud']==MIN_Altitud[0]]['LatitudMercator'].min(), text= str(round(MIN_Altitud[0])), x_offset= 5, y_offset= 0, text_font_size= '10pt', text_color= 'black', text_align= 'left', text_baseline= 'middle', text_font_style= 'bold', visible= False) PLT_Mapa.add_layout(PLT_Mapa_Valle_TXT) else: PLT_Mapa_Valle = PLT_Mapa.inverted_triangle(0, 0, size= 0, line_alpha= 0, visible= False) PLT_Mapa_Valle_TXT = Label(x= 0, y= 0, text= '', text_font_size= '0pt', text_alpha= 0, visible= False) # Atributos PLT_Mapa.sizing_mode = 'fixed' PLT_Mapa.xaxis.major_tick_line_color = None PLT_Mapa.xaxis.minor_tick_line_color = None PLT_Mapa.yaxis.major_tick_line_color = None PLT_Mapa.yaxis.minor_tick_line_color = None PLT_Mapa.xaxis.major_label_text_font_size = '0pt' PLT_Mapa.yaxis.major_label_text_font_size = '0pt' PLT_Mapa.grid.visible = False PLT_Mapa.toolbar.autohide = True # Sin bordes PLT_Mapa.min_border_left = 0 PLT_Mapa.min_border_right = 0 PLT_Mapa.min_border_top = 0 PLT_Mapa.min_border_bottom = 0 # Linea exterior PLT_Mapa.outline_line_width = 3 PLT_Mapa.outline_line_alpha = 0.3 PLT_Mapa.outline_line_color = 'black' """ BOTONES """ CodigoJS = """ var indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; l0.visible = indexOf.call(checkbox.active,0)>=0; l1.visible = indexOf.call(checkbox.active,0)>=0; l2.visible = indexOf.call(checkbox.active,1)>=0; l3.visible = indexOf.call(checkbox.active,1)>=0; l4.visible = indexOf.call(checkbox.active,2)>=0; l5.visible = indexOf.call(checkbox.active,2)>=0; l6.visible = indexOf.call(checkbox.active,2)>=0; l7.visible = indexOf.call(checkbox.active,2)>=0; l8.visible = indexOf.call(checkbox.active,3)>=0; """ BotonesMapa = CheckboxButtonGroup(labels=["INICIO/FIN", "PUNTOS KILOMETRICOS", "CIMA/VALLE", 'PAUSAS'], active=[0, 1], width=300, height=30) CodigoJSMapa = CustomJS(code=CodigoJS, args=dict(l0=PLT_Mapa_Inicio, l1=PLT_Mapa_Fin, l2=PLT_Mapa_PuntoKm, l3= PLT_Mapa_PuntoKm_TXT, l4=PLT_Mapa_Cima, l5=PLT_Mapa_Cima_TXT, l6=PLT_Mapa_Valle, l7=PLT_Mapa_Valle_TXT, l8=PLT_Mapa_Pausas, checkbox= BotonesMapa)) BotonesMapa.js_on_click(CodigoJSMapa) GridMapa = layout([PLT_Mapa, Column(BotonesMapa, width=300, height=35)], sizing_mode='stretch_width', width=900, height=470) return GridMapa
def widgets(): from bokeh.io import show from bokeh.models import Select, CheckboxButtonGroup, Button, CheckboxGroup, ColorPicker, Dropdown, \ FileInput, MultiSelect, RadioButtonGroup, RadioGroup, Slider, RangeSlider, TextAreaInput, TextInput, Toggle, \ Paragraph, PreText, Div put_text('Button') button = Button(label="Foo", button_type="success") show(button) put_text('CheckboxButtonGroup') checkbox_button_group = CheckboxButtonGroup( labels=["Option 1", "Option 2", "Option 3"], active=[0, 1]) show(checkbox_button_group) put_text('CheckboxGroup') checkbox_group = CheckboxGroup(labels=["Option 1", "Option 2", "Option 3"], active=[0, 1]) show(checkbox_group) put_text('ColorPicker') color_picker = ColorPicker(color="#ff4466", title="Choose color:", width=200) show(color_picker) put_text('Dropdown') menu = [("Item 1", "item_1"), ("Item 2", "item_2"), None, ("Item 3", "item_3")] dropdown = Dropdown(label="Dropdown button", button_type="warning", menu=menu) show(dropdown) put_text('FileInput') file_input = FileInput() show(file_input) put_text('MultiSelect') multi_select = MultiSelect(title="Option:", value=["foo", "quux"], options=[("foo", "Foo"), ("bar", "BAR"), ("baz", "bAz"), ("quux", "quux")]) show(multi_select) put_text('RadioButtonGroup') radio_button_group = RadioButtonGroup( labels=["Option 1", "Option 2", "Option 3"], active=0) show(radio_button_group) put_text('RadioGroup') radio_group = RadioGroup(labels=["Option 1", "Option 2", "Option 3"], active=0) show(radio_group) put_text('Select') select = Select(title="Option:", value="foo", options=["foo", "bar", "baz", "quux"]) show(select) put_text('Slider') slider = Slider(start=0, end=10, value=1, step=.1, title="Stuff") show(slider) put_text('RangeSlider') range_slider = RangeSlider(start=0, end=10, value=(1, 9), step=.1, title="Stuff") show(range_slider) put_text('TextAreaInput') text_input = TextAreaInput(value="default", rows=6, title="Label:") show(text_input) put_text('TextInput') text_input = TextInput(value="default", title="Label:") show(text_input) put_text('Toggle') toggle = Toggle(label="Foo", button_type="success") show(toggle) put_text('Div') div = Div( text= """Your <a href="https://en.wikipedia.org/wiki/HTML">HTML</a>-supported text is initialized with the <b>text</b> argument. The remaining div arguments are <b>width</b> and <b>height</b>. For this example, those values are <i>200</i> and <i>100</i> respectively.""", width=200, height=100) show(div) put_text('Paragraph') p = Paragraph( text="""Your text is initialized with the 'text' argument. The remaining Paragraph arguments are 'width' and 'height'. For this example, those values are 200 and 100 respectively.""", width=200, height=100) show(p) put_text('PreText') pre = PreText(text="""Your text is initialized with the 'text' argument. The remaining Paragraph arguments are 'width' and 'height'. For this example, those values are 500 and 100 respectively.""", width=500, height=100) show(pre)
class BokehForLabeledText(Loggable, ABC): """ Base class that keeps template explorer settings. Assumes: - in supplied dataframes - (always) text data in a `text` column - (always) xy coordinates in `x` and `y` columns - (always) an index for the rows - (likely) classification label in a `label` column Does not assume: - what the explorer serves to do. """ DEFAULT_FIGURE_KWARGS = { "tools": [ # change the scope "pan", "wheel_zoom", # make selections "tap", "poly_select", "lasso_select", # make inspections "hover", # navigate changes "undo", "redo", ], # inspection details "tooltips": bokeh_hover_tooltip(label=True, text=True, image=False, coords=True, index=True), # bokeh recommends webgl for scalability "output_backend": "webgl", } DATA_KEY_TO_KWARGS = {} MANDATORY_COLUMNS = ["text", "label", "x", "y"] def __init__(self, df_dict, **kwargs): """ Operations shared by all child classes. - settle the figure settings by using child class defaults & kwargs overrides - settle the glyph settings by using child class defaults - create widgets that child classes can override - create data sources the correspond to class-specific data subsets. - activate builtin search callbacks depending on the child class. - create a (typically) blank figure under such settings """ self.figure_kwargs = self.__class__.DEFAULT_FIGURE_KWARGS.copy() self.figure_kwargs.update(kwargs) self.glyph_kwargs = { _key: _dict["constant"].copy() for _key, _dict in self.__class__.DATA_KEY_TO_KWARGS.items() } self._setup_widgets() self._setup_dfs(df_dict) self._setup_sources() self._activate_search_builtin() self.figure = figure(**self.figure_kwargs) self.reset_figure() @classmethod def from_dataset(cls, dataset, subset_mapping, *args, **kwargs): """ Construct from a SupervisableDataset. """ # local import to avoid import cycles from hover.core.dataset import SupervisableDataset assert isinstance(dataset, SupervisableDataset) df_dict = {_v: dataset.dfs[_k] for _k, _v in subset_mapping.items()} return cls(df_dict, *args, **kwargs) def reset_figure(self): """Start over on the figure.""" self._info("Resetting figure") self.figure.renderers.clear() def _setup_widgets(self): """ Prepare widgets for interactive functionality. Create positive/negative text search boxes. """ from bokeh.models import TextInput, CheckboxButtonGroup # set up text search widgets, without assigning callbacks yet # to provide more flexibility with callbacks self._info("Setting up widgets") self.search_pos = TextInput( title="Text contains (plain text, or /pattern/flag for regex):", width_policy="fit", height_policy="fit", ) self.search_neg = TextInput(title="Text does not contain:", width_policy="fit", height_policy="fit") # set up subset display toggles which do have clearly defined callbacks data_keys = list(self.__class__.DATA_KEY_TO_KWARGS.keys()) self.data_key_button_group = CheckboxButtonGroup( labels=data_keys, active=list(range(len(data_keys)))) def update_data_key_display(active): visible_keys = { self.data_key_button_group.labels[idx] for idx in active } for _renderer in self.figure.renderers: # if the renderer has a name "on the list", update its visibility if _renderer.name in self.__class__.DATA_KEY_TO_KWARGS.keys(): _renderer.visible = _renderer.name in visible_keys # store the callback (useful, for example, during automated tests) and link it self.update_data_key_display = update_data_key_display self.data_key_button_group.on_click(self.update_data_key_display) def _layout_widgets(self): """Define the layout of widgets.""" return column(self.search_pos, self.search_neg, self.data_key_button_group) def view(self): """Define the layout of the whole explorer.""" return column(self._layout_widgets(), self.figure) def _setup_dfs(self, df_dict, copy=False): """ Check and store DataFrames BY REFERENCE BY DEFAULT. Intended to be extended in child classes for pre/post processing. """ self._info("Setting up DataFrames") supplied_keys = set(df_dict.keys()) expected_keys = set(self.__class__.DATA_KEY_TO_KWARGS.keys()) # perform high-level df key checks supplied_not_expected = supplied_keys.difference(expected_keys) expected_not_supplied = expected_keys.difference(supplied_keys) for _key in supplied_not_expected: self._warn( f"{self.__class__.__name__}.__init__(): got unexpected df key {_key}" ) for _key in expected_not_supplied: self._warn( f"{self.__class__.__name__}.__init__(): missing expected df key {_key}" ) # create df with column checks self.dfs = dict() for _key, _df in df_dict.items(): if _key in expected_keys: for _col in self.__class__.MANDATORY_COLUMNS: if _col not in _df.columns: # edge case: DataFrame has zero rows assert ( _df.shape[0] == 0 ), f"Missing column '{_col}' from non-empty {_key} DataFrame: found {list(_df.columns)}" _df[_col] = None self.dfs[_key] = _df.copy() if copy else _df def _setup_sources(self): """ Create (NOT UPDATE) ColumnDataSource objects. Intended to be extended in child classes for pre/post processing. """ self._info("Setting up sources") self.sources = { _key: ColumnDataSource(_df) for _key, _df in self.dfs.items() } def _update_sources(self): """ Update the sources with the corresponding dfs. Note that it seems mandatory to re-activate the search widgets. This is because the source loses plotting kwargs. """ for _key in self.dfs.keys(): self.sources[_key].data = self.dfs[_key] self._activate_search_builtin(verbose=False) def _activate_search_builtin(self, verbose=True): """ Typically called once during initialization. Highlight positive search results and mute negative search results. Note that this is a template method which heavily depends on class attributes. """ for _key, _dict in self.__class__.DATA_KEY_TO_KWARGS.items(): if _key in self.sources.keys(): _responding = list(_dict["search"].keys()) for _flag, _params in _dict["search"].items(): self.glyph_kwargs[_key] = self.activate_search( self.sources[_key], self.glyph_kwargs[_key], altered_param=_params, ) if verbose: self._info( f"Activated {_responding} on subset {_key} to respond to the search widgets." ) def activate_search(self, source, kwargs, altered_param=("size", 10, 5, 7)): """ Enables string/regex search-and-highlight mechanism. Modifies the plotting source in-place. """ assert isinstance(source, ColumnDataSource) assert isinstance(kwargs, dict) updated_kwargs = kwargs.copy() param_key, param_pos, param_neg, param_default = altered_param num_points = len(source.data["text"]) default_param_list = [param_default] * num_points source.add(default_param_list, f"{param_key}") updated_kwargs[param_key] = param_key search_callback = CustomJS( args={ "source": source, "key_pos": self.search_pos, "key_neg": self.search_neg, "param_pos": param_pos, "param_neg": param_neg, "param_default": param_default, }, code=f""" const data = source.data; const text = data['text']; var arr = data['{param_key}']; """ + """ var search_pos = key_pos.value; var search_neg = key_neg.value; var valid_pos = (search_pos.length > 0); var valid_neg = (search_neg.length > 0); function determineAttr(candidate) { var score = 0; if (valid_pos) { if (candidate.search(search_pos) >= 0) { score += 1; } else { score -= 2; } }; if (valid_neg) { if (candidate.search(search_neg) < 0) { score += 1; } else { score -= 2; } }; if (score > 0) { return param_pos; } else if (score < 0) { return param_neg; } else {return param_default;} } function toRegex(search_key) { var match = search_key.match(new RegExp('^/(.*?)/([gimy]*)$')); if (match) { return new RegExp(match[1], match[2]); } else { return search_key; } } if (valid_pos) {search_pos = toRegex(search_pos);} if (valid_neg) {search_neg = toRegex(search_neg);} for (var i = 0; i < arr.length; i++) { arr[i] = determineAttr(text[i]); } source.change.emit() """, ) self.search_pos.js_on_change("value", search_callback) self.search_neg.js_on_change("value", search_callback) return updated_kwargs def _prelink_check(self, other): """ Sanity check before linking two explorers. """ assert other is not self, "Self-loops are fordidden" assert isinstance( other, BokehForLabeledText), "Must link to BokehForLabelText" def link_selection(self, key, other, other_key): """ Sync the selected indices between specified sources. """ self._prelink_check(other) # link selection in a bidirectional manner sl, sr = self.sources[key], other.sources[other_key] sl.selected.js_link("indices", sr.selected, "indices") sr.selected.js_link("indices", sl.selected, "indices") def link_xy_range(self, other): """ Sync plotting ranges on the xy-plane. """ self._prelink_check(other) # link coordinate ranges in a bidirectional manner for _attr in ["start", "end"]: self.figure.x_range.js_link(_attr, other.figure.x_range, _attr) self.figure.y_range.js_link(_attr, other.figure.y_range, _attr) other.figure.x_range.js_link(_attr, self.figure.x_range, _attr) other.figure.y_range.js_link(_attr, self.figure.y_range, _attr) @abstractmethod def plot(self, *args, **kwargs): """ Plot something onto the figure. """ pass def auto_labels_cmap(self): """ Find all labels and an appropriate color map. """ labels = set() for _key in self.dfs.keys(): labels = labels.union(set(self.dfs[_key]["label"].values)) labels.discard(module_config.ABSTAIN_DECODED) labels = sorted(labels, reverse=True) assert len(labels) <= 20, "Too many labels to support (max at 20)" cmap = "Category10_10" if len(labels) <= 10 else "Category20_20" return labels, cmap def auto_legend_correction(self): """ Find legend items and deduplicate by label. """ if not hasattr(self.figure, "legend"): self._fail( "Attempting auto_legend_correction when there is no legend") return # extract all items and start over items = self.figure.legend.items[:] self.figure.legend.items.clear() # use one item to hold all renderers matching its label label_to_item = OrderedDict() for _item in items: _label = _item.label.get("value", "") if _label not in label_to_item.keys(): label_to_item[_label] = _item else: label_to_item[_label].renderers.extend(_item.renderers) # assign deduplicated items back to the legend self.figure.legend.items = list(label_to_item.values()) return
dlist[1], dlist[2], # dlist[3] ] crewlist = [ dlist[4], dlist[5], dlist[6], dlist[7], dlist[6], dlist[7], dlist[8] ] totallist = [ dlist[0], dlist[1], dlist[2], dlist[4], dlist[5], dlist[6], dlist[7], dlist[6], dlist[7], dlist[8] ] LABELS = ["Passengers", "Crew"] d1 = CheckboxButtonGroup(labels=passengerlist) d2 = CheckboxButtonGroup(labels=crewlist) d3 = CheckboxButtonGroup(labels=totallist) c = CheckboxButtonGroup(labels=LABELS, active=[0, 1]) d1.visible = False d2.visible = False def checkbox_changed(attr, old, new): if new == [0]: d1.visible = True d2.visible = False d3.visible = False elif new == [1]: d2.visible = True d1.visible = False
header_1 = Div(text="<h2> <b> Automated Clustering <b> </h2>") select = Select(title="Sample Data:", value="Glass", options=["Glass", "Iris", "Pathbased", "Spherical_6_2"]) subheader_1 = Div(text="<h3> Select Configurations </h3>") gen = Slider(title="Generations", value=10, start=-10, end=50, step=5) pop = Slider(title="Population", value=10, start=-10, end=100, step=5) button = Button(label="Search", button_type="success") subheader_2 = Div(text="<h3> Select Meta-Models </h3>") radio_group = RadioGroup(labels=[ "Meta-learning for Evaluation Metrics & Algorithm", "Meta-Learning for Initial Configuration" ], active=0) subheader_3 = Div(text="<h3> Other Preferences </h3>") checkbox_button_group = CheckboxButtonGroup( labels=["Show all non-dominated configurations"], active=[0]) file_input = FileInput() # Set up callbacks def display(): file = "./datasets/{}.csv".format(select.value.lower()) meta = Meta(file) df = meta.extract_metafeatures(file, "distance") columns = [TableColumn(field=Ci, title=Ci) for Ci in df.columns] data_table = DataTable(columns=columns, source=ColumnDataSource(df), width=1200,
concertpitch_slider = Slider(value=bt.converter.concertpitch, start=430, end=450, step=1, title="Concert Pitch") concertpitch_slider.on_change('value', bt.changeConcertPitch) fundamental_xrange = Slider(value=bt.xrange, start=5, end=100, step=1, title="X-range") fundamental_xrange.on_change('value', bt.change_xrange) checkbox_button_group = CheckboxButtonGroup( labels=["Auto-Save to Table", "FreezeInset"], active=[]) checkbox_button_group.on_change('active', bt.startstop_autoupdate) # This button allows to lock in the current data detect_button = Button(label='Manual Detect and add to Table') detect_button.on_change('clicks', bt.detect_base_freq_bokeh) save_button = Button(label='Save Current Table') #save_button.on_change('clicks',bt.save_table) save_button.callback = CustomJS(args=dict(source=bt.sources['savednotes']), code=open( join(dirname(__file__), "download.js")).read()) #%% # make the grid & add the plots
def run(self, doc: Document, visualisations: typing.Sequence[Visualisation], epoch_batches: int = 100, epoch_batch_size: int = 50, cols: int = 2, title: str = "Experiment"): """Run the experiment. Arguments: doc {Document} -- the bokeh Document visualisations {typing.Sequence[Visualisation]} -- the visualisations to show in real time Keyword Arguments: epoch_batches {int} -- the number of batches of training to perform for each agent (default: {100}) epoch_batch_size {int} -- the number of epochs to train for per training batch (default: {50}) cols {int} -- the number of columns to display the visualisations in (default: {2}) title {str} -- optional title of the web page (default: {"Experiment"}) """ # Determine which metrics need to be calculated. # This will ensure that we do not calculate useless metrics that are not visualised. metrics = set( itertools.chain(*[ visualisation.required_metrics for visualisation in visualisations ])) # Create plots plots, lines = zip(*[ visualisation.setup(self.agent_names, palette=Category10[10]) for visualisation in visualisations ]) # Create a button per agent to toggle their visibility buttons = CheckboxButtonGroup(labels=self.agent_names, active=list(range(len(self.agents)))) buttons.callback = CustomJS(args=dict(buttons=buttons, lines=lines), code="""console.log(buttons); lines.forEach(plot => plot.forEach((line, index) => { line.visible = buttons.active.includes( index); })); """) # Add the title, buttons, and plots doc.title = title doc.add_root(column(buttons, gridplot(plots, ncols=cols))) def run_blocking(): """Method to run the training of each agent that will update the visualisations in real time. This method should run on a separate thread. """ # Compile the agents [agent.compile() for agent in self.agents] # Plot initial point agent_data = [{ **{ k: v[np.newaxis, ...] for (k, v) in agent.problem.evaluate_metrics(metrics=metrics).items( ) }, "epoch": np.array([0]), "run_time": np.array([0]) } for agent in self.agents] for visualisation, plot in zip(visualisations, plots): visualisation.plot(agent_data, plot, doc) # Perform training and continually plot for epoch_batch in range(epoch_batches): start_epoch = epoch_batch * epoch_batch_size + 1 def get_agent_data(): for agent in self.agents: start = time.perf_counter() data = agent.train(epochs=epoch_batch_size, metrics=metrics) end = time.perf_counter() data["epoch"] = np.arange( start_epoch, start_epoch + epoch_batch_size) data["run_time"] = np.repeat( end - start, epoch_batch_size) / epoch_batch_size yield data data = list(get_agent_data()) for visualisation, plot in zip(visualisations, plots): visualisation.plot(data, plot, doc) # Run the experiment in a separate thread thread = Thread(target=run_blocking) thread.start()
def plot_time_series(activity: models.Activity): """ Plotting function to create the time series plots shown in tha activity page. Depending on what data is available this creates the following plots: - Altitude - Heart Rate - Speed - Cadence - Temperature All plots share a connected vertical cross hair tools. Parameters ---------- activity : models.Activity Activity model containing the required activity for which the plots should be generated Returns ------- script, div : tuple(str, str) the html script and div elements used to render the plots in the html templates """ attributes = activity.trace_file.__dict__ lap_data = models.Lap.objects.filter(trace=activity.trace_file) plots = [] lap_lines = [] timestamps = pd.to_datetime(pd.Series(json.loads( attributes["timestamps_list"]), dtype=float), unit="s") x_axis = pd.to_datetime(timestamps).dt.tz_localize("utc").dt.tz_convert( settings.TIME_ZONE) x_axis = x_axis - x_axis.min() for attribute, values in attributes.items(): if attribute in attributes_to_create_time_series_plot_for: values = pd.Series(json.loads(values), dtype=float) if values.any(): attribute = attribute.replace("_list", "") p = figure( x_axis_type="datetime", plot_height=int(settings.PLOT_HEIGHT / 2.5), sizing_mode="stretch_width", y_axis_label=plot_matrix[attribute]["axis"], ) lap = _add_laps_to_plot(laps=lap_data, plot=p, y_values=values) lap_lines += lap if attribute == "altitude": p.varea( x=x_axis, y1=values, y2=values.min(), color=plot_matrix[attribute]["second_color"], fill_alpha=0.5, ) p.line( x_axis, values, line_width=2, color=plot_matrix[attribute]["color"], legend_label=plot_matrix[attribute]["title"], ) else: p.line( x_axis, values, line_width=2, color=plot_matrix[attribute]["color"], legend_label=plot_matrix[attribute]["title"], ) x_hover = ("Time", "@x") hover = HoverTool( tooltips=[(plot_matrix[attribute]["title"], f"@y {plot_matrix[attribute]['axis']}"), x_hover], mode="vline", ) p.add_tools(hover) cross = CrosshairTool(dimensions="height") p.add_tools(cross) p.toolbar.logo = None p.toolbar_location = None p.xgrid.grid_line_color = None p.legend.location = "top_left" p.legend.label_text_font = "ubuntu" p.legend.background_fill_alpha = 0.7 dtf = DatetimeTickFormatter() dtf.minutes = ["%M:%S"] p.xaxis.formatter = dtf p.xaxis.major_label_overrides = {0: "0:00"} plots.append(p) values.ffill(inplace=True) values.bfill(inplace=True) x_axis.ffill(inplace=True) x_axis.bfill(inplace=True) _link_all_plots_with_each_other(all_plots=plots, x_values=x_axis) all_plots = column(*plots) all_plots.sizing_mode = "stretch_width" if lap_data: # include button to toggle rendering of laps log.debug(f"found some Lap data for {activity}: {lap_data}") checkbox = CheckboxButtonGroup(labels=["Show Laps"], active=[0], width=100) js = """ for (line in laps) { laps[line].visible = false; if (typeof markerGroup != "undefined") { markerGroup.removeFrom(map); } } for (i in cb_obj.active) { if (cb_obj.active[i] == 0) { for (line in laps) { laps[line].visible = true; if (typeof markerGroup != "undefined") { markerGroup.addTo(map); } } } } """ callback = CustomJS(args=dict(laps=lap_lines, checkbox=checkbox), code=js) checkbox.js_on_change("active", callback) layout = column(all_plots, checkbox) layout.sizing_mode = "stretch_width" script, div = components(layout) else: script, div = components(all_plots) return script, div
class BokehFlexLamp(object): """ A small class to blink the led, with varying rate """ # FAKE up some enums. ON = 0 # BokehFlexLamp.ON OFF = 1 # BokehFlexLamp.OFF RUN = 2 # BokehFlexLamp.RUN SateText = ["Off", "On", "Illegal"] brre = re.compile(r'\n') # used to convert newline to <br/> postmessage = { "name": "Unassigned", "near": None, "osram": None, "halpha": None, "oiii": None, "flat": None, "augflat": None } #__slots__ = [''] # add legal instance variables # (setq properties `("" "")) def __init__(self, name: str = "Default", display=fakedisplay, width=250, pin=4): # BokehFlexLamp::__init__() """Initialize this class.""" #super().__init__() # (wg-python-property-variables) self.wwidth = width self.display = display self.name = name self.display = display self.wheat_value = 1 # add a variable for each lamp self.osram_value = 0 # installed. self.halpha_value = 0 self.oiii_value = 0 self.flat_value = 0 self.augflat_value = 0 self.near_value = 0 # // coordinate with lampcheckboxes_handler self.CBLabels = [ "Wheat", "Osram", "H-alpha", "O[iii]", "Flat", "Blue Flat", "NeAr" ] self.LampCheckBoxes = CheckboxButtonGroup( labels=self.CBLabels, active=[0] * len(self.CBLabels)) # create/init them self.process = Button(align='end', label=f"{self.name} On", disabled=False, button_type="success", width=self.wwidth) self.offbutton = Button(align='end', label=f"{self.name} Off", disabled=False, button_type="primary", width=self.wwidth) self.LampCheckBoxes.on_change( 'active', lambda attr, old, new: self.lampcheckboxes_handler(attr, old, new)) self.process.on_click(lambda: self.update_process()) self.offbutton.on_click(lambda: self.update_offbutton()) ### BokehFlexLamp.__init__() def update_offbutton(self): # BokehFlexLamp::update_offbutton() """Set internal variables to off.""" msg = self.send_off() ### BokehFlexLamp.update_offbutton() def update_process(self): # BokehFlexLamp::update_button_in() """update_process Button via an event lambda""" #os = io.StringIO() #self.debug(f"{self.name} Debug",skip=['varmap'], os=os) #os.seek(0) msg = self.send_state() ### BokehFlexLamp.update_process() def lampcheckboxes_handler(self, attr, old, new): # BokehFlexLamp::lampcheckboxes_handler() """Handle the checkboxes, new is a list of indices into self.CBLabels for their purpose""" msg = f"attr {attr}, old {old}, new {new}" self.wheat_value = 1 if 0 in new else 0 self.osram_value = 1 if 1 in new else 0 self.halpha_value = 1 if 2 in new else 0 self.oiii_value = 1 if 3 in new else 0 self.flat_value = 1 if 4 in new else 0 self.augflat_value = 1 if 5 in new else 0 self.near_value = 1 if 6 in new else 0 #self.display(msg) ### BokehFlexLamp.lampcheckboxes_handler() def update_debugbtn(self): # BokehFlexLamp::update_button_in() """update_debugbtn Button via an event lambda""" os = io.StringIO() self.debug(f"{self.name} Debug", os=os) os.seek(0) self.display.display(BokehFlexLamp.brre.sub("<br/>", os.read())) ### BokehFlexLamp.update_edebugbtn() def send_state(self): # BokehFlexLamp::send_state() """Several ways to send things""" cmddict = dict([("wheat", self.wheat_value), ("osram", self.osram_value), ("halpha", self.halpha_value), ("oiii", self.oiii_value), ("flat", self.flat_value), ("augflat", self.augflat_value), ("near", self.near_value)]) d2 = dict([(f"{self.name}", dict([("Process", cmddict)]))]) jdict = json.dumps(d2) self.display.display( f'{{ "{self.name}" : {jdict} , "returnreceipt" : 1 }}') ### BokehFlexLamp.send_state() def send_off(self): # BokehFlexLamp::send_off() """Don't change the internal variables, fake a message to make the lamps off.""" cmddict = dict([("wheat", 0), ("osram", 0), ("halpha", 0), ("oiii", 0), ("flat", 0), ("augflat", 0), ("near", 0)]) d2 = dict([("Kzin", dict([("Process", cmddict)]))]) jdict = json.dumps(d2) self.display.display( f'{{ "{self.name}" : {jdict} , "returnreceipt" : 1 }}') return jdict ### BokehFlexLamp.send_off(() def layout(self): # BokehFlexLamp::layout() """Get the layout in gear""" return (row( column(self.LampCheckBoxes, row(self.process, self.offbutton)))) return self ### BokehFlexLamp.layout() def debug(self, msg="", skip=[], os=sys.stderr): # BokehFlexLamp::debug() """Help with momentary debugging, file to fit. msg -- special tag for this call skip -- the member variables to ignore os -- output stream: may be IOStream etc. """ import pprint print("BokehFlexLamp - %s " % msg, file=os) for key, value in self.__dict__.items(): if (key in skip): continue print(f'{key:20s} =', file=os, end='') pprint.pprint(value, stream=os, indent=4) return self ### BokehFlexLamp.debug() __BokehFlexLamp_debug = debug # really preserve our debug name if we're inherited
from bokeh.plotting import save menu = [("Item 1", "1"), ("Item 2", "2"), ("Item 3", "3")] layout = column( Button(label="Default Button 1", button_type="default"), Button(label="Primary Button 2", button_type="primary"), Button(label="Success Button 3", button_type="success"), Toggle(label="Default Toggle 1", button_type="default"), Toggle(label="Primary Toggle 2", button_type="primary"), Toggle(label="Success Toggle 3", button_type="success"), Dropdown(label="Default Dropdown 1", button_type="default", menu=menu), Dropdown(label="Primary Dropdown 2", button_type="primary", menu=menu), Dropdown(label="Success Dropdown 3", button_type="success", menu=menu), CheckboxButtonGroup( labels=["Checkbox Option 1", "Checkbox Option 2", "Checkbox Option 3"], button_type="default", active=[0, 1]), CheckboxButtonGroup( labels=["Checkbox Option 4", "Checkbox Option 5", "Checkbox Option 6"], button_type="primary", active=[1, 2]), CheckboxButtonGroup( labels=["Checkbox Option 7", "Checkbox Option 8", "Checkbox Option 9"], button_type="success", active=[0, 2]), RadioButtonGroup( labels=["Radio Option 1", "Radio Option 2", "Radio Option 3"], button_type="default", active=0), RadioButtonGroup( labels=["Radio Option 4", "Radio Option 5", "Radio Option 6"],
CF = CrossFiltDFs() # define the selection widgets for code, exchange, # TODO: enable widgets that support multi-selection # Elements selection widget from a periodic table code = Select(title='Code', value=codes[0], options=codes) code.on_change('value', lambda attr, old, new: CF.update_code()) exchange = Select(title='ExchangeCorrelation', value=exchanges[0], options=exchanges) exchange.on_change('value', lambda attr, old, new: CF.update_exchange()) struct = Select(title='Structure', value=structures[0], options=structures) struct.on_change('value', lambda attr, old, new: CF.update_struct()) element = CheckboxButtonGroup(labels=_elements, active=[1]) element.on_click(CF.update_element) prop = Select(title='Property', value=properties[0], options=properties) prop.on_change('value', lambda attr, old, new: CF.update_prop()) apply_crossfilter = Button(label='CrossFilter and Plot') apply_crossfilter.on_click(CF.update_crossfilter) clean_crossfilter = Button(label='Clear') clean_crossfilter.on_click(CF.clear_crossfilter) x_select.on_change('value', lambda attr, old, new: CF.update_x()) y_select.on_change('value', lambda attr, old, new: CF.update_y())
et_source.remove('index') ######################### MODELS ########################## m_header = header() m_footer = footer() m_css = style() m_blank = blank() m_text = textInit() m_year = textTitle('Année de campagne') m_quartier = textTitle('Choix de quartiers') m_status = textTitle('Statut des projets') ######################### WIDGETS ######################### f_year = CheckboxButtonGroup(labels=['2016', '2017', '2018', '2019']) f_quartier = CheckboxGroup(labels=df_data.brut_qt.q_nom.unique().tolist()) f_etat = CheckboxButtonGroup( labels=['Réalisé', 'Non réalisable', "A l'étude", 'En cours']) f_reset = Button(label="Réinitialiser", button_type="success") widget = widgetbox(m_year, f_year, m_quartier, f_quartier, m_status, f_etat, f_reset,