From a6c13f70f6c6669a8088827a602ac475fdf9b624 Mon Sep 17 00:00:00 2001 From: Johannes Ranke Date: Sun, 29 Jan 2017 16:58:53 +0100 Subject: Setting up PELMO runs, execution and evaluation It all works! --- ChangeLog | 29 +++++ DESCRIPTION | 2 +- NAMESPACE | 2 + R/FOCUS_PELMO_data.R | 14 +-- R/PELMO_runs.R | 163 +++++++++++++++++++++---- _pkgdown.yml | 3 + docs/reference/FOCUS_GW_scenarios_2012.html | 10 +- docs/reference/FOCUS_PELMO_crop_sze_names.html | 121 ++++++++++++++++++ docs/reference/FOCUS_PELMO_crops.html | 132 ++++++++++++++++++++ docs/reference/FOCUS_PELMO_location_codes.html | 113 +++++++++++++++++ docs/reference/PELMO_path.html | 112 +++++++++++++++++ docs/reference/PELMO_runs.html | 144 ++++++++++++++++++++++ docs/reference/create_run_list.html | 116 ++++++++++++++++++ docs/reference/evaluate_PELMO.html | 116 ++++++++++++++++++ docs/reference/focus_80th.html | 113 +++++++++++++++++ docs/reference/get_flux.html | 101 +++++++++++++++ docs/reference/get_interval.html | 101 +++++++++++++++ docs/reference/index.html | 11 +- docs/reference/run_PELMO.html | 119 ++++++++++++++++++ docs/reference/sum_periods.html | 101 +++++++++++++++ man/FOCUS_PELMO_crops.Rd | 4 +- man/PELMO_runs.Rd | 17 ++- man/focus_80th.Rd | 19 +++ man/get_flux.Rd | 11 ++ man/get_interval.Rd | 11 ++ man/run_PELMO.Rd | 27 ---- man/sum_periods.Rd | 11 ++ tests/testthat/test_PELMO.R | 74 ++++++++--- 28 files changed, 1717 insertions(+), 80 deletions(-) create mode 100644 docs/reference/FOCUS_PELMO_crop_sze_names.html create mode 100644 docs/reference/FOCUS_PELMO_crops.html create mode 100644 docs/reference/FOCUS_PELMO_location_codes.html create mode 100644 docs/reference/PELMO_path.html create mode 100644 docs/reference/PELMO_runs.html create mode 100644 docs/reference/create_run_list.html create mode 100644 docs/reference/evaluate_PELMO.html create mode 100644 docs/reference/focus_80th.html create mode 100644 docs/reference/get_flux.html create mode 100644 docs/reference/get_interval.html create mode 100644 docs/reference/run_PELMO.html create mode 100644 docs/reference/sum_periods.html create mode 100644 man/focus_80th.Rd create mode 100644 man/get_flux.Rd create mode 100644 man/get_interval.Rd delete mode 100644 man/run_PELMO.Rd create mode 100644 man/sum_periods.Rd diff --git a/ChangeLog b/ChangeLog index 762acf3..38beb77 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +commit 15c1b8c5ddadf938ce13d3dd9da2a09d8749f740 +Author: Johannes Ranke +Date: 2017-01-29 16:58:53 +0100 + + Setting up PELMO runs, execution and evaluation + + It all works! + +commit bc97a35a32c4f47e29364488a3601f94c6e68d45 +Author: Johannes Ranke +Date: 2017-01-27 18:33:45 +0100 + + Really use all scenarios in test data + + Maize, that was used in the last commit, is not parameterised for + Jokioinen + +commit a4081ddfea726283874968c0b62a7f46e4fd1232 +Author: Johannes Ranke +Date: 2017-01-27 18:23:35 +0100 + + Use all scenarios in the test data + +commit 3c82d26206e2f2e74600acd71a49c70eaed555c4 +Author: Johannes Ranke +Date: 2017-01-27 08:17:08 +0100 + + Also test run with metabolites + commit 8fd050e57b7babfbdb1ccfabb468a0398396d466 Author: Johannes Ranke Date: 2017-01-27 07:54:53 +0100 diff --git a/DESCRIPTION b/DESCRIPTION index 81f8df2..97b5962 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -2,7 +2,7 @@ Package: pfm Type: Package Title: Utilities for Pesticide Fate Modelling Version: 0.4-2 -Date: 2017-01-27 +Date: 2017-01-29 Authors@R: person("Johannes Ranke", email = "jranke@uni-bremen.de", role = c("aut", "cre", "cph")) Description: Utilities for simple calculations of predicted environmental diff --git a/NAMESPACE b/NAMESPACE index c795c89..feb5ca7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -26,6 +26,8 @@ export(SFO_actual_twa) export(SSLRC_mobility_classification) export(TOXSWA_cwa) export(endpoint) +export(evaluate_PELMO) +export(focus_80th) export(geomean) export(max_twa) export(one_box) diff --git a/R/FOCUS_PELMO_data.R b/R/FOCUS_PELMO_data.R index 28888e7..89fe5f6 100644 --- a/R/FOCUS_PELMO_data.R +++ b/R/FOCUS_PELMO_data.R @@ -2,10 +2,10 @@ #' #' A named character vector with the crop names used in the PELMO 5.5.3 GUI. #' For the names, three letter codes were constructed by generally taking the -#' first three letters in lower case. Only when there is an expression in -#' parentheses, the first letter of this expression becomes the first letter +#' first three letters in lower case. Only when there is an expression in +#' parentheses, the first letter of this expression becomes the first letter #' in the three letter code, i.e. 'Peas (animals)' has the code \code{ape}. -#' +#' #' @docType data #' @export #' @examples @@ -37,13 +37,13 @@ FOCUS_PELMO_crops = c( tom = "Tomatoes", vin = "Vines") -#' FOCUS PELMO crop acronyms used for naming sceneario files +#' FOCUS PELMO crop acronyms used for naming sceneario files #' #' A named character vector with the crop acronyms used in FOCUS PELMO 5.5.3 #' for naming the .sze files located in the FOCUS directory. The crop acronyms #' in the file names are sometimes capitalized, sometimes not. The scenario #' files used for Beans (field) and Beans (vegetable) are the same. -#' +#' #' @docType data #' @export #' @examples @@ -85,6 +85,6 @@ FOCUS_PELMO_crop_sze_names = c( #' @examples #' print(FOCUS_PELMO_location_codes) FOCUS_PELMO_location_codes = c( - Cha = "C", Ham = "H", Jok = "J", - Kre = "K", Oke = "N", Pia = "P", + Cha = "C", Ham = "H", Jok = "J", + Kre = "K", Oke = "N", Pia = "P", Por = "O", Sev = "S", Thi = "T") diff --git a/R/PELMO_runs.R b/R/PELMO_runs.R index f599110..5d401ea 100644 --- a/R/PELMO_runs.R +++ b/R/PELMO_runs.R @@ -1,7 +1,10 @@ #' Set up runs for FOCUS PELMO #' #' Per default, the runs are also executed with FOCUS PELMO, and the results are processed -#' and returned. +#' and returned. Currently, only FOCUS PELMO as installed on Linux (or other Unix systems) +#' using the \code{\link{install_PELMO}} from the \code{PELMO.installeR} package +#' maintained on github is supported. In such installations, FOCUS PELMO is installed into +#' package installation directory of \code{PELMO.installeR} and run with \code{wine}. #' #' @param runs A list of lists. Each inner lists has an element named 'psm' #' that holds the psm string, and elements named using three letter crop acronyms, @@ -15,6 +18,9 @@ #' @param cores The number of cores to execute PELMO runs in parallel #' @param evaluate Should the results be returned? #' @param overwrite Should an existing run directories be overwritten +#' @references PELMO.installeR \url{https://jranke.github.io/PELMO.installeR} +#' +#' Wine \url{https://winehq.org} #' @export PELMO_runs <- function(runs, psm_dir = ".", version = "5.5.3", PELMO_base = "auto", execute = TRUE, cores = getOption("mc.cores", 2L), @@ -80,26 +86,9 @@ PELMO_runs <- function(runs, psm_dir = ".", version = "5.5.3", PELMO_base = "aut add <- function(x) cat(paste0(x, "\r\n"), file = input_file, append = TRUE) - # How many years do we calculate (26, 46 or 66)? - psm <- readLines(psm_file, encoding = "latin1") - number_of_apps_lines <- grep("number of application location", psm) - absolute_apps_line <- grep(location_code, - psm[number_of_apps_lines]) - period <- 1 # application every year - if (length(absolute_apps_line) == 1) { - apps_root <- number_of_apps_lines[absolute_apps_line] - } else { - apps_root <- number_of_apps_lines[1] - } - - number_of_apps <- as.integer(substr(psm[apps_root], 1, 3)) - last_app_line <- psm[apps_root + number_of_apps] - last_app_year <- as.integer(gsub("^.{2,3} .. (..) .*", "\\1", - last_app_line)) - if (last_app_year > 26) period <- 2 - if (last_app_year > 46) period <- 3 + interval <- get_interval(psm_file, location_code) - n_years <- switch(as.character(period), + n_years <- switch(as.character(interval), "1" = 26, "2" = 46, "3" = 66) @@ -145,18 +134,23 @@ PELMO_runs <- function(runs, psm_dir = ".", version = "5.5.3", PELMO_base = "aut # the exe file from this directory file.copy(file.path(PELMO_base, "lf90.eer"), run_dir) } + run_list[[7]] + setup_run(run_list[[7]]) lapply(run_list, setup_run) if (execute) { run_PELMO(runs, version = version, PELMO_base = PELMO_base) } + + if (evaluate) { + evaluate_PELMO(runs, version = version, PELMO_base = PELMO_base) + } } -#' Run PELMO -#' #' @inheritParams PELMO_runs #' @importFrom parallel mclapply +#' @rdname PELMO_runs #' @export run_PELMO <- function(runs, version = "5.5.3", PELMO_base = "auto", cores = getOption("mc.cores", 2L)) @@ -295,3 +289,128 @@ create_run_list <- function(runs, psm_dir = ".", check_psm_files = FALSE) { } return(run_list) } + +#' @rdname PELMO_runs +#' @inheritParams PELMO_runs +#' @importFrom parallel mclapply +#' @export +evaluate_PELMO <- function(runs, version = "5.5.3", PELMO_base = "auto") +{ + + if (PELMO_base[1] == "auto") { + PELMO_base = file.path(system.file(package = "PELMO.installeR"), + paste0("FOCUSPELMO.", gsub("\\.", "", version))) + } + + for (run in runs) { + psm <- run$psm + crops <- setdiff(names(run), "psm") + for (crop in crops) { + for (scenario in run[[crop]]) { + run_dir <- file.path(PELMO_base, "FOCUS", PELMO_path(psm, crop, scenario)) + echo_file <- readLines(file.path(run_dir, "ECHO.PLM"), encoding = "latin1") + parm_lines <- grep("\\*\\*\\* PARAMETERS OF", echo_file, value = TRUE) + acronyms <- gsub(".*\\((.*)\\).*", "\\1", parm_lines) + met_codes <- gsub(".*METABOLITE (..).*", "\\1", parm_lines) + met_codes[1] <- NA + names(met_codes) <- acronyms + + psm_file <- file.path(run_dir, paste0(psm, ".psm")) + location_code <- FOCUS_PELMO_location_codes[scenario] + interval <- get_interval(psm_file, location_code) + + # Get percolate for each period + wasser <- readLines(file.path(run_dir, "WASSER.PLM")) + percolate_lines <- grep("RECHARGE BELOW ROOT ZONE", wasser, value = TRUE) + percolate <- as.numeric(substr(percolate_lines, 40, 46)) + percolate_period <- sum_periods(percolate, interval) + + # Set up results that should match period.plm generated by the PELMO GUI + results_pfm <- list() + for (acronym in acronyms) { + results_pfm[[acronym]] <- list() + periods <- data.frame( + period = 1:20, + flux = NA, + percolate = 10 * percolate_period, + conc = NA) + + if (is.na(met_codes[acronym])) { + chem_file <- file.path(run_dir, "CHEM.PLM") + } else { + chem_file <- file.path(run_dir, paste0("CHEM_", met_codes[acronym], ".PLM")) + } + + annual_flux <- get_flux(chem_file) + periods$flux <- sum_periods(annual_flux, interval) * 1000 + + periods$conc <- 100 * periods$flux / periods$percolate + + results_pfm[[acronym]]$periods <- periods + results_pfm[[acronym]]$focus <- focus_80th(periods$conc) + } + save(results_pfm, file = file.path(run_dir, "period_pfm.rda")) + } + } + } +} + +#' Get the application interval in years from a psm file +get_interval <- function(psm_file, location_code) { + # How many years do we calculate (26, 46 or 66)? + psm <- readLines(psm_file, encoding = "latin1") + number_of_apps_lines <- grep("number of application location", psm) + absolute_apps_line <- grep(location_code, + psm[number_of_apps_lines]) + interval <- 1 # application every year + if (length(absolute_apps_line) == 1) { + apps_root <- number_of_apps_lines[absolute_apps_line] + } else { + apps_root <- number_of_apps_lines[1] + } + + number_of_apps <- as.integer(substr(psm[apps_root], 1, 3)) + last_app_line <- psm[apps_root + number_of_apps] + last_app_year <- as.integer(gsub("^.{2,3} .. (..) .*", "\\1", + last_app_line)) + if (last_app_year > 26) interval <- 2 + if (last_app_year > 46) interval <- 3 + return(interval) +} + +#' Sum up values according to FOCUS periods +sum_periods <- function(annual, interval) { + n_years <- switch(as.character(interval), + "1" = 26, + "2" = 46, + "3" = 66) + period_start_years <- seq(from = 7, to = n_years, by = interval) + sapply(1:20, function(x) { + years_i <- period_start_years[x] + (0 : (interval - 1)) + sum(annual[years_i]) + }) +} + +#' Get the flux of a chemical out of the FOCUS layer from a CHEM*.PLM file +get_flux <- function(chem_file) { + chem <- readLines(chem_file) + lowest_focus_comp_lines <- grep("^ . 21 ", chem, value = TRUE) + lowest_focus_comp <- read.table(text = lowest_focus_comp_lines) + return(lowest_focus_comp$V9) +} + +#' Calculate the 80th percentile according to FOCUS guidance +#' +#' This is nowadays defined as the mean of the 16th and the 17th +#' highest value. Previously, the 17th highest values was used (FOCUS 2014, p. +#' 18). NaN values need to be set to zero in order to reproduce the +#' values obtained by PELMO. +#' @param c_period A numeric vector of values to calculate the percentile from +#' @param old Should the old calculation method be used (the 17th highest value)? +#' @export +focus_80th <- function(c_period, old = FALSE) { + c_period <- ifelse(is.na(c_period), 0, c_period) + c_period_sorted <- sort(c_period) + if (old) return(c_period_sorted[17]) + else return(mean(c_period_sorted[c(16, 17)])) +} diff --git a/_pkgdown.yml b/_pkgdown.yml index ff5f43d..829ba48 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -17,6 +17,9 @@ reference: contents: - PEC_soil - soil_scenario_data_EFSA_2015 + - title: Predicted environmental concentrations in groundwater + contents: + - PELMO_runs - title: Predicted environmental concentrations in surface water contents: - PEC_sw_drift diff --git a/docs/reference/FOCUS_GW_scenarios_2012.html b/docs/reference/FOCUS_GW_scenarios_2012.html index 64b42e9..fbc1649 100644 --- a/docs/reference/FOCUS_GW_scenarios_2012.html +++ b/docs/reference/FOCUS_GW_scenarios_2012.html @@ -70,10 +70,16 @@ -

Currently, only a small subset of the soil definitions are provided.

+

Currently, only scenario names with acronyms and a small subset of the soil definitions are provided. The +soil definitions are from page 46ff. from FOCUS (2012).

+
FOCUS_GW_scenarios_2012
+

Format

+ +

An object of class list of length 2.

+

References

FOCUS (2012) Generic guidance for Tier 1 FOCUS ground water assessments. Version 2.1. @@ -147,6 +153,8 @@

Contents