
library(startR)
library(s2dv)
library(CSTools)
library(lubridate)
library(multiApply)
source('/esarchive/scratch/jramon/GitLab_jramon/downscaling/csdownscale/R/Interpolation.R')
source('/esarchive/scratch/jramon/GitLab_jramon/downscaling/csdownscale/R/Utils.R')
source('/esarchive/scratch/jramon/GitLab_jramon/downscaling/csdownscale/R/Intbc.R')

plotpath <- '/esarchive/scratch/jramon/downscaling/plots/ip'
target_grid <- '/esarchive/recon/ecmwf/era5/monthly_mean/tas_f1h/tas_200002.nc'

#lonmin <- -22
#lonmax <- 45
#latmin <- 27
#latmax <- 72
lonmin <- -11.5
lonmax <- 5.35
latmin <- 35.1
latmax <- 44.1

#sdates <- c('20000201','20010201','20020201','20030201','20040201','20050201','20060201','20070201')
sdates <- format(ymd("20000201") + rep(years(0:20), each=1),"%Y%m%d")
sdates <- format(seq(ymd("20000201"), ymd("20200201"), "1 month"), "%Y%m%d")

obs <- startR::Start(dat = '/esarchive/recon/ecmwf/era5/monthly_mean/$var$_f1h-r1440x721cds/$var$_$sdate$.nc',
                     var = 'tas', time = indices(1), lat = values(list(latmin, latmax)),
                     lat_reorder = Sort(decreasing = FALSE), lon = values(list(lonmin, lonmax)),
                     lon_reorder = CircularSort(-180, 180), sdate = format(ymd(sdates), "%Y%m"), 
                     synonims = list(var = c('var','variable'), lon = c('lon', 'longitude'), 
                     lat = c('lat', 'latitude')), return_vars = list(lat = 'dat', lon = 'dat'),
                     num_procs = 1, retrieve = TRUE)

exp <- startR::Start(dat = '/esarchive/exp/ecmwf/system5c3s/monthly_mean/$var$_f6h/$var$_$sdate$.nc',
                     var = 'tas', time = indices(1), member = indices(1:3), sdate = sdates,
                     lat = values(list(latmin, latmax)), lat_reorder = Sort(decreasing = FALSE), 
                     lon = values(list(lonmin, lonmax)), lon_reorder = CircularSort(-180, 180),
                     synonims = list(var = c('var','variable'), lon = c('lon', 'longitude'), 
                     lat = c('lat', 'latitude'), member = c('member','ensemble')),
                     return_vars = list(lat = 'dat', lon = 'dat'),
                     num_procs = 1, retrieve = TRUE)

#------------------------------------
# Downscaling with Intbc
#------------------------------------
down_1_sbc <- Intbc(exp = exp, obs = obs, exp_lats = attr(exp, "Variables")$dat1$lat, 
                    exp_lons = attr(exp, "Variables")$dat1$lon, obs_lats = attr(obs, "Variables")$dat1$lat, 
                    obs_lons = attr(obs, "Variables")$dat1$lon, target_grid = target_grid, int_method = 'con', 
                    bc_method = 'simple_bias', ncores = 4)

down_1_cal <- Intbc(exp = exp, obs = obs, exp_lats = attr(exp, "Variables")$dat1$lat,
                    exp_lons = attr(exp, "Variables")$dat1$lon, obs_lats = attr(obs, "Variables")$dat1$lat,
                    obs_lons = attr(obs, "Variables")$dat1$lon, target_grid = target_grid, int_method = 'con',
                    bc_method = 'calibration', member_dim = "ensemble", ncores = 4)

down_1_qm <- Intbc(exp = exp, obs = obs, exp_lats = attr(exp, "Variables")$dat1$lat,
                   exp_lons = attr(exp, "Variables")$dat1$lon, obs_lats = attr(obs, "Variables")$dat1$lat,
                   obs_lons = attr(obs, "Variables")$dat1$lon, target_grid = target_grid, int_method = 'con',
                   bc_method = 'quantile_mapping', ncores = 4)

down_1_dbc <- Intbc(exp = exp, obs = obs, exp_lats = attr(exp, "Variables")$dat1$lat,
                    exp_lons = attr(exp, "Variables")$dat1$lon, obs_lats = attr(obs, "Variables")$dat1$lat,
                    obs_lons = attr(obs, "Variables")$dat1$lon, target_grid = target_grid, int_method = 'con',
                    bc_method = 'dynamical_bias', quanti = 0.6, ncores = 4)
#Error in (function (logdista, quanti)  : 
#  Parameter 'quanti' is too high for the length of the data provided.

#------------------------------------
# Transform exp and obs into s2dv_objects
#------------------------------------
obs <- s2dv_cube(obs, lat = attr(obs, "Variables")$dat1$lat, lon = attr(obs, "Variables")$dat1$lon,
                 source_files = attr(obs, "Files")[1,1,])
attr(obs$lon,"first_lon") <- obs$lon[1]
attr(obs$lon,"last_lon") <- obs$lon[length(obs$lon)]
attr(obs$lat,"first_lat") <- obs$lat[1]
attr(obs$lat,"last_lat") <- obs$lat[length(obs$lat)]

exp <- s2dv_cube(exp, lat = attr(exp, "Variables")$dat1$lat, lon = attr(exp, "Variables")$dat1$lon,
                 source_files = attr(exp, "Files")[1,1,])
attr(exp$lon,"first_lon") <- exp$lon[1]
attr(exp$lon,"last_lon") <- exp$lon[length(exp$lon)]
attr(exp$lat,"first_lat") <- exp$lat[1]
attr(exp$lat,"last_lat") <- exp$lat[length(exp$lat)]

#------------------------------------
# Downscaling with CST_Intbc
#------------------------------------
down_2_sbc <- CST_Intbc(exp = exp, obs = obs, target_grid = target_grid, int_method = 'con', 
                        bc_method = 'simple_bias', ncores = 4)

down_2_cal <- CST_Intbc(exp = exp, obs = obs, target_grid = target_grid, int_method = 'con', 
                        bc_method = 'calibration', ncores = 4)

down_2_qm <- CST_Intbc(exp = exp, obs = obs, target_grid = target_grid, int_method = 'con', 
                       bc_method = 'quantile_mapping', ncores = 4)

#------------------------------------
# Downscaling to point locations
#------------------------------------
points <- list(lat = c(36.1, 38.7), lon = c(-1.9, 0.8))
down_points_sbc <- CST_Intbc(exp = exp, obs = obs, points = points, method_point_interp = 'bilinear', 
                             target_grid = target_grid, bc_method = 'simple_bias', ncores = 4)
down_points_cal <- CST_Intbc(exp = exp, obs = obs, points = points, method_point_interp = 'bilinear',
                             target_grid = target_grid, bc_method = 'calibration', ncores = 4)
down_points_qm  <- CST_Intbc(exp = exp, obs = obs, points = points, method_point_interp = 'bilinear',
                             target_grid = target_grid, bc_method = 'quantile_mapping', ncores = 4)

#------------------------------------
# Downscaling to point locations given point observations
#------------------------------------
points <- list(lat = c(36.1, 38.7), lon = c(-1.9, 0.8))
obs_point <- Subset(obs, along = c("lat", "lon"), indices = list(1:2,1), drop = FALSE)
obs_point <- MergeDims(data = obs_point, merge_dims = c("lat", "lon"), rename_dim = 'location') 
down_points2_sbc <- Intbc(exp = exp, obs = obs_point, exp_lats = attr(exp, "Variables")$dat1$lat,
                          exp_lons = attr(exp, "Variables")$dat1$lon, obs_lats = points$lat,
                          obs_lons = points$lon, points = points, method_point_interp = 'bilinear',
                          source_file_exp = attr(exp, "Files")[1,1,1], source_file_obs = NULL,
                          target_grid = target_grid, bc_method = 'simple_bias', ncores = 4)
down_points2_cal <- Intbc(exp = exp, obs = obs_point, exp_lats = attr(exp, "Variables")$dat1$lat,
                          exp_lons = attr(exp, "Variables")$dat1$lon, obs_lats = points$lat,
                          obs_lons = points$lon, points = points, method_point_interp = 'bilinear',
                          source_file_exp = attr(exp, "Files")[1,1,1], source_file_obs = NULL, 
                          target_grid = target_grid, bc_method = 'calibration', ncores = 4)
down_points2_qm  <- Intbc(exp = exp, obs = obs_point, exp_lats = attr(exp, "Variables")$dat1$lat,
                          exp_lons = attr(exp, "Variables")$dat1$lon, obs_lats = points$lat,
                          obs_lons = points$lon, points = points, method_point_interp = 'bilinear',
                          source_file_exp = attr(exp, "Files")[1,1,1], source_file_obs = NULL,
                          target_grid = target_grid, bc_method = 'quantile_mapping', ncores = 4)





