Automate #usage documentation in Rcpp functions - r

How can I automate the documentation of the #usage section for Rcpp functions? In an ordinary R function within a package documented using roxygen2, the Usage section is added automatically. This is convenient for automatically documenting default arguments.
#' #title Hello world
#' #return Prints 'Hello world'
#' #export
#' #useDynLib RcppSandBox
hello <- function(x = 1) {
print("Hello, world!")
}
Hello world
Usage
hello(x = 1)
Value
Prints 'Hello world'
Yet when I write an analogous script with Rcpp, the documentation is produced but no #usage section is written.
//' Hello, Rcpp!
//' #name rcpp_hello
//' #param CharVec Print x or not.
//' #export
#include <Rcpp.h>
using namespace Rcpp;
// This is a simple function using Rcpp that creates an R list
// containing a character vector and a numeric vector.
//
// Learn more about how to use Rcpp at:
//
// http://www.rcpp.org/
// http://adv-r.had.co.nz/Rcpp.html
//
// and browse examples of code using Rcpp at:
//
// http://gallery.rcpp.org/
//
// [[Rcpp::export]]
List rcpp_hello(bool CharVec = true) {
CharacterVector x = CharacterVector::create("foo", "bar");
NumericVector y = NumericVector::create(0.0, 1.0);
List z = List::create(x, y);
if (CharVec) {
} else {
List z = List::create(y);
}
return z;
}
Hello, Rcpp!
Description
Hello, Rcpp!
Arguments
CharVec Print x or not.
I looked at the source code and documentation for dplyr::between, but there doesn't seem to be any special #usage section, yet the #usage section is present in the documentation.
I also looked at http://r-pkgs.had.co.nz/man.html and http://dirk.eddelbuettel.com/code/rcpp/Rcpp-attributes.pdf and Ctrl-F'd for usage, but found nothing relevant.
I know I can add //' #usage rcpp_hello(CharVec = TRUE) in this particular case but the advantage of letting roxygen2 automate the process is that I can change the default arguments.
DESCRIPTION file:
Package: RcppSandBox
Type: Package
Title: What the Package Does (Title Case)
Version: 0.1.0
Author: Who wrote it
Maintainer: The package maintainer <yourself#somewhere.net>
Description: More about what it does (maybe more than one line)
Use four spaces when indenting paragraphs within the Description.
License: What license is it under?
Encoding: UTF-8
LazyData: true
Imports: Rcpp (>= 0.12.10)
LinkingTo: Rcpp
RoxygenNote: 6.0.1
Session info:
> sessionInfo()
R version 3.4.0 (2017-04-21)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
Matrix products: default
locale:
[1] LC_COLLATE=English_Australia.1252 LC_CTYPE=English_Australia.1252 LC_MONETARY=English_Australia.1252
[4] LC_NUMERIC=C LC_TIME=English_Australia.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] RcppSandBox_0.1.0 dplyr_0.5.0 RevoUtilsMath_10.0.0
loaded via a namespace (and not attached):
[1] compiler_3.4.0 magrittr_1.5 R6_2.2.2 assertthat_0.2.0 RevoUtils_10.0.4 DBI_0.6-1 tools_3.4.0
[8] tibble_1.3.0 Rcpp_0.12.10

You haven't needed to use #usage since Roxygen2 2.0 and 3.0.0 for R or Rcpp. The issue you are running into is your roxygen tags are not directly above the Rcpp attributes tag...
#include <Rcpp.h>
//' Hello, Rcpp!
//' #param CharVec Print x or not.
//' #export
// [[Rcpp::export]]
Rcpp::List rcpp_hello(bool CharVec = true) {
Rcpp::CharacterVector x = Rcpp::CharacterVector::create("foo", "bar");
Rcpp::NumericVector y = Rcpp::NumericVector::create(0.0, 1.0);
Rcpp::List z = Rcpp::List::create(x, y);
if (CharVec) {
} else {
Rcpp::List z = Rcpp::List::create(y);
}
return z;
}
Try the above. This also means you do not need the #name tag either...

Related

Local images in DT call not being written to _site directory

