Exploración y usos prácticos de Dash Sylvereye en la visualización de redes geoespaciales

Dr. Alberto García Robledo

CentroGeo Querétaro

Seminario Multidisciplinario CentroGeo

27 de octubre de 2023

Observatorio Metropolitano CentroGeo

¿Qué es el Observatorio Metropolitano CentroGeo?

  • Es un colectivo de investigación (CI) formado en 2018 integrado por investigadores de diferentes disciplinas, incluyendo geografía humana, inteligencia artificial y ciencia de los datos.

Observatorio Metropolitano CentroGeo

Observatorio

Metropolitano

CentroGeo

¿Quiénes somos?

  • Los miembros del CI somos IxM adscritos a CentroGeo CDMX y Querétaro en el proyecto IxM #154 Observatorio Metropolitano.

Observatorio

Metropolitano

CentroGeo

¿Qué hacemos?

  • Realizamos actividades de investigación científica, formación de recursos humanos, desarrollo tecnológico, propuestas de intervención, y actividades de vinculación y difusión del conocimiento sobre aspectos estratégicos del fenómeno metropolitano y urbano.

Observatorio

Metropolitano

CentroGeo

Líneas de investigación

  • Agua y ciudades

  • Computación científica en problemas geoespaciales y sociales

  • Simulación y modelación numérica

  • Visualización y Big Data Geoespacial

Observatorio

Metropolitano

CentroGeo

¿Qué es una red geoespacial?

Observatorio

Metropolitano

CentroGeo

¿Qué es un tablero de visualización?

Un tablero de visualización, es una herramienta visual que permite representar y monitorear de manera centralizada información clave y métricas de rendimiento de una organización o sistema en tiempo real o en periodos definidos.

Observatorio

Metropolitano

CentroGeo

¿Qué es Dash?

  • Dash es un framework web escrito en Python para el desarrollo de tableros de visualización.

  • Está construido sobre Flask, Plotly.js y React.js

  • Permite el desarrollo de aplicaciones web de visualización de datos sin la necesidad de escribir HTML, JavaScript o CSS.

Observatorio

Metropolitano

CentroGeo

Componentes Dash de terceros

  • Dash provee herramientas para desarrollar componentes que expandan el framework

  • Básicamente, un componente Dash no es más que un envoltorio de un componente React.js

  • Dash goza de una nutrida comunidad de desarrolladores que han creado sus propios componentes Dash

Observatorio

Metropolitano

CentroGeo

Dash Cytoscape

  • Sin soporte de dibujo de poli-líneas para los enlaces

  • Sin soporte de coordenadas geográficas

  • Sin soporte de mapas web

  • Sin aceleración por GPU

Observatorio

Metropolitano

CentroGeo

Estado del Arte

Observatorio

Metropolitano

CentroGeo

Dash Sylvereye

  • Biblioteca Dash desarrollada en CentroGeo.

  • Permite la visualización de redes de caminos grandes utilizando WebGL.

  • Las visualizaciones son altamente personalizables.

  • Eventos de click para nodos y enlaces de la red.

Observatorio

Metropolitano

CentroGeo

Dash Sylvereye

Observatorio

Metropolitano

CentroGeo

Dash Sylvereye

Observatorio

Metropolitano

CentroGeo

Observatorio

Metropolitano

CentroGeo

Incrustación en un tablero Dash

  • Dash Sylvereye permite incrustar la visualización de una red de caminos en un tablero Dash

  • La topología de una red de caminos puede ser obtenida desde OSM a través de la biblioteca OSMnx

    • Es posible cargar otro tipo de redes geoespaciales

  • Dash Sylvereye permite la configuración de la capa de mapa web sobre la que se dibuja la red de caminos

Observatorio

Metropolitano

CentroGeo

Ejemplo 1: Visualización de una red de caminos 

Observatorio

Metropolitano

CentroGeo

Ejemplo 1: Visualización de una red de caminos 

import osmnx as ox
from dash import Dash
from dash_html_components import Div
from dash_sylvereye import SylvereyeRoadNetwork
from dash_sylvereye.utils import load_from_osmnx_graph

# configuración de la visualización
OSMNX_QUERY = 'Kamppi, Helsinki, Finland'
TILE_LAYER_URL = '//stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png'
TILE_LAYER_SUBDOMAINS = 'abcd'
TILE_LAYER_ATTRIBUTION = 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.'
MAP_CENTER = [60.1663, 24.9313]
MAP_ZOOM = 15
MAP_STYLE = {'width': '100%', 'height': '98vh'}

