def test_js_on_change_executes(self, bokeh_model_page: BokehModelPage) -> None: group = CheckboxButtonGroup(labels=LABELS) group.js_on_click(CustomJS(code=RECORD("active", "cb_obj.active"))) page = bokeh_model_page(group) el = find_element_for(page.driver, group, ".bk-btn:nth-child(3)") el.click() results = page.results assert results['active'] == [2] el = find_element_for(page.driver, group, ".bk-btn:nth-child(1)") el.click() results = page.results assert results['active'] == [0, 2] el = find_element_for(page.driver, group, ".bk-btn:nth-child(3)") el.click() results = page.results assert results['active'] == [0] assert page.has_no_console_errors()
def test_js_on_change_executes(self, bokeh_model_page) -> None: group = CheckboxButtonGroup(labels=LABELS, css_classes=["foo"]) group.js_on_click(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 test_js_on_change_executes(self, bokeh_model_page): group = CheckboxButtonGroup(labels=LABELS, css_classes=["foo"]) group.js_on_click(CustomJS(code=RECORD("active", "cb_obj.active"))) page = bokeh_model_page(group) el = page.driver.find_element_by_css_selector('div.foo div label input[value="2"]') el = el.find_element_by_xpath('..') el.click() results = page.results assert results['active'] == [2] el = page.driver.find_element_by_css_selector('div.foo div label input[value="0"]') el = el.find_element_by_xpath('..') el.click() results = page.results assert results['active'] == [0, 2] el = page.driver.find_element_by_css_selector('div.foo div label input[value="2"]') el = el.find_element_by_xpath('..') el.click() results = page.results assert results['active'] == [0] assert page.has_no_console_errors()
def test_js_on_change_executes(self, bokeh_model_page): group = CheckboxButtonGroup(labels=LABELS, css_classes=["foo"]) group.js_on_click(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()
//console.log(cb_obj.active); for (var i in lines) { lines[i].visible = false; lines2[i].visible = false; } for (var i in cb_obj.active) { //console.log(cb_obj.active[i]); lines[cb_obj.active[i]].visible = true; lines2[cb_obj.active[i]].visible = true; } """) # Build the checkbox group checkbox = CheckboxButtonGroup(active=list(range(len(lines))), labels=names) # Link it to the callback we built checkbox.js_on_click(CB_callback) # Add a text block for citing the data sources - Current Web Page cites in the html, so omitting this here. citation_text = "" """ citation_text = "Data Sources: \n" for index, name in enumerate(names): citation_text = citation_text + '\'' + names[index] + "\': " + authors[index] + '. ' + links[index] + '\n' """ citation_text = citation_text + "\nPlots created using the \'Bokeh\' plotting library.\nCreated by C.J. Ogilvie "\ "under the supervision of Dr. Matthew Toohey at the University of Saskatchewan." citation = PreText(text=citation_text) # Combine the main plot, range select plot, and checkbox together on a single tab tabs.append( Panel(child=column(checkbox, plot, select), title="Global Mean SAOD"))
def TabParcialesKilometricos(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 dfTramosKm = TablaParcialesKilometricos(df) dfTramosKm['Ritmo_STR'] = dfTramosKm.Ritmo.apply( lambda x: FormateoTiempos(x, 'R')) # Seleccion de un subconjunto de datos para visualizar dfBokehParcialesKM = df[[ 'Bloque', 'Distancia', 'Altitud', 'FrecuenciaCardiaca', 'Cadencia' ]].copy() dfBokehParcialesKM['AltitudEscalada'] = Reescalado( dfBokehParcialesKM['Altitud'], [ MIN_Altitud[0] - (MAX_Altitud[0] - MIN_Altitud[0]) * OffsetInferiorAltitud, MAX_Altitud[0] + (MAX_Altitud[0] - MIN_Altitud[0]) * OffsetSuperiorAltitud ], [0, dfTramosKm.Velocidad.max()]) dfBokehParcialesKM['FrecuenciaCardiacaEscalada'] = Reescalado( dfBokehParcialesKM['FrecuenciaCardiaca'], [MIN_FrecuenciaCardiaca[0], MAX_FrecuenciaCardiaca[0]], [0, dfTramosKm.Velocidad.max()]) dfBokehParcialesKM['CadenciaEscalada'] = Reescalado( dfBokehParcialesKM['Cadencia'], [MIN_Cadencia[0], MAX_Cadencia[0]], [0, dfTramosKm.Velocidad.max()]) # Reducion de la frecuencia de muestreo dfBokehParcialesKM_Agg = dfBokehParcialesKM.groupby('Bloque').resample( '10S').agg({ 'Distancia': np.max, 'Cadencia': np.mean }) dfBokehParcialesKM_Agg['Cadencia'] = dfBokehParcialesKM_Agg[ 'Cadencia'].round() dfBokehParcialesKM_Agg['CadenciaEscalada'] = Reescalado( dfBokehParcialesKM_Agg['Cadencia'], [MIN_Cadencia[0], MAX_Cadencia[0]], [0, dfTramosKm.Velocidad.max()]) # Creacion de los ColumnDataSource de origen de Bokeh OrigenParcialesKM = ColumnDataSource(dfBokehParcialesKM) OrigenParcialesKM_Agg = ColumnDataSource(dfBokehParcialesKM_Agg) OrigenTramosKm = ColumnDataSource(dfTramosKm) # 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 KILOMETRICOS | STRAVA """ PLT_TramosKm = figure(plot_width=900, plot_height=500, x_range=(0, df['Distancia'].max()), y_range=(0, dfTramosKm.Velocidad.max() * 1.1), tools='', toolbar_location=None) PLT_TramosKm.add_layout( Span(location=AVG_Velocidad[0], dimension='width', line_color=BlueJeans[2], line_dash='dashed', line_width=0.1, line_alpha=0.3)) PLT_BarrasKM = PLT_TramosKm.rect(x='x', y='y', width='Distancia', height='Velocidad', source=OrigenTramosKm, line_width=1, line_color=BlueJeans[2], fill_color=BlueJeans[1]) PLT_TramosKm.add_tools( HoverTool(tooltips=[('', '@Ritmo_STR')], renderers=[PLT_BarrasKM], mode='mouse')) PropiedadesLineas = dict(line_width=2, line_alpha=0.7, line_cap='round', visible=False) PLT_TramosKM_Altitud = PLT_TramosKm.line('Distancia', 'AltitudEscalada', source=OrigenParcialesKM, color=paleta_verde[6], **PropiedadesLineas) PLT_TramosKM_FC = PLT_TramosKm.line('Distancia', 'FrecuenciaCardiacaEscalada', source=OrigenParcialesKM, color=paleta_rojo[6], **PropiedadesLineas) PLT_TramosKM_Cadencia = PLT_TramosKm.circle( 'Distancia', 'CadenciaEscalada', source=OrigenParcialesKM_Agg, size=SizeCircle, line_color=transform('Cadencia', MapaColorCadencia), color=transform('Cadencia', MapaColorCadencia), fill_alpha=1, visible=False) # Atributos PLT_TramosKm.title.text = 'RITMO MEDIO KILOMETRICO' PLT_TramosKm.sizing_mode = 'fixed' PLT_TramosKm.xaxis.axis_label = 'Distancia' PLT_TramosKm.xaxis.formatter = NumeralTickFormatter(format='0 a') PLT_TramosKm.yaxis.axis_label = 'Ritmo [min/km]' PLT_TramosKm.grid.visible = False PLT_TramosKm.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_TramosKm.xaxis.ticker = SingleIntervalTicker(interval=1000) PLT_TramosKm.xaxis.major_label_overrides = FormateoEjes( OrigenParcialesKM.data['Distancia'], 1000, 1000, 0, 0) """ DATOS EN FORMA DE TABLA POR PARCIALES KILOMETRICOS """ TablaKm = [ 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_TablaKm = DataTable(source=OrigenTramosKm, columns=TablaKm, 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; """ BotonesTramosKm = CheckboxButtonGroup( labels=["Altitud", "Frecuencia Cardiaca", "Cadencia"], active=[], width=300, height=30) CodigoJSTramosKm = CustomJS(code=CodigoJS, args=dict(l0=PLT_TramosKM_Altitud, l1=PLT_TramosKM_FC, l2=PLT_TramosKM_Cadencia, checkbox=BotonesTramosKm)) BotonesTramosKm.js_on_click(CodigoJSTramosKm) """ LAYOUT """ GridGraficaTramosKm = layout([ Column(PLT_TramosKm, width=900, height=500), [ Spacer(width=300, height=30), Column(BotonesTramosKm, width=300, height=30), Spacer(width=300, height=30) ] ], sizing_mode='stretch_width', width=900, height=570) GridTablaTramosKm = layout([ Spacer(width=360, height=25), Column(PLT_TablaKm, width=360, height=550) ], sizing_mode='stretch_width', width=360, height=570) GridAnalisisKm = gridplot([GridGraficaTramosKm, GridTablaTramosKm], ncols=2, sizing_mode='stretch_width', toolbar_location=None, plot_width=1000, plot_height=570) return GridAnalisisKm
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_click( 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_click( CustomJS( code= "console.log('checkbox_button_group: active=' + this.active, this.toString())" )) radio_button_group = RadioButtonGroup( labels=["Option 1", "Option 2", "Option 3"], active=0) radio_button_group.js_on_click( CustomJS( code= "console.log('radio_button_group: active=' + this.active, this.toString())" )) widget_box = Column(children=[ button, button_disabled, toggle_inactive,
def bk_scatter(stat_one, stat_one_name, stat_two, stat_two_name, stat='goal_contributions', stat_name='Goal Contributions'): mapper = CategoricalColorMapper(palette=[ '#496cc3', '#00a499', '#4b3291', '#fcb50b', '#db0006', '#98c2e8' ], factors=[ "Frank Lampard", "Steven Gerrard", "Xabi Alonso", "Ngolo Kante", "Paul Scholes", "Yaya Toure" ]) LABELS = [ "Frank Lampard", "Steven Gerrard", "Xabi Alonso", "Ngolo Kante", "Paul Scholes", "Yaya Toure" ] checkbox_button_group = CheckboxButtonGroup(labels=LABELS) TOOLTIPS = [('Player', '@name'), ('Season', '@year'), ('Appearances', '@appearances'), (stat_one_name, '@' + stat_one), (stat_two_name, '@' + stat_two)] if stat_name == 'Goal Contributions': TOOLTIPS.append((stat_name, '@' + stat)) PLOT_OPTIONS = dict(plot_width=950, plot_height=450) p = figure(title="Comparison of " + stat_name + " Recorded in a Season", x_axis_label=stat_one_name, y_axis_label=stat_two_name, tools='pan,zoom_in,zoom_out,reset', tooltips=TOOLTIPS, **PLOT_OPTIONS) p.add_layout(Legend(), 'right') # for player in players: if stat_one_name in ['Assists', 'Total Shots']: df = combined('attack') if stat_one_name == 'Total Passes': df = combined('team_play') if stat_one_name in ['Total Tackles', 'Duels Won']: df = combined('defensive') if stat_one_name == 'Total Shots': df = df[df.year >= '2006/07'] df['size'] = [1.3 * exp(0.09 * val) for val in df['appearances']] df['fill'] = 0.8 df['line'] = 1 if stat_one_name in ['Total Shots', 'Total Tackles']: df[stat_two] = df[stat_two].str.replace('%', '').astype('int') if stat_one_name == 'Total Passes': df['total_pass'] = df['total_pass'].str.replace(',', '').astype('int') source = ColumnDataSource(df) p.circle(x=stat_one, y=stat_two, source=source, legend_group='name', size='size', fill_alpha='fill', line_color='#7c7e71', line_width=0.5, line_alpha='line', color={ 'field': 'name', 'transform': mapper }) # p.legend.click_policy = 'mute' p.grid.grid_line_dash = [6, 4] checkbox_button_group.js_on_click( CustomJS(args=dict(source=source), code=""" var labels = ["Frank Lampard", "Steven Gerrard", "Xabi Alonso", "Ngolo Kante", "Paul Scholes", "Yaya Toure"]; var ind; var act = []; var t = this.active console.log(t); for (ind in t) { console.log(t[ind]) act.push(labels[t[ind]]); } var data=source.data; var name = data['name']; var fill = data['fill']; var line = data['line']; for (var i = 0; i < name.length; i++) { if (act.includes(name[i])) { fill[i] = 0.1; line[i] = 0.1; } else { fill[i] = 0.8; line[i] = 1; } } source.change.emit(); """)) l = layout(column(p, checkbox_button_group)) return l
def bk_line(stat, stat_name): mapper = CategoricalColorMapper(palette=[ '#496cc3', '#00a499', '#4b3291', '#fcb50b', '#db0006', '#98c2e8' ], factors=[ "Frank Lampard", "Steven Gerrard", "Xabi Alonso", "Ngolo Kante", "Paul Scholes", "Yaya Toure" ]) LABELS = [ "Frank Lampard", "Steven Gerrard", "Xabi Alonso", "Ngolo Kante", "Paul Scholes", "Yaya Toure" ] checkbox_button_group = CheckboxButtonGroup(labels=LABELS) year = [ '1994/95', '1995/96', '1996/97', '1997/98', '1998/99', '1999/00', '2000/01', '2001/02', '2002/03', '2003/04', '2004/05', '2005/06', '2006/07', '2007/08', '2008/09', '2009/10', '2010/11', '2011/12', '2012/13', '2013/14', '2014/15', '2015/16', '2016/17', '2017/18', '2018/19', '2019/20' ] if stat_name == 'Through Balls' or stat_name == 'Recoveries': year = year[13:] elif stat_name == 'Long Balls' or stat_name == 'Interceptions': year = year[12:] TOOLTIPS = [('Player', '@name'), ('Season', '@year'), ('Appearances', '@appearances'), (stat_name, '@' + stat)] PLOT_OPTIONS = dict(plot_width=950, plot_height=450) p = figure(x_range=year, title="Comparison of " + stat_name + " Recorded in a Season", x_axis_label="Season", y_axis_label=stat_name, tools='pan,zoom_in,zoom_out,reset', tooltips=TOOLTIPS, **PLOT_OPTIONS) p.add_layout(Legend(), 'right') if stat in ['goals', 'goal_assist']: df = combined('attack') if stat in ['total_through_ball', 'accurate_long_balls']: df = combined('team_play') if stat in ['ball_recovery', 'interception']: df = combined('defensive') df['size'] = [1.3 * exp(0.09 * val) for val in df['appearances']] df['fill'] = 0.8 df['line'] = 1 source = ColumnDataSource(df) p.circle(x='year', y=stat, source=source, legend_group='name', size='size', fill_alpha='fill', line_color='#7c7e71', line_width=0.5, line_alpha='line', color={ 'field': 'name', 'transform': mapper }) p.xaxis.major_label_orientation = 1.5 p.grid.grid_line_dash = [6, 4] checkbox_button_group.js_on_click( CustomJS(args=dict(source=source), code=""" var labels = ["Frank Lampard", "Steven Gerrard", "Xabi Alonso", "Ngolo Kante", "Paul Scholes", "Yaya Toure"]; var ind; var act = []; var t = this.active console.log(t); for (ind in t) { console.log(t[ind]) act.push(labels[t[ind]]); } var data=source.data; var name = data['name']; var fill = data['fill']; var line = data['line']; for (var i = 0; i < name.length; i++) { if (act.includes(name[i])) { fill[i] = 0.1; line[i] = 0.1; } else { fill[i] = 0.8; line[i] = 1; } } source.change.emit(); """)) l = layout(column(p, checkbox_button_group)) return l
def update_tiles(DF): """ Render tiles chart report """ df = DF.loc[ :, [ "id", "img_sd", "img_hd", "lat", "lng", "geometry", "portals_id", "portals_url", "wikidata_id", "omeka_url", "rate", ], ] # construct coordinates coord = [] for y in range(0, 52): for x in range(0, 100): if len(coord) != len(df): coord.append([(x, y)]) else: break df_coord = pd.DataFrame(coord, columns=["coordinate"]) df_coord[["x", "y"]] = pd.DataFrame( df_coord["coordinate"].tolist(), index=df_coord.index ) df_coord = df_coord.drop(columns="coordinate") df_tiles = pd.merge( df, df_coord, left_index=True, right_index=True, validate="one_to_one" ) df_tiles_s = df_tiles.iloc[:, [0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10]].sort_values( by=["rate"], ascending=False, ignore_index=True ) df_tiles_sort = df_tiles_s.join(df_tiles[["x", "y"]]) # setting colors colors = ["#edf8e9", "#c7e9c0", "#a1d99b", "#74c476", "#31a354", "#006d2c"] mapper = LinearColorMapper(palette=colors, low=df.rate.min(), high=df.rate.max()) # config tooltip TOOLTIPS = """ <div style="margin: 5px; width: 400px" > <h3 style='font-size: 12px; font-weight: bold;'> @id </h3> <p style='font-size: 10px; font-weight: bold;'> Geolocated: (@lat,@lng) </p> <p style='font-size: 10px; font-weight: bold;'> Image: @img_sd @img_hd </p> <p style='font-size: 10px; font-weight: bold;'> Portals: @portals_url </p> <p style='font-size: 10px; font-weight: bold;'> Wikimedia: @wikidata_id </p> <p style='font-size: 10px; font-weight: bold;'> Omeka-S: @omeka_url </p> <img src="@img_sd" alt="@img_sd" height=200 style="margin: 0px;" border="2" ></img> </div> """ # construct base chart tiles = figure( x_axis_type=None, y_axis_type=None, plot_width=1500, plot_height=1000, min_border_bottom=150, min_border_top=150, toolbar_location=None, ) # create tiles rect_sort = tiles.rect( x="x", y="y", width=0.8, height=0.8, fill_color={"field": "rate", "transform": mapper}, line_color="black", line_join="round", line_width=1, source=df_tiles_sort, ) rect = tiles.rect( x="x", y="y", width=0.8, height=0.8, fill_color={"field": "rate", "transform": mapper}, line_color="black", line_join="round", line_width=1, source=df_tiles, ) # add tooltip in hover h1 = HoverTool(renderers=[rect], tooltips=TOOLTIPS, mode="mouse", show_arrow=False) h2 = HoverTool( renderers=[rect_sort], tooltips=TOOLTIPS, mode="mouse", show_arrow=False ) callback = CustomJS( args={"rect": rect, "rect_sort": rect_sort}, code=""" rect.visible = false; rect_sort.visible = false; if (cb_obj.active.includes(0)){rect_sort.visible = true;} else{rect.visible = true;} """, ) button = CheckboxButtonGroup(labels=["Sort by rate"]) button.js_on_click(callback) tiles.add_tools(h1, h2) tiles.grid.grid_line_color = None tiles.axis.axis_line_color = None tiles.axis.major_tick_line_color = None tiles.toolbar.active_drag = None tiles.axis.major_label_standoff = 0 tiles.y_range.flipped = True plot_tiles = Row(tiles, button) return plot_tiles
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