Closed spencer-tassone closed 1 month ago
Try calling https://doi-usgs.github.io/nhdplusTools/reference/get_raindrop_trace.html first and using the returned intersection point as your snap point.
I updated documentation in a recent PR but need to role it out to the pkgdown site and CRAN still.
I believe that is what I am doing in part 1 of my code above
# Snap point to the nearest NHDPlus flowline
trace <- get_raindrop_trace(start_point)
# Use the intersection point as the pour point
snap_point <- st_sfc(st_point(trace$intersection_point[[1]]),
crs = 4326)
Oh, sorry, I missed that. Looking now and this seems odd. A quick look at what's going on has me wondering if this is something strange with the web service we call for these split catchments.
Does this work anywhere else you have tried? Testing the function demo it is working as expected. I'll try and spend a bit more time looking at this later on.
It seems to work ok at an upstream pour point except now the delineated basin includes some discontinuous polygons/lines in the area outside of the basin (see the upper-right area of figure below).
library(tidyverse)
library(nhdplusTools)
library(sf)
#> Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
# 1. Define the starting point (pour point) ----
start_point <- st_sfc(st_point(c(-78.6389042, 38.74567048)), crs = 4326)
# Snap point to the nearest NHDPlus flowline
trace <- get_raindrop_trace(start_point)
# Use the intersection point as the pour point
snap_point <- st_sfc(st_point(trace$intersection_point[[1]]),
crs = 4326)
# 2. Retrieve NHDPlus COMID for the snapped point ----
start_comid <- discover_nhdplus_id(snap_point)
# 3. Navigate and extract upstream tributary flowlines ----
flowline <- navigate_nldi(list(featureSource = "comid",
featureID = start_comid),
mode = "upstreamTributaries",
distance_km = 1000)
# 4. Download and subset NHDPlus data for the flowlines ----
subset_file <- tempfile(fileext = ".gpkg")
subset <- subset_nhdplus(comids = as.integer(flowline$UT$nhdplus_comid),
output_file = subset_file,
nhdplus_data = "download",
flowline_only = FALSE,
return_data = TRUE, overwrite = TRUE)
#> All intersections performed in latitude/longitude.
#> Reading NHDFlowline_Network
#> Writing NHDFlowline_Network
#> Reading CatchmentSP
#> Writing CatchmentSP
flowline <- subset$NHDFlowline_Network
# Define the NLDI feature list for the starting COMID ----
nldi_nwis <- list(featureSource = "comid", featureID = start_comid)
# 5. Delineate the basin for the snap point ----
basin <- get_split_catchment(snap_point, upstream = TRUE)
basin <- basin[2,3]
# 6. Visualize watershed ----
ggplot() +
geom_sf(data = flowline, color = "blue", size = 1) +
geom_sf(data = basin, fill = NA, color = "red", size = 1) +
geom_sf(data = start_point, color = "green", size = 3, shape = 21, fill = "green") +
theme_bw() +
theme(axis.text = element_text(size = 14, color = 'black'))
Created on 2024-07-31 with reprex v2.1.1
Hi -- ok, I chatted with the developer of the service and he confirmed that this is a known issue that happens in rare cases. The issue is that the point you got on the flowline doesn't precisely coincide with a raster cell along the river pathway.
Unfortunately, the solution is to try a slightly different lat/lon position so it hits a cell that is on the river.
Yeah, so if I move your point to start_point <- st_sfc(st_point(c(-78.338, 38.979)), crs = 4269)
I get
Yes - I get a similar result when using a slightly different lat/long. However, I am still seeing the random geometries near the mouth of the basin (upper-right). Should I close out this question and open a new one to address this new issue?
No... that issue is also known. You need to explode the geometry and only keep the largest one if you want to fix the issue. The "clean_geometry" function in https://github.com/DOI-USGS/hyRefactor/blob/main/R/catchment_geometry.R will do it or you can craft your own pretty easily based on code in that function.
I'm talking to Anders who developed https://code.usgs.gov/wma/nhgf/toolsteam/nldi-flowtools (the code for the service in question) about fixing it on the service side.
OK, tracked this down from an email.
basin_id <- paste0('USGS-', c('01435000','01434498', '01434025','01434021', '01434017'))
nhd <- lapply(basin_id, function(x){
get_nldi_basin(list(featureSource = "nwissite",
featureID = x), simplify = FALSE, split = TRUE) %>%
ms_explode() %>%
rbind() %>%
dplyr::mutate(Area = st_area(geometry) ) %>%
dplyr::filter(Area == max(Area))
})
basin <- do.call(rbind, nhd)
gage <- lapply(basin_id, function(x){
get_nldi_feature(list(featureSource = "nwissite",
featureID = x))
})
gage <- do.call(rbind, gage)
plot(st_geometry(basin))
plot(st_geometry(gage), col = "red", add = TRUE, pch = 16)
Leave this issue open. I'll add a little clean up code to the service call to try and take care of the splinters.
I incorporated a little clean up code and now see:
library(nhdplusTools)
library(sf)
#> Linking to GEOS 3.12.1, GDAL 3.8.4, PROJ 9.3.1; sf_use_s2() is TRUE
start_point <- st_sfc(st_point(c(-78.338, 38.979)), crs = 4269)
trace <- get_raindrop_trace(start_point)
snap_point <- st_sfc(st_point(trace$intersection_point[[1]]),
crs = 4326)
basin <- get_split_catchment(snap_point, upstream = TRUE)
plot(basin$geometry[2])
Created on 2024-08-01 with reprex v2.1.1
I am trying to delineate a catchment basin from a provided pour point using the function
get_split_catchment()
. The function correctly delineates the COMID associated with the pour point however, it seems to stop running when it runs into the next upstream COMID. The ideal output would be a delineated basin for the entire upstream area of the provided pour point.Example
Created on 2024-07-31 with reprex v2.1.1
Created on 2024-07-31 with reprex v2.1.1