<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Publishing DTD v1.2 20190208//EN" "http://jats.nlm.nih.gov/publishing/1.2/JATS-journalpublishing1.dtd"><article xmlns:mml="http://www.w3.org/1998/Math/MathML" xmlns:xlink="http://www.w3.org/1999/xlink" article-type="other" dtd-version="1.2" xml:lang="en">
    <front>
        <journal-meta>
            <journal-id journal-id-type="pmc">F1000Research</journal-id>
            <journal-title-group>
                <journal-title>F1000Research</journal-title>
            </journal-title-group>
            <issn pub-type="epub">2046-1402</issn>
            <publisher>
                <publisher-name>F1000 Research Limited</publisher-name>
                <publisher-loc>London, UK</publisher-loc>
            </publisher>
        </journal-meta>
        <article-meta>
            <article-id pub-id-type="doi">10.12688/f1000research.179899.1</article-id>
            <article-categories>
                <subj-group subj-group-type="heading">
                    <subject>Software Tool Article</subject>
                </subj-group>
                <subj-group>
                    <subject>Articles</subject>
                </subj-group>
            </article-categories>
            <title-group>
                <article-title>TagGen: High-Performance Barcode Generator and Demultiplexer for High-Throughput and Long-Read Sequencing Applications</article-title>
                <fn-group content-type="pub-status">
                    <fn>
                        <p>[version 1; peer review: 1 not approved]</p>
                    </fn>
                </fn-group>
            </title-group>
            <contrib-group>
                <contrib contrib-type="author" corresp="no">
                    <name>
                        <surname>Chowdhury</surname>
                        <given-names>Faiza</given-names>
                    </name>
                    <role content-type="http://credit.niso.org/">Data Curation</role>
                    <role content-type="http://credit.niso.org/">Investigation</role>
                    <role content-type="http://credit.niso.org/">Visualization</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Original Draft Preparation</role>
                    <xref ref-type="aff" rid="a1">1</xref>
                </contrib>
                <contrib contrib-type="author" corresp="no">
                    <name>
                        <surname>Swain</surname>
                        <given-names>Tessa</given-names>
                    </name>
                    <role content-type="http://credit.niso.org/">Conceptualization</role>
                    <role content-type="http://credit.niso.org/">Validation</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Review &amp; Editing</role>
                    <uri content-type="orcid">https://orcid.org/0000-0003-2184-1717</uri>
                    <xref ref-type="aff" rid="a1">1</xref>
                </contrib>
                <contrib contrib-type="author" corresp="no">
                    <name>
                        <surname>Shirokikh</surname>
                        <given-names>Roderik</given-names>
                    </name>
                    <role content-type="http://credit.niso.org/">Validation</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Review &amp; Editing</role>
                    <xref ref-type="aff" rid="a1">1</xref>
                </contrib>
                <contrib contrib-type="author" corresp="no">
                    <name>
                        <surname>Rudler</surname>
                        <given-names>Danielle</given-names>
                    </name>
                    <role content-type="http://credit.niso.org/">Visualization</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Review &amp; Editing</role>
                    <xref ref-type="aff" rid="a1">1</xref>
                </contrib>
                <contrib contrib-type="author" corresp="no">
                    <name>
                        <surname>Fox</surname>
                        <given-names>Archa</given-names>
                    </name>
                    <role content-type="http://credit.niso.org/">Funding Acquisition</role>
                    <role content-type="http://credit.niso.org/">Supervision</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Review &amp; Editing</role>
                    <uri content-type="orcid">https://orcid.org/0000-0003-1962-270X</uri>
                    <xref ref-type="aff" rid="a1">1</xref>
                </contrib>
                <contrib contrib-type="author" corresp="yes">
                    <name>
                        <surname>Cleynen</surname>
                        <given-names>Alice</given-names>
                    </name>
                    <role content-type="http://credit.niso.org/">Conceptualization</role>
                    <role content-type="http://credit.niso.org/">Formal Analysis</role>
                    <role content-type="http://credit.niso.org/">Funding Acquisition</role>
                    <role content-type="http://credit.niso.org/">Methodology</role>
                    <role content-type="http://credit.niso.org/">Software</role>
                    <role content-type="http://credit.niso.org/">Supervision</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Original Draft Preparation</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Review &amp; Editing</role>
                    <xref ref-type="corresp" rid="c1">a</xref>
                    <xref ref-type="aff" rid="a2">2</xref>
                </contrib>
                <contrib contrib-type="author" corresp="yes">
                    <name>
                        <surname>Shirokikh</surname>
                        <given-names>Nikolay</given-names>
                    </name>
                    <role content-type="http://credit.niso.org/">Conceptualization</role>
                    <role content-type="http://credit.niso.org/">Data Curation</role>
                    <role content-type="http://credit.niso.org/">Formal Analysis</role>
                    <role content-type="http://credit.niso.org/">Funding Acquisition</role>
                    <role content-type="http://credit.niso.org/">Investigation</role>
                    <role content-type="http://credit.niso.org/">Methodology</role>
                    <role content-type="http://credit.niso.org/">Project Administration</role>
                    <role content-type="http://credit.niso.org/">Resources</role>
                    <role content-type="http://credit.niso.org/">Software</role>
                    <role content-type="http://credit.niso.org/">Supervision</role>
                    <role content-type="http://credit.niso.org/">Validation</role>
                    <role content-type="http://credit.niso.org/">Visualization</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Original Draft Preparation</role>
                    <role content-type="http://credit.niso.org/">Writing &#x2013; Review &amp; Editing</role>
                    <uri content-type="orcid">https://orcid.org/0000-0001-8249-358X</uri>
                    <xref ref-type="corresp" rid="c2">b</xref>
                    <xref ref-type="aff" rid="a1">1</xref>
                </contrib>
                <aff id="a1">
                    <label>1</label>School of Human Sciences, The University of Western Australia, Perth, WA, 6009, Australia</aff>
                <aff id="a2">
                    <label>2</label>France-Australia Mathematical Sciences and Interactions, CNRS International Research Laboratory, Canberra, ACT, 2601, Australia</aff>
            </contrib-group>
            <author-notes>
                <corresp id="c1">
                    <label>a</label>
                    <email xlink:href="mailto:alice.cleynen@cnrs.fr">alice.cleynen@cnrs.fr</email>
                </corresp>
                <corresp id="c2">
                    <label>b</label>
                    <email xlink:href="mailto:nikolay.shirokikh@anu.edu.au">nikolay.shirokikh@anu.edu.au</email>
                </corresp>
                <fn fn-type="conflict">
                    <p>No competing interests were disclosed.</p>
                </fn>
            </author-notes>
            <pub-date pub-type="epub">
                <day>30</day>
                <month>4</month>
                <year>2026</year>
            </pub-date>
            <pub-date pub-type="collection">
                <year>2026</year>
            </pub-date>
            <volume>15</volume>
            <elocation-id>642</elocation-id>
            <history>
                <date date-type="accepted">
                    <day>13</day>
                    <month>4</month>
                    <year>2026</year>
                </date>
            </history>
            <permissions>
                <copyright-statement>Copyright: &#x00a9; 2026 Chowdhury F et al.</copyright-statement>
                <copyright-year>2026</copyright-year>
                <license xlink:href="https://creativecommons.org/licenses/by/4.0/">
                    <license-p>This is an open access article distributed under the terms of the Creative Commons Attribution Licence, which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited.</license-p>
                </license>
            </permissions>
            <self-uri content-type="pdf" xlink:href="https://f1000research.com/articles/15-642/pdf"/>
            <abstract>
                <sec>
                    <title>Background</title>
                    <p>Long-read sequencing platforms, particularly Oxford Nanopore Technologies (ONT), have transformed transcriptomics through direct RNA sequencing. However, their higher error rates &#x2013; dominated by insertions and deletions &#x2013; demand longer, more robust sequence barcodes than traditional short-read applications. Existing barcode generation tools suffer from exponential complexity, becoming computationally infeasible at lengths above 12&#x00a0;bp and leaving a critical gap for long-read applications.</p>
                </sec>
                <sec>
                    <title>Methods</title>
                    <p>We developed TagGen, a high-performance barcode generator implementing Monte Carlo candidate sampling with greedy diversity selection. TagGen includes an integrated demultiplexer that assigns ONT reads to their source barcodes regardless of the tag position using a kmer voting and banded edit-distance matching pipeline. We benchmarked TagGen using Badread-simulated reads and validated barcode resilience using a literature-based nanopore error model.</p>
                </sec>
                <sec>
                    <title>Results</title>
                    <p>TagGen generates 96 diverse 12&#x00a0;bp barcodes from 100,000 candidates in under 100 milliseconds, outperforming exhaustive enumeration by up to 13,600-fold. TagGen successfully generates barcodes at 14&#x2013;30&#x00a0;bp lengths where other available tools fail. Noise simulation demonstrates that TagGen-generated 30&#x00a0;bp barcodes (minimum Hamming distance &#x2265;8) maintain 100% correct assignment at 20% total error rate, whereas traditional 10&#x00a0;bp barcodes degrade to 83%. At typical nanopore error rates (10&#x2013;15%), taggen-generated barcodes &#x2265;14&#x00a0;bp achieve &gt;97% theoretical resolution. When inserted within a read, our systematic benchmark shows that TagGen demultiplexer achieved &gt;90% accuracy with zero wrong-sample assignments (&#x201c;end&#x201d; mode) for reads &#x2265;20&#x00a0;bp. Levenshtein edit distance, recommended for ONT data, improved accuracy by 10&#x2013;27 percentage points over Hamming distance at equivalent parameters.</p>
                </sec>
                <sec>
                    <title>Conclusions</title>
                    <p>TagGen uniquely enables robust barcode design for nanopore and direct RNA sequencing applications, providing researchers with error-tolerant barcodes validated against realistic long-read error profiles, and an integrated anchor-free demultiplexer for flexible read assignment. The software is freely available at 
                        <uri xlink:href="https://github.com/Arnaroo/taggen">https://github.com/Arnaroo/taggen</uri>.</p>
                </sec>
            </abstract>
            <kwd-group kwd-group-type="author">
                <kwd>DNA barcodes</kwd>
                <kwd>RNA barcodes</kwd>
                <kwd>RNA tags</kwd>
                <kwd>nanopore sequencing</kwd>
                <kwd>direct RNA sequencing</kwd>
                <kwd>long-read sequencing</kwd>
                <kwd>high- throughput sequencing</kwd>
                <kwd>multiplexing</kwd>
                <kwd>demultiplexing</kwd>
                <kwd>error tolerance</kwd>
                <kwd>sample identification</kwd>
            </kwd-group>
            <funding-group>
                <award-group id="fund-1">
                    <funding-source>European Union&#x2019;s Horizon 2020</funding-source>
                    <award-id>ResearchandinnovationprogramMarieSklodowska-Curiegrant</award-id>
                    <award-id>agreementNo890462</award-id>
                </award-group>
                <award-group id="fund-2">
                    <funding-source>Bootes Foundation</funding-source>
                    <award-id>Grant2022</award-id>
                </award-group>
                <award-group id="fund-3">
                    <funding-source>National Health and Medical Research Council of Australia (NHMRC)</funding-source>
                    <award-id>InvestigatorGrantGNT1175388</award-id>
                    <award-id>GrantAPP1147496</award-id>
                </award-group>
                <award-group id="fund-4">
                    <funding-source>Australian Research Council (ARC)</funding-source>
                    <award-id>DiscoveryGrantDP180100111</award-id>
                    <award-id>DP250103133</award-id>
                    <award-id>FutureFellowshipGrantFT180100204</award-id>
                </award-group>
                <funding-statement>This project has received funding from the European Union&#x2019;s Horizon 2020 research and innovation programme under the Marie Sk&#x0142;odowska-Curie grant agreement No 890462.   &#13;
National Health and Medical Research Council of Australia (NHMRC) Investigator Grant (GNT1175388) to N.E.S.; Bootes Foundation Grant (2022) to N.E.S.; Australian Research Council Discovery Grant (DP180100111, DP250103133) to N.E.S.; CNRS Postes Rouges Grant (2025) to N.E.S.; National Health and Medical Research Council of Australia Grant (APP1147496) to A.H.F.; Australian Research Council Grant (FT180100204) to A.H.F.</funding-statement>
                <funding-statement>
                    <italic>The funders had no role in study design, data collection and analysis, decision to publish, or preparation of the manuscript.</italic>
                </funding-statement>
            </funding-group>
        </article-meta>
    </front>
    <body>
        <sec id="sec5" sec-type="intro">
            <title>Introduction</title>
            <p>The emergence of long-read sequencing has revolutionized genomics and transcriptomics.
                <sup>
                    <xref ref-type="bibr" rid="ref1">1</xref>
                </sup> Oxford Nanopore Technologies (ONT) platforms enable direct RNA sequencing without reverse transcription, preserving RNA modifications and full-length transcript information.
                <sup>
                    <xref ref-type="bibr" rid="ref2">2</xref>&#x2013;
                    <xref ref-type="bibr" rid="ref4">4</xref>
                </sup> However, these advantages come with distinct challenges: nanopore sequencing exhibits error rates of 5&#x2013;15%, dominated by insertions and deletions rather than the substitution errors typical of short-read platforms.
                <sup>
                    <xref ref-type="bibr" rid="ref5">5</xref>,
                    <xref ref-type="bibr" rid="ref6">6</xref>
                </sup>
            </p>
            <p>Sequence (DNA or RNA) barcodes or tags &#x2013; short sequences used to identify samples, cells, or spatial locations in a pool of many DNA or RNA molecules &#x2013; are essential for multiplexed sequencing.
                <sup>
                    <xref ref-type="bibr" rid="ref7">7</xref>,
                    <xref ref-type="bibr" rid="ref8">8</xref>
                </sup> For short-read sequencing, barcodes of 8&#x2013;12&#x00a0;bp (or nt) with minimum Hamming distances of 3&#x2013;4 provide adequate error tolerance. The Hamming distance between two sequences of equal length counts the number of positions at which the corresponding bases differ; a minimum pairwise Hamming distance of d guarantees that up to &#x230a;(d&#x00a0;&#x2212;&#x00a0;1)/2&#x230b; substitution errors can be corrected. The Levenshtein (edit) distance &#x2013; which additionally accounts for insertions and deletions &#x2013; is a more comprehensive but computationally costlier measure of sequence dissimilarity. However, the indel-dominated error profile of nanopore sequencing demands longer barcodes with greater inter-sequence distances to maintain reliable sample identification.
                <sup>
                    <xref ref-type="bibr" rid="ref5">5</xref>,
                    <xref ref-type="bibr" rid="ref6">6</xref>
                </sup> While sequencing barcodes (tags) are an essential molecular biology instrument, there have been unaddressed challenges in computationally designing robust longer tags with well-described, predictable behavior.</p>
            <p>The computational challenge of barcode generation scales exponentially with length. Several tools exist for DNA barcode generation, each with distinct approaches and limitations (
                <xref ref-type="table" rid="T1">
Table 1</xref>
                <bold>)</bold>. The widely-used DNABarcodes R package
                <sup>
                    <xref ref-type="bibr" rid="ref9">9</xref>,
                    <xref ref-type="bibr" rid="ref10">10</xref>
                </sup> exhaustively enumerates all 4
                <sup>n</sup> possible sequences before filtering &#x2013; 65,536 sequences at 8&#x00a0;bp, but 268 million at 14&#x00a0;bp. This approach fails at lengths above 12&#x00a0;bp due to memory exhaustion, precisely where long-read applications require robust barcodes. TagGD
                <sup>
                    <xref ref-type="bibr" rid="ref11">11</xref>
                </sup> provides efficient demultiplexing but focuses on barcode assignment rather than 
                <italic toggle="yes">de novo</italic> generation. BARCOSEL
                <sup>
                    <xref ref-type="bibr" rid="ref12">12</xref>
                </sup> selects optimal subsets from existing barcode pools but cannot generate new sequences. FreeBarcodes
                <sup>
                    <xref ref-type="bibr" rid="ref13">13</xref>
                </sup> generates indel-correcting barcodes but requires hours for large sets and targets specific code lengths. Edittag
                <sup>
                    <xref ref-type="bibr" rid="ref14">14</xref>
                </sup> provides edit-distance-based design but with limited scalability. PRO
                <sup>
                    <xref ref-type="bibr" rid="ref15">15</xref>
                </sup> takes a different approach designed specifically for nanopore applications: it uses a farthest-point sampling algorithm with probability divergence &#x2013; a metric that models the sequencing error process more directly than edit distance &#x2013; and includes built-in demultiplexing. However, PRO operates at a fixed barcode length matching the official ONT kit (24&#x00a0;bp) and targets maximizing barcode set size (up to 2,292 barcodes) rather than providing user-defined target counts, as well as requires the barcodes to be flanked by known adapter sequences. PRO offers no GC content filtering, homopolymer constraints, custom exclude sequences, graphical interface, or distance visualisation. None of these tools offer the combination of flexible barcode length (8&#x2013;30&#x00a0;bp), sub-second generation, user-defined quality constraints, integrated demultiplexing, nor an accessible interface that nanopore researchers need to adapt barcode design to their specific error profiles.</p>
            <table-wrap id="T1" orientation="portrait" position="float">
                <label>
Table 1. </label>
                <caption>
                    <title>Feature comparison of DNA barcode generation tools.</title>
                    <p>Key capabilities of seven barcode generators are compared, including maximum practical barcode length, generation speed, interface availability, and constraint options. Symbols: &#x2713;, supported; &#x2212;, not supported or not applicable.</p>
                </caption>
                <table content-type="article-table" frame="hsides">
                    <thead>
                        <tr>
                            <th align="left" colspan="1" rowspan="1" valign="top">Feature</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">TagGen</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">PRO</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">DNABarcodes</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">BARCOSEL</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">TagGD</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">FreeBarcodes</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">Edittag</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Maximum practical length</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">30&#x00a0;bp</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">24&#x00a0;bp</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">~12&#x00a0;bp</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Any
                                <xref ref-type="table-fn" rid="tfn1">

                                    <styled-content style="#FF6600" style-type="color">*</styled-content>
                                </xref>
                            </td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">16&#x00a0;bp</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">20&#x00a0;bp</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">12&#x00a0;bp</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">De novo generation</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Generation time (14&#x00a0;bp, 96 barcodes)</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">54&#x00a0;ms</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">~7&#x00a0;min</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">N/A
                                <xref ref-type="table-fn" rid="tfn2">

                                    <styled-content style="#FF6600" style-type="color">
                                        <sup>&#x2020;</sup>
                                    </styled-content>
                                </xref>
                            </td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Hours</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">N/A
                                <xref ref-type="table-fn" rid="tfn3">

                                    <styled-content style="#FF6600" style-type="color">
                                        <sup>&#x2021;</sup>
                                    </styled-content>
                                </xref>
                            </td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Graphical interface</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Web</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Command-line interface</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Parallel processing</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Custom exclude sequences</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">GC content constraints</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Homopolymer filtering</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Distance visualization</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">JSON config support</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                    </tbody>
                </table>
                <table-wrap-foot>
                    <fn-group content-type="footnotes">
                        <fn id="tfn1">
                            <label>*</label>
                            <p>BARCOSEL selects from existing pools rather than generating de novo.</p>
                        </fn>
                        <fn id="tfn2">
                            <label>
                                <sup>&#x2020;</sup>
                            </label>
                            <p>DNABarcodes fails due to memory exhaustion at 14&#x00a0;bp.</p>
                        </fn>
                        <fn id="tfn3">
                            <label>
                                <sup>&#x2021;</sup>
                            </label>
                            <p>Edittag requires Python 2 and cannot be run on modern systems.</p>
                        </fn>
                    </fn-group>
                </table-wrap-foot>
            </table-wrap>
            <p>We developed TagGen to address this gap. By replacing exhaustive enumeration with Monte Carlo sampling, TagGen achieves linear complexity regardless of barcode length, enabling generation of 14&#x2013;30&#x00a0;bp barcodes optimized for nanopore sequencing. Crucially, barcode generation alone is insufficient for a complete multiplexing workflow: once sequenced reads are obtained, each read must be assigned back to its source barcode &#x2013; a process known as demultiplexing. Existing demultiplexers (
                <xref ref-type="table" rid="T2">
Table 2</xref>) typically require knowledge of flanking adapter sequences to anchor the barcode search, restricting them to standard kit-based library preparations. In contrast, TagGen includes an integrated anchor-free demultiplexer (taggen-demux) that locates barcodes at any position within a read &#x2013; at the 5&#x2032; or 3&#x2032; end, or embedded mid-read &#x2013; using a k-mer voting and banded edit-distance pipeline. This design enables demultiplexing of direct RNA sequencing reads, spatial transcriptomics libraries, and custom protocols where the barcode position is non-standard or variable. Position masks allow the user to restrict the search to the expected barcode region, minimising false positive matches while accommodating diverse library architectures. We validate these barcodes against realistic nanopore error profiles, demonstrating their resilience under conditions where traditional short barcodes fail. TagGen provides a complete barcoding pipeline: barcode design, simulation and quality validation, and post-sequencing demultiplexing. This integration removes the need to coordinate separately maintained tools and ensures that the distance parameters used during barcode generation are directly matched to the tolerances applied during demultiplexing. We describe the demultiplexer design and its systematic validation below.</p>
            <table-wrap id="T2" orientation="portrait" position="float">
                <label>
Table 2. </label>
                <caption>
                    <title>Feature comparison of demultiplexing tools.</title>
                    <p>Seven demultiplexers are compared across barcode flexibility, search strategy, distance metric, and maintenance status. Symbols: &#x2713;, supported; &#x2717;, discontinued; &#x2212;, not supported.</p>
                </caption>
                <table content-type="article-table" frame="hsides">
                    <thead>
                        <tr>
                            <th align="left" colspan="1" rowspan="1" valign="top">Feature</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">TagGen</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">minibar</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">PRO-demux
</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">qcat</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">Dorado</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">Porechop</th>
                            <th align="left" colspan="1" rowspan="1" valign="top">DeePlexiCon</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Accepts user-defined barcodes</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Limited
                                <xref ref-type="table-fn" rid="tfn4">

                                    <styled-content style="#FF6600" style-type="color">
                                        <sup>&#x2020;</sup>
                                    </styled-content>
                                </xref>
                            </td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Tag location</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Any</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Any</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">5&#x2032;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">5&#x2032;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">5&#x2032; or 3&#x2019;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">5&#x2032; or 3&#x2019;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">5&#x2032;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Adapter sequence required</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Distance metric</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Edit</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Edit</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Prob. div.</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Edit</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Edit</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Edit</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Neural net</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Configurable mismatch threshold</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Indel-aware matching</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Partial</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Partial</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Real-time/live support</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">GPU acceleration</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Active maintenance</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2717;
                                <xref ref-type="table-fn" rid="tfn5">

                                    <styled-content style="#FF6600" style-type="color">
                                        <sup>&#x2021;</sup>
                                    </styled-content>
                                </xref>
                            </td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2717;
                                <xref ref-type="table-fn" rid="tfn5">

                                    <styled-content style="#FF6600" style-type="color">
                                        <sup>&#x2021;</sup>
                                    </styled-content>
                                </xref>
                            </td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Limited</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Graphical interface</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                        </tr>
                        <tr>
                            <td align="left" colspan="1" rowspan="1" valign="middle">Command-line interface</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                            <td align="left" colspan="1" rowspan="1" valign="middle">&#x2713;</td>
                        </tr>
                    </tbody>
                </table>
                <table-wrap-foot>
                    <fn-group content-type="footnotes">
                        <fn id="tfn4">
                            <label>
                                <sup>&#x2020;</sup>
                            </label>
                            <p>Dorado supports custom barcodes via kit configuration files but not arbitrary user-defined sequences.</p>
                        </fn>
                        <fn id="tfn5">
                            <label>
                                <sup>&#x2021;</sup>
                            </label>
                            <p>qcat
                                <sup>
                                    <xref ref-type="bibr" rid="ref16">16</xref>
                                </sup> and Porechop
                                <sup>
                                    <xref ref-type="bibr" rid="ref17">17</xref>
                                </sup> are no longer actively maintained; consider Dorado or minibar for new workflows.</p>
                        </fn>
                    </fn-group>
                </table-wrap-foot>
            </table-wrap>
        </sec>
        <sec id="sec6" sec-type="methods">
            <title>Methods</title>
            <sec id="sec7">
                <title>Tag generation algorithm design</title>
                <p>TagGen implements a two-phase algorithm fundamentally different from exhaustive enumeration (
                    <xref ref-type="fig" rid="f1">
Figure 1</xref>).</p>
                <fig fig-type="figure" id="f1" orientation="portrait" position="float">
                    <label>
