Cómo se hizo “Un Cielo Sin Estrellas”

Cada vez vemos menos estrellas y no se debe a que estén desapareciendo (afortunadamente). La contaminación lumínica es la responsable de este fenómeno.

Jaime Nieves, Solution Engineer del área de Tecnología e Innovación de Esri España, astrofísico de formación y, por tanto, un apasionado de la Astronomía, ha elaborado el Story Map Un Cielo sin Estrellas, en el que nos muestra qué 17% de la población mundial puede todavía tumbarse a ver las estrellas. Hoy está en Esriblog para contarnos él mismo cómo lo ha hecho.

mapa_estrellas

El Story Map Un Cielo sin Estrellas habla de la contaminación lumínica, el fenómeno por el cual la luz artificial de nuestras ciudades dificulta la visión del cielo nocturno. Los estudios muestran que el 85% de la población mundial vive en zonas con muy poca visibilidad de las estrellas.

Recuerdo que, siendo niño, a veces paseábamos por el campo cerca de Estepona, en Málaga. Mis abuelos tenían una casa allí, en una zona que por aquel entonces no estaba tan urbanizada como hoy. Allí, cerca del mar, en las noches de verano, la Vía Láctea era perfectamente visible en un cielo cuajado de estrellas. Ahora, desde la ventana de mi casa en Madrid, en un día claro, apenas puedo distinguir una docena de las estrellas más brillantes.

De pequeño me fascinaban las estrellas y los planetas, y tal interés me llevó a elegir la Física como destino académico. Ahora, tras 13 años de carrera en Esri, pensé que sería divertido unir la astronomía y la geografía a la hora de contar una historia con mapas.

Cuando empecé a trabajar en este Story Map, mi idea era simple: utilizar fotografías públicas de Flickr para encontrar los lugares preferidos de los astrofotógrafos aficionados, lo cual revelaría las mejores ubicaciones para la astronomía. Mi investigación me llevó al API de Flickr, y con un poco de mi oxidado Python y algo de prueba-error conseguí un sencillo script que obtenía las imágenes georreferenciadas que correspondían a ciertos criterios de búsqueda.

Expande el siguiente cuadro si te interesa ver el código del script de Python:

############################################################################
# Extrae fotos dentro del bounding box de España usando una búsqueda
# definida. Extrae las coordenadas y la URL de las imágenes.
# Script creado por Jaime Nieves
############################################################################

# Este script utiliza el API de Flickr para Python de https://stuvel.eu/flickrapi
import flickrapi

# Tienes que registrarte con tu cuenta de Flickr para recibir tu API Key
# Consulta https://www.flickr.com/services/api/
api_key = u'your-api-key'
api_secret = u'your-api-secret'

flickr = flickrapi.FlickrAPI(api_key, api_secret)

#######################################################################
# MODIFICA TU BÚSQUEDA AQUÍ                                           #

busqueda = u'astrophotography OR astronomy OR astrofotografia OR astronomia OR astronomía OR astrofotografía OR telescopio OR telescope'

# MODIFICA TU BÚSQUEDA AQUÍ                                           #
#######################################################################

# Busca fotografías y devuelve el número de fotos y páginas:
photos = flickr.photos.search(text=busqueda,
                              bbox='-18.160879,27.637738,4.327890,43.789994',
                              per_page='200', has_geo='1', extras='geo')
sets = photos.find('photos')
set = photos.find('photos').findall('photo')

pages = sets.attrib['pages']
total = sets.attrib['total']

print u'páginas: ' + pages
print 'fotos: ' + total

# Recorre las páginas y crea una lista de IDs y coordenadas
# Escribe los resultados a un fichero
result = 'ID;owner;ownerpage;url;thumb;lat;lon'+'\n'
num = 0
fichero = open('output.csv','w')
fichero.write(result)

