Using system2() in R to run compiled cpp file - r

I'm trying to run a compiled cpp file in my R program using system2(). The documentation for the cpp suggests that it's just one big command, so I'm thinking I'm not supposed to use the stdout or stder options in sys2.
the required network.nodes and network.edges files are there in the /files folder
I can run the system2() line but it doesn't output anything
I previously compiled the socialrank.cpp and put it in the /exe folder using Cygwin or cmd prompt maybe (g++ -o socialrank socialrank.cpp)
Guidance:
- To run the algorithm, simply run:
./socialrank summary_stats.txt graphname > debug.log
(You need to have the files graphname.nodes and graphname.edges)
My code (let me know if you need to see more):
> nodelist %>% write_delim("./files/network.nodes", col_names = F)
> edgelist %>% write_delim("./files/network.edges", col_names = F)
> #system("../exe/socialrank ../files/summary_stats.txt ../files/network") #I think this code is for macs??
> system2("./exe/socialrank ./files/summary_stats.txt ./files/network") #Is this how you correct relative file directories for Windows?
So nothing is being output into the /files folder. I can't tell if the CPP file is being run, not exporting files, or exporting them somewhere else?
Please let me know if you any suggestions on compiling, calling cpp programs, or the system2 function. I've also heard about the sys and processx packages, so not sure if there is a better way to call system files that perhaps works across operating systems?
Thank you so much for your help!!

The documentation for system2 gives us two pieces of information:
We need to specify the command to be executed and the args as separate arguments.
By default, the return value of system2 is invisible, and it’s the status code of the command we executed.
The second point is the reason you’re not seeing any output.1 The first point is the reason why it doesn’t work in the first place: you need to specify the command and its arguments separately (and the arguments need to be a vector):
system2('./exe/socialrank', c('./files/summary_stats.txt', './files/network'))
This assumes that exe and files are subdirectories of the current working directory (and that the respective files exist in these locations).
In your case, the same command works for macOS, Windows and Linux.
Anyway, this is not quite the same as the example given in the usage guidance:
./socialrank summary_stats.txt graphname > debug.log
… because in the command above, output isn’t stored in a debug.log file but sent to the R console. This is very rarely useful. It’s much more common that you want to store the output itself in a variable in R. You can do that by adding the argument stdout = TRUE to the system2 call. Alternatively, specify stdout = 'debug.log' to do the same as the command above, i.e. store the output in a file.
1 Actually, on my system I still get a message: “[…] command not found”.

Related

How to get the absolute path from the context of the current running R script?

Using python, if I need the absolute path from the context of the current running script all I need to do is to add the following in the code of that script:
import os
os.path.abspath(__file__)
This is very useful as having the absolute path I can then use os.path.join to form new absolute paths for my project components (inside the project directory tree) and more interesting is that everything will continue to work without any problem no matter where the package directory is moved.
I need to achieve the very same thing using R programming, that is obtaining the absolute path of the current running R script ( = the absolute path of its file on the disk). But trying to do the same in R turns out to be quite challenging, at least for me as a rather beginner in R.
After a lot of googling, I tried to use the reticulate package to call Python from R but __file__ is not available there, then I found a few threads on Stackoverflow suggesting to play with the running Stack and others suggesting the use of normalizePath. However none of these worked for me when the entire project package is transferred from one directory to another.
Therefore, I would like to know if for example you have the following file/directory tree
base_dir ( = /home/usr1/apps/R/base_dir)
|
|
|___ myscript.R (this is my R script to be run)
|___ data (this is a directory)
|___ sql (this is a directory)
Is there any solution allowing to add something in the code of myscript.R so that inside the script the program can always know that the base directory is /home/usr1/apps/R/base_dir and if later this base directory is moved to another directory then there is no need to change the code and the program would be able to find correctly the new base directory?
R has in general no way of finding this path, because there is no equivalent to Python’s __file__ in R.
The closest you can get is to look at commandArgs() and laboriously extract the script filename (which requires different handling depending on how the script was launched!). But this will fail if the script was executed in RStudio, and it will fail after calling setwd().
Other solutions (such as the ‘here’ package) rely on heuristics and specific project structures.
But luckily there’s actually a solution that will always work: use ‘box’ modules.
With modules, you’ll always be able to get the path of the current script/module via box::file(). This is the closest equivalent to Python’s __file__ you’ll get in R, and it always works — as long as you’re using ‘box’ modules consistently.
(Internally the ‘box’ package requires complex logic to determine the value of the file() function in all circumstances; I don’t recommend replicating it, it’s too complex. For the curious, the bulk of the relevant logic is in R/loaded.r.)
If you are running the script using Rscript you can use getwd().
#!/usr/bin/Rscript
getwd()
# or assign it to a variable
base_dir = getwd()
you can run it from the command line using one of the following
./yourscript.R
# or
Rscript yourscript.R
Note however, this only works if you run the script from inside the folder, the file is in.
cd ~
./script.R
# "/home/usr1"
cd /
/home/usr1/script.R
# "/"
For a more elaborate option you could consider https://stackoverflow.com/a/55322344/3250126

Is there a way to run julia script with arguments from REPL?

I can run julia script with arguments from Powershell as > julia test.jl 'a' 'b'. I can run a script from REPL with include("test.jl") but include accepts just one argument - the path to the script.
From playing around with include it seems that it runs a script as a code block with all the variables referencing the current(?) scope so if I explicitly redefine ARGS variable in REPL it catches on and displays corresponding script results:
>ARGS="c","d"
>include("test.jl") # prints its arguments in a loop
c
d
This however gives a warning for redefining ARGS and doesn't seem the intended way of doing that. Is there another way to run a script from REPL (or from another script) while stating its arguments explicitly?
You probably don't want to run a self-contained script by includeing it. There are two options:
If the script isn't in your control and calling it from the command-line is the canonical interface, just call it in a separate Julia process. run(`$JULIA_HOME/julia path/to/script.jl arg1 arg2`). See running external commands for more details.
If you have control over the script, it'd probably make more sense to split it up into two parts: a library-like file that just defines Julia functions (but doesn't run any analyses) and a command-line file that parses the arguments and calls the functions defined by the library. Both command-line interface and the second script your writing now can include the library — or better yet make the library-like file a full-fledged package.
This solution is not clean or Julia style of doing things. But if you insist:
To avoid the warning when messing with ARGS use the original ARGS but mutate its contents. Like the following:
empty!(ARGS)
push!(ARGS,"argument1")
push!(ARGS,"argument2")
include("file.jl")
And this question is also a duplicate, or related to: juliapassing-argument-to-the-includefile-jl as #AlexanderMorley pointed to.
Not sure if it helps, but it took me a while to figure this:
On your path "C:\Users\\.julia\config\" there may be a .jl file called startup.jl
The trick is that not always Julia setup will create this. So, if neither the directory nor the .jl file exists, create them.
Julia will treat this .jl file as a command list to be executed every time you run REPL. It is very handy in order to set the directory of your projects (i.e. C:\MyJuliaProject\MyJuliaScript.jl using cd("")) and frequent used libs (like using Pkg, using LinearAlgebra, etc)
I wanted to share this as I didn't find anyone explicit saying this directory might not exist in your Julia device's installation. It took me more than it should to figure this thing out.

Call SConstruct from R

How can I call a sconstruct script from R (e.g. in Rstudio)? I'd like to call SCons and, ideally, also read the output. So that I can get the print from e.g. scons --tree=all as a string.
If I run > system("scons")
I get: sh: scons: command not found
Setting the path Sys.setenv(PATH=paste(Sys.getenv("PATH"), "/path/to/my/sconstruct", sep=":")) doesn't help.
However, any other command works. E.g. if I have a Python script (in the same directory), I can call it as: > system('python test.py')
and get the expected: Hello Rld! back. >system('ls') lists the SConstruct, so I'm in the right work directory.
Calling from a Python script also works, eg: from subprocess import call call('scons') evokes the SConstruct as expected. However, calling that Python script from R -- doesn't work.
It appears as there is something in the R environment setting that I got wrong.
I'm on OS, but a portable solution would be fantastic!
You'll need to either be in the directory where the SConstruct is, specify it's file or use -C to change directory to it.
I don't know R or what the syntax is.
Sys.setenv(PATH=paste(Sys.getenv("PATH"), "/path/to/my/sconstruct", sep=":"))
Should likely be:
Sys.setenv(PATH=paste(Sys.getenv("PATH"), "/path/to/scons", sep=":"))