# obtener la topología de la red desde OSM
road_network = ox.graph_from_place(OSMNX_QUERY, network_type='drive') 
nodes_data, edges_data = load_from_osmnx_graph(road_network)

# construir visualización
app = Dash()
app.layout = Div([
    SylvereyeRoadNetwork(
                         id='sylvereye-roadnet',
                         tile_layer_url=TILE_LAYER_URL,
                         tile_layer_subdomains=TILE_LAYER_SUBDOMAINS,
                         tile_layer_attribution=TILE_LAYER_ATTRIBUTION,
                         map_center=MAP_CENTER,
                         map_zoom=MAP_ZOOM,
                         map_style=MAP_STYLE,
                         nodes_data=nodes_data,
                         edges_data=edges_data
                        )
])

# correr visualización
if __name__ == '__main__':
    app.run_server()

Interacción con nodos y enlaces

  • Dash Sylvereye permite interactuar con los nodos (cruces de caminos) y los enlaces (caminos)

  • Lo anterior a través de la detección de eventos de click  

  • Esto significa que puede asociar un callback al evento click de los nodos y/o enlaces

  • Dash Sylvereye pasará al callback los datos del elemento clickeado

Observatorio

Metropolitano

CentroGeo

Ejemplo 2: Interacción con la red de caminos 

Observatorio

Metropolitano

CentroGeo

Ejemplo 2: Interacción con la red de caminos

import osmnx as ox
from dash import Dash
from dash.dependencies import Input, Output
from dash_html_components import Div
from dash_html_components import H2, H3
from dash_sylvereye import SylvereyeRoadNetwork
from dash_sylvereye.utils import load_from_osmnx_graph

# configuración de la visualización
OSMNX_QUERY = 'Kamppi, Helsinki, Finland'
TILE_LAYER_URL = '//stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png'
TILE_LAYER_SUBDOMAINS = 'abcd'
TILE_LAYER_ATTRIBUTION = 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.'
MAP_CENTER = [60.1663, 24.9313]
MAP_ZOOM = 15
MAP_STYLE = {'width': '100%', 'height': '84vh'}

# obtener la topología de la red desde OSM
road_network = ox.graph_from_place(OSMNX_QUERY, network_type='drive') 
nodes_data, edges_data = load_from_osmnx_graph(road_network)

# construcción de la visualización
app = Dash()
app.layout = Div([
    SylvereyeRoadNetwork(
                         id='sylvereye-roadnet',
                         tile_layer_url=TILE_LAYER_URL,
                         tile_layer_subdomains=TILE_LAYER_SUBDOMAINS,
                         tile_layer_attribution=TILE_LAYER_ATTRIBUTION,
                         map_center=MAP_CENTER,
                         map_zoom=MAP_ZOOM,
                         map_style=MAP_STYLE,
                         nodes_data=nodes_data,
                         edges_data=edges_data
                        ),
    H5("Clicked elements:"),
    H6(id='h3-clicked-node-coords'),
    H6(id='h3-clicked-edge-coords')    
])

# callbacks
@app.callback(
    Output('h3-clicked-node-coords', 'children'),
    [Input('sylvereye-roadnet', 'clicked_node')])
def update_node_data(clicked_node):    
    if clicked_node:
        return f'Clicked node coords: {clicked_node["data"]["lat"]}, \
                                      {clicked_node["data"]["lon"]}'

@app.callback(
    Output('h3-clicked-edge-coords', 'children'),
    [Input('sylvereye-roadnet', 'clicked_edge')])
def update_edge_data(clicked_edge):    
    if clicked_edge:
        return f'Clicked edge coords: {clicked_edge["data"]["coords"]}'

# correr visualización      
if __name__ == '__main__':
    app.run_server()

Personalización de los estilos de la visualización

  • Dash Sylvereye permite la configuración visual de los nodos y enlaces individuales de la red

  • Para los nodos es posible configurar su diámetro, color y transparencia

  • Para los enlaces es posible configurar su grosor, color y transparencia

  • Dash Sylvereye puede calcular automáticamente el color de nodos y enlaces en función de un atributo de peso

Observatorio

Metropolitano

CentroGeo

Ejemplo 3: Personalización de la visualización de una red

Observatorio

Metropolitano

CentroGeo

