23  Metagenomics: Implementations

Implementationstooling reviewed 2026-09

Everything on this page is generated from tools/metagenomics.json. If something here is wrong or out of date, the fix belongs in that file, not in this prose.

For why a taxonomic label is a claim about a database rather than about a sample, and why an abundance needs its denominator stated, see Section 22.1.

The page follows the two routes of Section 22.2. The first section is the reference-based route, which answers who is here without reconstructing anything. The remaining four are the genome-resolved route, in the order it is run: assemble, bin, judge the bins, then ask what the genes do.

23.1 Who is in the sample

The four cards below are not four implementations of one method. They are three different answers to “what does a number in this table count”, and Section 22.4 is the reason that distinction is the first one to make.

Two of them are one method in two commands: Kraken 2 classifies reads against whole genomes, and Bracken turns those assignments into species abundances. Running the classifier without the estimator is the commonest way to produce a species table that is wrong in a direction nobody checks, which is why both carry a card. MetaPhlAn maps to clade-specific marker genes instead, so its denominator is closer to cells than to reads. sylph reports a sequence identity alongside every detection — the only one here that tells you how far your organism sits from the reference it matched.

Run more than one. Where they agree, the answer is about the sample; where they disagree, the disagreement is usually about the databases, and that is worth knowing before it becomes a result.

BrackenrecommendedC++py

Completes Kraken 2 rather than competing with it. A large share of reads stop at genus or family because their k-mers are shared, and those reads are simply missing from the species rows of a Kraken report; Bracken redistributes them using how the database’s own genomes classify at that read length. Without this step the species-level numbers are a biased lower bound, and the bias is a property of which relatives happen to be in the database. (Lu et al. 2017)

The redistribution is only as good as the database it was built against, and its k-mer distribution file must be rebuilt whenever the database or the read length changes. It cannot recover reads from an organism the database does not contain.
activelast release 2025-02last commit 2026-03GPL-3.0v3.1reviewed 2026-09
Kraken 2recommendedC++pypl

Exact k-mer matching against an index that labels each k-mer with the lowest common ancestor of every genome carrying it, which is why a read from a conserved region is reported at a rank the evidence supports rather than forced to a species. It is fast enough that classifying every sample is not a decision you have to plan around, and its report format is what almost everything downstream expects. (Wood et al. 2019)

It classifies reads, and a read count is not an abundance: it is proportional to the DNA an organism contributed, so a large genome outweighs an equally numerous small one. Pair it with Bracken rather than reading species percentages off the report. The confidence threshold also defaults to 0, which maximizes sensitivity and is the wrong default for a low-biomass sample.
activelast release 2025-11last commit 2026-08MITv2.17.1reviewed 2026-09
MetaPhlAnrecommendedpy

Maps to clade-specific marker genes rather than to whole genomes, which changes what the output is: because every clade contributes a comparable amount of marker sequence, the estimate approximates the fraction of cells rather than the fraction of reads, and is not distorted by genome size the way a whole-genome method is. Its marker database is also small enough to run anywhere, against the roughly 100 GB the standard prebuilt index of a whole-genome classifier occupies. (Blanco-Míguez et al. 2023; Segata et al. 2012)

Sees only what its markers cover, so an organism outside the database is not merely unclassified — it is invisible, and the reported fractions still sum to one across everything else. Its species-level answers for well-studied environments are strong and its behavior on novel environments is a different question.
activelast release 2026-07last commit 2026-08MITv4.2.6reviewed 2026-09
sylphrecommendedrs

Reports an average nucleotide identity for every genome it detects, which is the number that answers the question a taxonomic label cannot: whether the reference it matched is your organism or a relative of it. A classifier that says "Escherichia coli" and a profiler that says "96% ANI to this E. coli genome" are making very different claims, and only the second one degrades gracefully when your sample is not well represented in the database. (Shaw and Yu 2025)

Its README puts accurate ANI estimation down to 0.1x coverage, which is low but not zero — an organism below that is not reported with a wide interval, it is simply absent. Sketching also discards the reads, so there is nothing to go back to when a hit needs interrogating.
activelast release 2025-10last commit 2026-02MITv0.9.0reviewed 2026-09
Tool Upstream Languages Why / why not
Kaiju activelast release 2026-06last commit 2026-06 CC++