Question
How can I get each local image that is only referenced in a DT call to render to the _site directory so that it shows up in the site? Any suggestions or guidance would be much appreciated.
I reviewed this and this SO question.
Context
I am working in a Quarto website, but I get similar results from R Markdown.
I have a large number of image files in a series of sub-directories. These files correspond to records in a data frame (location, material, etc). Using the DT library, I would like to display the table and include the image files.
Problem
After rendering the website, local images only referenced within the DT call are not written out to the _site directory. However, if I reference an image using html that I pull directly from a data frame cell (i.e. df$imagefile[1]), the image is written to the _site directory and thus shows both in the html and the DT.
Without html chunk.
With html chunk.
Repro
Create a new Quarto website and add the code below to the index.qmd file.
First render the document without the final html chunk and no images will show.
Delete the _site directory and restart R.
Re-render the document including the html chunk and the first table image will show along with another copy below the table.
Note, sometimes once an image is knit is seems to remain in memory even if deleted. I've found it useful to both delete _site and restart R.
#| echo: false
knitr::opts_chunk$set(
echo = FALSE,
message = FALSE
)
#| label: libraries
library(dplyr)
library(DT)
#| label: create-dirs
main_dir <- here::here()
sub_dir <- "data"
sub_dir2 <- "data/Images"
# Check first dir
if (file.exists(sub_dir)){
} else {
dir.create(file.path(main_dir, sub_dir))
}
# Check second dir
if (file.exists(sub_dir2)){
} else {
dir.create(file.path(main_dir, sub_dir2))
}
#| label: make-images
jpeg(filename = "data/Images/2347.jpg")
plot(rnorm(25))
jpeg(filename = "data/Images/2348.jpg")
plot(rnorm(25))
jpeg(filename = "data/Images/2349.jpg")
plot(rnorm(25))
dev.off()
#| label: generate-list-make-df
image_list <- list.files("data/Images", full.names = TRUE)
df <- data.frame(imagefile = image_list)
df <- df |>
mutate(imagefile = paste0("<a href='",
imagefile,
"' target = 'blank'>",
"<img src='",
imagefile,
"' width = '125'></a></img>"))
datatable(df, escape = FALSE)
Final html chunk
Render first without and then again with the following chunk.
<a href='/data/Images/2347.jpg' target = 'blank'><img src='/data/Images/2347.jpg' width = '125'></a></img>
Session Info
R version 4.2.1 (2022-06-23 ucrt)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 19044)
Matrix products: default
locale:
1 LC_COLLATE=English_United States.utf8 LC_CTYPE=English_United States.utf8
[3] LC_MONETARY=English_United States.utf8 LC_NUMERIC=C
[5] LC_TIME=English_United States.utf8
attached base packages:
1 stats graphics grDevices datasets utils methods base
loaded via a namespace (and not attached):
1 compiler_4.2.1 here_1.0.1 fastmap_1.1.0 cli_3.4.1 rprojroot_2.0.3 htmltools_0.5.2 tools_4.2.1
[8] yaml_2.3.6 rmarkdown_2.17 knitr_1.40 xfun_0.33 digest_0.6.30 rlang_1.0.6 renv_0.15.5
[15] evaluate_0.16

defining operator doesn't work anymore (Error in UseMethod("%op%"): no applicable method for '%op%' applied to an object of class "character")

