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
Interacting with R GUI app from another Cocoa app
6 messages · Guillaume Chapron, Neil Tiffin, Christian Prinoth +1 more
On Nov 29, 2009, at 9:29 AM, Guillaume Chapron wrote:
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];
You might try to write the results into a file and read it back in R. This is probably safer anyway.
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?
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.
You might try to write the results into a file and read it back in R. This is probably safer anyway.
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.
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.
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:
You might try to write the results into a file and read it back in R. This is probably safer anyway.
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.
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.
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?
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.
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.
I would guess that writing to a file and importing into R would be much faster than using Applescript.
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.
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.
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
-----Original Message----- From: r-sig-mac-bounces at stat.math.ethz.ch [mailto:r-sig-mac-bounces at stat.math.ethz.ch] On Behalf Of Neil Tiffin Sent: 29 November, 2009 21:16 To: Guillaume Chapron Cc: r-sig-mac at stat.math.ethz.ch Subject: Re: [R-SIG-Mac] Interacting with R GUI app from another Cocoa app You might try to write the results into a file and read it back in R. This is probably safer anyway.
DISCLAIMER:\ L'utilizzo non autorizzato del presente mes...{{dropped:16}}
Guillaume,
On Nov 29, 2009, at 10:29 , Guillaume Chapron wrote:
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.
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).
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?
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.
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?
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