Meteorological Review

Author

Victor Munoz S.

Published

November 8, 2024

1 Introduction

SRK was asked to provide a simple review of local meteorology based on regional to local tools. This less-than-a-day effort is intended to quickly understand meteorological features, considering the limitations associated with time and effort.

Code
Longitude= -110.966575
Latitude = 66.908855

source(here::here("scripts","hydro_support.r"))
#For more information
#https://developers.google.com/maps/gmp-get-started\
key_google<-"AIzaSyC2wTuP1tK60AxlCGpPSNetOvyZEgnO6EA"

#For more information
# https://www.ncdc.noaa.gov//cdo-web/token
key_noaa<-"PacdvUWVYvHOPwXrHRILLOJpvDnORxEB"

ggmap::register_google(key = key_google)


#Get elevation from google maps
Elevation=GM_elev(Longitude,Latitude,key_google)

site.info<-data.frame(Location="Site",
                      Longitude=Longitude,
                      Latitude=Latitude,
                      Elevation=Elevation
                      ) 
#Site in looped with variables
site.info_xy<-site.info %>% 
  dplyr::rename(x="Longitude",y="Latitude",z="Elevation") %>% 
  reshape2::melt(id.vars="Location")

pandoc.table(site.info)
Location Longitude Latitude Elevation
Site -111 66.91 452.1
Code
#minimum year of information used, to be defined after seen the available info
min.ywi<-10 

2 SOURCES

As a simplified review, the records review included a simple check of ECCC records and climatic gridded models ERA5-Land and Daymet.

A climatic gridded model is a computational tool used to provide spatially and temporally continuous datasets of various meteorological variables such as temperature, precipitation, humidity, and wind speed. These models interpolate or reanalyze observed data from weather stations, satellites, and other sources to generate a comprehensive representation of climatic conditions over a specified area.

These models are invaluable for research and operational applications in fields such as hydrology, climate science, and environmental management, as they help to fill gaps in observational data and allow for the analysis of long-term climatic trends and variability.

2.1 SITE Records

Information was captured at an hourly scale, and the values were presented at a daily scale.

Code
library(readxl)

site_info_hly_tbl<- read_excel(here::here("data","csv","Ulucamp_Download.xlsx"), 
    sheet = "ulucamp") %>% as.data.table()

site_info_dly_tbl<-site_info_hly_tbl %>% 
  mutate(date_dly=as.Date(Date)) %>%
  dplyr::select(-c(1,2)) %>% 
  dplyr::select(-"m_sol",-"m_uv") %>%
    group_by(date_dly) %>% 
  summarise_all(.funs="mean")


site_info_dly_z<-zoo(site_info_dly_tbl[,-1],site_info_dly_tbl[,1] %>% pull())

plot.zoo(site_info_dly_z,type="b",main="Daily site records",yax.flip = T)

2.2 ECCC

Information in the region from Environment and Climate Change Canada was downloaded with the R-library Weathercan. As a reference local records were captured at daily scale.

Code
library(weathercan)

# stations_dl()
## Selecting all stations
station.selection <- stations_search(coords = c(Latitude,Longitude), 
                                     dist = 500, interval ="day")

## Selecting all stations

##remove stations with less than 10 years of data
station.selection <- station.selection[station.selection$end - station.selection$start >= 10, ]

## Remove stations with last year of data before 1980
station.selection <- station.selection[station.selection$end>1980,]
#write.csv(station.selection, file = "SDH_regional-stations_500km-daily.csv")

#-------
# station.selection2 <- stations_search(coords = c(Latitude,Longitude), dist = 500, interval ="hour")
# ##remove stations with less than 10 years of data
# station.selection2 <- station.selection2[station.selection2$end - station.selection2$start >= 10, ]
# 
# ## Remove stations with last year of data before 1980
# station.selection2 <- station.selection2[station.selection2$end>1980,]

# # write.csv(station.selection2, file = "SDH_regional-stations_500km-hrly.csv")

#go ahead with daily
station.selection.dly.idx <- data.frame("Station.Name" = station.selection$station_name,
                                   "Province" = station.selection$prov,
                                   "Climate.Identifier" = station.selection$climate_id,
                                   "WebID" = station.selection$station_id,
                                   "WMO.Identifier" = station.selection$WMO_id,
                                   "TC.ID" = station.selection$TC_id,
                                   "Latitude" = station.selection$lat,
                                   "Longitude" = station.selection$lon,
                                   "Elevation" = station.selection$elev,
                                   "First.Year" = station.selection$start,
                                   "Last.Year" = station.selection$end,
                                   "Distance" = station.selection$distance,
                                   "timeframe" = rep(2, times = length(station.selection$interval)))

## Download selected stations data (takes ~5min)
# regional.db2 <- weather_dl(station.selection2$station_id, interval = "hour")


## Artificial station.selection.idx formating to be able to use Victor's functions
# station.selection.idx <- data.frame("Station.Name" = station.selection2$station_name,
#                                    "Province" = station.selection2$prov,
#                                    "Climate.Identifier" = station.selection2$climate_id,
#                                    "WebID" = station.selection2$station_id,
#                                    "WMO.Identifier" = station.selection2$WMO_id,
#                                    "TC.ID" = station.selection2$TC_id,
#                                    "Latitude" = station.selection2$lat,
#                                    "Longitude" = station.selection2$lon,
#                                    "Elevation" = station.selection2$elev,
#                                    "First.Year" = station.selection2$start,
#                                    "Last.Year" = station.selection2$end,
#                                    "Distance" = station.selection2$distance,
#                                    "timeframe" = rep(2, times = length(station.selection2$interval)))


# ## Download selected stations data (takes ~5min) 

## Nadine - this takes over 20-30 minutes for me. Not sure what the issue is. 

eccc_file<-here::here("data","rds","EC Daily Canada Data - Daily Stations.Rdata")

if(file.exists(eccc_file)){
  
  eccc_info.dt<-arrow::read_parquet(eccc_file)
  
}else{
  
  regional.db <- weather_dl(station_ids = station.selection$station_id, interval = "day",
                            start = as.Date("1980-01-01"),end=as.Date("2024-07-01"))
  # 
  # ## Artificial database formating to be able to use Victor's functions
  regional.db <- data.frame("Climate.Id" = regional.db$climate_id,
                            "Date.Time" = regional.db$date,
                            "Max.Temp.C" = regional.db$max_temp,
                            "Min.Temp.C" = regional.db$min_temp,
                            "Mean.Temp.C" = regional.db$mean_temp,
                            "Heat.Deg.Days.C" = regional.db$heat_deg_days,
                            "Cool.Deg.Days.C" = regional.db$cool_deg_days,
                            "Total.Rain.mm" = regional.db$total_rain,
                            "Total.Snow.cm" = regional.db$total_snow,
                            "Total.Precip.mm" = regional.db$total_precip,
                            "Snow.on.Grnd.cm" = regional.db$snow_grnd,
                            "Dir.of.Max.Gust.10s.deg" = regional.db$dir_max_gust,
                            "Spd.of.Max.Gust.km.h" = regional.db$spd_max_gust) 
  
  eccc_info.dt<-regional.db %>% 
    data.table::as.data.table()
  
  arrow::write_parquet(x = eccc_info.dt,sink =eccc_file)
  
}


eccc_var_lst<-eccc_info.dt %>% 
  reshape2::melt(id.vars=c("Climate.Id","Date.Time")) %>% 
  dplyr::filter(complete.cases(value)) %>% 
  split(.,.$variable)

lapply(eccc_var_lst,FUN=function(x){
  
  # x<-eccc_var_lst[[2]] 
  
  x_var<-x$variable[1] %>% 
    as.character() %>% make.names()%>% str_replace_all(.,"\\.","_")
  
  x_z<-reshape2::dcast(data = x,formula = Date.Time~Climate.Id,
                       value.var = "value") %>% 
    tk_zoo(silent=T)
  
  x_z<-x_z[,match(station.selection.dly.idx$Climate.Identifier,
                  names(x_z))]
  
  # dwi.graph(x_z,start.year = 1900)
  
  assign(paste0("eccc_",x_var,".z"),x_z,envir = .GlobalEnv )
  
    
}) %>% invisible()

2.2.1 Total Precipitation

For total precipitation, all stations with records ending after the year 2010 were selected.

It is noted that the mean annual precipitation (MAP) is correlated with latitude, followed by longitude and distance from the coast. Values seem poorly correlated with elevation.

Note: These values do not consider undercatch!

Undercatch refers to the phenomenon where precipitation gauges, particularly those used to measure snowfall, collect less precipitation than actually occurs. This under-measurement is often caused by various factors such as wind-induced turbulence around the gauge, which can prevent snowflakes from being captured efficiently. Undercatch is a significant issue in high-wind environments where the aerodynamics of the precipitation gauge can affect its ability to capture all falling snow.

Code
#Index for total precipitation
eccc_prcp_idx<-station.selection.dly.idx %>% 
  mutate(map=eccc_Total_Precip_mm.z %>%
           # window(start=baseline_start, end = baseline_end) %>% 
           daily2annual.avg(FUN=sum) %>% .[,14]) %>% 
  # dplyr::filter(Distance<200) %>% 
  dplyr::filter(complete.cases(map)) %>% 
  dplyr::filter(map>10) %>% 
  dplyr::filter(Last.Year>=2010)

eccc_prcp_idx %>% 
  dplyr::select(Latitude, Longitude,Elevation,map) %>% 
  mutate(coast=coast.dist(Latitude,Longitude)) %>% 
  data.frame() %>% 
  hydropairs(dec=2)

Code
pandoc.table(eccc_prcp_idx %>% dplyr::select(-WMO.Identifier,-timeframe,-TC.ID),
             split.table=Inf,style="simple")
Station.Name Province Climate.Identifier WebID Latitude Longitude Elevation First.Year Last.Year Distance map
LUPIN CS NU 230N002 27376 65.76 -111.2 488 1997 2021 128.7 279.8
KUGLUKTUK A NU 2300902 1641 67.82 -115.1 22.6 1977 2014 206 244.8
KUGLUKTUK CLIMATE NU 2300904 43003 67.82 -115.1 22.6 2004 2021 206 217.3
EKATI A NT 220N001 27240 64.7 -110.6 468.2 1998 2016 246.8 295.1
CLUT LAKE (AUT) NT 2200777 10896 65.6 -117.8 185 1994 2010 338.6 305.5
CAMBRIDGE BAY A NU 2400600 1786 69.11 -105.1 31.09 1929 2015 345.6 145.1
CAMBRIDGE BAY GSN NU 2400602 32233 69.11 -105.1 18.69 2002 2021 345.6 158.1
LOWER CARP LAKE NT 220N004 27610 63.6 -113.9 373.4 1998 2021 392.8 278.7
GAMETI AIRPORT NT 2203361 27798 64.12 -117.3 220.4 2000 2014 427.2 296.2
GAMETI NT 2203359 10926 64.11 -117.3 221 1994 2021 428.7 231.1
ROBERTSON LAKE (AUT) NU 2303610 7337 65.1 -102.4 243.7 1994 2021 436.4 203.5
HANBURY RIVER NT 2202351 10897 63.6 -105.1 317.4 1994 2021 458.4 219.6
FORT RELIANCE (AUT) NT 2201903 8935 62.71 -109.2 167.6 1994 2021 475.8 299.3
Code
dwi.graph(eccc_Total_Precip_mm.z[,eccc_prcp_idx$Climate.Identifier],
          station.name = eccc_prcp_idx$Station.Name)

2.2.2 Air Temperature

For air temperature, all stations with records ending after the year 2010 were selected.

Mean annual air temperature (Tavg) is related to latitude and longitude. Values seem not correlated with elevation and weakly correlated with distance from the coast.

Code
#Index for air temperature
eccc_tavg_idx<-station.selection.dly.idx %>% 
  mutate(tavg=eccc_Mean_Temp_C.z %>%
           # window(start=baseline_start, end = baseline_end) %>% 
           daily2annual.avg(FUN=mean) %>% .[,14]) %>% 
  # dplyr::filter(Distance<200) %>% 
  dplyr::filter(complete.cases(tavg)) %>% 
  dplyr::filter(Last.Year>=2010)

eccc_tavg_idx %>% 
  dplyr::select(Latitude, Longitude,Elevation,tavg) %>% 
  mutate(coast=coast.dist(Latitude,Longitude)) %>% 
  data.frame() %>% 
  hydropairs(dec=2)

Code
pandoc.table(eccc_tavg_idx %>% dplyr::select(-WMO.Identifier,-timeframe,-TC.ID),
             split.table=Inf,style="simple")
Station.Name Province Climate.Identifier WebID Latitude Longitude Elevation First.Year Last.Year Distance tavg
LUPIN CS NU 230N002 27376 65.76 -111.2 488 1997 2021 128.7 -10.04
KUGLUKTUK A NU 2300902 1641 67.82 -115.1 22.6 1977 2014 206 -10.2
KUGLUKTUK CLIMATE NU 2300904 43003 67.82 -115.1 22.6 2004 2021 206 -9.373
EKATI A NT 220N001 27240 64.7 -110.6 468.2 1998 2016 246.8 -8.858
CAPE PEEL WEST NU 2400697 10828 69.04 -107.8 165.3 1993 2021 271.7 -12.84
CLUT LAKE (AUT) NT 2200777 10896 65.6 -117.8 185 1994 2010 338.6 -5.169
CAMBRIDGE BAY A NU 2400600 1786 69.11 -105.1 31.09 1929 2015 345.6 -13.78
CAMBRIDGE BAY GSN NU 2400602 32233 69.11 -105.1 18.69 2002 2021 345.6 -12.78
LOWER CARP LAKE NT 220N004 27610 63.6 -113.9 373.4 1998 2021 392.8 -5.434
GAMETI AIRPORT NT 2203361 27798 64.12 -117.3 220.4 2000 2014 427.2 -5.33
GAMETI NT 2203359 10926 64.11 -117.3 221 1994 2021 428.7 -4.927
CROKER RIVER NU 230J01Q 10826 69.28 -119.2 69.4 1993 2021 433.1 -9.478
ROBERTSON LAKE (AUT) NU 2303610 7337 65.1 -102.4 243.7 1994 2021 436.4 -10.93
HANBURY RIVER NT 2202351 10897 63.6 -105.1 317.4 1994 2021 458.4 -9.372
FORT RELIANCE (AUT) NT 2201903 8935 62.71 -109.2 167.6 1994 2021 475.8 -5.139
HAT ISLAND NU 2302370 1716 68.32 -100.1 36.1 1959 2021 487.7 -12.99
Code
dwi.graph(eccc_Mean_Temp_C.z[,eccc_tavg_idx$Climate.Identifier],
          station.name = eccc_tavg_idx$Station.Name)

Code
#used for ggsn graphical scale, same ranges but 8% smaller
xy <-ggmap::make_bbox(lon = eccc_prcp_idx$Longitude,
                      lat = eccc_prcp_idx$Latitude,f=0.05) 

#used for ggsn graphical scale, same ranges but 8% smaller
xy_min <-ggmap::make_bbox(lon = c(xy[1],xy[3]),
                      lat = c(xy[2],xy[4]),f=-0.08) 

#ggmap capture for goggle maps
map <- get_map(xy,scale=2,zoom=5,maptype="hybrid",source="google",
               messaging=FALSE)

2.3 ERA5-Land

Information was captured in the area for ERA5-Land for the complete region.

ERA5-Land is a higher spatial and temporal resolution reanalysis dataset produced by the European Centre for Medium-Range Weather Forecasts (ECMWF). It offers detailed information about various meteorological parameters such as precipitation, temperature, snow cover, and wind speed. ERA5-Land operates at a spatial resolution of approximately 9 km and provides data at hourly intervals, making it particularly useful for hydrological and environmental studies. This dataset is widely used in research and operational applications due to its comprehensive coverage and high accuracy in representing land-surface conditions.

It is particularly noted that wind speed (WS) is in the range of 4 to 5 m/s; this range may encourage a significant effect associated with undercatch.

Undercatch is the reduction of the actual efficiency of snow capture due to turbulence between the snow capture instrument and the local wind speed. This effect can be particularly relevant at wind speeds over 1 m/s.

Code
library(terra)

era5_land_tavg_dly_ras<-rast(here::here("data","netcdf","era5-land_tavg_dly.nc"))

era5_land_tmax_dly_ras<-rast(here::here("data","netcdf","era5-land_tmax_dly.nc"))

era5_land_tmin_dly_ras<-rast(here::here("data","netcdf","era5-land_tmin_dly.nc"))

era5_land_prcp_dly_ras<-rast(here::here("data","netcdf","era5-land_prcp_dly.nc"))

era5_land_ws_dly_ras<-rast(here::here("data","netcdf","era5-land_ws_dly.nc"))

era5_land_tavg_ma_ras<-rast(here::here("data","netcdf","era5-land_tavg_ma.nc"))

era5_land_prcp_ma_ras<-rast(here::here("data","netcdf","era5-land_prcp_ma.nc"))

era5_land_tavg_dly_z<-zoo(unlist(terra::extract(era5_land_tavg_dly_ras,cbind(Longitude,Latitude)))-273.15,
                      time(era5_land_tavg_dly_ras)) %>% 
  window(start=as.Date("1980-01-01"),end=as.Date("2023-10-31")) %>% subdaily2daily(FUN=mean)

era5_land_tmax_dly_z<-zoo(unlist(terra::extract(era5_land_tmax_dly_ras,cbind(Longitude,Latitude)))-273.15,
                      time(era5_land_tmax_dly_ras)) %>% 
  window(start=as.Date("1980-01-01"),end=as.Date("2023-10-31")) %>% subdaily2daily(FUN=mean)

era5_land_tmin_dly_z<-zoo(unlist(terra::extract(era5_land_tmin_dly_ras,cbind(Longitude,Latitude)))-273.15,
                      time(era5_land_tmin_dly_ras)) %>% 
  window(start=as.Date("1980-01-01"),end=as.Date("2023-10-31")) %>% subdaily2daily(FUN=mean)

era5_land_prcp_dly_z<-zoo(unlist(terra::extract(era5_land_prcp_dly_ras,cbind(Longitude,Latitude))),
                      time(era5_land_prcp_dly_ras)) %>% 
  window(start=as.Date("1980-01-01"),end=as.Date("2023-10-31")) %>% subdaily2daily(FUN=mean)

era5_land_ws_dly_z<-zoo(unlist(terra::extract(era5_land_ws_dly_ras,cbind(Longitude,Latitude))),
                      time(era5_land_ws_dly_ras)) %>% 
  window(start=as.Date("1980-01-01"),end=as.Date("2023-10-31")) %>% subdaily2daily(FUN=mean)



era5_land_meteo_dly_z<-merge(prcp=era5_land_prcp_dly_z*1000,
                         tavg=era5_land_tavg_dly_z,
                         tmax=era5_land_tmax_dly_z,
                         tmin=era5_land_tmin_dly_z,
                         ws=era5_land_ws_dly_z) %>% 
  fortify.zoo() %>% 
   dplyr::mutate(rain=if_else(tavg>0,prcp,0),
                snow=if_else(tavg<=0,prcp,0)) %>%
  tk_zoo(silent=T)

plot(era5_land_meteo_dly_z,main="Records at the site based on ERA5-Land")

2.4 DAYMET

Information was captured as a point and partially in the area to review the regional performance.

Daymet provides gridded meteorological data on a daily basis for North America, including variables such as daily maximum and minimum temperatures, precipitation, and shortwave radiation. Developed by the Oak Ridge National Laboratory, Daymet uses a set of spatial interpolation algorithms to estimate weather and climate patterns at a 1 km spatial resolution. Daymet is especially useful for ecological and hydrological modeling, as it offers high spatial detail over extended time periods, making it suitable for analyzing long-term climate trends and their impacts on various environmental processes.

Code
library(daymetr)

daymet_info<-daymetr::download_daymet(site = "Daymet",lat = Latitude,lon = Longitude,
                         start = 1980,end=lubridate::year(now())-1,silent = T)

daymet_z<-daymet_info$data %>%
  dplyr::mutate(dates=as.Date(paste0(year,"-01-01"))+lubridate::days(yday)-1) %>%
  dplyr::select(dates,prcp="prcp..mm.day.",tmax="tmax..deg.c.",tmin="tmin..deg.c.") %>%
  dplyr::mutate(tavg=0.5*tmax+0.5*tmin,
                rain=if_else(tavg>0,prcp,0),
                snow=if_else(tavg<=0,prcp,0)) %>%
  tk_zoo(silent=T)

plot(daymet_z, yax.flip = T,
         main="Records at the site based on Daymet")

3 Precipitation Review

Site records seem more correlated with ERA5-Land than with Daymet. As no snowpack review of undercatch is implemented, it is recommended to use ERA5-Land for now; however, the information may be biased as undercatch can be a particularly important factor.

3.1 Rainfall

As a reference, the rainfall values compared with ERA5-Land show a higher Pearson Correlation of 0.45. Furthermore, the values seem slightly higher, which can be the result of undercatch corrections from ERA5-Land.

Code
merge(site=site_info_dly_z$m_dr) %>% 
  window(start=as.Date("2021-06-01"),end=as.Date("2022-08-30")) %>% dygraph(group="1",main="SITE",ylab="mm") %>% 
  # dygraphs::dyRangeSelector() %>% 
  dygraphs::dyBarChart()
Code
merge(daymet=daymet_z$rain) %>% 
  window(start=as.Date("2021-06-01"),end=as.Date("2022-08-30")) %>% dygraph(group="1",main="DAYMET",ylab="mm") %>% 
  dygraphs::dyBarChart()
