Saturday, April 12, 2014

RCaller 2.2.0 has just been released

We have just uploaded the new compiled jar file of latest Rcaller, the simple library for calling R from within Java.

We plan to clean recently reported bugs, but the most important one was having some errors about the R package Runiversal, which is required by the library for generating XML files. The basic issue underlying this problem was the package storing policy of R which depends on the user that installed the package.

In the most recent version 2.2, users do not need to pre-install the R package Runiversal. Simply add RCaller-2.2.0-SNAPSHOT.jar to your classpath and go!

The download link of the compiled library is here [Google Driver Link]

The library is tested in a pc with Ubuntu OS installed and the usual test scenarios are success in all cases. The library has not been tested on Windows machines. 

Please use the link of Google code page at http://code.google.com/p/rcaller/issues/list and enter your problems in issues part and do not hesitate to contribute our library. 

19 comments:

  1. Hi... is RCaller available as a Maven Dependency?

    ReplyDelete
  2. I think no, at least we didn't make it available as a Maven dependency.

    ReplyDelete
  3. Hi ... Is there a way for me to use the same instance of R. I've a bunch of functionality for which I need to keep going to R but I don't want to lose the environment which loaded the required package etc. as that takes too much time.
    I did try the online run but it keeps getting into executable not found error whereas the regular run does go through.

    ReplyDelete
  4. did you try rcaller.setRExecutable(...) instead of rcaller.setRScriptExecutable() ? Because online running uses the R.exe rather than Rscript.exe

    ReplyDelete
  5. I'm trying RCaller in windows 8 with R 3.0.2 and throws me the following error: rcaller.exception.ParseException: Can not handle R results due to : rcaller.exception.ParseException: Can not parse output: The generated file C:\Users\yudiel\AppData\Local\Temp\Routput3294989421277770098 is empty

    ReplyDelete
    Replies
    1. there are thousands of situations that may produce this error. I can't say anything without seeing your code.

      Delete
  6. Do you know if it is in any way possible to stream the plot from R to Java without saving it in between? I am making an add-on for Vaadin framework for running R-scripts and I have been notified that this saving part is unpalatable for many people.

    ReplyDelete
    Replies
    1. This question has been already asked in stackoverflow

      http://stackoverflow.com/questions/23297478/streaming-plots-from-r-to-java-without-saving-the-plot/23337754#23337754

      and I answered the question. Have you seen it?

      Delete
  7. Ah, OK. Yeah, I have seen it. I was hoping I could get more info from here, but it doesn't matter. When it comes to grid.cap, it is my guess, that even if it would work the needed computations would still take longer than the actual writing to the file part. I guess I have to go with that.

    Another issue is how to delete the generated R codes the Rcaller saves to temp, but I try to think of something.

    Thank you for the answer, here and in stackoverflow.

    ReplyDelete
    Replies
    1. Welcome again! My recent answer in stackoverflow is complete and I have nothing more to say.
      You are right about the grid.cap, it consumes to much time to generate a pixel matrix with string
      values.

      I plan to add a functionality in next release about auto-cleaning of temporary files created by RCaller.
      Since these files are necessary for debugging issues, auto-clean functionality should be optionally turned on by the user.


      However, they have common prefix strings, which is rcaller for source codes, rouput for generated content and plot for graphics. Somebody on the internet writes user-functions to clean them periodicaly.

      Thank you for interest on RCaller.

      Delete
  8. thanks, this is the java class I am using to test is run in the same class Debian 7 R 2.15 and it works but when I run on Windows 8 with R 3.0.2 and devulve me the error:

    Class:

    import rcaller.Globals;
    import rcaller.RCaller;
    import rcaller.RCode;
    import rcaller.exception.ExecutionException;

    /**
    *
    * @author
    */
    public class RTest {

    public RTest() {
    }

    public void analysisR() {
    try {
    /*
    * Creating RCaller
    */
    RCaller caller = new RCaller();
    Globals.detect_current_rscript();
    caller.setRscriptExecutable(Globals.Rscript_current);
    RCode code = new RCode();
    code.clear();

    /*
    * Adding R Code
    */
    code.addRCode("rowSummaryArpncerlx <- c(\"Frequency phenotypic males:\", \"Frequency of recessive allele:\", \"Frequency of dominant allele:\", \"Frequency of female carriers in the population:\", \"Frequency of homozygous dominant women affected population:\")");
    code.addRCode("result <- c(0.6, 0.1, 0.3, 0.2, 0.1)");
    code.addRCode("SummaryArpncerlx <- round(as.matrix(result), 4)");
    code.addRCode("rownames(SummaryArpncerlx) <- rowSummaryArpncerlx");
    code.addRCode("result<-list(rowSummaryArpncerlx = rowSummaryArpncerlx, SummaryArpncerlx = SummaryArpncerlx)");

    /*
    * We want to handle the list 'my.all'
    */
    caller.setRCode(code);
    caller.runAndReturnResult("result");
    String resultAnalysisR = "";

    String[] results = caller.getParser().getAsStringArray("SummaryArpncerlx");

    String[] resultsNames = caller.getParser().getAsStringArray("rowSummaryArpncerlx");
    int cant = 0;
    for (int i = 0; i < results.length; i++) {
    if (cant != 0) {
    resultAnalysisR += "\n\n";
    }
    resultAnalysisR += resultsNames[i] + results[i];
    cant++;
    }
    System.out.print(resultAnalysisR);

    } catch (ExecutionException e) {
    e.printStackTrace();
    }
    }

    public static void main(String args[]) {
    RTest t = new RTest();
    t.analysisR();
    }

    }

    Error:
    rcaller.exception.ParseException: Can not handle R results due to : rcaller.exception.ParseException: Can not parse output: The generated file C:\Users\yudiel\AppData\Local\Temp\Routput213789758875866588 is empty

    ReplyDelete
    Replies
    1. Your code produces the output:

      Frequency phenotypic males:0.6

      Frequency of recessive allele:0.1

      Frequency of dominant allele:0.3

      Frequency of female carriers in the population:0.2

      Frequency of homozygous dominant women affected population:0.1

      is this output correct? if yes, I tried it using latest release of RCaller 2.2.
      The download link is provided in this blog entry.

      Delete
  9. if the output is correct, but it worked in windows, because I already have downloaded RCaller 2.2 from the link you have on this blog and it works in debian but not in windows 8 with R 3.0.2 installed, you need something specific installed part of Java and R
    thanks

    ReplyDelete
    Replies
    1. sorry, I didn't understand you last message. The output given in my last post was generated on a Win 8 machine with R 3.0.2 installed. Please try more simple examples to debug what is going on.

      Delete
  10. Excuse me, let me explain myself better, I have included the class on a project with RCaller 2.2.0, I run on a PC with Debian 7 having installed R 2.15 and JDK 1.7 and the output is correct. But if I run it on another PC with Windows 8 having R 3.0.2 and JDK 1.7 installed gives me the error:
    rcaller.exception.ParseException: Can not handle R results due to: rcaller.exception.ParseException: Can not parse output: The generated file C: \ Users \ Yudiel \ AppData \ Local \ Temp \ Routput2210372873021502516 is empty

    I need to know whether to install something besides Java and R to function properly and if you know where you can download the source code RCaller 2.2.0

    ReplyDelete
    Replies
    1. Ok, you do not need to install additional software for RCaller 2.2 on both linux and windows.

      You can reach the source code in page http://www.mhsatman.com/rcaller

      Good luck.

      Delete
  11. I already found the problem, this is given to making use of Globals.detect_current_rscript ();
    Globals.Rscript_current ;
    for R executable according to the distribution of this returned me " C: \ Program Files \ R \ R- 3.0.2 \ bin \ Rscript.exe " until all well here because the file exists but for some reason not using it get no results , now the operating system I have is 64 bits and probe caller.setRscriptExecutable ("C: \ \ Program Files \ \ R \ \ R- 3.0.2 \ \ bin \ \ x64 \ \ Rscript.exe " ) ; and I return the correct result.

    Reviewing the source code RCaller 2.2 rcaller.Globals see that in the static class attributes are defined as acontinuaciĆ³n show :

    public static String RScript_Windows = "C : \ \ Program Files \ \ R \ \ R- 3.0.2 \ \ bin \ \ Rscript.exe " ;
    public static String RScript_Linux = "/ usr / bin / RSCRIPT " ;
    public static String Rscript_current ;
    public static String R_Windows = "C : \ \ Program Files \ \ R \ \ R- 3.0.2 \ \ bin \ \ r.exe " ;
    public static String R_Linux = "/ usr / bin / R" ;
    public static String R_current ;

    In linux works perfect for any version of R , probe on Debian 7.

    Now the problem is in Windows because it is static for a specific R version and architecture ( 64bit or 32bit ) specifies .

    I 'm editing this class work for these parameters dynamically carge then sent it to the authors to value include the changes.

    ReplyDelete
  12. As promised and solved the problem of identifying the version of R that is installed on windows and directory, the solution I've been using the 15 days, I installed R in different directories, installing R probe for 32bit and 64bit R and runs perfection. Well no more I leave the solution is very simple but it is still functional.

    RCaller modified global class:

    package cu.seegenr.useful;

    import graphics.DefaultTheme;
    import graphics.GraphicsTheme;
    import java.lang.reflect.InvocationTargetException;
    import java.util.ArrayList;
    import java.util.logging.Level;
    import java.util.logging.Logger;

    public class Globals {

    public static String cranRepos = "http://cran.r-project.org";
    public static String RScript_Windows = getRInstallPath() + "Rscript.exe";
    public static String RScript_Linux = "/usr/bin/Rscript";
    public static String Rscript_current = get_current_rscript().get(0);
    public static String R_Windows = getRInstallPath() + "R.exe";
    public static String R_Linux = "/usr/bin/R";
    public static String R_current = get_current_rscript().get(1);

    public static GraphicsTheme theme = new DefaultTheme();

    public final static String version = "RCaller 2.0";
    public final static String about = "Author: Mehmet Hakan Satman - mhsatman@yahoo.com";
    public final static String licence = "LGPL v3.0";

    public static void detect_current_rscript() {
    if (System.getProperty("os.name").contains("Windows")) {
    Rscript_current = RScript_Windows;
    R_current = R_Windows;
    } else {
    Rscript_current = RScript_Linux;
    R_current = R_Linux;
    }
    }

    public static ArrayList get_current_rscript() {
    ArrayList r = new ArrayList();
    if (System.getProperty("os.name").contains("Windows")) {
    Rscript_current = getRInstallPath() + "Rscript.exe";
    r.add(Rscript_current);
    R_current = getRInstallPath() + "R.exe";
    r.add(R_current);
    } else {
    Rscript_current = RScript_Linux;
    r.add(Rscript_current);
    R_current = R_Linux;
    r.add(R_current);
    }
    return r;
    }

    public static String getRInstallPath() {
    try {
    if (System.getProperty("os.name").contains("Windows")) {
    String value = WinRegistry.readString(
    WinRegistry.HKEY_LOCAL_MACHINE, //HKEY
    "SOFTWARE\\R-core\\R", //Key
    "InstallPath"); //ValueName
    if (value != null) {
    return value + "\\bin\\x64\\";
    } else {
    String value2 = WinRegistry.readString(
    WinRegistry.HKEY_LOCAL_MACHINE, //HKEY
    "SOFTWARE\\Wow6432Node\\R-core\\R", //Key
    "InstallPath"); //ValueName
    if (value2 != null) {
    return value + "\\bin\\i386\\";
    }
    }
    } else {
    return null;
    }
    } catch (IllegalArgumentException ex) {
    Logger.getLogger(Globals.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalAccessException ex) {
    Logger.getLogger(Globals.class.getName()).log(Level.SEVERE, null, ex);
    } catch (InvocationTargetException ex) {
    Logger.getLogger(Globals.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
    }
    }

    ReplyDelete
  13. New helper class.

    package cu.seegenr.useful;

    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.prefs.Preferences;

    public class WinRegistry {

    public static final int HKEY_CURRENT_USER = 0x80000001;
    private static final int KEY_READ = 0x20019;
    private static final Preferences userRoot = Preferences.userRoot();
    private static final Preferences systemRoot = Preferences.systemRoot();
    private static Method regOpenKey = null;
    private static Method regCloseKey = null;
    private static Method regQueryValueEx = null;

    public static final int HKEY_LOCAL_MACHINE = 0x80000002;
    public static final int REG_SUCCESS = 0;
    private static final Class userClass = userRoot.getClass();

    static {
    try {
    regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey",
    new Class[]{int.class, byte[].class, int.class});
    regOpenKey.setAccessible(true);
    regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey",
    new Class[]{int.class});
    regCloseKey.setAccessible(true);
    regQueryValueEx = userClass.getDeclaredMethod("WindowsRegQueryValueEx",
    new Class[]{int.class, byte[].class});
    regQueryValueEx.setAccessible(true);
    // regCreateKeyEx = userClass.getDeclaredMethod(
    // "WindowsRegCreateKeyEx", new Class[]{int.class,
    // byte[].class});
    // regCreateKeyEx.setAccessible(true);
    } catch (NoSuchMethodException e) {
    e.printStackTrace();
    } catch (SecurityException e) {
    e.printStackTrace();
    }
    }

    private WinRegistry() {
    }

    /**
    * Read a value from key and value name
    *
    * @param hkey HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE
    * @param key
    * @param valueName
    * @return the value
    * @throws IllegalArgumentException
    * @throws IllegalAccessException
    * @throws InvocationTargetException
    */
    public static String readString(int hkey, String key, String valueName)
    throws IllegalArgumentException, IllegalAccessException,
    InvocationTargetException {
    if (hkey == HKEY_LOCAL_MACHINE) {
    return readString(systemRoot, hkey, key, valueName);
    } else if (hkey == HKEY_CURRENT_USER) {
    return readString(userRoot, hkey, key, valueName);
    } else {
    throw new IllegalArgumentException("hkey=" + hkey);
    }
    }

    private static String readString(Preferences root, int hkey, String key, String value)
    throws IllegalArgumentException, IllegalAccessException,
    InvocationTargetException {
    int[] handles = (int[]) regOpenKey.invoke(root, new Object[]{
    hkey, toCstr(key), KEY_READ});
    if (handles[1] != REG_SUCCESS) {
    return null;
    }
    byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[]{
    handles[0], toCstr(value)});
    regCloseKey.invoke(root, new Object[]{handles[0]});
    return (valb != null ? new String(valb).trim() : null);
    }

    // utility
    private static byte[] toCstr(String str) {
    byte[] result = new byte[str.length() + 1];

    for (int i = 0; i < str.length(); i++) {
    result[i] = (byte) str.charAt(i);
    }
    result[str.length()] = 0;
    return result;
    }

    }

    Ideally, the solution is added to RCaller by developers but meanwhile we can use this.

    ReplyDelete

Thanks