Translates reads and searches protein space, so it keeps finding organisms after nucleotide identity has decayed past the point where exact k-mer matching sees anything. That is the specific case a nucleotide classifier fails silently on — a divergent virus, or a lineage whose nearest sequenced relative is far away — and it is worth running alongside rather than instead of one. (Menzel et al. 2016)

mOTUs activelast release 2026-07last commit 2026-07 py

Profiles against universal single-copy marker genes, which lets it quantify lineages that have no sequenced genome at all: an uncharacterized cluster gets an identifier and an abundance rather than being dropped. For an environment where most of what is present has never been isolated, that is the difference between a profile and a profile of the parts you already knew about. (Ruscheweyh et al. 2022; Sunagawa et al. 2013)

Centrifuge maintainedlast release 2024-07last commit 2026-04 C++

Built an FM-index over a compressed reference set at a time when a Kraken-style index would not fit in a reasonable machine, and that was a real advantage. Kraken 2’s minimizer index removed most of the gap, so the reason to choose it has largely gone while the pipelines that adopted it have not. (Kim et al. 2016)

WarningThe default confidence threshold is a sensitivity setting

An exact k-mer classifier will assign a read on very little evidence, and published comparisons of these tools find that the false-positive behavior at permissive settings is substantial and varies enormously between tools and databases (Ye et al. 2019). The species list from a default run is therefore a list of things that had some support, not a list of things that were present, and the tail of it is mostly noise.

Two habits fix most of this: raise the confidence threshold and say what you raised it to, and apply a minimum-reads floor before anything downstream reads the table. Neither is a substitute for the negative control of Section 22.7, which is what tells you whether the low-abundance tail is noise or is real and came from a reagent.

23.2 Assembling a community

A metagenome assembler solves a harder version of the problem in Section 8.1, and the difference is coverage. A single-genome assembler can treat depth as roughly uniform and use a departure from it as evidence of a repeat; here depth varies by orders of magnitude between organisms and carries no such meaning, so every assumption built on even coverage has to be replaced.

The choice is made by read type before anything else. MEGAHIT is the short-read answer, alongside SPAdes’ metagenomic mode in the table below. metaMDBG and Flye take long reads — the route that made complete circular genomes from a community ordinary rather than remarkable — and they differ in what they assume about read accuracy, which is the axis Section 9.1 sets out.

FlyerecommendedC++py

Built for reads whose errors it cannot assume away, which makes it the answer for nanopore data and for anything where read accuracy is unknown. Its repeat graph represents repeats explicitly rather than trying to traverse through them, so what could not be resolved is visible in the output rather than guessed at. (Kolmogorov et al. 2019)

Produces a collapsed assembly rather than separated haplotypes. For a diploid genome that is a deliberate simplification, not an oversight — and it is the same collapse across closely related strains in a metagenome. Either way it is one you inherit.
dormantlast release 2025-05last commit 2025-05BSD-3-Clausev2.9.6reviewed 2026-08
MEGAHITrecommendedC++C

A succinct de Bruijn graph holds the whole multi-k graph in a fraction of the memory an ordinary one needs, which is what makes assembling a deeply sequenced or co-assembled short-read metagenome possible on a single node at all. Memory, not accuracy, is the constraint that decides most metagenome assemblies, and this is the tool that moves it. (Li et al. 2015)

Produces contigs and does not scaffold, which is the right choice here — scaffolding across a mixed community risks joining sequence from different organisms. Its memory advantage comes from the graph representation, so a run that is still too large is controlled with the k-mer range and the minimum count rather than with threads.
maintainedlast release 2019-10last commit 2025-10GPL-3.0v1.2.9reviewed 2026-09
metaMDBGrecommendedCC++

Assembles in minimizer space rather than base space, which collapses the graph enough that a long-read metagenome assembly stops being a large-memory job. Accurate long reads are what finally made complete circular genomes from a community routine, and the constraint on doing it at scale was the assembler’s footprint rather than the data. (Benoit et al. 2024)

Built for accurate long reads. Noisier nanopore data is supported but is not the case it was designed around, and the quality gap between the two inputs is a property of the reads rather than of the assembler.
activelast release 2026-05last commit 2026-05MITv1.4reviewed 2026-09
Tool Upstream Languages Why / why not
SPAdes activelast release 2026-06last commit 2026-06 C++

The short-read assembler that is still the right answer when short reads are what you have: bacterial isolates, single-cell amplified genomes, viral samples, metagenomes. Its multi-k de Bruijn approach handles the uneven coverage those give you, which is the case general assemblers handle worst. (Bankevich et al. 2012)