What are productive ways to debug Rcpp compiled code loaded in R (on OS X Mavericks)?

What is the most productive and quickest way to debug shared objects that are loaded into R, in particular on OS X Mavericks? I'm primarily interested in debugging compiled Rcpp code.
I have read the R externals on debugging compiled code (http://cran.r-project.org/doc/manuals/R-exts.html#Debugging-compiled-code) which favours using gdb, but gdb isn't officially supported on Mavericks. However, it seems that lldb is a viable alternative? I found the most useful resource for working out how to debug compiled code in R from Dirk's response to this post (Thanks Dirk!) (Debugging (line by line) of Rcpp-generated DLL under Windows).
I can successfully debug compiled Rcpp code by following the steps which I outline below explicitly step by step, which other Rcpp novices may find this useful (apologies for the length, but I figure it's better to be clear than to omit and be vague). But this development process is a bit tedious and time consuming.
Questions:
is there a faster and/or easier way to debug compiled Rcpp code, compared to what I do below?
I'm a big fan of Rstudio, and would love to incorporate debugging shared objects created from that IDE, so if anyone knows how to do this, I would be interested to know? Rstudio seems to use attributes, and it appears that step 4 below needs modification, because there doesn't seem to be a .cpp file in the temporary directory after compiling (in my example below, there is no "file5156292c0b48.cpp" file)
The steps:
1) (One off) Go to the directory ~/.R (a hidden directory with the .). Create a new file called "Makevars" and in it add the line CXXFLAGS=-g -O0 -Wall.
2) In the terminal, type R -d lldb to launch R. lldb will now start.
3) Type run at the lldb command line. This will start R.
4) Compile the Rcpp code and find the location of the compiled objects. Dirk's response to the above mentioned post shows one way to do this. Here is an example I'll use here. Run the following commands in R:
library(inline)
fun <- cxxfunction(signature(), plugin="Rcpp", verbose=TRUE, body='
int theAnswer = 1;
int theAnswer2 = 2;
int theAnswer3 = 3;
double theAnswer4 = 4.5;
return wrap(theAnswer4);
')
This creates a compiled shared object and other files which can be found by running setwd(tempdir()) and list.files() in R. There will be a .cpp file, like "file5156292c0b48.cpp" and .so file like "file5156292c0b48.so"
5) Load the shared object into R by running dyn.load("file5156292c0b48.so") at the R command line
6) Now we want to debug the C++ code in this .so object. Go back to lldb by hitting ctrl + c. Now I want to set a break point at a specific line in the file5156292c0b48.cpp file. I find the correct line number by opening another terminal and looking at the line number of interest in file5156292c0b48.cpp. Say it's line 31, which corresponds to the line int theAnswer = 1; above in my example. I then type at the lldb command line: breakpoint set -f file5156292c0b48.cpp -l 31. The debugger prints back that a break point has been set and some other stuff...
7) Go back to R by running cont in lldb (the R prompt doesn't automatically appear for me until I hit enter) and call the function. Run fun() at the R command line. Now I am debugging the shared object (hit n to go to next line, p [object name] to print variables etc)....
To debug simple Rcpp scripts like this, one thing you can do is create a .cpp application (with a main) that embeds R. This way you can debug it directly with Xcode which will give you a good debugging experience.
It gets more complicate when you start to want to debug packages.
This is tough. I tried Xcode and Eclipse with a standalone C++ application, but it was so difficult to get all the headers and libraries working. Furthermore, the RcppExport code calls your real R function through a pointer which seemed to really confuse Xcode, and I couldn't step into my function.
I ended up with (gdb or lldb):
In R:
R -d lldb
In debugger, set breakpoint:
b functionName
run
In R:
.Call(etc) # or just call your R code which invokes compiled C/C++ code
Then back in debugger once break happens, you can step, examine frames, etc.
This lldb/gdb command quick reference helped a lot.
Forget about trying to do this in a GUI at this point. Hopefully Rstudio will get this going.

How can I load my .RProfile using Textmate's R Bundle

This question is for those of you who happen to use R, on a Mac, in combination with Macromate's [Textmate](http://macromates.com/) text editor and the "R" Bundle. All of which are nifty, needless to say, but that's beside the point for now :-)
I've got a .RProfile file sitting in my default "~" startup directory, and it's got a number of useful functions in it I like to have access to when writing R scripts. But I also use Textmate for most of my writing, and the cmd-R functionality to to run my scripts within Textmate.
At the moment, I don't know how to tell Textmate where my .Rprofile is.
Is there a way--most likely through Textmate's Bundle settings--that I can point Textmate to my .RProfile so I don't have to write my functions into every script on a per-script basis?
OR
Is it actually better to include any custom functions in any script I write, so that anyone with a basic R setup can source and run my scripts?
I feel like I must be missing a dead-easy setting or config file here within either Textmate or the R environment it calls to run my scripts.
Thanks so much in advance!
The R Bundle Developer is apparently working on this (see this Post on the Mailing List) but it's not available at the moment.
In the meantime, you have a couple of choices.
First, you can create a new bundle (e..g, "briandk-R") then create a snippet w/in that bundle either with 'source($1)' or just hardcode the file you want to source instead of the placeholder (so, e.g., "source("~/some_file_to_source.R"). If you do the latter, then you can configure TM to source your file via a tab trigger (in the Bundle Editor, toggle over to 'settings' (upper left hand corner) and type "source.r, source.rd.console" in the 'Scope Selector' field then choose a few letters for your tab trigger (e.g., "src.")
If you don't want to do that, go to the 'Rdaemon' Directory (which is either in your home directory or in ~/Library/Application Support/Rdaemon). Look in this directory and you will see another directory called "daemon.' In there is a file called "start.r" which lists the files that are sourced upon starting R from the Rdaemon. You know what to do from there. (Note: This directory also contains a couple of other scripts which contain initial settings; you might wish to have a look at those as well)
The first part of Doug's response offers the simplest immediate solution... add
source('/Users/briandk/.Rprofile')
to the head of any .r files you want those functions in... with that one line of code, you get your utility functions. Of course, that only helps if you're running the whole TM file.
Ideally, the bundle will be updated... perhaps to support a shell variable via TM's preferences???
TM_RPROFILE
which could be set to the path to your .Rprofile file.
I just hacked this into tmR.rb with just 2 lines of code. To implement this, go to ~/Library/Application Support/TextMate/Pristine Copy/Bundles/ and Show the Contents of R.tmbundle
In there, you'll find support/tmR.rb
in my version, near line 112, you should change
tmpDir = File.join(ENV['TMP'] || "/tmp", "TM_R")
recursive_delete(tmpDir) if File.exists?(tmpDir) # remove the temp dir if it's already there
Dir::mkdir(tmpDir)
# Mechanism for dynamic reading
# stdin, stdout, stderr = popen3("R", "--vanilla", "--no-readline", "--slave", "--encoding=UTF-8")
stdin, stdout, stderr, pid = my_popen3("R --vanilla --slave --encoding=UTF-8 2>&1")
# init the R slave
stdin.puts(%{options(device="pdf")})
stdin.puts(%{options(repos="#{cran}")})
to
tmpDir = File.join(ENV['TMP'] || "/tmp", "TM_R")
recursive_delete(tmpDir) if File.exists?(tmpDir) # remove the temp dir if it's already there
Dir::mkdir(tmpDir)
rprofile = (ENV['TM_RPROFILE'] == nil) ? "" : "source('" + ENV['TM_RPROFILE'] + "')"
# Mechanism for dynamic reading
# stdin, stdout, stderr = popen3("R", "--vanilla", "--no-readline", "--slave", "--encoding=UTF-8")
stdin, stdout, stderr, pid = my_popen3("R --vanilla --slave --encoding=UTF-8 2>&1")
# init the R slave
stdin.puts("#{rprofile}")
stdin.puts(%{options(device="pdf")})
stdin.puts(%{options(repos="#{cran}")})
Just added 2 lines there... the one that begins "rprofile =" and the one that includes "#{rprofile}"
-Wil

Resources