/*
* Copyright (c) 2009 The Jackson Laboratory
*
* This software was developed by Gary Churchill's Lab at The Jackson
* Laboratory (see http://research.jax.org/faculty/churchill).
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jax.r.jriutilities;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.jax.r.RException;
import org.jax.r.RUtilities;
import org.rosuda.JRI.REXP;
import org.rosuda.JRI.RFactor;
/**
* Some commonly used utility functions
* @author <A HREF="mailto:keith.sheppard@jax.org">Keith Sheppard</A>
*/
// TODO do some meging/cleanup with RUtilities
public class JRIUtilityFunctions
{
/**
* The command for listing objects.
*/
private static final String IDENTIFIERS_LIST_COMMAND = "ls()";
/**
* Determine if the given {@link RObject} counts as a top level object
* @param rObject
* the object to test
* @return
* true iff its a top level object in R
*/
public static boolean isTopLevelObject(RObject rObject)
{
return JRIUtilityFunctions.isTopLevelObject(
rObject.getAccessorExpressionString(),
rObject.getRInterface());
}
/**
* Similar to {@link #isTopLevelObject(RObject)}
* @param accessorString
* the accessor string to test
* @param rInterface
* the R interface to use
* @return
* true if the object exists in the current environment
*/
public static boolean isTopLevelObject(
String accessorString,
RInterface rInterface)
{
String existsExpressionString =
"exists(\"" + accessorString + "\")";
REXP existsExpression = rInterface.evaluateCommand(
new SilentRCommand(existsExpressionString));
return existsExpression.asBool().isTRUE();
}
/**
* Get a list of all R identifiers in scope.
* @param rInterface
* the r interface to use
* @return
* the available identifiers
* @throws RException
* the r exception
*/
public static List<RObject> getTopLevelObjects(RInterface rInterface)
throws RException
{
// get a listing of all identifiers
REXP idsExpression = rInterface.evaluateCommand(new SilentRCommand(
IDENTIFIERS_LIST_COMMAND));
String[] ids = idsExpression.asStringArray();
ArrayList<RObject> rObjects = new ArrayList<RObject>(ids.length);
for(String currId: ids)
{
rObjects.add(new RObject(rInterface, currId));
}
return rObjects;
}
/**
* Get all identifiers in scope with the given type
* @param rInterface
* the R interface to use
* @param type
* the type to look for
* @return
* a list of matches
* @throws RException
* if we run into problems with the R interface
*/
public static List<RObject> getTopLevelObjectsOfType(
RInterface rInterface,
String type)
throws RException
{
// 1st get a list of all the id's... then filter by type
List<RObject> topLevelRObjects = JRIUtilityFunctions.getTopLevelObjects(
rInterface);
Iterator<RObject> objIter = topLevelRObjects.iterator();
while(objIter.hasNext())
{
RObject currRObj = objIter.next();
// filter this identifier out of the list if it isn't the right
// type
if(!JRIUtilityFunctions.inheritsRClass(currRObj, type))
{
objIter.remove();
}
}
return topLevelRObjects;
}
/**
* Return the result of "names(...)" on the given object.
* @param rObject
* the object to run names on
* @return
* the names
*/
public static String[] getNames(RObject rObject)
{
String namesExpressionString =
"names(" + rObject.getAccessorExpressionString() + ")";
REXP namesResult = rObject.getRInterface().evaluateCommand(
new SilentRCommand(namesExpressionString));
if(namesResult == null)
{
return null;
}
else
{
return namesResult.asStringArray();
}
}
/**
* The R equivalent of instanceof.
* @param rObject
* the R object
* @param rClassName
* the R class
* @return
* true iff the object inherits the given class type
*/
public static boolean inheritsRClass(
RObject rObject,
String rClassName)
{
String inheritsClassExpressionString =
"inherits(" + rObject.getAccessorExpressionString() + ", \"" +
rClassName + "\")";
REXP inheritsResult = rObject.getRInterface().evaluateCommand(
new SilentRCommand(inheritsClassExpressionString));
return inheritsResult.asBool().isTRUE();
}
/**
* Get the column names for the given matrix object
* @param rMatrix
* the matrix
* @return
* the column names
*/
public static String[] getColumnNames(
RObject rMatrix)
{
String namesExpressionString =
"colnames(" + rMatrix.getAccessorExpressionString() + ")";
REXP namesResult = rMatrix.getRInterface().evaluateCommand(
new SilentRCommand(namesExpressionString));
if(namesResult == null)
{
return null;
}
else
{
return namesResult.asStringArray();
}
}
/**
* Get the row names for the given matrix object
* @param rMatrix
* the matrix
* @return
* the row names
*/
public static String[] getRowNames(
RObject rMatrix)
{
String namesExpressionString =
"rownames(" + rMatrix.getAccessorExpressionString() + ")";
REXP namesResult = rMatrix.getRInterface().evaluateCommand(
new SilentRCommand(namesExpressionString));
if(namesResult == null)
{
return null;
}
else
{
return namesResult.asStringArray();
}
}
/**
* Get the number of rows in the matrix
* @param rMatrix
* the matrix
* @return
* the number of rows
*/
public static int getNumberOfRows(
RObject rMatrix)
{
String numRowsExpression =
"nrow(" + rMatrix.getAccessorExpressionString() + ")";
REXP numRowsResult = rMatrix.getRInterface().evaluateCommand(
new SilentRCommand(numRowsExpression));
return numRowsResult.asInt();
}
/**
* Get the number of columns in the matrix
* @param rMatrix
* the matrix
* @return
* the number of columns
*/
public static int getNumberOfColumns(
RObject rMatrix)
{
String numColsExpression =
"ncol(" + rMatrix.getAccessorExpressionString() + ")";
REXP numColsResult = rMatrix.getRInterface().evaluateCommand(
new SilentRCommand(numColsExpression));
return numColsResult.asInt();
}
/**
* Get column double values from a matrix
* @param rMatrix
* the matrix to get the values from
* @param zeroBasedColumnIndex
* the zero based column index to use
* @return
* the double values
*/
public static double[] getColumnDoubles(
RObject rMatrix,
int zeroBasedColumnIndex)
{
String columnExpressionString = RUtilities.columnIndexExpression(
rMatrix.getAccessorExpressionString(),
zeroBasedColumnIndex);
REXP columnRExpression = rMatrix.getRInterface().evaluateCommand(
new SilentRCommand(columnExpressionString));
if(columnRExpression == null)
{
return null;
}
else
{
return columnRExpression.asDoubleArray();
}
}
/**
* Get column string values from a matrix
* @param rMatrix
* the matrix to get the values from
* @param zeroBasedColumnIndex
* the zero based column index to use
* @return
* the string values
*/
public static String[] getColumnStrings(
RObject rMatrix,
int zeroBasedColumnIndex)
{
String columnExpressionString = RUtilities.columnIndexExpression(
rMatrix.getAccessorExpressionString(),
zeroBasedColumnIndex);
REXP columnRExpression = rMatrix.getRInterface().evaluateCommand(
new SilentRCommand(columnExpressionString));
if(columnRExpression == null)
{
return null;
}
else
{
return columnRExpression.asStringArray();
}
}
/**
* Get row string values from a matrix
* @param rMatrix
* the matrix to get the values from
* @param zeroBasedRowIndex
* the zero based row index to use
* @return
* the string values
*/
public static String[] getRowStrings(
RObject rMatrix,
int zeroBasedRowIndex)
{
String rowExpressionString = RUtilities.rowIndexExpression(
rMatrix.getAccessorExpressionString(),
zeroBasedRowIndex);
REXP rowRExpression = rMatrix.getRInterface().evaluateCommand(
new SilentRCommand(rowExpressionString));
if(rowRExpression == null)
{
return null;
}
else
{
return rowRExpression.asStringArray();
}
}
/**
* Get column factors as a string array from the given matrix
* @param rMatrix
* the R matrix that we're getting the factor from
* @param zeroBasedColumnIndex
* the column to get the factor from
* @return
* the factors as strings
*/
public static String[] getColumnFactors(
RObject rMatrix,
int zeroBasedColumnIndex)
{
String columnExpressionString = RUtilities.columnIndexExpression(
rMatrix.getAccessorExpressionString(),
zeroBasedColumnIndex);
REXP columnRExpression = rMatrix.getRInterface().evaluateCommand(
new SilentRCommand(columnExpressionString));
if(columnRExpression == null)
{
return null;
}
else
{
return JRIUtilityFunctions.extractStringArrayFromFactor(
columnRExpression);
}
}
/**
* Convert the given R expression into an integer array
* @param rExpression
* the expression to convert
* @return
* the int array with NA's converted to nulls
*/
public static Integer[] extractIntegerValues(REXP rExpression)
{
double[] expressionAsDoubles = rExpression.asDoubleArray();
Integer[] expressionAsIntObjects = new Integer[expressionAsDoubles.length];
for(int i = 0; i < expressionAsDoubles.length; i++)
{
if(Double.isNaN(expressionAsDoubles[i]))
{
expressionAsIntObjects[i] = null;
}
else
{
expressionAsIntObjects[i] = Integer.valueOf(
(int)expressionAsDoubles[i]);
}
}
return expressionAsIntObjects;
}
/**
* Convert the given R expression into an integer
* @param rExpression
* the expression to convert
* @return
* the integer (or null if it's an NA)
*/
public static Integer extractIntegerValue(REXP rExpression)
{
double value = rExpression.asDouble();
if(Double.isNaN(value))
{
return null;
}
else
{
return Integer.valueOf((int)value);
}
}
/**
* Convert the given R expression into a double array
* @param rExpression
* the expression to convert
* @return
* the double array with NA's converted to nulls
*/
public static Double[] extractDoubleValues(REXP rExpression)
{
double[] expressionAsDoubles = rExpression.asDoubleArray();
Double[] expressionAsDoubleObjects = new Double[expressionAsDoubles.length];
for(int i = 0; i < expressionAsDoubles.length; i++)
{
if(Double.isNaN(expressionAsDoubles[i]))
{
expressionAsDoubleObjects[i] = null;
}
else
{
expressionAsDoubleObjects[i] = Double.valueOf(
expressionAsDoubles[i]);
}
}
return expressionAsDoubleObjects;
}
/**
* Extract a string array from the given factor expression
* @param factorRExpression
* the factor expression
* @return
* the string array
* @throws IllegalArgumentException
* if the given R expression isn't a factor
*/
public static String[] extractStringArrayFromFactor(REXP factorRExpression)
throws
IllegalArgumentException
{
RFactor factor = factorRExpression.asFactor();
int factorSize = factor.size();
String[] factorStrings = new String[factorSize];
for(int i = 0; i < factorSize; i++)
{
factorStrings[i] = factor.at(i);
}
return factorStrings;
}
/**
* Extract boolean values from the given r expression
* @param rExpression
* the R expression that contains the boolean array
* @return
* the boolean array
*/
public static boolean[] extractBooleanValues(REXP rExpression)
{
int[] expressionAsInts = rExpression.asIntArray();
boolean[] expressionAsBools = new boolean[expressionAsInts.length];
for(int i = 0; i < expressionAsInts.length; i++)
{
expressionAsBools[i] = (expressionAsInts[i] == 1);
}
return expressionAsBools;
}
/**
* Create a unique identifier that starts with the given string
* @param rInterface
* the R Interface to use
* @param startingIdentifier
* the starting string to use
* @return
* the unique id that starts with the starting identifier
*/
public static String createUniqueIdentifier(
RInterface rInterface,
String startingIdentifier)
{
startingIdentifier = startingIdentifier.trim();
if(startingIdentifier.length() == 0)
{
startingIdentifier = "object";
}
String candidateIdentifier = startingIdentifier;
RObject candidateRObject = new RObject(rInterface, candidateIdentifier);
for(int i = 0;
JRIUtilityFunctions.isTopLevelObject(candidateRObject);
i++)
{
candidateIdentifier = startingIdentifier + i;
candidateRObject = new RObject(rInterface, candidateIdentifier);
}
return candidateIdentifier;
}
/**
* Find out if the R object referenced by the given ID is null
* @param rObject
* the R object we're checking for null
* @return
* true iff the given identifier is null
*/
public static boolean isNull(RObject rObject)
{
return isNull(
rObject.getRInterface(),
rObject.getAccessorExpressionString());
}
/**
* Find out if the R object referenced by the given ID is null
* @param rInterface
* the R interface to use
* @param identifier
* the identifier to check
* @return
* true iff the given identifier is null
*/
public static boolean isNull(
RInterface rInterface,
String identifier)
{
// we can use a null test to find out
REXP result = rInterface.evaluateCommand(new SilentRCommand(
"is.null(" + identifier + ')'));
return result.asBool().isTRUE();
}
}