Skip to content

Commit d4ee85c

Browse files
committed
Various flownet changes/fixes
1 parent 955f641 commit d4ee85c

5 files changed

Lines changed: 235 additions & 121 deletions

File tree

R/CreateFlownet.R

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#' @param readin readin indicates the maps to be used. If CreateFlowmet.R is run it's own, this should point to the template which references the maps(or values)
66
#' used for the various levels and statevars. Otherwise, if run inside of RHESSysPreprocess, readin will use the map data from world_gen.R,
77
#' Streams map, and other optional maps, still need to be specified.
8-
#' @param asp_list List of aspatial structure and inputs. Used internally
8+
#' @param asp_rules List of aspatial structure and inputs. Also can be path to rules file - must be used along with template input.
99
#' @param road_width >0, defaults to 1.
1010
#' @inheritParams RHESSysPreprocess
1111
#' @author Will Burke
@@ -15,7 +15,7 @@ CreateFlownet = function(flownet_name,
1515
readin = NULL,
1616
type = "raster",
1717
typepars = NULL,
18-
asp_list = NULL,
18+
asp_rules = NULL,
1919
streams = NULL,
2020
overwrite = FALSE,
2121
roads = NULL,
@@ -24,6 +24,7 @@ CreateFlownet = function(flownet_name,
2424
roofs = NULL,
2525
parallel = TRUE,
2626
make_stream = 4,
27+
skip_hillslope_check = FALSE,
2728
wrapper = FALSE) {
2829

2930
# ------------------------------ Read and check inputs ------------------------------
@@ -40,7 +41,9 @@ CreateFlownet = function(flownet_name,
4041

4142
if (!wrapper & is.character(readin)) { #if run outside of rhessyspreprocess.R, and if readin is character. readin is the template (and path)
4243
template_list = template_read(readin)
43-
map_info = template_list[[5]]
44+
template_clean = template_list[[1]] # template in list form
45+
var_names = template_list[[2]] # names of template vars
46+
map_info = template_list[[5]] # tables of maps and their inputs/names in the template
4447
cfmaps = rbind(map_info,c("cell_length","none"), c("streams","none"), c("roads","none"), c("impervious","none"),c("roofs","none"))
4548
} else if (wrapper | (!wrapper & is.matrix(readin))) { # map info is passsed directly from world gen - either in wrapper or outside of wrapper and readin is matrix
4649
cfmaps = readin
@@ -113,6 +116,18 @@ CreateFlownet = function(flownet_name,
113116
raw_impervious_data = NULL
114117
if (!is.null(impervious)) {raw_impervious_data = map_list[[cfmaps[cfmaps[,1] == "impervious",2]]]}
115118

119+
# read aspatial rules if needed
120+
if (!is.null(asp_rules) && is.character(asp_rules)) {
121+
asp_map = template_clean[[which(var_names == "asp_rule")]][3] # get rule map/value
122+
if (suppressWarnings(any(is.na(as.numeric(asp_map))))) { # if it's a map
123+
asp_map = gsub(".tif|.tiff","",asp_map)
124+
asp_mapdata = as.data.frame(readmap)[asp_map]
125+
} else if (suppressWarnings(all(!is.na(as.numeric(asp_map))))) { # if is a single number
126+
asp_mapdata = as.numeric(asp_map)
127+
}
128+
asp_rules = aspatial_patches(asprules = asp_rules, asp_mapdata = asp_mapdata)
129+
}
130+
116131
# ------------------------------ Make flownet list ------------------------------
117132
cat("Building flowtable")
118133
CF1 = make_flow_list(
@@ -127,18 +142,19 @@ CreateFlownet = function(flownet_name,
127142
road_width = road_width,
128143
cell_length = cell_length,
129144
parallel = parallel,
130-
make_stream = make_stream)
145+
make_stream = make_stream,
146+
skip_hillslope_check = skip_hillslope_check)
131147

132148
# ------------------------------ Multiscale routing/aspatial patches ------------------------------
133-
if (!is.null(asp_list)) {
149+
if (!is.null(asp_rules)) {
134150
if ("asp_rule" %in% notamap) {
135151
map_list[["asp_rule"]] = raw_basin_data
136152
map_list[["asp_rule"]][!is.na(map_list[["asp_rule"]])] = as.numeric(cfmaps[cfmaps[,1] == "asp_rule",2])
137153
#cfmaps = rbind(cfmaps, c("asp_rule", "asp_rule"))
138154
cfmaps[cfmaps[,1] == "asp_rule", 2] = "asp_rule"
139155
}
140156

141-
CF1 = multiscale_flow(CF1 = CF1, map_list = map_list, cfmaps = cfmaps, asp_list = asp_list)
157+
CF1 = multiscale_flow(CF1 = CF1, map_list = map_list, cfmaps = cfmaps, asp_list = asp_rules)
142158
}
143159

144160
# ---------- Flownet list to flow table file ----------

R/GIS_read.R

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,14 @@ GIS_read = function(maps_in, type, typepars, map_info = NULL, seq_patch_IDs = FA
9999
if (length(file) == 0) { # if there were no matches
100100
stop(paste("No file named:",name,"at path:",typepars))
101101
}
102+
if (length(file) > 1) { # ignore .xml files
103+
file = file[!grepl(".xml$",file)]
104+
}
102105
if (length(file) > 1) { # if multiple files, use tif preferentially
103106
file = file[grep(".tif$",file)]
107+
if (length(file) > 1) {
108+
file = file[grep(".tiff$",file)]
109+
}
104110
}
105111
if (length(file) > 1) { # if STILL multiple files, can only be one file for each name in maps_in
106112
stop(paste("multiple files containing name:",name,"check directory:",typepars))

R/RHESSysPreprocess.R

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
#' @param make_stream The maximum distance (cell lengths) away from an existing stream that a patch can be automatically coerced to be a stream.
3636
#' Setting to TRUE will include patches at any distance. This is needed for hillslope parallelization, as all hillslopes must have an outlet stream patch.
3737
#' Default is 4.
38+
#' @param skip_hillslope_check TRUE/FALSE to skip the recursive check for segmented hillslopes. Segmented hillslopes will break the routing, but the
39+
#' recursive check can trigger various recursion protections when hillslopes are large.
3840
#' @param wrapper internal argument to track if being run as all-in-one
3941
#' @seealso \code{\link[raster]{raster}}, \code{\link[RHESSysIOinR]{run_rhessys}}
4042
#' @author Will Burke
@@ -59,6 +61,7 @@ RHESSysPreprocess = function(template,
5961
fire_grid_out = FALSE,
6062
parallel = TRUE,
6163
make_stream = 4,
64+
skip_hillslope_check = FALSE,
6265
wrapper = TRUE) {
6366

6467
# ---------- Check Inputs ----------

R/make_flow_list.R

Lines changed: 73 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,18 @@
2020
#' @importFrom utils setTxtProgressBar
2121

2222
make_flow_list <- function(raw_patch_data,
23-
raw_patch_elevation_data,
24-
raw_hill_data,
25-
raw_basin_data,
26-
raw_zone_data,
27-
raw_slope_data,
28-
raw_stream_data,
29-
raw_road_data,
30-
cell_length,
31-
road_width = NULL,
32-
parallel,
33-
make_stream) {
23+
raw_patch_elevation_data,
24+
raw_hill_data,
25+
raw_basin_data,
26+
raw_zone_data,
27+
raw_slope_data,
28+
raw_stream_data,
29+
raw_road_data,
30+
cell_length,
31+
road_width = NULL,
32+
parallel,
33+
make_stream,
34+
skip_hillslope_check) {
3435

3536
# -------------------- Error checking and NULL handling --------------------
3637
if (cell_length <= 0) {stop("Cell length is <=0")}
@@ -258,8 +259,7 @@ make_flow_list <- function(raw_patch_data,
258259
}
259260

260261

261-
262-
find_connected = function(patch_borders, start, history = NULL, found = NULL, missing, hill) {
262+
find_connected = function(patch_borders, start, history = NULL, found = NULL, missing, hill, itr_ct = NULL, itr_max = 10000) {
263263
# add start to found, only for first itr tho
264264
if (is.null(history)) {
265265
found = start
@@ -268,6 +268,7 @@ make_flow_list <- function(raw_patch_data,
268268
history = c(history, start)
269269
# find the neighbors
270270
neighbors = names(patch_borders[[start]])[-1][names(patch_borders[[start]])[-1] %in% flw_struct[flw_struct$Hill == hill, "Number"]]
271+
neighbors = as.numeric(neighbors)
271272
# update the found vector to include those neighbors
272273
found = c(found, neighbors)
273274
# remove the found from missing
@@ -280,62 +281,81 @@ make_flow_list <- function(raw_patch_data,
280281
if (all(found %in% history)) {
281282
return(missing)
282283
}
284+
285+
if (!is.null(itr_ct)) {
286+
itr_ct = itr_ct + 1
287+
if (itr_ct == itr_max) {
288+
cat("Reached iteration limit of ",itr_max)
289+
return(list(missing, found, history, start))
290+
}
291+
}
292+
283293
# if we haven't found everything, keep iterating through found patches not in the history
284-
next_patch = as.numeric(found[!found %in% history][1])
294+
opts = as.numeric(found[!found %in% history])
295+
next_patch = opts[round(runif(1,min = 1, max = length(opts)))]
296+
#next_patch = as.numeric(found[!found %in% history][1])
297+
285298
find_connected(
286299
patch_borders = patch_borders,
287300
start = next_patch,
288301
history = history,
289302
found = found,
290303
missing = missing,
291-
hill = hill
304+
hill = hill,
305+
itr_ct = itr_ct,
306+
itr_max = itr_max
292307
)
293308
}
294309

295-
# check for segmented hillslopes - this is going to be so slow but oh well
296-
cat("Checking for segmented hillslopes")
297-
segmented_hills = NULL
298-
segmented_patch_ct = NULL
299-
segmented_patch_list = list()
300-
301-
pb = txtProgressBar(min = 0,max = length(unique(flw_struct$Hill)),style = 3)
302-
ct = 0
310+
if (!skip_hillslope_check) {
311+
# check for segmented hillslopes - this is going to be so slow but oh well
312+
cat("Checking for segmented hillslopes")
313+
segmented_hills = NULL
314+
segmented_patch_ct = NULL
315+
segmented_patch_list = list()
303316

304-
for (i in unique(flw_struct$Hill)) {
305-
ct = ct + 1
306-
setTxtProgressBar(pb,ct)
307-
# start from outlet
308-
min_patch = flw_struct[flw_struct$Hill == i,][min_hill_patch[min_hill_patch$hillID == i, "patch_ind"],]
309-
all_patches = flw_struct[flw_struct$Hill == i, "Number"]
317+
pb = txtProgressBar(min = 0,max = length(unique(flw_struct$Hill)),style = 3)
318+
ct = 0
310319

311-
missing = find_connected(
312-
patch_borders = patch_borders,
313-
start = min_patch$Number,
314-
history = NULL,
315-
found = NULL,
316-
missing = all_patches,
317-
hill = i
318-
)
320+
# for testing:
321+
i = unique(flw_struct$Hill)[4]
319322

320-
if (!is.null(missing)) {
321-
322-
segmented_hills = c(segmented_hills, i)
323-
segmented_patch_ct = c(segmented_patch_ct, length(missing))
324-
segmented_df = data.frame("Hillslope ID" = segmented_hills, "Segmented patch count" = segmented_patch_ct)
325-
segmented_patch_list[[as.character(i)]] = missing
326-
327-
warning(
328-
"One or more hillslopes are disconnected with segmented segmented patches and do not reach the outlet patch.\n",
329-
"This will lead to problems in your simulaion. See table below for hilslope IDs and segmented patch counts.\n",
330-
"Regenerate hillslopes with a higher threshold for accumulated upslope area to correct this.\n"
323+
for (i in unique(flw_struct$Hill)) {
324+
ct = ct + 1
325+
setTxtProgressBar(pb,ct)
326+
# start from outlet
327+
min_patch = flw_struct[flw_struct$Hill == i,][min_hill_patch[min_hill_patch$hillID == i, "patch_ind"],]
328+
all_patches = flw_struct[flw_struct$Hill == i, "Number"]
329+
330+
missing = find_connected(
331+
patch_borders = patch_borders,
332+
start = min_patch$Number,
333+
history = NULL,
334+
found = NULL,
335+
missing = all_patches,
336+
hill = i,
337+
itr_ct = 0,
338+
itr_max = length(all_patches)
331339
)
332-
print(segmented_df)
333-
#error("")
334340

335-
}
341+
if (!is.null(missing)) {
342+
segmented_hills = c(segmented_hills, i)
343+
segmented_patch_ct = c(segmented_patch_ct, length(missing))
344+
segmented_df = data.frame("Hillslope ID" = segmented_hills, "Segmented patch count" = segmented_patch_ct)
345+
segmented_patch_list[[as.character(i)]] = missing
346+
warning(
347+
"One or more hillslopes are disconnected with segmented segmented patches and do not reach the outlet patch.\n",
348+
"This will lead to problems in your simulaion. See table below for hilslope IDs and segmented patch counts.\n",
349+
"Regenerate hillslopes with a higher threshold for accumulated upslope area to correct this.\n"
350+
)
351+
print(segmented_df)
352+
#error("")
353+
354+
}
336355

337-
} # end for segmented hills
338-
close(pb)
356+
} # end for segmented hills
357+
close(pb)
358+
}
339359

340360

341361
} # end parallel if

0 commit comments

Comments
 (0)