Skip to content

Interacting with R GUI app from another Cocoa app

6 messages · Guillaume Chapron, Neil Tiffin, Christian Prinoth +1 more

#
Hello,

I have a standalone simulation model written in Objective C/Cocoa. Once the simulations are done, I would like to send the output (a large C array) to R.app for further analysis and plotting. I'm able to launch R.app from a Cocoa app by this:

	[[NSWorkspace sharedWorkspace] launchApplication:@"R.app"];

But I'm not able to send the C array or in fact any kind of instructions. I have tried a modified code:

	NSBundle *bundle = [NSBundle bundleWithPath:@"/Applications/R.app"]; 
	NSString *path = [bundle executablePath];
	NSTask *task = [[NSTask alloc] init];
	
	[task setLaunchPath:path];
	[task setArguments:[NSArray arrayWithObject:@"2+3"]];
	[task launch];

But it seems that R.app does not understand the arguments of the NSTask. How from my Cocoa app, can I tell R.app to read a pointer to a C array and convert it to a R object, and how can I send R instructions?

Before I wrote the Objective C model as a dyn library and I could call it from R and run the simulations, but because simulations last hours, I cannot use R.app during that time, so I'm trying to do the reverse, interact with R from a Cocoa app once the simulations are done. Has anyone done something like that?

Thanks for any help!

Guillaume
#
On Nov 29, 2009, at 9:29 AM, Guillaume Chapron wrote:

            
You might try to write the results into a file and read it back in R.   
This is probably safer anyway.
Why not run the original dyn library simulation as another user, then  
the current user can do whatever they want with R?  To do this enable  
"fast user switching" in the "Accounts" preference.  Now you can leave  
a program running as one user and log in as another user to do  
something else.  Of course, you will need to create a 2nd user account.
#
This was my initial approach, but I expect a lot of overheads reading an array that can be as large as 100,000,000*10,000*100.

But did you mean that the Cocoa app should save its output as an R workspace? Is it possible to convert and save a C array into its equivalent in an R workspace?

While searching more on the web, I came across a post of someone wanting to export a C++ array to R, and Simon Urbanek replied "the short answer is no, you can't, because the memory has to be allocated by R". But R.app is Applescript enabled, so I should be able to tell R to create an array, and maybe later assign this object to the simulation output.
That would work, but that would not be very practicable, for example, I would need as many accounts as simulations I want to run at the same time.

Thanks for your help

Guillaume
#
On Nov 29, 2009, at 3:40 PM, Guillaume Chapron wrote:

            
Coding it should take at most, an hour, I would try it, you might be  
surprised.  Usually, I always code a working version then optimize  
it.  More than once, I have been surprised when the problem areas  
turned out to be completely different than I originally thought and I  
avoided a lot of additional complexity trying to solve a problem that  
did not exist.  If the simulation runs a few hours, spending a few  
more minutes reading and writing the results might be inconsequential.
You might follow this, http://developer.r-project.org/embedded.html to  
embed R into the Cocoa app.  I have no experience with this but it may  
lead you to something else.  You might also look at https://stat.ethz.ch/pipermail/r-sig-mac/2005-March/001706.html

Its possible to use interprocess communications to have R request the  
data from the Cocoa App.  However, there are a number of problems with  
this.  For example, the cocoa app has to be running.  When R is  
requesting the data it will be locked up waiting for the data.  You  
need to read state back and forth to know when to do what.  You will  
need to write an R extension in C, much the like the database  
extensions.  This seems like a lot of complexity to me.  In essence,  
your Cocoa GUI app would act like a database provider.

If R processing is segmenting the array at all, then you might be able  
to use a common database from both the Cocoa app and R.  A database  
just writes to a file with a lot more overhead, so if its not  
segmenting the array then you are probably better off reading a flat  
file as it all needs to be in memory at one time.
I would guess that writing to a file and importing into R would be  
much faster than using Applescript.
Then why not run R from the command line, you can have as many R  
instances running as you have machine (memory and CPUs), then use your  
original library version.
#
Some time ago I was exploring the general issue of "remote controlling"
R from different apps, eg Excel or Openoffice. Simon Urbanek suggested
using the clipboard (pasted from his post):

-- the easiest solution is to use clipboard and it's easily scriptable:

* select a table in Excel
* Copy (<Cmd><C>)
* switch to R and run
  read.table(pipe("pbpaste -"),T,"\t")

This appears to work fairly well, at least for me. You should probably
write a function copying your data to the clipboard.


Christian Prinoth <cp at epsilonsgr.it>
Epsilon SGR
+39-02-88102355
DISCLAIMER:\ L'utilizzo non autorizzato del presente mes...{{dropped:16}}
#
Guillaume,
On Nov 29, 2009, at 10:29 , Guillaume Chapron wrote:

            
R.app is a a LS app so it doesn't process command line arguments. You  
can talk to R.app using AppleScript (see the FAQ).
I think you're approaching this form the wrong end. You can load  
arbitrary C/Obj-C code into R (see R-ext) and that is how you can  
create R objects from C arrays (or rather you allocate the R object  
instead of using malloc). You can use the RController object to talk  
to the R.app GUI if you wish - e.g. you may be able to use the Cocoa  
package
http://rforge.net/Cocoa
to call Obj-C code such as issuing Obj-C messages from R.
There are two issues depending how you define "cannot use R.app".  
First, you should be calling R_CheckUserInterrupt() periodically to  
make sure your simulation doesn't block R and the GUI.

Second, if you really want to simulation to run entirely in parallel,  
you can simply create a separate thread in your simulation code such  
that your initialization function returns back to R as soon as all  
objects are preserved or copied so R can continue to work while your  
simulation is running on a separate thread. Then you can always check  
the objects from the R code to see if it has finished and yet you can  
safely work in parallel. The only restriction is that your threaded  
code may not call any R API functions as soon as it dispatches the new  
thread, but that's usually ok if you allocate the R objects before that.

Cheers,
Simon