Ejemplo 3: Personalización de la visualización de una red

import osmnx as ox
import numpy as np
from dash import Dash
from dash_html_components import Div
from dash_sylvereye import SylvereyeRoadNetwork
from dash_sylvereye.utils import load_from_osmnx_graph 
from dash_sylvereye.enums import NodeSizeMethod, EdgeColorMethod, EdgeWidthMethod
from dash_sylvereye.defaults import get_default_node_options, get_default_edge_options

OSMNX_QUERY = 'Kamppi, Helsinki, Finland'
TILE_LAYER_URL = '//stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png'
TILE_LAYER_SUBDOMAINS = 'abcd'
TILE_LAYER_ATTRIBUTION = 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.'
MAP_CENTER = [60.1663, 24.9313]
MAP_ZOOM = 15
MAP_STYLE = {'width': '100%', 'height': '84vh'}

# obtener la red desde OSM
road_network = ox.graph_from_place(OSMNX_QUERY, network_type='drive') 
nodes_data, edges_data = load_from_osmnx_graph(road_network)

# asignar pesos aleatorios a los nodos y enlaces de acuerdo a una dist. libre de escala
for node in nodes_data: node["data"]["weight"] = 1 - np.random.power(a=3, size=None)
for edge in edges_data: edge["data"]["weight"] = 1 - np.random.power(a=3, size=None)

# configurar las opciones visuales de los nodos
node_options = get_default_node_options()
node_options["alpha_default"] = 0.25
node_options["size_method"] = NodeSizeMethod.SCALE
node_options["size_scale_field"] = "weight"

# configurar las opciones visualies de los enlaces
edge_options = get_default_edge_options()
edge_options["width_method"] = EdgeWidthMethod.SCALE
edge_options["width_scale_field"] = "weight"
edge_options["color_method"] = EdgeColorMethod.SCALE
edge_options["color_scale_field"] = "weight"
edge_options["color_scale_left"] = 0xcbdbff
edge_options["color_scale_right"] = 0x06696

# construir la visualización
app = Dash()
app.layout = Div([
    SylvereyeRoadNetwork(
                         id='sylvereye-roadnet',
                         tile_layer_url=TILE_LAYER_URL,
                         tile_layer_subdomains=TILE_LAYER_SUBDOMAINS,
                         tile_layer_attribution=TILE_LAYER_ATTRIBUTION,
                         map_center=MAP_CENTER,
                         map_zoom=MAP_ZOOM,
                         map_style=MAP_STYLE,
                         nodes_data=nodes_data,
                         edges_data=edges_data,
                         node_options=node_options,
                         edge_options=edge_options
                        )    
])

# correr servidor
if __name__ == '__main__':
    app.run_server()

Visualización de marcadores

  • Dash Sylvereye permite visualizar marcadores encima tanto del mapa web como de la red

  • Los marcadores son interactivos: es posible asociar un callback al evento click de cada marcador

  • Dash Sylvereye pasará los datos del marcador clickeado a un parámetro del callback

Observatorio

Metropolitano

CentroGeo

Ejemplo 4: Visualización de marcadores sobre la red

Observatorio

Metropolitano

CentroGeo

Ejemplo 4: Visualización de marcadores sobre la red

import osmnx as ox
from dash import Dash
from dash.dependencies import Input, Output
from dash_html_components import Div
from dash_html_components import H2, H3
from dash_sylvereye import SylvereyeRoadNetwork
from dash_sylvereye.utils import load_from_osmnx_graph, generate_markers_from_coords
from dash_sylvereye.defaults import get_default_marker_options

OSMNX_QUERY = 'Kamppi, Helsinki, Finland'
TILE_LAYER_URL = '//stamen-tiles-{s}.a.ssl.fastly.net/toner/{z}/{x}/{y}.png'
TILE_LAYER_SUBDOMAINS = 'abcd'
TILE_LAYER_ATTRIBUTION = 'Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.'
MAP_CENTER = [60.1663, 24.9313]
MAP_ZOOM = 15
MAP_STYLE = {'width': '100%', 'height': '80vh'}

# obtener red de caminos desde OSM
road_network = ox.graph_from_place(OSMNX_QUERY, network_type='drive') 
nodes_data, edges_data = load_from_osmnx_graph(road_network)

# crear un marcador por cada nodo de la red
markers_coords = [ [node_data["lat"], node_data["lon"]] for node_data in nodes_data ]
markers_data = generate_markers_from_coords(markers_coords)

# escalar el tamaño de los marcadores al nivel de zoom
marker_options = get_default_marker_options()
marker_options["enable_zoom_scaling"] = True

# construir visualización
app = Dash()
app.layout = Div([
    SylvereyeRoadNetwork(
                         id='sylvereye-roadnet',
                         tile_layer_url=TILE_LAYER_URL,
                         tile_layer_subdomains=TILE_LAYER_SUBDOMAINS,
                         tile_layer_attribution=TILE_LAYER_ATTRIBUTION,
                         map_center=MAP_CENTER,
                         map_zoom=MAP_ZOOM,
                         map_style=MAP_STYLE,
                         nodes_data=nodes_data,
                         edges_data=edges_data,
                         markers_data=markers_data,
                         marker_options=marker_options
                        ),
    H2("Clicked elements:"),
    H3(id='h3-clicked-marker-coords')
])

@app.callback(
    Output('h3-clicked-marker-coords', 'children'),
    [Input('sylvereye-roadnet', 'clicked_marker')])
def update_marker_data(clicked_marker):  
    if clicked_marker:  
        marker = clicked_marker["marker"]
        return f'Clicked marker coords: {[ marker["lat"], marker["lon"] ]}'

# correr visualización
if __name__ == '__main__':
    app.run_server()

Ejemplo 4: Visualización de marcadores sobre la red

Observatorio

Metropolitano

CentroGeo

Observatorio

Metropolitano

CentroGeo

Visualización de simulaciones SUMO

Observatorio

Metropolitano

CentroGeo

Visualización de simulaciones SUMO

Observatorio

Metropolitano

CentroGeo

Visualización de simulaciones SUMO

Observatorio

Metropolitano

CentroGeo

Visualización de redes de caminos

Observatorio

Metropolitano

CentroGeo

Visualización de dispersión del COVID-19

Observatorio

Metropolitano

CentroGeo

Visualización de dispersión del COVID-19

Observatorio

Metropolitano

CentroGeo

Visualización de dispersión del COVID-19

Observatorio

Metropolitano

CentroGeo

Vis. de correlación de índices entre ZMs

Observatorio

Metropolitano

CentroGeo

Vis. de correlación de índices entre ZMs

Observatorio

Metropolitano

CentroGeo

Vis. de tiempos y distancias de traslado O-D

Observatorio

Metropolitano

CentroGeo

Vis. de tiempos y distancias de traslado O-D

Observatorio

Metropolitano

CentroGeo

Estudio de rendimiento

Observatorio

Metropolitano

CentroGeo

Aplicaciones

Urbanismo y Desarrollo Urbano:

  • Análisis del flujo de tráfico para optimizar rutas.
  • Identificación de zonas carentes de infraestructura esencial.
  • Evaluación visual de proyectos de desarrollo urbano propuestos.

Observatorio

Metropolitano

CentroGeo

Aplicaciones

Transporte Público:

  • Visualización de rutas y frecuencias de autobuses, trenes y otros medios de transporte.
  • Análisis de la cobertura del transporte público en diferentes zonas urbanas.

Investigación Académica:

  • Estudios sobre patrones de movilidad urbana.
  • Investigación sobre la estructura y conectividad de redes de infraestructura, biológicas o sociales.

Observatorio

Metropolitano

CentroGeo

Aplicaciones

Salud Pública:

  • Rastreo y visualización de brotes de enfermedades.

Seguridad y Emergencia:

  • Rastreo de incidentes delictivos en una ciudad.

Servicios Públicos y Utilities:

  • Mapeo de redes de suministro eléctrico, agua o gas.

Observatorio

Metropolitano

CentroGeo

Trabajo futuro

  • Optimización del procedimiento de primer dibujado para reducir su impacto de rendimiento (overhead)
  • Introducción de mejoras para la visualización de redes sin enlaces georeferenciados.
  • Introducción de mejoras para el dibujado de elementos que no conformen parte de la red (polígonos, líneas, etc.)
  • Creación de tutoriales y divulgación de la herramienta.
  • Reparación de bugs.

Observatorio

Metropolitano

CentroGeo

¡Gracias!

 

 

agarcia@centrogeo.edu.mx

 

Observatorio Metropolitano CentroGeo

Seminario Multidisciplinario CentroGeo 2023

By Alberto Garcia-Robledo

Seminario Multidisciplinario CentroGeo 2023

  • 132