I want to create a package containing a RcppArmadillo function:
library(Rcpp)
library(RcppArmadillo)
sourceCpp("calculSignSim.cpp")
RcppArmadillo.package.skeleton(name = "calculSignSimCPP",list = "calculSignSim")
The function created by sourceCpp works fine.
However, this latter line gives me the following error:
Calling package.skeleton to create basic package.
Creating directories ...
Creating DESCRIPTION ...
Creating NAMESPACE ...
Creating Read-and-delete-me ...
Saving functions and data ...
Making help files ...
Done.
Further steps are described in './calculSignSimCPP/Read-and-delete-me'.
Adding RcppArmadillo settings
>> added Imports: Rcpp
>> added LinkingTo: Rcpp, RcppArmadillo
>> added useDynLib and importFrom directives to NAMESPACE
>> added Makevars file with Rcpp settings
>> added Makevars.win file with RcppArmadillo settings
>> added example src file using armadillo classes
>> added example Rd file for using armadillo classes
Error in Rcpp::compileAttributes(root) :
Evaluation error: D:/R packages/calculSignSimCPP/R/calculSignSim.R:3:21: unexpected '<'
2: function (lemmesV, ulemmesV, optionLien)
3: .Primitive(".Call")(<
^.
In addition: Warning message:
In dump(item, file = file.path(code_dir, sprintf("%s.R", list0[item])), :
deparse may be incomplete
I really don't understand why it doesn't work.
When I do not explicitely indicate which function I want to include, i.e. when I do
RcppArmadillo.package.skeleton(name = "calculSignSimCPP")
Everything works fine, but the created package does not contain my function...
Any idea ?
Related
Assume an R package (myPackage) that imports the R package RCircos via the DESCRIPTION file and the NAMESPACE file.
$ cat DESCRIPTION
Package: myPackage
Imports: RCircos (>= 1.2.0)
...
$ cat NAMESPACE
import(RCircos)
...
One of the perks of RCircos is that it defines a custom environment (called RCircos.Env) and reads/writes variables to this environment from various of its functions. For example, function RCircos.Initialize.Plot.Parameters reads and writes to this environment.
...
RCircosEnvironment <- NULL;
RCircosEnvironment <- get("RCircos.Env", envir = globalenv());
RCircosEnvironment[["RCircos.PlotPar"]] <- plot.param;
(This peculiar behavior has also been recognized by other R packages; see, for example, lines 247-249 of this package).
Unfortunately, it seems that the environment RCircos.Env is not recognized out of the box in myPackage when I simply import RCircos via the DESCRIPTION file and the NAMESPACE file.
So what can be done?
There seem to be two options of making the environment RCircos.Env accessible to functions like RCircos.Initialize.Plot.Parameters. However, both of these options cause the CRAN check (R CMD check myPackage --as-cran) to issue WARNINGs or NOTEs during the mandatory evaluation of myPackage prior to the submission to CRAN, thus preventing its acceptance on CRAN.
Option 1: I include the following line directly prior to the function demanding the object:
# my code here #
assign("RCircos.Env", RCircos::RCircos.Env, .GlobalEnv)
RCircos.Set.Core.Components(...)
# my code here #
However, the CRAN check highlights this line with a NOTE, thus preventing the acceptance of myPackage on CRAN.
* checking R code for possible problems ... NOTE
Found the following assignments to the global environment:
File ‘PACViR/R/visualizeWithRCircos.R’:
assign("RCircos.Env", RCircos::RCircos.Env, .GlobalEnv)
Option 2: I load the entire RCircos library prior to the function demanding the object:
# my code here #
library(RCircos)
RCircos.Set.Core.Components(...)
# my code here #
However, the CRAN check highlights this option with a WARNING, again preventing the acceptance of myPackage on CRAN.
* checking dependencies in R code ... WARNING
'library' or 'require' call not declared from: ‘RCircos’
'library' or 'require' call to ‘RCircos’ in package code.
Please use :: or requireNamespace() instead.
See section 'Suggested packages' in the 'Writing R Extensions' manual.
Surely, there must be an easy and CRAN-compatible way of making the environment RCircos.Env accessible to functions such as RCircos.Set.Core.Components within myPackage! Can someone name and explain such a way?
Apparently the normal re-export does not work with environments as it does with functions. But this does work:
RCircos.Env <- RCircos::RCircos.Env
#' test
#'
#' #param ... data
#'
#' #export
test_fun <- function(...) {
RCircos::RCircos.Set.Core.Components(...)
}
With DESCRIPTION:
Package: test
Type: Package
Title: test
Description: This is a description.
Version: 0.1.0
Authors#R: person("Wouter", "van der Bijl",
email = "redacted#redacted.com",
role = c("aut", "cre"))
Maintainer: Wouter van der Bijl <redacted#redacted.com>
License: GPL-3
Encoding: UTF-8
LazyData: true
Imports: RCircos
RoxygenNote: 6.1.1
And this NAMESPACE:
# Generated by roxygen2: do not edit by hand
export(test_fun)
Test with:
library(test)
data(UCSC.HG19.Human.CytoBandIdeogram, package = 'RCircos')
test_fun(UCSC.HG19.Human.CytoBandIdeogram)
Basically, when RCircos runs get("RCircos.Env", envir = globalenv()), it will traverse up the search path until it finds the RCircos.Env from your package instead.
When running R CMD Check I get 0 errors, 0 warnings, 0 notes.
Note that this strategy that RCircos uses, with an environment that gets looked up by using get(.., envir = globalenv()) is really unorthodox and generally not a good idea. R functions should generally not have side-effects, such as editing unseen environments. Setting default values etc. is typically done using options(). The whole package is probably not something you'd want to emulate, but at least now you can use it as a dependency.
I have an R package that uses Rcpp for some internal functions. These functions are not exported for the user to access directly (see minimally reproducible example in the rcpptest repository).
I am now attempting to add Stan code to the src/ directory to be compiled when the package is installed (reproducible example in the rcppstan repository). However, when I modify the package to work with Stan, I get the following error in R CMD CHECK:
#> ❯ checking R code for possible problems ... NOTE
#> meanC: no visible binding for global variable ‘_rcppstan_meanC’
#> Undefined global functions or variables:
#> _rcppstan_meanC
And indeed, when I try to call the R function that uses the meanC function, I get an error saying Error in meanC(x) : object '_rcppstan_meanC' not found.
From what I can tell, here is what is changing when I modify the package to work with rstan, and thus the likely cause.
When only using Rcpp, the following is in the src/RcppExports.cpp:
static const R_CallMethodDef CallEntries[] = {
{"_rcpptest_timesTwo", (DL_FUNC) &_rcpptest_timesTwo, 1},
{NULL, NULL, 0}
};
RcppExport void R_init_rcpptest(DllInfo *dll) {
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, FALSE);
}
When Stan is incorporated, that code is no longer generated in the src/RcppExports.cpp file. Instead, it appears that this is being handles by the src/init.cpp file created by the rstantools package. The relevant chunk from that file is here:
static const R_CallMethodDef CallEntries[] = {
{NULL, NULL, 0}
};
void attribute_visible R_init_rcppstan(DllInfo *dll) {
// next line is necessary to avoid a NOTE from R CMD check
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
R_useDynamicSymbols(dll, TRUE); // necessary for .onLoad() to work
}
Why does the code in src/init.cpp make the Rcpp functions undefined? Conversely, is there a way to edit src/init.cpp so that the Stan models are able to compile and be accessed correctly, while still allowing the Rcpp functions to be defined?
The init.cpp takes of registering methods and Makevars inhibits compilation of the cpp files. With the following changes in Makevars (and Makevars.win) I got it to compile:
diff --git a/src/Makevars b/src/Makevars
index 7aedc5b..3ea312e 100644
--- a/src/Makevars
+++ b/src/Makevars
## -1,8 +1,9 ##
STANHEADERS_SRC = `"$(R_HOME)/bin$(R_ARCH_BIN)/Rscript" --vanilla -e "cat(system.file('include', 'src', package = 'StanHeaders'))"`
PKG_CPPFLAGS = -I"../inst/include" -I"$(STANHEADERS_SRC)" -DBOOST_RESULT_OF_USE_TR1 -DBOOST_NO_DECLTYPE -DBOOST_DISABLE_ASSERTS -DEIGEN_NO_DEBUG -DBOOST_MATH_OVERFLOW_ERROR_POLICY=errno_on_error
-SOURCES = $(wildcard stan_files/*.stan)
-OBJECTS = $(SOURCES:.stan=.o) init.o
+CPP_SOURCES = $(wildcard *.cpp)
+STAN_SOURCES = $(wildcard stan_files/*.stan)
+OBJECTS = $(STAN_SOURCES:.stan=.o) $(CPP_SOURCES:.cpp=.o)
all: $(SHLIB)
#if test -e "/usr/bin/install_name_tool" && test -e "/usr/local/clang4/lib/libc++.1.dylib" && test -e "/usr/lib/libc++.1.dylib"; then /usr/bin/install_name_tool -change /usr/local/clang4/lib/libc++.1.dylib /usr/lib/libc++.1.dylib $(SHLIB); fi
After calling Rcpp::compileAttributes() the method registration was again present in RcppExports.cpp. When I tried R CMD INSTALL, I got an error from .onLoad(), c.f. https://github.com/stan-dev/rstanarm/issues/190. Using the workaround from there, i.e. R CMD INSTALL --preclean solved the issue first, but was not reliable. What solved the issue for me was to change
R_useDynamicSymbols(dll, FALSE);
into
R_useDynamicSymbols(dll, TRUE);
in RcppExports.cpp. That is of course problematic, since that file might be overwritten, in particular when RStudio/devtools is used. A rather hacky solution would be to add
RcppExports.o: patch
patch:
sed -i 's/R_useDynamicSymbols(dll, FALSE)/R_useDynamicSymbols(dll, TRUE)/' RcppExports.cpp
.phony: all clean patch
in the Makevars(.win). But in the end the problem seems to be that C++ code for Rcpp modules is generated during package installation in a subdirectory of src. Therefore Rcpp::compileAttributes() cannot include the corresponding methofs in the list of registered methods. I do not see a good solution for that.
Now the package builds, checks and installs with two NOTEs:
N checking installed package size
installed size is 7.8Mb
sub-directories of 1Mb or more:
libs 7.7Mb
N checking for GNU extensions in Makefiles
GNU make is a SystemRequirements.
I created a package for R to learn how to develop these things and I got a error that I can't resolve. I saw this error was nor uncommon but I could not find a solution.
This is the code of my package (pretty simple):
absconc<-function(x,a,b,...)
{
a<-as.numeric(a)
b<-as.numeric(b)
absconcCalc<- function(x,a,b,...)
{
conc<- (x*a)+b
}
conc<-absconcCalc(x,a,b,...)
print.absconc<- function(x,a,b,...)
{
cat("Slope:")
cat(a,"\n")
cat("Intercept:")
cat(b,"\n")
cat("Concentration:")
cat(conc)
}
print.absconc(x,a,b)
}
I created the package using package.skeleton and it worked like a charm, even the building of the package using R CMD build absconc worked.
The problem was when I trying to use the package it gave me Error: could not find function "absconc".
I though it was a problem coming from NAMESPACE and the export so I tried exporting the functions using export(absconc). When I tried building that I got an error saying:
Error in namespaceExport(ns, exports) :
undefined exports: absconc, absconcCalc, print.absconc
I am now scratching my head to understand why my function are not recognized.
I would appreciate some help on that as this is only my first package.
EDIT: here are my files (A bit messy, sorry)
https://github.com/Frisacher/absconc
You should not edit NAMESPACE by hand. Insert the line #' #export at the top of your R file and run devtools::document() in the console. This will do what is necessary for you.
Now you can execute devtools::load_all() and run your function.
More explicitly:
1) Create a folder named "R" below the root directory and create an R script that contains your function as Martin Morgan suggested in the comments.
2) Add a roxygen comment to your R script to export it:
#' #export
absconc<-function(x,a,b,...)
{
a<-as.numeric(a)
b<-as.numeric(b)
...
}
3) Execute devtools::document() in the console.
> devtools::document()
Updating absconc documentation
Loading absconc
Writing NAMESPACE
4) Load your package with devtools::load_all().
> devtools::load_all()
Loading absconc
5) Run your function.
> absconc(1,2,3)
Slope:2
Intercept:3
Concentration:5
I am creating an R package with the standard directory hierarchy. Inside the R directory, I create a test subdirectory.
In the R directory, I create a uTest.R file containing:
uTest <- function() {
test.suite <- defineTestSuite('test',
dirs = file.path('R/test'))
test.result <- runTestSuite(test.suite)
printTextProtocol(test.result)
}
In the R/test directory, I create a runit.test.R file containing:
test.validDim <- function() {
testFile <- "test/mat.csv"
generateDummyData(testFile,
10,
10)
checkEquals(validDim(testFile), TRUE)
}
I build and install my package using R CMD INSTALL --no-multiarch --with-keep.source RMixtComp in Rstudio. When I try to launch the function uTest(), I get this error message:
1 Test Suite :
test - 1 test function, 1 error, 0 failures
ERROR in test.validDim: Error in func() : could not find function "checkEquals"
However, if I call library(RUnit) prior to calling uTest(), everything works fine. In the import field of the DESCRIPTION file, I added RUnit, and in the NAMESPACE file I added import(RUnit).
How can I call uTest() directly after loading my package, without manually loading RUnit ?
You should not add RUnit to the Depends (or Imports) field in the DESCRIPTION file (despite the comment to the contrary). Doing so implies that the RUnit package is necessary in order to use your package, which is likely not the case. In other words, putting RUnit in Depends or Imports implies RUnit needs to be installed (Imports) and on the users' search path (Depends) in order for them to use your package.
You should add RUnit to the Suggests field in the DESCRIPTION file, then modify your uTest function as below:
uTest <- function() {
stopifnot(requireNamespace("RUnit"))
test.suite <- RUnit::defineTestSuite('test', dirs = file.path('R/test'))
test.result <- RUnit::runTestSuite(test.suite)
RUnit::printTextProtocol(test.result)
}
Doing this allows you to use RUnit for your tests, but does not require users to have RUnit installed (and possibly on their search path) in order to use your package. Obviously, they'll need RUnit if they wish to run your tests.
I'm creating a package using devtools and roxygen2 (in RStudio), however after I've built the package my function no longer works as intended. Yet, if I load the function's .R file and run the function from there in RStudio, it works perfectly. I've created another package using this method before and it worked fine (13 functions all working as intended from my other package), yet I cant seem to get this new one to work.
To start creating the package I start with:
library("devtools")
devtools::install_github("klutometis/roxygen")
library(roxygen2)
setwd("my parent directory")
create("triale")
All is working fine so far. So I put my .R file containing my function in the R folder under the triale folder. The .R file looks like this:
#' Trial Z Function
#'
#' This function counts the values in the columns
#' #param x is the number
#' #keywords x
#' #export
#' #examples
#' trialz()
trialz = function(x) {w_id= c(25,x,25,25,25,1,1,1,1,1);
wcenter= c(rep("BYSTAR-1",10));
df1 <<- data.frame(w_id, wcenter);
countit <<- data.table(df1);
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
Again if I were to just run the code from the .R file, and test the function it works fine. But to continue, next I enter:
setwd("./triale")
document()
The triale documentation is updated, triale is loaded, and the NAMESPACE and trialz.Rd are both written so that trialz.Rd is under the man folder, and NAMESPACE is under the triale folder as intended. Next I install triale:
setwd("..")
install("triale")
Which I know works because I get the following:
Installing triale
"C:/PROGRA~1/R/R-31~1.3/bin/x64/R" --vanilla CMD INSTALL \
"C:/Users/grice/Documents/R/triale" \
--library="C:/Users/grice/Documents/R/win-library/3.1" --install-tests
* installing *source* package 'triale' ...
** R
** preparing package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
*** arch - i386
*** arch - x64
* DONE (triale)
Reloading installed triale
Package is now built, so I do the following:
library("triale")
library("data.table")
Note whenever I load the package data.table I get the following error message:
data.table 1.9.4 For help type: ?data.table
*** NB: by=.EACHI is now explicit. See README to restore previous behaviour.
However it doesnt seem to affect my function. So now its time to test my function from my package:
trialz(25)
This goes through, and I of course get a populated df1, and countit, but for whatever reason view is always empty (as in 0 obs. of 0 variables).
So I test my work using the dummy code below:
>trialy = function(x) {wid= c(25,x,25,25,25,1,1,1,1,1);
wc= c(rep("BYSTAR-1",10));
df2 <<- data.frame(wid, wc);
countitt <<- data.table(df2);
viewer <<- countitt[, .N, by = list(wid, wc)];
View(viewer)}
>trialy(25)
Even though this is the same exact code with just the names changed around it works. Dumbfounded I open trialz.R and copy the function from there and run it as below, and that works:
> trialz = function(x) {w_id= c(25,x,25,25,25,1,1,1,1,1);
wcenter= c(rep("BYSTAR-1",10));
df1 <<- data.frame(w_id, wcenter);
countit <<- data.table(df1);
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
> trialz(25)
Since I've created a package before I know my method is solid (that package had 13 dif. functions, all of which worked). I just don't understand how a function can work fine as written, yet when I package it, the function no longer works.
Again here is where it stops working as intended when using my package:
view <<- countit[, .N, by = list(w_id, wcenter)];
View(view)}
And my end result should look something like this, if my package worked:
wid wc N
1 25 BYSTAR-1 5
2 1 BYSTAR-1 5
Can anyone explain why view is never populated after I package my function? I've tested it as much as I know how, and my results should be reproducible for anyone thats willing to try it for themselves.
Thanks, I appreciate any feedback.
Your problem here is that "<<-" does not create variables in the global environment but rather in the parent environment. (See help("<<-").)
The parent environment of a function is the environment in which it has been defined. In the case where you defined your function directly in your workspace, this parent environment actually is the same as your workspace environment (namely: .GlobalEnv), which is why your variables are assigned values as you expect them to. In the case where your function is packaged, however, the parent environment is the package environment and not the .GlobalEnv! This is why you do not see your variables being assigned values in your workspace.
Refer to the chapter on environments in Hadley's book and How R Searches and Finds Stuff for more details on environments in R.
Note that doing this would not be considered a proper debugging technique, to say the least. In general, you never want to use the "<<-" operator.
For options on debugging R code, see, e.g., this question. I, in particular, like the debugonce function very well. See ?debugonce.
I forgot one important part when editing my description file in that I for got to add
Imports: data.table
Also the NAMESPACE file needed to include the data.table package as an import as well, like so:
import(data.table)
export(Z)
export(AS) .... etc.
Doing this ensures that whenever a function within your package uses a function from another package, that (second) package is called up before your code is executed.