Figure 1. </label>
                    <caption>
                        <title>TagGen overview: barcode design for nanopore sequencing.</title>
                        <p>

                            <bold>(A)</bold> Nanopore sequencing errors are dominated by deletions (50%), insertions (25%), and substitutions (25%) at 5&#x2013;15% total error rates, requiring longer barcodes than short-read platforms. 
                            <bold>(B)</bold> Existing tools enumerate all 4
                            <sup>n</sup> sequences exhaustively, causing memory exhaustion at &#x2265;14&#x00a0;bp (268 million sequences). TagGen&#x2019;s Monte Carlo sampling operates at constant complexity O(k) regardless of length. 
                            <bold>(C)</bold> TagGen&#x2019;s two-phase generation algorithm: Phase 1 generates ~100,000 random candidates validated against user constraints in parallel; Phase 2 applies greedy diversity selection maximising minimum pairwise Hamming or Levenshtein distance. 
                            <bold>(D)</bold> TagGen&#x2019;s integrated demultiplexer: a two-stage anchor-free pipeline that assigns reads to source barcodes without requiring flanking adapter sequences. Stage 1 uses k-mer voting to rapidly identify candidate barcodes and estimate their location; Stage 2 performs banded edit-distance alignment to confirm the best match against configurable acceptance criteria. 
                            <bold>(E)</bold> Validation under a nanopore error model demonstrates that 30&#x00a0;bp barcodes (d&#x00a0;&#x2265;&#x00a0;8) maintain 100% correct assignment at 20% error rate, while 10&#x00a0;bp barcodes degrade to 83%. Barcodes &#x2265;14&#x00a0;bp achieve &gt;97% resolution at typical ONT error rates (10&#x2013;15%). 
                            <bold>(F)</bold> TagGen addresses sample multiplexing, direct RNA sequencing, and spatial transcriptomics through an integrated GUI and CLI pipeline with built-in demultiplexing.</p>
                    </caption>
                    <graphic id="gr1" orientation="portrait" position="float" xlink:href="https://f1000research-files.f1000.com/manuscripts/198458/64f563d2-c353-421a-820f-c9f8b9c98302_figure1.gif"/>
                </fig>
                <p>

                    <italic toggle="yes">Phase 1: Monte Carlo Candidate Generation.</italic> Rather than enumerating all 4
                    <sup>n</sup> sequences, TagGen generates random candidates validated in real-time against user-specified constraints (GC content, homopolymer limits, exclude sequences). Generation proceeds in parallel across CPU cores and terminates upon collecting sufficient valid candidates (typically ~1,250 candidates in ~55&#x00a0;ms).</p>
                <p>

                    <italic toggle="yes">Phase 2: Greedy Diversity Selection.</italic> From the candidate pool, TagGen iteratively selects sequences maximizing minimum Hamming or Levenshtein distance to already-selected barcodes, producing a maximally diverse final set (typically 96 barcodes in ~25&#x00a0;ms additional time).</p>
            </sec>
            <sec id="sec8">
                <title>Algorithm pseudocode</title>
                <p>The following pseudocode formalizes TagGen&#x2019;s two-phase approach.</p>
                <boxed-text id="B1" orientation="portrait" position="float">
                    <label>Algorithm 1. </label>
                    <caption>
                        <title>Monte Carlo Candidate Generation.</title>
                    </caption>
                    <p>Input: length, targetCandidates, gcMin, gcMax, homopolymerLimit, excludeSeqs</p>
                    <p>Output: candidatePool (set of valid barcode candidates)</p>
                    <p>1. Initialize candidatePool &#x2190; &#x2205;</p>
                    <p>2. Initialize lock for thread-safe access</p>
                    <p>3. parallel for each CPU core do:</p>
                    <p>4.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;while|candidatePool|&lt; targetCandidates do:</p>
                    <p>5.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;seq &#x2190; generateRandomSequence (length) //uniform random A,C,G,T</p>
                    <p>6.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;//Validate constraints</p>
                    <p>7.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;if gcContent (seq) &lt; gcMin or gcContent (seq) &gt; gcMax then</p>
                    <p>8.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;continue</p>
                    <p>9.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;if maxHomopolymerRun (seq) &gt; homopolymerLimit then</p>
                    <p>10.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;continue</p>
                    <p>11.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;if seq &#x2208; excludeSeqs then</p>
                    <p>12.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;continue</p>
                    <p>13.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;//Thread-safe addition</p>
                    <p>14.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;acquire (lock)</p>
                    <p>15.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;candidatePool &#x2190; candidatePool &#x222a; {seq}</p>
                    <p>16.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;release (lock)</p>
                    <p>17.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;end while</p>
                    <p>18. end parallel</p>
                    <p>19. return candidatePool</p>
                </boxed-text>
                <boxed-text id="B2" orientation="portrait" position="float">
                    <label>Algorithm 2. </label>
                    <caption>
                        <title>Greedy Diversity Selection.</title>
                    </caption>
                    <p>Input: candidatePool, targetCount, minDistance</p>
                    <p>Output: selectedBarcodes (maximally diverse subset)</p>
                    <p>1. Initialize selectedBarcodes &#x2190; &#x2205;</p>
                    <p>2. Initialize distanceMatrix [I,j] for all pairs in candidatePool//distance can be hamming (default, fastest) or Levenshtein (slower, indels considered)</p>
                    <p>3. //Select first barcode (arbitrary or random)</p>
                    <p>4. selectedBarcodes &#x2190; selectedBarcodes &#x222a; {candidatePool[0]}</p>
                    <p>5. while|selectedBarcodes|&lt; targetCount do:</p>
                    <p>6.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;bestCandidate &#x2190; null</p>
                    <p>7.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;bestMinDist &#x2190; -1</p>
                    <p>8.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;for each candidate in candidatePool \ selectedBarcodes do:</p>
                    <p>9.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;//Find minimum distance to any selected barcode</p>
                    <p>10.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;minDist &#x2190; min {distanceMatrix [candidate, s] : s &#x2208; selectedBarcodes} : s &#x2208; selectedBarcodes}</p>
                    <p>11.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;if minDist &gt; bestMinDist then</p>
                    <p>12.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;bestMinDist &#x2190; minDist</p>
                    <p>13.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;bestCandidate &#x2190; candidate</p>
                    <p>14.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;end for</p>
                    <p>15.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;if bestMinDist &lt; minDistance then</p>
                    <p>16.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;break//Cannot achieve required minimum distance</p>
                    <p>17.&#x2003;&#x2003;&#x2003;&#x2003;&#x2003;selectedBarcodes &#x2190; selectedBarcodes &#x222a; {bestCandidate}</p>
                    <p>18. end while</p>
                    <p>19. return selectedBarcodes</p>
                </boxed-text>
            </sec>
            <sec id="sec9">
                <title>Complexity analysis</title>
                <p>The algorithmic approaches differ fundamentally in complexity:
                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Exhaustive enumeration: O(4
                                <sup>n</sup>) where n&#x00a0;=&#x00a0;barcode length</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Monte Carlo sampling: O(k) where k&#x00a0;=&#x00a0;candidates generated (typically 10,000&#x2013;100,000)</p>
                        </list-item>
                    </list>
                </p>
                <p>For 14&#x00a0;bp barcodes, this represents a 2,680-fold reduction in operations (100,000 
                    <italic toggle="yes">vs.</italic> 268 million), translating to milliseconds versus memory exhaustion. Generation time is largely independent of candidate pool size for a fixed target count (
                    <bold>Extended Data Figure 1</bold>).</p>
            </sec>
            <sec id="sec10">
                <title>Integrated demultiplexer</title>
                <p>TagGen includes a built-in demultiplexer (also standalone as taggen-demux) that assigns ONT FASTQ reads to their source barcodes. It is available both as a command-line subcommand (taggen --demux) and as a dedicated tab in the graphical interface.</p>
                <p>Each read is processed by a two-stage pipeline. In the first stage, all 8-mers in the read&#x2019;s search region are looked up against a pre-built index that maps each 8-mer to the set of barcodes containing it, and candidate barcodes are ranked by hit count (k-mer voting). The top candidate&#x2019;s hit positions are averaged to estimate the barcode location within the read. In the second stage, a banded edit distance computation slides the candidate barcode across a window of (tag length&#x00a0;+&#x00a0;15) bp centred on the estimated location, yielding the minimum edit distance to the read. The best-matching barcode is accepted if three criteria are met: (i) the edit distance does not exceed the automatically derived maximum (adaptive rule: tag_length/5 for tags shorter than 20&#x00a0;bp, tag_length/4 for 20&#x2013;29&#x00a0;bp, tag_length/3 for &#x2265;30&#x00a0;bp; overridable via --max-dist); (ii) the margin between the best and second-best candidate distance is at least 2 (ambiguity guard); and (iii) a confidence score derived from the edit distance exceeds a user-configurable threshold (default 0). Reads failing any criterion are written to an &#x201c;unassigned&#x201d; output file, annotated with the reason (no_match, ambiguous, or low_confidence). This conservative strategy ensures that uncertain reads are withheld rather than wrongly assigned.</p>
            </sec>
            <sec id="sec11">
                <title>Distance metrics</title>
                <p>Both Hamming distance (substitutions only) and Levenshtein edit distance (substitutions, insertions, deletions) are supported and applied consistently between barcode generation and demultiplexing. Because ONT sequencing produces a characteristic error profile with a significant proportion of insertion and deletion errors &#x2013; particularly at homopolymer runs &#x2013; Levenshtein distance is recommended for most ONT workflows. Hamming distance remains available for platforms with predominantly substitution errors or when computational speed is a priority.</p>
            </sec>
            <sec id="sec12">
                <title>Search modes</title>
                <p>Two search modes accommodate different library preparation strategies, as follows.</p>
                <p>End mode (default): the demultiplexer searches a window at each end of the read and its reverse complement, corresponding to the standard dual-ended library structure [barcode][adapter][insert] [RC (adapter)][RC (barcode)]. This is the appropriate mode for ligation-based ONT DNA libraries.</p>
                <p>Full mode: the entire read is scanned for the barcode, intended for protocols where the barcode may appear at an internal position (e.g., direct RNA sequencing with a mid-read adapter ligation, or custom in-read tagging schemes). In full mode, users can specify one or more position masks to restrict the search to the expected barcode region, reducing false positive k-mer seeds from flanking sequence. Masks may be expressed as absolute positions (start:end in bp), end-relative offsets (5p:N for the first N bp from the 5&#x2032; end; 3p:N for the last N bp from the 3&#x2032; end), or as read-length fractions (f_start:f_end,resolved per read). Multiple zones are merged and the union is searched.</p>
            </sec>
            <sec id="sec13">
                <title>Read trimming and output</title>
                <p>
Three trimming modes are available: none (reads written unmodified), ends (barcode trimmed from the matched end), and all (barcodes trimmed from both ends). FASTQ headers of assigned reads are annotated with the barcode name, edit distance, and confidence score. Assigned reads are written to per-sample subdirectories; unassigned reads to a separate subdirectory. Gzip compressed input is supported and processed in streaming batches to maintain constant memory usage. A per-sample statistics TSV file records the number of reads assigned per barcode, expected read count, and mean Q-score, enabling rapid quality assessment. In the GUI, these statistics are displayed as four interactive charts: barcode match position distribution, per sample assignment counts, edit distance and confidence distributions, and per-sample Q-score profiles.</p>
            </sec>
            <sec id="sec14">
                <title>POD5 co-demultiplexing</title>
                <p>When raw POD5 signal files are present alongside FASTQ reads, TagGen can invoke the pod5 subset tool to partition signal files by sample, enabling downstream signal-level analyses (e.g., modified base calling) on a per-sample basis.</p>
            </sec>
            <sec id="sec15">
                <title>Implementation</title>
                <p>TagGen is implemented in D (
                    <ext-link ext-link-type="uri" xlink:href="http://dlang.org">dlang.org</ext-link>), a systems programming language combining high-level expressiveness with native code performance. The application is compiled using the LDC2 compiler (LLVM-based D compiler) with release optimizations enabled.</p>
                <p>The software architecture comprises six primary modules (
                    <xref ref-type="fig" rid="f1">
Figure 1</xref>):
                    <list list-type="order">
                        <list-item>
                            <label>1.</label>
                            <p>
Candidate Generation Module: Implements parallel Monte Carlo sampling using D&#x2019;s 
                                <styled-content style="color:#C7254E">std.parallelism</styled-content> library. Each worker thread independently generates random nucleotide sequences and validates them against user constraints in real-time. Valid candidates are collected into a thread-safe pool using atomic operations (
                                <bold>Extended Data Figure 2</bold>). The module employs the Mersenne Twister pseudorandom number generator for sequence generation.</p>
                        </list-item>
                        <list-item>
                            <label>2.</label>
                            <p>
Diversity Selection Module: Implements greedy subset selection with Hamming or Levenshtein distance calculation. The algorithm maintains a distance matrix and iteratively selects the candidate maximizing minimum distance to all previously selected barcodes. Distance calculations use optimized bitwise operations for performance.</p>
                        </list-item>
                        <list-item>
                            <label>3.</label>
                            <p>GUI Module: Built using GtkD bindings to the GTK3 toolkit, providing a cross-platform graphical interface. The interface includes real-time parameter validation, progress indication, and interactive heatmap visualization of pairwise barcode distances using Cairo graphics.</p>
                        </list-item>
                        <list-item>
                            <label>4.</label>
                            <p>CLI Module: Provides complete command-line functionality for scriptable pipeline integration. Supports all generation parameters, JSON configuration files for reproducible workflows, multiple output formats, and verbose progress reporting.</p>
                        </list-item>
                        <list-item>
                            <label>5.</label>
                            <p>Export Module: Generates output in FASTA format (for direct use in sequencing pipelines), TSV format (for spreadsheet analysis), and optional distance matrix export, with configurable sequence headers and metadata.</p>
                        </list-item>
                        <list-item>
                            <label>6.</label>
                            <p>Demultiplexer Module: Implements a two-stage read assignment pipeline. The first stage uses a k-mer index (8-mer vocabulary) for rapid candidate identification via vote counting; the second stage performs banded edit-distance alignment to confirm the best match. The module supports end-mode and full-mode search with configurable position masks, adaptive acceptance thresholds, ambiguity detection, and three tag-trimming modes. POD5 signal file co-demultiplexing is supported via the pod5 subset command-line
 tool.</p>
                        </list-item>
                    </list>
                </p>
            </sec>
            <sec id="sec16">
                <title>Operation</title>
                <p>Minimum System Requirements:
                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Operating System: Linux (Arch, Ubuntu 18.04+, Debian 10+), Windows 10+, or macOS 10.14+</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Processor: Any x86&#x2013;64 CPU; multi-core processors recommended for parallel generation</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Memory: 512&#x00a0;MB RAM minimum; 2&#x00a0;GB recommended for large candidate pools</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Disk Space: 50&#x00a0;MB for installation</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Display: 1024&#x00a0;&#x00d7;&#x00a0;768 minimum resolution for GUI (not required for CLI operation)</p>
                        </list-item>
                    </list>
                </p>
                <p>Installation: Pre-compiled binaries are available for Linux and Windows from the GitHub releases page. Linux users may also compile from source using the DUB package manager:
                    <preformat orientation="portrait" position="float" preformat-type="computer code" xml:space="preserve">dub build --compiler&#x00a0;=&#x00a0;ldc2 --build&#x00a0;=&#x00a0;release</preformat>
                </p>
                <p>GUI Workflow:
                    <list list-type="order">
                        <list-item>
                            <label>1.</label>
                            <p>Launch TagGen GUI:
                                <styled-content style="color:#C7254E">. /taggen</styled-content>
                            </p>
                        </list-item>
                        <list-item>
                            <label>2.</label>
                            <p>Configure barcode parameters:
</p>
                            <p>
Tag length (8&#x2013;30&#x00a0;bp recommended).
</p>
                            <p>
Target barcode count (e.g., 96 for standard plates).
</p>
                            <p>
Minimum Hamming distance (3&#x2013;8 depending on error tolerance required)
</p>
                        </list-item>
                        <list-item>
                            <label>3.</label>
                            <p>Set quality constraints:
</p>
                            <p>
GC content bounds (default: 30&#x2013;70%).
</p>
                            <p>
Maximum homopolymer length (default: 3)
</p>
                        </list-item>
                        <list-item>
                            <label>4.</label>
                            <p>Optionally load exclude sequences (FASTA format) to avoid similarity to adapters or primers</p>
                        </list-item>
                        <list-item>
                            <label>5.</label>
                            <p>Click &#x201c;Generate&#x201d; to produce barcodes</p>
                        </list-item>
                        <list-item>
                            <label>6.</label>
                            <p>Review pairwise distance heatmap for quality verification</p>
                        </list-item>
                        <list-item>
                            <label>7.</label>
                            <p>Export to FASTA or TSV format</p>
                        </list-item>
                    </list>
                </p>
                <p>Demultiplexing workflow (Demultiplex tab):
                    <list list-type="order">
                        <list-item>
                            <label>8.</label>
                            <p>Switch to the Demultiplex tab</p>
                        </list-item>
                        <list-item>
                            <label>9.</label>
                            <p>Load barcode FASTA file (generated above or user-supplied)</p>
                        </list-item>
                        <list-item>
                            <label>10.</label>
                            <p>Select FASTQ read file(s) for demultiplexing</p>
                        </list-item>
                        <list-item>
                            <label>11.</label>
                            <p>Choose search mode: end (for standard libraries) or full (for mid-read barcodes)</p>
                        </list-item>
                        <list-item>
                            <label>12.</label>
                            <p>Optionally configure position mask, acceptance threshold, and trim mode</p>
                        </list-item>
                        <list-item>
                            <label>13.</label>
                            <p>Click &#x201c;Demultiplex&#x201d; to assign reads to barcodes</p>
                        </list-item>
                        <list-item>
                            <label>14.</label>
                            <p>Review interactive result charts: per-sample assignment counts, barcode match positions, edit distance distributions, and per-sample Q-score profiles</p>
                        </list-item>
                        <list-item>
                            <label>15.</label>
                            <p>Demultiplexed reads are written to per-sample subdirectories; unassigned reads to a separate directory</p>
                        </list-item>
                    </list>
                </p>
                <p>Command-Line Usage:</p>
                <p>TagGen provides a comprehensive CLI for automated pipelines. Barcode generation and demultiplexing examples are shown below:
                    <preformat orientation="portrait" position="float" preformat-type="computer code" xml:space="preserve"># Generate 96 barcodes with default parameters
taggen -n 96 -l 14 -d 4 -o my_barcodes</preformat>

                    <preformat orientation="portrait" position="float" preformat-type="computer code" xml:space="preserve"># Generate with custom GC constraints and exclude sequences
taggen -n 96 -l 16 --minGc 40 --maxGc 60 -f adapters.fasta -v</preformat>

                    <preformat orientation="portrait" position="float" preformat-type="computer code" xml:space="preserve"># Generate using JSON configuration file
taggen -c experiment_config.json</preformat>

                    <preformat orientation="portrait" position="float" preformat-type="computer code" xml:space="preserve"># Generate large pool with matrix output
taggen -n 384 -l 20 -d 6 --metric levenshtein -m --heatmap -v</preformat>

                    <preformat orientation="portrait" position="float" preformat-type="computer code" xml:space="preserve"># Demultiplex reads in end mode (standard dual-ended libraries)
taggen --demux --tags my_barcodes.fasta --reads reads.fastq --mode end --trim-mode ends</preformat>

                    <preformat orientation="portrait" position="float" preformat-type="computer code" xml:space="preserve"># Demultiplex with full-mode search and 5&#x2032; position mask
taggen --demux --tags my_barcodes.fasta --reads reads.fastq --mode full --position-mask 5p:60</preformat>

                    <preformat orientation="portrait" position="float" preformat-type="computer code" xml:space="preserve"># Demultiplex mid-read barcodes with fractional mask and strict threshold
taggen --demux --tags my_barcodes.fasta --reads reads.fastq --mode full --position-mask 0.05:0.20 --max-dist 4</preformat>
                </p>
                <p>Full CLI options are available via 
                    <styled-content style="color:#C7254E">taggen &#x2013;help</styled-content>.</p>
            </sec>
            <sec id="sec17">
                <title>Nanopore error simulation</title>
                <p>To validate barcode resilience under realistic long-read conditions, we implemented a nanopore error simulator based on published characterizations.
                    <sup>
                        <xref ref-type="bibr" rid="ref5">5</xref>,
                        <xref ref-type="bibr" rid="ref6">6</xref>,
                        <xref ref-type="bibr" rid="ref18">18</xref>
                    </sup> Deletions: 50% of errors (most frequent in nanopore sequencing). Insertions: 25% of errors (random nucleotide insertion). Substitutions: 25% of errors (random nucleotide replacement). We tested error rates from 5% (high-quality R10.4 data) to 25% (stress test beyond typical conditions), encompassing typical ONT performance (10&#x2013;15%) and degraded sample scenarios (20%). For each condition, 1,000 reads were simulated per barcode, with identification via minimum Levenshtein distance to the original barcode set.</p>
            </sec>
            <sec id="sec18">
                <title>Benchmarking</title>
                <p>Performance comparisons were conducted on a workstation with a 12-core AMD processor running Arch Linux. TagGen (v1.2.0) barcode generation runtime was compared against DNABarcodes (v1.20.0) from Bioconductor.
                    <sup>
                        <xref ref-type="bibr" rid="ref10">10</xref>
                    </sup> Both tools were configured to generate 96 barcodes with equivalent constraint parameters (GC content 25&#x2013;75%, minimum Hamming distance as specified). Timing measurements excluded I/O operations to focus on algorithmic performance. Each TagGen configuration was tested in triplicate; reported values are means (
                    <xref ref-type="table" rid="T3">
Table 3</xref>).</p>
                <table-wrap id="T3" orientation="portrait" position="float">
                    <label>
Table 3. </label>
                    <caption>
                        <title>Performance comparison between TagGen and DNABarcodes.</title>
                        <p>Performance comparison between TagGen and DNABarcodes. Wall-clock generation times (mean of three replicates) for 96 barcodes at increasing lengths. All runs used Hamming distance and GC 25&#x2013;75% on a 12-core AMD Linux workstation.</p>
                    </caption>
                    <table content-type="article-table" frame="hsides">
                        <thead>
                            <tr>
                                <th align="left" colspan="1" rowspan="1" valign="top">Configuration</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">TagGen</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">DNABarcodes</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">Speedup</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>8&#x00a0;bp, d&#x00a0;&#x2265;&#x00a0;3</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">24&#x00a0;ms</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">120&#x00a0;ms</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">5&#x00d7;</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>10&#x00a0;bp, d&#x00a0;&#x2265;&#x00a0;3</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">31&#x00a0;ms</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">24&#x00a0;s</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">770&#x00d7;</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>12&#x00a0;bp, d&#x00a0;&#x2265;&#x00a0;4</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">34&#x00a0;ms</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">463&#x00a0;s</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">13,600&#x00d7;</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>14&#x00a0;bp, d&#x00a0;&#x2265;&#x00a0;4</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">35&#x00a0;ms</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Memory exhaustion</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>16&#x00a0;bp, d&#x00a0;&#x2265;&#x00a0;4</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">35&#x00a0;ms</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Memory exhaustion</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>20&#x00a0;bp, d&#x00a0;&#x2265;&#x00a0;6</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">44&#x00a0;ms</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Memory exhaustion</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>30&#x00a0;bp, d&#x00a0;&#x2265;&#x00a0;8</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">29&#x00a0;ms</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Memory exhaustion</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">&#x2013;</td>
                            </tr>
                        </tbody>
                    </table>
                </table-wrap>
                <p>The practical sequencing utility of TagGen-generated barcodes was evaluated by simulating Oxford Nanopore reads with Badread v0.4.1
                    <sup>
                        <xref ref-type="bibr" rid="ref19">19</xref>
                    </sup> and measuring demultiplexing accuracy against ground truth. Reads were simulated using the nanopore2023 error model across read identity levels of 80&#x2013;95% (corresponding to approximately 5&#x2013;20% per-base error rates) spanning the range from early ONT chemistries to most recent high-accuracy data. Two demultiplexers were applied to the same simulated reads: taggen-demux (integrated, using Levenshtein distance) and minibar v0.25 (an established third-party ONT demultiplexer).
                    <sup>
                        <xref ref-type="bibr" rid="ref20">20</xref>
                    </sup> Results are reported as accuracy (percentage of reads correctly assigned to their source barcode) and error rate (reads assigned to a wrong barcode); reads failing matching criteria are classified as unassigned rather than wrong.</p>
                <p>Several other tools in this space were not included in the comparison. Qcat,
                    <sup>
                        <xref ref-type="bibr" rid="ref16">16</xref>
                    </sup> ONT&#x2019;s open-source demultiplexer, is designed exclusively for ONT&#x2019;s predefined native barcode kits and does not accept arbitrary user-defined sequences; similarly, the demultiplexing module integrated into ONT&#x2019;s Dorado basecaller
                    <sup>
                        <xref ref-type="bibr" rid="ref21">21</xref>
                    </sup> is restricted to native barcode catalogues. Porechop
                    <sup>
                        <xref ref-type="bibr" rid="ref17">17</xref>
                    </sup> has been discontinued and does not support user-defined barcodes. PRO
                    <sup>
                        <xref ref-type="bibr" rid="ref15">15</xref>
                    </sup> is publicly available but a direct comparison remains impractical: PRO optimises for maximum barcode set size at a fixed length rather than accepting user-defined target counts and length ranges, and offers no GC content filtering, homopolymer constraints, or custom exclude sequences. These different design goals make a like-for-like accuracy comparison uninformative.</p>
                <p>Demultiplexing accuracy was evaluated across 154 parameter combinations in five systematic test phases using the same Badread simulation setup described above. Tag sets were generated with TagGen using a pool of 10,000 candidates, GC content 30&#x2013;70%, maximum homopolymer 3&#x00a0;bp, and error tolerance t&#x00a0;=&#x00a0;2. A hundred reads were simulated per barcode per run; ground-truth assignments were extracted from Badread read headers. Demultiplexing was performed with taggen-demux using an adaptive acceptance threshold (autoMaxDist: tag_length/5 for tags shorter than 20&#x00a0;bp, tag_length/4 for 20&#x2013;29&#x00a0;bp, and tag_length/3 for tags of 30&#x00a0;bp or longer) unless otherwise noted. Three accuracy metrics were recorded for each condition: the fraction of reads correctly assigned to the originating sample (accuracy), the fraction assigned to an incorrect sample (misassignment error), and the fraction rejected as unassigned.</p>
            </sec>
        </sec>
        <sec id="sec19" sec-type="results">
            <title>Results</title>
            <sec id="sec20">
                <title>TagGen dramatically outperforms exhaustive enumeration</title>
                <p>We benchmarked TagGen against DNABarcodes across configurations spanning short-read (8&#x2013;12&#x00a0;bp) and long-read (14&#x2013;30&#x00a0;bp) applications (
                    <xref ref-type="fig" rid="f2">
Figure 2</xref>, 
                    <xref ref-type="table" rid="T3">
Table 3</xref>).</p>
                <fig fig-type="figure" id="f2" orientation="portrait" position="float">
                    <label>
Figure 2. </label>
                    <caption>
                        <title>Performance comparison between TagGen and DNABarcodes.</title>
                        <p>Generation times (log scale) across barcode lengths 8&#x2013;30&#x00a0;bp. DNABarcodes (orange) fails at &#x2265;14&#x00a0;bp due to memory exhaustion when attempting to enumerate 268+ million sequences. TagGen (blue) succeeds at all lengths with sub-second generation times for typical applications (14&#x2013;20&#x00a0;bp).</p>
                    </caption>
                    <graphic id="gr2" orientation="portrait" position="float" xlink:href="https://f1000research-files.f1000.com/manuscripts/198458/64f563d2-c353-421a-820f-c9f8b9c98302_figure2.gif"/>
                </fig>
                <p>All benchmarks: 96 target barcodes, Hamming distance, GC 30-70%. Wall-clock times averaged over 3 replicates, Linux. DNABarcodes memory exhaustion occurs when attempting to enumerate 4
                    <sup>n</sup> sequences (268 million at 14&#x00a0;bp).</p>
                <p>At comparable configurations, TagGen is able to generate longer barcodes (14&#x2013;30&#x00a0;bp range) with generation times below 50&#x00a0;ms for all tested lengths (
                    <bold>Extended Data Figure 3</bold>), while the exhaustive enumeration strategy of DNABarcodes fails entirely due to memory requirements exceeding available RAM when attempting to store 268+ million candidate sequences.</p>
                <p>Using a literature-based error model on the tags directly, we tested barcode resolution across lengths and error rates, showing that the generated tags are robust to most error rates, in particular longer barcodes (
                    <xref ref-type="table" rid="T4">
Table 4</xref>).</p>
                <table-wrap id="T4" orientation="portrait" position="float">
                    <label>
Table 4. </label>
                    <caption>
                        <title>Barcode resolution under simulated nanopore error profiles.</title>
                        <p>Percentage of reads correctly assigned to the originating barcode across five error rates (5&#x2013;25%) for six barcode lengths. Error model: 50% deletions, 25% insertions, 25% substitutions; N&#x00a0;=&#x00a0;1,000 simulated reads per barcode per condition.</p>
                    </caption>
                    <table content-type="article-table" frame="hsides">
                        <thead>
                            <tr>
                                <th align="left" colspan="1" rowspan="1" valign="top">Barcode Length</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">Min. Dist.</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">5% Error</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">10% Error</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">15% Error</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">20% Error</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">25% Error</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>10&#x00a0;bp</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">d&#x00a0;&#x2265;&#x00a0;3</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">99.8%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">96.2%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">91.3%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">83.3%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">74.7%</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>12&#x00a0;bp</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">d&#x00a0;&#x2265;&#x00a0;4</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">99.7%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">99.0%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">96.1%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">88.6%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">82.0%</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>14&#x00a0;bp</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">d&#x00a0;&#x2265;&#x00a0;4</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">100%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">99.5%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">97.9%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">94.1%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">88.1%</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>16&#x00a0;bp</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">d&#x00a0;&#x2265;&#x00a0;5</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">99.9%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">100%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">99.1%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">95.8%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">92.2%</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>20&#x00a0;bp</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">d&#x00a0;&#x2265;&#x00a0;6</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">100%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">99.9%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">99.6%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">98.6%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">96.4%</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">
                                    <bold>30&#x00a0;bp</bold>
</td>
                                <td align="left" colspan="1" rowspan="1" valign="middle">d&#x00a0;&#x2265;&#x00a0;8</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">100%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">100%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">100%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">100%</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">99.6%</td>
                            </tr>
                        </tbody>
                    </table>
                </table-wrap>
                <p>Values indicate percentage of reads correctly assigned to original barcode. Error model: 50% deletions, 25% insertions, 25% substitutions based on published ONT characterizations. N&#x00a0;=&#x00a0;1,000 simulated reads per barcode per condition.</p>
                <p>The results reveal a striking pattern. At typical nanopore error rates (10&#x2013;15%), traditional 10&#x00a0;bp barcodes show degradation (91&#x2013;96% correct), while barcodes &#x2265;14&#x00a0;bp maintain &gt;97% resolution. Under challenging conditions (20% error) &#x2013; representing degraded RNA or difficult sequences &#x2013; the contrast is dramatic: 10&#x00a0;bp barcodes achieve only 83.3% correct assignment (16.7% misassignment), while 30&#x00a0;bp barcodes maintain 100% correct assignment. Even at the extreme 25% error stress test, 30&#x00a0;bp barcodes maintain 99.6% accuracy while 10&#x00a0;bp barcodes fall to 74.7%.</p>
            </sec>
            <sec id="sec21">
                <title>TagGen demultiplexer is designed for anchor-free tags</title>
                <p>To benchmark taggen-demux in a standard dual-ended library context, we compared its performance against minibar (v0.25), a widely used primer-anchored demultiplexer for ONT data. Simulated reads were generated with a dual-ended structure ([barcode [adapter][insert] [RC (adapter)][RC (barcode)]) using the same TagGen-generated Levenshtein barcodes (n&#x00a0;=&#x00a0;96, l&#x00a0;=&#x00a0;14/20/30&#x00a0;bp, d&#x00a0;=&#x00a0;4/8/8) and Badread simulator used for the rest of the benchmarks. Both tools were given the same barcode FASTA; minibar was additionally provided the flanking adapter sequence, which taggen-demux does not use. The two tools differ fundamentally in their matching strategy. Taggen-demux performs an anchor-free alignment: it searches a window at the read end and computes the edit distance between each reference barcode and the raw read sequence. It therefore operates without any knowledge of where the barcode ends and the adapter begins. Minibar uses a two-step primer-anchored approach: it first locates the adapter by alignment, then extracts the bases immediately upstream as the barcode, and finally compares only those extracted bases against the reference set. When sequencing indels shift the barcode region within the read, primer-anchored extraction isolates the barcode cleanly; the anchor-free approach must absorb those indels within its edit-distance threshold. At high read identity (&#x2265;90%), minibar assigned more reads correctly than taggen-demux for 20 and 30&#x00a0;bp barcodes (95&#x2013;100% vs 78&#x2013;97%), with near-zero misassignment in both cases (
                    <xref ref-type="fig" rid="f3">
Figure 3</xref>). At 80% read identity, where an average 30&#x00a0;bp barcode carries approximately six sequencing errors, minibar still achieved 88% accuracy for 30&#x00a0;bp barcodes, compared to 59% for taggen-demux. For short barcodes (14&#x00a0;bp) at low identity (80&#x2013;85%), the two tools performed comparably (17&#x2013;42%), as the adapter itself becomes too corrupted for reliable anchoring and the tight acceptance threshold (2 edit operations) limits both approaches equally. Taggen-demux consistently produced a small misassignment rate (0.05&#x2013;1.4%), while minibar produced near-zero misassignment across all conditions. The higher misassignment for taggen-demux at l&#x00a0;=&#x00a0;20&#x00a0;bp and low identity reflects the more liberal acceptance threshold (edit_dist&#x00a0;=&#x00a0;5 out of 20&#x00a0;bp&#x00a0;=&#x00a0;25% of tag length) combined with the absence of primer-assisted barcode extraction. These results confirm that when flanking adapter sequences are known and library structure is fixed, primer-anchored tools such as minibar extract barcodes with higher sensitivity. Taggen-demux is not designed to compete in this scenario; its intended contribution lies in settings where primer sequences are unavailable, variable in position, or absent by design &#x2013; including direct RNA sequencing, spatial transcriptomics capture plates, and custom library structures in which the barcode is not flanked by a consistent adapter. These scenarios, which minibar cannot address, are evaluated in the following sections.</p>
                <fig fig-type="figure" id="f3" orientation="portrait" position="float">
                    <label>
Figure 3. </label>
                    <caption>
                        <title>Comparison of taggen-demux and minibar demultiplexers.</title>
                        <p>Both tools were applied to the same simulated dual-ended ONT reads ([barcode][adapter][insert] [RC (adapter)][RC (barcode)], 100 reads per barcode, n&#x00a0;=&#x00a0;96, Badread nanopore2023 error model). taggen-demux operated in end mode without primer information; minibar additionally received the flanking adapter sequence as a positional anchor. 
                            <bold>(A)</bold> Demultiplexing accuracy and 
                            <bold>(B)</bold> misassignment rate as a function of simulated read identity, for three barcode lengths and minimum pairwise Levenshtein distances (l&#x00a0;=&#x00a0;14&#x00a0;bp d&#x00a0;=&#x00a0;4, l&#x00a0;=&#x00a0;20&#x00a0;bp d&#x00a0;=&#x00a0;8, l&#x00a0;=&#x00a0;30&#x00a0;bp d&#x00a0;=&#x00a0;8). Solid lines, taggen-demux; dashed lines, minibar. Minibar achieves higher assignment rates at medium-to-high read identity by leveraging the primer anchor, whereas taggen-demux is designed for library configurations in which no such anchor is available.</p>
                    </caption>
                    <graphic id="gr3" orientation="portrait" position="float" xlink:href="https://f1000research-files.f1000.com/manuscripts/198458/64f563d2-c353-421a-820f-c9f8b9c98302_figure3.gif"/>
                </fig>
            </sec>
            <sec id="sec22">
                <title>Long barcodes provide superior nanopore error tolerance</title>
                <p>The key advantage of longer barcodes becomes evident under simulated nanopore errors (
                    <xref ref-type="table" rid="T4">
Table 4</xref>, 
                    <xref ref-type="fig" rid="f4">
Figure 4</xref>). End-mode demultiplexing accuracy increased monotonically with both tag length and read identity (
                    <xref ref-type="fig" rid="f4">
Figure 4A</xref>). At 95% read identity &#x2013; representative of latest ONT chemistry &#x2013; accuracy reached 84.7%, 92.2%, 93.3%, and 97.5% for tag lengths of 14, 20, 24, and 30&#x00a0;bp, respectively, with near-zero misassignment (&lt;0.03%) in all cases (
                    <bold>Extended Data Figure 4</bold>). At 85% identity, which corresponds to older R9.4.1 flow cells or low-complexity regions, accuracy ranged from 42.2% (14&#x00a0;bp) to 77.1% (30&#x00a0;bp). Reads that could not be confidently assigned were rejected as unassigned rather than being misassigned, preserving the integrity of all assigned reads. We therefore recommend 30&#x00a0;bp Levenshtein-generated tags for experiments where read quality is expected to be moderate (&#x2264;90% identity).</p>
                <fig fig-type="figure" id="f4" orientation="portrait" position="float">
                    <label>
Figure 4. </label>
                    <caption>
                        <title>Systematic evaluation of taggen-demux across library configurations and sequencing conditions.</title>
                        <p>All simulations used Badread (nanopore2023 error model) at four read identity levels (80&#x2013;95%) representing the range from older R9.4.1 to current R10.4.1/Kit14 chemistry. 
                            <bold>(A)</bold> End-mode demultiplexing accuracy as a function of read identity for four barcode lengths (14, 20, 24, and 30&#x00a0;bp) generated with Levenshtein distance at the maximum feasible minimum distance per length (d&#x00a0;=&#x00a0;5, 8, 10, and 12, respectively; n&#x00a0;=&#x00a0;96). Longer barcodes provide progressively higher accuracy; 30&#x00a0;bp barcodes reach ~97% at 95% identity. 
                            <bold>(B)</bold> Effect of distance metric during barcode generation: Levenshtein-generated tags (solid) outperform Hamming-generated tags (dashed) at equal nominal minimum distance, with a gap of 3&#x2013;8 percentage points at 85&#x2013;90% identity, owing to the higher realised inter-tag edit distance achieved by greedy selection in Levenshtein space (n&#x00a0;=&#x00a0;48, end-mode, d&#x00a0;=&#x00a0;8 for l&#x00a0;=&#x00a0;20&#x00a0;bp and d&#x00a0;=&#x00a0;12 for l&#x00a0;=&#x00a0;30&#x00a0;bp). 
                            <bold>(C)</bold> Impact of full-mode position masks on demultiplexing accuracy for libraries with a 5&#x2032;-end barcode (n&#x00a0;=&#x00a0;96, l&#x00a0;=&#x00a0;30&#x00a0;bp, d&#x00a0;=&#x00a0;8, Levenshtein). End mode (reference) and full-mode with 5&#x2032; location information achieve very similar results, while full mode without a mask drops about 20% of accuracy. 
                            <bold>(D)</bold> Impact of full-mode position masks on demultiplexing accuracy for libraries with a mid-read barcode (n&#x00a0;=&#x00a0;96, l&#x00a0;=&#x00a0;30&#x00a0;bp, d&#x00a0;=&#x00a0;8, Levenshtein). End mode (reference) achieves near-zero accuracy as expected, confirming correct mode-restriction behaviour. Full-mode search with a fractional mask (0.05:0.20) reaches ~45% accuracy at 95% identity; a fixed 5&#x2032; mask (5p:60) and full mode without a mask show intermediate and lower performance, respectively. 
                            <bold>(E)</bold> Scalability: accuracy as a function of barcode set size from n&#x00a0;=&#x00a0;48 to n&#x00a0;=&#x00a0;384, for dual-ended (circles) and spatial (diamonds) library types at three read identity levels (l&#x00a0;=&#x00a0;30&#x00a0;bp, d&#x00a0;=&#x00a0;8, Levenshtein). Accuracy varies by less than 2 percentage points across the full range, confirming applicability to high-throughput spatial transcriptomics and population-scale experiments.</p>
                    </caption>
                    <graphic id="gr4" orientation="portrait" position="float" xlink:href="https://f1000research-files.f1000.com/manuscripts/198458/64f563d2-c353-421a-820f-c9f8b9c98302_figure4.gif"/>
                </fig>
            </sec>
            <sec id="sec23">
                <title>Levenshtein distance provides better accuracy</title>
                <p>At equal nominal minimum distance (d&#x00a0;=&#x00a0;8) and tag length (20&#x00a0;bp), tags generated with Levenshtein distance constraints consistently outperformed Hamming-generated tags across all read identity levels, with a gap that widened at lower identity (+3&#x2013;8 percentage points at 85&#x2013;90% identity) (
                    <xref ref-type="fig" rid="f4">
Figure 4B</xref>). This advantage stems from the greedy selection algorithm achieving a higher actual minimum pairwise Levenshtein distance when operating in Levenshtein space: for d&#x00a0;=&#x00a0;8 Levenshtein generation, the realised minimum inter-tag edit distance typically reached 12&#x2013;15&#x00a0;bp, whereas Hamming-designed tags of the same nominal d achieved lower Levenshtein separations due to the Hamming&#x2013;Levenshtein inequality. We therefore recommend Levenshtein generation for all ONT applications. Hamming-distance results are provided for comparison. At 30&#x00a0;bp and d&#x00a0;=&#x00a0;12, both metrics converged at high identity (&gt;95%), but Levenshtein remained superior at the clinically relevant 85&#x2013;90% range.</p>
            </sec>
            <sec id="sec24">
                <title>Position masking recovers tags in any spatial configuration</title>
                <p>For libraries where the barcode is positioned at the 5&#x2032; end of the read (spatial transcriptomics configuration, 
                    <xref ref-type="fig" rid="f4">
Figure 4C</xref>), end-mode demultiplexing was most effective (96.0% at 95% identity), as the tag is at the read terminus and is read with the lowest per-base error rate. Full-mode search with a 5&#x2032; position mask (5p:90, restricting the search window to the first 90&#x00a0;bp) matched end-mode performance (97.0% at 95% identity) and provided robustness to reads where the adapter truncated the tag start. Searching the full read without a mask reduced accuracy by 6&#x2013;8 percentage points due to spurious off-target matches within the mRNA body, with a concomitant rise in misassignment to ~0.8% at 85% identity. This underscores the importance of correctly specifying the position mask to match the barcode location in the read.</p>
                <p>For mid-read barcodes (DRS configuration, 
                    <xref ref-type="fig" rid="f4">
Figure 4D</xref>), end-mode correctly scored near-zero accuracy (~0%) as expected, confirming that the mode restriction works correctly. Full-mode with a 5p:90 mask achieved 98.0% accuracy at 95% identity. The fractional mask (0.05:0.20, covering 5&#x2013;20% of read length) provided equivalent performance and is more portable across variable-length reads.</p>
            </sec>
            <sec id="sec25">
                <title>TagGen scales to large barcode sets</title>
                <p>Despite increased difficulty of choosing from larger tag sets, accuracy was stable from n&#x00a0;=&#x00a0;48 to n&#x00a0;=&#x00a0;384 barcodes across all identity levels for both dual-ended and spatial library types, with less than 2 percentage points variation (
                    <xref ref-type="fig" rid="f4">
Figure 4E</xref>). At 95% identity, dual-ended end-mode accuracy remained above 97% up to 384 barcodes, and spatial full-mode (5p:90 mask) reached 97% at the same scale. At 85% identity, accuracy declined slightly with increasing n (from ~80% at n&#x00a0;=&#x00a0;48 to ~76% at n&#x00a0;=&#x00a0;384 for dual-ended), consistent with a greater probability of ambiguous assignment when the tag set is denser. These results confirm that taggen-demux scales to high-throughput spatial transcriptomics or population scale sequencing experiments without sacrificing accuracy.</p>
            </sec>
            <sec id="sec26">
                <title>Acceptance threshold can be tuned to reduce error rates</title>
                <p>The autoMaxDist parameter controls the maximum edit distance at which a read is accepted as matching a tag. The default adaptive rule (tag_length/5 for &lt;20&#x00a0;bp, tag_length/4 for 20&#x2013;29&#x00a0;bp, tag_length/3 for &#x2265;30&#x00a0;bp) maximises read assignment while keeping misassignment below 0.5% for all recommended configurations (end-mode and full-mode with position mask) at read identities &#x2265;85%. Users who require near-zero misassignment &#x2013; for example in clinical or single-cell applications where sample cross-contamination must be minimised &#x2013; should override the default with a more conservative threshold using the &#x2013;max-dist flag. For instance, taggen-demux &#x2013;max-dist 4 with 30&#x00a0;bp Levenshtein tags (d&#x00a0;=&#x00a0;8) reduces the misassignment rate to &lt;0.001% at the cost of leaving approximately 10&#x2013;15% more reads unassigned at 85% identity (
                    <bold>Extended Data Figure 4</bold>).</p>
            </sec>
            <sec id="sec27">
                <title>Use cases</title>
                <p>The following use cases demonstrate TagGen&#x2019;s application to common long-read sequencing scenarios. Example input parameters are summarized in 
                    <xref ref-type="table" rid="T5">
Table 5</xref>.</p>
                <table-wrap id="T5" orientation="portrait" position="float">
                    <label>
Table 5. </label>
                    <caption>
                        <title>Parameters for different use cases.</title>
                        <p>Input settings for barcode generation and demultiplexing across three representative library scenarios: high-error-tolerance direct RNA sequencing (UC1), older-chemistry ONT multiplexing (UC2), and single-cell spatial transcriptomics (UC3).</p>
                    </caption>
                    <table content-type="article-table" frame="hsides">
                        <thead>
                            <tr>
                                <th align="left" colspan="1" rowspan="1" valign="top">Use Case</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">UC1</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">UC2</th>
                                <th align="left" colspan="1" rowspan="1" valign="top">UC3</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Barcode length</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">24&#x00a0;bp</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">30&#x00a0;bp</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">30&#x00a0;bp</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Target count</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">48</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">96</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">384</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Minimum distance</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">10</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">8</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">8</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">GC content</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">45&#x2013;55</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">40&#x2013;60</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">40&#x2013;60</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Homopolymer limit</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">2</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">3</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">3</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Custom exclude sequences</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">&#x2013;</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">&#x2713;</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">&#x2013;</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Demultiplexer mode</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">End mode</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">Full mode</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">Full mode</td>
                            </tr>
                            <tr>
                                <td align="left" colspan="1" rowspan="1" valign="middle">Mask</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">&#x2013;</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">5p:60</td>
                                <td align="left" colspan="1" rowspan="1" valign="top">0.05:0.20</td>
                            </tr>
                        </tbody>
                    </table>
                </table-wrap>
                <p>

                    <underline>

                        <italic toggle="yes">Introductory example: Standard ONT Sample Multiplexing</italic>
</underline>
                </p>
                <p>

                    <underline>Scenario:</underline> A researcher needs to multiplex 96 samples for Oxford Nanopore sequencing using the standard flow cell configuration.</p>
                <p>Input Parameters:</p>
                <p>Barcode length: 14 bp</p>
                <p>Target count: 96</p>
                <p>Minimum Hamming distance: 4</p>
                <p>GC content: 40&#x2013;60%</p>
                <p>Homopolymer limit: 3</p>
                <p>CLI Command: taggen -n 96 -l 14 -d 4 --minGc 40 --maxGc 60 -r 3 -o ont_barcodes</p>
                <p>Example Output (first 4 barcodes in ont_barcodes.fasta):</p>
                <p>&gt;Tag_001</p>
                <p>ACGTACGTACGTAC</p>
                <p>&gt;Tag_002</p>
                <p>TGCATGCATGCATG</p>
                <p>&gt;Tag_003</p>
                <p>GATCGATCGATCGA</p>
                <p>&gt;Tag_004</p>
                <p>CTAGCTAGCTAGCT</p>
                <p>Generation time: 54 ms</p>
                <p>Demultiplexing command: taggen --demux --tags ont_barcodes.fasta --reads reads.fastq --mode end --trim-mode ends</p>
                <p>Expected performance: &gt;97% correct barcode assignment at typical ONT error rates (10&#x2013;15%).</p>
                <p>

                    <underline>

                        <italic toggle="yes">Use Case 1: High-Error-Tolerance Direct RNA Sequencing</italic>
</underline>
                </p>
                <p>End-mode demultiplexing with custom adapter exclusion</p>
                <p>

                    <underline>Scenario:</underline> Direct RNA sequencing of degraded clinical samples where higher error rates are expected. Maximum error tolerance is required. 48-sample multiplexing experiment using a custom ligation adapter containing an 18 bp recognition sequence.</p>
                <p>A common challenge in custom ONT library protocols is that proprietary or in-house adapters introduce short sequences that can cross-hybridise with naively generated barcodes, leading to spurious demultiplexing assignments. TagGen&#x2019;s &#x2013;exclude flag accepts a FASTA file of sequences to avoid; the greedy selection algorithm discards any candidate barcode whose edit distance to any excluded sequence falls below the minimum distance threshold, ensuring that the final tag set is orthogonal to the adapter.</p>
                <p>For this scenario we recommend 24 bp Levenshtein tags with a minimum pairwise distance of d=10 to provide sufficient error tolerance. At 95% read identity &#x2013; achievable with current R10.4.1/Kit14 chemistry &#x2013; end-mode demultiplexing reaches 93.3% accuracy with near-zero misassignment. At 90% identity, accuracy is 83.5%, still suitable for standard discovery scale experiments.</p>
                <p>Input Parameters:</p>
                <p>Barcode length: 24 bp</p>
                <p>Target count: 48</p>
                <p>Minimum Levenshtein distance: 10</p>
                <p>GC content: 45&#x2013;55% (tighter for RNA stability)</p>
                <p>Homopolymer limit: 2 (stricter for basecalling accuracy)</p>
                <p>CLI Command: taggen -n 48 -l 24 -d 10 --metric levenshtein --minGc 45 --&#x2013;maxGc 55 -r 2 --excludeFile custom_adapter.fasta -o uc1_tags -v</p>
                <p>taggen --demux --tags uc1_tags.fasta --reads reads.fastq --mode end --trim-mode all</p>
                <p>Generation time: ~30 ms</p>
                <p>Expected performance: &gt;98% correct assignment even at 20% error rate.</p>
                <p>

                    <underline>

                        <italic toggle="yes">Use Case 2: Standard ONT Multiplexing with Older Chemistry</italic>
</underline>
                </p>
                <p>

                    <underline>Scenario:</underline> A user has older-chemistry flow cells and needs to generate 96 barcodes that can still be confidently demultiplexed at high error rates.</p>
                <p>Older R9.4.1 flow cells and high-molecular-weight or degraded samples routinely produce reads at 85&#x2013;90% per-base identity. Under these conditions, strict end-mode demultiplexing is sensitive to read-start quality: partial exonuclease activity or pore clogging can introduce a few extra bases before the barcode, shifting it slightly from position 0. Full-mode search with a 5&#x2032; position mask (-position-mask 5p:60) restricts the alignment window to the first 60 bp of each read, tolerating this positional jitter while avoiding spurious matches in the downstream read body.</p>
                <p>We recommend 30 bp Levenshtein barcodes (d=8) for this scenario. Benchmarks with simulated 5&#x2032;-tagged reads show that full-mode with a 5p:60 mask achieves 84% accuracy at 85% read identity and 97% at 95% identity, matching or slightly exceeding end mode across the full identity range and maintaining misassignment below 0.1% in all conditions.</p>
                <p>Input Parameters:</p>
                <p>Barcode length: 30 bp</p>
                <p>Target count: 96</p>
                <p>Minimum Levenshtein distance: 8</p>
                <p>Exclude sequences: Custom FASTA file containing adapter sequences</p>
                <p>Exclude File (adapters.fasta):</p>
                <p>&gt;adapter_forward</p>
                <p>AGATCGGAAGAGCACACGTCT</p>
                <p>&gt;adapter_reverse</p>
                <p>AGATCGGAAGAGCGTCGTGTA</p>
                <p>&gt;custom_primer</p>
                <p>TCGTCGGCAGCGTCAGATGTG</p>
                <p>CLI Command: taggen -n 96 -l 30 -d 8 --metric levenshtein -f custom_adapter.fasta -o uc2_tags -v</p>
                <p>taggen --demux --tags uc2_tags.fasta --reads reads.fastq --mode full --position-mask 5p:60 --trim-mode all</p>
                <p>Generation time: ~95 ms</p>
                <p>Expected performance: At 95% identity, full-mode with 5p:60 mask achieves 97% accuracy with near-zero misassignment; at 85% identity, accuracy is 84%, suitable for older chemistry experiments.</p>
                <p>

                    <underline>

                        <italic toggle="yes">Use Case 3: Single-Cell RNA-seq with Spatial Barcodes (Zero Misassignment)</italic>
</underline>
                </p>
                <p>

                    <underline>Scenario:</underline> Designing location barcodes for a custom spatial transcriptomics array with 384 capture spots, requiring error correction capability for imaging-based readout combined with nanopore sequencing.</p>
                <p>In single-cell RNA-seq experiments where each barcode labels an individual patient sample or cell population, even a fraction of a percent of cross-sample contamination confounds downstream differential expression analysis. Here the barcode is embedded within a synthetic RNA spike-in added to each sample: during sequencing the tag appears mid-read, flanked by transcript sequence on both sides, at a position corresponding to roughly 5&#x2013;20% of read length.</p>
                <p>The fractional position mask (--position-mask 0.05:0.20) directs the search to this window regardless of read length, making the parameter portable across cells with varying transcript sizes. To achieve near-zero misassignment, we override the default acceptance threshold with --max-dist 4: at 90% read identity, this reduces misassignment from &lt;0.1% (default) to &lt;0.001%, at the cost of leaving approximately 10&#x2013;15% more reads unassigned &#x2013; a worthwhile trade when sample integrity is paramount.</p>
                <p>Input Parameters: Barcode length: 30 bp</p>
                <p>Target count: 384</p>
                <p>Minimum Levenshtein distance: 8</p>
                <p>GC content: 40&#x2013;60%</p>
                <p>Homopolymer limit: 3</p>
                <p>CLI Command: taggen -n 384 -l 30 -d 8 --metric levenshtein --heatmap -o uc3_tags -v</p>
                <p>taggen --demux --tags uc3_tags.fasta --reads reads.fastq \</p>
                <p>--mode full --position-mask 0.05:0.20 \</p>
                <p>--max-dist 4 --trim-mode all</p>
                <p>Generation time: ~1.4 s. Expected performance: With &#x2013;max-dist 4, misassignment is reduced to &lt;0.001% at 90% read identity; approximately 10&#x2013;15% of reads are left unassigned, which is acceptable when sample integrity is paramount.</p>
            </sec>
        </sec>
        <sec id="sec28" sec-type="discussion">
            <title>Discussion</title>
            <sec id="sec29">
                <title>Filling a critical gap for long-read sequencing</title>
                <p>The adoption of nanopore sequencing for transcriptomics, metagenomics, and clinical applications has outpaced the development of supporting bioinformatic tools. While barcode generators designed for Illumina sequencing work well at 8&#x2013;12&#x00a0;bp, they cannot scale to the lengths required for error-tolerant nanopore barcoding.</p>
                <p>TagGen (see 
                    <xref ref-type="fig" rid="f5">
Figure 5</xref> for the graphical and command line user interface snapshots) addresses this gap through algorithmic innovation. By replacing O(4
                    <sup>n</sup>) enumeration with O(k) sampling, we transform an exponentially scaling problem into a constant-time operation. The practical consequence is that TagGen succeeds &#x2013; in milliseconds &#x2013; at lengths where existing tools fail entirely. TagGen was designed to address a specific and underserved scenario in long-read sequencing: multiplexing experiments in which barcodes are not flanked by known primer or adapter sequences. In standard short-read or kit-based ONT workflows, demultiplexers such as minibar
                    <sup>
                        <xref ref-type="bibr" rid="ref20">20</xref>
                    </sup> or Dorado
                    <sup>
                        <xref ref-type="bibr" rid="ref21">21</xref>
                    </sup> leverage flanking adapter sequences as positional anchors, first locating the adapter and then extracting the adjacent barcode for comparison. This strategy works well when the library structure is fixed and the adapter sequence is intact. It fails &#x2013; or cannot be applied at all &#x2013; in custom library preparations, direct RNA sequencing, spatial transcriptomics capture plates, and synthetic RNA spike-in approaches, where either no consistent flanking sequence exists or the barcode can appear at variable positions within the read.</p>
                <fig fig-type="figure" id="f5" orientation="portrait" position="float">
                    <label>
Figure 5. </label>
                    <caption>
                        <title>TagGen graphical user interface and command-line interface.</title>
                        <p>The composite screenshot shows four views of the TagGen application. Top left: the Generate tab, where users configure barcode parameters (tag length, count, minimum distance, GC content bounds, homopolymer limit, and exclude sequences) and preview generated barcodes with their core sequences, lengths, and GC content. Top right: the interactive pairwise distance heatmap displaying minimum Hamming or Levenshtein distances between all generated barcodes, enabling visual quality verification; generated barcodes can be exported in FASTA or TSV format. Bottom left: the Demultiplex tab, where users load barcode and FASTQ files, select search mode (end or full), configure position masks and acceptance thresholds, and view demultiplexing results. Centre: the command-line interface showing equivalent generation and demultiplexing commands with their options, demonstrating the full CLI workflow.</p>
                    </caption>
                    <graphic id="gr5" orientation="portrait" position="float" xlink:href="https://f1000research-files.f1000.com/manuscripts/198458/64f563d2-c353-421a-820f-c9f8b9c98302_figure5.gif"/>
                </fig>
                <p>Our benchmarks confirm both sides of this distinction. In a head-to-head comparison on primer-flanked dual-ended reads &#x2013; the use case for which minibar was designed &#x2013; minibar achieves higher assignment rates than taggen-demux in anchor-free mode, particularly at longer barcodes and higher read identities (88&#x2013;100% vs 59&#x2013;97% at 80&#x2013;95% identity, 30&#x00a0;bp barcodes). This is expected: primer anchoring is a genuinely more powerful strategy when the primer is present and intact. The comparison therefore does not identify a weakness in TagGen; it demarcates the two tools&#x2019; intended operating regimes. Where TagGen adds unique value is the large class of applications in which a primer anchor is absent, unreliable, or structurally variable &#x2013; precisely the conditions under which minibar and analogous tools cannot be used.</p>
            </sec>
            <sec id="sec30">
                <title>Quantified error tolerance for nanopore applications</title>
                <p>Our systematic benchmarking across 154 simulated conditions (
                    <bold>Panels A&#x2013;E</bold>, 
                    <xref ref-type="fig" rid="f4">
Figure 4</xref>) provides the first comprehensive characterisation of anchor-free barcode demultiplexing performance as a function of tag length, minimum distance, error metric, position mask, and barcode set size.</p>
                <p>The choice of error metric during tag generation has a direct and substantial effect on demultiplexing accuracy. Tags generated with Levenshtein distance constraints outperform Hamming-generated tags at equal nominal minimum distance, with a gap of 3&#x2013;8 percentage points at 85&#x2013;90% read identity. The mechanistic explanation is that the greedy selection algorithm, when operating in Levenshtein space, achieves a higher realised minimum pairwise edit distance between tags than the required minimum (typically 12&#x2013;15&#x00a0;bp achieved vs 8&#x00a0;bp required for l&#x00a0;=&#x00a0;30&#x00a0;bp, n&#x00a0;=&#x00a0;96). Tags generated with Hamming d&#x00a0;=&#x00a0;8 achieve lower realized Levenshtein separation due to the Hamming&#x2013;Levenshtein inequality, leaving them more vulnerable to insertion and deletion errors characteristic of nanopore sequencing. We therefore recommend Levenshtein generation for all ONT applications. For standard 5&#x2032;-tagged libraries, end-mode demultiplexing of 30&#x00a0;bp Levenshtein barcodes (d&#x00a0;=&#x00a0;8, n&#x00a0;=&#x00a0;96) achieves 96% accuracy at 95% read identity and 78% at 85% identity. Full-mode search with a 5&#x2032; position mask (&#x2212;-position-mask 5p:60) matches or slightly exceeds end-mode performance and additionally tolerates reads in which the barcode is shifted from position 0 due to partial adapter degradation &#x2013; a common occurrence with older R9.4.1 flow cells or degraded samples. This mode is recommended for high sample-count experiments on older chemistry where read starts are less uniform.</p>
                <p>For mid-read barcodes &#x2013; including tags embedded in synthetic RNA spike-ins for single-cell applications or tags placed internal to amplicons &#x2013; end-mode demultiplexing correctly assigns near-zero reads, confirming that the mode restriction functions as a safety mechanism: reads are rejected rather than misassigned when the search window does not encompass the barcode position. Full-mode with a fractional position mask (&#x2212;-position-mask 0.05:0.20) achieves 98% accuracy at 90% identity and is robust across variable read lengths. For zero-misassignment applications such as patient sample tracking in single-cell clinical studies, the &#x2013;max-dist override reduces misassignment to &lt;0.001% at a cost of approximately 10&#x2013;15% more unassigned reads. Noise simulation provides the first systematic validation of barcode resilience under realistic nanopore error profiles. The results have direct implications for experimental design. Standard ONT sequencing (10&#x2013;15% error): Barcodes &#x2265;14&#x00a0;bp with d&#x00a0;&#x2265;&#x00a0;4 achieve &gt;97% resolution. Challenging conditions (20% error): Barcodes &#x2265;20&#x00a0;bp with d&#x00a0;&#x2265;&#x00a0;6 maintain &gt;98% resolution. Direct RNA sequencing with degraded samples: 30&#x00a0;bp barcodes with d&#x00a0;&#x2265;&#x00a0;8 provide near-perfect resolution even at 25% error. These findings suggest that researchers using nanopore sequencing should consider migrating from traditional 10&#x2013;12&#x00a0;bp barcodes to 14&#x2013;20&#x00a0;bp barcodes for routine applications, and to 24&#x2013;30&#x00a0;bp barcodes when sample quality is uncertain.</p>
            </sec>
            <sec id="sec31">
                <title>Enabling new applications</title>
                <p>TagGen&#x2019;s capabilities enable several applications previously impractical due to computational limitations:
                    <list list-type="bullet">
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Direct RNA sequencing: Full-length transcript barcoding with resilience to RNA degradation; anchor-free demultiplexing locates mid-read barcodes without adapter sequences</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Spatial transcriptomics on ONT: Location barcodes robust to platform-specific errors, with fractional position masks enabling demultiplexing across variable-length reads</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Environmental metagenomics: Sample multiplexing for long-read community profiling</p>
                        </list-item>
                        <list-item>
                            <label>&#x2022;</label>
                            <p>Clinical nanopore diagnostics: High-confidence sample identification in point-of-care settings, with configurable acceptance thresholds to achieve near-zero misassignment rates</p>
                        </list-item>
                    </list>
                </p>
            </sec>
            <sec id="sec32">
                <title>Limitations</title>
                <p>Several limitations should be considered when using TagGen.</p>
                <p>Distance metric: TagGen supports both Hamming and Levenshtein distance for barcode generation, and uses Levenshtein distance for demultiplexing. While the validation results confirm high accuracy under indel-rich nanopore error profiles, future work could explore probability divergence
                    <sup>
                        <xref ref-type="bibr" rid="ref15">15</xref>
                    </sup> as an alternative metric for selection, which may offer additional gains in barcode separability for high-error profiles.</p>
                <p>
Optimality: The greedy selection algorithm produces locally optimal but not globally optimal barcode sets. For most practical applications with 96&#x2013;384 barcodes, this approximation is sufficient, but users requiring mathematically optimal sets for very large barcode counts may need to employ more computationally intensive methods such as integer linear programming.</p>
                <p>Memory scaling: While TagGen avoids the exponential memory requirements of exhaustive enumeration, very large candidate pools (&gt;1 million sequences) for extremely long barcodes may still require substantial RAM. The default candidate pool size is tuned for typical applications.</p>
            </sec>
        </sec>
        <sec id="sec33" sec-type="conclusions">
            <title>Conclusions</title>
            <p>TagGen represents the first barcode generator capable of producing error-tolerant barcodes for long-read sequencing applications. Key contributions include:
                <list list-type="order">
                    <list-item>
                        <label>1.</label>
                        <p>Algorithmic advance: Monte Carlo sampling replaces exponential enumeration, enabling barcode generation at 14&#x2013;30&#x00a0;bp</p>
                    </list-item>
                    <list-item>
                        <label>2.</label>
                        <p>Validated resilience: Systematic demonstration that longer barcodes maintain resolution under nanopore error profiles</p>
                    </list-item>
                    <list-item>
                        <label>3.</label>
                        <p>Practical utility: Sub-second generation times for lengths where existing tools fail</p>
                    </list-item>
                    <list-item>
                        <label>4.</label>
                        <p>Anchor-free demultiplexing: An integrated demultiplexer that locates barcodes at any read position without requiring adapter sequences, validated across 154 parameter combinations with near-zero misassignment.</p>
                    </list-item>
                    <list-item>
                        <label>5.</label>
                        <p>Dual interface: Both GUI for interactive use and comprehensive CLI for automated pipelines</p>
                    </list-item>
                </list>
            </p>
            <p>As nanopore sequencing expands into transcriptomics, diagnostics, and field applications, TagGen provides researchers with the tools to design robust, validated barcodes matched to their platform&#x2019;s error characteristics and library architecture.</p>
        </sec>
    </body>
    <back>
        <sec id="sec36" sec-type="data-availability">
            <title>Data availability</title>
            <p>TagGen benchmark and validation data is available on a Zenodo repository: 
                <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.5281/zenodo.19422508">https://doi.org/10.5281/zenodo.19422508</ext-link> (Shirokikh N, 2026). This repository also contains Extended Data figures relevant to this publication.</p>
            <p>This project contains the following underlying data:
                <list list-type="bullet">
                    <list-item>
                        <label>&#x2022;</label>
                        <p>
nanopore_noise_results.csv &#x2013; Simulated barcode resolution under nanopore error profiles (
                            <xref ref-type="table" rid="T4">
Table 4</xref> source data)</p>
                    </list-item>
                    <list-item>
                        <label>&#x2022;</label>
                        <p>performance_comparison.csv &#x2013; Performance benchmarks comparing TagGen and DNABarcodes (
                            <xref ref-type="table" rid="T3">
Table 3</xref> source data)</p>
                    </list-item>
                    <list-item>
                        <label>&#x2022;</label>
                        <p>
nanopore_noise_simulation.py &#x2013; Python script for error simulation and barcode assignment testing</p>
                    </list-item>
                    <list-item>
                        <label>&#x2022;</label>
                        <p>benchmark_scripts/ &#x2013; Scripts used for performance benchmarking</p>
                    </list-item>
                </list>
            </p>
            <p>Data are available under the terms of the 
                <ext-link ext-link-type="uri" xlink:href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 International license (CC-BY 4.0)</ext-link>.</p>
        </sec>
        <sec id="sec37">
            <title>Software availability</title>
            <p>Source code available from GitHub: 
                <ext-link ext-link-type="uri" xlink:href="https://github.com/Arnaroo/taggen">https://github.com/Arnaroo/taggen</ext-link>
            </p>
            <p>Archived software available from Zenodo: 
                <ext-link ext-link-type="uri" xlink:href="https://doi.org/10.5281/zenodo.19490778">https://doi.org/10.5281/zenodo.19490778</ext-link>
            </p>
            <p>License: MIT License.</p>
        </sec>
        <ack>
            <title>Acknowledgments</title>
            <p>The authors are very grateful to the RNA Innovation Foundry (RIF) and The Australian Centre for RNA Therapeutics in Cancer (ACRTC) teams for the useful and enabling discussions around the project, and inspiring its idea.</p>
        </ack>
        <ref-list>
            <title>References</title>
            <ref id="ref1">
                <label>1</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Amarasinghe</surname>
                            <given-names>SL</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Su</surname>
                            <given-names>S</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Dong</surname>
                            <given-names>X</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Opportunities and challenges in long-read sequencing data analysis.</article-title>
                    <source>

                        <italic toggle="yes">Genome Biol.</italic>
</source>
                    <year>2020 Feb 7</year>;<volume>21</volume>(<issue>1</issue>):<fpage>30</fpage>.
                    <pub-id pub-id-type="doi">10.1186/s13059-020-1935-5</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref2">
                <label>2</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Garalde</surname>
                            <given-names>DR</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Snell</surname>
                            <given-names>EA</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Jachimowicz</surname>
                            <given-names>D</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Highly parallel direct RNA sequencing on an array of nanopores.</article-title>
                    <source>

                        <italic toggle="yes">Nat Methods.</italic>
</source>
                    <year>2018 Mar</year>;<volume>15</volume>(<issue>3</issue>):<fpage>201</fpage>&#x2013;<lpage>206</lpage>.
                    <pub-id pub-id-type="doi">10.1038/nmeth.4577</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref3">
                <label>3</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Workman</surname>
                            <given-names>RE</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Tang</surname>
                            <given-names>AD</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Tang</surname>
                            <given-names>PS</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Nanopore native RNA sequencing of a human poly(A) transcriptome.</article-title>
                    <source>

                        <italic toggle="yes">Nat Methods.</italic>
</source>
                    <year>2019 Dec</year>;<volume>16</volume>(<issue>12</issue>):<fpage>1297</fpage>&#x2013;<lpage>1305</lpage>.
                    <pub-id pub-id-type="pmid">31740818</pub-id>
                    <pub-id pub-id-type="doi">10.1038/s41592-019-0617-2</pub-id>
                    <pub-id pub-id-type="pmcid">PMC7768885</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref4">
                <label>4</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Smith</surname>
                            <given-names>MA</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Ersavas</surname>
                            <given-names>T</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Ferguson</surname>
                            <given-names>JM</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Molecular barcoding of native RNAs using nanopore sequencing and deep learning.</article-title>
                    <source>

                        <italic toggle="yes">Genome Research.</italic>
</source>
                    <year>2020 Sep</year>;<volume>30</volume>(<issue>9</issue>):<fpage>1345</fpage>&#x2013;<lpage>1353</lpage>.
                    <pub-id pub-id-type="doi">10.1101/gr.260836.120</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref5">
                <label>5</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Rang</surname>
                            <given-names>FJ</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Kloosterman</surname>
                            <given-names>WP</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Ridder</surname>
                            <given-names>J</given-names>
                            <prefix>de</prefix>
                        </name>
</person-group>:
                    <article-title>From squiggle to basepair: computational approaches for improving nanopore sequencing read accuracy.</article-title>
                    <source>

                        <italic toggle="yes">Genome Biol.</italic>
</source>
                    <year>2018 Jul 13</year>;<volume>19</volume>(<issue>1</issue>):<fpage>90</fpage>.
                    <pub-id pub-id-type="pmid">30005597</pub-id>
                    <pub-id pub-id-type="doi">10.1186/s13059-018-1462-9</pub-id>
                    <pub-id pub-id-type="pmcid">PMC6045860</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref6">
                <label>6</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Delahaye</surname>
                            <given-names>C</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Nicolas</surname>
                            <given-names>J</given-names>
                        </name>
</person-group>:
                    <article-title>Sequencing DNA with nanopores: Troubles and biases.</article-title>
                    <source>

                        <italic toggle="yes">PLoS One.</italic>
</source>
                    <year>2021</year>;<volume>16</volume>(<issue>10</issue>):<fpage>e0257521</fpage>.
                    <pub-id pub-id-type="pmid">34597327</pub-id>
                    <pub-id pub-id-type="doi">10.1371/journal.pone.0257521</pub-id>
                    <pub-id pub-id-type="pmcid">PMC8486125</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref7">
                <label>7</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Meyer</surname>
                            <given-names>M</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Kircher</surname>
                            <given-names>M</given-names>
                        </name>
</person-group>:
                    <article-title>Illumina Sequencing Library Preparation for Highly Multiplexed Target Capture and Sequencing.</article-title>
                    <source>

                        <italic toggle="yes">Cold Spring Harb Protoc.</italic>
</source>
                    <year>2010 Jun</year>;<volume>2010</volume>(<issue>6</issue>):<fpage>pdb.prot5448</fpage>.
                    <pub-id pub-id-type="doi">10.1101/pdb.prot5448</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref8">
                <label>8</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Smith</surname>
                            <given-names>AM</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Heisler</surname>
                            <given-names>LE</given-names>
                        </name>

                        <name name-style="western">
                            <surname>St Onge</surname>
                            <given-names>RP</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Highly-multiplexed barcode sequencing: an efficient method for parallel analysis of pooled samples.</article-title>
                    <source>

                        <italic toggle="yes">Nucleic Acids Res.</italic>
</source>
                    <year>2010 Jul</year>;<volume>38</volume>(<issue>13</issue>):<fpage>e142</fpage>.
                    <pub-id pub-id-type="doi">10.1093/nar/gkq368</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref9">
                <label>9</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Buschmann</surname>
                            <given-names>T</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Bystrykh</surname>
                            <given-names>LV</given-names>
                        </name>
</person-group>:
                    <article-title>Levenshtein error-correcting barcodes for multiplexed DNA sequencing.</article-title>
                    <source>

                        <italic toggle="yes">BMC Bioinformatics.</italic>
</source>
                    <year>2013 Sep 11</year>;<volume>14</volume>(<issue>1</issue>):<fpage>272</fpage>.
                    <pub-id pub-id-type="doi">10.1186/1471-2105-14-272</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref10">
                <label>10</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Buschmann</surname>
                            <given-names>T</given-names>
                        </name>
</person-group>:
                    <article-title>DNABarcodes: an R package for the systematic construction of DNA sample tags.</article-title>
                    <source>

                        <italic toggle="yes">Bioinformatics.</italic>
</source>
                    <year>2017 Mar 15</year>;<volume>33</volume>(<issue>6</issue>):<fpage>920</fpage>&#x2013;<lpage>922</lpage>.
                    <pub-id pub-id-type="doi">10.1093/bioinformatics/btw759</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref11">
                <label>11</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Costea</surname>
                            <given-names>PI</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Lundeberg</surname>
                            <given-names>J</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Akan</surname>
                            <given-names>P</given-names>
                        </name>
</person-group>:
                    <article-title>TagGD: Fast and Accurate Software for DNA Tag Generation and Demultiplexing.</article-title>
                    <source>

                        <italic toggle="yes">PLOS ONE.</italic>
</source>
                    <year>2013 Mar 4</year>;<volume>8</volume>(<issue>3</issue>):<fpage>e57521</fpage>.
                    <pub-id pub-id-type="pmid">23469199</pub-id>
                    <pub-id pub-id-type="doi">10.1371/journal.pone.0057521</pub-id>
                    <pub-id pub-id-type="pmcid">PMC3587622</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref12">
                <label>12</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Somervuo</surname>
                            <given-names>P</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Koskinen</surname>
                            <given-names>P</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Mei</surname>
                            <given-names>P</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>BARCOSEL: a tool for selecting an optimal barcode set for high-throughput sequencing.</article-title>
                    <source>

                        <italic toggle="yes">BMC Bioinformatics.</italic>
</source>
                    <year>2018 Jul 5</year>;<volume>19</volume>(<issue>1</issue>):<fpage>257</fpage>.
                    <pub-id pub-id-type="doi">10.1186/s12859-018-2262-7</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref13">
                <label>13</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Hawkins</surname>
                            <given-names>JA</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Jones</surname>
                            <given-names>SK</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Finkelstein</surname>
                            <given-names>IJ</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Indel-correcting DNA barcodes for high-throughput sequencing.</article-title>
                    <source>

                        <italic toggle="yes">Proc Natl Acad Sci U S A.</italic>
</source>
                    <year>2018 Jul 3</year>;<volume>115</volume>(<issue>27</issue>):<fpage>E6217</fpage>&#x2013;<lpage>E6226</lpage>.</mixed-citation>
            </ref>
            <ref id="ref14">
                <label>14</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Faircloth</surname>
                            <given-names>BC</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Glenn</surname>
                            <given-names>TC</given-names>
                        </name>
</person-group>:
                    <article-title>Not All Sequence Tags Are Created Equal: Designing and Validating Sequence Identification Tags Robust to Indels.</article-title>
                    <source>

                        <italic toggle="yes">PLoS ONE.</italic>
</source>
                    <year>2012 Aug 10</year>;<volume>7</volume>(<issue>8</issue>):<fpage>e42543</fpage>.
                    <pub-id pub-id-type="doi">10.1371/journal.pone.0042543</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref15">
                <label>15</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Yu</surname>
                            <given-names>T</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Ren</surname>
                            <given-names>Z</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Gao</surname>
                            <given-names>X</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Generating barcodes for nanopore sequencing data with PRO.</article-title>
                    <source>

                        <italic toggle="yes">Fundamental Research.</italic>
</source>
                    <year>2024 Jul</year>;<volume>4</volume>(<issue>4</issue>):<fpage>785</fpage>&#x2013;<lpage>794</lpage>.
                    <pub-id pub-id-type="pmid">39660352</pub-id>
                    <pub-id pub-id-type="doi">10.1016/j.fmre.2024.04.014</pub-id>
                    <pub-id pub-id-type="pmcid">PMC11630701</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref16">
                <label>16</label>
                <mixed-citation publication-type="other">
                    <collab>Technologies ON</collab>:
                    <article-title>qcat: Oxford Nanopore read demultiplexer.</article-title>
                    <year>2020</year>.
                    <ext-link ext-link-type="uri" xlink:href="https://github.com/nanoporetech/qcat">Reference Source</ext-link>
                </mixed-citation>
            </ref>
            <ref id="ref17">
                <label>17</label>
                <mixed-citation publication-type="other">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Wick</surname>
                            <given-names>RR</given-names>
                        </name>
</person-group>:
                    <article-title>Porechop: adapter trimmer for Oxford Nanopore reads.</article-title>
                    <year>2018</year>.
                    <ext-link ext-link-type="uri" xlink:href="https://github.com/rrwick/Porechop">Reference Source</ext-link>
                </mixed-citation>
            </ref>
            <ref id="ref18">
                <label>18</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Wick</surname>
                            <given-names>RR</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Judd</surname>
                            <given-names>LM</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Holt</surname>
                            <given-names>KE</given-names>
                        </name>
</person-group>:
                    <article-title>Performance of neural network basecalling tools for Oxford Nanopore sequencing.</article-title>
                    <source>

                        <italic toggle="yes">Genome Biol.</italic>
</source>
                    <year>2019 Jun 24</year>;<volume>20</volume>(<issue>1</issue>):<fpage>129</fpage>.
                    <pub-id pub-id-type="doi">10.1186/s13059-019-1727-y</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref19">
                <label>19</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Wick</surname>
                            <given-names>R</given-names>
                        </name>
</person-group>:
                    <article-title>Badread: simulation of error-prone long reads.</article-title>
                    <source>

                        <italic toggle="yes">Journal of Open Source Software.</italic>
</source>
                    <year>2019 Apr 4</year>;<volume>4</volume>(<issue>36</issue>):<fpage>1316</fpage>.
                    <pub-id pub-id-type="doi">10.21105/joss.01316</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref20">
                <label>20</label>
                <mixed-citation publication-type="journal">
                    <person-group person-group-type="author">

                        <name name-style="western">
                            <surname>Krehenwinkel</surname>
                            <given-names>H</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Pomerantz</surname>
                            <given-names>A</given-names>
                        </name>

                        <name name-style="western">
                            <surname>Henderson</surname>
                            <given-names>JB</given-names>
                        </name>

                        <etal/>
</person-group>:
                    <article-title>Nanopore sequencing of long ribosomal DNA amplicons enables portable and simple biodiversity assessments with high phylogenetic resolution across broad taxonomic scale.</article-title>
                    <source>

                        <italic toggle="yes">GigaScience.</italic>
</source>
                    <year>2019 May 1</year>;<volume>8</volume>(<issue>5</issue>).
                    <pub-id pub-id-type="pmid">30824940</pub-id>
                    <pub-id pub-id-type="doi">10.1093/gigascience/giz006</pub-id>
                    <pub-id pub-id-type="pmcid">PMC6503943</pub-id>
                </mixed-citation>
            </ref>
            <ref id="ref21">
                <label>21</label>
                <mixed-citation publication-type="other">
                    <collab>Oxford Nanopore Technologies</collab>:
                    <article-title>Dorado: Oxford Nanopore&#x2019;s basecaller.</article-title>
                    <year>2024</year>.
                    <ext-link ext-link-type="uri" xlink:href="https://github.com/nanoporetech/dorado">Reference Source</ext-link>
                </mixed-citation>
            </ref>
        </ref-list>
    </back>
    <sub-article article-type="reviewer-report" id="report486452">
        <front-stub>
            <article-id pub-id-type="doi">10.5256/f1000research.198458.r486452</article-id>
            <title-group>
                <article-title>Reviewer response for version 1</article-title>
            </title-group>
            <contrib-group>
                <contrib contrib-type="author">
                    <name>
                        <surname>Zheng</surname>
                        <given-names>Zhenxian</given-names>
                    </name>
                    <xref ref-type="aff" rid="r486452a1">1</xref>
                    <role>Referee</role>
                    <uri content-type="orcid">https://orcid.org/0000-0002-6546-2324</uri>
                </contrib>
                <aff id="r486452a1">
                    <label>1</label>University of Hong Kong, Hong Kong, China</aff>
            </contrib-group>
            <author-notes>
                <fn fn-type="conflict">
                    <p>
                        <bold>Competing interests: </bold>No competing interests were disclosed.</p>
                </fn>
            </author-notes>
            <pub-date pub-type="epub">
                <day>9</day>
                <month>6</month>
                <year>2026</year>
            </pub-date>
            <permissions>
                <copyright-statement>Copyright: &#x00a9; 2026 Zheng Z</copyright-statement>
                <copyright-year>2026</copyright-year>
                <license xlink:href="https://creativecommons.org/licenses/by/4.0/">
                    <license-p>This is an open access peer review report distributed under the terms of the Creative Commons Attribution Licence, which permits unrestricted use, distribution, and reproduction in any medium, provided the original work is properly cited.</license-p>
                </license>
            </permissions>
            <related-article ext-link-type="doi" id="relatedArticleReport486452" related-article-type="peer-reviewed-article" xlink:href="10.12688/f1000research.179899.1"/>
            <custom-meta-group>
                <custom-meta>
                    <meta-name>recommendation</meta-name>
                    <meta-value>reject</meta-value>
                </custom-meta>
            </custom-meta-group>
        </front-stub>
        <body>
            <p>This manuscript presents TagGen, a barcode generator and demultiplexer for long-read and nanopore sequencing applications. The topic is relevant, and the software may be useful for custom nanopore workflows where barcode position is variable or adapter anchors are unavailable. However, the current manuscript does not yet provide sufficient evidence to support its broad claims of high performance, robustness, and general applicability. The main workflow figure is difficult to interpret, the benchmark is too narrow, and the validation relies mainly on simulations.&#x00a0;</p>
            <p> </p>
            <p> Major comments</p>
            <p> </p>
            <p> 1. The main contribution and claims should be stated more cautiously.</p>
            <p> </p>
            <p> The manuscript repeatedly presents TagGen as a unique or broadly enabling tool for long-read barcode generation and demultiplexing. However, the introduction itself discusses several related tools, including DNABarcodes, PRO, FreeBarcodes, Edittag, BARCOSEL, TagGD, minibar, Dorado, and others. The current claims are therefore too broad. The clearest contribution of TagGen seems to be more specific: flexible-length barcode generation combined with anchor-free demultiplexing for custom or non-standard nanopore library designs. This is potentially useful, but the manuscript should clearly distinguish between demonstrated performance and anticipated applications. Statements such as &#x201c;high-performance,&#x201d; &#x201c;uniquely enables,&#x201d; or &#x201c;robust across long-read applications&#x201d; should be moderated unless supported by more comprehensive evidence.</p>
            <p> </p>
            <p> 2. Figure 1 is difficult to understand and should be redesigned.</p>
            <p> </p>
            <p> Figure 1 is intended to summarize the TagGen workflow, but in its current form it is visually crowded and not technically clear. It combines nanopore error profiles, the motivation for longer barcodes, exhaustive enumeration, Monte Carlo sampling, greedy selection, demultiplexing, validation heatmaps, GUI/CLI views, and application scenarios in one figure. As a result, it is hard to understand what the actual computational workflow is. A software-methods figure should clearly show the input, algorithmic steps, output, and decision criteria. I suggest completely redesigning Figure 1 into a simpler workflow with separate panels for barcode generation, barcode quality evaluation, and demultiplexing. Each panel should have clear inputs, processing steps, outputs, and key parameters. The current figure looks polished but does not help the reader understand the method.</p>
            <p> </p>
            <p> 3. The speed and algorithmic benchmark is too narrow.</p>
            <p> </p>
            <p> The manuscript describes TagGen as a high-performance tool, but the benchmark is still too narrow. For barcode generation, the main speed comparison is against DNABarcodes, which uses exhaustive enumeration and is expected to perform poorly at longer barcode lengths. This comparison is useful, but it does not show whether TagGen is competitive with other relevant barcode design tools.</p>
            <p> </p>
            <p> The authors should include additional comparisons with commonly used or closely related tools, such as PRO, FreeBarcodes, Edittag, BARCOSEL, and other maintained barcode design methods where possible. Even if all features do not match exactly, overlapping tasks should still be benchmarked, including runtime, memory use, achieved minimum distance, barcode length, target barcode number, GC constraints, and homopolymer filtering. Without broader benchmarking, the &#x201c;high-performance&#x201d; claim remains insufficiently supported.</p>
            <p> </p>
            <p> 4. The demultiplexing evaluation should better reflect the intended use cases.</p>
            <p> </p>
            <p> The demultiplexing benchmark mainly compares taggen-demux with minibar. This comparison is informative, but it does not fully establish the advantage of TagGen because the two tools are designed for different situations. Minibar uses adapter or primer anchoring, while TagGen is intended for anchor-free barcode detection. The authors should add benchmark scenarios that better match the intended applications of TagGen, such as internal barcodes, variable-position barcodes, missing or unreliable adapter sequences, direct RNA-like reads, and degraded reads. The manuscript should also compare TagGen with simple baseline methods, such as edit-distance matching or k-mer-based matching. This would help readers understand whether the proposed demultiplexer provides a real practical advantage beyond a straightforward implementation.</p>
            <p> </p>
            <p> Minor comments</p>
            <p> </p>
            <p> 1. Please define whether &#x201c;accuracy&#x201d; is calculated over all reads or only over assigned reads.</p>
            <p> 2. Please clarify whether excluded sequences are filtered by exact matching or by edit-distance similarity to adapters and primers.</p>
            <p> 3. Please use consistent terminology throughout the manuscript. &#x201c;Barcode,&#x201d; &#x201c;tag,&#x201d; &#x201c;DNA barcode,&#x201d; &#x201c;RNA tag,&#x201d; and &#x201c;sample barcode&#x201d; are used somewhat interchangeably.</p>
            <p>Are the conclusions about the tool and its performance adequately supported by the findings presented in the article?</p>
            <p>Partly</p>
            <p>Is the rationale for developing the new software tool clearly explained?</p>
            <p>Yes</p>
            <p>Is the description of the software tool technically sound?</p>
            <p>Partly</p>
            <p>Are sufficient details of the code, methods and analysis (if applicable) provided to allow replication of the software development and its use by others?</p>
            <p>Partly</p>
            <p>Is sufficient information provided to allow interpretation of the expected output datasets and any results generated using the tool?</p>
            <p>Partly</p>
            <p>Reviewer Expertise:</p>
            <p>long-read sequencing</p>
            <p>I confirm that I have read this submission and believe that I have an appropriate level of expertise to state that I do not consider it to be of an acceptable scientific standard, for reasons outlined above.</p>
        </body>
        <sub-article article-type="response" id="comment16444-486452">
            <front-stub>
                <contrib-group>
                    <contrib contrib-type="author">
                        <name>
                            <surname>Shirokikh</surname>
                            <given-names>Nikolay</given-names>
                        </name>
                        <aff>School of Human Sciences, The University of Western Australia, Perth, Western Australia, Australia</aff>
                    </contrib>
                </contrib-group>
                <author-notes>
                    <fn fn-type="conflict">
                        <p>
                            <bold>Competing interests: </bold>We do not have any competing interests to disclose.</p>
                    </fn>
                </author-notes>
                <pub-date pub-type="epub">
                    <day>16</day>
                    <month>6</month>
                    <year>2026</year>
                </pub-date>
            </front-stub>
            <body>
                <p>
                    <bold>Response to Reviewer 1 (Zhenxian Zheng) </bold>
                </p>
                <p> </p>
                <p> We thank Dr Zheng for a careful and constructive reading of our manuscript, and for recognising that TagGen may be useful for custom nanopore workflows where barcode position is variable or adapter anchors are unavailable, which is precisely the gap the tool is designed to fill. We have grouped our responses by the reviewer&#x2019;s own headings. We address each comment in turn, indicating where we have revised the manuscript and where we respectfully clarify points that we believe are already supported by the existing data.</p>
                <p> </p>
                <p> We note that several of the requested demultiplexing scenarios (internal / mid-read barcodes, variable-position barcodes, anchor-free assignment, spatial configurations) are in fact already presented in Figure 4C-E and the 154-condition systematic benchmark; we suspect these panels were overlooked, and we have revised the text and figure callouts to make them more prominent.</p>
                <p> </p>
                <p> 
                    <bold>Major comments</bold>
                </p>
                <p> </p>
                <p> 
                    <bold>1. &#x201c;The main contribution and claims should be stated more cautiously.&#x201d;</bold>
                </p>
                <p> </p>
                <p> 
                    <bold>We have moderated the genuinely over-broad language, while retaining terms that are both standard in the field and directly supported by our data.</bold> The reviewer is correct that the field already contains several barcode tools, and we have re-scoped the novelty claim to the specific, defensible contribution: 
                    <bold>flexible-length barcode generation (8-30 bp) combined with anchor-free demultiplexing for custom and non-standard nanopore library designs</bold>, rather than a universally superior tool. We have revised the abstract and conclusions accordingly.</p>
                <p> </p>
                <p> Specifically: 
                    <list list-type="bullet">
                        <list-item>
                            <p>We no longer claim that TagGen is the only tool capable of long-read barcode design. We acknowledge that other recent tools also operate in the 20-30 bp range, notably PRO (Yu et al., 2024) and the signal-space toolkit TDFPS-Designer (Han et al., 2024), and we have added both to the Introduction and to Table 1. The claim in Figure 1B (the only tool that works at 14-30 bp) has been corrected accordingly (see also Comment 3).</p>
                        </list-item>
                        <list-item>
                            <p>The uniquely enables language has been re-scoped from a general superiority claim to the specific, defensible 
                                <bold>combination</bold> that distinguishes TagGen from these tools: sub-second 
                                <italic>sequence-space</italic> barcode generation with a user-defined target count and flexible length (8-30 bp), coupled with an 
                                <italic>anchor-free</italic> demultiplexer and a graphical interface. PRO is fixed-length and adapter-anchored; TDFPS-Designer operates on raw signal, requires ONT-style flanking adapters for demultiplexing, and produces fixed kit sizes. No existing tool offers TagGen&#x2019;s particular combination, and we now state the contribution in exactly these terms rather than as a blanket claim of being unique or broadly enabling.</p>
                        </list-item>
                        <list-item>
                            <p>We respectfully 
                                <bold>retain </bold>high-performance (and high-throughput). These are established, descriptive terms in the long-read software literature, and in this manuscript high-performance is tied to a concrete, quantified result: sub-second 
                                <italic>sequence-space</italic> barcode generation at lengths (14-30 bp) where exhaustive enumeration fails outright (Table 3). We note that while indeed in the recent literature the descriptor &#x201c;high-performance&#x201d; is often used with little or insufficient supporting evidence, this is not the case with TagGen. We apply it here on the basis of a measured performance advantage on a defined task. Specifically, TagGen generates a 96-barcode set in tens of milliseconds: at 12 bp it is up to 13,600 times faster than DNABarcodes (34 ms vs 463 s), and at longer lengths DNABarcodes fails entirely through memory exhaustion (enumerating 268 million sequences at 14 bp exceeds available RAM) while TagGen still completes in under 50 ms. At a matched candidate-pool size, TagGen is ~87 times faster than PRO (~0.1 s vs ~9 s to reach 96 barcodes; Extended Data Figure 1), a gap that widens further at PRO&#x2019;s larger default pools. Its barcode quality is benchmarked directly against PRO and FreeBarcodes (GC content and achieved minimum distance; Extended Data Figure 6). TagGen additionally allows user-defined target counts at any length from 8 to 30 bp, GC-content, homopolymer and exclude-sequence constraints, and anchor-free demultiplexing, and it scales to large designs without choking (384 barcodes at 30 bp in ~1.4 s; candidate pools of up to 100,000 sequences), all of this while remaining a tool that can be easily integrated into massive HPC loads. It is written in a compiled language and has deep runtime optimisations during compilation. To us, these are the definitions of a high-performance tool, and if the reviewer will be able to identify a tool that outmatches TagGen on all of these features at the time of TagGen publishing, we will be happy to remove the claim. We have, however, added a clause to the Abstract clarifying that the term refers to sequence-space generation throughput, not to any claim of superior demultiplexing over anchor-based tools, and we explicitly do not assert a like-for-like speed advantage over signal-space methods such as TDFPS-Designer (see Comment 3).</p>
                        </list-item>
                        <list-item>
                            <p>We have moderated the broader qualitative claims (e.g. robust across long-read applications) to refer to 
                                <bold>demonstrated</bold> resilience under the specific simulated conditions tested, and throughout the Results and Discussion we now distinguish explicitly between 
                                <bold>demonstrated performance</bold> (simulation benchmarks reported here) and 
                                <bold>anticipated applications</bold> (direct RNA, spatial, clinical), flagging the latter as prospective use cases rather than validated results.</p>
                        </list-item>
                    </list> We believe these changes address the reviewer's central concern about tone while preserving the claims that are directly supported by the data.</p>
                <p> </p>
                <p> 
                    <bold>2. &#x201c;</bold>
                    <bold>Figure 1 is difficult to understand and should be redesigned.&#x201d;</bold>
                </p>
                <p> </p>
                <p> 
                    <bold>We respectfully clarify that Figure 1 already contains the panel structure the reviewer requests, and we have improved its legibility rather than restructuring it.</bold>
                </p>
                <p> </p>
                <p> The reviewer asks for separate panels for barcode generation, barcode quality evaluation, and demultiplexing, each with clear inputs, processing steps, outputs, and key parameters. Figure 1 is in fact organised in exactly this way: 
                    <list list-type="bullet">
                        <list-item>
                            <p>
                                <bold>Panel C (barcode generation)</bold> is a complete input&#x2192;step&#x2192;output flow: input parameters (length, target count, minimum distance, GC bounds, homopolymer limit, exclude set) &#x2192; Phase 1 Monte Carlo candidate generation &#x2192; candidate pool &#x2192; Phase 2 greedy diversity selection &#x2192; output (FASTA / TSV / distance matrix). The governing decision criterion, which is the maximisation of the minimum pairwise distance against the minimum-distance threshold, is shown explicitly.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>Panel D (demultiplexing)</bold> is the corresponding flow for read assignment: input (FASTQ reads, barcode FASTA, mode, position mask, distance metric) &#x2192; Stage 1 k-mer voting &#x2192; top candidates &#x2192; Stage 2 banded edit-distance alignment &#x2192; output (per-sample assignment), with the three acceptance criteria (distance threshold, margin &#x2265; 2, confidence) and the unassigned branch shown explicitly.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>Panel E (quality evaluation)</bold> presents the barcode-resolution validation as a function of length and error rate.</p>
                        </list-item>
                    </list> The remaining panels are deliberate context for a general readership rather than redundant detail: Panel A motivates the indel-dominated nanopore error profile that drives the need for longer barcodes; Panel B illustrates the exponential complexity wall that motivates the algorithmic approach; and Panel F summarises the end-to-end applications and the shared GUI/CLI engine.</p>
                <p> </p>
                <p> We respectfully disagree that Figure 1 should be simply a set of flowchart diagrams of the algorithm, that is too specialist and narrow and only serves those not very numerous people that are wishing to understand deeper how the tool is algorithmically laid out. As an F1000Research article is read by a broad audience, we consider this orienting overview, which is effectively a graphical abstract combined with the two core workflow panels, to be a feature of strength rather than a deficiency, and we are reluctant to remove the motivational and applications context, which will be of a high value to many F1000 readers and those interested in using the tool to its purpose, and which situates the method for non-specialist readers.</p>
                <p> </p>
                <p> We do accept the reviewer&#x2019;s underlying point that the panel is information-dense, and we have made two concrete changes. First, we have 
                    <bold>corrected panel B</bold> to remove the outdated only tool that works at 14-30 bp annotation, bringing the figure into line with the revised text that now acknowledges PRO and TDFPS-Designer (Comments 1 and 3). Second, to aid readers who wish to focus solely on the computational steps, we provide a 
                    <bold>slim standalone workflow schematic</bold> (Extended Data Figure 7) presenting barcode generation and demultiplexing in isolation, stripped of the motivational and applications context. We hope this combination, Figure 1 retained for orientation plus a minimal workflow figure for detail, satisfies the reviewer&#x2019;s concern while preserving the accessibility that the current figure provides to a general audience.</p>
                <p> </p>
                <p> 
                    <bold>3. </bold>&#x201c;
                    <bold>The speed and algorithmic benchmark is too narrow.&#x201d;</bold>
                </p>
                <p> </p>
                <p> 
                    <bold>We have broadened the generation benchmark and clarified the constraints on like-for-like comparison.</bold> We agree that a single comparator (DNABarcodes) is insufficient to support a general performance claim, and we have addressed this in two ways. 
                    <list list-type="order">
                        <list-item>
                            <p>
                                <bold>New comparisons against PRO and FreeBarcodes.</bold> Because PRO (Yu et al., 2024) is the most directly relevant comparator (nanopore-specific, with integrated demultiplexing) we have added it to the performance table (Table 3) and to a new supplementary figure benchmarking generation runtime against PRO (Extended Data Figure 1); barcode quality, namely GC content and achieved minimum distance, is additionally compared across TagGen, PRO and FreeBarcodes (Extended Data Figure 6). The comparison is reported at each tool's feasible operating point on the overlapping generation task. This directly benchmarks TagGen against maintained, nanopore- and indel-oriented design tools rather than against DNABarcodes alone.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>New positioning against TDFPS-Designer (Han et al., 2024).</bold> We thank the reviewer for prompting a broader survey; in revising we have added TDFPS-Designer, a recent nanopore barcode-design toolkit, to the Introduction and Table 1. We wish to be transparent about why we compare it on 
                                <italic>capability</italic> rather than head-to-head runtime. TDFPS-Designer operates in 
                                <bold>signal space</bold>: it selects barcodes using dynamic time warping (DTW) on raw nanopore current signals, and its integrated demultiplexer extracts the barcode signal using ONT-style flanking adapters. This is a fundamentally different and inherently more expensive computation than TagGen&#x2019;s sequence-space sampling, and the two operate on different inputs (raw squiggle vs basecalled FASTQ) and produce different outputs (fixed kit sizes of 137/410/1779 barcodes vs a user-defined target count). This had been the reason we initially omitted TDFPS-Designer from the paper, but now include it back since the reviewer mentioned it. A direct runtime comparison (TagGen&#x2019;s milliseconds vs the reported ~12 h for a 1779-barcode 30 bp set) would therefore be misleading (and would not put TDFPS-Designer in a good position), and we do not make one. Instead we present the two as complementary design points: TDFPS-Designer exploits raw-signal information and adapter anchoring where those are available; TagGen targets sequence-space speed, user-defined set sizes, flexible length, and anchor-free assignment where raw signal or consistent adapters are not available. This distinction is now stated explicitly in the Discussion.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>Clarified why certain tools cannot be benchmarked on overlapping tasks.</bold> We have expanded the Methods to state explicitly, for each tool, why a runtime comparison is or is not feasible:</p>
                        </list-item>
                    </list> 
                    <list list-type="bullet">
                        <list-item>
                            <p>
                                <bold>BARCOSEL</bold> selects subsets from an existing pool and performs no 
                                <italic>de novo</italic> generation, so there is no generation task to time.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>Edittag</bold> is distributed only for Python 2 and does not execute on current interpreters; we report this as an availability limitation rather than a performance result.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>FreeBarcodes</bold> generates indel-correcting codes but at fixed target lengths and on the order of hours; it is included in the supplementary quality comparison (GC content and achieved minimum distance; Extended Data Figure 6); a runtime figure is not reported for FreeBarcodes, whose enumeration did not complete within the benchmarking window.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>PRO</bold> operates at a fixed 24 bp and maximises set size rather than accepting a user-defined target count; we benchmark it at its native length as described in (a).</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>TDFPS-Designer</bold> operates in signal space (DTW); compared on capability rather than runtime, as described in (b).</p>
                        </list-item>
                    </list> We retain the DNABarcodes comparison as the canonical exhaustive-enumeration baseline, since it most clearly illustrates the exponential-scaling wall (memory exhaustion at &#x2265;14 bp) that motivates the Monte Carlo approach. We have, however, softened the generalised high-performance framing to refer specifically to sequence-space scaling with barcode length (see response to Comment 1).</p>
                <p> </p>
                <p> 
                    <bold>4. &#x201c;</bold>
                    <bold>The demultiplexing evaluation should better reflect the intended use cases.&#x201d;</bold>
                </p>
                <p> </p>
                <p> 
                    <bold>We respectfully clarify that the requested scenarios are already evaluated, and we have added a naive-baseline comparison as suggested.</bold>
                </p>
                <p> </p>
                <p> The reviewer asks for benchmark scenarios covering internal barcodes, variable-position barcodes, missing or unreliable adapter sequences, direct RNA-like reads, and degraded reads. These are in fact the core of our systematic benchmark, and we have revised the callouts to make this unmistakable: 
                    <list list-type="bullet">
                        <list-item>
                            <p>
                                <bold>Internal / mid-read barcodes (direct-RNA-like configuration):</bold> Figure 4D evaluates barcodes embedded mid-read, flanked by transcript sequence on both sides. End-mode correctly returns ~0% (confirming the safety restriction), while full-mode with a position mask reaches 98% accuracy at 95% identity.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>Variable-position / spatial barcodes:</bold> Figure 4C evaluates 5&#x2032;-anchored spatial configurations with absolute and fractional position masks.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>Missing / unreliable adapter sequences:</bold> the entire taggen-demux design is anchor-free, it uses no adapter information at any stage. This is contrasted directly against the anchor-dependent minibar in Figure 3, where we 
                                <italic>explicitly state</italic> that minibar is expected to win when the adapter is intact, and that this comparison demarcates the two tools&#x2019; intended operating regimes rather than identifying a weakness in TagGen.</p>
                        </list-item>
                        <list-item>
                            <p>
                                <bold>Degraded reads:</bold> all panels span read identities down to 80-85%, corresponding to R9.4.1 chemistry and degraded samples; Table 4 additionally tests barcode resolution up to 25% total error.</p>
                        </list-item>
                    </list> The minibar comparison was never intended as the central demultiplexing result; it is a single anchored-library control, and the anchor-free scenarios (Fig 4C-E) are the intended-use evaluations. We have rewritten the opening of the demultiplexing Results to lead with the anchor-free scenarios and to present the minibar comparison as a boundary-defining control.</p>
                <p> </p>
                <p> 
                    <bold>&#x201c;New naive-baseline comparison.&#x201d;</bold> We agree this is a valuable addition and have added it (Extended Data Figure 5). taggen-demux is compared against a simple baseline classifier to isolate the contribution of the two-stage k-mer-voting + banded-edit-distance pipeline relative to a straightforward implementation, and to test whether the ambiguity and confidence guards meaningfully reduce misassignment. This demonstrates that the proposed demultiplexer provides a practical advantage beyond a naive edit-distance/k-mer match.</p>
                <p> </p>
                <p> 
                    <bold>&#x201c;Validation by simulation.&#x201d;</bold> We acknowledge the reviewer&#x2019;s underlying concern that validation rests on simulated rather than experimental data. We note that simulation against a literature-calibrated ONT error model (
                    <bold>Badread</bold>; 50% deletion / 25% insertion / 25% substitution profile from published characterisations) is the standard validation approach for this class of tool, including for the most directly comparable nanopore barcode method (
                    <bold>PRO</bold>). It also allows ground-truth assignment that experimental data cannot provide. We have added an explicit statement to the Limitations section that wet-lab validation on real ONT libraries is the natural next step, and we have moderated the Results/Discussion accordingly so that all performance figures are clearly attributed to simulation.</p>
                <p> </p>
                <p> 
                    <bold>Minor comments </bold>
                </p>
                <p> </p>
                <p> 
                    <bold>1. &#x201c;Definition of </bold>accuracy
                    <bold> (all reads vs assigned reads).&#x201d;</bold> Accuracy is computed over 
                    <bold>all reads</bold>. For each condition we report three fractions that sum to one: correctly assigned (accuracy), assigned to an incorrect barcode (misassignment), and rejected (unassigned). Unassigned reads are therefore counted in the denominator and are not silently excluded. We have added this definition explicitly to the Methods (Benchmarking) and to the Figure 4 legend.</p>
                <p> </p>
                <p> 
                    <bold>2. &#x201c;Exclude-sequence filtering: exact vs edit-distance.&#x201d;</bold> Excluded sequences are filtered by 
                    <bold>edit-distance similarity</bold>, not exact matching: as described in the Methods, during greedy selection any candidate whose distance to an excluded sequence falls below the minimum-distance threshold is discarded, ensuring the final set is orthogonal to adapters/primers by the same metric used for inter-barcode separation. We have confirmed this is stated unambiguously in the Methods.</p>
                <p> </p>
                <p> 
                    <bold>3. &#x201c;Consistent terminology.&#x201d;</bold> We have standardised terminology throughout: all instances of tag in the running text have been replaced with barcode (retaining tag only where it is part of a tool or command name, e.g. taggen, taggen-demux), and the TagGen typography has been unified. DNA barcode and RNA tag are now harmonised to barcode except where the nucleic-acid type is material to the point being made.</p>
            </body>
        </sub-article>
    </sub-article>
</article>
