From 89b179d273ceb79ade933643bcc3604456a6382f Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Mon, 28 Jan 2019 15:10:36 -0500 Subject: [PATCH 01/37] allow for returning objects other than Annotated, see #19 --- R/functions.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/functions.R b/R/functions.R index b955fb3..4299f55 100644 --- a/R/functions.R +++ b/R/functions.R @@ -161,6 +161,7 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA S4Vectors::metadata(object) = list(PEP=pep) object }else{ - stop("Type error: The 'object' argument has to be of class 'Annotated', got '", class(object),"'. And the pep argument has to be of class 'Project', got '", class(pep),"'") + warning("The 'object' argument has to be of class 'Annotated', got '", class(object),"'. And the pep argument has to be of class 'Project', got '", class(pep),"'") + list(result=object,metadata=pep) } } From a8eb491bcd997ca824e3ed3e1c1c7de9bb7cba1e Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Mon, 28 Jan 2019 16:26:31 -0500 Subject: [PATCH 02/37] return just an error message in .callBiocFun error handler --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index f69ee5b..9c0792e 100644 --- a/R/utils.R +++ b/R/utils.R @@ -34,7 +34,7 @@ # error handler .wrapFunMessages(e$message,"error") message("No data was read. The error message was returned instead.") - List(e$message) + e$message } res = withCallingHandlers(tryCatch(do.call(func, arguments), error = eHandler),warning = wHandler) if(length(.warnings) > 0){ From 8b88002d4ca1d5b3be7240032ab65d7b46db4eba Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Mon, 28 Jan 2019 16:39:42 -0500 Subject: [PATCH 03/37] error handling related changes --- R/functions.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/functions.R b/R/functions.R index 4299f55..b8186ee 100644 --- a/R/functions.R +++ b/R/functions.R @@ -85,6 +85,7 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA # use the anonymous function if provided if (is.function(func)) { readData = .callBiocFun(func, list(p)) + message("Used function from the 'func' argument") return(.insertPEP(readData, p)) } else{ stop("The anonymous function you provided is invalid.") @@ -162,6 +163,6 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA object }else{ warning("The 'object' argument has to be of class 'Annotated', got '", class(object),"'. And the pep argument has to be of class 'Project', got '", class(pep),"'") - list(result=object,metadata=pep) + S4Vectors::List(result=object,metadata=pep) } } From 831e1bb336f155e190615df5af5e4daf25dbc133 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 11:56:34 -0500 Subject: [PATCH 04/37] allow to pass func args from the config, resolves #22 --- R/functions.R | 17 ++++++++++------- R/methods_Annotated.R | 5 ++++- R/utils.R | 24 ++++++++++++++++++++++++ man/BiocProject.Rd | 2 +- man/is-Annotated-method.Rd | 5 +++++ 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/R/functions.R b/R/functions.R index b8186ee..53c06f5 100644 --- a/R/functions.R +++ b/R/functions.R @@ -50,7 +50,7 @@ #' See \code{Details} for more information #' @param funcArgs a named list with arguments you want to pass to the \code{func}. #' The PEP will be passed automatically, -#' but if provided regardless, the constructor will disregard it +#' but if provided regardless, the constructor will disregard it. You can also pass the arguments in a \code{funcArgs} section within the \code{bioconductor} section in the config file. #' @param autoLoad a logical indicating whether the data should be loaded #' automatically. See \code{Details} for more information. #' @@ -80,6 +80,9 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA funcArgs = funcArgs[-which(pepArgs)] } args = append(list(p), funcArgs) + if(pepr::checkSection(pepr::config(p), c("bioconductor", "funcArgs"))){ + args = .updateList(args,p@config$bioconductor$funcArgs) + } if (!is.null(func)) { # use the anonymous function if provided @@ -94,11 +97,11 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA # use config to find it if (autoLoad) { # check if the config consists of bioconductor section - if(is.null(pepr::config(p)$bioconductor)){ - warning("The config YAML is missing the bioconductor section.") - message("No data was read. Returning a Project object") - return(p) - } + if(!pepr::checkSection(pepr::config(p),"bioconductor")){ + message("No data was read. Returning a Project object") + warning("The config YAML is missing the 'bioconductor' section.") + return(p) + } funcName = pepr::config(p)$bioconductor$read_fun_name # check if the function name was provided # and if it exists in the environment @@ -113,7 +116,7 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA # was specified in the config.yaml read_fun_name splitted = strsplit(funcName, ":")[[1]] nonEmpty = splitted[which(splitted != "")] - funcName = getFromNamespace(x=nonEmpty[2], ns=nonEmpty[1]) + funcName = utils::getFromNamespace(x=nonEmpty[2], ns=nonEmpty[1]) readData = .callBiocFun(funcName, args) message("Used function ", funcName, " from the environment") return(.insertPEP(readData, p)) diff --git a/R/methods_Annotated.R b/R/methods_Annotated.R index 909503c..5569cd1 100644 --- a/R/methods_Annotated.R +++ b/R/methods_Annotated.R @@ -91,12 +91,15 @@ setGeneric("is", package = "methods") #' #' see the \code{\link[methods]{is}} for more details #' +#' @param object the object to be tested +#' @param class2 the class name to test the object against +#' #' @export setMethod("is", "Annotated", definition = function(object, class2){ if(class2=="Project" & .is.project(object)){ TRUE } else { - extends(class(object), class2) + methods::extends(class(object), class2) } }) diff --git a/R/utils.R b/R/utils.R index 9c0792e..7c109e4 100644 --- a/R/utils.R +++ b/R/utils.R @@ -79,4 +79,28 @@ if(!is.character(path)) stop("The path must be character.") firstChar = substr(path, 1, 1) return(identical("/", firstChar) | identical("~", firstChar)) +} + +#' Update list with another list +#' +#' This function performs a union of two lists and updates the elements of the first one if are found in the other one +#' +#' @param list1 a list to be updated +#' @param list2 a list to update with +#' +#' @return an updated list +.updateList = function(list1,list2) { + newNms = names(list2) + nms = names(list1) + for(n in newNms){ + idx = which(nms == n) + if(length(idx) > 0){ + list1[[idx]] = list2[[n]] + }else{ + add = list2[[n]] + names(add) = n + list1 = c(list1,add) + } + } + return(list1) } \ No newline at end of file diff --git a/man/BiocProject.Rd b/man/BiocProject.Rd index c687196..ffddcbe 100644 --- a/man/BiocProject.Rd +++ b/man/BiocProject.Rd @@ -22,7 +22,7 @@ See \code{Details} for more information} \item{funcArgs}{a named list with arguments you want to pass to the \code{func}. The PEP will be passed automatically, -but if provided regardless, the constructor will disregard it} +but if provided regardless, the constructor will disregard it. You can also pass the arguments in a \code{funcArgs} section within the \code{bioconductor} section in the config file.} } \value{ an object of \code{\link[S4Vectors]{Annotated-class}} that is returned by the user provided function with the \code{\link[pepr]{Project-class}} object inserted into the first element of the list in its medatada slot diff --git a/man/is-Annotated-method.Rd b/man/is-Annotated-method.Rd index 05ee832..e71b324 100644 --- a/man/is-Annotated-method.Rd +++ b/man/is-Annotated-method.Rd @@ -7,6 +7,11 @@ \usage{ \S4method{is}{Annotated}(object, class2) } +\arguments{ +\item{object}{the object to be tested} + +\item{class2}{the class name to test the object against} +} \description{ Functions to test inheritance relationships between an object and a class or between two classes. It uses the generic is function but overrides its behavior for obejcts of class \code{\link[S4Vectors]{Annotated-class}} when testing for inheritance from \code{\link[pepr]{Project-class}} class. } From 7b7686f4e99e74a3e89dc771a9ede387133aa659 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 12:12:43 -0500 Subject: [PATCH 05/37] update args vignette --- vignettes/2multipleArguments.Rmd | 53 +++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/vignettes/2multipleArguments.Rmd b/vignettes/2multipleArguments.Rmd index a580c06..f854173 100644 --- a/vignettes/2multipleArguments.Rmd +++ b/vignettes/2multipleArguments.Rmd @@ -20,7 +20,27 @@ knitr::opts_chunk$set( Before you start see the [Getting started with `BiocProject` vignette](./1getStarted.html) for the basic information and installation instructions. -# Additional arguments in your function +Get paths to the files used in this vignette +```{r echo=T,message=FALSE} +library(BiocProject) +ProjectConfigArgs = system.file( + "extdata", + "example_peps-master", + "example_BiocProject", + "project_config_resize.yaml", + package = "BiocProject" +) + +readBedFiles_resize = system.file( + "extdata", + "example_peps-master", + "example_BiocProject", + "readBedFiles_resize.R", + package = "BiocProject" +) +``` + +# Ways to provide addtional arguments **What if your custom data processing function requires more arguments than just a PEP?** @@ -38,15 +58,39 @@ source(processFunction) ```{r echo=FALSE, comment=""} readBedFiles_resize ``` - There are a few ways to enable your function to get multiple arguments - not just a PEP ([`pepr::Project`](http://code.databio.org/pepr/reference/Project-class.html)) object, which is the basic scenario. +**The options:** + +- additional section in the config file +- using `funcArgs` argument of `BiocProject` function +- using an anonymous function in the `func` argument of `BiocProject` function + +# How to provide addtional section in the config file + +The easiest way to provide addtional arguments to your data reading/processing function is to add addtional section in the config file. See the config file below for reference: + +```{r, warning=FALSE, echo=FALSE, message=FALSE, collapse=TRUE, comment=" "} +library(pepr) +config_resize = configFile = system.file( + "extdata", + "example_peps-master", + "example_BiocProject", + "project_config_resize.yaml", + package = "BiocProject" +) +.printNestedList(yaml::read_yaml(config_resize)) +``` + +The section `funcArgs` was added within the `bioconductor` section. + # How to use the `funcArgs` argument Provide additional `funcArgs` argument to the `BiocProject` function. This argument has to be a named list. The names have to correspond to the argument names of your function. **The PEP (`pepr::Project` object) will be passed to your function by default**. For example: -Get paths to the files used in this vignette -```{r echo=T,message=FALSE} + +Read the function into R environment and run the `BiocProject` function with the `funcArgs` argument +```{r include=F,eval=TRUE} library(BiocProject) ProjectConfigArgs = system.file( "extdata", @@ -64,7 +108,6 @@ readBedFiles_resize = system.file( package = "BiocProject" ) ``` -Read the function into R environment and run the `BiocProject` function ```{r} source(readBedFiles_resize) bpArgs = BiocProject(file=ProjectConfigArgs, funcArgs=list(resize.width=100)) From 522a2bf071f929785b79d4546681760acb7352dc Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 12:16:18 -0500 Subject: [PATCH 06/37] update changelog --- NEWS.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/NEWS.md b/NEWS.md index 014860b..207ec4d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,16 @@ +# BiocProject 0.1.1 + +## Unreleased + +## Added + +* option to specify additional arguments in the config file + +## Changed + +* not only object that inherit from `Annotated` can be returned by the data processing function +* error handling changes + # BiocProject 0.1 ## 2019-01-28 From 82b1c34e34be5c811c1ba46eb9256921de7e448c Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 14:38:19 -0500 Subject: [PATCH 07/37] outsource constant config sections names, work on docs --- R/constants.R | 14 ++++++++++ R/functions.R | 28 +++++++++---------- .../example_BiocProject/project_config.yaml | 4 +-- .../project_config_resize.yaml | 7 +++-- .../project_config.yaml | 4 +-- .../project_config.yaml | 4 +-- man/dot-insertPEP.Rd | 19 +++++++++++++ man/dot-isAbsolute.Rd | 17 +++++++++++ man/dot-makeAbsPath.Rd | 19 +++++++++++++ man/dot-updateList.Rd | 19 +++++++++++++ 10 files changed, 113 insertions(+), 22 deletions(-) create mode 100644 R/constants.R create mode 100644 man/dot-insertPEP.Rd create mode 100644 man/dot-isAbsolute.Rd create mode 100644 man/dot-makeAbsPath.Rd create mode 100644 man/dot-updateList.Rd diff --git a/R/constants.R b/R/constants.R new file mode 100644 index 0000000..8972cc9 --- /dev/null +++ b/R/constants.R @@ -0,0 +1,14 @@ +# config section names +# +# The YAML file looks like this: +# +# MAIN_SECTION: +# FUNCTION_NAME: +# FUNCTION_PATH: +# FUNCTION_ARGS: +# : +# : +MAIN_SECTION = "bioconductor" +FUNCTION_ARGS = "funcArgs" +FUNCTION_PATH = "readFunPath" +FUNCTION_NAME = "readFunName" diff --git a/R/functions.R b/R/functions.R index 53c06f5..165d250 100644 --- a/R/functions.R +++ b/R/functions.R @@ -10,15 +10,15 @@ #' \itemize{ #' \item use a function loaded into the \code{R} environment and specified in #' the config slot in \code{\link[pepr]{Project-class}} -#' (specifically: \code{config(project)$bioconductor$read_fun_name}). +#' (specifically: \code{config(project)$bioconductor$readFunName}). #' \item use a function \emph{not} loaded into the \code{R} environment and specified in #' the config slot in \code{\link[pepr]{Project}} -#' (specifically: \code{config(project)$bioconductor$read_fun_path}). +#' (specifically: \code{config(project)$bioconductor$readFunPath}). #' \item use a function from other \code{R} package not loaded into #' the \code{R} environment and specified in the config slot #' in \code{\link[pepr]{Project}} -#' (specifically: \code{config(project)$bioconductor$read_fun_name}), like: -#' \code{pkgName::functionName} +#' (specifically: \code{config(project)$bioconductor$readFunName}), like: +#' \code{pkgName::FUNCTION_NAME} #' \item use a function implemented in the \code{\link{BiocProject}} #' call (passed to the \code{func} argument - anonymous function). This option is given the top priority and overrides #' other arguments if provided. @@ -80,8 +80,8 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA funcArgs = funcArgs[-which(pepArgs)] } args = append(list(p), funcArgs) - if(pepr::checkSection(pepr::config(p), c("bioconductor", "funcArgs"))){ - args = .updateList(args,p@config$bioconductor$funcArgs) + if(pepr::checkSection(pepr::config(p), c(MAIN_SECTION, FUNCTION_ARGS))){ + args = .updateList(args,config(p)[[MAIN_SECTION]][[FUNCTION_ARGS]]) } if (!is.null(func)) { @@ -96,13 +96,13 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA } else{ # use config to find it if (autoLoad) { - # check if the config consists of bioconductor section - if(!pepr::checkSection(pepr::config(p),"bioconductor")){ + # check if the config consists of MAIN_SECTION section + if(!pepr::checkSection(pepr::config(p), MAIN_SECTION)){ message("No data was read. Returning a Project object") - warning("The config YAML is missing the 'bioconductor' section.") + warning("The config YAML is missing the '", MAIN_SECTION,"' section.") return(p) } - funcName = pepr::config(p)$bioconductor$read_fun_name + funcName = pepr::config(p)[[MAIN_SECTION]][[FUNCTION_NAME]] # check if the function name was provided # and if it exists in the environment if (!is.null(funcName) && exists(funcName)) { @@ -113,7 +113,7 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA } else{ if (!is.null(funcName) && length(grep("(\\:){2,3}", funcName)) != 0) { # trying to access the function from the namespace that - # was specified in the config.yaml read_fun_name + # was specified in the config.yaml FUNCTION_NAME splitted = strsplit(funcName, ":")[[1]] nonEmpty = splitted[which(splitted != "")] funcName = utils::getFromNamespace(x=nonEmpty[2], ns=nonEmpty[1]) @@ -123,9 +123,9 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA } # function from config.yaml in read_fun_name not in environment, # trying to source the file specified in - # the config.yaml read_fun_path + # the config.yaml FUNCTION_PATH funcPath = - pepr::.expandPath(pepr::config(p)$bioconductor$read_fun_path) + pepr::.expandPath(pepr::config(p)[[MAIN_SECTION]][[FUNCTION_PATH]]) if (!is.null(funcPath)){ if (!file.exists(funcPath)) funcPath = .makeAbsPath(funcPath,dirname(p@file)) @@ -140,7 +140,7 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA readData = .callBiocFun(readFun, args) return(.insertPEP(readData, p)) }else{ - warning("Can't find function in the environment and the value for read_fun_path key was not provided in the config YAML.") + warning("Can't find function in the environment and the value for '", FUNCTION_PATH, "' key was not provided in the config YAML.") message("No data was read. Returning a Project object") return(p) } diff --git a/inst/extdata/example_peps-master/example_BiocProject/project_config.yaml b/inst/extdata/example_peps-master/example_BiocProject/project_config.yaml index 7e21bc3..7e4de85 100644 --- a/inst/extdata/example_peps-master/example_BiocProject/project_config.yaml +++ b/inst/extdata/example_peps-master/example_BiocProject/project_config.yaml @@ -2,5 +2,5 @@ metadata: sample_annotation: sample_annotation.csv bioconductor: - read_fun_name: readBedFiles - read_fun_path: readBedFiles.R + readFunName: readBedFiles + readFunPath: readBedFiles.R diff --git a/inst/extdata/example_peps-master/example_BiocProject/project_config_resize.yaml b/inst/extdata/example_peps-master/example_BiocProject/project_config_resize.yaml index 2bf1070..f10bd9e 100644 --- a/inst/extdata/example_peps-master/example_BiocProject/project_config_resize.yaml +++ b/inst/extdata/example_peps-master/example_BiocProject/project_config_resize.yaml @@ -2,5 +2,8 @@ metadata: sample_annotation: sample_annotation.csv bioconductor: - read_fun_name: readBedFiles_resize - read_fun_path: readBedFiles_resize.R + readFunName: readBedFiles_resize + readFunPath: readBedFiles_resize.R + funcArgs: + resize.width: 100 + diff --git a/inst/extdata/example_peps-master/example_BiocProject_exceptions/project_config.yaml b/inst/extdata/example_peps-master/example_BiocProject_exceptions/project_config.yaml index b572fe4..d295359 100644 --- a/inst/extdata/example_peps-master/example_BiocProject_exceptions/project_config.yaml +++ b/inst/extdata/example_peps-master/example_BiocProject_exceptions/project_config.yaml @@ -2,5 +2,5 @@ metadata: sample_annotation: sample_annotation.csv bioconductor: - read_fun_name: readBedFilesExceptions - read_fun_path: readBedFilesExceptions.R + readFunName: readBedFilesExceptions + readFunPath: readBedFilesExceptions.R diff --git a/inst/extdata/example_peps-master/example_BiocProject_remote/project_config.yaml b/inst/extdata/example_peps-master/example_BiocProject_remote/project_config.yaml index acb19b1..1027b21 100644 --- a/inst/extdata/example_peps-master/example_BiocProject_remote/project_config.yaml +++ b/inst/extdata/example_peps-master/example_BiocProject_remote/project_config.yaml @@ -2,5 +2,5 @@ metadata: sample_annotation: sample_annotation.csv bioconductor: - read_fun_name: readRemoteData - read_fun_path: readRemoteData.R + readFunName: readRemoteData + readFunPath: readRemoteData.R diff --git a/man/dot-insertPEP.Rd b/man/dot-insertPEP.Rd new file mode 100644 index 0000000..1c8dc92 --- /dev/null +++ b/man/dot-insertPEP.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/functions.R +\name{.insertPEP} +\alias{.insertPEP} +\title{Insert a PEP metadata in a metadata slot of Annotated} +\usage{ +.insertPEP(object, pep) +} +\arguments{ +\item{object}{an object of \code{\link[S4Vectors]{Annotated-class}}} + +\item{pep}{an object of class \code{\link[pepr]{Project-class}}} +} +\value{ +an object of the same class as the object argument but enriched with the metadata from the pep argument +} +\description{ +This function inserts the PEP (\code{\link[pepr]{Project-class}}) into the metadata slot of objects that extend the \code{\link[S4Vectors]{Annotated-class}} +} diff --git a/man/dot-isAbsolute.Rd b/man/dot-isAbsolute.Rd new file mode 100644 index 0000000..9a91ca1 --- /dev/null +++ b/man/dot-isAbsolute.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{.isAbsolute} +\alias{.isAbsolute} +\title{Determine whether a path is absolute.} +\usage{ +.isAbsolute(path) +} +\arguments{ +\item{path}{The path to check for seeming absolute-ness.} +} +\value{ +Flag indicating whether the \code{path} appears to be absolute. +} +\description{ +Determine whether a path is absolute. +} diff --git a/man/dot-makeAbsPath.Rd b/man/dot-makeAbsPath.Rd new file mode 100644 index 0000000..8d5806d --- /dev/null +++ b/man/dot-makeAbsPath.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{.makeAbsPath} +\alias{.makeAbsPath} +\title{Create an absolute path from a primary target and a parent candidate.} +\usage{ +.makeAbsPath(perhapsRelative, parent) +} +\arguments{ +\item{perhapsRelative:}{Path to primary target directory.} + +\item{parent:}{Path to parent folder to use if target isn't absolute.} +} +\value{ +Target itself if already absolute, else target nested within parent. +} +\description{ +Create an absolute path from a primary target and a parent candidate. +} diff --git a/man/dot-updateList.Rd b/man/dot-updateList.Rd new file mode 100644 index 0000000..ecff201 --- /dev/null +++ b/man/dot-updateList.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/utils.R +\name{.updateList} +\alias{.updateList} +\title{Update list with another list} +\usage{ +.updateList(list1, list2) +} +\arguments{ +\item{list1}{a list to be updated} + +\item{list2}{a list to update with} +} +\value{ +an updated list +} +\description{ +This function performs a union of two lists and updates the elements of the first one if are found in the other one +} From 44038242faf70fc573226d226ee02fa9eeb2587b Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 14:41:15 -0500 Subject: [PATCH 08/37] correct typo --- R/functions.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/functions.R b/R/functions.R index 165d250..7461b7c 100644 --- a/R/functions.R +++ b/R/functions.R @@ -18,7 +18,7 @@ #' the \code{R} environment and specified in the config slot #' in \code{\link[pepr]{Project}} #' (specifically: \code{config(project)$bioconductor$readFunName}), like: -#' \code{pkgName::FUNCTION_NAME} +#' \code{pkgName::functionName} #' \item use a function implemented in the \code{\link{BiocProject}} #' call (passed to the \code{func} argument - anonymous function). This option is given the top priority and overrides #' other arguments if provided. From 811ff784ed990ac7a066b13597a6506150b045f4 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 14:52:00 -0500 Subject: [PATCH 09/37] the returned object/error does not have to be of class Annotated, see 16 The S4Vectors::List is returned if this happens. And the metadata slot is poplulated with the PEP --- NEWS.md | 1 + R/functions.R | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 207ec4d..53faaf3 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,7 @@ * not only object that inherit from `Annotated` can be returned by the data processing function * error handling changes +* new config file section naming scheme # BiocProject 0.1 diff --git a/R/functions.R b/R/functions.R index 7461b7c..5c9305b 100644 --- a/R/functions.R +++ b/R/functions.R @@ -166,6 +166,8 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA object }else{ warning("The 'object' argument has to be of class 'Annotated', got '", class(object),"'. And the pep argument has to be of class 'Project', got '", class(pep),"'") - S4Vectors::List(result=object,metadata=pep) + result = S4Vectors::List(result=object) + S4Vectors::metadata(result) = list(PEP=pep) + result } } From 5431a8259601b66f5c6f80acdae01dd6063b551e Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 15:06:39 -0500 Subject: [PATCH 10/37] update vignette after config file naming scheme change --- vignettes/1getStarted.Rmd | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/vignettes/1getStarted.Rmd b/vignettes/1getStarted.Rmd index 674c6e1..58e1299 100644 --- a/vignettes/1getStarted.Rmd +++ b/vignettes/1getStarted.Rmd @@ -98,10 +98,10 @@ knitr::kable(sampleAnnotationDF, format = "html") In this example, our PEP has two samples, which have two attributes: `sample_name`, and `file_path`, which points the location for the data. -The configuration file also points to a third file (``r { basename(config(bp)$bioconductor$read_fun_path) }``). This file holds a single `R` function called ``r { basename(config(bp)$bioconductor$read_fun_name) }``, which has these contents: +The configuration file also points to a third file (``r { basename(config(bp)$bioconductor$readFunPath) }``). This file holds a single `R` function called ``r { basename(config(bp)$bioconductor$readFunName) }``, which has these contents: ```{r echo=FALSE, eval=TRUE, comment=""} -get(config(bp)$bioconductor$read_fun_name) +get(config(bp)$bioconductor$readFunName) ``` And that's all there is to it! **This PEP consists really of 3 components:** @@ -150,15 +150,15 @@ In the basic case the function name (and path to source file, if necessary) is s ``` bioconductor: - read_fun_name: function_name + readFunName: function_name ``` or ``` bioconductor: - read_fun_name: function_name - read_fun_path: /path/to/the/file.R + readFunName: function_name + readFunPath: /path/to/the/file.R ``` The function specified can be a data processing function of any complexity, but has to follow 3 rules listed below. From f38e9ef8529320f6cf1c704ee741efebd9a4e5ac Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 15:14:55 -0500 Subject: [PATCH 11/37] update docs, version bump --- DESCRIPTION | 2 +- R/functions.R | 2 +- man/BiocProject.Rd | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index a98d27c..8f48182 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: BiocProject Title: Bioconductor Management with Portable Encapsulated Project (PEP) Objects -Version: 0.1 +Version: 0.1.1 Authors@R: c(person("Michal", "Stolarczyk", email = "mjs5kd@virginia.edu",role = c("aut", "cre")), person("Nathan", "Sheffield", email = "nathan@code.databio.org",role = c("aut"))) Description: A Bioconductor-oriented project management class. It wraps the diff --git a/R/functions.R b/R/functions.R index 5c9305b..018006a 100644 --- a/R/functions.R +++ b/R/functions.R @@ -2,7 +2,7 @@ #' Portable Encapsulated Project (PEP) for biological applications #' #' This function creates a \code{\link[pepr]{Project-class}} object, and executes the user provided function with the created object as a first argument. -#' \cr\cr\emph{The custom data processing function has to return and object of \code{\link[S4Vectors]{Annotated-class}}, otherwise an error will be returned.} +#' \cr\cr\emph{If the custom data processing function returns an object of class other than \code{\link[S4Vectors]{Annotated-class}}, the output will be packaged in a \code{\link[S4Vectors]{List-class}} with a metadata slot populated with the \code{\link[pepr]{Project-class}}.} #' #' This \code{\link{BiocProject}} function provides some degree #' of flexibility in your custom data processing function usage and diff --git a/man/BiocProject.Rd b/man/BiocProject.Rd index ffddcbe..406a7a6 100644 --- a/man/BiocProject.Rd +++ b/man/BiocProject.Rd @@ -29,7 +29,7 @@ an object of \code{\link[S4Vectors]{Annotated-class}} that is returned by the us } \description{ This function creates a \code{\link[pepr]{Project-class}} object, and executes the user provided function with the created object as a first argument. -\cr\cr\emph{The custom data processing function has to return and object of \code{\link[S4Vectors]{Annotated-class}}, otherwise an error will be returned.} +\cr\cr\emph{If the custom data processing function returns an object of class other than \code{\link[S4Vectors]{Annotated-class}}, the output will be packaged in a \code{\link[S4Vectors]{List-class}} with a metadata slot populated with the \code{\link[pepr]{Project-class}}.} } \details{ This \code{\link{BiocProject}} function provides some degree @@ -38,14 +38,14 @@ implementation. Consider the possibilities listed below: \itemize{ \item use a function loaded into the \code{R} environment and specified in the config slot in \code{\link[pepr]{Project-class}} - (specifically: \code{config(project)$bioconductor$read_fun_name}). + (specifically: \code{config(project)$bioconductor$readFunName}). \item use a function \emph{not} loaded into the \code{R} environment and specified in the config slot in \code{\link[pepr]{Project}} - (specifically: \code{config(project)$bioconductor$read_fun_path}). + (specifically: \code{config(project)$bioconductor$readFunPath}). \item use a function from other \code{R} package not loaded into the \code{R} environment and specified in the config slot in \code{\link[pepr]{Project}} - (specifically: \code{config(project)$bioconductor$read_fun_name}), like: + (specifically: \code{config(project)$bioconductor$readFunName}), like: \code{pkgName::functionName} \item use a function implemented in the \code{\link{BiocProject}} call (passed to the \code{func} argument - anonymous function). This option is given the top priority and overrides From cca9bb411ade5b6f5a6888b6c85f595c8a2a6a12 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 15:35:35 -0500 Subject: [PATCH 12/37] update docs, exports, pkgdown website --- NAMESPACE | 2 ++ R/functions.R | 12 ++++++++++++ R/methods_Annotated.R | 7 ++++++- R/utils.R | 22 ++++++++++++++-------- _pkgdown.yaml | 11 +++++++++++ man/dot-insertPEP.Rd | 11 +++++++++++ man/dot-updateList.Rd | 5 +++++ man/getProject-Annotated-method.Rd | 2 +- man/is-Annotated-method.Rd | 8 ++++++++ 9 files changed, 70 insertions(+), 10 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index b2da0ad..84c7ce0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,7 @@ # Generated by roxygen2: do not edit by hand +export(.insertPEP) +export(.updateList) export(BiocProject) exportMethods(config) exportMethods(getProject) diff --git a/R/functions.R b/R/functions.R index 018006a..dadd55f 100644 --- a/R/functions.R +++ b/R/functions.R @@ -160,6 +160,18 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA #' @param pep an object of class \code{\link[pepr]{Project-class}} #' #' @return an object of the same class as the object argument but enriched with the metadata from the pep argument +#' +#' @examples +#' # If the object is of class Annotated +#' object = S4Vectors::List(result="test") +#' result = .insertPEP(object, pepr::Project()) +#' metadata(result) +#' +#' # If the object is not of class Annotated +#' object1 = "test" +#' result1 = .insertPEP(object1, pepr::Project()) +#' metadata(result1) +#' @export .insertPEP = function(object, pep) { if(is(object, "Annotated") & is(pep, "Project")){ S4Vectors::metadata(object) = list(PEP=pep) diff --git a/R/methods_Annotated.R b/R/methods_Annotated.R index 5569cd1..f9c4fc5 100644 --- a/R/methods_Annotated.R +++ b/R/methods_Annotated.R @@ -26,7 +26,7 @@ setGeneric("getProject", function(.Object) #' projectConfig = system.file("extdata", "example_peps-master", #' "example_BiocProject", "project_config.yaml", package="BiocProject") #' p=BiocProject(projectConfig) -#' samples(p) +#' getProject(p) #' #' @export setMethod("getProject","Annotated",function(.Object){ @@ -94,6 +94,11 @@ setGeneric("is", package = "methods") #' @param object the object to be tested #' @param class2 the class name to test the object against #' +#' @return a logical +#' @examples +#' object = S4Vectors::List(test="test") +#' is(object,"Annotated") +#' #' @export setMethod("is", "Annotated", definition = function(object, class2){ if(class2=="Project" & .is.project(object)){ diff --git a/R/utils.R b/R/utils.R index 7c109e4..2294d4f 100644 --- a/R/utils.R +++ b/R/utils.R @@ -44,12 +44,12 @@ return(res) } -#' Create an absolute path from a primary target and a parent candidate. +# Create an absolute path from a primary target and a parent candidate. # -#' @param perhapsRelative: Path to primary target directory. -#' @param parent: Path to parent folder to use if target isn't absolute. +# @param perhapsRelative: Path to primary target directory. +# @param parent: Path to parent folder to use if target isn't absolute. # -#' @return Target itself if already absolute, else target nested within parent. +# @return Target itself if already absolute, else target nested within parent. .makeAbsPath = function(perhapsRelative, parent) { if (!.isDefined(perhapsRelative)) { return(perhapsRelative)} perhapsRelative = pepr::.expandPath(perhapsRelative) @@ -71,10 +71,10 @@ .isDefined = function(var) { ! (is.null(var) || is.na(var)) } -#' Determine whether a path is absolute. -#' -#' @param path The path to check for seeming absolute-ness. -#' @return Flag indicating whether the \code{path} appears to be absolute. +# Determine whether a path is absolute. +# +# @param path The path to check for seeming absolute-ness. +# @return Flag indicating whether the \code{path} appears to be absolute. .isAbsolute = function(path) { if(!is.character(path)) stop("The path must be character.") firstChar = substr(path, 1, 1) @@ -89,6 +89,12 @@ #' @param list2 a list to update with #' #' @return an updated list +#' +#' @examples +#' list1=list(a=1,b=2) +#' list2=list(a=1,b=1,c=3) +#' .updateList(list1,list2) +#' @export .updateList = function(list1,list2) { newNms = names(list2) nms = names(list1) diff --git a/_pkgdown.yaml b/_pkgdown.yaml index 70f2285..fa57a3a 100644 --- a/_pkgdown.yaml +++ b/_pkgdown.yaml @@ -32,3 +32,14 @@ articles: - 2multipleArguments - 3simpleCache - 4remoteData + +reference: + - title: "BiocProject API" + desc: "Exported functions of `BiocProject`." + contents: + - -matches("\\.") + - title: "utilities" + desc: "Extra non-exported utility functions." + contents: + - .updateList + - .insertPEP diff --git a/man/dot-insertPEP.Rd b/man/dot-insertPEP.Rd index 1c8dc92..bdcfb06 100644 --- a/man/dot-insertPEP.Rd +++ b/man/dot-insertPEP.Rd @@ -17,3 +17,14 @@ an object of the same class as the object argument but enriched with the metadat \description{ This function inserts the PEP (\code{\link[pepr]{Project-class}}) into the metadata slot of objects that extend the \code{\link[S4Vectors]{Annotated-class}} } +\examples{ +# If the object is of class Annotated +object = S4Vectors::List(result="test") +result = .insertPEP(object, pepr::Project()) +metadata(result) + +# If the object is not of class Annotated +object1 = "test" +result1 = .insertPEP(object1, pepr::Project()) +metadata(result1) +} diff --git a/man/dot-updateList.Rd b/man/dot-updateList.Rd index ecff201..32fc2b2 100644 --- a/man/dot-updateList.Rd +++ b/man/dot-updateList.Rd @@ -17,3 +17,8 @@ an updated list \description{ This function performs a union of two lists and updates the elements of the first one if are found in the other one } +\examples{ +list1=list(a=1,b=2) +list2=list(a=1,b=1,c=3) +.updateList(list1,list2) +} diff --git a/man/getProject-Annotated-method.Rd b/man/getProject-Annotated-method.Rd index 6551604..44413c0 100644 --- a/man/getProject-Annotated-method.Rd +++ b/man/getProject-Annotated-method.Rd @@ -20,6 +20,6 @@ This method can be used to extract the project metadata from objects of \code{\l projectConfig = system.file("extdata", "example_peps-master", "example_BiocProject", "project_config.yaml", package="BiocProject") p=BiocProject(projectConfig) -samples(p) +getProject(p) } diff --git a/man/is-Annotated-method.Rd b/man/is-Annotated-method.Rd index e71b324..12d99d6 100644 --- a/man/is-Annotated-method.Rd +++ b/man/is-Annotated-method.Rd @@ -12,9 +12,17 @@ \item{class2}{the class name to test the object against} } +\value{ +a logical +} \description{ Functions to test inheritance relationships between an object and a class or between two classes. It uses the generic is function but overrides its behavior for obejcts of class \code{\link[S4Vectors]{Annotated-class}} when testing for inheritance from \code{\link[pepr]{Project-class}} class. } \details{ see the \code{\link[methods]{is}} for more details } +\examples{ +object = S4Vectors::List(test="test") +is(object,"Annotated") + +} From 0aab914392ea864ee0f41ab90e3b8251b137fea3 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 16:01:56 -0500 Subject: [PATCH 13/37] add first unit tests and infrastructure, see #23 --- DESCRIPTION | 3 ++- tests/testthat.R | 5 +++++ tests/testthat/test_all.R | 40 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100755 tests/testthat.R create mode 100644 tests/testthat/test_all.R diff --git a/DESCRIPTION b/DESCRIPTION index 8f48182..a42dd73 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -12,7 +12,8 @@ LazyData: true Depends: S4Vectors, pepr Suggests: knitr, - rmarkdown + rmarkdown, + testthat Enhances: BiocFileCache, simpleCache, GenomicRanges RoxygenNote: 6.1.1 BugReports: https://github.com/pepkit/BiocProject diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100755 index 0000000..978d6a4 --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,5 @@ +Sys.setenv("R_TESTS" = "") +library(testthat) +library(BiocProject) + +test_check("BiocProject") diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R new file mode 100644 index 0000000..8934b70 --- /dev/null +++ b/tests/testthat/test_all.R @@ -0,0 +1,40 @@ +library(BiocProject) +# Prep data --------------------------------------------------------------- + +configFile = system.file( + "extdata", + "example_peps-master", + "example_BiocProject", + "project_config.yaml", + package = "BiocProject" +) + +configFileArgs = system.file( + "extdata", + "example_peps-master", + "example_BiocProject", + "project_config_resize.yaml", + package = "BiocProject" +) + +configFileExceptions = system.file( + "extdata", + "example_peps-master", + "example_BiocProject_exceptions", + "project_config.yaml", + package = "BiocProject" +) + + +# Test -------------------------------------------------------------------- +context("Test utility functions/methods") + +test_that(".updateList returns correct object type", { + expect_is(.updateList(list(a=1),list(a=2,b=2)), 'list') +}) + +test_that(".updateList returns list of correct length", { + expect_equal(length(.updateList(list(a=1),list(a=2,b=2))), 2) + expect_equal(length(.updateList(list(a=1,c=3),list(a=2,b=2))), 3) + expect_equal(length(.updateList(list(a=1,b=3),list(c=2,d=2))), 4) +}) \ No newline at end of file From 65c7cf90fa5de829db88d8acdf4192bcf294518d Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 16:13:30 -0500 Subject: [PATCH 14/37] add class assertions in .updateList fun --- R/utils.R | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/R/utils.R b/R/utils.R index 2294d4f..d49c7b0 100644 --- a/R/utils.R +++ b/R/utils.R @@ -96,10 +96,14 @@ #' .updateList(list1,list2) #' @export .updateList = function(list1,list2) { - newNms = names(list2) - nms = names(list1) - for(n in newNms){ - idx = which(nms == n) + if((!is.list(list1)) || (!is.list(list2))) + stop("One of the arguments was not a list") + nms1 = names(list1) + nms2 = names(list2) + if(length(list1)!=length(nms1) || length(list2)!=length(nms2)) + stop("All elements in both lists have to be named") + for(n in nms2){ + idx = which(nms1 == n) if(length(idx) > 0){ list1[[idx]] = list2[[n]] }else{ @@ -109,4 +113,4 @@ } } return(list1) -} \ No newline at end of file +} From d049ff5011bb3449b955c2c6ec870115f69a2ef3 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Tue, 29 Jan 2019 16:54:25 -0500 Subject: [PATCH 15/37] loosen the assertions in .updateList, tests --- R/utils.R | 7 ++- man/dot-updateList.Rd | 6 +- tests/testthat/test_all.R | 128 +++++++++++++++++++++++++++++++++++++- 3 files changed, 135 insertions(+), 6 deletions(-) diff --git a/R/utils.R b/R/utils.R index d49c7b0..3687048 100644 --- a/R/utils.R +++ b/R/utils.R @@ -83,7 +83,9 @@ #' Update list with another list #' -#' This function performs a union of two lists and updates the elements of the first one if are found in the other one +#' This function performs a union of two lists and updates the elements of the first one if are found in the other one. +#' +#' Both elements have to be lists. If some elements are not named, they are preserved but the order might be lost. #' #' @param list1 a list to be updated #' @param list2 a list to update with @@ -94,14 +96,13 @@ #' list1=list(a=1,b=2) #' list2=list(a=1,b=1,c=3) #' .updateList(list1,list2) +#' #' @export .updateList = function(list1,list2) { if((!is.list(list1)) || (!is.list(list2))) stop("One of the arguments was not a list") nms1 = names(list1) nms2 = names(list2) - if(length(list1)!=length(nms1) || length(list2)!=length(nms2)) - stop("All elements in both lists have to be named") for(n in nms2){ idx = which(nms1 == n) if(length(idx) > 0){ diff --git a/man/dot-updateList.Rd b/man/dot-updateList.Rd index 32fc2b2..35097b3 100644 --- a/man/dot-updateList.Rd +++ b/man/dot-updateList.Rd @@ -15,10 +15,14 @@ an updated list } \description{ -This function performs a union of two lists and updates the elements of the first one if are found in the other one +This function performs a union of two lists and updates the elements of the first one if are found in the other one. +} +\details{ +Both elements have to be lists. If some elements are not named, they are preserved but the order might be lost. } \examples{ list1=list(a=1,b=2) list2=list(a=1,b=1,c=3) .updateList(list1,list2) + } diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index 8934b70..a010e70 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -1,4 +1,5 @@ library(BiocProject) +library(yaml) # Prep data --------------------------------------------------------------- configFile = system.file( @@ -27,7 +28,7 @@ configFileExceptions = system.file( # Test -------------------------------------------------------------------- -context("Test utility functions/methods") +context("Test utility .updateList function") test_that(".updateList returns correct object type", { expect_is(.updateList(list(a=1),list(a=2,b=2)), 'list') @@ -37,4 +38,127 @@ test_that(".updateList returns list of correct length", { expect_equal(length(.updateList(list(a=1),list(a=2,b=2))), 2) expect_equal(length(.updateList(list(a=1,c=3),list(a=2,b=2))), 3) expect_equal(length(.updateList(list(a=1,b=3),list(c=2,d=2))), 4) -}) \ No newline at end of file +}) + +test_that(".updateList throws errors", { + expect_error(.updateList(list(a=1),2)) +}) + + + +# test_that("Project throws errors", { +# expect_error(Project(file = p@config$metadata$sample_annotation)) +# }) +# +# test_that("Project creates an object of class Project", { +# expect_is(p, 'Project') +# }) +# +# test_that("Project (loadConfig) produces a proper config file. +# YAML read config has to consist of list elements of the same length +# as the config processed with the Project constructor", { +# expect_equal(unlist(lapply(config(p_yaml)$metadata,length)), +# unlist(lapply(yaml$metadata,length))) +# }) +# +# context("utils") +# +# test_that("listifyDF returns correct object type and throws errors", { +# expect_is(.listifyDF(DF = DF), 'data.frame') +# expect_is(.listifyDF(DF = DF)[[1]], 'list') +# expect_error(.listifyDF(DF = 1)) +# }) +# +# test_that("listifyDF does not change the dimensions", { +# expect_equal(dim(.listifyDF(DF)), dim(DF)) +# }) +# +# test_that(".expandPath returns correct object type and throws errors", { +# expect_is(.expandPath(path = "~/UVA/"), 'character') +# expect_error(.expandPath(1)) +# expect_error(.expandPath("~/$HOME/test/$NonExistentVar")) +# }) +# +# test_that("strformat returns correct object type and throws errors", { +# expect_is(.strformat("{VAR1}{VAR2}_file", list(VAR1 = "hi", VAR2 = "hello")), "character") +# expect_error(.strformat("{VAR1}{VAR2}_file", list(VAR1 = "hi"))) +# expect_error(.strformat(1)) +# }) +# +# test_that("makeMetadataSectionAbsolute returns correct object type and throws errors", +# { +# expect_is(.makeMetadataSectionAbsolute(p@config, dirname(p@file)), 'list') +# expect_error(.makeMetadataSectionAbsolute(p@file, 1)) +# }) +# +# test_that("makeMetadataSectionAbsolute does not change the length(s) of the list", +# { +# expect_equal(as.numeric(lapply(p@config$metadata, length)), as.numeric(lapply( +# .makeMetadataSectionAbsolute(p@config, dirname(p@file)), length +# ))) +# }) +# +# test_that(".isAbsolute returns correct object type and throws errors", { +# expect_is(.isAbsolute("/home/mjs5kd"), 'logical') +# expect_error(.isAbsolute(1)) +# }) +# +# test_that(".isAbsolute works properly", { +# expect_true(.isAbsolute("/home/mjs5kd")) +# expect_false(.isAbsolute("UVA/data")) +# }) +# +# test_that("printNestedList throws errors", { +# expect_error(.printNestedList(1)) +# }) +# +# context("Project operations") +# +# test_that("getSubsample method throws errors", { +# expect_error(getSubsample(mtcars)) +# expect_error(getSubsample(p, "frog_1", "test")) +# }) +# +# test_that("getSubsample method returns a correct size DF", { +# expect_equal(dim(getSubsample(p_sub, "frog_1", "sub_a")), c(1, 4)) +# }) +# +# test_that(".loadSampleAnnotation returns a Project object", { +# expect_is(.loadSampleAnnotation(p), 'Project') +# }) +# +# test_that(".loadSampleAnnotation thorws an error when file not fond", { +# expect_error(.loadSampleAnnotation(p_file_missing)) +# }) +# +# test_that(".loadSamplesubnnotation always returns a Project", { +# expect_is(.loadSampleSubannotation(p), 'Project') +# expect_is(.loadSampleSubannotation(p_subproj2), 'Project') +# expect_is(.loadSampleSubannotation(p_sub), 'Project') +# }) +# +# test_that(".implyColumns returns Project object", { +# expect_is(.implyAttributes(p_implied), 'Project') +# }) +# +# test_that(".implyColumns returns Project object", { +# expect_is(.deriveAttributes(p), 'Project') +# }) +# +# test_that(".listSubprojects internal function returns correct object type, length and throws errors", +# { +# expect_equal(length(.listSubprojects(p_subproj1@config)), 2) +# expect_is(.listSubprojects(p_subproj2@config), 'character') +# expect_null(.listSubprojects(p@config)) +# expect_error(.listSubprojects(1)) +# }) +# +# test_that("listSubprojects exported method returns correct object type, length and throws errors", +# { +# expect_equal(length(listSubprojects(p_subproj1)), 2) +# expect_is(listSubprojects(p_subproj1), 'character') +# expect_null(listSubprojects(p)) +# expect_error(listSubprojects(1)) +# expect_equal(length(listSubprojects(p_subproj1)), 2) +# }) +# From 0b77eaa88cabb1fd5199ad928a521c65b7133dd3 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Wed, 30 Jan 2019 14:01:57 -0500 Subject: [PATCH 16/37] add tests, small corrections --- R/functions.R | 5 +- R/utils.R | 44 ++++----- man/dot-isAbsolute.Rd | 17 ---- man/dot-makeAbsPath.Rd | 19 ---- tests/testthat/test_all.R | 195 +++++++++++++++----------------------- 5 files changed, 103 insertions(+), 177 deletions(-) delete mode 100644 man/dot-isAbsolute.Rd delete mode 100644 man/dot-makeAbsPath.Rd diff --git a/R/functions.R b/R/functions.R index dadd55f..59a27f7 100644 --- a/R/functions.R +++ b/R/functions.R @@ -173,11 +173,12 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA #' metadata(result1) #' @export .insertPEP = function(object, pep) { - if(is(object, "Annotated") & is(pep, "Project")){ + if(!is(pep, "Project")) stop("the pep argument has to be of class 'Project', got '", class(pep),"'") + if(is(object, "Annotated")){ S4Vectors::metadata(object) = list(PEP=pep) object }else{ - warning("The 'object' argument has to be of class 'Annotated', got '", class(object),"'. And the pep argument has to be of class 'Project', got '", class(pep),"'") + warning("The 'object' argument has to be of class 'Annotated', got '", class(object),"'") result = S4Vectors::List(result=object) S4Vectors::metadata(result) = list(PEP=pep) result diff --git a/R/utils.R b/R/utils.R index 3687048..4245520 100644 --- a/R/utils.R +++ b/R/utils.R @@ -20,28 +20,28 @@ # internal function that wraps the external function execution # in tryCatch to indicate problems with the external function execution -.callBiocFun <- function(func, arguments) -{ - .warnings = c() - frameNumber <- sys.nframe() - wHandler <- function(w){ - # warning handler - assign(".warnings", append(.warnings,w$message), - envir = sys.frame(frameNumber)) - invokeRestart("muffleWarning") - } - eHandler <- function(e){ - # error handler - .wrapFunMessages(e$message,"error") - message("No data was read. The error message was returned instead.") - e$message - } - res = withCallingHandlers(tryCatch(do.call(func, arguments), error = eHandler),warning = wHandler) - if(length(.warnings) > 0){ - warning("There were warnings associated with your function execution.") - .wrapFunMessages(.warnings,"warning") - } - return(res) +.callBiocFun <- function(func, arguments) { + if(!is(arguments, "list")) stop("The 'arguments' argument has to be a list, got '", class(arguments),"'") + .warnings = c() + frameNumber <- sys.nframe() + wHandler <- function(w){ + # warning handler + assign(".warnings", append(.warnings,w$message), + envir = sys.frame(frameNumber)) + invokeRestart("muffleWarning") + } + eHandler <- function(e){ + # error handler + .wrapFunMessages(e$message,"error") + message("No data was read. The error message was returned instead.") + e$message + } + res = withCallingHandlers(tryCatch(do.call(func, arguments), error = eHandler),warning = wHandler) + if(length(.warnings) > 0){ + warning("There were warnings associated with your function execution.") + .wrapFunMessages(.warnings,"warning") + } + return(res) } # Create an absolute path from a primary target and a parent candidate. diff --git a/man/dot-isAbsolute.Rd b/man/dot-isAbsolute.Rd deleted file mode 100644 index 9a91ca1..0000000 --- a/man/dot-isAbsolute.Rd +++ /dev/null @@ -1,17 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{.isAbsolute} -\alias{.isAbsolute} -\title{Determine whether a path is absolute.} -\usage{ -.isAbsolute(path) -} -\arguments{ -\item{path}{The path to check for seeming absolute-ness.} -} -\value{ -Flag indicating whether the \code{path} appears to be absolute. -} -\description{ -Determine whether a path is absolute. -} diff --git a/man/dot-makeAbsPath.Rd b/man/dot-makeAbsPath.Rd deleted file mode 100644 index 8d5806d..0000000 --- a/man/dot-makeAbsPath.Rd +++ /dev/null @@ -1,19 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/utils.R -\name{.makeAbsPath} -\alias{.makeAbsPath} -\title{Create an absolute path from a primary target and a parent candidate.} -\usage{ -.makeAbsPath(perhapsRelative, parent) -} -\arguments{ -\item{perhapsRelative:}{Path to primary target directory.} - -\item{parent:}{Path to parent folder to use if target isn't absolute.} -} -\value{ -Target itself if already absolute, else target nested within parent. -} -\description{ -Create an absolute path from a primary target and a parent candidate. -} diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index a010e70..6067d17 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -26,9 +26,22 @@ configFileExceptions = system.file( package = "BiocProject" ) +a=function(arg) { + stop(arg) +} + +b=function(arg) { + warning(arg) +} + +c=function(arg) { + return(arg) +} + +testChar = "a" # Test -------------------------------------------------------------------- -context("Test utility .updateList function") +context("Test .updateList utility function") test_that(".updateList returns correct object type", { expect_is(.updateList(list(a=1),list(a=2,b=2)), 'list') @@ -44,121 +57,69 @@ test_that(".updateList throws errors", { expect_error(.updateList(list(a=1),2)) }) +context("Test .makeAbsPath utility function") + +test_that(".makeAbsPath returns correct object", { + expect_is(.makeAbsPath("~"),"character") +}) + +test_that(".makeAbsPath returns correct value", { + expect_equal(.makeAbsPath("~"),Sys.getenv("HOME")) +}) + +context("Test .isDefined utility function") + +test_that(".isDefined returns correct object", { + expect_is(.isDefined(NA),"logical") +}) + +test_that(".isDefined returns correct value", { + expect_equal(.isDefined(NA),F) + expect_equal(.isDefined(NULL),F) + expect_equal(.isDefined(configFile),T) +}) + +context("Test .isAbsolute utility function") + +test_that(".isAbsolute returns correct object", { + expect_is(.isAbsolute("~"),"logical") +}) + +test_that(".isAbsolute returns correct value", { + expect_equal(.isAbsolute("~"),T) + expect_equal(.isAbsolute("../test"),F) +}) + +context("Test .callBiocFun untility function") + +test_that(".callBiocFun catches errors", { + expect_error(expect_error(.callBiocFun(a,list(testChar)))) + expect_equal(.callBiocFun(a,list(testChar)),testChar) + expect_warning(.callBiocFun(b,list(testChar))) +}) + +test_that(".callBiocFun returns correct object on success", { + expect_is(.callBiocFun(c,list(testChar)),class(testChar)) +}) +test_that(".callBiocFun returns correct value on success", { + expect_equal(.callBiocFun(c,list(testChar)),testChar) +}) + +test_that(".callBiocFun throws errors", { + expect_error(.callBiocFun(a,testChar)) +}) + +context("Test .insertPEP function") + +test_that(".insertPEP returns correct object with a warning",{ + expect_warning(expect_is(.insertPEP("a",pepr::Project()),"Annotated")) +}) + +test_that(".insertPEP returns correct object",{ + expect_is(.insertPEP(S4Vectors::List(),pepr::Project()),"Annotated") +}) -# test_that("Project throws errors", { -# expect_error(Project(file = p@config$metadata$sample_annotation)) -# }) -# -# test_that("Project creates an object of class Project", { -# expect_is(p, 'Project') -# }) -# -# test_that("Project (loadConfig) produces a proper config file. -# YAML read config has to consist of list elements of the same length -# as the config processed with the Project constructor", { -# expect_equal(unlist(lapply(config(p_yaml)$metadata,length)), -# unlist(lapply(yaml$metadata,length))) -# }) -# -# context("utils") -# -# test_that("listifyDF returns correct object type and throws errors", { -# expect_is(.listifyDF(DF = DF), 'data.frame') -# expect_is(.listifyDF(DF = DF)[[1]], 'list') -# expect_error(.listifyDF(DF = 1)) -# }) -# -# test_that("listifyDF does not change the dimensions", { -# expect_equal(dim(.listifyDF(DF)), dim(DF)) -# }) -# -# test_that(".expandPath returns correct object type and throws errors", { -# expect_is(.expandPath(path = "~/UVA/"), 'character') -# expect_error(.expandPath(1)) -# expect_error(.expandPath("~/$HOME/test/$NonExistentVar")) -# }) -# -# test_that("strformat returns correct object type and throws errors", { -# expect_is(.strformat("{VAR1}{VAR2}_file", list(VAR1 = "hi", VAR2 = "hello")), "character") -# expect_error(.strformat("{VAR1}{VAR2}_file", list(VAR1 = "hi"))) -# expect_error(.strformat(1)) -# }) -# -# test_that("makeMetadataSectionAbsolute returns correct object type and throws errors", -# { -# expect_is(.makeMetadataSectionAbsolute(p@config, dirname(p@file)), 'list') -# expect_error(.makeMetadataSectionAbsolute(p@file, 1)) -# }) -# -# test_that("makeMetadataSectionAbsolute does not change the length(s) of the list", -# { -# expect_equal(as.numeric(lapply(p@config$metadata, length)), as.numeric(lapply( -# .makeMetadataSectionAbsolute(p@config, dirname(p@file)), length -# ))) -# }) -# -# test_that(".isAbsolute returns correct object type and throws errors", { -# expect_is(.isAbsolute("/home/mjs5kd"), 'logical') -# expect_error(.isAbsolute(1)) -# }) -# -# test_that(".isAbsolute works properly", { -# expect_true(.isAbsolute("/home/mjs5kd")) -# expect_false(.isAbsolute("UVA/data")) -# }) -# -# test_that("printNestedList throws errors", { -# expect_error(.printNestedList(1)) -# }) -# -# context("Project operations") -# -# test_that("getSubsample method throws errors", { -# expect_error(getSubsample(mtcars)) -# expect_error(getSubsample(p, "frog_1", "test")) -# }) -# -# test_that("getSubsample method returns a correct size DF", { -# expect_equal(dim(getSubsample(p_sub, "frog_1", "sub_a")), c(1, 4)) -# }) -# -# test_that(".loadSampleAnnotation returns a Project object", { -# expect_is(.loadSampleAnnotation(p), 'Project') -# }) -# -# test_that(".loadSampleAnnotation thorws an error when file not fond", { -# expect_error(.loadSampleAnnotation(p_file_missing)) -# }) -# -# test_that(".loadSamplesubnnotation always returns a Project", { -# expect_is(.loadSampleSubannotation(p), 'Project') -# expect_is(.loadSampleSubannotation(p_subproj2), 'Project') -# expect_is(.loadSampleSubannotation(p_sub), 'Project') -# }) -# -# test_that(".implyColumns returns Project object", { -# expect_is(.implyAttributes(p_implied), 'Project') -# }) -# -# test_that(".implyColumns returns Project object", { -# expect_is(.deriveAttributes(p), 'Project') -# }) -# -# test_that(".listSubprojects internal function returns correct object type, length and throws errors", -# { -# expect_equal(length(.listSubprojects(p_subproj1@config)), 2) -# expect_is(.listSubprojects(p_subproj2@config), 'character') -# expect_null(.listSubprojects(p@config)) -# expect_error(.listSubprojects(1)) -# }) -# -# test_that("listSubprojects exported method returns correct object type, length and throws errors", -# { -# expect_equal(length(listSubprojects(p_subproj1)), 2) -# expect_is(listSubprojects(p_subproj1), 'character') -# expect_null(listSubprojects(p)) -# expect_error(listSubprojects(1)) -# expect_equal(length(listSubprojects(p_subproj1)), 2) -# }) -# +test_that(".insertPEP throws errors",{ + expect_error(.insertPEP(S4Vectors::List(),"test")) +}) \ No newline at end of file From ee16b2791b608191948c04ff3fac35c5f415428a Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Wed, 30 Jan 2019 17:04:38 -0500 Subject: [PATCH 17/37] more unit tests, formatting --- R/functions.R | 23 +++++++++----- tests/testthat/test_all.R | 64 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 7 deletions(-) diff --git a/R/functions.R b/R/functions.R index 59a27f7..f87b8f2 100644 --- a/R/functions.R +++ b/R/functions.R @@ -59,13 +59,15 @@ #' @seealso \url{https://pepkit.github.io/} #' #' @export BiocProject -BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcArgs = NULL) { +BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, + funcArgs = NULL) { p = tryCatch( expr = { - pepr::Project(file = file, subproject = subproject) + pepr::Project(file=file, subproject=subproject) },warning = function(w) { message(w) - stop("There are warnings associated with the 'Project' object creation.") + stop("There are warnings + associated with the 'Project' object creation.") } ) # prevent PEP (Project object) input. This prevents BiocProject object @@ -95,11 +97,14 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA } } else{ # use config to find it + if(!is.logical(autoLoad)) stop("'autoLoad' argument has to be a logical, + got '", class(autoLoad),"'") if (autoLoad) { # check if the config consists of MAIN_SECTION section if(!pepr::checkSection(pepr::config(p), MAIN_SECTION)){ message("No data was read. Returning a Project object") - warning("The config YAML is missing the '", MAIN_SECTION,"' section.") + warning("The config YAML is missing the '", + MAIN_SECTION,"' section.") return(p) } funcName = pepr::config(p)[[MAIN_SECTION]][[FUNCTION_NAME]] @@ -140,7 +145,9 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA readData = .callBiocFun(readFun, args) return(.insertPEP(readData, p)) }else{ - warning("Can't find function in the environment and the value for '", FUNCTION_PATH, "' key was not provided in the config YAML.") + warning("Can't find function in the environment and the value for '" + , FUNCTION_PATH, + "' key was not provided in the config YAML.") message("No data was read. Returning a Project object") return(p) } @@ -173,12 +180,14 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcA #' metadata(result1) #' @export .insertPEP = function(object, pep) { - if(!is(pep, "Project")) stop("the pep argument has to be of class 'Project', got '", class(pep),"'") + if(!is(pep, "Project")) stop("the pep argument has to be of class 'Project', + got '", class(pep),"'") if(is(object, "Annotated")){ S4Vectors::metadata(object) = list(PEP=pep) object }else{ - warning("The 'object' argument has to be of class 'Annotated', got '", class(object),"'") + warning("The 'object' argument has to be of class 'Annotated', got '", + class(object),"'") result = S4Vectors::List(result=object) S4Vectors::metadata(result) = list(PEP=pep) result diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index 6067d17..94efec1 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -26,6 +26,8 @@ configFileExceptions = system.file( package = "BiocProject" ) +bp = BiocProject(configFile) + a=function(arg) { stop(arg) } @@ -122,4 +124,66 @@ test_that(".insertPEP returns correct object",{ test_that(".insertPEP throws errors",{ expect_error(.insertPEP(S4Vectors::List(),"test")) +}) + +context("Test BiocProject function") + +test_that("BiocProject function return correct object", { + expect_is(BiocProject(configFile),"Annotated") +}) + +test_that("BiocProject function returns Annotated when provided objects of + different class and thorows a warning", { + expect_warning(expect_is(BiocProject(configFile, func = function(x){ + return("test") + }),"Annotated")) +}) + +test_that("BiocProject function returns a Project object when autoload is set to FALSE", { + expect_is(BiocProject(file=configFile,autoLoad = F),"Project") +}) + +test_that("BiocProject function throws errors/warnings when the arguments are inappropriate", { + expect_error(BiocProject(file=configFile,func = "2")) + expect_warning(BiocProject(file=configFile,funcArgs = "a")) + expect_error(BiocProject(file = "test")) + expect_error(BiocProject(file = configFile,autoLoad = "test")) +}) + +test_that("BiocProject function catches errors in the user-provided function, warns and returns the error message as Annotated", { + expect_warning(expect_is(BiocProject(file=configFile,func=function(x) { + stop("test") + }),"Annotated")) +}) + + +context("Test Annotated methods") + +test_that("samples returns a correct object", { + expect_is(samples(bp),"data.table") +}) + +test_that("config returns a correct object", { + expect_is(config(bp),"Config") +}) + +test_that(".is.project returns a correct object", { + expect_is(.is.project(bp),"logical") +}) + +test_that(".is.project returns a value", { + expect_equal(.is.project(bp),T) + expect_equal(.is.project(S4Vectors::List(a=1)), F) +}) + +test_that("is method returns correct value when Annotated provided", { + expect_equal(is(bp,"Project"), T) +}) + +test_that("getProject returns a correct object", { + expect_is(getProject(bp),"Project") +}) + +test_that("getProject returns a correct value", { + expect_equal(getProject(bp), pepr::Project(configFile)) }) \ No newline at end of file From 28fb4af4f676c33c1680da7e64cfc463a929d51d Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Thu, 31 Jan 2019 16:13:36 -0500 Subject: [PATCH 18/37] fix problems related to BiocCheck, see #24 --- .gitignore | 4 +- DESCRIPTION | 2 + NAMESPACE | 2 + R/functions.R | 191 ++++++++++++++++------------- R/methods_Annotated.R | 17 ++- R/utils.R | 78 ++++++------ man/BiocProject.Rd | 47 ++++--- man/config-Annotated-method.Rd | 3 +- man/dot-insertPEP.Rd | 7 +- man/dot-updateList.Rd | 6 +- man/getProject-Annotated-method.Rd | 6 +- man/is-Annotated-method.Rd | 5 +- man/samples-Annotated-method.Rd | 3 +- tests/testthat/test_all.R | 27 ++-- vignettes/1getStarted.Rmd | 4 +- vignettes/2multipleArguments.Rmd | 4 +- vignettes/3simpleCache.Rmd | 4 +- vignettes/4remoteData.Rmd | 6 +- 18 files changed, 245 insertions(+), 171 deletions(-) diff --git a/.gitignore b/.gitignore index d1de5fe..8916f8e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ .Rproj.user .Rhistory .RData -.DS_Store \ No newline at end of file +.DS_Store +docs +*.RProj \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION index a42dd73..abc8fa4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -15,6 +15,8 @@ Suggests: rmarkdown, testthat Enhances: BiocFileCache, simpleCache, GenomicRanges +biocViews: DataImport, DataRepresentation RoxygenNote: 6.1.1 +URL: https://github.com/pepkit/BiocProject BugReports: https://github.com/pepkit/BiocProject VignetteBuilder: knitr diff --git a/NAMESPACE b/NAMESPACE index 84c7ce0..ae92028 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -7,3 +7,5 @@ exportMethods(config) exportMethods(getProject) exportMethods(is) exportMethods(samples) +import(S4Vectors) +import(pepr) diff --git a/R/functions.R b/R/functions.R index f87b8f2..4e6d69d 100644 --- a/R/functions.R +++ b/R/functions.R @@ -1,8 +1,13 @@ #' Portable Encapsulated Project (PEP) for biological applications #' -#' This function creates a \code{\link[pepr]{Project-class}} object, and executes the user provided function with the created object as a first argument. -#' \cr\cr\emph{If the custom data processing function returns an object of class other than \code{\link[S4Vectors]{Annotated-class}}, the output will be packaged in a \code{\link[S4Vectors]{List-class}} with a metadata slot populated with the \code{\link[pepr]{Project-class}}.} +#' This function creates a \code{\link[pepr]{Project-class}} object, +#' and executes the user provided function with the created object +#' as a first argument. +#' \cr\cr\emph{If the custom data processing function returns an object of +#' class other than \code{\link[S4Vectors]{Annotated-class}}, the output +#' will be packaged in a \code{\link[S4Vectors]{List-class}} with a metadata +#' slot populated with the \code{\link[pepr]{Project-class}}.} #' #' This \code{\link{BiocProject}} function provides some degree #' of flexibility in your custom data processing function usage and @@ -11,8 +16,8 @@ #' \item use a function loaded into the \code{R} environment and specified in #' the config slot in \code{\link[pepr]{Project-class}} #' (specifically: \code{config(project)$bioconductor$readFunName}). -#' \item use a function \emph{not} loaded into the \code{R} environment and specified in -#' the config slot in \code{\link[pepr]{Project}} +#' \item use a function \emph{not} loaded into the \code{R} environment and +#' specified in the config slot in \code{\link[pepr]{Project}} #' (specifically: \code{config(project)$bioconductor$readFunPath}). #' \item use a function from other \code{R} package not loaded into #' the \code{R} environment and specified in the config slot @@ -20,16 +25,17 @@ #' (specifically: \code{config(project)$bioconductor$readFunName}), like: #' \code{pkgName::functionName} #' \item use a function implemented in the \code{\link{BiocProject}} -#' call (passed to the \code{func} argument - anonymous function). This option is given the top priority and overrides -#' other arguments if provided. +#' call (passed to the \code{func} argument - anonymous function). +#' This option is given the top priority and overrides other +#' arguments if provided. #' } #' The custom data processing function must take #' the \code{\link[pepr]{Project-class}} as an argument since this object will #' be passed to the function by default. However, if the function requires #' addtional arguments, ones can be provided with the \code{funcArgs} argument #' in the \code{\link{BiocProject}} function call. -#' Besides, the \code{func} argument with the anonymous function may serve similar -#' possibility. +#' Besides, the \code{func} argument with the anonymous +#' function may serve similar possibility. #' #' #' If the \code{autoLoad} is set to \code{FALSE} the data will not be loaded @@ -45,40 +51,52 @@ #' @param file a character vector with a path to the PEP config file #' @param subproject a character vector with a name of the subproject #' to be activated -#' @param func a anonymous function that reads and/or processess the data, it must take +#' @param func a anonymous function that reads and/or processess the data, +#' it must take #' the \code{\link[pepr]{Project-class}} as an argument. #' See \code{Details} for more information -#' @param funcArgs a named list with arguments you want to pass to the \code{func}. +#' @param funcArgs a named list with arguments you want +#' to pass to the \code{func}. #' The PEP will be passed automatically, -#' but if provided regardless, the constructor will disregard it. You can also pass the arguments in a \code{funcArgs} section within the \code{bioconductor} section in the config file. +#' but if provided regardless, the constructor will disregard it. +#' You can also pass the arguments in a \code{funcArgs} section within +#' the \code{bioconductor} section in the config file. #' @param autoLoad a logical indicating whether the data should be loaded #' automatically. See \code{Details} for more information. #' -#' @return an object of \code{\link[S4Vectors]{Annotated-class}} that is returned by the user provided function with the \code{\link[pepr]{Project-class}} object inserted into the first element of the list in its medatada slot +#' @return an object of \code{\link[S4Vectors]{Annotated-class}} that is +#' returned by the user provided function with +#' the \code{\link[pepr]{Project-class}} object inserted into the first +#' element of the list in its medatada slot +#' +#' @examples +#' projectConfig = system.file("extdata", "example_peps-master", +#' "example_BiocProject", "project_config.yaml", package="BiocProject") +#' p=BiocProject(projectConfig) #' #' @seealso \url{https://pepkit.github.io/} -#' +#' @import pepr #' @export BiocProject -BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, - funcArgs = NULL) { +BiocProject = function(file, subproject = NULL, autoLoad = TRUE, func = NULL, + funcArgs = NULL) { p = tryCatch( - expr = { - pepr::Project(file=file, subproject=subproject) + expr = { + pepr::Project(file=file, subproject=subproject) },warning = function(w) { message(w) stop("There are warnings - associated with the 'Project' object creation.") + associated with the 'Project' object creation.") } ) # prevent PEP (Project object) input. This prevents BiocProject object # failing when the user provides the Project object if(is.null(funcArgs)){ - funcArgs = list() + funcArgs = list() }else{ - pepArgs = as.logical(lapply(funcArgs, function(x) { - is(x, "Project") - })) - if (any(pepArgs)) + pepArgs = as.logical(lapply(funcArgs, function(x) { + is(x, "Project") + })) + if (any(pepArgs)) funcArgs = funcArgs[-which(pepArgs)] } args = append(list(p), funcArgs) @@ -87,19 +105,19 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, } if (!is.null(func)) { - # use the anonymous function if provided - if (is.function(func)) { - readData = .callBiocFun(func, list(p)) - message("Used function from the 'func' argument") - return(.insertPEP(readData, p)) - } else{ - stop("The anonymous function you provided is invalid.") - } - } else{ - # use config to find it - if(!is.logical(autoLoad)) stop("'autoLoad' argument has to be a logical, - got '", class(autoLoad),"'") - if (autoLoad) { + # use the anonymous function if provided + if (is.function(func)) { + readData = .callBiocFun(func, list(p)) + message("Used function from the 'func' argument") + return(.insertPEP(readData, p)) + }else{ + stop("The anonymous function you provided is invalid.") + } + }else{ + # use config to find it + if(!is.logical(autoLoad)) stop("'autoLoad' argument has to be a logical, + got '", class(autoLoad),"'") + if (autoLoad) { # check if the config consists of MAIN_SECTION section if(!pepr::checkSection(pepr::config(p), MAIN_SECTION)){ message("No data was read. Returning a Project object") @@ -110,63 +128,66 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, funcName = pepr::config(p)[[MAIN_SECTION]][[FUNCTION_NAME]] # check if the function name was provided # and if it exists in the environment - if (!is.null(funcName) && exists(funcName)) { - # function from config.yaml in environment - readData = .callBiocFun(funcName, args) - message("Used function ", funcName, " from the environment") - return(.insertPEP(readData, p)) - } else{ - if (!is.null(funcName) && length(grep("(\\:){2,3}", funcName)) != 0) { - # trying to access the function from the namespace that - # was specified in the config.yaml FUNCTION_NAME - splitted = strsplit(funcName, ":")[[1]] - nonEmpty = splitted[which(splitted != "")] - funcName = utils::getFromNamespace(x=nonEmpty[2], ns=nonEmpty[1]) - readData = .callBiocFun(funcName, args) - message("Used function ", funcName, " from the environment") - return(.insertPEP(readData, p)) - } - # function from config.yaml in read_fun_name not in environment, - # trying to source the file specified in - # the config.yaml FUNCTION_PATH - funcPath = - pepr::.expandPath(pepr::config(p)[[MAIN_SECTION]][[FUNCTION_PATH]]) - if (!is.null(funcPath)){ - if (!file.exists(funcPath)) - funcPath = .makeAbsPath(funcPath,dirname(p@file)) - if(!file.exists(funcPath)) - stop( - "The function does not exist in the environment and file ", - funcPath, - " does not exist" - ) - readFun = source(funcPath)$value - message("Function read from file: ", funcPath) - readData = .callBiocFun(readFun, args) - return(.insertPEP(readData, p)) - }else{ - warning("Can't find function in the environment and the value for '" - , FUNCTION_PATH, - "' key was not provided in the config YAML.") + if (!is.null(funcName) && exists(funcName)) { + # function from config.yaml in environment + readData = .callBiocFun(funcName, args) + message("Used function ", funcName, " from the environment") + return(.insertPEP(readData, p)) + }else{ + if (!is.null(funcName) && length(grep("(\\:){2,3}", funcName)) != 0) { + # trying to access the function from the namespace that + # was specified in the config.yaml FUNCTION_NAME + splitted = strsplit(funcName, ":")[[1]] + nonEmpty = splitted[which(splitted != "")] + funcName = utils::getFromNamespace(x=nonEmpty[2], ns=nonEmpty[1]) + readData = .callBiocFun(funcName, args) + message("Used function ", funcName, " from the environment") + return(.insertPEP(readData, p)) + } + # function from config.yaml in read_fun_name not in environment, + # trying to source the file specified in + # the config.yaml FUNCTION_PATH + funcPath =pepr::.expandPath( + pepr::config(p)[[MAIN_SECTION]][[FUNCTION_PATH]]) + if (!is.null(funcPath)){ + if (!file.exists(funcPath)) + funcPath = .makeAbsPath(funcPath,dirname(p@file)) + if(!file.exists(funcPath)) + stop( + "The function does not exist in the environment and file ", + funcPath, + " does not exist" + ) + readFun = source(funcPath)$value + message("Function read from file: ", funcPath) + readData = .callBiocFun(readFun, args) + return(.insertPEP(readData, p)) + }else{ + warning("Can't find function in the environment and the value for '" + , FUNCTION_PATH, + "' key was not provided in the config YAML.") + message("No data was read. Returning a Project object") + return(p) + } + } + }else{ message("No data was read. Returning a Project object") return(p) - } } - } else{ - message("No data was read. Returning a Project object") - return(p) - } } } #' Insert a PEP metadata in a metadata slot of Annotated #' -#' This function inserts the PEP (\code{\link[pepr]{Project-class}}) into the metadata slot of objects that extend the \code{\link[S4Vectors]{Annotated-class}} +#' This function inserts the PEP (\code{\link[pepr]{Project-class}}) +#' into the metadata slot of objects that +#' extend the \code{\link[S4Vectors]{Annotated-class}} #' #' @param object an object of \code{\link[S4Vectors]{Annotated-class}} #' @param pep an object of class \code{\link[pepr]{Project-class}} #' -#' @return an object of the same class as the object argument but enriched with the metadata from the pep argument +#' @return an object of the same class as the object argument but enriched +#' with the metadata from the pep argument #' #' @examples #' # If the object is of class Annotated @@ -178,11 +199,13 @@ BiocProject = function(file, subproject = NULL, autoLoad = T, func = NULL, #' object1 = "test" #' result1 = .insertPEP(object1, pepr::Project()) #' metadata(result1) +#' @import S4Vectors #' @export .insertPEP = function(object, pep) { - if(!is(pep, "Project")) stop("the pep argument has to be of class 'Project', - got '", class(pep),"'") - if(is(object, "Annotated")){ + if(!methods::is(pep, "Project")) + stop("the pep argument has to be of class 'Project', + got '", class(pep),"'") + if(methods::is(object, "Annotated")){ S4Vectors::metadata(object) = list(PEP=pep) object }else{ diff --git a/R/methods_Annotated.R b/R/methods_Annotated.R index f9c4fc5..955c5f0 100644 --- a/R/methods_Annotated.R +++ b/R/methods_Annotated.R @@ -14,9 +14,11 @@ setMethod(".is.project","Annotated",function(.Object){ setGeneric("getProject", function(.Object) standardGeneric("getProject")) -#' Extract the object of \code{\link[pepr]{Project-class}} from the \code{\link[S4Vectors]{Annotated-class}} +#' Extract the object of \code{\link[pepr]{Project-class}} from +#' the \code{\link[S4Vectors]{Annotated-class}} #' -#' This method can be used to extract the project metadata from objects of \code{\link[S4Vectors]{Annotated-class}} +#' This method can be used to extract the project metadata from objects of +#' \code{\link[S4Vectors]{Annotated-class}} #' #' @param object an object of \code{\link[S4Vectors]{Annotated-class}} #' @@ -40,7 +42,8 @@ setMethod("getProject","Annotated",function(.Object){ #' View samples in the objects of \code{\link[pepr]{Project-class}} #' #' This method can be used to view the samples slot -#' of the \code{\link[pepr]{Project-class}} or \code{\link[S4Vectors]{Annotated-class}} +#' of the \code{\link[pepr]{Project-class}} +#' or \code{\link[S4Vectors]{Annotated-class}} #' #' @param object an object of \code{\link[pepr]{Project-class}} #' @@ -63,7 +66,8 @@ setMethod( #' View PEP config of the object of \code{\link[pepr]{Project-class}} #' #' This method can be used to view the config slot of -#' the \code{\link[pepr]{Project-class}} or or \code{\link[S4Vectors]{Annotated-class}} +#' the \code{\link[pepr]{Project-class}} +#' or \code{\link[S4Vectors]{Annotated-class}} #' #' @param object an object of \code{\link[pepr]{Project-class}} #' @@ -87,7 +91,10 @@ setGeneric("is", package = "methods") #' Is an Object from a Class? #' -#' Functions to test inheritance relationships between an object and a class or between two classes. It uses the generic is function but overrides its behavior for obejcts of class \code{\link[S4Vectors]{Annotated-class}} when testing for inheritance from \code{\link[pepr]{Project-class}} class. +#' Functions to test inheritance relationships between an object and a class +#' or between two classes. It uses the generic is function but overrides its +#' behavior for obejcts of class \code{\link[S4Vectors]{Annotated-class}} when +#' testing for inheritance from \code{\link[pepr]{Project-class}} class. #' #' see the \code{\link[methods]{is}} for more details #' diff --git a/R/utils.R b/R/utils.R index 4245520..3d8f5f8 100644 --- a/R/utils.R +++ b/R/utils.R @@ -1,27 +1,28 @@ # internal function used for wrapping the user-supplied function meessages # in a box .wrapFunMessages = function(messages, type) { - n = options("width")[[1]] - header = ifelse( - length(messages) > 1, - paste0(" Your function ", type, "s (", length(messages), ") "), - paste0(" Your function ", type, " ") - ) - nH = floor(nchar(header) / 2) - nFill = floor(n / 2) - message("\n",rep("-", nFill - nH), header, rep("-", nFill - nH)) - i = 1 - for (i in seq_along(messages)) { - m = trimws(messages[i], which="both") - message("\n", type, " ", i , ": ", m, "\n") - } - message(rep("-", n), "\n") + n = options("width")[[1]] + header = ifelse( + length(messages) > 1, + paste0(" Your function ", type,"s (", length(messages), ") "), + paste0(" Your function ", type, " ") + ) + nH = floor(nchar(header) / 2) + nFill = floor(n / 2) + message("\n",rep("-", nFill - nH), header, rep("-", nFill - nH)) + i = 1 + for (i in seq_along(messages)) { + m = trimws(messages[i], which="both") + message("\n", type, " ", i , ": ", m, "\n") + } + message(rep("-", n), "\n") } # internal function that wraps the external function execution # in tryCatch to indicate problems with the external function execution .callBiocFun <- function(func, arguments) { - if(!is(arguments, "list")) stop("The 'arguments' argument has to be a list, got '", class(arguments),"'") + if(!is(arguments, "list")) stop("The 'arguments' argument has to be a list, + got '", class(arguments),"'") .warnings = c() frameNumber <- sys.nframe() wHandler <- function(w){ @@ -36,7 +37,8 @@ message("No data was read. The error message was returned instead.") e$message } - res = withCallingHandlers(tryCatch(do.call(func, arguments), error = eHandler),warning = wHandler) + res = withCallingHandlers( + tryCatch(do.call(func, arguments), error = eHandler),warning = wHandler) if(length(.warnings) > 0){ warning("There were warnings associated with your function execution.") .wrapFunMessages(.warnings,"warning") @@ -47,23 +49,23 @@ # Create an absolute path from a primary target and a parent candidate. # # @param perhapsRelative: Path to primary target directory. -# @param parent: Path to parent folder to use if target isn't absolute. +# @param parent a path to parent folder to use if target isn't absolute. # -# @return Target itself if already absolute, else target nested within parent. +# @return Target itself if already absolute, else target nested within parent. .makeAbsPath = function(perhapsRelative, parent) { - if (!.isDefined(perhapsRelative)) { return(perhapsRelative)} - perhapsRelative = pepr::.expandPath(perhapsRelative) - if (.isAbsolute(perhapsRelative)) { - abspath = perhapsRelative - } else { - abspath = file.path(normalizePath(parent), perhapsRelative) - } - if (!.isAbsolute(abspath)) { - errmsg = sprintf("Relative path '%s' and parent '%s' failed to create - absolute path: '%s'", perhapsRelative, parent, abspath) - stop(errmsg) - } - return(abspath) + if (!.isDefined(perhapsRelative)) return(perhapsRelative) + perhapsRelative = pepr::.expandPath(perhapsRelative) + if (.isAbsolute(perhapsRelative)) { + abspath = perhapsRelative + }else { + abspath = file.path(normalizePath(parent), perhapsRelative) + } + if (!.isAbsolute(abspath)) { + errmsg = sprintf("Relative path '%s' and parent '%s' failed to create + absolute path: '%s'", perhapsRelative, parent, abspath) + stop(errmsg) + } + return(abspath) } # Must test for is.null first, since is.na(NULL) returns a logical(0) which is @@ -76,16 +78,18 @@ # @param path The path to check for seeming absolute-ness. # @return Flag indicating whether the \code{path} appears to be absolute. .isAbsolute = function(path) { - if(!is.character(path)) stop("The path must be character.") - firstChar = substr(path, 1, 1) - return(identical("/", firstChar) | identical("~", firstChar)) + if(!is.character(path)) stop("The path must be character.") + firstChar = substr(path, 1, 1) + return(identical("/", firstChar) | identical("~", firstChar)) } #' Update list with another list #' -#' This function performs a union of two lists and updates the elements of the first one if are found in the other one. +#' This function performs a union of two lists and updates the elements of the +#' first one if are found in the other one. #' -#' Both elements have to be lists. If some elements are not named, they are preserved but the order might be lost. +#' Both elements have to be lists. If some elements are not named, they are +#' preserved but the order might be lost. #' #' @param list1 a list to be updated #' @param list2 a list to update with diff --git a/man/BiocProject.Rd b/man/BiocProject.Rd index 406a7a6..f4b568a 100644 --- a/man/BiocProject.Rd +++ b/man/BiocProject.Rd @@ -4,7 +4,7 @@ \alias{BiocProject} \title{Portable Encapsulated Project (PEP) for biological applications} \usage{ -BiocProject(file, subproject = NULL, autoLoad = T, func = NULL, +BiocProject(file, subproject = NULL, autoLoad = TRUE, func = NULL, funcArgs = NULL) } \arguments{ @@ -16,20 +16,32 @@ to be activated} \item{autoLoad}{a logical indicating whether the data should be loaded automatically. See \code{Details} for more information.} -\item{func}{a anonymous function that reads and/or processess the data, it must take +\item{func}{a anonymous function that reads and/or processess the data, +it must take the \code{\link[pepr]{Project-class}} as an argument. See \code{Details} for more information} -\item{funcArgs}{a named list with arguments you want to pass to the \code{func}. -The PEP will be passed automatically, -but if provided regardless, the constructor will disregard it. You can also pass the arguments in a \code{funcArgs} section within the \code{bioconductor} section in the config file.} +\item{funcArgs}{a named list with arguments you want +to pass to the \code{func}. + The PEP will be passed automatically, + but if provided regardless, the constructor will disregard it. + You can also pass the arguments in a \code{funcArgs} section within + the \code{bioconductor} section in the config file.} } \value{ -an object of \code{\link[S4Vectors]{Annotated-class}} that is returned by the user provided function with the \code{\link[pepr]{Project-class}} object inserted into the first element of the list in its medatada slot +an object of \code{\link[S4Vectors]{Annotated-class}} that is +returned by the user provided function with +the \code{\link[pepr]{Project-class}} object inserted into the first +element of the list in its medatada slot } \description{ -This function creates a \code{\link[pepr]{Project-class}} object, and executes the user provided function with the created object as a first argument. -\cr\cr\emph{If the custom data processing function returns an object of class other than \code{\link[S4Vectors]{Annotated-class}}, the output will be packaged in a \code{\link[S4Vectors]{List-class}} with a metadata slot populated with the \code{\link[pepr]{Project-class}}.} +This function creates a \code{\link[pepr]{Project-class}} object, +and executes the user provided function with the created object +as a first argument. +\cr\cr\emph{If the custom data processing function returns an object of +class other than \code{\link[S4Vectors]{Annotated-class}}, the output +will be packaged in a \code{\link[S4Vectors]{List-class}} with a metadata +slot populated with the \code{\link[pepr]{Project-class}}.} } \details{ This \code{\link{BiocProject}} function provides some degree @@ -39,8 +51,8 @@ implementation. Consider the possibilities listed below: \item use a function loaded into the \code{R} environment and specified in the config slot in \code{\link[pepr]{Project-class}} (specifically: \code{config(project)$bioconductor$readFunName}). - \item use a function \emph{not} loaded into the \code{R} environment and specified in - the config slot in \code{\link[pepr]{Project}} + \item use a function \emph{not} loaded into the \code{R} environment and + specified in the config slot in \code{\link[pepr]{Project}} (specifically: \code{config(project)$bioconductor$readFunPath}). \item use a function from other \code{R} package not loaded into the \code{R} environment and specified in the config slot @@ -48,16 +60,17 @@ implementation. Consider the possibilities listed below: (specifically: \code{config(project)$bioconductor$readFunName}), like: \code{pkgName::functionName} \item use a function implemented in the \code{\link{BiocProject}} - call (passed to the \code{func} argument - anonymous function). This option is given the top priority and overrides - other arguments if provided. + call (passed to the \code{func} argument - anonymous function). + This option is given the top priority and overrides other + arguments if provided. } The custom data processing function must take the \code{\link[pepr]{Project-class}} as an argument since this object will be passed to the function by default. However, if the function requires addtional arguments, ones can be provided with the \code{funcArgs} argument in the \code{\link{BiocProject}} function call. -Besides, the \code{func} argument with the anonymous function may serve similar -possibility. +Besides, the \code{func} argument with the anonymous +function may serve similar possibility. If the \code{autoLoad} is set to \code{FALSE} the data will not be loaded and empty \code{\link[pepr]{Project-class}} object will be returned. @@ -69,6 +82,12 @@ Browse the for more detailed explanation with examples. } +\examples{ +projectConfig = system.file("extdata", "example_peps-master", +"example_BiocProject", "project_config.yaml", package="BiocProject") +p=BiocProject(projectConfig) + +} \seealso{ \url{https://pepkit.github.io/} } diff --git a/man/config-Annotated-method.Rd b/man/config-Annotated-method.Rd index 5d54bd3..8ca99c8 100644 --- a/man/config-Annotated-method.Rd +++ b/man/config-Annotated-method.Rd @@ -15,7 +15,8 @@ a list with the config file } \description{ This method can be used to view the config slot of -the \code{\link[pepr]{Project-class}} or or \code{\link[S4Vectors]{Annotated-class}} +the \code{\link[pepr]{Project-class}} + or \code{\link[S4Vectors]{Annotated-class}} } \examples{ projectConfig = system.file("extdata", "example_peps-master", diff --git a/man/dot-insertPEP.Rd b/man/dot-insertPEP.Rd index bdcfb06..27aff49 100644 --- a/man/dot-insertPEP.Rd +++ b/man/dot-insertPEP.Rd @@ -12,10 +12,13 @@ \item{pep}{an object of class \code{\link[pepr]{Project-class}}} } \value{ -an object of the same class as the object argument but enriched with the metadata from the pep argument +an object of the same class as the object argument but enriched + with the metadata from the pep argument } \description{ -This function inserts the PEP (\code{\link[pepr]{Project-class}}) into the metadata slot of objects that extend the \code{\link[S4Vectors]{Annotated-class}} +This function inserts the PEP (\code{\link[pepr]{Project-class}}) +into the metadata slot of objects that +extend the \code{\link[S4Vectors]{Annotated-class}} } \examples{ # If the object is of class Annotated diff --git a/man/dot-updateList.Rd b/man/dot-updateList.Rd index 35097b3..4d5b78d 100644 --- a/man/dot-updateList.Rd +++ b/man/dot-updateList.Rd @@ -15,10 +15,12 @@ an updated list } \description{ -This function performs a union of two lists and updates the elements of the first one if are found in the other one. +This function performs a union of two lists and updates the elements of the +first one if are found in the other one. } \details{ -Both elements have to be lists. If some elements are not named, they are preserved but the order might be lost. +Both elements have to be lists. If some elements are not named, they are +preserved but the order might be lost. } \examples{ list1=list(a=1,b=2) diff --git a/man/getProject-Annotated-method.Rd b/man/getProject-Annotated-method.Rd index 44413c0..e730f6b 100644 --- a/man/getProject-Annotated-method.Rd +++ b/man/getProject-Annotated-method.Rd @@ -3,7 +3,8 @@ \docType{methods} \name{getProject,Annotated-method} \alias{getProject,Annotated-method} -\title{Extract the object of \code{\link[pepr]{Project-class}} from the \code{\link[S4Vectors]{Annotated-class}}} +\title{Extract the object of \code{\link[pepr]{Project-class}} from +the \code{\link[S4Vectors]{Annotated-class}}} \usage{ \S4method{getProject}{Annotated}(.Object) } @@ -14,7 +15,8 @@ an object of \code{\link[pepr]{Project-class}} } \description{ -This method can be used to extract the project metadata from objects of \code{\link[S4Vectors]{Annotated-class}} +This method can be used to extract the project metadata from objects of +\code{\link[S4Vectors]{Annotated-class}} } \examples{ projectConfig = system.file("extdata", "example_peps-master", diff --git a/man/is-Annotated-method.Rd b/man/is-Annotated-method.Rd index 12d99d6..0661bc6 100644 --- a/man/is-Annotated-method.Rd +++ b/man/is-Annotated-method.Rd @@ -16,7 +16,10 @@ a logical } \description{ -Functions to test inheritance relationships between an object and a class or between two classes. It uses the generic is function but overrides its behavior for obejcts of class \code{\link[S4Vectors]{Annotated-class}} when testing for inheritance from \code{\link[pepr]{Project-class}} class. +Functions to test inheritance relationships between an object and a class +or between two classes. It uses the generic is function but overrides its +behavior for obejcts of class \code{\link[S4Vectors]{Annotated-class}} when +testing for inheritance from \code{\link[pepr]{Project-class}} class. } \details{ see the \code{\link[methods]{is}} for more details diff --git a/man/samples-Annotated-method.Rd b/man/samples-Annotated-method.Rd index f26ac86..62646c7 100644 --- a/man/samples-Annotated-method.Rd +++ b/man/samples-Annotated-method.Rd @@ -15,7 +15,8 @@ a data.table with the with metadata about samples } \description{ This method can be used to view the samples slot -of the \code{\link[pepr]{Project-class}} or \code{\link[S4Vectors]{Annotated-class}} +of the \code{\link[pepr]{Project-class}} +or \code{\link[S4Vectors]{Annotated-class}} } \examples{ projectConfig = system.file("extdata", "example_peps-master", diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index 94efec1..6e27997 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -76,9 +76,9 @@ test_that(".isDefined returns correct object", { }) test_that(".isDefined returns correct value", { - expect_equal(.isDefined(NA),F) - expect_equal(.isDefined(NULL),F) - expect_equal(.isDefined(configFile),T) + expect_equal(.isDefined(NA),FALSE) + expect_equal(.isDefined(NULL),FALSE) + expect_equal(.isDefined(configFile),TRUE) }) context("Test .isAbsolute utility function") @@ -88,8 +88,8 @@ test_that(".isAbsolute returns correct object", { }) test_that(".isAbsolute returns correct value", { - expect_equal(.isAbsolute("~"),T) - expect_equal(.isAbsolute("../test"),F) + expect_equal(.isAbsolute("~"),TRUE) + expect_equal(.isAbsolute("../test"),FALSE) }) context("Test .callBiocFun untility function") @@ -139,18 +139,21 @@ test_that("BiocProject function returns Annotated when provided objects of }),"Annotated")) }) -test_that("BiocProject function returns a Project object when autoload is set to FALSE", { - expect_is(BiocProject(file=configFile,autoLoad = F),"Project") +test_that("BiocProject function returns a Project object + when autoload is set to FALSE", { + expect_is(BiocProject(file=configFile,autoLoad = FALSE),"Project") }) -test_that("BiocProject function throws errors/warnings when the arguments are inappropriate", { +test_that("BiocProject function throws errors/warnings + when the arguments are inappropriate", { expect_error(BiocProject(file=configFile,func = "2")) expect_warning(BiocProject(file=configFile,funcArgs = "a")) expect_error(BiocProject(file = "test")) expect_error(BiocProject(file = configFile,autoLoad = "test")) }) -test_that("BiocProject function catches errors in the user-provided function, warns and returns the error message as Annotated", { +test_that("BiocProject function catches errors in the user-provided + function, warns and returns the error message as Annotated", { expect_warning(expect_is(BiocProject(file=configFile,func=function(x) { stop("test") }),"Annotated")) @@ -172,12 +175,12 @@ test_that(".is.project returns a correct object", { }) test_that(".is.project returns a value", { - expect_equal(.is.project(bp),T) - expect_equal(.is.project(S4Vectors::List(a=1)), F) + expect_equal(.is.project(bp),TRUE) + expect_equal(.is.project(S4Vectors::List(a=1)), FALSE) }) test_that("is method returns correct value when Annotated provided", { - expect_equal(is(bp,"Project"), T) + expect_equal(is(bp,"Project"), TRUE) }) test_that("getProject returns a correct object", { diff --git a/vignettes/1getStarted.Rmd b/vignettes/1getStarted.Rmd index 58e1299..b9609f3 100644 --- a/vignettes/1getStarted.Rmd +++ b/vignettes/1getStarted.Rmd @@ -2,9 +2,9 @@ title: "Getting started with BiocProject" author: "Michal Stolarczyk" date: "`r Sys.Date()`" -output: rmarkdown::html_vignette +output: BiocStyle::html_document vignette: > - %\VignetteIndexEntry{Vignette Title} + %\VignetteIndexEntry{Getting started with BiocProject} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- diff --git a/vignettes/2multipleArguments.Rmd b/vignettes/2multipleArguments.Rmd index f854173..86474ff 100644 --- a/vignettes/2multipleArguments.Rmd +++ b/vignettes/2multipleArguments.Rmd @@ -2,9 +2,9 @@ title: "More arguments than just a PEP in your function?" author: "Michal Stolarczyk" date: "`r Sys.Date()`" -output: rmarkdown::html_vignette +output: BiocStyle::html_document vignette: > - %\VignetteIndexEntry{Vignette Title} + %\VignetteIndexEntry{More arguments than just a PEP in your function?} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- diff --git a/vignettes/3simpleCache.Rmd b/vignettes/3simpleCache.Rmd index f3a5cc7..f082fe2 100644 --- a/vignettes/3simpleCache.Rmd +++ b/vignettes/3simpleCache.Rmd @@ -2,9 +2,9 @@ title: "Working with large datasets - simpleCache" author: "Michal Stolarczyk" date: "`r Sys.Date()`" -output: rmarkdown::html_vignette +output: BiocStyle::html_document vignette: > - %\VignetteIndexEntry{Vignette Title} + %\VignetteIndexEntry{Working with large datasets - simpleCache} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- diff --git a/vignettes/4remoteData.Rmd b/vignettes/4remoteData.Rmd index 119be13..391f4ca 100644 --- a/vignettes/4remoteData.Rmd +++ b/vignettes/4remoteData.Rmd @@ -2,9 +2,9 @@ title: "Working with remote data" author: "Michal Stolarczyk" date: "`r Sys.Date()`" -output: rmarkdown::html_vignette +output: BiocStyle::html_document vignette: > - %\VignetteIndexEntry{Vignette Title} + %\VignetteIndexEntry{Working with remote data} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- @@ -72,7 +72,7 @@ library(pepr) ## Execute the `BiocProject` function Get path to the config file -```{r echo=T,message=FALSE} +```{r echo=TRUE,message=FALSE} library(BiocProject) ProjectConfigRemote = system.file( "extdata", From a9c424c0f86820f7a1900fc428c874c46a481992 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Thu, 31 Jan 2019 16:26:58 -0500 Subject: [PATCH 19/37] update travis CI config after pepr release --- .travis.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index ac1471b..bca6337 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,8 @@ language: R sudo: false cache: packages warnings_are_errors: false -before_install: - - Rscript -e "install.packages('devtools');devtools::install_github(repo = 'pepkit/pepr',ref = 'dev');source('https://bioconductor.org/biocLite.R');biocLite('GenomicRanges');biocLite('BiocFileCache');devtools::install_github(repo = 'databio/simpleCache')" +r_packages: devtools +r_github_packages: pepkit/pepr databio/simpleCache +bioc_packages: GenomicRanges BiocStyle BiocFileCache +# before_install: + # - Rscript -e "install.packages('devtools');devtools::install_github(repo = 'pepkit/pepr',ref = 'dev');source('https://bioconductor.org/biocLite.R');biocLite('GenomicRanges');biocLite('BiocFileCache');devtools::install_github(repo = 'databio/simpleCache')" From a87217a8d0d3da295bb391c468182b9e0705ba20 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Thu, 31 Jan 2019 16:34:58 -0500 Subject: [PATCH 20/37] update travis config --- .travis.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index bca6337..c8731d1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,12 @@ -# R for travis: see documentation at https://docs.travis-ci.com/user/languages/r - language: R sudo: false cache: packages warnings_are_errors: false r_packages: devtools -r_github_packages: pepkit/pepr databio/simpleCache -bioc_packages: GenomicRanges BiocStyle BiocFileCache -# before_install: - # - Rscript -e "install.packages('devtools');devtools::install_github(repo = 'pepkit/pepr',ref = 'dev');source('https://bioconductor.org/biocLite.R');biocLite('GenomicRanges');biocLite('BiocFileCache');devtools::install_github(repo = 'databio/simpleCache')" +r_github_packages: + - pepkit/pepr + - databio/simpleCache +bioc_packages: + - GenomicRanges + - BiocStyle + - BiocFileCache \ No newline at end of file From 10ac44ca1d31101af2717fd56389a96509fa2eee Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Thu, 31 Jan 2019 17:07:13 -0500 Subject: [PATCH 21/37] return an Annotated object on error --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index 3d8f5f8..86ecc3f 100644 --- a/R/utils.R +++ b/R/utils.R @@ -35,7 +35,7 @@ # error handler .wrapFunMessages(e$message,"error") message("No data was read. The error message was returned instead.") - e$message + S4Vectors::List(e$message) } res = withCallingHandlers( tryCatch(do.call(func, arguments), error = eHandler),warning = wHandler) From 757eebd86cc28c0e6119fd3eb1d3657edad4d056 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Thu, 31 Jan 2019 17:24:48 -0500 Subject: [PATCH 22/37] correct tests needed after previous modification --- R/utils.R | 5 +++-- tests/testthat/test_all.R | 9 ++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/R/utils.R b/R/utils.R index 86ecc3f..d40d3ce 100644 --- a/R/utils.R +++ b/R/utils.R @@ -21,8 +21,9 @@ # internal function that wraps the external function execution # in tryCatch to indicate problems with the external function execution .callBiocFun <- function(func, arguments) { - if(!is(arguments, "list")) stop("The 'arguments' argument has to be a list, - got '", class(arguments),"'") + if(!is(arguments, "list")) + stop("The 'arguments' argument has to be a list, got '", + class(arguments),"'") .warnings = c() frameNumber <- sys.nframe() wHandler <- function(w){ diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index 6e27997..ee38850 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -96,7 +96,7 @@ context("Test .callBiocFun untility function") test_that(".callBiocFun catches errors", { expect_error(expect_error(.callBiocFun(a,list(testChar)))) - expect_equal(.callBiocFun(a,list(testChar)),testChar) + expect_equal(.callBiocFun(a,list(testChar)),S4Vectors::List(testChar)) expect_warning(.callBiocFun(b,list(testChar))) }) @@ -147,16 +147,15 @@ test_that("BiocProject function returns a Project object test_that("BiocProject function throws errors/warnings when the arguments are inappropriate", { expect_error(BiocProject(file=configFile,func = "2")) - expect_warning(BiocProject(file=configFile,funcArgs = "a")) expect_error(BiocProject(file = "test")) expect_error(BiocProject(file = configFile,autoLoad = "test")) }) test_that("BiocProject function catches errors in the user-provided - function, warns and returns the error message as Annotated", { - expect_warning(expect_is(BiocProject(file=configFile,func=function(x) { + function returns the error message as Annotated", { + expect_is(BiocProject(file=configFile,func=function(x) { stop("test") - }),"Annotated")) + }),"Annotated") }) From a46d378502537b652677a951549165f642adb73e Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 09:54:23 -0500 Subject: [PATCH 23/37] add faulty project for testing, see #23 --- .../faulty_project/project_config.yaml | 6 ++++++ .../test_projects/faulty_project/readBedFiles.R | 16 ++++++++++++++++ .../faulty_project/sample_annotation.csv | 3 +++ 3 files changed, 25 insertions(+) create mode 100644 tests/test_projects/faulty_project/project_config.yaml create mode 100644 tests/test_projects/faulty_project/readBedFiles.R create mode 100644 tests/test_projects/faulty_project/sample_annotation.csv diff --git a/tests/test_projects/faulty_project/project_config.yaml b/tests/test_projects/faulty_project/project_config.yaml new file mode 100644 index 0000000..bdf992b --- /dev/null +++ b/tests/test_projects/faulty_project/project_config.yaml @@ -0,0 +1,6 @@ +metadata: + sample_annotation: sample_annotation.csv + +bioconductor: + readFunName: readBedFiles_faulty + readFunPath: readBedFiles_faulty.R diff --git a/tests/test_projects/faulty_project/readBedFiles.R b/tests/test_projects/faulty_project/readBedFiles.R new file mode 100644 index 0000000..363c5c0 --- /dev/null +++ b/tests/test_projects/faulty_project/readBedFiles.R @@ -0,0 +1,16 @@ +readBedFiles = function(project) { + cwd = getwd() + paths = pepr::samples(project)$file_path + sampleNames = pepr::samples(project)$sample_name + setwd(dirname(project@file)) + result = lapply(paths, function(x){ + df = read.table(x) + colnames(df) = c('chr', 'start', 'end') + gr = GenomicRanges::GRanges(df) + }) + setwd(cwd) + names(result) = sampleNames + return(GenomicRanges::GRangesList(result)) +} + + diff --git a/tests/test_projects/faulty_project/sample_annotation.csv b/tests/test_projects/faulty_project/sample_annotation.csv new file mode 100644 index 0000000..59de6e5 --- /dev/null +++ b/tests/test_projects/faulty_project/sample_annotation.csv @@ -0,0 +1,3 @@ +sample_name,file_path +laminB1Lads,data/laminB1Lads.bed +vistaEnhancers,data/vistaEnhancers.bed From 111cc78f71aac1a5f3fb1927516c14962d26188b Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 11:37:46 -0500 Subject: [PATCH 24/37] correct arguments final order when provided from 2 sources --- R/functions.R | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/R/functions.R b/R/functions.R index 4e6d69d..a645227 100644 --- a/R/functions.R +++ b/R/functions.R @@ -93,15 +93,17 @@ BiocProject = function(file, subproject = NULL, autoLoad = TRUE, func = NULL, if(is.null(funcArgs)){ funcArgs = list() }else{ - pepArgs = as.logical(lapply(funcArgs, function(x) { - is(x, "Project") - })) - if (any(pepArgs)) - funcArgs = funcArgs[-which(pepArgs)] + if (length(.findProjectInList(funcArgs)) > 0) + funcArgs = funcArgs[-.findProjectInList(funcArgs)] } args = append(list(p), funcArgs) if(pepr::checkSection(pepr::config(p), c(MAIN_SECTION, FUNCTION_ARGS))){ - args = .updateList(args,config(p)[[MAIN_SECTION]][[FUNCTION_ARGS]]) + args = .updateList(config(p)[[MAIN_SECTION]][[FUNCTION_ARGS]],args) + argsNames = names(args) + project = args[[.findProjectInList(args)]] + argsNames = append("",argsNames[-.findProjectInList(args)]) + args = append(list(p), args[[-.findProjectInList(args)]]) + names(args) = argsNames } if (!is.null(func)) { From 1c799e25c8214f86b4f7a939df2581e0f865c0be Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 11:38:54 -0500 Subject: [PATCH 25/37] fix problems in .updateList when unnamed list was provided, add new func --- R/utils.R | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/R/utils.R b/R/utils.R index d40d3ce..53d38f4 100644 --- a/R/utils.R +++ b/R/utils.R @@ -108,15 +108,27 @@ stop("One of the arguments was not a list") nms1 = names(list1) nms2 = names(list2) + if(is.null(nms2)) nms2 = "" + counter=1 for(n in nms2){ idx = which(nms1 == n) if(length(idx) > 0){ list1[[idx]] = list2[[n]] }else{ - add = list2[[n]] + add = list(list2[[counter]]) names(add) = n - list1 = c(list1,add) + list1 = append(list1,add) } + counter = counter + 1 } return(list1) } + +# Finds the pepr::Project object in a list and returns its index +# If it is not present, returns integer(0) +.findProjectInList = function(l) { + which(as.logical(lapply(l, function(x) { + is(x, "Project") + }))) +} + From 96930f4c4c76c600dcd35d36fa0b5998a00bc15f Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 11:39:53 -0500 Subject: [PATCH 26/37] add tests, #23 --- .../faulty_project/project_config.yaml | 2 ++ tests/testthat/test_all.R | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/tests/test_projects/faulty_project/project_config.yaml b/tests/test_projects/faulty_project/project_config.yaml index bdf992b..2407a65 100644 --- a/tests/test_projects/faulty_project/project_config.yaml +++ b/tests/test_projects/faulty_project/project_config.yaml @@ -1,3 +1,5 @@ +# This is a faulty PEP. +# The readFunName and readFunPath values point to function that does not exist metadata: sample_annotation: sample_annotation.csv diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index ee38850..d684718 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -18,14 +18,15 @@ configFileArgs = system.file( package = "BiocProject" ) -configFileExceptions = system.file( - "extdata", - "example_peps-master", - "example_BiocProject_exceptions", +configFileFaulty = system.file( + "tests", + "test_projects", + "faulty_project", "project_config.yaml", package = "BiocProject" ) + bp = BiocProject(configFile) a=function(arg) { @@ -132,6 +133,19 @@ test_that("BiocProject function return correct object", { expect_is(BiocProject(configFile),"Annotated") }) +test_that("BiocProject function works with arguments", { + expect_is(BiocProject(configFileArgs),"Annotated") + expect_is(BiocProject(configFileArgs, funcArgs = list(resize.width=200)), "Annotated") +}) + +test_that("BiocProject function overrides the arguments specified in the config + file with ones that have the same names in the funcArgs list", { + expect_false(identical( + BiocProject(configFileArgs), + BiocProject(configFileArgs, funcArgs = list(resize.width = 101)) + )) +}) + test_that("BiocProject function returns Annotated when provided objects of different class and thorows a warning", { expect_warning(expect_is(BiocProject(configFile, func = function(x){ @@ -158,6 +172,10 @@ test_that("BiocProject function catches errors in the user-provided }),"Annotated") }) +test_that("BiocProject function catches errors when the function specified + does not exist", { + expect_error(BiocProject(configFileFaulty)) + }) context("Test Annotated methods") From 7c443b8ed5460329c36add6f330c002f045ca36f Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 12:21:17 -0500 Subject: [PATCH 27/37] update example, update vignette --- R/functions.R | 6 +++++- man/BiocProject.Rd | 6 +++++- vignettes/2multipleArguments.Rmd | 10 ++++++++-- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/R/functions.R b/R/functions.R index a645227..3b8a163 100644 --- a/R/functions.R +++ b/R/functions.R @@ -72,7 +72,11 @@ #' @examples #' projectConfig = system.file("extdata", "example_peps-master", #' "example_BiocProject", "project_config.yaml", package="BiocProject") -#' p=BiocProject(projectConfig) +#' bp=BiocProject(projectConfig) +#' +#' bp +#' +#' metadata(bp) #' #' @seealso \url{https://pepkit.github.io/} #' @import pepr diff --git a/man/BiocProject.Rd b/man/BiocProject.Rd index f4b568a..751a8de 100644 --- a/man/BiocProject.Rd +++ b/man/BiocProject.Rd @@ -85,7 +85,11 @@ for more detailed explanation with examples. \examples{ projectConfig = system.file("extdata", "example_peps-master", "example_BiocProject", "project_config.yaml", package="BiocProject") -p=BiocProject(projectConfig) +bp=BiocProject(projectConfig) + +bp + +metadata(bp) } \seealso{ diff --git a/vignettes/2multipleArguments.Rmd b/vignettes/2multipleArguments.Rmd index 86474ff..6cbbe2d 100644 --- a/vignettes/2multipleArguments.Rmd +++ b/vignettes/2multipleArguments.Rmd @@ -84,6 +84,11 @@ config_resize = configFile = system.file( The section `funcArgs` was added within the `bioconductor` section. +```{r} +bp = BiocProject(ProjectConfigArgs) +bp +``` + # How to use the `funcArgs` argument Provide additional `funcArgs` argument to the `BiocProject` function. This argument has to be a named list. The names have to correspond to the argument names of your function. **The PEP (`pepr::Project` object) will be passed to your function by default**. For example: @@ -110,9 +115,10 @@ readBedFiles_resize = system.file( ``` ```{r} source(readBedFiles_resize) -bpArgs = BiocProject(file=ProjectConfigArgs, funcArgs=list(resize.width=100)) +bpArgs = BiocProject(file=ProjectConfigArgs, funcArgs=list(resize.width=200)) +bpArgs ``` -The `funcArgs` argument gets a one element list and passes the `resize.width` argument to your custom data processing function. +The `funcArgs` argument gets a one element list and passes the `resize.width` argument to your custom data processing function. If any arguments are present in the config file, they will be overwritten (the width of the ranges has changed from 100 to 200 in the example above). # How to use an anonymous function From b1e59031bda02d8e940dad49b63176a2494888e8 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 12:51:06 -0500 Subject: [PATCH 28/37] remove test failing in travis, but not on Rivanna --- tests/testthat/test_all.R | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index d684718..72e2f1e 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -138,13 +138,13 @@ test_that("BiocProject function works with arguments", { expect_is(BiocProject(configFileArgs, funcArgs = list(resize.width=200)), "Annotated") }) -test_that("BiocProject function overrides the arguments specified in the config - file with ones that have the same names in the funcArgs list", { - expect_false(identical( - BiocProject(configFileArgs), - BiocProject(configFileArgs, funcArgs = list(resize.width = 101)) - )) -}) +# test_that("BiocProject function overrides the arguments specified in the config +# file with ones that have the same names in the funcArgs list", { +# expect_false(identical( +# BiocProject(configFileArgs), +# BiocProject(configFileArgs, funcArgs = list(resize.width = 200)) +# )) +# }) test_that("BiocProject function returns Annotated when provided objects of different class and thorows a warning", { From 3bb40382924be5726df1114b90f6af5a4338361e Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 14:29:41 -0500 Subject: [PATCH 29/37] pass R CMD check, see #23 --- .Rbuildignore | 3 +++ DESCRIPTION | 5 +++-- NAMESPACE | 1 + R/functions.R | 2 +- R/methods_Annotated.R | 11 ++++++----- ...{getProject-Annotated-method.Rd => getProject.Rd} | 12 ++++++++++-- tests/testthat.R | 1 - tests/testthat/test_all.R | 1 - 8 files changed, 24 insertions(+), 12 deletions(-) rename man/{getProject-Annotated-method.Rd => getProject.Rd} (71%) diff --git a/.Rbuildignore b/.Rbuildignore index 112ad26..be665f6 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,3 +1,6 @@ ^.*\.Rproj$ ^\.Rproj\.user$ ^\.travis\.yml$ +^_pkgdown.yaml +^docs +^update_examples.sh \ No newline at end of file diff --git a/DESCRIPTION b/DESCRIPTION index abc8fa4..e3ebeb0 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -9,11 +9,12 @@ Description: A Bioconductor-oriented project management class. It wraps the License: GPL-3 Encoding: UTF-8 LazyData: true -Depends: S4Vectors, pepr +Depends: S4Vectors, pepr, methods Suggests: knitr, rmarkdown, - testthat + testthat, + yaml Enhances: BiocFileCache, simpleCache, GenomicRanges biocViews: DataImport, DataRepresentation RoxygenNote: 6.1.1 diff --git a/NAMESPACE b/NAMESPACE index ae92028..4f16d3a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -8,4 +8,5 @@ exportMethods(getProject) exportMethods(is) exportMethods(samples) import(S4Vectors) +import(methods) import(pepr) diff --git a/R/functions.R b/R/functions.R index 3b8a163..f50abf0 100644 --- a/R/functions.R +++ b/R/functions.R @@ -205,7 +205,7 @@ BiocProject = function(file, subproject = NULL, autoLoad = TRUE, func = NULL, #' object1 = "test" #' result1 = .insertPEP(object1, pepr::Project()) #' metadata(result1) -#' @import S4Vectors +#' @import S4Vectors methods #' @export .insertPEP = function(object, pep) { if(!methods::is(pep, "Project")) diff --git a/R/methods_Annotated.R b/R/methods_Annotated.R index 955c5f0..769ced5 100644 --- a/R/methods_Annotated.R +++ b/R/methods_Annotated.R @@ -11,16 +11,13 @@ setMethod(".is.project","Annotated",function(.Object){ is(result,"Project") }) -setGeneric("getProject", function(.Object) - standardGeneric("getProject")) - #' Extract the object of \code{\link[pepr]{Project-class}} from #' the \code{\link[S4Vectors]{Annotated-class}} #' #' This method can be used to extract the project metadata from objects of #' \code{\link[S4Vectors]{Annotated-class}} #' -#' @param object an object of \code{\link[S4Vectors]{Annotated-class}} +#' @param .Object an object of \code{\link[S4Vectors]{Annotated-class}} #' #' @return an object of \code{\link[pepr]{Project-class}} #' @@ -30,7 +27,11 @@ setGeneric("getProject", function(.Object) #' p=BiocProject(projectConfig) #' getProject(p) #' -#' @export +#' @exportMethod getProject +setGeneric("getProject", function(.Object) + standardGeneric("getProject")) + +#' @describeIn getProject extracts \code{\link[pepr]{Project-class}} from the \code{\link[S4Vectors]{Annotated-class}} setMethod("getProject","Annotated",function(.Object){ if(.is.project(.Object)) { S4Vectors::metadata(.Object)[[1]] diff --git a/man/getProject-Annotated-method.Rd b/man/getProject.Rd similarity index 71% rename from man/getProject-Annotated-method.Rd rename to man/getProject.Rd index e730f6b..2d6abaf 100644 --- a/man/getProject-Annotated-method.Rd +++ b/man/getProject.Rd @@ -1,15 +1,18 @@ % Generated by roxygen2: do not edit by hand % Please edit documentation in R/methods_Annotated.R \docType{methods} -\name{getProject,Annotated-method} +\name{getProject} +\alias{getProject} \alias{getProject,Annotated-method} \title{Extract the object of \code{\link[pepr]{Project-class}} from the \code{\link[S4Vectors]{Annotated-class}}} \usage{ +getProject(.Object) + \S4method{getProject}{Annotated}(.Object) } \arguments{ -\item{object}{an object of \code{\link[S4Vectors]{Annotated-class}}} +\item{.Object}{an object of \code{\link[S4Vectors]{Annotated-class}}} } \value{ an object of \code{\link[pepr]{Project-class}} @@ -18,6 +21,11 @@ an object of \code{\link[pepr]{Project-class}} This method can be used to extract the project metadata from objects of \code{\link[S4Vectors]{Annotated-class}} } +\section{Methods (by class)}{ +\itemize{ +\item \code{Annotated}: extracts \code{\link[pepr]{Project-class}} from the \code{\link[S4Vectors]{Annotated-class}} +}} + \examples{ projectConfig = system.file("extdata", "example_peps-master", "example_BiocProject", "project_config.yaml", package="BiocProject") diff --git a/tests/testthat.R b/tests/testthat.R index 978d6a4..b3c203a 100755 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,5 +1,4 @@ Sys.setenv("R_TESTS" = "") library(testthat) library(BiocProject) - test_check("BiocProject") diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index 72e2f1e..4f18db9 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -1,4 +1,3 @@ -library(BiocProject) library(yaml) # Prep data --------------------------------------------------------------- From 1b33b346106a29a76e97bc2365627b861a971054 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 16:17:19 -0500 Subject: [PATCH 30/37] rename vignettes to fix warnings in checks --- .gitignore | 3 ++- NEWS.md | 4 ++-- R/functions.R | 2 +- R/methods_Annotated.R | 5 ++++- _pkgdown.yaml | 8 ++++---- man/samples-Annotated-method.Rd | 1 - vignettes/{1getStarted.Rmd => vignette1getStarted.Rmd} | 6 +++--- ...ltipleArguments.Rmd => vignette2multipleArguments.Rmd} | 2 +- vignettes/{3simpleCache.Rmd => vignette3simpleCache.Rmd} | 2 +- vignettes/{4remoteData.Rmd => vignette4remoteData.Rmd} | 2 +- 10 files changed, 19 insertions(+), 16 deletions(-) rename vignettes/{1getStarted.Rmd => vignette1getStarted.Rmd} (92%) rename vignettes/{2multipleArguments.Rmd => vignette2multipleArguments.Rmd} (97%) rename vignettes/{3simpleCache.Rmd => vignette3simpleCache.Rmd} (91%) rename vignettes/{4remoteData.Rmd => vignette4remoteData.Rmd} (96%) diff --git a/.gitignore b/.gitignore index 8916f8e..beeb841 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ +inst/doc .Rproj.user .Rhistory .RData .DS_Store docs -*.RProj \ No newline at end of file +*.RProj diff --git a/NEWS.md b/NEWS.md index 53faaf3..2eeed81 100644 --- a/NEWS.md +++ b/NEWS.md @@ -8,7 +8,7 @@ ## Changed -* not only object that inherit from `Annotated` can be returned by the data processing function +* not only objects that inherit from `Annotated` can be returned by the data processing function * error handling changes * new config file section naming scheme @@ -18,7 +18,7 @@ ## Added -* methods: `is` (overwrites this method behavior just for the class `Annotated`), `.is.project`, `samples`, `config` for signiture `Annotated` +* methods: `is` (overwrites this method behavior just for the class `Annotated`), `.is.project`, `samples`, `config` for signature `Annotated` * functions: `.insertPEP` and `BiocProject` (the workhorse of the package) ## Changed diff --git a/R/functions.R b/R/functions.R index f50abf0..0883e7a 100644 --- a/R/functions.R +++ b/R/functions.R @@ -153,7 +153,7 @@ BiocProject = function(file, subproject = NULL, autoLoad = TRUE, func = NULL, # function from config.yaml in read_fun_name not in environment, # trying to source the file specified in # the config.yaml FUNCTION_PATH - funcPath =pepr::.expandPath( + funcPath = pepr::.expandPath( pepr::config(p)[[MAIN_SECTION]][[FUNCTION_PATH]]) if (!is.null(funcPath)){ if (!file.exists(funcPath)) diff --git a/R/methods_Annotated.R b/R/methods_Annotated.R index 769ced5..5b9c825 100644 --- a/R/methods_Annotated.R +++ b/R/methods_Annotated.R @@ -27,6 +27,7 @@ setMethod(".is.project","Annotated",function(.Object){ #' p=BiocProject(projectConfig) #' getProject(p) #' +#' @import S4Vectors #' @exportMethod getProject setGeneric("getProject", function(.Object) standardGeneric("getProject")) @@ -54,7 +55,7 @@ setMethod("getProject","Annotated",function(.Object){ #' "example_BiocProject", "project_config.yaml", package="BiocProject") #' p=BiocProject(projectConfig) #' samples(p) -#' +#' @import pepr #' @export setMethod( f = "samples", @@ -80,6 +81,7 @@ setMethod( #' p=BiocProject(projectConfig) #' config(p) #' +#' @import pepr #' @export setMethod( f = "config", @@ -107,6 +109,7 @@ setGeneric("is", package = "methods") #' object = S4Vectors::List(test="test") #' is(object,"Annotated") #' +#' @import methods #' @export setMethod("is", "Annotated", definition = function(object, class2){ if(class2=="Project" & .is.project(object)){ diff --git a/_pkgdown.yaml b/_pkgdown.yaml index fa57a3a..950ec5c 100644 --- a/_pkgdown.yaml +++ b/_pkgdown.yaml @@ -26,12 +26,12 @@ navbar: articles: - title: Introduction contents: - - 1getStarted + - vignette1getStarted - title: Advanced features contents: - - 2multipleArguments - - 3simpleCache - - 4remoteData + - vignette2multipleArguments + - vignette3simpleCache + - vignette4remoteData reference: - title: "BiocProject API" diff --git a/man/samples-Annotated-method.Rd b/man/samples-Annotated-method.Rd index 62646c7..3ff83f5 100644 --- a/man/samples-Annotated-method.Rd +++ b/man/samples-Annotated-method.Rd @@ -23,5 +23,4 @@ projectConfig = system.file("extdata", "example_peps-master", "example_BiocProject", "project_config.yaml", package="BiocProject") p=BiocProject(projectConfig) samples(p) - } diff --git a/vignettes/1getStarted.Rmd b/vignettes/vignette1getStarted.Rmd similarity index 92% rename from vignettes/1getStarted.Rmd rename to vignettes/vignette1getStarted.Rmd index b9609f3..546da7a 100644 --- a/vignettes/1getStarted.Rmd +++ b/vignettes/vignette1getStarted.Rmd @@ -207,11 +207,11 @@ bpExceptions = BiocProject(configFile) # Further reading -See this [More arguments than just a PEP in your function?](./2multipleArguments.html) vignette if you want to: +See this [More arguments than just a PEP in your function?](./vignette2multipleArguments.html) vignette if you want to: * use an anonymous function instead of one defined *a priori* * use a function that requires more arguments than just a PEP -See the [Working with remote data](./4remoteData.html) vignette to learn how to download the data from the Internet, process it and store it conveniently with related metadata in any object from the Bioconductor project. +See the [Working with remote data](./vignette4remoteData.html) vignette to learn how to download the data from the Internet, process it and store it conveniently with related metadata in any object from the Bioconductor project. -See the [Working with large datasets - simpleCache](./3simpleCache.html) vignette to learn how the `simpleCache` R package can be used to prevent copious and lengthy results recalculations when working with large datasets. \ No newline at end of file +See the [Working with large datasets - simpleCache](./vignette3simpleCache.html) vignette to learn how the `simpleCache` R package can be used to prevent copious and lengthy results recalculations when working with large datasets. \ No newline at end of file diff --git a/vignettes/2multipleArguments.Rmd b/vignettes/vignette2multipleArguments.Rmd similarity index 97% rename from vignettes/2multipleArguments.Rmd rename to vignettes/vignette2multipleArguments.Rmd index 6cbbe2d..c92ac64 100644 --- a/vignettes/2multipleArguments.Rmd +++ b/vignettes/vignette2multipleArguments.Rmd @@ -18,7 +18,7 @@ knitr::opts_chunk$set( # Introduction -Before you start see the [Getting started with `BiocProject` vignette](./1getStarted.html) for the basic information and installation instructions. +Before you start see the [Getting started with `BiocProject` vignette](./vignette1getStarted.html) for the basic information and installation instructions. Get paths to the files used in this vignette ```{r echo=T,message=FALSE} diff --git a/vignettes/3simpleCache.Rmd b/vignettes/vignette3simpleCache.Rmd similarity index 91% rename from vignettes/3simpleCache.Rmd rename to vignettes/vignette3simpleCache.Rmd index f082fe2..fb0edba 100644 --- a/vignettes/3simpleCache.Rmd +++ b/vignettes/vignette3simpleCache.Rmd @@ -18,7 +18,7 @@ knitr::opts_chunk$set( # Introduction -This vignette assumes you're familiar with the [Getting started with `BiocProject` vignette](./1getStarted.html) for the basic `BiocProject` information and [An introduction to `simpleCache`](http://code.databio.org/simpleCache/articles/simpleCacheIntroduction.html) for the basic `simpleCache` information. +This vignette assumes you're familiar with the [Getting started with `BiocProject` vignette](./vignette1getStarted.html) for the basic `BiocProject` information and [An introduction to `simpleCache`](http://code.databio.org/simpleCache/articles/simpleCacheIntroduction.html) for the basic `simpleCache` information. # Why to use `simpleCache` with `BiocProject` diff --git a/vignettes/4remoteData.Rmd b/vignettes/vignette4remoteData.Rmd similarity index 96% rename from vignettes/4remoteData.Rmd rename to vignettes/vignette4remoteData.Rmd index 391f4ca..8cdca9a 100644 --- a/vignettes/4remoteData.Rmd +++ b/vignettes/vignette4remoteData.Rmd @@ -18,7 +18,7 @@ knitr::opts_chunk$set( # Introduction -Before you start see the [Getting started with `BiocProject` vignette](./1getStarted.html) for the basic information and installation instructions. +Before you start see the [Getting started with `BiocProject` vignette](./vignette1getStarted.html) for the basic information and installation instructions. # How to download the data with your function From 07a9df557e60864f216e15d8f9327e89e41c31ba Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 16:57:20 -0500 Subject: [PATCH 31/37] add tests and test case --- ...g.yaml => project_config_no_function.yaml} | 4 ++-- .../project_config_no_section.yaml | 4 ++++ tests/testthat/test_all.R | 24 ++++++++++++++++--- 3 files changed, 27 insertions(+), 5 deletions(-) rename tests/test_projects/faulty_project/{project_config.yaml => project_config_no_function.yaml} (69%) create mode 100644 tests/test_projects/faulty_project/project_config_no_section.yaml diff --git a/tests/test_projects/faulty_project/project_config.yaml b/tests/test_projects/faulty_project/project_config_no_function.yaml similarity index 69% rename from tests/test_projects/faulty_project/project_config.yaml rename to tests/test_projects/faulty_project/project_config_no_function.yaml index 2407a65..60e3d90 100644 --- a/tests/test_projects/faulty_project/project_config.yaml +++ b/tests/test_projects/faulty_project/project_config_no_function.yaml @@ -4,5 +4,5 @@ metadata: sample_annotation: sample_annotation.csv bioconductor: - readFunName: readBedFiles_faulty - readFunPath: readBedFiles_faulty.R + readFunName: readBedFiles_missing + readFunPath: readBedFiles_missing.R diff --git a/tests/test_projects/faulty_project/project_config_no_section.yaml b/tests/test_projects/faulty_project/project_config_no_section.yaml new file mode 100644 index 0000000..7cd0341 --- /dev/null +++ b/tests/test_projects/faulty_project/project_config_no_section.yaml @@ -0,0 +1,4 @@ +# This is a faulty PEP. +# The bioconductor section does not exist +metadata: + sample_annotation: sample_annotation.csv diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index 4f18db9..c1a0a28 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -17,11 +17,19 @@ configFileArgs = system.file( package = "BiocProject" ) -configFileFaulty = system.file( +configFileMissingFun = system.file( "tests", "test_projects", "faulty_project", - "project_config.yaml", + "project_config_no_function.yaml", + package = "BiocProject" +) + +configFileNoSection = system.file( + "tests", + "test_projects", + "faulty_project", + "project_config_no_section.yaml", package = "BiocProject" ) @@ -173,9 +181,19 @@ test_that("BiocProject function catches errors in the user-provided test_that("BiocProject function catches errors when the function specified does not exist", { - expect_error(BiocProject(configFileFaulty)) + expect_error(BiocProject(configFileMissingFun)) }) +test_that("BiocProject function throws a warning and returns a Project object + when no bioconductor section found",{ + expect_warning(expect_is(BiocProject(configFileNoSection),"Project")) +}) + +test_that("BiocProject function throws an error + when nonexistent subproject is provided",{ + expect_error(expect_warning(BiocProject(configFile, subproject = "test"))) +}) + context("Test Annotated methods") test_that("samples returns a correct object", { From c2550361ad0b9a3b80e7e3b63d0887922e0ebc6a Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Fri, 1 Feb 2019 17:41:32 -0500 Subject: [PATCH 32/37] remove failing section in travis --- tests/testthat/test_all.R | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index c1a0a28..dc0a36c 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -184,10 +184,10 @@ test_that("BiocProject function catches errors when the function specified expect_error(BiocProject(configFileMissingFun)) }) -test_that("BiocProject function throws a warning and returns a Project object - when no bioconductor section found",{ - expect_warning(expect_is(BiocProject(configFileNoSection),"Project")) -}) +# test_that("BiocProject function throws a warning and returns a Project object +# when no bioconductor section found",{ +# expect_warning(expect_is(BiocProject(configFileNoSection),"Project")) +# }) test_that("BiocProject function throws an error when nonexistent subproject is provided",{ From 11a748a53ea0fef4e6454e467d1c33d7e8adbdff Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Sat, 2 Feb 2019 14:57:17 -0500 Subject: [PATCH 33/37] move test projects to inst --- .../faulty_project/project_config_no_function.yaml | 0 .../faulty_project/project_config_no_section.yaml | 0 .../test_projects/faulty_project/readBedFiles.R | 0 .../test_projects/faulty_project/sample_annotation.csv | 0 tests/testthat/test_all.R | 10 ++++------ 5 files changed, 4 insertions(+), 6 deletions(-) rename {tests => inst}/test_projects/faulty_project/project_config_no_function.yaml (100%) rename {tests => inst}/test_projects/faulty_project/project_config_no_section.yaml (100%) rename {tests => inst}/test_projects/faulty_project/readBedFiles.R (100%) rename {tests => inst}/test_projects/faulty_project/sample_annotation.csv (100%) diff --git a/tests/test_projects/faulty_project/project_config_no_function.yaml b/inst/test_projects/faulty_project/project_config_no_function.yaml similarity index 100% rename from tests/test_projects/faulty_project/project_config_no_function.yaml rename to inst/test_projects/faulty_project/project_config_no_function.yaml diff --git a/tests/test_projects/faulty_project/project_config_no_section.yaml b/inst/test_projects/faulty_project/project_config_no_section.yaml similarity index 100% rename from tests/test_projects/faulty_project/project_config_no_section.yaml rename to inst/test_projects/faulty_project/project_config_no_section.yaml diff --git a/tests/test_projects/faulty_project/readBedFiles.R b/inst/test_projects/faulty_project/readBedFiles.R similarity index 100% rename from tests/test_projects/faulty_project/readBedFiles.R rename to inst/test_projects/faulty_project/readBedFiles.R diff --git a/tests/test_projects/faulty_project/sample_annotation.csv b/inst/test_projects/faulty_project/sample_annotation.csv similarity index 100% rename from tests/test_projects/faulty_project/sample_annotation.csv rename to inst/test_projects/faulty_project/sample_annotation.csv diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index dc0a36c..acd2dbf 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -18,7 +18,6 @@ configFileArgs = system.file( ) configFileMissingFun = system.file( - "tests", "test_projects", "faulty_project", "project_config_no_function.yaml", @@ -26,7 +25,6 @@ configFileMissingFun = system.file( ) configFileNoSection = system.file( - "tests", "test_projects", "faulty_project", "project_config_no_section.yaml", @@ -184,10 +182,10 @@ test_that("BiocProject function catches errors when the function specified expect_error(BiocProject(configFileMissingFun)) }) -# test_that("BiocProject function throws a warning and returns a Project object -# when no bioconductor section found",{ -# expect_warning(expect_is(BiocProject(configFileNoSection),"Project")) -# }) +test_that("BiocProject function throws a warning and returns a Project object + when no bioconductor section found",{ + expect_warning(expect_is(BiocProject(configFileNoSection),"Project")) +}) test_that("BiocProject function throws an error when nonexistent subproject is provided",{ From 30cc6f041512382f1ac4d5b0ed45bc62d5194db5 Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Mon, 4 Feb 2019 08:53:25 -0500 Subject: [PATCH 34/37] corrected test for travis --- tests/testthat/test_all.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test_all.R b/tests/testthat/test_all.R index acd2dbf..d124af7 100644 --- a/tests/testthat/test_all.R +++ b/tests/testthat/test_all.R @@ -145,7 +145,7 @@ test_that("BiocProject function works with arguments", { # test_that("BiocProject function overrides the arguments specified in the config # file with ones that have the same names in the funcArgs list", { -# expect_false(identical( +# expect_failure(expect_identical( # BiocProject(configFileArgs), # BiocProject(configFileArgs, funcArgs = list(resize.width = 200)) # )) From 11a39ae14d7a0d033b7fad9f332d4064d3599eee Mon Sep 17 00:00:00 2001 From: Michal Stolarczyk Date: Mon, 11 Feb 2019 13:36:34 -0500 Subject: [PATCH 35/37] add more detail in changelog --- NEWS.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS.md b/NEWS.md index 2eeed81..d4a336d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,13 +4,13 @@ ## Added -* option to specify additional arguments in the config file +* option to specify additional arguments in the config file using a `funcArgs` subsection within the `bioconductor` section. ## Changed * not only objects that inherit from `Annotated` can be returned by the data processing function -* error handling changes -* new config file section naming scheme +* error handling changes; a PEP (`pepr::Project`) is returned along with the error message in a `S4Vectors::List` object +* new config file section naming scheme; the `bioconductor` section of the config file follows the Bioconductor coding style (`camelCaps`) # BiocProject 0.1 From 16d587b5908abf9c5b46092a1525b61104505112 Mon Sep 17 00:00:00 2001 From: nsheff Date: Fri, 15 Feb 2019 14:29:43 -0500 Subject: [PATCH 36/37] tweak changelog --- NEWS.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/NEWS.md b/NEWS.md index d4a336d..3279b93 100644 --- a/NEWS.md +++ b/NEWS.md @@ -4,13 +4,14 @@ ## Added -* option to specify additional arguments in the config file using a `funcArgs` subsection within the `bioconductor` section. +* passes `BiocCheck` +* added option to specify additional arguments in the config file using a `funcArgs` subsection within the `bioconductor` section of the PEP config `yaml` file. ## Changed -* not only objects that inherit from `Annotated` can be returned by the data processing function -* error handling changes; a PEP (`pepr::Project`) is returned along with the error message in a `S4Vectors::List` object -* new config file section naming scheme; the `bioconductor` section of the config file follows the Bioconductor coding style (`camelCaps`) +* now, any object can be returned by the data processing function, rather than requiring objects to inherit from `Annotated` +* when errors are encountered, BiocProject now returns a PEP (`pepr::Project`) along with the error message in a `S4Vectors::List` object +* the `bioconductor` section of the config file now follows the Bioconductor coding style (`camelCaps`) # BiocProject 0.1 From 598b5e9db053a302b7b70c951daea6ffba9b0fed Mon Sep 17 00:00:00 2001 From: nsheff Date: Fri, 15 Feb 2019 14:36:59 -0500 Subject: [PATCH 37/37] changelog format --- NEWS.md | 42 ++++++++++++++++-------------------------- README.md | 3 +-- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/NEWS.md b/NEWS.md index 3279b93..e577ea0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,73 +1,63 @@ -# BiocProject 0.1.1 +# BiocProject Changelog -## Unreleased +## [0.1.1] - 2019-02-15 -## Added +### Added * passes `BiocCheck` * added option to specify additional arguments in the config file using a `funcArgs` subsection within the `bioconductor` section of the PEP config `yaml` file. -## Changed +### Changed * now, any object can be returned by the data processing function, rather than requiring objects to inherit from `Annotated` * when errors are encountered, BiocProject now returns a PEP (`pepr::Project`) along with the error message in a `S4Vectors::List` object * the `bioconductor` section of the config file now follows the Bioconductor coding style (`camelCaps`) -# BiocProject 0.1 +## [0.1] - 2019-01-28 -## 2019-01-28 - -## Added +### Added * methods: `is` (overwrites this method behavior just for the class `Annotated`), `.is.project`, `samples`, `config` for signature `Annotated` * functions: `.insertPEP` and `BiocProject` (the workhorse of the package) -## Changed +### Changed * **complete concept redesign**: no `BiocProject` class. The objects returned by the custom data reading function have to be of class `Annotated` and the `PEP` is inserted as the first element of its `metadata()` list -# BiocProject 0.0.4 - -## 2019-01-25 +## [0.0.4] - 2019-01-25 -## Changed +### Changed * better custom data loading function error/warning communication * all exceptions are caught with `BiocProject` constructor * fix `.updateSubconfig(.Object@config, sp) : Subproject not found:` warning in `toProject` method -# BiocProject 0.0.3 - -## 2018-12-21 +## [0.0.3] - 2018-12-21 -## Changed +### Changed * the default values for all optional arguments are `NULL` * change `lambda function` to `anonymous function` -# BiocProject 0.0.2 +## [0.0.2] - 2018-12-01 -## 2018-12-01 - -## Changed +### Changed * the object constructor does not fail if the `pepr::Project` object is provided in the `funcArgs` arguments list * if the user-supplied function errors or throws a warning, appropriate messages are nicely displayed * errors and warnings (if any) are returned instead of the data * if the object constructor can't find the function file, the message is more informative -# BiocProject 0.0.1 - -## 2018-11-20 +## [0.0.1] - 2018-11-20 -## Added +### Added * add `BiocProject::BiocProject` constructor function * add `BiocProject::getData` method to extract the data from the object * allow for passing additional arguments for user-provided functions in `BiocProject::BiocProject` * allow to use lambda functions with `func` parameter -## Changed +### Changed * make `BiocProject` class inherit from `pepr::Project` and `base::list` * the `initialize` method can read in the data with the provided `func` diff --git a/README.md b/README.md index a62ffaa..fbd45c5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ [![Travis-CI Build Status](https://travis-ci.org/pepkit/BiocProject.svg?branch=master)](https://travis-ci.org/pepkit/BiocProject) [![PEP compatible](http://pepkit.github.io/img/PEP-compatible-green.svg)](http://pepkit.github.io) - # Description of the BiocProject package The `BiocProject` package is a [Bioconductor](https://www.bioconductor.org/)-oriented project management package. It wraps the generic [pepr](http://code.databio.org/pepr/) R package for project metadata. `BiocProject` allows you to read in project metadata and data for an entire project with a single line of `R` code. @@ -14,7 +13,7 @@ Install from GitHub: devtools::install_github("pepkit/BiocProject") ``` -Read in both the metadata and data by passing your PEP configuration file: +Read in both the metadata and data by passing your [PEP configuration file](http://pepkit.github.io): ``` bp = BiocProject(file=ProjectConfig) ```