for p in range(1,int(pages)+1):
    photos = flickr.photos.search(text=busqueda,
                              bbox='-18.160879,27.637738,4.327890,43.789994',
                              per_page='200', has_geo='1', page=p, extras='geo')
    sets = photos.find('photos')
    set = photos.find('photos').findall('photo')
    print u'Página ' + str(p) + ' ========================== '

    for i in range(len(set)):
        num = num + 1
        myId = set[i].attrib['id']
        usuario = set[i].attrib['owner']
        userHome = 'https://www.flickr.com/people/' + usuario + '/'
        url = 'https://www.flickr.com/photos/' + usuario + '/' + myId + '/'
        userHome = 'https://www.flickr.com/people/' + usuario + '/'

        # Hacemos una petición para obtener la url directa
        pSize = flickr.photos.getSizes(photo_id=myId)
        sizes = pSize.find('sizes').findall('size')
        thumb = sizes[3].attrib['source']

        # Hacemos una petición para obtener la ubicación
        ubic = flickr.photos.geo.getLocation(photo_id=myId)
        loc = ubic.find('photo').find('location')

        # Juntamos todo y escribimos
        result = str(myId) + ';' + str(usuario) + ';' + userHome + ';' \
                 + url + ';' + thumb + ';' + str(loc.attrib['latitude']) \
                 + ';' + str(loc.attrib['longitude']) + '\n'
        progreso = (float(num) / float(total))*100
        print 'Procesando ID ' + str(myId) + ' (' + str(round(progreso,1)) + '%)'
        fichero.write(result)

fichero.close()

Encontré así mi primera barrera: no había suficientes imágenes como para un análisis estadístico interesante, y muchas de ellas aparecían en las grandes ciudades. Es lógico encontrar más elementos donde más población hay, y tal vez mucha gente geo-etiqueta sus fotos en el lugar donde vive, en vez de donde la foto fue tomada.

Flickr_Density

Algunos patrones prometedores, pero oscurecidos por las grandes urbes. Story Map 1, Jaime 0.

Esto parecía llevarme a un callejón sin salida. No obstante, durante el proceso de documentar mi historia, había encontrado unos datos interesantes que me mostraban otro camino: el llamado “Nuevo Atlas del Brillo Artificial del Cielo”, un trabajo científico cuyos autores utilizan información de los focos de luz artificial para crear un modelo que estima el brillo artificial del cielo. Es decir, la contaminación lumínica.

Y sus datos se podían descargar en formato KMZ.

Me puse manos a la obra. El KMZ estaba compuesto por un montón de teselas en JPEG con información de coordenadas que cubrían todo el mundo. Poco sospechaba que mi infierno cartográfico estaba a punto de comenzar.

La compresión JPEG, esa gran enemiga del GIS

La compresión JPEG, esa gran enemiga del GIS

ArcGIS permite importar un KMZ como el que me descargué y convertirlo a un Raster Catalog, que a su vez se puede mosaicar fácilmente para obtener una única imagen. Sin embargo, las imágenes dentro del KMZ eran RGB corrientes, como cualquier imagen digital cotidiana. Y además bastante sucias por la elevada compresión JPEG.

Me explico: Necesitaba conseguir una imagen en la que cada color tuviera un único valor de pixel, de modo que pudiera extraer las clases y llevar a cabo mis análisis. Para que una imagen tenga utilidad en un proceso GIS es necesario que sus píxels representen información. La imagen procedente del KMZ estaba codificada en modo RGB (es decir, los colores estaban formados por la combinación de tres bandas) y, además, muy mezclados debido a la compresión.

Escribí a los autores del trabajo para intentar conseguir el GeoTIFF original con sus resultados, pero se negaron. Así que dediqué muchas horas a probar métodos para conseguir separar las clases de la imagen.

Hice cientos de pruebas con muchas herramientas ráster de ArcGIS: segmentación, clasificación supervisada y no supervisada, muestreo con una capa de puntos aleatorios para luego interpolar, filtros de agregación, limpieza de bordes y un larguísimo etcétera. En mi disco duro quedan 15 Gb de datos ráster como silencioso testimonio de mis fracasos.

La Segmentación (Segment Mean Shift) casi, casi, daba un resultado usable

La Segmentación (Segment Mean Shift) casi, casi, daba un resultado usable

La clasificación, que me parecía prometedora, funcionaba bien para 5 ó 6 clases, pero al introducir más algunos colores se mezclaban entre sí y el sistema no era capaz de separar las clases. La segmentación me devolvía una imagen bastante limpia, aunque aún introducía mezclas de clases en los bordes. Pensé que, si podía convertir la imagen RGB segmentada en una imagen de una sola banda con códigos para cada color, podía reclasificar los valores similares y conseguir separar las clases.

A partir de la imagen segmentada usé Álgebra de bandas (Map Algebra) para sumar las tres bandas (rojo, verde y azul) de modo que obtuviera una banda única con un solo valor por cada clase. Esto parece una tontería, pero resulta que colores aparentemente muy distintos pueden tener una suma de bandas muy similar. Un ejemplo sencillo: el rojo puro (255,0,0) y el verde puro (0,255,0) dan como resultado la misma suma: 255.

Si sumas las tres bandas, pasa esto. Aunque los colores originales sean distintos (valores distintos para R, G y B), su suma puede ser muy parecida

