From b38055278d4a801598ece9d2c93716a9bf67134a Mon Sep 17 00:00:00 2001 From: Johannes Ranke Date: Fri, 27 Jan 2017 01:00:07 +0100 Subject: Set up FOCUS PELMO runs and run them in parallel - This works on Linux using wine - PELMO runs (including pelmo.inp files) are correctly generated - The PLM files for FOCUS Pesticide_D in the test data archive are correctly reproduced - The data files (including FOCUS groundwater scenario data) are now created and documented in R files --- ChangeLog | 48 ++++++ DESCRIPTION | 8 +- NAMESPACE | 9 ++ R/FOCUS_GW_scenarios_2012.R | 62 +++++++- R/FOCUS_PELMO_data.R | 90 +++++++++++ R/PELMO_runs.R | 296 +++++++++++++++++++++++++++++++++++++ data/FOCUS_GW_scenarios_2012.RData | Bin 993 -> 0 bytes man/FOCUS_GW_scenarios_2012.Rd | 9 +- man/FOCUS_PELMO_crop_sze_names.Rd | 20 +++ man/FOCUS_PELMO_crops.Rd | 21 +++ man/FOCUS_PELMO_location_codes.Rd | 18 +++ man/PELMO_path.Rd | 18 +++ man/PELMO_runs.Rd | 35 +++++ man/create_run_list.Rd | 22 +++ man/run_PELMO.Rd | 27 ++++ tests/testthat/test_PELMO.R | 101 +++++++++++++ tests/testthat/test_TOXSWA.R | 56 +++++++ tests/testthat/test_TOXSWA_cwa.R | 56 ------- 18 files changed, 834 insertions(+), 62 deletions(-) create mode 100644 R/FOCUS_PELMO_data.R create mode 100644 R/PELMO_runs.R delete mode 100644 data/FOCUS_GW_scenarios_2012.RData create mode 100644 man/FOCUS_PELMO_crop_sze_names.Rd create mode 100644 man/FOCUS_PELMO_crops.Rd create mode 100644 man/FOCUS_PELMO_location_codes.Rd create mode 100644 man/PELMO_path.Rd create mode 100644 man/PELMO_runs.Rd create mode 100644 man/create_run_list.Rd create mode 100644 man/run_PELMO.Rd create mode 100644 tests/testthat/test_PELMO.R create mode 100644 tests/testthat/test_TOXSWA.R delete mode 100644 tests/testthat/test_TOXSWA_cwa.R diff --git a/ChangeLog b/ChangeLog index 0a73e39..19fe18d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,51 @@ +commit 8f943c9dd2322482f64e1c6348c1ad7cfd253ee8 +Author: Johannes Ranke +Date: 2017-01-27 01:00:07 +0100 + + Set up FOCUS PELMO runs and run them in parallel + + - This works on Linux using wine. + - The PLM files for FOCUS Pesticide_D in the test data archive are + correctly reproduced + - The data files (including FOCUS groundwater scenario data) are now + created and documented in R files + +commit 40c2f387775a168df1be699813807586cf098648 +Author: Johannes Ranke +Date: 2017-01-26 10:30:32 +0100 + + Improved test data with 'irrigation' + +commit 228ab628b407af4812a48f20693a9a3a6bba8af4 +Author: Johannes Ranke +Date: 2017-01-25 16:45:24 +0100 + + More variable selection of test data + +commit bf6634b7d9a5033a217f04060f77e0c7d5b3046a +Author: Johannes Ranke +Date: 2017-01-25 15:27:05 +0100 + + Use tar.bz2 to correctly transfer file names + +commit 476d556cb6a490b138e47d487dd732f298aa6c3d +Author: Johannes Ranke +Date: 2017-01-25 14:29:41 +0100 + + Add FOCUS PELMO 5.5.3 output for dummy pesticide D + +commit 9f16be247e851c948edb30ac756550d89ba0af52 +Author: Johannes Ranke +Date: 2017-01-19 11:44:22 +0100 + + Another correction of the docs + +commit 2ab822d51c4c7e29d62076336d7a3f02a46e41a5 +Author: Johannes Ranke +Date: 2017-01-19 11:41:19 +0100 + + Corrections in the documentation + commit 46883a0c3a3c00127a563a7befa0af440573baaa Author: Johannes Ranke Date: 2017-01-19 11:22:08 +0100 diff --git a/DESCRIPTION b/DESCRIPTION index 3c96ed5..81f8df2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,8 @@ Package: pfm Type: Package Title: Utilities for Pesticide Fate Modelling -Version: 0.4-1 -Date: 2017-01-19 +Version: 0.4-2 +Date: 2017-01-27 Authors@R: person("Johannes Ranke", email = "jranke@uni-bremen.de", role = c("aut", "cre", "cph")) Description: Utilities for simple calculations of predicted environmental @@ -18,7 +18,9 @@ Imports: Suggests: testthat, chents, - magrittr + magrittr, + R.utils, + PELMO.installeR License: GPL LazyLoad: yes LazyData: yes diff --git a/NAMESPACE b/NAMESPACE index 35245d9..c795c89 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -11,11 +11,17 @@ S3method(plot,TOXSWA_cwa) S3method(plot,one_box) S3method(print,GUS_result) S3method(twa,one_box) +export(FOCUS_GW_scenarios_2012) +export(FOCUS_PELMO_crop_sze_names) +export(FOCUS_PELMO_crops) +export(FOCUS_PELMO_location_codes) export(GUS) export(PEC_soil) export(PEC_sw_drainage_UK) export(PEC_sw_drift) export(PEC_sw_sed) +export(PELMO_path) +export(PELMO_runs) export(SFO_actual_twa) export(SSLRC_mobility_classification) export(TOXSWA_cwa) @@ -25,6 +31,7 @@ export(max_twa) export(one_box) export(pfm_degradation) export(read.TOXSWA_cwa) +export(run_PELMO) export(sawtooth) export(soil_DT50) export(soil_Kfoc) @@ -36,6 +43,7 @@ import(mkin) importFrom(R6,R6Class) importFrom(methods,is) importFrom(mkin,mkinpredict) +importFrom(parallel,mclapply) importFrom(readr,fwf_empty) importFrom(readr,read_fwf) importFrom(stats,end) @@ -45,3 +53,4 @@ importFrom(stats,plot.ts) importFrom(stats,start) importFrom(stats,time) importFrom(stats,ts) +importFrom(utils,data) diff --git a/R/FOCUS_GW_scenarios_2012.R b/R/FOCUS_GW_scenarios_2012.R index 49cf7dd..e26ea50 100644 --- a/R/FOCUS_GW_scenarios_2012.R +++ b/R/FOCUS_GW_scenarios_2012.R @@ -1,11 +1,69 @@ #' A very small subset of the FOCUS Groundwater scenario defitions #' -#' 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). #' #' @name FOCUS_GW_scenarios_2012 #' @references FOCUS (2012) Generic guidance for Tier 1 FOCUS ground water assessments. Version 2.1. #' FOrum for the Co-ordination of pesticde fate models and their USe. #' http://focus.jrc.ec.europa.eu/gw/docs/Generic_guidance_FOCV2_1.pdf +#' @export #' @examples #' FOCUS_GW_scenarios_2012 -NULL +FOCUS_GW_scenarios_2012 = list() + +n_layers = c(7, 6, 6, 5, 5, 6, 4, 6, 6) +acronyms = c("Cha", "Ham", "Jok", "Kre", "Oke", "Pia", "Por", "Sev", "Thi") +FOCUS_GW_scenarios_2012$names = c("Ch\u00e2teaudun", "Hamburg", "Jokioinen", + "Kremsm\u00fcnster", "Okehampton", + "Piacenza", "Porto", "Sevilla", "Thiva") + +names(FOCUS_GW_scenarios_2012$names) = acronyms +FOCUS_GW_scenarios_2012$soils <- data.frame( + location= rep(acronyms, times = n_layers), + horizon = c("Ap", "B1", "B2", "II C1", "II C1", "II C2", "M", + "Ap", "BvI", "BvII", "Bv/Cv", "Cv", "Cv", + "Ap", "Bs", "BC1", "BC2", "BC2", "Cg", + rep(NA, 5), + "A", "Bw1", "BC", "C", "C", + "Ap", "Ap", "Bw", "Bw", "2C", "2C", + rep(NA, 4), + rep(NA, 6), + "Ap1", "Ap2", "Bw", "Bw", "Ck1", "Ck1"), + number = unlist(sapply(n_layers, function(x) 1:x)), + pH_H2O = c(8.0, 8.1, 8.2, 8.5, 8.5, 8.5, 8.3, + 6.4, 5.6, 5.6, 5.7, 5.5, 5.5, + 6.2, 5.6, 5.4, 5.4, 5.4, 5.3, + 7.7, 7.0, 7.1, 7.1, 7.1, + 5.8, 6.3, 6.5, 6.6, 6.6, + 7, 7, 6.3, 6.3, 6.4, 6.4, + 4.9, 4.8, 4.8, 4.8, + 7.3, 7.3, 7.8, 8.1, 8.1, 8.2, + 7.7, 7.7, 7.8, 7.8, 7.8, 7.8), + perc_clay = c(30, 31, 25, 26, 26, 24, 31, + 7.2, 6.7, 0.9, 0, 0, 0, + 3.6, 1.8, 1.2, 1.7, 1.7, 1.9, + 14, 25, 27, 27, 27, + 18, 17, 14, 9, 9, + 15, 15, 7, 7, 0, 0, + 10, 8, 8, 8, + 14, 13, 15, 16, 16, 22, + 25.3, 25.3, 29.6, 31.9, 32.9, 32.9), + perc_oc = c(1.39, 0.93, 0.7, 0.3, 0.3, 0.27, 0.21, + 1.5, 1, 0.2, 0, 0, 0, + 4.06, 0.84, 0.36, 0.29, 0.29, 0.21, + 3.6, 1.0, 0.5, 0.5, 0.5, + 2.2, 0.7, 0.4, 0.1, 0.1, + 1.26, 1.26, 0.47, 0.47, 0, 0, + 1.42, 0.78, 0.78, 0.78, + 0.93, 0.93, 0.70, 0.58, 0.58, 0.49, + 0.74, 0.74, 0.57, 0.31, 0.18, 0.18), + rel_deg = c(1, 0.5, 0.5, 0.3, 0, 0, 0, + 1, 0.5, 0.3, 0.3, 0.3, 0, + 1, 0.5, 0.3, 0.3, 0, 0, + 1, 0.5, 0.5, 0.3, 0, + 1, 0.5, 0.3, 0.3, 0, + 1, 0.5, 0.5, 0.3, 0.3, 0, + 1, 0.5, 0.3, 0, + 1, 1, 0.5, 0.3, 0, 0, + 1, 0.5, 0.5, 0.3, 0.3, 0)) diff --git a/R/FOCUS_PELMO_data.R b/R/FOCUS_PELMO_data.R new file mode 100644 index 0000000..28888e7 --- /dev/null +++ b/R/FOCUS_PELMO_data.R @@ -0,0 +1,90 @@ +#' FOCUS PELMO crop names +#' +#' 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 +#' in the three letter code, i.e. 'Peas (animals)' has the code \code{ape}. +#' +#' @docType data +#' @export +#' @examples +#' print(FOCUS_PELMO_crops) +FOCUS_PELMO_crops = c( + app = "Apples", + gra = "Grass and alfalfa", + pot = "Potatoes", + sug = "Sugar beets", + win = "Winter cereals", + fbe = "Beans (field)", + vbe = "Beans (vegetables)", + bus = "Bushberries", + cab = "Cabbage", + car = "Carrots", + cit = "Citrus", + cot = "Cotton", + lin = "Linseed", + mai = "Maize", + soi = "Oil seed rape (summer)", + woi = "Oil seed rape (winter)", + oni = "Onions", + ape = "Peas (animals)", + soy = "Soybeans", + spr = "Spring cereals", + str = "Strawberries", + sun = "Sunflower", + tob = "Tobacco", + tom = "Tomatoes", + vin = "Vines") + +#' 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 +#' print(FOCUS_PELMO_crop_sze_names) +FOCUS_PELMO_crop_sze_names = c( + app = "apples", + gra = "grass", + pot = "potato", + sug = "sbeets", + win = "wcerea", + fbe = "beans", + vbe = "beans", # Same sze as for fbe is used, with 'irrigation' which has no effect on the run + bus = "bushb", + cab = "cabbag", + car = "carrot", + cit = "citrus", + cot = "cotton", + lin = "linse", + mai = "maize", + soi = "rapesu", + woi = "rapewi", + oni = "onions", + ape = "peas", + soy = "soyb", + spr = "scerea", + str = "strawb", + sun = "sunflo", + tob = "tobacc", + tom = "tomato", + vin = "vines") + +#' Location codes in FOCUS PELMO +#' +#' A named character vector of one letter location codes used in FOCUS PELMO, +#' indexed by three letter acronyms. + +#' @docType data +#' @export +#' @examples +#' print(FOCUS_PELMO_location_codes) +FOCUS_PELMO_location_codes = c( + 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 new file mode 100644 index 0000000..7430b40 --- /dev/null +++ b/R/PELMO_runs.R @@ -0,0 +1,296 @@ +#' Set up runs for FOCUS PELMO +#' +#' Per default, the runs are also executed with FOCUS PELMO, and the results are processed +#' and returned. +#' +#' @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, +#' as used in \code{\link{FOCUS_PELMO_crops}}, +#' that hold character vectors of three letter scenario acronyms +#' as used in \code{\link{FOCUS_GW_scenarios_2012}}. +#' @param psm_dir The directory where the psm files are located +#' @param version The FOCUS PELMO version +#' @param PELMO_base Where the FOCUS PELMO installation is located +#' @param execute Should PELMO be executed directly? +#' @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 +#' @export +PELMO_runs <- function(runs, psm_dir = ".", version = "5.5.3", PELMO_base = "auto", + execute = TRUE, cores = getOption("mc.cores", 2L), + evaluate = TRUE, overwrite = FALSE) +{ + if (PELMO_base[1] == "auto") { + PELMO_base = file.path(system.file(package = "PELMO.installeR"), + paste0("FOCUSPELMO.", gsub("\\.", "", version))) + } + PELMO_exe = list.files(PELMO_base, "^pelmo.*.exe", full.names = TRUE) + if (length(PELMO_exe) == 0) { + stop("Could not find PELMO executable. Did you run PELMO.installeR::install_PELMO()?") + } + + run_list <- create_run_list(runs, psm_dir = psm_dir, check_psm_files = TRUE) + + setup_run <- function(x) { + psm <- x$psm + crop <- x$crop + scenario <- x$scenario + + location_code <- FOCUS_PELMO_location_codes[scenario] + + run_dir <- file.path(PELMO_base, "FOCUS", PELMO_path(psm, crop, scenario)) + + if (dir.exists(run_dir)) { + if (overwrite) { + unlink(run_dir, recursive = TRUE) + } else { + stop("Run directory for ", crop, " in ", scenario, "\n", run_dir, "\nalready exists") + } + } + + # Create the run directory + dir.create(run_dir, recursive = TRUE) + + # Copy the psm file + psm_file <- file.path(psm_dir, paste0(psm, ".psm")) + file.copy(psm_file, run_dir) + + # Copy Haude factors + file.copy(file.path(PELMO_base, "FOCUS", "HAUDE.DAT"), file.path(run_dir, "Haude.dat")) + + # Copy scenario file + sze_file_upper <- paste0(location_code, "_", + toupper(FOCUS_PELMO_crop_sze_names[crop]), ".sze") + sze_file_lower <- paste0(location_code, "_", + FOCUS_PELMO_crop_sze_names[crop], ".sze") + if (file.exists(file.path(PELMO_base, "FOCUS", sze_file_lower))) { + sze_file <- sze_file_lower + } else { + if (file.exists(file.path(PELMO_base, "FOCUS", sze_file_upper))) { + sze_file <- sze_file_upper + } else { + stop("Could not find szenario file for ", crop, " in ", scenario) + } + } + file.copy(file.path(PELMO_base, "FOCUS", sze_file), file.path(run_dir, sze_file_lower)) + + # Generate PELMO input file + input_file <- file(file.path(run_dir, "pelmo.inp"), encoding = "latin1", open = "w+") + on.exit(close(input_file)) + + 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 + + n_years <- switch(as.character(period), + "1" = 26, + "2" = 46, + "3" = 66) + + # First line with number of climate years + add(paste0(formatC(n_years, width = 3, flag = "0"), + " 01 01 31 12 Version ", substr(version, 1, 1))) + + # Second line with scenario file (why did we copy it, if this line refers to the FOCUS dir... + add(paste0("..\\..\\..\\", sze_file_lower)) + + # Third line with psm file + add(basename(psm_file)) + + # Lines with climate files + for (year in 1:n_years) { + add(paste0("..\\..\\..\\", location_code, "_", formatC(year, width = 2, flag = "0"), ".cli")) + } + + # Output control section + add("00000015 00.") + add(" PRSN TSER 000.0 1.0 00000001") + add(" TETD TSER 000.0 1.0 00000001") + add(" INFL TSER 100.0 1.0 00000001") + add(" RUNF TSER 000.0 1.0 00000001") + add(" THET TSER 000.0 1.0 00000001") + add(" THET TSER 030.0 1.0 00000001") + add(" TEMP TSER 000.0 1.0 00000001") + add(" TEMP TSER 030.0 1.0 00000001") + add(" TPAP TSER 000.0 1.0E05 00000001") + add(" TDKF TSER 000.0 1.0E05 00000001") + add(" TUPF TSER 000.0 1.0E05 00000001") + add(" TPST TSER 005.0 1.0E06 00000001") + add(" PFLX TSER 100.0 1.0E05 00000001") + add(" RFLX TSER 000.0 1.0E05 00000001") + add(" LEAC TSER 100.0 1.0E09 00000001") + + # Copy pelmo executable + file.copy(PELMO_exe, run_dir) + + # In addition to the files copied by the FOCUS PELMO GUI, we + # need the error file in the run directory, as we start + # the exe file from this directory + file.copy(file.path(PELMO_base, "lf90.eer"), run_dir) + } + + lapply(run_list, setup_run) + + if (execute) { + run_PELMO(runs, version = version, PELMO_base = PELMO_base) + } +} + +#' Run PELMO +#' +#' @inheritParams PELMO_runs +#' @importFrom parallel mclapply +#' @export +run_PELMO <- function(runs, psm_dir = ".", version = "5.5.3", PELMO_base = "auto", + cores = getOption("mc.cores", 2L)) +{ + + if (PELMO_base[1] == "auto") { + PELMO_base = file.path(system.file(package = "PELMO.installeR"), + paste0("FOCUSPELMO.", gsub("\\.", "", version))) + } + + pelmo_exe = list.files(PELMO_base, "^pelmo.*.exe") + + # Create list of runs to traverse using mclapply + run_list <- create_run_list(runs, check_psm_files = FALSE) + + # In order to run in parallel, we need to make a directory tree starting + # from the base of the PELMO installation, as pelmo401.exe seems to look + # for ..\..\..\summary.PLM and does not start if this is in use by another + # instance + run_exe <- function(x) { + psm <- x$psm + crop <- x$crop + scenario <- x$scenario + run_dir <- file.path(PELMO_base, "FOCUS", PELMO_path(psm, crop, scenario)) + exe_dir <- file.path(PELMO_base, paste(sample(c(0:9, letters, LETTERS), + size = 8, replace = TRUE), + collapse = "")) + dir.create(exe_dir) + + # Fresh PELMO base directory for every run with random name + run_dir_exe <- file.path(exe_dir, "FOCUS", PELMO_path(psm, crop, scenario)) + dir.create(run_dir_exe, recursive = TRUE) + + # Copy the contents of the run directory + run_files <- list.files(run_dir, full.names = TRUE) + file.copy(run_files, run_dir_exe) + + # Copy FOCUS files + location_code <- FOCUS_PELMO_location_codes[x$scenario] + location_files <- list.files(file.path(PELMO_base, "FOCUS"), paste0("^", location_code), + full.names = TRUE) + focus_dir_exe <- file.path(exe_dir, "FOCUS") + file.copy(location_files, focus_dir_exe) + file.copy(file.path(PELMO_base, "FOCUS", "FOCUSCHECK.DAT"), focus_dir_exe) + + # We need to go the directory to simplify calling pelmo with wine + setwd(run_dir_exe) + psm_file <- file.path(psm_dir, paste0(psm, ".psm")) + system(paste("wine", pelmo_exe, psm_file), ignore.stdout = TRUE) + + # Copy the results to the original run directory + plm_files <- list.files(run_dir_exe, ".plm$", full.names = TRUE) + PLM_files <- list.files(run_dir_exe, ".PLM$", full.names = TRUE) + file.copy(c(plm_files, PLM_files), run_dir) + + # Clean up + unlink(exe_dir, recursive = TRUE) + } + + mclapply(run_list, run_exe, mc.cores = cores) +} + +#' Create a path of run directories as the PELMO GUI does +#' +#' @export +#' @importFrom utils data +#' @param psm The psm identifier +#' @param crop The PELMO crop acronym +#' @param scenario The scenario +PELMO_path <- function(psm, crop, scenario) { + if (crop %in% names(FOCUS_PELMO_crops)) { + crop <- FOCUS_PELMO_crops[crop] + } + if (!crop %in% FOCUS_PELMO_crops) stop(crop, " is not in FOCUS_PELMO_crops.") + psm_dir <- paste0(psm, ".run") + crop_dir <- paste0(gsub(" ", "_-_", crop), ".run") + + # Deal with 'irrigation'. It only affects the naming of the scenario directory, + # but it does not appear to affect the PELMO run. This can be seen when + # comparing runs set up for Beans (field) and Beans (vegetable) for the Porto + # scenario + irrigation_string <- "" + + # 'Irrigation' is only possible in the GUI for five scenarios + if (scenario %in% c("Cha", "Pia", "Por", "Sev", "Thi")) { + crop_acronyms <- names(FOCUS_PELMO_crops) + names(crop_acronyms) <- FOCUS_PELMO_crops + crop_acronym <- crop_acronyms[[crop]] + # Some crops are not 'irrigated' according to the GUI + if (crop_acronym %in% c("win", "fbe", "woi", "ape", "spr")) { + irrigation_string <- "--_-_no_-_irrigation" + } else { + irrigation_string <- "--_-_irrigated" + } + } + + scenario_dir <- paste0( + FOCUS_GW_scenarios_2012$names[scenario], "_-_(", FOCUS_PELMO_location_codes[scenario], ")", + irrigation_string, ".run") + + return(file.path(psm_dir, crop_dir, scenario_dir)) +} + +#' Create a list of runs that we can traverse +#' +#' @inheritParams PELMO_runs +#' @param check_psm_files Should we check if the psm file exists +create_run_list <- function(runs, psm_dir = ".", check_psm_files = FALSE) { + i <- 0 + run_list <- list() + for (run in runs) { + psm <- run$psm + if (check_psm_files) { + psm_file <- file.path(psm_dir, paste0(psm, ".psm")) + if (file.access(psm_file) == -1) { + stop(psm_file, " is not readable") + } + } + crops <- setdiff(names(run), "psm") + for (crop in crops) { + crop_acronyms <- names(FOCUS_PELMO_crops) + names(crop_acronyms) <- FOCUS_PELMO_crops + if (!crop %in% crop_acronyms) { + if (crop %in% FOCUS_PELMO_crops) { + crop <- crop_acronyms[crop] + } else { + stop("Invalid crop specification ", crop) + } + } + for (scenario in run[[crop]]) { + i <- i + 1 + run_list[[i]] <- list(psm = psm, crop = crop, scenario = scenario) + } + } + } + return(run_list) +} diff --git a/data/FOCUS_GW_scenarios_2012.RData b/data/FOCUS_GW_scenarios_2012.RData deleted file mode 100644 index 4b2622e..0000000 Binary files a/data/FOCUS_GW_scenarios_2012.RData and /dev/null differ diff --git a/man/FOCUS_GW_scenarios_2012.Rd b/man/FOCUS_GW_scenarios_2012.Rd index f2417d9..a19bbe5 100644 --- a/man/FOCUS_GW_scenarios_2012.Rd +++ b/man/FOCUS_GW_scenarios_2012.Rd @@ -1,10 +1,16 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/FOCUS_GW_scenarios_2012.R +\docType{data} \name{FOCUS_GW_scenarios_2012} \alias{FOCUS_GW_scenarios_2012} \title{A very small subset of the FOCUS Groundwater scenario defitions} +\format{An object of class \code{list} of length 2.} +\usage{ +FOCUS_GW_scenarios_2012 +} \description{ -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). } \examples{ FOCUS_GW_scenarios_2012 @@ -14,3 +20,4 @@ FOCUS (2012) Generic guidance for Tier 1 FOCUS ground water assessments. Version FOrum for the Co-ordination of pesticde fate models and their USe. http://focus.jrc.ec.europa.eu/gw/docs/Generic_guidance_FOCV2_1.pdf } +\keyword{datasets} diff --git a/man/FOCUS_PELMO_crop_sze_names.Rd b/man/FOCUS_PELMO_crop_sze_names.Rd new file mode 100644 index 0000000..180c011 --- /dev/null +++ b/man/FOCUS_PELMO_crop_sze_names.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/FOCUS_PELMO_data.R +\docType{data} +\name{FOCUS_PELMO_crop_sze_names} +\alias{FOCUS_PELMO_crop_sze_names} +\title{FOCUS PELMO crop acronyms used for naming sceneario files} +\format{An object of class \code{character} of length 25.} +\usage{ +FOCUS_PELMO_crop_sze_names +} +\description{ +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. +} +\examples{ +print(FOCUS_PELMO_crop_sze_names) +} +\keyword{datasets} diff --git a/man/FOCUS_PELMO_crops.Rd b/man/FOCUS_PELMO_crops.Rd new file mode 100644 index 0000000..f6a41b4 --- /dev/null +++ b/man/FOCUS_PELMO_crops.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/FOCUS_PELMO_data.R +\docType{data} +\name{FOCUS_PELMO_crops} +\alias{FOCUS_PELMO_crops} +\title{FOCUS PELMO crop names} +\format{An object of class \code{character} of length 25.} +\usage{ +FOCUS_PELMO_crops +} +\description{ +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 +in the three letter code, i.e. 'Peas (animals)' has the code \code{ape}. +} +\examples{ +print(FOCUS_PELMO_crops) +} +\keyword{datasets} diff --git a/man/FOCUS_PELMO_location_codes.Rd b/man/FOCUS_PELMO_location_codes.Rd new file mode 100644 index 0000000..961a840 --- /dev/null +++ b/man/FOCUS_PELMO_location_codes.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/FOCUS_PELMO_data.R +\docType{data} +\name{FOCUS_PELMO_location_codes} +\alias{FOCUS_PELMO_location_codes} +\title{Location codes in FOCUS PELMO} +\format{An object of class \code{character} of length 9.} +\usage{ +FOCUS_PELMO_location_codes +} +\description{ +A named character vector of one letter location codes used in FOCUS PELMO, +indexed by three letter acronyms. +} +\examples{ +print(FOCUS_PELMO_location_codes) +} +\keyword{datasets} diff --git a/man/PELMO_path.Rd b/man/PELMO_path.Rd new file mode 100644 index 0000000..e8ca50e --- /dev/null +++ b/man/PELMO_path.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PELMO_runs.R +\name{PELMO_path} +\alias{PELMO_path} +\title{Create a path of run directories as the PELMO GUI does} +\usage{ +PELMO_path(psm, crop, scenario) +} +\arguments{ +\item{psm}{The psm identifier} + +\item{crop}{The PELMO crop acronym} + +\item{scenario}{The scenario} +} +\description{ +Create a path of run directories as the PELMO GUI does +} diff --git a/man/PELMO_runs.Rd b/man/PELMO_runs.Rd new file mode 100644 index 0000000..71fe6ef --- /dev/null +++ b/man/PELMO_runs.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PELMO_runs.R +\name{PELMO_runs} +\alias{PELMO_runs} +\title{Set up runs for FOCUS PELMO} +\usage{ +PELMO_runs(runs, psm_dir = ".", version = "5.5.3", PELMO_base = "auto", + execute = TRUE, cores = getOption("mc.cores", 2L), evaluate = TRUE, + overwrite = FALSE) +} +\arguments{ +\item{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, +as used in \code{\link{FOCUS_PELMO_crops}}, +that hold character vectors of three letter scenario acronyms +as used in \code{\link{FOCUS_GW_scenarios_2012}}.} + +\item{psm_dir}{The directory where the psm files are located} + +\item{version}{The FOCUS PELMO version} + +\item{PELMO_base}{Where the FOCUS PELMO installation is located} + +\item{execute}{Should PELMO be executed directly?} + +\item{cores}{The number of cores to execute PELMO runs in parallel} + +\item{evaluate}{Should the results be returned?} + +\item{overwrite}{Should an existing run directories be overwritten} +} +\description{ +Per default, the runs are also executed with FOCUS PELMO, and the results are processed +and returned. +} diff --git a/man/create_run_list.Rd b/man/create_run_list.Rd new file mode 100644 index 0000000..3151165 --- /dev/null +++ b/man/create_run_list.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PELMO_runs.R +\name{create_run_list} +\alias{create_run_list} +\title{Create a list of runs that we can traverse} +\usage{ +create_run_list(runs, psm_dir = ".", check_psm_files = FALSE) +} +\arguments{ +\item{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, +as used in \code{\link{FOCUS_PELMO_crops}}, +that hold character vectors of three letter scenario acronyms +as used in \code{\link{FOCUS_GW_scenarios_2012}}.} + +\item{psm_dir}{The directory where the psm files are located} + +\item{check_psm_files}{Should we check if the psm file exists} +} +\description{ +Create a list of runs that we can traverse +} diff --git a/man/run_PELMO.Rd b/man/run_PELMO.Rd new file mode 100644 index 0000000..a286c5c --- /dev/null +++ b/man/run_PELMO.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/PELMO_runs.R +\name{run_PELMO} +\alias{run_PELMO} +\title{Run PELMO} +\usage{ +run_PELMO(runs, psm_dir = ".", version = "5.5.3", PELMO_base = "auto", + cores = getOption("mc.cores", 2L)) +} +\arguments{ +\item{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, +as used in \code{\link{FOCUS_PELMO_crops}}, +that hold character vectors of three letter scenario acronyms +as used in \code{\link{FOCUS_GW_scenarios_2012}}.} + +\item{psm_dir}{The directory where the psm files are located} + +\item{version}{The FOCUS PELMO version} + +\item{PELMO_base}{Where the FOCUS PELMO installation is located} + +\item{cores}{The number of cores to execute PELMO runs in parallel} +} +\description{ +Run PELMO +} diff --git a/tests/testthat/test_PELMO.R b/tests/testthat/test_PELMO.R new file mode 100644 index 0000000..4bd36ef --- /dev/null +++ b/tests/testthat/test_PELMO.R @@ -0,0 +1,101 @@ +# Remove when the test is ready to be run by testthat +#library(testthat) +#test_dir <- "/tmp/Rtmp8DFCT5" +#psm_name <- "D_rel_1" +#source("~/git/pfm/inst/extdata/FOCUS_PELMO_data.R") +#source("~/git/pfm/R/PELMO_runs.R") + +library(pfm) +context("Create PELMO runs from psm files and execute them") +PELMO_base <- system.file("FOCUSPELMO.553", package = "PELMO.installeR") + +test_archive <- system.file("testdata/FOCUS_PELMO.tar.bz2", package = "pfm") +test_dir <- tempdir() +untar(test_archive, exdir = test_dir, compressed = "bzip2") + +runs <- list( + list( + psm = "Pesticide_D", + fbe = c("Por"), + vbe = c("Por")), + list( + psm = "Pesticide_D_1_day_pre_em_every_third_year", + pot = c("Cha", "Ham")), + list( + psm = "Pesticide_D_1_May_every_other_year", + mai = c("Cha"))) + +psm_paths = c( + D_rel_1 = PELMO_path(runs[1]$psm, "fbe", "Por"), + D_rel_3 = PELMO_path(runs[2]$psm, "pot", "Ham"), + D_abs_2 = PELMO_path(runs[3]$psm, "mai", "Cha")) + +# Get psm files and put them into PELMO_base +psm_new_locations <- character(0) +for (psm_name in names(psm_paths)) { + psm_file <- file.path(test_dir, psm_paths[psm_name], paste0(runs[1]$psm, ".psm")) + psm_new_location <- file.path(PELMO_base, basename(psm_file)) + psm_new_locations[psm_name] <- psm_new_location + file.copy(psm_file, psm_new_location) +} + +test_that("PELMO runs are correctly set up", { + + # Prepare runs in analogy to the test archive + PELMO_runs(runs, psm_dir = PELMO_base, execute = FALSE, overwrite = TRUE) + + # Check that input files are correctly generated in the right location + for (run in runs) { + psm <- run$psm + message(psm) + crops <- setdiff(names(run), "psm") + for (crop in crops) { + message(crop) + for (scenario in run[[crop]]) { + message(scenario) + pp <- PELMO_path(psm, crop, scenario) + + input_new <- readLines(file.path(PELMO_base, "FOCUS", pp, "pelmo.inp")) + input_test <- readLines(file.path(test_dir, pp, "pelmo.inp")) + + # Check if the input files are correctly reproduced + expect_identical(input_new, input_test) + } + } + } +}) + +test_that("PELMO runs can be run and give the expected result files", { + run_PELMO(runs, psm_dir = PELMO_base, cores = 5) + + plm_files <- c("CHEM.PLM", "ECHO.PLM", "KONZCHEM.PLM", "PLNTPEST.plm", + "PLOT.PLM", "WASSER.PLM") + + # Check that if output is the same as in the test archive + for (run in runs) { + psm <- run$psm + crops <- setdiff(names(run), "psm") + for (crop in crops) { + # message(crop) + for (scenario in run[[crop]]) { + # message(scenario) + pp <- PELMO_path(psm, crop, scenario) + + for (plm in plm_files) { + new <- readLines(file.path(PELMO_base, "FOCUS", pp, plm)) + test <- readLines(file.path(test_dir, pp, plm)) + + # Check if the ouput files are correctly reproduced + expect_identical(new, test) + } + } + } + } +}) + +test_that("PELMO runs are correctly evaluated", { + +}) + +# Clean up +unlink(psm_new_locations) diff --git a/tests/testthat/test_TOXSWA.R b/tests/testthat/test_TOXSWA.R new file mode 100644 index 0000000..7c9a73c --- /dev/null +++ b/tests/testthat/test_TOXSWA.R @@ -0,0 +1,56 @@ +library(pfm) +context("Read and analyse TOXSWA cwa files") + +zipfile_test = system.file("testdata/SwashProjects.zip", package = "pfm") +basedir_test = "SwashProjects/project_H_sw/TOXSWA" + +H_sw_D4_pond <- read.TOXSWA_cwa("00001p_pa.cwa", + basedir = basedir_test, + zipfile = zipfile_test) + +H_sw_R1_stream <- read.TOXSWA_cwa("00003s_pa.cwa", + basedir = basedir_test, + zipfile = zipfile_test) + +basedir_test_2 = "SwashProjects/Project_1/TOXSWA" + +EXSW2_R1_stream <- read.TOXSWA_cwa("3.out", + basedir = basedir_test_2, + zipfile = zipfile_test) + + + +test_that("TOXSWA cwa file is correctly read and printed", { + + # This was the setting when printing the output into text files + options(width = 100) + + # Most content of the R6 object is at least partially printed + + H_sw_D4_pond_printed <- capture.output(print(H_sw_D4_pond)) + + expect_equal(H_sw_D4_pond_printed, readLines("H_sw_D4_pond_printed.txt")) + + H_sw_R1_stream_printed <- capture.output(print(H_sw_R1_stream)) + expect_equal(H_sw_R1_stream_printed, readLines("H_sw_R1_stream_printed.txt")) + + # The basedir is not printed, therefore tested separately + expect_equal(H_sw_D4_pond$basedir, basedir_test) + + EXSW2_R1_stream_printed <- capture.output(print(EXSW2_R1_stream)) + expect_equal(EXSW2_R1_stream_printed, readLines("EXSW2_R1_stream_printed.txt")) + + # The basedir is not printed, therefore tested separately + expect_equal(H_sw_D4_pond$basedir, basedir_test) +}) + +test_that("Getting events and moving window analysis works", { + + # Event analysis with two different thresholds + H_sw_R1_stream$get_events(c(2, 10)) + expect_equal_to_reference(H_sw_R1_stream$events, file = "H_sw_R1_stream_events.rds") + + # Moving window analysis + H_sw_R1_stream$moving_windows(c(7, 21)) + expect_equal_to_reference(H_sw_R1_stream$windows, file = "H_sw_R1_stream_windows.rds") +}) diff --git a/tests/testthat/test_TOXSWA_cwa.R b/tests/testthat/test_TOXSWA_cwa.R deleted file mode 100644 index 7c9a73c..0000000 --- a/tests/testthat/test_TOXSWA_cwa.R +++ /dev/null @@ -1,56 +0,0 @@ -library(pfm) -context("Read and analyse TOXSWA cwa files") - -zipfile_test = system.file("testdata/SwashProjects.zip", package = "pfm") -basedir_test = "SwashProjects/project_H_sw/TOXSWA" - -H_sw_D4_pond <- read.TOXSWA_cwa("00001p_pa.cwa", - basedir = basedir_test, - zipfile = zipfile_test) - -H_sw_R1_stream <- read.TOXSWA_cwa("00003s_pa.cwa", - basedir = basedir_test, - zipfile = zipfile_test) - -basedir_test_2 = "SwashProjects/Project_1/TOXSWA" - -EXSW2_R1_stream <- read.TOXSWA_cwa("3.out", - basedir = basedir_test_2, - zipfile = zipfile_test) - - - -test_that("TOXSWA cwa file is correctly read and printed", { - - # This was the setting when printing the output into text files - options(width = 100) - - # Most content of the R6 object is at least partially printed - - H_sw_D4_pond_printed <- capture.output(print(H_sw_D4_pond)) - - expect_equal(H_sw_D4_pond_printed, readLines("H_sw_D4_pond_printed.txt")) - - H_sw_R1_stream_printed <- capture.output(print(H_sw_R1_stream)) - expect_equal(H_sw_R1_stream_printed, readLines("H_sw_R1_stream_printed.txt")) - - # The basedir is not printed, therefore tested separately - expect_equal(H_sw_D4_pond$basedir, basedir_test) - - EXSW2_R1_stream_printed <- capture.output(print(EXSW2_R1_stream)) - expect_equal(EXSW2_R1_stream_printed, readLines("EXSW2_R1_stream_printed.txt")) - - # The basedir is not printed, therefore tested separately - expect_equal(H_sw_D4_pond$basedir, basedir_test) -}) - -test_that("Getting events and moving window analysis works", { - - # Event analysis with two different thresholds - H_sw_R1_stream$get_events(c(2, 10)) - expect_equal_to_reference(H_sw_R1_stream$events, file = "H_sw_R1_stream_events.rds") - - # Moving window analysis - H_sw_R1_stream$moving_windows(c(7, 21)) - expect_equal_to_reference(H_sw_R1_stream$windows, file = "H_sw_R1_stream_windows.rds") -}) -- cgit v1.2.1