Repository: chrovis/cljam
Pull request #212 (2020-10-15 09:48:01)

Add support for indexed? for vcf/bcf.
Since `indexed?` of vcf / bcf was not implemented, I added it.
The implementation is almost the same as the `indexed?` of fasta.


Patch:
diff --git a/src/cljam/io/bcf/reader.clj b/src/cljam/io/bcf/reader.clj
index 866233b..1d85996 100644
--- a/src/cljam/io/bcf/reader.clj
+++ b/src/cljam/io/bcf/reader.clj
@@ -10,7 +10,7 @@
             [cljam.util :as util]
             [cljam.io.util.bin :as util-bin]
             [cljam.io.csi :as csi])
-  (:import [java.io Closeable IOException]
+  (:import [java.io Closeable IOException FileNotFoundException]
            [java.net URL]
            [java.nio Buffer ByteBuffer]
            [bgzf4j BGZFInputStream]))
@@ -27,7 +27,12 @@
   (reader-url [this] (.url this))
   (read [this] (protocols/read this {}))
   (read [this option] (read-variants this option))
-  (indexed? [_] false)
+  (indexed? [_]
+    (try
+      @index-delay
+      true
+      (catch FileNotFoundException _
+        false)))
   protocols/IRegionReader
   (read-in-region [this region]
     (protocols/read-in-region this region {}))
diff --git a/src/cljam/io/vcf.clj b/src/cljam/io/vcf.clj
index 869feca..0bd9306 100644
--- a/src/cljam/io/vcf.clj
+++ b/src/cljam/io/vcf.clj
@@ -2,6 +2,7 @@
   "Functions to read and write the VCF (Variant Call Format) format and BCF (its
   binary equivalent). See https://samtools.github.io/hts-specs/ for the detail
   VCF/BCF specifications."
+  (:refer-clojure :exclude [indexed?])
   (:require [clojure.java.io :as cio]
             [cljam.util :as util]
             [cljam.io.protocols :as protocols]
@@ -97,6 +98,12 @@
   [rdr]
   (protocols/header rdr))
 
+(defn indexed?
+  "Returns true if the reader can be randomly accessed, false if not. Note this
+  function immediately realizes a delayed index."
+  [rdr]
+  (protocols/indexed? rdr))
+
 (defn read-variants
   "Reads variants of the VCF/BCF file, returning them as a lazy sequence. rdr
   must implement cljam.io.protocols/IVariantReader. Can take an option :depth to
diff --git a/src/cljam/io/vcf/reader.clj b/src/cljam/io/vcf/reader.clj
index 9047a65..bf5bc18 100644
--- a/src/cljam/io/vcf/reader.clj
+++ b/src/cljam/io/vcf/reader.clj
@@ -8,7 +8,7 @@
             [proton.core :refer [as-long]]
             [cljam.io.util.bin :as util-bin]
             [cljam.io.vcf.util :as vcf-util])
-  (:import [java.io Closeable BufferedReader]
+  (:import [java.io Closeable BufferedReader FileNotFoundException]
            [clojure.lang LazilyPersistentVector]
            bgzf4j.BGZFInputStream))
 
@@ -25,7 +25,12 @@
   (reader-url [this] (.url this))
   (read [this] (read-variants this))
   (read [this option] (read-variants this option))
-  (indexed? [_] false)
+  (indexed? [_]
+    (try
+      @index-delay
+      true
+      (catch FileNotFoundException _
+        false)))
   protocols/IRegionReader
   (read-in-region [this region]
     (protocols/read-in-region this region {}))


Test patch:
diff --git a/test/cljam/io/vcf_test.clj b/test/cljam/io/vcf_test.clj
index 202e043..dd78c4e 100644
--- a/test/cljam/io/vcf_test.clj
+++ b/test/cljam/io/vcf_test.clj
@@ -39,6 +39,7 @@
   (:import bgzf4j.BGZFException))
 
 (def ^:private temp-file (str temp-dir "/test.vcf"))
+(def ^:private temp-gz-file (str temp-dir "/test.vcf.gz"))
 (def ^:private temp-bcf-file (str temp-dir "/test.bcf"))
 
 (defn- slurp-vcf-for-test
@@ -120,6 +121,25 @@
   (with-open [r (vcf/bcf-reader test-bcf-v4_3-file)]
     (is (= (vcf/header r) test-vcf-v4_3-header))))
 
+(deftest indexed?-test
+  (testing "vcf"
+    (with-open [rdr (vcf/reader test-vcf-v4_0-file)]
+      (is (false? (vcf/indexed? rdr))))
+    (are [f] (with-open [rdr (vcf/reader f)]
+               (true? (vcf/indexed? rdr)))
+      test-vcf-complex-gz-file
+      test-vcf-chr-skipped-file)
+    (with-before-after {:before (do (prepare-cache!)
+                                    (cio/copy (cio/file test-vcf-complex-gz-file) (cio/file temp-gz-file)))
+                        :after (clean-cache!)}
+      (is (with-open [rdr (vcf/reader temp-gz-file)]
+            (false? (vcf/indexed? rdr))))))
+  (testing "bcf"
+    (with-open [rdr (vcf/reader test-bcf-v4_3-file)]
+      (is (false? (vcf/indexed? rdr))))
+    (with-open [rdr (vcf/reader test-bcf-complex-file)]
+      (is (true? (vcf/indexed? rdr))))))
+
 (deftest read-variants-vcf-test
   (testing "VCF v4.0"
     (with-open [rdr (vcf/reader test-vcf-v4_0-file)]