Menú

domingo, 7 de octubre de 2018

Interpolar lluvia usando de covariable elevación con el método Thin Plate Spline

Thin Plate Splines (Tps)
La interpolación de Thin Plate Spline corresponde a las técnicas de interpolación n-dimensional a partir de datos dispersos. La función de interpolación correspondiente es una función continuamente diferenciable (función C1) que tiene la energía (norma L2) de su segundo derivado mínimo.

El residuo de interpolación con respecto a esta interpolación puede ser 0 ó, lo que es más interesante, se puede hacer una compensación de regularidad entre el error de interpolación y la energía de la curvatura de la función.
Wahba (1990) propone un método basado en la validación cruzada para determinar la compensación óptima.

  • Thin Plate Spline adapta los datos espaciados irregularmente a una superficie. 
  • El parámetro de suavizado se elige mediante validación cruzada generalizada. 
  • El modelo asumido es el aditivo Y = f (X) + e donde f (X) es una superficie dimensional. 
  • Este es un caso especial de la estimación espacial.
Thin Plate Spline es el resultado de minimizar la suma residual de cuadrados sujetos a una restricción de que la función tiene un cierto nivel de suavidad (o penalización de rugosidad). En donde la rugosidad se cuantifica por la integral de los derivados de orden m cuadrado al cuadrado.


Para una dimensión y m = 2, la penalización de rugosidad es el cuadrado integrado de la segunda derivada de la función. Para dos dimensiones, la penalización por rugosidad es la integral de

(Dxx (f))^2 + 2 (Dxy (f)) ^2 + (Dyy (f)) ^2

Además de controlar el orden de las derivadas, el valor de m también determina el polinomio base que se ajusta a los datos. El grado de este polinomio es (m-1).

El parámetro de suavizado controla la cantidad de suavización de los datos. En la forma habitual, esto se denota con lambda, el multiplicador de Lagrange del problema de minimización. Aunque esta es una escala incómoda, lambda = 0 no corresponde con restricciones de suavidad y los datos se interpolan. lambda = infinito corresponde a simplemente ajustar el modelo de base polinomial por mínimos cuadrados ordinarios.

Este estimador se implementa pasando la función de covarianza generalizada correcta basada en funciones de base radial a la función más general Krig.  Una ventaja de esta implementación es que una vez que se crea un objeto Tps / Krig, el estimador se puede encontrar rápidamente para otros datos y parámetros de suavizado siempre que las ubicaciones permanezcan sin cambios. Esto hace que la simulación dentro de R sea eficiente.  Tps no admite actualmente el argumento de los nudos donde se puede usar un conjunto reducido de funciones básicas. Esto es principalmente para simplificar y una buena alternativa al usar nudos sería usar una covarianza válida de la familia Matern y un parámetro de gran rango.

Código utilizado en R

##################################################################
#
#       Walter Arnoldo Bardales Espinoza (bardaleswa@gmail.com)
#       julio de 2018
#
##################################################################

# Cargar librerias
library(fields)
library(raster)
library(rgdal)
library(lattice)
library(stringr)


# Cargar modelo de elevación
dem = raster("D:/Documents/GIS DataBase/DEM_CA/geotif/dem_90_gtm.tif")

# Extraer las coordenadas del DEM
coords = xyFromCell(dem,1:ncell(dem))

# Extraer los factores de las coordenadas x e y
coord_x = as.numeric(levels(factor(coords[,"x"])))
coord_y = as.numeric(levels(factor(coords[,"y"])))

# Convertir el dem en matriz y transponerlo
z = t(as.matrix(dem))

# Corregir la matriz de elevacion debido a que esta rotada 180 grados
coord_z = matrix(, nrow=length(coord_x), ncol=length(coord_y))

for(i in 1:length(coord_y)){
  j = length(coord_y)+1-i
  coord_z[,j] = z[,i]
}

#crear lista de elevación a partir del dem
elevacion = list(x=coord_x,y=coord_y,z=coord_z)

# Evaluar la lista
str(elevacion)

# Cargar los datos de lluvia
datospp = read.csv("D:/Documents/Lluvia/Lluviaxy_1980_2016.csv",sep=",")
datos = datospp

# Convertir en puntos geograficos y asignarle las coordenadas GTM
coordinates(datos) = ~x + y
gtm = CRS("+proj=tmerc +lat_0=0 +lon_0=-90.5 +y_0=0 +x_0=500000 +k=0.9998  +datum=WGS84 +units=m  +no_defs +ellps=WGS84 +towgs84=0,0,0")

proj4string(datos) = gtm

# Extraer los valores de elevacion de las estaciones a partir del DEM
altura = extract(dem,datos)

# Crear lista con los datos x, y, z y variable
xydatos = data.frame(lon=datospp$x,lat=datospp$y)
zdatos = altura

# Antes de continuar verificar que no hallan datos faltantes en las series

# Nombrar columnas
mes = c(0,0,0,1:13)
meses = c("","","","enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre", "Anual")

for(k in 4:16){
  ydatos = datospp[,k]
  
  precip = list(x=xydatos,elev=zdatos,y=ydatos)
  
  # Graficar las estaciones y valores de lluvia
  quilt.plot(precip$x,precip$y)
  
  # Crear el modelo de lluvia elevacion
  fit = Tps(precip$x, precip$y, Z=precip$elev)
  
  # Resumen del modelo lluvia elevacion con TPS
  summary(fit)
  
  # Graficar los resultados
  set.panel(2,2)
  plot(fit)
  
  # Intrpolar superficie del modelo creado
  set.panel()

  # Crear la lista de coordenadas a interpolar
  grid.list = list(x=elevacion$x, y=elevacion$y)
  
  #Interpolacion del modelo usando de covariable la elevación
  fit.full = predictSurface(fit, grid.list, extrap=TRUE, ZGrid = elevacion)

  # Transponer la matriz de resultados
  pp_z1 = t(fit.full$z)
  
  # Crear el raster interpolado
  ras = raster(pp_z1, xmn=extent(dem)[1],xmx=extent(dem)[2],ymn=extent(dem)[3],ymx=extent(dem)[4])
  ras = flip(ras,direction="y")
  crs(ras) = gtm
  ras[ras<0 0="" p="">
  
  # Guardaer el raster
  destino5 = paste("D:/Documents/Consultorias_2018/balance_hidrico/Raster/lluvia/prueb/prec_",str_pad(mes[k],width =2, pad="0"),".tif", sep ="")
  writeRaster(ras,filename=destino5, overwrite=TRUE)
}

Resultados de la interpolación 















domingo, 5 de agosto de 2018

sábado, 4 de agosto de 2018

miércoles, 11 de julio de 2018

Estimar parámetros de la curva de calibración de caudales o descarga con R

#################################################################################
#
#
# Estimación de los parámetros de l curva de descarga
# Ajusta y plotea la grafica de curva descarga siguiendo una funcion exponencial
#
#  Walter Arnoldo Bardales Espinoza
#
#################################################################################

# remover todos los objetos de almacenamiento
rm(list = ls())

# cargar libreria
require(Hmisc)
library(minpack.lm)

# leer datos de aforos y niveles
dato.aforos = read.table("D:/Documents/Curva_calibracion_de_caudales/est_Matucuy.txt", header = TRUE, sep = "\t",na.strings = "-99.9")


plot(Caudal~Nivel)

# Para usar los nombres de los campos de las columnas
attach(dato.aforos)


# Estima los valores de los parametros iniciales de la curva
# Estableciendo h0 a un valor por debajo del minimo observado
rango=range(Nivel)
h.min=rango[1]
h.max=rango[2]
ho.inicial =  h.min - 0.1*(h.max - h.min)

# modelo lineal para estimar los valores inicial de k y n
modelo.log = lm( log10(Caudal) ~ log10(Nivel - ho.inicial) )
a.inicial = 10^modelo.log$coefficients[[1]]
b.inicial = modelo.log$coefficients[[2]]

# Utilizar los coeficientes calculados inicialmente para estimar los parametros de la regresion no lineal
curva.descarga = nlsLM( Caudal ~ k*(Nivel-ho)^n, start = list(k=a.inicial,n=b.inicial, ho=ho.inicial), control = list(maxiter=500))

# Resumen de los estadisticos de la curva de descarga
summary(curva.descarga)

# Grafico de la curva de descarga o calibracion
xmin = min(Nivel)
xmax = max(Nivel)
dx = 0.01*(xmax - xmin)
x = seq(xmin,xmax,dx)
coef.model = coef(curva.descarga)
qest = coef.model[1]*(x - coef.model[3])^coef.model[2]


plot(Nivel, Caudal,
     ylim = c(0, max(Caudal)+0.2*(max(Caudal)-min(Caudal))),
     xlim = c(min(Nivel)-0.1*(rango[2]-rango[1]), max(Nivel)+0.2*(rango[2]-rango[1])),
     xlab = "Nivel (m)",
     ylab = expression("Q ("*m^3*s^{-1}*")"),
     pch = 21, bg = "black",
     main = "Curva de calibracion de caudales de la estacion Matucuy, Periodo 2002 - 2015"
)
lines(x, qest, col = "red")
text(min(Nivel)+0.1*(max(Nivel)-min(Nivel)),max(Caudal), paste0("Q = ",round(coef.model[1],3),"*(H-(",round(coef.model[3],3),"))^",round(coef.model[2],3)))
text(min(Nivel)+0.1*(max(Nivel)-min(Nivel)),0.95*max(Caudal),paste0("RMS =", round(mean((Caudal-(coef.model[1]*(Nivel - coef.model[3])^coef.model[2]))^2))))

#################################################################### Fin código


viernes, 6 de julio de 2018

Relleno de datos de lluvia mensual de una estación con CHIRPS

Anteriormente, generamos una función para descargar los raster de lluvia estimada a partir de satélite (CHIRPS V 2.0), ahora lo que vamos hacer es extraer los datos para un punto en especifico o la ubicación de una estación climática, el periodo de tiempo de la serie de datos chirps debe ser la misma que la serie de datos de la estación (no importa que existan datos faltantes, solo especificar el datos faltante como -99.9) para que sean comparables.

Luego se creara un modelo de ajuste entre los datos estimados y los datos reales, esto con el fin de que los datos a rellenar sean acordes a la tendencia de los datos observados o pluviometricos.

La importancia de completar series de datos radica darle continuidad a la serie y que esto me permita realizar mejores análisis, crear modelos hidrológicos estables, balances hídricos, etc.

####################################################################

library(raster)

# Ruta del directorio de trabajo
setwd("D:/Documents/chirps/")

# Directorio de los datos de chirp V-2.0
ruta_chirps = "D:/Documents/chirps/raster/"

# Periodo de datos a analizar
fecha_inicial = c("1981/1/1")
fecha_final = c("2018/5/1")

# Coordenada geografica de las estacion (longitud, Latitud)
coor.x = c(-89.8106)
coor.y = c(15.6083)

# Convertir las coordenadas de las estaciones a puntos
ubicacion = data.frame(lon=coor.x, lat=coor.y)
coordinates(ubicacion) = c("lon", "lat")
proj4string(ubicacion) = CRS("+init=epsg:4326") # WGS 84

# Cargar los datos raster
lista_chirps = paste0(ruta_chirps,"chirps-v2.0.", format(seq(as.Date(fecha_inicial), as.Date(fecha_final), "month"), "%Y.%m"), ".tif")
ras_chirps = stack(lista_chirps)

# Extraer datos de lluvia de la estacion
chirps = as.vector((extract(ras_chirps, ubicacion)))

# Cargar datos pluviometricos (reales u observados) de la estacion
estacion = scan("estaciones/Cahabon_1_1981_5_2018.txt", sep = "\t", na.strings = "-99.9")
serie = estacion


# Modelo de ajuste de datos chirps a pluviometicos
model = lm(estacion~chirps)

# estadisticos del modelo de ajuste lineal
summary(model)

# coeficientes del modelo de ajuste lineal
alfa = coef(model)[[2]]
beta = coef(model)[[1]]

# Grafica
plot(estacion~chirps)
abline(b=1,a=1, col="red")

# posiciones de datos faltantes pluviometricos
faltantes = which(is.na(serie))

# Datos chirps ajustados para relleno
relleno = round(alfa*chirps[faltantes]+beta,1)

# Completacion de la serie real
serie[faltantes] = relleno

# Grafico de serie completa (negro) y serie incompleta (rojo)
plot(serie,type="l", xlab="Lluvia [mm]", main="Comparacion de serie completa e incompleta de lluvia")
lines(estacion, col="red")

# Crear tabla de fechas y serie completa
fecha = format(seq(as.Date(fecha_inicial), as.Date(fecha_final), "month"), "%Y.%m")
serie.completa = data.frame(fecha,serie)

write.csv(serie.completa, "Cahabon_rellenada.csv", row.names = FALSE)

#############################################################

Descargar
Archivo_R

Delimitacion de cuencas con qgis y grass

https://youtu.be/ytsEYNy4Xn4

jueves, 5 de julio de 2018

Extraer datos de lluvia en una cuenca usando R

La falta de datos de lluvia en una cuenca, no es impedimento para poder realizar un balance hídrico hoy en día, ya que existen datos de hidroestimación o datos de lluvia estimada a partir de satelites o radares.  Estos datos tienen la ventaja que proporcionan la distribución espacial de la lluvia, pero su desventaja es que tienen a subestimar o sobrestimar en algunos eventos de lluvia y esto depende del tipo de lluvia; pero mediante un ajuste por regresión se puede reducir el error.
 También, pueden usarse para rellenar datos mensuales, trimestrales, anuales de lluvia en las series observadas, mediante un ajuste.

## Script para descargar datos chirps 2.0 y extraer la lluvia media de la cuenca
## Walter Bardales
## Fecha: 01/07/2018


#################################################################################

library(R.utils)

# Funcion de descarga Chirps V2.0
download.chirps2.0 = function(Ruta, fecha_inicial, fecha_final){
fecha=format(seq(as.Date(fecha_inicial), as.Date(fecha_final), "month"), format="%Y.%m")
for (i in 1:length(fecha)){
wurl=paste0("ftp://ftp.chg.ucsb.edu/pub/org/chg/products/CHIRPS-2.0/camer-carib_monthly/tifs/","chirps-v2.0.",fecha[i],".tif.gz")
download.file(wurl,paste0(Ruta,"chirps-v2.0.",fecha[i],".tif.gz"))
gunzip(paste0(Ruta,"chirps-v2.0.",fecha[i],".tif.gz"))
}
}

#################################################################################

# Cargar libreria de trabajo
library(raster)
library(rgdal)

# Directorio de trabajo
setwd("D:/Documents/chirps/")

# Cargar funcion de descarga chirps V2.0
source("Funcion_descarga_chirps.R")

# Directorio de la descarga
Ruta = "D:/Documents/chirps/raster/"

# Periodo de descarga
fecha_inicial = c("1983/5/1")
fecha_final = c("1983/8/1")

# Descargar archivos chirps y descomprimir
download.chirps2.0(Ruta,fecha_inicial, fecha_final)

# Desactivar el paquete R.utils por tener conflicto con el paquete Raster
detach("package:R.utils", unload=TRUE)

# Cargar los datos de chirps 2.0
lista_archivos = paste0("raster/","chirps-v2.0.",format(seq(as.Date(fecha_inicial), as.Date(fecha_final), "month"),"%Y.%m"),".tif")
chirps = stack(lista_archivos)

# Cargar el poligono de la cuenca en coordenadas geograficas
cuenca = readOGR("shapefile/La_Pasion.shp") # Indicar el directorio de la cuenca

# Extraer los datos
ppcuenca = t(extract(chirps, cuenca, fun=mean))
row.names(ppcuenca) = NULL # Crear serie de datos y guardar
lluvia_media = data.frame(fecha=format(seq(as.Date(fecha_inicial), as.Date(fecha_final), "month"),"%Y.%m"), Lluvia=ppcuenca)

write.csv(lluvia_media, "Lluvia_La_Pasion.csv", row.names = FALSE) # Cambiar el nombre del archivo de salida


#######################################################################

Descargar scripts