/*
* Copyright (c) 2010 The Jackson Laboratory
*
* 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.maanova.test;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jax.maanova.madata.MicroarrayExperiment;
import org.jax.maanova.madata.ProbesetRow;
import org.jax.maanova.test.gui.TestStatisticItem;
import org.jax.r.RCommand;
import org.jax.r.RCommandParameter;
import org.jax.r.RMethodInvocationCommand;
import org.jax.r.RUtilities;
import org.jax.r.jriutilities.JRIUtilityFunctions;
import org.jax.r.jriutilities.RInterface;
import org.jax.r.jriutilities.RObject;
import org.jax.r.jriutilities.SilentRCommand;
import org.rosuda.JRI.REXP;
/**
* Class that acts as a wrapper around an R/maanova matest object
* @author <A HREF="mailto:keith.sheppard@jax.org">Keith Sheppard</A>
*/
public class MaanovaTestResult extends RObject
{
/**
* our logger
*/
private static final Logger LOG = Logger.getLogger(
MaanovaTestResult.class.getName());
/**
* This is the name that R/maanova assigns to the underlying R type.
*/
private static final String R_CLASS_STRING = "matest";
private static final String FOLD_CHANGE_VALS_METHOD = "calVolcanoXval";
private static final String PROBESET_ID_COMPONENT = "$probeid";
private final MicroarrayExperiment parentExperiment;
private volatile TestType testType = null;
/**
* Constructor
* @param parentExperiment
* the parent experiment for this test result
* @param accessorExpressionString
* the accessor expression
*/
public MaanovaTestResult(
MicroarrayExperiment parentExperiment,
String accessorExpressionString)
{
super(parentExperiment.getRInterface(), accessorExpressionString);
this.parentExperiment = parentExperiment;
}
/**
* Get the test type for this test result
* @return the test type
*/
public TestType getTestType()
{
if(this.testType == null)
{
if(JRIUtilityFunctions.inheritsRClass(this, TestType.T_TEST.getRParameterString()))
{
this.testType = TestType.T_TEST;
}
else if(JRIUtilityFunctions.inheritsRClass(this, TestType.F_TEST.getRParameterString()))
{
this.testType = TestType.F_TEST;
}
}
return this.testType;
}
/**
* Get all of the top-level R objects whose class is {@value #R_CLASS_STRING}
* @param rInterface
* the R interface to extract the objects from
* @return
* the R objects of type {@value #R_CLASS_STRING}
*/
public static List<RObject> getAllMaanovaTestRObjects(RInterface rInterface)
{
List<RObject> fitIdentifiers = JRIUtilityFunctions.getTopLevelObjectsOfType(
rInterface,
R_CLASS_STRING);
if(LOG.isLoggable(Level.FINEST))
{
StringBuffer message = new StringBuffer(
"detected fit data objects:");
for(RObject currFitId: fitIdentifiers)
{
message.append(" " + currFitId.getAccessorExpressionString());
}
LOG.finest(message.toString());
}
return fitIdentifiers;
}
/**
* Getter for the parent experiment
* @return the parent experiment
*/
public MicroarrayExperiment getParentExperiment()
{
return this.parentExperiment;
}
/**
* Get the fold change (x coordinates) that should be used in a
* volcano plot. Note that the x-values should be the same no matter what
* statistic is chosen
* @param plotIndex
* the index of the plot (t-tests will have one plot per
* contrast row, f-tests will have a single plot)
* @return
* the coordinates
*/
public Double[] getFoldChangeValues(int plotIndex)
{
RMethodInvocationCommand fcValsMethod = new RMethodInvocationCommand(
FOLD_CHANGE_VALS_METHOD,
new RCommandParameter(this.getAccessorExpressionString()));
final RCommand rCmd;
switch(this.getTestType())
{
case F_TEST:
{
// cbind does nothing if the arg is already a matrix and if it is a
// vector it turns the vector into a single column matrix. we need
// this because the f-test gets a vector
RMethodInvocationCommand vecFcValsMethod = new RMethodInvocationCommand(
"as.vector",
new RCommandParameter(fcValsMethod.getCommandText()));
rCmd = new SilentRCommand(vecFcValsMethod);
}
break;
case T_TEST:
{
// cbind does nothing if the arg is already a matrix and if it is a
// vector it turns the vector into a single column matrix. we need
// this because the f-test gets a vector
RMethodInvocationCommand matFcValsMethod = new RMethodInvocationCommand(
"cbind",
new RCommandParameter(fcValsMethod.getCommandText()));
String indexedFcVals = RUtilities.columnIndexExpression(
matFcValsMethod.getCommandText(),
plotIndex);
rCmd = new SilentRCommand(indexedFcVals);
}
break;
default: throw new IllegalStateException(
"Failed to determine if this is a t-test or f-test");
}
REXP vals = this.getRInterface().evaluateCommand(rCmd);
return JRIUtilityFunctions.extractDoubleValues(vals);
}
/**
* Get statistics for the given statistic type
* @param statType
* the statistic type
* @return
* the statistics
*/
public MaanovaTestStatistics getStatistics(MaanovaTestStatisticType statType)
{
String statComponent =
this.getAccessorExpressionString() +
statType.getRComponentAccessorString();
boolean statComponentIsNull = JRIUtilityFunctions.isNull(
this.getRInterface(),
statComponent);
if(statComponentIsNull)
{
return null;
}
else
{
return new MaanovaTestStatistics(this.getRInterface(), statComponent);
}
}
/**
* Get the statistics values for the given test statistic item and
* contrast index
* @param testStatisticItem
* the statistic we want
* @param contrastIndex
* the contrast index we want
* @return
* the results
*/
public Double[] getStatisticsValues(
TestStatisticItem testStatisticItem,
int contrastIndex)
{
MaanovaTestStatistics stats =
this.getStatistics(testStatisticItem.getTestStatisticType());
if(stats == null)
{
return null;
}
else
{
return stats.getValues(
testStatisticItem.getTestStatisticSubtype(),
contrastIndex);
}
}
/**
* Getter for the probeset ID strings
* @return
* the probeset ID strings
*/
public String[] getProbesetIds()
{
SilentRCommand probesetIdsCommand = new SilentRCommand(
this.probesetIdAcessor());
REXP probesetIdsExpr = this.getRInterface().evaluateCommand(
probesetIdsCommand);
return probesetIdsExpr.asStringArray();
}
/**
* Get the probeset ID at the given index
* @param probesetIndex
* the index
* @return the probeset ID string
*/
public String getProbesetId(int probesetIndex)
{
SilentRCommand probesetIdCommand = new SilentRCommand(
RUtilities.indexExpression(
this.probesetIdAcessor(),
probesetIndex));
REXP probesetIdsExpr = this.getRInterface().evaluateCommand(
probesetIdCommand);
return probesetIdsExpr.asString();
}
private String probesetIdAcessor()
{
// TODO correct this in R/maanova
// the as.character is necessary because read.madata sometimes
// results in integer rather than string data
return
"as.character(" +
this.getAccessorExpressionString() + PROBESET_ID_COMPONENT +
")";
}
/**
* Get the statistic value for the given test statistic item and
* contrast index
* @param probeIndex
* the probe index
* @param testStatisticItem
* the statistic we want
* @param contrastIndex
* the contrast index we want
* @return
* the results
*/
public Double getStatisticsValue(
int probeIndex,
TestStatisticItem testStatisticItem,
int contrastIndex)
{
MaanovaTestStatistics stats =
this.getStatistics(testStatisticItem.getTestStatisticType());
if(stats == null)
{
return null;
}
else
{
return stats.getValue(
probeIndex,
testStatisticItem.getTestStatisticSubtype(),
contrastIndex);
}
}
/**
* Getter for the probeset row
* @param probesetIndex
* the probeset index
* @param contrastIndex
* the contrast index
* @param testStatistics
* the kind of statistics that we're looking for
* @return
* the probeset row
*/
public ProbesetRow getProbesetRow(
int probesetIndex,
int contrastIndex,
TestStatisticItem[] testStatistics)
{
String probesetId = this.getProbesetId(probesetIndex);
if(probesetId == null)
{
return null;
}
Double[] values = new Double[testStatistics.length];
for(int i = 0; i < values.length; i++)
{
values[i] = this.getStatisticsValue(
probesetIndex,
testStatistics[i],
contrastIndex);
if(values[i] == null)
{
return null;
}
}
return new ProbesetRow(probesetId, values, probesetIndex);
}
/**
* delete this test result from the R environment
*/
public void delete()
{
RMethodInvocationCommand rmMethod = new RMethodInvocationCommand(
"rm",
new RCommandParameter(this.getAccessorExpressionString()));
this.getRInterface().evaluateCommandNoReturn(rmMethod);
}
}