[med-svn] [htsjdk] 01/03: New upstream version 2.6.1+dfsg
Andreas Tille
tille at debian.org
Sat Sep 10 07:24:29 UTC 2016
This is an automated email from the git hooks/post-receive script.
tille pushed a commit to branch master
in repository htsjdk.
commit 00ff79c932305f3f642fa87ba339b43d77318331
Author: Andreas Tille <tille at debian.org>
Date: Sat Sep 10 08:02:45 2016 +0200
New upstream version 2.6.1+dfsg
---
README.md | 2 +
build.gradle | 1 +
src/main/java/htsjdk/samtools/CRAMIterator.java | 12 +-
.../htsjdk/samtools/DuplicateScoringStrategy.java | 10 +-
src/main/java/htsjdk/samtools/SAMRecordUtil.java | 104 ++++++++++++-----
src/main/java/htsjdk/samtools/SAMUtils.java | 124 ++++++++++++++++++++
src/main/java/htsjdk/samtools/SRAFileReader.java | 3 +-
src/main/java/htsjdk/samtools/SamPairUtil.java | 5 +-
.../java/htsjdk/samtools/cram/build/Utils.java | 4 +-
.../cram/encoding/reader/DataReaderFactory.java | 4 +-
.../samtools/cram/ref/CRAMReferenceSource.java | 4 +-
.../htsjdk/samtools/cram/ref/ReferenceSource.java | 22 ++--
.../samtools/cram/structure/CompressionHeader.java | 4 +-
.../htsjdk/samtools/filter/IntervalFilter.java | 5 +-
.../samtools/filter/IntervalKeepPairFilter.java | 108 +++++++++++++++++
.../java/htsjdk/samtools/sra/SRAAccession.java | 4 +-
.../htsjdk/samtools/util/AbstractAsyncWriter.java | 7 +-
.../java/htsjdk/samtools/util/BlockGunzipper.java | 29 ++++-
src/main/java/htsjdk/samtools/util/Lazy.java | 1 +
.../htsjdk/samtools/util/SamLocusIterator.java | 2 +
src/main/java/htsjdk/samtools/util/TestUtil.java | 5 +
.../java/htsjdk/tribble/BinaryFeatureCodec.java | 9 ++
src/main/java/htsjdk/tribble/FeatureCodec.java | 14 +++
.../tribble/TribbleIndexedFeatureReader.java | 10 +-
src/main/java/htsjdk/tribble/bed/BEDCodec.java | 5 +
.../java/htsjdk/tribble/index/IndexFactory.java | 31 ++++-
.../variant/variantcontext/FastGenotype.java | 5 +-
.../htsjdk/variant/variantcontext/Genotype.java | 6 +-
.../variant/variantcontext/GenotypeBuilder.java | 35 +++++-
.../java/htsjdk/variant/vcf/AbstractVCFCodec.java | 6 +
.../htsjdk/variant/vcf/VCFStandardHeaderLines.java | 129 +++++++++------------
.../java/htsjdk/samtools/BAMRemoteFileTest.java | 3 +-
.../java/htsjdk/samtools/CRAMCRAIIndexerTest.java | 5 +
.../java/htsjdk/samtools/SAMRecordUtilTest.java | 29 +++++
src/test/java/htsjdk/samtools/SAMUtilsTest.java | 77 +++++++++++-
.../java/htsjdk/samtools/SamReaderFactoryTest.java | 13 +--
.../htsjdk/samtools/cram/structure/SliceTests.java | 34 ++++++
.../filter/IntervalKeepPairFilterTest.java | 123 ++++++++++++++++++++
.../seekablestream/SeekableStreamFactoryTest.java | 9 +-
.../java/htsjdk/samtools/sra/AbstractSRATest.java | 34 +++++-
.../java/htsjdk/samtools/sra/SRAAccessionTest.java | 3 +-
.../java/htsjdk/samtools/sra/SRAIndexTest.java | 2 +-
.../htsjdk/samtools/sra/SRALazyRecordTest.java | 2 +-
src/test/java/htsjdk/samtools/sra/SRATest.java | 78 +++++++------
.../java/htsjdk/samtools/util/AsyncWriterTest.java | 77 ++++++++++++
.../htsjdk/samtools/util/SamLocusIteratorTest.java | 24 +++-
.../htsjdk/tribble/AbstractFeatureReaderTest.java | 3 +-
.../java/htsjdk/tribble/BinaryFeaturesTest.java | 5 +
.../tribble/TribbleIndexFeatureReaderTest.java | 4 +-
src/test/java/htsjdk/tribble/bed/BEDCodecTest.java | 5 +
.../htsjdk/tribble/readers/TabixReaderTest.java | 3 +-
.../variantcontext/GenotypeBuilderTest.java | 75 ++++++++++++
.../variant/variantcontext/GenotypeUnitTest.java | 4 +
.../htsjdk/variant/vcf/AbstractVCFCodecTest.java | 7 ++
.../vcf/VCFStandardHeaderLinesUnitTest.java | 56 ++++++++-
.../htsjdk/samtools/cram/auxf.alteredForMD5test.fa | 2 +
.../samtools/cram/auxf.alteredForMD5test.fa.fai | 1 +
src/test/resources/htsjdk/samtools/cram/auxf.fasta | 2 -
src/test/resources/htsjdk/samtools/cram/test.fasta | 2 -
.../resources/htsjdk/samtools/cram/test2.fasta | 2 -
.../resources/htsjdk/tribble/test with spaces.vcf | 24 ++++
src/test/resources/htsjdk/tribble/test.vcf.bgz | Bin 0 -> 849 bytes
src/test/resources/htsjdk/variant/ex2.bgzf.bcf | Bin 1062 -> 0 bytes
.../resources/htsjdk/variant/ex2.uncompressed.bcf | Bin 1892 -> 0 bytes
64 files changed, 1197 insertions(+), 221 deletions(-)
diff --git a/README.md b/README.md
index 284fa9a..0e468d3 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,8 @@ Example gradle usage from the htsjdk root directory:
```
./gradlew test
+ ./gradlew test -Dtest.single=TestClassName
+
./gradlew test --tests htsjdk.variant.variantcontext.AlleleUnitTest
./gradlew test --tests "*AlleleUnitTest"
diff --git a/build.gradle b/build.gradle
index 174b702..9e8f351 100644
--- a/build.gradle
+++ b/build.gradle
@@ -129,6 +129,7 @@ task testSRA(type: Test) {
description "Run the SRA tests"
useTestNG {
+ configFailurePolicy 'continue'
includeGroups "sra"
}
}
diff --git a/src/main/java/htsjdk/samtools/CRAMIterator.java b/src/main/java/htsjdk/samtools/CRAMIterator.java
index 4238677..f8179e6 100644
--- a/src/main/java/htsjdk/samtools/CRAMIterator.java
+++ b/src/main/java/htsjdk/samtools/CRAMIterator.java
@@ -177,10 +177,14 @@ public class CRAMIterator implements SAMRecordIterator {
final Slice slice = container.slices[i];
if (slice.sequenceId < 0)
continue;
- if (validationStringency != ValidationStringency.SILENT && !slice.validateRefMD5(refs)) {
- log.error(String
- .format("Reference sequence MD5 mismatch for slice: seq id %d, start %d, span %d, expected MD5 %s", slice.sequenceId,
- slice.alignmentStart, slice.alignmentSpan, String.format("%032x", new BigInteger(1, slice.refMD5))));
+ if (!slice.validateRefMD5(refs)) {
+ final String msg = String.format(
+ "Reference sequence MD5 mismatch for slice: sequence id %d, start %d, span %d, expected MD5 %s",
+ slice.sequenceId,
+ slice.alignmentStart,
+ slice.alignmentSpan,
+ String.format("%032x", new BigInteger(1, slice.refMD5)));
+ throw new CRAMException(msg);
}
}
diff --git a/src/main/java/htsjdk/samtools/DuplicateScoringStrategy.java b/src/main/java/htsjdk/samtools/DuplicateScoringStrategy.java
index 9d0bed5..1abd514 100644
--- a/src/main/java/htsjdk/samtools/DuplicateScoringStrategy.java
+++ b/src/main/java/htsjdk/samtools/DuplicateScoringStrategy.java
@@ -24,6 +24,8 @@
package htsjdk.samtools;
+import htsjdk.samtools.util.Murmur3;
+
/**
* This class helps us compute and compare duplicate scores, which are used for selecting the non-duplicate
* during duplicate marking (see MarkDuplicates).
@@ -33,9 +35,13 @@ public class DuplicateScoringStrategy {
public enum ScoringStrategy {
SUM_OF_BASE_QUALITIES,
- TOTAL_MAPPED_REFERENCE_LENGTH
+ TOTAL_MAPPED_REFERENCE_LENGTH,
+ RANDOM,
}
+ /** Hash used for the RANDOM scoring strategy. */
+ private static final Murmur3 hasher = new Murmur3(1);
+
/** An enum to use for storing temporary attributes on SAMRecords. */
private static enum Attr { DuplicateScore }
@@ -80,6 +86,8 @@ public class DuplicateScoringStrategy {
score += SAMUtils.getMateCigar(record).getReferenceLength();
}
break;
+ case RANDOM:
+ score += (short) (hasher.hashUnencodedChars(record.getReadName()) >> 16);
}
storedScore = score;
diff --git a/src/main/java/htsjdk/samtools/SAMRecordUtil.java b/src/main/java/htsjdk/samtools/SAMRecordUtil.java
index 8b9eec5..d290074 100644
--- a/src/main/java/htsjdk/samtools/SAMRecordUtil.java
+++ b/src/main/java/htsjdk/samtools/SAMRecordUtil.java
@@ -26,56 +26,104 @@ package htsjdk.samtools;
import htsjdk.samtools.util.SequenceUtil;
import htsjdk.samtools.util.StringUtil;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
/**
* @author alecw at broadinstitute.org
*/
public class SAMRecordUtil {
-
- /** List of String tags that must be reversed if present when a SAMRecord is reverseComplemented */
- private static final short[] STRING_TAGS_TO_REVERSE = {
- SAMTagUtil.getSingleton().U2,
- SAMTagUtil.getSingleton().OQ
- };
+ public static List<String> TAGS_TO_REVERSE_COMPLEMENT = Arrays.asList(SAMTag.E2.name(), SAMTag.SQ.name());
+ public static List<String> TAGS_TO_REVERSE = Arrays.asList(SAMTag.OQ.name(), SAMTag.U2.name());
/**
- * Reverse-complement all known sequence and base quality attributes of the SAMRecord.
+ * Reverse-complement bases and reverse quality scores along with known optional attributes that
+ * need the same treatment. See {@link #TAGS_TO_REVERSE_COMPLEMENT} {@link #TAGS_TO_REVERSE}
+ * for the default set of tags that are handled.
*/
public static void reverseComplement(final SAMRecord rec) {
+ reverseComplement(rec, TAGS_TO_REVERSE_COMPLEMENT, TAGS_TO_REVERSE);
+ }
+
+ /**
+ * Reverse complement bases and reverse quality scores. In addition reverse complement any
+ * non-null attributes specified by tagsToRevcomp and reverse and non-null attributes
+ * specified by tagsToReverse.
+ */
+ public static void reverseComplement(final SAMRecord rec, final Collection<String> tagsToRevcomp, final Collection<String> tagsToReverse) {
final byte[] readBases = rec.getReadBases();
SequenceUtil.reverseComplement(readBases);
rec.setReadBases(readBases);
final byte qualities[] = rec.getBaseQualities();
reverseArray(qualities);
rec.setBaseQualities(qualities);
- final byte[] sqTagValue = (byte[])rec.getAttribute(SAMTagUtil.getSingleton().SQ);
- if (sqTagValue != null) {
- SQTagUtil.reverseComplementSqArray(sqTagValue);
- rec.setAttribute(SAMTagUtil.getSingleton().SQ, sqTagValue);
- }
- final String e2TagValue = (String)rec.getAttribute(SAMTagUtil.getSingleton().E2);
- if (e2TagValue != null) {
- final byte[] secondaryBases = StringUtil.stringToBytes(e2TagValue);
- SequenceUtil.reverseComplement(secondaryBases);
- rec.setAttribute(SAMTagUtil.getSingleton().E2, StringUtil.bytesToString(secondaryBases));
+
+ // Deal with tags that need to be reverse complemented
+ if (tagsToRevcomp != null) {
+ for (final String tag: tagsToRevcomp) {
+ Object value = rec.getAttribute(tag);
+ if (value != null) {
+ if (value instanceof byte[]) SequenceUtil.reverseComplement((byte[]) value);
+ else if (value instanceof String) value = SequenceUtil.reverseComplement((String) value);
+ else throw new UnsupportedOperationException("Don't know how to reverse complement: " + value);
+ rec.setAttribute(tag, value);
+ }
+ }
}
- for (final short stringTag : STRING_TAGS_TO_REVERSE) {
- final String value = (String)rec.getAttribute(stringTag);
- if (value != null) {
- rec.setAttribute(stringTag, StringUtil.reverseString(value));
+
+ // Deal with tags that needed to just be reversed
+ if (tagsToReverse != null) {
+ for (final String tag : tagsToReverse) {
+ Object value = rec.getAttribute(tag);
+ if (value != null) {
+ if (value instanceof String) {
+ value = StringUtil.reverseString((String) value);
+ }
+ else if (value.getClass().isArray()) {
+ if (value instanceof byte[]) reverseArray((byte[]) value);
+ else if (value instanceof short[]) reverseArray((short[]) value);
+ else if (value instanceof int[]) reverseArray((int[]) value);
+ else if (value instanceof float[]) reverseArray((float[]) value);
+ else throw new UnsupportedOperationException("Reversing array attribute of type " + value.getClass().getComponentType() + " not supported.");
+ }
+ else throw new UnsupportedOperationException("Don't know how to reverse: " + value);
+
+ rec.setAttribute(tag, value);
+ }
}
}
}
- /**
- * Reverse the given array in place.
- */
- public static void reverseArray(final byte[] array) {
- final int lastIndex = array.length - 1;
- int i, j;
- for (i=0, j=lastIndex; i<j; ++i, --j) {
+ private static void reverseArray(final byte[] array) {
+ for (int i=0, j=array.length-1; i<j; ++i, --j) {
final byte tmp = array[i];
array[i] = array[j];
array[j] = tmp;
}
}
+
+ private static void reverseArray(final short[] array) {
+ for (int i=0, j=array.length-1; i<j; ++i, --j) {
+ final short tmp = array[i];
+ array[i] = array[j];
+ array[j] = tmp;
+ }
+ }
+
+ private static void reverseArray(final int[] array) {
+ for (int i=0, j=array.length-1; i<j; ++i, --j) {
+ final int tmp = array[i];
+ array[i] = array[j];
+ array[j] = tmp;
+ }
+ }
+
+ private static void reverseArray(final float[] array) {
+ for (int i=0, j=array.length-1; i<j; ++i, --j) {
+ final float tmp = array[i];
+ array[i] = array[j];
+ array[j] = tmp;
+ }
+ }
}
diff --git a/src/main/java/htsjdk/samtools/SAMUtils.java b/src/main/java/htsjdk/samtools/SAMUtils.java
index b31b771..c0432ac 100644
--- a/src/main/java/htsjdk/samtools/SAMUtils.java
+++ b/src/main/java/htsjdk/samtools/SAMUtils.java
@@ -41,12 +41,18 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
+import java.util.regex.Pattern;
/**
* Utilty methods.
*/
public final class SAMUtils {
+ /** regex for semicolon, used in {@link SAMUtils#getOtherCanonicalAlignments(SAMRecord)} */
+ private static final Pattern SEMICOLON_PAT = Pattern.compile("[;]");
+ /** regex for comma, used in {@link SAMUtils#getOtherCanonicalAlignments(SAMRecord)} */
+ private static final Pattern COMMA_PAT = Pattern.compile("[,]");
+
// Representation of bases, one for when in low-order nybble, one for when in high-order nybble.
private static final byte COMPRESSED_EQUAL_LOW = 0;
private static final byte COMPRESSED_A_LOW = 1;
@@ -1096,4 +1102,122 @@ public final class SAMUtils {
public static boolean isValidUnsignedIntegerAttribute(long value) {
return value >= 0 && value <= BinaryCodec.MAX_UINT;
}
+
+ /**
+ * Extract a List of 'other canonical alignments' from a SAM record. Those alignments are stored as a string in the 'SA' tag as defined
+ * in the SAM specification.
+ * The name, sequence and qualities, mate data are copied from the original record.
+ * @param record must be non null and must have a non-null associated header.
+ * @return a list of 'other canonical alignments' SAMRecords. The list is empty if the 'SA' attribute is missing.
+ */
+ public static List<SAMRecord> getOtherCanonicalAlignments(final SAMRecord record) {
+ if( record == null ) throw new IllegalArgumentException("record is null");
+ if( record.getHeader() == null ) throw new IllegalArgumentException("record.getHeader() is null");
+ /* extract value of SA tag */
+ final Object saValue = record.getAttribute( SAMTagUtil.getSingleton().SA );
+ if( saValue == null ) return Collections.emptyList();
+ if( ! (saValue instanceof String) ) throw new SAMException(
+ "Expected a String for attribute 'SA' but got " + saValue.getClass() );
+
+ final SAMRecordFactory samReaderFactory = new DefaultSAMRecordFactory();
+
+ /* the spec says: "Other canonical alignments in a chimeric alignment, formatted as a
+ * semicolon-delimited list: (rname,pos,strand,CIGAR,mapQ,NM;)+.
+ * Each element in the list represents a part of the chimeric alignment.
+ * Conventionally, at a supplementary line, the 1rst element points to the primary line.
+ */
+
+ /* break string using semicolon */
+ final String semiColonStrs[] = SEMICOLON_PAT.split((String)saValue);
+
+ /* the result list */
+ final List<SAMRecord> alignments = new ArrayList<>( semiColonStrs.length );
+
+ /* base SAM flag */
+ int record_flag = record.getFlags() ;
+ record_flag &= ~SAMFlag.PROPER_PAIR.flag;
+ record_flag &= ~SAMFlag.SUPPLEMENTARY_ALIGNMENT.flag;
+ record_flag &= ~SAMFlag.READ_REVERSE_STRAND.flag;
+
+
+ for(int i=0; i< semiColonStrs.length;++i ) {
+ final String semiColonStr = semiColonStrs[i];
+ /* ignore empty string */
+ if( semiColonStr.isEmpty() ) continue;
+
+ /* break string using comma */
+ final String commaStrs[] = COMMA_PAT.split(semiColonStr);
+ if( commaStrs.length != 6 ) throw new SAMException("Bad 'SA' attribute in " + semiColonStr);
+
+ /* create the new record */
+ final SAMRecord otherRec = samReaderFactory.createSAMRecord( record.getHeader() );
+
+ /* copy fields from the original record */
+ otherRec.setReadName( record.getReadName() );
+ otherRec.setReadBases( record.getReadBases() );
+ otherRec.setBaseQualities( record.getBaseQualities() );
+ if( record.getReadPairedFlag() && !record.getMateUnmappedFlag()) {
+ otherRec.setMateReferenceIndex( record.getMateReferenceIndex() );
+ otherRec.setMateAlignmentStart( record.getMateAlignmentStart() );
+ }
+
+
+ /* get reference sequence */
+ final int tid = record.getHeader().getSequenceIndex( commaStrs[0] );
+ if( tid == -1 ) throw new SAMException("Unknown contig in " + semiColonStr);
+ otherRec.setReferenceIndex( tid );
+
+ /* fill POS */
+ final int alignStart;
+ try {
+ alignStart = Integer.parseInt(commaStrs[1]);
+ } catch( final NumberFormatException err ) {
+ throw new SAMException("bad POS in "+semiColonStr, err);
+ }
+
+ otherRec.setAlignmentStart( alignStart );
+
+ /* set TLEN */
+ if( record.getReadPairedFlag() &&
+ !record.getMateUnmappedFlag() &&
+ record.getMateReferenceIndex() == tid ) {
+ otherRec.setInferredInsertSize( record.getMateAlignmentStart() - alignStart );
+ }
+
+ /* set FLAG */
+ int other_flag = record_flag;
+ other_flag |= (commaStrs[2].equals("+") ? 0 : SAMFlag.READ_REVERSE_STRAND.flag) ;
+ /* spec: Conventionally, at a supplementary line, the 1st element points to the primary line */
+ if( !( record.getSupplementaryAlignmentFlag() && i==0 ) ) {
+ other_flag |= SAMFlag.SUPPLEMENTARY_ALIGNMENT.flag;
+ }
+ otherRec.setFlags(other_flag);
+
+ /* set CIGAR */
+ otherRec.setCigar( TextCigarCodec.decode( commaStrs[3] ) );
+
+ /* set MAPQ */
+ try {
+ otherRec.setMappingQuality( Integer.parseInt(commaStrs[4]) );
+ } catch (final NumberFormatException err) {
+ throw new SAMException("bad MAPQ in "+semiColonStr, err);
+ }
+
+ /* fill NM */
+ try {
+ otherRec.setAttribute( SAMTagUtil.getSingleton().NM , Integer.parseInt(commaStrs[5]) );
+ } catch (final NumberFormatException err) {
+ throw new SAMException("bad NM in "+semiColonStr, err);
+ }
+
+ /* if strand is not the same: reverse-complement */
+ if( otherRec.getReadNegativeStrandFlag() != record.getReadNegativeStrandFlag() ) {
+ SAMRecordUtil.reverseComplement(otherRec);
+ }
+
+ /* add the alignment */
+ alignments.add( otherRec );
+ }
+ return alignments;
+ }
}
diff --git a/src/main/java/htsjdk/samtools/SRAFileReader.java b/src/main/java/htsjdk/samtools/SRAFileReader.java
index 6925ffc..e76e10b 100644
--- a/src/main/java/htsjdk/samtools/SRAFileReader.java
+++ b/src/main/java/htsjdk/samtools/SRAFileReader.java
@@ -61,7 +61,8 @@ public class SRAFileReader extends SamReader.ReaderImplementation implements Sam
this.acc = acc;
if (!acc.isValid()) {
- throw new IllegalArgumentException("Invalid SRA accession was passed to SRA reader: " + acc);
+ throw new IllegalArgumentException("SRAFileReader: cannot resolve SRA accession '" + acc + "'\n" +
+ "Possible causes are an invalid SRA accession or a connection problem.");
}
try {
diff --git a/src/main/java/htsjdk/samtools/SamPairUtil.java b/src/main/java/htsjdk/samtools/SamPairUtil.java
index 5daf6e6..01a59cb 100644
--- a/src/main/java/htsjdk/samtools/SamPairUtil.java
+++ b/src/main/java/htsjdk/samtools/SamPairUtil.java
@@ -244,7 +244,7 @@ public class SamPairUtil {
mapped.setMateAlignmentStart(unmapped.getAlignmentStart());
mapped.setMateNegativeStrandFlag(unmapped.getReadNegativeStrandFlag());
mapped.setMateUnmappedFlag(true);
- // For the mapped read, set it's mateCigar to null, since the other read must be unmapped
+ mapped.setAttribute(SAMTag.MQ.name(), null);
mapped.setAttribute(SAMTag.MC.name(), null);
mapped.setInferredInsertSize(0);
@@ -252,7 +252,8 @@ public class SamPairUtil {
unmapped.setMateAlignmentStart(mapped.getAlignmentStart());
unmapped.setMateNegativeStrandFlag(mapped.getReadNegativeStrandFlag());
unmapped.setMateUnmappedFlag(false);
- // For the unmapped read, set it's mateCigar to the mate's Cigar, since the mate must be mapped
+ unmapped.setAttribute(SAMTag.MQ.name(), mapped.getMappingQuality());
+ // For the unmapped read, set mateCigar to the mate's Cigar, since the mate must be mapped
if (setMateCigar) unmapped.setAttribute(SAMTag.MC.name(), mapped.getCigarString());
else unmapped.setAttribute(SAMTag.MC.name(), null);
unmapped.setInferredInsertSize(0);
diff --git a/src/main/java/htsjdk/samtools/cram/build/Utils.java b/src/main/java/htsjdk/samtools/cram/build/Utils.java
index 60efc3b..7fdeeba 100644
--- a/src/main/java/htsjdk/samtools/cram/build/Utils.java
+++ b/src/main/java/htsjdk/samtools/cram/build/Utils.java
@@ -17,7 +17,9 @@
*/
package htsjdk.samtools.cram.build;
-class Utils {
+final public class Utils {
+
+ private Utils() {};
/**
* CRAM operates with upper case bases, so both read and ref bases should be
diff --git a/src/main/java/htsjdk/samtools/cram/encoding/reader/DataReaderFactory.java b/src/main/java/htsjdk/samtools/cram/encoding/reader/DataReaderFactory.java
index 4e5c4ec..253ab15 100644
--- a/src/main/java/htsjdk/samtools/cram/encoding/reader/DataReaderFactory.java
+++ b/src/main/java/htsjdk/samtools/cram/encoding/reader/DataReaderFactory.java
@@ -56,9 +56,7 @@ public class DataReaderFactory {
final DataSeries dataSeries = field.getAnnotation(DataSeries.class);
final EncodingKey key = dataSeries.key();
final DataSeriesType type = dataSeries.type();
- if (header.encodingMap.get(key) == null) {
- log.debug("Encoding not found for key: " + key);
- } else {
+ if (header.encodingMap.get(key) != null) {
try {
field.set(reader,
createReader(type, header.encodingMap.get(key), bitInputStream, inputMap));
diff --git a/src/main/java/htsjdk/samtools/cram/ref/CRAMReferenceSource.java b/src/main/java/htsjdk/samtools/cram/ref/CRAMReferenceSource.java
index 35a3e79..c77aaae 100644
--- a/src/main/java/htsjdk/samtools/cram/ref/CRAMReferenceSource.java
+++ b/src/main/java/htsjdk/samtools/cram/ref/CRAMReferenceSource.java
@@ -15,8 +15,8 @@ public interface CRAMReferenceSource {
* against the reference by using common name variations,
* such as adding or removing a leading "chr" prefix
* from the requested name. if false, use exact match
- * @return the bases representing the requested sequence. or null if the sequence
- * cannot be found
+ * @return the upper cased, normalized (see {@link htsjdk.samtools.cram.build.Utils#normalizeBase})
+ * bases representing the requested sequence, or null if the sequence cannot be found
*/
byte[] getReferenceBases(final SAMSequenceRecord sequenceRecord, final boolean tryNameVariants);
}
diff --git a/src/main/java/htsjdk/samtools/cram/ref/ReferenceSource.java b/src/main/java/htsjdk/samtools/cram/ref/ReferenceSource.java
index da3d43f..e73fb41 100644
--- a/src/main/java/htsjdk/samtools/cram/ref/ReferenceSource.java
+++ b/src/main/java/htsjdk/samtools/cram/ref/ReferenceSource.java
@@ -20,6 +20,7 @@ package htsjdk.samtools.cram.ref;
import htsjdk.samtools.Defaults;
import htsjdk.samtools.SAMException;
import htsjdk.samtools.SAMSequenceRecord;
+import htsjdk.samtools.cram.build.Utils;
import htsjdk.samtools.cram.io.InputStreamUtils;
import htsjdk.samtools.reference.ReferenceSequence;
import htsjdk.samtools.reference.ReferenceSequenceFile;
@@ -123,13 +124,23 @@ public class ReferenceSource implements CRAMReferenceSource {
return null;
}
+ // Upper case and normalize (-> ACGTN) in-place, and add to the cache
+ private byte[] addToCache(final String sequenceName, final byte[] bases) {
+ for (int i = 0; i < bases.length; i++) {
+ bases[i] = Utils.normalizeBase(bases[i]);
+ }
+ cacheW.put(sequenceName, new WeakReference<byte[]>(bases));
+ return bases;
+ }
+
public synchronized byte[] getReferenceBases(final SAMSequenceRecord record,
final boolean tryNameVariants) {
{ // check cache by sequence name:
final String name = record.getSequenceName();
final byte[] bases = findInCache(name);
- if (bases != null)
+ if (bases != null) {
return bases;
+ }
}
final String md5 = record.getAttribute(SAMSequenceRecord.MD5_TAG);
@@ -152,10 +163,7 @@ public class ReferenceSource implements CRAMReferenceSource {
{ // try to fetch sequence by name:
bases = findBasesByName(record.getSequenceName(), tryNameVariants);
if (bases != null) {
- SequenceUtil.upperCase(bases);
- cacheW.put(record.getSequenceName(), new WeakReference<byte[]>(
- bases));
- return bases;
+ return addToCache(record.getSequenceName(), bases);
}
}
@@ -169,9 +177,7 @@ public class ReferenceSource implements CRAMReferenceSource {
}
}
if (bases != null) {
- SequenceUtil.upperCase(bases);
- cacheW.put(md5, new WeakReference<byte[]>(bases));
- return bases;
+ return addToCache(md5, bases);
}
}
}
diff --git a/src/main/java/htsjdk/samtools/cram/structure/CompressionHeader.java b/src/main/java/htsjdk/samtools/cram/structure/CompressionHeader.java
index 323b3f6..2278bf1 100644
--- a/src/main/java/htsjdk/samtools/cram/structure/CompressionHeader.java
+++ b/src/main/java/htsjdk/samtools/cram/structure/CompressionHeader.java
@@ -17,6 +17,7 @@
*/
package htsjdk.samtools.cram.structure;
+import htsjdk.samtools.cram.CRAMException;
import htsjdk.samtools.cram.encoding.ExternalCompressor;
import htsjdk.samtools.cram.encoding.NullEncoding;
import htsjdk.samtools.cram.io.ITF8;
@@ -170,8 +171,7 @@ public class CompressionHeader {
final String key = new String(new byte[]{buffer.get(), buffer.get()});
final EncodingKey encodingKey = EncodingKey.byFirstTwoChars(key);
if (encodingKey == null) {
- log.debug("Unknown encoding key: " + key);
- continue;
+ throw new CRAMException("Unknown encoding key: " + key);
}
final EncodingID id = EncodingID.values()[buffer.get()];
diff --git a/src/main/java/htsjdk/samtools/filter/IntervalFilter.java b/src/main/java/htsjdk/samtools/filter/IntervalFilter.java
index ee3de6d..ff3620a 100644
--- a/src/main/java/htsjdk/samtools/filter/IntervalFilter.java
+++ b/src/main/java/htsjdk/samtools/filter/IntervalFilter.java
@@ -94,6 +94,9 @@ public class IntervalFilter implements SamRecordFilter {
* @return true if the SAMRecords matches the filter, otherwise false
*/
public boolean filterOut(final SAMRecord first, final SAMRecord second) {
- throw new UnsupportedOperationException("Paired IntervalFilter filter not implemented!");
+ // This can never be implemented because if the bam is coordinate sorted,
+ // which it has to be for this filter, it will never get both the first and second reads together
+ // and the filterOut method goes in order of the intervals in coordinate order so it will miss reads.
+ throw new UnsupportedOperationException("Paired IntervalFilter filter cannot be implemented, use IntervalKeepPairFilter.");
}
}
diff --git a/src/main/java/htsjdk/samtools/filter/IntervalKeepPairFilter.java b/src/main/java/htsjdk/samtools/filter/IntervalKeepPairFilter.java
new file mode 100644
index 0000000..5a7961b
--- /dev/null
+++ b/src/main/java/htsjdk/samtools/filter/IntervalKeepPairFilter.java
@@ -0,0 +1,108 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2016 The Broad Institute
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package htsjdk.samtools.filter;
+
+import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.SAMUtils;
+import htsjdk.samtools.util.Interval;
+import htsjdk.samtools.util.OverlapDetector;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Filter out SAMRecords where neither record of a pair overlaps a given set of
+ * intervals. If one record of a pair overlaps the interval list, than both are
+ * kept. It is required that the SAMRecords are passed in coordinate order, have
+ * non-null SAMFileHeaders, and that Mate Cigar (MC) is present.
+ *
+ * @author kbergin at broadinstitute.org
+ */
+public class IntervalKeepPairFilter implements SamRecordFilter {
+ private final OverlapDetector<Interval> intervalOverlapDetector;
+
+ /**
+ * Prepare to filter out SAMRecords that do not overlap the given list of
+ * intervals
+ * @param intervals
+ */
+ public IntervalKeepPairFilter(final List<Interval> intervals) {
+ this.intervalOverlapDetector = new OverlapDetector<>(0, 0);
+ this.intervalOverlapDetector.addAll(intervals, intervals);
+ }
+
+ /**
+ * Determines whether a SAMRecord matches this filter. Takes record, finds
+ * the location of its mate using the MC tag. Checks if either record
+ * overlaps the current interval using overlap detector. If yes, return
+ * false -> don't filter it out.
+ *
+ * If a read is secondary or supplementary, filter read out. Use
+ * {@link IntervalFilter} if you want to keep these reads, but NOTE: the
+ * resulting bam may not be valid.
+ *
+ * @param record the SAMRecord to evaluate
+ * @return true if the SAMRecord matches the filter, otherwise false
+ */
+ public boolean filterOut(final SAMRecord record) {
+ if (record.isSecondaryOrSupplementary()) {
+ return true;
+ }
+
+ if (!record.getReadUnmappedFlag()
+ && hasOverlaps(record.getReferenceName(), record.getStart(), record.getEnd())) {
+ return false;
+ }
+
+ return record.getMateUnmappedFlag() || !hasOverlaps(record.getMateReferenceName(),
+ record.getMateAlignmentStart(), SAMUtils.getMateAlignmentEnd(record));
+ }
+
+ /**
+ * Returns true if the record overlaps any intervals in list, false otherwise.
+ *
+ * @param refSequence Reference contig name where record maps
+ * @param start Record alignment start
+ * @param end Record alignment end
+ * @return true if SAMRecord overlaps any intervals in list
+ */
+ private boolean hasOverlaps(final String refSequence, final int start, final int end) {
+ final Interval readInterval = new Interval(refSequence, start, end);
+ final Collection<Interval> overlapsRead = intervalOverlapDetector.getOverlaps(readInterval);
+
+ return !overlapsRead.isEmpty();
+ }
+
+ /**
+ * Determines whether a pair of SAMRecord matches this filter
+ *
+ * @param first the first SAMRecord to evaluate
+ * @param second the second SAMRecord to evaluate
+ *
+ * @return true if both SAMRecords do not overlap the interval list
+ */
+ public boolean filterOut(final SAMRecord first, final SAMRecord second) {
+ return filterOut(first) && filterOut(second);
+ }
+}
diff --git a/src/main/java/htsjdk/samtools/sra/SRAAccession.java b/src/main/java/htsjdk/samtools/sra/SRAAccession.java
index aadfdc3..17180d7 100644
--- a/src/main/java/htsjdk/samtools/sra/SRAAccession.java
+++ b/src/main/java/htsjdk/samtools/sra/SRAAccession.java
@@ -54,6 +54,8 @@ public class SRAAccession implements Serializable {
private final static String defaultAppVersionString = "[unknown software]";
private final static String htsJdkVersionString = "HTSJDK-NGS";
+ static final String REMOTE_ACCESSION_PATTERN = "^[SED]RR[0-9]{6,9}$";
+
private String acc;
static {
@@ -127,7 +129,7 @@ public class SRAAccession implements Serializable {
// anything else local other than a file is not an SRA archive
looksLikeSRA = false;
} else {
- looksLikeSRA = acc.toUpperCase().matches ( "^[SED]RR[0-9]{6,9}$" );
+ looksLikeSRA = acc.toUpperCase().matches ( REMOTE_ACCESSION_PATTERN );
}
if (!looksLikeSRA) return false;
diff --git a/src/main/java/htsjdk/samtools/util/AbstractAsyncWriter.java b/src/main/java/htsjdk/samtools/util/AbstractAsyncWriter.java
index 86c18b9..ef1803b 100644
--- a/src/main/java/htsjdk/samtools/util/AbstractAsyncWriter.java
+++ b/src/main/java/htsjdk/samtools/util/AbstractAsyncWriter.java
@@ -14,6 +14,10 @@ import java.util.concurrent.atomic.AtomicReference;
* NOTE: Objects of subclasses of this class are not intended to be shared between threads.
* In particular there must be only one thread that calls {@link #write} and {@link #close}.
*
+ * NOTE: Any exception thrown by the underlying Writer will be propagated back to the caller
+ * during the next available call to {@link #write} or {@link #close}. After the exception
+ * has been thrown to the caller, it is not safe to attempt further operations on the instance.
+ *
* @author Tim Fennell
*/
public abstract class AbstractAsyncWriter<T> implements Closeable {
@@ -92,8 +96,9 @@ public abstract class AbstractAsyncWriter<T> implements Closeable {
* or RuntimeException as appropriate.
*/
private final void checkAndRethrow() {
- final Throwable t = this.ex.get();
+ final Throwable t = this.ex.getAndSet(null);
if (t != null) {
+ this.isClosed.set(true); // Ensure no further attempts to write
if (t instanceof Error) throw (Error) t;
if (t instanceof RuntimeException) throw (RuntimeException) t;
else throw new RuntimeException(t);
diff --git a/src/main/java/htsjdk/samtools/util/BlockGunzipper.java b/src/main/java/htsjdk/samtools/util/BlockGunzipper.java
index 759f5ee..18e9285 100644
--- a/src/main/java/htsjdk/samtools/util/BlockGunzipper.java
+++ b/src/main/java/htsjdk/samtools/util/BlockGunzipper.java
@@ -57,10 +57,26 @@ public class BlockGunzipper {
* @param uncompressedBlock must be big enough to hold decompressed output.
* @param compressedBlock compressed data starting at offset 0
* @param compressedLength size of compressed data, possibly less than the size of the buffer.
+ * @return the uncompressed data size.
*/
- void unzipBlock(byte[] uncompressedBlock, byte[] compressedBlock, int compressedLength) {
+ public int unzipBlock(byte[] uncompressedBlock, byte[] compressedBlock, int compressedLength) {
+ return unzipBlock(uncompressedBlock, 0, compressedBlock, 0, compressedLength);
+ }
+
+ /**
+ * Decompress GZIP-compressed data
+ * @param uncompressedBlock must be big enough to hold decompressed output.
+ * @param uncompressedBlockOffset the offset into uncompressedBlock.
+ * @param compressedBlock compressed data starting at offset 0.
+ * @param compressedBlock the offset into the compressed data.
+ * @param compressedLength size of compressed data, possibly less than the size of the buffer.
+ * @return the uncompressed data size.
+ */
+ public int unzipBlock(byte[] uncompressedBlock, int uncompressedBlockOffset,
+ byte[] compressedBlock, int compressedBlockOffset, int compressedLength) {
+ int uncompressedSize;
try {
- ByteBuffer byteBuffer = ByteBuffer.wrap(compressedBlock, 0, compressedLength);
+ ByteBuffer byteBuffer = ByteBuffer.wrap(compressedBlock, compressedBlockOffset, compressedLength);
byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
// Validate GZIP header
@@ -88,12 +104,12 @@ public class BlockGunzipper {
final int deflatedSize = compressedLength - BlockCompressedStreamConstants.BLOCK_HEADER_LENGTH - BlockCompressedStreamConstants.BLOCK_FOOTER_LENGTH;
byteBuffer.position(byteBuffer.position() + deflatedSize);
int expectedCrc = byteBuffer.getInt();
- int uncompressedSize = byteBuffer.getInt();
+ uncompressedSize = byteBuffer.getInt();
inflater.reset();
// Decompress
- inflater.setInput(compressedBlock, BlockCompressedStreamConstants.BLOCK_HEADER_LENGTH, deflatedSize);
- final int inflatedBytes = inflater.inflate(uncompressedBlock, 0, uncompressedSize);
+ inflater.setInput(compressedBlock, compressedBlockOffset + BlockCompressedStreamConstants.BLOCK_HEADER_LENGTH, deflatedSize);
+ final int inflatedBytes = inflater.inflate(uncompressedBlock, uncompressedBlockOffset, uncompressedSize);
if (inflatedBytes != uncompressedSize) {
throw new SAMFormatException("Did not inflate expected amount");
}
@@ -101,7 +117,7 @@ public class BlockGunzipper {
// Validate CRC if so desired
if (this.checkCrcs) {
crc32.reset();
- crc32.update(uncompressedBlock, 0, uncompressedSize);
+ crc32.update(uncompressedBlock, uncompressedBlockOffset, uncompressedSize);
final long crc = crc32.getValue();
if ((int)crc != expectedCrc) {
throw new SAMFormatException("CRC mismatch");
@@ -111,5 +127,6 @@ public class BlockGunzipper {
{
throw new RuntimeIOException(e);
}
+ return uncompressedSize;
}
}
diff --git a/src/main/java/htsjdk/samtools/util/Lazy.java b/src/main/java/htsjdk/samtools/util/Lazy.java
index b42ec7c..13726b8 100644
--- a/src/main/java/htsjdk/samtools/util/Lazy.java
+++ b/src/main/java/htsjdk/samtools/util/Lazy.java
@@ -28,6 +28,7 @@ public class Lazy<T> {
}
/** Describes how to build the instance of the lazy object. */
+ @FunctionalInterface
public interface LazyInitializer<T> {
/** Returns the desired object instance. */
T make();
diff --git a/src/main/java/htsjdk/samtools/util/SamLocusIterator.java b/src/main/java/htsjdk/samtools/util/SamLocusIterator.java
index 466d0d6..33bcfd3 100644
--- a/src/main/java/htsjdk/samtools/util/SamLocusIterator.java
+++ b/src/main/java/htsjdk/samtools/util/SamLocusIterator.java
@@ -116,6 +116,8 @@ public class SamLocusIterator implements Iterable<SamLocusIterator.LocusInfo>, C
public List<RecordAndOffset> getInsertedInRecord() {
return (insertedInRecord == null) ? Collections.emptyList() : Collections.unmodifiableList(insertedInRecord);
}
+ /** @return the number of records overlapping the position, with deletions included if they are being tracked. */
+ public int size() { return this.recordAndOffsets.size() + ((deletedInRecord == null) ? 0 : deletedInRecord.size()); }
/**
* @return <code>true</code> if all the RecordAndOffset lists are empty;
diff --git a/src/main/java/htsjdk/samtools/util/TestUtil.java b/src/main/java/htsjdk/samtools/util/TestUtil.java
index 28c6c39..bbdf464 100644
--- a/src/main/java/htsjdk/samtools/util/TestUtil.java
+++ b/src/main/java/htsjdk/samtools/util/TestUtil.java
@@ -29,6 +29,11 @@ import java.io.*;
public class TestUtil {
+ /**
+ * Base url where all test files for http tests are found
+ */
+ public static final String BASE_URL_FOR_HTTP_TESTS = "https://personal.broadinstitute.org/picard/testdata/";
+
public static File getTempDirectory(final String prefix, final String suffix) {
final File tempDirectory;
try {
diff --git a/src/main/java/htsjdk/tribble/BinaryFeatureCodec.java b/src/main/java/htsjdk/tribble/BinaryFeatureCodec.java
index dfe1c91..dbd0afc 100644
--- a/src/main/java/htsjdk/tribble/BinaryFeatureCodec.java
+++ b/src/main/java/htsjdk/tribble/BinaryFeatureCodec.java
@@ -3,6 +3,7 @@ package htsjdk.tribble;
import htsjdk.samtools.util.CloserUtil;
import htsjdk.samtools.util.LocationAware;
import htsjdk.samtools.util.RuntimeIOException;
+import htsjdk.tribble.index.tabix.TabixFormat;
import htsjdk.tribble.readers.PositionalBufferedStream;
import java.io.IOException;
@@ -40,4 +41,12 @@ abstract public class BinaryFeatureCodec<T extends Feature> implements FeatureCo
throw new RuntimeIOException("Failure reading from stream.", e);
}
}
+
+ /**
+ * Marked as final because binary features could not be tabix indexed
+ */
+ @Override
+ public final TabixFormat getTabixFormat() {
+ throw new TribbleException("Binary codecs does not support tabix");
+ }
}
diff --git a/src/main/java/htsjdk/tribble/FeatureCodec.java b/src/main/java/htsjdk/tribble/FeatureCodec.java
index b45d8cf..f14191a 100644
--- a/src/main/java/htsjdk/tribble/FeatureCodec.java
+++ b/src/main/java/htsjdk/tribble/FeatureCodec.java
@@ -19,6 +19,7 @@
package htsjdk.tribble;
import htsjdk.samtools.util.LocationAware;
+import htsjdk.tribble.index.tabix.TabixFormat;
import java.io.IOException;
import java.io.InputStream;
@@ -119,4 +120,17 @@ public interface FeatureCodec<FEATURE_TYPE extends Feature, SOURCE> {
* @return true if potentialInput can be parsed, false otherwise
*/
public boolean canDecode(final String path);
+
+ /**
+ * Define the tabix format for the feature, used for indexing. Default implementation throws an exception.
+ *
+ * Note that only {@link AsciiFeatureCodec} could read tabix files as defined in
+ * {@link AbstractFeatureReader#getFeatureReader(String, String, FeatureCodec, boolean)}
+ *
+ * @return the format to use with tabix
+ * @throws TribbleException if the format is not defined
+ */
+ default public TabixFormat getTabixFormat() {
+ throw new TribbleException(this.getClass().getSimpleName() + "does not have defined tabix format");
+ }
}
diff --git a/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java b/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java
index ae278f4..514782d 100644
--- a/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java
+++ b/src/main/java/htsjdk/tribble/TribbleIndexedFeatureReader.java
@@ -33,10 +33,12 @@ import htsjdk.tribble.readers.PositionalBufferedStream;
import htsjdk.tribble.util.ParsingUtils;
import java.io.BufferedInputStream;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -217,7 +219,7 @@ public class TribbleIndexedFeatureReader<T extends Feature, SOURCE> extends Abst
PositionalBufferedStream pbs = null;
try {
is = ParsingUtils.openInputStream(path);
- if (isGZIPPath(path)) {
+ if (hasBlockCompressedExtension(new URI(URLEncoder.encode(path, "UTF-8")))) {
// TODO -- warning I don't think this can work, the buffered input stream screws up position
is = new GZIPInputStream(new BufferedInputStream(is));
}
@@ -273,7 +275,11 @@ public class TribbleIndexedFeatureReader<T extends Feature, SOURCE> extends Abst
return new WFIterator();
}
+ /**
+ * @deprecated use {@link #hasBlockCompressedExtension(String)} instead
+ */
//Visible for testing
+ @Deprecated
static boolean isGZIPPath(final String path) {
if (path.toLowerCase().endsWith(".gz")) {
return true;
@@ -310,7 +316,7 @@ public class TribbleIndexedFeatureReader<T extends Feature, SOURCE> extends Abst
final InputStream inputStream = ParsingUtils.openInputStream(path);
final PositionalBufferedStream pbs;
- if (isGZIPPath(path)) {
+ if (hasBlockCompressedExtension(path)) {
// Gzipped -- we need to buffer the GZIPInputStream methods as this class makes read() calls,
// and seekableStream does not support single byte reads
final InputStream is = new GZIPInputStream(new BufferedInputStream(inputStream, 512000));
diff --git a/src/main/java/htsjdk/tribble/bed/BEDCodec.java b/src/main/java/htsjdk/tribble/bed/BEDCodec.java
index 0e91850..62d202c 100644
--- a/src/main/java/htsjdk/tribble/bed/BEDCodec.java
+++ b/src/main/java/htsjdk/tribble/bed/BEDCodec.java
@@ -25,6 +25,7 @@ package htsjdk.tribble.bed;
import htsjdk.tribble.AsciiFeatureCodec;
import htsjdk.tribble.annotation.Strand;
+import htsjdk.tribble.index.tabix.TabixFormat;
import htsjdk.tribble.readers.LineIterator;
import htsjdk.tribble.util.ParsingUtils;
@@ -224,4 +225,8 @@ public class BEDCodec extends AsciiFeatureCodec<BEDFeature> {
}
}
+ @Override
+ public TabixFormat getTabixFormat() {
+ return TabixFormat.BED;
+ }
}
diff --git a/src/main/java/htsjdk/tribble/index/IndexFactory.java b/src/main/java/htsjdk/tribble/index/IndexFactory.java
index 85fbd72..a588220 100644
--- a/src/main/java/htsjdk/tribble/index/IndexFactory.java
+++ b/src/main/java/htsjdk/tribble/index/IndexFactory.java
@@ -260,11 +260,25 @@ public class IndexFactory {
public static <FEATURE_TYPE extends Feature, SOURCE_TYPE> Index createIndex(final File inputFile,
final FeatureCodec<FEATURE_TYPE, SOURCE_TYPE> codec,
final IndexType type) {
+ return createIndex(inputFile, codec, type, null);
+ }
+
+ /**
+ * Create an index of the specified type with default binning parameters
+ *
+ * @param inputFile the input file to load features from
+ * @param codec the codec to use for decoding records
+ * @param type the type of index to create
+ * @param sequenceDictionary May be null, but if present may reduce memory footprint for tabix index creation
+ */
+ public static <FEATURE_TYPE extends Feature, SOURCE_TYPE> Index createIndex(final File inputFile,
+ final FeatureCodec<FEATURE_TYPE, SOURCE_TYPE> codec,
+ final IndexType type,
+ final SAMSequenceDictionary sequenceDictionary) {
switch (type) {
case INTERVAL_TREE: return createIntervalIndex(inputFile, codec);
case LINEAR: return createLinearIndex(inputFile, codec);
- // Tabix index initialization requires additional information, so this construction method won't work.
- case TABIX: throw new UnsupportedOperationException("Tabix indices cannot be created through a generic interface");
+ case TABIX: return createTabixIndex(inputFile, codec, sequenceDictionary);
}
throw new IllegalArgumentException("Unrecognized IndexType " + type);
}
@@ -318,7 +332,18 @@ public class IndexFactory {
return (TabixIndex)createIndex(inputFile, new FeatureIterator<FEATURE_TYPE, SOURCE_TYPE>(inputFile, codec), indexCreator);
}
-
+ /**
+ * @param inputFile The file to be indexed.
+ * @param codec the codec to use for decoding records
+ * @param sequenceDictionary May be null, but if present may reduce memory footprint for index creation. Features
+ * in inputFile must be in the order defined by sequenceDictionary, if it is present.
+ *
+ */
+ public static <FEATURE_TYPE extends Feature, SOURCE_TYPE> TabixIndex createTabixIndex(final File inputFile,
+ final FeatureCodec<FEATURE_TYPE, SOURCE_TYPE> codec,
+ final SAMSequenceDictionary sequenceDictionary) {
+ return createTabixIndex(inputFile, codec, codec.getTabixFormat(), sequenceDictionary);
+ }
private static Index createIndex(final File inputFile, final FeatureIterator iterator, final IndexCreator creator) {
Feature lastFeature = null;
diff --git a/src/main/java/htsjdk/variant/variantcontext/FastGenotype.java b/src/main/java/htsjdk/variant/variantcontext/FastGenotype.java
index 935d825..665e672 100644
--- a/src/main/java/htsjdk/variant/variantcontext/FastGenotype.java
+++ b/src/main/java/htsjdk/variant/variantcontext/FastGenotype.java
@@ -29,7 +29,10 @@ import java.util.List;
import java.util.Map;
/**
- * This class encompasses all the basic information about a genotype. It is immutable.
+ * This class encompasses all the basic information about a genotype.
+ *
+ * For the sake of performance, it does not make a copy of the Collections/arrays it's constructed from, and so
+ * subsequent changes to those Collections/arrays will be reflected in the FastGenotype object
*
* A genotype has several key fields
*
diff --git a/src/main/java/htsjdk/variant/variantcontext/Genotype.java b/src/main/java/htsjdk/variant/variantcontext/Genotype.java
index a104b0e..8d781a0 100644
--- a/src/main/java/htsjdk/variant/variantcontext/Genotype.java
+++ b/src/main/java/htsjdk/variant/variantcontext/Genotype.java
@@ -528,7 +528,7 @@ public abstract class Genotype implements Comparable<Genotype>, Serializable {
}
/**
- * A totally generic getter, that allows you to specific keys that correspond
+ * A totally generic getter, that allows you to get specific keys that correspond
* to even inline values (GQ, for example). Can be very expensive. Additionally,
* all <code>int[]</code> are converted inline into <code>List<Integer></code> for convenience.
*
@@ -556,6 +556,8 @@ public abstract class Genotype implements Comparable<Genotype>, Serializable {
return Collections.EMPTY_LIST;
} else if (key.equals(VCFConstants.DEPTH_KEY)) {
return getDP();
+ } else if (key.equals(VCFConstants.GENOTYPE_FILTER_KEY)) {
+ return getFilters();
} else {
return getExtendedAttribute(key);
}
@@ -572,6 +574,8 @@ public abstract class Genotype implements Comparable<Genotype>, Serializable {
return hasPL();
} else if (key.equals(VCFConstants.DEPTH_KEY)) {
return hasDP();
+ } else if (key.equals(VCFConstants.GENOTYPE_FILTER_KEY)) {
+ return true; //always available
} else {
return hasExtendedAttribute(key);
}
diff --git a/src/main/java/htsjdk/variant/variantcontext/GenotypeBuilder.java b/src/main/java/htsjdk/variant/variantcontext/GenotypeBuilder.java
index a0ec1c8..483e1c6 100644
--- a/src/main/java/htsjdk/variant/variantcontext/GenotypeBuilder.java
+++ b/src/main/java/htsjdk/variant/variantcontext/GenotypeBuilder.java
@@ -28,6 +28,7 @@ package htsjdk.variant.variantcontext;
import htsjdk.tribble.util.ParsingUtils;
import htsjdk.variant.vcf.VCFConstants;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
@@ -49,6 +50,11 @@ import java.util.Map;
* or with intervening sets to conveniently make similar Genotypes with
* slight modifications.
*
+ * Re-using the same GenotypeBuilder to build multiple Genotype objects via calls
+ * to make() is dangerous, since reference types in the builder (eg., Collections/arrays)
+ * don't get copied when making each Genotype. To safely re-use the same builder object
+ * multiple times, use makeWithShallowCopy() instead of make().
+ *
* @author Mark DePristo
* @since 06/12
*/
@@ -185,14 +191,35 @@ public final class GenotypeBuilder {
* created, althrough the contents of array values like PL should never be modified
* inline as they are not copied for efficiency reasons.
*
+ * Note: if attributes are added via this builder after a call to make(), the new Genotype will
+ * be modified. Use {@link #makeWithShallowCopy} to safely re-use the same builder object
+ * multiple times.
+ *
* @return a newly minted Genotype object with values provided from this builder
*/
public Genotype make() {
- final Map<String, Object> ea = extendedAttributes == null ? NO_ATTRIBUTES : extendedAttributes;
+ final Map<String, Object> ea = (extendedAttributes == null) ? NO_ATTRIBUTES : extendedAttributes;
return new FastGenotype(sampleName, alleles, isPhased, GQ, DP, AD, PL, filters, ea);
}
/**
+ * Create a new Genotype object using the values set in this builder, and perform a
+ * shallow copy of reference types to allow safer re-use of this builder
+ *
+ * After creation the values in this builder can be modified and more Genotypes
+ * created.
+ *
+ * @return a newly minted Genotype object with values provided from this builder
+ */
+ public Genotype makeWithShallowCopy() {
+ final Map<String, Object> ea = (extendedAttributes == null) ? NO_ATTRIBUTES : new HashMap<>(extendedAttributes);
+ final List<Allele> al = new ArrayList<>(alleles);
+ final int[] copyAD = (AD == null) ? null : Arrays.copyOf(AD, AD.length);
+ final int[] copyPL = (PL == null) ? null : Arrays.copyOf(PL, PL.length);
+ return new FastGenotype(sampleName, al, isPhased, GQ, DP, copyAD, copyPL, filters, ea);
+ }
+
+ /**
* Set this genotype's name
* @param sampleName
* @return
@@ -303,9 +330,9 @@ public final class GenotypeBuilder {
}
/**
- * This genotype has these attributes.
+ * This genotype has these attributes. Attributes are added to previous ones.
*
- * Cannot contain inline attributes (DP, AD, GQ, PL)
+ * Cannot contain inline attributes (DP, AD, GQ, PL). Note: this is not checked
* @return
*/
public GenotypeBuilder attributes(final Map<String, Object> attributes) {
@@ -327,7 +354,7 @@ public final class GenotypeBuilder {
/**
* This genotype has this attribute key / value pair.
*
- * Cannot contain inline attributes (DP, AD, GQ, PL)
+ * Cannot contain inline attributes (DP, AD, GQ, PL). Note: this is not checked
* @return
*/
public GenotypeBuilder attribute(final String key, final Object value) {
diff --git a/src/main/java/htsjdk/variant/vcf/AbstractVCFCodec.java b/src/main/java/htsjdk/variant/vcf/AbstractVCFCodec.java
index 7b157ca..16857b4 100644
--- a/src/main/java/htsjdk/variant/vcf/AbstractVCFCodec.java
+++ b/src/main/java/htsjdk/variant/vcf/AbstractVCFCodec.java
@@ -30,6 +30,7 @@ import htsjdk.tribble.AsciiFeatureCodec;
import htsjdk.tribble.Feature;
import htsjdk.tribble.NameAwareCodec;
import htsjdk.tribble.TribbleException;
+import htsjdk.tribble.index.tabix.TabixFormat;
import htsjdk.tribble.util.ParsingUtils;
import htsjdk.variant.utils.GeneralUtils;
import htsjdk.variant.variantcontext.Allele;
@@ -782,4 +783,9 @@ public abstract class AbstractVCFCodec extends AsciiFeatureCodec<VariantContext>
protected static void generateException(String message, int lineNo) {
throw new TribbleException(String.format("The provided VCF file is malformed at approximately line number %d: %s", lineNo, message));
}
+
+ @Override
+ public TabixFormat getTabixFormat() {
+ return TabixFormat.VCF;
+ }
}
diff --git a/src/main/java/htsjdk/variant/vcf/VCFStandardHeaderLines.java b/src/main/java/htsjdk/variant/vcf/VCFStandardHeaderLines.java
index dfb3f0f..de2817c 100644
--- a/src/main/java/htsjdk/variant/vcf/VCFStandardHeaderLines.java
+++ b/src/main/java/htsjdk/variant/vcf/VCFStandardHeaderLines.java
@@ -37,17 +37,19 @@ import java.util.Map;
import java.util.Set;
/**
- * Manages header lines for standard VCF INFO and FORMAT fields.
+ * Manages header lines for standard VCF <pre>INFO</pre> and <pre>FORMAT</pre> fields.
*
- * Provides simple mechanisms for registering standard lines,
- * looking them up, and adding them to headers.
+ * Provides simple mechanisms for
+ * 1) registering standard lines,
+ * 2) looking them up, and
+ * 3) adding them to headers.
*
* @author Mark DePristo
* @since 6/12
*/
public class VCFStandardHeaderLines {
/**
- * Enabling this causes us to repair header lines even if only their descriptions differ
+ * Enabling this causes us to repair header lines even if only their descriptions differ.
*/
private final static boolean REPAIR_BAD_DESCRIPTIONS = false;
private static Standards<VCFFormatHeaderLine> formatStandards = new Standards<VCFFormatHeaderLine>();
@@ -55,10 +57,7 @@ public class VCFStandardHeaderLines {
/**
* Walks over the VCF header and repairs the standard VCF header lines in it, returning a freshly
- * allocated VCFHeader with standard VCF header lines repaired as necessary
- *
- * @param header
- * @return
+ * allocated {@link VCFHeader} with standard VCF header lines repaired as necessary.
*/
public static VCFHeader repairStandardHeaderLines(final VCFHeader header) {
final Set<VCFHeaderLine> newLines = new LinkedHashSet<VCFHeaderLine>(header.getMetaDataInInputOrder().size());
@@ -77,11 +76,8 @@ public class VCFStandardHeaderLines {
/**
* Adds header lines for each of the format fields in IDs to header, returning the set of
- * IDs without standard descriptions, unless throwErrorForMissing is true, in which
- * case this situation results in a TribbleException
- *
- * @param IDs
- * @return
+ * {@code IDs} without standard descriptions, unless {@code throwErrorForMissing} is true, in which
+ * case this situation results in a {@link TribbleException}
*/
public static Set<String> addStandardFormatLines(final Set<VCFHeaderLine> headerLines, final boolean throwErrorForMissing, final Collection<String> IDs) {
return formatStandards.addToHeader(headerLines, IDs, throwErrorForMissing);
@@ -89,49 +85,31 @@ public class VCFStandardHeaderLines {
/**
* @see #addStandardFormatLines(java.util.Set, boolean, java.util.Collection)
- *
- * @param headerLines
- * @param throwErrorForMissing
- * @param IDs
- * @return
*/
public static Set<String> addStandardFormatLines(final Set<VCFHeaderLine> headerLines, final boolean throwErrorForMissing, final String ... IDs) {
return addStandardFormatLines(headerLines, throwErrorForMissing, Arrays.asList(IDs));
}
/**
- * Returns the standard format line for ID. If none exists, return null or throw an exception, depending
- * on throwErrorForMissing
- *
- * @param ID
- * @param throwErrorForMissing
- * @return
+ * Returns the standard format line for {@code ID}.
+ * If none exists, return null or throw an exception, depending on {@code throwErrorForMissing}.
*/
public static VCFFormatHeaderLine getFormatLine(final String ID, final boolean throwErrorForMissing) {
return formatStandards.get(ID, throwErrorForMissing);
}
/**
- * Returns the standard format line for ID. If none exists throw an exception
- *
- * @param ID
- * @return
+ * Returns the standard format line for {@code ID}.
+ * If none exists, throw an {@link TribbleException}
*/
public static VCFFormatHeaderLine getFormatLine(final String ID) {
return formatStandards.get(ID, true);
}
- private static void registerStandard(final VCFFormatHeaderLine line) {
- formatStandards.add(line);
- }
-
/**
- * Adds header lines for each of the info fields in IDs to header, returning the set of
- * IDs without standard descriptions, unless throwErrorForMissing is true, in which
- * case this situation results in a TribbleException
- *
- * @param IDs
- * @return
+ * Adds header lines for each of the info fields in {@code IDs} to header, returning the set of
+ * IDs without standard descriptions, unless {@code throwErrorForMissing} is true, in which
+ * case this situation results in a {@link TribbleException}.
*/
public static Set<String> addStandardInfoLines(final Set<VCFHeaderLine> headerLines, final boolean throwErrorForMissing, final Collection<String> IDs) {
return infoStandards.addToHeader(headerLines, IDs, throwErrorForMissing);
@@ -139,65 +117,60 @@ public class VCFStandardHeaderLines {
/**
* @see #addStandardFormatLines(java.util.Set, boolean, java.util.Collection)
- *
- * @param IDs
- * @return
*/
public static Set<String> addStandardInfoLines(final Set<VCFHeaderLine> headerLines, final boolean throwErrorForMissing, final String ... IDs) {
return addStandardInfoLines(headerLines, throwErrorForMissing, Arrays.asList(IDs));
}
/**
- * Returns the standard info line for ID. If none exists, return null or throw an exception, depending
- * on throwErrorForMissing
- *
- * @param ID
- * @param throwErrorForMissing
- * @return
+ * Returns the standard info line for {@code ID}.
+ * If none exists, return {@code null} or throw a {@link TribbleException}, depending on {@code throwErrorForMissing}.
*/
public static VCFInfoHeaderLine getInfoLine(final String ID, final boolean throwErrorForMissing) {
return infoStandards.get(ID, throwErrorForMissing);
}
/**
- * Returns the standard info line for ID. If none exists throw an exception
- *
- * @param ID
- * @return
+ * Returns the standard info line for {@code ID}.
+ * If none exists throw a {@link TribbleException}.
*/
public static VCFInfoHeaderLine getInfoLine(final String ID) {
return getInfoLine(ID, true);
}
+
private static void registerStandard(final VCFInfoHeaderLine line) {
infoStandards.add(line);
}
+ private static void registerStandard(final VCFFormatHeaderLine line) {
+ formatStandards.add(line);
+ }
//
// VCF header line constants
//
static {
// FORMAT lines
- registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_KEY, 1, VCFHeaderLineType.String, "Genotype"));
- registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_QUALITY_KEY, 1, VCFHeaderLineType.Integer, "Genotype Quality"));
- registerStandard(new VCFFormatHeaderLine(VCFConstants.DEPTH_KEY, 1, VCFHeaderLineType.Integer, "Approximate read depth (reads with MQ=255 or with bad mates are filtered)"));
- registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_PL_KEY, VCFHeaderLineCount.G, VCFHeaderLineType.Integer, "Normalized, Phred-scaled likelihoods for genotypes as defined in the VCF specification"));
- registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_ALLELE_DEPTHS, VCFHeaderLineCount.R, VCFHeaderLineType.Integer, "Allelic depths for the ref and alt alleles in the order listed"));
- registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_FILTER_KEY, 1, VCFHeaderLineType.String, "Genotype-level filter"));
- registerStandard(new VCFFormatHeaderLine(VCFConstants.PHASE_QUALITY_KEY, 1, VCFHeaderLineType.Float, "Read-backed phasing quality"));
+ registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_KEY, 1, VCFHeaderLineType.String, "Genotype"));
+ registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_QUALITY_KEY, 1, VCFHeaderLineType.Integer, "Genotype Quality"));
+ registerStandard(new VCFFormatHeaderLine(VCFConstants.DEPTH_KEY, 1, VCFHeaderLineType.Integer, "Approximate read depth (reads with MQ=255 or with bad mates are filtered)"));
+ registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_PL_KEY, VCFHeaderLineCount.G, VCFHeaderLineType.Integer, "Normalized, Phred-scaled likelihoods for genotypes as defined in the VCF specification"));
+ registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_ALLELE_DEPTHS, VCFHeaderLineCount.R, VCFHeaderLineType.Integer, "Allelic depths for the ref and alt alleles in the order listed"));
+ registerStandard(new VCFFormatHeaderLine(VCFConstants.GENOTYPE_FILTER_KEY, VCFHeaderLineCount.UNBOUNDED, VCFHeaderLineType.String, "Genotype-level filter"));
+ registerStandard(new VCFFormatHeaderLine(VCFConstants.PHASE_QUALITY_KEY, 1, VCFHeaderLineType.Float, "Read-backed phasing quality"));
// INFO lines
- registerStandard(new VCFInfoHeaderLine(VCFConstants.END_KEY, 1, VCFHeaderLineType.Integer, "Stop position of the interval"));
- registerStandard(new VCFInfoHeaderLine(VCFConstants.DBSNP_KEY, 0, VCFHeaderLineType.Flag, "dbSNP Membership"));
- registerStandard(new VCFInfoHeaderLine(VCFConstants.DEPTH_KEY, 1, VCFHeaderLineType.Integer, "Approximate read depth; some reads may have been filtered"));
- registerStandard(new VCFInfoHeaderLine(VCFConstants.STRAND_BIAS_KEY, 1, VCFHeaderLineType.Float, "Strand Bias"));
- registerStandard(new VCFInfoHeaderLine(VCFConstants.ALLELE_FREQUENCY_KEY, VCFHeaderLineCount.A, VCFHeaderLineType.Float, "Allele Frequency, for each ALT allele, in the same order as listed"));
- registerStandard(new VCFInfoHeaderLine(VCFConstants.ALLELE_COUNT_KEY, VCFHeaderLineCount.A, VCFHeaderLineType.Integer, "Allele count in genotypes, for each ALT allele, in the same order as listed"));
- registerStandard(new VCFInfoHeaderLine(VCFConstants.ALLELE_NUMBER_KEY, 1, VCFHeaderLineType.Integer, "Total number of alleles in called genotypes"));
- registerStandard(new VCFInfoHeaderLine(VCFConstants.MAPPING_QUALITY_ZERO_KEY, 1, VCFHeaderLineType.Integer, "Total Mapping Quality Zero Reads"));
- registerStandard(new VCFInfoHeaderLine(VCFConstants.RMS_MAPPING_QUALITY_KEY, 1, VCFHeaderLineType.Float, "RMS Mapping Quality"));
- registerStandard(new VCFInfoHeaderLine(VCFConstants.SOMATIC_KEY, 0, VCFHeaderLineType.Flag, "Somatic event"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.END_KEY, 1, VCFHeaderLineType.Integer, "Stop position of the interval"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.DBSNP_KEY, 0, VCFHeaderLineType.Flag, "dbSNP Membership"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.DEPTH_KEY, 1, VCFHeaderLineType.Integer, "Approximate read depth; some reads may have been filtered"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.STRAND_BIAS_KEY, 1, VCFHeaderLineType.Float, "Strand Bias"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.ALLELE_FREQUENCY_KEY, VCFHeaderLineCount.A, VCFHeaderLineType.Float, "Allele Frequency, for each ALT allele, in the same order as listed"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.ALLELE_COUNT_KEY, VCFHeaderLineCount.A, VCFHeaderLineType.Integer, "Allele count in genotypes, for each ALT allele, in the same order as listed"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.ALLELE_NUMBER_KEY, 1, VCFHeaderLineType.Integer, "Total number of alleles in called genotypes"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.MAPPING_QUALITY_ZERO_KEY, 1, VCFHeaderLineType.Integer, "Total Mapping Quality Zero Reads"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.RMS_MAPPING_QUALITY_KEY, 1, VCFHeaderLineType.Float, "RMS Mapping Quality"));
+ registerStandard(new VCFInfoHeaderLine(VCFConstants.SOMATIC_KEY, 0, VCFHeaderLineType.Flag, "Somatic event"));
}
private static class Standards<T extends VCFCompoundHeaderLine> {
@@ -207,10 +180,10 @@ public class VCFStandardHeaderLines {
final T standard = get(line.getID(), false);
if ( standard != null ) {
final boolean badCountType = line.getCountType() != standard.getCountType();
- final boolean badCount = line.isFixedCount() && ! badCountType && line.getCount() != standard.getCount();
- final boolean badType = line.getType() != standard.getType();
- final boolean badDesc = ! line.getDescription().equals(standard.getDescription());
- final boolean needsRepair = badCountType || badCount || badType || (REPAIR_BAD_DESCRIPTIONS && badDesc);
+ final boolean badCount = line.isFixedCount() && ! badCountType && line.getCount() != standard.getCount();
+ final boolean badType = line.getType() != standard.getType();
+ final boolean badDesc = ! line.getDescription().equals(standard.getDescription());
+ final boolean needsRepair = badCountType || badCount || badType || (REPAIR_BAD_DESCRIPTIONS && badDesc);
if ( needsRepair ) {
if ( GeneralUtils.DEBUG_MODE_ENABLED ) {
@@ -221,10 +194,12 @@ public class VCFStandardHeaderLines {
+ (badDesc ? " -- descriptions disagree; header has '" + line.getDescription() + "' but standard is '" + standard.getDescription() + "'": ""));
}
return standard;
- } else
+ } else {
return line;
- } else
+ }
+ } else {
return line;
+ }
}
public Set<String> addToHeader(final Set<VCFHeaderLine> headerLines, final Collection<String> IDs, final boolean throwErrorForMissing) {
@@ -241,15 +216,17 @@ public class VCFStandardHeaderLines {
}
public void add(final T line) {
- if ( standards.containsKey(line.getID()) )
+ if ( standards.containsKey(line.getID()) ) {
throw new TribbleException("Attempting to add multiple standard header lines for ID " + line.getID());
+ }
standards.put(line.getID(), line);
}
public T get(final String ID, final boolean throwErrorForMissing) {
final T x = standards.get(ID);
- if ( throwErrorForMissing && x == null )
+ if ( throwErrorForMissing && x == null ) {
throw new TribbleException("Couldn't find a standard VCF header line for field " + ID);
+ }
return x;
}
}
diff --git a/src/test/java/htsjdk/samtools/BAMRemoteFileTest.java b/src/test/java/htsjdk/samtools/BAMRemoteFileTest.java
index 387de4e..4b686cf 100644
--- a/src/test/java/htsjdk/samtools/BAMRemoteFileTest.java
+++ b/src/test/java/htsjdk/samtools/BAMRemoteFileTest.java
@@ -24,6 +24,7 @@
package htsjdk.samtools;
import htsjdk.samtools.util.CloserUtil;
+import htsjdk.samtools.util.TestUtil;
import org.testng.annotations.Test;
import java.io.File;
@@ -42,7 +43,7 @@ import static org.testng.Assert.*;
public class BAMRemoteFileTest {
private final File BAM_INDEX_FILE = new File("src/test/resources/htsjdk/samtools/BAMFileIndexTest/index_test.bam.bai");
private final File BAM_FILE = new File("src/test/resources/htsjdk/samtools/BAMFileIndexTest/index_test.bam");
- private final String BAM_URL_STRING = "http://www.broadinstitute.org/~picard/testdata/index_test.bam";
+ private final String BAM_URL_STRING = TestUtil.BASE_URL_FOR_HTTP_TESTS + "index_test.bam";
private final URL bamURL;
private final boolean mVerbose = false;
diff --git a/src/test/java/htsjdk/samtools/CRAMCRAIIndexerTest.java b/src/test/java/htsjdk/samtools/CRAMCRAIIndexerTest.java
index 19284b2..11d2f3c 100644
--- a/src/test/java/htsjdk/samtools/CRAMCRAIIndexerTest.java
+++ b/src/test/java/htsjdk/samtools/CRAMCRAIIndexerTest.java
@@ -30,6 +30,11 @@ public class CRAMCRAIIndexerTest {
refSource,
ValidationStringency.STRICT);
SAMFileHeader samHeader = reader.getFileHeader();
+ Iterator<SAMRecord> it = reader.getIterator();
+ while(it.hasNext()) {
+ SAMRecord samRec = it.next();
+ }
+
reader.close();
FileInputStream fis = new FileInputStream(CRAMFile);
diff --git a/src/test/java/htsjdk/samtools/SAMRecordUtilTest.java b/src/test/java/htsjdk/samtools/SAMRecordUtilTest.java
new file mode 100644
index 0000000..eb3712f
--- /dev/null
+++ b/src/test/java/htsjdk/samtools/SAMRecordUtilTest.java
@@ -0,0 +1,29 @@
+package htsjdk.samtools;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+
+public class SAMRecordUtilTest {
+ @Test public void testReverseComplement() {
+ final SAMFileHeader header = new SAMFileHeader();
+ final SAMRecord rec = new SAMRecord(header);
+ rec.setReadString("ACACACACAC");
+ rec.setBaseQualityString("HHHHHIIIII");
+ rec.setAttribute("X1", new byte[] {1,2,3,4,5});
+ rec.setAttribute("X2", new short[] {1,2,3,4,5});
+ rec.setAttribute("X3", new int[] {1,2,3,4,5});
+ rec.setAttribute("X4", new float[] {1.0f,2.0f,3.0f,4.0f,5.0f});
+ rec.setAttribute("Y1", "AAAAGAAAAC");
+
+ SAMRecordUtil.reverseComplement(rec, Arrays.asList("Y1"), Arrays.asList("X1", "X2", "X3", "X4", "X5"));
+ Assert.assertEquals(rec.getReadString(), "GTGTGTGTGT");
+ Assert.assertEquals(rec.getBaseQualityString(), "IIIIIHHHHH");
+ Assert.assertEquals(rec.getByteArrayAttribute("X1"), new byte[] {5,4,3,2,1});
+ Assert.assertEquals(rec.getSignedShortArrayAttribute("X2"), new short[] {5,4,3,2,1});
+ Assert.assertEquals(rec.getSignedIntArrayAttribute("X3"), new int[] {5,4,3,2,1});
+ Assert.assertEquals(rec.getFloatArrayAttribute("X4"), new float[] {5.0f,4.0f,3.0f,2.0f,1.0f});
+ Assert.assertEquals(rec.getStringAttribute("Y1"), "GTTTTCTTTT");
+ }
+}
diff --git a/src/test/java/htsjdk/samtools/SAMUtilsTest.java b/src/test/java/htsjdk/samtools/SAMUtilsTest.java
index 48baf44..0fa6b4a 100644
--- a/src/test/java/htsjdk/samtools/SAMUtilsTest.java
+++ b/src/test/java/htsjdk/samtools/SAMUtilsTest.java
@@ -26,7 +26,7 @@ package htsjdk.samtools;
import org.testng.Assert;
import org.testng.annotations.Test;
-import java.util.Arrays;
+import java.util.List;
public class SAMUtilsTest {
@Test
@@ -173,4 +173,79 @@ public class SAMUtilsTest {
record.setSecondOfPairFlag(true);
Assert.assertEquals(SAMUtils.getNumOverlappingAlignedBasesToClip(record), 10);
}
+
+ @Test
+ public void testOtherCanonicalAlignments() {
+ // setup the record
+ final SAMFileHeader header = new SAMFileHeader();
+ header.addSequence(new SAMSequenceRecord("1", 1000));
+ header.addSequence(new SAMSequenceRecord("2", 1000));
+ final SAMRecord record = new SAMRecord(header);
+ record.setReadPairedFlag(true);
+ record.setFirstOfPairFlag(true);
+ record.setCigar(TextCigarCodec.decode("10M"));
+ record.setReferenceIndex(0);
+ record.setAlignmentStart(1);
+ record.setMateReferenceIndex(0);
+ record.setMateAlignmentStart(1);
+ record.setReadPairedFlag(true);
+ record.setSupplementaryAlignmentFlag(true);//spec says first 'SA' record will be the primary record
+
+ record.setMateReferenceIndex(0);
+ record.setMateAlignmentStart(100);
+ record.setInferredInsertSize(99);
+
+ record.setReadBases("AAAAAAAAAA".getBytes());
+ record.setBaseQualities("##########".getBytes());
+ // check no alignments if no SA tag */
+ Assert.assertEquals(SAMUtils.getOtherCanonicalAlignments(record).size(),0);
+
+
+ record.setAttribute(SAMTagUtil.getSingleton().SA,
+ "2,500,+,3S2=1X2=2S,60,1;" +
+ "1,191,-,8M2S,60,0;");
+
+ // extract suppl alignments
+ final List<SAMRecord> suppl = SAMUtils.getOtherCanonicalAlignments(record);
+ Assert.assertNotNull(suppl);
+ Assert.assertEquals(suppl.size(), 2);
+
+ for(final SAMRecord other: suppl) {
+ Assert.assertFalse(other.getReadUnmappedFlag());
+ Assert.assertTrue(other.getReadPairedFlag());
+ Assert.assertFalse(other.getMateUnmappedFlag());
+ Assert.assertEquals(other.getMateAlignmentStart(),record.getMateAlignmentStart());
+ Assert.assertEquals(other.getMateReferenceName(),record.getMateReferenceName());
+
+ Assert.assertEquals(other.getReadName(),record.getReadName());
+ if( other.getReadNegativeStrandFlag()==record.getReadNegativeStrandFlag()) {
+ Assert.assertEquals(other.getReadString(),record.getReadString());
+ Assert.assertEquals(other.getBaseQualityString(),record.getBaseQualityString());
+ }
+ }
+
+ SAMRecord other = suppl.get(0);
+ Assert.assertFalse(other.getSupplementaryAlignmentFlag());//1st of suppl and 'record' is supplementary
+ Assert.assertEquals(other.getReferenceName(),"2");
+ Assert.assertEquals(other.getAlignmentStart(),500);
+ Assert.assertFalse(other.getReadNegativeStrandFlag());
+ Assert.assertEquals(other.getMappingQuality(), 60);
+ Assert.assertEquals(other.getAttribute(SAMTagUtil.getSingleton().NM),1);
+ Assert.assertEquals(other.getCigarString(),"3S2=1X2=2S");
+ Assert.assertEquals(other.getInferredInsertSize(),0);
+
+
+ other = suppl.get(1);
+ Assert.assertTrue(other.getSupplementaryAlignmentFlag());
+ Assert.assertEquals(other.getReferenceName(),"1");
+ Assert.assertEquals(other.getAlignmentStart(),191);
+ Assert.assertTrue(other.getReadNegativeStrandFlag());
+ Assert.assertEquals(other.getMappingQuality(), 60);
+ Assert.assertEquals(other.getAttribute(SAMTagUtil.getSingleton().NM),0);
+ Assert.assertEquals(other.getCigarString(),"8M2S");
+ Assert.assertEquals(other.getInferredInsertSize(),-91);//100(mate) - 191(other)
+
+
+ }
+
}
diff --git a/src/test/java/htsjdk/samtools/SamReaderFactoryTest.java b/src/test/java/htsjdk/samtools/SamReaderFactoryTest.java
index 74adbf1..ece91e2 100644
--- a/src/test/java/htsjdk/samtools/SamReaderFactoryTest.java
+++ b/src/test/java/htsjdk/samtools/SamReaderFactoryTest.java
@@ -5,12 +5,7 @@ import htsjdk.samtools.seekablestream.ISeekableStreamFactory;
import htsjdk.samtools.seekablestream.SeekableFileStream;
import htsjdk.samtools.seekablestream.SeekableHTTPStream;
import htsjdk.samtools.seekablestream.SeekableStreamFactory;
-import htsjdk.samtools.util.Iterables;
-import htsjdk.samtools.util.Log;
-import htsjdk.samtools.util.RuntimeIOException;
-import htsjdk.samtools.util.StopWatch;
-
-import java.nio.file.Path;
+import htsjdk.samtools.util.*;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -21,9 +16,9 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.function.BiFunction;
@@ -159,8 +154,8 @@ public class SamReaderFactoryTest {
{
try {
- bamUrl = new URL("http://www.broadinstitute.org/~picard/testdata/index_test.bam");
- bamIndexUrl = new URL("http://www.broadinstitute.org/~picard/testdata/index_test.bam.bai");
+ bamUrl = new URL(TestUtil.BASE_URL_FOR_HTTP_TESTS + "index_test.bam");
+ bamIndexUrl = new URL(TestUtil.BASE_URL_FOR_HTTP_TESTS + "index_test.bam.bai");
} catch (final MalformedURLException e) {
throw new RuntimeException(e);
}
diff --git a/src/test/java/htsjdk/samtools/cram/structure/SliceTests.java b/src/test/java/htsjdk/samtools/cram/structure/SliceTests.java
index a5c1669..c52dccb 100644
--- a/src/test/java/htsjdk/samtools/cram/structure/SliceTests.java
+++ b/src/test/java/htsjdk/samtools/cram/structure/SliceTests.java
@@ -1,10 +1,19 @@
package htsjdk.samtools.cram.structure;
+import htsjdk.samtools.CRAMFileReader;
+import htsjdk.samtools.SAMFileHeader;
import htsjdk.samtools.SAMRecord;
+import htsjdk.samtools.ValidationStringency;
+import htsjdk.samtools.cram.CRAMException;
+import htsjdk.samtools.cram.ref.ReferenceSource;
import htsjdk.samtools.util.SequenceUtil;
import org.testng.Assert;
import org.testng.annotations.Test;
+import java.io.File;
+import java.io.IOException;
+import java.util.Iterator;
+
/**
* Created by vadim on 07/12/2015.
*/
@@ -33,4 +42,29 @@ public class SliceTests {
Assert.assertEquals(slice.refMD5, md5);
Assert.assertTrue(slice.validateRefMD5(ref));
}
+
+ @Test(expectedExceptions= CRAMException.class)
+ public void testFailsMD5Check() throws IOException {
+ // auxf.alteredForMD5test.fa has been altered slightly from the original reference
+ // to cause the CRAM md5 check to fail
+ final File CRAMFile = new File("src/test/resources/htsjdk/samtools/cram/auxf#values.3.0.cram");
+ final File refFile = new File("src/test/resources/htsjdk/samtools/cram/auxf.alteredForMD5test.fa");
+ ReferenceSource refSource = new ReferenceSource(refFile);
+ CRAMFileReader reader = null;
+ try {
+ reader = new CRAMFileReader(
+ CRAMFile,
+ null,
+ refSource,
+ ValidationStringency.STRICT);
+ Iterator<SAMRecord> it = reader.getIterator();
+ while (it.hasNext()) {
+ it.next();
+ }
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
}
diff --git a/src/test/java/htsjdk/samtools/filter/IntervalKeepPairFilterTest.java b/src/test/java/htsjdk/samtools/filter/IntervalKeepPairFilterTest.java
new file mode 100644
index 0000000..3d30255
--- /dev/null
+++ b/src/test/java/htsjdk/samtools/filter/IntervalKeepPairFilterTest.java
@@ -0,0 +1,123 @@
+package htsjdk.samtools.filter;
+
+import htsjdk.samtools.SAMRecordSetBuilder;
+import htsjdk.samtools.util.CollectionUtil;
+import org.testng.Assert;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import htsjdk.samtools.util.Interval;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.stream.StreamSupport;
+
+public class IntervalKeepPairFilterTest {
+ private static final int READ_LENGTH = 151;
+ private final SAMRecordSetBuilder builder = new SAMRecordSetBuilder();
+
+ @BeforeTest
+ public void setUp() {
+ builder.setReadLength(READ_LENGTH);
+ // Will be kept when an interval overlaps chromosome 1 in the first 151
+ // bases.
+ builder.addPair("mapped_pair_chr1", 0, 1, 151);
+ // Will be kept when an interval overlaps chromsome 2 in the first 151
+ // bases.
+ builder.addPair("mapped_pair_chr2", 1, 1, 151);
+ // The first read should pass and second should not, but both will
+ // be kept in first test.
+ builder.addPair("one_of_pair", 0, 1, 1000);
+ // The second read is unmapped, but both should be kept in an
+ // interval test where the interval includes chromosome four, where
+ // read one will overlap.
+ builder.addPair("second_mate_unmapped", 3, -1, 1, 1000, false, true,
+ "151M", null, false, false, false, false, -1);
+ // The first read is unmapped but both should be kept in an
+ // interval test where the interval includes chromosome four, where
+ // read two will overlap.
+ builder.addPair("first_mate_unmapped", -1, 3, 1000, 1, true, false,
+ null, "151M", false, false, false, false, -1);
+ // This pair will overlap any interval that includes chromosome 1:1000
+ builder.addPair("prove_one_of_pair", 0, 1000, 1000);
+ // These reads are unmapped and will not map to any intervals, so they
+ // are never kept. This is tested below.
+ builder.addPair("both_unmapped", -1, -1, 1, 1, true, true, null, null,
+ false, false, false, false, -1);
+ // Secondary alignments are never kept by the interval filter.
+ builder.addFrag("mapped_pair_chr1", 0, 1, false, false, "151M", null, -1, true, false);
+ // Supplementary alignment are never kept by the interval filter.
+ builder.addFrag("mapped_pair_chr1", 0, 1, false, false, "151M", null, -1, false, true);
+ }
+
+ @Test(dataProvider = "testData")
+ public void testIntervalPairFilter(final List<Interval> intervals, final long expectedPassingRecords) {
+ final IntervalKeepPairFilter filter = new IntervalKeepPairFilter(intervals);
+
+ long actualPassingRecords = StreamSupport.stream(builder.spliterator(), false)
+ .filter(rec -> !filter.filterOut(rec))
+ .count();
+
+ Assert.assertEquals(actualPassingRecords, expectedPassingRecords);
+ }
+
+ @Test
+ public void testUnmappedPair() {
+ final List<Interval> intervalList = new ArrayList<>();
+
+ final Interval interval1 = new Interval("chr1", 1, 999);
+ final Interval interval2 = new Interval("chr3", 1, 2);
+ final Interval interval3 = new Interval("chr2", 1, 2);
+ final Interval interval4 = new Interval("chr4", 1, 2);
+
+ intervalList.addAll(CollectionUtil.makeList(interval1, interval2, interval3, interval4));
+
+ final IntervalKeepPairFilter filter = new IntervalKeepPairFilter(intervalList);
+
+ boolean unmappedPassed = StreamSupport.stream(builder.spliterator(), false)
+ .filter(rec -> !filter.filterOut(rec))
+ .anyMatch(rec -> rec.getReadName().equals("both_unmapped"));
+
+ Assert.assertFalse(unmappedPassed);
+ }
+
+ @Test
+ public void testNotPrimaryReads() {
+ final List<Interval> intervalList = new ArrayList<>();
+ final Interval interval1 = new Interval("chr1", 1, 999);
+ intervalList.add(interval1);
+
+ final IntervalKeepPairFilter filter = new IntervalKeepPairFilter(intervalList);
+
+ boolean notPrimary = StreamSupport.stream(builder.spliterator(), false)
+ .filter(rec -> !filter.filterOut(rec))
+ .anyMatch(rec -> rec.getNotPrimaryAlignmentFlag() || rec.getSupplementaryAlignmentFlag());
+
+ Assert.assertFalse(notPrimary);
+ }
+
+ @DataProvider(name = "testData")
+ private Object[][] testData() {
+ Interval interval = new Interval("chr1", 1, 999);
+ final List<Interval> intervalList_twoPair = new ArrayList<>();
+ intervalList_twoPair.add(interval);
+
+ interval = new Interval("chr3", 1, 2);
+ final List<Interval> intervalList_noMatch = new ArrayList<>();
+ intervalList_noMatch.add(interval);
+
+ interval = new Interval("chr2", 1, 2);
+ final List<Interval> intervalList_onePair = new ArrayList<>();
+ intervalList_onePair.add(interval);
+
+ interval = new Interval("chr4", 1, 2);
+ final List<Interval> intervalList_unmapped = new ArrayList<>();
+ intervalList_unmapped.add(interval);
+
+ return new Object[][]{
+ {intervalList_twoPair, 4},
+ {intervalList_noMatch, 0},
+ {intervalList_onePair, 2},
+ {intervalList_unmapped, 4}
+ };
+ }
+}
diff --git a/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamFactoryTest.java b/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamFactoryTest.java
index 979d944..5eb0af6 100644
--- a/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamFactoryTest.java
+++ b/src/test/java/htsjdk/samtools/seekablestream/SeekableStreamFactoryTest.java
@@ -1,5 +1,6 @@
package htsjdk.samtools.seekablestream;
+import htsjdk.samtools.util.TestUtil;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
@@ -29,10 +30,10 @@ public class SeekableStreamFactoryTest {
new File(TEST_DATA_DIR, "cram_with_bai_index.cram").getAbsolutePath() },
{ new URL("file://" + new File(TEST_DATA_DIR, "cram_with_bai_index.cram").getAbsolutePath()).toExternalForm(),
new File(TEST_DATA_DIR, "cram_with_bai_index.cram").getAbsolutePath() },
- { new URL("http://www.broadinstitute.org/~picard/testdata/index_test.bam").toExternalForm(),
- new URL("http://www.broadinstitute.org/~picard/testdata/index_test.bam").toExternalForm() },
- { new URL("http://www.broadinstitute.org/~picard/testdata/index_test.bam.bai").toExternalForm(),
- new URL("http://www.broadinstitute.org/~picard/testdata/index_test.bam.bai").toExternalForm() }
+ { new URL(TestUtil.BASE_URL_FOR_HTTP_TESTS + "index_test.bam").toExternalForm(),
+ new URL(TestUtil.BASE_URL_FOR_HTTP_TESTS + "index_test.bam").toExternalForm() },
+ { new URL(TestUtil.BASE_URL_FOR_HTTP_TESTS + "index_test.bam.bai").toExternalForm(),
+ new URL(TestUtil.BASE_URL_FOR_HTTP_TESTS + "index_test.bam.bai").toExternalForm() }
};
}
diff --git a/src/test/java/htsjdk/samtools/sra/AbstractSRATest.java b/src/test/java/htsjdk/samtools/sra/AbstractSRATest.java
index c50f3b8..a0984d7 100644
--- a/src/test/java/htsjdk/samtools/sra/AbstractSRATest.java
+++ b/src/test/java/htsjdk/samtools/sra/AbstractSRATest.java
@@ -4,21 +4,53 @@ import htsjdk.samtools.SAMRecord;
import htsjdk.samtools.SAMRecordIterator;
import org.testng.Assert;
import org.testng.SkipException;
+import org.testng.annotations.BeforeGroups;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import java.lang.reflect.Method;
import java.util.NoSuchElementException;
@Test(groups = "sra")
public abstract class AbstractSRATest {
+ private static boolean canResolveNetworkAccession = false;
+ private static String checkAccession = "SRR000123";
+
+ @BeforeGroups(groups = "sra")
+ public final void checkIfCanResolve() {
+ if (!SRAAccession.isSupported()) {
+ return;
+ }
+ canResolveNetworkAccession = SRAAccession.isValid(checkAccession);
+ }
@BeforeMethod
- public final void assertSRAIsSupported(){
+ public final void assertSRAIsSupported() {
if(!SRAAccession.isSupported()){
throw new SkipException("Skipping SRA Test because SRA native code is unavailable.");
}
}
+ @BeforeMethod
+ public final void skipIfCantResolve(Method method, Object[] params) {
+ String accession = null;
+
+ if (params.length > 0) {
+ Object firstParam = params[0];
+ if (firstParam instanceof String) {
+ accession = (String)firstParam;
+ } else if (firstParam instanceof SRAAccession) {
+ accession = firstParam.toString();
+ }
+ }
+
+ if (accession != null &&
+ accession.matches(SRAAccession.REMOTE_ACCESSION_PATTERN) && !canResolveNetworkAccession) {
+ throw new SkipException("Skipping network SRA Test because cannot resolve remote SRA accession '" +
+ checkAccession + "'.");
+ }
+ }
+
/**
* Exhaust the iterator and check that it produce the expected number of mapped and unmapped reads.
* Also checks that the hasNext() agrees with the actual results of next() for the given iterator.
diff --git a/src/test/java/htsjdk/samtools/sra/SRAAccessionTest.java b/src/test/java/htsjdk/samtools/sra/SRAAccessionTest.java
index e241ca9..4b89b7e 100644
--- a/src/test/java/htsjdk/samtools/sra/SRAAccessionTest.java
+++ b/src/test/java/htsjdk/samtools/sra/SRAAccessionTest.java
@@ -13,8 +13,7 @@ public class SRAAccessionTest extends AbstractSRATest {
private Object[][] getIsValidAccData() {
return new Object[][] {
{ "SRR000123", true },
- { "DRR000001", true },
- { "SRR000000", false },
+ { "DRR010511", true },
{ "src/test/resources/htsjdk/samtools/sra/test_archive.sra", true },
{ "src/test/resources/htsjdk/samtools/compressed.bam", false },
{ "src/test/resources/htsjdk/samtools/uncompressed.sam", false },
diff --git a/src/test/java/htsjdk/samtools/sra/SRAIndexTest.java b/src/test/java/htsjdk/samtools/sra/SRAIndexTest.java
index a141203..0cdfc69 100644
--- a/src/test/java/htsjdk/samtools/sra/SRAIndexTest.java
+++ b/src/test/java/htsjdk/samtools/sra/SRAIndexTest.java
@@ -46,7 +46,7 @@ import java.util.Set;
* Created by andrii.nikitiuk on 10/28/15.
*/
public class SRAIndexTest extends AbstractSRATest {
- private static final SRAAccession DEFAULT_ACCESSION = new SRAAccession("SRR1298981");
+ private static final SRAAccession DEFAULT_ACCESSION = new SRAAccession("SRR2096940");
private static final int LAST_BIN_LEVEL = GenomicIndexUtil.LEVEL_STARTS.length - 1;
private static final int SRA_BIN_OFFSET = GenomicIndexUtil.LEVEL_STARTS[LAST_BIN_LEVEL];
diff --git a/src/test/java/htsjdk/samtools/sra/SRALazyRecordTest.java b/src/test/java/htsjdk/samtools/sra/SRALazyRecordTest.java
index 97a1ad8..36ef346 100644
--- a/src/test/java/htsjdk/samtools/sra/SRALazyRecordTest.java
+++ b/src/test/java/htsjdk/samtools/sra/SRALazyRecordTest.java
@@ -12,7 +12,7 @@ import org.testng.annotations.Test;
* Tests for SRA extension of SAMRecord objects which load fields on demand
*/
public class SRALazyRecordTest extends AbstractSRATest {
- private static final SRAAccession DEFAULT_ACCESSION = new SRAAccession("SRR1298981");
+ private static final SRAAccession DEFAULT_ACCESSION = new SRAAccession("SRR2096940");
@DataProvider(name = "serializationTestData")
private Object[][] getSerializationTestData() {
diff --git a/src/test/java/htsjdk/samtools/sra/SRATest.java b/src/test/java/htsjdk/samtools/sra/SRATest.java
index 2bdd7d7..c106bfc 100644
--- a/src/test/java/htsjdk/samtools/sra/SRATest.java
+++ b/src/test/java/htsjdk/samtools/sra/SRATest.java
@@ -101,13 +101,8 @@ public class SRATest extends AbstractSRATest {
@DataProvider(name = "testGroups")
private Object[][] createDataForGroups() {
return new Object[][] {
- {"SRR822962", new TreeSet<>(Arrays.asList(
- "GS54389-FS3-L08", "GS57511-FS3-L08", "GS54387-FS3-L02", "GS54387-FS3-L01",
- "GS57510-FS3-L01", "GS57510-FS3-L03", "GS54389-FS3-L07", "GS54389-FS3-L05",
- "GS54389-FS3-L06", "GS57510-FS3-L02", "GS57510-FS3-L04", "GS54387-FS3-L03",
- "GS46253-FS3-L03"))
- },
- {"SRR2096940", new HashSet<>(Arrays.asList("SRR2096940"))}
+ {"SRR1035115", new TreeSet<>(Arrays.asList("15656144_B09YG", "15656144_B09MR"))},
+ {"SRR2096940", new TreeSet<>(Arrays.asList("SRR2096940"))}
};
}
@@ -148,15 +143,17 @@ public class SRATest extends AbstractSRATest {
private Object[][] createDataForReferences() {
return new Object[][] {
// primary alignment only
- {"SRR1063272", 1,
- Arrays.asList("supercont2.1", "supercont2.2", "supercont2.3", "supercont2.4",
- "supercont2.5", "supercont2.6", "supercont2.7", "supercont2.8",
- "supercont2.9", "supercont2.10", "supercont2.11", "supercont2.12",
- "supercont2.13", "supercont2.14"),
- Arrays.asList(2291499, 1621675, 1575141, 1084805,
- 1814975, 1422463, 1399503, 1398693,
- 1186808, 1059964, 1561994, 774062,
- 756744, 926563)},
+ {"SRR353866", 9,
+ Arrays.asList(
+ "AAAB01001871.1", "AAAB01002233.1", "AAAB01004056.1", "AAAB01006027.1",
+ "AAAB01008846.1", "AAAB01008859.1", "AAAB01008960.1", "AAAB01008982.1",
+ "AAAB01008987.1"
+ ),
+ Arrays.asList(
+ 1115, 1034, 1301, 1007,
+ 11308833, 12516315, 23099915, 1015562,
+ 16222597
+ )},
};
}
@@ -208,67 +205,66 @@ public class SRATest extends AbstractSRATest {
private Object[][] createDataForRowsTest() {
return new Object[][] {
// primary alignment only
- {"SRR1063272", 0, 99, "SRR1063272.R.1",
- "ACTCGACATTCTGCCTTCGACCTATCTTTCTCCTCTCCCAGTCATCGCCCAGTAGAATTACCAGGCAATGAACCAGGGCCTTCCATCCCAACGGCACAGCA",
- "@@CDDBDFFBFHFIEEFGIGGHIEHIGIGGFGEGAFDHIIIIIGGGDFHII;=BF at FEHGIEEH?AHHFHFFFFDC5'5=?CC?ADCD at AC??9BDDCDB<",
- 86, "101M", "supercont2.1", 60, true, false},
+ {"SRR2127895", 1, 83, "SRR2127895.R.1",
+ "CGTGCGCGTGACCCATCAGATGCTGTTCAATCAGTGGCAAATGCGGAACGGTTTCTGCGGGTTGCCGATATTCTGGAGAGTAATGCCAGGCAGGGGCAGGT",
+ "DDBDDDDDBCABC at CCDDDC?99CCA:CDCDDDDDDDECDDDFFFHHHEGIJIIGIJIHIGJIJJJJJJJIIJIIHIGJIJJJIJJIHFFBHHFFFDFBBB",
+ 366, "29S72M", "gi|152968582|ref|NC_009648.1|", 147, true, false, false},
// small SRA archive
{"SRR2096940", 1, 16, "SRR2096940.R.3",
"GTGTGTCACCAGATAAGGAATCTGCCTAACAGGAGGTGTGGGTTAGACCCAATATCAGGAGACCAGGAAGGAGGAGGCCTAAGGATGGGGCTTTTCTGTCACCAATCCTGTCCCTAGTGGCCCCACTGTGGGGTGGAGGGGACAGATAAAAGTACCCAGAACCAGAG",
"AAAABFFFFFFFGGGGGGGGIIIIIIIIIIIIIIIIIIIIIIIIIIIIII7IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIGGGGGFGFFDFFFFFC",
- 55627016, "167M", "CM000681.1", 42, false, false},
+ 55627016, "167M", "CM000681.1", 42, false, false, false},
{"SRR2096940", 10591, 4, "SRR2096940.R.10592",
"CTCTGGTTCTGGGTACTTTTATCTGTCCCCTCCACCCCACAGTGGCGAGCCAGATTCCTTATCTGGTGACACAC",
"IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII",
- -1, null, null, -1, false, false},
+ -1, null, null, -1, false, false, false},
// primary and secondary alignments
{"SRR833251", 81, 393, "SRR833251.R.51",
"ATGCAAATCCGAATGGGCTATTTGTGGGTACTTGGGCAGGTAAGTAGCTGGCAATCTTGGTCGGTAAACCAATACCCAAGTTCACATAGGCACCATCGGGA",
"CCCFFFFFHHHHHIJJJIJJJJJIIJJJGIJIJIIJIJJJDGIGIIJIJIHIJJJJJJGIGHIHEDFFFFDDEEEDDDDDCDEEDDDDDDDDDDDDDBBDB",
- 1787186, "38M63S", "gi|169794206|ref|NC_010410.1|", 11, true, true},
+ 1787186, "38M63S", "gi|169794206|ref|NC_010410.1|", 11, true, true, true},
// local SRA file
{"src/test/resources/htsjdk/samtools/sra/test_archive.sra", 1, 99, "test_archive.R.2",
"TGTCGATGCTGAAAGTGTCTGCGGTGAACCACTTCATGCACAGCGCACACTGCAGCTCCACTTCACCCAGCTGACGGCCGTTCTCATCGTCTCCAGAGCCCGTCTGAGCGTCCGCTGCTTCAGAACTGTCCCCGGCTGTATCCTGAAGAC",
"BBAABBBFAFFFGGGGGGGGGGGGEEFHHHHGHHHHHFHHGHFDGGGGGHHGHHHHHHHHHHHHFHHHGHHHHHHGGGGGGGHGGHHHHHHHHHGHHHHHGGGGHGHHHGGGGGGGGGHHHHEHHHHHHHHHHGCGGGHHHHHHGBFFGF",
- 2811570, "150M", "NC_007121.5", 60, true, false}
+ 2811570, "150M", "NC_007121.5", 60, true, false, false}
};
}
@Test(dataProvider = "testRows")
public void testRows(String acc, int recordIndex, int flags, String readName, String bases, String quals, int refStart, String cigar,
- String refName, int mapQ, boolean hasMate, boolean isSecondaryAlignment) {
+ String refName, int mapQ, boolean hasMate, boolean isSecondOfPair, boolean isSecondaryAlignment) {
SAMRecord record = getRecordByIndex(acc, recordIndex, false);
- checkSAMRecord(record, flags, readName, bases, quals, refStart, cigar, refName, mapQ, hasMate, isSecondaryAlignment);
+ checkSAMRecord(record, flags, readName, bases, quals, refStart, cigar, refName, mapQ, hasMate, isSecondOfPair, isSecondaryAlignment);
}
@Test(dataProvider = "testRows")
public void testRowsAfterIteratorDetach(String acc, int recordIndex, int flags, String readName, String bases, String quals,
int refStart, String cigar, String refName, int mapQ, boolean hasMate,
- boolean isSecondaryAlignment) {
+ boolean isSecondOfPair, boolean isSecondaryAlignment) {
SAMRecord record = getRecordByIndex(acc, recordIndex, true);
- checkSAMRecord(record, flags, readName, bases, quals, refStart, cigar, refName, mapQ, hasMate, isSecondaryAlignment);
+ checkSAMRecord(record, flags, readName, bases, quals, refStart, cigar, refName, mapQ, hasMate, isSecondOfPair, isSecondaryAlignment);
}
@Test(dataProvider = "testRows")
public void testRowsOverrideValues(String acc, int recordIndex, int flags, String readName, String bases, String quals,
int refStart, String cigar, String refName, int mapQ, boolean hasMate,
- boolean isSecondaryAlignment) {
+ boolean isSecondOfPair, boolean isSecondaryAlignment) {
SAMRecord record = getRecordByIndex(acc, recordIndex, true);
SAMFileHeader header = record.getHeader();
-
record.setFlags(0);
record.setReadUnmappedFlag(refStart == -1);
record.setReadBases("C".getBytes());
record.setBaseQualities(SAMUtils.fastqToPhred("A"));
if (refStart == -1) {
- checkSAMRecord(record, 4, readName, "C", "A", refStart, "1M", refName, mapQ, false, false);
+ checkSAMRecord(record, 4, readName, "C", "A", refStart, "1M", refName, mapQ, false, false, false);
} else {
int sequenceIndex = header.getSequenceIndex(refName);
Assert.assertFalse(sequenceIndex == -1);
@@ -288,14 +284,14 @@ public class SRATest extends AbstractSRATest {
record.setMappingQuality(mapQ - 1);
record.setReferenceIndex(sequenceIndex);
- checkSAMRecord(record, 0, readName, "C", "A", refStart - 100, "1M", refName, mapQ - 1, false, false);
+ checkSAMRecord(record, 0, readName, "C", "A", refStart - 100, "1M", refName, mapQ - 1, false, false, false);
}
}
@Test(dataProvider = "testRows")
public void testRowsBySpan(String acc, int recordIndex, int flags, String readName, String bases, String quals,
int refStart, String cigar, String refName, int mapQ, boolean hasMate,
- boolean isSecondaryAlignment) {
+ boolean isSecondOfPair, boolean isSecondaryAlignment) {
SamReader reader = SamReaderFactory.make().validationStringency(ValidationStringency.SILENT).open(
SamInputResource.of(new SRAAccession(acc))
);
@@ -330,13 +326,13 @@ public class SRATest extends AbstractSRATest {
}
}
- checkSAMRecord(record, flags, readName, bases, quals, refStart, cigar, refName, mapQ, hasMate, isSecondaryAlignment);
+ checkSAMRecord(record, flags, readName, bases, quals, refStart, cigar, refName, mapQ, hasMate, isSecondOfPair, isSecondaryAlignment);
}
@Test(dataProvider = "testRows")
public void testRowsByIndex(String acc, int recordIndex, int flags, String readName, String bases, String quals,
int refStart, String cigar, String refName, int mapQ, boolean hasMate,
- boolean isSecondaryAlignment) {
+ boolean isSecondOfPair, boolean isSecondaryAlignment) {
SamReader reader = SamReaderFactory.make().validationStringency(ValidationStringency.SILENT).open(
SamInputResource.of(new SRAAccession(acc))
);
@@ -366,13 +362,15 @@ public class SRATest extends AbstractSRATest {
continue;
}
- if (currentRecord.getReadName().equals(readName)) {
+ if (currentRecord.getReadName().equals(readName)
+ && currentRecord.getNotPrimaryAlignmentFlag() == isSecondaryAlignment
+ && (!hasMate || currentRecord.getSecondOfPairFlag() == isSecondOfPair)) {
record = currentRecord;
break;
}
}
- checkSAMRecord(record, flags, readName, bases, quals, refStart, cigar, refName, mapQ, hasMate, isSecondaryAlignment);
+ checkSAMRecord(record, flags, readName, bases, quals, refStart, cigar, refName, mapQ, hasMate, isSecondOfPair, isSecondaryAlignment);
}
private SAMRecord getRecordByIndex(String acc, int recordIndex, boolean detach) {
@@ -401,7 +399,7 @@ public class SRATest extends AbstractSRATest {
private void checkSAMRecord(SAMRecord record, int flags, String readName, String bases, String quals,
int refStart, String cigar, String refName, int mapQ, boolean hasMate,
- boolean isSecondaryAlignment) {
+ boolean isSecondOfPair, boolean isSecondaryAlignment) {
Assert.assertNotNull(record, "Record with read id: " + readName + " was not found by span created from index");
@@ -409,11 +407,15 @@ public class SRATest extends AbstractSRATest {
Assert.assertNull(validationErrors, "SRA Lazy record is invalid. List of errors: " +
(validationErrors != null ? validationErrors.toString() : ""));
+ Assert.assertEquals(record.getReadName(), readName);
Assert.assertEquals(new String(record.getReadBases()), bases);
Assert.assertEquals(record.getBaseQualityString(), quals);
Assert.assertEquals(record.getReadPairedFlag(), hasMate);
Assert.assertEquals(record.getFlags(), flags);
Assert.assertEquals(record.getNotPrimaryAlignmentFlag(), isSecondaryAlignment);
+ if (hasMate) {
+ Assert.assertEquals(record.getSecondOfPairFlag(), isSecondOfPair);
+ }
if (refStart == -1) {
Assert.assertEquals(record.getReadUnmappedFlag(), true);
Assert.assertEquals(record.getAlignmentStart(), 0);
diff --git a/src/test/java/htsjdk/samtools/util/AsyncWriterTest.java b/src/test/java/htsjdk/samtools/util/AsyncWriterTest.java
new file mode 100644
index 0000000..c807cef
--- /dev/null
+++ b/src/test/java/htsjdk/samtools/util/AsyncWriterTest.java
@@ -0,0 +1,77 @@
+/*
+ * The MIT License
+ *
+ * Copyright (c) 2016 Len Trigg
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package htsjdk.samtools.util;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class AsyncWriterTest {
+ private static class MyException extends RuntimeException {
+ final Integer item;
+ public MyException(Integer item) {
+ this.item = item;
+ }
+ }
+ private static class TestAsyncWriter extends AbstractAsyncWriter<Integer> {
+ protected TestAsyncWriter() {
+ super(1); // Queue size of 1 to give us more control over the order of events
+ }
+
+ @Override
+ protected String getThreadNamePrefix() {
+ return "TestAsyncWriter";
+ }
+
+ @Override
+ protected void synchronouslyWrite(Integer item) {
+ throw new MyException(item);
+ }
+
+ @Override
+ protected void synchronouslyClose() {
+ // Nothing
+ }
+ }
+ @Test
+ public void testNoSelfSuppression() {
+ try (TestAsyncWriter t = new TestAsyncWriter()) {
+ try {
+ t.write(1); // Will trigger exception in writing thread
+ t.write(2); // Will block if the above write has not been executed, but may not trigger checkAndRethrow()
+ t.write(3); // Will trigger checkAndRethrow() if not already done by the above write
+ Assert.fail("Expected exception");
+ } catch (MyException e) {
+ // Pre-bug fix, this was a "Self-suppression not permitted" exception from Java, rather than MyException
+ Assert.assertEquals(1, e.item.intValue());
+ }
+ // Verify that attempts to write after exception will fail
+ try {
+ t.write(4);
+ Assert.fail("Expected exception");
+ } catch (RuntimeIOException e) {
+ // Expected
+ }
+ }
+ }
+}
diff --git a/src/test/java/htsjdk/samtools/util/SamLocusIteratorTest.java b/src/test/java/htsjdk/samtools/util/SamLocusIteratorTest.java
index 092e6e5..17e77b2 100644
--- a/src/test/java/htsjdk/samtools/util/SamLocusIteratorTest.java
+++ b/src/test/java/htsjdk/samtools/util/SamLocusIteratorTest.java
@@ -86,6 +86,7 @@ public class SamLocusIteratorTest {
for (final SamLocusIterator.LocusInfo li : sli) {
Assert.assertEquals(li.getPosition(), pos++);
Assert.assertEquals(li.getRecordAndPositions().size(), coverage);
+ Assert.assertEquals(li.size(), coverage);
// make sure that we are not accumulating indels
Assert.assertEquals(li.getDeletedInRecord().size(), 0);
Assert.assertEquals(li.getInsertedInRecord().size(), 0);
@@ -108,10 +109,10 @@ public class SamLocusIteratorTest {
// make sure we accumulated depth of 2 for each position
int pos = 165;
for (final SamLocusIterator.LocusInfo li : sli) {
- Assert.assertEquals(pos++, li.getPosition());
- Assert.assertEquals(2, li.getRecordAndPositions().size());
+ Assert.assertEquals(li.getPosition(), pos++);
+ Assert.assertEquals(li.getRecordAndPositions().size(), 2);
+ Assert.assertEquals(li.size(), 2);
}
-
}
/**
@@ -146,6 +147,7 @@ public class SamLocusIteratorTest {
expectedReads = 0;
}
Assert.assertEquals(li.getRecordAndPositions().size(), expectedReads);
+ Assert.assertEquals(li.size(), expectedReads);
// make sure that we are not accumulating indels
Assert.assertEquals(li.getDeletedInRecord().size(), 0);
Assert.assertEquals(li.getInsertedInRecord().size(), 0);
@@ -183,6 +185,7 @@ public class SamLocusIteratorTest {
int pos = startPosition;
for (final SamLocusIterator.LocusInfo li : sli) {
Assert.assertEquals(li.getRecordAndPositions().size(), (pos % 2 == 0) ? coverage / 2 : coverage);
+ Assert.assertEquals(li.size(), (pos % 2 == 0) ? coverage / 2 : coverage);
Assert.assertEquals(li.getPosition(), pos++);
// make sure that we are not accumulating indels
Assert.assertEquals(li.getDeletedInRecord().size(), 0);
@@ -221,12 +224,16 @@ public class SamLocusIteratorTest {
if (isDeletedPosition) {
// make sure there are no reads without indels
Assert.assertEquals(li.getRecordAndPositions().size(), 0);
+ Assert.assertEquals(li.size(), coverage); // should include deletions
+
// make sure that we are accumulating indels
Assert.assertEquals(li.getDeletedInRecord().size(), coverage);
Assert.assertEquals(li.getInsertedInRecord().size(), 0);
} else {
// make sure we are accumulating normal coverage
Assert.assertEquals(li.getRecordAndPositions().size(), coverage);
+ Assert.assertEquals(li.size(), coverage);
+
// make sure that we are not accumulating indels
Assert.assertEquals(li.getDeletedInRecord().size(), 0);
Assert.assertEquals(li.getInsertedInRecord().size(), 0);
@@ -258,6 +265,8 @@ public class SamLocusIteratorTest {
Assert.assertEquals(li.getPosition(), pos++);
// make sure we are accumulating normal coverage
Assert.assertEquals(li.getRecordAndPositions().size(), coverage);
+ Assert.assertEquals(li.size(), coverage);
+
// make sure that we are not accumulating deletions
Assert.assertEquals(li.getDeletedInRecord().size(), 0);
if (incIndels && li.getPosition() == insStart) {
@@ -293,6 +302,8 @@ public class SamLocusIteratorTest {
Assert.assertEquals(li.getPosition(), pos);
// accumulation of coverage
Assert.assertEquals(li.getRecordAndPositions().size(), (indelPosition) ? 0 : coverage);
+ Assert.assertEquals(li.size(), (indelPosition) ? 0 : coverage);
+
// no accumulation of deletions
Assert.assertEquals(li.getDeletedInRecord().size(), 0);
// accumulation of insertion
@@ -332,6 +343,7 @@ public class SamLocusIteratorTest {
Assert.assertEquals(li.getPosition(), pos);
// accumulation of coverage
Assert.assertEquals(li.getRecordAndPositions().size(), (indelPosition) ? 0 : coverage);
+ Assert.assertEquals(li.size(), (indelPosition) ? 0 : coverage);
// no accumulation of deletions
Assert.assertEquals(li.getDeletedInRecord().size(), 0);
// accumulation of insertion
@@ -376,6 +388,7 @@ public class SamLocusIteratorTest {
Assert.assertEquals(li.getPosition(), pos);
// accumulation of coverage
Assert.assertEquals(li.getRecordAndPositions().size(), (pos == endN) ? 0 : coverage);
+ Assert.assertEquals(li.size(), (pos == endN) ? 0 : coverage);
// no accumulation of deletions
Assert.assertEquals(li.getDeletedInRecord().size(), 0);
// accumulation of insertion
@@ -427,6 +440,7 @@ public class SamLocusIteratorTest {
Assert.assertEquals(li.getPosition(), pos);
// accumulation of coverage
Assert.assertEquals(li.getRecordAndPositions().size(), (insideDeletion) ? 0 : coverage);
+ Assert.assertEquals(li.size(), coverage); // either will be all deletions, or all non-deletions, but always of size `coverage`.
// accumulation of deletions
Assert.assertEquals(li.getDeletedInRecord().size(), (insideDeletion) ? coverage : 0);
// no accumulation of insertion
@@ -515,12 +529,14 @@ public class SamLocusIteratorTest {
// check the coverage for insertion and normal records
Assert.assertEquals(li.getDeletedInRecord().size(), coverage);
Assert.assertEquals(li.getRecordAndPositions().size(), 0);
+ Assert.assertEquals(li.size(), coverage); // includes deletions
// check the offset for the deletion
Assert.assertEquals(li.getDeletedInRecord().get(0).getOffset(), expectedReadOffsets[i]);
Assert.assertEquals(li.getDeletedInRecord().get(1).getOffset(), expectedReadOffsets[i]);
} else {
// if it is not a deletion, perform the same test as before
Assert.assertEquals(li.getRecordAndPositions().size(), coverage);
+ Assert.assertEquals(li.size(), coverage);
// Assert.assertEquals(li.getDeletedInRecord().size(), 0);
Assert.assertEquals(li.getRecordAndPositions().get(0).getOffset(), expectedReadOffsets[i]);
Assert.assertEquals(li.getRecordAndPositions().get(1).getOffset(), expectedReadOffsets[i]);
@@ -582,6 +598,7 @@ public class SamLocusIteratorTest {
i = 0;
for (final SamLocusIterator.LocusInfo li : sli) {
Assert.assertEquals(li.getRecordAndPositions().size(), expectedDepths[i]);
+ Assert.assertEquals(li.size(), expectedDepths[i]);
Assert.assertEquals(li.getPosition(), expectedReferencePositions[i]);
Assert.assertEquals(li.getRecordAndPositions().size(), expectedReadOffsets[i].length);
for (int j = 0; j < expectedReadOffsets[i].length; ++j) {
@@ -657,6 +674,7 @@ public class SamLocusIteratorTest {
for (final SamLocusIterator.LocusInfo li : sli) {
// checking the same as without indels
Assert.assertEquals(li.getRecordAndPositions().size(), expectedDepths[i]);
+ Assert.assertEquals(li.size(), expectedDepths[i] + expectedDelDepths[i]); // include deletions
Assert.assertEquals(li.getPosition(), expectedReferencePositions[i]);
Assert.assertEquals(li.getRecordAndPositions().size(), expectedReadOffsets[i].length);
for (int j = 0; j < expectedReadOffsets[i].length; ++j) {
diff --git a/src/test/java/htsjdk/tribble/AbstractFeatureReaderTest.java b/src/test/java/htsjdk/tribble/AbstractFeatureReaderTest.java
index f266bc2..6d65e9d 100644
--- a/src/test/java/htsjdk/tribble/AbstractFeatureReaderTest.java
+++ b/src/test/java/htsjdk/tribble/AbstractFeatureReaderTest.java
@@ -1,5 +1,6 @@
package htsjdk.tribble;
+import htsjdk.samtools.util.TestUtil;
import htsjdk.tribble.bed.BEDCodec;
import htsjdk.tribble.bed.BEDFeature;
import htsjdk.tribble.readers.LineIterator;
@@ -23,7 +24,7 @@ import static org.testng.Assert.*;
*/
public class AbstractFeatureReaderTest {
- final static String HTTP_INDEXED_VCF_PATH = "http://www.broadinstitute.org/~picard/testdata/ex2.vcf";
+ final static String HTTP_INDEXED_VCF_PATH = TestUtil.BASE_URL_FOR_HTTP_TESTS + "ex2.vcf";
final static String LOCAL_MIRROR_HTTP_INDEXED_VCF_PATH = VariantBaseTest.variantTestDataRoot + "ex2.vcf";
/**
diff --git a/src/test/java/htsjdk/tribble/BinaryFeaturesTest.java b/src/test/java/htsjdk/tribble/BinaryFeaturesTest.java
index 9466097..eff8939 100644
--- a/src/test/java/htsjdk/tribble/BinaryFeaturesTest.java
+++ b/src/test/java/htsjdk/tribble/BinaryFeaturesTest.java
@@ -54,4 +54,9 @@ public class BinaryFeaturesTest {
originalReader.close();
binaryReader.close();
}
+
+ @Test(expectedExceptions = TribbleException.class)
+ public void testGetTabixFormatThrowsException() {
+ new ExampleBinaryCodec().getTabixFormat();
+ }
}
diff --git a/src/test/java/htsjdk/tribble/TribbleIndexFeatureReaderTest.java b/src/test/java/htsjdk/tribble/TribbleIndexFeatureReaderTest.java
index 76bd410..afdd827 100644
--- a/src/test/java/htsjdk/tribble/TribbleIndexFeatureReaderTest.java
+++ b/src/test/java/htsjdk/tribble/TribbleIndexFeatureReaderTest.java
@@ -64,7 +64,9 @@ public class TribbleIndexFeatureReaderTest {
public Object[][] createFeatureFileStrings() {
return new Object[][]{
{TestUtils.DATA_DIR + "test.vcf", 5},
- {TestUtils.DATA_DIR + "test.vcf.gz", 5}
+ {TestUtils.DATA_DIR + "test.vcf.gz", 5},
+ {TestUtils.DATA_DIR + "test.vcf.bgz", 5},
+ {TestUtils.DATA_DIR + "test with spaces.vcf", 5}
};
}
diff --git a/src/test/java/htsjdk/tribble/bed/BEDCodecTest.java b/src/test/java/htsjdk/tribble/bed/BEDCodecTest.java
index 581466f..c7b2193 100644
--- a/src/test/java/htsjdk/tribble/bed/BEDCodecTest.java
+++ b/src/test/java/htsjdk/tribble/bed/BEDCodecTest.java
@@ -31,6 +31,7 @@ import htsjdk.tribble.annotation.Strand;
import htsjdk.tribble.bed.FullBEDFeature.Exon;
import htsjdk.tribble.index.IndexFactory;
import htsjdk.tribble.index.linear.LinearIndex;
+import htsjdk.tribble.index.tabix.TabixFormat;
import htsjdk.tribble.util.LittleEndianOutputStream;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -219,6 +220,10 @@ public class BEDCodecTest {
stream.close();
}
}
+ }
+ @Test
+ public void testGetTabixFormat() {
+ Assert.assertEquals(new BEDCodec().getTabixFormat(), TabixFormat.BED);
}
}
diff --git a/src/test/java/htsjdk/tribble/readers/TabixReaderTest.java b/src/test/java/htsjdk/tribble/readers/TabixReaderTest.java
index 832cf4d..d7b36df 100644
--- a/src/test/java/htsjdk/tribble/readers/TabixReaderTest.java
+++ b/src/test/java/htsjdk/tribble/readers/TabixReaderTest.java
@@ -1,6 +1,7 @@
package htsjdk.tribble.readers;
+import htsjdk.samtools.util.TestUtil;
import htsjdk.tribble.TestUtils;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -142,7 +143,7 @@ public class TabixReaderTest {
*/
@Test
public void testRemoteQuery() throws IOException {
- String tabixFile = "http://www.broadinstitute.org/~picard/testdata/igvdata/tabix/trioDup.vcf.gz";
+ String tabixFile = TestUtil.BASE_URL_FOR_HTTP_TESTS +"igvdata/tabix/trioDup.vcf.gz";
TabixReader tabixReader = new TabixReader(tabixFile);
diff --git a/src/test/java/htsjdk/variant/variantcontext/GenotypeBuilderTest.java b/src/test/java/htsjdk/variant/variantcontext/GenotypeBuilderTest.java
new file mode 100644
index 0000000..5e3f0b9
--- /dev/null
+++ b/src/test/java/htsjdk/variant/variantcontext/GenotypeBuilderTest.java
@@ -0,0 +1,75 @@
+/*
+* Copyright (c) 2016 The Broad Institute
+*
+* Permission is hereby granted, free of charge, to any person
+* obtaining a copy of this software and associated documentation
+* files (the "Software"), to deal in the Software without
+* restriction, including without limitation the rights to use,
+* copy, modify, merge, publish, distribute, sublicense, and/or sell
+* copies of the Software, and to permit persons to whom the
+* Software is furnished to do so, subject to the following
+* conditions:
+*
+* The above copyright notice and this permission notice shall be
+* included in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
+* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+package htsjdk.variant.variantcontext;
+
+import htsjdk.variant.VariantBaseTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class GenotypeBuilderTest extends VariantBaseTest {
+
+ @Test
+ public void testMakeWithShallowCopy() {
+ final GenotypeBuilder gb = new GenotypeBuilder("test");
+ final List<Allele> alleles = new ArrayList<>(
+ Arrays.asList(Allele.create("A", true), Allele.create("T")));
+ final int[] ad = new int[]{1,5};
+ final int[] pl = new int[]{1,6};
+ final int[] first = new int[]{1, 2};
+ final int[] second = new int[]{3, 4};
+ final Genotype firstG = gb.alleles(alleles).attribute("first", first).makeWithShallowCopy();
+ final Genotype secondG = gb.AD(ad).PL(pl).attribute("second", second).makeWithShallowCopy();
+ // both genotypes have the first field
+ Assert.assertEquals(first, firstG.getExtendedAttribute("first"));
+ Assert.assertEquals(first, secondG.getExtendedAttribute("first"));
+ // both genotypes have the the alleles
+ Assert.assertEquals(alleles, firstG.getAlleles());
+ Assert.assertEquals(alleles, secondG.getAlleles());
+ // only the second genotype should have the AD field
+ Assert.assertNull(firstG.getAD());
+ Assert.assertEquals(ad, secondG.getAD());
+ // only the second genotype should have the PL field
+ Assert.assertNull(firstG.getPL());
+ Assert.assertEquals(pl, secondG.getPL());
+ // only the second genotype should have the second field
+ Assert.assertNull(firstG.getExtendedAttribute("second"));
+ Assert.assertEquals(second, secondG.getExtendedAttribute("second"));
+ // modification of alleles does not change the genotypes
+ alleles.add(Allele.create("C"));
+ Assert.assertNotEquals(alleles, firstG.getAlleles());
+ Assert.assertNotEquals(alleles, secondG.getAlleles());
+ // modification of ad or pl does not change the genotypes
+ ad[0] = 0;
+ pl[0] = 10;
+ Assert.assertNotEquals(ad, secondG.getAD());
+ Assert.assertNotEquals(pl, secondG.getPL());
+ }
+
+}
\ No newline at end of file
diff --git a/src/test/java/htsjdk/variant/variantcontext/GenotypeUnitTest.java b/src/test/java/htsjdk/variant/variantcontext/GenotypeUnitTest.java
index a698407..a447a0b 100644
--- a/src/test/java/htsjdk/variant/variantcontext/GenotypeUnitTest.java
+++ b/src/test/java/htsjdk/variant/variantcontext/GenotypeUnitTest.java
@@ -30,6 +30,7 @@ package htsjdk.variant.variantcontext;
import htsjdk.variant.VariantBaseTest;
+import htsjdk.variant.vcf.VCFConstants;
import org.testng.Assert;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
@@ -63,6 +64,9 @@ public class GenotypeUnitTest extends VariantBaseTest {
Assert.assertEquals(makeGB().filters("x", "y", "z").make().getFilters(), "x;y;z", "Multiple filter field values should be joined with ;");
Assert.assertTrue(makeGB().filters("x", "y", "z").make().isFiltered(), "Multiple filter values should be filtered");
Assert.assertEquals(makeGB().filter("x;y;z").make().getFilters(), "x;y;z", "Multiple filter field values should be joined with ;");
+ Assert.assertEquals(makeGB().filter("x;y;z").make().getAnyAttribute(VCFConstants.GENOTYPE_FILTER_KEY), "x;y;z", "getAnyAttribute(GENOTYPE_FILTER_KEY) should return the filter");
+ Assert.assertTrue(makeGB().filter("x;y;z").make().hasAnyAttribute(VCFConstants.GENOTYPE_FILTER_KEY), "hasAnyAttribute(GENOTYPE_FILTER_KEY) should return true");
+ Assert.assertTrue(makeGB().make().hasAnyAttribute(VCFConstants.GENOTYPE_FILTER_KEY), "hasAnyAttribute(GENOTYPE_FILTER_KEY) should return true");
Assert.assertFalse(makeGB().filter("").make().isFiltered(), "empty filters should count as unfiltered");
Assert.assertEquals(makeGB().filter("").make().getFilters(), null, "empty filter string should result in null filters");
}
diff --git a/src/test/java/htsjdk/variant/vcf/AbstractVCFCodecTest.java b/src/test/java/htsjdk/variant/vcf/AbstractVCFCodecTest.java
index 051c19b..9f81547 100644
--- a/src/test/java/htsjdk/variant/vcf/AbstractVCFCodecTest.java
+++ b/src/test/java/htsjdk/variant/vcf/AbstractVCFCodecTest.java
@@ -1,6 +1,7 @@
package htsjdk.variant.vcf;
import htsjdk.tribble.TribbleException;
+import htsjdk.tribble.index.tabix.TabixFormat;
import htsjdk.variant.VariantBaseTest;
import htsjdk.variant.variantcontext.Allele;
import htsjdk.variant.variantcontext.VariantContext;
@@ -14,6 +15,7 @@ import java.util.List;
public class AbstractVCFCodecTest extends VariantBaseTest {
+
@Test
public void shouldPreserveSymbolicAlleleCase() {
VCFFileReader reader = new VCFFileReader(new File(VariantBaseTest.variantTestDataRoot + "breakpoint.vcf"), false);
@@ -50,4 +52,9 @@ public class AbstractVCFCodecTest extends VariantBaseTest {
Assert.assertEquals(AbstractVCFCodec.canDecodeFile(potentialInput, VCFCodec.VCF4_MAGIC_HEADER), canDecode);
}
+ @Test
+ public void testGetTabixFormat() {
+ Assert.assertEquals(new VCFCodec().getTabixFormat(), TabixFormat.VCF);
+ Assert.assertEquals(new VCF3Codec().getTabixFormat(), TabixFormat.VCF);
+ }
}
diff --git a/src/test/java/htsjdk/variant/vcf/VCFStandardHeaderLinesUnitTest.java b/src/test/java/htsjdk/variant/vcf/VCFStandardHeaderLinesUnitTest.java
index 5a8ce6e..f72cd87 100644
--- a/src/test/java/htsjdk/variant/vcf/VCFStandardHeaderLinesUnitTest.java
+++ b/src/test/java/htsjdk/variant/vcf/VCFStandardHeaderLinesUnitTest.java
@@ -53,6 +53,10 @@ public class VCFStandardHeaderLinesUnitTest extends VariantBaseTest {
tests.add(new Object[]{"DP", "info", true});
tests.add(new Object[]{"DB", "info", true});
tests.add(new Object[]{"END", "info", true});
+ tests.add(new Object[]{"SB", "info", true});
+ tests.add(new Object[]{"MQ", "info", true});
+ tests.add(new Object[]{"MQ0", "info", true});
+ tests.add(new Object[]{"SOMATIC", "info", true});
// format
tests.add(new Object[]{"GT", "format", true});
@@ -60,6 +64,8 @@ public class VCFStandardHeaderLinesUnitTest extends VariantBaseTest {
tests.add(new Object[]{"DP", "format", true});
tests.add(new Object[]{"AD", "format", true});
tests.add(new Object[]{"PL", "format", true});
+ tests.add(new Object[]{"FT", "format", true});
+ tests.add(new Object[]{"PQ", "format", true});
tests.add(new Object[]{"NOT_STANDARD", "info", false});
tests.add(new Object[]{"NOT_STANDARD", "format", false});
@@ -81,8 +87,51 @@ public class VCFStandardHeaderLinesUnitTest extends VariantBaseTest {
if ( expectedToBeStandard ) {
Assert.assertNotNull(line);
Assert.assertEquals(line.getID(), key);
- } else
+ Assert.assertTrue(deeperTest(line));
+ } else {
Assert.assertNull(line);
+ }
+ }
+
+ private boolean deeperTest(final VCFCompoundHeaderLine line){
+
+ final String id = line.getID();
+ if(id.equals(VCFConstants.GENOTYPE_KEY))
+ return line.getType().equals(VCFHeaderLineType.String) && line.getCount()==1 ;
+ else if(id.equals(VCFConstants.GENOTYPE_QUALITY_KEY))
+ return line.getType().equals(VCFHeaderLineType.Integer) && line.getCount()==1;
+ else if(id.equals(VCFConstants.DEPTH_KEY))
+ return line.getType().equals(VCFHeaderLineType.Integer) && line.getCount()==1;
+ else if(id.equals(VCFConstants.GENOTYPE_PL_KEY))
+ return line.getType().equals(VCFHeaderLineType.Integer) && line.getCountType().equals(VCFHeaderLineCount.G);
+ else if(id.equals(VCFConstants.GENOTYPE_ALLELE_DEPTHS))
+ return line.getType().equals(VCFHeaderLineType.Integer) && line.getCountType().equals(VCFHeaderLineCount.R);
+ else if(id.equals(VCFConstants.GENOTYPE_FILTER_KEY))
+ return line.getType().equals(VCFHeaderLineType.String) && line.getCountType().equals(VCFHeaderLineCount.UNBOUNDED);
+ else if(id.equals(VCFConstants.PHASE_QUALITY_KEY))
+ return line.getType().equals(VCFHeaderLineType.Float) && line.getCount()==1;
+ else if(id.equals(VCFConstants.END_KEY))
+ return line.getType().equals(VCFHeaderLineType.Integer) && line.getCount()==1;
+ else if(id.equals(VCFConstants.DBSNP_KEY))
+ return line.getType().equals(VCFHeaderLineType.Flag) && line.getCount()==0;
+ else if(id.equals(VCFConstants.DEPTH_KEY))
+ return line.getType().equals(VCFHeaderLineType.Integer) && line.getCount()==1;
+ else if(id.equals(VCFConstants.STRAND_BIAS_KEY))
+ return line.getType().equals(VCFHeaderLineType.Float) && line.getCount()==1;
+ else if(id.equals(VCFConstants.ALLELE_FREQUENCY_KEY))
+ return line.getType().equals(VCFHeaderLineType.Float) && line.getCountType().equals(VCFHeaderLineCount.A);
+ else if(id.equals(VCFConstants.ALLELE_COUNT_KEY))
+ return line.getType().equals(VCFHeaderLineType.Integer) && line.getCountType().equals(VCFHeaderLineCount.A);
+ else if(id.equals(VCFConstants.ALLELE_NUMBER_KEY))
+ return line.getType().equals(VCFHeaderLineType.Integer) && line.getCount()==1;
+ else if(id.equals(VCFConstants.MAPPING_QUALITY_ZERO_KEY))
+ return line.getType().equals(VCFHeaderLineType.Integer) && line.getCount()==1;
+ else if(id.equals(VCFConstants.RMS_MAPPING_QUALITY_KEY))
+ return line.getType().equals(VCFHeaderLineType.Float) && line.getCount()==1;
+ else if(id.equals(VCFConstants.SOMATIC_KEY))
+ return line.getType().equals(VCFHeaderLineType.Flag) && line.getCount()==0;
+ else
+ throw new IllegalArgumentException("Unexpected id : " + id);
}
private class RepairHeaderTest {
@@ -137,7 +186,7 @@ public class VCFStandardHeaderLinesUnitTest extends VariantBaseTest {
}
@Test(dataProvider = "RepairHeaderTest")
- public void testRepairHeaderTest(RepairHeaderTest cfg) {
+ public void testRepairHeaderTest(final RepairHeaderTest cfg) {
final VCFHeader toRepair = new VCFHeader(Collections.singleton((VCFHeaderLine)cfg.original));
final VCFHeader repaired = VCFStandardHeaderLines.repairStandardHeaderLines(toRepair);
@@ -148,7 +197,8 @@ public class VCFStandardHeaderLinesUnitTest extends VariantBaseTest {
Assert.assertEquals(repairedLine.getID(), cfg.expectedResult.getID());
Assert.assertEquals(repairedLine.getType(), cfg.expectedResult.getType());
Assert.assertEquals(repairedLine.getCountType(), cfg.expectedResult.getCountType());
- if ( repairedLine.getCountType() == VCFHeaderLineCount.INTEGER )
+ if ( repairedLine.getCountType() == VCFHeaderLineCount.INTEGER ) {
Assert.assertEquals(repairedLine.getCount(), cfg.expectedResult.getCount());
+ }
}
}
diff --git a/src/test/resources/htsjdk/samtools/cram/auxf.alteredForMD5test.fa b/src/test/resources/htsjdk/samtools/cram/auxf.alteredForMD5test.fa
new file mode 100644
index 0000000..1089240
--- /dev/null
+++ b/src/test/resources/htsjdk/samtools/cram/auxf.alteredForMD5test.fa
@@ -0,0 +1,2 @@
+>Sheila
+CTAGCTCAGAAAAAAAAAA
diff --git a/src/test/resources/htsjdk/samtools/cram/auxf.alteredForMD5test.fa.fai b/src/test/resources/htsjdk/samtools/cram/auxf.alteredForMD5test.fa.fai
new file mode 100644
index 0000000..5709288
--- /dev/null
+++ b/src/test/resources/htsjdk/samtools/cram/auxf.alteredForMD5test.fa.fai
@@ -0,0 +1 @@
+Sheila 19 8 19 20
diff --git a/src/test/resources/htsjdk/samtools/cram/auxf.fasta b/src/test/resources/htsjdk/samtools/cram/auxf.fasta
deleted file mode 100644
index 11d25dd..0000000
--- a/src/test/resources/htsjdk/samtools/cram/auxf.fasta
+++ /dev/null
@@ -1,2 +0,0 @@
->Sheila
-GCTAGCTCAGAAAAAAAAAA
diff --git a/src/test/resources/htsjdk/samtools/cram/test.fasta b/src/test/resources/htsjdk/samtools/cram/test.fasta
deleted file mode 100644
index 11d25dd..0000000
--- a/src/test/resources/htsjdk/samtools/cram/test.fasta
+++ /dev/null
@@ -1,2 +0,0 @@
->Sheila
-GCTAGCTCAGAAAAAAAAAA
diff --git a/src/test/resources/htsjdk/samtools/cram/test2.fasta b/src/test/resources/htsjdk/samtools/cram/test2.fasta
deleted file mode 100644
index 11d25dd..0000000
--- a/src/test/resources/htsjdk/samtools/cram/test2.fasta
+++ /dev/null
@@ -1,2 +0,0 @@
->Sheila
-GCTAGCTCAGAAAAAAAAAA
diff --git a/src/test/resources/htsjdk/tribble/test with spaces.vcf b/src/test/resources/htsjdk/tribble/test with spaces.vcf
new file mode 100644
index 0000000..27d4500
--- /dev/null
+++ b/src/test/resources/htsjdk/tribble/test with spaces.vcf
@@ -0,0 +1,24 @@
+##fileformat=VCFv4.1
+##fileDate=20090805
+##source=myImputationProgramV3.1
+##reference=file:///seq/references/1000GenomesPilot-NCBI36.fasta
+##contig=<ID=20,length=62435964,assembly=B36,md5=f126cdf8a6e0c7f379d618ff66beb2da,species="Homo sapiens",taxonomy=x>
+##phasing=partial
+##INFO=<ID=NS,Number=1,Type=Integer,Description="Number of Samples With Data">
+##INFO=<ID=DP,Number=1,Type=Integer,Description="Total Depth">
+##INFO=<ID=AF,Number=A,Type=Float,Description="Allele Frequency">
+##INFO=<ID=AA,Number=1,Type=String,Description="Ancestral Allele">
+##INFO=<ID=DB,Number=0,Type=Flag,Description="dbSNP membership, build 129">
+##INFO=<ID=H2,Number=0,Type=Flag,Description="HapMap2 membership">
+##FILTER=<ID=q10,Description="Quality below 10">
+##FILTER=<ID=s50,Description="Less than 50% of samples have data">
+##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
+##FORMAT=<ID=GQ,Number=1,Type=Integer,Description="Genotype Quality">
+##FORMAT=<ID=DP,Number=1,Type=Integer,Description="Read Depth">
+##FORMAT=<ID=HQ,Number=2,Type=Integer,Description="Haplotype Quality">
+#CHROM POS ID REF ALT QUAL FILTER INFO FORMAT NA00001 NA00002 NA00003
+20 14370 rs6054257 G A 29 PASS NS=3;DP=14;AF=0.5;DB;H2 GT:GQ:DP:HQ 0|0:48:1:51,51 1|0:48:8:51,51 1/1:43:5:.,.
+20 17330 . T A 3 q10 NS=3;DP=11;AF=0.017 GT:GQ:DP:HQ 0|0:49:3:58,50 0|1:3:5:65,3 0/0:41:3
+20 1110696 rs6040355 A G,T 67 PASS NS=2;DP=10;AF=0.333,0.667;AA=T;DB GT:GQ:DP:HQ 1|2:21:6:23,27 2|1:2:0:18,2 2/2:35:4
+20 1230237 . T . 47 PASS NS=3;DP=13;AA=T GT:GQ:DP:HQ 0|0:54:7:56,60 0|0:48:4:51,51 0/0:61:2
+20 1234567 microsat1 GTC G,GTCT 50 PASS NS=3;DP=9;AA=G GT:GQ:DP 0/1:35:4 0/2:17:2 1/1:40:3
diff --git a/src/test/resources/htsjdk/tribble/test.vcf.bgz b/src/test/resources/htsjdk/tribble/test.vcf.bgz
new file mode 100644
index 0000000..44072dc
Binary files /dev/null and b/src/test/resources/htsjdk/tribble/test.vcf.bgz differ
diff --git a/src/test/resources/htsjdk/variant/ex2.bgzf.bcf b/src/test/resources/htsjdk/variant/ex2.bgzf.bcf
deleted file mode 100755
index eaa40af..0000000
Binary files a/src/test/resources/htsjdk/variant/ex2.bgzf.bcf and /dev/null differ
diff --git a/src/test/resources/htsjdk/variant/ex2.uncompressed.bcf b/src/test/resources/htsjdk/variant/ex2.uncompressed.bcf
deleted file mode 100755
index d0e41aa..0000000
Binary files a/src/test/resources/htsjdk/variant/ex2.uncompressed.bcf and /dev/null differ
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/htsjdk.git
More information about the debian-med-commit
mailing list