In my toy package, I have defined %+% operator as an alias to paste0(). Trying to reduce interference with other packages, I realized it the following way:
`%+%` <- function(...) UseMethod("%+%")
`%+%.character` <- paste0
`%+%.numeric` <- paste0
`%+%.default` <- function (arg1, arg2){
e <- parent.env(getEnvByName(.GlobalEnv,'package:mypackagename'));
if (exists('%+%', envir = e)) get('%+%',envir = e)(arg1,arg2);
}
i.e. I override it only for character and numeric arguments, otherwise it tries to find if the method was previously defined.
It was working just fine until recently when it started giving an error:
'a' %+% 'b'
# Error in UseMethod("%+%") :
# no applicable method for '%+%' applied to an object of class "character"
It only fails when called outside of the package. If I define a function within the package, it works correctly:
# testab2() is defined in R file as a part of the package:
testab2 <- function(inpA, inpB){
print (inpA %+% inpB)
}
# when called outside of the package:
testab2('a','b')
# ab
I am pretty sure I didn't change anything in my code, so I'm wondering if it could be caused by R update. What could have changed and how to make it work back?
P.S. getEnvByName() is my helper function that searches for an object in parent environments:
getEnvByName <- function(inpEnv=.GlobalEnv, lookFor){
e <- inpEnv;
while (environmentName(e) != 'R_EmptyEnv' & environmentName(e)!=lookFor) e <- parent.env(e);
if (environmentName(e) != lookFor) return(NULL);
return(e);
}
And the exporting was done by the following lines in the NAMESPACE file:
exportPattern("^[[:alpha:]]+")
exportPattern("%.*%")
export("%+%.default")
export("%+%.character")
P.P.S. sessionInfo:
R version 4.0.2 (2020-06-22)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 10 x64 (build 18363)
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C LC_TIME=English_United States.1252
system code page: 1251
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] vautils_0.1.1.105 magrittr_1.5 data.table_1.13.0
loaded via a namespace (and not attached):
[1] dplyr_1.0.2 crayon_1.3.4 grid_4.0.2 R6_2.4.1 lifecycle_0.2.0 gtable_0.3.0
[7] scales_1.1.1 ggplot2_3.3.2 pillar_1.4.6 rlang_0.4.7 rstudioapi_0.11 generics_0.0.2
[13] vctrs_0.3.4 ellipsis_0.3.1 tools_4.0.2 glue_1.4.2 purrr_0.3.4 munsell_0.5.0
[19] compiler_4.0.2 pkgconfig_2.0.3 colorspace_1.4-1 tidyselect_1.1.0 tibble_3.0.3
To export S3 methods, your NAMESPACE file needs to (in your case) contain the following declarations:
export(`%+%`)
S3method(`%+%`, default)
S3method(`%+%`, character)
S3method(`%+%`, numeric)
That is, export the %+% generic, and declare S3 methods for the methods.
Better yet, instead of manually editing the NAMESPACE file use ‘roxygen2’, which generates the correct declarations for you based on the #export documentation tag.

RcppTN .cpp script works when sourced but not when compiled in library

I am trying to create a R package that uses random draws from a truncated normal in a .cpp script. I am using the rtn1 function from the pckage RcppTN. If I source the code, the function works fine. Once I build the package I get the error:
> library(testtruncnorm)
> testtruncnorm()
Error in testtruncnorm::testtruncnorm() :
function 'RcppTN_rtn1' not provided by package 'RcppTN'
Simplified .cpp code is here
#include <RcppArmadillo.h>
// [[Rcpp::depends(RcppArmadillo)]]
#include <RcppTN.h>
// [[Rcpp::depends(RcppTN)]]
#include<armadillo>
using namespace Rcpp;
//' draw truncated normal
//'
//' testtruncnorm()
//' #return returns 2 draws from a truncated normal
// [[Rcpp::export]]
arma::vec testtruncnorm()
{
arma::vec result = arma::ones(2);
result[1] = RcppTN::rtn1(1, 1, 0,HUGE_VAL);
result[2] = RcppTN::rtn1(1, 1, 0,HUGE_VAL);
return result;
}
My NAMESPACE file is
useDynLib(testtruncnorm, .registration=TRUE)
importFrom(Rcpp, evalCpp)
exportPattern("^[[:alpha:]]+")
My DESCRIPTION file is
Package: testtruncnorm
Type: Package
Title: What the Package Does Using Title Case
Version: 1.0
Date: 2018-10-23
Author: Your Name
Maintainer: Your Name <your#email.com>
Description: More details about what the package does. See
<http://cran.r-project.org/doc/manuals/r-release/R-exts.html#The-
DESCRIPTION-file>
for details on how to write this part.
License: GPL (>= 2)
Imports: Rcpp (>= 0.12.19), RcppTN
LinkingTo: Rcpp, RcppArmadillo, RcppTN
I am using RStudio create "R Package with RcppArmadillo" to get started. RStudio version 1.1.456. R version 3.5.1. Windows 10.
You have to make sure that RcppTN gets attached. You can do this using
importFrom(RcppTN, rtn)
in NAMESPACE. In the documentation for RcppTN it says that one should add
Depends: RcppTN
which should have the same effect.