Si sumas las tres bandas, pasa esto. Aunque los colores originales sean distintos (valores distintos para R, G y B), su suma puede ser muy parecida

Así que introduje pesos aleatorios para cada banda con el objetivo de “romper la simetría” y conseguir una capa que pudiera distinguirme todos los colores. Cuando logré un resultado aceptable, reclasifiqué los resultados con la herramienta Reclassify de ArcGIS. Básicamente fui examinando la imagen con la herramienta Pixel Inspector (una pequeña joya oculta en ArcGIS a la que sólo se puede acceder añadiendo su botón a cualquier barra de herramientas) para ver qué rangos de valores de celda de mi ráster “suma” correspondían a cada uno de los colores originales.

Con esto conseguí por fin un ráster con 13 valores únicos de celda para las 13 clases (del 0 al 12). Perdí una clase por el camino que fui incapaz de separar, pero, dado que estaba en el extremo más brillante, bien podía considerarla fusionada con su vecina sin afectar a mi historia.

La capa vectorizada final. La zona violeta debería tener dos tonos de violeta. Después de un centenar de pruebas, decidí que podía vivir sin la otra.

La capa vectorizada final. La zona violeta debería tener dos tonos de violeta; pero después de un centenar de pruebas, decidí que podía vivir sin la otra.

El ráster resultante aún tenía algunas zonas algo raras, pero era en general una aproximación más que aceptable a los datos originales, sobre todo para el propósito de mi estudio, que no exigía demasiada precisión. Así que vectoricé mi ráster y probé algunos métodos para suavizarlo, tales como Simplify polygon y Smooth polygon, de la caja de herramientas de cartografía de ArcGIS.

Estaba razonablemente feliz hasta que cargué un mapa base.

¿En serio? Después de tanto esfuerzo… ¿las coordenadas TAMBIÉN están mal?

¿En serio? Después de tanto esfuerzo… ¿las coordenadas TAMBIÉN están mal?

Pues sí. Los datos originales estaban mal georreferenciados, de modo que al proyectarlos sobre el mapa base de Esri… ¡sorpresa! No cuadraban.

Afortunadamente ArcGIS tiene una barra de herramientas llamada Ajuste espacial, para tomar puntos de control y reposicionar una capa usando simplemente desplazamiento lineal o métodos más complejos con deformación como el rubber sheet.

Mi nueva muy mejor amiga, la barra de herramientas de Ajuste espacial

Mi nueva muy mejor amiga, la barra de herramientas de Ajuste espacial

El desafío era tomar puntos en una capa vectorial que sólo contiene manchas. ¿Cómo ajustarla con la geografía real? Tomé cientos de puntos intentando cuadrar las ubicaciones más fácilmente distinguibles de la costa. Sin embargo, en algunas zonas muy iluminadas era francamente difícil casar el mapa de contaminación con la geografía física. Al final cargué una capa de núcleos urbanos y fui capaz de cuadrar los puntos de luz en mi mapa de contaminación lumínica con las zonas urbanas, sobre todo en localidades aisladas del interior.

Una vez tienes el mapa en bonito, el resto es la parte divertida

Una vez tienes el mapa en bonito, el resto es la parte divertida

Ya tenía unos buenos datos preparados, lo que me había costado una parte de mi ya escasa cabellera. Pero a partir de aquí venía lo fácil. Elegí una simbología nueva (la original de los autores del trabajo no me convencía estéticamente), publiqué los datos en ArcGIS Online y comencé a crear mapas. Tenía un volumen de datos bastante alto para la visualización web, así que probé la nueva capacidad de ArcGIS Online para optimizar las geometrías de una capa. Con esta optimización la capa se mueve muy rápido a todas las escalas, así que me evité tener que cachearla.

Empecé a construir mi historia usando la plantilla de Story Map Cascade, una aplicación preciosa cuando se usa con buenas imágenes y que ofrece una experiencia inmersiva al lector, combinando mapas, medios y texto en un flujo continuo.

Para los mapas iniciales que muestran las luces nocturnas y la contaminación lumínica para todo el mundo decidí crear escenas 3D. Para la mayoría de los otros mapas usé el código para embeber que el visor de ArcGIS Online genera para nosotros con el objetivo de incrustar los mapas en la historia. Al embeber mapas podemos incluir opciones como el cuadro de búsqueda que permite encontrar ubicaciones.

Algunos de los mapas que forman parte de este Story Map merecen mención especial. Uno de ellos es la comparativa del cielo con y sin estrellas. Pensé brevemente en buscar algún trozo de código en  Javascript que me permitiera comparar dos fotografías, pero luego me di cuenta de que Esri ya tenía una solución para mí sin salir de la Plataforma.

Una de las apps configurables de ArcGIS permite comparar dos mapas con una barra deslizante. Así que me di cuenta de que podía usarla para mis propósitos. Lo primero que hice fue buscar una foto bonita del Madrid nocturno, y luego conseguir un mapa del cielo tal y como se vería desde Madrid. Usé un programa de creación gráfica y mis mañas como ilustrador para combinar ambas imágenes y crear la visión del Madrid estrellado.

Luego cargué las fotos en ArcGIS y las geocodifiqué, colocándolas arbitrariamente sobre España. Las publiqué en ArcGIS Online como servicios cacheados, y las añadí a un mapa que luego usé en mi app de comparación.

Un uso no geográfico para un app geográfica, o “el hambre nos hace mejores cocineros”

Un uso no geográfico para un app geográfica, o “el hambre nos hace mejores cocineros”

Otro de los mapas de la historia usa la app configurable llamada Resumen de impacto, que permite agregar muy fácilmente los valores numéricos contenidos en una capa de polígonos. Para producir los datos usé la herramienta Tabulate intersection, que genera estadísticas de área al intersecar dos capas. De este modo obtuve qué porcentaje de cada municipio estaba presente en cada categoría de contaminación lumínica. Empleé luego los datos de CensalView de Esri España para añadir la población proporcional, de modo que para cada área de contaminación lumínica tenía información estimada de población, rangos de edad y nivel educativo.

La aplicación Resumen de impacto es básicamente auto-configurable, así que, tras publicar la capa con los datos demográficos, tardé sólo diez minutos en definir las variables de interés y configurar textos y colores. El gráfico de población lo generé directamente con ArcGIS Desktop a partir de la tabla de atributos, y lo exporté como JPEG para poder cargarlo en mi Story Map.

Esto es lo maravilloso de ArcGIS: una vez tienes los datos, crear aplicaciones espectaculares es una cuestión de minutos.

Esto es lo maravilloso de ArcGIS: una vez tienes los datos, crear aplicaciones espectaculares es una cuestión de minutos.

Por último, filtré mi capa de brillo artificial para quedarme con las mejores zonas para observar el cielo (las zonas menos contaminadas). A partir de ellas generé un ráster de distancia euclídea que representaba cuánto había que desplazarse para llegar desde cualquier punto de España a la más cercana de estas zonas ideales. Tuve que vectorizarlo para poder publicarlo en ArcGIS Online sin necesidad de cachear.

El mapa de "cuánto-tienes-que-viajar-para-ver-estrellas"

El mapa de “cuánto-tienes-que-viajar-para-ver-estrellas”

Luego crucé estas zonas ideales con la capa de municipios de CensalView para obtener cuáles de ellos tenían parte de su territorio en una zona de cielos limpios y producir así un mapa de localidades idóneas para los astrónomos aficionados.

Mucho trabajo se fue en poner las cosas bonitas: que los pop-ups aparecieran limpios y atractivos, que la simbología estuviera correctamente aplicada, que los contenidos estuvieran bien documentados y etiquetados, etcétera. Puede parecer un trabajo tedioso pero es imprescindible para que nuestra historia luzca.

 El enlace por defecto puede cambiarse, y así vincular dos versiones de la misma historia en idiomas distintos.


El enlace por defecto puede cambiarse, y así vincular dos versiones de la misma historia en idiomas distintos.

Terminé creando una versión en inglés del mismo Story Map, y usé el enlace que todos los Story Maps incluyen en la parte superior derecha para vincular uno con otro, de modo que, aunque son dos aplicaciones, parecen la misma. Sólo me quedaba difundirlo a través de las redes sociales y confiar en que todo el trabajo hubiera merecido la pena.

De esta experiencia puedo extraer una moraleja clara: crear Story Maps con ArcGIS es muy fácil. Lo difícil es conseguir buenos datos para tus Story Maps.

Así que, si tenéis buenos datos y una historia que contar, no tenéis excusa para no compartirla con el mundo.

¿Y después de todo esto? Me iré de vacaciones, claro.

 

¿Quieres hacer un Story Map como éste?

Si vosotros también queréis contar una historia, aquí os damos todas las herramientas para hacer un Story Map. Una vez hecho, podéis compartirlo con nosotros o presentarlo al Concurso de Story Maps para la Conferencia Esri España 2016.

 

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: