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:
parent
24ec35deaf
commit
01b721ab61
|
|
@ -157,6 +157,9 @@ public class HierarchicalMicroScheduler extends MicroScheduler implements Hierar
|
||||||
result = reduceTree.getResult().get();
|
result = reduceTree.getResult().get();
|
||||||
notifyTraversalDone(walker,result);
|
notifyTraversalDone(walker,result);
|
||||||
}
|
}
|
||||||
|
catch (ReviewedStingException ex) {
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new ReviewedStingException("Unable to retrieve result", ex);
|
throw new ReviewedStingException("Unable to retrieve result", ex);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@
|
||||||
|
|
||||||
package org.broadinstitute.sting.gatk.walkers.varianteval;
|
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.apache.log4j.Logger;
|
||||||
import org.broad.tribble.util.variantcontext.MutableVariantContext;
|
import org.broad.tribble.util.variantcontext.MutableVariantContext;
|
||||||
import org.broad.tribble.util.variantcontext.VariantContext;
|
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.VCFWriter;
|
||||||
import org.broad.tribble.vcf.VCFHeader;
|
import org.broad.tribble.vcf.VCFHeader;
|
||||||
import org.broad.tribble.vcf.VCFHeaderLine;
|
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.AlignmentContext;
|
||||||
import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
|
import org.broadinstitute.sting.gatk.contexts.ReferenceContext;
|
||||||
import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContextUtils;
|
import org.broadinstitute.sting.gatk.contexts.variantcontext.VariantContextUtils;
|
||||||
|
|
@ -63,6 +67,7 @@ import java.io.FileNotFoundException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
// todo -- evalations should support comment lines
|
// 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)
|
@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>();
|
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)
|
@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};
|
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 boolean isSelected() { return selectExp == null; }
|
||||||
|
|
||||||
public String getDisplayName() {
|
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(); }
|
public String toString() { return getDisplayName(); }
|
||||||
|
|
@ -740,6 +757,14 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> implements Tr
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onTraversalDone(Integer result) {
|
public void onTraversalDone(Integer result) {
|
||||||
|
writeReport();
|
||||||
|
validateContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the report out to disk.
|
||||||
|
*/
|
||||||
|
private void writeReport() {
|
||||||
// our report mashaller
|
// our report mashaller
|
||||||
ReportMarshaller marshaller;
|
ReportMarshaller marshaller;
|
||||||
|
|
||||||
|
|
@ -761,6 +786,64 @@ public class VariantEvalWalker extends RodWalker<Integer, Integer> implements Tr
|
||||||
marshaller.close();
|
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
|
* create some additional output lines about the analysis
|
||||||
* @return a list of nodes to attach to the report as tags
|
* @return a list of nodes to attach to the report as tags
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package org.broadinstitute.sting.gatk.walkers.varianteval;
|
package org.broadinstitute.sting.gatk.walkers.varianteval;
|
||||||
|
|
||||||
import org.broadinstitute.sting.WalkerTest;
|
import org.broadinstitute.sting.WalkerTest;
|
||||||
|
import org.broadinstitute.sting.utils.exceptions.UserException;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
@ -149,4 +150,27 @@ public class VariantEvalIntegrationTest extends WalkerTest {
|
||||||
//executeTest("testACDiscordanceAtAC1EvalAC2Comp",spec);
|
//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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue