Estudios de paisaje, cartografía (R y QGIS), diseño ambiental 3D (Blender) y análisis de datos geográficos en R

Contact Info
Ferrol, Santiago de Compostela, Galicia, Spain, The World

+00(34) not yet...

Privacy

Follow ModlEarth

Zonificación Ambiental Energías Renovables, WMS y R parallel

Zonificación Ambiental Energías Renovables, WMS y R parallel

Este post está destinado a aquellos que, como en mi caso, os hayais dado de bruces intentando replicar o al menos manejar los nuevos mapas de Zonificación Ambiental para proyectos de energías renovables. En resumen, estos mapas cruzan multitud de fuentes de información para “calificar” el territorio en función de la sensibilidad ambiental. Supuestamente hay unas zonas de valores máximos que deberían ser, bajo los métodos de cálculo, intocables, peeeero…la fuente no es vinculante ni obliga a nada.

¿Cómo se descarga la zonificación?

La respuesta a esta pregunta no la sé. Es posible que se deba a que será un servicio vivo y que puede estar expuesto a modificaciones. Así que, ¿por qué sobrecargar los servidores con miles de descargas que quedarán obsoletas en unos meses? Lo que sí se ofrecen son los servicios WMS para cargar en vuestros proyectos:

Si no es suficiente el WMS para ti, entonces tendrás que trabajar un poco. Vamos allá.

Capturar el servicio WMS (método QGIS a lo bruto)

QGIS puede ser utilizado de forma un poco salvaje para descargar un servicio WMS completo. Claro, son imágenes, pero si calculáis bien la resolución y dimensiones totales y de las partes del raster podréis conseguir un buen resultado. Quizá el proceso de cálculo de teselas, generación del atlas y exportación podrían ser explicadas en otro artículo. De momento lo indico en un pequeño resumen:

  1. Diseñar un mapa sencillo en el atlas. Si es demasiado grande (por ejemplo la extensión de España) podréis ser bloqueados por el servidor o bloqueados por vuestos modulos de RAM. En mi caso, el diseño de hoja es de 1x1m. Not bad.
  2. Calcular la resolución y escala a la que la imagen empieza a “mostrar” el tamaño de pixel. Lo podéis ver también en la información del servicio.
  3. Crear un grid con vuestra herramienta favorita a partir de la escala total y escala a la que irán las hojas tendréis más o menos teselas. Estas serán las teselas a imprimir.
  4. El grid servirá de atlas. Así que, una vez tengáis todo listo, activáis el atlas y vais exportando a .tif o a otro formato pero con información georreferenciada. Haced esto por la noche que los servidores estarán más ligeros y no molestaréis a nadie.
  5. Construir un raster virtual a partir de todas esas hojas generadas y listo. Ya tenéis el servicio descargado.

Aquí una pequeña vista para que os hagáis una idea.

Un momento… ¡¡Malditos raster multibanda, solo quiero los valores!!

Este es el meollo del artículo. Malditos colores y bandas, si tan siquiera pudiésemos tener simples valores numéricos. ¿Cómo se hace eso? Volviendo a trabajar.

La transformación de los rasters puede ser realizada en R, como todo, como siempre. En este caso os expongo el código completo junto a un pequeño resumen de lo que se ejecuta en él. El código es suficientemente explicativo, aunque cabe destacar que hay partes que se ejecutan con procesos en paralelo y están configuradas para ejecutarse en entorno linux. Por lo demás, nada de qué preocuparse.

Procesado de rasters en paralelo

El resumen del proceso:

  1. Establecer los parámetros: directorios donde se alojan los archivos raster georreferenciados, las carpetas de salida para los archivos transformados en valores y nombre del raster virtual a generar con ellos. Calcular las combinaciones posibles de colores. Esto es necesario para establecer el gradiente correcto de valores. En este proceso básicamente se leerán los rasters en paralelo y se extractarán todos los colores diferentes en cada uno. Los valores se convertirán en formato hex.
  2. Ordenar colores. Es uno de los principales hándicaps de haber descargado el wms a lo bruto. A partir del visor web se ha comprobado que los valores van de 0 a 10, siendo 10 el máximo valor ambiental. En base a esto, se asignarán los valores a los colores. En este caso, el naranja más fuerte será el 10.
  3. Transformar los colores de los rasters en valores 0 a 10. Esto se realiza también en paralelo para agilizar el proceso. Esto permite (1) aligerar los archivos iniciales al pasar de un raster multibanda a un raster singleband y (2) poder fliparse.
  4. Crear un raster virtual con los nuevos archivos. Una función muy sencilla de utilizar está en la librería landtools, todavía en proceso de pulido.
library(raster)
library(ggplot2)
library(parallel)

