<commit_before>(ns cljam.io.vcf.writer
  "A type of VCF writer and internal functions to write VCF contents. See
  https://samtools.github.io/hts-specs/ for the detail VCF specifications."
  (:require [clojure.string :as cstr]
            [camel-snake-kebab.core :refer [->camelCaseString]]
            [cljam.io.protocols :as protocols]
            [cljam.io.vcf.util :as vcf-util])
  (:import [java.io Closeable BufferedWriter]))

(declare write-variants)

;; VCFWriter
;; ---------

(deftype VCFWriter [url writer meta-info header]
  Closeable
  (close [this]
    (.close ^Closeable (.writer this)))
  protocols/IWriter
  (writer-url [this] (.url this))
  protocols/IVariantWriter
  (write-variants [this variants]
    (write-variants this variants)))

;; Vars and utilities
;; ------------------

(def ^:private default-fileformat "VCFv4.3")

(def ^:private meta-info-prefix "##")
(def ^:private header-prefix "#")

(defn- nil->dot
  [s]
  (if (nil? s) "." s))

(defn- write-line
  [^BufferedWriter bwtr ^String s]
  (doto bwtr
    (.write s)
    (.newLine)))

;; Writing meta-information
;; ------------------------

(defn stringify-key
  [k]
  (if (#{:info :filter :format :alt :sample :pedigree} k)
    (cstr/upper-case (name k))
    (->camelCaseString k)))

(defn- stringify-meta-info-contig
  [m]
  (->> (cond-> [(str "ID=" (:id m))
                (str "length=" (:length m))
                (str "assembly=" (:assembly m))
                (str "md5=" (:md-5 m))]
         (:species m) (conj (str "species=\"" (:species m) "\""))
         (:taxonomy m) (conj (str "taxonomy=" (:taxonomy m)))
         (:idx m) (conj (str "idx=" (:idx m))))
       (cstr/join \,)))

(defn- stringify-meta-info-info
  [m]
  (->> (cond-> [(str "ID=" (:id m))
                (str "Number=" (nil->dot (:number m)))
                (str "Type=" (nil->dot (:type m)))
                (str "Description=\"" (:description m) "\"")]
         (:source m) (conj (str "Source=" (:source m)))
         (:version m) (conj (str "Version=" (:version m)))
         (:idx m) (conj (str "idx=" (:idx m))))
       (cstr/join \,)))

(defn- stringify-meta-info-filter
  [m]
  (->> (cond-> [(str "ID=" (:id m))
                (str "Description=\"" (:description m) "\"")]
         (:idx m) (conj (str "idx=" (:idx m))))
       (cstr/join \,)))

(defn- stringify-meta-info-format
  [m]
  (->> (cond-> [(str "ID=" (:id m))
                (str "Number=" (nil->dot (:number m)))
                (str "Type=" (nil->dot (:type m)))
                (str "Description=\"" (:description m) "\"")]
         (:idx m) (conj (str "idx=" (:idx m))))
       (cstr/join \,)))

(defn- stringify-meta-info-alt
  [m]
  (->> [(str "ID=" (:id m))
        (str "Description=\"" (:description m) "\"")]
       (cstr/join \,)))

(defn- stringify-meta-info-sample
  [m]
  (->> [(str "ID=" (:id m))
        (str "Genomes=" (:genomes m))
        (str "Mixture=" (:mixture m))
        (str "Description=\"" (:description m) "\"")]
       (cstr/join \,)))

(defn- stringify-meta-info-pedigree
  [m]
  (->> (range (count m))
       (map (fn [i]
              (str "Name_" i "=" (get m (keyword (str "name-" i))))))
       (cstr/join \,)))

(defn stringify-structured-line
  [k m]
  (let [f (case k
            :contig stringify-meta-info-contig
            :info stringify-meta-info-info<commit_msg>Write out extra fields for each meta info in VCF file<commit_after>(ns cljam.io.vcf.writer
  "A type of VCF writer and internal functions to write VCF contents. See
  https://samtools.github.io/hts-specs/ for the detail VCF specifications."
  (:require [clojure.string :as cstr]
            [camel-snake-kebab.core :refer [->camelCaseString]]
            [cljam.io.protocols :as protocols]
            [cljam.io.vcf.util :as vcf-util])
  (:import [java.io Closeable BufferedWriter]))

(declare write-variants)

;; VCFWriter
;; ---------

(deftype VCFWriter [url writer meta-info header]
  Closeable
  (close [this]
    (.close ^Closeable (.writer this)))
  protocols/IWriter
  (writer-url [this] (.url this))
  protocols/IVariantWriter
  (write-variants [this variants]
    (write-variants this variants)))

;; Vars and utilities
;; ------------------

(def ^:private default-fileformat "VCFv4.3")

(def ^:private meta-info-prefix "##")
(def ^:private header-prefix "#")

(defn- nil->dot
  [s]
  (if (nil? s) "." s))

(defn- write-line
  [^BufferedWriter bwtr ^String s]
  (doto bwtr
    (.write s)
    (.newLine)))

;; Writing meta-information
;; ------------------------

(defn stringify-key
  [k]
  (if (#{:info :filter :format :alt :sample :pedigree} k)
    (cstr/upper-case (name k))
    (->camelCaseString k)))

(defn- add-extra-fields
  [fields m required-keys]
  (reduce-kv (fn [fields k v]
               (conj fields (str (->camelCaseString k) "=\"" v "\"")))
             fields
             (apply dissoc m required-keys)))

(defn- pack-meta-info
  [fields m required-keys]
  (cstr/join \, (add-extra-fields fields m required-keys)))

(defn- stringify-meta-info-contig
  [m]
  (-> [(str "ID=" (:id m))
       (str "length=" (:length m))
       (str "assembly=" (:assembly m))
       (str "md5=" (:md-5 m))]
      (pack-meta-info m [:id :length :assembly :md-5])))

(defn- stringify-meta-info-info
  [m]
  (-> [(str "ID=" (:id m))
       (str "Number=" (nil->dot (:number m)))
       (str "Type=" (nil->dot (:type m)))
       (str "Description=\"" (:description m) "\"")]
      (cond->
        (:source m) (conj (str "Source=" (:source m)))
        (:version m) (conj (str "Version=" (:version m))))
      (pack-meta-info m [:id :number :type :description :source :version])))

(defn- stringify-meta-info-filter
  [m]
  (-> [(str "ID=" (:id m))
       (str "Description=\"" (:description m) "\"")]
      (pack-meta-info m [:id :description])))

(defn- stringify-meta-info-format
  [m]
  (-> [(str "ID=" (:id m))
       (str "Number=" (nil->dot (:number m)))
       (str "Type=" (nil->dot (:type m)))
       (str "Description=\"" (:description m) "\"")]
      (pack-meta-info m [:id :number :type :description])))

(defn- stringify-meta-info-alt
  [m]
  (-> [(str "ID=" (:id m))
       (str "Description=\"" (:description m) "\"")]
      (pack-meta-info m [:id :description])))

(defn- stringify-meta-info-sample
  [m]
  (-> [(str "ID=" (:id m))
       (str "Genomes=" (:genomes m))
       (str "Mixture=" (:mixture m))
       (str "Description=\"" (:description m) "\"")]
      (pack-meta-info m [:id :genomes :mixture :description])))

(defn- stringify-meta-info-pedigree
  [m]
  (->> (range (count m))
       (map (fn [i]
              (str "Name_" i "=" (get m (keyword (str "name-" i))))))
       (cstr/join \,)))

(defn stringify-structured-line
  [k m]
  (let [f (case k
            :contig stringify-meta-info-contig
            :info stringify-meta-info-info
{'fraction_non_alphanumeric': 0.21824581988853037, 'fraction_numerical': 0.0013200352009386917, 'mean_word_length': 2.426633165829146, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 45, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1654945', 'n_tokens_mistral': 2561, 'n_tokens_neox': 2425, 'n_words': 651}