From bd91dafe60d6996bb3c5a24ce5bb6b822043a72c Mon Sep 17 00:00:00 2001 From: f-delpu Date: Fri, 31 Jul 2026 11:56:53 +0200 Subject: [PATCH 1/7] Wip allow parameter override --- R/calculate_water_balance.R | 26 +++++-- R/frontend_helpers.R | 60 +++++++++++----- man/calculate_water_balance.Rd | 10 ++- man/get_measure_info.Rd | 12 +++- .../test-function-get_measures_config.R | 70 +++++++++++++++++-- 5 files changed, 142 insertions(+), 36 deletions(-) diff --git a/R/calculate_water_balance.R b/R/calculate_water_balance.R index 93728d5..ebd14dc 100644 --- a/R/calculate_water_balance.R +++ b/R/calculate_water_balance.R @@ -6,10 +6,17 @@ #' \code{code}. There is one numeric field per measure. The names of the #' measure-related fields must correspond to the \code{field_name}s returned #' by \code{\link{get_measure_info}}. +#' @param parameters optional. list of parameters for each measure as returned +#' by \code{\link{get_measure_info}(parameters_only = TRUE)}. #' @param convert_types logical value indicating whether or not to convert the #' data types in the \code{blocks} data frame as required by R-ABIMO. #' @export -calculate_water_balance <- function(blocks, measures, convert_types = FALSE) { +calculate_water_balance <- function( + blocks, + measures, + parameters = get_measure_info(parameters_only = TRUE), + convert_types = FALSE +) { #blocks <- kwb.smartwater::get_test_blocks() #measures <- kwb.smartwater::get_test_block_measures() @@ -28,7 +35,7 @@ calculate_water_balance <- function(blocks, measures, convert_types = FALSE) { } config <- kwb.rabimo:::reconfigure(kwb.rabimo::rabimo_inputs_2025$config) - config[["measures"]] <- get_measures_config() + config[["measures"]] <- get_measures_config(parameters) # Calculate water balance for natural state water_balance_natural <- kwb.rabimo::run_rabimo( @@ -234,17 +241,22 @@ add_delta_w <- function(water_balance, delta_w) { cbind(water_balance, delta_w = delta_w[["delta_w"]]) } -get_measures_config <- function() { +get_measures_config <- function(parameters = NULL) { lapply( X = stats::setNames(nm = c("green_roof", "infiltration", "retention")), FUN = function(type) { - abimo_parameters <- lapply(get_measure_info(type), function(x) { + parameters <- lapply(get_measure_info(type), function(x) { + input_column <- x[["field_name"]] c( - list(input_column = x[["field_name"]]), - x[["abimo_parameters"]] + list(input_column = input_column), + if (!is.null(parameters) && length(parameters[[input_column]])) { + parameters[[input_column]] + } else { + x[["parameters"]] + } ) }) - abimo_parameters[!sapply(abimo_parameters, is.null)] + parameters[!sapply(parameters, is.null)] } ) } diff --git a/R/frontend_helpers.R b/R/frontend_helpers.R index 057e0ee..9328d49 100644 --- a/R/frontend_helpers.R +++ b/R/frontend_helpers.R @@ -6,15 +6,22 @@ #' ("green_roof", "pavement", "trees", "infiltration", "retention") for which #' to filter the output. #' @param field_name_only optional. Logical of length one indicating whether or -#' not to return only the "field_name" instead of all info fields per measure +#' not to return only the "field_name" instead of all info fields per measure. +#' Default is FALSE. +#' @param parameters_only if TRUE only returns parameters for each measure. +#' Default is FALSE. #' @export -get_measure_info <- function(type = character(0), field_name_only = FALSE) { +get_measure_info <- function( + type = character(0), + field_name_only = FALSE, + parameters_only = FALSE +) { measures <- list( list( type = "green_roof", field_name = "green_roof_ext", long_name_de = "Extensive Dachbegr\u00fcnung", - abimo_parameters = list( + parameters = list( bagrov_value = 0.65 ) ), @@ -22,7 +29,7 @@ get_measure_info <- function(type = character(0), field_name_only = FALSE) { type = "green_roof", field_name = "green_roof_int", long_name_de = "Intensive Dachbegr\u00fcnung", - abimo_parameters = list( + parameters = list( bagrov_value = 0.75 ) ), @@ -39,23 +46,32 @@ get_measure_info <- function(type = character(0), field_name_only = FALSE) { list( type = "trees", field_name = "trees_sm", - long_name_de = "B\u00e4ume (klein)" + long_name_de = "B\u00e4ume (klein)", + parameters = list( + tree_volume = 200 + ) ), list( type = "trees", field_name = "trees_md", - long_name_de = "B\u00e4ume (mittel)" + long_name_de = "B\u00e4ume (mittel)", + parameters = list( + tree_volume = 300 + ) ), list( type = "trees", field_name = "trees_lg", - long_name_de = "B\u00e4ume (gro\u00df)" + long_name_de = "B\u00e4ume (gro\u00df)", + parameters = list( + tree_volume = 400 + ) ), list( type = "infiltration", field_name = "to_swale", # "to_inf_mulde" long_name_de = "Mulde", - abimo_parameters = list( + parameters = list( evaporation_factor = 0.1, overflow_factor = 0.05 ) @@ -64,7 +80,7 @@ get_measure_info <- function(type = character(0), field_name_only = FALSE) { type = "infiltration", field_name = "to_surf_infil", long_name_de = "Fl\u00e4chenversickerung", - abimo_parameters = list( + parameters = list( evaporation_factor = 0.15, overflow_factor = 0.15 ) @@ -73,7 +89,7 @@ get_measure_info <- function(type = character(0), field_name_only = FALSE) { type = "infiltration", field_name = "to_swale_trench", # "to_inf_mulde_rigole" long_name_de = "Mulden-Rigolen-Element", - abimo_parameters = list( + parameters = list( evaporation_factor = 0.08, overflow_factor = 0.1 ) @@ -82,7 +98,7 @@ get_measure_info <- function(type = character(0), field_name_only = FALSE) { type = "infiltration", field_name = "to_tree_pit", long_name_de = "Optimierter Baumstandort", - abimo_parameters = list( + parameters = list( evaporation_factor = 0.2, overflow_factor = 0.15 ) @@ -91,7 +107,7 @@ get_measure_info <- function(type = character(0), field_name_only = FALSE) { type = "infiltration", field_name = "to_trench", long_name_de = "Rigole", - abimo_parameters = list( + parameters = list( evaporation_factor = 0.15, overflow_factor = 0.15 ) @@ -100,7 +116,7 @@ get_measure_info <- function(type = character(0), field_name_only = FALSE) { type = "retention", field_name = "to_cistern", # "to_retention" long_name_de = "Zisterne", # (= Regentonne) - abimo_parameters = list( + parameters = list( overflow_factor = 0.5 ) ) @@ -109,6 +125,7 @@ get_measure_info <- function(type = character(0), field_name_only = FALSE) { collect <- function(x, field) { sapply(x, `[[`, field) } + # filter for type if type is given if (length(type) > 0L) { allowed_types <- unique(collect(measures, "type")) unknown_types <- setdiff(type, allowed_types) @@ -122,10 +139,15 @@ get_measure_info <- function(type = character(0), field_name_only = FALSE) { measures <- measures[collect(measures, "type") %in% type] } if (field_name_only) { - collect(measures, "field_name") - } else { - measures + return(collect(measures, "field_name")) + } + if (parameters_only) { + return(stats::setNames( + collect(measures, "parameters"), + collect(measures, "field_name") + )) } + measures } #' Get one block (columns as expected by kwb.rabimo) for testing @@ -183,7 +205,7 @@ rabimo_block_to_partial_areas_m2 <- function(block) { current <- cbind(current, as.data.frame(as.list( stats::setNames(rep(0, length(measures)), measures) ))) - + # recalculate `pvd`, `sealed`, `unsealed` current <- update_calculated_fields(current) @@ -257,10 +279,10 @@ apply_measure <- function(areas, measure) { if (!name %in% get_measure_info(field_name_only = TRUE)) { stop(sprintf("Measure '%s' not supported!", name)) } - + # Add the area of the measure to area that is already allocated to the measure areas[[name]] <- areas[[name]] + measure[["area"]] - + # Only measures related to paving need special treatment ("accordeon"): if (name == "unpaving") { diff --git a/man/calculate_water_balance.Rd b/man/calculate_water_balance.Rd index b72f8f3..ae736f0 100644 --- a/man/calculate_water_balance.Rd +++ b/man/calculate_water_balance.Rd @@ -4,7 +4,12 @@ \alias{calculate_water_balance} \title{Calculate Water Balance for Given Block Areas and Measures} \usage{ -calculate_water_balance(blocks, measures, convert_types = FALSE) +calculate_water_balance( + blocks, + measures, + parameters = get_measure_info(parameters_only = TRUE), + convert_types = FALSE +) } \arguments{ \item{blocks}{data.frame as returned by \code{\link{get_test_blocks}}} @@ -15,6 +20,9 @@ in m2. Each row refers to a block area, linked by the text field measure-related fields must correspond to the \code{field_name}s returned by \code{\link{get_measure_info}}.} +\item{parameters}{optional. list of parameters for each measure as returned +by \code{\link{get_measure_info}(parameters_only = TRUE)}.} + \item{convert_types}{logical value indicating whether or not to convert the data types in the \code{blocks} data frame as required by R-ABIMO.} } diff --git a/man/get_measure_info.Rd b/man/get_measure_info.Rd index 504b398..3d4e9c7 100644 --- a/man/get_measure_info.Rd +++ b/man/get_measure_info.Rd @@ -4,7 +4,11 @@ \alias{get_measure_info} \title{Get info on the measures supported by kwb.smartwater} \usage{ -get_measure_info(type = character(0), field_name_only = FALSE) +get_measure_info( + type = character(0), + field_name_only = FALSE, + parameters_only = FALSE +) } \arguments{ \item{type}{optional. Vector of character indicating the measure types @@ -12,7 +16,11 @@ get_measure_info(type = character(0), field_name_only = FALSE) to filter the output.} \item{field_name_only}{optional. Logical of length one indicating whether or -not to return only the "field_name" instead of all info fields per measure} +not to return only the "field_name" instead of all info fields per measure. +Default is FALSE.} + +\item{parameters_only}{if TRUE only returns parameters for each measure. +Default is FALSE.} } \description{ Get information on the rainwater management measures supported by diff --git a/tests/testthat/test-function-get_measures_config.R b/tests/testthat/test-function-get_measures_config.R index 3ee3575..1b0b4cf 100644 --- a/tests/testthat/test-function-get_measures_config.R +++ b/tests/testthat/test-function-get_measures_config.R @@ -1,13 +1,69 @@ -# -# This test file has been generated by kwb.test::create_test_files() -# launched by user hsonne on 2026-07-17 11:33:04.201605. -# Your are strongly encouraged to modify the dummy functions -# so that real cases are tested. You should then delete this comment. -# +#library(testthat) test_that("get_measures_config() works", { + + result <- kwb.smartwater:::get_measures_config() + + expect_true(is.list(result)) + expect_equal(names(result), c("green_roof", "infiltration", "retention")) - kwb.smartwater:::get_measures_config() +}) + +test_that("get_measures_config() accepts parameters to be overridden", { + + f <- kwb.smartwater:::get_measures_config + parameters <- get_measure_info(parameters_only = TRUE) + expect_identical(f(parameters), f()) + + parameters[[c("green_roof_ext", "bagrov_value")]] <- 0.75 + result <- f(parameters) + result$green_roof[[1]] }) + + +parameter_list <- '{ + "green_roof_ext": { + "bagrov_value": 0.65 + }, + "green_roof_int": { + "bagrov_value": 0.75 + }, + "permeable_paving": {}, + "unpaving": {}, + "trees_sm": { + "tree_volume": 200 + }, + "trees_md": { + "tree_volume": 300 + }, + "trees_lg": { + "tree_volume": 400 + }, + "to_swale": { + "evaporation_factor": 0.1, + "overflow_factor": 0.05 + }, + "to_surf_infil": { + "evaporation_factor": 0.15, + "overflow_factor": 0.15 + }, + "to_swale_trench": { + "evaporation_factor": 0.08, + "overflow_factor": 0.1 + }, + "to_tree_pit": { + "evaporation_factor": 0.2, + "overflow_factor": 0.15 + }, + "to_trench": { + "evaporation_factor": 0.15, + "overflow_factor": 0.15 + }, + "to_cistern": { + "overflow_factor": 0.5 + } +}' + +kwb.smartwater:::get_measures_config(parameter_list) From f9a9d6dc754a2f91ff433a76e7ec95f1bf4f3874 Mon Sep 17 00:00:00 2001 From: hsonne Date: Fri, 31 Jul 2026 12:09:23 +0200 Subject: [PATCH 2/7] Finish test and add one more --- .../test-function-get_measures_config.R | 60 ++++--------------- 1 file changed, 12 insertions(+), 48 deletions(-) diff --git a/tests/testthat/test-function-get_measures_config.R b/tests/testthat/test-function-get_measures_config.R index 1b0b4cf..87a04fd 100644 --- a/tests/testthat/test-function-get_measures_config.R +++ b/tests/testthat/test-function-get_measures_config.R @@ -17,53 +17,17 @@ test_that("get_measures_config() accepts parameters to be overridden", { parameters[[c("green_roof_ext", "bagrov_value")]] <- 0.75 result <- f(parameters) - result$green_roof[[1]] - + + green_roof <- result[["green_roof"]] + input_columns <- sapply(green_roof, "[[", "input_column") + expect_equal( + green_roof[[which(input_columns == "green_roof_ext")]][["bagrov_value"]], + 0.75 + ) }) - - -parameter_list <- '{ - "green_roof_ext": { - "bagrov_value": 0.65 - }, - "green_roof_int": { - "bagrov_value": 0.75 - }, - "permeable_paving": {}, - "unpaving": {}, - "trees_sm": { - "tree_volume": 200 - }, - "trees_md": { - "tree_volume": 300 - }, - "trees_lg": { - "tree_volume": 400 - }, - "to_swale": { - "evaporation_factor": 0.1, - "overflow_factor": 0.05 - }, - "to_surf_infil": { - "evaporation_factor": 0.15, - "overflow_factor": 0.15 - }, - "to_swale_trench": { - "evaporation_factor": 0.08, - "overflow_factor": 0.1 - }, - "to_tree_pit": { - "evaporation_factor": 0.2, - "overflow_factor": 0.15 - }, - "to_trench": { - "evaporation_factor": 0.15, - "overflow_factor": 0.15 - }, - "to_cistern": { - "overflow_factor": 0.5 - } -}' - -kwb.smartwater:::get_measures_config(parameter_list) +test_that("get_measures_config() accepts an empty parameter list", { + f <- kwb.smartwater:::get_measures_config + expect_no_error(config <- f(list())) + expect_identical(config, f()) +}) From 87290513ad87d95dc249aa5179c12daf2eb24eca Mon Sep 17 00:00:00 2001 From: f-delpu Date: Fri, 31 Jul 2026 16:05:07 +0200 Subject: [PATCH 3/7] add tree measures --- R/calculate_water_balance.R | 31 +++++++++---- R/frontend_helpers.R | 6 ++- R/n_trees_to_veg_class_increment.R | 20 -------- R/veg_class_functions.R | 46 +++++++++++++++++++ man/calculate_water_balance.Rd | 8 ++-- man/get_veg_class_increment.Rd | 21 +++++++++ man/n_trees_to_veg_class_increment.Rd | 30 ------------ tests/testthat/get_tree_measure_volume.R | 27 +++++++++++ .../test-function-calculate_water_balance.R | 36 +++++++++++++++ .../test-function-get_veg_class_increment.R | 11 +++++ ...st-function-get_water_quality_indicators.R | 13 ++++++ ...-function-n_trees_to_veg_class_increment.R | 17 ------- 12 files changed, 185 insertions(+), 81 deletions(-) delete mode 100644 R/n_trees_to_veg_class_increment.R create mode 100644 R/veg_class_functions.R create mode 100644 man/get_veg_class_increment.Rd delete mode 100644 man/n_trees_to_veg_class_increment.Rd create mode 100644 tests/testthat/get_tree_measure_volume.R create mode 100644 tests/testthat/test-function-get_veg_class_increment.R create mode 100644 tests/testthat/test-function-get_water_quality_indicators.R delete mode 100644 tests/testthat/test-function-n_trees_to_veg_class_increment.R diff --git a/R/calculate_water_balance.R b/R/calculate_water_balance.R index ebd14dc..f75cf0e 100644 --- a/R/calculate_water_balance.R +++ b/R/calculate_water_balance.R @@ -6,22 +6,26 @@ #' \code{code}. There is one numeric field per measure. The names of the #' measure-related fields must correspond to the \code{field_name}s returned #' by \code{\link{get_measure_info}}. -#' @param parameters optional. list of parameters for each measure as returned -#' by \code{\link{get_measure_info}(parameters_only = TRUE)}. +#' @param parameters optional.List of parameters for each measure for which +#' parameter values shall be overridden. Its format should refer to the format +#' of the list returned by \code{\link{get_measure_info}(parameters_only = +#' TRUE)}. #' @param convert_types logical value indicating whether or not to convert the #' data types in the \code{blocks} data frame as required by R-ABIMO. #' @export calculate_water_balance <- function( blocks, measures, - parameters = get_measure_info(parameters_only = TRUE), - convert_types = FALSE + parameters = NULL, + convert_types = FALSE, + max_veg_class = 80 ) { - #blocks <- kwb.smartwater::get_test_blocks() - #measures <- kwb.smartwater::get_test_block_measures() - #convert_types = FALSE - #kwb.utils::assignPackageObjects("kwb.smartwater") + # blocks <- kwb.smartwater::get_test_blocks() + # measures <- kwb.smartwater::get_test_block_measures() + # parameters = get_measure_info(parameters_only = TRUE) + # convert_types = FALSE + # kwb.utils::assignPackageObjects("kwb.smartwater") # kwb.rabimo is strict about data types. Therefore, convert data types as # necessary @@ -96,7 +100,16 @@ calculate_water_balance <- function( } } - # TODO: tree measures + # tree measures + veg_class_increment <- get_veg_class_increment( + tree_measure_volume = get_tree_measure_volume(block_measures, parameters), + unsealed_area_m2 = areas_m2$unsealed + ) + block$veg_class <- min( + block$veg_class + veg_class_increment, + max_veg_class + ) + } # Calculate m2 back into percentages diff --git a/R/frontend_helpers.R b/R/frontend_helpers.R index 9328d49..349f9b3 100644 --- a/R/frontend_helpers.R +++ b/R/frontend_helpers.R @@ -64,7 +64,9 @@ get_measure_info <- function( field_name = "trees_lg", long_name_de = "B\u00e4ume (gro\u00df)", parameters = list( - tree_volume = 400 + # 440 m3 determined for Bayerischer Platz, Berlin, rounded down to + # nearest multiple of 100 + tree_volume = 400 ) ), list( @@ -143,7 +145,7 @@ get_measure_info <- function( } if (parameters_only) { return(stats::setNames( - collect(measures, "parameters"), + lapply(measures, `[[`, "parameters"), collect(measures, "field_name") )) } diff --git a/R/n_trees_to_veg_class_increment.R b/R/n_trees_to_veg_class_increment.R deleted file mode 100644 index 73f562b..0000000 --- a/R/n_trees_to_veg_class_increment.R +++ /dev/null @@ -1,20 +0,0 @@ -#' Vegetation Class Increment Caused by Planting Trees -#' -#' @param n_trees number of trees to be planted -#' @param unpaved_area_m2 unpaved area (= total_area * (1 - roof - pvd)) in m2 -#' @param m slope of the linear relation between normalised vegetation volume -#' per unpaved area (vegnorm) and veg_scaled. Default: 4.7, calculated from -#' block with highest vegetation class in Berlin (code = 0000000012002198): -#' m = veg_scaled/vegnorm = 118.1306/24.92435 -#' @param volume_per_tree_m3 assumed green volume per tree in m3. Default: 400 -#' (440 m3 determined for Bayerischer Platz, Berlin, rounded down to nearest -#' multiple of 100) -n_trees_to_veg_class_increment <- function( - n_trees, - unpaved_area_m2, - m = 4.7, - volume_per_tree_m3 = 400 -) -{ - m * n_trees * volume_per_tree_m3 / unpaved_area_m2 -} diff --git a/R/veg_class_functions.R b/R/veg_class_functions.R new file mode 100644 index 0000000..167a739 --- /dev/null +++ b/R/veg_class_functions.R @@ -0,0 +1,46 @@ +get_tree_measure_volume <- function(block_measures, parameters = NULL) { + + stopifnot(is.data.frame(block_measures), + nrow(block_measures) == 1L) + + default_tree_parameters <- get_measure_info("trees", parameters_only = TRUE) + + stopifnot(all(names(default_tree_parameters) %in% names(block_measures))) + + fields_trees <- get_measure_info("trees", TRUE) + + sum(sapply(fields_trees, function(field) { + + # field <- fields_trees[1] + + n_trees <- block_measures[[field]] + volume_per_tree <- if (!is.null(parameters) && length(parameters[[field]])) { + parameters[[field]]$tree_volume + } else { + default_tree_parameters[[field]]$tree_volume + } + n_trees * volume_per_tree + })) +} + + +#' Vegetation Class Increment Caused by Planting Trees +#' +#' @param unsealed_area_m2 unpaved area (= total_area * (1 - roof - pvd)) in m2 +#' @param m slope of the linear relation between normalised vegetation volume +#' per unsealed area (vegnorm) and veg_scaled. Default: 4.7, calculated from +#' block with highest vegetation class in Berlin (code = 0000000012002198): +#' m = veg_scaled/vegnorm = 118.1306/24.92435 +#' @param tree_measure_volume assumed green volume of trees in m3. +get_veg_class_increment <- function( + tree_measure_volume, + unsealed_area_m2, + m = 4.7 +) +{ + if (unsealed_area_m2 == 0) { + return(0) + } + m * tree_measure_volume / unsealed_area_m2 +} + diff --git a/man/calculate_water_balance.Rd b/man/calculate_water_balance.Rd index ae736f0..7900d49 100644 --- a/man/calculate_water_balance.Rd +++ b/man/calculate_water_balance.Rd @@ -7,7 +7,7 @@ calculate_water_balance( blocks, measures, - parameters = get_measure_info(parameters_only = TRUE), + parameters = NULL, convert_types = FALSE ) } @@ -20,8 +20,10 @@ in m2. Each row refers to a block area, linked by the text field measure-related fields must correspond to the \code{field_name}s returned by \code{\link{get_measure_info}}.} -\item{parameters}{optional. list of parameters for each measure as returned -by \code{\link{get_measure_info}(parameters_only = TRUE)}.} +\item{parameters}{optional.List of parameters for each measure for which +parameter values shall be overridden. Its format should refer to the format +of the list returned by \code{\link{get_measure_info}(parameters_only = + TRUE)}.} \item{convert_types}{logical value indicating whether or not to convert the data types in the \code{blocks} data frame as required by R-ABIMO.} diff --git a/man/get_veg_class_increment.Rd b/man/get_veg_class_increment.Rd new file mode 100644 index 0000000..971ba55 --- /dev/null +++ b/man/get_veg_class_increment.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/veg_class_functions.R +\name{get_veg_class_increment} +\alias{get_veg_class_increment} +\title{Vegetation Class Increment Caused by Planting Trees} +\usage{ +get_veg_class_increment(tree_measure_volume, unsealed_area_m2, m = 4.7) +} +\arguments{ +\item{tree_measure_volume}{assumed green volume of trees in m3.} + +\item{unsealed_area_m2}{unpaved area (= total_area * (1 - roof - pvd)) in m2} + +\item{m}{slope of the linear relation between normalised vegetation volume +per unsealed area (vegnorm) and veg_scaled. Default: 4.7, calculated from +block with highest vegetation class in Berlin (code = 0000000012002198): +m = veg_scaled/vegnorm = 118.1306/24.92435} +} +\description{ +Vegetation Class Increment Caused by Planting Trees +} diff --git a/man/n_trees_to_veg_class_increment.Rd b/man/n_trees_to_veg_class_increment.Rd deleted file mode 100644 index 905bba3..0000000 --- a/man/n_trees_to_veg_class_increment.Rd +++ /dev/null @@ -1,30 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/n_trees_to_veg_class_increment.R -\name{n_trees_to_veg_class_increment} -\alias{n_trees_to_veg_class_increment} -\title{Vegetation Class Increment Caused by Planting Trees} -\usage{ -n_trees_to_veg_class_increment( - n_trees, - unpaved_area_m2, - m = 4.7, - volume_per_tree_m3 = 400 -) -} -\arguments{ -\item{n_trees}{number of trees to be planted} - -\item{unpaved_area_m2}{unpaved area (= total_area * (1 - roof - pvd)) in m2} - -\item{m}{slope of the linear relation between normalised vegetation volume -per unpaved area (vegnorm) and veg_scaled. Default: 4.7, calculated from -block with highest vegetation class in Berlin (code = 0000000012002198): -m = veg_scaled/vegnorm = 118.1306/24.92435} - -\item{volume_per_tree_m3}{assumed green volume per tree in m3. Default: 400 -(440 m3 determined for Bayerischer Platz, Berlin, rounded down to nearest -multiple of 100)} -} -\description{ -Vegetation Class Increment Caused by Planting Trees -} diff --git a/tests/testthat/get_tree_measure_volume.R b/tests/testthat/get_tree_measure_volume.R new file mode 100644 index 0000000..07ddd95 --- /dev/null +++ b/tests/testthat/get_tree_measure_volume.R @@ -0,0 +1,27 @@ +test_that("get_tree_measure_volume() works", { + #library(testthat) + + f <- kwb.smartwater:::get_tree_measure_volume + + expect_error(f()) + + expect_error(f(block_measures = 1)) + + expect_error(f(block_measures = data.frame(trees_sm = 1:2))) + + expect_error(f(block_measures = data.frame(trees_sm = 1))) + + expect_equal(f(block_measures = data.frame(trees_sm = 1, + trees_md = 0, + trees_lg = 0)), 200) + + expect_equal(f(block_measures = data.frame(trees_sm = 0, + trees_md = 0, + trees_lg = 0)), 0) + + expect_equal(f(block_measures = data.frame(trees_sm = 0, + trees_md = 0, + trees_lg = 10)), 4000) + +}) + diff --git a/tests/testthat/test-function-calculate_water_balance.R b/tests/testthat/test-function-calculate_water_balance.R index 41cbe3e..4ff3a45 100644 --- a/tests/testthat/test-function-calculate_water_balance.R +++ b/tests/testthat/test-function-calculate_water_balance.R @@ -194,3 +194,39 @@ test_that("existing green roofs are always considered", { result <- kwb.smartwater::calculate_water_balance(blocks, measures) expect_equal(result$water_balance$status_quo, result$water_balance$with_measures) }) + + +test_that("trees increase evaporation", { + blocks <- data.frame( + code = "test", + prec_yr = 621L, + prec_s = 327L, + epot_yr = 666L, + epot_s = 509L, + total_area = 10000, + roof = 0.3, + green_roof = 0.3203, + swg_roof = 0.94, + pvd = 0.3, + swg_pvd = 0.84, + srf1_pvd = 0.5, + srf2_pvd = 0.34, + srf3_pvd = 0.09, + srf4_pvd = 0.07, + srf5_pvd = 0, + to_swale = 0, + gw_dist = 3.4, + ufc30 = 11, + ufc150 = 10, + land_type = "urban", + veg_class = 20, + irrigation = 0L + ) + measures <- kwb.smartwater::get_test_block_measures( + codes = blocks$code, value = 0) + measures$trees_md <- 30 + results <- kwb.smartwater::calculate_water_balance(blocks, measures) + + expect_true(results$water_balance$status_quo$evapor <= + results$water_balance$with_measures$evapor) +}) \ No newline at end of file diff --git a/tests/testthat/test-function-get_veg_class_increment.R b/tests/testthat/test-function-get_veg_class_increment.R new file mode 100644 index 0000000..8a66aa0 --- /dev/null +++ b/tests/testthat/test-function-get_veg_class_increment.R @@ -0,0 +1,11 @@ +test_that("get_veg_class_increment() works", { + + f <- kwb.smartwater:::get_veg_class_increment + # library(testthat) + expect_error(f()) + + expect_equal(f(tree_measure_volume = 0, unsealed_area_m2 = 200), 0) + expect_equal(f(tree_measure_volume = 200, unsealed_area_m2 = 0), 0) + +}) + diff --git a/tests/testthat/test-function-get_water_quality_indicators.R b/tests/testthat/test-function-get_water_quality_indicators.R new file mode 100644 index 0000000..6729142 --- /dev/null +++ b/tests/testthat/test-function-get_water_quality_indicators.R @@ -0,0 +1,13 @@ +# +# This test file has been generated by kwb.test::create_test_files() +# launched by user fdpunt on 2026-07-31 14:30:20.934085. +# Your are strongly encouraged to modify the dummy functions +# so that real cases are tested. You should then delete this comment. +# + +test_that("get_water_quality_indicators() works", { + + kwb.smartwater:::get_water_quality_indicators() + +}) + diff --git a/tests/testthat/test-function-n_trees_to_veg_class_increment.R b/tests/testthat/test-function-n_trees_to_veg_class_increment.R deleted file mode 100644 index 60d216c..0000000 --- a/tests/testthat/test-function-n_trees_to_veg_class_increment.R +++ /dev/null @@ -1,17 +0,0 @@ -# -# This file was generated by kwb.test::create_test_files(), -# launched by hsonne on 2026-07-17 11:59:34.917226. -# Please modify the dummy functions so that real cases are -# tested. Then, delete this comment. -# - -test_that("n_trees_to_veg_class_increment() works", { - - f <- kwb.smartwater:::n_trees_to_veg_class_increment - - expect_error( - f() - # Argument "n_trees" fehlt (ohne Standardwert) - ) - -}) From 16d5961a5faf12ee80d23b5cd8ba6e4b637eeef1 Mon Sep 17 00:00:00 2001 From: hsonne Date: Fri, 31 Jul 2026 16:45:08 +0200 Subject: [PATCH 4/7] Document max_veg_class argument and fix a test --- R/calculate_water_balance.R | 4 +++ man/calculate_water_balance.Rd | 8 +++++- ...st-function-get_water_quality_indicators.R | 28 ++++++++++++------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/R/calculate_water_balance.R b/R/calculate_water_balance.R index f75cf0e..01acd84 100644 --- a/R/calculate_water_balance.R +++ b/R/calculate_water_balance.R @@ -12,6 +12,10 @@ #' TRUE)}. #' @param convert_types logical value indicating whether or not to convert the #' data types in the \code{blocks} data frame as required by R-ABIMO. +#' @param max_veg_class maximum vegetation class value. When increasing the +#' vegetation class index in order to consider tree measures, the resulting +#' vegetation class index of a block will be limited to this value. The +#' default is 80. #' @export calculate_water_balance <- function( blocks, diff --git a/man/calculate_water_balance.Rd b/man/calculate_water_balance.Rd index 7900d49..190db5d 100644 --- a/man/calculate_water_balance.Rd +++ b/man/calculate_water_balance.Rd @@ -8,7 +8,8 @@ calculate_water_balance( blocks, measures, parameters = NULL, - convert_types = FALSE + convert_types = FALSE, + max_veg_class = 80 ) } \arguments{ @@ -27,6 +28,11 @@ of the list returned by \code{\link{get_measure_info}(parameters_only = \item{convert_types}{logical value indicating whether or not to convert the data types in the \code{blocks} data frame as required by R-ABIMO.} + +\item{max_veg_class}{maximum vegetation class value. When increasing the +vegetation class index in order to consider tree measures, the resulting +vegetation class index of a block will be limited to this value. The +default is 80.} } \description{ Calculate Water Balance for Given Block Areas and Measures diff --git a/tests/testthat/test-function-get_water_quality_indicators.R b/tests/testthat/test-function-get_water_quality_indicators.R index 6729142..20bc523 100644 --- a/tests/testthat/test-function-get_water_quality_indicators.R +++ b/tests/testthat/test-function-get_water_quality_indicators.R @@ -1,13 +1,21 @@ -# -# This test file has been generated by kwb.test::create_test_files() -# launched by user fdpunt on 2026-07-31 14:30:20.934085. -# Your are strongly encouraged to modify the dummy functions -# so that real cases are tested. You should then delete this comment. -# - +# library(testthat) test_that("get_water_quality_indicators() works", { - kwb.smartwater:::get_water_quality_indicators() - + f <- kwb.smartwater:::get_water_quality_indicators + + expect_error(f()) + + result_10 <- f(10) + expect_true(is.list(result_10)) + expect_equal( + names(result_10), + c("overflow_volume", "critical_hours", "critical_events") + ) + + result_100 <- f(100) + expect_equal(result_100$critical_hours, 0) + + expect_true(result_10$overflow_volume > result_100$overflow_volume) + expect_true(result_10$critical_hours > result_100$critical_hours) + expect_true(result_10$critical_events > result_100$critical_events) }) - From 7262638d62ee3d297f5e8e1402d350aa5bd58e59 Mon Sep 17 00:00:00 2001 From: hsonne Date: Fri, 31 Jul 2026 17:08:04 +0200 Subject: [PATCH 5/7] Tag new version v0.3.0 indicate dependency on kwb.rabimo@v2.2.0 in DESCRIPTION --- DESCRIPTION | 4 ++-- NEWS.md | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index d667025..7abfc89 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: kwb.smartwater Title: Functions Related to the SmartWater Project -Version: 0.2.1 +Version: 0.3.0 Authors@R: c( person("Hauke", "Sonnenberg", , "hauke.sonnenberg@kompetenz-wasser.de", role = c("aut", "cre"), comment = c(ORCID = "0000-0001-9134-2871")), @@ -22,7 +22,7 @@ Suggests: plumber2, testthat (>= 3.0.0) Remotes: - github::kwb-r/kwb.rabimo@dev, + github::kwb-r/kwb.rabimo@v2.2.0, github::kwb-r/kwb.utils Config/roxygen2/version: 8.0.0 RoxygenNote: 7.3.3 diff --git a/NEWS.md b/NEWS.md index ed6c658..53271b3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,10 @@ +# kwb.smartwater v0.3.0 + +In this version, + +- tree measures are considered by increasing the vegetation class, +- default model parameters can be overridden. + # kwb.smartwater v0.2.1 Fix bug in considering existing green roofs for status quo calculation From 82e6be0e98964042bf4ea3849eab7f908b5dc8fa Mon Sep 17 00:00:00 2001 From: hsonne Date: Fri, 31 Jul 2026 17:28:14 +0200 Subject: [PATCH 6/7] Allow to set measure "parameters" via plumber --- R/calculate_water_balance.R | 2 +- inst/scripts/plumber.R | 6 ++++-- man/calculate_water_balance.Rd | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/R/calculate_water_balance.R b/R/calculate_water_balance.R index 01acd84..90ca3b1 100644 --- a/R/calculate_water_balance.R +++ b/R/calculate_water_balance.R @@ -6,7 +6,7 @@ #' \code{code}. There is one numeric field per measure. The names of the #' measure-related fields must correspond to the \code{field_name}s returned #' by \code{\link{get_measure_info}}. -#' @param parameters optional.List of parameters for each measure for which +#' @param parameters optional. List of parameters for each measure for which #' parameter values shall be overridden. Its format should refer to the format #' of the list returned by \code{\link{get_measure_info}(parameters_only = #' TRUE)}. diff --git a/inst/scripts/plumber.R b/inst/scripts/plumber.R index d97590b..5e50809 100644 --- a/inst/scripts/plumber.R +++ b/inst/scripts/plumber.R @@ -22,15 +22,17 @@ function(type = character(0), field_name_only = FALSE) #* Run R-Abimo for a given set of block areas and a given set of corresponding measures. #* @param blocks:data.frame Array of block areas, as e.g. returned by /get_test_blocks #* @param measures:data.frame Array of objects containing information about the planned measures in m2. Each object has a text field "code" that identifies the block area to which the measures relate. All other fields are numeric and relate to a measure type. See /get_test_block_measures for an example object and for the expected measure names. +#* @param parameters:list Optional. Object with element names corresponding to measure names. Each element contains parameters to be overridden for the corresponding measure. #* @serializer unboxedJSON function( blocks = kwb.smartwater::get_test_blocks(), - measures = kwb.smartwater::get_test_block_measures() + measures = kwb.smartwater::get_test_block_measures(), + parameters = kwb.smartwater::get_measure_info(parameters_only = TRUE) ) { to_plumber_response(try({ kwb.smartwater::calculate_water_balance( - blocks, measures, convert_types = TRUE + blocks, measures, parameters = parameters, convert_types = TRUE ) })) } diff --git a/man/calculate_water_balance.Rd b/man/calculate_water_balance.Rd index 190db5d..aeff9a6 100644 --- a/man/calculate_water_balance.Rd +++ b/man/calculate_water_balance.Rd @@ -21,7 +21,7 @@ in m2. Each row refers to a block area, linked by the text field measure-related fields must correspond to the \code{field_name}s returned by \code{\link{get_measure_info}}.} -\item{parameters}{optional.List of parameters for each measure for which +\item{parameters}{optional. List of parameters for each measure for which parameter values shall be overridden. Its format should refer to the format of the list returned by \code{\link{get_measure_info}(parameters_only = TRUE)}.} From a2935dde08b4c8244b360a8aa905c99d75a6164d Mon Sep 17 00:00:00 2001 From: hsonne Date: Fri, 31 Jul 2026 17:34:25 +0200 Subject: [PATCH 7/7] Set date for version v0.3.0 in NEWS.md --- NEWS.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/NEWS.md b/NEWS.md index 53271b3..02a99c1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,24 +1,24 @@ -# kwb.smartwater v0.3.0 +## kwb.smartwater v0.3.0 (2026-07-31) In this version, - tree measures are considered by increasing the vegetation class, - default model parameters can be overridden. -# kwb.smartwater v0.2.1 +## kwb.smartwater v0.2.1 Fix bug in considering existing green roofs for status quo calculation -# kwb.smartwater v0.2.0 +## kwb.smartwater v0.2.0 Changed interface to the plot-related functions, allowing to specify the margins -# kwb.smartwater v0.1.0 +## kwb.smartwater v0.1.0 First version to be used by the Smartwater Web App, developed by Technologiestiftung Berlin -# kwb.smartwater 0.0.0.9000 +## kwb.smartwater 0.0.0.9000 * Added a `NEWS.md` file to track changes to the package. * see https://style.tidyverse.org/news.html for writing a good `NEWS.md`