NotemetaSPAdes and metaFlye are modes, not tools

Both appear here as their parent projects, because that is what they are: one repository, one release, one version number, and a flag that selects the metagenomic algorithm. The registry gives each project one record, so --meta and metaspades.py are documented on the cards above rather than duplicated as separate entries. Cite the assembler you ran and say which mode.

This is the same rule that keeps MACS2 and MACS3 to one entry, applied to the first case in the book where a part is built partly out of records another part already owns.

WarningCo-assembly is a decision, not a default

Assembling many samples together gives low-abundance organisms enough combined depth to assemble, and it also merges strain variation from every sample into one graph, which fragments exactly the genomes that differ between samples — often the ones the study is about. Assembling per sample does the opposite. Neither is correct in general. What is not defensible is choosing by whichever the pipeline did by default and reporting the contig count as though it were a property of the community.

23.3 Grouping contigs into genomes

Binning is where a pile of contigs becomes a set of proposed genomes, and Section 22.5 is the argument that a bin is a hypothesis rather than an observation. Every tool here works from the same two signals — sequence composition and per-sample coverage — and they differ in what they do with them.

The older generation clusters those features directly. The newer generation learns a representation first and clusters in that, and the published comparisons are consistent about the direction of the difference (Kim et al. 2026; Yazhini et al. 2025). SemiBin2 is the card for that generation, and the table holds both the other learned binners and the ones they beat.

DAS Tool, the other card, is not a binner at all. It takes several binners’ output and selects among them, which is the cheapest quality improvement available at this stage and the reason to run more than one of the tools in the table rather than choosing between them.

DAS ToolrecommendedRrbsh

Different binners disagree about different contigs, and that disagreement is information rather than noise. It scores candidate bins from several binners by single-copy marker content and selects a non-redundant set, which recovers genomes no single binner produced. Running two or three binners and combining them is the cheapest quality improvement available at this stage. (Sieber et al. 2018)

It selects among the bins it is given and cannot invent a better one, so the result is bounded by the binners underneath. It is a scoring step over other tools' output rather than a method tracking a moving field, which is why a quiet upstream weighs less here than it would for a binner.
dormantlast release 2024-01last commit 2024-01BSD-3-Clause-LBNLv1.1.7reviewed 2026-09
SemiBin2recommendedpy

Learns the embedding it clusters in rather than clustering composition and coverage directly, and the published comparisons that rank binners put it and the other learned-representation methods consistently ahead of the composition-and-coverage generation (Kim et al. 2026; Yazhini et al. 2025). Its second version made that training self-supervised, so it no longer needs reference-derived labels to learn from, and built-in environment models are selectable with --environment where one fits your sample. (Pan et al. 2023, 2022)

The multi-sample modes are where most of the gain is, and they need the samples to be assembled and mapped in a compatible way. Running it single-sample on one library gives up much of what it is for.
activelast release 2026-08last commit 2026-08MITv2.4.1reviewed 2026-09
Tool Upstream Languages Why / why not
COMEBin activelast release 2026-08last commit 2026-08 py

Learns a representation by contrastive training over augmented views of each contig, and lands with SemiBin2 at the top of the recent binning comparisons (Kim et al. 2026; Yazhini et al. 2025). Its distinctive strength is short contigs, which is where a composition signal is weakest and where most of the recoverable genome fragments sit. (Wang et al. 2024)

MetaBAT 2 activelast release 2025-01last commit 2026-08 C++

The parameter-free default that most pipelines still run, and by a wide margin the fastest of the serious binners, which is why it remains the sensible first pass and the sensible input to an ensemble. Recent comparisons put it behind the learned-representation binners on genome recovery (Kim et al. 2026), so choose it for throughput or for ensemble diversity rather than because it will find the most genomes. (Kang et al. 2019, 2015)

VAMB activelast release 2025-04last commit 2026-04 py

The variational autoencoder that established learned embeddings for this problem, and it is built around binning many samples at once rather than treating multi-sample as an extension. When a study has tens or hundreds of libraries from one environment, that framing recovers genomes that per-sample binning splits across samples and loses. (Nissen et al. 2021)

CONCOCT dormantlast release 2019-08last commit 2019-11 pyC

One of the originals, and the paper that made composition-plus-coverage clustering the standard shape of this problem. You will meet it inside older pipeline wrappers, where it is usually one member of an ensemble. Recent comparisons place it in the group that the learned-representation binners consistently beat (Kim et al. 2026), and it has not been developed for years. (Alneberg et al. 2014)

