/* * 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.logging.Logger; import org.jax.qtl.cross.Cross; 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; /** * Base class for scan one and two * @author <A HREF="mailto:keith.sheppard@jax.org">Keith Sheppard</A> */ public abstract class ScanResult extends RObject { /** * our logger */ private static final Logger LOG = Logger.getLogger( ScanResult.class.getName()); /** * the parent cross for this scan result */ private final Cross parentCross; private static final String LOD_P_PREFIX = "lod.p."; private static final String LOD_MU_PREFIX = "lod.mu."; private static final String LOD_P_MU_PREFIX = "lod.p.mu."; /** * Constructor * @param rInterface * the r interface * @param accessorExpressionString * the accessor expression string * @param parentCross * the parent cross */ public ScanResult( RInterface rInterface, String accessorExpressionString, Cross parentCross) { super(rInterface, accessorExpressionString); this.parentCross = parentCross; } /** * Getter for this scan's parent cross * @return the parentCross */ public Cross getParentCross() { return this.parentCross; } /** * Getter for the scanned phenotype indices * @return * the scanned (zero-based) phenotype indices */ protected int[] getScannedPhenotypeIndices() { Cross parentCross = this.parentCross; if(parentCross != null) { RCommandParameter[] attrParameters = new RCommandParameter[] { new RCommandParameter(this.getAccessorExpressionString()), new RCommandParameter(RUtilities.javaStringToRString( ScanCommandBuilder.PHENOTYPE_INDICES_PARAMETER_NAME))}; RMethodInvocationCommand phenoAttributeCommand = new RMethodInvocationCommand( "attr", attrParameters); REXP phenoRExpression = this.getRInterface().evaluateCommand(new SilentRCommand( phenoAttributeCommand)); if(phenoRExpression.getType() == REXP.XT_NULL) { LOG.warning( "cant get scanned phenotype since " + phenoAttributeCommand.getCommandText() + " is null"); return new int[0]; } else { Integer[] phenotypeIndexObjects = JRIUtilityFunctions.extractIntegerValues(phenoRExpression); int[] phenotypeIndices = new int[phenotypeIndexObjects.length]; for(int i = 0; i < phenotypeIndices.length; i++) { phenotypeIndices[i] = phenotypeIndexObjects[i] - 1; } return phenotypeIndices; } } else { LOG.warning("cant get scanned phenotype. parent cross is null"); return new int[0]; } } /** * Get the index of the scanned phenotype * @return * the index of the scanned phenotype */ private int getScannedPhenotypeIndex() { int[] phenotypeIndices = this.getScannedPhenotypeIndices(); if(phenotypeIndices.length == 1) { return phenotypeIndices[0]; } else { LOG.warning( "cant return a single phenotype index since " + phenotypeIndices.length + " were scanned"); return -1; } } /** * Get the scanned phenotype name * @return * the name */ protected String getScannedPhenotypeName() { int phenotypeIndex = this.getScannedPhenotypeIndex(); if(phenotypeIndex >= 0) { return this.parentCross.getPhenotypeData().getDataNames()[phenotypeIndex]; } else { LOG.warning("bad phenotypeIndex value: " + phenotypeIndex); return null; } } /** * Get the scanned phenotype name * @return * the name */ public String[] getScannedPhenotypeNames() { int[] scannedPhenotypeIndices = this.getScannedPhenotypeIndices(); String[] scannedPhenotypeNames = new String[scannedPhenotypeIndices.length]; String[] allPhenotypeNames = this.parentCross.getPhenotypeData().getDataNames(); for(int i = 0; i < scannedPhenotypeIndices.length; i++) { if(scannedPhenotypeIndices[i] < allPhenotypeNames.length) { scannedPhenotypeNames[i] = allPhenotypeNames[scannedPhenotypeIndices[i]]; } else { LOG.warning( "phenotype index is out of bounds... returning an " + "empty array"); return new String[0]; } } return scannedPhenotypeNames; } /** * Use a very permissive search to try to find the phenotype that * matches up with a lod scan column * @param scanColumnName * the LOD column from the scan * @return * the matching phenotype name or null if we can't find a match */ public String findScannedPhenotypeNameForScanColumn(String scanColumnName) { String[] scannedPhenotypeNames = this.getScannedPhenotypeNames(); // first see if just one phenotype was scanned if(scannedPhenotypeNames.length == 1) { return scannedPhenotypeNames[0]; } // OK, we have more than one phenotype. see if any are exact matches for(int i = 0; i < scannedPhenotypeNames.length; i++) { if(scanColumnName.equals(scannedPhenotypeNames[i])) { return scannedPhenotypeNames[i]; } } // OK, there are no exact matches. lets see if we can find a // match based on a two-part scan distribution for(int i = 0; i < scannedPhenotypeNames.length; i++) { if(scanColumnName.equals(LOD_P_PREFIX + scannedPhenotypeNames[i]) || scanColumnName.equals(LOD_MU_PREFIX + scannedPhenotypeNames[i]) || scanColumnName.equals(LOD_P_MU_PREFIX + scannedPhenotypeNames[i])) { return scannedPhenotypeNames[i]; } } // we could not find any match LOG.warning("failed to find a phenotype to match column name: " + scanColumnName); return null; } }