Multiple bugfixes

-- VariantFiltration now properly sets passFilters in VC
-- BCF2 writer now properly decodes lazy BCF genotype data that it uses.  Improper use generated a horrible subtle bug but the good news is that the extra checks I put in (unnecessarily a few days ago) caught the bug!

Signed-off-by: Mark DePristo <depristo@broadinstitute.org>
This commit is contained in:
Mark DePristo 2012-07-24 17:20:21 -04:00
parent 3066894215
commit 19a257a5c1
3 changed files with 31 additions and 21 deletions

View File

@ -333,6 +333,10 @@ public class VariantFiltration extends RodWalker<Integer, Integer> {
filters.add(exp.name); filters.add(exp.name);
} }
} }
if ( filters.isEmpty() )
builder.passFilters();
else
builder.filters(filters); builder.filters(filters);
writer.add(builder.make()); writer.add(builder.make());

View File

@ -246,8 +246,10 @@ class BCF2Writer extends IndexingVariantContextWriter {
private BCF2Codec.LazyData getLazyData(final VariantContext vc) { private BCF2Codec.LazyData getLazyData(final VariantContext vc) {
if ( vc.getGenotypes().isLazyWithData() ) { if ( vc.getGenotypes().isLazyWithData() ) {
LazyGenotypesContext lgc = (LazyGenotypesContext)vc.getGenotypes(); LazyGenotypesContext lgc = (LazyGenotypesContext)vc.getGenotypes();
if ( lgc.getUnparsedGenotypeData() instanceof BCF2Codec.LazyData ) if ( WRITE_UNDECODED_GENOTYPE_BLOCK && lgc.getUnparsedGenotypeData() instanceof BCF2Codec.LazyData )
return (BCF2Codec.LazyData)lgc.getUnparsedGenotypeData(); return (BCF2Codec.LazyData)lgc.getUnparsedGenotypeData();
else
lgc.decode(); // WARNING -- required to avoid keeping around bad lazy data for too long
} }
return null; return null;
@ -286,6 +288,8 @@ class BCF2Writer extends IndexingVariantContextWriter {
private void buildFilter( VariantContext vc ) throws IOException { private void buildFilter( VariantContext vc ) throws IOException {
if ( vc.isFiltered() ) { if ( vc.isFiltered() ) {
encodeStringsByRef(vc.getFilters()); encodeStringsByRef(vc.getFilters());
} else if ( vc.filtersWereApplied() ) {
encodeStringsByRef(Collections.singleton(VCFConstants.PASSES_FILTERS_v4));
} else { } else {
encoder.encodeTypedMissing(BCF2Type.INT8); encoder.encodeTypedMissing(BCF2Type.INT8);
} }
@ -303,11 +307,12 @@ class BCF2Writer extends IndexingVariantContextWriter {
} }
private byte[] buildSamplesData(final VariantContext vc) throws IOException { private byte[] buildSamplesData(final VariantContext vc) throws IOException {
final BCF2Codec.LazyData lazyData = getLazyData(vc); final BCF2Codec.LazyData lazyData = getLazyData(vc); // has critical side effects
if ( WRITE_UNDECODED_GENOTYPE_BLOCK && lazyData != null ) { if ( lazyData != null ) {
// we never decoded any data from this BCF file, so just pass it back // we never decoded any data from this BCF file, so just pass it back
return lazyData.bytes; return lazyData.bytes;
} else { }
// we have to do work to convert the VC into a BCF2 byte stream // we have to do work to convert the VC into a BCF2 byte stream
final List<String> genotypeFields = VCFWriter.calcVCFGenotypeKeys(vc, header); final List<String> genotypeFields = VCFWriter.calcVCFGenotypeKeys(vc, header);
for ( final String field : genotypeFields ) { for ( final String field : genotypeFields ) {
@ -324,7 +329,6 @@ class BCF2Writer extends IndexingVariantContextWriter {
} }
return encoder.getRecordBytes(); return encoder.getRecordBytes();
} }
}
/** /**
* Throws a meaningful error message when a field (INFO or FORMAT) is found when writing out a file * Throws a meaningful error message when a field (INFO or FORMAT) is found when writing out a file

View File

@ -740,6 +740,8 @@ public class VariantContextTestProvider {
Assert.assertEquals(actual.getAlleles(), expected.getAlleles(), "alleles"); Assert.assertEquals(actual.getAlleles(), expected.getAlleles(), "alleles");
assertAttributesEquals(actual.getAttributes(), expected.getAttributes()); assertAttributesEquals(actual.getAttributes(), expected.getAttributes());
Assert.assertEquals(actual.filtersWereApplied(), expected.filtersWereApplied(), "filtersWereApplied");
Assert.assertEquals(actual.isFiltered(), expected.isFiltered(), "isFiltered");
BaseTest.assertEqualsSet(actual.getFilters(), expected.getFilters(), "filters"); BaseTest.assertEqualsSet(actual.getFilters(), expected.getFilters(), "filters");
BaseTest.assertEqualsDoubleSmart(actual.getPhredScaledQual(), expected.getPhredScaledQual()); BaseTest.assertEqualsDoubleSmart(actual.getPhredScaledQual(), expected.getPhredScaledQual());