NoteThe mapping matters more than the binner

Coverage is half the signal every one of these tools uses, and coverage comes from mapping reads back to the assembly — with the multi-mapping problem of Section 16.3 at its worst, because a conserved gene is now shared between organisms rather than between paralogs. How that mapping was run, and what it did with reads that fit several contigs equally well, changes the coverage profile that binning then clusters on.

A poor bin set is more often a mapping problem than a binning problem, and it is worth checking the coverage table before changing binners.

23.4 Judging the bins

A binner will emit bins for anything. The question this section answers is which of them are genomes, and it is the point at which a metagenome-assembled genome either acquires the standing to be reported or does not (Bowers et al. 2017).

Three separate questions, three cards. Is this bin a whole genome and only one genome — completeness and contamination, which CheckM2 estimates. Is this the same genome as that one — the dereplication dRep performs, which decides whether a catalogue built across many samples counts an organism once or eleven times. And what is it — placement in a phylogeny by GTDB-Tk, which for a novel organism is a genuinely different claim from a best-hit name.

CheckM2recommendedpy

Predicts completeness and contamination from a model trained across genomes rather than by counting marker genes within a lineage, which removes the failure that mattered most: a genome from a lineage with few relatives had few reliable markers, so exactly the novel organisms a metagenome is run to find were the ones scored worst. It is also fast enough to score every bin from every sample without planning for it. (Chklovski et al. 2023)

A machine-learning estimate rather than a count, so it can be confidently wrong on genomes unlike anything in its training set — the same class of organism its predecessor mishandled, for a different reason. Report which tool produced a completeness figure, because the two do not produce the same number.
dormantlast release 2025-02last commit 2025-03GPL-3.0v1.1.0reviewed 2026-09
dReprecommendedpy

Binning many samples separately recovers the same organism many times, and a MAG catalogue that has not been dereplicated will report the same genome as several and inflate every count derived from it. This clusters by average nucleotide identity and picks a representative per cluster on a quality score, which is the step that turns a pile of bins into a set of genomes. (Olm et al. 2017)

The identity threshold is a definition, not a discovery: 95% is the conventional species boundary and choosing it decides whether strains are separate genomes or one. Say which threshold you used, because the catalogue size depends on it more than on the binning did.
activelast release 2026-06last commit 2026-07MITv3.7.1reviewed 2026-09
GTDB-Tkrecommendedpy

Places a genome in a phylogeny built from concatenated marker proteins and assigns it a rank-normalized name, which is a different and stronger claim than a best-hit label: an organism with no close relative gets placed at the rank the tree supports instead of being handed the name of the nearest thing in the database. For a MAG, which is usually novel to some degree, that distinction is the whole point. (Chaumeil et al. 2022; Parks et al. 2022)

Its taxonomy is GTDB's, which deliberately disagrees with NCBI where the genome evidence disagrees with the historical name. Reporting a GTDB name as though it were an NCBI one, or comparing across the two without saying which, produces confusion that is difficult to unpick later.
activelast release 2026-05last commit 2026-05GPL-3.0v2.7.2reviewed 2026-09
Tool Upstream Languages Why / why not
CheckM activelast release 2026-03last commit 2026-03 py

Defined what a completeness and contamination estimate is for this field, and most published MAG quality numbers are its numbers, so it is worth knowing what they mean. Its lineage-specific marker sets are also its limitation — a genome with no well-sampled lineage gets a marker set that does not fit it, which is the case CheckM2 was built for. (Parks et al. 2015)

WarningReport the tool with the number

“95% complete, 2% contaminated” is not a portable statement. The two estimators above disagree, sometimes substantially and most often on exactly the novel lineages a metagenome study cares about, because one counts lineage-specific markers and the other predicts from a trained model. A quality threshold applied to a catalogue built with one tool is not the same threshold applied to a catalogue built with the other.

The MIMAG standard defines the quality tiers most papers report against; it does not fix which estimator produced the inputs, so the tool and its version belong in the methods next to the cutoff.

23.5 What the community is doing

Section 22.8 is the caution this section is run under: a gene found in a metagenome is a gene that was present in some cell’s DNA, and nothing here observes it being used.

