<?xml version="1.0" encoding="UTF-8"?>
<TEI xmlns="http://www.tei-c.org/ns/1.0" xml:lang="en">
  <teiHeader>
    <fileDesc>
      <titleStmt>
        <title>Improved metagenomic analysis with Kraken 2</title>
        <author>Derrick E. Wood</author>
        <author>Jennifer Lu</author>
        <author>Ben Langmead</author>
      </titleStmt>
      <publicationStmt>
        <p>Tag layer of the DHSS Meta-Tagging Project. The article text is reproduced from the
           staged copy named in sourceDesc and is not altered; the tags are held separately in
           standOff so that overlapping and nested spans are preserved.</p>
      </publicationStmt>
      <sourceDesc>
        <bibl>
          <title>Improved metagenomic analysis with Kraken 2</title>
          <date>2019</date>
          <publisher>Genome Biology</publisher>
          <idno type="DOI">10.1186/s13059-019-1891-0</idno>
          
          <idno type="record">wood2019-improved-metagenomic-analysis-kraken-2</idno>
          <note type="staged-file">wood2019-improved-metagenomic-analysis-kraken-2.txt, the project's staged copy</note>
          <note type="text-sha1">93b03b21bf251d131f8de9a907f1e247acccf92b</note>
          <note type="rights">cc-by</note>
        </bibl>
      </sourceDesc>
    </fileDesc>
    <profileDesc>
      <textClass><keywords><term>bioinformatics</term></keywords></textClass>
      <particDesc>
        <person xml:id="paper"><p>the paper's own words</p></person>
        <person xml:id="tagger"><p>the tag layer; a sentence written by the tagger about the
          paper, always anchored to a quotation but not itself a quotation</p></person>
      </particDesc>
    </profileDesc>
    <revisionDesc>
      <change when="2026-10-06"
              who="build_paper_edition.py">157 spans located by searching the stored text for the quote's exact words, allowing any whitespace between them</change>
    </revisionDesc>
  </teiHeader>
  <standOff>
    <spanGrp type="tags">
      <span xml:id="t0" from="#a1" to="#a2" type="object_of_study" ana="#object_of_study" resp="#paper">Kraken 2&#x27;s data structures, classification algorithms, resource use, accuracy, and translated-search behavior</span>
      <span xml:id="t1" from="#a5" to="#a6" type="research_question" ana="#research_question" resp="#paper">whether minimizer indexing and a compact probabilistic table can reduce metagenomic-classifier memory and runtime without materially sacrificing accuracy</span>
      <span xml:id="t2" from="#a3" to="#a4" type="contribution" ana="#contribution" resp="#paper">Kraken 2, a minimizer-based classifier with compact hashing, internal taxonomy compression, spaced seeds, translated search, and Bracken compatibility</span>
      <span xml:id="t3" from="#a1" to="#a2" type="claim_type" ana="#claim_type" resp="#paper">method</span>
      <span xml:id="t4" from="#a3" to="#a4" type="phenomenon" ana="#phenomenon" resp="#paper">the memory, speed, and sensitivity constraints of taxonomic metagenomic sequence classification</span>
      <span xml:id="t5" from="#a11" to="#a12" type="method" ana="#method" resp="#paper">system-or-tool-building<term>system-or-tool-building</term></span>
      <span xml:id="t6" from="#a5" to="#a6" type="mechanisms" ana="#mechanisms[0]" resp="#tagger" cert="0.95">Only minimizers are stored as compact hash codes associated with LCA values.<term>compact minimizer indexing</term></span>
      <span xml:id="t7" from="#a27" to="#a28" type="mechanisms" ana="#mechanisms[1]" resp="#tagger" cert="0.95">Linear probing compares compact hash codes in fixed 32-bit cells, accepting a small collision risk for memory savings.<term>probabilistic compact hash querying</term></span>
      <span xml:id="t8" from="#a31" to="#a32" type="mechanisms" ana="#mechanisms[2]" resp="#tagger" cert="0.95">Reference-bearing nodes and ancestors are renumbered breadth-first so ancestor IDs precede descendant IDs.<term>minimal breadth-first taxonomy numbering</term></span>
      <span xml:id="t9" from="#a42" to="#a43" type="mechanisms" ana="#mechanisms[3]" resp="#tagger" cert="0.95">A deque maintains the smallest canonical substring while successive overlapping k-mers are scanned.<term>sliding-window minimizer calculation</term></span>
      <span xml:id="t10" from="#a44" to="#a45" type="mechanisms" ana="#mechanisms[4]" resp="#tagger" cert="0.95">Alternating minimizer positions are masked before candidate selection and table lookup.<term>spaced-seed masking</term></span>
      <span xml:id="t11" from="#a49" to="#a50" type="mechanisms" ana="#mechanisms[5]" resp="#tagger" cert="0.95">A hash threshold retains only the fraction of minimizers that fits a user-specified table size.<term>capacity-bounded hash subsampling</term></span>
      <span xml:id="t12" from="#a55" to="#a56" type="mechanisms" ana="#mechanisms[6]" resp="#tagger" cert="0.95">LCA hits form a pruned tree and the maximally scoring root-to-leaf path supplies the classification.<term>root-to-leaf taxonomic scoring</term></span>
      <span xml:id="t13" from="#a57" to="#a58" type="mechanisms" ana="#mechanisms[7]" resp="#tagger" cert="0.95">Input is copied in blocks inside a critical section and parsed later in thread-local execution.<term>deferred parsing</term></span>
      <span xml:id="t14" from="#a59" to="#a60" type="mechanisms" ana="#mechanisms[8]" resp="#tagger" cert="0.95">All six DNA reading frames are translated to a reduced alphabet and their minimizers are pooled for table queries.<term>six-frame translated search</term></span>
      <span xml:id="t15" from="#a21" to="#a22" type="mechanisms" ana="#mechanisms[9]" resp="#tagger" cert="0.95">Bracken integrates reads classified at higher taxonomic levels into species and genus abundance estimates.<term>Bayesian abundance redistribution</term></span>
      <span xml:id="t16" from="#a3" to="#a4" type="limitations" ana="#limitations[0]" resp="#tagger" cert="0.95">Kraken 1&#x27;s memory use can exceed 100 GB and force reduced-sensitivity databases or partitioned indexes.</span>
      <span xml:id="t17" from="#a5" to="#a6" type="limitations" ana="#limitations[1]" resp="#tagger" cert="0.95">The compact hash table trades some specificity and accuracy for memory reduction.</span>
      <span xml:id="t18" from="#a7" to="#a8" type="limitations" ana="#limitations[2]" resp="#tagger" cert="0.95">Reducing target table size lowers memory use and raises throughput at the cost of classification accuracy.</span>
      <span xml:id="t19" from="#a17" to="#a18" type="limitations" ana="#limitations[3]" resp="#tagger" cert="0.95">Species-level assignment can fail when different species or genera have high genomic identity.</span>
      <span xml:id="t20" from="#a27" to="#a28" type="limitations" ana="#limitations[4]" resp="#tagger" cert="0.95">Compact hash codes permit false-positive presence reports and confusion between values.</span>
      <span xml:id="t21" from="#a29" to="#a30" type="limitations" ana="#limitations[5]" resp="#tagger" cert="0.95">The compact hash table cannot be resized after construction and admits soft hash collisions that a counting quotient filter avoids.</span>
      <span xml:id="t22" from="#a65" to="#a66" type="limitations" ana="#limitations[6]" resp="#tagger" cert="0.95">Real FDA-ARGOS classifications cannot be scored as sensitivity or PPV because true fragment origins and discordance causes are uncertain.</span>
      <span xml:id="t23" from="#a21" to="#a22" type="limitations" ana="#limitations[7]" resp="#tagger" cert="0.95">Low viral nucleotide-search sensitivity prevents Bracken from inferring taxonomy for many viral reads.</span>
      <span xml:id="t24" from="#a3" to="#a4" type="concepts" ana="#concepts[0]" resp="#paper" cert="0.95">Kraken<term>Kraken</term></span>
      <span xml:id="t25" from="#a1" to="#a2" type="concepts" ana="#concepts[1]" resp="#paper" cert="0.95">Kraken 2<term>Kraken 2</term></span>
      <span xml:id="t26" from="#a3" to="#a4" type="concepts" ana="#concepts[2]" resp="#paper" cert="0.95">taxonomic labels<term>taxonomic labels</term></span>
      <span xml:id="t27" from="#a3" to="#a4" type="concepts" ana="#concepts[3]" resp="#paper" cert="0.95">sequencing reads<term>sequencing reads</term></span>
      <span xml:id="t28" from="#a3" to="#a4" type="concepts" ana="#concepts[4]" resp="#paper" cert="0.95">computational genomics pipelines<term>computational genomics pipelines</term></span>
      <span xml:id="t29" from="#a3" to="#a4" type="concepts" ana="#concepts[5]" resp="#paper" cert="0.95">metagenomics<term>metagenomics</term></span>
      <span xml:id="t30" from="#a3" to="#a4" type="concepts" ana="#concepts[6]" resp="#paper" cert="0.95">k -mers<term>k -mers</term></span>
      <span xml:id="t31" from="#a3" to="#a4" type="concepts" ana="#concepts[7]" resp="#paper" cert="0.95">lowest common ancestor<term>lowest common ancestor</term></span>
      <span xml:id="t32" from="#a3" to="#a4" type="concepts" ana="#concepts[8]" resp="#paper" cert="0.95">KrakenUniq<term>KrakenUniq</term></span>
      <span xml:id="t33" from="#a3" to="#a4" type="concepts" ana="#concepts[9]" resp="#paper" cert="0.95">MiniKraken database<term>MiniKraken database</term></span>
      <span xml:id="t34" from="#a3" to="#a4" type="concepts" ana="#concepts[10]" resp="#paper" cert="0.95">reference sequences<term>reference sequences</term></span>
      <span xml:id="t35" from="#a5" to="#a6" type="concepts" ana="#concepts[11]" resp="#paper" cert="0.95">compact hash table<term>compact hash table</term></span>
      <span xml:id="t36" from="#a5" to="#a6" type="concepts" ana="#concepts[12]" resp="#paper" cert="0.95">minimizers<term>minimizers</term></span>
      <span xml:id="t37" from="#a5" to="#a6" type="concepts" ana="#concepts[13]" resp="#paper" cert="0.95">LCAs<term>LCAs</term></span>
      <span xml:id="t38" from="#a33" to="#a34" type="concepts" ana="#concepts[14]" resp="#paper" cert="0.95">LCA<term>LCA</term></span>
      <span xml:id="t39" from="#a35" to="#a36" type="concepts" ana="#concepts[15]" resp="#paper" cert="0.95">Kraken 2 database<term>Kraken 2 database</term></span>
      <span xml:id="t40" from="#a35" to="#a36" type="concepts" ana="#concepts[16]" resp="#paper" cert="0.95">internal taxonomy representation<term>internal taxonomy representation</term></span>
      <span xml:id="t41" from="#a7" to="#a8" type="concepts" ana="#concepts[17]" resp="#paper" cert="0.95">smaller hash tables<term>smaller hash tables</term></span>
      <span xml:id="t42" from="#a7" to="#a8" type="concepts" ana="#concepts[18]" resp="#paper" cert="0.95">higher classification throughput<term>higher classification throughput</term></span>
      <span xml:id="t43" from="#a7" to="#a8" type="concepts" ana="#concepts[19]" resp="#paper" cert="0.95">classification accuracy<term>classification accuracy</term></span>
      <span xml:id="t44" from="#a9" to="#a10" type="concepts" ana="#concepts[20]" resp="#paper" cert="0.95">translated search mode<term>translated search mode</term></span>
      <span xml:id="t45" from="#a9" to="#a10" type="concepts" ana="#concepts[21]" resp="#paper" cert="0.95">Kraken 2X<term>Kraken 2X</term></span>
      <span xml:id="t46" from="#a9" to="#a10" type="concepts" ana="#concepts[22]" resp="#paper" cert="0.95">reduced amino acid alphabet<term>reduced amino acid alphabet</term></span>
      <span xml:id="t47" from="#a13" to="#a14" type="concepts" ana="#concepts[23]" resp="#paper" cert="0.95">strain-exclusion approach<term>strain-exclusion approach</term></span>
      <span xml:id="t48" from="#a13" to="#a14" type="concepts" ana="#concepts[24]" resp="#paper" cert="0.95">simulated sequencing errors<term>simulated sequencing errors</term></span>
      <span xml:id="t49" from="#a15" to="#a16" type="concepts" ana="#concepts[25]" resp="#paper" cert="0.95">per-sequence accuracy<term>per-sequence accuracy</term></span>
      <span xml:id="t50" from="#a15" to="#a16" type="concepts" ana="#concepts[26]" resp="#paper" cert="0.95">viral read data<term>viral read data</term></span>
      <span xml:id="t51" from="#a17" to="#a18" type="concepts" ana="#concepts[27]" resp="#paper" cert="0.95">sensitivity at the species level<term>sensitivity at the species level</term></span>
      <span xml:id="t52" from="#a17" to="#a18" type="concepts" ana="#concepts[28]" resp="#paper" cert="0.95">redefinition of the taxonomy based on the phylogeny<term>redefinition of the taxonomy based on the phylogeny</term></span>
      <span xml:id="t53" from="#a19" to="#a20" type="concepts" ana="#concepts[29]" resp="#paper" cert="0.95">processing speed<term>processing speed</term></span>
      <span xml:id="t54" from="#a19" to="#a20" type="concepts" ana="#concepts[30]" resp="#paper" cert="0.95">memory requirement<term>memory requirement</term></span>
      <span xml:id="t55" from="#a21" to="#a22" type="concepts" ana="#concepts[31]" resp="#paper" cert="0.95">Bracken<term>Bracken</term></span>
      <span xml:id="t56" from="#a21" to="#a22" type="concepts" ana="#concepts[32]" resp="#paper" cert="0.95">sequence abundance<term>sequence abundance</term></span>
      <span xml:id="t57" from="#a21" to="#a22" type="concepts" ana="#concepts[33]" resp="#paper" cert="0.95">Bayesian algorithm<term>Bayesian algorithm</term></span>
      <span xml:id="t58" from="#a21" to="#a22" type="concepts" ana="#concepts[34]" resp="#paper" cert="0.95">higher sensitivity<term>higher sensitivity</term></span>
      <span xml:id="t59" from="#a25" to="#a26" type="concepts" ana="#concepts[35]" resp="#paper" cert="0.95">compact hash table (CHT)<term>compact hash table (CHT)</term></span>
      <span xml:id="t60" from="#a35" to="#a36" type="concepts" ana="#concepts[36]" resp="#paper" cert="0.95">CHT<term>CHT</term></span>
      <span xml:id="t61" from="#a25" to="#a26" type="concepts" ana="#concepts[37]" resp="#paper" cert="0.95">hash cells<term>hash cells</term></span>
      <span xml:id="t62" from="#a25" to="#a26" type="concepts" ana="#concepts[38]" resp="#paper" cert="0.95">linear probing<term>linear probing</term></span>
      <span xml:id="t63" from="#a25" to="#a26" type="concepts" ana="#concepts[39]" resp="#paper" cert="0.95">key-value pairs<term>key-value pairs</term></span>
      <span xml:id="t64" from="#a27" to="#a28" type="concepts" ana="#concepts[40]" resp="#paper" cert="0.95">false-positive query results<term>false-positive query results</term></span>
      <span xml:id="t65" from="#a31" to="#a32" type="concepts" ana="#concepts[41]" resp="#paper" cert="0.95">minimal set of nodes<term>minimal set of nodes</term></span>
      <span xml:id="t66" from="#a31" to="#a32" type="concepts" ana="#concepts[42]" resp="#paper" cert="0.95">breadth-first search<term>breadth-first search</term></span>
      <span xml:id="t67" from="#a31" to="#a32" type="concepts" ana="#concepts[43]" resp="#paper" cert="0.95">external taxonomy ID numbers<term>external taxonomy ID numbers</term></span>
      <span xml:id="t68" from="#a37" to="#a39" type="concepts" ana="#concepts[44]" resp="#paper" cert="0.95">minimizer-based subsampling<term>minimizer-based subsampling</term></span>
      <span xml:id="t69" from="#a40" to="#a41" type="concepts" ana="#concepts[45]" resp="#paper" cert="0.95">sliding window minimum algorithm<term>sliding window minimum algorithm</term></span>
      <span xml:id="t70" from="#a44" to="#a45" type="concepts" ana="#concepts[46]" resp="#paper" cert="0.95">spaced seed<term>spaced seed</term></span>
      <span xml:id="t71" from="#a48" to="#a50" type="concepts" ana="#concepts[47]" resp="#paper" cert="0.95">hash-based subsampling<term>hash-based subsampling</term></span>
      <span xml:id="t72" from="#a51" to="#a52" type="concepts" ana="#concepts[48]" resp="#paper" cert="0.95">minimizer collisions<term>minimizer collisions</term></span>
      <span xml:id="t73" from="#a51" to="#a52" type="concepts" ana="#concepts[49]" resp="#paper" cert="0.95">hash table collisions<term>hash table collisions</term></span>
      <span xml:id="t74" from="#a51" to="#a52" type="concepts" ana="#concepts[50]" resp="#paper" cert="0.95">incorrectly classified k -mers<term>incorrectly classified k -mers</term></span>
      <span xml:id="t75" from="#a53" to="#a54" type="concepts" ana="#concepts[51]" resp="#paper" cert="0.95">low-complexity sequences<term>low-complexity sequences</term></span>
      <span xml:id="t76" from="#a53" to="#a54" type="concepts" ana="#concepts[52]" resp="#paper" cert="0.95">false positives<term>false positives</term></span>
      <span xml:id="t77" from="#a55" to="#a56" type="concepts" ana="#concepts[53]" resp="#paper" cert="0.95">classification tree<term>classification tree</term></span>
      <span xml:id="t78" from="#a59" to="#a60" type="concepts" ana="#concepts[54]" resp="#paper" cert="0.95">six reading frames<term>six reading frames</term></span>
      <span xml:id="t79" from="#a63" to="#a64" type="concepts" ana="#concepts[55]" resp="#paper" cert="0.95">rank-level sensitivity<term>rank-level sensitivity</term></span>
      <span xml:id="t80" from="#a63" to="#a64" type="concepts" ana="#concepts[56]" resp="#paper" cert="0.95">TP/(TP + VP + FN + FP)<term>TP/(TP + VP + FN + FP)</term></span>
      <span xml:id="t81" from="#a63" to="#a64" type="concepts" ana="#concepts[57]" resp="#paper" cert="0.95">rank-level positive predictive value<term>rank-level positive predictive value</term></span>
      <span xml:id="t82" from="#a63" to="#a64" type="concepts" ana="#concepts[58]" resp="#paper" cert="0.95">TP/(TP + FP)<term>TP/(TP + FP)</term></span>
      <span xml:id="t83" from="#a63" to="#a64" type="concepts" ana="#concepts[59]" resp="#paper" cert="0.95">F1-measure<term>F1-measure</term></span>
      <span xml:id="t84" from="#a63" to="#a64" type="concepts" ana="#concepts[60]" resp="#paper" cert="0.95">harmonic mean<term>harmonic mean</term></span>
      <span xml:id="t85" from="#a5" to="#a6" type="concepts" ana="#concepts[61]" resp="#paper" cert="0.95">Kraken 1<term>Kraken 1</term></span>
      <span xml:id="t86" from="#a15" to="#a16" type="concepts" ana="#concepts[62]" resp="#paper" cert="0.95">Kaiju<term>Kaiju</term></span>
      <span xml:id="t87" from="#a7" to="#a8" type="unhoused_relations" ana="#unhoused_relations[0]" resp="#tagger" cert="0.95">smaller hash tables → classification accuracy<note>Smaller hash tables lower classification accuracy.</note></span>
      <span xml:id="t88" from="#a23" to="#a24" type="unhoused_relations" ana="#unhoused_relations[1]" resp="#tagger" cert="0.95">Kraken 2 → Bracken<note>Kraken 2 is compatible with Bracken for species-level quantification.</note></span>
      <span xml:id="t89" from="#a33" to="#a34" type="unhoused_relations" ana="#unhoused_relations[2]" resp="#tagger" cert="0.95">internal taxonomy representation → LCA<note>The internal taxonomy representation makes lowest-common-ancestor computation easier.</note></span>
      <span xml:id="t90" from="#a51" to="#a52" type="unhoused_relations" ana="#unhoused_relations[3]" resp="#tagger" cert="0.95">minimizer collisions → incorrectly classified k -mers<note>Minimizer collisions can elevate LCA values or incorrectly classify k-mers.</note></span>
      <span xml:id="t91" from="#a51" to="#a52" type="unhoused_relations" ana="#unhoused_relations[4]" resp="#tagger" cert="0.95">hash table collisions → incorrectly classified k -mers<note>Hash-table collisions can elevate LCA values or incorrectly classify k-mers.</note></span>
      <span xml:id="t92" from="#a53" to="#a54" type="unhoused_relations" ana="#unhoused_relations[5]" resp="#tagger" cert="0.95">low-complexity sequences → false positives<note>Masking low-complexity sequences seeks to reduce false-positive classifications.</note></span>
      <span xml:id="t93" from="#a23" to="#a24" type="senses" ana="#senses[0]" resp="#tagger" cert="0.95">Kraken 2 as a minimizer-indexed, memory-efficient metagenomic taxonomic sequence classifier</span>
      <span xml:id="t94" from="#a25" to="#a26" type="senses" ana="#senses[1]" resp="#tagger" cert="0.95">compact hash table as a probabilistic 32-bit key-value store using linear probing</span>
      <span xml:id="t95" from="#a38" to="#a39" type="senses" ana="#senses[2]" resp="#tagger" cert="0.95">minimizer as the lexicographically smallest canonical substring within a k-mer</span>
      <span xml:id="t96" from="#a31" to="#a32" type="senses" ana="#senses[3]" resp="#tagger" cert="0.95">internal taxonomy as a minimal node set numbered breadth-first so ancestors precede descendants</span>
      <span xml:id="t97" from="#a13" to="#a14" type="senses" ana="#senses[4]" resp="#tagger" cert="0.95">strain exclusion as evaluation against references that omit the simulated strain of origin</span>
      <span xml:id="t98" from="#a59" to="#a60" type="senses" ana="#senses[5]" resp="#tagger" cert="0.95">translated search as six-frame amino-acid-space querying through a reduced alphabet</span>
      <span xml:id="t99" from="#a63" to="#a64" type="senses" ana="#senses[6]" resp="#tagger" cert="0.95">sensitivity as true positives divided by all fragment outcome categories</span>
      <span xml:id="t100" from="#a63" to="#a64" type="senses" ana="#senses[7]" resp="#tagger" cert="0.95">positive predictive value as true positives divided by true and false positives</span>
      <span xml:id="t101" from="#a61" to="#a62" type="senses" ana="#senses[8]" resp="#tagger" cert="0.95">vague positive as a classification at an ancestor of the true genus</span>
      <span xml:id="t102" from="#a51" to="#a52" type="senses" ana="#senses[9]" resp="#tagger" cert="0.95">collision risk as k-mer sharing at the minimizer layer or compact-code aliasing at the hash-table layer</span>
      <span xml:id="t103" from="#a55" to="#a56" type="senses" ana="#senses[10]" resp="#tagger" cert="0.95">classification as maximizing the score of a root-to-leaf path through a pruned taxonomic hit tree</span>
      <span xml:id="t104" from="#a67" to="#a68" type="senses" ana="#senses[11]" resp="#tagger" cert="0.95">parameter robustness as many configurations producing approximately the same near-optimal accuracy</span>
      <span xml:id="t105" from="#a3" to="#a4" type="claim_relations" ana="#claim_relations[0]" resp="#tagger" cert="0.95">extends → Kraken 1<note>note: Kraken 2 replaces the earlier design while retaining the same classification framework.</note></span>
      <span xml:id="t106" from="#a7" to="#a8" type="claim_relations" ana="#claim_relations[1]" resp="#tagger" cert="0.95">builds-on → minimizer-based read alignment<note>note: The authors point to a similar minimizer approach that accelerated read alignment.</note></span>
      <span xml:id="t107" from="#a59" to="#a60" type="claim_relations" ana="#claim_relations[2]" resp="#tagger" cert="0.95">extends → Kraken 2 nucleotide search<note>note: Kraken 2X extends the database/query pipeline into six-frame protein-space search.</note></span>
      <span xml:id="t108" from="#a5" to="#a6" type="concept_edges" ana="#concept_edges[0]" resp="#tagger" cert="0.95">Kraken 2 —contrasted-with→ Kraken 1<note>the relation itself is separately evidenced · strength of the relation: 0.95 · note: A direct unhedged architectural contrast. · the relation stated: Kraken 2 stores minimizers in a compact hash table whereas Kraken 1 stored all k-mers.</note><term>Kraken 2</term><term>Kraken 1</term></span>
      <span xml:id="t109" from="#a35" to="#a36" type="concept_edges" ana="#concept_edges[1]" resp="#tagger" cert="0.95">CHT —part-of→ Kraken 2 database<note>the relation itself is separately evidenced · strength of the relation: 1 · note: Categorical composition statement. · the relation stated: A Kraken 2 database consists of a CHT and its internal taxonomy representation.</note><term>CHT</term><term>Kraken 2 database</term></span>
      <span xml:id="t110" from="#a35" to="#a36" type="concept_edges" ana="#concept_edges[2]" resp="#tagger" cert="0.95">internal taxonomy representation —part-of→ Kraken 2 database<note>the relation itself is separately evidenced · strength of the relation: 1 · note: Categorical composition statement. · the relation stated: A Kraken 2 database consists of a CHT and its internal taxonomy representation.</note><term>internal taxonomy representation</term><term>Kraken 2 database</term></span>
      <span xml:id="t111" from="#a7" to="#a8" type="concept_edges" ana="#concept_edges[3]" resp="#tagger" cert="0.95">smaller hash tables —causes→ higher classification throughput<note>direction on the measure: increases · the relation itself is separately evidenced · strength of the relation: 0.95 · note: The paper makes a direct unhedged yield claim. · the relation stated: Smaller hash tables yield higher classification throughput.</note><term>smaller hash tables</term><term>higher classification throughput</term></span>
      <span xml:id="t112" from="#a17" to="#a18" type="concept_edges" ana="#concept_edges[4]" resp="#tagger" cert="0.95">redefinition of the taxonomy based on the phylogeny —causes→ sensitivity at the species level<note>direction on the measure: increases · the relation itself is separately evidenced · strength of the relation: 0.6 — the record marks this weak · note: The counterfactual &#x27;would likely&#x27; makes the paper strength provisional. · the relation stated: A phylogeny-based taxonomy redefinition would likely improve species-level sensitivity.
Audit 2026-09-28: DOUBTFUL - read against its full span and kept, but the span says the redefinition WOULD LIKELY improve sensitivity; hedged.</note><term>redefinition of the taxonomy based on the phylogeny</term><term>sensitivity at the species level</term></span>
      <span xml:id="t113" from="#a21" to="#a22" type="concept_edges" ana="#concept_edges[5]" resp="#tagger" cert="0.95">higher sensitivity —causes→ sequence abundance<note>direction on the measure: increases · the relation itself is separately evidenced · strength of the relation: 0.6 — the record marks this weak · note: The authors explicitly hedge the explanation with &#x27;likely owing&#x27;. · the relation stated: Kraken 2&#x27;s higher sensitivity likely made Bracken&#x27;s abundance estimates more accurate.
Audit 2026-09-28: DOUBTFUL - read against its span and kept, but Kraken 2&#x27;s sensitivity likely made abundance ESTIMATES more accurate; &#x27;increases sequence abundance&#x27; is wrong.</note><term>higher sensitivity</term><term>sequence abundance</term></span>
      <span xml:id="t114" from="#a63" to="#a64" type="concept_edges" ana="#concept_edges[6]" resp="#tagger" cert="0.95">rank-level sensitivity —operationalised-as→ TP/(TP + VP + FN + FP)<note>the relation itself is separately evidenced · strength of the relation: 1 · note: Exact mathematical definition. · the relation stated: Rank-level sensitivity is defined as TP divided by TP plus VP, FN, and FP.</note><term>rank-level sensitivity</term><term>TP/(TP + VP + FN + FP)</term></span>
      <span xml:id="t115" from="#a63" to="#a64" type="concept_edges" ana="#concept_edges[7]" resp="#tagger" cert="0.95">rank-level positive predictive value —operationalised-as→ TP/(TP + FP)<note>the relation itself is separately evidenced · strength of the relation: 1 · note: Exact mathematical definition. · the relation stated: Rank-level positive predictive value is defined as TP divided by TP plus FP.</note><term>rank-level positive predictive value</term><term>TP/(TP + FP)</term></span>
      <span xml:id="t116" from="#a63" to="#a64" type="concept_edges" ana="#concept_edges[8]" resp="#tagger" cert="0.95">F1-measure —operationalised-as→ harmonic mean<note>the relation itself is separately evidenced · strength of the relation: 1 · note: Exact mathematical definition. · the relation stated: F1-measure is defined as the harmonic mean of sensitivity and PPV.</note><term>F1-measure</term><term>harmonic mean</term></span>
      <span xml:id="t117" from="#a1" to="#a2" type="content_tags" ana="#content_tags.findings[0]" resp="#tagger" cert="0.95">Kraken 2 reduces memory usage by 85 percent while maintaining high accuracy and increasing speed fivefold.</span>
      <span xml:id="t118" from="#a5" to="#a6" type="content_tags" ana="#content_tags.findings[1]" resp="#tagger" cert="0.95">A compact minimizer table replaces Kraken 1&#x27;s full k-mer list.</span>
      <span xml:id="t119" from="#a7" to="#a8" type="content_tags" ana="#content_tags.findings[2]" resp="#tagger" cert="0.95">Only distinct query minimizers trigger table access, improving speed.</span>
      <span xml:id="t120" from="#a7" to="#a8" type="content_tags" ana="#content_tags.findings[3]" resp="#tagger" cert="0.95">Smaller tables trade classification accuracy for memory and throughput.</span>
      <span xml:id="t121" from="#a9" to="#a10" type="content_tags" ana="#content_tags.findings[4]" resp="#tagger" cert="0.95">Translated search improves sensitivity on viral data compared with nucleotide search.</span>
      <span xml:id="t122" from="#a13" to="#a14" type="content_tags" ana="#content_tags.findings[5]" resp="#tagger" cert="0.95">Strain exclusion and simulated errors create a less optimistic and more realistic evaluation.</span>
      <span xml:id="t123" from="#a15" to="#a16" type="content_tags" ana="#content_tags.findings[6]" resp="#tagger" cert="0.95">Kraken 2 is often as accurate as or more accurate than other nucleotide classifiers.</span>
      <span xml:id="t124" from="#a19" to="#a20" type="content_tags" ana="#content_tags.findings[7]" resp="#tagger" cert="0.95">Kraken 2 exceeds 93 million paired-end reads per minute with 16 threads.</span>
      <span xml:id="t125" from="#a19" to="#a20" type="content_tags" ana="#content_tags.findings[8]" resp="#tagger" cert="0.95">Kraken 2 uses 15 percent of Kraken 1&#x27;s memory for the tested reference.</span>
      <span xml:id="t126" from="#a19" to="#a20" type="content_tags" ana="#content_tags.findings[9]" resp="#tagger" cert="0.95">Kraken 2X is more than three times faster and uses 47 percent less memory than Kaiju.</span>
      <span xml:id="t127" from="#a21" to="#a22" type="content_tags" ana="#content_tags.findings[10]" resp="#tagger" cert="0.95">Bracken estimates are more accurate from Kraken 2 than Kraken 1 at genus and species levels.</span>
      <span xml:id="t128" from="#a27" to="#a28" type="content_tags" ana="#content_tags.findings[11]" resp="#tagger" cert="0.95">The default compact-table collision probability is below one percent and is mitigated across read k-mers.</span>
      <span xml:id="t129" from="#a67" to="#a68" type="content_tags" ana="#content_tags.findings[12]" resp="#tagger" cert="0.95">Many parameter combinations produced approximately the same near-optimal accuracy.</span>
      <span xml:id="t130" from="#a69" to="#a70" type="content_tags" ana="#content_tags.findings[13]" resp="#tagger" cert="0.95">The full reference calculation estimates a Kraken 2 table at about 15 percent of Kraken 1&#x27;s k-mer database size.</span>
      <span xml:id="t131" from="#a23" to="#a24" type="content_tags" ana="#content_tags.definitions[0]" resp="#tagger" cert="0.95">an extremely memory-efficient metagenomics classification tool<term>Kraken 2</term></span>
      <span xml:id="t132" from="#a25" to="#a26" type="content_tags" ana="#content_tags.definitions[1]" resp="#tagger" cert="0.95">a fixed array of 32-bit cells storing compact hash-code and taxonomy-value pairs<term>compact hash table</term></span>
      <span xml:id="t133" from="#a38" to="#a39" type="content_tags" ana="#content_tags.definitions[2]" resp="#tagger" cert="0.95">the lexicographically smallest canonical l-mer within a k-mer<term>minimizer</term></span>
      <span xml:id="t134" from="#a35" to="#a36" type="content_tags" ana="#content_tags.definitions[3]" resp="#tagger" cert="0.95">a compact hash table together with an internal taxonomy representation<term>Kraken 2 database</term></span>
      <span xml:id="t135" from="#a61" to="#a62" type="content_tags" ana="#content_tags.definitions[4]" resp="#tagger" cert="0.95">a classification at the true genus or one of its descendants<term>true-positive classification</term></span>
      <span xml:id="t136" from="#a63" to="#a64" type="content_tags" ana="#content_tags.definitions[8]" resp="#tagger" cert="0.95">TP divided by TP plus VP, FN, and FP<term>rank-level sensitivity</term></span>
      <span xml:id="t137" from="#a63" to="#a64" type="content_tags" ana="#content_tags.definitions[9]" resp="#tagger" cert="0.95">TP divided by TP plus FP<term>positive predictive value</term></span>
      <span xml:id="t138" from="#a63" to="#a64" type="content_tags" ana="#content_tags.definitions[10]" resp="#tagger" cert="0.95">the harmonic mean of sensitivity and positive predictive value<term>F1-measure</term></span>
      <span xml:id="t139" from="#a1" to="#a2" type="content_tags" ana="#content_tags.quantities[0]" resp="#tagger" cert="0.95">85% — Kraken 2 memory reduction relative to Kraken 1</span>
      <span xml:id="t140" from="#a1" to="#a2" type="content_tags" ana="#content_tags.quantities[1]" resp="#tagger" cert="0.95">fivefold — Kraken 2 speed increase stated in the abstract</span>
      <span xml:id="t141" from="#a5" to="#a6" type="content_tags" ana="#content_tags.quantities[2]" resp="#tagger" cert="0.95">10.6 GB — Kraken 2 classification memory for the 9.1-Gbp reference</span>
      <span xml:id="t142" from="#a5" to="#a6" type="content_tags" ana="#content_tags.quantities[3]" resp="#tagger" cert="0.95">72.4 GB — Kraken 1 classification memory for the same reference</span>
      <span xml:id="t143" from="#a19" to="#a20" type="content_tags" ana="#content_tags.quantities[4]" resp="#tagger" cert="0.95">93 million reads per minute — Kraken 2 paired-end processing speed using 16 threads</span>
      <span xml:id="t144" from="#a19" to="#a20" type="content_tags" ana="#content_tags.quantities[5]" resp="#tagger" cert="0.95">15% — Kraken 2 memory requirement relative to Kraken 1</span>
      <span xml:id="t145" from="#a19" to="#a20" type="content_tags" ana="#content_tags.quantities[6]" resp="#tagger" cert="0.95">47% less memory — Kraken 2X memory reduction relative to Kaiju</span>
      <span xml:id="t146" from="#a27" to="#a28" type="content_tags" ana="#content_tags.quantities[7]" resp="#tagger" cert="0.95">&lt; 1% — probability of either compact-table error at the default load factor</span>
      <span xml:id="t147" from="#a27" to="#a28" type="content_tags" ana="#content_tags.quantities[8]" resp="#tagger" cert="0.95">70% — default compact hash table load factor</span>
      <span xml:id="t148" from="#a59" to="#a60" type="content_tags" ana="#content_tags.quantities[9]" resp="#tagger" cert="0.95">15 — amino-acid symbols in the reduced translated-search alphabet before the extra stop/special value</span>
      <span xml:id="t149" from="#a7" to="#a8" type="content_tags" ana="#content_tags.variables[0]" resp="#tagger" cert="0.95">target hash table size<term>target hash table size</term></span>
      <span xml:id="t150" from="#a7" to="#a8" type="content_tags" ana="#content_tags.variables[1]" resp="#tagger" cert="0.95">memory usage<term>memory usage</term></span>
      <span xml:id="t151" from="#a7" to="#a8" type="content_tags" ana="#content_tags.variables[2]" resp="#tagger" cert="0.95">classification throughput<term>classification throughput</term></span>
      <span xml:id="t152" from="#a7" to="#a8" type="content_tags" ana="#content_tags.variables[3]" resp="#tagger" cert="0.95">classification accuracy<term>classification accuracy</term></span>
      <span xml:id="t153" from="#a38" to="#a39" type="content_tags" ana="#content_tags.variables[4]" resp="#tagger" cert="0.95">k<term>k</term></span>
      <span xml:id="t154" from="#a46" to="#a47" type="content_tags" ana="#content_tags.variables[5]" resp="#tagger" cert="0.95">s<term>s</term></span>
      <span xml:id="t155" from="#a27" to="#a28" type="content_tags" ana="#content_tags.variables[6]" resp="#tagger" cert="0.95">load factor<term>load factor</term></span>
      <span xml:id="t156" from="#a61" to="#a62" type="content_tags" ana="#content_tags.variables[7]" resp="#tagger" cert="0.95">taxonomic rank<term>taxonomic rank</term></span>
    </spanGrp>
  </standOff>
  <text>
    <body>
        <p><anchor xml:id="a0"/> Improved metagenomic analysis with Kraken 2</p>
        <p>Abstract</p>
        <p><anchor xml:id="a1"/>Although Kraken’s k -mer-based approach provides a fast taxonomic classification of metagenomic sequence data, its large memory requirements can be limiting for some applications. Kraken 2 improves upon Kraken 1 by reducing memory usage by 85%, allowing greater amounts of reference genomic data to be used, while maintaining high accuracy and increasing speed fivefold. Kraken 2 also introduces a translated search mode, providing increased sensitivity in viral metagenomics analysis<anchor xml:id="a2"/>.</p>
        <p>Keywords: Metagenomics, Metagenomics classification, Microbiome, Probabilistic data structures, Alignment-free methods, Minimizers</p>
        <p><anchor xml:id="a3"/>Assigning taxonomic labels to sequencing reads is an important part of many computational genomics pipelines for metagenomics projects. Recent years have seen several approaches to accomplish this task in a time-efficient manner [ 1 – 3 ]. One such tool, Kraken [ 4 ], uses a memory-intensive algorithm that associates short genomic substrings ( k -mers) with the lowest common ancestor (LCA) taxa. Kraken and related tools like KrakenUniq [ 5 ] have proven highly efficient and accurate in independent tool comparisons [ 6 , 7 ]. But Kraken’s high memory requirements force many researchers to either use a reduced-sensitivity MiniKraken database [ 8 , 9 ] or to build and use many indexes over subsets of the reference sequences [ 10 , 11 ]. Its memory requirements can easily exceed 100 GB [ 7 ], especially when the reference data includes large eukaryotic genomes [ 12 , 13 ]. Here, we introduce Kraken 2, which provides a major reduction in memory usage as well as faster classification, a spaced seed searching scheme, a translated search mode for matching in amino acid space, and continued compatibility with the Bracken [ 14 ] species-level sequence abundance estimation algorithm<anchor xml:id="a4"/>.</p>
        <p><anchor xml:id="a5"/>Kraken 2 addresses the issue of large memory requirements through two changes to Kraken 1’s data structures and algorithms. While Kraken 1 used a sorted list of k -mer/LCA pairs indexed by minimizers [ 15 ], Kraken 2 introduces a probabilistic, compact hash table to map minimizers to LCAs. This table uses one third of the memory of a standard hash table, at the cost of some specificity and accuracy. Additionally, Kraken 2 only stores minimizers (of length ℓ , ℓ ≤ k ) from the reference sequence library in its data structure, whereas Kraken 1 stored all k -mers. This change means that, during classification, the minimizer ( ℓ -mer) is the substring compared against a reference set in Kraken 2, while Kraken 1 compared k -mers (Fig. 1 a, b). Kraken 2’s index for a specific reference database with 9.1 Gbp of genomic sequences uses 10.6 GB of memory when classifying. Kraken 1’s index for the same reference uses 72.4 GB of memory for classification (Fig. 2 a, Additional file 1 : Table S1). In general, a Kraken 2 database is about 85% smaller than a Kraken 1 database over the same references<anchor xml:id="a6"/> (Additional file 2 : Figure S1).</p>
        <p>Differences in operation between the two versions of Kraken. a Both versions of Kraken begin classifying a k -mer by computing its ℓ bp minimizer (highlighted in magenta). The default values of k and ℓ for each version are shown in the figure. b Kraken 2 applies a spaced seed mask of s spaces to the minimizer and calculates a compact hash code, which is then used as a search query in its compact hash table; the lowest common ancestor (LCA) taxon associated with the compact hash code is then assigned to the k -mer (see the “ Methods ” section for full details). In Kraken 1, the minimizer is used to accelerate the search for the k -mer, through the use of an offset index and a limited-range binary search; the association between k -mer and LCA is directly stored in the sorted list. c Kraken 2 also achieves lower memory usage than Kraken 1 by using fewer bits to store the LCA and storing a compact hash code of the minimizer rather than the full k -mer. d Impact on speed, memory usage, and prokaryotic genus F1-measure in Kraken 2 when changing k with respect to ℓ ( ℓ = 31, s = 7 for all three graphs). e Impact on prokaryotic genus sensitivity and positive predictive value (PPV) when changing the number of minimizer spaces s ( k = 35, ℓ = 31 for both graphs). In d and e , the data are from our parameter sweep results in Additional file 1 : Table S2, and the default values of the independent variables for Kraken 2 are marked with a circle.</p>
        <p>Comparison between Kraken 2 and other sequence classification tools. a Processing speed (in millions of reads per minute) and memory usage (measured by maximum resident set size, in gigabytes) are shown for each classifier, as evaluated on 50 million paired-end simulated reads with 16 threads. Accuracy results are shown for b 40 prokaryotic genomes and c 10 viral genomes. The results here are shown for sensitivity, positive predictive value (PPV), and F1-measure as evaluated on a per-fragment basis at the genus rank, with 1000 reads simulated from each genome. The strains from which reads were simulated were excluded from the reference libraries for each classification tool. “Kraken 2X” is Kraken 2 using translated search against a protein database. Full results for these strain-exclusion experiments are available in Additional file 1 : Table S1</p>
        <p><anchor xml:id="a7"/>Kraken 2’s approach is faster than Kraken 1’s because only distinct minimizers from the query (read) trigger accesses to the hash table. A similar minimizer-based approach has proven useful in accelerating read alignment [ 16 ]. Kraken 2 additionally provides a hash-based subsampling approach that reduces the set of minimizer/LCA pairs included in the table, allowing the user to specify a target hash table size; smaller hash tables yield lower memory usage and higher classification throughput at the expense of lower classification accuracy<anchor xml:id="a8"/> (Fig. 1 d, Additional file 1 : Table S2).</p>
        <p><anchor xml:id="a9"/>Kraken 2 also features other improvements to accuracy and runtime. A new translated search mode (Kraken 2X) uses a reduced amino acid alphabet and increases sensitivity on viral datasets compared to nucleotide-based search. Block- and batch-based parsing within the critical section is used to improve thread scaling, in a manner similar to that used in recent versions of Bowtie 2 [ 17 ]. We also added a form of spaced seed search and automated masking of low-complexity reference sequences to improve accuracy<anchor xml:id="a10"/>.</p>
        <p><anchor xml:id="a11"/>To assess the accuracy and performance of Kraken 2, we selected 40 prokaryotic and 10 viral genomes for which we had reference genomes for at least 2 sister subspecies and at least 2 sister species (Additional file 1 : Table S3). We then created a reference genome (or protein) set that excluded the 50 taxa for the genomes we selected. This reference set and taxonomy were held constant between the various classifiers we examined, avoiding any confounding due to the differences in the reference database<anchor xml:id="a12"/>. A similar approach has been recently used for this same purpose in another study [ 7 ].</p>
        <p>We simulated 1 million Illumina 100 × 100 nt paired-end reads from each of the 50 selected genomes, for a total of 50 million reads (25 million fragments). We processed these data with 4 nucleotide search-based sequence classification programs (Centrifuge [ 1 ], CLARK [ 2 ], Kraken 1 [ 4 ], and KrakenUniq [ 5 ]) and a translated search classifier (Kaiju [ 3 ]). We additionally processed these data with Kraken 2, using several different databases created with different parameters (the “ Methods ” section).</p>
        <p><anchor xml:id="a13"/>This strain-exclusion approach mimics the real-world scenario where reads likely originate from strains that are genetically distinct from those in the database. The addition of simulated sequencing errors also provides further genetic distance between the test data and the reference sequences. Through this approach, we sought to avoid overly optimistic estimates of a classifier’s performance<anchor xml:id="a14"/>.</p>
        <p><anchor xml:id="a15"/>We found that Kraken 2 exhibited similar, and often superior, per-sequence accuracy to the other nucleotide classifiers and that Kraken 2X provided similar (though slightly lower) accuracy compared to Kaiju (Fig. 2 b, Additional file 1 : Table S1). The nucleotide-based classifiers exhibited lower accuracy on the viral read data than did the translated search classifiers, demonstrating the advantage of translated search in scenarios marked by high genetic variability and sparsity of available reference genomes<anchor xml:id="a16"/> [ 3 ].</p>
        <p><anchor xml:id="a17"/>In some cases, we found that Kraken 2 would not classify a large proportion of reads correctly at the species level, despite the presence of at least two sister strains in the reference database (Additional file 2 : Figure. S2). This was often the result of classifications that were either incorrect at the species level or correct but only made at the genus level (or higher). Such classifications can occur when genomes from different species or genera share a high genomic identity, which is the case in multiple places of the taxonomy, including the Shigella [ 18 ], Bacillus [ 19 ], and Pseudomonas [ 20 ] genera. A redefinition of the taxonomy based on the phylogeny as recently proposed [ 21 ] would likely improve sensitivity at the species level<anchor xml:id="a18"/>.</p>
        <p><anchor xml:id="a19"/>Following our evaluation of the classifiers’ accuracy, we then examined the runtime and memory requirements of each program. Kraken 2 provided substantial increases in processing speed, classifying paired-end data at over 93 million reads per minute while using 16 threads, a speed over 5 times faster than Kraken 1, the next-fastest classifier (Fig. 2 a, Additional file 1 : Table S1). Additionally, Kraken 2 exhibited superior thread scaling to Kraken 1 (Additional file 1 : Table S4). Kraken 2’s memory requirement is also 15% of Kraken 1’s, and only 2.5 times as much as that of the least memory-intensive classifier we examined, Centrifuge. With respect to the translated search programs, Kraken 2X is over 3 times faster and uses 47% less memory than Kaiju<anchor xml:id="a20"/>.</p>
        <p>To determine if Kraken 2 exhibited similar analytical performance on real sequencing data, we classified read data from the FDA-ARGOS project [ 22 ]. We compared the fragment classifications obtained by the various classification programs to the taxonomic labels attached to the corresponding ARGOS experiment. Kraken 2 exhibits similar genus-level concordance and discordance statistics to the other nucleotide search classifiers, while Kraken 2X exhibits similar but less agreement with the ARGOS labels than does Kaiju (Additional file 1 : Table S5). These results agree with those obtained in the strain-exclusion experiment on simulated data.</p>
        <p><anchor xml:id="a21"/>As a continuation of the strain-exclusion experiments, we applied Bracken [ 14 ] to the Kraken 1 and Kraken 2 results, estimating species- and genus-level sequence abundance for prokaryotic species. Bracken uses a Bayesian algorithm to integrate reads Kraken classified at higher taxonomic levels into the abundance estimates. Although the true strain-level taxa are excluded from the database, Bracken recaptured most of the true genus-level and species-level sequence abundances using both Kraken 2 and Kraken 1 classification results. Comparing the results, the Bracken estimates were more accurate with Kraken 2 than with Kraken 1 at both the genus and species levels, likely owing to Kraken 2’s higher sensitivity (Additional file 2 : Figure S2). Bracken ran in less than 1 s, a minute fraction of the runtime of any of the classification programs we examined<anchor xml:id="a22"/>.</p>
        <p><anchor xml:id="a23"/>As databases of assembled genomes continue to grow, databases of reference sequences used for metagenomics studies will also grow [ 21 , 23 ]. We presented Kraken 2, an extremely memory-efficient metagenomics classification tool that replaces Kraken 1’s k -mer database with a probabilistic data structure that is substantially smaller, allowing six to seven times more reference data compared to Kraken 1. The algorithms introduced in Kraken 2 to subsample the set of genomic substrings also provide Kraken 2 with the ability to further reduce the size of its database and accelerate the processing of sequencing data. We showed Kraken 2’s accuracy is comparable to that of Kraken 1 and other competing tools, consistent with other studies [ 6 , 7 ]. We also showed that its new translated search mode has accuracy approaching that of the protein-focused Kaiju tool, while using less memory and runtime. Also, Kraken 2 is compatible with the Bracken software for species-level quantification, making Kraken 2 straightforwardly usable for that application<anchor xml:id="a24"/>.</p>
        <p>In the future, it will be important to consider additional use cases for Kraken 2. For example, other data structures similar to our compact hash table, such as the counting quotient filter [ 24 ], could be implemented and used in computing environments and applications that may benefit from a particular data structure’s design and properties. Additionally, the KrakenUniq [ 5 ] tool uses the HyperLogLog sketch [ 25 ] to estimate the number of distinct k -mers matched at each node of the taxonomy, a statistic that is used in turn to better determine the presence or absence of individual genomes. We plan to add this functionality in the future, as it enables applications in the diagnosis of infections where the infectious agent is present at low abundance.</p>
        <p>Methods</p>
        <p>Compact hash table</p>
        <p><anchor xml:id="a25"/>The hash table used by Kraken 2 to store minimizer/LCA key-value pairs is very similar to a traditional hash table that would use linear probing for collision resolution, with some modifications. Kraken 2’s compact hash table (CHT) uses a fixed-size array of 32-bit hash cells to store key-value pairs. Within a cell, the number of bits used to store the value of the key-value pair will vary depending on the number of bits needed to represent all unique taxonomy ID numbers found in the reference sequence library; this was 17 bits with the standard Kraken 2 database in September 2018. The value is stored in the least significant bits of the hash cell and must be a positive integer. Values of 0 represent empty cells. Within the remaining bits of the hash cell, the most significant bits of the key’s hash code (a compact hash code) are stored. Searching for a key K in the CHT is done by computing the hash code of the key h ( K ) then linearly scanning the table array starting at position h ( K ) mod | T | (where | T | is the number of cells in the array) for a matching key. Examples of this search process—including both key/value insertion and querying—are shown in Additional file 2 : Figure S3. In Kraken 2, the hash function h used is the finalization function from MurmurHash3<anchor xml:id="a26"/> [ 26 ].</p>
        <p><anchor xml:id="a27"/>Compacting hash codes in this way allows Kraken 2 to use 32 bits for a key-value pair, a reduction compared to the 96 bits used by Kraken 1 (64 bits for key, 32 for value) (Fig. 1 c). But it also creates a new way in which keys can “collide,” in turn impacting the accuracy of queries to the CHT. Two distinct keys can be treated as identical by the CHT if they share the same compact hash code and their starting search positions are close enough to cause a linear probe to encounter a stored matching compact hash code before an empty cell is found. This property gives the CHT its probabilistic nature, in that two types of false-positive query results are possible: either (a) a key that was not inserted can be reported as present in the table or (b) the values of two keys can be confused with each other. In Kraken 2, the former error is indeed a false positive, whereas the latter results in a less specific LCA being assigned to the minimizer (Additional file 2 : Figure S3). The probability of either of these errors is &lt; 1% with Kraken 2’s default load factor of 70% (Additional file 2 : Figure S4). The adverse effect on read-level classification is further mitigated by the algorithm Kraken 2 uses to combine information from across the read, which is unchanged from Kraken 1 and utilizes information from all k -mers in a sequence to counteract low-frequency erroneous LCA values that could be returned by a key-value store<anchor xml:id="a28"/>.</p>
        <p><anchor xml:id="a29"/>The probabilistic nature and comparisons involving parts of a key’s hash code make the CHT similar to the counting quotient filter (CQF) described by Pandey et al. [ 24 ] Like the CQF, Kraken 2’s CHT features high locality of memory access during an individual query due to the linear probing that the CHT employs. Unlike the CQF, however, our CHT does not allow the full hash code to be recovered from a stored value (the CQF’s remainder ), and so we are unable to resize a CHT once it is instantiated. Additionally, our CHT has an additional possibility of error compared to the CQF, where two keys that do not have the same full hash code but share a truncated hash code will be treated as identical. The CQF can avoid such “soft” hash collisions<anchor xml:id="a30"/>.</p>
        <p>Internal taxonomy of a Kraken 2 database</p>
        <p><anchor xml:id="a31"/>While Kraken 1 used the taxonomy provided by the user without modification, Kraken 2 makes some modifications to its internal representation of the taxonomy that causes that representation to differ from the user-provided taxonomy. First, Kraken 2 finds a minimal set of nodes in the user-provided taxonomy. This minimal set consists of all nodes to which a reference sequence is assigned, as well as all of those nodes’ ancestors; vertices between nodes in this set remain as they were in the user-provided taxonomy, maintaining the tree structure in the internal representation. Kraken 2 then assigns nodes in the minimal set sequentially increasing internal taxonomy ID numbers using a breadth-first search (BFS) beginning at the root, with the root having an internal ID number of 1. This BFS provides a guarantee that ancestor nodes will have smaller internal ID numbers than their descendants; an example of this numbering is shown in Additional file 2 : Figure S3. Kraken 2 stores a mapping of its internal taxonomy numbers to the external taxonomy ID numbers to make its results more easily interpretable, and performs all output using the external taxonomy ID numbers<anchor xml:id="a32"/>.</p>
        <p><anchor xml:id="a33"/>Kraken 2’s use of this internal taxonomy representation allows for the easier computation of the LCA of two nodes because the ID numbers themselves give information as to their relative depths in the tree, while the National Center for Biotechnology Information (NCBI) taxonomy IDs lack this property. The internal taxonomy representation also allows Kraken 2 to use the minimal number of bits for storage of taxonomy ID numbers, giving maximal space for the compact hash codes and reducing the probability of CHT errors<anchor xml:id="a34"/> (or “hash table collisions,” as we describe elsewhere in this paper).</p>
        <p><anchor xml:id="a35"/>A Kraken 2 database consists of a CHT and this internal taxonomy representation. Typical databases will be built using the NCBI taxonomy [ 27 ], but users can override this default to create custom databases for atypical use cases<anchor xml:id="a36"/>.</p>
        <p><anchor xml:id="a37"/>Minimizer-based subsampling</p>
        <p><anchor xml:id="a38"/>In contrast to Kraken 1’s use of all k -mers in the standard use case, Kraken 2 subsamples the set of genomic substrings and inserts only the distinct minimizers into its database (Fig. 1 b). We define the ℓ bp minimizer of a k -mer ( ℓ ≤ k ) to be the lexicographically smallest canonical ℓ -mer found within the k -mer. An ℓ -mer is called canonical if it is lexicographically less than or equal to its reverse complement. Note that if k = ℓ , no subsampling occurs and Kraken 2 inserts the same substrings into its data structure that Kraken 1 would. Additionally, as the difference between k and ℓ grows, fewer substrings are inserted into the CHT, reducing its size along with Kraken 2’s memory usage and runtime (Fig. 1 d, Additional file 1 : Table S2). The default values for Kraken 2, k = 35 and ℓ = 31, were determined after the analysis of the parameter sweep results we show in Additional file 1 : Table S2<anchor xml:id="a39"/>.</p>
        <p><anchor xml:id="a40"/>Kraken 2 determines which ℓ -mers are minimizers by the use of a sliding window minimum algorithm<anchor xml:id="a41"/>, in contrast to Kraken 1’s implementation which examined each k- mer anew. This allows for a faster determination of minimizers, as less work is required when moving from one k- mer to the next overlapping k- mer (in terms of computational complexity, the new approach uses an average of O (1) time to calculate a new minimizer vs. Θ ( k ) time with the older algorithm). <anchor xml:id="a42"/>The sliding window minimum calculation uses a double-ended queue (or “deque”) in which canonicalized candidate ℓ -mers are inserted in the back, along with the candidates’ position in the original sequence. As a new candidate is encountered, enqueued candidates are removed from the back of the deque until the candidate at the back has a greater value than the new candidate (as determined by lexicographical ordering). The new candidate is then pushed onto the back of the deque<anchor xml:id="a43"/>.</p>
        <p>Once a k- mer’s worth of ℓ -mers has been processed in this way, the front of the deque contains the minimizer of that k- mer. This property is then maintained during scanning subsequent bases by removing the front element in the deque if it is from a position in the original sequence that is not in the current k- mer. In this way, the front element of the deque holds the minimizer of the k- mer currently being examined.</p>
        <p>We further augmented the sliding window algorithm to include the exclusive or (XOR) shuffling operation from Kraken 1. This operation serves to permute the ordering of the ℓ -mers when calculating minimizers and helps to avoid a bias toward low-complexity ℓ -mers when selecting the minimizer of a k -mer [ 4 , 15 ]. To shuffle, we calculate the XOR value of the ℓ -mer and a predefined constant and use this value as the “candidate” that is put in the deque. When the original ℓ -mer value is needed again, the operation is reversed by XORing a second time with the same constant.</p>
        <p>Spaced seed usage</p>
        <p><anchor xml:id="a44"/>Spaced k -mers, a similar concept to spaced seeds, have been shown to improve the ability to classify reads within the Kraken framework [ 28 ]. Kraken 2 uses a simple spaced seed approach where a user specifies an integer s when building a database that indicates how many positions in the minimizer will be masked (i.e., not considered when searching). Beginning with the next-to-rightmost position in the minimizer, every other position is masked until s positions have been masked. For example, if s = 3 and ℓ = 12, the positions in the bit string 1111 1101 0101 with a “0” would be masked. When using Kraken 2, Kraken 1’s classification results can be most closely approximated by setting k = ℓ = 31 and s = 0, as these settings will avoid any minimizer-based subsampling and spaced seed usage. Kraken 2’s default value for s is 7 and was determined after the analysis of the parameter sweep results we show in Additional file 1 : Table S2.</p>
        <p>The canonical ℓ -mers that are minimizer candidates are masked with the spaced seed mask prior to their insertion into the deque for the sliding window calculation. By performing canonicalization of the minimizer candidates prior to applying the spaced seed mask, we ensure the result is the same whether applied to the ℓ -mer or its reverse complement<anchor xml:id="a45"/>.</p>
        <p><anchor xml:id="a46"/>Kraken 1’s sensitivity performance was governed by the value of k (the length of the searched substring). By comparison, the use of spaced seeds and minimizer-based subsampling means that Kraken 2’s sensitivity performance will be largely governed by ℓ - s (the number of compared bases in Kraken 2’s searched substring). Thus, increasing s will generally increase sensitivity while decreasing positive predictive value<anchor xml:id="a47"/> (Fig. 1 e, Additional file 1 : Table S2).</p>
        <p><anchor xml:id="a48"/>Hash-based subsampling</p>
        <p><anchor xml:id="a49"/>Kraken 2 estimates the required capacity of the hash table given the k , ℓ , and s values chosen along with the sequence data in a database’s reference genomic library. Some users will not have access to large memory computers, and therefore, this estimate may be greater than the maximum possible hash table size that they can work with. To aid such users, Kraken 2 allows them to specify a maximum size when building a database. If the estimated required capacity is larger than the maximum requested size, then the minimizers will be subsampled further using a hash function. Given an estimated required capacity S ′ and a maximum user-specified capacity of S ( S &lt; S ′), we can calculate the value f = S / S ′, which is the fraction of available minimizers that the user will be able to hold in their database. A minimum allowable hash value of v = (1 − f )∙ M can also be calculated, where M is the maximum value output by hash function h . Any minimizer in the reference library with a hash code less than v will not be inserted into the hash table. This value v is also provided to the classifier so that only minimizers with hash codes greater than or equal to v will be used to probe the hash table, saving the search failure runtime penalty<anchor xml:id="a50"/> that would be incurred by searching for minimizers guaranteed not to be in the hash table.</p>
        <p>Evaluation of k -mer level discordance rates</p>
        <p><anchor xml:id="a51"/>At a k -mer level, there are two main types of discordance between Kraken 1 and Kraken 2’s results: those caused by two distinct k -mers sharing the same minimizer (a “minimizer collision”) and those caused by two distinct minimizers being indistinguishable by the CHT (a “hash table collision”). Minimizer collisions are not always damaging. When it occurs between k -mers from very closely related genomes, such a collision might detect true homology even in the face of single nucleotide polymorphisms and/or sequencing error. That said, minimizer collisions between k -mers from distantly related genomes could produce either elevated LCA values (if both genomes are in the reference library) or incorrectly classified k -mers (if one of the genomes is not in the reference library). Hash table collisions are a consequence of the probabilistic nature of the CHT and can also cause either elevated LCA values or incorrectly classified k -mers (Additional file 2 : Figure S3). We note that these different discordant results are all at a k -mer level and may not always affect a query sequence’s classification due to the many k -mers’ worth of data that are used to classify a query sequence; aside from slight modifications to handle the subsampling methods we use in Kraken 2, the classification method of Kraken 2 is identical to Kraken 1<anchor xml:id="a52"/>.</p>
        <p>We wished to estimate the rate at which these collisions would cause discordance at a k -mer level between the Kraken 1 and Kraken 2 results. To do so, we selected a specific bacterial genome for which we had neighboring genomes at each taxonomic rank from species to phylum. The selected genome was our “reference sequence,” and eight others were progressively more taxonomically distant from the reference sequence. We list the nine genomes used in these experiments in Additional file 1 : Table S6. We additionally created a synthetic genome with 4 Mbp of uniformly random DNA. Together, these ten sequences formed a set of “query sequences” and were the basis for our evaluation of collision rates. For these experiments, we used the default Kraken 2 values of k = 35, ℓ = 31, and s = 7, unless otherwise noted.</p>
        <p>To determine the rates of discordance caused by minimizer collisions, we compared each of the ten query sequences’ k -mers to the set of reference sequence k -mers. For each sequence, the minimizer collision rate is the proportion of distinct k -mers in a query sequence that (a) are not in the set of reference sequence k -mers and (b) share a minimizer with a reference sequence k -mer. The various sequences’ minimizer collision rates are summarized in Additional file 1 : Table S7. We hypothesized that the minimizer collision rate would be influenced by the length of the minimizer used, due to the length’s direct relationship to the number of possible minimizers. To test this, we repeated the minimizer collision rate estimation experiment focusing on the reference genome and using the random synthetic genome as the sole query sequence. Setting k = 35 and s = 0, we varied the ℓ parameter from 8 to 31. Minimizer lengths greater than 15 had collision rates under 1%. Minimizer lengths greater than 22 had 0 collisions. The full results are shown in Additional file 2 : Figure S5.</p>
        <p>To determine the rates of discordance caused by hash table collisions, we compared each of the ten query sequences’ minimizers to a CHT populated with the reference sequence minimizers. The CHT was created with a load factor of 70% and 15 bits reserved for the truncated hash code (the same parameters used in Kraken 2’s standard database in September 2018). For each sequence, the hash table collision rate is the proportion of distinct minimizers in a query sequence that (a) are not minimizers in the set of reference sequence minimizers and (b) are reported by the CHT as being inserted in the hash table. The various sequences’ hash table collision rates are summarized in Additional file 1 : Table S8. To investigate the impact of load factor and truncated hash code size on hash table collision rates, we repeated the hash table collision rate experiment, but focused only on the reference genome and used the random synthetic genome as the sole query sequence. We used the same default values of k , ℓ , and s as before (35, 31, and 7, respectively) and calculated hash table collision rates while varying both the load factor and truncated hash code size. The impact of these two parameters on hash table collision rates is shown in Additional file 2 : Figure S4. The parameters adopted for Kraken 2’s default mode had an error rate of 0.016%, consistent with the results seen when comparing genomes of different species (Additional file 1 : Table S8).</p>
        <p>Processing of a standard genomic reference library</p>
        <p>The CHT’s modest memory requirements, and the additional savings yielded by minimizer-based subsampling, allow more reference genomic data to be included in Kraken 2’s standard reference library. Whereas Kraken 1’s default database had data from archeal, bacterial, and viral genomes, Kraken 2’s default database additionally includes the GRCh38 assembly of the human genome [ 29 ] and the “UniVec_Core” subset of the UniVec database [ 30 ]. We include these in Kraken 2’s default database to allow for easier classification of human microbiome reads and more accurate classification of reads containing vector sequences.</p>
        <p><anchor xml:id="a53"/>Additionally, we have implemented masking of low-complexity sequences from reference sequences in Kraken 2, by using the “dustmasker” [ 31 ] (for nucleotide sequences) and “segmasker” [ 32 ] (for protein sequences) tools from NCBI. Using the tools’ default settings, nucleotide and protein sequences are checked for low-complexity regions, and those regions identified are masked and not processed further by the Kraken 2 database building process. In this manner, we seek to reduce false positives resulting from these low-complexity sequences, similar to the build process for Centrifuge<anchor xml:id="a54"/> [ 1 ].</p>
        <p>Populating the Kraken 2 hash table</p>
        <p>Kraken 2 begins building a CHT by first estimating the number of distinct minimizers present in the reference library for the selected values of k , ℓ , and s . This is done through a form of zeroth frequency moment estimation [ 33 ] where Kraken 2 creates a small set structure implemented with a traditional hash table. In this set Q , we insert only the distinct minimizers that satisfy the criterion h ( m ) mod F &lt; E , where h ( m ) is the hash code of the minimizer m and E ≪ F (in practice, Kraken 2 uses E = 4 and F = 1024). We then find the estimate of the total number of distinct minimizers by multiplying the number of satisfactory distinct minimizers (| Q |) by F / E . This form of estimation requires storing in memory only a fraction of all distinct minimizers (approximately E / F ) and allows us to quickly set the capacity of our CHT properly without needing to first store all elements in it.</p>
        <p>After estimating the number of distinct minimizers D = | Q |( F / E ) present in the reference library, Kraken 2 then allocates memory for a CHT containing D /0.7 hash table cells. We selected the divisor of 0.7 so that the resultant hash table will have approximately 30% of its cells remain empty after the population of the CHT (i.e., the CHT will have a load factor of 70%). As stated earlier, the cells of this table are 32 bits each, and so the total memory required for Kraken 2’s CHT is 32 D /0.7 bits or 4 D /0.7 bytes.</p>
        <p>Kraken 2 then proceeds to scan each genome in the reference library. Each genome must be associated with a taxonomic ID number so that Kraken 2 can calculate LCA values; genomes without associated taxonomy IDs are therefore not processed by Kraken 2. For a minimizer M in a genome G, Kraken 2 attempts to insert a key-value pair containing M (key) and the taxonomic ID T (value) associated with G into the CHT. If the CHT does not report that M was previously inserted, then the &lt; M , T &gt; key-value pair will be inserted, indicating that the LCA of M is currently T . If M was previously inserted into the CHT, with LCA value T* , then its associated LCA value is updated to equal the LCA of T and T* . All minimizers are processed in this way; once the reference library’s minimizers are all processed, the LCA values are properly set for each of the minimizers and the database build is complete. The LCA operation is both commutative and associative, facilitating parallel index construction.</p>
        <p>Classification of a sequence fragment with Kraken 2</p>
        <p><anchor xml:id="a55"/>Kraken 2 classifies sequence fragments similarly to Kraken 1, with modifications to facilitate minimizer- and hash-based subsampling. For each k -mer in an input sequence, Kraken 2 finds its minimizer and, if it is distinct from the previous k -mer’s minimizer, uses it as a key to probe the CHT. If the minimizer matches a key in the CHT, Kraken 2 considers the associated LCA value to be the k -mer’s LCA (Fig. 1 b). Classification then proceeds in the same manner as Kraken 1, taking note of how many k -mer hits mapped to each taxon, constructing a pruned classification tree, and using the leaf of the maximally scoring root-to-leaf path of that tree to classify the sequence [ 4 ]. If hash-based subsampling was used to build the CHT, each minimizer has its hash code compared against the table’s maximum allowable hash code, and minimizers with higher-than-allowed hash codes are not searched against the CHT. Any k -mer containing an ambiguous nucleotide code is also not searched against the CHT<anchor xml:id="a56"/>.</p>
        <p>We note that although Kraken 2 only uses the minimizer to query the CHT, the LCA found via this query is assigned by Kraken 2 to the k -mer rather than only the minimizer. This means that a stretch of n overlapping k -mers that share a minimizer will all be assigned the same LCA value by Kraken 2 and that n hits to that LCA will be part of the classification tree, even though only one distinct minimizer was present among the k -mers.</p>
        <p>Parsing of input files</p>
        <p>Previous work by Langmead et al. [ 17 ] <anchor xml:id="a57"/>has shown the importance of removing parsing work from critical sections, i.e., portions of the program that can be executed by only 1 thread at a time. Kraken 2 uses 2 different methods to defer a majority of parsing work from the critical section to thread-local execution. The first method (referred to as “batch deferred” parsing by Langmead et al.) reads a set number of lines (40,000 in Kraken 2) of input in a thread-local buffer within the critical section and then parses the input within a single thread’s execution. This method is used to perform reading of paired-end FASTQ input, where the lengths of a fragment’s mates can be different and reading a consistent number of lines from both input files is necessary to ensure a thread is working with complete mate pairs. For FASTA or single-end FASTQ input, Kraken 2 instead uses a more efficient method that reads in a set number of bytes (3 MB in Kraken 2) of input into a thread-local buffer within the critical section and continues reading input into that buffer until a record boundary is found, at which point a thread leaves the critical section and parses its input. These modifications allow Kraken 2 to more efficiently use multiple threads than did Kraken 1<anchor xml:id="a58"/> (Additional file 1 : Table S4).</p>
        <p>Translated search</p>
        <p><anchor xml:id="a59"/>To perform a translated search, Kraken 2X first builds a database from a set of reference proteins in the same manner that Kraken 2 does for nucleotide sequences. The usual alphabet of 20 amino acids is reduced to 15 using the 15-character alphabet of Solis [ 34 ]; we add a single additional value representing selenocysteine, pyrrolysine, and translation termination (stop codons). This gives us 16 characters in our reduced alphabet, allowing us to represent a character with 4 bits. Minimizers of reference proteins are calculated using the same methods for nucleotide sequences (i.e., using spaced seeds if requested and a sliding window minimum algorithm), but reverse complements are not calculated and by default k = 15, ℓ = 12, and s = 0.</p>
        <p>When searching against a protein minimizer database, Kraken 2X translates all six reading frames of the input query DNA sequences into the reduced amino acid alphabet. Minimizers from all six frames are pooled and used to query the CHT, and therefore, all contribute to the Kraken 2X classification of a query sequence<anchor xml:id="a60"/>.</p>
        <p>Generation of data for strain exclusion experiments</p>
        <p>We downloaded the reference genome and protein data used for the clade exclusion experiments from NCBI in January 2018 from the archaeal, bacterial, and viral domains. We also downloaded the taxonomy from NCBI at this same time. Using the taxonomy ID information for each sequence, we obtained a set of all taxonomy IDs represented by the reference genomes. From this set, we selected a subset of “eligible strains” that had both two sister sub-species taxa present and two sister species taxa present in the set of reference genomes. We selected this subset by examining only those nucleotide sequences with the phrase “complete genome” in their FASTA record header but excluding those that were plasmids or second or third chromosomes. In this manner, we sought to ensure we did not count a genome multiple times due to multiple sequences being associated with that genome. From the eligible strain subset, 40 prokaryotic taxonomy IDs and 10 viral taxonomy IDs were selected arbitrarily to be the strains of origin for our experiments. The strains selected are listed in Additional file 1 : Table S3.</p>
        <p>After selecting the taxonomy IDs that represented the strains of origin, we gathered all of the nucleotide sequences we had downloaded—including chromosome and plasmid sequences excluded from our examination when creating the eligible strain subset—into a single file and did the same for the protein sequences. For both the nucleotide and protein files, we placed sequences with taxonomy IDs that were outside the strains of origin into a strain exclusion reference file. Then, for each taxonomy ID in our strain of origin set, we created a single “strain reference” file containing all nucleotide sequences that were associated with that taxonomy ID.</p>
        <p>We used Mason 2 [ 35 ] to simulate 100-bp paired-end Illumina sequence data from our strains of origin, with 500,000 fragments being simulated from each strain. When simulating the reads, we used the default options for simulating sequencing errors with Mason 2’s “mason_simulator” command. These defaults caused the simulator to simulate sequencing errors at rates of 0.4% for mismatches, 0.005% for insertions, and 0.005% for deletions. We combined simulated reads from the strains of origin into a single set of read data. We also shuffled the order of the fragments in this set to control for ordering effects that might affect runtime.</p>
        <p>Execution of strain exclusion experiments</p>
        <p>To evaluate the accuracy and computational performance of Kraken 2, we compared it to Kraken 1 and several other programs. In selecting these programs, we concentrated on three main properties. First, because Kraken’s principal aim is to provide high-speed taxonomic sequence classification, we looked for taxonomic sequence classification tools that were high in classification speed (within approximately an order of magnitude of Kraken 1). Secondly, because our experiments rely on holding fixed the reference data between programs, we selected tools which had the ability to customize the underlying reference sequence set and taxonomy using whole-genome reference data. These two requirements led to our selection of KrakenUniq, CLARK, Centrifuge, and Kaiju as comparator programs. We note that these requirements exclude an accuracy evaluation against programs that are not taxonomic sequence classifiers (programs that output a mapping of sequences to taxa). Sequence abundance estimation programs (which map taxa to sequence counts or frequencies), such as Bracken, and population abundance estimation programs (which map taxa to organism counts or frequencies), such as MetaPhlAn [ 36 ], are answering related but different problems than those in our comparator set. For example, Bracken does not actually change any of the taxonomic labels associated with the sequenced fragments but rather adjusts the fragment counts associated with low-rank taxa. We also note that although MetaPhlAn does, as part of its operation, classify a small proportion of reads that map to marker genes, this proportion can be less than 10% of reads [ 6 ] in whole-genome shotgun metagenomic experiments (such as ours), and thus, MetaPhlAn would yield far lower per-sequence sensitivity relative to the tools in our comparison.</p>
        <p>In brief, we used the nucleotide search-based classification programs (Kraken 1, KrakenUniq, Kraken 2, CLARK, and Centrifuge) to build a strain-exclusion database from reference genomes, and we used the translated search-based classification programs (Kraken 2X and Kaiju) to build a strain-exclusion database from reference protein sequences. We compared Kraken 2 and Kraken 2X (both using the code base from Kraken 2.0.8) against Kraken 1.1.1, KrakenUniq 0.5.6, CLARK 1.2.4, Centrifuge 1.0.3-beta, and Kaiju 1.5.0. Because CLARK requires a rank to be specified at the time of building a database, and our evaluations center on genus-rank accuracy, we built a CLARK database for the genus rank for our evaluation work in this paper.</p>
        <p>Classifiers received the simulated read data as paired-end FASTQ input. To evaluate runtime and memory usage, we sought to eliminate the performance impact of reading or writing from disk or from a network storage location. To accomplish this, we copied simulated read data and classifier databases onto a random access memory (RAM) filesystem and directed the classifiers to read input from and write output to that RAM filesystem.</p>
        <p>Accuracy was evaluated on a smaller subset of the simulated data containing 1000 fragments per genome of origin or 50,000 fragments in total. To obtain processing speed and memory usage information, we ran each classifier using 16 threads on 25 million sequences’ worth of simulated read data. We used the taskset command to restrict each classifier to the appropriate number of processors (e.g., “taskset -c 0-15” was used with our 16 thread experiments); this ensures that a classifier that uses an external process to aid in its execution has that process’ runtime properly counted against its runtime here. The “/usr/bin/time -v” command provided us with elapsed wall clock time and maximum resident set size data (memory usage) for each experiment and allowed us to verify that no major page faults were incurred by a classifier during its execution (the absence of which indicates minimal disk- or network-related input/output effects on the runtime). Classifiers were run on a computer with 32 Xeon 2.3 GHz CPUs (16 hyperthreaded cores) and 244 GB of RAM.</p>
        <p>Evaluation of accuracy in strain exclusion experiments</p>
        <p><anchor xml:id="a61"/>We evaluated the accuracy of each classifier at a per-fragment level, with respect to a particular taxonomic rank. Each fragment had a known true subspecies taxon of origin, which implied a true taxon of origin at both the species and genus ranks, which is where we measured accuracy. We now describe how we counted true-positive (TP), false-negative (FN), vague positive (VP), and false-positive (FP) results at the genus and species levels. We describe this at the genus level specifically, but the analogous procedure was also used at the species level. For a given true genus of origin, a TP classification is a classification at that genus or at a descendant of that genus. Because we excluded the strains of origin from our reference databases, we expected all classifiers to make incorrect strain-level classifications and so allow classifications of descendants of the true genus to be judged as TP. We define an FN classification as a failure of a classifier to assign any classification to a sequence and a VP classification as a classification at an ancestor of the true genus of origin. Finally, we define an FP classification as a classification that is incorrect, that is, not at the true genus of origin nor an ancestor or descendant of that true genus. These four categories are mutually exclusive, and all fragments run through a classifier will have their classification<anchor xml:id="a62"/> (or lack thereof) categorized by one of these categories.</p>
        <p>These categories are different from those typically used for binary classification problems; they are used here because these methods can make classifications that are not at leaves of the taxonomic tree but are still correct. For example, a classification of an Escherichia coli fragment as Escherichia would be evaluated as TP for genus-rank accuracy, but as VP for species-rank accuracy. Classification of that same fragment as Vibrio would be evaluated as FP at any rank below class (because the LCA of Vibrio and Escherichia is the class taxon Gammaproteobacteria) and would be evaluated as TP for the class rank and above.</p>
        <p><anchor xml:id="a63"/>Using these categories, we define rank-level sensitivity as the proportion of input fragments that were true-positive classifications, or TP/(TP + VP + FN + FP). We define rank-level positive predictive value (PPV) as the proportion of classifications that were true positives (excluding vague positives), or TP/(TP + FP). Along with these definitions of rank-level sensitivity and PPV, we also define an F1-measure as the harmonic mean of those two values<anchor xml:id="a64"/>.</p>
        <p>Evaluation of thread scaling efficiency</p>
        <p>To evaluate Kraken 1’s and Kraken 2’s ability to efficiently use multiple threads, we performed an experiment using the strain exclusion databases and simulated read data we describe previously in this section. We ran both Kraken 1 and Kraken 2 on the same data using 1, 4, and 16 threads. The 2 programs were run once on the data as paired-end read data and once as single-end read data. Read data and Kraken database files were all placed on a RAM filesystem, and the “taskset” command was used to limit the classifier programs to only as many cores as the number of threads being used. These conditions mirror those of our main strain exclusion experiments, only varying the number of threads between the various runs of the classifiers. The results for this experiment are shown in Additional file 1 : Table S4. In short, Kraken 2 exhibits superior speedup with respect to the number of threads allocated compared to Kraken 1. This is especially true for paired-end reads.</p>
        <p>FDA-ARGOS experimental concordance evaluation</p>
        <p>The FDA-ARGOS (dAtabase for Reference Grade micrObial Sequences) project provides sequencing experiments for many microbial isolates [ 22 ]. We used the NCBI’s Sequence Read Archive [ 37 ] to find all 1392 experiments related to the FDA-ARGOS project (accession PRJNA231221). Because some tools are unable to properly process reads of differing lengths, we selected only those 263 experiments that were run on an Illumina HiSeq 4000 instrument and produced 151-bp reads. We then randomly selected 1 experiment from each genus to download and used reservoir sampling to select a subset of 10,000 paired-end fragments from each selected experiment. We also removed experiments for which our strain-exclusion reference genome set did not have a reference genome of the same species as the sequenced isolate. These steps yielded 25 experiments’ worth of data, for 250,000 paired-end fragments in total. Using the strain-exclusion databases created earlier, we then used each classifier to classify the data and examined the percentage of each experiment’s fragments that were classified.</p>
        <p><anchor xml:id="a65"/>Because the FDA-ARGOS data are from real sequencing experiments, several factors could explain discordance between a classifier’s results and the experiments’ assigned taxa, including the evolutionary distance between sequences and reference data, low-quality sequencing runs, and contamination. The true causes of such discordance may not be discernable, and even when they are, they often require an in-depth examination of the sequencing and reference data. For these reasons, we do not report sensitivity and PPV for these data because we cannot be certain of the true taxonomic origin of each individual fragment of real sequencing data. Rather, we evaluated the concordance of the SRA-assigned taxa with the fragments’ classifications at the genus rank and report for each classifier the following quantities: (a) the percentage of fragments with a concordant classification at the genus rank, (b) the percentage of fragments with a discordant classification at the genus rank, (c) the percentage of fragments with a classification of an ancestor of the SRA-assigned genus taxon, and (d) the percentage of fragments that were not classified. The results of this concordance evaluation are provided in full in Additional file 1 : Table S5<anchor xml:id="a66"/>.</p>
        <p>Parameter sweeps</p>
        <p><anchor xml:id="a67"/>We examined various values for parameters to ensure Kraken 2’s default parameters would provide an advantageous balance of accuracy, classification speed, and memory usage. Specifically, we looked at parameters relating to minimizer-based subsampling ( k and ℓ ), hash-based subsampling ( f = S / S′ ), and spaced seed usage ( s ). For Kraken 2, we performed two parameter sweeps, with one focused on minimizer-based subsampling and one focused on hash-based subsampling. The first parameter sweep looked at values for ℓ in the interval [ 25 , 31 ], values for k in the interval [ ℓ , ℓ + 10], and values for s in the interval [0, 7]; the second parameter sweep looked at values of ℓ in the interval [ 25 , 31 ], fixed k = ℓ , values for f in the set {0.125, 0.25, 0.5}, and values for s in the interval [0, 7]. We also performed a third parameter sweep, focused on translated search (Kraken 2X), where we looked at values for ℓ in the interval [ 11 , 15 ], values for k in the interval [ ℓ , ℓ + 3], and values for s in the interval [0, 3].</p>
        <p>Each parameter sweep used the strain exclusion data that we previously created to build databases, and we used the same accuracy and timing methods for these databases that we did in the cross-classifier comparison. The results of the first two parameter sweeps, run on nucleotide databases, are provided in Additional file 1 : Table S2, while the results of the third parameter sweep, run on protein databases, are provided in Additional file 1 : Table S9. We note that the parameter sweeps yielded a large number of parameter combinations giving approximately the same, near-optimal levels of accuracy. This suggests performance is not overly sensitive to particular parameter settings<anchor xml:id="a68"/>.</p>
        <p>Evaluation of database sizes of Kraken 1 and Kraken 2</p>
        <p>We began by shuffling the reference DNA sequences in our strain exclusion set and recorded the total number of bases in each sequence. We modified Kraken 2’s capacity estimator to report an estimate of the number of distinct minimizers after each sequence processed, rather than only after all sequences are processed. Finally, we ran the capacity estimator twice on the shuffled genomic data, once with k = 31, ℓ = 31, s = 0 (corresponding to Kraken 1’s defaults—effectively counting the number of distinct k -mers) and again with k = 35, ℓ = 31, s = 7 (Kraken 2’s defaults).</p>
        <p>The size of a Kraken 1 database is a function of the number of distinct k -mers in the reference data. If there are X distinct k -mers, the size of Kraken 1’s database.kdb (sorted list of k -mer/LCA pairs) file will be 1072 + 12 X bytes; the 1072-byte term is the size of the Jellyfish/Kraken header data, and 12 bytes are used for each k -mer/LCA pair. The database.idx (minimizer offset index) file is 8,589,934,608 bytes, a function of Kraken 1’s default minimizer length of 15. The full database size is the sum of the sizes of those two files.</p>
        <p>Similarly, the size of a Kraken 2 hash table is a function of the estimate of the number of distinct minimizers in the reference data. If there are an estimated Y distinct minimizers, Kraken 2’s hash table will be 32 + ⌊4 Y /0.7⌋ bytes in size (representing 32 bytes of metadata and using 4 bytes per cell and a load factor of 0.7).</p>
        <p>We used the estimates of the numbers of distinct k -mers and distinct minimizers to calculate the database sizes of Kraken 1 and Kraken 2 for successively larger subsets of the strain exclusion set. The results of this evaluation are shown in Additional file 2 : Figure S1, with raw data available in Additional file 1 : Table S10.</p>
        <p><anchor xml:id="a69"/>Reviewing the results when all genomic sequences were added, our results indicate that the number of distinct k -mers is approximately 3.1 times the number of distinct minimizers for the settings we have selected for Kraken 1 and Kraken 2. It is not possible to draw a direct relationship between the number of distinct k -mers or minimizers and the number of sequence bases processed. For example, homology between similar strains and species will cause the number of distinct k -mers/minimizers to grow slower than the total number of bases. Examining the linear-term coefficients from the database-size expressions (12 X and 4 Y /0.7) indicates a Kraken 2 database will be approximately 15% of the size of a Kraken 1 database of the same reference data; this is because X ≈ 3.1 Y , and (4/0.7)/(12 × 3.1) = 0.15. When we examine the full reference set, the 15% estimate is consistent with the ratio of Kraken 2’s hash table size (10.456 GB) to Kraken 1’s database.kdb file size (77.490 − 8.589 = 68.901 GB), which is 10.456/68.901 = 0.152<anchor xml:id="a70"/>.</p>
        <p>Bracken experiments on strain exclusion data</p>
        <p>We first generated Bracken metadata from each of the Kraken 1 and Kraken 2 reference libraries used in the strain exclusion experiments. We then used Bracken to estimate genus- and species-level abundance from the Kraken 1 and Kraken 2 classification results on the prokaryotic strain exclusion read data. Due to the low sequence similarity between our simulated viral reads and the strain-exclusion reference data, none of the nucleotide search programs exhibited high sensitivity on these reads, including Kraken 1 and Kraken 2. Such low classification rates prevent Bracken from inferring taxonomy for a large proportion of the viral reads. Additionally, the taxonomy for viruses has several examples where species are not grouped by ancestry and lack similarity in both gene organization and genomic sequence [ 38 ]. For these reasons, we chose to exclude the simulated viral reads from our analysis of Bracken.</p>
        <p>For overall evaluation of the accuracy of Bracken in these strain exclusion experiments, we calculated the mean absolute percentage error (MAPE):</p>
        <p>where S x is the estimated number of reads and T x is the true number of reads for taxon x . In this strain exclusion experiment, n = 40, the total number of distinct prokaryotic species and genera in the sample and T x = 1000 for each taxon.</p>
        <p>Supplementary information</p>
        <p>Additional file 1: Table S1. Comparison of accuracy and computational performance. Table S2. Comparison of Kraken 2 with other classifiers, using various parameter values. Table S3. Genomes excluded in strain-exclusion simulation. Table S4. Thread scaling evaluation results. Table S5. Evaluation of FDA-ARGOS sequencing data. Table S6. Sequences used for evaluation of collision rates. Table S7. Minimizer collision evaluation results. Table S8. Hash table collision evaluation results. Table S9. Comparison of Kraken 2X with other classifiers, using various parameter values. Table S10. Database size evaluation results.</p>
        <p>Additional file 2: Figure. S1. Estimation of database sizes for Kraken 1 and Kraken 2 as sequences are added to the reference set. Figure S2. Bracken performance on strain exclusion simulated prokaryotic data. Figure S3. Examples of compact hash table usage with Kraken 2. Figure S4. Evaluation of compact hash table error rates as a function of two variables. Figure S5. Evaluation of minimizer collision rates as a function of minimizer length.</p>
        <p>Additional file 3: Review history.</p>
        <p>Acknowledgements</p>
        <p>The authors would like to thank James R. White and Steven Salzberg for the helpful discussions about the manuscript.</p>
        <p>Peer review information</p>
        <p>Barbara Cheifet was the primary editor of this article and managed its editorial process and peer review in collaboration with the rest of the editorial team.</p>
        <p>Review history</p>
        <p>The review history is available as Additional file 3 .</p>
        <p>Authors’ contributions</p>
        <p>DEW and BL designed the algorithms for Kraken 2. DEW developed the Kraken 2 software. DEW, JL, and BL designed the experiments. DEW and JL performed the experiments. DEW, JL, and BL prepared and reviewed the manuscript. All authors read and approved the final manuscript.</p>
        <p>Funding</p>
        <p>BL and DEW were supported by NSF grant IIS-1349906. BL was additionally supported by NIH grant R01-GM118568. JL was supported by NIH grant R35-GM130151.</p>
        <p>Availability of data and materials</p>
        <p>We have made the data for our strain exclusion experiments publicly available for download, including all reference sequences, taxonomy, and simulated read data [ 39 ]. Code to generate all databases from these reference sequences, to generate simulated read data, and to run the comparison of classifiers’ accuracy and performance is also available for public download in a GitHub repository [ 40 ] and via permanent storage at 10.5281/zenodo.3520278 .</p>
        <p>Kraken 2’s source code is open-source, licensed under the MIT License, and available in a GitHub repository [ 41 ]. The specific version of Kraken 2 evaluated here, version 2.0.8, is also permanently available at 10.5281/zenodo.3520272.</p>
        <p>Ethics approval and consent to participate</p>
        <p>Not applicable.</p>
        <p>Consent for publication</p>
        <p>Not applicable.</p>
        <p>Competing interests</p>
        <p>The authors declare that they have no competing interests.</p>
        <p>Footnotes</p>
        <p>Supplementary information</p>
        <p>Supplementary information accompanies this paper at 10.1186/s13059-019-1891-0.</p>
        <p>References</p>
        <p>Associated Data</p>
        <p>Supplementary Materials</p>
        <p>Additional file 1: Table S1. Comparison of accuracy and computational performance. Table S2. Comparison of Kraken 2 with other classifiers, using various parameter values. Table S3. Genomes excluded in strain-exclusion simulation. Table S4. Thread scaling evaluation results. Table S5. Evaluation of FDA-ARGOS sequencing data. Table S6. Sequences used for evaluation of collision rates. Table S7. Minimizer collision evaluation results. Table S8. Hash table collision evaluation results. Table S9. Comparison of Kraken 2X with other classifiers, using various parameter values. Table S10. Database size evaluation results.</p>
        <p>Additional file 2: Figure. S1. Estimation of database sizes for Kraken 1 and Kraken 2 as sequences are added to the reference set. Figure S2. Bracken performance on strain exclusion simulated prokaryotic data. Figure S3. Examples of compact hash table usage with Kraken 2. Figure S4. Evaluation of compact hash table error rates as a function of two variables. Figure S5. Evaluation of minimizer collision rates as a function of minimizer length.</p>
        <p>Additional file 3: Review history.</p>
        <p>Data Availability Statement</p>
        <p>We have made the data for our strain exclusion experiments publicly available for download, including all reference sequences, taxonomy, and simulated read data [ 39 ]. Code to generate all databases from these reference sequences, to generate simulated read data, and to run the comparison of classifiers’ accuracy and performance is also available for public download in a GitHub repository [ 40 ] and via permanent storage at 10.5281/zenodo.3520278 .</p>
        <p>Kraken 2’s source code is open-source, licensed under the MIT License, and available in a GitHub repository [ 41 ]. The specific version of Kraken 2 evaluated here, version 2.0.8, is also permanently available at 10.5281/zenodo.3520272.<anchor xml:id="a71"/></p>
    </body>
  </text>
</TEI>
