# Hands-on 5: Spatial grid interpolation

## Goal
To learn how to use Start() to load the data and do the interpolation. 
In this use case, we only use Start() and load the data in the local memory.
The default transformation function is startR::CDORemapper, a wrapper function of s2dv::CDORemap that uses CDO inside.

In detail, we are going to:  
(1) Learn different ways to assign longitude and latitude in Start().  
(2) Use parameter '<dimname>_reorder' to specify the sorted order.  
(3) Use transform-related parameters.  

## 0. Load required modules and packages

We need to have CDO module loaded for interpolation. If you did not load it, quit the 
R console and load it. As for R packages, we need startR for data loading and s2dv for plotting.

```r
# Clean the session
rm(list = ls())

library(startR)
library(s2dv)
```

## 1. Define longitude and latitude
```r
  # Use this one if on workstation or nord3
  repos <- "/esarchive/exp/ecmwf/system5_m1/monthly_mean/$var$_f6h/$var$_$sdate$.nc"
  # Use this one if on Marenostrum4 and log in with PATC2022 account
  repos <- paste0('/gpfs/scratch/nct01/nct01127/d3_R_handson/esarchive/',
                  'exp/ecmwf/system5_m1/monthly_mean/',
                  '$var$_f6h/$var$_$sdate$.nc')
 
 var <- 'tas'
  sdate <- c('20170101')
  lon.min <- 0
  lon.max <- 359.9
  lat.min <- -90
  lat.max <- 90

  data <- Start(dat = repos,
                var = var,
                sdate = sdate,
                ensemble = indices(1),
                time = 'all',
                latitude = values(list(lat.min, lat.max)),
                latitude_reorder = Sort(),
                longitude = values(list(lon.min, lon.max)),
                longitude_reorder = CircularSort(0, 360),
                synonims = list(latitude = c('lat', 'latitude'),
                             longitude = c('lon', 'longitude')),
                return_vars = list(time = 'sdate',
                                   longitude = 'dat', 
                                   latitude = 'dat'),
                retrieve = TRUE
               )
```

1. Run the above script. Check the dimensions, the warning messages, and the values of 
longitude and latitude. What is the range of longitude and latitude?
```r
dim(data)
      dat       var     sdate  ensemble      time  latitude longitude 
        1         1         1         1         7       640      1296 

longitude <- attr(data, 'Variables')$dat1$longitude
range(longitude)
[1]   0.0000 359.7222

latitude <- attr(data, 'Variables')$dat1$latitude
latitude[1]
[1] -89.78488
latitude[640]
[1] 89.78488
```

2. Why 'lon.max' is 359.9 but not 360? What will happen if it is 360?
If it is 360, you only get one point of longitude. Because of `longitude_reorder = CircularSort(0, 360)`, Start() regards 0 and 360 as the same point. Therefore, we need to set a number slightly smaller than 360 but bigger than the maximum value in the original data, so we can get the whole range.

3. Now, change
	-  `latitude_reorder = Sort()` to `latitude_reorder = Sort(decreasing = TRUE)`
	-  `longitude_reorder = CircularSort(0, 360)` to `longitude_reorder = CircularSort(-180, 180)`
	-  Set `lon.min <- -180` and `lon.max <- 179.9`  
 
Check the values of longitude and latitude again. Is it different from the original script?
```r
  lon.min <- -180
  lon.max <- 179.9

  data <- Start(dat = repos,
                var = var,
                sdate = sdate,
                ensemble = indices(1),
                time = 'all',
                latitude = values(list(lat.min, lat.max)),
                latitude_reorder = Sort(decreasing = TRUE),
                longitude = values(list(lon.min, lon.max)),
                longitude_reorder = CircularSort(-180, 180),
                synonims = list(latitude = c('lat', 'latitude'),
                             longitude = c('lon', 'longitude')),
                return_vars = list(time = 'sdate',
                                   longitude = 'dat', 
                                   latitude = 'dat'),
                retrieve = TRUE)

dim(data)
      dat       var     sdate  ensemble      time  latitude longitude
        1         1         1         1         7       640      1296

longitude <- attr(data, 'Variables')$dat1$longitude
range(longitude)
[1] -180.0000  179.7222

latitude <- attr(data, 'Variables')$dat1$latitude
latitude[1]
[1] 89.78488
latitude[640]
[1] -89.78488

```
The dimensions are the same. The longitude range changes to [-180, 180], and the latitude sorts from 90 to -90.


## 2. Interpolation  
Now, let us add the transformation parameters. To understand the usage of the `transform` parameters, check FAQ on GitLab https://earth.bsc.es/gitlab/es/startR/-/blob/master/inst/doc/faq.md#5-do-interpolation-in-start-using-parameter-transform
  
```r
  data_1deg <- Start(dat = repos,
                     var = var,
                     sdate = sdate,
                     ensemble = indices(1),
                     time = 'all',
                     latitude = values(list(lat.min, lat.max)),
                     latitude_reorder = Sort(),
                     longitude = values(list(lon.min, lon.max)),
                     longitude_reorder = CircularSort(0, 360),
                   ## transformation
                     transform = CDORemapper,
                     transform_extra_cells = 2,
                     transform_params = list(grid = 'r360x181',
                                             method = 'conservative'),
                     transform_vars = c('latitude', 'longitude'),
                   ##
                     synonims = list(latitude = c('lat', 'latitude'),
                                     longitude = c('lon', 'longitude')),
                     return_vars = list(time = 'sdate',
                                        longitude = 'dat',
                                        latitude = 'dat'),
                     retrieve = TRUE)
```

1. Run the above script. Check the dimensions and the values of longitude and latitude.
```r
dim(data_1deg)
      dat       var     sdate  ensemble      time  latitude longitude 
        1         1         1         1         7       181       360 

longitude <- attr(data_1deg, 'Variables')$dat1$longitude
range(longitude)
[1]   0 359

latitude <- attr(data_1deg, 'Variables')$dat1$latitude
range(latitude)
[1] -90  90
```

2. Plot maps
Plot the two data and see the difference.

```r
# original data
lon_ori <- attr(data, 'Variables')$dat1$longitude
lat_ori <- attr(data, 'Variables')$dat1$latitude
PlotEquiMap(drop(data)[1, , ], lon = lon_ori, lat = lat_ori,
            filled.continent = FALSE,
            toptitle = "Original data: 640x1296, method: con",
            fileout = "~/handson_5_fig1.png")

# regridded data
lon_1deg <- attr(data_1deg, 'Variables')$dat1$longitude
lat_1deg <- attr(data_1deg, 'Variables')$dat1$latitude
PlotEquiMap(drop(data_1deg)[1, , ], lon = lon_1deg, lat = lat_1deg,
            filled.continent = FALSE,
            toptitle = "Regridded data: 181x360, method: con",
            fileout = "~/handson_5_fig2.png")
```
![original grid, method = 'con'](./Figures/handson_5_fig1.png)

![regrid to 1 degree, method = 'con'](./Figures/handson_5_fig2.png)


3. Try different grids and interpolation methods

- Change `method` to "bil", "bic", or other available options (check s2dv::CDORemap for details.) 

- Change `grid` to "r100x50", "t106grid", or other available options.

- Plot the map to see the difference.

![regrid to r100x50, method = 'bil'](./Figures/handson_5_fig3.png)

![regrid to t106grid, method = 'bic'](./Figures/handson_5_fig4.png)
