SnpEff 2.0.4 support
-Modified the SnpEff parser to work with the SnpEff 2.0.4 VCF output format -Assigning functional classes and effect impacts now handled directly by SnpEff rather than the GATK -Removed support for SnpEff 2.0.2, as we no longer trust the output of that version since it doesn't exclude effects associated with certain nonsensical transcripts. These effects are excluded as of 2.0.4. -Updated unit and integration tests This support is based on a *release-candidate* of SnpEff 2.0.4, and so is subject to change between now and the next GATK release.
This commit is contained in:
parent
7fada320a9
commit
0d163e3f52
|
|
@ -56,7 +56,7 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
|
|
||||||
// We refuse to parse SnpEff output files generated by unsupported versions, or
|
// We refuse to parse SnpEff output files generated by unsupported versions, or
|
||||||
// lacking a SnpEff version number in the VCF header:
|
// lacking a SnpEff version number in the VCF header:
|
||||||
public static final String[] SUPPORTED_SNPEFF_VERSIONS = { "2.0.2" };
|
public static final String[] SUPPORTED_SNPEFF_VERSIONS = { "2.0.4" };
|
||||||
public static final String SNPEFF_VCF_HEADER_VERSION_LINE_KEY = "SnpEffVersion";
|
public static final String SNPEFF_VCF_HEADER_VERSION_LINE_KEY = "SnpEffVersion";
|
||||||
public static final String SNPEFF_VCF_HEADER_COMMAND_LINE_KEY = "SnpEffCmd";
|
public static final String SNPEFF_VCF_HEADER_COMMAND_LINE_KEY = "SnpEffCmd";
|
||||||
|
|
||||||
|
|
@ -77,13 +77,13 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
public enum InfoFieldKey {
|
public enum InfoFieldKey {
|
||||||
EFFECT_KEY ("SNPEFF_EFFECT", -1),
|
EFFECT_KEY ("SNPEFF_EFFECT", -1),
|
||||||
IMPACT_KEY ("SNPEFF_IMPACT", 0),
|
IMPACT_KEY ("SNPEFF_IMPACT", 0),
|
||||||
CODON_CHANGE_KEY ("SNPEFF_CODON_CHANGE", 1),
|
FUNCTIONAL_CLASS_KEY ("SNPEFF_FUNCTIONAL_CLASS", 1),
|
||||||
AMINO_ACID_CHANGE_KEY ("SNPEFF_AMINO_ACID_CHANGE", 2),
|
CODON_CHANGE_KEY ("SNPEFF_CODON_CHANGE", 2),
|
||||||
GENE_NAME_KEY ("SNPEFF_GENE_NAME", 3),
|
AMINO_ACID_CHANGE_KEY ("SNPEFF_AMINO_ACID_CHANGE", 3),
|
||||||
GENE_BIOTYPE_KEY ("SNPEFF_GENE_BIOTYPE", 4),
|
GENE_NAME_KEY ("SNPEFF_GENE_NAME", 4),
|
||||||
TRANSCRIPT_ID_KEY ("SNPEFF_TRANSCRIPT_ID", 6),
|
GENE_BIOTYPE_KEY ("SNPEFF_GENE_BIOTYPE", 5),
|
||||||
EXON_ID_KEY ("SNPEFF_EXON_ID", 7),
|
TRANSCRIPT_ID_KEY ("SNPEFF_TRANSCRIPT_ID", 7),
|
||||||
FUNCTIONAL_CLASS_KEY ("SNPEFF_FUNCTIONAL_CLASS", -1);
|
EXON_ID_KEY ("SNPEFF_EXON_ID", 8);
|
||||||
|
|
||||||
// Actual text of the key
|
// Actual text of the key
|
||||||
private final String keyName;
|
private final String keyName;
|
||||||
|
|
@ -110,70 +110,53 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
// are validated against this list.
|
// are validated against this list.
|
||||||
public enum EffectType {
|
public enum EffectType {
|
||||||
// High-impact effects:
|
// High-impact effects:
|
||||||
FRAME_SHIFT (EffectFunctionalClass.NONE, false),
|
SPLICE_SITE_ACCEPTOR,
|
||||||
STOP_GAINED (EffectFunctionalClass.NONSENSE, false),
|
SPLICE_SITE_DONOR,
|
||||||
START_LOST (EffectFunctionalClass.NONE, false),
|
START_LOST,
|
||||||
SPLICE_SITE_ACCEPTOR (EffectFunctionalClass.NONE, false),
|
EXON_DELETED,
|
||||||
SPLICE_SITE_DONOR (EffectFunctionalClass.NONE, false),
|
FRAME_SHIFT,
|
||||||
EXON_DELETED (EffectFunctionalClass.NONE, false),
|
STOP_GAINED,
|
||||||
STOP_LOST (EffectFunctionalClass.NONE, false),
|
STOP_LOST,
|
||||||
|
|
||||||
// Moderate-impact effects:
|
// Moderate-impact effects:
|
||||||
NON_SYNONYMOUS_CODING (EffectFunctionalClass.MISSENSE, false),
|
NON_SYNONYMOUS_CODING,
|
||||||
CODON_CHANGE (EffectFunctionalClass.NONE, false),
|
CODON_CHANGE,
|
||||||
CODON_INSERTION (EffectFunctionalClass.NONE, false),
|
CODON_INSERTION,
|
||||||
CODON_CHANGE_PLUS_CODON_INSERTION (EffectFunctionalClass.NONE, false),
|
CODON_CHANGE_PLUS_CODON_INSERTION,
|
||||||
CODON_DELETION (EffectFunctionalClass.NONE, false),
|
CODON_DELETION,
|
||||||
CODON_CHANGE_PLUS_CODON_DELETION (EffectFunctionalClass.NONE, false),
|
CODON_CHANGE_PLUS_CODON_DELETION,
|
||||||
UTR_5_DELETED (EffectFunctionalClass.NONE, false),
|
UTR_5_DELETED,
|
||||||
UTR_3_DELETED (EffectFunctionalClass.NONE, false),
|
UTR_3_DELETED,
|
||||||
|
|
||||||
// Low-impact effects:
|
// Low-impact effects:
|
||||||
SYNONYMOUS_CODING (EffectFunctionalClass.SILENT, false),
|
SYNONYMOUS_START,
|
||||||
SYNONYMOUS_START (EffectFunctionalClass.SILENT, false),
|
NON_SYNONYMOUS_START,
|
||||||
NON_SYNONYMOUS_START (EffectFunctionalClass.SILENT, false),
|
START_GAINED,
|
||||||
SYNONYMOUS_STOP (EffectFunctionalClass.SILENT, false),
|
SYNONYMOUS_CODING,
|
||||||
NON_SYNONYMOUS_STOP (EffectFunctionalClass.SILENT, false),
|
SYNONYMOUS_STOP,
|
||||||
START_GAINED (EffectFunctionalClass.NONE, false),
|
NON_SYNONYMOUS_STOP,
|
||||||
|
|
||||||
// Modifiers:
|
// Modifiers:
|
||||||
NONE (EffectFunctionalClass.NONE, true),
|
NONE,
|
||||||
CHROMOSOME (EffectFunctionalClass.NONE, true),
|
CHROMOSOME,
|
||||||
INTERGENIC (EffectFunctionalClass.NONE, true),
|
CUSTOM,
|
||||||
UPSTREAM (EffectFunctionalClass.NONE, true),
|
CDS,
|
||||||
UTR_5_PRIME (EffectFunctionalClass.NONE, true),
|
GENE,
|
||||||
CDS (EffectFunctionalClass.NONE, true),
|
TRANSCRIPT,
|
||||||
GENE (EffectFunctionalClass.NONE, true),
|
EXON,
|
||||||
TRANSCRIPT (EffectFunctionalClass.NONE, true),
|
INTRON_CONSERVED,
|
||||||
EXON (EffectFunctionalClass.NONE, true),
|
UTR_5_PRIME,
|
||||||
INTRON (EffectFunctionalClass.NONE, true),
|
UTR_3_PRIME,
|
||||||
UTR_3_PRIME (EffectFunctionalClass.NONE, true),
|
DOWNSTREAM,
|
||||||
DOWNSTREAM (EffectFunctionalClass.NONE, true),
|
INTRAGENIC,
|
||||||
INTRON_CONSERVED (EffectFunctionalClass.NONE, true),
|
INTERGENIC,
|
||||||
INTERGENIC_CONSERVED (EffectFunctionalClass.NONE, true),
|
INTERGENIC_CONSERVED,
|
||||||
REGULATION (EffectFunctionalClass.NONE, true),
|
UPSTREAM,
|
||||||
CUSTOM (EffectFunctionalClass.NONE, true),
|
REGULATION,
|
||||||
WITHIN_NON_CODING_GENE (EffectFunctionalClass.NONE, true);
|
INTRON
|
||||||
|
|
||||||
private final EffectFunctionalClass functionalClass;
|
|
||||||
private final boolean isModifier;
|
|
||||||
|
|
||||||
EffectType ( EffectFunctionalClass functionalClass, boolean isModifier ) {
|
|
||||||
this.functionalClass = functionalClass;
|
|
||||||
this.isModifier = isModifier;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public EffectFunctionalClass getFunctionalClass() {
|
// SnpEff labels each effect as either LOW, MODERATE, or HIGH impact, or as a MODIFIER.
|
||||||
return functionalClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isModifier() {
|
|
||||||
return isModifier;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SnpEff labels each effect as either LOW, MODERATE, or HIGH impact. We take the additional step of
|
|
||||||
// classifying some of the LOW impact effects as MODIFIERs.
|
|
||||||
public enum EffectImpact {
|
public enum EffectImpact {
|
||||||
MODIFIER (0),
|
MODIFIER (0),
|
||||||
LOW (1),
|
LOW (1),
|
||||||
|
|
@ -202,7 +185,7 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
}
|
}
|
||||||
|
|
||||||
// We assign a functional class to each SnpEff effect.
|
// SnpEff assigns a functional class to each effect.
|
||||||
public enum EffectFunctionalClass {
|
public enum EffectFunctionalClass {
|
||||||
NONE (0),
|
NONE (0),
|
||||||
SILENT (1),
|
SILENT (1),
|
||||||
|
|
@ -379,13 +362,13 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
public List<String> getKeyNames() {
|
public List<String> getKeyNames() {
|
||||||
return Arrays.asList( InfoFieldKey.EFFECT_KEY.getKeyName(),
|
return Arrays.asList( InfoFieldKey.EFFECT_KEY.getKeyName(),
|
||||||
InfoFieldKey.IMPACT_KEY.getKeyName(),
|
InfoFieldKey.IMPACT_KEY.getKeyName(),
|
||||||
|
InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName(),
|
||||||
InfoFieldKey.CODON_CHANGE_KEY.getKeyName(),
|
InfoFieldKey.CODON_CHANGE_KEY.getKeyName(),
|
||||||
InfoFieldKey.AMINO_ACID_CHANGE_KEY.getKeyName(),
|
InfoFieldKey.AMINO_ACID_CHANGE_KEY.getKeyName(),
|
||||||
InfoFieldKey.GENE_NAME_KEY.getKeyName(),
|
InfoFieldKey.GENE_NAME_KEY.getKeyName(),
|
||||||
InfoFieldKey.GENE_BIOTYPE_KEY.getKeyName(),
|
InfoFieldKey.GENE_BIOTYPE_KEY.getKeyName(),
|
||||||
InfoFieldKey.TRANSCRIPT_ID_KEY.getKeyName(),
|
InfoFieldKey.TRANSCRIPT_ID_KEY.getKeyName(),
|
||||||
InfoFieldKey.EXON_ID_KEY.getKeyName(),
|
InfoFieldKey.EXON_ID_KEY.getKeyName()
|
||||||
InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -393,13 +376,13 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
return Arrays.asList(
|
return Arrays.asList(
|
||||||
new VCFInfoHeaderLine(InfoFieldKey.EFFECT_KEY.getKeyName(), 1, VCFHeaderLineType.String, "The highest-impact effect resulting from the current variant (or one of the highest-impact effects, if there is a tie)"),
|
new VCFInfoHeaderLine(InfoFieldKey.EFFECT_KEY.getKeyName(), 1, VCFHeaderLineType.String, "The highest-impact effect resulting from the current variant (or one of the highest-impact effects, if there is a tie)"),
|
||||||
new VCFInfoHeaderLine(InfoFieldKey.IMPACT_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Impact of the highest-impact effect resulting from the current variant " + Arrays.toString(EffectImpact.values())),
|
new VCFInfoHeaderLine(InfoFieldKey.IMPACT_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Impact of the highest-impact effect resulting from the current variant " + Arrays.toString(EffectImpact.values())),
|
||||||
|
new VCFInfoHeaderLine(InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Functional class of the highest-impact effect resulting from the current variant: " + Arrays.toString(EffectFunctionalClass.values())),
|
||||||
new VCFInfoHeaderLine(InfoFieldKey.CODON_CHANGE_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Old/New codon for the highest-impact effect resulting from the current variant"),
|
new VCFInfoHeaderLine(InfoFieldKey.CODON_CHANGE_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Old/New codon for the highest-impact effect resulting from the current variant"),
|
||||||
new VCFInfoHeaderLine(InfoFieldKey.AMINO_ACID_CHANGE_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Old/New amino acid for the highest-impact effect resulting from the current variant"),
|
new VCFInfoHeaderLine(InfoFieldKey.AMINO_ACID_CHANGE_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Old/New amino acid for the highest-impact effect resulting from the current variant (in HGVS style)"),
|
||||||
new VCFInfoHeaderLine(InfoFieldKey.GENE_NAME_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Gene name for the highest-impact effect resulting from the current variant"),
|
new VCFInfoHeaderLine(InfoFieldKey.GENE_NAME_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Gene name for the highest-impact effect resulting from the current variant"),
|
||||||
new VCFInfoHeaderLine(InfoFieldKey.GENE_BIOTYPE_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Gene biotype for the highest-impact effect resulting from the current variant"),
|
new VCFInfoHeaderLine(InfoFieldKey.GENE_BIOTYPE_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Gene biotype for the highest-impact effect resulting from the current variant"),
|
||||||
new VCFInfoHeaderLine(InfoFieldKey.TRANSCRIPT_ID_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Transcript ID for the highest-impact effect resulting from the current variant"),
|
new VCFInfoHeaderLine(InfoFieldKey.TRANSCRIPT_ID_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Transcript ID for the highest-impact effect resulting from the current variant"),
|
||||||
new VCFInfoHeaderLine(InfoFieldKey.EXON_ID_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Exon ID for the highest-impact effect resulting from the current variant"),
|
new VCFInfoHeaderLine(InfoFieldKey.EXON_ID_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Exon ID for the highest-impact effect resulting from the current variant")
|
||||||
new VCFInfoHeaderLine(InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName(), 1, VCFHeaderLineType.String, "Functional class of the highest-impact effect resulting from the current variant: " + Arrays.toString(EffectFunctionalClass.values()))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -409,6 +392,7 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
protected static class SnpEffEffect {
|
protected static class SnpEffEffect {
|
||||||
private EffectType effect;
|
private EffectType effect;
|
||||||
private EffectImpact impact;
|
private EffectImpact impact;
|
||||||
|
private EffectFunctionalClass functionalClass;
|
||||||
private String codonChange;
|
private String codonChange;
|
||||||
private String aminoAcidChange;
|
private String aminoAcidChange;
|
||||||
private String geneName;
|
private String geneName;
|
||||||
|
|
@ -420,16 +404,21 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
private String parseError = null;
|
private String parseError = null;
|
||||||
private boolean isWellFormed = true;
|
private boolean isWellFormed = true;
|
||||||
|
|
||||||
private static final int EXPECTED_NUMBER_OF_METADATA_FIELDS = 8;
|
private static final int EXPECTED_NUMBER_OF_METADATA_FIELDS = 9;
|
||||||
private static final int NUMBER_OF_METADATA_FIELDS_UPON_WARNING = 9;
|
private static final int NUMBER_OF_METADATA_FIELDS_UPON_EITHER_WARNING_OR_ERROR = 10;
|
||||||
private static final int NUMBER_OF_METADATA_FIELDS_UPON_ERROR = 10;
|
private static final int NUMBER_OF_METADATA_FIELDS_UPON_BOTH_WARNING_AND_ERROR = 11;
|
||||||
|
|
||||||
// Note that contrary to the description for the EFF field layout that SnpEff adds to the VCF header,
|
// If there is either a warning OR an error, it will be in the last field. If there is both
|
||||||
// errors come after warnings, not vice versa:
|
// a warning AND an error, the warning will be in the second-to-last field, and the error will
|
||||||
private static final int SNPEFF_WARNING_FIELD_INDEX = NUMBER_OF_METADATA_FIELDS_UPON_WARNING - 1;
|
// be in the last field.
|
||||||
private static final int SNPEFF_ERROR_FIELD_INDEX = NUMBER_OF_METADATA_FIELDS_UPON_ERROR - 1;
|
private static final int SNPEFF_WARNING_OR_ERROR_FIELD_UPON_SINGLE_ERROR = NUMBER_OF_METADATA_FIELDS_UPON_EITHER_WARNING_OR_ERROR - 1;
|
||||||
|
private static final int SNPEFF_WARNING_FIELD_UPON_BOTH_WARNING_AND_ERROR = NUMBER_OF_METADATA_FIELDS_UPON_BOTH_WARNING_AND_ERROR - 2;
|
||||||
|
private static final int SNPEFF_ERROR_FIELD_UPON_BOTH_WARNING_AND_ERROR = NUMBER_OF_METADATA_FIELDS_UPON_BOTH_WARNING_AND_ERROR - 1;
|
||||||
|
|
||||||
private static final int SNPEFF_CODING_FIELD_INDEX = 5;
|
// Position of the field indicating whether the effect is coding or non-coding. This field is used
|
||||||
|
// in selecting the most significant effect, but is not included in the annotations we return
|
||||||
|
// since it can be deduced from the SNPEFF_GENE_BIOTYPE field.
|
||||||
|
private static final int SNPEFF_CODING_FIELD_INDEX = 6;
|
||||||
|
|
||||||
public SnpEffEffect ( String effectName, String[] effectMetadata ) {
|
public SnpEffEffect ( String effectName, String[] effectMetadata ) {
|
||||||
parseEffectName(effectName);
|
parseEffectName(effectName);
|
||||||
|
|
@ -447,11 +436,14 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
|
|
||||||
private void parseEffectMetadata ( String[] effectMetadata ) {
|
private void parseEffectMetadata ( String[] effectMetadata ) {
|
||||||
if ( effectMetadata.length != EXPECTED_NUMBER_OF_METADATA_FIELDS ) {
|
if ( effectMetadata.length != EXPECTED_NUMBER_OF_METADATA_FIELDS ) {
|
||||||
if ( effectMetadata.length == NUMBER_OF_METADATA_FIELDS_UPON_WARNING ) {
|
if ( effectMetadata.length == NUMBER_OF_METADATA_FIELDS_UPON_EITHER_WARNING_OR_ERROR ) {
|
||||||
parseError(String.format("SnpEff issued the following warning: %s", effectMetadata[SNPEFF_WARNING_FIELD_INDEX]));
|
parseError(String.format("SnpEff issued the following warning or error: \"%s\"",
|
||||||
|
effectMetadata[SNPEFF_WARNING_OR_ERROR_FIELD_UPON_SINGLE_ERROR]));
|
||||||
}
|
}
|
||||||
else if ( effectMetadata.length == NUMBER_OF_METADATA_FIELDS_UPON_ERROR ) {
|
else if ( effectMetadata.length == NUMBER_OF_METADATA_FIELDS_UPON_BOTH_WARNING_AND_ERROR ) {
|
||||||
parseError(String.format("SnpEff issued the following error: %s", effectMetadata[SNPEFF_ERROR_FIELD_INDEX]));
|
parseError(String.format("SnpEff issued the following warning: \"%s\", and the following error: \"%s\"",
|
||||||
|
effectMetadata[SNPEFF_WARNING_FIELD_UPON_BOTH_WARNING_AND_ERROR],
|
||||||
|
effectMetadata[SNPEFF_ERROR_FIELD_UPON_BOTH_WARNING_AND_ERROR]));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
parseError(String.format("Wrong number of effect metadata fields. Expected %d but found %d",
|
parseError(String.format("Wrong number of effect metadata fields. Expected %d but found %d",
|
||||||
|
|
@ -461,16 +453,25 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( effect != null && effect.isModifier() ) {
|
// The impact field will never be empty, and should always contain one of the enumerated values:
|
||||||
impact = EffectImpact.MODIFIER;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
try {
|
||||||
impact = EffectImpact.valueOf(effectMetadata[InfoFieldKey.IMPACT_KEY.getFieldIndex()]);
|
impact = EffectImpact.valueOf(effectMetadata[InfoFieldKey.IMPACT_KEY.getFieldIndex()]);
|
||||||
}
|
}
|
||||||
catch ( IllegalArgumentException e ) {
|
catch ( IllegalArgumentException e ) {
|
||||||
parseError(String.format("Unrecognized value for effect impact: %s", effectMetadata[InfoFieldKey.IMPACT_KEY.getFieldIndex()]));
|
parseError(String.format("Unrecognized value for effect impact: %s", effectMetadata[InfoFieldKey.IMPACT_KEY.getFieldIndex()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The functional class field will be empty when the effect has no functional class associated with it:
|
||||||
|
if ( effectMetadata[InfoFieldKey.FUNCTIONAL_CLASS_KEY.getFieldIndex()].trim().length() > 0 ) {
|
||||||
|
try {
|
||||||
|
functionalClass = EffectFunctionalClass.valueOf(effectMetadata[InfoFieldKey.FUNCTIONAL_CLASS_KEY.getFieldIndex()]);
|
||||||
|
}
|
||||||
|
catch ( IllegalArgumentException e ) {
|
||||||
|
parseError(String.format("Unrecognized value for effect functional class: %s", effectMetadata[InfoFieldKey.FUNCTIONAL_CLASS_KEY.getFieldIndex()]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
functionalClass = EffectFunctionalClass.NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
codonChange = effectMetadata[InfoFieldKey.CODON_CHANGE_KEY.getFieldIndex()];
|
codonChange = effectMetadata[InfoFieldKey.CODON_CHANGE_KEY.getFieldIndex()];
|
||||||
|
|
@ -478,6 +479,7 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
geneName = effectMetadata[InfoFieldKey.GENE_NAME_KEY.getFieldIndex()];
|
geneName = effectMetadata[InfoFieldKey.GENE_NAME_KEY.getFieldIndex()];
|
||||||
geneBiotype = effectMetadata[InfoFieldKey.GENE_BIOTYPE_KEY.getFieldIndex()];
|
geneBiotype = effectMetadata[InfoFieldKey.GENE_BIOTYPE_KEY.getFieldIndex()];
|
||||||
|
|
||||||
|
// The coding field will be empty when SnpEff has no coding info for the effect:
|
||||||
if ( effectMetadata[SNPEFF_CODING_FIELD_INDEX].trim().length() > 0 ) {
|
if ( effectMetadata[SNPEFF_CODING_FIELD_INDEX].trim().length() > 0 ) {
|
||||||
try {
|
try {
|
||||||
coding = EffectCoding.valueOf(effectMetadata[SNPEFF_CODING_FIELD_INDEX]);
|
coding = EffectCoding.valueOf(effectMetadata[SNPEFF_CODING_FIELD_INDEX]);
|
||||||
|
|
@ -534,7 +536,7 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if ( impact.isSameImpactAs(other.impact) ) {
|
else if ( impact.isSameImpactAs(other.impact) ) {
|
||||||
return effect.getFunctionalClass().isHigherPriorityThan(other.effect.getFunctionalClass());
|
return functionalClass.isHigherPriorityThan(other.functionalClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -545,13 +547,13 @@ public class SnpEff extends InfoFieldAnnotation implements RodRequiringAnnotatio
|
||||||
|
|
||||||
addAnnotation(annotations, InfoFieldKey.EFFECT_KEY.getKeyName(), effect.toString());
|
addAnnotation(annotations, InfoFieldKey.EFFECT_KEY.getKeyName(), effect.toString());
|
||||||
addAnnotation(annotations, InfoFieldKey.IMPACT_KEY.getKeyName(), impact.toString());
|
addAnnotation(annotations, InfoFieldKey.IMPACT_KEY.getKeyName(), impact.toString());
|
||||||
|
addAnnotation(annotations, InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName(), functionalClass.toString());
|
||||||
addAnnotation(annotations, InfoFieldKey.CODON_CHANGE_KEY.getKeyName(), codonChange);
|
addAnnotation(annotations, InfoFieldKey.CODON_CHANGE_KEY.getKeyName(), codonChange);
|
||||||
addAnnotation(annotations, InfoFieldKey.AMINO_ACID_CHANGE_KEY.getKeyName(), aminoAcidChange);
|
addAnnotation(annotations, InfoFieldKey.AMINO_ACID_CHANGE_KEY.getKeyName(), aminoAcidChange);
|
||||||
addAnnotation(annotations, InfoFieldKey.GENE_NAME_KEY.getKeyName(), geneName);
|
addAnnotation(annotations, InfoFieldKey.GENE_NAME_KEY.getKeyName(), geneName);
|
||||||
addAnnotation(annotations, InfoFieldKey.GENE_BIOTYPE_KEY.getKeyName(), geneBiotype);
|
addAnnotation(annotations, InfoFieldKey.GENE_BIOTYPE_KEY.getKeyName(), geneBiotype);
|
||||||
addAnnotation(annotations, InfoFieldKey.TRANSCRIPT_ID_KEY.getKeyName(), transcriptID);
|
addAnnotation(annotations, InfoFieldKey.TRANSCRIPT_ID_KEY.getKeyName(), transcriptID);
|
||||||
addAnnotation(annotations, InfoFieldKey.EXON_ID_KEY.getKeyName(), exonID);
|
addAnnotation(annotations, InfoFieldKey.EXON_ID_KEY.getKeyName(), exonID);
|
||||||
addAnnotation(annotations, InfoFieldKey.FUNCTIONAL_CLASS_KEY.getKeyName(), effect.getFunctionalClass().toString());
|
|
||||||
|
|
||||||
return annotations;
|
return annotations;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ public class SnpEffUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void testParseWellFormedEffect() {
|
public void testParseWellFormedEffect() {
|
||||||
String effectName = "NON_SYNONYMOUS_CODING";
|
String effectName = "NON_SYNONYMOUS_CODING";
|
||||||
String[] effectMetadata = { "MODERATE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829" };
|
String[] effectMetadata = { "MODERATE", "MISSENSE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829" };
|
||||||
|
|
||||||
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
||||||
Assert.assertTrue( effect.isWellFormed() && effect.isCoding() );
|
Assert.assertTrue( effect.isWellFormed() && effect.isCoding() );
|
||||||
|
|
@ -42,7 +42,7 @@ public class SnpEffUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void testParseInvalidEffectNameEffect() {
|
public void testParseInvalidEffectNameEffect() {
|
||||||
String effectName = "MADE_UP_EFFECT";
|
String effectName = "MADE_UP_EFFECT";
|
||||||
String[] effectMetadata = { "MODERATE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829" };
|
String[] effectMetadata = { "MODERATE", "MISSENSE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829" };
|
||||||
|
|
||||||
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
||||||
Assert.assertFalse(effect.isWellFormed());
|
Assert.assertFalse(effect.isWellFormed());
|
||||||
|
|
@ -51,7 +51,7 @@ public class SnpEffUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void testParseInvalidEffectImpactEffect() {
|
public void testParseInvalidEffectImpactEffect() {
|
||||||
String effectName = "NON_SYNONYMOUS_CODING";
|
String effectName = "NON_SYNONYMOUS_CODING";
|
||||||
String[] effectMetadata = { "MEDIUM", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829" };
|
String[] effectMetadata = { "MEDIUM", "MISSENSE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829" };
|
||||||
|
|
||||||
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
||||||
Assert.assertFalse(effect.isWellFormed());
|
Assert.assertFalse(effect.isWellFormed());
|
||||||
|
|
@ -60,27 +60,27 @@ public class SnpEffUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void testParseWrongNumberOfMetadataFieldsEffect() {
|
public void testParseWrongNumberOfMetadataFieldsEffect() {
|
||||||
String effectName = "NON_SYNONYMOUS_CODING";
|
String effectName = "NON_SYNONYMOUS_CODING";
|
||||||
String[] effectMetadata = { "MODERATE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990" };
|
String[] effectMetadata = { "MODERATE", "MISSENSE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990" };
|
||||||
|
|
||||||
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
||||||
Assert.assertFalse(effect.isWellFormed());
|
Assert.assertFalse(effect.isWellFormed());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseSnpEffWarningEffect() {
|
public void testParseSnpEffOneWarningOrErrorEffect() {
|
||||||
String effectName = "NON_SYNONYMOUS_CODING";
|
String effectName = "NON_SYNONYMOUS_CODING";
|
||||||
String[] effectMetadata = { "MODERATE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829", "SNPEFF_WARNING" };
|
String[] effectMetadata = { "MODERATE", "MISSENSE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829", "SNPEFF_WARNING_OR_ERROR_TEXT" };
|
||||||
|
|
||||||
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
||||||
Assert.assertTrue( ! effect.isWellFormed() && effect.getParseError().equals("SnpEff issued the following warning: SNPEFF_WARNING") );
|
Assert.assertTrue( ! effect.isWellFormed() && effect.getParseError().equals("SnpEff issued the following warning or error: \"SNPEFF_WARNING_OR_ERROR_TEXT\"") );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseSnpEffErrorEffect() {
|
public void testParseSnpEffBothWarningAndErrorEffect() {
|
||||||
String effectName = "NON_SYNONYMOUS_CODING";
|
String effectName = "NON_SYNONYMOUS_CODING";
|
||||||
String[] effectMetadata = { "MODERATE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829", "", "SNPEFF_ERROR" };
|
String[] effectMetadata = { "MODERATE", "MISSENSE", "Aca/Gca", "T/A", "OR4F5", "protein_coding", "CODING", "ENST00000534990", "exon_1_69037_69829", "SNPEFF_WARNING_TEXT", "SNPEFF_ERROR_TEXT" };
|
||||||
|
|
||||||
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
SnpEffEffect effect = new SnpEffEffect(effectName, effectMetadata);
|
||||||
Assert.assertTrue( ! effect.isWellFormed() && effect.getParseError().equals("SnpEff issued the following error: SNPEFF_ERROR") );
|
Assert.assertTrue( ! effect.isWellFormed() && effect.getParseError().equals("SnpEff issued the following warning: \"SNPEFF_WARNING_TEXT\", and the following error: \"SNPEFF_ERROR_TEXT\"") );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -148,9 +148,9 @@ public class VariantAnnotatorIntegrationTest extends WalkerTest {
|
||||||
WalkerTestSpec spec = new WalkerTestSpec(
|
WalkerTestSpec spec = new WalkerTestSpec(
|
||||||
"-T VariantAnnotator -R " + hg19Reference + " -NO_HEADER -o %s -A SnpEff --variant " +
|
"-T VariantAnnotator -R " + hg19Reference + " -NO_HEADER -o %s -A SnpEff --variant " +
|
||||||
validationDataLocation + "1kg_exomes_unfiltered.AFR.unfiltered.vcf --snpEffFile " + validationDataLocation +
|
validationDataLocation + "1kg_exomes_unfiltered.AFR.unfiltered.vcf --snpEffFile " + validationDataLocation +
|
||||||
"snpEff.AFR.unfiltered.vcf -L 1:1-1,500,000 -L 2:232,325,429",
|
"snpEff2.0.4.AFR.unfiltered.vcf -L 1:1-1,500,000 -L 2:232,325,429",
|
||||||
1,
|
1,
|
||||||
Arrays.asList("122321a85e448f21679f6ca15c5e22ad")
|
Arrays.asList("51258f5c880bd1ca3eb45a1711335c66")
|
||||||
);
|
);
|
||||||
executeTest("Testing SnpEff annotations", spec);
|
executeTest("Testing SnpEff annotations", spec);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,16 +21,16 @@ public class VariantEvalIntegrationTest extends WalkerTest {
|
||||||
"-T VariantEval",
|
"-T VariantEval",
|
||||||
"-R " + b37KGReference,
|
"-R " + b37KGReference,
|
||||||
"--dbsnp " + b37dbSNP132,
|
"--dbsnp " + b37dbSNP132,
|
||||||
"--eval " + validationDataLocation + "snpEff.AFR.unfiltered.VariantAnnotator.output.vcf",
|
"--eval " + validationDataLocation + "snpEff2.0.4.AFR.unfiltered.VariantAnnotator.output.vcf",
|
||||||
"-noEV",
|
"-noEV",
|
||||||
"-EV TiTvVariantEvaluator",
|
"-EV TiTvVariantEvaluator",
|
||||||
"-noST",
|
"-noST",
|
||||||
"-ST FunctionalClass",
|
"-ST FunctionalClass",
|
||||||
"-L " + validationDataLocation + "snpEff.AFR.unfiltered.VariantAnnotator.output.vcf",
|
"-L " + validationDataLocation + "snpEff2.0.4.AFR.unfiltered.VariantAnnotator.output.vcf",
|
||||||
"-o %s"
|
"-o %s"
|
||||||
),
|
),
|
||||||
1,
|
1,
|
||||||
Arrays.asList("d9dcb352c53106f54fcc981f15d35a90")
|
Arrays.asList("a36414421621b377d6146d58d2fcecd0")
|
||||||
);
|
);
|
||||||
executeTest("testFunctionClassWithSnpeff", spec);
|
executeTest("testFunctionClassWithSnpeff", spec);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue