#install.packages("gstat")
#install.packages("sp")
#install.packages("automap")
#install.packages("ggmap")
#install.packages("mapview")
#install.packages("raster")
#install.packages("viridis")
#install.packages("viridisLite")
#install.packages("akima")
#install.packages("ggpubr")
#install.packages("jtools")


# Load libraries
library(gstat)
library(sp)
library(automap)
library(ggmap)
library(mapview)
library(raster)
library(viridis)
library(akima)

#library(AgroR)
library(ggplot2)
library(ggpubr)
library(jtools)




# Setting
wdir <- "/home/abarrant/Documents/RStudio/handon_final/"
crs_latlon <- "+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0" #projeccio dades 
crs_utm    <- "+proj=utm +zone=31 +ellps=intl +units=m +no_defs"       #universal transversal mercator zona 31 cat

############################################################
#                                                          #
#     Step 1: load obs and model                           #
#                                                          #
############################################################
sp_model <-readRDS(paste0(wdir,"sp_model.RDS"))                       #carregar dades model CALIOPSE
sp_obs_locations <- readRDS(paste0(wdir,"sp_obs_locations.RDS"))      #carregar coordenades estacions obs
df_obs <- readRDS(paste0(wdir,"df_obs.RDS"))                          #carregar dades obs 
df_obs_filled <- readRDS(paste0(wdir,"df_obs_filled.RDS"))            #carregar dades amb el gap filling fet

mapview(sp_model)  #fitxer special points
mapview(sp_obs_locations)


#df_obs <- df_obs_filled  #en cas que volguem correr el codi amb les dades filled


############################################################
#                                                          #
#     Step 2: interpolate raw to AQMS's location           #
#                                                          #
############################################################

#Compute Variogram
#we are picking random points to ease the variogram computation (there are >8000 points)  (mostra dels 8000 punts, n'agafem 1000)
set.seed(1)                 #pq sigui reproduible i donin els mateixos resultats

pick_random_points        <- sample(1:nrow(sp_model),1000)  #crear un vector amb 1000 punts amb valors aleatoris del 1 al numero total de punts del model

input_data_example <- sp_model[pick_random_points, ] #seleccionem dels punts que teniem del model els que hem generat aleatoriament (files concretes, totes les col)
mapview(input_data_example)

# Variogram fitting (correlacio espacial del model)
pollutant.fit_ok          <- automap::autofitVariogram(formula=pollutant_model~1, input_data=sp_model[pick_random_points,],model="Gau")  #agafem 1000 punts per fer el variograma (si els agafessim tots seria molt pesat)
# Visualize the resulting variogram
plot(pollutant.fit_ok)  #np es refereix al numero de punts que han agrupat en aquella dist

# Set gstat object  (pollutant~1 estimacio lineal)                    #col var_model, nmax=25 agafar les 25 punts mes propers 
ok_gstat <- gstat(formula=pollutant_model~1, data = sp_model, model = pollutant.fit_ok$var_model, nmax=25)  #transformem el variograma a un gstat (geostatistics)

# project the spatial points dataframe to indicate where to interpolate in UTM
sp_obs <- spTransform(sp_obs_locations, sp::CRS(crs_utm))   #transformacio de la projeccio original a la mercator, ho fem pq els calculs van mes rapids

# Interpolation using Ordinary Kriging
OK   <- predict(object=ok_gstat, newdata=sp_obs)   #fem l'ordinary kriging a partir del variograma trsnformat a gstats, i la new data es les dades de les observacions en totes les estacions 
                                                   #dona el valor predit del model amb la correcio gracies al variograma i la variancia

# Visualize the raw model values at the AQMS' locations 
mapview(OK, zcol="var1.pred")  #valor predit corregit
mapview(OK, zcol="var1.var")   #variancia de cada valor

############################################################
#                                                          #
#    Step 3&4: Universal Kriging                           #
#                                                          #
############################################################

