Passing ReviewedStingExceptions through the HMS.

Added a @Hidden experimental argument -validate to VariantEval that allows external JEXL assertions that must evaluate to true will throw an exception.


git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@4692 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
kshakir 2010-11-16 21:50:42 +00:00
parent 24ec35deaf
commit 01b721ab61
3 changed files with 111 additions and 1 deletions

View File

@ -157,6 +157,9 @@ public class HierarchicalMicroScheduler extends MicroScheduler implements Hierar
result = reduceTree.getResult().get();
notifyTraversalDone(walker,result);
}
catch (ReviewedStingException ex) {
throw ex;
}
catch (Exception ex) {
throw new ReviewedStingException("Unable to retrieve result", ex);
}

View File

@ -25,6 +25,9 @@
package org.broadinstitute.sting.gatk.walkers.varianteval;
import org.apache.commons.jexl2.*;
import org.apache.commons.jexl2.introspection.*;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Logger;
import org.broad.tribble.util.variantcontext.MutableVariantContext;
import org.broad.tribble.util.variantcontext.VariantContext;
@ -32,6 +35,7 @@ import org.broad.tribble.vcf.VCFConstants;
import org.broad.tribble.vcf.VCFWriter;
import org.broad.tribble.vcf.VCFHeader;
import org.broad.tribble.vcf.VCFHeaderLine;
import org.broadinstitute.sting.commandline.Hidden;
import org.broadinstitute.sting.gatk.contexts.AlignmentContext;
import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContextUtils;
@ -63,6 +67,7 @@ import java.io.FileNotFoundException;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.*;
// todo -- evalations should support comment lines
@ -121,6 +126,10 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> implements Tr
@Argument(shortName="selectName", doc="Names to use for the list of stratifications (must be a 1-to-1 mapping)", required=false)
protected ArrayList<String> SELECT_NAMES = new ArrayList<String>();
@Hidden
@Argument(shortName="validate", doc="One or more JEXL validations to use after evaluating the data", required=false)
protected ArrayList<String> VALIDATE_EXPS = new ArrayList<String>();
@Argument(shortName="known", doc="Name of ROD bindings containing variant sites that should be treated as known when splitting eval rods into known and novel subsets", required=false)
protected String[] KNOWN_NAMES = {DbSNPHelper.STANDARD_DBSNP_TRACK_NAME};
@ -231,7 +240,15 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> implements Tr
public boolean isSelected() { return selectExp == null; }
public String getDisplayName() {
return Utils.join(CONTEXT_SEPARATOR, Arrays.asList(evalTrackName, compTrackName, selectExp == null ? "all" : selectExp.name, filtered, novelty));
return getName(CONTEXT_SEPARATOR);
}
public String getJexlName() {
return getName(".");
}
private String getName(String separator) {
return Utils.join(separator, Arrays.asList(evalTrackName, compTrackName, selectExp == null ? "all" : selectExp.name, filtered, novelty));
}
public String toString() { return getDisplayName(); }
@ -740,6 +757,14 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> implements Tr
}
public void onTraversalDone(Integer result) {
writeReport();
validateContext();
}
/**
* Writes the report out to disk.
*/
private void writeReport() {
// our report mashaller
ReportMarshaller marshaller;
@ -761,6 +786,64 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> implements Tr
marshaller.close();
}
/**
* Validates the JEXL expressions and throws an exception if they do not all return true.
*/
private void validateContext() {
if (VALIDATE_EXPS.size() == 0)
return;
JexlContext jc = new MapContext();
for (EvaluationContext context : contexts)
for (VariantEvaluator eval: context.evaluations)
jc.set(context.getJexlName() + "." + eval.getName(), eval);
Uberspect uberspect = new UberspectImpl(LogFactory.getLog(JexlEngine.class)) {
/** Gets the field, even if the field was non-public. */
@Override
public Field getField(Object obj, String name, JexlInfo info) {
Field result = super.getField(obj, name, info);
if (result == null && obj != null) {
Class<?> clazz = obj instanceof Class<?> ? (Class<?>)obj : obj.getClass();
try {
// TODO: Default UberspectImpl uses an internal field cache by class type
result = clazz.getDeclaredField(name);
result.setAccessible(true);
} catch (NoSuchFieldException nsfe) {
/* ignore */
}
}
return result;
}
};
JexlEngine jexl = new JexlEngine(uberspect, null, null, null);
List<String> failedExpressions = new ArrayList<String>();
for (String expression: VALIDATE_EXPS) {
// ex: evalYRI.compYRI.all.called.novel.titv.tiTvRatio > 1.0
Object jexlResult = jexl.createExpression(expression).evaluate(jc);
boolean pass = Boolean.TRUE.equals(jexlResult);
if (!pass) {
logger.error("FAIL: " + expression);
failedExpressions.add(expression);
} else if (logger.isDebugEnabled()) {
logger.debug("PASS: " + expression);
}
}
int failed = failedExpressions.size();
int total = VALIDATE_EXPS.size();
logger.info(String.format("Validations: Total %s, Passed %s, Failed %s", total, (total-failed), failed));
if (failed > 0) {
StringBuilder message = new StringBuilder("The validation expressions below did not return true. Please check the report output for more info.");
for (String expression: failedExpressions)
message.append(String.format("%n ")).append(expression);
throw new UserException(message.toString());
}
}
/**
* create some additional output lines about the analysis
* @return a list of nodes to attach to the report as tags

View File

@ -1,6 +1,7 @@
package org.broadinstitute.sting.gatk.walkers.varianteval;
import org.broadinstitute.sting.WalkerTest;
import org.broadinstitute.sting.utils.exceptions.UserException;
import org.testng.annotations.Test;
import java.util.Arrays;
@ -149,4 +150,27 @@ public class VariantEvalIntegrationTest extends WalkerTest {
//executeTest("testACDiscordanceAtAC1EvalAC2Comp",spec);
}
@Test
public void testVEValidatePass() {
String extraArgs = "-L 1:1-10,000,000";
for (String tests : testsEnumerations) {
WalkerTestSpec spec = new WalkerTestSpec(withValidateTiTv(withSelect(tests, "DP < 50", "DP50"), 1.0, 4.0) + " " + extraArgs + " -o %s",
1, Arrays.asList("8a0203f0533b628ad7f1f230a43f105f"));
executeTestParallel("testVEValidatePass", spec);
}
}
@Test
public void testVEValidateFail() {
String extraArgs = "-L 1:1-10,000,000";
for (String tests : testsEnumerations) {
WalkerTestSpec spec = new WalkerTestSpec(withValidateTiTv(withSelect(tests, "DP < 50", "DP50"), 1.0, 1.2) + " " + extraArgs + " -o %s",
1, UserException.class);
executeTestParallel("testVEValidateFail", spec);
}
}
private static String withValidateTiTv(String cmd, double min, double max) {
return String.format("%s -validate 'eval.comp_genotypes.all.called.all.titv.tiTvRatio >= %2$s' -validate 'eval.comp_genotypes.all.called.all.titv.tiTvRatio <= %3$s'", cmd, min, max);
}
}