---
author: "An-Chi Ho"
date: "2023-05-03"
output: html_document
vignette: >
  %\VignetteEngine{R.rsp::md}
  %\VignetteIndexEntry{Visualisation}
  %\usepackage[utf8]{inputenc}
---

# Visualization of different projections

This vignette shows how to use function `PlotRobinson()`, which can plot maps with the projection of your choice. Since packages `sf` and `rnaturalearth` are required by the function, make sure you have modules `PROJ`, `GEOS`, `GDAL` loaded.
The projection types and IDs can be found on https://epsg.io/.

```r
## Load packages
library(sf)
library(ggplot2)
library(rnaturalearth)
library(RColorBrewer)
library(cowplot)
library(startR)
library(s2dv)

## Source function
#URL: https://earth.bsc.es/gitlab/es/s2dv/-/raw/develop-PlotRobinson/R/PlotRobinson.R
source("/esarchive/scratch/aho/tmp/PlotRobinson.R")
## Source unexported s2dv functions used in PlotRobinson
.KnownLonNames <- s2dv:::.KnownLonNames
.KnownLatNames <- s2dv:::.KnownLatNames
.IsColor <- s2dv:::.IsColor
```
Specify where you want to save the figures later.
```r
fileout_path <- "/esarchive/scratch/<userid>"
```

## Global map

### 1. Load data

We use `startR::Start` to load system5c3s monthly temperature data from esarchive. To focus on visualization, we simply load one file with one ensemble and one time step.

```r
repos <- "/esarchive/exp/ecmwf/system5c3s/monthly_mean/$var$_f6h/$var$_$sdate$.nc"
data <- Start(dat = list(list(name = 'system5c3s', path = repos)),
              var = 'tas',
              sdate = '20170101',
              ensemble = indices(1),
              time = indices(1),
              lon = 'all',
              lon_reorder = CircularSort(-180, 180),
              lat = 'all',
              lat_reorder = Sort(decreasing = T),
              synonims = list(lat = c('lat', 'latitude'),
                              lon = c('lon', 'longitude')),
              return_vars = list(time = 'sdate', longitude = 'dat', latitude = 'dat'),
              retrieve = T)
lon <- attributes(data)$Variable$system5c3s$lon
lat <- attributes(data)$Variable$system5c3s$lat
data <- data - 273.15 # K to degC
```

### 2. Create mask

We can create a logical or [0, 1] array to serve as mask in the plot.
```r
mask <- drop(data)
mask[which(mask > -20 & mask < -10)] <- 0
mask[which(mask != 0)] <- 1
```

### 3. Create colorbar breaks and colors

Create the adequete colorbar elements for the plot
```r
## have exceeded values
brks1 <- seq(-40, 40, 10)
cols1 <- brewer.pal(9, 'PuOr')[-9]
## cover all values
#brks1 <- seq(-ceiling(max(abs(range(data)))), ceiling(max(abs(range(data)))), length.out = 11)
```
### 4. Plot

You can find more projection types through the URL above. `PlotRobinson()` is mainly designed for Robinson projection, but it is possible to use other projections as well.
E.g., Mollweide projection is "ESRI:54009" or "ESRI:53009".
Note that different PROJ and GDAL module versions have different CRS codes. If on Nord3v2, please use "ESRI:53030" or "+proj=robin" to get the correct Robinson projection.

There are two types of legend, 'ggplot2' or 's2dv'. You can also set `legend` as `NULL` to not plot legend.

```r
## legend = 'ggplot2'
PlotRobinson(data, lon, lat, brks = brks1, cols = NULL, legend = 'ggplot2',
             target_proj = 54030, style = 'point',
             toptitle = "system5c3s monthly tas Jan 2017", caption = "Projection: Robinson",
             dots = mask, units = 'degC', colNA = 'red',
             width = 10, height = 6)

## legend = 's2dv'
PlotRobinson(data, lon, lat, brks = brks1, cols = cols1, legend = 's2dv',
             target_proj = 54030, style = 'point',
             toptitle = "system5c3s monthly tas Jan 2017", caption = "Projection: Robinson",
             dots = mask, units = "degC", col_inf = 'brown',
             width = 10, height = 5,
             bar_extra_margin = c(0, 5, 0, 5),
             vertical = F)
```

<img src="vis_proj_global_1.png" width="600" />

<img src="vis_proj_global_2.png" width="600" />


## European region

### 1. Subset data

Crop the european area from the global data we loaded above.

```r
data_eu <- ClimProjDiags::Subset(data, c('lat', 'lon'), list(21:61, 161:221))
lon_eu <- lon[161:221]
lat_eu <- lat[21:61]
```
### 2. Crop mask

```r
mask_eu <- ClimProjDiags::Subset(mask, c('lat', 'lon'), list(21:61, 161:221))
```

### 3. Create colorbar breaks

