---
title: "Map: Equidistant Projection"
author: "An-Chi Ho"
date: "2023-11-20"
output: html_document
vignette: >
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteIndexEntry{Map: Equidistant Projection}
  %\usepackage[utf8]{inputenc}
---

We will use the data loaded in [Data Loading](data_loading.md) in this vignette. 
Please follow that vignette first to get the data if you want to replicate the results in this vignette. Load European region data with `region = "euro"` in the loading script.

# Map plotting

In this vignette, we will go through the functions that plot the maps with equidistant projection: 
`VizEquiMap()`, `VizAnimateMap()`, `VizLayout()`.

Some traits of these plotting functions:
 - Expect a data matrix in the parameter `var` of dimensions 
`c(n. of latitudes, n. of longitudes)`, `lat` with a vector with the latitudes 
of the centers of the grid cells and `lon`, a vector with the longitudes. 
 - The N colors to paint the grid cells with (via `cols`) as well as the N +
1 threshold magnitudes (via `brks`) that will allow to assign each grid cell 
value one of the N colours. The colour for any missing values can be adjusted 
with `colNA`.
 - Whether to fill the map continents or only draw coast wires can be adjusted
with `filled.continents`.
 - A matrix of `dots` can be plotted over the drawn map to, e.g., highlight 
cells where a skill has been greatest or most significant.
 - A legend can be drawn (unless disabled with `drawleg`) and the amount of 
ticks on that legend can be adjusted with `subsampleg`.
 - They accept any additional parameters via the parameter `...` to be sent to
the underlying R graphics `image()` function for a fine tuning.

Check the function documentation to see all the parameters that help you adjust the visualization.

## VizEquiMap()

VizEquiMap() plots the map with rectangular equidistant projection. 
It has various parameters to adjust the visualization.

### Basic usage

Plot the raw experimental and observational data.
```r
# Plot the first experiment, ensemble mean, first start year, first forecast time
exp1 <- ClimProjDiags::Subset(exp, c("dat", "var"), list(1, 1), drop = 'selected')
exp1 <- s2dv::MeanDims(exp1, "ensemble")
lats <- attr(exp, 'Variables')$system5c3s$lat
lons <- attr(exp, 'Variables')$system5c3s$lon

VizEquiMap(exp1[1, 1, , ], lon = lons, lat = lats, filled.continents = FALSE,
           toptitle = "SEAS5 near-surface temperature, Nov. 1997", 
           units = "K", bar_limits = c(250, 300), brks = 21,
           width = 8, height = 8, bar_extra_margin = c(1, 0, 1, 0),
           fileout = 'map_equi_raw_exp1.png')

# Plot corresponding observational data
obs1 <- ClimProjDiags::Subset(obs, c("dat", "var"), list(1, 1), drop = 'selected')
VizEquiMap(obs1[1, 1, , ], lon = lons, lat = lats, filled.continents = FALSE,
           toptitle = "ERA5 near-surface temperature, Nov. 1997", 
           units = "K", bar_limits = c(250, 300), brks = 21,
           width = 8, height = 8, bar_extra_margin = c(1, 0, 1, 0),
           fileout = 'map_equi_raw_obs.png')
```
<img src="./Figures/map_equi_raw_exp1.png" width="600" />
<img src="./Figures/map_equi_raw_obs.png" width="600" />

### dots

Plot correlation with the significance by parameter `dots`. 
Use s2dv function `Corr()` to calculate the correlation. The dotted points are the insignificant ones.

```r
corr <- s2dv::Corr(exp1, obs1, time_dim = 'sdate', dat_dim = NULL, sign = TRUE,
                   conf = FALSE, pval = FALSE)
VizEquiMap(corr$corr[1, , ], lon = lons, lat = lats, filled.continents = FALSE,
           dots = !drop(corr$sign)[1, , ], dot_symbol = 3, dot_size = 1.2,
           toptitle = "Correlation of near-surface temperature, SEAS5 - ERA5, Nov. 1997", 
           title_scale = 0.7, color_fun = ClimPalette("yellowred"),
           bar_limits = c(0, 1), brks = 21,
           width = 8, height = 8, bar_extra_margin = c(1, 0, 1, 0),
           fileout = 'map_equi_corr_exp1_obs.png')
```

