/*
* 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.qtl.scan;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.jax.qtl.cross.Cross;
import org.jax.qtl.cross.CrossChromosome;
import org.jax.qtl.cross.GeneticMarker;
import org.jax.r.RAssignmentCommand;
import org.jax.r.RCommand;
import org.jax.r.RCommandParameter;
import org.jax.r.RMethodInvocationCommand;
import org.jax.r.RUtilities;
/**
* This class is basically just a more safe and convenient way of creating
* a scan command than creating the command string directly.
* @author <A HREF="mailto:keith.sheppard@jax.org">Keith Sheppard</A>
*/
// TODO add weights, incl.markers, clean.output, perm.strata,
// ties.random, & start functionality
public class ScanCommandBuilder
{
/**
* our logger
*/
private static final Logger LOG = Logger.getLogger(
ScanCommandBuilder.class.getName());
private volatile Cross cross;
private static final String CROSS_PARAMETER_NAME = "cross";
private volatile String[] chromosomeNames;
private static final String CHROMOSOME_NAMES_PARAMETER_NAME = "chr";
private volatile int[] phenotypeIndices;
/**
* The parameter name used for the phenotype indices
*/
public static final String PHENOTYPE_INDICES_PARAMETER_NAME = "pheno.col";
private volatile PhenotypeDistribution phenotypeDistribution =
PhenotypeDistribution.NORMAL;
private volatile ScanMethod scanMethod = ScanMethod.EM_ALGORITHM;
private volatile ScanType scanType = ScanType.SCANONE;
private volatile String[] additivePhenotypeCovariates;
private volatile List<GeneticMarker> additiveGenotypeCovariates;
private static final String ADDITIVE_COVARIATES_PARAMETER_NAME = "addcovar";
private volatile String[] interactivePhenotypeCovariates;
private volatile List<GeneticMarker> interactiveGenotypeCovariates;
private static final String INTERACTIVE_COVARIATES_PARAMETER_NAME = "intcovar";
private volatile boolean useMissingPhenotypes;
private static final String USE_MISSING_PHENOTYPES_PARAMETER_NAME = "use";
private static final String USE_MISSING_TRUE_PARAMETER_VALUE = "all.obs";
private static final String USE_MISSING_FALSE_PARAMETER_VALUE = "complete.obs";
/**
* a string representation of the convergence tolerance value that is used
* by default if no value is given
*/
public static final String UNSPECIFIED_CONVERGENCE_TOLERANCE = "1e-4";
private volatile Double convergenceTolerance;
private static final String CONVERGENCE_TOLERANCE_PARAMETER_NAME = "tol";
private volatile Integer maximumNumberOfIterations;
private static final String MAXIMUM_NUMBER_OF_ITERATIONS_PARAMETER_NAME = "maxit";
private volatile Integer numberOfPermutations;
private static final String NUMBER_OF_PERMUTATIONS_PARAMETER_NAME = "n.perm";
private volatile boolean seperatePermutationsForAutosome;
private static final String SEPERATE_PERMUTATIONS_FOR_AUTOSOME_PARAMETER_NAME = "perm.Xsp";
private volatile String scanResultName;
private volatile boolean verbosePermutationsOutput;
private static final String VERBOSE_PERMUTATIONS_OUTPUT_PERAMETER_NAME = "verbose";
private volatile boolean useAllMarkers;
private static final String USE_ALL_MARKERS_PARAMETER_NAME = "incl.markers";
private volatile boolean cleanOutput;
private static final String CLEAN_OUTPUT_PARAMETER_NAME = "clean.output";
/**
* This suffix that we tack on to the identifier when we create an
* assignment command for {@link #getCommandWithPermutations()}
*/
public static final String PERMUTATION_IDENTIFIER_SUFFIX = ".permutations";
/**
* Getter for the cross that this scan works on.
* @return the cross
*/
public Cross getCross()
{
return this.cross;
}
/**
* Setter for the cross that this scan works on.
* @param selectedCross the cross to set
*/
public void setCross(Cross selectedCross)
{
this.cross = selectedCross;
}
/**
* The names of the chromosomes that this scan with work on
* @return the chromosome names
*/
public String[] getChromosomeNames()
{
return this.chromosomeNames;
}
/**
* Setter for the names of the chromosomes that this scan will work on
* @param chromosomeNames the chromosome names to set
*/
public void setChromosomeIndices(String[] chromosomeNames)
{
this.chromosomeNames = chromosomeNames;
}
/**
* Getter for the phenotypes that this scan will work on
* @return the phenotype indices
*/
public int[] getPhenotypeIndices()
{
return this.phenotypeIndices;
}
/**
* Setter for the selected phenotypes that this command will work on
* @param phenotypeIndices
* the phenotype indices
*/
public void setPhenotypeIndices(int[] phenotypeIndices)
{
this.phenotypeIndices = phenotypeIndices;
}
/**
* Getter for the phenotype distribution to use for this scan
* @return the phenotypeDistribution
*/
public PhenotypeDistribution getPhenotypeDistribution()
{
return this.phenotypeDistribution;
}
/**
* Setter for the phenotype distribution to use for this scan
* @param phenotypeDistribution the phenotypeDistribution to set
*/
public void setPhenotypeDistribution(
PhenotypeDistribution phenotypeDistribution)
{
this.phenotypeDistribution = phenotypeDistribution;
}
/**
* Getter for the scan method to use
* @return the scanMethod
*/
public ScanMethod getScanMethod()
{
return this.scanMethod;
}
/**
* Setter for the scan method to use
* @param scanMethod the scanMethod to set
*/
public void setScanMethod(ScanMethod scanMethod)
{
this.scanMethod = scanMethod;
}
/**
* Getter for the scan type
* @return
* the scanType
*/
public ScanType getScanType()
{
return this.scanType;
}
/**
* Setter for the scan type
* @param scanType
* the scanType to set
*/
public void setScanType(ScanType scanType)
{
this.scanType = scanType;
}
/**
* Getter for the additive covariate names
* @return the additivePhenotypeCovariates
*/
public String[] getAdditiveCovariates()
{
return this.additivePhenotypeCovariates;
}
/**
* Setter for the additive covariate names
* @param additivePhenotypeCovariates the additive covariates to set
*/
public void setAdditivePhenotypeCovariates(String[] additivePhenotypeCovariates)
{
this.additivePhenotypeCovariates = additivePhenotypeCovariates;
}
/**
* Getter for the interactive covariate names
* @return the interactiveCovariates
*/
public String[] getInteractivePhenotypeCovariates()
{
return this.interactivePhenotypeCovariates;
}
/**
* Setter for the interactive covariate names
* @param interactivePhenotypeCovariates the interactive covariates to set
*/
public void setInteractivePhenotypeCovariates(String[] interactivePhenotypeCovariates)
{
this.interactivePhenotypeCovariates = interactivePhenotypeCovariates;
}
/**
* If true use missing phenotypes (assuming we're scanning more than
* one phenotype)
* @return the useMissingPhenotypes
*/
public boolean getUseMissingPhenotypes()
{
return this.useMissingPhenotypes;
}
/**
* Setter for use missing phenotypes
* @see #getUseMissingPhenotypes()
* @param useMissingPhenotypes the useMissingPhenotypes to set
*/
public void setUseMissingPhenotypes(boolean useMissingPhenotypes)
{
this.useMissingPhenotypes = useMissingPhenotypes;
}
/**
* Getter for the maximum number of iterations to use. Null indicates
* that the default value should be used.
* @return the maximumNumberOfIterations
*/
public Integer getMaximumNumberOfIterations()
{
return this.maximumNumberOfIterations;
}
/**
* Setter for the maximum number of iterations to use.
* @param maximumNumberOfIterations the maximumNumberOfIterations to set
*/
public void setMaximumNumberOfIterations(Integer maximumNumberOfIterations)
{
this.maximumNumberOfIterations = maximumNumberOfIterations;
}
/**
* Getter for the convergence tolerance to use. Null means that the default
* should be used.
* @return the convergenceTolerance
*/
public Double getConvergenceTolerance()
{
return this.convergenceTolerance;
}
/**
* Setter for the convergence tolerance to use
* @param convergenceTolerance the convergenceTolerance to set
*/
public void setConvergenceTolerance(Double convergenceTolerance)
{
this.convergenceTolerance = convergenceTolerance;
}
/**
* Getter for the number of permutations to use. Null means to use the
* default.
* @return the numberOfPermutations
* @see #getCommandWithPermutations()
*/
public Integer getNumberOfPermutations()
{
return this.numberOfPermutations;
}
/**
* Setter for the number of permutations to use.
* @param numberOfPermutations the numberOfPermutations to set
*/
public void setNumberOfPermutations(Integer numberOfPermutations)
{
this.numberOfPermutations = numberOfPermutations;
}
/**
* Getter that determines if we use seperate permutations for the
* autosome
* @return the seperatePermutationsForAutosome
*/
public boolean getSeperatePermutationsForAutosome()
{
return this.seperatePermutationsForAutosome;
}
/**
* Setter for determining whether or not we use seperate permutations
* for the autosome
* @param seperatePermutationsForAutosome the seperatePermutationsForAutosome to set
*/
public void setSeperatePermutationsForAutosome(
boolean seperatePermutationsForAutosome)
{
this.seperatePermutationsForAutosome = seperatePermutationsForAutosome;
}
/**
* Getter for the name that the scan result should be given
* @return the scanResultName
*/
public String getScanResultName()
{
String scanResultName = this.scanResultName;
if(scanResultName == null)
{
return null;
}
else
{
return scanResultName.trim();
}
}
/**
* Setter for the name that the scan result should be given
* @param scanResultName the scanResultName to set
*/
public void setScanResultName(String scanResultName)
{
this.scanResultName = scanResultName;
}
/**
* Create a parameter list that includes all of the parameters from
* {@link #createParameterListWithoutPermutations()} plus any permutation
* specific parameters that we need.
* @return
* the parameter list or null if there are no permutation specific
* parameters
*/
private List<RCommandParameter> createParameterListWithPermutations()
{
// take care of "n.perm" parameter
ScanType scanType = this.getScanType();
Integer numberOfPermutations = this.numberOfPermutations;
if(numberOfPermutations == null || numberOfPermutations.intValue() == 0)
{
return null;
}
else
{
List<RCommandParameter> commandParameters =
this.createParameterListWithoutPermutations();
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.NUMBER_OF_PERMUTATIONS_PARAMETER_NAME,
numberOfPermutations.toString()));
// take care of "perm.Xsp" & "verbose" parameter
if(numberOfPermutations.intValue() > 0)
{
if(scanType == ScanType.SCANONE)
{
// seperate permutations command is only valid
// for scan one
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.SEPERATE_PERMUTATIONS_FOR_AUTOSOME_PARAMETER_NAME,
RUtilities.javaBooleanToRBoolean(
this.seperatePermutationsForAutosome)));
}
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.VERBOSE_PERMUTATIONS_OUTPUT_PERAMETER_NAME,
RUtilities.javaBooleanToRBoolean(
this.verbosePermutationsOutput)));
}
return commandParameters;
}
}
/**
* Create a parameter list for the current settings
* @return
* the parameter list
*/
private List<RCommandParameter> createParameterListWithoutPermutations()
{
List<RCommandParameter> commandParameters =
new ArrayList<RCommandParameter>();
// throughout this method, we're grabbing local copies of "this"
// references before using them. we do this for thread safety
// create the cross parameter
Cross cross = this.cross;
if(cross != null)
{
commandParameters.add(new RCommandParameter(
CROSS_PARAMETER_NAME,
cross.getAccessorExpressionString()));
// take care of the additive covariates
String[] additivePhenotypeCovariates = this.additivePhenotypeCovariates;
List<GeneticMarker> additiveGenotypeCovariates = this.additiveGenotypeCovariates;
if(additivePhenotypeCovariates != null && additivePhenotypeCovariates.length > 0 ||
additiveGenotypeCovariates != null && !additiveGenotypeCovariates.isEmpty())
{
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.ADDITIVE_COVARIATES_PARAMETER_NAME,
this.covariatesToExpression(
additivePhenotypeCovariates,
additiveGenotypeCovariates,
cross)));
}
// take care of the interactive covariates
String[] interactivePhenotypeCovariates = this.interactivePhenotypeCovariates;
List<GeneticMarker> interactiveGenotypeCovariates = this.interactiveGenotypeCovariates;
if(interactivePhenotypeCovariates != null && interactivePhenotypeCovariates.length > 0 ||
interactiveGenotypeCovariates != null && !interactiveGenotypeCovariates.isEmpty())
{
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.INTERACTIVE_COVARIATES_PARAMETER_NAME,
this.covariatesToExpression(
interactivePhenotypeCovariates,
interactiveGenotypeCovariates,
cross)));
}
}
// create the chromosome indices parameter
String[] chromosomeNames = this.chromosomeNames;
if(chromosomeNames != null && chromosomeNames.length > 0)
{
commandParameters.add(new RCommandParameter(
CHROMOSOME_NAMES_PARAMETER_NAME,
RUtilities.stringArrayToRVector(chromosomeNames)));
}
// create the phenotype indices parameter
int[] phenotypeIndices = this.phenotypeIndices;
if(phenotypeIndices != null && phenotypeIndices.length > 0)
{
// R has 1 based indices
int[] onesBasedPhenotypeIndices = new int[phenotypeIndices.length];
for(int i = 0; i < phenotypeIndices.length; i++)
{
onesBasedPhenotypeIndices[i] = phenotypeIndices[i] + 1;
}
commandParameters.add(new RCommandParameter(
PHENOTYPE_INDICES_PARAMETER_NAME,
RUtilities.intArrayToRVector(onesBasedPhenotypeIndices)));
}
// create the model parameter
PhenotypeDistribution phenotypeDistribution = this.phenotypeDistribution;
if(phenotypeDistribution != null)
{
commandParameters.add(new RCommandParameter(
PhenotypeDistribution.MODEL_PARAMETER_NAME,
RUtilities.javaStringToRString(
phenotypeDistribution.getModelParameterValue())));
// take care of the "upper" parameter
if(phenotypeDistribution == PhenotypeDistribution.TWO_PART_SPIKES_UP)
{
commandParameters.add(new RCommandParameter(
PhenotypeDistribution.SPIKE_DIRECTION_PARAMETER_NAME,
RUtilities.javaBooleanToRBoolean(true)));
}
else if(phenotypeDistribution == PhenotypeDistribution.TWO_PART_SPIKES_DOWN)
{
commandParameters.add(new RCommandParameter(
PhenotypeDistribution.SPIKE_DIRECTION_PARAMETER_NAME,
RUtilities.javaBooleanToRBoolean(false)));
}
}
// create the method parameter
ScanMethod scanMethod = this.scanMethod;
if(scanMethod != null)
{
commandParameters.add(new RCommandParameter(
ScanMethod.PARAMETER_NAME,
RUtilities.javaStringToRString(
scanMethod.getValue())));
// take care of "maxit" parameter
Integer maximumNumberOfIterations = this.maximumNumberOfIterations;
if(maximumNumberOfIterations != null &&
(scanMethod == ScanMethod.EM_ALGORITHM ||
scanMethod == ScanMethod.EXTENDED_HALEY_KNOTT_METHOD))
{
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.MAXIMUM_NUMBER_OF_ITERATIONS_PARAMETER_NAME,
maximumNumberOfIterations.toString()));
}
// take care of "tol" parameter
Double convergenceTolerance = this.convergenceTolerance;
if(convergenceTolerance != null &&
(scanMethod == ScanMethod.EM_ALGORITHM ||
scanMethod == ScanMethod.EXTENDED_HALEY_KNOTT_METHOD))
{
// TODO is this always going to be OK (Double.toString())?
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.CONVERGENCE_TOLERANCE_PARAMETER_NAME,
convergenceTolerance.toString()));
}
}
// take care of the "use" parameters
if(phenotypeIndices != null && phenotypeIndices.length > 1)
{
if(this.useMissingPhenotypes)
{
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.USE_MISSING_PHENOTYPES_PARAMETER_NAME,
RUtilities.javaStringToRString(
ScanCommandBuilder.USE_MISSING_TRUE_PARAMETER_VALUE)));
}
else
{
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.USE_MISSING_PHENOTYPES_PARAMETER_NAME,
RUtilities.javaStringToRString(
ScanCommandBuilder.USE_MISSING_FALSE_PARAMETER_VALUE)));
}
}
ScanType scanType = this.getScanType();
if(scanType == ScanType.SCANTWO)
{
// take care of some scantwo only stuff
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.USE_ALL_MARKERS_PARAMETER_NAME,
RUtilities.javaBooleanToRBoolean(this.useAllMarkers)));
commandParameters.add(new RCommandParameter(
ScanCommandBuilder.CLEAN_OUTPUT_PARAMETER_NAME,
RUtilities.javaBooleanToRBoolean(this.cleanOutput)));
}
return commandParameters;
}
/**
* Convert the covariates to an expression string
* @param phenotypeCovariates
* the phenotype covariates
* @param genotypeCovariates
* the genotype covariates
* @param cross
* the cross object
* @return
* the R expression
*/
private String covariatesToExpression(
String[] phenotypeCovariates,
List<GeneticMarker> genotypeCovariates,
Cross cross)
{
// In R this might look like:
// cbind(fake.f2$pheno[, "sex"], fake.f2$pheno[, "pgm"], fake.f2$geno$"X"$data[,3])
StringBuffer expressionBuffer = new StringBuffer("cbind(");
if(phenotypeCovariates != null && phenotypeCovariates.length > 0)
{
for(int i = 0; i < phenotypeCovariates.length; i++)
{
if(i >=1)
{
expressionBuffer.append(",");
}
expressionBuffer.append(cross.getAccessorExpressionString());
expressionBuffer.append("$pheno[, ");
expressionBuffer.append(
RUtilities.javaStringToRString(phenotypeCovariates[i]));
expressionBuffer.append("]");
}
}
{
StringBuffer genotypeExpressionBuffer = new StringBuffer();
boolean anyGenotypeErrors = false;
if(phenotypeCovariates != null && phenotypeCovariates.length > 0 &&
genotypeCovariates != null && !genotypeCovariates.isEmpty())
{
genotypeExpressionBuffer.append(",");
}
if(genotypeCovariates != null && !genotypeCovariates.isEmpty())
{
List<CrossChromosome> genotypeData = cross.getGenotypeData();
int numGenoCovars = genotypeCovariates.size();
for(int currGenoCovarIndex = 0;
currGenoCovarIndex < numGenoCovars;
currGenoCovarIndex++)
{
if(currGenoCovarIndex >=1)
{
genotypeExpressionBuffer.append(",");
}
GeneticMarker currMarker = genotypeCovariates.get(currGenoCovarIndex);
int matchingChromoIndex = cross.getIndexOfChromosomeNamed(
currMarker.getChromosomeName());
if(matchingChromoIndex >= 0)
{
CrossChromosome matchingChromosome =
genotypeData.get(matchingChromoIndex);
int matchingMarkerIndex = -1;
List<GeneticMarker> geneticMarkers =
matchingChromosome.getAnyGeneticMap().getMarkerPositions();
int numMarkersInMap = geneticMarkers.size();
for(int j = 0; j < numMarkersInMap; j++)
{
GeneticMarker otherCurrMarker = geneticMarkers.get(j);
if(otherCurrMarker != null &&
otherCurrMarker.getMarkerName().equals(currMarker.getMarkerName()))
{
matchingMarkerIndex = j;
break;
}
}
if(matchingMarkerIndex >= 0)
{
String markerDataIndexExpression = RUtilities.columnIndexExpression(
matchingChromosome.getMarkerDataRObject().getAccessorExpressionString(),
matchingMarkerIndex);
genotypeExpressionBuffer.append(markerDataIndexExpression);
}
else
{
LOG.severe(
"Failed to find marker for: " + currMarker);
anyGenotypeErrors = true;
break;
}
}
else
{
LOG.severe(
"Failed to find chromosome for: " + currMarker);
anyGenotypeErrors = true;
break;
}
}
}
if(!anyGenotypeErrors)
{
expressionBuffer.append(genotypeExpressionBuffer);
}
}
expressionBuffer.append(")");
return expressionBuffer.toString();
}
/**
* Get the command for scanning, ignoring any permutation settings
* @return
* the command
*/
public RCommand getCommandWithoutPermutations()
{
List<RCommandParameter> parameters = this.createParameterListWithoutPermutations();
String scanResultName = this.scanResultName;
RMethodInvocationCommand methodInvocation =
new RMethodInvocationCommand(
this.getScanType().getRMethodName(),
parameters);
if(scanResultName == null || scanResultName.trim().length() == 0)
{
return methodInvocation;
}
else
{
RAssignmentCommand assignmentCommand =
new RAssignmentCommand(
scanResultName.trim(),
methodInvocation.getCommandText());
return assignmentCommand;
}
}
/**
* Get the command with permutations
* @return
* the command with permutations, or null if the permutation
* specific parameters are not set
* @see #getNumberOfPermutations()
*/
public RCommand getCommandWithPermutations()
{
List<RCommandParameter> parameters = this.createParameterListWithPermutations();
String scanResultName = this.getScanResultName();
if(parameters == null)
{
return null;
}
else
{
RMethodInvocationCommand methodInvocation =
new RMethodInvocationCommand(
this.getScanType().getRMethodName(),
parameters);
if(scanResultName == null || scanResultName.length() == 0)
{
return methodInvocation;
}
else
{
RAssignmentCommand assignmentCommand =
new RAssignmentCommand(
scanResultName + PERMUTATION_IDENTIFIER_SUFFIX,
methodInvocation.getCommandText());
return assignmentCommand;
}
}
}
/**
* Get the command that provides an accessor to the phenotype attribute.
* @return
* the phenotype accessor command
*/
public RCommand getPhenotypeAttributeCommand()
{
String scanResultName = this.getScanResultName();
if(scanResultName != null)
{
List<RCommandParameter> parameterList =
new ArrayList<RCommandParameter>();
parameterList.add(new RCommandParameter(this.getScanResultName()));
parameterList.add(new RCommandParameter(
RUtilities.javaStringToRString(
PHENOTYPE_INDICES_PARAMETER_NAME)));
RMethodInvocationCommand attributeCommand =
new RMethodInvocationCommand(
"attr",
parameterList);
int[] phenotypeIndices = this.phenotypeIndices;
if(phenotypeIndices != null && phenotypeIndices.length > 0)
{
// R has 1 based indices
int[] onesBasedPhenotypeIndices = new int[phenotypeIndices.length];
for(int i = 0; i < phenotypeIndices.length; i++)
{
onesBasedPhenotypeIndices[i] = phenotypeIndices[i] + 1;
}
String phenoIndices =
RUtilities.intArrayToRVector(onesBasedPhenotypeIndices);
RAssignmentCommand attibuteAssignmentCommand =
new RAssignmentCommand(
attributeCommand.getCommandText(),
phenoIndices);
return attibuteAssignmentCommand;
}
}
// return null if we can't create a good phenotype attribute command
return null;
}
/**
* See if this command represents a valid assignment.
* @return
* null if it is valid, or the error message if it isn't
*/
public String getInvalidAssignmentCommandMessage()
{
String invalidCommandMessage = this.getInvalidCommandMessage();
if(invalidCommandMessage != null)
{
return invalidCommandMessage;
}
String scanResultName = this.scanResultName;
if(scanResultName == null || scanResultName.trim().length() == 0)
{
return "Scan result name required";
}
scanResultName = scanResultName.trim();
// we crossed all of the hurdles OK
return null;
}
/**
* See if this command is valid (assignment or not)
* @return
* true if the command is valid
*/
// TODO messages should come from a properties file
public String getInvalidCommandMessage()
{
Cross cross = this.cross;
if(cross == null)
{
return "Command requires a cross to scan";
}
String crossName = cross.getAccessorExpressionString();
if(crossName == null || crossName.length() == 0)
{
return "Could not find a name for the selected cross";
}
PhenotypeDistribution phenotypeDistribution = this.phenotypeDistribution;
if(phenotypeDistribution == null)
{
return "Command requires a phenotype distribution";
}
else
{
if(phenotypeDistribution != PhenotypeDistribution.OTHER && this.scanMethod == null)
{
return "Command requires a scan method";
}
}
String[] chromosomeNames = this.chromosomeNames;
if(chromosomeNames == null || chromosomeNames.length == 0)
{
return "Command requires that at least one chromosome is selected";
}
int[] phenotypeIndices = this.phenotypeIndices;
if(phenotypeIndices == null || phenotypeIndices.length == 0)
{
return "Command requires that at least one phenotype is selected";
}
// we passed all of the hurdles OK
return null;
}
/**
* Setter that determines if the permutations output is verbose or quiet
* @param verbosePermutationsOutput
* the value to set
*/
public void setVerbosePermutationsOutput(boolean verbosePermutationsOutput)
{
this.verbosePermutationsOutput = verbosePermutationsOutput;
}
/**
* Getter that determines if our permutations output is verbose or not.
* @return
* true if it is verbose
*/
public boolean getVerbosePermutationsOutput()
{
return this.verbosePermutationsOutput;
}
/**
* @return the useAllMarkers
*/
public boolean isUseAllMarkers()
{
return this.useAllMarkers;
}
/**
* @param useAllMarkers the useAllMarkers to set
*/
public void setUseAllMarkers(boolean useAllMarkers)
{
this.useAllMarkers = useAllMarkers;
}
/**
* @return the cleanOutput
*/
public boolean isCleanOutput()
{
return this.cleanOutput;
}
/**
* @param cleanOutput the cleanOutput to set
*/
public void setCleanOutput(boolean cleanOutput)
{
this.cleanOutput = cleanOutput;
}
/**
* Setter for the additive genotype covariates
* @param additiveGenotypeCovariates
* the additive genotype covariates
*/
public void setAdditiveGenotypeCovariates(
List<GeneticMarker> additiveGenotypeCovariates)
{
this.additiveGenotypeCovariates = additiveGenotypeCovariates;
}
/**
* Setter for the interactive genotype covariates
* @param interactiveGenotypeCovariates
* the covariates
*/
public void setInteractiveGenotypeCovariates(
List<GeneticMarker> interactiveGenotypeCovariates)
{
this.interactiveGenotypeCovariates = interactiveGenotypeCovariates;
}
}