Repository: chrovis/cljam
Pull request #200 (2020-06-03 09:25:58)

Add support cloning VCF/BCF.
This PR adds a function to create a new object by copying except stream when VCF/BCF object is put in the reader.
This function is almost the same as "cljam.io.bam.core/clone-reader".



Patch:
diff --git a/src/cljam/io/vcf.clj b/src/cljam/io/vcf.clj
index a6490b5..869feca 100644
--- a/src/cljam/io/vcf.clj
+++ b/src/cljam/io/vcf.clj
@@ -46,16 +46,46 @@
   [f]
   (bcf-reader/reader f))
 
+(defn ^VCFReader clone-vcf-reader
+  "Clones vcf reader sharing persistent objects."
+  [^VCFReader rdr]
+  (let [url (.url rdr)
+        input-stream (if (bgzf/bgzip? url)
+                       (bgzf/bgzf-input-stream url)
+                       (cio/reader (util/compressor-input-stream url)))]
+    (VCFReader. url (.meta-info rdr) (.header rdr)
+                input-stream
+                (.index-delay rdr))))
+
+(defn ^BCFReader clone-bcf-reader
+  "Clones bcf reader sharing persistent objects."
+  [^BCFReader rdr]
+  (let [url (.url rdr)
+        input-stream (bgzf/bgzf-input-stream url)]
+    (BCFReader. (.url rdr) (.meta-info rdr) (.header rdr)
+                input-stream (.start-pos rdr) (.index-delay rdr))))
+
+(defn ^Closeable clone-reader
+  "Clones vcf/bcf reader sharing persistent objects."
+  [rdr]
+  (cond
+    (io-util/vcf-reader? rdr) (clone-vcf-reader rdr)
+    (io-util/bcf-reader? rdr) (clone-bcf-reader rdr)
+    :else (throw (IllegalArgumentException. "Invalid file type"))))
+
 (defn ^Closeable reader
   "Selects suitable reader from f's extension, returning the open reader. This
   function supports VCF and BCF formats."
   [f]
-  (case (try (io-util/file-type f)
-             (catch IllegalArgumentException _
-               (io-util/file-type-from-contents f)))
-    :vcf (vcf-reader f)
-    :bcf (bcf-reader f)
-    (throw (IllegalArgumentException. "Invalid file type"))))
+  (if (or (io-util/vcf-reader? f)
+          (io-util/bcf-reader? f))
+    (clone-reader f)
+    (case (try (io-util/file-type f)
+               (catch IllegalArgumentException _
+                 (io-util/file-type-from-contents f)))
+      :vcf (vcf-reader f)
+      :bcf (bcf-reader f)
+      (throw (IllegalArgumentException. "Invalid file type")))))
 
 (defn meta-info
   "Returns meta-info section of VCF/BCF file as a map."


Test patch:
diff --git a/test/cljam/io/vcf_test.clj b/test/cljam/io/vcf_test.clj
index 30be3f2..202e043 100644
--- a/test/cljam/io/vcf_test.clj
+++ b/test/cljam/io/vcf_test.clj
@@ -80,6 +80,17 @@
         (cio/copy (cio/file test-bcf-v4_3-file) tmp)
         (with-open [rdr (vcf/reader tmp)]
           (is (instance? cljam.io.bcf.reader.BCFReader rdr))))))
+  (testing "clone vcf"
+    (with-open [rdr (vcf/reader test-vcf-v4_3-file)
+                crdr (vcf/reader rdr)]
+      (is (instance? cljam.io.vcf.reader.VCFReader crdr)))
+    (with-open [rdr (vcf/reader test-vcf-complex-gz-file)
+                crdr (vcf/reader rdr)]
+      (is (instance? cljam.io.vcf.reader.VCFReader crdr))))
+  (testing "clone bcf"
+    (with-open [rdr (vcf/reader test-bcf-v4_3-file)
+                crdr (vcf/reader rdr)]
+      (is (instance? cljam.io.bcf.reader.BCFReader crdr))))
   (testing "throws Exception"
     (are [f] (thrown? Exception (vcf/reader f))
       "test-resources/vcf/not-found.vcf"