# Build a dataframe with model&obs information
df_rawmodel_interpolated               <- data.frame(lat=sp_obs_locations@coords[,2],
                                           lon=sp_obs_locations@coords[,1],
                                           pollutant_model=OK@data$var1.pred,
                                           ref_obs=sp_obs_locations@data$code)
df_obs_cols <- data.frame(pollutant_obs = as.numeric(df_obs[1,]) , ref_obs = colnames(df_obs))
df_model_obs <- merge(df_rawmodel_interpolated, df_obs_cols, by = "ref_obs")

# Visualize model & obs
head(df_model_obs)
plot(df_model_obs$pollutant_obs,df_model_obs$pollutant_model,xlab="Observations",ylab="Raw model",xlim=c(0,50),ylim=c(0,50))

# Remove missing values
df_model_obs <- na.omit(df_model_obs)  #no podem treballar amb nan, per tant els eliminem i ens quedem nomes amb els valors que tenim 
View(df_model_obs) #tobre el fitxer de dades

# Build spatial points dataframe (passar dun dataframe a un special point, MOLT UTIL)
sp_model_obs <- df_model_obs 
coordinates(sp_model_obs)        <- ~lon+lat
sp::proj4string(sp_model_obs)    <- crs_utm
mapview(sp_model_obs)

# Fit variogram of the residual regression model between obs and raw CALIOPE
pollutant.fit_loocv <- automap::autofitVariogram(formula=pollutant_obs~pollutant_model,input_data=sp_model_obs, verbose=FALSE,model="Gau", miscFitOptions = list(merge.small.bins = FALSE))
plot(pollutant.fit_loocv)

# Apply Universal Kriging to the whole map
uk_gstat         <- gstat(formula=pollutant_obs~pollutant_model,data=sp_model_obs, model = pollutant.fit_loocv$var_model)
corrected_model  <- predict(object=uk_gstat, newdata=sp_model)
#mapview(corrected_model)  #et corretgeix a tots els punts del model

mapview(corrected_model, zcol="var1.pred") 
mapview(corrected_model, zcol="var1.var") 


############################################################ 
#                                                          #
#    Plot PM2.5 map corrected and not corrected            #
#                                                          #
############################################################
# Plot PM2.5 map  not corrected
sp_uniform           <- akima::interp(x=sp_model,z="pollutant_model",nx=200,ny=200)
mean_raster            <- raster::raster(sp_uniform)
mapview(mean_raster)

# Plot PM2.5 map corrected
sp_uniform_uk           <- akima::interp(x=corrected_model,z="var1.pred",nx=200,ny=200)
mean_raster_uk            <- raster::raster(sp_uniform_uk)
mapview(mean_raster_uk)








############################################################
#                GAP FILLING FET                           #
############################################################

df_obs <- df_obs_filled  #en cas que volguem correr el codi amb les dades filled


############################################################
#                                                          #
#     Step 2: interpolate raw to AQMS's location           #
#                                                          #
############################################################

#Compute Variogram
#we are picking random points to ease the variogram computation (there are >8000 points)  (mostra dels 8000 punts, n'agafem 1000)
set.seed(1)                 #pq sigui reproduible i donin els mateixos resultats

pick_random_points        <- sample(1:nrow(sp_model),1000)  #crear un vector amb 1000 punts amb valors aleatoris del 1 al numero total de punts del model

input_data_example <- sp_model[pick_random_points, ] #seleccionem dels punts que teniem del model els que hem generat aleatoriament (files concretes, totes les col)
mapview(input_data_example)

# Variogram fitting (pesos de cada estacio)
pollutant.fit_ok          <- automap::autofitVariogram(formula=pollutant_model~1, input_data=sp_model[pick_random_points,],model="Gau")  #agafem 1000 punts per fer el variograma (si els agafessim tots seria molt pesat)
# Visualize the resulting variogram
plot(pollutant.fit_ok)  #np es refereix al numero de putns que han agrupat en aquella dist

# Set gstat object  (pollutant~1 estimacio lineal)                    #col var_model, nmax=25 agafar les 25 estacions mes properes
ok_gstat <- gstat(formula=pollutant_model~1, data = sp_model, model = pollutant.fit_ok$var_model, nmax=25)  #transformem el variograma a un gstat (geostatistics)

# project the spatial points dataframe to indicate where to interpolate in UTM
sp_obs <- spTransform(sp_obs_locations, sp::CRS(crs_utm))   #transformacio de la projeccio original a la mercator, ho fem pq els calculs van mes rapids

# Interpolation using Ordinary Kriging
OK   <- predict(object=ok_gstat, newdata=sp_obs)   #fem l'orginari kriging a partir del variograma trsnformat a gstats, i la new data es les dades de les observacions en totes les estacions 
#dona el valor predit del model amb la correcio gracies al variograma i la variancia

# Visualize the raw model values at the AQMS' locations 
mapview(OK, zcol="var1.pred")

############################################################
#                                                          #
#    Step 3&4: Universal Kriging                           #
#                                                          #
############################################################

# Build a dataframe with model&obs information
df_rawmodel_interpolated               <- data.frame(lat=sp_obs_locations@coords[,2],
                                                     lon=sp_obs_locations@coords[,1],
                                                     pollutant_model=OK@data$var1.pred,
                                                     ref_obs=sp_obs_locations@data$code)
df_obs_cols <- data.frame(pollutant_obs = as.numeric(df_obs[1,]) , ref_obs = colnames(df_obs))
df_model_obs <- merge(df_rawmodel_interpolated, df_obs_cols, by = "ref_obs")

# Visualize model & obs
head(df_model_obs)
plot(df_model_obs$pollutant_obs,df_model_obs$pollutant_model,xlab="Observations",ylab="Raw model",xlim=c(0,50),ylim=c(0,50))

# Remove missing values
df_model_obs <- na.omit(df_model_obs)  #no podem treballar amb nan, per tant els eliminem i ens quedem nomes amb els valors que tenim 
View(df_model_obs) #tobre el fitxer de dades

# Build spatial points dataframe (passar dun dataframe a un special point, MOLT UTIL)
sp_model_obs <- df_model_obs 
coordinates(sp_model_obs)        <- ~lon+lat
sp::proj4string(sp_model_obs)    <- crs_utm
mapview(sp_model_obs)

# Fit variogram of the residual regresision model between obs and raw CALIOPE
pollutant.fit_loocv <- automap::autofitVariogram(formula=pollutant_obs~pollutant_model,input_data=sp_model_obs, verbose=FALSE,model="Gau", miscFitOptions = list(merge.small.bins = FALSE))
plot(pollutant.fit_loocv)

# Apply Universal Kriging to the whole map
uk_gstat         <- gstat(formula=pollutant_obs~pollutant_model,data=sp_model_obs, model = pollutant.fit_loocv$var_model)
corrected_model_gapfilled  <- predict(object=uk_gstat, newdata=sp_model)
mapview(corrected_model_gapfilled)  #et corretgeix a tots els punts del model

############################################################
#                                                          #
#    Plot PM2.5 map corrected and not corrected            #
#                                                          #
############################################################
# Plot PM2.5 map  not corrected
sp_uniform           <- akima::interp(x=sp_model,z="pollutant_model",nx=200,ny=200)
mean_raster            <- raster::raster(sp_uniform)
mapview(mean_raster)

# Plot PM2.5 map corrected
sp_uniform_uk           <- akima::interp(x=corrected_model,z="var1.pred",nx=200,ny=200)
mean_raster_uk_gapfilled  <- raster::raster(sp_uniform_uk)
mapview(mean_raster_uk_gapfilled)


#########
plot(corrected_model$var1.pred, corrected_model_gapfilled$var1.pred)
plot(corrected_model$var1.var, corrected_model_gapfilled$var1.var)

#data(movies) # Telling R we want to use this data
#fit <- lm(corrected_model$var1.pred ~ corrected_model_gapfilled$var1.pred)
#summ(fit)


