I have an Rcpp module in my package which, as well as exposing the class, exposes a number of methods. Is it possible to document the methods (on the C++ side) using roxygen2? My module looks like this:
RCPP_MODULE(BayesFst) {
using namespace Rcpp;
class_<BayesFst>( "BayesFst")
.default_constructor("Standard constructor")
.method("printData", &BayesFst::printData)
.method("printCounts", &BayesFst::printCounts)
.method("printInitialPvals", &BayesFst::printInitialPvals)
.method("printFstSummary", &BayesFst::printFstSummary)
.method("run", &BayesFst::run)
.method("setData", &BayesFst::setData)
.method("setPriorParameters", &BayesFst::setPriorParameters)
.method("setRunParameters", &BayesFst::setRunParameters)
.method("ldiriTest", &BayesFst::ldiriTest)
.property("interaction", &BayesFst::getInteraction, &BayesFst::setInteraction)
;
}
I would like to document all of these methods ideally. A simple idea is to hide the class behind wrapper functions and then call the methods from within R wrapper functions, but this feels kind of inelegant to me.
I have tried adding the roxygen comment lines to the functions, but because they don't get exported in the same way the documentation doesn't seem to get picked up.
You will not be able to rely on Rcpp to carry the roxygen documentation over the way compileAttributes() would ... as you are not invoking compileAttributes().
Feel free to construct (and test and then contribute :) a new helper function; otherwise I would just use roxygen in an R file and proceed from there.
Edit: I also filed an issue so that we don't forget about it.
Related
I have been developing a package with Rcpp for C++ integration. I used RcppExport to make the functions return SEXP objects.
The issue is travis-ci seems to give warnings telling that there are undocumented code objects. (These are cpp functions). However I do not want users to directly access those functions as well.
How can I resolve this issue? How can I document these functions as well?
You seem to have an elementary misunderstanding here.
If your NAMESPACE contains a wildcard 'export all' a la exportPattern("^[[:alpha:]]+") then each global symbol is exported and per R standards that are clearly documented needs a help entry.
One easy fix is NOT to export everything and just write documentation for what you want exported. We sometimes do that and call the Rcpp function something like foo_impl and then have R functions foo (with documentation) call foo_impl. In that case you would just export foo and all is good.
In short, you are confused about R packages and not so much Rcpp. I would recommend downloading the sources of a few (small) Rcpp packages to get a feel for what they do.
I know what a namespace is from other languages but in R I just cannot find a difference between the environment and namespace. Could anyone explain this since in the tutorials I have read (as The Art of R Programming and others) I just cannot find a distinction?
A namespace is something specific to a package. It is defined as a list of directive that allow you to import functions from other packages to be used locally or to export your functions and classes to be used in R.
So if you have created in your package a function called foo you will add to your namespace something like export(foo) to make your function usable.
If you want to import function from a specific package to use them in yours, you will add import(thePackage)
The environment is simply the space where you associate names to values. You can see it as a context in which you can evaluate functions and expressions.
I am receiving an error [could not find function "str_trim"] when I run check() on an R package I am developing. I have since added two things:
1) In DESCRIPTION
Imports: stringr
2) In NAMESPACE
importFrom(stringr,str_trim)
However, when I then run install() and document(), then the line in NAMESPACE is removed. Then, when I again run check(), I receive the original error.
Why is this line being removed? Should I try a different approach, and if so, what kind of approach? Thank you!
It seems you are doing package development "the Hadley way".
Hadley wants you to use roxygen (i.e. the roxygen2 package but that should be automatic if you use his 'devtools').
Then, the roxygen "magic" is used to auto-write your NAMESPACE file... and so also destroys things you've put there.
You must add #importFrom .... statements to your R/*.R files if you want to use roxygen.
I agree with many things Hadley advocates; the wholesale use of 'roxygen' is not among them however.
I want good, carefully maintained help files with \link{}s, \eqn{}, etc etc
-> I edit my man/*.Rd files and I manually build NAMESPACE (so it ends up looking well organized, I can also add comments there, and I can even use
if(getRVersion() >= "3.2.0") { ...... } in the NAMESPACE file, something that's not easily possible with roxygen.
I am currently developing a plug-in for the R-Commander GUI. In this package I am using a great deal of other packages which I simply attached by using the Depends option in the description file.
I am however now switching them over to the Imports option and am experiencing some problems with it.
Because I want to use some functions not only internally in my own code, but also be able to print and use them in the script window of R Commander, I will also have to export them in the namespace.
Let's take for example the biclust package. This package has the following exports in its namespace:
# First a bunch of functions are exported (Note that the biclust function is not in here!)
export(drawHeatmap,drawHeatmap2,bubbleplot,...,heatmapBC)
# The classes are exported
exportClasses(BiclustMethod,Biclust,BCBimax,BCCC,BCXmotifs,BCSpectral,BCPlaid)
# Methods are exported
exportMethods(biclust,show,summary)
So when I library(biclust) in an R session, it works as intended, meaning I can use the biclust method/function in the R console.
Now this how my namespace file looks like (or at least the part of it relevant to this discussion)
# I select those functions I need and import them.
importFrom(biclust, drawHeatmap,...,biclustbarchart)
# I import all the classes
importClassesFrom(biclust,BiclustMethod,Biclust,BCBimax,BCCC,BCXmotifs,BCSpectral,BCPlaid)
# I import all the methods
importMethodsFrom(biclust,show,summary,biclust)
# I now export all of the previous again so I can use the doItAndPrint functionality in R Commander
export( drawHeatmap,...,biclustbarchart)
exportClasses(BiclustMethod,Biclust,BCBimax,BCCC,BCXmotifs,BCSpectral,BCPlaid)
exportMethods(biclust,show,summary)
However when I load in my own package now, it is not working as intended. While functions such as drawHeatmap are working, the biclust method/function can not be found.(Though I have clearly imported and exported the method.)
Seemingly the only way to get this working, is to put the biclust method also in the normal export() command.
export(biclust,drawHeatmap,...,biclustbarchart)
Could someone clarify what I am doing wrong or what is going on here? Why are the same exports working for the biclust package, but not for my own package?
The only description of your error is that "it is not working as intended", so the following is a little stab in the dark.
It's useful to distinguish between methods and the generics that they are associated with. Biclust makes available both, and they are tightly associated. importFrom(biclust, biclust) imports the generic and associated methods, importMethodsFrom(biclust, biclust) imports the biclust methods defined in the biclust package, and implicitly the generic(s) on which the methods are defined. These are functionally equivalent so far; I think the original intention of importMethodsFrom() was when pkgA defines a generic, pkgB defines methods on the generic, and pkgD wants to use the generic from pkgA and the methods on that generic defined in pkgA and pkgB -- import(pkgA, foo), importMethodsFrom(pkgB, foo).
On the other end, when you say exportMethods(foo), it instructs R to make foo methods defined in your package available for others to use. But there are no foo methods defined in your package, so nothing is exported (maybe this should generate an error, or the methods that you import should be exported again). On the other hand, export(foo) tells R to export the foo generic, which is available for export -- it's the symbol that you'd imported earlier. (You mention that you "put the biclust method also in the normal export()", but actually it is the generic (and any methods associated with it) available for export.) So exporting biclust, rather than methods defined on it, seems to be what you want to do.
Normally, I would say that importing and then re-exporting functions or generics defined in other packages is not the right thing to do -- biclust, not your package, provides and documents the generic, and biclust would probably belong in Depends: -- presumably, many other functions from biclust are typically used in conjunction with the generic. Perhaps your Rcommander GUI is an exception.
Even though Imports: implies additional work (in the NAMESPACE file), it is usually the case that packages belong as Imports: rather than Depends: -- it makes the code in your package much more robust (imported functions are found in the package name space, rather than on the search path that the user can easily modify) and reduces the likelihood that the user experiences name clashes between identical symbols defined in different packages.
I have 2 files, Rfile.R and Cppfile.cpp.
Contents in Cppfile.cpp:
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
int CPPF(int k){return ++k;}
Contents in Rfile.R:
RF<-function(k){return(CPPF(k))}
I want to build an R package based on the 2 files. I use the lastest versions of Rstudio and Roxygen2.
I tried 3 ways to build the package with or without Roxygen2, and had different results:
New Project->New Directory->R package->Type:Package w/Rcpp, add both Rfile.R and Cppfile.cpp as source files. Build & reload, everything works out fine. The functions work as they do.
New Project->New Directory->R package->Type:Package w/Rcpp, add both Rfile.R and Cppfile.cpp as source files. Select "Generate documentations with Roxygen", check all its options. Build & Reload, the functions don't work. Inputting "RF" gives the contents of RF, inputting "CPPF" pops "Object not found".
New Project->New Directory->R package->Type:Package w/Rcpp, add only Cppfile.cpp as source files. Select "Generate documentations with Roxygen", check all its options. Build & Reload, the function works.
Then copy Rfile.R directly into the project folder->R folder. Build & Reload, everything fine, functions work well.
Am I using the Roxygen wrong or Roxygen has bugs? I need it to document. I can stick to the 3rd way which cost me much energy to find, but wired.
Thanks!
One Way To Solve The Issue:
When selecting "Generate documentations with Roxygen", Don't check "NAMESPACE file" option.
You're mixing up two things (which are easy to mix up, unfortunately):
First, the // [[Rcpp::export]] attribute is used for auto-generating wrapper functions in two files, RcppExports.cpp and RcppExports.R. A wrapper R function, CPPF, will be auto-generated by Rcpp::compileAttributes() here, and placed into R/RcppExports.R.
Second, roxygen comments can be used to manage the NAMESPACE, e.g. with the #export tag. Note that this is different from // [[Rcpp::export]]!
The auto-generated function is not automatically exported. The Rcpp.package.skeleton() will generate a NAMESPACE file that automatically exports all functions of a given name; ie, the exportPattern("^[[:alpha:]]+") entry. This is good enough for small packages; but as your package gets more complicated you will want more fine-grained control over your namespace. Or you can just adopt a convention where all internal, non-exported functions begin with a .. Either way, this mechanism is what allows the auto-generated function to be exported to your package namespace.
If you want to use roxygen to manage the NAMESPACE, you need to add roxygen comments to your C++ functions if you want them to be exported in the namespace. So you could modify your function as the following:
#include <Rcpp.h>
using namespace Rcpp;
//' #export
// [[Rcpp::export]]
int CPPF(int k){return ++k;}
Note that you might have to run roxygen2::upgradeRoxygen() to ensure that roxygen2 takes over the NAMESPACE, for new versions of roxygen2.
So if 2. does not work, file it as a (reproducible) bug report with the roxygen2 team.
I see no Rcpp issue; it is possible that something went wrong with the Imports: / NAMESPACE declaration. I see no Rcpp issue here (as 1. works fine).
FWIW I also use roxygen2 on some packages, and I too build them from time to time in RStudio.