Two routes again, and the split is the one from the top of the page. HUMAnN works from reads against a reference and needs no assembly, which makes it the practical choice for a study with many samples and no interest in reconstructing genomes. Bakta and eggNOG-mapper work from predicted proteins on assembled sequence — one annotating a bacterial genome or MAG end to end, the other handling an arbitrary protein set from anywhere. The table holds the gene caller all of this sits on and the annotator Bakta replaced.

Baktarecommendedpy

Annotates a bacterial genome or MAG end to end and gives as many genes as it can a stable, database-backed identifier rather than a free-text product description. That is the difference between an annotation you can join across studies and one you can only read: two labs annotating the same genome get the same identifiers, which no description-matching workflow will give you. (Schwengers et al. 2021)

Built for bacteria, archaea and plasmids. Pointing it at a eukaryotic bin, which a metagenome will occasionally produce, gives output that looks well-formed and means very little.
activelast release 2026-08last commit 2026-08GPL-3.0v1.12.1reviewed 2026-09
eggNOG-mapperrecommendedpy

Transfers annotation from precomputed fine-grained orthologs rather than from the best hit, which is the distinction that matters: a best hit can be a paralog with a different function, and orthology restricts the transfer to the relationship where function is most likely conserved. It is the general-purpose answer for a set of predicted proteins from anywhere, which is what a metagenome assembly produces. (Cantalapiedra et al. 2021)

The annotation is only as current as the eggNOG release it runs against, and the database version belongs in the methods alongside the tool version. Its current documented line targets a database release that its predecessor's data cannot be used with, so the two are pinned together rather than independently.
activelast release 2026-08last commit 2026-08AGPL-3.0v3.0.0-beta6reviewed 2026-09
HUMAnNrecommendedpy

Answers the functional question from reads without an assembly, and does it in a way that keeps the answer attributable: gene families and pathway abundances are reported both in total and stratified by the species contributing them. A community-level pathway table with no idea which organism carries the pathway is a much weaker result, and stratification is what separates a description from a hypothesis. (Beghini et al. 2021; Abubucker et al. 2012)

Runs on top of a taxonomic profile and searches pangenomes for the species found there, so anything the profiler missed is functionally invisible too. Its version 4 line is in testing on the default branch rather than released; the released 3.x line is what pipelines should pin.
maintainedlast release 2024-02last commit 2026-07MITv3.9reviewed 2026-09
Tool Upstream Languages Why / why not
Pyrodigal activelast release 2026-03last commit 2026-03 pyC

Wraps Prodigal’s own C rather than reimplementing it, so gene calls are the reference implementation’s calls, obtained from a maintained package with a Python API and vectorized inner loops. When the choice is between a binding to the reference and a rewrite that may drift from it, the binding is the safer object to depend on — and here it is also the one still being released. (Larralde 2022)

Prodigal dormantlast release 2016-02last commit 2023-01 C

The prokaryotic gene caller nearly everything in this part depends on, directly or through a wrapper, and its metagenomic mode is what makes gene prediction on mixed contigs possible without training data. It is recorded as legacy because the code has stopped moving, not because the method has: for new work the binding above gives the same calls from a maintained package. (Hyatt et al. 2010)

Prokka activelast release 2025-12last commit 2026-01 pl

The tool that made whole-genome bacterial annotation a single command, and an enormous amount of published annotation is its output. Its results are free-text product descriptions from a hierarchy of databases rather than stable identifiers, which is workable for reading and painful for any analysis that has to join annotations across genomes. (Seemann 2014)

NoteThe database version is part of the result

Every entry in this section is a lookup against a reference that is versioned separately from the software and released on its own schedule. Two runs of the same tool version against different database releases will produce different annotations, and the difference will look like biology in any comparison that does not control for it.

Record the database release beside the tool version, and re-annotate rather than merge when a project spans an upgrade. This is the same discipline the variant annotation part asks for in Section 14.1, for the same reason.

23.6 What is not here

MaxBin2 is the conspicuous absence among the binners, and it is absent for the reason ANNOVAR is absent from the variant annotation part rather than for any judgment about the software. It is distributed from SourceForge, has no public git repository, and publishes versions as file uploads. Every field a record would need is therefore unobtainable, and both honest options are false: latest_version: null renders as “unrefreshed”, which claims nobody looked, and a hand-typed version is exactly the practice the refresh pass exists to prevent. So the position goes here. It belongs to the same generation as the legacy entry in the table above and the recent comparisons place it in the same group (Kim et al. 2026); if a pipeline already runs it as one member of an ensemble that is fine, and it is not a reason to add it to a new one.