devtools manual build with ASCII titles

I'm building a package but the documentation must be in Spanish, including the tilde character (i.e. í, é).
I have a simple function like this in an R file:
#' Función con acénto
#'
#' Permite instalar rápidamente de manera local un paquete previamente descargado
#' #param direccion La dirección del archivo local, poner .zip
#' #keywords FAhorroDS
#' #export
#' #encoding UTF-8
#' #author Eduardo Flores
#' #examples
#' FA_InstalarLocal("paquete_x_1.10.zip")
FA_InstalarLocal<-function(direccion)
{
install.packages(direccion, repos = NULL, type="source")
}
And building the Rd via devtools::document(). The Rd file in man generated seems fine:
% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/test.R
\encoding{UTF-8}
\name{FA_InstalarLocal}
\alias{FA_InstalarLocal}
\title{Función con acénto}
\usage{
FA_InstalarLocal(direccion)
}
\arguments{
\item{direccion}{La dirección del archivo local, poner .zip}
}
\description{
Permite instalar rápidamente de manera local un paquete previamente descargado
}
\examples{
FA_InstalarLocal("paquete_x_1.10.zip")
}
\author{
Eduardo Flores
}
\keyword{FAhorroDS}
However even if i'm specifying the encoding both here and in the DOCUMENTATION file, when I run: system("R CMD Rd2pdf . --output=manual.pdf --force"), I get the following error:
Hmm ... looks like a package
Converting Rd files to LaTeX Warning: ./man/FA_InstalarLocal.Rd:6: Some input could not be re-encoded to ASCII
When I see the package, the description is okay, but the title of the function turns out as NA.
Any ideas as to why everything else (the description has a tilde) is being correctly encoded but not the title?
> sessionInfo()
R version 3.2.4 Revised (2016-03-16 r70336)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
locale:
[1] LC_COLLATE=Spanish_Mexico.1252 LC_CTYPE=Spanish_Mexico.1252
[3] LC_MONETARY=Spanish_Mexico.1252 LC_NUMERIC=C
[5] LC_TIME=Spanish_Mexico.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] fahorro_0.1 devtools_1.10.0 magrittr_1.5 readxl_0.1.0 dplyr_0.4.3
[6] FAhorroDS_1.0.1
loaded via a namespace (and not attached):
[1] Rcpp_0.11.6 roxygen2_5.0.1 R6_2.1.2 xlsx_0.5.7 stringr_1.0.0
[6] plyr_1.8.3 tools_3.2.4 parallel_3.2.4 DBI_0.3.1 withr_1.0.0
[11] assertthat_0.1 digest_0.6.9 rJava_0.9-8 RODBC_1.3-12 xlsxjars_0.6.1
[16] memoise_1.0.0 stringi_1.0-1 SOAR_0.99-11

Building package with Rcpp, generated .h file missing header