Code
era5_land_meteo_dly_z$rain[era5_land_meteo_dly_z$rain<0]<-0

merge(era5_land=era5_land_meteo_dly_z$rain) %>% 
  window(start=as.Date("2021-06-01"),end=as.Date("2022-08-30")) %>% 
  dygraph(group="1",main="ERA5-LAND",ylab="mm") %>% 
  dygraphs::dyRangeSelector() %>% 
  dygraphs::dyBarChart()
Code
merge(site=site_info_dly_z$m_dr,
      daymet=daymet_z$rain,
      era5_land=era5_land_meteo_dly_z$rain) %>% 
  window(start=as.Date("2021-06-01"),end=as.Date("2022-08-30")) %>% data.frame() %>% 
  hydropairs(dec=2)

3.2 Total Precipitation Comparison

Based on the possible relevant effect associated with undercatch (due to the high wind speed), it is encouraged to use the higher range of precipitation (Daymet vs. ERA5-Land); furthermore, it is known that typically ERA5 and ERA5-Land have “some” undercatch effect already included in the total precipitation records.

Code
daily2annual.avg(daymet_z[,c("prcp","rain","snow")],FUN=sum) %>% 
  pandoc.table(split.table=Inf,round=1,caption="Mean annual precipitation based on Daymet")
Mean annual precipitation based on Daymet
Station Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Ann
prcp 6.2 6.1 10.4 11.2 13.6 22.4 39.4 47.3 40 24.8 12.3 9.1 242.8
rain 0 0 0 0 2.4 21.3 39.4 47.2 32.5 2.1 0 0 144.9
snow 6.2 6.1 10.4 11.2 11.2 1.1 0 0.1 7.5 22.7 12.3 9.1 97.9
Code
daily2annual.avg(era5_land_meteo_dly_z[,c("prcp","rain","snow")],FUN=sum) %>% 
  pandoc.table(split.table=Inf,round=1,caption="Mean annual precipitation based on ERA5-Land")
Mean annual precipitation based on ERA5-Land
Station Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Ann
prcp 11.1 10.3 14.2 17 25.5 38.8 48.9 56.9 46.7 36.7 18.9 14 338.9
rain 0 0 0 0 5.5 35.2 48.9 55.7 29.6 3.7 0 0 178.8
snow 11.1 10.3 14.2 17 20 3.6 0 1.1 17 32.9 18.9 14 160.1

It is noted that in the region, the mean annual precipitation measured by ECCC regional stations appears to be in the lower range compared to what is suggested by ERA5-Land. However, it is suspected that these values need to be corrected for undercatch, which would likely result in higher local values. This observation is speculative, as no review was conducted on this topic. To properly evaluate undercatch, a snowpack model needs to be implemented in the regional to local context.

Code
library(tidyterra)

era5_land_prcp_ma_tbl<-fortify(era5_land_prcp_ma_ras) %>% 
  dplyr::filter(complete.cases(prcp))

#Map
ggmap(map, darken = c(0.3, "white"))+
  #TOPOGRAHY  
  # geom_tile(data = SRTM_tbl, aes(x = x, y = y, 
  #                             fill=cut(value,seq(0,8000,500),
  #                                      include.lowest=T,dig.lab=10)),
  #           alpha=0.4)+
  #MERRA
  geom_tile(data = era5_land_prcp_ma_tbl,aes(x=x,y=y,
                              fill=prcp),alpha=0.6)+
  
  geom_label_repel(data=eccc_prcp_idx,
                   aes(x=Longitude,y=Latitude,
                       label=paste0(Station.Name,"\n",round(map,-1))),colour="darkblue",
                   fontface="bold",alpha=0.6,
                   box.padding =unit(0.5, "lines"),segment.color = "black",
                   size=3 )+
  
  geom_point(data=eccc_prcp_idx,
                   aes(x=Longitude,y=Latitude,
                 fill=map),size=4,shape=22,alpha=0.6)+
  
  geom_point(data=site.info,
             aes(x=Longitude,y=Latitude),shape=5,col="red")+
  geom_label_repel(data=site.info,
                   aes(x=Longitude,y=Latitude,label=Location))+
  # scale_fill_brewer(palette="Spectral",direction = -1)+
  labs(size="Elevation [masl]",x="Longitude [deg]",y="Latitude [deg]",
       shape="Station Name", 
      title = "Mean Annual Precipitation",
      subtitle="Background from ERA5-Land |Points from ECCC",
      fill="mm/yr",
       # fill = "Topography\nfrom SRTM",
       # col="MAAT from\nNOAA[degC]\n(1980-2022)",
       caption=
         "Note: Site is presented as a red diamond")+
  # theme(legend.position="bottom")+
     ggsn::scalebar(x.min=xy_min[1],x.max=xy_min[3],
                y.min=xy_min[2],y.max=xy_min[4],dist = 150,dist_unit = "km",transform = T,model = "WGS84")+
  scale_fill_binned(breaks=seq(200,600,50),type = "viridis")+

  coord_quickmap()

4 Air Temperature Review

Typically, the performance of air temperature models (climatic gridded models) tends to be particularly high. It is also noted that the local records seem highly correlated on a daily scale with Daymet and ERA5-Land; however, the records from ERA5-Land show the highest values (0.97).

Thus, the values from the climatic gridded model of ERA5-Land are recommended as preliminary values. Note that sometimes climatic gridded models tend to be slightly biased for minimum temperature; this assessment was not implemented.

Code
merge(site=site_info_dly_z$m_temp,
      daymet=daymet_z$tavg,
      era5_land=era5_land_meteo_dly_z$tavg) %>% 
  window(start=as.Date("2021-06-01"),end=as.Date("2022-08-30")) %>% dygraph() %>% 
  dygraphs::dyRangeSelector()
Code
merge(site=site_info_dly_z$m_temp,
      daymet=daymet_z$tavg,
      era5_land=era5_land_meteo_dly_z$tavg) %>% 
  window(start=as.Date("2021-06-01"),end=as.Date("2022-08-30")) %>% 
  data.frame() %>% 
  hydropairs(dec=2)

Code
daily2annual.avg(daymet_z[,c("tmax","tavg","tmin")],FUN=mean) %>% 
  pandoc.table(split.table=Inf,round=1,caption="Mean annual air temperature based on Daymet")
Mean annual air temperature based on Daymet
Station Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Ann
tmax -24.6 -24.2 -20.3 -11.5 -1.1 10 15.5 12.7 5 -4.4 -15.5 -21.9 -6.7
tavg -28.3 -28.1 -24.5 -16.1 -5 5.8 10.9 8.8 2.2 -7.1 -19 -25.4 -10.5
tmin -32 -31.9 -28.7 -20.6 -9 1.6 6.3 4.8 -0.7 -9.9 -22.5 -29 -14.3
Code
daily2annual.avg(era5_land_meteo_dly_z[,c("tmax","tavg","tmin")],FUN=mean) %>% 
  pandoc.table(split.table=Inf,round=1,caption="Mean annual air temperature based on ERA5-Land")
Mean annual air temperature based on ERA5-Land
Station Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Ann
tmax -27 -25.5 -19.8 -10.3 -0.9 11.3 17 13.5 5.1 -5.6 -18.6 -24.9 -7.1
tavg -29.9 -28.9 -24.2 -14.8 -4.5 6.7 12.1 8.8 1.6 -8.3 -21.5 -27.7 -10.9
tmin -32.6 -31.5 -27.2 -18.1 -7.3 2.7 7.5 5.1 -0.9 -10.5 -24.3 -30.5 -14
Code
era5_land_tavg_ma_tbl<-fortify(era5_land_tavg_ma_ras) %>% 
  dplyr::filter(complete.cases(tavg)) %>% 
  mutate(tavg=tavg-273.15)

# tapp(era5_land_tavg_dly_ras,index="years",fun=mean)


#Map
ggmap(map, darken = c(0.3, "white"))+
  #TOPOGRAHY  
  # geom_tile(data = SRTM_tbl, aes(x = x, y = y, 
  #                             fill=cut(value,seq(0,8000,500),
  #                                      include.lowest=T,dig.lab=10)),
  #           alpha=0.4)+
  #MERRA
  geom_tile(data = era5_land_tavg_ma_tbl,aes(x=x,y=y,
                              fill=tavg),alpha=0.6)+
  
  geom_label_repel(data=eccc_tavg_idx,
                   aes(x=Longitude,y=Latitude,
                       label=paste0(Station.Name,"\n",round(tavg,0))),colour="darkblue",
                   fontface="bold",alpha=0.6,
                   box.padding =unit(0.5, "lines"),segment.color = "black",
                   size=3 )+
  
  geom_point(data=eccc_tavg_idx,
                   aes(x=Longitude,y=Latitude,
                 fill=tavg),size=4,shape=22,alpha=0.6)+
  
  geom_point(data=site.info,
             aes(x=Longitude,y=Latitude),shape=5,col="red")+
  geom_label_repel(data=site.info,
                   aes(x=Longitude,y=Latitude,label=Location))+
  # scale_fill_brewer(palette="Spectral",direction = -1)+
  labs(size="Elevation [masl]",x="Longitude [deg]",y="Latitude [deg]",
       shape="Station Name", 
      title = "Mean Annual Air Temperature",
      subtitle="Background from ERA5-Land |Points from ECCC",
      fill="degC",
       # fill = "Topography\nfrom SRTM",
       # col="MAAT from\nNOAA[degC]\n(1980-2022)",
       caption=
         "Note: Site is presented as a red diamond")+
  # theme(legend.position="bottom")+
     ggsn::scalebar(x.min=xy_min[1],x.max=xy_min[3],
                y.min=xy_min[2],y.max=xy_min[4],dist = 150,dist_unit = "km",transform = T,model = "WGS84")+
  scale_fill_binned(type = "viridis",breaks=seq(-20,10,2))+

  coord_quickmap()

5 Evaporation

5.1 Evaporation Function Corrections!

It was found that the evaporation has issue representing values beyond the artic circle, as this site is located northern than the artic circle, the equation needs to be corrected.

5.1.1 Hargreaves Samani

Code
ET.HargreavesSamani_rev2<-function (data, constants, ts = "daily", message = "yes", AdditionalStats = "yes", 
  save.csv = "no", ...) 
{
  if (is.null(data$Tmax) | is.null(data$Tmin)) {
    stop("Required data missing for 'Tmax' and 'Tmin', or 'Temp'")
  }
  Ta <- (data$Tmax + data$Tmin)/2
  P <- 101.3 * ((293 - 0.0065 * constants$Elev)/293)^5.26
  delta <- 4098 * (0.6108 * exp((17.27 * Ta)/(Ta + 237.3)))/((Ta + 
    237.3)^2)
  gamma <- 0.00163 * P/constants$lambda
  d_r2 <- 1 + 0.033 * cos(2 * pi/365 * data$J)
  delta2 <- 0.409 * sin(2 * pi/365 * data$J - 1.39)
  # w_s <- acos(-tan(constants$lat_rad) * tan(delta2))
  w_s <- acos(pmax(pmin(-tan(constants$lat_rad) * tan(delta2),1),-1))
  
  # dygraph(merge(w_s1,w_s2))
  
  
  N <- 24/pi * w_s
  R_a <- (1440/pi) * d_r2 * constants$Gsc * (w_s * sin(constants$lat_rad) * 
    sin(delta2) + cos(constants$lat_rad) * cos(delta2) * 
    sin(w_s))
  C_HS <- 0.00185 * (data$Tmax - data$Tmin)^2 - 0.0433 * (data$Tmax - 
    data$Tmin) + 0.4023
  ET_HS.Daily <- 0.0135 * C_HS * R_a/constants$lambda * (data$Tmax - 
    data$Tmin)^0.5 * (Ta + 17.8)
  ET.Daily <- ET_HS.Daily
  ET.Monthly <- aggregate(ET.Daily, as.yearmon(data$Date.daily, 
    "%m/%y"), FUN = sum)
  ET.Annual <- aggregate(ET.Daily, floor(as.numeric(as.yearmon(data$Date.daily, 
    "%m/%y"))), FUN = sum)
  ET.MonthlyAve <- ET.AnnualAve <- NULL
  if (AdditionalStats == "yes") {
    for (mon in min(as.POSIXlt(data$Date.daily)$mon):max(as.POSIXlt(data$Date.daily)$mon)) {
      i = mon - min(as.POSIXlt(data$Date.daily)$mon) + 
        1
      ET.MonthlyAve[i] <- mean(ET.Daily[as.POSIXlt(data$Date.daily)$mon == 
        mon])
    }
    for (year in min(as.POSIXlt(data$Date.daily)$year):max(as.POSIXlt(data$Date.daily)$year)) {
      i = year - min(as.POSIXlt(data$Date.daily)$year) + 
        1
      ET.AnnualAve[i] <- mean(ET.Daily[as.POSIXlt(data$Date.daily)$year == 
        year])
    }
  }
  ET_formulation <- "Hargreaves-Samani"
  ET_type <- "Reference Crop ET"
  results <- list(ET.Daily = ET.Daily, ET.Monthly = ET.Monthly, 
    ET.Annual = ET.Annual, ET.MonthlyAve = ET.MonthlyAve, 
    ET.AnnualAve = ET.AnnualAve, ET_formulation = ET_formulation, 
    ET_type = ET_type)
  if (ts == "daily") {
    res_ts <- ET.Daily
  }
  else if (ts == "monthly") {
    res_ts <- ET.Monthly
  }
  else if (ts == "annual") {
    res_ts <- ET.Annual
  }
  if (message == "yes") {
    message(ET_formulation, " ", ET_type)
    message("Evaporative surface: reference crop")
    message("Timestep: ", ts)
    message("Units: mm")
    message("Time duration: ", time(res_ts[1]), " to ", 
      time(res_ts[length(res_ts)]))
    if (NA %in% res_ts) {
      message(length(res_ts), " ET estimates obtained; ", 
        length(which(is.na(res_ts))), " NA output entries due to missing data")
      message("Basic stats (NA excluded)")
      message("Mean: ", round(mean(res_ts, na.rm = T), 
        digits = 2))
      message("Max: ", round(max(res_ts, na.rm = T), digits = 2))
      message("Min: ", round(min(res_ts, na.rm = T), digits = 2))
    }
    else {
      message(length(res_ts), " ET estimates obtained")
      message("Basic stats")
      message("Mean: ", round(mean(res_ts), digits = 2))
      message("Max: ", round(max(res_ts), digits = 2))
      message("Min: ", round(min(res_ts), digits = 2))
    }
  }
  if (save.csv == "yes") {
    for (i in 1:length(results)) {
      namer <- names(results[i])
      write.table(as.character(namer), file = "ET_HargreavesSamani.csv", 
        dec = ".", quote = FALSE, col.names = FALSE, 
        row.names = F, append = TRUE, sep = ",")
      write.table(data.frame(get(namer, results)), file = "ET_HargreavesSamani.csv", 
        col.names = F, append = T, sep = ",")
    }
    invisible(results)
  }
  else {
    return(results)
  }
}

5.1.2 McGuiness Bordne

Code
ET.McGuinnessBordne_rev2<-function (data, constants, ts = "daily", message = "yes", AdditionalStats = "yes", 
  save.csv = "no", ...) 
{
  if (is.null(data$Tmax) | is.null(data$Tmin)) {
    stop("Required data missing for 'Tmax' and 'Tmin', or 'Temp'")
  }
  Ta <- (data$Tmax + data$Tmin)/2
  P <- 101.3 * ((293 - 0.0065 * constants$Elev)/293)^5.26
  delta <- 4098 * (0.6108 * exp((17.27 * Ta)/(Ta + 237.3)))/((Ta + 
    237.3)^2)
  gamma <- 0.00163 * P/constants$lambda
  d_r2 <- 1 + 0.033 * cos(2 * pi/365 * data$J)
  delta2 <- 0.409 * sin(2 * pi/365 * data$J - 1.39)

  # w_s <- acos(-tan(constants$lat_rad) * tan(delta2))
  w_s <- acos(pmax(pmin(-tan(constants$lat_rad) * tan(delta2),1),-1))

  
  N <- 24/pi * w_s
  R_a <- (1440/pi) * d_r2 * constants$Gsc * (w_s * sin(constants$lat_rad) * 
    sin(delta2) + cos(constants$lat_rad) * cos(delta2) * 
    sin(w_s))
  ET_MB.Daily <- R_a * (Ta + 5)/(constants$lambda * 68)
  ET.Daily <- ET_MB.Daily
  ET.Monthly <- aggregate(ET.Daily, as.yearmon(data$Date.daily, 
    "%m/%y"), FUN = sum)
  ET.Annual <- aggregate(ET.Daily, floor(as.numeric(as.yearmon(data$Date.daily, 
    "%m/%y"))), FUN = sum)
  ET.MonthlyAve <- ET.AnnualAve <- NULL
  if (AdditionalStats == "yes") {
    for (mon in min(as.POSIXlt(data$Date.daily)$mon):max(as.POSIXlt(data$Date.daily)$mon)) {
      i = mon - min(as.POSIXlt(data$Date.daily)$mon) + 
        1
      ET.MonthlyAve[i] <- mean(ET.Daily[as.POSIXlt(data$Date.daily)$mon == 
        mon])
    }
    for (year in min(as.POSIXlt(data$Date.daily)$year):max(as.POSIXlt(data$Date.daily)$year)) {
      i = year - min(as.POSIXlt(data$Date.daily)$year) + 
        1
      ET.AnnualAve[i] <- mean(ET.Daily[as.POSIXlt(data$Date.daily)$year == 
        year])
    }
  }
  ET_formulation <- "McGuinness-Bordne"
  ET_type <- "Potential ET"
  results <- list(ET.Daily = ET.Daily, ET.Monthly = ET.Monthly, 
    ET.Annual = ET.Annual, ET.MonthlyAve = ET.MonthlyAve, 
    ET.AnnualAve = ET.AnnualAve, ET_formulation = ET_formulation, 
    ET_type = ET_type)
  if (ts == "daily") {
    res_ts <- ET.Daily
  }
  else if (ts == "monthly") {
    res_ts <- ET.Monthly
  }
  else if (ts == "annual") {
    res_ts <- ET.Annual
  }
  if (message == "yes") {
    message(ET_formulation, " ", ET_type)
    message("Timestep: ", ts)
    message("Units: mm")
    message("Time duration: ", time(res_ts[1]), " to ", 
      time(res_ts[length(res_ts)]))
    if (NA %in% res_ts) {
      message(length(res_ts), " ET estimates obtained; ", 
        length(which(is.na(res_ts))), " NA output entries due to missing data")
      message("Basic stats (NA excluded)")
      message("Mean: ", round(mean(res_ts, na.rm = T), 
        digits = 2))
      message("Max: ", round(max(res_ts, na.rm = T), digits = 2))
      message("Min: ", round(min(res_ts, na.rm = T), digits = 2))
    }
    else {
      message(length(res_ts), " ET estimates obtained")
      message("Basic stats")
      message("Mean: ", round(mean(res_ts), digits = 2))
      message("Max: ", round(max(res_ts), digits = 2))
      message("Min: ", round(min(res_ts), digits = 2))
    }
  }
  if (save.csv == "yes") {
    for (i in 1:length(results)) {
      namer <- names(results[i])
      write.table(as.character(namer), file = "ET_McGuinnessBordne.csv", 
        dec = ".", quote = FALSE, col.names = FALSE, 
        row.names = F, append = TRUE, sep = ",")
      write.table(data.frame(get(namer, results)), file = "ET_McGuinnessBordne.csv", 
        col.names = F, append = T, sep = ",")
    }
    invisible(results)
  }
  else {
    return(results)
  }
}

5.2 Evaluation

Code
library(Evapotranspiration)

data("constants")

constants$lat<-site.info$Latitude[1]
constants$lat_rad<-site.info$Latitude[1]/180*pi
constants$Elev<-site.info$Elevation[1]

constants$PA<-daily2annual.avg(era5_land_meteo_dly_z$prcp,
                               FUN=sum)[,"Ann"]

era5_land_meteo_dly_z$prcp[era5_land_meteo_dly_z$prcp<0]<-0

site_evap <- era5_land_meteo_dly_z %>%
  fortify.zoo() %>% 
  dplyr::select(Date=Index, 
                Precip = prcp,
                Tmax = tmax,
                Tavg= tavg,
                Tmin = tmin,
                uz = ws)%>% 
  tk_zoo() %>% 
  window(start = "1980-01-01", end = "2022-11-29") %>% 
  tk_tbl() %>% 
  mutate(Year = year(index), 
         Month = month(index), 
         Day = day(index)) %>% 
  dplyr::select(-index)

evap_data <- ReadInputs(varnames = c("Tmax","Tavg",
                                     "Tmin","Temp","Precip", "uz"),
                    climatedata = site_evap,
                    constants,
                    timestep="daily",
                    stopmissing=c(10,10,3),
                    interp_missing_days = TRUE, 
                    interp_missing_entries = TRUE, 
                    interp_abnormal = FALSE, 
                    missing_method = "monthly average", 
                    abnormal_method = NULL)

5.2.1 Hargreaves-Samani

The Hargreaves-Samani method is a temperature-based approach to estimate potential evapotranspiration.

Code
#Pen Pan - Pan A Evaporation (Daily)
ET.HargreavesSamani<- ET.HargreavesSamani_rev2(
  data = evap_data,
  constants = constants,
  ts = "daily")

5.2.2 McGuinness-Bordne

The McGuinness-Bordne method is another empirical approach for estimating potential evapotranspiration using daily temperature data.

Code
#Guiness Bordne - Potential Evaporation (Daily)
ET.GuinessBordne<- ET.McGuinnessBordne_rev2(
  data = evap_data,
  constants = constants,
  ts = "daily",
  solar = "data",
  wind="yes")

5.2.3 Oudin

The Oudin method simplifies the estimation of potential evapotranspiration using only temperature, making it useful for regions with scarce data.

Code
#Oudin
evap_oudin <- airGR::PE_Oudin(
  JD = evap_data$J %>% tk_tbl(preserve_index = FALSE) %>% pull(value),
  Temp = (0.5*evap_data$Tmax+0.5*evap_data$Tmin) %>% 
    tk_tbl(preserve_index = FALSE) %>% pull(value),
  Lat = site.info$Latitude[1], 
  LatUnit = "deg",
  TimeStepIn = "daily", 
  TimeStepOut = "daily") %>% 
  zoo(.,as.Date(evap_data$Date.daily))

ET.Oudin <- list()
ET.Oudin$ET_formulation <- "Oudin"
ET.Oudin$ET_type <- "Potential ET"
ET.Oudin$ET.Daily <- evap_oudin %>% tk_zoo()
ET.Oudin$ET.Monthly <- ET.Oudin$ET.Daily %>%
        daily2monthly.V2(FUN = sum) %>% 
        tk_tbl() %>% 
        mutate(index = as.yearmon(index)) %>% 
        tk_zoo()

5.3 Results

Code
ET.HargreavesSamani$ET.Daily[ET.HargreavesSamani$ET.Daily<0]<-0

ET.GuinessBordne$ET.Daily[ET.GuinessBordne$ET.Daily<0]<-0

et_dly_z<-merge("Hargreaves_Samani"=ET.HargreavesSamani$ET.Daily,
                "Guiness Bordne"=ET.GuinessBordne$ET.Daily,
                "Oudin"=ET.Oudin$ET.Daily$x
) 


daily2monthly.V2(et_dly_z,FUN=sum) %>% 
  fortify.zoo() %>% 
  reshape2::melt(id.vars=c("Index")) %>%
  mutate(mon=lubridate::month(Index,label=T)) %>% 
  ggplot(data=.,aes(x=mon,y=value,
                    fill=variable))+
  geom_boxplot()+
  # facet_wrap(variable~.)+
  theme_bw()+
  theme(legend.position="bottom")+
  labs(x="months",y="evaporation [mm/mon]",fill="method:")+
  scale_y_continuous(breaks=seq(0,200,20))

Code
daily2annual.avg(et_dly_z,FUN=sum) %>% 
  pandoc.table(round=1,split.table=Inf)
Station Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Ann
Hargreaves_Samani 0 0.1 1.3 10.5 42.3 88.1 102.1 68.1 27.8 6 0.2 0 346.4
Guiness Bordne 0 0 0 1.1 17.3 88.7 121.7 76.4 22.6 1.7 0 0 329.5
Oudin 0 0 0 0.8 11.9 61.5 84.9 53.6 16 1.2 0 0 229.9
Code
excel_out<-list(
  Info=data.frame(Longitude=Longitude,
                  Latitude=Latitude,
                  info="ULU GOLD"),
  "daily_ts_mm.d"=et_dly_z %>% 
    fortify.zoo() %>% 
    dplyr::rename("date"="Index"),
  "month_ts_mm_mon"=daily2monthly.V2(et_dly_z,FUN=sum) %>% 
    fortify.zoo()  %>% 
    dplyr::rename("date"="Index"),
  "month_avg_mm_mon"=daily2annual.avg(et_dly_z,FUN=sum))


openxlsx::write.xlsx(x = excel_out,
                     file = here::here("outputs","evaporation_info.xlsx"))

6 Synthesis

As a preliminary time series, it is recommended to use ERA5-Land for the site; however, this low-effort analysis suggests implementing a deeper analysis to complement with other climatic gridded models such as ERA5 and MERRA2. Additionally, this analysis did not include a comprehensive review considering the meteorological stations or bias correction. Furthermore, this review did not include snowpack review or comparison, which can help understand effects such as snow capture efficiency (undercatch).

Despite these comments, it is considered an educated guess to consider the time series for ERA5-Land at the site as a preliminary understanding of local meteorology.

6.1 Climograph

Code
source_gp<-"ERA5-Land"

reanalysis_z<-era5_land_meteo_dly_z

#In the case of DAYMET "unlock" these lines
# source_gp<-"DAYMET"
# 
# reanalysis_z<-daymet_z
  
year_start_z<-lubridate::year(start(reanalysis_z))
year_end_z<-lubridate::year(last(reanalysis_z))

#Mean monthly
reanalysis_mean_mon<-rbind(
daily2annual.avg(reanalysis_z,FUN = sum) %>% 
  dplyr::filter(Station%in%c("prcp","rain","snow")),
daily2annual.avg(reanalysis_z,FUN = mean)%>% 
  dplyr::filter(!Station%in%c("prcp","rain","snow"))
)


reanalysis_mean_mon_gp<-reanalysis_mean_mon %>% 
  reshape2::melt(data = .,id.vars="Station") %>% 
  dplyr::filter(!variable=="Ann") %>% 
  reshape2::dcast(data =.,formula=variable~Station)

prcp_range_max<-max(reanalysis_mean_mon_gp$prcp)

prcp_range_min<-min(reanalysis_mean_mon_gp$prcp,0)

tavg_range_max<-max(reanalysis_mean_mon_gp$tavg)

tavg_range_min<-min(reanalysis_mean_mon_gp$tavg)

#ranges in Kelvin
tavg_range_max<-(tavg_range_max+273.15)*1.003-273.15

tavg_range_min<-(tavg_range_min+273.15)*0.998-273.15

slope_temp<-(prcp_range_max-prcp_range_min)/(tavg_range_max-tavg_range_min)

inter_temp<-prcp_range_min-tavg_range_min*slope_temp

reanalysis_mean_mon_prcp<-reanalysis_mean_mon_gp %>%
  rename(mon="variable") %>% 
  reshape::melt.data.frame(measure.vars=c("rain","snow")) 

#Climograph
ggplot(data=reanalysis_mean_mon_gp,aes(x=variable))+
  geom_bar(data=reanalysis_mean_mon_prcp,stat = "Identity", aes(x=mon,y=value,fill=variable) ,col="black") +
  geom_point( aes(y=slope_temp*tavg+inter_temp), size=2, color="red",alpha=0.6,shape=21,fill="red")+
  geom_line(aes(y=slope_temp*tavg+inter_temp,group="tavg"), size=1, color="red",alpha=0.6)+
  scale_y_continuous(sec.axis=sec_axis(trans=~(.-inter_temp)/slope_temp,
                                       name="Temperature [degC]"))+
  geom_text(aes(y=prcp*1.02,label=round(prcp,1)),alpha=0.6,nudge_y = 0.6)+
  geom_text(aes(y=slope_temp*tavg+inter_temp,label=round(tavg,1)),alpha=0.6,
            nudge_y = -0.6,col="red",fontface="bold")+
  theme_bw()+
  theme(axis.line.y.right = element_line(color = "red"), 
        axis.ticks.y.right = element_line(color = "red"),
        axis.text.y.right = element_text(color = "red"), 
        axis.title.y.right = element_text(color = "red")
  ) +
  labs(x="",y="Total Precipitation [mm]", 
       title=glue::glue("Climatogram for Longitude: {round(Longitude,2)} / Latitude: {round(Latitude,2)}"),
                                                           subtitle=glue::glue("Based on {source_gp} ({year_start_z} to {year_end_z})"),
       fill="")+
  scale_fill_manual(values = c("rain"="dodgerblue3","snow"="snow2"))+
  theme(legend.position="bottom")

