From 3ec3cd6a5a1424a04d8acdbb6a9c986f043f8372 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Christoph=20Sch=C3=BCrz?= <christoph.schuerz@ufz.de>
Date: Mon, 12 Dec 2022 20:41:26 +0100
Subject: [PATCH] Add function to get overview of triggered management

---
 DESCRIPTION         |   2 +-
 NAMESPACE           |   6 ++-
 R/plot_mgt_harv.R   |   1 +
 R/print_mgt.R       | 103 ++++++++++++++++++++++++++++++++++++++++++++
 R/run_swat_verify.R |  50 ++++++++++++++++++++-
 man/read_sch.Rd     |  15 +++++++
 6 files changed, 174 insertions(+), 3 deletions(-)
 create mode 100644 man/read_sch.Rd

diff --git a/DESCRIPTION b/DESCRIPTION
index 7861527..30fdd8b 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,7 +1,7 @@
 Package: SWATdoctR
 Type: Package
 Title: Finding the right diagnoses and treatments for SWAT+ models
-Version: 0.1.1
+Version: 0.1.2
 Author: c(person("Svajunas", "Plunge",
              email = "svajunas_plunge@sggw.edu.pl",
              role = c("aut")),
diff --git a/NAMESPACE b/NAMESPACE
index d80c339..88abee4 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -38,12 +38,17 @@ importFrom(lubridate,year)
 importFrom(lubridate,ymd)
 importFrom(processx,run)
 importFrom(purrr,map)
+importFrom(purrr,map2)
 importFrom(purrr,map2_chr)
+importFrom(purrr,map2_df)
+importFrom(purrr,map_chr)
 importFrom(purrr,map_df)
+importFrom(purrr,map_int)
 importFrom(purrr,set_names)
 importFrom(readr,read_lines)
 importFrom(readr,write_lines)
 importFrom(stringr,str_replace)
+importFrom(stringr,str_replace_all)
 importFrom(stringr,str_split)
 importFrom(stringr,str_sub)
 importFrom(stringr,str_trim)
@@ -51,4 +56,3 @@ importFrom(tibble,as_tibble)
 importFrom(tibble,tibble)
 importFrom(tidyr,pivot_longer)
 importFrom(tidyselect,all_of)
-importFrom(vroom,vroom_lines)
diff --git a/R/plot_mgt_harv.R b/R/plot_mgt_harv.R
index a812c44..81f7af1 100644
--- a/R/plot_mgt_harv.R
+++ b/R/plot_mgt_harv.R
@@ -16,6 +16,7 @@
 #' @importFrom dplyr filter group_by mutate n rename select ungroup %>%
 #' @importFrom ggplot2 aes ggplot geom_boxplot geom_hline labs theme_bw
 #' @importFrom purrr set_names
+#'
 #' @export
 #'
 plot_variable_at_harvkill <- function(sim_verify, variable, years = 1900:2100) {
diff --git a/R/print_mgt.R b/R/print_mgt.R
index 9de813d..f6742aa 100644
--- a/R/print_mgt.R
+++ b/R/print_mgt.R
@@ -15,6 +15,7 @@
 #' @return Prints a tibble with triggered operations to the R console.
 #'
 #' @importFrom dplyr filter mutate rename select %>%
+#'
 #' @export
 #'
 print_triggered_mgt <- function(sim_verify, hru_id, start_year = 1900, end_year = 2100) {
@@ -31,3 +32,105 @@ print_triggered_mgt <- function(sim_verify, hru_id, start_year = 1900, end_year
     select(., year, mon, day, phuplant, operation, op_data1, op_data3) %>%
     print(., n = Inf)
 }
+
+#' Generate a report table that compares the scheduled and triggered managements
+#'
+#' report_mgt compares the scheduled management operations for all schedules
+#' with the triggered management operations. Therefore HRUs are randomly
+#' selected for each schedule where one of the schedules is implemented.
+#'
+#' @param sim_verify Simulation output of the function \code{run_swat_verification()}.
+#'   To print the management at least the output option \code{outputs = 'mgt'} must
+#'   be set in  \code{run_swat_verification()}
+#'
+#' @return Returns a tibble that summarises all management schedules for
+#'   which operations where scheduled, that were either not triggered of
+#'   for which operation properties differ..
+#'
+#' @importFrom dplyr filter group_by group_split lead left_join mutate rename select slice_sample summarise %>%
+#' @importFrom purrr map
+#' @importFrom stringr str_sub
+#'
+#' @export
+#'
+report_mgt <- function(sim_verify) {
+  yr_start <- min(sim_verify$mgt_out$year)
+  mgt_lbl <- unique(sim_verify$lum_mgt$mgt)
+  mgt_lbl <- mgt_lbl[!is.na(mgt_lbl)]
+
+  schdl_mgt <- sim_verify$mgt_sch %>%
+    filter(schedule %in% mgt_lbl) %>%
+    filter(!is.na(op_typ)) %>%
+    group_by(schedule) %>%
+    mutate(rm_skp = lead(op_typ, 1),
+           rm_skp = ifelse(op_typ == 'skip' &
+                             rm_skp  != 'skip' |
+                             is.na(rm_skp), TRUE, FALSE)) %>%
+    filter(!rm_skp) %>%
+    select(-rm_skp) %>%
+    mutate(year = c(NA, diff(mon)),
+           year = ifelse(is.na(year) | year >= 0, 0, 1),
+           year = cumsum(year) + yr_start) %>%
+    ungroup(.)
+
+  mgt_lbl <- unique(schdl_mgt$schedule)
+
+  hru_sel <- sim_verify$lum_mgt %>%
+    filter(mgt %in% mgt_lbl) %>%
+    group_by(mgt) %>%
+    slice_sample(., n = 1)
+
+  mgt_i <- sim_verify$mgt_out %>%
+    filter(hru %in% hru_sel$id) %>%
+    left_join(., hru_sel, by = c('hru' = 'id')) %>%
+    rename(schedule = mgt,
+           op_typ = operation,
+           op_data1_trig = op_typ) %>%
+    select(., schedule, year, mon, day, op_typ, op_data1_trig) %>%
+    mutate(op_typ = str_sub(op_typ, 1, 4) %>%  tolower(.),
+           op_typ = ifelse(op_typ == 'plan', 'plnt', op_typ))
+
+  schdl_join <- left_join(schdl_mgt, mgt_i,
+                          by = c("schedule", "year",  "mon", "day", "op_typ")) %>%
+    select(schedule, year, mon, day, op_typ, op_data1_trig, starts_with('op_data')) %>%
+    mutate(op_issue = is.na(op_data1_trig) | op_data1_trig != op_data1,
+           year = year - yr_start + 1) %>%
+    filter(op_issue)
+
+  schdl_report <- schdl_join %>%
+    select(schedule, op_issue) %>%
+    group_by(schedule) %>%
+    summarise(op_issue = sum(op_issue),
+              .groups = 'drop')
+
+  ops_detail <- schdl_join %>%
+    group_by(schedule) %>%
+    group_split() %>%
+    map(., ~ filter(.x, op_issue)) %>%
+    map(., ~ select(.x, year, mon, day, op_typ, op_data1_trig, starts_with('op_data')))
+
+  schdl_report <- schdl_report %>%
+    mutate(schedule_report = ops_detail)
+
+  return(schdl_report)
+}
+
+
+#' Transform x to a matrix with 7 columns and fill up with NA values
+#'
+#' @param x character vector or NULL
+#'
+#' @keywords internal
+#'
+as_mtx_null <- function(x) {
+  if(is.null(x)) {
+    matrix(rep(NA_character_, 7), ncol = 7)
+  } else {
+    matrix(x, nrow = 7) %>%
+      t(.)
+  }
+}
+
+
+
+
diff --git a/R/run_swat_verify.R b/R/run_swat_verify.R
index d5f96a0..8624cb5 100644
--- a/R/run_swat_verify.R
+++ b/R/run_swat_verify.R
@@ -80,6 +80,7 @@ run_swat_verification <- function(project_path, outputs = c('wb', 'mgt', 'plt'),
     }
     if ('mgt' %in% outputs) {
       model_output$mgt_out <- read_mgt(run_path)
+      model_output$mgt_sch <- read_sch(run_path)
 
       hru_data <- read_tbl('hru-data.hru', run_path, 2)
       landuse_lum <- read_tbl('landuse.lum', run_path, 2)
@@ -203,9 +204,9 @@ read_tbl <- function(file, run_path, n_skip) {
 #'
 #' @importFrom dplyr %>%
 #' @importFrom purrr map map_df set_names
+#' @importFrom readr read_lines
 #' @importFrom stringr str_trim str_split
 #' @importFrom tibble as_tibble
-#' @importFrom vroom vroom_lines
 #'
 #' @keywords internal
 #'
@@ -231,6 +232,53 @@ read_mgt <- function(run_path) {
   return(mgt)
 }
 
+#' Read SWAT+ management schedule file and return the read file in a tibble
+#'
+#' @param run_path Path to the folder where simulations are performed
+#'
+#' @importFrom dplyr mutate %>%
+#' @importFrom purrr map map_int map_chr map2 map2_df map_df set_names
+#' @importFrom readr read_lines
+#' @importFrom stringr str_replace_all str_trim str_split
+#' @importFrom tibble as_tibble
+#'
+#' @keywords internal
+#'
+read_sch <- function(run_path) {
+  schdl_path <- paste0(run_path, '/management.sch')
+
+  schdl <- read_lines(schdl_path, skip = 2, lazy = FALSE) %>%
+    str_trim(.) %>%
+    str_replace_all(., '\t', ' ') %>%
+    str_split(., '[:space:]+')
+
+  n_elem <- map_int(schdl, length)
+  schdl <- schdl[n_elem != 1]
+  n_elem <- map_int(schdl, length)
+  schdl_def_pos <- which(n_elem == 3)
+
+  schdl_name <- map_chr(schdl_def_pos, ~ schdl[[.x]][1])
+
+  schdl_start <- schdl_def_pos + 1
+  schdl_end <- c(schdl_def_pos[2:length(schdl_def_pos)] - 1, length(schdl))
+  no_entry <- schdl_start > schdl_end
+  schdl_start[no_entry] <- length(schdl) + 1
+  schdl_end[no_entry] <- length(schdl) + 1
+  schdl_start[no_entry] <- 1e9
+  schdl_end[no_entry] <- 1e9
+
+  schdl_mgt <- map2(schdl_start, schdl_end, ~ schdl[.x:.y]) %>%
+    map(., unlist) %>%
+    map(., as_mtx_null) %>%
+    map(., ~ as_tibble(.x, .name_repair = 'minimal')) %>%
+    map(., ~ set_names(.x, c('op_typ', 'mon', 'day', 'hu_sch', paste0('op_data', 1:3)))) %>%
+    map2_df(., schdl_name, ~ mutate(.x, schedule = .y, .before = 1))
+
+  schdl_mgt[,c(3:5, 8)] <- map_df(schdl_mgt[,c(3:5, 8)], as.numeric)
+
+  return(schdl_mgt)
+}
+
 #' Generate folder structure for SWAT execution
 #'
 #' @param project_path Path to the SWAT project folder (i.e. TxtInOut)
diff --git a/man/read_sch.Rd b/man/read_sch.Rd
new file mode 100644
index 0000000..3f127b6
--- /dev/null
+++ b/man/read_sch.Rd
@@ -0,0 +1,15 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/run_swat_verify.R
+\name{read_sch}
+\alias{read_sch}
+\title{Read SWAT+ management schedule file and return the read file in a tibble}
+\usage{
+read_sch(run_path)
+}
+\arguments{
+\item{run_path}{Path to the folder where simulations are performed}
+}
+\description{
+Read SWAT+ management schedule file and return the read file in a tibble
+}
+\keyword{internal}
-- 
GitLab