I am currently building a package in RStudio that uses Rcpp. I have defined the following .cpp file, which works with Rcpp::sourceCpp.
// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::interfaces(r, cpp)]]
#include <Rcpp.h>
#include <unordered_set>
using namespace Rcpp;
// [[Rcpp::export]]
std::unordered_set<int> traverse_cor(NumericMatrix x, float maxcor) {
std::unordered_set<int> elements;
int ncol = x.ncol();
for(int i = 0; i < ncol; i++) {
for(int j = 0; j < ncol; j++) {
if(i < j) {
if(x(i, j) > maxcor && x(i, j) < 1){
elements.insert(i + 1);
}
}
}
}
return elements;
}
I am following the directions from here and here. Next I call Rcpp::compileAttributes(). This produces the following files:
src/RcppExports.cpp
R/RcppExports.R
inst/include/mypackage.h
inst/include/mypackage_RcppExports.h
The generated mypackage_RcppExports.h file looks as follows:
// This file was generated by Rcpp::compileAttributes
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
#ifndef __gwassim_RcppExports_h__
#define __gwassim_RcppExports_h__
#include <Rcpp.h>
namespace gwassim {
using namespace Rcpp;
namespace {
void validateSignature(const char* sig) {
Rcpp::Function require = Rcpp::Environment::base_env()["require"];
require("gwassim", Rcpp::Named("quietly") = true);
typedef int(*Ptr_validate)(const char*);
static Ptr_validate p_validate = (Ptr_validate)
R_GetCCallable("gwassim", "gwassim_RcppExport_validate");
if (!p_validate(sig)) {
throw Rcpp::function_not_exported(
"C++ function with signature '" + std::string(sig) + "' not found in gwassim");
}
}
}
inline std::unordered_set<int> traverse_cor(NumericMatrix x, float maxcor) {
typedef SEXP(*Ptr_traverse_cor)(SEXP,SEXP);
static Ptr_traverse_cor p_traverse_cor = NULL;
if (p_traverse_cor == NULL) {
validateSignature("std::unordered_set<int>(*traverse_cor)(NumericMatrix,float)");
p_traverse_cor = (Ptr_traverse_cor)R_GetCCallable("gwassim", "gwassim_traverse_cor");
}
RObject __result;
{
RNGScope __rngScope;
__result = p_traverse_cor(Rcpp::wrap(x), Rcpp::wrap(maxcor));
}
if (__result.inherits("interrupted-error"))
throw Rcpp::internal::InterruptedException();
if (__result.inherits("try-error"))
throw Rcpp::exception(as<std::string>(__result).c_str());
return Rcpp::as<std::unordered_set<int> >(__result);
}
}
#endif // __gwassim_RcppExports_h__
After attempting to build and reload the package, I receive the following errors (1):
../inst/include/gwassim_RcppExports.h:27:12: error: 'unordered_set' in
namespace 'std' does not name a type
And (2)
RcppExports.cpp:12:1: error: 'unordered_set' in namespace 'std' does
not name a type
I have limited C++ experience, but my sense is that these errors occur due to #include <unordered_set> being omitted. How do I get these automatically generated files to have the correct headers?
My sessionInfo is the following:
Session info ----------------------------------------------------------------------
setting value
version R version 3.1.0 (2014-04-10)
system x86_64, mingw32
ui RStudio (0.99.235)
language (EN)
collate English_United States.1252
tz America/New_York
Packages --------------------------------------------------------------------------
package * version date source
devtools 1.7.0.9000 2015-02-11 Github (hadley/devtools#9415a8a)
digest * 0.6.4 2013-12-03 CRAN (R 3.1.0)
memoise * 0.2.1 2014-04-22 CRAN (R 3.1.0)
mvtnorm 1.0-2 2014-12-18 CRAN (R 3.1.2)
Rcpp 0.11.4 2015-01-24 CRAN (R 3.1.2)
roxygen2 * 4.1.0 2014-12-13 CRAN (R 3.1.2)
rstudioapi * 0.2 2014-12-31 CRAN (R 3.1.2)
stringr * 0.6.2 2012-12-06 CRAN (R 3.0.0)
And my version of g++ is 4.6.3, as included in the RTools package for Windows. I have enabled C++11 features with the following:
Sys.setenv("PKG_CXXFLAGS"="-std=c++0x").
That is a finicky one. I think you want Section 3.5.2 of the Rcpp Attributes vignette and this trick:
The Package.h file does nothing other than include the
Package_RcppExports.h header. This is done so that package
authors can replace the Package.h header with a custom one
and still be able to include the automatically generated exports
(details on doing this are provided in the next section).
In passing, I think I also convinced you to create a package rather than to rely just on sourceCpp() :)
Edit: Doh!! I overlooked the part that
std::unordered_set<int> traverse_cor(NumericMatrix x, float maxcor)
is probably not an automatically wrappable function. You may need to convert your set into a vector (or list or ...) to get one of the types that matches naturally into R.

Resources