Code
pander::pandoc.table(reanalysis_mean_mon,split.table=Inf,style="simple",round=1,
               caption=glue::glue("Mean monthly parameters based on {source_gp}"))
Mean monthly parameters based on ERA5-Land
Station Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Ann
prcp 11.1 10.3 14.2 17 25.5 38.8 48.9 56.9 46.7 36.7 18.9 14 338.9
rain 0 0 0 0 5.5 35.2 48.9 55.7 29.6 3.7 0 0 178.8
snow 11.1 10.3 14.2 17 20 3.6 0 1.1 17 32.9 18.9 14 160.1
tavg -29.9 -28.9 -24.2 -14.8 -4.5 6.7 12.1 8.8 1.6 -8.3 -21.5 -27.7 -10.9
tmax -27 -25.5 -19.8 -10.3 -0.9 11.3 17 13.5 5.1 -5.6 -18.6 -24.9 -7.1
tmin -32.6 -31.5 -27.2 -18.1 -7.3 2.7 7.5 5.1 -0.9 -10.5 -24.3 -30.5 -14
ws 5.5 5.5 5.1 4.7 4.4 4.1 4 4.1 4.3 4.4 4.9 5.2 4.7

6.2 Koppen- Geiger Climate Classification

The area is predominantly characterized by a Dfc subarctic climate. However, the local region lies on the boundary between this climate type and the ET tundra climate. Further meteorological analysis is required to accurately define the local conditions.

Code
clim_class_tbl<-data.frame(col=
                       c("#960000", "#FF0000", "#FF6E6E", "#FFCCCC", "#CC8D14", "#CCAA54", "#FFCC00", "#FFFF64", "#007800", "#005000", "#003200", "#96FF00", "#00D700", "#00AA00", "#BEBE00", "#8C8C00", "#5A5A00", "#550055", "#820082", "#C800C8", "#FF6EFF", "#646464", "#8C8C8C", "#BEBEBE", "#E6E6E6", "#6E28B4", "#B464FA", "#C89BFA", "#C8C8FF", "#6496FF", "#64FFFF", "#F5FFFF"),
                     
                     class=c('Af', 'Am', 'As', 'Aw', 'BSh', 'BSk', 'BWh', 'BWk', 'Cfa', 'Cfb','Cfc', 'Csa', 'Csb', 'Csc', 'Cwa','Cwb', 'Cwc', 'Dfa', 'Dfb', 'Dfc','Dfd', 'Dsa', 'Dsb', 'Dsc', 'Dsd','Dwa', 'Dwb', 'Dwc', 'Dwd', 'EF','ET', 'Ocean'),
                     
                     description=c("Tropical rainforest climate", "Tropical monsoon climate", "Tropical dry savanna climate", "Tropical savanna, wet", "Hot semi-arid (steppe) climate", "Cold semi-arid (steppe) climate", "Hot deserts climate", "Cold desert climate", "Humid subtropical climate", "Temperate oceanic climate", "Subpolar oceanic climate", "Hot-summer Mediterranean climate", "Warm-summer Mediterranean climate", "Cool-summer Mediterranean climate", "Monsoon-influenced humid subtropical climate", "Subtropical highland climate or temperate oceanic climate with dry winters", "Cold subtropical highland climate or subpolar oceanic climate with dry winters", "Hot-summer humid continental climate", "Warm-summer humid continental climate", "Subarctic climate", "Extremely cold subarctic climate", "Hot, dry-summer continental climate", "Warm, dry-summer continental climate", "Dry-summer subarctic climate", "Very Cold Subarctic Climate", "Monsoon-influenced hot-summer humid continental climate", "Monsoon-influenced warm-summer humid continental climate", "Monsoon-influenced subarctic climate", "Monsoon-influenced extremely cold subarctic climate", "Ice cap climate", "Tundra", "Ocean"))


clim_class<-data.table(lon=kgc::genCoords(latlong='lon',full='true'),
                       lat=kgc::genCoords(latlong='lat',full='true'),
                       kg=kgc::kmz) %>% 
  dplyr::filter(lon>=xy[1],lon<=xy[3],lat>=xy[2],lat<=xy[4]) %>% 
  as.data.frame() %>% 
  mutate(kg_clas=getZone(kg)) %>% 
  left_join(.,clim_class_tbl,by=c("kg_clas"="class")) %>% 
  mutate(description=paste0(kg_clas,": ",description) %>% 
           str_wrap(.,30))

clim_class_fill<-clim_class %>% 
  dplyr::select(kg_clas,col,description) %>% unique() %>% 
  arrange(kg_clas)



ggmap(map, darken = c(0.3, "white"))+
  geom_tile(data=clim_class,aes(x=lon,y=lat,fill=description),alpha=0.4)+
  geom_point(data=site.info,
             aes(x=Longitude,y=Latitude),shape=5,col="red")+
  geom_label_repel(data=site.info,
                   aes(x=Longitude,y=Latitude,label=Location))+
  
    geom_label_repel(data=eccc_prcp_idx,
                   aes(x=Longitude,y=Latitude,
                       label=paste0(Station.Name)),colour="darkblue",
                   fontface="bold",alpha=0.6,
                   box.padding =unit(0.5, "lines"),segment.color = "black",
                   size=3 )+
  
  geom_point(data=eccc_prcp_idx,
                   aes(x=Longitude,y=Latitude),size=4,shape=22,alpha=0.6)+

  
  coord_quickmap()+
  # ggsn::scalebar(x.min=xy_min[1],x.max=xy_min[3],
  #              y.min=xy_min[2],y.max=xy_min[4],dist = 50,dist_unit = "km",transform = T,model = "WGS84")+
  scale_fill_manual(breaks=clim_class_fill$description,values = clim_class_fill$col)+
  labs(caption="Rubel, F., Brugger, K., Haslinger, K., Auer, I., 2016. The climate of the European Alps: Shift
of very high resolution Köppen-Geiger climate zones 1800–2100. Meteorologische Zeitschrift.
doi:10.1127/metz/2016/0816 http://koeppen-geiger.vu-wien.ac.at/",
title="Koppen-Geiger Climate Classification",
fill="",
x="Longitude [deg]",y="Latitude[deg]")+
  theme(legend.position="bottom")+
  guides(fill=guide_legend(ncol=3))

7 Output

On the output folder of this project a csv was exported with the meteorological parameters at the site based on climatic gridded model ERA5-Land.

Code
data.table::fwrite(x=fortify.zoo(era5_land_meteo_dly_z) %>% 
                     rename(date="Index"),
                   file = here::here("outputs","meteo_era5_land_dly.csv"))

file.image<-here::here("data","rds",paste0("Backup Meteorological review_",as.Date(now()),".rdata"))

save.image(file = file.image)