from dash import Dash, dcc, html, Input, Output, callback, State import polars as pl from utils.retorna_dfs_grfaicos_tab4 import retorna_dfs_graficos_tab4 from components.component_home import component_home from components.component_tab2 import component_tab_2 from components.component_tab2_textos import textos_left_tab2 from components.component_tab2_grafico import retorna_grafico_tab2 from components.component_tab3 import retorna_tab3 from components.component_tab3_tarjetas import retorna_tarjetas_tab3 from components.component_tab3_barras import retorna_barras_tab3 from components.component_tab3_donuts import retorna_pies_tab3 from components.component_tab4 import component_tab_4 from components.component_tab4_mapa import retorna_mapa from components.component_tab4_donuts import retorna_graf_tab4 from components.component_tab4_retorna_texto import retorna_tab4_texto_resultado accesos_localidades = pl.read_parquet('data/accesos_localidades_dash.parquet') rangos_localidades = pl.read_parquet('data/rangos_localidades.parquet') data_tablero = pl.read_parquet('data/data_tablero_dashboard.parquet') tarjetas = pl.read_parquet('data/tarjetas.parquet') lista_periodos = data_tablero['Periodo Tablero'].unique().to_list() lista_periodos.sort() lista_periodos = [item[7:] for item in lista_periodos] periodos_dashboard = lista_periodos.copy() periodos_dashboard.pop(0) app = Dash( __name__, suppress_callback_exceptions=True, title="Telecomunicaciones Argentina", meta_tags=[{"name": "viewport", "content": "width=device-width, initial-scale=1"}], ) tabs_styles = {"height": "2em", "marginLeft": "0.5em", "marginRight": "1.5em"} tab_style = { "border": "1px solid #656565", "color": "#d0d0d0", "backgroundColor": "#2b2b2b", "padding": "0.5em", "fontWeight": "bold", "fontSize": "0.9em", } tab_selected_style = { "borderTop": "1px solid #ffffff", "borderLeft": "1px solid #656565", "borderRight": "1px solid #656565", "backgroundColor": "#2b2b2b", "color": "#ffffff", "padding": "0.5em", "fontSize": "1.1em", } server = app.server app.layout = html.Div( [ dcc.Tabs( id="tabs-inline", value="tab-1", children=[ dcc.Tab( label="Home", value="tab-1", style=tab_style, selected_style=tab_selected_style, ), dcc.Tab( label="¿Porqué Internet?", value="tab-2", style=tab_style, selected_style=tab_selected_style, ), dcc.Tab( label="Seguimiento a Métricas", value="tab-3", style=tab_style, selected_style=tab_selected_style, ), dcc.Tab( label="Mapa de Oportunidades", value="tab-4", style=tab_style, selected_style=tab_selected_style, ), ], style=tabs_styles, ), html.Div(id="tabs-content-inline-3"), ] ) @callback(Output("tabs-content-inline-3", "children"), Input("tabs-inline", "value")) def render_content(tab): if tab == "tab-1": return component_home elif tab == "tab-2": return component_tab_2 elif tab == "tab-3": return retorna_tab3(periodos=periodos_dashboard) elif tab == "tab-4": return component_tab_4 @app.callback( Output('tab4_rangos_response', 'children'), Output('tab4_center', 'children'), Output('tab4_right', 'children'), Output('tab4_texto_resultados', 'children'), Output("store_tab4", "data"), Input('btn_tab4', 'n_clicks'), Input('drop-minimo_tab4', 'value'), Input('drop-maximo_tab4', 'value'), State("store_tab4", "data"), prevent_initial_call=True, ) def update_tab_4(n_clicks: int, min_value: int, max_value: int, data: dict ) -> tuple[html.Label | html.Br, html.Div | None , html.Div | None, html.Div | None, dict]: """update_tab_4: Actualiza los componentes de La Pestaña 4 o "Mapa de Oportunidades" Args: n_clicks (int): Numero de Veces que se le ha dado click al boton del tab 4 min_value (int): Valor seleccionado por el Usuario, capturado por un componente dcc.Drop (mínimo población) max_value (int): Valor seleccionado por el Usuario, capturado por un componente dcc.Drop (máximo población) data (dict): Banco de Datos tipo dcc.Store. pertenece al componente con el id="store_tab4" en el archivo component_tab4_left.py Utilizado para llevar un paralelo de cuantas veces an clickleado el boton Returns: tuple[html.Label|html.Br, html.Div|None , html.Div|None, html.Div|None, dict]: html.Label|html.Br: Label cuando se selecciona mal un rango, Br cuando es correcto el rango html.Div|None : Componente que tiene el Mapa de la Tab 4 html.Div|None: Componente que contiene los dos graficos tipo pies de la tab 4 html.Div|None: Componente de Texto que se muestra en la parte izquierda de la pestaña Tab_4 donde se dice Numero de Localidades, cantidad de Hab, etc dict: Banco de Datos dcc.Store con id="store_tab4" """ btn_tab4 = data.get("btn_tab4") if not n_clicks or n_clicks == btn_tab4: return (html.Br(), None, None, None, data) if n_clicks > btn_tab4: btn_tab4 += 1 data["btn_tab4"] = btn_tab4 if max_value > min_value: response = html.Br() df_mapa, df_pie_rangos, df_tecnologias, n_accesos, n_localidades = retorna_dfs_graficos_tab4( df_accesos_localidades=accesos_localidades, df_rangos=rangos_localidades, hab_minimo=min_value, hab_maximo=max_value ) poblacion_total_rango = df_mapa['Población'].sum() componente_texto = retorna_tab4_texto_resultado( total_poblacion=poblacion_total_rango, total_localidades=n_localidades, total_accesos=n_accesos ) mapa = retorna_mapa(df=df_mapa) graficos_tab4 = retorna_graf_tab4( df_pie_rangos=df_pie_rangos, df_tecnologias=df_tecnologias['ADSL', 'CABLEMODEM', 'FIBRA', 'WIRELESS'] ) else: response = html.Label('Rango no Permitido !!!') mapa = None graficos_tab4 = None componente_texto = None return (response, mapa, graficos_tab4, componente_texto, data) @callback( Output('title_right_tab2', 'children'), Output('grafico_right_tab2', 'children'), Output('texto_tab2', 'children'), Input('control_slides_tab2', 'value'), prevent_initial_call=True, ) def update_tab_2(value: int) -> tuple[str | None, html.Div | None, html.Div | None]: """update_tab_2: Se encarga de actualizar los componentes de la pesataña Tab2 o "¿Porque Internet? Args: value (int): Valor que se recibe del componente daq.NumericInput del archivo component_tab2_left.py Returns: tuple[str|None, html.Div|None, html.Div|None]: str|None: Título de la Diapositiva en la Tab 2 o "¿Porque Internet? html.Div|None: Diapositiva (Gráfico) en la Tab 2 o "¿Porque Internet? html.Div|None: Texto que se muestra en la parte izquierda de la pantalla en la Tab 2 o "¿Porque Internet? """ titulos_diapositivas = [ 'Ingresos en Miles de Pesos Argentinos', 'Ingresos en Miles de Dolares', 'Comparación de Ingresos en Dolares por Tecnología', 'Accesos por cada 100 Habitantes', 'Accesos de Telefonía Movil', 'Cantidad de Llamadas Telefonía Movil', 'Cantidad de Minutos Consumidos Telefonía Movil', 'Evolución en Accesos e Ingresos en la última Decada', 'Evolución de los Accesos de las Tecnologías para el Acceso a Internet', 'Evolución de los Accesos a Internet en los Distintos Rangos de Velocidad', ] if value in range(1, 11): componente = retorna_grafico_tab2(numero_graf=value) title = html.Label(titulos_diapositivas[value - 1]) texto = textos_left_tab2[value - 1] if value in [1, 2, 3, 4, 7, 8, 9, 10] else None return (title, componente, texto) else: return (None, None, None) @callback( Output('tarjeta_1', 'children'), Output('tarjeta_2', 'children'), Output('tarjeta_3', 'children'), Output('barras_tab3_origen', 'figure'), Output('pies_tab3', 'children'), Output("store_tab3", "data"), Input('drop-tab3', 'value'), Input('barras_tab3_origen', 'clickData'), State("store_tab3", "data"), prevent_initial_call=False, ) def update_tab_3(value: str, clickData: dict, data: dict) -> tuple[html.Div, html.Div, html.Div, html.Div, html.Div]: """update_tab_3: Se encarga de actualizar los componentes de la Tab 3 o "Seguimiento a Métricas" Args: value (str): Periodo Seleccionado por el Usuario en la Pestaña del Tablero Returns: tuple[html.Div, html.Div, html.Div, html.Div, html.Div]: html.Div: Componente que se Ubica en la tarjeta Variacion Trimestral Accesos 100 Hog html.Div: Componente que se Ubica en la tarjeta Variacion Trimestral MBPS html.Div: Componente que se Ubica en la tarjeta Total Accesos en Trimestre html.Div: Componente con el Grafico de Barras del Tablero html.Div Componente con los dos Graficos tipo Pie del tablero """ periodo = data.get("periodo") if value == periodo: mask_df_pies = (data_tablero['Periodo'] == value) &\ (data_tablero['Provincia'] == clickData["points"][0]["x"]) titulo = 'Rangos y Tecnologías en la Provincia ' + clickData["points"][0]["x"] else: periodo = value data['periodo'] = periodo mask_df_pies = data_tablero["Periodo"] == value titulo = 'Accesos por Rangos de Velocidad y Tecnología' # Filtro para Pies df_pies = data_tablero.filter(mask_df_pies) # Filtro para Barras mask = data_tablero['Periodo'] == value df = data_tablero.filter(mask) # Filtro para Tarjetas mask_tarjetas = tarjetas['Periodo'] == value df_tarjetas = tarjetas.filter(mask_tarjetas) barras = retorna_barras_tab3(df=df) pies = retorna_pies_tab3(df=df_pies, titulo=titulo) tarjeta_1, tarjeta_2, tarjeta_3 = retorna_tarjetas_tab3(df=df_tarjetas, accesos=df['Total Accesos'].sum()) return (tarjeta_1, tarjeta_2, tarjeta_3, barras, pies, data) if __name__ == "__main__": app.run_server(debug=False)