```r
## have exceeded values
brks_eu <- seq(-18, 18, length.out = 11)
## cover all values
#brks_eu <- seq(-ceiling(max(abs(range(data_eu)))), ceiling(max(abs(range(data_eu)))), length.out = 11)
```

### 4. Plot
In the previous plots, we use `dots` to mark the masked area. This time, we use parameter `mask` to remove the unwanted data. The removed points are left as blank.

The parameter `crop_coastlines` helps to adjust the map coastline plotting. You can test and find the best range. Note that this parameter is not suitable for the case that longitude range exceeds half of the earth (i.e., 180 degrees.)

We can also choose to plot the map by polygon instead of point. Note that polygon is relatively **slow** so it takes a long time for global map, and it **does not work on our workstation** for some technical reason.

Note that `target_proj = 102014` does not work well on Nord3v2. Use PROJ.4 string `target_proj = "+proj=lcc +lat_0=30 +lon_0=10 +lat_1=43 +lat_2=62 +x_0=0 +y_0=0 +ellps=intl +units=m +no_defs +type=crs"` instead.

```r
## style = point
PlotRobinson(data_eu, lon_eu, lat_eu, brks = brks_eu, cols = NULL, legend = 's2dv',
             target_proj = 102014, style = 'point',
             toptitle = "system5c3s monthly tas Jan 2017",
             caption = paste0("Projection: Lambert Europe\nESRI:102014\n", "Europe"),
             mask = mask_eu, units = "degC",
             width = 8, height = 6, point_size = 1.3,
             crop_coastlines = c(lonmin = -20, lonmax = 40, latmin = 27, latmax = 70),
             triangle_ends = c(T, T), bar_extra_margin = c(0.4, 4, 0.4, 4),
             vertical = F)

## style = polygon
PlotRobinson(data_eu, lon_eu, lat_eu, brks = brks_eu, cols = NULL, legend = 's2dv',
             target_proj = 102014, style = 'polygon',
             toptitle = "system5c3s monthly tas Jan 2017",
             caption = paste0("Projection: Lambert Europe\nESRI:102014\n", "Europe"),
             mask = mask_eu, units = "degC",
             width = 8, height = 6,
             crop_coastlines = c(lonmin = -20, lonmax = 40, latmin = 27, latmax = 70),
             triangle_ends = c(T, T), bar_extra_margin = c(0.4, 4, 0.4, 4),
             vertical = F)
```

<img src="vis_proj_eu_1.png" width="450" />

<img src="vis_proj_eu_2.png" width="450" />


## North Pole region

### 1. Subset data

Crop the north pole area from the global data we loaded above.
```r
data_np <- ClimProjDiags::Subset(data, c('lat'), list(1:31))
lon_np <- lon
lat_np <- lat[1:31]
```
### 2. Crop mask

```r
mask_np <- ClimProjDiags::Subset(mask, c('lat'), list(1:31))
```

### 3. Create colorbar breaks

```r
## have exceeded values
brks_np <- seq(-40, 0, length.out = 11)
## cover all values
#brks_np <- seq(-ceiling(max(abs(range(data_np)))), ceiling(max(abs(range(data_np)))), length.out = 11)
```

### 4. Plot

We compare `PlotRobinson()` with `PlotStereoMap()`, which is specifically for the stereographic projection and it uses polygon to plot. 
Note that we cannot use `crop_coastlines` here in `PlotRobinson()` because the longitude range is global.
It is recommended saving the figures for these two plots (especially `PlotStereoMap()`) because polygon plotting is time-consuming when it is in the pop-up window.

The projection used here is Arctic Polar Stereographic (EPSG:3995).
```r
#NOTE: A bit slow, be patience.
PlotRobinson(data_np, lon_np, lat_np, brks = brks_np, cols = NULL, legend = 's2dv',
             target_proj = 3995, style = 'polygon',
             toptitle = "system5c3s monthly tas Jan 2017",
             caption = paste0("Projection: WGS 84 / Arctic Polar Stereographic\nEPSG:3995\n", "North Pole"),
             dots = mask_np, dots_size = 1.5,
             units = "degC", color_fun = clim.palette("orangepurple"),
             width = 8, height = 8,
             triangle_ends = c(T, T), bar_extra_margin = c(0.4, 4, 0.4, 4),
             vertical = F, fileout = paste0(fileout_path, '/PlotRobinson_np.png'))

# Compare with PlotStereoMap
#NOTE: Save the figure instead of plotting in pop-up window because it is slow.
PlotStereoMap(data_np, lon = lon_np, lat = lat_np, brks = brks_np, cols = NULL,
              color_fun = clim.palette("orangepurple"),
              toptitle = "system5c3s monthly tas Jan 2017 (PlotStereoMap)",
              width = 8, height = 8, filled.continent = F,
              dots = mask_np, units = "degC", title_scale = 0.8,
              fileout = paste0(fileout_path, '/PlotStereoMap_np.png'))
```

<img src="vis_proj_np_1.png" width="400" />   

<img src="vis_proj_np_2.png" width="400" />
