AIM : Compare interpolation outputs from 3 methods: (1) Moving window (MW) following the coastline and using the relationships of Kd with Distance to shore (2) Nearest-Neighbor (NN) (3) Inverse-Distance Weighting (IDW).
#knitr::opts_chunk$set(echo = TRUE)
library(sp)
library(raster)
library(tidyverse)
## -- Attaching packages --------------------------------------- tidyverse 1.3.1 --
## v ggplot2 3.3.5 v purrr 0.3.4
## v tibble 3.1.2 v dplyr 1.0.7
## v tidyr 1.1.3 v stringr 1.4.0
## v readr 1.4.0 v forcats 0.5.1
## -- Conflicts ------------------------------------------ tidyverse_conflicts() --
## x tidyr::extract() masks raster::extract()
## x dplyr::filter() masks stats::filter()
## x dplyr::lag() masks stats::lag()
## x dplyr::select() masks raster::select()
library(sf)
## Linking to GEOS 3.9.0, GDAL 3.2.1, PROJ 7.2.1
library(plotly)
##
## Attaching package: 'plotly'
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:raster':
##
## select
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
library(viridis)
## Loading required package: viridisLite
library(tabularaster)
## Registered S3 method overwritten by 'spatstat.geom':
## method from
## print.boxx cli
library(RColorBrewer)
library(gstat)
library(broom)
library(knitr)
library(stargazer)
##
## Please cite as:
## Hlavac, Marek (2018). stargazer: Well-Formatted Regression and Summary Statistics Tables.
## R package version 5.2.2. https://CRAN.R-project.org/package=stargazer
## Part 4: Moving the window, storing estimated values, producing full estimated map - Size of window consistent vs DShore (keep 15km of pixels)
#####
## Loading data - KPAR raster, crop in KK zone - Coastline shp file
#####
## Zone
xmin <- 1600000
xmax <- 1730000
ymin <- 5200000
ymax <- 5390000
##
## Load raster of KPAR + crop KK
kpar <- raster('A20021822002212_MO_KPAR_exp_coastal_v01.nc')
kpar_KK <- crop(kpar,extent(xmin, xmax, ymin, ymax))
kpar_KK_sp <- rasterToPoints(kpar_KK,spatial=T)
kpar_KK_sf <- st_as_sf(kpar_KK_sp) %>% rename(KPAR=DownwellingPARattenuation)
##
## Coastline + crop KK
coastline <- st_read('Coastline_Reproj_Line.shp') %>%
st_set_crs(.,crs(kpar_KK_sf))
coastline_KK <- st_crop(coastline,xmin=xmin,ymin=ymin,xmax=xmax,ymax=ymax)
##
## Convert Coastline Multinestring to Raster
coastline_KK_ras <- rasterize(coastline_KK,kpar_KK)
##
## Load DShore from previous Bathymetry grid
dShore_bathy <- raster('NZ_Dist2Shore.tif')
dShore_bathy_KK <- crop(dShore_bathy,extent(xmin, xmax, ymin, ymax))
dShore_KK_sp <- rasterToPoints(dShore_bathy_KK,spatial=T)
dShore_KK_sf <- st_as_sf(dShore_KK_sp) %>% rename(DShore=NZ_Dist2Shore) %>%
st_set_crs(.,crs(kpar_KK_sf))
##
## Moving the window, storing estimated values, producing full estimated map - Size of window consistent vs DShore (keep ~10km of pixels)
rot <- function(a){
# Rotation matrix,
# Takes angle, a, in radian as input
# cf https://r-spatial.github.io/sf/articles/sf3.html
# and https://geocompr.robinlovelace.net/geometric-operations.html
matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2)
}
##
## Initialization of Box - Width, Length, Buff_dist
start_pix_ID <- 1
length <- 50#20 #Length factor of normal line
buff_dist <- 2500
dShore_max <- 5000#10000
kpar_KK_sp <- rasterToPoints(kpar_KK,spatial=T)
kpar_KK_sf <- st_as_sf(kpar_KK_sp) %>%
rename(KPAR=DownwellingPARattenuation) %>%
st_join(dShore_KK_sf,.,by=c('geometry'),left=T) %>% #Merge with DShore straight away here, keep NA in KPAR
dplyr::filter(DShore<=dShore_max) #+ filter by DShore<dShore_max
##
## Step 1: Get index (not x,y as before) of coastline pixels
#idx_coastline <- which(!values(coastline_KK_ras)==0)
idx_coastline <- which(!is.na(values(coastline_KK_ras)))
#end_domain <- nrow(idx_coastline)
end_domain <- length(idx_coastline)
#The box will go from start_pix_ID to end_domain
##
## Matrix of cells (x,y) which need to be filled (which have KPAR==NA)
kpar_coastal_NA <- xyFromCell(coastline_KK_ras,which(is.na(values(kpar_KK))==T)) %>%
as_tibble() %>% add_column(Pred = NA)
kpar_coastal_NA_ls <- list()
##
system.time(
#for (i in start_pix_ID:end_domain){
for (i in 20:500){
print(i)
## Step 2: Select pixel #1 (or i), get adjacent pixels, only keep adjacent with not NA, get x/y
idx_adj <- adjacent(coastline_KK_ras,idx_coastline[i],directions=8,include=T)#Issue of taking all ngb cells, regardless if it's coastline (non 0) or not
idx_adj_coast <- idx_adj[which(!is.na(coastline_KK_ras)[idx_adj[,2]]),2]#Here only keep pixels without NA, i.e, coastline
xy_box <- xyFromCell(coastline_KK_ras,idx_adj_coast)
##
## Step 3: Keep First and Last Points
pixs_coastline_fl_box <- xy_box[c(1,nrow(xy_box)),]
#--> Can be more thought of as first and last points not always best, cf plots
##
## Step 4: Draw lines between first and last points in box
pixs_coastline_line <- st_linestring(pixs_coastline_fl_box) %>%
st_sfc() %>% st_set_crs(crs(kpar_KK))
##
## Step 5: Create normal/perpendicular line by rotating by 90deg + extend by factor length +
# cut normal line in 2 lines around centroid and keep offshore line
cntrd <- st_centroid(pixs_coastline_line) %>%
st_sfc() %>% st_set_crs(crs(kpar_KK))
pixs_coastline_normal <- (pixs_coastline_line - cntrd) * rot(pi/2) *length + cntrd
pixs_coastline_normal <- pixs_coastline_normal %>%
st_sfc() %>% st_set_crs(crs(kpar_KK))
pixs_coastline_normal_split <- st_split(pixs_coastline_normal,cntrd) %>%
st_collection_extract(.,"LINESTRING")
# Let's continue by only keeping bit==1, meanig that what follows (cut, pixs_coastline_normal_fixLength) not needed
pixs_coastline_normal <- pixs_coastline_normal_split[1]
##
## Step 6: Create buffer around normal/perpendicular line
pixs_coastline_normal_buff <- st_buffer(pixs_coastline_normal,dist=buff_dist)
##
## Step 7: Crop KPAR pixels in buffered polygon
kpar_dshore_buff_allpix <- st_intersection(kpar_KK_sf,pixs_coastline_normal_buff)
##
if (sum(!is.na(kpar_dshore_buff_allpix$KPAR))>1){#nkpar_min
## Step 8: Estimate KPAR at missing pixels (where DShore is), shouldnt be issue of land pixels
loess_out <- loess(KPAR ~ DShore, kpar_dshore_buff_allpix,control = loess.control(surface = "direct"))
## Step 9: Create list of predictions at each pixels
# --> Will be use to have several estimates per pixels (keep median at the end)
kpar_dshore_buff_NA <- kpar_dshore_buff_allpix %>%
dplyr::filter(is.na(KPAR)==T) %>%
mutate(KPAR_pred=predict(loess_out,DShore)) %>%
mutate(x = sf::st_coordinates(.)[,1],y = sf::st_coordinates(.)[,2])
kpar_coastal_NA_ls[[i]] <- kpar_dshore_buff_NA %>% dplyr::select(-KPAR)
# THIS LIST KEEPS IN MEMORY THE X, Y and KPAR Prediction AT EACH PIXELS THAT HAVE KPAR==NA
##
}else{
kpar_coastal_NA_ls[[i]] <- NA
}
}
)#156s for 602i
## Unlist and unnest kpar_coastal_NA_ls, calculate median of KPAR_Pred to each pixels (x,y)
# in new object containing pred at NA pixels, make sf and merge with kpar_dShore_KK_sf
kpar_KK_pred_sf <- tibble(
x = map(kpar_coastal_NA_ls, "x"),
y = map(kpar_coastal_NA_ls, "y"),
DShore = map(kpar_coastal_NA_ls, "DShore"),
KPAR_pred = map(kpar_coastal_NA_ls, "KPAR_pred")) %>% #Good for switching from list to tibble which contains lists
unnest(cols = c(x, y, DShore, KPAR_pred)) %>%
group_by(x, y,DShore) %>%
#summarise(KPAR_pred_list = list(KPAR_pred)) %>% #To check number of predictions per pixels
summarise(KPAR = median(KPAR_pred)) %>% #Name of KPAR column should match name column in kpar_KK_sf for easy rbind
st_as_sf(.,coords = c('x','y'), crs=crs(kpar_KK))
# --> Yeeeew
kpar_KK_sf_noNA <- kpar_KK_sf %>%
dplyr::filter(!is.na(KPAR))
kpar_KK_merge_sf <- rbind(kpar_KK_sf_noNA,kpar_KK_pred_sf)
st_write(kpar_KK_sf,'KPARKK_Before_Large_Win4_v2.shp')
st_write(kpar_KK_merge_sf,'KPARKK_After_Large_Win4_v2.shp')
st_write(kpar_KK_pred_sf,'KPARKK_Estimated_Large_Win4_v2.shp')