Newer
Older

Blodgett, David L.
committed
---
title: "NHD Navigate"
output: html_document
editor_options:
chunk_output_type: console

Blodgett, David L.
committed
---
This notebook Generate Segments and POIS from POI data sources and builds
a minimally-sufficient stream network connecting all POis, as well as generating first-cut of
national segment network.

Blodgett, David L.
committed
```{r setup_rmd, echo=FALSE, cache=FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.width=6,
fig.height=4,
cache=FALSE)

Blodgett, David L.
committed
```{r setup}
source("R/utils.R")

Blodgett, David L.
committed
source("R/NHD_navigate.R")
source("R/hyrefactor_funs.R")
# Load Configuration of environment
source("R/config.R")
gages <- read_sf("cache/Gages_info.gpkg", "Gages")
nc <- RNetCDF::open.nc(data_paths$nwm_network)
nwm_gages <- data.frame(
comid = RNetCDF::var.get.nc(nc, "link"),
gage_id = RNetCDF::var.get.nc(nc, "gages")) %>%
mutate(gage_id = gsub(" ", "", gage_id)) %>%
mutate(gage_id = ifelse(gage_id == "", NA, gage_id))
RNetCDF::close.nc(nc)
atts <- readRDS(file.path(data_paths$nhdplus_dir, "nhdplus_flowline_attributes.rds"))
if(needs_layer(temp_gpkg, nav_poi_layer)) {
try(nhd <- select(nhd, -c(minNet, WB, struct_POI, struct_Net, POI_ID)), silent = TRUE)
grep_exp <- paste0("^", substr(vpu, start = 1, stop = 2))
HUC12_COMIDs <- read_sf(data_paths$hu12_points_path, "hu_points") %>%
# Remove this when HUC12 outlets finished
group_by(COMID) %>%
# Create POIs - some r05 HUC12 POIs not in R05 NHD
huc12_POIs <- POI_creation(st_drop_geometry(HUC12_COMIDs), filter(nhd, poi == 1), "HUC12")
# Write out geopackage layer representing POIs for given theme
write_sf(huc12_POIs, temp_gpkg, nav_poi_layer)
tmp_POIs <- huc12_POIs
# Load HUC12 POIs as the tmpPOIs if they already exist
tmp_POIs <- read_sf(temp_gpkg, nav_poi_layer)
mapview(filter(tmp_POIs, Type_HUC12 != ""), layer.name = "HUC12 POIs", col.regions = "red")
if(all(is.na(tmp_POIs$Type_Gages))) {
# Previously identified streamgages within Gage_Selection.Rmd
filter(COMID %in% nhd$COMID) %>%
switchDiv(., nhd)
streamgages <- streamgages_VPU %>%
# If multiple gages per COMID, pick one with highest rank as rep POI_ID
# Derive GAGE POIs; use NHD as we've alredy filtered by NWIS DA in the Gage selection step
tmp_POIs <- POI_creation(streamgages, nhd, "Gages") %>%
addType(., tmp_POIs, "Gages")
# As a fail-safe, write out list of gages not assigned a POI
if(nrow(filter(streamgages_VPU, !site_no %in% tmp_POIs$Type_Gages)) > 0) {
write_sf(filter(streamgages_VPU, !site_no %in% tmp_POIs$Type_Gages),
temp_gpkg, "unassigned_gages")
# Start documenting gages that are dropped out; these gages have no mean daily Q
gage_document(filter(streamgages_VPU, !site_no %in% tmp_POIs$Type_Gages) %>%
select(site_no),
"Gages_info", paste0("VPU ", vpu, "; low gage score"))
# Write out geopackage layer representing POIs for given theme
write_sf(tmp_POIs, temp_gpkg, nav_poi_layer)
tmp_POIs <- read_sf(temp_gpkg, nav_poi_layer)
mapview(filter(tmp_POIs, !is.na(Type_Gages)), layer.name = "Streamgage POIs", col.regions = "blue")
if(all(is.na(tmp_POIs$Type_TE))) {
nhd$VPUID <- "08"
} else {
nhd$VPUID <- substr(nhd$RPUID, 1, 2)
}
# Read in Thermoelectric shapefile
TE_COMIDs <- read_sf(data_paths$TE_points_path, "2015_TE_Model_Estimates_lat.long_COMIDs") %>%
mutate(COMID = as.integer(COMID)) %>%
inner_join(., select(st_drop_geometry(nhd), COMID, VPUID), by = "COMID") %>%
filter(grepl(paste0("^", substr(vpu, 1, 2), ".*"), .data$VPUID), COMID > 0) %>%
summarize(EIA_PLANT = paste0(unique(EIA_PLANT_), collapse = " "), count = n()) %>%
ungroup()
# Derive TE POIs
tmp_POIs <- POI_creation(st_drop_geometry(TE_COMIDs), filter(nhd, dend == 1), "TE") %>%
addType(., tmp_POIs, "TE")
# As a fail-safe, write out list of TE plants not assigned a POI
if(nrow(filter(TE_COMIDs, !COMID %in% tmp_POIs$COMID)) > 0) {
write_sf(filter(TE_COMIDs, !COMID %in% tmp_POIs$COMID),
temp_gpkg, "unassigned_TE")
# Write out geopackage layer representing POIs for given theme
write_sf(tmp_POIs, temp_gpkg, nav_poi_layer)
} else {
# Load TE POIs if they already exist
tmp_POIs <- read_sf(temp_gpkg, nav_poi_layer)
mapview(filter(tmp_POIs, Type_TE != ""), layer.name = "TE Plant POIs", col.regions = "blue")
```{r Terminal POIs}
# Derive or load Terminal POIs ----------------------
# Terminal POIs on levelpaths with upstream POIs
term_paths <- filter(st_drop_geometry(nhd), Hydroseq %in% filter(nhd, COMID %in% tmp_POIs$COMID)$TerminalPa)
# Non-POI levelpath terminal pois, but meet size criteria
terminal_POIs <- st_drop_geometry(nhd) %>%
filter(Hydroseq == TerminalPa | (toCOMID == 0 | is.na(toCOMID) | !toCOMID %in% COMID)) %>%
filter(!COMID %in% term_paths$COMID, TotDASqKM >= 20) %>%
bind_rows(term_paths) %>%
# Use level path identifier as Type ID
select(COMID, LevelPathI)
tmp_POIs <- POI_creation(terminal_POIs, nhd, "Term") %>%
addType(., tmp_POIs, "Term")
write_sf(tmp_POIs, temp_gpkg, nav_poi_layer)
tmp_POIs <- read_sf(temp_gpkg, nav_poi_layer)
mapview(filter(tmp_POIs, !is.na(Type_Term)), layer.name = "Terminal POIs", col.regions = "blue")
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
```{r waterbody outlet POIs}
# Derive or load Waterbody POIs ----------------------
if(all(is.na(tmp_POIs$Type_WBOut))) {
# Waterbodies sourced from NHD waterbody layer for entire VPU
WBs_VPU_all <- filter(readRDS("data/NHDPlusNationalData/nhdplus_waterbodies.rds"),
COMID %in% nhd$WBAREACOMI) %>%
mutate(FTYPE = as.character(FTYPE)) %>%
mutate(source = "NHDv2WB")
# Waterbody list that strictly meet the size criteria
wb_lst <- st_drop_geometry(WBs_VPU_all) %>%
dplyr::filter(FTYPE %in% c("LakePond", "Reservoir") & AREASQKM >= (min_da_km/2)) %>%
dplyr::select(COMID)
if (file.exists(data_paths$resops_NID_CW)){
# ResOpsUS locations in the VPU waterbody set
resops_wb_df <- read.csv(data_paths$resops_NID_CW) %>%
dplyr::filter(WBAREACOMI %in% WBs_VPU_all$COMID) %>%
dplyr::select(DAM_ID, DAM_NAME, COMID = WBAREACOMI, FlowLcomid) %>%
distinct()
# Add ResOPsUS locations to waterbody list
if(nrow(resops_wb_df) > 0){
wb_lst <- rbind(wb_lst, select(resops_wb_df, COMID)) %>%
distinct()
}
}
# Waterbodies that meet the size criteria and/or are in ResOpsUS datasets
WBs_VPU <- WBs_VPU_all %>%
dplyr::filter(COMID %in% wb_lst$COMID)
# Attribute flowlines that are in waterbodies
nhd <- mutate(nhd, WB = ifelse(WBAREACOMI > 0 & WBAREACOMI %in% WBs_VPU$COMID, 1, 0))
# Create waterbody outlet POIs for waterbodies that are in NHDv2 waterbody set
wbout_COMIDs <- filter(nhd, dend == 1 & WB == 1) %>%
group_by(WBAREACOMI) %>%
slice(which.min(Hydroseq)) %>%
switchDiv(., nhd) %>%
select(COMID, WBAREACOMI, LevelPathI)
# Get NHDArea and HI-Res waterbodies for ResOpsUS locaitons
WBs_VPU_areaHR <- HR_Area_coms(nhd, WBs_VPU, data_paths)
# If the return is not NA
if(inherits(WBs_VPU_areaHR, "list")){
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# Attribute flowlines that intersect NHDARea and/or NHD HR waterbodies with
# waterbody COMIDs
nhd <- nhd %>%
left_join(select(WBs_VPU_areaHR$wb_table, comid, wb_comid), by = c("COMID" = "comid")) %>%
mutate(WBAREACOMI = ifelse(!is.na(wb_comid), wb_comid, WBAREACOMI)) %>%
select(-wb_comid)
# Full table of HR and NHDArea waterbodies and their flowlines
# Subset down to specific outlets
resops_wb_hr <- WBs_VPU_areaHR$wb_table %>%
filter(!wb_comid %in% WBs_VPU$COMID, !is.na(outlet)) %>%
rename(WBAREACOMI = wb_comid) %>%
select(DAM_ID, DAM_NAME, COMID = WBAREACOMI, FlowLcomid = comid) %>%
rbind(resops_wb_df)
# NHD flowlines within the HR/NHDArea waterbodies
nhd_WBs <- filter(nhd, WBAREACOMI %in% WBs_VPU_areaHR$wb_table$wb_comid)
if(nrow(nhd_WBs) > 0){
# Create outlet events for splitting HR and NHDArea waterbodies
wb_outlet_events <- WB_event(WBs_VPU_areaHR, nhd_WBs, "outlet")
# Create Navigate POIs for the NHDarea and HR waterbodies
wbout_COMIDs <- rbind(select(wbout_COMIDs, COMID, WBAREACOMI),
select(wb_outlet_events, COMID, WBAREACOMI))
}
WBs_VPU_areaHR$wb <- nhdplusTools::st_compatibalize(
WBs_VPU_areaHR$wb, WBs_VPU)
# Append NHDArea and NHDHR waterbodies to waterbody layer
WBs_VPU <- data.table::rbindlist(list(WBs_VPU, WBs_VPU_areaHR$wb), fill = TRUE) %>%
st_as_sf()
st_geometry(WBs_VPU) <- st_make_valid(st_geometry(WBs_VPU))
}
# Write out waterbodies
write_sf(WBs_VPU, nav_gpkg, WBs_layer)
tmp_POIs <- POI_creation(wbout_COMIDs, nhd, "WBOut") %>%
addType(., tmp_POIs, "WBOut")
# Write specific ResOpsUS data to a separate sheet
if(nrow(wb_lst) > 0){
resops_POIs_df <- st_drop_geometry(tmp_POIs) %>%
dplyr::select(COMID, Type_WBOut) %>%
dplyr::filter(!is.na(Type_WBOut)) %>%
dplyr::inner_join(select(resops_wb_df, -FlowLcomid), by = c("Type_WBOut" = "COMID"))
write.csv(resops_POIs_df, file.path("data/reservoir_Data", paste0("resops_POIs_",vpu,".csv")))
}
write_sf(nhd, nav_gpkg, nhd_flowline)
write_sf(tmp_POIs, temp_gpkg, nav_poi_layer)
tmp_POIs <- read_sf(temp_gpkg, nav_poi_layer)
nhd <- read_sf(nav_gpkg, nhd_flowline)
WBs_VPU <- read_sf(nav_gpkg, WBs_layer)
resops_POIs_df <- read.csv(file.path("data/reservoir_Data", paste0("resops_POIs_",vpu,".csv")))
}
mapview(filter(tmp_POIs, !is.na(Type_WBOut)), layer.name = "Waterbody outlet POIs", col.regions = "red")
```
# Derive POIs at confluences where they are absent ----------------------
if(all(is.na(tmp_POIs$Type_Conf))) {
# Navigate upstream from each POI and determine minimally-sufficient network between current POI sets
up_net <- unique(unlist(lapply(unique(tmp_POIs$COMID), NetworkNav, nhd)))
finalNet <- unique(NetworkConnection(up_net, st_drop_geometry(nhd)))
# Subset NHDPlusV2 flowlines to navigation results and write to shapefile
nhd <- mutate(nhd, minNet = ifelse(COMID %in% finalNet, 1, 0))
conf_COMIDs <- st_drop_geometry(filter(nhd, minNet == 1)) %>%
group_by(DnHydroseq) %>%
filter(n()> 1) %>%
mutate(Type_Conf = LevelPathI) %>%
tmp_POIs <- POI_creation(conf_COMIDs, filter(nhd, minNet == 1), "Conf") %>%
addType(., tmp_POIs, "Conf")
write_sf(tmp_POIs, temp_gpkg, nav_poi_layer)
tmp_POIs <- read_sf(temp_gpkg, nav_poi_layer)
mapview(filter(tmp_POIs, !is.na(Type_Conf)), layer.name = "Confluence POIs", col.regions = "blue")
# Derive or load NID POIs ----------------------
if(all(is.na(tmp_POIs$Type_NID))) {
# Read in NID shapefile
NID_COMIDs <- read.csv(file.path(data_paths$NID_points_path, "NID_attributes_20170612.txt"),
stringsAsFactors = FALSE) %>%
filter(ONNHDPLUS == 1, FlowLcomid %in% filter(nhd, dend ==1)$COMID) %>%
group_by(FlowLcomid) %>%
summarize(Type_NID = paste0(unique(NIDID), collapse = " "))
tmp_POIs <- POI_creation(NID_COMIDs, filter(nhd, dend ==1), "NID") %>%
addType(., tmp_POIs, "NID", bind = FALSE)
# Write out geopackage layer representing POIs for given theme
write_sf(tmp_POIs, temp_gpkg, nav_poi_layer)
} else {
# Load NID POIs if they already exist
tmp_POIs <- read_sf(temp_gpkg, nav_poi_layer)
mapview(filter(tmp_POIs, Type_NID != ""), layer.name = "NID POIs", col.regions = "blue")
# Derive or load Waterbody POIs ----------------------
# Get waterbody outlet POIs
wbout_COMIDs <- filter(tmp_POIs, !is.na(Type_WBOut))
DnHydroseq %in% filter(nhd, WB == 1)$Hydroseq) %>%
inner_join(st_drop_geometry(filter(nhd, minNet == 1)) %>%
select(Hydroseq, WBAREACOMI), by = c("DnHydroseq" = "Hydroseq")) %>%
# Ensure the inlets are on the network defined by confluence POIs
filter(minNet == 1)
# Headwater Waterbodies that may need the network extended through the inlet
need_wbin <- st_drop_geometry(filter(WBs_VPU, source == "NHDv2WB")) %>%
dplyr::select(COMID)%>%
dplyr::filter(!COMID %in% wbin_COMIDs$WBAREACOMI)
if(nrow(need_wbin)>0){
nhd_inlet <- mutate(nhd, WB = ifelse(WBAREACOMI > 0 & WBAREACOMI %in% need_wbin$COMID, 1, 0))
missing_wbin_COMIDs <- filter(nhd_inlet, WB == 0,
DnHydroseq %in% filter(nhd_inlet, WB == 1)$Hydroseq) %>%
select(-WBAREACOMI) %>%
switchDiv(., nhd_inlet) %>%
inner_join(st_drop_geometry(filter(nhd_inlet, minNet == 1)) %>%
select(Hydroseq, WBAREACOMI), by = c("DnHydroseq" = "Hydroseq")) %>%
select(COMID, WBAREACOMI) %>%
group_by(COMID) %>%
filter(row_number() == 1) %>%
ungroup()
missing_wbin_COMIDs <- missing_wbin_COMIDs %>%
left_join(select(st_drop_geometry(nhd_inlet), COMID, TotDASqKM, minNet), by = c("COMID")) %>%
group_by(COMID) %>%
slice(which.max(TotDASqKM))%>%
select(-TotDASqKM)
if(nrow(missing_wbin_COMIDs) > 0){
wbin_COMIDs <- rbind(wbin_COMIDs, missing_wbin_COMIDs)
}
# Get NHDArea and HR waterbodies
WBs_VPU_areaHR <- HR_Area_coms(nhd, WBs_VPU, data_paths)
# Get flowlines that intersect waterbodies and are on the minimal network
# (outlets should already be defined)
nhd_WBs <- filter(nhd, minNet == 1 & WBAREACOMI %in% WBs_VPU_areaHR$wb_table$wb_comid)
if(nrow(nhd_WBs) > 0){
# Get the outlet events again
wb_outlet_events <- WB_event(WBs_VPU_areaHR, nhd_WBs, "outlet")
# Drive the inlet events
nhd_inlet <- filter(nhd_WBs, !COMID %in% wb_outlet_events$COMID)
if (nrow(nhd_inlet) > 0){
# Get inlet events and bind with outlets
wb_inlet_events <- WB_event(WBs_VPU_areaHR, nhd_inlet, "inlet")
wb_events <- rbind(wb_inlet_events, wb_outlet_events)
wbin_COMIDs <- rbind(select(wbin_COMIDs, COMID, WBAREACOMI),
filter(select(wb_inlet_events, COMID, WBAREACOMI)))
} else {
wb_events <- wb_outlet_events
}
# write out to geopackage
write_sf(wb_events, nav_gpkg, WB_events_layer)
}
tmp_POIs <- POI_creation(filter(st_drop_geometry(wbin_COMIDs), !COMID %in% wbout_COMIDs$COMID),
nhd, "WBIn") %>%
addType(., tmp_POIs, "WBIn")
write_sf(nhd, nav_gpkg, nhd_flowline)
write_sf(tmp_POIs, nav_gpkg, nav_poi_layer)
mapview(filter(tmp_POIs, !is.na(Type_WBIn)), layer.name = "Waterbody inlet POIs", col.regions = "blue") +
mapview(filter(tmp_POIs, !is.na(Type_WBOut)), layer.name = "Waterbody outlet POIs", col.regions = "red") +
mapview(wb_events) + mapview(WBs_VPU_areaHR$wb)
```
This chunk breaks up potential aggregated segments where the elevation range of the are contributing to the segment exceeds 500-m
```{r Elevation Break POIs}
# derive incremental segments from POIs
inc_segs <- segment_increment(filter(nhd, minNet == 1),
filter(st_drop_geometry(nhd),
COMID %in% tmp_POIs$COMID, COMID %in% filter(nhd, minNet == 1)$COMID)) %>%
# bring over VAA data
inner_join(select(atts, COMID, DnHydroseq, VA_MA, TOTMA, LENGTHKM, MAXELEVSMO, MINELEVSMO, WBAREACOMI, WBAreaType, FTYPE,
AreaSqKM, TotDASqKM), by = "COMID")
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
# Build dataframe for creation of points based on breaks
elev_pois_split <- inc_segs %>%
group_by(POI_ID) %>%
# Get elevation info
mutate(MAXELEVSMO = na_if(MAXELEVSMO, -9998), MINELEVSMO = na_if(MINELEVSMO, -9998),
elev_diff_seg = max(MAXELEVSMO) - min(MINELEVSMO)) %>%
# Filter out to those incremental segments that need splitting above the defined elevation threshold
filter((max(MAXELEVSMO) - min(MINELEVSMO)) > (elev_diff * 100)) %>%
# Do not aggregate on fake lfowlines
filter(AreaSqKM > 0, TotDASqKM > max_elev_TT_DA) %>%
# Order from upstream to downstream
arrange(desc(Hydroseq)) %>%
# Get attributes used for splitting
# csum_length = cumulative length US to DS along segment, cumsum_elev = cumulative US to DS elev diff along segment
# inc_elev = elevation range of each segment
# iter = estimated number of times we'd need to split existing agg flowlines, or number of rows in set
mutate(csum_length = cumsum(LENGTHKM),
inc_elev = cumsum(MAXELEVSMO - MINELEVSMO),
#nc_elev_diff = c(inc_elev[1], (inc_elev - lag(inc_elev))[-1]),
iter = min(round(max(inc_elev) / (elev_diff * 100)), n()),
elev_POI_ID = NA) %>%
# Remove segments we can't break
filter(iter > 0, n() > 1) %>%
# Track original iteration number
mutate(orig_iter = iter) %>%
ungroup()
if(nrow(elev_pois_split) > 0) {
# For reach iteration
elev_POIs <- do.call("rbind", lapply(unique(elev_pois_split$POI_ID), split_elev,
elev_pois_split, elev_diff*100, max_elev_TT_DA)) %>%
filter(!elev_POI_ID %in% tmp_POIs$COMID, COMID == elev_POI_ID) %>%
mutate(Type_Elev = 1) %>%
select(COMID, Type_Elev) %>%
unique()
if(nrow(elev_POIs) > 0){
tmp_POIs <- POI_creation(select(elev_POIs, COMID, Type_Elev), nhd, "Elev") %>%
addType(., tmp_POIs, "Elev")
}
tmp_POIs$Type_Elev <- rep(NA, nrow(tmp_POIs))
write_sf(tmp_POIs, temp_gpkg, nav_poi_layer)
tmp_POIs <- read_sf(temp_gpkg, nav_poi_layer)
if(!all(is.na(tmp_POIs$Type_Elev)))
mapview(filter(tmp_POIs, Type_Elev == 1), layer.name = "Elevation break POIs", col.regions = "blue")
```{r Time of travel POIs}
if(all(is.na(tmp_POIs$Type_Travel))) {
# derive incremental segments from POIs
inc_segs <- segment_increment(filter(nhd, minNet == 1),
filter(st_drop_geometry(nhd),
COMID %in% tmp_POIs$COMID, COMID %in% filter(nhd, minNet == 1)$COMID)) %>%
# bring over VAA data
inner_join(select(atts, COMID, DnHydroseq, VA_MA, TOTMA, LENGTHKM, MAXELEVSMO, MINELEVSMO, WBAREACOMI, WBAreaType, FTYPE,
AreaSqKM, TotDASqKM), by = "COMID")
# TT POIs
tt_pois_split <- inc_segs %>%
# Should we substitute with a very small value
mutate(VA_MA = ifelse(VA_MA < 0, NA, VA_MA)) %>%
mutate(FL_tt_hrs = (LENGTHKM * 3280.84)/ VA_MA / 3600 ) %>%
group_by(POI_ID) %>%
filter(sum(FL_tt_hrs) > travt_diff, TotDASqKM > max_elev_TT_DA) %>%
# Sort upstream to downsream
arrange(desc(Hydroseq)) %>%
# Get cumulative sums of median elevation
mutate(csum_length = cumsum(LENGTHKM),
cumsum_tt = cumsum(FL_tt_hrs),
iter = min(round(sum(FL_tt_hrs) / travt_diff), n()),
tt_POI_ID = NA) %>%
# Only look to split segments based on travel time longer than 10 km
#filter(sum(LENGTHKM) > (split_meters/1000)) %>%
filter(iter > 0, n() > 1) %>%
# Track original iteration number
mutate(orig_iter = iter) %>%
# For reach iteration
tt_POIs <- do.call("rbind", lapply(unique(tt_pois_split$POI_ID), split_tt,
tt_pois_split, travt_diff, max_elev_TT_DA)) %>%
filter(!tt_POI_ID %in% tmp_POIs$COMID, COMID == tt_POI_ID) %>%
mutate(Type_Travel = 1) %>%
select(COMID, Type_Travel) %>%
unique()
tmp_POIs <- POI_creation(select(tt_POIs, COMID, Type_Travel), nhd, "Travel") %>%
addType(., tmp_POIs, "Travel")
write_sf(tmp_POIs, temp_gpkg, nav_poi_layer)
tmp_POIs <- read_sf(temp_gpkg, nav_poi_layer)
}
mapview(filter(tmp_POIs, Type_Travel == 1), layer.name = "Travel time break POIs", col.regions = "blue")
```
```{r Final POIs}
# Derive final POI set ----------------------
if(needs_layer(temp_gpkg, pois_all_layer)) {
unCon_POIs <- filter(st_drop_geometry(filter(nhd, minNet == 1)), COMID %in% tmp_POIs$COMID, AreaSqKM == 0)
# If any POIs happened to fall on flowlines w/o catchment
if (nrow(unCon_POIs) >0){
# For confluence POIs falling on Flowlines w/o catchments, derive upstream valid flowline,
poi_fix <- DS_poiFix(tmp_POIs, filter(nhd, dend == 1))
new_POIs <- st_compatibalize(poi_fix$new_POIs, tmp_POIs)
xWalk <- poi_fix$xWalk
# POIs that didn't need to be moved
tmp_POIs_fixed <- filter(tmp_POIs, !COMID %in% c(poi_fix$xWalk$oldPOI, poi_fix$xWalk$COMID))
# bind together
final_POIs <- bind_rows(tmp_POIs_fixed, select(poi_fix$new_POIs, -c(oldPOI, to_com)))
# Write out fixes
write_sf(new_POIs, temp_gpkg, poi_moved_layer)
write_sf(xWalk, temp_gpkg, poi_xwalk_layer)
# write out final POIs
write_sf(final_POIs, temp_gpkg, pois_all_layer)
} else {
# If no fixes designate as NA
poi_fix <- NA
# write out final POIs
write_sf(tmp_POIs, temp_gpkg, pois_all_layer)
# Need all three sets for attribution below
final_POIs <- read_sf(temp_gpkg, pois_all_layer)
new_POIs <- if(!needs_layer(temp_gpkg, poi_moved_layer)) read_sf(temp_gpkg, poi_moved_layer) else (NA)
xWalk <- if(!needs_layer(temp_gpkg, poi_xwalk_layer)) read_sf(temp_gpkg, poi_xwalk_layer) else (NA)
unCon_POIs <- filter(st_drop_geometry(filter(nhd, minNet == 1)),
COMID %in% tmp_POIs$COMID, AreaSqKM == 0)
if(needs_layer(temp_gpkg, nsegments_layer)) {
# Sort POIs by Levelpath and Hydrosequence in upstream to downstream order
seg_POIs <- filter(st_drop_geometry(nhd), COMID %in% tmp_POIs$COMID, COMID %in% filter(nhd, minNet == 1)$COMID)
inc_segs <- segment_increment(filter(nhd, minNet == 1), seg_POIs)
nhd_Final <- nhd %>%
left_join(select(inc_segs, COMID, POI_ID), by = "COMID")
# create and write out final dissolved segments
nsegments_fin <- segment_creation(nhd_Final, xWalk)
left_join(select(st_drop_geometry(nsegments_fin$raw_segs), COMID, POI_ID), by = "COMID")
nsegments <- nsegments_fin$diss_segs
# Produce the minimal POIs needed to derive the network based on LP and terminal outlets
strucFeat <- structPOIsNet(nhd_Final, final_POIs)
mutate(struct_POI = ifelse(COMID %in% strucFeat$struc_POIs$COMID, 1, 0),
struct_Net = ifelse(COMID %in% strucFeat$structnet$COMID, 1, 0))
write_sf(nhd_Final, nav_gpkg, nhd_flowline)
write_sf(nsegments, temp_gpkg, nsegments_layer)
# Read in NHDPlusV2 flowline simple features and filter by vector processing unit (VPU)
final_POIs <- read_sf(temp_gpkg, pois_all_layer)
nsegments <- read_sf(temp_gpkg, nsegments_layer)
# Ensure that all the problem POIs have been taken care of
sub <- nhd_Final %>% filter(COMID %in% final_POIs$COMID)
print (paste0(nrow(sub[sub$AreaSqKM == 0,]), " POIs on flowlines with no local drainage contributions"))
```
if(!"Type_Elev" %in% names(final_POIs)) final_POIs$Type_Elev <- rep(NA_real_, nrow(final_POIs))
#1 Move POIs downstream by category
out_HUC12 <- POI_move_down(temp_gpkg, final_POIs, nsegments, filter(nhd_Final, !is.na(POI_ID)), "Type_HUC12", .10)
out_gages <- POI_move_down(temp_gpkg, out_HUC12$allPOIs, out_HUC12$segs, out_HUC12$FL, "Type_Gages", .05)
out_gages$allPOIs <- mutate_all(out_gages$allPOIs, list(~na_if(.,"")))
out_gages$allPOIs$snapped <- out_gages$allPOIs$COMID %in% new_POIs$COMID
nhd_Final <- select(nhd_Final, -POI_ID) %>%
select(COMID, POI_ID), by = "COMID")
# Write out geopackage layer representing POIs for given theme
write_sf(out_gages$segs, temp_gpkg, nsegments_layer)
nsegments <- out_gages$segs
final_POIs <- out_gages$allPOIs
final_POIs <- read_sf(nav_gpkg, final_poi_layer)
nhd_Final <- read_sf(nav_gpkg, nhd_flowline)
nsegments <- read_sf(temp_gpkg, nsegments_layer)
mapview(final_POIs, layer.name = "All POIs", col.regions = "red") +
mapview(nsegments, layer.name = "Nsegments", col.regions = "blue")