# Parámetros
# Realizar cambios en función de la fuente y localización de los archivos raster
# generados a partir del proceso explicado para QGIS
source <- '../01_Fuentes/02_GIS/Zonificación/EAEF/E25000_CAN/'
r <- stack('../01_Fuentes/02_GIS/Zonificación/EAEF/EAEF_E25000_CAN.vrt')
outdir <- '../01_Fuentes/02_GIS/Zonificación/EAEF/E25000_CAN_val/'
outname <- 'EAEF.tif'

# Salida para el vrt
out <- '../01_Fuentes/02_GIS/Zonificación/EAEF/'
vrtname <- 'EAEF_E25000_CAN_val.vrt'

#-------------------------------------------------------------------------------
# 1. Calcular todas las combinaciones posibles de colores RGB
#-------------------------------------------------------------------------------
files <- list.files(source, '.tif$', full.names = TRUE)

#-----
# Proceso en paralelo con barra de progreso
library(doSNOW)
library(tcltk)

cl <- makeSOCKcluster(detectCores())
registerDoSNOW(cl)

pb <- txtProgressBar(max=100, style=3)
progress <- function(n) setTxtProgressBar(pb, n)
opts <- list(progress=progress)
vals <- foreach(i=seq_along(files), .options.snow=opts) %dopar% {
        unique(paste(raster::values(raster::raster(files[[i]], 1)),
                     raster::values(raster::raster(files[[i]], 2)),
                     raster::values(raster::raster(files[[i]], 3))))
}
close(pb)
stopCluster(cl)
#-----
RGBcomb <- unique(unlist(vals))

# Agrupar los valores
numbs <- str_split(RGBcomb, ' ')

# Crear lista de valores en formato hex
hexs <- list()
for(i in seq_along(numbs)){
        x <- as.numeric(numbs[[i]])
        hexs[[i]] <- rgb(x[1], x[2], x[3], maxColorValue = 255)
}

#-------------------------------------------------------------------------------
# 2. ORDENAR COLORES, 
# https://stackoverflow.com/questions/61193516/how-to-sort-colours-in-r
# Por suerte solo hace falta ordenarlos por intensidad
#-------------------------------------------------------------------------------
library(TSP)
rgbs <- col2rgb(hexs)
lab <- convertColor(t(rgbs), 'sRGB', 'Lab')
oc2 <- hexs[order(lab[, 'L'])]
qplot(x = seq_along(hexs), y = 1, fill = I(oc2), geom = 'col', width = 1) +
    theme_void()

# color alto = 10, color bajo = 0 (sin valor)
# el resto de valores se dividen por igual  
maxhex <- oc2[[1]]
minhex <- oc2[[length(oc2)]]
maxval <- 10
minval <- 0
interhex <- length(oc2)-2
interdiv <- ceiling(interhex/9)
vals <- rep(9:1, times = interhex, length.out = interhex, each = interdiv)
vals <- c(maxval, vals, minval)

# Compound list of values (index)
hex <- unlist(oc2)
val <- vals

#-------------------------------------------------------------------------------
# 3. Transformar todos los rasters de colores en raster de valores
#-------------------------------------------------------------------------------
cl <- parallel::makeCluster(detectCores(), type="FORK")
doParallel::registerDoParallel(cl)
foreach(i=seq_along(files)) %dopar% {
        r <- stack(files[i])
        rasterhex <- rgb(values(r), maxColorValue = 255)
        
        # map values
        nval <- as.numeric(plyr::mapvalues(rasterhex, from=hex, to=val))
        
        # Create a raster replacing hex values for vals calculated
        newr <- raster()
        res(newr) <- res(r)
        dim(newr) <- dim(r)
        crs(newr) <- crs(r)
        extent(newr) <- extent(r)
        
        # Change raster values
        newr[] <- nval
        
        # Export raster
        # fname <- str_replace(basename(files[i]), '.tif$', '')
        fname <- basename(files[i])
        writeRaster(newr, paste(outdir, fname), datatype="FLT4S", overwrite=T)
}
stopCluster(cl)

#-------------------------------------------------------------------------------
# 4. Construir un nuevo raster virtual con los nuevos archivos raster de valores
#-------------------------------------------------------------------------------
library(landtools)
library(rgdal)
library(gdalUtils)
landtools::dir2vrt(outdir, out, vrtname = vrtname, pattern = '.tif$')

Aquí podéis ver cómo la ejecución de los procesos en paralelo os permite generar archivos raster modificados a toda leche. Os lo recomiendo mucho para ejecutar cualquier tipo de tareas sobre ellos (crops, masks, reclass, etc). Con esto estarían listos los rasters donde como mínimo podréis ver las zonas con valores máximos y qué proyectos, presentes o futuros, están actualmente sobre ellas.


También podrían interesarte las siguientes entradas del blog...