JAL-1793 wrapper for plain or indexed VCF + simple tests
[jalview.git] / src / jalview / ext / htsjdk / VCFReader.java
diff --git a/src/jalview/ext/htsjdk/VCFReader.java b/src/jalview/ext/htsjdk/VCFReader.java
new file mode 100644 (file)
index 0000000..8dfd7e2
--- /dev/null
@@ -0,0 +1,90 @@
+package jalview.ext.htsjdk;
+
+import htsjdk.samtools.util.CloseableIterator;
+import htsjdk.variant.variantcontext.VariantContext;
+import htsjdk.variant.vcf.VCFFileReader;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * A thin wrapper for htsjdk classes to read either plain, or compressed, or
+ * compressed and indexed VCF files
+ */
+public class VCFReader implements Closeable, Iterable<VariantContext>
+{
+  private static final String GZ = "gz";
+
+  private static final String TBI_EXTENSION = ".tbi";
+
+  private boolean indexed;
+
+  private VCFFileReader reader;
+
+  /**
+   * Constructor given a raw or compressed VCF file or a (tabix) index file
+   * <p>
+   * For now, file type is inferred from its suffix: .gz or .bgz for compressed
+   * data, .tbi for an index file, anything else is assumed to be plain text
+   * VCF.
+   * 
+   * @param f
+   * @throws IOException
+   */
+  public VCFReader(String filePath) throws IOException
+  {
+    if (filePath.endsWith(GZ))
+    {
+      if (new File(filePath + TBI_EXTENSION).exists())
+      {
+        indexed = true;
+      }
+    }
+    else if (filePath.endsWith(TBI_EXTENSION))
+    {
+      indexed = true;
+      filePath = filePath.substring(0, filePath.length() - 4);
+    }
+
+    reader = new VCFFileReader(new File(filePath), indexed);
+  }
+
+  @Override
+  public void close() throws IOException
+  {
+    if (reader != null)
+    {
+      reader.close();
+    }
+  }
+
+  /**
+   * Returns an iterator over VCF variants in the file. The client should call
+   * close() on the iterator when finished with it.
+   */
+  @Override
+  public CloseableIterator<VariantContext> iterator()
+  {
+    return reader == null ? null : reader.iterator();
+  }
+
+  /**
+   * Queries for records overlapping the region specified. Note that this method
+   * requires a VCF file with an associated index. If no index exists a
+   * TribbleException will be thrown.
+   * 
+   * @param chrom
+   *          the chromosome to query
+   * @param start
+   *          query interval start
+   * @param end
+   *          query interval end
+   * @return
+   */
+  public CloseableIterator<VariantContext> query(final String chrom,
+          final int start, final int end)
+  {
+    return reader == null ? null : reader.query(chrom, start, end);
+  }
+}