[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