From 43d97c2e00024311f43c0024104ac9311ff31865 Mon Sep 17 00:00:00 2001 From: Mark DePristo Date: Thu, 3 May 2012 07:02:28 -0400 Subject: [PATCH] Rev Tribble to r97, adding binary feature support From tribble logs: Binary feature support in tribble -- Massive refactoring and cleanup -- Many bug fixes throughout -- FeatureCodec is now general, with decode etc. taking a PositionBufferedStream as an argument not a String -- See ExampleBinaryCodec for an example binary codec -- AbstractAsciiFeatureCodec provides to its subclass the same String decode, readHeader functionality before. Old ASCII codecs should inherit from this base class, and will work without additional modifications -- Split AsciiLineReader into a position tracking stream (PositionalBufferedStream). The new AsciiLineReader takes as an argument a PositionalBufferedStream and provides the readLine() functionality of before. Could potentially use optimizations (its a TODO in the code) -- The Positional interface includes some more functionality that's now necessary to support the more general decoding of binary features -- FeatureReaders now work using the general FeatureCodec interface, so they can index binary features -- Bugfixes to LinearIndexCreator off by 1 error in setting the end block position -- Deleted VariantType, since this wasn't used anywhere and it's a particularly clean why of thinking about the problem -- Moved DiploidGenotype, which is specific to Gelitext, to the gelitext package -- TabixReader requires an AsciiFeatureCodec as it's currently only implemented to handle line oriented records -- Renamed AsciiFeatureReader to TribbleIndexedFeatureReader now that it handles Ascii and binary features -- Removed unused functions here and there as encountered -- Fixed build.xml to be truly headless -- FeatureCodec readHeader returns a FeatureCodecHeader obtain that contains a value and the position in the file where the header ends (not inclusive). TribbleReaders now skip the header if the position is set, so its no longer necessary, if one implements the general readHeader(PositionalBufferedStream) version to see header lines in the decode functions. Necessary for binary codecs but a nice side benefit for ascii codecs as well -- Cleaned up the IndexFactory interface so there's a truly general createIndex function that takes the enumerated index type. Added a writeIndex() function that writes an index to disk. -- Vastly expanded the index unit tests and reader tests to really test linear, interval, and tabix indexed files. Updated test.bed, and created a tabix version of it as well. -- Significant BinaryFeaturesTest suite. -- Some test files have indent changes --- .../sting/commandline/IntervalBinding.java | 18 +--- .../ReferenceDependentFeatureCodec.java | 2 +- .../walkers/diffengine/VCFDiffableReader.java | 28 +++--- .../utils/codecs/beagle/BeagleCodec.java | 28 ++---- .../utils/codecs/hapmap/RawHapMapCodec.java | 21 ++--- .../utils/codecs/refseq/RefSeqCodec.java | 22 ++--- .../codecs/sampileup/SAMPileupCodec.java | 26 +----- .../utils/codecs/samread/SAMReadCodec.java | 28 +----- .../utils/codecs/table/BedTableCodec.java | 2 +- .../sting/utils/codecs/table/TableCodec.java | 24 ++--- .../utils/codecs/vcf/AbstractVCFCodec.java | 28 +++--- .../variantutils/CombineVariantsUnitTest.java | 3 +- .../utils/codecs/hapmap/HapMapUnitTest.java | 3 +- .../utils/genotype/vcf/VCFHeaderUnitTest.java | 3 +- .../utils/genotype/vcf/VCFWriterUnitTest.java | 24 ++--- .../VariantContextBenchmark.java | 84 +++++++++--------- .../sting/queue/util/VCF_BAM_utilities.scala | 6 +- .../{tribble-94.jar => tribble-98.jar} | Bin 297688 -> 308843 bytes .../{tribble-94.xml => tribble-98.xml} | 2 +- 19 files changed, 131 insertions(+), 221 deletions(-) rename settings/repository/org.broad/{tribble-94.jar => tribble-98.jar} (73%) rename settings/repository/org.broad/{tribble-94.xml => tribble-98.xml} (51%) diff --git a/public/java/src/org/broadinstitute/sting/commandline/IntervalBinding.java b/public/java/src/org/broadinstitute/sting/commandline/IntervalBinding.java index d1d616c97..1f873ffbd 100644 --- a/public/java/src/org/broadinstitute/sting/commandline/IntervalBinding.java +++ b/public/java/src/org/broadinstitute/sting/commandline/IntervalBinding.java @@ -25,8 +25,10 @@ package org.broadinstitute.sting.commandline; import com.google.java.contract.Requires; +import org.broad.tribble.AbstractFeatureReader; import org.broad.tribble.Feature; import org.broad.tribble.FeatureCodec; +import org.broad.tribble.FeatureReader; import org.broad.tribble.readers.AsciiLineReader; import org.broadinstitute.sting.gatk.GenomeAnalysisEngine; import org.broadinstitute.sting.gatk.refdata.ReferenceDependentFeatureCodec; @@ -77,27 +79,15 @@ public final class IntervalBinding { if ( featureIntervals != null ) { intervals = new ArrayList(); - //RMDTrackBuilder builder = new RMDTrackBuilder(toolkit.getReferenceDataSource().getReference().getSequenceDictionary(), - // toolkit.getGenomeLocParser(), - // toolkit.getArguments().unsafe); - // TODO -- after ROD system cleanup, go through the ROD system so that we can handle things like gzipped files final FeatureCodec codec = new FeatureManager().getByName(featureIntervals.getTribbleType()).getCodec(); if ( codec instanceof ReferenceDependentFeatureCodec ) ((ReferenceDependentFeatureCodec)codec).setGenomeLocParser(toolkit.getGenomeLocParser()); try { - final FileInputStream fis = new FileInputStream(new File(featureIntervals.getSource())); - final AsciiLineReader lineReader = new AsciiLineReader(fis); - codec.readHeader(lineReader); - String line = lineReader.readLine(); - while ( line != null ) { - final Feature feature = codec.decodeLoc(line); - if ( feature == null ) - throw new UserException.MalformedFile(featureIntervals.getSource(), "Couldn't parse line '" + line + "'"); + FeatureReader reader = AbstractFeatureReader.getFeatureReader(featureIntervals.getSource(), codec, false); + for ( Feature feature : reader.iterator() ) intervals.add(toolkit.getGenomeLocParser().createGenomeLoc(feature)); - line = lineReader.readLine(); - } } catch (Exception e) { throw new UserException.MalformedFile(featureIntervals.getSource(), "Problem reading the interval file", e); } diff --git a/public/java/src/org/broadinstitute/sting/gatk/refdata/ReferenceDependentFeatureCodec.java b/public/java/src/org/broadinstitute/sting/gatk/refdata/ReferenceDependentFeatureCodec.java index b4427c228..d24686ad7 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/refdata/ReferenceDependentFeatureCodec.java +++ b/public/java/src/org/broadinstitute/sting/gatk/refdata/ReferenceDependentFeatureCodec.java @@ -33,7 +33,7 @@ import org.broadinstitute.sting.utils.GenomeLocParser; * A HACK. Tribble should contain all the information in needs to decode the unqualified position of * a feature. */ -public interface ReferenceDependentFeatureCodec extends FeatureCodec { +public interface ReferenceDependentFeatureCodec { /** * Sets the appropriate GenomeLocParser, providing additional context when decoding larger and more variable features. * @param genomeLocParser The parser to supply. diff --git a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java index c9a6cb8f2..ce79c7138 100644 --- a/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java +++ b/public/java/src/org/broadinstitute/sting/gatk/walkers/diffengine/VCFDiffableReader.java @@ -25,15 +25,16 @@ package org.broadinstitute.sting.gatk.walkers.diffengine; import org.apache.log4j.Logger; +import org.broad.tribble.AbstractFeatureReader; +import org.broad.tribble.FeatureReader; import org.broad.tribble.readers.AsciiLineReader; import org.broad.tribble.readers.LineReader; import org.broadinstitute.sting.utils.codecs.vcf.*; import org.broadinstitute.sting.utils.variantcontext.Genotype; import org.broadinstitute.sting.utils.variantcontext.VariantContext; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; +import java.io.*; +import java.util.Iterator; import java.util.Map; @@ -56,16 +57,14 @@ public class VCFDiffableReader implements DiffableReader { DiffNode root = DiffNode.rooted(file.getName()); try { // read the version line from the file - LineReader lineReader = new AsciiLineReader(new FileInputStream(file)); - final String version = lineReader.readLine(); + BufferedReader br = new BufferedReader(new FileReader(file)); + final String version = br.readLine(); root.add("VERSION", version); - lineReader.close(); - - lineReader = new AsciiLineReader(new FileInputStream(file)); - VCFCodec vcfCodec = new VCFCodec(); + br.close(); // must be read as state is stored in reader itself - VCFHeader header = (VCFHeader)vcfCodec.readHeader(lineReader); + FeatureReader reader = AbstractFeatureReader.getFeatureReader(file.getAbsolutePath(), new VCFCodec(), false); + VCFHeader header = (VCFHeader)reader.getHeader(); for ( VCFHeaderLine headerLine : header.getMetaData() ) { String key = headerLine.getKey(); if ( headerLine instanceof VCFIDHeaderLine) @@ -76,14 +75,14 @@ public class VCFDiffableReader implements DiffableReader { root.add(key, headerLine.toString()); } - String line = lineReader.readLine(); int count = 0, nRecordsAtPos = 1; String prevName = ""; - while ( line != null ) { + Iterator it = reader.iterator(); + while ( it.hasNext() ) { if ( count++ > maxElementsToRead && maxElementsToRead != -1) break; - VariantContext vc = (VariantContext)vcfCodec.decode(line); + VariantContext vc = it.next(); String name = vc.getChr() + ":" + vc.getStart(); if ( name.equals(prevName) ) { name += "_" + ++nRecordsAtPos; @@ -121,10 +120,9 @@ public class VCFDiffableReader implements DiffableReader { } root.add(vcRoot); - line = lineReader.readLine(); } - lineReader.close(); + reader.close(); } catch ( IOException e ) { return null; } diff --git a/public/java/src/org/broadinstitute/sting/utils/codecs/beagle/BeagleCodec.java b/public/java/src/org/broadinstitute/sting/utils/codecs/beagle/BeagleCodec.java index e4768fd5b..ecd396bf2 100755 --- a/public/java/src/org/broadinstitute/sting/utils/codecs/beagle/BeagleCodec.java +++ b/public/java/src/org/broadinstitute/sting/utils/codecs/beagle/BeagleCodec.java @@ -25,16 +25,14 @@ package org.broadinstitute.sting.utils.codecs.beagle; */ +import org.broad.tribble.AsciiFeatureCodec; import org.broad.tribble.Feature; import org.broad.tribble.exception.CodecLineParsingException; -import org.broad.tribble.readers.AsciiLineReader; import org.broad.tribble.readers.LineReader; import org.broadinstitute.sting.gatk.refdata.ReferenceDependentFeatureCodec; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; -import java.io.File; -import java.io.FileInputStream; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; @@ -63,7 +61,7 @@ import java.util.regex.Pattern; * @author Mark DePristo * @since 2010 */ -public class BeagleCodec implements ReferenceDependentFeatureCodec { +public class BeagleCodec extends AsciiFeatureCodec implements ReferenceDependentFeatureCodec { private String[] header; public enum BeagleReaderType {PROBLIKELIHOOD, GENOTYPES, R2}; private BeagleReaderType readerType; @@ -80,25 +78,16 @@ public class BeagleCodec implements ReferenceDependentFeatureCodec getFeatureType() { - return BeagleFeature.class; - } - public BeagleFeature decode(String line) { String[] tokens; diff --git a/public/java/src/org/broadinstitute/sting/utils/codecs/hapmap/RawHapMapCodec.java b/public/java/src/org/broadinstitute/sting/utils/codecs/hapmap/RawHapMapCodec.java index 8bdb24b6c..916fb43ea 100644 --- a/public/java/src/org/broadinstitute/sting/utils/codecs/hapmap/RawHapMapCodec.java +++ b/public/java/src/org/broadinstitute/sting/utils/codecs/hapmap/RawHapMapCodec.java @@ -24,8 +24,7 @@ package org.broadinstitute.sting.utils.codecs.hapmap; -import org.broad.tribble.AbstractFeatureCodec; -import org.broad.tribble.Feature; +import org.broad.tribble.AsciiFeatureCodec; import org.broad.tribble.annotation.Strand; import org.broad.tribble.readers.LineReader; @@ -71,18 +70,14 @@ import java.util.Arrays; * @author Mark DePristo * @since 2010 */ -public class RawHapMapCodec extends AbstractFeatureCodec { +public class RawHapMapCodec extends AsciiFeatureCodec { // the minimum number of features in the HapMap file line private static final int minimumFeatureCount = 11; private String headerLine; - /** - * decode the location only - * @param line the input line to decode - * @return a HapMapFeature - */ - public Feature decodeLoc(String line) { - return decode(line); + + public RawHapMapCodec() { + super(RawHapMapFeature.class); } /** @@ -90,7 +85,7 @@ public class RawHapMapCodec extends AbstractFeatureCodec { * @param line the input line to decode * @return a HapMapFeature, with the given fields */ - public Feature decode(String line) { + public RawHapMapFeature decode(String line) { String[] array = line.split("\\s+"); // make sure the split was successful - that we got an appropriate number of fields @@ -113,10 +108,6 @@ public class RawHapMapCodec extends AbstractFeatureCodec { headerLine); } - public Class getFeatureType() { - return RawHapMapFeature.class; - } - public Object readHeader(LineReader reader) { try { headerLine = reader.readLine(); diff --git a/public/java/src/org/broadinstitute/sting/utils/codecs/refseq/RefSeqCodec.java b/public/java/src/org/broadinstitute/sting/utils/codecs/refseq/RefSeqCodec.java index cb392f29c..736c989c6 100644 --- a/public/java/src/org/broadinstitute/sting/utils/codecs/refseq/RefSeqCodec.java +++ b/public/java/src/org/broadinstitute/sting/utils/codecs/refseq/RefSeqCodec.java @@ -1,8 +1,8 @@ package org.broadinstitute.sting.utils.codecs.refseq; +import org.broad.tribble.AsciiFeatureCodec; import org.broad.tribble.Feature; import org.broad.tribble.TribbleException; -import org.broad.tribble.readers.LineReader; import org.broadinstitute.sting.gatk.refdata.ReferenceDependentFeatureCodec; import org.broadinstitute.sting.utils.GenomeLoc; import org.broadinstitute.sting.utils.GenomeLocParser; @@ -46,13 +46,18 @@ import java.util.ArrayList; * @author Mark DePristo * @since 2010 */ -public class RefSeqCodec implements ReferenceDependentFeatureCodec { +public class RefSeqCodec extends AsciiFeatureCodec implements ReferenceDependentFeatureCodec { /** * The parser to use when resolving genome-wide locations. */ private GenomeLocParser genomeLocParser; private boolean zero_coding_length_user_warned = false; + + public RefSeqCodec() { + super(RefSeqFeature.class); + } + /** * Set the parser to use when resolving genetic data. * @param genomeLocParser The supplied parser. @@ -130,17 +135,4 @@ public class RefSeqCodec implements ReferenceDependentFeatureCodec getFeatureType() { - return RefSeqFeature.class; - } - - public boolean canDecode(final String potentialInput) { return false; } - } diff --git a/public/java/src/org/broadinstitute/sting/utils/codecs/sampileup/SAMPileupCodec.java b/public/java/src/org/broadinstitute/sting/utils/codecs/sampileup/SAMPileupCodec.java index d9f16c353..f4ba185b4 100644 --- a/public/java/src/org/broadinstitute/sting/utils/codecs/sampileup/SAMPileupCodec.java +++ b/public/java/src/org/broadinstitute/sting/utils/codecs/sampileup/SAMPileupCodec.java @@ -25,10 +25,9 @@ package org.broadinstitute.sting.utils.codecs.sampileup; -import org.broad.tribble.AbstractFeatureCodec; +import org.broad.tribble.AsciiFeatureCodec; import org.broad.tribble.Feature; import org.broad.tribble.exception.CodecLineParsingException; -import org.broad.tribble.readers.LineReader; import org.broad.tribble.util.ParsingUtils; import java.util.ArrayList; @@ -76,7 +75,7 @@ import static org.broadinstitute.sting.utils.codecs.sampileup.SAMPileupFeature.V * @author Matt Hanna * @since 2009 */ -public class SAMPileupCodec extends AbstractFeatureCodec { +public class SAMPileupCodec extends AsciiFeatureCodec { // the number of tokens we expect to parse from a pileup line private static final int expectedTokenCount = 10; private static final char fldDelim = '\t'; @@ -88,24 +87,8 @@ public class SAMPileupCodec extends AbstractFeatureCodec { private static final String baseT = "T"; private static final String emptyStr = ""; // we will use this for "reference" allele in insertions - /** - * Return the # of header lines for this file. - * - * @param reader the line reader - * @return 0 in this case, we assume no header lines. - */ - public Object readHeader(LineReader reader) { - // we don't require a header line, but it may exist. We'll deal with that above. - return null; - } - - @Override - public Class getFeatureType() { - return SAMPileupFeature.class; - } - - public Feature decodeLoc(String line) { - return decode(line); + public SAMPileupCodec() { + super(SAMPileupFeature.class); } public SAMPileupFeature decode(String line) { @@ -285,5 +268,4 @@ public class SAMPileupCodec extends AbstractFeatureCodec { feature.setPileupBases(baseBuilder.toString()); feature.setPileupQuals(qualBuilder.toString()); } - } diff --git a/public/java/src/org/broadinstitute/sting/utils/codecs/samread/SAMReadCodec.java b/public/java/src/org/broadinstitute/sting/utils/codecs/samread/SAMReadCodec.java index 0f2b94e63..4459c44f2 100644 --- a/public/java/src/org/broadinstitute/sting/utils/codecs/samread/SAMReadCodec.java +++ b/public/java/src/org/broadinstitute/sting/utils/codecs/samread/SAMReadCodec.java @@ -27,10 +27,9 @@ package org.broadinstitute.sting.utils.codecs.samread; import net.sf.samtools.Cigar; import net.sf.samtools.TextCigarCodec; import net.sf.samtools.util.StringUtil; -import org.broad.tribble.AbstractFeatureCodec; +import org.broad.tribble.AsciiFeatureCodec; import org.broad.tribble.Feature; import org.broad.tribble.exception.CodecLineParsingException; -import org.broad.tribble.readers.LineReader; import org.broad.tribble.util.ParsingUtils; /** @@ -52,31 +51,14 @@ import org.broad.tribble.util.ParsingUtils; * @author Matt Hanna * @since 2009 */ -public class SAMReadCodec extends AbstractFeatureCodec { +public class SAMReadCodec extends AsciiFeatureCodec { /* SL-XBC:1:10:628:923#0 16 Escherichia_coli_K12 1 37 76M = 1 0 AGCTTTTCATTCTGACTGCAACGGGCAATATGTCTCTGTGTGGATTAAAAAAAGAGTGTCTGATAGCAGCTTCTGA B@>87<;A@?@957:>>@AA@B>@A9AB@B>@A@@@@@A;=AAB@BBBBBCBBBB@>A>:ABB@BAABCB=CA@CB */ // the number of tokens we expect to parse from a read line private static final int expectedTokenCount = 11; - /** - * Return the # of header lines for this file. - * - * @param reader the line reader - * @return 0 in this case, we assume no header lines. The reads file may have a - * header line beginning with '@', but we can ignore that in the decode function. - */ - public Object readHeader(LineReader reader) { - // we don't require a header line, but it may exist. We'll deal with that above. - return null; - } - - @Override - public Class getFeatureType() { - return SAMReadFeature.class; - } - - public Feature decodeLoc(String line) { - return decode(line); + public SAMReadCodec() { + super(SAMReadFeature.class); } /** @@ -131,6 +113,4 @@ public class SAMReadCodec extends AbstractFeatureCodec { bases, qualities); } - - } diff --git a/public/java/src/org/broadinstitute/sting/utils/codecs/table/BedTableCodec.java b/public/java/src/org/broadinstitute/sting/utils/codecs/table/BedTableCodec.java index fdcc8ed10..5937d1f1f 100755 --- a/public/java/src/org/broadinstitute/sting/utils/codecs/table/BedTableCodec.java +++ b/public/java/src/org/broadinstitute/sting/utils/codecs/table/BedTableCodec.java @@ -23,7 +23,7 @@ import java.util.Arrays; public class BedTableCodec extends TableCodec implements ReferenceDependentFeatureCodec { @Override - public Feature decode(String line) { + public TableFeature decode(String line) { if (line.startsWith(headerDelimiter) || line.startsWith(commentDelimiter) || line.startsWith(igvHeaderDelimiter)) return null; String[] split = line.split(delimiterRegex); diff --git a/public/java/src/org/broadinstitute/sting/utils/codecs/table/TableCodec.java b/public/java/src/org/broadinstitute/sting/utils/codecs/table/TableCodec.java index aa6d7d345..22d754098 100755 --- a/public/java/src/org/broadinstitute/sting/utils/codecs/table/TableCodec.java +++ b/public/java/src/org/broadinstitute/sting/utils/codecs/table/TableCodec.java @@ -1,6 +1,6 @@ package org.broadinstitute.sting.utils.codecs.table; -import org.broad.tribble.Feature; +import org.broad.tribble.AsciiFeatureCodec; import org.broad.tribble.readers.LineReader; import org.broadinstitute.sting.gatk.refdata.ReferenceDependentFeatureCodec; import org.broadinstitute.sting.utils.GenomeLocParser; @@ -39,7 +39,7 @@ import java.util.Arrays; * @author Mark DePristo * @since 2009 */ -public class TableCodec implements ReferenceDependentFeatureCodec { +public class TableCodec extends AsciiFeatureCodec implements ReferenceDependentFeatureCodec { final static protected String delimiterRegex = "\\s+"; final static protected String headerDelimiter = "HEADER"; final static protected String igvHeaderDelimiter = "track"; @@ -52,6 +52,10 @@ public class TableCodec implements ReferenceDependentFeatureCodec { */ protected GenomeLocParser genomeLocParser; + public TableCodec() { + super(TableFeature.class); + } + /** * Set the parser to use when resolving genetic data. * @param genomeLocParser The supplied parser. @@ -61,14 +65,8 @@ public class TableCodec implements ReferenceDependentFeatureCodec { this.genomeLocParser = genomeLocParser; } - @Override - public Feature decodeLoc(String line) { - return decode(line); - } - - @Override - public Feature decode(String line) { + public TableFeature decode(String line) { if (line.startsWith(headerDelimiter) || line.startsWith(commentDelimiter) || line.startsWith(igvHeaderDelimiter)) return null; String[] split = line.split(delimiterRegex); @@ -77,11 +75,6 @@ public class TableCodec implements ReferenceDependentFeatureCodec { return new TableFeature(genomeLocParser.parseGenomeLoc(split[0]),Arrays.asList(split),header); } - @Override - public Class getFeatureType() { - return TableFeature.class; - } - @Override public Object readHeader(LineReader reader) { String line = ""; @@ -106,7 +99,4 @@ public class TableCodec implements ReferenceDependentFeatureCodec { } return header; } - - public boolean canDecode(final String potentialInput) { return false; } - } diff --git a/public/java/src/org/broadinstitute/sting/utils/codecs/vcf/AbstractVCFCodec.java b/public/java/src/org/broadinstitute/sting/utils/codecs/vcf/AbstractVCFCodec.java index 7d39dc789..66ed908eb 100755 --- a/public/java/src/org/broadinstitute/sting/utils/codecs/vcf/AbstractVCFCodec.java +++ b/public/java/src/org/broadinstitute/sting/utils/codecs/vcf/AbstractVCFCodec.java @@ -1,8 +1,8 @@ package org.broadinstitute.sting.utils.codecs.vcf; import org.apache.log4j.Logger; +import org.broad.tribble.AsciiFeatureCodec; import org.broad.tribble.Feature; -import org.broad.tribble.FeatureCodec; import org.broad.tribble.NameAwareCodec; import org.broad.tribble.TribbleException; import org.broad.tribble.readers.LineReader; @@ -10,14 +10,20 @@ import org.broad.tribble.util.BlockCompressedInputStream; import org.broad.tribble.util.ParsingUtils; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.broadinstitute.sting.utils.exceptions.UserException; -import org.broadinstitute.sting.utils.variantcontext.*; +import org.broadinstitute.sting.utils.variantcontext.Allele; +import org.broadinstitute.sting.utils.variantcontext.LazyGenotypesContext; +import org.broadinstitute.sting.utils.variantcontext.VariantContext; +import org.broadinstitute.sting.utils.variantcontext.VariantContextBuilder; -import java.io.*; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.util.*; import java.util.zip.GZIPInputStream; -public abstract class AbstractVCFCodec implements FeatureCodec, NameAwareCodec { +public abstract class AbstractVCFCodec extends AsciiFeatureCodec implements NameAwareCodec { public final static int MAX_ALLELE_SIZE_BEFORE_WARNING = (int)Math.pow(2, 20); protected final static Logger log = Logger.getLogger(VCFCodec.class); @@ -61,6 +67,10 @@ public abstract class AbstractVCFCodec implements FeatureCodec, NameAwareCodec { protected Map stringCache = new HashMap(); + protected AbstractVCFCodec() { + super(VariantContext.class); + } + /** * Creates a LazyParser for a LazyGenotypesContext to use to decode * our genotypes only when necessary. We do this instead of eagarly @@ -266,7 +276,7 @@ public abstract class AbstractVCFCodec implements FeatureCodec, NameAwareCodec { * @param line the line * @return a VariantContext */ - public Feature decode(String line) { + public VariantContext decode(String line) { // the same line reader is not used for parsing the header and parsing lines, if we see a #, we've seen a header line if (line.startsWith(VCFHeader.HEADER_INDICATOR)) return null; @@ -378,14 +388,6 @@ public abstract class AbstractVCFCodec implements FeatureCodec, NameAwareCodec { return vc; } - /** - * - * @return the type of record - */ - public Class getFeatureType() { - return VariantContext.class; - } - /** * get the name of this codec * @return our set name diff --git a/public/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java b/public/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java index a64d0b5ab..464dcd807 100644 --- a/public/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/gatk/walkers/variantutils/CombineVariantsUnitTest.java @@ -1,6 +1,7 @@ package org.broadinstitute.sting.gatk.walkers.variantutils; import org.broad.tribble.readers.AsciiLineReader; +import org.broad.tribble.readers.PositionalBufferedStream; import org.broadinstitute.sting.utils.codecs.vcf.VCFCodec; import org.broadinstitute.sting.utils.codecs.vcf.VCFHeader; import org.broadinstitute.sting.utils.codecs.vcf.VCFHeaderLine; @@ -63,7 +64,7 @@ public class CombineVariantsUnitTest { private VCFHeader createHeader(String headerStr) { VCFCodec codec = new VCFCodec(); - VCFHeader head = (VCFHeader)codec.readHeader(new AsciiLineReader(new StringBufferInputStream(headerStr))); + VCFHeader head = (VCFHeader)codec.readHeader(new AsciiLineReader(new PositionalBufferedStream(new StringBufferInputStream(headerStr)))); return head; } diff --git a/public/java/test/org/broadinstitute/sting/utils/codecs/hapmap/HapMapUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/codecs/hapmap/HapMapUnitTest.java index 5fd4c610e..914783ca8 100644 --- a/public/java/test/org/broadinstitute/sting/utils/codecs/hapmap/HapMapUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/codecs/hapmap/HapMapUnitTest.java @@ -26,6 +26,7 @@ package org.broadinstitute.sting.utils.codecs.hapmap; import org.broad.tribble.annotation.Strand; import org.broad.tribble.readers.AsciiLineReader; +import org.broad.tribble.readers.PositionalBufferedStream; import org.testng.Assert; import org.testng.annotations.Test; @@ -152,7 +153,7 @@ public class HapMapUnitTest { public AsciiLineReader getReader() { try { - return new AsciiLineReader(new FileInputStream(hapMapFile)); + return new AsciiLineReader(new PositionalBufferedStream(new FileInputStream(hapMapFile))); } catch (FileNotFoundException e) { Assert.fail("Unable to open hapmap file : " + hapMapFile); } diff --git a/public/java/test/org/broadinstitute/sting/utils/genotype/vcf/VCFHeaderUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/genotype/vcf/VCFHeaderUnitTest.java index 14e63191d..a6bfffab1 100644 --- a/public/java/test/org/broadinstitute/sting/utils/genotype/vcf/VCFHeaderUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/genotype/vcf/VCFHeaderUnitTest.java @@ -1,6 +1,7 @@ package org.broadinstitute.sting.utils.genotype.vcf; import org.broad.tribble.readers.AsciiLineReader; +import org.broad.tribble.readers.PositionalBufferedStream; import org.broadinstitute.sting.utils.codecs.vcf.*; import org.broadinstitute.sting.utils.exceptions.ReviewedStingException; import org.testng.Assert; @@ -24,7 +25,7 @@ public class VCFHeaderUnitTest extends BaseTest { private VCFHeader createHeader(String headerStr) { VCFCodec codec = new VCFCodec(); - VCFHeader header = (VCFHeader)codec.readHeader(new AsciiLineReader(new StringBufferInputStream(headerStr))); + VCFHeader header = (VCFHeader)codec.readHeader(new AsciiLineReader(new PositionalBufferedStream(new StringBufferInputStream(headerStr)))); Assert.assertEquals(header.getMetaData().size(), VCF4headerStringCount); return header; } diff --git a/public/java/test/org/broadinstitute/sting/utils/genotype/vcf/VCFWriterUnitTest.java b/public/java/test/org/broadinstitute/sting/utils/genotype/vcf/VCFWriterUnitTest.java index 96a33b738..7059cdced 100644 --- a/public/java/test/org/broadinstitute/sting/utils/genotype/vcf/VCFWriterUnitTest.java +++ b/public/java/test/org/broadinstitute/sting/utils/genotype/vcf/VCFWriterUnitTest.java @@ -1,7 +1,10 @@ package org.broadinstitute.sting.utils.genotype.vcf; +import org.broad.tribble.AbstractFeatureReader; +import org.broad.tribble.FeatureReader; import org.broad.tribble.Tribble; import org.broad.tribble.readers.AsciiLineReader; +import org.broad.tribble.readers.PositionalBufferedStream; import org.broadinstitute.sting.utils.variantcontext.*; import org.broadinstitute.sting.utils.codecs.vcf.*; import org.broadinstitute.sting.utils.exceptions.UserException; @@ -59,16 +62,10 @@ public class VCFWriterUnitTest extends BaseTest { writer.add(createVC(header)); writer.add(createVC(header)); writer.close(); - VCFCodec reader = new VCFCodec(); - AsciiLineReader lineReader; + VCFCodec codec = new VCFCodec(); VCFHeader headerFromFile = null; - try { - lineReader = new AsciiLineReader(new FileInputStream(fakeVCFFile)); - headerFromFile = (VCFHeader)reader.readHeader(lineReader); - } - catch (FileNotFoundException e ) { - throw new ReviewedStingException(e.getMessage()); - } + FeatureReader reader = AbstractFeatureReader.getFeatureReader(fakeVCFFile.getAbsolutePath(), codec, false); + headerFromFile = (VCFHeader)reader.getHeader(); int counter = 0; @@ -76,12 +73,9 @@ public class VCFWriterUnitTest extends BaseTest { validateHeader(headerFromFile); try { - while(true) { - String line = lineReader.readLine(); - if (line == null) - break; - - VariantContext vc = (VariantContext)reader.decode(line); + Iterator it = reader.iterator(); + while(it.hasNext()) { + VariantContext vc = it.next(); counter++; } Assert.assertEquals(counter, 2); diff --git a/public/java/test/org/broadinstitute/sting/utils/variantcontext/VariantContextBenchmark.java b/public/java/test/org/broadinstitute/sting/utils/variantcontext/VariantContextBenchmark.java index a71949369..e38466beb 100644 --- a/public/java/test/org/broadinstitute/sting/utils/variantcontext/VariantContextBenchmark.java +++ b/public/java/test/org/broadinstitute/sting/utils/variantcontext/VariantContextBenchmark.java @@ -78,30 +78,31 @@ public class VariantContextBenchmark extends SimpleBenchmark { private GenomeLocParser b37GenomeLocParser; @Override protected void setUp() { - try { - ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(BaseTest.b37KGReference)); - b37GenomeLocParser = new GenomeLocParser(seq); - } catch ( FileNotFoundException e) { - throw new RuntimeException(e); - } - - // read it into a String so that we don't try to benchmark IO issues - try { - FileInputStream s = new FileInputStream(new File(vcfFile)); - AsciiLineReader lineReader = new AsciiLineReader(s); - int counter = 0; - StringBuffer sb = new StringBuffer(); - while (counter++ < linesToRead ) { - String line = lineReader.readLine(); - if ( line == null ) - break; - sb.append(line + "\n"); - } - s.close(); - INPUT_STRING = sb.toString(); - } catch (IOException e) { - throw new RuntimeException(e); - } + // TODO -- update for new tribble interface +// try { +// ReferenceSequenceFile seq = new CachingIndexedFastaSequenceFile(new File(BaseTest.b37KGReference)); +// b37GenomeLocParser = new GenomeLocParser(seq); +// } catch ( FileNotFoundException e) { +// throw new RuntimeException(e); +// } +// +// // read it into a String so that we don't try to benchmark IO issues +// try { +// FileInputStream s = new FileInputStream(new File(vcfFile)); +// AsciiLineReader lineReader = new AsciiLineReader(s); +// int counter = 0; +// StringBuffer sb = new StringBuffer(); +// while (counter++ < linesToRead ) { +// String line = lineReader.readLine(); +// if ( line == null ) +// break; +// sb.append(line + "\n"); +// } +// s.close(); +// INPUT_STRING = sb.toString(); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } } private interface FunctionToBenchmark { @@ -109,23 +110,24 @@ public class VariantContextBenchmark extends SimpleBenchmark { } private void runBenchmark(FeatureCodec codec, FunctionToBenchmark func) { - try { - InputStream is = new ByteArrayInputStream(INPUT_STRING.getBytes()); - AsciiLineReader lineReader = new AsciiLineReader(is); - codec.readHeader(lineReader); - - int counter = 0; - while (counter++ < linesToRead ) { - String line = lineReader.readLine(); - if ( line == null ) - break; - - T vc = codec.decode(line); - func.run(vc); - } - } catch (Exception e) { - System.out.println("Benchmarking run failure because of " + e.getMessage()); - } + // TODO -- update for new Tribble interface +// try { +// InputStream is = new ByteArrayInputStream(INPUT_STRING.getBytes()); +// AsciiLineReader lineReader = new AsciiLineReader(is); +// codec.readHeader(lineReader); +// +// int counter = 0; +// while (counter++ < linesToRead ) { +// String line = lineReader.readLine(); +// if ( line == null ) +// break; +// +// T vc = codec.decode(line); +// func.run(vc); +// } +// } catch (Exception e) { +// System.out.println("Benchmarking run failure because of " + e.getMessage()); +// } } public void timeV14(int rep) { diff --git a/public/scala/src/org/broadinstitute/sting/queue/util/VCF_BAM_utilities.scala b/public/scala/src/org/broadinstitute/sting/queue/util/VCF_BAM_utilities.scala index bb2d4f864..33e9adb8d 100644 --- a/public/scala/src/org/broadinstitute/sting/queue/util/VCF_BAM_utilities.scala +++ b/public/scala/src/org/broadinstitute/sting/queue/util/VCF_BAM_utilities.scala @@ -6,12 +6,14 @@ import scala.io.Source._ import net.sf.samtools.SAMFileReader import org.broadinstitute.sting.utils.codecs.vcf.{VCFHeader, VCFCodec} import scala.collection.JavaConversions._ -import org.broad.tribble.AbstractFeatureReader +import org.broad.tribble.{FeatureCodec, AbstractFeatureReader} object VCF_BAM_utilities { def getSamplesFromVCF(vcfFile: File): List[String] = { - return AbstractFeatureReader.getFeatureReader(vcfFile.getPath(), new VCFCodec()).getHeader().asInstanceOf[VCFHeader].getGenotypeSamples().toList + List(); + // TODO -- ask khalid for help here with type error + //return AbstractFeatureReader.getFeatureReader(vcfFile.getPath(), new VCFCodec()).getHeader().asInstanceOf[VCFHeader].getGenotypeSamples().toList } def getSamplesInBAM(bam: File): List[String] = { diff --git a/settings/repository/org.broad/tribble-94.jar b/settings/repository/org.broad/tribble-98.jar similarity index 73% rename from settings/repository/org.broad/tribble-94.jar rename to settings/repository/org.broad/tribble-98.jar index 5f534f08bd8951ca1ceb23b660d5b79b0a428822..7a4be053929b08a3a365ec353423fe258d361402 100644 GIT binary patch delta 40972 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%0D(kaozqkd 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 W12>u#lS#$xj?b;e-L8#j9>f2ba7#-7 delta 33088 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 - +