<img src="./Figures/map_equi_corr_exp1_obs.png" width="600" />

### contours

To draw the contour lines, set parameter `square` as FALSE to smooth the grid borders.
The contours can be adjusted by providing a matrix to parameter `contours` with dimensions 
`c(n. of longitudes, n. of latitudes)`. The contours matrix will be drawn over the map, 
using the thresholds provided in `brks2`.

You can also plot the contours of the original data without border 
smoothing, to plot only some of the default contours, or to plot contours 
defined by another field.  

Here, we plot the same raw data as the previous section but with contours. 
```r
VizEquiMap(exp1[1, 1, , ], lon = lons, lat = lats, filled.continents = FALSE,
           square = FALSE,
           toptitle = "SEAS5 near-surface temperature, Nov. 1997", 
           units = "K", bar_limits = c(250, 300), brks = 21,
           width = 8, height = 8, bar_extra_margin = c(1, 0, 1, 0),
           fileout = 'map_equi_contour_raw_exp1.png')

# Adjust the styles
VizEquiMap(exp1[1, 1, , ], lon = lons, lat = lats, filled.continents = FALSE,
           square = TRUE, 
           contours = exp1[1, 1, , ], contour_lwd = 1, brks2 = seq(240, 300, 5),
           contour_color = 'blue', contour_lty = 5, contour_label_scale = 0.7,
           toptitle = "SEAS5 near-surface temperature, Nov. 1997", 
           units = "K", bar_limits = c(250, 300), brks = 21,
           width = 8, height = 8, bar_extra_margin = c(1, 0, 1, 0),
           fileout = 'map_equi_contour_raw_exp1_ver2.png')
```

<img src="./Figures/map_equi_contour_raw_exp1.png" width="600" />
<img src="./Figures/map_equi_contour_raw_exp1_ver2.png" width="600" />

### Boxes

We can draw boxes on the map using parameters `boxlim`, `boxcol` and `boxlwd`.
They specify the position of the corners, color and thickness of a box to be drawn 
on the map. 

We use the same raw data from the previous section and add two boxes, 
one over Alpine region (green) and one over south side of Mediterranean Sea (yellow). 
```r
VizEquiMap(exp1[1, 1, , ], lon = lons, lat = lats, filled.continents = FALSE,
           toptitle = "SEAS5 near-surface temperature, Nov. 1997", 
           units = "K", bar_limits = c(250, 300), brks = 21,
           width = 8, height = 8, bar_extra_margin = c(1, 0, 1, 0),
           boxlim = list(c(6, 45, 15, 48), c(10, 30, 20, 36)), 
           boxcol = c('green', 'yellow'), boxlwd = c(2, 2),
           fileout = 'map_equi_raw_exp1_boxes.png')
```

<img src="./Figures/map_equi_raw_exp1_boxes.png" width="600" />


## VizAnimateMap()

`VizAnimateMap()` generates animation of maps from `VizEquiMap()` or 
`VizStereoMap()` and saves them as .gif file . The input array should have dimensions as follow: 
```r
  c(n. of experiments/observations, n. of observations, 3, n. of forecast times, n. of latitudes, n. of longitudes)
```
The first 3 dimensions are optional; the 3rd dimension corresponding to the lower 
confidence interval, the actual value and the upper confidence interval. 
The confidence intervals, if provided, are drawn with
black dots on grid cells where reach 95% significance level, if requested via `msk95lev`.

The data is assumed to be monthly frequency and to start in
January. Otherwise it can be adjusted with `monini` and `freq`.

Whether to plot with a equidistant rectangular projection or a stereographic 
projection can be chosen with the parameter `equi`. The plot can be limited to 
a sub-region of the provided data via the parameters `lonmin`, `lonmax`, `latmin` and `latmax`.
Check function documentation for more explanations of function arguments.

In the following example, we use s2dv function MeanDims() to calcualte climatologies, then make animation through forecast time.

```r
exp_clim <- s2dv::MeanDims(exp1, dims = "sdate", na.rm = T, drop = TRUE)

cols <- ClimColors(50)
col_inf <- cols[1]
col_sup <- tail(cols, 1)
cols <- cols[c(2:49)]
brks_range <- range(exp_clim, na.rm = TRUE)
brks <- round(seq(ceiling(brks_range[1]), floor(brks_range[2]),
                  length.out = length(cols) + 1), 1)

VizAnimateMap(exp_clim, lon = lons, lat = lats, 
              monini = 11, 
              toptitle = "SEAS5 climatologies (1997-2016)", 
              units = "K", brks = brks, cols = cols,
              col_inf = col_inf, col_sup = col_sup,
              triangle_ends = c(T, T),
              fileout = "map_equi_anim_clim_exp1.gif")
```
<img src="./Figures/map_equi_anim_clim_exp1.gif" width="600" />

## VizLayout()

This function combined plots from any R plot function in 
layouts, and a common color bar can be set for the multi-panel.

In the following example, we plot the ensemble-mean climatology at each forecast time by VizEquiMap().

```r
VizLayout(fun = VizEquiMap, plot_dims = c('lat', 'lon'),
          var = exp_clim, lon = lons, lat = lats,
          units = 'K', title_scale = 0.8,
          toptitle = "SEAS5 tas climatology (1997-2016)",
           titles = paste0("ftime ", seq_len(dim(exp_clim)[1]), ": ", 
                           lubridate::month(c(11:12, 1:4), label = T)),
           brks = brks, cols = cols, 
           col_inf = col_inf, col_sup = col_sup,
           triangle_ends = c(T, T), coast_color = 'black',
           fileout = "map_equi_layout_exp1_ftime.png") 
```

<img src="./Figures/map_equi_layout_exp1_ftime.png" width="600" />

VizLayout() can also put plots from different plotting functions together. In the next plot, we use VizEquiMap(), base function plot(), and VizVsLTime() in VizLayout().

Check [data_loading.md](#data-loading) to get spatial mean `exp_sm` and `obs_sm`., and [time_series.md](#time-series#1-trend-and-regression) to see the explanation of trend calculation.

```r
# Calculate anomalies and trend
ano <- s2dv::Ano_CrossValid(exp_sm, obs_sm, memb = FALSE, dat_dim = c("dat", "ensemble"), memb_dim = "ensemble")
trend_exp <- s2dv::Trend(s2dv::MeanDims(ano$exp, 'ensemble'), time_dim = "sdate")
input_trend <- array(dim = c(dat = 2, 4, time = 6))
input_trend[, 1, ] <- trend_exp$conf.lower[2, , ]
input_trend[, 2, ] <- trend_exp$trend[2, , ]
input_trend[, 3, ] <- trend_exp$conf.upper[2, , ]
input_trend[, 4, ] <- trend_exp$trend[1, , ]

# Arguments for each plot
args <- list(
  list(lon = lons, lat = lons, 
       filled.continents = FALSE, title_scale = 0.5, axes_label_scale = 0.6, 
       units = 'K', units_scale = 2),
       list(), list(),
       list(monini = 11, freq = 12, ytitle = "K/year",  limits = c(-0.02, 0.1), 
            listexp = c('SEAS5', 'Meteo-France System 7'), sizetit = 0.5, leg = F)
)

VizLayout(fun = c('VizEquiMap', 'plot', 'plot', 'VizVsLTime'),
          plot_dims = list(c('lat', 'lon'), 1, 1, 1:3),
          var = list(exp_clim, array(1:10), array(10:1), input_trend),
          special_args = args, drawleg = 'E',
          brks = brks, cols = cols, 
          col_inf = col_inf, col_sup = col_sup, triangle_ends = c(T, T),
          titles = paste('Fig.', 1:9), toptitle = 'Multipanel',
          row_titles = paste('Row', 1:3), col_titles = paste('Col', 1:3), 
          width = 12, height = 12, res = 200, 
          fileout = 'map_equi_layout_complex.png')
```
<img src="./Figures/map_equi_layout_complex.png" width="800" />

As you can see, some plots in the layout  don't have appropriate plot setting. For example, the axis labels in the last plot from VizVsLTime() are too big; plots from plot() don't have titles. Please contact us if you'd like to have VizLayout() work well with these plotting functions and we can try to improve it.
