diff --git a/DESCRIPTION b/DESCRIPTION index cac02a9d..a5991ad5 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,15 +1,25 @@ Package: Rsoilwat31 Version: 1.0.1 -Date: 06-22-2016 +Date: 07-01-2016 Title: SoilWat v31 Authors@R: c(person("Ryan", "Murphy", role = "aut", email = "not@available.com"), person("Daniel", "Schlaepfer", role = c("aut", "cre"), email = "daniel.schlaepfer@unibas.ch"), person("John", "Bradford", role = "ctb", email = "not@available.com"), person("William", "Lauenroth", role = "ctb", email = "not@available.com")) -Depends: R (>= 2.12.0), RSQLite -Description: SoilWat package is a R wrapper for the SOILWAT C code. It allows data to be accessed directly via memory. This package currently uses SOILWAT v3.2.0. +Depends: + R (>= 2.15.0) +Imports: + methods +Suggests: + RSQLite (>= 1.0.0), + DBI (>= 0.4.1), + testthat +Description: SoilWat package is a R wrapper for the SOILWAT C code. It allows + data to be accessed directly via memory. This package currently uses SOILWAT + v3.2.0. LazyData: true ByteCompile: true License: GPL (>= 3) URL: https://github.com/Burke-Lauenroth-Lab/Rsoilwat/tree/Rsoilwat_v31 BugReports: https://github.com/Burke-Lauenroth-Lab/Rsoilwat/issues +RoxygenNote: 5.0.1 diff --git a/NAMESPACE b/NAMESPACE index c132f473..09e89b5b 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -24,7 +24,11 @@ dbW_dataframe_to_weatherData, dbW_weather_to_SOILWATfiles, dbW_weatherData_to_monthly, -dbW_dataframe_to_monthly) +dbW_dataframe_to_monthly, + +dbW_upgrade_v3to31, +dbW_upgrade_v2to3, +dbW_upgrade_v1to2) exportClasses( swFiles, diff --git a/R/Rsoilwat31.R b/R/Rsoilwat31.R new file mode 100644 index 00000000..b4bd98a1 --- /dev/null +++ b/R/Rsoilwat31.R @@ -0,0 +1,199 @@ +#' Package `Rsoilwat31': summary information +#' +#' The package `Rsoilwat' / 'Rsoilwat31' is a R implementation of SoilWat +#' Modeling Software. The C code was converted into a library with +#' input/output functions to R. SoilWat is a simulator of the dynamics of soil +#' water. Originally written in the 1900's by a highly trained team of Botany's +#' finest. It is now maintained by Dr. William Lauenroth's Lab and Dr. Daniel +#' Schlaepfer. The input data structure is S4. Generic functions that +#' apply to the input container or individual object control setting/getting +#' input data. Output data is in the form of lists. +#' +#' +#' @aliases Rsoilwat31 Rsoilwat31-package +#' @section Version: The version level of the package is given by the command +#' \code{packageDescription("Rsoilwat31")}. The most recent version of the +#' package can be obtained from github at +#' \url{https://github.com/Burke-Lauenroth-Lab/Rsoilwat} +#' @seealso \itemize{ \item \code{\link{sw_exec}} for running a simulation +#' \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +#' data input \item \code{\link{dbW_getWeatherData}} and +#' \code{\link{getWeatherData_folders}} for weather data input } +#' @references Bradford, J. B., D. R. Schlaepfer, and W. K. Lauenroth (2014) +#' Ecohydrology of adjacent sagebrush and lodgepole pine ecosystems: The +#' consequences of climate change and disturbance. \emph{Ecosystems} +#' \bold{17}:590--605. +#' +#' Schlaepfer, D. R., W. K. Lauenroth, and J. B. Bradford (2012) +#' Ecohydrological niche of sagebrush ecosystems. \emph{Ecohydrology} +#' \bold{5}:453--466. +#' +#' Parton, W.J. (1978). \emph{Abiotic section of ELM}. In: Grassland +#' simulation model (ed. Innis, G.S.). Springer New York, NY, pp. 31--53. +#' +#' Sala, O.E., Lauenroth, W.K. & Parton, W.J. (1992) Long-term soil-water +#' dynamics in the shortgrass steppe. \emph{Ecology} \bold{73}:1175--1181. +#' +#' @docType package +#' @name Rsoilwat31 +#' @aliases Rsoilwat, SoilWat, SOILWAT, Rsoilwat-package +NULL + + + + + +#' Class \code{"swInputData"} +#' +#' %% ~~ A concise (1-5 lines) description of what the class is. ~~ This class +#' is a container class to the input file S4 objects. The generic functions +#' listed work on this and the proper sw Class in the container's slots. +#' +#' +#' @name swInputData-class +#' @aliases swInputData-class get_Markov,swInputData-method +#' get_swCloud,swInputData-method get_swFiles,swInputData-method +#' get_swOUT,swInputData-method get_swProd,swInputData-method +#' get_swSite,swInputData-method get_swSoils,swInputData-method +#' get_swSWC,swInputData-method get_swWeatherData,swInputData-method +#' get_swWeather,swInputData-method get_swYears,swInputData-method +#' get_WeatherHistory,swInputData-method set_Markov<-,swInputData-method +#' set_swCloud<-,swInputData-method set_swFiles<-,swInputData-method +#' set_swOUT<-,swInputData-method set_swProd<-,swInputData-method +#' set_swSite<-,swInputData-method set_swSoils<-,swInputData,swSoils-method +#' set_swSWC<-,swInputData,swSWC-method +#' set_swWeatherData<-,swInputData,swWeatherData-method +#' set_swWeather<-,swInputData-method set_swYears<-,swInputData-method +#' set_WeatherHistory<-,swInputData,list-method swClear,swInputData-method +#' swCloud_Humidity<-,swInputData-method swCloud_Humidity,swInputData-method +#' swCloud_SkyCover<-,swInputData-method swCloud_SkyCover,swInputData-method +#' swCloud_SnowDensity<-,swInputData-method +#' swCloud_SnowDensity,swInputData-method +#' swCloud_Transmissivity<-,swInputData-method +#' swCloud_Transmissivity,swInputData-method +#' swCloud_WindSpeed<-,swInputData-method swCloud_WindSpeed,swInputData-method +#' swFiles_Cloud<-,swInputData-method swFiles_Cloud,swInputData-method +#' swFiles_Estab<-,swInputData-method swFiles_Estab,swInputData-method +#' swFiles_filesIn<-,swInputData-method swFiles_filesIn,swInputData-method +#' swFiles_LogFile<-,swInputData-method swFiles_LogFile,swInputData-method +#' swFiles_MarkovCov<-,swInputData-method swFiles_MarkovCov,swInputData-method +#' swFiles_MarkovProbs<-,swInputData-method +#' swFiles_MarkovProbs,swInputData-method +#' swFiles_OutputPrefix<-,swInputData-method +#' swFiles_OutputPrefix,swInputData-method swFiles_Output<-,swInputData-method +#' swFiles_Output,swInputData-method swFiles_Prod<-,swInputData-method +#' swFiles_Prod,swInputData-method swFiles_ProjDir<-,swInputData-method +#' swFiles_ProjDir,swInputData-method swFiles_SiteParams<-,swInputData-method +#' swFiles_SiteParams,swInputData-method swFiles_Soils<-,swInputData-method +#' swFiles_Soils,swInputData-method swFiles_SWCsetup<-,swInputData-method +#' swFiles_SWCsetup,swInputData-method +#' swFiles_WeatherPrefix<-,swInputData-method +#' swFiles_WeatherPrefix,swInputData-method +#' swFiles_WeatherSetup<-,swInputData-method +#' swFiles_WeatherSetup,swInputData-method swFiles_Years<-,swInputData-method +#' swFiles_Years,swInputData-method swLog_setLine<-,swInputData-method +#' swMarkov_Conv<-,swInputData-method swMarkov_Conv,swInputData-method +#' swMarkov_Prob<-,swInputData-method swMarkov_Prob,swInputData-method +#' swOUT_OutputSeparator<-,swInputData-method +#' swOUT_OutputSeparator,swInputData-method swOUT_TimeStep<-,swInputData-method +#' swOUT_TimeStep,swInputData-method swProd_Albedo<-,swInputData-method +#' swProd_Albedo,swInputData-method swProd_CanopyHeight<-,swInputData-method +#' swProd_CanopyHeight,swInputData-method +#' swProd_Composition<-,swInputData-method +#' swProd_Composition,swInputData-method swProd_Cover_stcr<-,swInputData-method +#' swProd_Cover_stcr,swInputData-method +#' swProd_CritSoilWaterPotential<-,swInputData-method +#' swProd_CritSoilWaterPotential,swInputData-method +#' swProd_Es_param_limit<-,swInputData-method +#' swProd_Es_param_limit,swInputData-method +#' swProd_EsTpartitioning_param<-,swInputData-method +#' swProd_EsTpartitioning_param,swInputData-method +#' swProd_HydrRedstro<-,swInputData-method +#' swProd_HydrRedstro,swInputData-method +#' swProd_HydrRedstro_use<-,swInputData-method +#' swProd_HydrRedstro_use,swInputData-method +#' swProd_LitterInterParam<-,swInputData-method +#' swProd_LitterInterParam,swInputData-method +#' swProd_MonProd_grass<-,swInputData-method +#' swProd_MonProd_grass,swInputData-method +#' swProd_MonProd_shrub<-,swInputData-method +#' swProd_MonProd_shrub,swInputData-method +#' swProd_MonProd_tree<-,swInputData-method +#' swProd_MonProd_tree,swInputData-method swProd_Shade<-,swInputData-method +#' swProd_Shade,swInputData-method swProd_VegInterParam<-,swInputData-method +#' swProd_VegInterParam,swInputData-method +#' swReadLines,swInputData,character-method +#' swSite_DrainageCoefficient<-,swInputData-method +#' swSite_DrainageCoefficient,swInputData-method +#' swSite_EvapCoefficients<-,swInputData-method +#' swSite_EvapCoefficients,swInputData-method +#' swSite_IntrinsicSiteParams<-,swInputData-method +#' swSite_IntrinsicSiteParams,swInputData-method +#' swSite_ModelCoefficients<-,swInputData-method +#' swSite_ModelCoefficients,swInputData-method +#' swSite_ModelFlags<-,swInputData-method swSite_ModelFlags,swInputData-method +#' swSite_SnowSimulationParams<-,swInputData-method +#' swSite_SnowSimulationParams,swInputData-method +#' swSite_SoilTemperatureConsts<-,swInputData-method +#' swSite_SoilTemperatureConsts,swInputData-method +#' swSite_SoilTemperatureFlag<-,swInputData-method +#' swSite_SoilTemperatureFlag,swInputData-method +#' swSite_SWClimits<-,swInputData-method swSite_SWClimits,swInputData-method +#' swSite_TranspCoefficients<-,swInputData-method +#' swSite_TranspCoefficients,swInputData-method +#' swSite_TranspirationRegions<-,swInputData-method +#' swSite_TranspirationRegions,swInputData-method +#' swSoils_Layers<-,swInputData,matrix-method swSoils_Layers,swInputData-method +#' swSWC_FirstYear<-,swInputData,integer-method +#' swSWC_FirstYear,swInputData-method +#' swSWC_HistoricData<-,swInputData,swSWC_hist-method +#' swSWC_HistoricData,swInputData-method +#' swSWC_HistoricList<-,swInputData,list-method +#' swSWC_HistoricList,swInputData-method +#' swSWC_Method<-,swInputData,integer-method swSWC_Method,swInputData-method +#' swSWC_prefix<-,swInputData,character-method swSWC_prefix,swInputData-method +#' swSWC_use<-,swInputData,logical-method swSWC_use,swInputData-method +#' swWeather_DaysRunningAverage<-,swInputData-method +#' swWeather_DaysRunningAverage,swInputData-method +#' swWeather_FirstYearHistorical<-,swInputData-method +#' swWeather_FirstYearHistorical,swInputData-method +#' swWeather_MonScalingParams<-,swInputData-method +#' swWeather_MonScalingParams,swInputData-method +#' swWeather_pct_SnowDrift<-,swInputData-method +#' swWeather_pct_SnowDrift,swInputData-method +#' swWeather_pct_SnowRunoff<-,swInputData-method +#' swWeather_pct_SnowRunoff,swInputData-method +#' swWeather_UseMarkov<-,swInputData-method +#' swWeather_UseMarkov,swInputData-method +#' swWeather_UseSnow<-,swInputData-method swWeather_UseSnow,swInputData-method +#' swWriteLines,swInputData,character-method swYears_EDOEY<-,swInputData-method +#' swYears_EDOEY,swInputData-method swYears_EndYear<-,swInputData-method +#' swYears_EndYear,swInputData-method swYears_FDOFY<-,swInputData-method +#' swYears_FDOFY,swInputData-method swYears_isNorth<-,swInputData-method +#' swYears_isNorth,swInputData-method swYears_StartYear<-,swInputData-method +#' swYears_StartYear,swInputData-method +#' @docType class +#' @note %% ~~further notes~~ +#' @section Objects from the Class: Objects can be created by calls of the form +#' \code{new("swInputData", ...)}. %% ~~ describe objects here ~~ +#' @author %% ~~who you are~~ Ryan Murphy +#' @seealso %% ~~objects to See Also as \code{\link{~~fun~~}}, ~~~ %% ~~or +#' \code{\linkS4class{CLASSNAME}} for links to other classes ~~~ +#' \code{\linkS4class{swFiles}} \code{\linkS4class{swYears}} +#' \code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} +#' \code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} +#' \code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} +#' \code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} +#' \code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} +#' @references %% ~~put references to the literature/web site here~~ +#' https://github.com/Burke-Lauenroth-Lab/Rsoilwat +#' @keywords classes +#' @examples +#' +#' showClass("swInputData") +#' +NULL + + + + diff --git a/R/Rsw.R b/R/Rsw.R index fe3908a7..3a798aa6 100644 --- a/R/Rsw.R +++ b/R/Rsw.R @@ -17,6 +17,149 @@ ############################################################################### + + +#' Execute a SOILWAT simulation run +#' +#' Run the simulation and get the output data. Executes Soil Water simulator +#' and returns Soil Water data via List. Uses .Call to pass data to/from C +#' library. +#' +#' The input data for a simulation run can be passed to the function +#' \code{\link{sw_exec}} either as \code{swInputData} and \code{weatherList} or +#' as text files organized in a folder \code{dir} and explained in +#' \code{files.in}. +#' +#' The weather data can be a part of the input data S4 class or separate as a +#' list to reduce the input object size. The option 'weatherList' if set will +#' use the weatherList provided and not the inputdata object's weather data if +#' it has it. Weather data can also be read in when 'dir' and 'files.in' are +#' set. +#' +#' SOILWAT does not handle missing data. If you have missing data, then you +#' have to impute yourself or use the built-in Markov weather generator (see +#' examples section). If you use the weather generator, then you have to +#' provide appropriate values for the input (files) 'mkv_covar.in' and +#' 'mkv_prob.in' for your simulation run - currently, SOILWAT does not contain +#' code to estimate these values. +#' +#' @param inputData an object of the S4 class \code{swInputData} which is +#' generated from \code{\link{sw_inputData}} or +#' \code{\link{sw_inputDataFromFiles}}. +#' @param weatherList a list of weather data generated via +#' \code{\link{dbW_getWeatherData}} or \code{\link{getWeatherData_folders}}. +#' @param dir a character vector that represents the path to the input data. +#' Use with files.in +#' @param files.in a character vector that represents the partial path of the +#' 'files.in' file +#' @param echo logical. This option will echo the inputs to the Log Data. +#' Helpful for debugging. +#' @param quiet logical. Quiet mode doesn't print messages to the logfile. +#' @return A S4 Object Containing 28 outputkey slots. Each of those has slots +#' for Yr Mo Wk Dy. +#' +#' NOTE: WTHR ALLH2O ET ALLVEG do not work. +#' +#' The output also contains slots for the number of rows for each time period. +#' Individual outputKeys also have slots for time periods used. Title from +#' outputsetup. They also have the number of data columns. +#' +#' These elements contain the output data from soilwat based on the +#' outputSetup. Output columns should all be labeled. +#' @author Ryan Murphy +#' @seealso \itemize{ \item \code{\link{sw_exec}} for running a simulation +#' \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +#' data input \item \code{\link{dbW_getWeatherData}} and +#' \code{\link{getWeatherData_folders}} for weather data input } +#' @references Bradford, J. B., D. R. Schlaepfer, and W. K. Lauenroth (2014) +#' Ecohydrology of adjacent sagebrush and lodgepole pine ecosystems: The +#' consequences of climate change and disturbance. \emph{Ecosystems} +#' \bold{17}:590--605. +#' +#' Schlaepfer, D. R., W. K. Lauenroth, and J. B. Bradford (2012) +#' Ecohydrological niche of sagebrush ecosystems. \emph{Ecohydrology} +#' \bold{5}:453--466. +#' +#' Parton, W.J. (1978). \emph{Abiotic section of ELM}. In: Grassland +#' simulation model (ed. Innis, G.S.). Springer New York, NY, pp. 31--53. +#' +#' Sala, O.E., Lauenroth, W.K. & Parton, W.J. (1992) Long-term soil-water +#' dynamics in the shortgrass steppe. \emph{Ecology} \bold{73}:1175--1181. +#' @examples +#' +#' ## ------ Simulation with demonstration data ------------ +#' ## Access demonstration data (including daily weather forcing) +#' sw_in <- sw_inputData() +#' +#' ## Slots of the input object of class 'swInputData' +#' str(sw_in, max.level=2) +#' +#' ## Execute the simulation run +#' sw_out <- sw_exec(inputData = sw_in) +#' +#' +#' ## ------ Directory to a SOLWAT project used in the following examples +#' path_demo <- dirname(system.file("extdata", "example1", "files_v31.in", package = "Rsoilwat31")) +#' +#' ## ------ Simulation with data read from disk during execution ------------ +#' ## Execute the simulation run +#' sw_out1 <- sw_exec(dir = path_demo, files.in = "files_v31.in") +#' +#' ## Slots of the output object of class 'swOutput' +#' str(sw_out1, max.level=2) +#' +#' +#' ## ------ Simulation with data prepared beforehand ------------ +#' ## Read inputs from files on disk (including daily weather forcing) +#' sw_in2 <- sw_inputDataFromFiles(dir = path_demo, files.in = "files_v31.in") +#' +#' ## Slots of the input object of class 'swInputData' +#' str(sw_in2, max.level=2) +#' +#' ## Execute the simulation run +#' sw_out2 <- sw_exec(inputData = sw_in2) +#' +#' +#' ## ------ Simulation with data prepared beforehand and separate weather data ------------ +#' ## Read inputs from files on disk +#' sw_in3 <- sw_inputDataFromFiles(dir = path_demo, files.in = "files_v31.in") +#' +#' ## Read forcing weather data from files on disk (there are also functions to set up a SQLite database for the weather data) +#' sw_weath3 <- getWeatherData_folders(LookupWeatherFolder=file.path(path_demo, "Input"), weatherDirName="data_weather", filebasename="weath", startYear=1979, endYear=2010) +#' +#' ## List of the slots of the input objects of class 'swWeatherData' +#' str(sw_weath3, max.level=1) +#' +#' ## Execute the simulation run +#' sw_out3 <- sw_exec(inputData = sw_in3, weatherList = sw_weath3) +#' +#' +#' ## ------ Simulation with manipulated input data ------------ +#' sw_in4 <- sw_in3 +#' +#' ## Set the vegetation composition to 40% grass and 60% shrubs +#' swProd_Composition(sw_in4) <- c(0.4, 0.6, 0, 0, 0) +#' +#' ## Execute the simulation run +#' sw_out4 <- sw_exec(inputData = sw_in4, weatherList = sw_weath3) +#' +#' +#' ## ------ Simulation with weather generator ------------ +#' ## Currently, the Markov weather generator flag must be turned on prior to reading files to disk +#' ## - otherwise, the Markov prob.in and covar.in are not being loaded (NOTE: this should be fixed) +#' path_demo2 <- dirname(system.file("extdata", "example2", "files_v31.in", package = "Rsoilwat31")) +#' sw_in5 <- sw_inputDataFromFiles(dir = path_demo2, files.in = "files_v31.in") +#' +#' ## Turn on the Markov weather generator +#' # swWeather_UseMarkov(sw_in5) <- TRUE +#' +#' ## Execute the simulation run +#' sw_out5 <- sw_exec(inputData = sw_in5, weatherList = NULL) +#' +#' +#' +#' ## See help(package = "Rsoilwat31") for a full list of functions +#' sw_exec <- function(inputData=NULL,weatherList=NULL,dir="", files.in="files_v31.in", echo=FALSE, quiet=FALSE) { input <- c("sw_v27") if(dir!="") @@ -35,6 +178,67 @@ sw_exec <- function(inputData=NULL,weatherList=NULL,dir="", files.in="files_v31. return(.Call("start",input,inputData,weatherList)) } + + +#' Rsoilwat sw_inputDataFromFiles +#' +#' Reads in a SoilWat Project's input data. Returns swInputData Object. +#' +#' swInputData Object is a S4 object containing slots for all input data. +#' Calling sw_inputDataFromFiles generates a new swInputData object with data +#' from the Project files given. +#' +#' The data returned can be directly used to run the simulation if weather Data +#' was included in the Project Directory. If weather data was not in the +#' project directory then use onGetWeatherData_database or +#' onGetWeatherData_folders to obtain weatherDataList and pass both to sw_exec. +#' +#' swInputData consists of slots for each file that is read in. These slots can +#' be accessed via the following functions: \tabular{ll}{ \code{get_Markov} +#' \tab #get markov prop and conv\cr \code{get_swCloud} \tab #get cloud\cr +#' \code{get_swFiles} \tab #get files.in\cr \code{get_swOUT} \tab #get +#' outpusetup.in\cr \code{get_swProd} \tab #get prod.in\cr \code{get_swSite} +#' \tab #get site.in\cr \code{get_swSoils} \tab #get soils.in\cr +#' \code{get_swSWC} \tab #get swcSetup.in\cr \code{get_swWeather} \tab #get +#' weatherSetup.in\cr \code{get_swWeatherData} \tab #get individual year\cr +#' \code{get_swYears} \tab #get years.in data object\cr +#' \code{get_WeatherHistory} \tab #get S4 of WeatherHistory\cr } +#' +#' generic functions to get/set individual elements follow a format: 'sw' + +#' file name + '_' + option, e.g. \itemize{ \item \code{swFiles_Cloud} \item +#' \code{swProd_Albedo} } Remember tab complete is your friend. +#' +#' SOILWAT does not handle missing weather data. If you have missing data, then +#' you have to impute yourself or use the built-in Markov weather generator +#' (see examples for \code{\link{sw_exec}}). +#' +#' @param dir String. The path to the Project Directory. Use with files.in +#' @param files.in String. The partial path, after project dir path, and file +#' name to files.in file. +#' @return Returns a S4 class of type swInputData. This is a container for the +#' input S4 objects used to run soilwat. The data for the given project is +#' loaded. +#' @author Ryan Murphy +#' @seealso \itemize{ \item \code{\link{sw_exec}} for running a simulation +#' \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +#' data input \item \code{\link{dbW_getWeatherData}} and +#' \code{\link{getWeatherData_folders}} for weather data input } +#' @examples +#' +#' path_demo <- dirname(system.file("extdata", "files_v31.in", package = "Rsoilwat31")) +#' +#' +#' ## ------ Simulation with data prepared beforehand ------------ +#' ## Read inputs from files on disk (including daily weather forcing) +#' sw_in2 <- sw_inputDataFromFiles(dir = path_demo, files.in = "files_v31.in") +#' +#' ## Slots of the input object of class 'swInputData' +#' str(sw_in2, max.level=2) +#' +#' ## Execute the simulation run +#' sw_out2 <- sw_exec(inputData = sw_in2) +#' +#' sw_inputDataFromFiles <- function(dir="", files.in="files_v30.in") { echo=FALSE quiet=FALSE @@ -57,6 +261,62 @@ sw_outputData <- function(inputData) { .Call("onGetOutput",inputData) } + + +#' Rsoilwat sw_inputData +#' +#' Default data Set for SoilWat. Use this as a template or for testing the +#' package. +#' +#' swInputData Object is a S4 object containing slots for all input data. +#' Calling sw_inputData() generates a new swInputData object with test project +#' data loaded into them. This can be used for testing or as a template to +#' build another project off of. +#' +#' The data returned can be directly used to run the simulation. Use the +#' function sw_exec and pass it the output from this function to run SW. +#' +#' \code{showMethods(class="swInputData")} # Will show all generic functions +#' that be applied to the inputData. These include getters/setters for slots. +#' +#' swInputData consists of slots for each file that is read in. These slots can +#' be accessed via the following functions: \tabular{ll}{ \code{get_Markov} +#' \tab #get markov prop and conv\cr \code{get_swCloud} \tab #get cloud\cr +#' \code{get_swFiles} \tab #get files.in\cr \code{get_swOUT} \tab #get +#' outpusetup.in\cr \code{get_swProd} \tab #get prod.in\cr \code{get_swSite} +#' \tab #get site.in\cr \code{get_swSoils} \tab #get soils.in\cr +#' \code{get_swSWC} \tab #get swcSetup.in\cr \code{get_swWeather} \tab #get +#' weatherSetup.in\cr \code{get_swWeatherData} \tab #get individual year\cr +#' \code{get_swYears} \tab #get years.in data object\cr +#' \code{get_WeatherHistory} \tab #get S4 of WeatherHistory\cr } +#' +#' generic functions to get/set individual elements follow a format: 'sw' + +#' file name + '_' + option, e.g. \itemize{ \item \code{swFiles_Cloud} \item +#' \code{swProd_Albedo} } Remember tab complete is your friend. +#' +#' SOILWAT does not handle missing data. If you have missing data, then you +#' have to impute yourself or use the built-in Markov weather generator (see +#' examples for \code{\link{sw_exec}}). +#' +#' @return Returns a S4 class of type swInputData. This is a container for the +#' input S4 objects used to run soilwat. The data for a test project is loaded. +#' @author Ryan Murphy +#' @seealso \itemize{ \item \code{\link{sw_exec}} for running a simulation +#' \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +#' data input \item \code{\link{dbW_getWeatherData}} and +#' \code{\link{getWeatherData_folders}} for weather data input } +#' @examples +#' +#' ## ------ Simulation with demonstration data ------------ +#' ## Access demonstration data (including daily weather forcing) +#' sw_in <- sw_inputData() +#' +#' ## Slots of the input object of class 'swInputData' +#' str(sw_in, max.level=2) +#' +#' ## Execute the simulation run +#' sw_out <- sw_exec(inputData = sw_in) +#' sw_inputData <- function() { temp<-swInputData() data(package="Rsoilwat31", weatherData) diff --git a/R/swFunctions.R b/R/swFunctions.R index 6074eda8..e585e490 100644 --- a/R/swFunctions.R +++ b/R/swFunctions.R @@ -22,47 +22,195 @@ con.env <- new.env() con.env$con <- NULL -con.env$dbW_version <- "2.0.0" +con.env$dbW_version <- "3.1.0" +con.env$default_blob_compression_type <- "gzip" +con.env$blob_compression_type <- NULL dbW_version <- function() { - numeric_version(dbGetQuery(con.env$con, "SELECT Version FROM Version;")) + stopifnot(requireNamespace("RSQLite")) + + numeric_version(as.character(DBI::dbGetQuery(con.env$con, "SELECT Value FROM Meta WHERE Desc=\'Version\'")[1, 1])) } -dbW_getSiteId <- function(lat=NULL, long=NULL, Label=NULL) { - lat<-as.numeric(lat) - long<-as.numeric(long) - if(!is.null(Label)) { - if(is.character(Label)) { - SQL <- paste("SELECT Site_id FROM Sites WHERE Label='",Label,"';",sep="") - site <- dbGetQuery(con.env$con,SQL) - Site_id <- as.integer(site) +dbW_compression <- function() { + stopifnot(requireNamespace("RSQLite")) + + as.character(DBI::dbGetQuery(con.env$con, "SELECT Value FROM Meta WHERE Desc=\'Compression_type\'")[1, 1]) +} + +#' Extract weather database key to connect a site with weather data +#' +#' @details The key (SiteId) can be located by either providing a \code{Label} or +#' by providing \code{lat} and \code{long} of the requested site. +#' +#' @param lat A numeric value or \code{NULL}. The latitude in decimal degrees of WGS84. Northern latitude are positive, sites on the southern hemisphere have negative values. +#' @param long A numeric value or \code{NULL}. The longitude in decimal degrees of WGS84. Eastern longitudes are positive, sites on the western hemisphere have negative values. +#' @param Label A character string or \code{NULL}. +#' @return An integer value or \code{NULL}. +dbW_getSiteId <- function(lat = NULL, long = NULL, Label = NULL) { + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + + lat <- as.numeric(lat) + long <- as.numeric(long) + SQL <- NULL + + if (!is.null(Label)) { + if (is.character(Label)) { + SQL <- paste("SELECT Site_id FROM Sites WHERE Label='", Label, "';", sep = "") } - } else if(!is.null(lat) & !is.null(long)) { - if(!is.na(lat) & !is.na(long) & length(lat) == 1 & length(long) == 1) { - SQL <- paste("SELECT Site_id FROM Sites WHERE Latitude=",lat," AND Longitude=",long,";",sep="") - site <- dbGetQuery(con.env$con,SQL) - Site_id <- as.integer(site) + } else if (!is.null(lat) && !is.null(long)) { + if (!is.na(lat) && !is.na(long) && length(lat) == 1 && length(long) == 1) { + SQL <- paste("SELECT Site_id FROM Sites WHERE Latitude=", lat, " AND Longitude=", long, ";", sep = "") } } - if(is.na(Site_id)) - return(NULL) - if(!is.null(Site_id) && is.integer(Site_id) && Site_id >= 0) { - return(Site_id) - } else { - warning("Could not obtain Site Id.") - return(NULL) - } + + Site_id <- if (!is.null(SQL)) { + as.integer(DBI::dbGetQuery(con.env$con, SQL)) + } else NULL + + if (!is.finite(Site_id) || Site_id < 0) + Site_id <- NULL + + if (is.null(Site_id)) + warning("'dbW_getSiteId': could not obtain site ID") + + Site_id } dbW_getSiteTable <- function() { - return(dbReadTable(con.env$con, "Sites")) + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + + DBI::dbReadTable(con.env$con, "Sites") } dbW_getScenariosTable <- function() { - return(dbReadTable(con.env$con, "Scenarios")) + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + + DBI::dbReadTable(con.env$con, "Scenarios") } + + +#' Extracts daily weather data from a SQLite database +#' +#' Reads weather data from database. Returns list of weather data. +#' +#' Weather data for the soil water simulation run can be stored in the input +#' data or it can be separate to keep the input data size down for multiple +#' variations of the same site. This function is used to return the weather +#' data from a pre defined weather database. Using the database was faster then +#' reading in multiple weather files from disk. +#' +#' SOILWAT does not handle missing weather data. If you have missing data, then +#' you have to impute yourself or use the built-in Markov weather generator +#' (see examples for \code{\link{sw_exec}}). +#' +#' The output from this function can be passed directly to sw_exec with input +#' data. +#' +#' @param con RSQLite con object. A connection to the weather data database. +#' requires(RSQLite) +#' @param Site_id Numeric. Used to identify site and extract weather data. +#' @param lat Numeric. Latitude used with longitude to identify site id if +#' Site_id is missing. +#' @param long Numeric. Longitude and Latitude are used to identify site if +#' Site_id is missing. +#' @param weatherDirName String. If Site_id, lat, and long is missing then this +#' will be used to identify Site_id by parsing the lat and long out of the +#' name. +#' @param startYear Numeric. Extracted weather data will start with this year. +#' @param endYear Numeric. Extracted weather data will end with this year. +#' @return Returns weather data as list. Each element contains data for one +#' year. +#' @author Ryan Murphy +#' @seealso \itemize{ \item \code{\link{sw_exec}} for running a simulation +#' \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +#' data input \item \code{\link{dbW_getWeatherData}} and +#' \code{\link{getWeatherData_folders}} for weather data input } +#' @examples +#' +#' ## Default data set without weather data. +#' ## Column Names are also turned on for output +#' library(Rsoilwat) +#' library(RSQLite) +#' drv <- dbDriver("SQLite") +#' con <- dbConnect(drv, "/path/to/weather/database/lookupWeatherDB.sqlite3") +#' inputData <- sw_inputDataFromFiles(dir="/path/to/project",files.in="files_v27.in") #Get the data set +#' weatherData <- dbW_getWeatherData(con, Site_id=200) +#' #Run the simulation +#' run<-sw_exec(data=inputData, weatherList=weatherData, colNames=TRUE) +#' dbW_getWeatherData <- function(Site_id=NULL,lat=NULL,long=NULL,Label=NULL,startYear=NULL,endYear=NULL, Scenario="Current") { + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + + if(is.null(Site_id) && is.null(Label) && is.null(lat) && is.null(long)) { + stop("No way to locate weather data from input") + } + + useYears<-FALSE + useStart<-FALSE + useEnd <-FALSE + if(!is.null(startYear) | !is.null(endYear)) {#See if we should narrow the start end year range + startYear <- as.integer(startYear) + if(!is.na(startYear)) useStart<-TRUE + endYear <- as.integer(endYear) + if(!is.na(endYear)) useEnd<-TRUE + if(useStart | useEnd) useYears<-TRUE + if(useStart & useEnd) { + if(startYear >= endYear | startYear<0 | endYear<0) { + stop("Wrong start or end year") + } + } + } + + Site_id <- as.integer(Site_id) + if (length(Site_id) == 0 || !is.finite(Site_id)) { + Site_id <- dbW_getSiteId(lat, long, Label) + } else { + if (!DBI::dbGetQuery(con.env$con, paste("SELECT COUNT(*) FROM WeatherData WHERE Site_id=",Site_id,";",sep=""))[1,1]) { + stop("Site_id does not exist.") + } + } + + if (!is.null(Site_id)) { + Scenario <- DBI::dbGetQuery(con.env$con, paste("SELECT id FROM Scenarios WHERE Scenario='",Scenario,"';",sep=""))[1,1] + result <- DBI::dbGetQuery(con.env$con, paste("SELECT StartYear,EndYear,data FROM WeatherData WHERE Site_id=",Site_id, " AND Scenario=",Scenario,";",sep="")); + data <- try(dbW_blob_to_weatherData(result$data, con.env$blob_compression_type)) + if(inherits(data, "try-error")) stop(paste("Weather data for Site_id", Site_id, "is corrupted")) + + } else { + stop(paste("Site_id for", Label, "not obtained.")) + } + + if(useYears) { + if(useStart && useEnd) { + # adjusting so we actually explore the values of the "year" slots of our soilwatDB object list + # startYear_idx <- match(startYear,as.integer(names(data))) + startYear_idx <- match(startYear, + as.integer(unlist(lapply(data, FUN=slot, "year")))) + # endYear_idx <- match(endYear,as.integer(names(data))) + endYear_idx <- match(endYear, + as.integer(unlist(lapply(data, FUN=slot, "year")))) + data <- data[startYear_idx:endYear_idx] + } else if(useStart) { + #startYear_idx <- match(startYear,as.integer(names(data))) + startYear_idx <- match(startYear, + as.integer(unlist(lapply(data, FUN=slot, "year")))) + # data <- data[startYear_idx:length(as.integer(names(data)))] + data <- data[startYear_idx:length(as.integer(unlist(lapply(data, FUN=slot, "year"))))] + } else if(useEnd) { + # endYear_idx <- match(endYear,as.integer(names(data))) + endYear_idx <- match(endYear, + as.integer(unlist(lapply(data, FUN=slot, "year")))) + data <- data[1:endYear_idx] + } + } + return(data) +} + +dbW_getWeatherData_old <- function(Site_id=NULL,lat=NULL,long=NULL,Label=NULL,startYear=NULL,endYear=NULL, Scenario="Current") { + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + if(is.null(Site_id) && is.null(Label) && is.null(lat) && is.null(long)) { stop("No way to locate weather data from input") } @@ -86,14 +234,14 @@ dbW_getWeatherData <- function(Site_id=NULL,lat=NULL,long=NULL,Label=NULL,startY if(length(Site_id) == 0) { Site_id <- dbW_getSiteId(lat,long,Label) } else { - if(!dbGetQuery(con.env$con, paste("SELECT COUNT(*) FROM WeatherData WHERE Site_id=",Site_id,";",sep=""))[1,1]) { + if(!DBI::dbGetQuery(con.env$con, paste("SELECT COUNT(*) FROM WeatherData WHERE Site_id=",Site_id,";",sep=""))[1,1]) { stop("Site_id does not exist.") } } if(!is.null(Site_id) && is.integer(Site_id) && Site_id >= 0) { - Scenario <- dbGetQuery(con.env$con, paste("SELECT id FROM Scenarios WHERE Scenario='",Scenario,"';",sep=""))[1,1] - result <- dbGetQuery(con.env$con, paste("SELECT StartYear,EndYear,data FROM WeatherData WHERE Site_id=",Site_id, " AND Scenario=",Scenario,";",sep="")); - data <- dbW_blob_to_weatherData(result$StartYear, result$EndYear, result$data) + Scenario <- DBI::dbGetQuery(con.env$con, paste("SELECT id FROM Scenarios WHERE Scenario='",Scenario,"';",sep=""))[1,1] + result <- DBI::dbGetQuery(con.env$con, paste("SELECT StartYear,EndYear,data FROM WeatherData WHERE Site_id=",Site_id, " AND Scenario=",Scenario,";",sep="")); + data <- dbW_blob_to_weatherData_old(result$StartYear, result$EndYear, result$data, con.env$blob_compression_type) if(inherits(data, "try-error")) stop(paste("Weather data for Site_id", Site_id, "is corrupted")) } else { stop(paste("Site_id for", Label, "not obtained.")) @@ -125,107 +273,149 @@ dbW_getWeatherData <- function(Site_id=NULL,lat=NULL,long=NULL,Label=NULL,startY return(data) } + dbW_addSite <- function(Site_id=NULL,lat=NULL,long=NULL,Label=NULL) { + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + #First See if Site_id exists - Site_id<-as.integer(Site_id) - if(length(Site_id) == 0) {#Site_id is null + Site_id <- as.integer(Site_id) + if (length(Site_id) == 0) { #Site_id is null Site_id <- dbW_getSiteId(lat,long,Label) - if(is.null(Site_id)) { #Site_id does not exist for given lat,long, and/or Label. Create it - if(is.null(lat)) lat <- "NULL" - if(is.null(long)) long <- "NULL" - if(is.null(Label)) Label <- "NULL" else Label <- paste("'",Label,"'",sep="") - temp<-dbGetQuery(con.env$con, "SELECT MAX(Site_id) FROM Sites;")[1,1] - Site_id <- ifelse(is.na(temp),1,temp+1) - dbGetQuery(con.env$con, paste("INSERT INTO Sites VALUES(",Site_id,",",lat,",",long,",",Label,");",sep="")) - return(Site_id) - } else { #Site_id exists already - SiteData <- dbGetQuery(con.env$con, paste("SELECT * FROM Sites WHERE Site_id=",Site_id,sep="")) - SiteData_lat <- SiteData[1,2] - if(is.na(SiteData_lat)) SiteData_lat <- NULL - SiteData_long <- SiteData[1,3] - if(is.na(SiteData_long)) SiteData_long <- NULL - SiteData_label <- SiteData[1,4] - if(is.na(SiteData_label)) SiteData_label <- NULL - if( (ifelse(length(temp<-SiteData_lat != lat) == 0, TRUE, temp)) | (ifelse(length(temp<-SiteData_long != long) == 0, TRUE, temp)) | (ifelse(length(temp <- Label != "") == 0, TRUE, temp) & ifelse(length(temp <- SiteData_label != Label) == 0, TRUE, temp)) ) { - stop(paste("Site_id: ",Site_id," already existed in database. Data mismatch, NULL where ignored : (database:given) lat(",SiteData[1,2],":",lat,") long(",SiteData[1,3],":",long,") label(",SiteData[1,4],":",Label,").",sep="")) - } - return(Site_id) - } - } else { - if(dbGetQuery(con.env$con, paste("SELECT COUNT(*) FROM Sites WHERE Site_id=",Site_id,sep=""))[1,1]) {#Site id already Exists - SiteData <- dbGetQuery(con.env$con, paste("SELECT * FROM Sites WHERE Site_id=",Site_id,sep="")) - if(is.na(SiteData_lat)) SiteData_lat <- NULL - SiteData_long <- SiteData[1,3] - if(is.na(SiteData_long)) SiteData_long <- NULL - SiteData_label <- SiteData[1,4] - if(is.na(SiteData_label)) SiteData_label <- NULL - if( (!is.null(lat) & SiteData_lat != lat) | (!is.null(long) & SiteData_long != long) | (!is.null(Label) & Label != "" & SiteData_label != Label) ) { + } + + if (is.null(Site_id) || + 1 > DBI::dbGetQuery(con.env$con, paste("SELECT COUNT(*) FROM Sites WHERE Site_id=",Site_id,sep=""))[1,1]) { #Site_id does not exist for given lat,long, and/or Label. Create it + + if (is.null(lat)) lat <- "NULL" + if (is.null(long)) long <- "NULL" + Label <- if (is.null(Label)) "NULL" else paste("'", Label, "'", sep = "") + temp <- DBI::dbGetQuery(con.env$con, "SELECT MAX(Site_id) FROM Sites;")[1,1] + Site_id <- if(is.na(temp)) 1 else {temp + 1} + DBI::dbGetQuery(con.env$con, paste("INSERT INTO Sites VALUES(", Site_id, ",", lat, ",", long, ",", Label, ");", sep = "")) + + } else { #Site_id exists already + SiteData <- DBI::dbGetQuery(con.env$con, paste("SELECT * FROM Sites WHERE Site_id=", Site_id, sep = "")) + + if( (!is.null(lat) && !is.null(SiteData[1, "Latitude"]) && SiteData[1, "Latitude"] != lat) || + (!is.null(long) && !is.null(SiteData[1, "Longitude"]) && SiteData[1, "Longitude"] != long) || + (!is.null(Label) && nchar(Label) > 0 && !is.null(SiteData[1, "Label"]) && SiteData[1, "Label"] != Label) ) { stop(paste("Site_id: ",Site_id," already existed in database. Data mismatch, NULL where ignored : (database:given) lat(",SiteData[1,2],":",lat,") long(",SiteData[1,3],":",long,") label(",SiteData[1,4],":",Label,").",sep="")) - } - return(Site_id) - } else {#Create it - if(is.null(lat)) lat <- "NULL" - if(is.null(long)) long <- "NULL" - if(is.null(Label)) Label <- "NULL" else Label <- paste("'",Label,"'",sep="") - temp<-dbGetQuery(con.env$con, "SELECT MAX(Site_id) FROM Sites;")[1,1] - Site_id <- ifelse(is.na(temp),1,temp+1) - dbGetQuery(con.env$con, paste("INSERT INTO Sites VALUES(",Site_id,",",lat,",",long,",",Label,");",sep="")) - return(Site_id) } } + + Site_id } -dbW_setConnection <- function(dbFilePath, createAdd=FALSE) { - require(RSQLite) - drv <- dbDriver("SQLite") +dbW_setConnection <- function(dbFilePath) { + stopifnot(requireNamespace("RSQLite")) + + dbFilePath <- file.path(dbFilePath) + if (!file.exists(dbFilePath)) { + print(paste("'dbW_setConnection':", basename(dbFilePath), "does not exist. Creating database.")) + } + con.env$con <- DBI::dbConnect(RSQLite::SQLite(), dbname = dbFilePath) + con.env$blob_compression_type <- if (DBI::dbExistsTable(con.env$con, "Meta")) dbW_compression() else con.env$default_blob_compression_type #settings <- c("PRAGMA page_size=8192","PRAGMA cache_size = 400000;","PRAGMA synchronous = OFF;","PRAGMA journal_mode = OFF;","PRAGMA locking_mode = EXCLUSIVE;","PRAGMA count_changes = OFF;","PRAGMA temp_store = MEMORY;","PRAGMA auto_vacuum = NONE;") - - tfile <- file.path(dbFilePath) - if(!file.exists(dbFilePath)) { - print("dbFilePath does not exist. Creating database.") - } - con.env$con <- dbConnect(drv, dbname = tfile) - #if(createAdd) lapply(settings, function(x) dbGetQuery(con.env$con,x)) + #lapply(settings, function(x) DBI::dbGetQuery(con.env$con,x)) } dbW_disconnectConnection <- function() { - dbDisconnect(con.env$con) + stopifnot(requireNamespace("RSQLite")) + + DBI::dbDisconnect(con.env$con) + con.env$con <- NULL + con.env$blob_compression_type <- NULL } dbW_addSites <- function(dfLatitudeLongitudeLabel) {#lat #long #Label 1 .... 20165 - dbGetPreparedQuery(con.env$con, "INSERT INTO Sites VALUES(NULL, :Latitude, :Longitude, :Label)", bind.data = as.data.frame(dfLatitudeLongitudeLabel,stringsAsFactors=FALSE)) + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + + RSQLite::dbGetPreparedQuery(con.env$con, "INSERT INTO Sites VALUES(NULL, :Latitude, :Longitude, :Label)", bind.data = as.data.frame(dfLatitudeLongitudeLabel,stringsAsFactors=FALSE)) } dbW_addScenarios <- function(dfScenario) {#names 1 ... 32 - dbGetPreparedQuery(con.env$con, "INSERT INTO Scenarios VALUES(NULL, :Scenario)", bind.data = as.data.frame(dfScenario,stringsAsFactors=FALSE)) + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + + RSQLite::dbGetPreparedQuery(con.env$con, "INSERT INTO Scenarios VALUES(NULL, :Scenario)", bind.data = as.data.frame(dfScenario,stringsAsFactors=FALSE)) } -dbW_addWeatherDataNoCheck <- function(Site_id, Scenario_id, StartYear, EndYear, weatherData) { - dbGetQuery(con.env$con, paste("INSERT INTO WeatherData (Site_id, Scenario, StartYear, EndYear, data) VALUES (",Site_id,",",Scenario_id,",",StartYear,",",EndYear,",",weatherData,");",sep="")) +dbW_addWeatherDataNoCheck <- function(Site_id, Scenario_id, StartYear, EndYear, weather_blob) { + DBI::dbGetQuery(con.env$con, paste("INSERT INTO WeatherData (Site_id, Scenario, StartYear, EndYear, data) VALUES (",Site_id,",",Scenario_id,",",StartYear,",",EndYear,",",weather_blob,");",sep="")) } dbW_addWeatherData <- function(Site_id=NULL, lat=NULL, long=NULL, weatherFolderPath=NULL, weatherData=NULL, label=NULL, ScenarioName="Current") { + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + + if( (is.null(weatherFolderPath) | ifelse(!is.null(weatherFolderPath), (weatherFolderPath == "" | !file.exists(weatherFolderPath)), FALSE)) & (is.null(weatherData) | !is.list(weatherData) | class(weatherData[[1]]) != "swWeatherData") ) stop("addWeatherDataToDataBase does not have folder path or weatherData to insert") + if( (is.null(Site_id) & is.null(lat) & is.null(long) & is.null(weatherFolderPath) & (is.null(label))) | ((!is.null(Site_id) & !is.numeric(Site_id)) & (!is.null(lat) & !is.numeric(lat)) & (!is.null(long) & !is.numeric(long))) ) stop("addWeatherDataToDataBase not enough info to create Site in Sites table.") + + Site_id <- dbW_addSite( + Site_id = Site_id, + lat = lat, + long = long, + Label = if (!is.null(weatherFolderPath) && is.null(label)) basename(weatherFolderPath) else label) + + Scenarios <- DBI::dbReadTable(con.env$con,"Scenarios")$Scenario + if(ScenarioName %in% Scenarios) { + scenarioID <- which(ScenarioName %in% Scenarios) + } else { + temp <- DBI::dbGetQuery(con.env$con, "SELECT MAX(id) FROM \"Scenarios\";")[1,1] + scenarioID <- ifelse(is.na(temp),1,temp+1) + SQL <- paste("INSERT INTO \"Scenarios\" VALUES(",scenarioID,",'",ScenarioName,"');",sep="") + DBI::dbGetQuery(con.env$con, SQL) + } + + if(!is.null(weatherData)) { + data_blob <- dbW_weatherData_to_blob(weatherData, con.env$blob_compression_type) + StartYear <- head(as.integer(names(weatherData)),n=1) + EndYear <- tail(as.integer(names(weatherData)),n=1) + DBI::dbGetQuery(con.env$con, paste("INSERT INTO WeatherData (Site_id, Scenario, StartYear, EndYear, data) VALUES (",Site_id,",",scenarioID,",",StartYear,",",EndYear,",",data_blob,");",sep="")) + #dbCommit(con.env$con) + } else { + weath <- list.files(weatherFolderPath) + years <- as.numeric(sub(pattern="weath.",replacement="",weath)) + weatherData <- list() + for(j in 1:length(weath)) { + year <- as.numeric(sub(pattern="weath.",replacement="",weath[j])) + temp <-read.csv(file.path(weatherFolderPath,weath[j]),header=FALSE,skip=2,sep="\t") + weatherData[[j]] <- swReadLines(new("swWeatherData",year),file.path(weatherFolderPath,weath[j])) + } + StartYear <- head(years,n=1) + EndYear <- tail(years,n=1) + data_blob <- dbW_weatherData_to_blob(weatherData, con.env$blob_compression_type) + DBI::dbGetQuery(con.env$con, paste("INSERT INTO WeatherData (Site_id, Scenario, StartYear, EndYear, data) VALUES (",Site_id,",",scenarioID,",",StartYear,",",EndYear,",",data_blob,");",sep="")) + #dbCommit(con.env$con) + } +} + +dbW_addWeatherData_old <- function(Site_id=NULL, lat=NULL, long=NULL, weatherFolderPath=NULL, weatherData=NULL, label=NULL, ScenarioName="Current") { + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + if( (is.null(weatherFolderPath) | ifelse(!is.null(weatherFolderPath), (weatherFolderPath == "" | !file.exists(weatherFolderPath)), FALSE)) & (is.null(weatherData) | !is.list(weatherData) | class(weatherData[[1]]) != "swWeatherData") ) stop("addWeatherDataToDataBase does not have folder path or weatherData to insert") if( (is.null(Site_id) & is.null(lat) & is.null(long) & is.null(weatherFolderPath) & (is.null(label))) | ((!is.null(Site_id) & !is.numeric(Site_id)) & (!is.null(lat) & !is.numeric(lat)) & (!is.null(long) & !is.numeric(long))) ) stop("addWeatherDataToDataBase not enough info to create Site in Sites table.") - Site_id <- dbW_addSite(Site_id=Site_id, lat=lat, long=long, Label=ifelse(!is.null(weatherFolderPath) & is.null(label), basename(weatherFolderPath), label)) + Site_id <- dbW_addSite( + Site_id = Site_id, + lat = lat, + long = long, + Label = if (!is.null(weatherFolderPath) && is.null(label)) basename(weatherFolderPath) else label) - Scenarios <- dbReadTable(con.env$con,"Scenarios")$Scenario + Scenarios <- DBI::dbReadTable(con.env$con,"Scenarios")$Scenario if(ScenarioName %in% Scenarios) { scenarioID <- which(ScenarioName %in% Scenarios) } else { - temp <- dbGetQuery(con.env$con, "SELECT MAX(id) FROM \"Scenarios\";")[1,1] + temp <- DBI::dbGetQuery(con.env$con, "SELECT MAX(id) FROM \"Scenarios\";")[1,1] scenarioID <- ifelse(is.na(temp),1,temp+1) SQL <- paste("INSERT INTO \"Scenarios\" VALUES(",scenarioID,",'",ScenarioName,"');",sep="") - dbGetQuery(con.env$con, SQL) + DBI::dbGetQuery(con.env$con, SQL) } if(!is.null(weatherData)) { - data_blob <- dbW_weatherData_to_blob(weatherData) + data_blob <- dbW_weatherData_to_blob_old(weatherData, con.env$blob_compression_type) StartYear <- head(as.integer(names(weatherData)),n=1) EndYear <- tail(as.integer(names(weatherData)),n=1) - dbGetQuery(con.env$con, paste("INSERT INTO WeatherData (Site_id, Scenario, StartYear, EndYear, data) VALUES (",Site_id,",",scenarioID,",",StartYear,",",EndYear,",",data_blob,");",sep="")) + DBI::dbGetQuery(con.env$con, paste("INSERT INTO WeatherData (Site_id, Scenario, StartYear, EndYear, data) VALUES (",Site_id,",",scenarioID,",",StartYear,",",EndYear,",",data_blob,");",sep="")) #dbCommit(con.env$con) } else { weath <- list.files(weatherFolderPath) @@ -238,25 +428,37 @@ dbW_addWeatherData <- function(Site_id=NULL, lat=NULL, long=NULL, weatherFolderP } StartYear <- head(years,n=1) EndYear <- tail(years,n=1) - data_blob <- dbW_weatherData_to_blob(weatherData) - dbGetQuery(con.env$con, paste("INSERT INTO WeatherData (Site_id, Scenario, StartYear, EndYear, data) VALUES (",Site_id,",",scenarioID,",",StartYear,",",EndYear,",",data_blob,");",sep="")) + data_blob <- dbW_weatherData_to_blob_old(weatherData, con.env$blob_compression_type) + DBI::dbGetQuery(con.env$con, paste("INSERT INTO WeatherData (Site_id, Scenario, StartYear, EndYear, data) VALUES (",Site_id,",",scenarioID,",",StartYear,",",EndYear,",",data_blob,");",sep="")) #dbCommit(con.env$con) } } -dbW_createDatabase <- function(dbFilePath = "dbWeatherData.sqlite", site_data = NULL, site_subset = NULL, scenarios = NULL) { + +dbW_createDatabase <- function(dbFilePath = "dbWeatherData.sqlite", site_data = NULL, site_subset = NULL, scenarios = NULL, compression_type) { + stopifnot(requireNamespace("RSQLite")) + + dbW_setConnection(dbFilePath) + #---Create tables - # Version - dbW_setConnection(dbFilePath, FALSE) - dbGetQuery(con.env$con, "CREATE TABLE \"Version\" (\"Version\" TEXT);") - dbGetQuery(con.env$con, paste0("INSERT INTO Version (Version) VALUES (\'", con.env$dbW_version, "\');")) + # Meta information + if (missing(compression_type) || !(compression_type %in% eval(formals(memCompress)[[2]]))) { + compression_type <- con.env$default_blob_compression_type + } + con.env$blob_compression_type <- compression_type + + stopifnot(DBI::dbIsValid(con.env$con)) + DBI::dbGetQuery(con.env$con, "CREATE TABLE \"Meta\" (\"Desc\" TEXT PRIMARY KEY, \"Value\" TEXT);") + RSQLite::dbGetPreparedQuery(con.env$con, "INSERT INTO Meta VALUES(:Desc, :Value)", + bind.data = data.frame(Desc = c("Version", "Compression_type"), + Value = c(con.env$dbW_version, con.env$blob_compression_type))) # Table of sites - dbGetQuery(con.env$con, "CREATE TABLE \"Sites\" (\"Site_id\" integer PRIMARY KEY, \"Latitude\" REAL, \"Longitude\" REAL, \"Label\" TEXT);") + DBI::dbGetQuery(con.env$con, "CREATE TABLE \"Sites\" (\"Site_id\" integer PRIMARY KEY, \"Latitude\" REAL, \"Longitude\" REAL, \"Label\" TEXT);") # Table for weather data - dbGetQuery(con.env$con, "CREATE TABLE \"WeatherData\" (\"Site_id\" integer, \"Scenario\" integer, \"StartYear\" integer, \"EndYear\" integer, \"data\" BLOB, PRIMARY KEY (\"Site_id\", \"Scenario\"));") + DBI::dbGetQuery(con.env$con, "CREATE TABLE \"WeatherData\" (\"Site_id\" integer, \"Scenario\" integer, \"StartYear\" integer, \"EndYear\" integer, \"data\" BLOB, PRIMARY KEY (\"Site_id\", \"Scenario\"));") # Table of scenario names - dbGetQuery(con.env$con, "CREATE TABLE \"Scenarios\" (\"id\" integer PRIMARY KEY, \"Scenario\" TEXT);") + DBI::dbGetQuery(con.env$con, "CREATE TABLE \"Scenarios\" (\"id\" integer PRIMARY KEY, \"Scenario\" TEXT);") #---Add sites if (NROW(site_data) > 0 && sapply(c("Site_id", "Latitude", "Longitude", "Label"), function(x) x %in% colnames(site_data))) { @@ -291,16 +493,20 @@ dbW_addFromFolders <- function(MetaData=NULL, FoldersPath, ScenarioName="Current } dbW_deleteSite <- function(Site_id) { - dbGetQuery(con.env$con, paste("DELETE FROM \"Sites\" WHERE Site_id=",Site_id,";",sep="")) + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + + DBI::dbGetQuery(con.env$con, paste("DELETE FROM \"Sites\" WHERE Site_id=",Site_id,";",sep="")) } dbW_deleteSiteData <- function(Site_id, Scenario=NULL) { + stopifnot(requireNamespace("RSQLite"), DBI::dbIsValid(con.env$con)) + if(is.null(Scenario)) { #Remove all data for this site - dbGetQuery(con.env$con, paste("DELETE FROM \"WeatherData\" WHERE Site_id=",Site_id,";",sep="")) + DBI::dbGetQuery(con.env$con, paste("DELETE FROM \"WeatherData\" WHERE Site_id=",Site_id,";",sep="")) dbW_deleteSite(Site_id) } else { - dbGetQuery(con.env$con, paste("DELETE FROM \"WeatherData\" WHERE Site_id=",Site_id," AND Scenario='",Scenario,"';",sep="")) - if(!dbGetQuery(con.env$con, paste("SELECT COUNT(*) FROM Sites WHERE Site_id=",Site_id,sep=""))[1,1]) { + DBI::dbGetQuery(con.env$con, paste("DELETE FROM \"WeatherData\" WHERE Site_id=",Site_id," AND Scenario='",Scenario,"';",sep="")) + if(!DBI::dbGetQuery(con.env$con, paste("SELECT COUNT(*) FROM Sites WHERE Site_id=",Site_id,sep=""))[1,1]) { dbW_deleteSite(Site_id) } } @@ -308,40 +514,123 @@ dbW_deleteSiteData <- function(Site_id, Scenario=NULL) { ## ------ Conversion of weather data formats +#' Conversion: (Compressed) raw vector (e.g., SQL-retrieved blob) to (uncompressed) object +#' +#' The Rsoilwat SQlite-DB which manages daily weather data (each as a list of elements +#' of class 'swWeatherData'), uses internally (compressed) blobs. This function is used +#' to convert the blob object to the object used by Rsoilwat's simulation functions. +#' +#' @param data_blob A raw vector +#' @param type A character string. One of c("gzip", "bzip2", "xz", "none"). +#' +#' @seealso \code{\link{memDecompress}}, \code{\link{unserialize}} +dbW_blob_to_weatherData <- function(data_blob, type = "gzip") { + if (inherits(data_blob, "list") && inherits(data_blob[[1]], "raw") && length(data_blob) == 1) + data_blob <- data_blob[[1]] + + unserialize(memDecompress(data_blob, type = type)) +} + +#' Conversion: R object to (compressed) SQL-blob-ready character vector +#' +#' The Rsoilwat SQLite-DB which manages daily weather data (each as a list of elements +#' of class 'swWeatherData'), uses internally (compressed) blobs. This function is used +#' to a list of daily weather data used by Rsoilwat's simulation functions to a blob object +#' which can be inserted into a SQLite DB. +#' +#' @param weatherData A list of elements of class 'swWeatherData' or any suitable object. +#' @param type A character string. One of c("gzip", "bzip2", "xz", "none"). +#' +#' @seealso \code{\link{memCompress}}, \code{\link{serialize}} +dbW_weatherData_to_blob <- function(weatherData, type = "gzip") { + paste0("x'", paste0(memCompress(serialize(weatherData, connection = NULL), type = type), collapse = ""), "'") +} + # Conversion: SQL-blob to object of class 'swWeatherData' -dbW_blob_to_weatherData <- function(StartYear, EndYear, data_blob) { - if(typeof(data_blob) == "list") +dbW_blob_to_weatherData_old <- function(StartYear, EndYear, data_blob, type = "gzip") { + if (typeof(data_blob) == "list") data_blob <- data_blob[[1]] - data <- strsplit(rawToChar(memDecompress(data_blob, type="gzip")), ";")[[1]] - years <- seq(from=StartYear, to=EndYear) + data <- strsplit(memDecompress(data_blob, type = type, asChar = TRUE), ";")[[1]] + years <- StartYear:EndYear weatherData <- list() - for(i in 1:length(years)) { - ydata <- read.table(textConnection(data[i]),header=FALSE,sep=",",stringsAsFactors=FALSE) - ydata <- as.matrix(cbind(seq(from=1,to=nrow(ydata)),ydata)) - colnames(ydata) <- c("DOY","Tmax_C","Tmin_C","PPT_cm") - weatherData[[i]] <- new("swWeatherData",year=years[i],data=ydata) + for (i in seq_along(years)) { + zz <- textConnection(data[i]) + ydata <- read.table(zz, header = FALSE, sep = ",", stringsAsFactors = FALSE) + close(zz) + ydata <- as.matrix(cbind(seq_len(nrow(ydata)), ydata)) + colnames(ydata) <- c("DOY", "Tmax_C", "Tmin_C", "PPT_cm") + weatherData[[i]] <- new("swWeatherData", year = years[i], data = ydata) } names(weatherData) <- years - return(weatherData) + weatherData } # Conversion: object of class 'swWeatherData' to SQL-blob -dbW_weatherData_to_blob <- function(weatherData) { - string <- character(length=length(weatherData)) - for(i in 1:length(weatherData)) { - zz <- textConnection("dataString","w") - write.table(x=weatherData[[i]]@data[,2:4], file=zz, col.names=FALSE, sep="," ,row.names=FALSE) +dbW_weatherData_to_blob_old <- function(weatherData, type = "gzip") { + string <- character(length = length(weatherData)) + for(i in seq_along(weatherData)) { + zz <- textConnection("dataString", "w") + write.table(x = weatherData[[i]]@data[, -1], file = zz, col.names = FALSE, sep = "," , row.names = FALSE) close(zz) - string[i] <-paste(dataString,collapse="\n") + string[i] <- paste(dataString, collapse = "\n") } - string<-paste(string,collapse=";") - data_blob <- paste0("x'",paste0(memCompress(string,type="gzip"),collapse = ""),"'",sep="") - return(data_blob) + string <- paste(string, collapse=";") + + paste0("x'", paste0(memCompress(string, type = type), collapse = ""), "'") } # Conversion: reading of SOILWAT input text files to object of class 'swWeatherData' + + +#' Rsoilwat getWeatherData_folders +#' +#' Reads weather data from files. Returns list of weather data. +#' +#' Weather data for the soil water simulation run can be stored in the input +#' data or it can be separate to keep the input data size down for multiple +#' variations of the same site. This function is used to return the weather +#' data from folders. The other option is to use onGetWeatherData_database. +#' +#' SOILWAT does not handle missing weather data. If you have missing data, then +#' you have to impute yourself or use the built-in Markov weather generator +#' (see examples for \code{\link{sw_exec}}). +#' +#' The output from this function can be passed directly to sw_exec with input +#' data. +#' +#' @param LookupWeatherFolder String Path. Path to the LookupWeatherFolder +#' location. +#' @param weatherDirName String. Name of the folder containing weather data +#' files. +#' @param filebasename String. File prefix for weather data. Usually 'weath'. +#' @param startYear Numeric. Extracted weather data will start with this year. +#' @param endYear Numeric. Extracted weather data will end with this year. +#' @return Returns weather data as list. Each element contains data for one +#' year. +#' @author Ryan Murphy +#' @seealso \itemize{ \item \code{\link{sw_exec}} for running a simulation +#' \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +#' data input \item \code{\link{dbW_getWeatherData}} and +#' \code{\link{getWeatherData_folders}} for weather data input } +#' @examples +#' +#' path_demo <- dirname(system.file("extdata", "files_v31.in", package = "Rsoilwat31")) +#' +#' ## ------ Simulation with data prepared beforehand and separate weather data ------------ +#' ## Read inputs from files on disk +#' sw_in3 <- sw_inputDataFromFiles(dir = path_demo, files.in = "files_v31.in") +#' +#' ## Read forcing weather data from files on disk (there are also functions to set up a SQLite database for the weather data) +#' sw_weath3 <- getWeatherData_folders(LookupWeatherFolder=file.path(path_demo, "Input"), weatherDirName="data_weather", filebasename="weath", startYear=1979, endYear=2010) +#' +#' ## List of the slots of the input objects of class 'swWeatherData' +#' str(sw_weath3, max.level=1) +#' +#' ## Execute the simulation run +#' sw_out3 <- sw_exec(inputData = sw_in3, weatherList = sw_weath3) +#' getWeatherData_folders <- function(LookupWeatherFolder=NULL, weatherDirName=NULL,filebasename=NULL,startYear=NULL,endYear=NULL) { if(is.null(LookupWeatherFolder) | is.null(weatherDirName) | is.null(filebasename)) stop("Need LookupWeatherFolder and weatherDirName information to get weather data") @@ -464,7 +753,7 @@ dbW_dataframe_to_weatherData <- function(weatherDF, years=NULL, weatherDF_dataCo # Conversion: object of class 'swWeatherData' or data.frame to SOILWAT input text files dbW_weather_to_SOILWATfiles <- function(path, site.label, weatherData=NULL, weatherDF=NULL, years=NULL, weatherDF_dataColumns=c("DOY","Tmax_C","Tmin_C","PPT_cm")){ - stopifnot(is.null(weatherData), is.null(weatherDF)) + stopifnot(is.null(weatherData) || is.null(weatherDF)) dir.create(path, recursive = TRUE, showWarnings = FALSE) if(!is.null(weatherData)){ diff --git a/R/sw_dbW_upgrade.R b/R/sw_dbW_upgrade.R index 4d38fc93..c05c4c93 100644 --- a/R/sw_dbW_upgrade.R +++ b/R/sw_dbW_upgrade.R @@ -19,44 +19,136 @@ ## ------SQLite weather database function: upgrade -dbW_upgrade_v1to2 <- function(dbWeatherDataFile, fbackup = NULL, SWRunInformation) { - dbW_setConnection(dbWeatherDataFile) - v_dbW <- dbW_version() +dbW_upgrade_v3to31 <- function(dbWeatherDataFile, fbackup = NULL, type_new = "gzip") { + print(paste(Sys.time(), ": upgrading database", basename(dbWeatherDataFile), "to version 3.1.0")) - if (v_dbW >= "1" && v_dbW < "2") { - warning("The function 'dbW_upgrade_v1to2' upgrades weather databases from version 1.y.z to 2.0.0; this database is version ", v_dbW) + con <- DBI::dbConnect(RSQLite::SQLite(), dbname = dbWeatherDataFile) + v_dbW <- try(numeric_version(as.character(DBI::dbGetQuery(con, "SELECT Value FROM Meta WHERE Desc=\'Version\'")[1, 1])), silent = TRUE) + + if (inherits(v_dbW, "try-error") || v_dbW >= "3.1.0" && v_dbW < "3.0.0") { + warning("The function 'dbW_upgrade_v3to31' upgrades weather databases from version 3.0.z to 3.1.0; this database is version ", v_dbW) return(invisible(0)) } - print(paste(Sys.time(), ": upgrading database", basename(dbWeatherDataFile), "to version 2.0.0; be patient, this may take considerable time depending on the size of the database")) + type_old <- as.character(DBI::dbGetQuery(con, "SELECT Value FROM Meta WHERE Desc=\'Compression_type\'")[1, 1]) + if (!(type_new %in% eval(formals(memCompress)[[2]]))) { + warning("The upgraded weather database cannot store BLOBs with compression type: ", type_new) + warning("Instead, the previous compression type: ", type_old, " will be used") + } - dir_old <- getwd() - on.exit(setwd(dir_old)) - setwd(dirname(dbWeatherDataFile)) - # Backup copy - if (is.null(fbackup)) { - temp <- strsplit(basename(dbWeatherDataFile), split = ".", fixed = TRUE)[[1]] - temp <- paste0(paste(temp[1], collapse = ""), "_copy.", temp[length(temp)]) - - fbackup <- file.path(dirname(dbWeatherDataFile), temp) + backup_copy(dbWeatherDataFile, fbackup) + + # Update weather blobs + ids <- DBI::dbGetQuery(con, "SELECT Site_id, Scenario FROM WeatherData;") + n_ids <- NROW(ids) + + blob_to_weatherData_old <- function(StartYear, EndYear, data_blob, type = "gzip") { + if (typeof(data_blob) == "list") + data_blob <- data_blob[[1]] + data <- strsplit(memDecompress(data_blob, type = type, asChar = TRUE), ";")[[1]] + years <- StartYear:EndYear + + weatherData <- list() + for (i in seq_along(years)) { + zz <- textConnection(data[i]) + ydata <- read.table(zz, header = FALSE, sep = ",", stringsAsFactors = FALSE) + close(zz) + ydata <- as.matrix(cbind(seq_len(nrow(ydata)), ydata)) + colnames(ydata) <- c("DOY", "Tmax_C", "Tmin_C", "PPT_cm") + weatherData[[i]] <- new("swWeatherData", year = years[i], data = ydata) + } + names(weatherData) <- years + + weatherData } - if (file.exists(dbWeatherDataFile) && !file.exists(fbackup)) { - system2("cp", args = c(dbWeatherDataFile, fbackup)) - } else if (!file.exists(dbWeatherDataFile) && file.exists(fbackup)) { - system2("cp", args = c(fbackup, dbWeatherDataFile)) + + if (n_ids > 0) { + for (i in seq_len(n_ids)) { + print(paste(Sys.time(), ":", i, "out of", n_ids)) + + result <- DBI::dbGetQuery(con, paste0("SELECT StartYear,EndYear,data FROM WeatherData WHERE Site_id =", ids[i, 1], " AND Scenario =", ids[i, 2], ";")) + weatherData <- blob_to_weatherData_old(result$StartYear, result$EndYear, result$data, type_old) + if (inherits(weatherData, "try-error") || length(weatherData) == 0) { + warning("Weather data for Site_id = ", ids[i, 1], " and Scenario = ", ids[i, 2], " is missing or is corrupted") + + } else { + blob_new <- paste0("x'", paste0(memCompress(serialize(weatherData, connection = NULL), type = type_new), collapse = ""), "'") + DBI::dbGetQuery(con, paste0("UPDATE WeatherData SET data =", blob_new, "WHERE Site_id =", ids[i, 1], " AND Scenario =", ids[i, 2], ";")) + rm(blob_new) + + } + } + } + + + # Update version number + DBI::dbGetQuery(con, "UPDATE Meta SET Value = \'3.1.0\' WHERE Desc = \'Version\';") + if (type_new != type_old) + DBI::dbGetQuery(con, paste0("UPDATE Meta SET Value = \'", type_new, "\' WHERE Desc = \'Compression_type\';")) + + # Checks and clean-up + check_updatedDB(con) + DBI::dbDisconnect(con) + + invisible(0) +} + + +dbW_upgrade_v2to3 <- function(dbWeatherDataFile, fbackup = NULL) { + con <- DBI::dbConnect(RSQLite::SQLite(), dbname = dbWeatherDataFile) + v_dbW <- try(numeric_version(as.character(DBI::dbGetQuery(con, "SELECT Version FROM Version;"))), silent = TRUE) + + if (inherits(v_dbW, "try-error") || v_dbW >= "3" && v_dbW < "2") { + warning("The function 'dbW_upgrade_v2to3' upgrades weather databases from version 2.y.z to 3.0.0; this database is version ", v_dbW) + return(invisible(0)) } + + print(paste(Sys.time(), ": upgrading database", basename(dbWeatherDataFile), "to version 3.0.0")) + # Backup copy + backup_copy(dbWeatherDataFile, fbackup) + + # Add new table 'Meta' + DBI::dbGetQuery(con, "CREATE TABLE \"Meta\" (\"Desc\" TEXT PRIMARY KEY, \"Value\" TEXT);") + RSQLite::dbGetPreparedQuery(con, "INSERT INTO Meta VALUES(:Desc, :Value)", + bind.data = data.frame(Desc = c("Version", "Compression_type"), + Value = c("3.0.0", "gzip"))) + + # Delete old table 'Version' + DBI::dbGetQuery(con, "DROP TABLE Version;") + + # Checks and clean-up + check_updatedDB(con) + DBI::dbDisconnect(con) + + invisible(0) +} + + +dbW_upgrade_v1to2 <- function(dbWeatherDataFile, fbackup = NULL, SWRunInformation) { + con <- DBI::dbConnect(RSQLite::SQLite(), dbname = dbWeatherDataFile) + v_dbW <- try(numeric_version(as.character(DBI::dbGetQuery(con, "SELECT Version FROM Version;"))), silent = TRUE) + + if (inherits(v_dbW, "try-error") || v_dbW >= "2" && v_dbW < "1") { + warning("The function 'dbW_upgrade_v1to2' upgrades weather databases from version 1.y.z to 2.0.0; this database is version ", v_dbW) + return(invisible(0)) + } + + print(paste(Sys.time(), ": upgrading database", basename(dbWeatherDataFile), "to version 2.0.0; be patient, this may take considerable time depending on the size of the database")) + + # Backup copy + backup_copy(dbWeatherDataFile, fbackup) runIDs_sites <- which(SWRunInformation[, "Include_YN"] > 0) # Rename table 'Sites' as 'Sites_old' - dbGetQuery(env.con$con, "ALTER TABLE Sites RENAME TO Sites_old;") + DBI::dbGetQuery(con, "ALTER TABLE Sites RENAME TO Sites_old;") # Add new table 'Sites' - dbGetQuery(env.con$con, "CREATE TABLE \"Sites\" (\"Site_id\" integer PRIMARY KEY, \"Latitude\" REAL, \"Longitude\" REAL, \"Label\" TEXT);") + DBI::dbGetQuery(con, "CREATE TABLE \"Sites\" (\"Site_id\" integer PRIMARY KEY, \"Latitude\" REAL, \"Longitude\" REAL, \"Label\" TEXT);") site_data <- data.frame(Site_id = SWRunInformation$site_id, Latitude = SWRunInformation$Y_WGS84, @@ -73,26 +165,26 @@ dbW_upgrade_v1to2 <- function(dbWeatherDataFile, fbackup = NULL, SWRunInformatio im <- match(site_data[runIDs_sites, "Site_id"], MetaData[, "Site_id"]) MetaData[im, c("Latitude", "Longitude", "Label")] <- site_data[runIDs_sites, c("Latitude", "Longitude", "Label")] - dbGetPreparedQuery(env.con$con, "INSERT INTO Sites VALUES(NULL, :Latitude, :Longitude, :Label)", bind.data = MetaData) + RSQLite::dbGetPreparedQuery(con, "INSERT INTO Sites VALUES(NULL, :Latitude, :Longitude, :Label)", bind.data = MetaData) } # Create step by step a new WeatherData table: Update Site_id based on matching labels of tables 'Sites' and 'Sites_old' - old_ids <- dbGetQuery(env.con$con, "SELECT Site_id, Scenario FROM WeatherData;") + old_ids <- DBI::dbGetQuery(con, "SELECT Site_id, Scenario FROM WeatherData;") index_old <- sort.int(unique(old_ids[, "Site_id"]), decreasing = TRUE) # this assumes that all new Site_id are larger than the old ones if (length(old_ids) > 0) { for (iold in index_old) { print(paste(Sys.time(), ":", iold, "out of", length(index_old))) - site_old <- dbGetQuery(env.con$con, paste("SELECT Latitude, Longitude, Label FROM Sites_old WHERE Site_id =", iold, ";")) + site_old <- DBI::dbGetQuery(con, paste("SELECT Latitude, Longitude, Label FROM Sites_old WHERE Site_id =", iold, ";")) if (nrow(site_old) == 1) { - site_new <- dbGetQuery(env.con$con, paste0("SELECT * FROM Sites WHERE Label = \'", site_old$Label, "\' AND Latitude = ", site_old$Latitude, " AND Longitude = ", site_old$Longitude, ";")) + site_new <- DBI::dbGetQuery(con, paste0("SELECT * FROM Sites WHERE Label = \'", site_old$Label, "\' AND Latitude = ", site_old$Latitude, " AND Longitude = ", site_old$Longitude, ";")) if (nrow(site_new) == 1) { - #dbGetQuery(env.con$con, paste("SELECT Site_id, Scenario, StartYear, EndYear FROM WeatherData WHERE Site_id =", iold, ";")) - dbGetQuery(env.con$con, paste("UPDATE WeatherData SET Site_id =", site_new$Site_id, "WHERE Site_id =", iold, ";")) + #DBI::dbGetQuery(con, paste("SELECT Site_id, Scenario, StartYear, EndYear FROM WeatherData WHERE Site_id =", iold, ";")) + DBI::dbGetQuery(con, paste("UPDATE WeatherData SET Site_id =", site_new$Site_id, "WHERE Site_id =", iold, ";")) } else { str(site_new) warning("No updated record for old site_id = ", iold) @@ -103,21 +195,51 @@ dbW_upgrade_v1to2 <- function(dbWeatherDataFile, fbackup = NULL, SWRunInformatio } } - cur_ids <- dbGetQuery(env.con$con, "SELECT Site_id, Scenario FROM WeatherData;") + cur_ids <- DBI::dbGetQuery(con, "SELECT Site_id, Scenario FROM WeatherData;") } - dbGetQuery(env.con$con, "DROP TABLE Sites_old;") + DBI::dbGetQuery(con, "DROP TABLE Sites_old;") # Update version number - dbGetQuery(env.con$con, "DROP TABLE Version;") - dbGetQuery(env.con$con, "CREATE TABLE \"Version\" (\"Version\" TEXT);") - dbGetQuery(env.con$con, "INSERT INTO Version (Version) VALUES (\"2.0.0\");") + DBI::dbGetQuery(con, "DROP TABLE Version;") + DBI::dbGetQuery(con, "CREATE TABLE \"Version\" (\"Version\" TEXT);") + DBI::dbGetQuery(con, "INSERT INTO Version (Version) VALUES (\"2.0.0\");") # Checks and clean-up - print(paste(Sys.time(), ": check database integrity")) - print(dbGetQuery(env.con$con, "PRAGMA integrity_check;")) - - print(dbGetQuery(env.con$con, "PRAGMA index_list(WeatherData);")) - print(dbGetQuery(env.con$con, "PRAGMA index_info(sqlite_autoindex_WeatherData_1);")) + check_updatedDB(con) + DBI::dbDisconnect(con) invisible(0) } + + +check_updatedDB <- function(con) { + print(paste0(Sys.time(), ": check database integrity")) + print(DBI::dbGetQuery(con, "PRAGMA integrity_check;")) + + print(DBI::dbGetQuery(con, "PRAGMA index_list(WeatherData);")) + print(DBI::dbGetQuery(con, "PRAGMA index_info(sqlite_autoindex_WeatherData_1);")) +} + + +backup_copy <- function(dbWeatherDataFile, fbackup = NULL) { + dbWeatherDataFile <- normalizePath(dbWeatherDataFile) + + dir_old <- getwd() + on.exit(setwd(dir_old)) + setwd(dirname(dbWeatherDataFile)) + + if (is.null(fbackup)) { + fbackup <- strsplit(basename(dbWeatherDataFile), split = ".", fixed = TRUE)[[1]] + fbackup <- paste0(paste(fbackup[1], collapse = ""), "_copy.", fbackup[length(fbackup)]) + } else { + fbackup <- basename(fbackup) + } + + res <- if (file.exists(dbWeatherDataFile) && !file.exists(fbackup)) { + system2("cp", args = c(basename(dbWeatherDataFile), fbackup)) + } else if (!file.exists(dbWeatherDataFile) && file.exists(fbackup)) { + system2("cp", args = c(fbackup, basename(dbWeatherDataFile))) + } + + res +} diff --git a/R/zzz.R b/R/zzz.R index 9c520868..55bc5378 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -17,13 +17,12 @@ ############################################################################### -.onAttach <- function(library, pkg) -{ - if(interactive()) - { +.onAttach <- function(library, pkg) { + if (interactive()) { meta <- packageDescription("Rsoilwat31") packageStartupMessage("Package 'Rsoilwat_31', ", meta$Version, " (", meta$Date, ").") - packageStartupMessage("Daily weather database version 2.0.0") + packageStartupMessage("Daily weather database version ", con.env$dbW_version) } + invisible() } diff --git a/man/Rsoilwat31-package.Rd b/man/Rsoilwat31-package.Rd deleted file mode 100644 index 92def479..00000000 --- a/man/Rsoilwat31-package.Rd +++ /dev/null @@ -1,74 +0,0 @@ -% -% TODO: Review -% -\name{Rsoilwat31} -\alias{Rsoilwat31} -\alias{Rsoilwat31-package} -\title{Package `Rsoilwat31': summary information} -\description{ - The package `Rsoilwat' / 'Rsoilwat31' is a R implementation of SoilWat Modeling Software. - The C code was converted into a library with input/output functions to R. - SoilWat is a simulator of the dynamics of soil water. Originally written - in the 1900's by a highly trained team of Botany's finest. It is now - maintained by Dr. William Lauenroth's Lab and Dr. Daniel Rodolphe Schlaepfer. - The input data structure is S4. Generic functions that apply to the input - container or individual object control setting/getting input data. Output - data is in the form of lists. -} - -\section{Version}{ -The version level of the package is given by the command -\code{packageDescription("Rsoilwat31")}. -The most recent version of the package can be obtained from -github at \url{https://github.com/Burke-Lauenroth-Lab/Rsoilwat} -} - -\section{Author}{ -Ryan Murphy, Department of Botany, Electrical Engineer, -University of Wyoming, Laramie, Wyoming -(\url{http://www.google}) - -Dr. Daniel Rodolphe Schlaepfer, Department of Botany, -University of Wyoming, Laramie, Wyoming, USA -(\url{https://sites.google.com/site/drschlaepfer/home}) -} - -\section{Licence}{ -This package and its documentation are usable under the terms of the -"GNU General Public License", a copy of which is distributed with the -package. While the software is freely usable, it would be appreciated -if a reference is inserted in publications or other work -which makes use of it; for this purpose, see the command -\code{citation("Rsoilwat31")}. -} - -\references{ - Bradford, J. B., D. R. Schlaepfer, and W. K. Lauenroth (2014) - Ecohydrology of adjacent sagebrush and lodgepole pine ecosystems: The consequences of climate change and disturbance. - \emph{Ecosystems} \bold{17}:590--605. - - Schlaepfer, D. R., W. K. Lauenroth, and J. B. Bradford (2012) - Ecohydrological niche of sagebrush ecosystems. - \emph{Ecohydrology} \bold{5}:453--466. - - Parton, W.J. (1978). - \emph{Abiotic section of ELM}. In: Grassland simulation model (ed. Innis, G.S.). - Springer New York, NY, pp. 31--53. - - Sala, O.E., Lauenroth, W.K. & Parton, W.J. (1992) - Long-term soil-water dynamics in the shortgrass steppe. - \emph{Ecology} \bold{73}:1175--1181. -} - -\section{Acknowledgements}{ -The package has evolved through several versions, developed over some months. - -Many thanks to all that points out bugs, provide suggestions and comments. -} -\seealso{ - \itemize{ - \item \code{\link{sw_exec}} for running a simulation - \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for data input - \item \code{\link{dbW_getWeatherData}} and \code{\link{getWeatherData_folders}} for weather data input - } -} diff --git a/man/Rsoilwat31.Rd b/man/Rsoilwat31.Rd new file mode 100644 index 00000000..bccfb1f8 --- /dev/null +++ b/man/Rsoilwat31.Rd @@ -0,0 +1,46 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Rsoilwat31.R +\docType{package} +\name{Rsoilwat31} +\alias{Rsoilwat31} +\alias{Rsoilwat31-package} +\title{Package `Rsoilwat31': summary information} +\description{ +The package `Rsoilwat' / 'Rsoilwat31' is a R implementation of SoilWat +Modeling Software. The C code was converted into a library with +input/output functions to R. SoilWat is a simulator of the dynamics of soil +water. Originally written in the 1900's by a highly trained team of Botany's +finest. It is now maintained by Dr. William Lauenroth's Lab and Dr. Daniel +Schlaepfer. The input data structure is S4. Generic functions that +apply to the input container or individual object control setting/getting +input data. Output data is in the form of lists. +} +\section{Version}{ + The version level of the package is given by the command +\code{packageDescription("Rsoilwat31")}. The most recent version of the +package can be obtained from github at +\url{https://github.com/Burke-Lauenroth-Lab/Rsoilwat} +} +\references{ +Bradford, J. B., D. R. Schlaepfer, and W. K. Lauenroth (2014) +Ecohydrology of adjacent sagebrush and lodgepole pine ecosystems: The +consequences of climate change and disturbance. \emph{Ecosystems} +\bold{17}:590--605. + +Schlaepfer, D. R., W. K. Lauenroth, and J. B. Bradford (2012) +Ecohydrological niche of sagebrush ecosystems. \emph{Ecohydrology} +\bold{5}:453--466. + +Parton, W.J. (1978). \emph{Abiotic section of ELM}. In: Grassland +simulation model (ed. Innis, G.S.). Springer New York, NY, pp. 31--53. + +Sala, O.E., Lauenroth, W.K. & Parton, W.J. (1992) Long-term soil-water +dynamics in the shortgrass steppe. \emph{Ecology} \bold{73}:1175--1181. +} +\seealso{ +\itemize{ \item \code{\link{sw_exec}} for running a simulation +\item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +data input \item \code{\link{dbW_getWeatherData}} and +\code{\link{getWeatherData_folders}} for weather data input } +} + diff --git a/man/dbW_blob_to_weatherData.Rd b/man/dbW_blob_to_weatherData.Rd new file mode 100644 index 00000000..d239a28e --- /dev/null +++ b/man/dbW_blob_to_weatherData.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/swFunctions.R +\name{dbW_blob_to_weatherData} +\alias{dbW_blob_to_weatherData} +\title{Conversion: (Compressed) raw vector (e.g., SQL-retrieved blob) to (uncompressed) object} +\usage{ +dbW_blob_to_weatherData(data_blob, type = "gzip") +} +\arguments{ +\item{data_blob}{A raw vector} + +\item{type}{A character string. One of c("gzip", "bzip2", "xz", "none").} +} +\description{ +The Rsoilwat SQlite-DB which manages daily weather data (each as a list of elements +of class 'swWeatherData'), uses internally (compressed) blobs. This function is used +to convert the blob object to the object used by Rsoilwat's simulation functions. +} +\seealso{ +\code{\link{memDecompress}}, \code{\link{unserialize}} +} + diff --git a/man/dbW_getSiteId.Rd b/man/dbW_getSiteId.Rd new file mode 100644 index 00000000..9474059a --- /dev/null +++ b/man/dbW_getSiteId.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/swFunctions.R +\name{dbW_getSiteId} +\alias{dbW_getSiteId} +\title{Extract weather database key to connect a site with weather data} +\usage{ +dbW_getSiteId(lat = NULL, long = NULL, Label = NULL) +} +\arguments{ +\item{lat}{A numeric value or \code{NULL}. The latitude in decimal degrees of WGS84. Northern latitude are positive, sites on the southern hemisphere have negative values.} + +\item{long}{A numeric value or \code{NULL}. The longitude in decimal degrees of WGS84. Eastern longitudes are positive, sites on the western hemisphere have negative values.} + +\item{Label}{A character string or \code{NULL}.} +} +\value{ +An integer value or \code{NULL}. +} +\description{ +Extract weather database key to connect a site with weather data +} +\details{ +The key (SiteId) can be located by either providing a \code{Label} or +by providing \code{lat} and \code{long} of the requested site. +} + diff --git a/man/dbW_getWeatherData.Rd b/man/dbW_getWeatherData.Rd index 796a5f7f..8ce7b7fb 100644 --- a/man/dbW_getWeatherData.Rd +++ b/man/dbW_getWeatherData.Rd @@ -1,49 +1,55 @@ -% -% TODO: Write Documentation -% +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/swFunctions.R \name{dbW_getWeatherData} \alias{dbW_getWeatherData} \title{Extracts daily weather data from a SQLite database} -\description{ -Reads weather data from database. -Returns list of weather data. -} \usage{ -dbW_getWeatherData(con, Site_id = NULL, lat = NULL, long = NULL, weatherDirName = NULL, startYear = NULL, endYear = NULL) +dbW_getWeatherData(Site_id = NULL, lat = NULL, long = NULL, + Label = NULL, startYear = NULL, endYear = NULL, Scenario = "Current") } \arguments{ - \item{con}{RSQLite con object. A connection to the weather data database. requires(RSQLite)} - \item{Site_id}{Numeric. Used to identify site and extract weather data.} - \item{lat}{Numeric. Latitude used with longitude to identify site id if Site_id is missing.} - \item{long}{Numeric. Longitude and Latitude are used to identify site if Site_id is missing.} - \item{weatherDirName}{String. If Site_id, lat, and long is missing then this will be used to identify Site_id by parsing the lat and long out of the name.} - \item{startYear}{Numeric. Extracted weather data will start with this year.} - \item{endYear}{Numeric. Extracted weather data will end with this year.} -} -\details{ - Weather data for the soil water simulation run can be stored in the input data - or it can be separate to keep the input data size down for multiple variations - of the same site. This function is used to return the weather data from a pre - defined weather database. Using the database was faster then reading in multiple - weather files from disk. - - SOILWAT does not handle missing weather data. If you have missing data, then you have to impute yourself - or use the built-in Markov weather generator (see examples for \code{\link{sw_exec}}). - - The output from this function can be passed directly to sw_exec with input data. +\item{Site_id}{Numeric. Used to identify site and extract weather data.} + +\item{lat}{Numeric. Latitude used with longitude to identify site id if +Site_id is missing.} + +\item{long}{Numeric. Longitude and Latitude are used to identify site if +Site_id is missing.} + +\item{startYear}{Numeric. Extracted weather data will start with this year.} + +\item{endYear}{Numeric. Extracted weather data will end with this year.} + +\item{con}{RSQLite con object. A connection to the weather data database. +requires(RSQLite)} + +\item{weatherDirName}{String. If Site_id, lat, and long is missing then this +will be used to identify Site_id by parsing the lat and long out of the +name.} } \value{ - Returns weather data as list. Each element contains data for one year. +Returns weather data as list. Each element contains data for one +year. } -\author{Ryan Murphy} -\seealso{ - \itemize{ - \item \code{\link{sw_exec}} for running a simulation - \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for data input - \item \code{\link{dbW_getWeatherData}} and \code{\link{getWeatherData_folders}} for weather data input - } +\description{ +Reads weather data from database. Returns list of weather data. +} +\details{ +Weather data for the soil water simulation run can be stored in the input +data or it can be separate to keep the input data size down for multiple +variations of the same site. This function is used to return the weather +data from a pre defined weather database. Using the database was faster then +reading in multiple weather files from disk. + +SOILWAT does not handle missing weather data. If you have missing data, then +you have to impute yourself or use the built-in Markov weather generator +(see examples for \code{\link{sw_exec}}). + +The output from this function can be passed directly to sw_exec with input +data. } \examples{ + ## Default data set without weather data. ## Column Names are also turned on for output library(Rsoilwat) @@ -54,4 +60,15 @@ dbW_getWeatherData(con, Site_id = NULL, lat = NULL, long = NULL, weatherDirName weatherData <- dbW_getWeatherData(con, Site_id=200) #Run the simulation run<-sw_exec(data=inputData, weatherList=weatherData, colNames=TRUE) + +} +\author{ +Ryan Murphy +} +\seealso{ +\itemize{ \item \code{\link{sw_exec}} for running a simulation +\item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +data input \item \code{\link{dbW_getWeatherData}} and +\code{\link{getWeatherData_folders}} for weather data input } } + diff --git a/man/dbW_weatherData_to_blob.Rd b/man/dbW_weatherData_to_blob.Rd new file mode 100644 index 00000000..139bf3ab --- /dev/null +++ b/man/dbW_weatherData_to_blob.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/swFunctions.R +\name{dbW_weatherData_to_blob} +\alias{dbW_weatherData_to_blob} +\title{Conversion: R object to (compressed) SQL-blob-ready character vector} +\usage{ +dbW_weatherData_to_blob(weatherData, type = "gzip") +} +\arguments{ +\item{weatherData}{A list of elements of class 'swWeatherData' or any suitable object.} + +\item{type}{A character string. One of c("gzip", "bzip2", "xz", "none").} +} +\description{ +The Rsoilwat SQLite-DB which manages daily weather data (each as a list of elements +of class 'swWeatherData'), uses internally (compressed) blobs. This function is used +to a list of daily weather data used by Rsoilwat's simulation functions to a blob object +which can be inserted into a SQLite DB. +} +\seealso{ +\code{\link{memCompress}}, \code{\link{serialize}} +} + diff --git a/man/deleteSiteData.Rd b/man/deleteSiteData.Rd deleted file mode 100644 index ca4bda24..00000000 --- a/man/deleteSiteData.Rd +++ /dev/null @@ -1,39 +0,0 @@ -% -% TODO: Write Documentation -% -\name{deleteSiteData} -\alias{deleteSiteData} -\title{Rsoilwat deleteSiteData} -\description{ - Remove one or more weather Data Scenario(s) from Weather Database. -} -\usage{ - deleteSiteData(dbFilePath, Site_id, Scenario=NULL) -} -\arguments{ - \item{dbFilePath}{A filepath to the existing database file.} - \item{Site_id}{The Id of the Site to remove data from.} - \item{Scenario}{Removes given scenario or all if NULL.} -} -\details{ - Removes one or all scenarios for a site. Will also remove site if - it has no more data. -} -\value{ - Returns nothing if pass. If fails then error message. -} -\author{Ryan Murphy} -\seealso{ - \code{\link{swInputData}} - \code{\link{sw_exec}} - \code{\link{sw_inputDataFromFiles}} - \code{\link{getWeatherData_folders}} - \code{\link{addWeatherDataToDataBase}} - \code{\link{createDatabase}} - \code{\link{getWeatherData_database}} - \code{\link{deleteSiteData}} -} -\examples{ - deleteSiteData(dbFilePath="dbWeatherData.sqlite", Site_id=1)) -} -\keyword{deleteSiteData} \ No newline at end of file diff --git a/man/getWeatherData_folders.Rd b/man/getWeatherData_folders.Rd index 4cd49360..38097e02 100644 --- a/man/getWeatherData_folders.Rd +++ b/man/getWeatherData_folders.Rd @@ -1,46 +1,47 @@ -% -% TODO: Review -% +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/swFunctions.R \name{getWeatherData_folders} \alias{getWeatherData_folders} \title{Rsoilwat getWeatherData_folders} -\description{ - Reads weather data from files. - Returns list of weather data. -} \usage{ - getWeatherData_folders(LookupWeatherFolder=NULL, weatherDirName=NULL, filebasename=NULL, startYear=NULL, endYear=NULL) +getWeatherData_folders(LookupWeatherFolder = NULL, weatherDirName = NULL, + filebasename = NULL, startYear = NULL, endYear = NULL) } \arguments{ - \item{LookupWeatherFolder}{String Path. Path to the LookupWeatherFolder location.} - \item{weatherDirName}{String. Name of the folder containing weather data files.} - \item{filebasename}{String. File prefix for weather data. Usually 'weath'.} - \item{startYear}{Numeric. Extracted weather data will start with this year.} - \item{endYear}{Numeric. Extracted weather data will end with this year.} -} -\details{ - Weather data for the soil water simulation run can be stored in the input data - or it can be separate to keep the input data size down for multiple variations - of the same site. This function is used to return the weather data from folders. - The other option is to use onGetWeatherData_database. - - SOILWAT does not handle missing weather data. If you have missing data, then you have to impute yourself - or use the built-in Markov weather generator (see examples for \code{\link{sw_exec}}). - - The output from this function can be passed directly to sw_exec with input data. +\item{LookupWeatherFolder}{String Path. Path to the LookupWeatherFolder +location.} + +\item{weatherDirName}{String. Name of the folder containing weather data +files.} + +\item{filebasename}{String. File prefix for weather data. Usually 'weath'.} + +\item{startYear}{Numeric. Extracted weather data will start with this year.} + +\item{endYear}{Numeric. Extracted weather data will end with this year.} } \value{ - Returns weather data as list. Each element contains data for one year. +Returns weather data as list. Each element contains data for one +year. } -\author{Ryan Murphy} -\seealso{ - \itemize{ - \item \code{\link{sw_exec}} for running a simulation - \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for data input - \item \code{\link{dbW_getWeatherData}} and \code{\link{getWeatherData_folders}} for weather data input - } +\description{ +Reads weather data from files. Returns list of weather data. +} +\details{ +Weather data for the soil water simulation run can be stored in the input +data or it can be separate to keep the input data size down for multiple +variations of the same site. This function is used to return the weather +data from folders. The other option is to use onGetWeatherData_database. + +SOILWAT does not handle missing weather data. If you have missing data, then +you have to impute yourself or use the built-in Markov weather generator +(see examples for \code{\link{sw_exec}}). + +The output from this function can be passed directly to sw_exec with input +data. } \examples{ + path_demo <- dirname(system.file("extdata", "files_v31.in", package = "Rsoilwat31")) ## ------ Simulation with data prepared beforehand and separate weather data ------------ @@ -55,4 +56,15 @@ str(sw_weath3, max.level=1) ## Execute the simulation run sw_out3 <- sw_exec(inputData = sw_in3, weatherList = sw_weath3) + +} +\author{ +Ryan Murphy } +\seealso{ +\itemize{ \item \code{\link{sw_exec}} for running a simulation +\item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +data input \item \code{\link{dbW_getWeatherData}} and +\code{\link{getWeatherData_folders}} for weather data input } +} + diff --git a/man/swInputData-class.Rd b/man/swInputData-class.Rd index 3a39bb1e..df42ca16 100644 --- a/man/swInputData-class.Rd +++ b/man/swInputData-class.Rd @@ -1,408 +1,210 @@ -\name{swInputData-class} -\Rdversion{1.1} +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Rsoilwat31.R \docType{class} -\alias{swInputData-class} +\name{swInputData-class} \alias{get_Markov,swInputData-method} +\alias{get_WeatherHistory,swInputData-method} \alias{get_swCloud,swInputData-method} \alias{get_swFiles,swInputData-method} \alias{get_swOUT,swInputData-method} \alias{get_swProd,swInputData-method} +\alias{get_swSWC,swInputData-method} \alias{get_swSite,swInputData-method} \alias{get_swSoils,swInputData-method} -\alias{get_swSWC,swInputData-method} -\alias{get_swWeatherData,swInputData-method} \alias{get_swWeather,swInputData-method} +\alias{get_swWeatherData,swInputData-method} \alias{get_swYears,swInputData-method} -\alias{get_WeatherHistory,swInputData-method} \alias{set_Markov<-,swInputData-method} +\alias{set_WeatherHistory<-,swInputData,list-method} \alias{set_swCloud<-,swInputData-method} \alias{set_swFiles<-,swInputData-method} \alias{set_swOUT<-,swInputData-method} \alias{set_swProd<-,swInputData-method} +\alias{set_swSWC<-,swInputData,swSWC-method} \alias{set_swSite<-,swInputData-method} \alias{set_swSoils<-,swInputData,swSoils-method} -\alias{set_swSWC<-,swInputData,swSWC-method} -\alias{set_swWeatherData<-,swInputData,swWeatherData-method} \alias{set_swWeather<-,swInputData-method} +\alias{set_swWeatherData<-,swInputData,swWeatherData-method} \alias{set_swYears<-,swInputData-method} -\alias{set_WeatherHistory<-,swInputData,list-method} \alias{swClear,swInputData-method} -\alias{swCloud_Humidity<-,swInputData-method} \alias{swCloud_Humidity,swInputData-method} -\alias{swCloud_SkyCover<-,swInputData-method} +\alias{swCloud_Humidity<-,swInputData-method} \alias{swCloud_SkyCover,swInputData-method} -\alias{swCloud_SnowDensity<-,swInputData-method} +\alias{swCloud_SkyCover<-,swInputData-method} \alias{swCloud_SnowDensity,swInputData-method} -\alias{swCloud_Transmissivity<-,swInputData-method} +\alias{swCloud_SnowDensity<-,swInputData-method} \alias{swCloud_Transmissivity,swInputData-method} -\alias{swCloud_WindSpeed<-,swInputData-method} +\alias{swCloud_Transmissivity<-,swInputData-method} \alias{swCloud_WindSpeed,swInputData-method} -\alias{swFiles_Cloud<-,swInputData-method} +\alias{swCloud_WindSpeed<-,swInputData-method} \alias{swFiles_Cloud,swInputData-method} -\alias{swFiles_Estab<-,swInputData-method} +\alias{swFiles_Cloud<-,swInputData-method} \alias{swFiles_Estab,swInputData-method} -\alias{swFiles_filesIn<-,swInputData-method} -\alias{swFiles_filesIn,swInputData-method} -\alias{swFiles_LogFile<-,swInputData-method} +\alias{swFiles_Estab<-,swInputData-method} \alias{swFiles_LogFile,swInputData-method} -\alias{swFiles_MarkovCov<-,swInputData-method} +\alias{swFiles_LogFile<-,swInputData-method} \alias{swFiles_MarkovCov,swInputData-method} -\alias{swFiles_MarkovProbs<-,swInputData-method} +\alias{swFiles_MarkovCov<-,swInputData-method} \alias{swFiles_MarkovProbs,swInputData-method} -\alias{swFiles_OutputPrefix<-,swInputData-method} -\alias{swFiles_OutputPrefix,swInputData-method} -\alias{swFiles_Output<-,swInputData-method} +\alias{swFiles_MarkovProbs<-,swInputData-method} \alias{swFiles_Output,swInputData-method} -\alias{swFiles_Prod<-,swInputData-method} +\alias{swFiles_Output<-,swInputData-method} +\alias{swFiles_OutputPrefix,swInputData-method} +\alias{swFiles_OutputPrefix<-,swInputData-method} \alias{swFiles_Prod,swInputData-method} -\alias{swFiles_ProjDir<-,swInputData-method} +\alias{swFiles_Prod<-,swInputData-method} \alias{swFiles_ProjDir,swInputData-method} -\alias{swFiles_SiteParams<-,swInputData-method} +\alias{swFiles_ProjDir<-,swInputData-method} +\alias{swFiles_SWCsetup,swInputData-method} +\alias{swFiles_SWCsetup<-,swInputData-method} \alias{swFiles_SiteParams,swInputData-method} -\alias{swFiles_Soils<-,swInputData-method} +\alias{swFiles_SiteParams<-,swInputData-method} \alias{swFiles_Soils,swInputData-method} -\alias{swFiles_SWCsetup<-,swInputData-method} -\alias{swFiles_SWCsetup,swInputData-method} -\alias{swFiles_WeatherPrefix<-,swInputData-method} +\alias{swFiles_Soils<-,swInputData-method} \alias{swFiles_WeatherPrefix,swInputData-method} -\alias{swFiles_WeatherSetup<-,swInputData-method} +\alias{swFiles_WeatherPrefix<-,swInputData-method} \alias{swFiles_WeatherSetup,swInputData-method} -\alias{swFiles_Years<-,swInputData-method} +\alias{swFiles_WeatherSetup<-,swInputData-method} \alias{swFiles_Years,swInputData-method} +\alias{swFiles_Years<-,swInputData-method} +\alias{swFiles_filesIn,swInputData-method} +\alias{swFiles_filesIn<-,swInputData-method} +\alias{swInputData-class} \alias{swLog_setLine<-,swInputData-method} -\alias{swMarkov_Conv<-,swInputData-method} \alias{swMarkov_Conv,swInputData-method} -\alias{swMarkov_Prob<-,swInputData-method} +\alias{swMarkov_Conv<-,swInputData-method} \alias{swMarkov_Prob,swInputData-method} -\alias{swOUT_OutputSeparator<-,swInputData-method} +\alias{swMarkov_Prob<-,swInputData-method} \alias{swOUT_OutputSeparator,swInputData-method} -\alias{swOUT_TimeStep<-,swInputData-method} +\alias{swOUT_OutputSeparator<-,swInputData-method} \alias{swOUT_TimeStep,swInputData-method} -\alias{swProd_Albedo<-,swInputData-method} +\alias{swOUT_TimeStep<-,swInputData-method} \alias{swProd_Albedo,swInputData-method} -\alias{swProd_CanopyHeight<-,swInputData-method} +\alias{swProd_Albedo<-,swInputData-method} \alias{swProd_CanopyHeight,swInputData-method} -\alias{swProd_Composition<-,swInputData-method} +\alias{swProd_CanopyHeight<-,swInputData-method} \alias{swProd_Composition,swInputData-method} -\alias{swProd_Cover_stcr<-,swInputData-method} +\alias{swProd_Composition<-,swInputData-method} \alias{swProd_Cover_stcr,swInputData-method} -\alias{swProd_CritSoilWaterPotential<-,swInputData-method} +\alias{swProd_Cover_stcr<-,swInputData-method} \alias{swProd_CritSoilWaterPotential,swInputData-method} -\alias{swProd_Es_param_limit<-,swInputData-method} -\alias{swProd_Es_param_limit,swInputData-method} -\alias{swProd_EsTpartitioning_param<-,swInputData-method} +\alias{swProd_CritSoilWaterPotential<-,swInputData-method} \alias{swProd_EsTpartitioning_param,swInputData-method} -\alias{swProd_HydrRedstro<-,swInputData-method} +\alias{swProd_EsTpartitioning_param<-,swInputData-method} +\alias{swProd_Es_param_limit,swInputData-method} +\alias{swProd_Es_param_limit<-,swInputData-method} \alias{swProd_HydrRedstro,swInputData-method} -\alias{swProd_HydrRedstro_use<-,swInputData-method} +\alias{swProd_HydrRedstro<-,swInputData-method} \alias{swProd_HydrRedstro_use,swInputData-method} -\alias{swProd_LitterInterParam<-,swInputData-method} +\alias{swProd_HydrRedstro_use<-,swInputData-method} \alias{swProd_LitterInterParam,swInputData-method} -\alias{swProd_MonProd_grass<-,swInputData-method} +\alias{swProd_LitterInterParam<-,swInputData-method} \alias{swProd_MonProd_grass,swInputData-method} -\alias{swProd_MonProd_shrub<-,swInputData-method} +\alias{swProd_MonProd_grass<-,swInputData-method} \alias{swProd_MonProd_shrub,swInputData-method} -\alias{swProd_MonProd_tree<-,swInputData-method} +\alias{swProd_MonProd_shrub<-,swInputData-method} \alias{swProd_MonProd_tree,swInputData-method} -\alias{swProd_Shade<-,swInputData-method} +\alias{swProd_MonProd_tree<-,swInputData-method} \alias{swProd_Shade,swInputData-method} -\alias{swProd_VegInterParam<-,swInputData-method} +\alias{swProd_Shade<-,swInputData-method} \alias{swProd_VegInterParam,swInputData-method} +\alias{swProd_VegInterParam<-,swInputData-method} \alias{swReadLines,swInputData,character-method} -\alias{swSite_DrainageCoefficient<-,swInputData-method} +\alias{swSWC_FirstYear,swInputData-method} +\alias{swSWC_FirstYear<-,swInputData,integer-method} +\alias{swSWC_HistoricData,swInputData-method} +\alias{swSWC_HistoricData<-,swInputData,swSWC_hist-method} +\alias{swSWC_HistoricList,swInputData-method} +\alias{swSWC_HistoricList<-,swInputData,list-method} +\alias{swSWC_Method,swInputData-method} +\alias{swSWC_Method<-,swInputData,integer-method} +\alias{swSWC_prefix,swInputData-method} +\alias{swSWC_prefix<-,swInputData,character-method} +\alias{swSWC_use,swInputData-method} +\alias{swSWC_use<-,swInputData,logical-method} \alias{swSite_DrainageCoefficient,swInputData-method} -\alias{swSite_EvapCoefficients<-,swInputData-method} +\alias{swSite_DrainageCoefficient<-,swInputData-method} \alias{swSite_EvapCoefficients,swInputData-method} -\alias{swSite_IntrinsicSiteParams<-,swInputData-method} +\alias{swSite_EvapCoefficients<-,swInputData-method} \alias{swSite_IntrinsicSiteParams,swInputData-method} -\alias{swSite_ModelCoefficients<-,swInputData-method} +\alias{swSite_IntrinsicSiteParams<-,swInputData-method} \alias{swSite_ModelCoefficients,swInputData-method} -\alias{swSite_ModelFlags<-,swInputData-method} +\alias{swSite_ModelCoefficients<-,swInputData-method} \alias{swSite_ModelFlags,swInputData-method} -\alias{swSite_SnowSimulationParams<-,swInputData-method} +\alias{swSite_ModelFlags<-,swInputData-method} +\alias{swSite_SWClimits,swInputData-method} +\alias{swSite_SWClimits<-,swInputData-method} \alias{swSite_SnowSimulationParams,swInputData-method} -\alias{swSite_SoilTemperatureConsts<-,swInputData-method} +\alias{swSite_SnowSimulationParams<-,swInputData-method} \alias{swSite_SoilTemperatureConsts,swInputData-method} -\alias{swSite_SoilTemperatureFlag<-,swInputData-method} +\alias{swSite_SoilTemperatureConsts<-,swInputData-method} \alias{swSite_SoilTemperatureFlag,swInputData-method} -\alias{swSite_SWClimits<-,swInputData-method} -\alias{swSite_SWClimits,swInputData-method} -\alias{swSite_TranspCoefficients<-,swInputData-method} +\alias{swSite_SoilTemperatureFlag<-,swInputData-method} \alias{swSite_TranspCoefficients,swInputData-method} -\alias{swSite_TranspirationRegions<-,swInputData-method} +\alias{swSite_TranspCoefficients<-,swInputData-method} \alias{swSite_TranspirationRegions,swInputData-method} -\alias{swSoils_Layers<-,swInputData,matrix-method} +\alias{swSite_TranspirationRegions<-,swInputData-method} \alias{swSoils_Layers,swInputData-method} -\alias{swSWC_FirstYear<-,swInputData,integer-method} -\alias{swSWC_FirstYear,swInputData-method} -\alias{swSWC_HistoricData<-,swInputData,swSWC_hist-method} -\alias{swSWC_HistoricData,swInputData-method} -\alias{swSWC_HistoricList<-,swInputData,list-method} -\alias{swSWC_HistoricList,swInputData-method} -\alias{swSWC_Method<-,swInputData,integer-method} -\alias{swSWC_Method,swInputData-method} -\alias{swSWC_prefix<-,swInputData,character-method} -\alias{swSWC_prefix,swInputData-method} -\alias{swSWC_use<-,swInputData,logical-method} -\alias{swSWC_use,swInputData-method} -\alias{swWeather_DaysRunningAverage<-,swInputData-method} +\alias{swSoils_Layers<-,swInputData,matrix-method} \alias{swWeather_DaysRunningAverage,swInputData-method} -\alias{swWeather_FirstYearHistorical<-,swInputData-method} +\alias{swWeather_DaysRunningAverage<-,swInputData-method} \alias{swWeather_FirstYearHistorical,swInputData-method} -\alias{swWeather_MonScalingParams<-,swInputData-method} +\alias{swWeather_FirstYearHistorical<-,swInputData-method} \alias{swWeather_MonScalingParams,swInputData-method} -\alias{swWeather_pct_SnowDrift<-,swInputData-method} -\alias{swWeather_pct_SnowDrift,swInputData-method} -\alias{swWeather_pct_SnowRunoff<-,swInputData-method} -\alias{swWeather_pct_SnowRunoff,swInputData-method} -\alias{swWeather_UseMarkov<-,swInputData-method} +\alias{swWeather_MonScalingParams<-,swInputData-method} \alias{swWeather_UseMarkov,swInputData-method} -\alias{swWeather_UseSnow<-,swInputData-method} +\alias{swWeather_UseMarkov<-,swInputData-method} \alias{swWeather_UseSnow,swInputData-method} +\alias{swWeather_UseSnow<-,swInputData-method} +\alias{swWeather_pct_SnowDrift,swInputData-method} +\alias{swWeather_pct_SnowDrift<-,swInputData-method} +\alias{swWeather_pct_SnowRunoff,swInputData-method} +\alias{swWeather_pct_SnowRunoff<-,swInputData-method} \alias{swWriteLines,swInputData,character-method} -\alias{swYears_EDOEY<-,swInputData-method} \alias{swYears_EDOEY,swInputData-method} -\alias{swYears_EndYear<-,swInputData-method} +\alias{swYears_EDOEY<-,swInputData-method} \alias{swYears_EndYear,swInputData-method} -\alias{swYears_FDOFY<-,swInputData-method} +\alias{swYears_EndYear<-,swInputData-method} \alias{swYears_FDOFY,swInputData-method} -\alias{swYears_isNorth<-,swInputData-method} -\alias{swYears_isNorth,swInputData-method} -\alias{swYears_StartYear<-,swInputData-method} +\alias{swYears_FDOFY<-,swInputData-method} \alias{swYears_StartYear,swInputData-method} - +\alias{swYears_StartYear<-,swInputData-method} +\alias{swYears_isNorth,swInputData-method} +\alias{swYears_isNorth<-,swInputData-method} \title{Class \code{"swInputData"}} \description{ -%% ~~ A concise (1-5 lines) description of what the class is. ~~ - This class is a container class to the input file S4 objects. - The generic functions listed work on this and the proper sw - Class in the container's slots. -} -\section{Objects from the Class}{ -Objects can be created by calls of the form \code{new("swInputData", ...)}. -%% ~~ describe objects here ~~ +%% ~~ A concise (1-5 lines) description of what the class is. ~~ This class +is a container class to the input file S4 objects. The generic functions +listed work on this and the proper sw Class in the container's slots. } -\section{Slots}{ - \describe{ - \item{\code{files}:}{Object of class \code{"swFiles"} ~~ } - \item{\code{years}:}{Object of class \code{"swYears"} ~~ } - \item{\code{weather}:}{Object of class \code{"swWeather"} ~~ } - \item{\code{cloud}:}{Object of class \code{"swCloud"} ~~ } - \item{\code{weatherHistory}:}{Object of class \code{"list"} ~~ } - \item{\code{markov}:}{Object of class \code{"swMarkov"} ~~ } - \item{\code{prod}:}{Object of class \code{"swProd"} ~~ } - \item{\code{site}:}{Object of class \code{"swSite"} ~~ } - \item{\code{soils}:}{Object of class \code{"swSoils"} ~~ } - \item{\code{estab}:}{Object of class \code{"swEstab"} ~~ } - \item{\code{output}:}{Object of class \code{"swOUT"} ~~ } - \item{\code{swc}:}{Object of class \code{"swSWC"} ~~ } - \item{\code{log}:}{Object of class \code{"swLog"} ~~ } - } +\note{ +%% ~~further notes~~ } -\section{Methods}{ - \describe{ - \item{get_Markov}{\code{signature(object = "swInputData")}: ... } - \item{get_swCloud}{\code{signature(object = "swInputData")}: ... } - \item{get_swFiles}{\code{signature(object = "swInputData")}: ... } - \item{get_swOUT}{\code{signature(object = "swInputData")}: ... } - \item{get_swProd}{\code{signature(object = "swInputData")}: ... } - \item{get_swSite}{\code{signature(object = "swInputData")}: ... } - \item{get_swSoils}{\code{signature(object = "swInputData")}: ... } - \item{get_swSWC}{\code{signature(object = "swInputData")}: ... } - \item{get_swWeatherData}{\code{signature(object = "swInputData")}: ... } - \item{get_swWeather}{\code{signature(object = "swInputData")}: ... } - \item{get_swYears}{\code{signature(object = "swInputData")}: ... } - \item{get_WeatherHistory}{\code{signature(object = "swInputData")}: ... } - \item{set_Markov<-}{\code{signature(object = "swInputData")}: ... } - \item{set_swCloud<-}{\code{signature(object = "swInputData")}: ... } - \item{set_swFiles<-}{\code{signature(object = "swInputData")}: ... } - \item{set_swOUT<-}{\code{signature(object = "swInputData")}: ... } - \item{set_swProd<-}{\code{signature(object = "swInputData")}: ... } - \item{set_swSite<-}{\code{signature(object = "swInputData")}: ... } - \item{set_swSoils<-}{\code{signature(object = "swInputData", value = "swSoils")}: ... } - \item{set_swSWC<-}{\code{signature(object = "swInputData", swSWC = "swSWC")}: ... } - \item{set_swWeatherData<-}{\code{signature(object = "swInputData", value = "swWeatherData")}: ... } - \item{set_swWeather<-}{\code{signature(object = "swInputData")}: ... } - \item{set_swYears<-}{\code{signature(object = "swInputData")}: ... } - \item{set_WeatherHistory<-}{\code{signature(object = "swInputData", value = "list")}: ... } - \item{swClear}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_Humidity<-}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_Humidity}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_SkyCover<-}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_SkyCover}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_SnowDensity<-}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_SnowDensity}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_Transmissivity<-}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_Transmissivity}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_WindSpeed<-}{\code{signature(object = "swInputData")}: ... } - \item{swCloud_WindSpeed}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Cloud<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Cloud}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Estab<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Estab}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_filesIn<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_filesIn}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_LogFile<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_LogFile}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_MarkovCov<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_MarkovCov}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_MarkovProbs<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_MarkovProbs}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_OutputPrefix<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_OutputPrefix}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Output<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Output}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Prod<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Prod}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_ProjDir<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_ProjDir}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_SiteParams<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_SiteParams}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Soils<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Soils}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_SWCsetup<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_SWCsetup}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_WeatherPrefix<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_WeatherPrefix}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_WeatherSetup<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_WeatherSetup}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Years<-}{\code{signature(object = "swInputData")}: ... } - \item{swFiles_Years}{\code{signature(object = "swInputData")}: ... } - \item{swLog_setLine<-}{\code{signature(object = "swInputData")}: ... } - \item{swMarkov_Conv<-}{\code{signature(object = "swInputData")}: ... } - \item{swMarkov_Conv}{\code{signature(object = "swInputData")}: ... } - \item{swMarkov_Prob<-}{\code{signature(object = "swInputData")}: ... } - \item{swMarkov_Prob}{\code{signature(object = "swInputData")}: ... } - \item{swOUT_OutputSeparator<-}{\code{signature(object = "swInputData")}: ... } - \item{swOUT_OutputSeparator}{\code{signature(object = "swInputData")}: ... } - \item{swOUT_TimeStep<-}{\code{signature(object = "swInputData")}: ... } - \item{swOUT_TimeStep}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Albedo<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Albedo}{\code{signature(object = "swInputData")}: ... } - \item{swProd_CanopyHeight<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_CanopyHeight}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Composition<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Composition}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Cover_stcr<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Cover_stcr}{\code{signature(object = "swInputData")}: ... } - \item{swProd_CritSoilWaterPotential<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_CritSoilWaterPotential}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Es_param_limit<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Es_param_limit}{\code{signature(object = "swInputData")}: ... } - \item{swProd_EsTpartitioning_param<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_EsTpartitioning_param}{\code{signature(object = "swInputData")}: ... } - \item{swProd_HydrRedstro<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_HydrRedstro}{\code{signature(object = "swInputData")}: ... } - \item{swProd_HydrRedstro_use<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_HydrRedstro_use}{\code{signature(object = "swInputData")}: ... } - \item{swProd_LitterInterParam<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_LitterInterParam}{\code{signature(object = "swInputData")}: ... } - \item{swProd_MonProd_grass<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_MonProd_grass}{\code{signature(object = "swInputData")}: ... } - \item{swProd_MonProd_shrub<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_MonProd_shrub}{\code{signature(object = "swInputData")}: ... } - \item{swProd_MonProd_tree<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_MonProd_tree}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Shade<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_Shade}{\code{signature(object = "swInputData")}: ... } - \item{swProd_VegInterParam<-}{\code{signature(object = "swInputData")}: ... } - \item{swProd_VegInterParam}{\code{signature(object = "swInputData")}: ... } - \item{swReadLines}{\code{signature(object = "swInputData", file = "character")}: ... } - \item{swSite_DrainageCoefficient<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_DrainageCoefficient}{\code{signature(object = "swInputData")}: ... } - \item{swSite_EvapCoefficients<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_EvapCoefficients}{\code{signature(object = "swInputData")}: ... } - \item{swSite_IntrinsicSiteParams<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_IntrinsicSiteParams}{\code{signature(object = "swInputData")}: ... } - \item{swSite_ModelCoefficients<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_ModelCoefficients}{\code{signature(object = "swInputData")}: ... } - \item{swSite_ModelFlags<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_ModelFlags}{\code{signature(object = "swInputData")}: ... } - \item{swSite_SnowSimulationParams<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_SnowSimulationParams}{\code{signature(object = "swInputData")}: ... } - \item{swSite_SoilTemperatureConsts<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_SoilTemperatureConsts}{\code{signature(object = "swInputData")}: ... } - \item{swSite_SoilTemperatureFlag<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_SoilTemperatureFlag}{\code{signature(object = "swInputData")}: ... } - \item{swSite_SWClimits<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_SWClimits}{\code{signature(object = "swInputData")}: ... } - \item{swSite_TranspCoefficients<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_TranspCoefficients}{\code{signature(object = "swInputData")}: ... } - \item{swSite_TranspirationRegions<-}{\code{signature(object = "swInputData")}: ... } - \item{swSite_TranspirationRegions}{\code{signature(object = "swInputData")}: ... } - \item{swSoils_Layers<-}{\code{signature(object = "swInputData", value = "matrix")}: ... } - \item{swSoils_Layers}{\code{signature(object = "swInputData")}: ... } - \item{swSWC_FirstYear<-}{\code{signature(object = "swInputData", SWCfirstYear = "integer")}: ... } - \item{swSWC_FirstYear}{\code{signature(object = "swInputData")}: ... } - \item{swSWC_HistoricData<-}{\code{signature(object = "swInputData", swSWCdata = "swSWC_hist")}: ... } - \item{swSWC_HistoricData}{\code{signature(object = "swInputData")}: ... } - \item{swSWC_HistoricList<-}{\code{signature(object = "swInputData", swSWC_HistoricList = "list")}: ... } - \item{swSWC_HistoricList}{\code{signature(object = "swInputData")}: ... } - \item{swSWC_Method<-}{\code{signature(object = "swInputData", SWCmethod = "integer")}: ... } - \item{swSWC_Method}{\code{signature(object = "swInputData")}: ... } - \item{swSWC_prefix<-}{\code{signature(object = "swInputData", SWCprefix = "character")}: ... } - \item{swSWC_prefix}{\code{signature(object = "swInputData")}: ... } - \item{swSWC_use<-}{\code{signature(object = "swInputData", UseSWC = "logical")}: ... } - \item{swSWC_use}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_DaysRunningAverage<-}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_DaysRunningAverage}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_FirstYearHistorical<-}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_FirstYearHistorical}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_MonScalingParams<-}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_MonScalingParams}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_pct_SnowDrift<-}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_pct_SnowDrift}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_pct_SnowRunoff<-}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_pct_SnowRunoff}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_UseMarkov<-}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_UseMarkov}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_UseSnow<-}{\code{signature(object = "swInputData")}: ... } - \item{swWeather_UseSnow}{\code{signature(object = "swInputData")}: ... } - \item{swWriteLines}{\code{signature(object = "swInputData", file = "character")}: ... } - \item{swYears_EDOEY<-}{\code{signature(object = "swInputData")}: ... } - \item{swYears_EDOEY}{\code{signature(object = "swInputData")}: ... } - \item{swYears_EndYear<-}{\code{signature(object = "swInputData")}: ... } - \item{swYears_EndYear}{\code{signature(object = "swInputData")}: ... } - \item{swYears_FDOFY<-}{\code{signature(object = "swInputData")}: ... } - \item{swYears_FDOFY}{\code{signature(object = "swInputData")}: ... } - \item{swYears_isNorth<-}{\code{signature(object = "swInputData")}: ... } - \item{swYears_isNorth}{\code{signature(object = "swInputData")}: ... } - \item{swYears_StartYear<-}{\code{signature(object = "swInputData")}: ... } - \item{swYears_StartYear}{\code{signature(object = "swInputData")}: ... } - } +\section{Objects from the Class}{ + Objects can be created by calls of the form +\code{new("swInputData", ...)}. %% ~~ describe objects here ~~ } -\references{ -%% ~~put references to the literature/web site here~~ - https://github.com/Burke-Lauenroth-Lab/Rsoilwat +\examples{ + +showClass("swInputData") + } \author{ -%% ~~who you are~~ - Ryan Murphy +%% ~~who you are~~ Ryan Murphy } -\note{ -%% ~~further notes~~ - +\references{ +%% ~~put references to the literature/web site here~~ +https://github.com/Burke-Lauenroth-Lab/Rsoilwat } - -%% ~Make other sections like Warning with \section{Warning }{....} ~ - \seealso{ -%% ~~objects to See Also as \code{\link{~~fun~~}}, ~~~ -%% ~~or \code{\linkS4class{CLASSNAME}} for links to other classes ~~~ -\code{\linkS4class{swFiles}} -\code{\linkS4class{swYears}} -\code{\linkS4class{swWeather}} -\code{\linkS4class{swCloud}} -\code{\linkS4class{swMarkov}} -\code{\linkS4class{swProd}} -\code{\linkS4class{swSite}} -\code{\linkS4class{swSoils}} -\code{\linkS4class{swEstab}} -\code{\linkS4class{swOUT}} -\code{\linkS4class{swSWC}} -\code{\linkS4class{swLog}} -} -\examples{ -showClass("swInputData") +%% ~~objects to See Also as \code{\link{~~fun~~}}, ~~~ %% ~~or +\code{\linkS4class{CLASSNAME}} for links to other classes ~~~ +\code{\linkS4class{swFiles}} \code{\linkS4class{swYears}} +\code{\linkS4class{swWeather}} \code{\linkS4class{swCloud}} +\code{\linkS4class{swMarkov}} \code{\linkS4class{swProd}} +\code{\linkS4class{swSite}} \code{\linkS4class{swSoils}} +\code{\linkS4class{swEstab}} \code{\linkS4class{swOUT}} +\code{\linkS4class{swSWC}} \code{\linkS4class{swLog}} } \keyword{classes} + diff --git a/man/swReadLines.Rd b/man/swReadLines.Rd deleted file mode 100644 index 4706d89f..00000000 --- a/man/swReadLines.Rd +++ /dev/null @@ -1,36 +0,0 @@ -% -% TODO: Write Documentation -% -\name{swReadLines} -\alias{swReadLines} -\title{Rsoilwat swReadLines} -\description{ - Reads input data to file(s) from within R. - This does not use C code. -} -\usage{ - swReadLines(object) -} -\arguments{ - \item{object}{S4 Rsoilwat inputData class.} -} -\details{ - This will write to hard drive the file represented by the object. -} -\value{ - returns nothing -} -\author{Ryan Murphy} -\seealso{ - \code{\link{swInputData}} - \code{\link{sw_exec}} - \code{\link{sw_inputDataFromFiles}} - \code{\link{onGetWeatherData_database}} -} -\examples{ - ## Default data set without weather data. - ## Column Names are also turned on for output - inputData <- sw_inputDataFromFiles(dir="/path/to/project",files.in="files_v27.in") #Get the data set - swReadLines(get_swSite) -} -\keyword{swWriteLines} diff --git a/man/swWriteLines.Rd b/man/swWriteLines.Rd deleted file mode 100644 index 55416fb0..00000000 --- a/man/swWriteLines.Rd +++ /dev/null @@ -1,37 +0,0 @@ -% -% TODO: Write Documentation -% -\name{swWriteLines} -\alias{swWriteLines} -\title{Rsoilwat swWriteLines} -\description{ - Writes input data to file(s). -} -\usage{ - swWriteLines(object) -} -\arguments{ - \item{object}{S4 Rsoilwat inputData class.} - \item{dir}{String for the path to recreate Project in} -} -\details{ - This will write to hard drive the file represented by the object. -} -\value{ - returns nothing -} -\author{Ryan Murphy} -\seealso{ - \code{\link{swInputData}} - \code{\link{sw_exec}} - \code{\link{sw_inputDataFromFiles}} - \code{\link{onGetWeatherData_database}} -} -\examples{ - ## Default data set without weather data. - ## Column Names are also turned on for output - inputData <- sw_inputDataFromFiles(dir="/path/to/project",files.in="files_v27.in") #Get the data set - swWriteLines(get_swSite) -} -\keyword{swWriteLines} - diff --git a/man/sw_exec.Rd b/man/sw_exec.Rd index 89a2849c..a9efaad2 100644 --- a/man/sw_exec.Rd +++ b/man/sw_exec.Rd @@ -1,76 +1,70 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Rsw.R \name{sw_exec} \alias{sw_exec} \title{Execute a SOILWAT simulation run} -\description{ - Run the simulation and get the output data. - Executes Soil Water simulator and returns Soil Water data via List. - Uses .Call to pass data to/from C library. -} \usage{ -sw_exec(inputData = NULL, weatherList = NULL, dir = "", files.in = "files_v31.in", echo = FALSE, quiet = FALSE) +sw_exec(inputData = NULL, weatherList = NULL, dir = "", + files.in = "files_v31.in", echo = FALSE, quiet = FALSE) } \arguments{ - \item{inputData}{an object of the S4 class \code{swInputData} which is generated from \code{\link{sw_inputData}} or \code{\link{sw_inputDataFromFiles}}.} - \item{weatherList}{a list of weather data generated via \code{\link{dbW_getWeatherData}} or \code{\link{getWeatherData_folders}}.} - \item{dir}{a character vector that represents the path to the input data. Use with files.in} - \item{files.in}{a character vector that represents the partial path of the 'files.in' file} - \item{echo}{logical. This option will echo the inputs to the Log Data. Helpful for debugging.} - \item{quiet}{logical. Quiet mode doesn't print messages to the logfile.} -} -\details{ - The input data for a simulation run can be passed to the function \code{\link{sw_exec}} either as \code{swInputData} and \code{weatherList} or as text files organized in a folder \code{dir} and explained in \code{files.in}. - - The weather data can be a part of the input - data S4 class or separate as a list to reduce the input object size. - The option 'weatherList' if set will use the weatherList provided - and not the inputdata object's weather data if it has it. Weather - data can also be read in when 'dir' and 'files.in' are set. - - SOILWAT does not handle missing data. If you have missing data, then you have to impute yourself - or use the built-in Markov weather generator (see examples section). If you use the weather generator, - then you have to provide appropriate values for the input (files) 'mkv_covar.in' and 'mkv_prob.in' - for your simulation run - currently, SOILWAT does not contain code to estimate these values. +\item{inputData}{an object of the S4 class \code{swInputData} which is +generated from \code{\link{sw_inputData}} or +\code{\link{sw_inputDataFromFiles}}.} + +\item{weatherList}{a list of weather data generated via +\code{\link{dbW_getWeatherData}} or \code{\link{getWeatherData_folders}}.} + +\item{dir}{a character vector that represents the path to the input data. +Use with files.in} + +\item{files.in}{a character vector that represents the partial path of the +'files.in' file} + +\item{echo}{logical. This option will echo the inputs to the Log Data. +Helpful for debugging.} + +\item{quiet}{logical. Quiet mode doesn't print messages to the logfile.} } \value{ - A S4 Object Containing 28 outputkey slots. - Each of those has slots for Yr Mo Wk Dy. - - NOTE: WTHR ALLH2O ET ALLVEG do not work. - - The output also contains slots for the number of rows - for each time period. Individual outputKeys also have slots - for time periods used. Title from outputsetup. They also have - the number of data columns. - - These elements contain the output data from soilwat based on the outputSetup. - Output columns should all be labeled. +A S4 Object Containing 28 outputkey slots. Each of those has slots +for Yr Mo Wk Dy. + +NOTE: WTHR ALLH2O ET ALLVEG do not work. + +The output also contains slots for the number of rows for each time period. +Individual outputKeys also have slots for time periods used. Title from +outputsetup. They also have the number of data columns. + +These elements contain the output data from soilwat based on the +outputSetup. Output columns should all be labeled. } -\references{ - Bradford, J. B., D. R. Schlaepfer, and W. K. Lauenroth (2014) - Ecohydrology of adjacent sagebrush and lodgepole pine ecosystems: The consequences of climate change and disturbance. - \emph{Ecosystems} \bold{17}:590--605. - - Schlaepfer, D. R., W. K. Lauenroth, and J. B. Bradford (2012) - Ecohydrological niche of sagebrush ecosystems. - \emph{Ecohydrology} \bold{5}:453--466. - - Parton, W.J. (1978). - \emph{Abiotic section of ELM}. In: Grassland simulation model (ed. Innis, G.S.). - Springer New York, NY, pp. 31--53. - - Sala, O.E., Lauenroth, W.K. & Parton, W.J. (1992) - Long-term soil-water dynamics in the shortgrass steppe. - \emph{Ecology} \bold{73}:1175--1181. +\description{ +Run the simulation and get the output data. Executes Soil Water simulator +and returns Soil Water data via List. Uses .Call to pass data to/from C +library. } -\author{Ryan Murphy} -\seealso{ - \itemize{ - \item \code{\link{sw_exec}} for running a simulation - \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for data input - \item \code{\link{dbW_getWeatherData}} and \code{\link{getWeatherData_folders}} for weather data input - } +\details{ +The input data for a simulation run can be passed to the function +\code{\link{sw_exec}} either as \code{swInputData} and \code{weatherList} or +as text files organized in a folder \code{dir} and explained in +\code{files.in}. + +The weather data can be a part of the input data S4 class or separate as a +list to reduce the input object size. The option 'weatherList' if set will +use the weatherList provided and not the inputdata object's weather data if +it has it. Weather data can also be read in when 'dir' and 'files.in' are +set. + +SOILWAT does not handle missing data. If you have missing data, then you +have to impute yourself or use the built-in Markov weather generator (see +examples section). If you use the weather generator, then you have to +provide appropriate values for the input (files) 'mkv_covar.in' and +'mkv_prob.in' for your simulation run - currently, SOILWAT does not contain +code to estimate these values. } \examples{ + ## ------ Simulation with demonstration data ------------ ## Access demonstration data (including daily weather forcing) sw_in <- sw_inputData() @@ -121,7 +115,7 @@ sw_out3 <- sw_exec(inputData = sw_in3, weatherList = sw_weath3) ## ------ Simulation with manipulated input data ------------ sw_in4 <- sw_in3 -## Set the vegetation composition to 40% grass and 60% shrubs +## Set the vegetation composition to 40\% grass and 60\% shrubs swProd_Composition(sw_in4) <- c(0.4, 0.6, 0, 0, 0) ## Execute the simulation run @@ -143,4 +137,31 @@ sw_out5 <- sw_exec(inputData = sw_in5, weatherList = NULL) ## See help(package = "Rsoilwat31") for a full list of functions + } +\author{ +Ryan Murphy +} +\references{ +Bradford, J. B., D. R. Schlaepfer, and W. K. Lauenroth (2014) +Ecohydrology of adjacent sagebrush and lodgepole pine ecosystems: The +consequences of climate change and disturbance. \emph{Ecosystems} +\bold{17}:590--605. + +Schlaepfer, D. R., W. K. Lauenroth, and J. B. Bradford (2012) +Ecohydrological niche of sagebrush ecosystems. \emph{Ecohydrology} +\bold{5}:453--466. + +Parton, W.J. (1978). \emph{Abiotic section of ELM}. In: Grassland +simulation model (ed. Innis, G.S.). Springer New York, NY, pp. 31--53. + +Sala, O.E., Lauenroth, W.K. & Parton, W.J. (1992) Long-term soil-water +dynamics in the shortgrass steppe. \emph{Ecology} \bold{73}:1175--1181. +} +\seealso{ +\itemize{ \item \code{\link{sw_exec}} for running a simulation +\item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +data input \item \code{\link{dbW_getWeatherData}} and +\code{\link{getWeatherData_folders}} for weather data input } +} + diff --git a/man/sw_inputData.Rd b/man/sw_inputData.Rd index e25b0b47..1d8e7e3f 100644 --- a/man/sw_inputData.Rd +++ b/man/sw_inputData.Rd @@ -1,72 +1,52 @@ -% -% TODO: Review -% +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Rsw.R \name{sw_inputData} \alias{sw_inputData} \title{Rsoilwat sw_inputData} -\description{ - Default data Set for SoilWat. - Use this as a template or for testing the package. -} \usage{ - sw_inputData() -} -\arguments{ - -} -\details{ - swInputData Object is a S4 object containing slots for all input data. - Calling sw_inputData() generates a new swInputData object with test - project data loaded into them. This can be used for testing or as a - template to build another project off of. - - The data returned can be directly used to run the simulation. Use the - function sw_exec and pass it the output from this function to run SW. - - \code{showMethods(class="swInputData")} # Will show all generic functions that - be applied to the inputData. These include getters/setters for slots. - - swInputData consists of slots for each file that is read in. These slots - can be accessed via the following functions: - \tabular{ll}{ - \code{get_Markov} \tab #get markov prop and conv\cr - \code{get_swCloud} \tab #get cloud\cr - \code{get_swFiles} \tab #get files.in\cr - \code{get_swOUT} \tab #get outpusetup.in\cr - \code{get_swProd} \tab #get prod.in\cr - \code{get_swSite} \tab #get site.in\cr - \code{get_swSoils} \tab #get soils.in\cr - \code{get_swSWC} \tab #get swcSetup.in\cr - \code{get_swWeather} \tab #get weatherSetup.in\cr - \code{get_swWeatherData} \tab #get individual year\cr - \code{get_swYears} \tab #get years.in data object\cr - \code{get_WeatherHistory} \tab #get S4 of WeatherHistory\cr - } - - generic functions to get/set individual elements follow a format: - 'sw' + file name + '_' + option, e.g. - \itemize{ - \item \code{swFiles_Cloud} - \item \code{swProd_Albedo} - } - Remember tab complete is your friend. - - SOILWAT does not handle missing data. If you have missing data, then you have to impute yourself - or use the built-in Markov weather generator (see examples for \code{\link{sw_exec}}). +sw_inputData() } \value{ - Returns a S4 class of type swInputData. This is a container for the input - S4 objects used to run soilwat. The data for a test project is loaded. +Returns a S4 class of type swInputData. This is a container for the +input S4 objects used to run soilwat. The data for a test project is loaded. } -\author{Ryan Murphy} -\seealso{ - \itemize{ - \item \code{\link{sw_exec}} for running a simulation - \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for data input - \item \code{\link{dbW_getWeatherData}} and \code{\link{getWeatherData_folders}} for weather data input - } +\description{ +Default data Set for SoilWat. Use this as a template or for testing the +package. +} +\details{ +swInputData Object is a S4 object containing slots for all input data. +Calling sw_inputData() generates a new swInputData object with test project +data loaded into them. This can be used for testing or as a template to +build another project off of. + +The data returned can be directly used to run the simulation. Use the +function sw_exec and pass it the output from this function to run SW. + +\code{showMethods(class="swInputData")} # Will show all generic functions +that be applied to the inputData. These include getters/setters for slots. + +swInputData consists of slots for each file that is read in. These slots can +be accessed via the following functions: \tabular{ll}{ \code{get_Markov} +\tab #get markov prop and conv\cr \code{get_swCloud} \tab #get cloud\cr +\code{get_swFiles} \tab #get files.in\cr \code{get_swOUT} \tab #get +outpusetup.in\cr \code{get_swProd} \tab #get prod.in\cr \code{get_swSite} +\tab #get site.in\cr \code{get_swSoils} \tab #get soils.in\cr +\code{get_swSWC} \tab #get swcSetup.in\cr \code{get_swWeather} \tab #get +weatherSetup.in\cr \code{get_swWeatherData} \tab #get individual year\cr +\code{get_swYears} \tab #get years.in data object\cr +\code{get_WeatherHistory} \tab #get S4 of WeatherHistory\cr } + +generic functions to get/set individual elements follow a format: 'sw' + +file name + '_' + option, e.g. \itemize{ \item \code{swFiles_Cloud} \item +\code{swProd_Albedo} } Remember tab complete is your friend. + +SOILWAT does not handle missing data. If you have missing data, then you +have to impute yourself or use the built-in Markov weather generator (see +examples for \code{\link{sw_exec}}). } \examples{ + ## ------ Simulation with demonstration data ------------ ## Access demonstration data (including daily weather forcing) sw_in <- sw_inputData() @@ -76,5 +56,15 @@ str(sw_in, max.level=2) ## Execute the simulation run sw_out <- sw_exec(inputData = sw_in) + +} +\author{ +Ryan Murphy +} +\seealso{ +\itemize{ \item \code{\link{sw_exec}} for running a simulation +\item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +data input \item \code{\link{dbW_getWeatherData}} and +\code{\link{getWeatherData_folders}} for weather data input } } diff --git a/man/sw_inputDataFromFiles.Rd b/man/sw_inputDataFromFiles.Rd index 82ddf215..a4455a9f 100644 --- a/man/sw_inputDataFromFiles.Rd +++ b/man/sw_inputDataFromFiles.Rd @@ -1,71 +1,56 @@ -% -% TODO: Write Documentation -% +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/Rsw.R \name{sw_inputDataFromFiles} \alias{sw_inputDataFromFiles} \title{Rsoilwat sw_inputDataFromFiles} -\description{ - Reads in a SoilWat Project's input data. - Returns swInputData Object. -} \usage{ - sw_inputDataFromFiles(dir="", files.in="") +sw_inputDataFromFiles(dir = "", files.in = "files_v30.in") } \arguments{ - \item{dir}{String. The path to the Project Directory. Use with files.in} - \item{files.in}{String. The partial path, after project dir path, and file name to files.in file.} -} -\details{ - swInputData Object is a S4 object containing slots for all input data. - Calling sw_inputDataFromFiles generates a new swInputData object with - data from the Project files given. - - The data returned can be directly used to run the simulation if weather Data - was included in the Project Directory. If weather data was not in the project - directory then use onGetWeatherData_database or onGetWeatherData_folders to - obtain weatherDataList and pass both to sw_exec. - - swInputData consists of slots for each file that is read in. These slots - can be accessed via the following functions: - \tabular{ll}{ - \code{get_Markov} \tab #get markov prop and conv\cr - \code{get_swCloud} \tab #get cloud\cr - \code{get_swFiles} \tab #get files.in\cr - \code{get_swOUT} \tab #get outpusetup.in\cr - \code{get_swProd} \tab #get prod.in\cr - \code{get_swSite} \tab #get site.in\cr - \code{get_swSoils} \tab #get soils.in\cr - \code{get_swSWC} \tab #get swcSetup.in\cr - \code{get_swWeather} \tab #get weatherSetup.in\cr - \code{get_swWeatherData} \tab #get individual year\cr - \code{get_swYears} \tab #get years.in data object\cr - \code{get_WeatherHistory} \tab #get S4 of WeatherHistory\cr - } - - generic functions to get/set individual elements follow a format: - 'sw' + file name + '_' + option, e.g. - \itemize{ - \item \code{swFiles_Cloud} - \item \code{swProd_Albedo} - } - Remember tab complete is your friend. - - SOILWAT does not handle missing weather data. If you have missing data, then you have to impute yourself - or use the built-in Markov weather generator (see examples for \code{\link{sw_exec}}). +\item{dir}{String. The path to the Project Directory. Use with files.in} + +\item{files.in}{String. The partial path, after project dir path, and file +name to files.in file.} } \value{ - Returns a S4 class of type swInputData. This is a container for the input - S4 objects used to run soilwat. The data for the given project is loaded. +Returns a S4 class of type swInputData. This is a container for the +input S4 objects used to run soilwat. The data for the given project is +loaded. } -\author{Ryan Murphy} -\seealso{ - \itemize{ - \item \code{\link{sw_exec}} for running a simulation - \item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for data input - \item \code{\link{dbW_getWeatherData}} and \code{\link{getWeatherData_folders}} for weather data input - } +\description{ +Reads in a SoilWat Project's input data. Returns swInputData Object. +} +\details{ +swInputData Object is a S4 object containing slots for all input data. +Calling sw_inputDataFromFiles generates a new swInputData object with data +from the Project files given. + +The data returned can be directly used to run the simulation if weather Data +was included in the Project Directory. If weather data was not in the +project directory then use onGetWeatherData_database or +onGetWeatherData_folders to obtain weatherDataList and pass both to sw_exec. + +swInputData consists of slots for each file that is read in. These slots can +be accessed via the following functions: \tabular{ll}{ \code{get_Markov} +\tab #get markov prop and conv\cr \code{get_swCloud} \tab #get cloud\cr +\code{get_swFiles} \tab #get files.in\cr \code{get_swOUT} \tab #get +outpusetup.in\cr \code{get_swProd} \tab #get prod.in\cr \code{get_swSite} +\tab #get site.in\cr \code{get_swSoils} \tab #get soils.in\cr +\code{get_swSWC} \tab #get swcSetup.in\cr \code{get_swWeather} \tab #get +weatherSetup.in\cr \code{get_swWeatherData} \tab #get individual year\cr +\code{get_swYears} \tab #get years.in data object\cr +\code{get_WeatherHistory} \tab #get S4 of WeatherHistory\cr } + +generic functions to get/set individual elements follow a format: 'sw' + +file name + '_' + option, e.g. \itemize{ \item \code{swFiles_Cloud} \item +\code{swProd_Albedo} } Remember tab complete is your friend. + +SOILWAT does not handle missing weather data. If you have missing data, then +you have to impute yourself or use the built-in Markov weather generator +(see examples for \code{\link{sw_exec}}). } \examples{ + path_demo <- dirname(system.file("extdata", "files_v31.in", package = "Rsoilwat31")) @@ -79,5 +64,15 @@ str(sw_in2, max.level=2) ## Execute the simulation run sw_out2 <- sw_exec(inputData = sw_in2) + +} +\author{ +Ryan Murphy +} +\seealso{ +\itemize{ \item \code{\link{sw_exec}} for running a simulation +\item \code{\link{sw_inputData}} and \code{\link{sw_inputDataFromFiles}} for +data input \item \code{\link{dbW_getWeatherData}} and +\code{\link{getWeatherData_folders}} for weather data input } } diff --git a/tests/Test_Rsoilwat31_SegmentationFault_v3.R b/tests/Test_Rsoilwat31_SegmentationFault_v3.R deleted file mode 100644 index f393927c..00000000 --- a/tests/Test_Rsoilwat31_SegmentationFault_v3.R +++ /dev/null @@ -1,43 +0,0 @@ -# Running from command line --> segfaults -# r --slave -f Test_Rsoilwat31_SegmentationFault_v3.R -# r -d "valgrind --dsymutil=yes --leak-check=full --track-origins=yes --expensive-definedness-checks=yes" --slave -f Test_Rsoilwat31_SegmentationFault_v3.R -# r -d "valgrind --vgdb-error=0" --slave -f Test_Rsoilwat31_SegmentationFault_v3.R - -# Running interactively with source() --> segfaults on the second time source() is called -# r -d lldb # run -# r via r.app GUI - -options(warn=0, error=traceback) -options(CBoundsCheck = TRUE) #https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Debugging-compiled-code -gctorture(FALSE) #https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Using-gctorture - -#comp <- "eo" # "err" -#.libPaths(new=file.path(getwd(), "Packages", comp, "debug")) -#.libPaths(new=file.path(getwd(), "Packages", comp, "normal")) -library(Rsoilwat31) - -print(sessionInfo()) - -print("Step 1") -a <- sw_inputDataFromFiles(dir = dirname(system.file("extdata", "files_v31.in", package = "Rsoilwat31")), files.in = "files_v31.in") - -print("Step 2") -# Location of segfaults with upper bound of b -# - (eo/debug/!interactive()): step 2 >= 558151 > step 3 >= 558105 > step 4 >= 555193 > no segfault -b <- 1:1e6 -b2 <- 1:1e7 -b3 <- 1:1e7 - -print("Step 3") -elems <- ls() - -print("Step 4") -if(length(elems) > 0){ - for(i in seq_along(elems)){ - x <- get(elems[i]) - print(paste(i, elems[i], object.size(x))) - } -} - -print("No segmentation fault") - diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 00000000..db5f137b --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,4 @@ +library(testthat) +library(Rsoilwat31) + +test_check("Rsoilwat") diff --git a/tests/testthat/test_SegmentationFault_v3.R b/tests/testthat/test_SegmentationFault_v3.R new file mode 100644 index 00000000..ee4884ec --- /dev/null +++ b/tests/testthat/test_SegmentationFault_v3.R @@ -0,0 +1,34 @@ +context("Rsoilwat segfault") + +# Running from command line --> segfaults +# r --slave -f Test_Rsoilwat31_SegmentationFault_v3.R +# r -d "valgrind --dsymutil=yes --leak-check=full --track-origins=yes --expensive-definedness-checks=yes" --slave -f Test_Rsoilwat31_SegmentationFault_v3.R +# r -d "valgrind --vgdb-error=0" --slave -f Test_Rsoilwat31_SegmentationFault_v3.R + +# Running interactively with source() --> segfaults on the second time source() is called +# r -d lldb # run +# r via r.app GUI + +#options(warn=0, error=traceback) +#options(CBoundsCheck = TRUE) #https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Debugging-compiled-code +#gctorture(FALSE) #https://cran.r-project.org/doc/manuals/r-release/R-exts.html#Using-gctorture + + +# Create reference objects +path_demo <- system.file("extdata", "example1", package = "Rsoilwat31") + +a <- sw_inputDataFromFiles(dir = path_demo, files.in = file.path(path_demo, "files_v31.in")) + +# Location of segfaults with upper bound of b +# - (eo/debug/!interactive()): step 2 >= 558151 > step 3 >= 558105 > step 4 >= 555193 > no segfault +b <- 1:1e6 +b2 <- 1:1e7 +b3 <- 1:1e7 + +test_that("Test for segfault", { + expect_silent({ + elems <- ls(envir = .GlobalEnv) + if (length(elems) > 0) for (i in seq_along(elems)) x <- get(elems[i]) + }) +}) + diff --git a/tests/testthat/test_dbWeather_Compression.R b/tests/testthat/test_dbWeather_Compression.R new file mode 100644 index 00000000..d3788701 --- /dev/null +++ b/tests/testthat/test_dbWeather_Compression.R @@ -0,0 +1,119 @@ +context("Test dbWeather compression types") + +# Create reference objects +do_benchmark <- FALSE +year_start <- 1979 +year_end <- 2010 +path_demo <- system.file("extdata", "example1", package = "Rsoilwat31") + +dbWs3 <- list(list(fname = "dbWeatherData_test1_gzip_old.sqlite3", type = "gzip", mode = "old"), + list(fname = "dbWeatherData_test1_gzip_new.sqlite3", type = "gzip", mode = "new"), + list(fname = "dbWeatherData_test1_bzip2_old.sqlite3", type = "bzip2", mode = "old"), + list(fname = "dbWeatherData_test1_bzip2_new.sqlite3", type = "bzip2", mode = "new"), + list(fname = "dbWeatherData_test1_xy_old.sqlite3", type = "xy", mode = "old"), + list(fname = "dbWeatherData_test1_xy_new.sqlite3", type = "xy", mode = "new"), + list(fname = "dbWeatherData_test1_none_old.sqlite3", type = "none", mode = "old"), + list(fname = "dbWeatherData_test1_none_new.sqlite3", type = "none", mode = "new")) + +sw_weath <- getWeatherData_folders( + LookupWeatherFolder = file.path(path_demo, "Input"), + weatherDirName = "data_weather", + filebasename = "weath", startYear = year_start, endYear = year_end) + +site_ids <- seq_len(10) +site_data <- data.frame(Site_id = site_ids, + Latitude = site_ids, + Longitude = site_ids, + Label = paste0("site", site_ids)) + +for (it in seq_along(dbWs3)) { + dbW_createDatabase(dbFilePath = dbWs3[[it]]$fname, + site_data = site_data, + scenarios = data.frame(Scenario = "Current"), + compression_type = dbWs3[[it]]$type) + dbW_setConnection(dbFilePath = dbWs3[[it]]$fname) + + for (iw in site_ids) { + if (dbWs3[[it]]$mode == "new") { + dbW_addWeatherData(Site_id = iw, + weatherData = sw_weath, + ScenarioName = "Current") + } else { + Rsoilwat31:::dbW_addWeatherData_old(Site_id = iw, + weatherData = sw_weath, + ScenarioName = "Current") + } + } + dbW_disconnectConnection() +} + +print("Compression rates of dbWeather:") +dbW_disk <- sapply(dbWs3, function(dbW) file.size(dbW$fname)) +dbW_disk <- matrix(1 - signif(dbW_disk / max(dbW_disk, na.rm = TRUE), 2), ncol = 1) +dimnames(dbW_disk) <- list(sapply(dbWs3, function(x) paste(x$type, x$mode, sep = "-")), + "Compression_ratio") + +print(dbW_disk) + + +# Test object identity +test_that("Test weather object coherence", { + skip_on_cran() + + for (it in seq_along(dbWs3)) { + dbW_setConnection(dbFilePath = dbWs3[[it]]$fname) + + for (iw in site_ids) { + expect_equal(sw_weath, + if (dbWs3[[it]]$mode == "new") { + dbW_getWeatherData(Site_id = iw, + startYear = year_start, + endYear = year_end, + Scenario = "Current") + } else { + Rsoilwat31:::dbW_getWeatherData_old(Site_id = iw, + startYear = year_start, + endYear = year_end, + Scenario = "Current") + }) + } + dbW_disconnectConnection() + } +}) + + +# Compare speed +test_that("Benchmark dbWeather retrieval speed", { + skip_on_cran() + skip_if_not_installed("microbenchmark") + skip_if_not(do_benchmark, "Benchmarking is turned off.") + + retrievals <- function(path_dbW, site_ids, mode) { + dbW_setConnection(dbFilePath = path_dbW) + + for (iw in site_ids) { + temp <- if (mode == "new") { + dbW_getWeatherData(Site_id = iw, + startYear = year_start, + endYear = year_end, + Scenario = "Current") + } else { + Rsoilwat31:::dbW_getWeatherData_old(Site_id = iw, + startYear = year_start, + endYear = year_end, + Scenario = "Current") + } + } + dbW_disconnectConnection() + } + + to_bench <- lapply(dbWs3, function(dbW) + call("retrievals", path_dbW = dbW$fname, site_ids = site_ids, mode = dbW$mode)) + names(to_bench) <- sapply(dbWs3, function(x) paste(x$type, x$mode, sep = "-")) + + expect_s3_class(bench <- microbenchmark::microbenchmark(list = to_bench, times = 200), "microbenchmark") + print(bench) +}) + +# Clean up +temp <- sapply(dbWs3, function(dbW) unlink(dbW$fname))