16S and other amplicon surveys are excluded because they are a different measurement, not a cheaper version of this one. An amplicon study PCR-amplifies one marker gene and sequences that; a metagenome sequences whatever DNA was in the tube. The consequences run all the way down — primer choice and PCR bias replace database coverage as the dominant systematic error, copy-number variation in the marker replaces genome size as the abundance distortion, and there is no assembly, no binning and no functional layer at all. Almost nothing on this page applies. The book’s view, for the reader who has such data: use a method that resolves exact sequence variants rather than clustering reads into operational units at an arbitrary identity, because the units are then comparable between studies instead of being an artifact of one run’s clustering. That is a subject with its own tools and its own review cycle, and giving it three rows here would misrepresent how much of it this page had checked.

Strain-resolved metagenomics — separating populations of the same species within a sample, and tracking them between samples — is left to Section 22.6 in the concepts chapter rather than surveyed. It is the frontier of this field rather than its settled core, the tools disagree about what a strain is, and a “start here” verdict would overstate how much agreement exists.

Viral and eukaryotic metagenomics. Every reference database on this page is overwhelmingly bacterial and archaeal, and the tools inherit that. Viruses have no universal marker gene and no single-copy core, so completeness and contamination as defined above do not apply to them; microbial eukaryotes have genomes large and repetitive enough that assembly from a community is a different problem. Both are subjects, not sections.

Antimicrobial resistance and other gene-family screens. The substance of such an analysis is which curated gene catalogue you searched, and those are versioned databases on their own release cycles. This is the same shape as the annotation databases in the variant part: ranking the search programs would put a review date on the wrong object.

Host read removal and quality control belong to Section 5.1 and are not repeated here. The metagenomic specifics are that the host is a much larger fraction of the library than anywhere else in this book, and that removing host reads by mapping to a host reference will also remove real microbial reads from conserved regions. Both are properties of the experiment rather than of a tool.

The reference databases themselves — the Kraken and Bracken indexes, GTDB, UniRef, eggNOG — are the largest single determinant of every result on this page, and none of them is a record. They are versioned datasets, not software, and the honest treatment is the one the callouts above ask for: name the release you used. A survey that ranked them would be dating an object that changes on a schedule this book does not follow.

Pipeline wrappers. MetaWRAP, ATLAS, nf-core/mag and the rest compose the tools above into a runnable workflow. They are workflows, and the engines that run them are surveyed in Section 25.1. Reading one is an efficient way to see how these tools are wired together correctly; adopting one is a decision about the pipeline rather than about the methods.

23.7 Language coverage: the most Python-dependent part of the book

Sixteen of the twenty-five entries here are Python, which makes this the most Python-dependent part of the book by a wide margin. The interesting thing is not the count but where the boundary falls: not between subfields, but between stages.

Work whose cost scales with the number of reads is compiled. Both metagenome assemblers are C and C++, the exact k-mer classifiers are C++, and the newest profiler is Rust. The two Python entries in that first section are the exception that confirms the rule — they are Python orchestration around a compiled aligner, which is doing the read-scale work on their behalf.

Downstream of the assembly, where the objects are contigs and bins rather than reads, Python takes over almost completely: every quality and taxonomy tool, four of the six binners, and every functional annotator that has been written this decade. The exceptions are one binner that clusters in C++ and the two older annotators, in C and Perl, which predate that consolidation.

This is the exact mirror of the epigenomics part, where seven of sixteen entries are R packages and there is no Python route through the modelling sections. Here there is a single R entry, and it is a scoring script over other tools’ output rather than a statistical method. The reason is structural: this field’s decisions are made about genomes rather than about count matrices, so it never arrives at the place where Bioconductor becomes unavoidable.

The other thing worth noticing is where Rust has and has not arrived. It is present at the top of the page, in the newest profiler, and nowhere else. That is the same pattern the alignment part reports: a new language enters this field at the layer where throughput dominates, and it enters by a new tool arriving rather than by an established one migrating.

NoteWhat this means in practice

A metagenomics pipeline is a sequence of command-line tools with Python available at every point where you would want to intervene, and it crosses no language boundary that has to be planned for. That is unusually comfortable, and it has a cost worth naming: because everything is scriptable, it is easy to build a pipeline that runs end to end without ever stopping to check a negative control, a coverage profile or a bin’s quality. The friction that other parts of this book complain about is also a place where somebody looks at the data.