R package akin to Rstanarm - how to include auxiliary files and avoid build errors?

Operating System: Max OS X 10.9.5
Interface Version: rstan
Compiler/Toolkit:

I’m working on creating an r package that uses stan/rstan . Akin to rstanarm’s file organization I have an inst/chunks directory where I’m putting a common_functions.stan file however when I build the package, I get an error: the script doesn’t appear to include the file in the build process. Here’s the layout below, any insight as to why I get the error would be greatly appreciated.

/R/model_function.R
/exec/model_in_stancode.stan
/inst/chunks/common_functions.stan

model_function.R has the following code

model <- rstan::stan_model(stanc_ret = rstan::stanc_builder(f,isystem = 'inst/chunks/'),
                           verbose = T)

model_in_stancode.stan has

functions{
    #include "common_functions.stan"
}
...
model{
...
auxiliary_function(x,y);
}
....

common_functions.stan has

row_vector auxiliary_function(vector x, real y){
 // function action here
}

Error message is:

** preparing package for lazy loading
SYNTAX ERROR, MESSAGE(S) FROM PARSER:

No matches for: 

auxiliary_function(vector, real)

Function auxiliary_function not found.

ERROR at line 36

I don’t think you should need this function. If you called rstantools::rstan_package.skeleton() then it would have downloaded a make_cpp.R file to the tools subdirectory. When you call R CMD build or R CMD INSTALL --preclean it should parse the Stan files to C++ with any #include statements. Then there will be a named list called stanmodels inside the namespace of your package and one of the elements of that list will be model_in_stancode. This will be the precompiled result of calling stan_model, so you should not need to do it again.

Hi - Thanks for your help.

You’re right. the make_cpp file appears needed. However make_cpp function references the file models.hpp in the src directory with which I neither have nor am familiar - resulting in another error thrown. Could you help me understand what this file is? I don’t see an analogous file in the rstanarm package.

Thank you again.

Ironically, the cleanup (or cleanup.win on Windows) script — which is executed if you do R CMD build or R CMD INSTALL --preclean — calls tools/make_cpp, which creates src/include/models.hpp.

Hm. Okay I’m making some progress. Current error message is in reference specifically when the fit function is called. I’m using similar function call to rstanarm

out <- do.call(rstan::sampling,sampling_args)

and I get:

Error in get(paste0("model_", model_cppname)) : 
    object 'model_modelname' not found

Any idea why this is? this appears to be from the stanmodels file in the skeleton

## other code in front which builds stanobjects from .stan files  
return(do.call(methods::new, args = c(stanfit[-(1:3)], Class = "stanmodel", 
             mk_cppmodule = function(x) get(paste0("model_", model_cppname)))))

As always - thanks

What is

dir("exec", pattern = "stan$", full.names = TRUE)

This function produces a character vector containing the stan files in the exec directory - I have only one in my case.

This function executes normally. and the stanfit class made without issue, e.g. when I run these commands through the terminal and then execute

stanmodels$my_model

I see the stan script I wrote in the exec directory…yet the error still appears when I run it after building the library and using my “fit” function

What is the output of R CMD INSTALL --preclean in a shell?

I’ve included what I believe to be the pertinent part of the output

==> R CMD INSTALL --preclean my_package

* installing to library ‘/Library/Frameworks/R.framework/Versions/3.3/Resources/library’
* installing *source* package ‘my_package’ ...
$my_model
NULL

OK, no user-defined functions to include.
Wrote C++ file "src/my_modelModule.cc"
cp: src/*.hpp: No such file or directory

And you have this in R/zzz.R?

.onLoad <- function(libname, pkgname) { # nocov start
  modules <- paste0("stan_fit4", names(stanmodels), "_mod")
  for (m in modules) loadModule(m, what = TRUE)
}

Ah. I had commented that out. Because leaving that in gives me the following error:

Error in is(module, "character") : object 'm' not found
Calls: suppressPackageStartupMessages ... load_all -> run_ns_load_actions -> action -> loadModule -> is
Execution halted

I should say that, again, if I run this in the terminal on it’s own this executes without issue

You mean devtools::load_all() gives you that error? If so, then I think you need to specify the recompile = TRUE argument. But either way, that .onLoad function is definitely necessary.

I’ll keep it in.

I’m still getting the same error, even with the command

devtools::load_all(recompile=T)

Any suggestions? I can’t understand why it shouldn’t be able to find the module.

Can you temporarily change your .onLoad function to

.onLoad <- function(libname, pkgname) { # nocov start
  modules <- paste0("stan_fit4", names(stanmodels), "_mod")
  print(modules)
  for (m in modules) loadModule(m, what = TRUE)
}

Yeah so I’ve done that, and ran a few other little debugging tests as well. For the following code

 .onLoad <- function(libname, pkgname) {
    modules <- paste0("stan_fit4", names(stanmodels), "_mod")
    print(modules)
    loadModule(modules[1])
   #for (m_ix in seq_along(modules)) loadModule(modules[m_ix], what = TRUE)

}

I get the following output (after all the usual log printing)

[1] "stan_fit4my_model_mod"
Error in is(module, "character") : object 'modules' not found

So it printed out the object…but then couldn’t find it.

This is weird, right? Am I wrong for thinking this is weird?

Yes, that is weird. Do you have Rcpp in the Depends section of your DESCRIPTION?

Yep

Depends: R (>= 3.0.2), Rcpp (>= 0.12.11), methods

I don’t remember if the what = TRUE argument is critical, but you omitted it from loadModule(modules[1]).

I included it and still get the same result

My guess is that it is looking in the package namespace for an object modules and not finding it. Does it work if you hard code
loadModule("stan_fit4my_model_mod", what = TRUE)?