Section 6 Landuse Parameterization
This section covers the modifications made to the landuse file. For some reason it was written in a tutorial fashion, as if the reader were new to R.
require(tidyverse)
require(reshape2)
require(sf)
require(DT)
require(dplyr) # require dplyr last to overwrite plyr count()
require(ggplot2)
ggplot theme(s):
sf_theme <- theme(axis.text.x=element_blank(), #remove x axis labels
axis.ticks.x=element_blank(), #remove x axis ticks
axis.text.y=element_blank(), #remove y axis labels
axis.ticks.y=element_blank() #remove y axis ticks
)
6.1 Data preperation
We read in the land use file. We want to set skip = 1
to ignore the
SWAT+editor text, and set header = T
. We then convert it to a tibble
format for better printing to console
landuse_lum <-
read.table("model_data/cs10_setup/swat_input/landuse.lum", skip = 1, header = T) %>% tibble::as_tibble()
## # A tibble: 6 × 14
## name cal_group plnt_com mgt cn2 cons_prac urban urb_ro ov_mann tile
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 a_001f_1_… null nopl_co… null null null null null null mw24…
## 2 a_001f_2_… null nopl_co… null null null null null null mw24…
## 3 a_001f_3_… null nopl_co… null null null null null null mw24…
## 4 a_001f_4_… null nopl_co… null null null null null null mw24…
## 5 a_001f_5_… null nopl_co… null null null null null null mw24…
## 6 a_001f_6_… null nopl_co… null null null null null null mw24…
## # ℹ 4 more variables: sep <chr>, vfs <chr>, grww <chr>, bmp <chr>
Our field_id
for our cropland does not match name
of landuse_lum
so we need to parse it out, we can do this many ways, but a safe way is
to split it by “_” and combine the first 3 splits with that same
underscore:
splitted <- landuse_lum$name %>% str_split("_")
landuse_lum$field_id <-
paste(splitted %>% map(1), splitted %>% map(2), splitted %>% map(3), sep = "_")
head(landuse_lum$field_id)
## [1] "a_001f_1" "a_001f_2" "a_001f_3" "a_001f_4" "a_001f_5" "a_001f_6"
But wait, this does not work for our “non-fields”. So lets find out
which ones they are, and set them to NA
So, what non-fields do we have?
## [1] "frst_lum" "past_lum" "rngb_lum" "urml_lum" "utrn_lum" "wetf_lum"
Good to know. We’ll keep that in mind.
6.2 Assigning landuse values
6.2.1 Setting cal_group
There is no info on this column, so we are going to leave it as null
. Dicussion in Issue #18
6.2.4 Setting urb_ro
We want to set the urb_ro
column for all urban land uses (in our case
this would be urml
and utrn
) to usgs_reg
.
This has been discussed in Issue #6
We can do this like so:
## # A tibble: 2 × 15
## name cal_group plnt_com mgt cn2 cons_prac urban urb_ro ov_mann tile
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 urml_lum null null null null null null usgs_reg null null
## 2 utrn_lum null null null null null null usgs_reg null null
## # ℹ 5 more variables: sep <chr>, vfs <chr>, grww <chr>, bmp <chr>,
## # field_id <chr>
Very good. In our case this was only two – could be done by hand, but that will not be the case for all of our land uses.
6.2.5 Setting urban
This one is easy, we set our urban
column to an urban parameter set of
the same name. The rest we leave as null
This has been discussed in Issue #5
landuse_lum$urban[which(landuse_lum$name =="utrn_lum")] <- "utrn"
landuse_lum$urban[which(landuse_lum$name =="urml_lum")] <- "urml"
## # A tibble: 1 × 15
## name cal_group plnt_com mgt cn2 cons_prac urban urb_ro ov_mann tile
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 urml_lum null null null null null urml usgs_reg null null
## # ℹ 5 more variables: sep <chr>, vfs <chr>, grww <chr>, bmp <chr>,
## # field_id <chr>
Lets make sure other land uses still have null
:
## # A tibble: 1 × 15
## name cal_group plnt_com mgt cn2 cons_prac urban urb_ro ov_mann tile
## <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
## 1 frst_lum null nopl_comm null null null null null null null
## # ℹ 5 more variables: sep <chr>, vfs <chr>, grww <chr>, bmp <chr>,
## # field_id <chr>
Looks good.
6.2.6 Setting Manning’s n (ovn
)
This has been discussed in Issue #13
Lets get the easy ones out of the way
landuse_lum$ov_mann[which(landuse_lum$name =="past_lum")] <- "densegrass"
landuse_lum$ov_mann[which(landuse_lum$name =="rngb_lum")] <- "rangeland_20cover"
landuse_lum$ov_mann[which(landuse_lum$name =="urml_lum")] <- "urban_rubble"
landuse_lum$ov_mann[which(landuse_lum$name =="urtn_lum")] <- "urban_asphalt"
Don’t fall asleep yet! For wetf
we want forest_heavy
but with a
higher value. this means we need to add a new entry. And since we are
doing this fancy Rmarkdown stuff, we’re going to do it with code! Lets
jump in and get at this file. (REMEBER TO REMOVE THE TEMP)
ovn_table_path <- "model_data/cs10_setup/swat_input/ovn_table.lum"
ovn_table_path_new <- "model_data/cs10_setup/swat_input_mod/ovn_table.lum"
ovn_table <- readLines(ovn_table_path)
Good, now where is this forest heavy entry? and what does the format look like?
## [1] "name ovn_mean ovn_min ovn_max description"
## [2] "forest_heavy 0.80000 0.70000 0.90000 Forest_heavy"
Now, lets make our own and add it in. But only if it doesn’t exist it (Like if the script has been run before…)
if(grepl(x = ovn_table, "forest_heavy_cs10") %>% which %>% length() == 0) {
entry <-
"forest_heavy_cs10 0.90000 0.80000 0.95000 Forest_heavy_mod"
ovn_table <- c(ovn_table, entry)
}
Did it work? Yes:
## [1] "forest_med 0.60000 0.50000 0.70000 Forest_medimum_good"
## [2] "forest_heavy 0.80000 0.70000 0.90000 Forest_heavy"
## [3] "urban_asphalt 0.01100 0.01100 0.01100 Urban_asphalt"
## [4] "urban_concrete 0.01200 0.01200 0.01200 Urban_concrete"
## [5] "urban_rubble 0.02400 0.02400 0.02400 Urban_rubble"
## [6] "forest_heavy_cs10 0.90000 0.80000 0.95000 Forest_heavy_mod"
Now lets write this new table
And now we can enter our wetland class:
For the fields we are going to need the crop rotation info which we created in section ??.
crop_rotation <- read_csv("model_data/input/crop/cs10_crop_rotation.csv",
show_col_types = F)
head(crop_rotation)
## # A tibble: 6 × 5
## field y_2016 y_2017 y_2018 y_2019
## <chr> <chr> <chr> <chr> <chr>
## 1 a_025f_1 wwht wwht wwht wwht
## 2 a_025f_3 wwht wwht wwht wwht
## 3 a_025f_4 wwht wwht wwht wwht
## 4 a_025f_2 wwht wwht wwht wwht
## 5 a_105f_1 wwht wwht wwht wwht
## 6 a_105f_4 wwht wwht wwht wwht
We have decided to classify ovn
based on the degree to which a crop
rotation contains meadow
, conventional crops (wwht
, pota
), and
conservation crops (all others). To do this we need to analyze the crop
rotation.
Now it gets a little complicated, but trust me its not actually as bad as it looks. We need to count how many times certain crops show up in the crop rotation of a certain field. Lets do it for conventional crops first.
Now, lets get into it
conv_crop_count <- crop_rotation %>% melt(. ,"field") %>% group_by(field) %>%
filter(value %in% c("wwht", "pota")) %>% dplyr::count() %>% dplyr::rename(conv = n)
head(conv_crop_count)
## # A tibble: 6 × 2
## # Groups: field [6]
## field conv
## <chr> <int>
## 1 a_001f_1 4
## 2 a_001f_2 4
## 3 a_001f_3 4
## 4 a_001f_4 4
## 5 a_001f_5 4
## 6 a_001f_6 4
What happened here? well we took our crop_rotation
, and melted it by
field
using melt
. This function converts the data into tidy
format (Wickham 2014). This
format makes it easier to apply the following operations on a field
basis. What does this look like?
## field variable value
## 1 a_001f_1 y_2016 wwht
## 2 a_001f_1 y_2017 wwht
## 3 a_001f_1 y_2018 wwht
## 4 a_001f_1 y_2019 wwht
## 5 a_001f_2 y_2016 wwht
## 6 a_001f_2 y_2017 wwht
melt
is a function from reshape2
which is why we required
it. And
what does that “.
” mean in there, to the left of "field"
?? That is a
code word for the object to the left of the “pipe” (in this case
crop_rotation
). the pipe is “%>%
” and passes the object to the left
of it, into the function to the right of it. look it
up!
When arranged
by field, we can see that every field gets one entry per
crop per year. This is a good format to count how many times we have a
certain type of crop on a field.
Next we group_by
the field
– this means all the following
operations will be done on a field basis. Then we filter our value
(which is the crop name). For conventional we needed to filter in any
fields with the crop "wwht"
or "pota"
.
What does this look like?
## # A tibble: 1,519 × 3
## # Groups: field [415]
## field variable value
## <chr> <fct> <chr>
## 1 a_025f_1 y_2016 wwht
## 2 a_025f_3 y_2016 wwht
## 3 a_025f_4 y_2016 wwht
## 4 a_025f_2 y_2016 wwht
## 5 a_105f_1 y_2016 wwht
## 6 a_105f_4 y_2016 wwht
## 7 a_105f_2 y_2016 wwht
## 8 a_105f_3 y_2016 wwht
## 9 a_187f_1 y_2016 wwht
## 10 a_206f_1 y_2016 wwht
## # ℹ 1,509 more rows
Looks good. We only have crops with winter wheat and potatoes, for every
year. Exactly what we need, now we just need to count()
them.
conv_crop_count <- crop_rotation %>% melt(. ,"field") %>% group_by(field) %>%
filter(value %in% c("wwht", "pota")) %>% dplyr::count()
head(conv_crop_count)
## # A tibble: 6 × 2
## # Groups: field [6]
## field n
## <chr> <int>
## 1 a_001f_1 4
## 2 a_001f_2 4
## 3 a_001f_3 4
## 4 a_001f_4 4
## 5 a_001f_5 4
## 6 a_001f_6 4
And we are back where we started! See, not that complicated. One last
thing we need to do is rename n
to conv
, we do that like so:
conv_crop_count <- crop_rotation %>% melt(. ,"field") %>% group_by(field) %>%
filter(value %in% c("wwht", "pota")) %>% dplyr::count() %>% dplyr::rename(conv = n)
head(conv_crop_count)
## # A tibble: 6 × 2
## # Groups: field [6]
## field conv
## <chr> <int>
## 1 a_001f_1 4
## 2 a_001f_2 4
## 3 a_001f_3 4
## 4 a_001f_4 4
## 5 a_001f_5 4
## 6 a_001f_6 4
Now lets go ahead and do the same thing for the two other categories:
cons
andmeadow
.
meadow_crop_count <- crop_rotation %>% melt(. ,"field") %>% group_by(field) %>%
filter(value == "meadow" ) %>% dplyr::count() %>%
dplyr::rename(meadow = n)
cons_crop_count <- crop_rotation %>% melt(. ,"field") %>% group_by(field) %>%
filter(!(value %in% c("wwht", "pota", "meadow"))) %>% dplyr::count() %>%
dplyr::rename(cons = n)
cons_crop_count %>% head()
## # A tibble: 6 × 2
## # Groups: field [6]
## field cons
## <chr> <int>
## 1 a_002f_1 2
## 2 a_002f_2 2
## 3 a_002f_3 4
## 4 a_002f_4 4
## 5 a_002f_5 2
## 6 a_002f_6 4
## # A tibble: 6 × 2
## # Groups: field [6]
## field meadow
## <chr> <int>
## 1 a_012f_3 4
## 2 a_012f_6 4
## 3 a_016f_3 4
## 4 a_017f_2 4
## 5 a_017f_3 4
## 6 a_046f_1 4
meadow
was a simple filter, all we have to do was grab crops with the
meadow
name. For cons
crops, we just grabbed the remaining crops
that were not conv
or meadow
.
Great. We have these 3 separate, we need to combine them. we can do that
with left_join
and join by the field
column which contains our IDs
# create a base dataframe to join to
crop_fractions <- crop_rotation %>% dplyr::select(field) %>% distinct()
# join our 3 data frames
crop_fractions <- left_join(crop_fractions, conv_crop_count, by = "field")
crop_fractions <- left_join(crop_fractions, cons_crop_count, by = "field")
crop_fractions <- left_join(crop_fractions, meadow_crop_count, by = "field")
# lets have a look
crop_fractions %>% head()
## # A tibble: 6 × 4
## field conv cons meadow
## <chr> <int> <int> <int>
## 1 a_025f_1 4 NA NA
## 2 a_025f_3 4 NA NA
## 3 a_025f_4 4 NA NA
## 4 a_025f_2 4 NA NA
## 5 a_105f_1 4 NA NA
## 6 a_105f_4 4 NA NA
That does not look good! when it seems like when the count
is 0, it is
returned as NA
. Lets fix that…
crop_fractions <- crop_fractions %>%
mutate(cons = ifelse(is.na(cons), 0, cons))
crop_fractions <- crop_fractions %>%
mutate(conv = ifelse(is.na(conv), 0, conv))
crop_fractions <- crop_fractions %>%
mutate(meadow = ifelse(is.na(meadow), 0, meadow))
What are we doing here? we are mutating
the the 3 columns using an
ifelse
statement. The statement is simple. If the value is.na
then
we set it to 0
. Otherwise, we set it to the same value it had before.
did it work?
## # A tibble: 6 × 4
## field conv cons meadow
## <chr> <dbl> <dbl> <dbl>
## 1 a_025f_1 4 0 0
## 2 a_025f_3 4 0 0
## 3 a_025f_4 4 0 0
## 4 a_025f_2 4 0 0
## 5 a_105f_1 4 0 0
## 6 a_105f_4 4 0 0
Very good. Now we need to decide what to classify our fields at. lets
Define some functions
to do that.
is_meadow <- function(conv, cons, meadow) {
((meadow > cons) & (meadow > conv)) %>% return()
}
is_cons <- function(conv, cons, meadow) {
((cons >= meadow) & (cons > conv)) %>% return()
}
is_conv <- function(conv, cons, meadow) {
((conv >= meadow) & (conv >= cons)) %>% return()
}
The &
sign means that both conditions need to be met. and >=
you
should know already. Lets use those functions in action. lets do the
meadow first. We will create a new dataframe from crop fractions, named
field_class
.
## # A tibble: 6 × 4
## field conv cons meadow
## <chr> <dbl> <dbl> <lgl>
## 1 a_025f_1 4 0 FALSE
## 2 a_025f_3 4 0 FALSE
## 3 a_025f_4 4 0 FALSE
## 4 a_025f_2 4 0 FALSE
## 5 a_105f_1 4 0 FALSE
## 6 a_105f_4 4 0 FALSE
Ok, so none of those first 6 fields are meadow
dominated. What about
cons
? (lets stick with our field_class
dataframe and just keep
adding on)
## # A tibble: 6 × 4
## field conv cons meadow
## <chr> <dbl> <lgl> <lgl>
## 1 a_025f_1 4 FALSE FALSE
## 2 a_025f_3 4 FALSE FALSE
## 3 a_025f_4 4 FALSE FALSE
## 4 a_025f_2 4 FALSE FALSE
## 5 a_105f_1 4 FALSE FALSE
## 6 a_105f_4 4 FALSE FALSE
Nope, not cons
either. Then it must be conv
dominant.
## # A tibble: 6 × 4
## field conv cons meadow
## <chr> <lgl> <lgl> <lgl>
## 1 a_025f_1 TRUE FALSE FALSE
## 2 a_025f_3 TRUE FALSE FALSE
## 3 a_025f_4 TRUE FALSE FALSE
## 4 a_025f_2 TRUE FALSE FALSE
## 5 a_105f_1 TRUE FALSE FALSE
## 6 a_105f_4 TRUE FALSE FALSE
Correct! now lets just double check that we didnt have any cases where
all
are TRUE
or where all
are FALSE
## [1] FALSE
## [1] FALSE
Looks good to me! carry on:
We have our field classifications now, they will be very useful to us
later. Lets pull
them out of our dataframe to store them as a nice
list
.
cons_fields <- field_class %>% filter(cons) %>% dplyr::select(field) %>% pull()
conv_fields <- field_class %>% filter(conv) %>% dplyr::select(field) %>% pull()
meadow_fields <- field_class %>% filter(meadow) %>% dplyr::select(field) %>% pull()
cons_fields %>% head()
## [1] "a_182f_1" "a_182f_5" "a_182f_3" "a_182f_4" "a_182f_2" "a_182f_7"
## [1] "a_025f_1" "a_025f_3" "a_025f_4" "a_025f_2" "a_105f_1" "a_105f_4"
## [1] "a_182f_6" "a_182f_8" "a_017f_3" "a_017f_2" "a_012f_3" "a_012f_6"
Fantastic! Now that was a big task, but it makes the next bit very easy.
Lets assign the correct ovn
to the types of fields we have classified:
6.2.6.4 Forest
Initially we wanted certain classes for the forest land use based on how
good the soil quality was. But to do this, we would need multiple land
uses, which we do not have. We will just use forest_medium
for all
frst
. We can only change this if we go back to buildR
and define
more generic forest classes.
6.2.6.5 Summary
With all that data processing out of the way, lets have a quick look at what we’ve done:
landuse_lum$ov_mann[which(landuse_lum$name == "past_lum")] <-
"densegrass"
landuse_lum$ov_mann[which(landuse_lum$name == "rngb_lum")] <-
"rangeland_20cover"
landuse_lum$ov_mann[which(landuse_lum$name == "urml_lum")] <-
"urban_rubble"
landuse_lum$ov_mann[which(landuse_lum$name == "urtn_lum")] <-
"urban_asphalt"
landuse_lum$ov_mann[which(landuse_lum$name == "frst_lum")] <-
"forest_med"
landuse_lum$ov_mann[which(landuse_lum$field_id %in% meadow_fields)] <-
"shortgrass"
landuse_lum$ov_mann[which(landuse_lum$field_id %in% conv_fields)] <-
"convtill_nores"
landuse_lum$ov_mann[which(landuse_lum$field_id %in% cons_fields)] <-
"falldisk_res"
landuse_lum$ov_mann[which(landuse_lum$name == "wetf_lum")] <-
"forest_heavy_cs10"
Sweet. Next column..
6.2.7 Setting cn2
:
This has been discussed in Issue Issue #1
You know the drill – I am sure you know how to read this code by now.
# Brush-brush-weed-grass_mixture_with_brush_the_major_element (poor)
landuse_lum$cn2[which(landuse_lum$name == "rngb_lum")] <- "brush_p"
# Woods (poor)
landuse_lum$cn2[which(landuse_lum$name == "wetf_lum")] <- "wood_p"
# Paved_streets_and_roads;_open_ditches_(incl._right-of-way)
landuse_lum$cn2[which(landuse_lum$name == "utrn_lum")] <- "paveroad"
# Paved_parking_lots_roofs_driveways_etc_(excl_right-of-way)
landuse_lum$cn2[which(landuse_lum$name == "urml_lum")] <- "urban"
# Woods (fair)
landuse_lum$cn2[which(landuse_lum$name == "frst_lum")] <- "wood_f"
# Pasture_grassland_or_range-continuous_forage_for_grazing
landuse_lum$cn2[which(landuse_lum$name == "past_lum")] <- "pastg_g"
# Meadow-continuous_grass_protected_from_grazing_mowed_for_hay
landuse_lum$cn2[which(landuse_lum$field_id %in% meadow_fields)] <-
"pasth"
# Row_crops
landuse_lum$cn2[which(landuse_lum$field_id %in% cons_fields)] <-
"rc_conterres_g"
# Row_crops
landuse_lum$cn2[which(landuse_lum$field_id %in% conv_fields)] <-
"rc_strow_p"
6.2.8 Setting cons_prac
This has been discussed in Issue #4
For this, we need to add some custom entries to the database:
cons_prac_path <- "model_data/cs10_setup/swat_input/cons_practice.lum"
cons_prac_path_new <- "model_data/cs10_setup/swat_input_mod/cons_practice.lum"
cons_prac <- readLines(cons_prac_path)
cons_prac[1:3] %>% print()
## [1] "cons_practice.lum: written by SWAT+ editor v2.1.0 on 2023-05-30 10:39 for SWAT+ rev.60.5.4"
## [2] "name usle_p slp_len_max description"
## [3] "up_down_slope 1.00000 121.00000 Up_and_down_slope"
Let us do it in a way so that it is only added if it doesn’t exist yet:
if(grepl(x = cons_prac, "agri_conv") %>% which %>% length() == 0) {
entry <-
"agri_conv 1.00000 60.00000 no_convervation"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "agri_part_conv") %>% which %>% length() == 0) {
entry <-
"agri_part_conv 0.85000 60.00000 75_percent_convential"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "agri_half") %>% which %>% length() == 0) {
entry <-
"agri_half 0.70000 50.00000 50_percent_convential"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "agri_part_cons") %>% which %>% length() == 0) {
entry <-
"agri_part_cons 0.50000 30.00000 75_percent_consveration"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "agri_cons") %>% which %>% length() == 0) {
entry <-
"agri_cons 0.30000 30.00000 100_percent_consveration"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "past_cons") %>% which %>% length() == 0) {
entry <-
"past_cons 0.1 60 pasture"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "rngb_cons") %>% which %>% length() == 0) {
entry <-
"rngb_cons 0.2 60 rangeland"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "frst_cons") %>% which %>% length() == 0) {
entry <-
"frst_cons 0.1 60 forest"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "urml_cons") %>% which %>% length() == 0) {
entry <-
"urml_cons 1 60 cs10urban"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "utrn_cons") %>% which %>% length() == 0) {
entry <-
"utrn_cons 1 60 road"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "cs10_meadow") %>% which %>% length() == 0) {
entry <-
"cs10_meadow 0.2 60 cs10_meadow"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "wetf_cons") %>% which %>% length() == 0) {
entry <-
"wetf_cons 0.05 30 wetlands"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "cs10_sed_pond") %>% which %>% length() == 0) {
entry <-
"cs10_sed_pond 0.1 30 cs10_sed_pond"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "cs10_cons_wetl") %>% which %>% length() == 0) {
entry <-
"cs10_cons_wetl 0.1 30 cs10_cons_wetl"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "cs10_buff_grass") %>% which %>% length() == 0) {
entry <-
"cs10_buff_grass 0.25 10 cs10_buff_grass"
cons_prac <- c(cons_prac, entry)
}
if (grepl(x = cons_prac, "cs_10_buff_wood") %>% which %>% length() == 0) {
entry <-
"cs_10_buff_wood 0.2 10 cs_10_buff_wood"
cons_prac <- c(cons_prac, entry)
}
And write the updated file:
Now we need to define the 0, 25, 50, 75, 100 percent conventional crops. We can use our old “crop_fractions” dataframe:
## # A tibble: 6 × 4
## field conv cons meadow
## <chr> <dbl> <dbl> <dbl>
## 1 a_025f_1 4 0 0
## 2 a_025f_3 4 0 0
## 3 a_025f_4 4 0 0
## 4 a_025f_2 4 0 0
## 5 a_105f_1 4 0 0
## 6 a_105f_4 4 0 0
Lets derive which fields get classified as what
p100_conv <- crop_fractions %>% filter(conv==4) %>% dplyr::select(field) %>% pull()
p75_conv <- crop_fractions %>% filter(conv==3) %>% dplyr::select(field) %>% pull()
p50_conv <- crop_fractions %>% filter(conv==2) %>% dplyr::select(field) %>% pull()
p25_conv <- crop_fractions %>% filter(conv==1) %>% dplyr::select(field) %>% pull()
p0_conv <- crop_fractions %>% filter(conv==0) %>% dplyr::select(field) %>% pull()
Now we can assign the all the land uses
# Agricultural
landuse_lum$cons_prac[which(landuse_lum$field_id %in% p100_conv)] <-
"agri_conv"
landuse_lum$cons_prac[which(landuse_lum$field_id %in% p75_conv)] <-
"agri_part_conv"
landuse_lum$cons_prac[which(landuse_lum$field_id %in% p50_conv)] <-
"agri_half"
landuse_lum$cons_prac[which(landuse_lum$field_id %in% p25_conv)] <-
"agri_part_cons"
landuse_lum$cons_prac[which(landuse_lum$field_id %in% p0_conv)] <-
"agri_cons"
# Meadow
landuse_lum$cons_prac[which(field_class$meadow)] <-
"cs10_meadow"
# Generic
landuse_lum$cons_prac[which(landuse_lum$name == "past_lum")] <-
"past_cons"
landuse_lum$cons_prac[which(landuse_lum$name == "rngb_lum")] <-
"rngb_cons"
landuse_lum$cons_prac[which(landuse_lum$name == "frst_lum")] <-
"frst_cons"
landuse_lum$cons_prac[which(landuse_lum$name == "urml_lum")] <-
"urml_cons"
landuse_lum$cons_prac[which(landuse_lum$name == "utrn_lum")] <-
"utrn_cons"
landuse_lum$cons_prac[which(landuse_lum$name == "wetf_lum")] <-
"wetf_cons"
# Measures
landuse_lum$cons_prac[which(landuse_lum$name == "cs10_sed_pond")] <-
"cs10_sed_pond"
landuse_lum$cons_prac[which(landuse_lum$name == "cs10_cons_wetl")] <-
"cs10_cons_wetl"
landuse_lum$cons_prac[which(landuse_lum$name == "cs10_buff_grass")] <-
"cs10_buff_grass"
landuse_lum$cons_prac[which(landuse_lum$name == "cs_10_buff_wood")] <-
"cs_10_buff_wood"
6.2.9 Setting tile
This column has already been completed by SWATbuildR
in
2.4
6.2.10 Setting sep
This column has been left as null
as discussed in Issue #9
6.2.11 Setting vfs
This column has been left as null
as discussed in Issue #10
6.2.12 Setting grww
This column has been left as null
as discussed in Issue #11
6.2.13 Setting bmp
This column has been left as null
as discussed in Issue #12
6.3 Writing Changes
We are done with our modifications however, we need to remove the
field_id
column
lets take a look at the final product:
Lets write out changes in a new directory where we will store any SWAT+ input files which we have modified from their source BuildR form.
dir.create("model_data/cs10_setup/swat_input_mod", showWarnings = F)
new_lum_path <- "model_data/cs10_setup/swat_input_mod/landuse.lum"
write.table(landuse_lum, file = new_lum_path, sep = "\t", quote = F, row.names = F)
But wait – we need to keep that pesky header, otherwise the FarmR will be very angry with us.
lum_lines <- readLines(new_lum_path)
header <- "header header HEADER, delete me and you will regret it FOREVER!"
lum_lines2<- c(header,lum_lines)
writeLines(text = lum_lines2, con = new_lum_path)
Done!
Now that We’ve changed another input file, we should test if our model still
runs. We will do that with our custom test_swat_mod()
function. This function
is basically the same as the previous test_swat()
function, only that it
incorporates the modified SWAT input files
Related Milestone
Related minor issues
Don’t write rownames! - #50
Update the land use file - #40