All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feedzai.fos.impl.r.rserve.FosRserve Maven / Gradle / Ivy

/*
 * $#
 * FOS R implementation
 *  
 * Copyright (C) 2013 Feedzai SA
 *  
 * This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
 * Lesser General Public License version 3 (the "GPL License"). You may choose either license to govern
 * your use of this software only upon the condition that you accept all of the terms of either the Apache
 * License or the LGPL License.
 *
 * You may obtain a copy of the Apache License and the LGPL License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0.txt
 * http://www.gnu.org/licenses/lgpl-3.0.txt
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the Apache License
 * or the LGPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the Apache License and the LGPL License for the specific language governing
 * permissions and limitations under the Apache License and the LGPL License.
 * #$
 */

package com.feedzai.fos.impl.r.rserve;

import com.feedzai.fos.api.FOSException;
import com.google.common.io.Files;
import org.apache.commons.io.Charsets;
import org.rosuda.REngine.REXP;
import org.rosuda.REngine.REXPMismatchException;
import org.rosuda.REngine.REngineException;
import org.rosuda.REngine.Rserve.RConnection;
import org.rosuda.REngine.Rserve.RserveException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.List;

/**
 * This library was tested in Linux and Windows with R-2.15.1.
 * In either systems, R must be globally available in the include path.
 * (in Widows you need to add the R bin directory to the "Path" system variable)
 *
 * A previously running RServe process must be running before using this package
 *
 * To install Rserve open a command line, start R and type install.packages("Rserve").
 *
 * After Rserve has been installed sucessfully, start a rserve daemon using the following command line
 * R --no-save --slave -e "library(Rserve);Rserve(args='--no-save --slave');"
 *
 *
 * @author rafael.marmelo
 * @author miguel.duarte
 * @since 1.0.2
 */
public class FosRserve implements FosRServeAPI {
    private static Process rProcess;
    private RConnection connection;
    Logger logger = LoggerFactory.getLogger(FosRserve.class);

    /**
     * Create a new R communication handle spawning a new RServe process if necessary
     *
     * @throws FOSException
     */
    public FosRserve() throws FOSException {
        try {
            this.connection = new RConnection();
        } catch (RserveException e) {
            throw new FOSException(e);
        }
    }



    @Override
    public void load(String script) throws FOSException {
        try {
            File file = new File(script);

            if (!file.exists()) {
                throw new FOSException("Error loading script '" + script + "' into R (script not found).");
            }

            if (!file.isFile()) {
                throw new FOSException("Error loading script '" + script + "' into R (unsupported file type).");
            }

            // read file
            String contents = Files.toString(new File(script), Charsets.UTF_8);
            // strip all CR because R in Windows does not like them
            contents = contents.replaceAll("\r\n", "\n");

            // evaluate script
            eval(contents);
        } catch (IOException e) {
            throw new FOSException("Error loading script '" + script + "' into R.", e);
        }
    }

    @Override
    public  T eval(String command) throws FOSException {
        try {
            if(logger.isTraceEnabled()) {
                logger.trace(command);
            }

            connection.assign("trycodeblock", command);

            REXP result = connection.parseAndEval("try(eval(parse(text=trycodeblock)),silent=TRUE)");
            if (result != null && result.inherits("try-error")) {
                throw new FOSException(result.asString());
            }
            if (result == null || result.isNull()) {
                return null;
            } else if( result.isVector() && result.isNumeric()) {
              return (T) result.asDoubles();
            } else if (result.isInteger()) {
                return (T) new Integer(result.asInteger());
            } else if (result.isNumeric()) {
                return (T) new Double(result.asDouble());
            } else if (result.isString()) {
                return (T) new String(result.asString());
            }



            return null;
        } catch (REngineException e) {
            throw new FOSException("Error executing R script.", e);
        } catch (REXPMismatchException e) {
            throw new FOSException("Error executing R script.", e);
        }
    }

    @Override
    public void reset() throws FOSException {
        eval("rm(list = ls(all = TRUE))");
    }

    @Override
    public void close() throws FOSException {
        if (connection != null && connection.isConnected()) {
            connection.close();
        }
    }

    @Override
    public void shutdown() throws FOSException {
        if (connection != null && connection.isConnected()) {
            try {
                connection.shutdown();
            } catch (RserveException e) {
                throw new FOSException("Error shutting down R server.", e);
            }
        }
    }

    @Override
    public void assignStringList(String varname, String rEnvironment, List values) throws FOSException {
        StringBuilder sb = new StringBuilder();

        sb.append(rEnvironment)
          .append('$')
          .append(varname)
          .append(" <- c(\n");
        boolean addComma = false;

        int i = 0;
        while(i < values.size() - 1) {
            sb.append("   '").append(values.get(i++)).append("',\n");
        }
        sb.append("   '").append(values.get(i)).append("')");


        eval(sb.toString());
    }

    @Override
    public void assignIntList(String varname, String rEnvironment, List values) throws FOSException {
        StringBuilder sb = new StringBuilder();

        sb.append(rEnvironment)
                .append('$')
                .append(varname)
                .append(" <- c(\n");
        boolean addComma = false;

        int i = 0;
        while(i < values.size() - 1) {
            sb.append("   ").append(values.get(i++)).append(",\n");
        }
        sb.append("   ").append(values.get(i)).append(")");

        eval(sb.toString());
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy