Output files¶
Everything a run writes goes under directories.output_dir. BacFlux resolves that
to an absolute path before any job starts, so a relative value in the config still
lands where you expect, and the workflow never changes its working directory.
Inside it the directories are numbered in the order the stages run, so a plain ls
reads like the workflow itself. The numbering is identical in all four modes.
Everything technology-specific is grouped under 01.reads and 02.assembly, and
every shared stage below that gets the same number whichever front end produced the
genome. A stage a mode cannot produce is simply absent — it is never renumbered.
The stage numbers changed in 2.0.0
They differed per workflow before the four front ends were merged. The old-to-new map is on Coming from v1; this page describes only what a 2.0.0 run writes.
Terms used on this page
| QC | quality control — the read, assembly and completeness checks |
| AMR | antimicrobial resistance |
| GTDB | Genome Taxonomy Database, the reference GTDB-Tk places each genome in |
| ANI | average nucleotide identity, a genome-to-genome similarity measure |
| EFSA | European Food Safety Authority, whose reporting thresholds the ABRicate leg applies |
| ICE | integrative and conjugative element — sits in the chromosome and can move itself to another cell |
| IME | integrative mobilisable element — the same, but needs a helper element to move |
| COG, GO, KEGG, EC | the ortholog, gene-ontology, pathway and enzyme classifications eggNOG assigns to a protein |
The files to read first¶
A full run leaves several thousand files. These are the ones that carry the result.
| File | Answers | Modes |
|---|---|---|
02.assembly/{sample}/contigs_final.fasta |
The delivered genome. Every later stage works from this one file. | all |
02.assembly/{sample}/contaminants/contig_taxonomy_decisions.tsv |
Which contigs were kept, which were dropped, and the reason for each. | all |
02.assembly/{sample}/eval/checkm/{sample}_checkm_stats.tsv |
Completeness and contamination of that genome. | all |
03.taxonomy/{sample}/classify/gtdbtk.*.summary.tsv |
What the isolate is. | all |
04.annotation/bakta/{sample}/{sample}.tsv |
The gene calls, with products. | all |
05.amr/abricate/{sample}/AMR_summary.txt |
AMR and virulence hits on the assembly, across eight databases. | all |
05.amr/mapping/{sample}/{sample}_CARD_report.tsv |
AMR determinants found in the reads, classified by what kind of CARD entry each is. | [illumina, hybrid] |
06.plasmids/{sample}/platon/verified_plasmids.txt |
Which contigs are plasmids. | all |
07.phages/checkv/{sample}/quality_summary.tsv |
Predicted prophages and how complete each one is. | all |
08.mobilome/{sample}/{sample}_amr_mobility.tsv |
For each AMR gene: the mobile-element context and a mobility tier. | all, opt-in |
09.report/multiqc_report.html |
Read QC, assembly QC, completeness and taxonomy for the whole batch on one page. | all |
One output directory, one batch
A sample name is the only thing separating two runs that share an output_dir:
reuse a name and the second run overwrites the first sample's results throughout.
09.report/multiqc_report.html is overwritten unconditionally — the rule passes
MultiQC --force, because without it MultiQC writes multiqc_report_1.html
instead and the rule then fails on a missing output.
The downloaded databases under 04, 07 and 08 are not per sample and are
reused, so one output directory per project is cheaper than one per run.
Layout¶
Bracketed tags follow config/config.yaml: [illumina, hybrid] means only those
modes write the line. Untagged lines are written in all four.
output_dir/
|-- 01.reads/ [illumina, nanopore, hybrid]
| `-- {sample}/
| |-- illumina/ [illumina, hybrid]
| `-- ont/ [nanopore, hybrid]
|-- 02.assembly/
| `-- {sample}/
| |-- contigs_final.fasta <- the delivered genome
| |-- contigs_filt.fasta [illumina, hybrid, contigs]
| |-- spades/ [illumina, hybrid]
| |-- flye/ fix_start/ medaka/ [nanopore, hybrid]
| |-- polypolish/ snps/ [hybrid]
| |-- {sample}_replicons.tsv + _audit [nanopore, hybrid]
| |-- {sample}_medaka_model.txt [nanopore, hybrid]
| |-- contaminants/ BLAST + BlobTools + the audit
| `-- eval/ QUAST, CheckM, Qualimap
|-- 03.taxonomy/{sample}/ GTDB-Tk
|-- 04.annotation/
| |-- bakta/{sample}/ eggnog/{sample}/
| |-- antismash/{sample}/ + antismash/databases/
| `-- dbcan/{sample}/ + dbcan/<db version>/
|-- 05.amr/
| |-- abricate/{sample}/ eight databases + a summary
| `-- mapping/{sample}/ [illumina, hybrid]
|-- 06.plasmids/{sample}/platon/
|-- 07.phages/
| |-- virsorter/{sample}/ + vs2_db/ unless phage.caller: genomad
| |-- genomad/{sample}/ + genomad_db/ only when phage.caller: genomad
| `-- checkv/{sample}/ + checkv_db/
|-- 08.mobilome/ only when mobilome.run: true
|-- 09.report/ multiqc_report.html
`-- logs/ one file per rule per sample
01.reads — read QC and filtering¶
Absent entirely in contigs mode, which has no reads to QC.
| Path | Written by | Contents |
|---|---|---|
{sample}/illumina/{sample}_fastp.html |
trim_adapters |
fastp's adapter- and quality-trimming report, for a human. |
{sample}/illumina/{sample}_fastp.json |
trim_adapters |
The same numbers for MultiQC. |
{sample}/illumina/{sample}_sel_R{1,2}.fastq |
map_sel_contigs |
[hybrid] The Illumina pairs that mapped as proper pairs to the decontaminated Illumina assembly. Two rules read them: Filtlong scores the Oxford Nanopore reads against these pairs, so a contig dropped by the contamination screen takes its long reads with it; Polypolish then uses them to correct the final genome. Kept, not temporary — deleting them would force the whole short-read half to re-run. |
{sample}/ont/{sample}_filt.fastq |
filter_long_reads |
The Oxford Nanopore reads Filtlong kept — what Flye assembled and what Medaka polished with. |
{sample}/ont/raw_qc/, {sample}/ont/filt_qc/ |
raw_long_read_qc, filtered_long_read_qc |
NanoPlot read-length and quality profiles, before and after filtering. Read side by side: the difference is what the filter did. |
The trimmed Illumina pairs ({sample}_trim_R{1,2}.fastq) and the PhiX reference and
its index under 01.reads/phix/ are all temporary and are gone when the run finishes.
See Illumina mode and Nanopore mode.
02.assembly — the genome and everything used to judge it¶
The delivered genome¶
02.assembly/{sample}/contigs_final.fasta is the one hand-off between the front end
and everything after it. Every rule in stages 03 to 08 works from this file or
from something built out of it, so nothing downstream has to know which assembler
ran. The one deliberate exception is hybrid, where QUAST, CheckM and GTDB-Tk are
also handed the Illumina assembly as a comparator — see eval/ below.
What it is differs by mode:
| Mode | contigs_final.fasta is |
Also kept |
|---|---|---|
illumina |
the decontaminated SPAdes assembly — decontamination is the last assembly step | contigs_filt.fasta, the pre-decontamination draft |
contigs |
the decontaminated input assembly | contigs_filt.fasta |
nanopore |
the Medaka consensus of the decontaminated, reoriented Flye assembly | contaminants/assembly_decontam.fasta |
hybrid |
the Oxford Nanopore assembly after Medaka and Polypolish | contaminants/contigs_sel.fasta, the decontaminated Illumina assembly, kept as the QC comparator and as Snippy's reference |
Set parameters.{nanopore,hybrid}.medaka_model: false and the consensus step drops
out of the last two rows: nanopore then delivers the decontaminated reoriented
assembly as it stands, hybrid delivers that assembly after Polypolish alone.
In contigs mode, what contigs_filt.fasta holds depends on the headers you fed in.
The length and coverage filter reads both numbers out of the header itself, so it can
only run on SPAdes-style headers: those keep their names and lose any contig under
500 bp or 2× coverage. Any other header style has no numbers to read, so nothing is
filtered and the headers are trimmed to their first token instead. Which branch ran
is the first line of logs/filter_contigs_{sample}.log.
In hybrid the contamination screen runs on the Illumina draft while the delivered
genome comes from the Oxford Nanopore leg, so those two FASTAs have entirely different
contig names. That is not a bug and it is why the plasmid step gets its own BLAST
table (below).
contaminants/¶
The contamination screen and its audit trail, all under
02.assembly/{sample}/contaminants/.
| File | Contents |
|---|---|
{sample}_blastout |
The megablast table over the draft assembly: 15 tab-separated columns with the subject title last. |
{sample}_final_blastout |
[nanopore, hybrid] A second megablast, over contigs_final.fasta. It exists because the plasmid step looks contigs up by ID, and in the long-read modes the screened contigs and the delivered contigs do not share names. |
bestscore.blob.blobDB.table.txt |
The BlobTools per-contig table — taxonomy and coverage. The evidence behind every keep/drop decision, so it is kept. |
contig_taxonomy_decisions.tsv |
The audit file. Every contig, its assigned genus, and the reason it was kept or dropped. |
contigs.list |
The kept contig IDs, one per line. |
{sample}_composition.txt |
One line per genus with its share of the DNA and of the contig count, over every contig in the BlobTools table — kept or dropped. Also read by the annotation step as Bakta's genus hint. |
blob.blobDB.json, the coverage file beside it, and the alignment BAM are all
temporary. Full reasoning, and the two routes by which this step can delete a real
plasmid, on Decontamination.
eval/¶
| Path | Contents |
|---|---|
{sample}_qc_genomes.tsv |
Which genome is which: bin id, role (primary or comparator), technology, source path. In hybrid this is the file that says which of the two rows is the delivered genome. |
quast/ |
QUAST assembly metrics — contig count, N50, largest contig, total length, GC. |
checkm/{sample}_checkm_stats.tsv |
CheckM completeness and contamination. lineage.ms beside it is CheckM's own marker-set file. |
qualimap/ |
Coverage depth and evenness of the reads on the assembly. Absent in contigs mode, where the only alignment is the contigs against themselves and a report on it would say nothing. |
In hybrid, QUAST, CheckM and GTDB-Tk each run over two genomes per sample —
{sample}_illumina and {sample}_ont — so one report holds both and the comparison
is the point. The staging directory eval/genomes/ that carries them there is
temporary. See Assembly QC.
Front-end working directories¶
Kept as the assembler left them, for when you need to see what happened.
| Directory | Modes | Contents |
|---|---|---|
spades/ |
[illumina, hybrid] |
SPAdes' own output, including contigs.fasta before the length and coverage filter. |
flye/ |
[nanopore, hybrid] |
assembly.fasta, Flye's assembly_info.txt (which carries the circularity call), and ignore_list.txt — the contigs Flye did not close, which dnaapler must not rotate. |
fix_start/ |
[nanopore, hybrid] |
dnaapler's reoriented assembly, the header-trimmed copy, and the reorientation summary. |
medaka/ |
[nanopore, hybrid] |
consensus.fasta and Medaka's working files. Absent when Medaka is switched off. |
polypolish/ |
[hybrid] |
Empty at the end — every file in it is temporary. |
snps/ |
[hybrid] |
One numbered sub-directory per Snippy run — 01.flye_snps_dir through 04.polypolish_snps_dir — each comparing one Oxford Nanopore stage against the Illumina assembly, plus SNPs_summary.txt. With Medaka off, 03 holds a skipped.txt instead of a comparison. |
{sample}_replicons.tsv |
[nanopore, hybrid] |
The five-column table handed to Bakta as --replicons: topology from Flye, replicon type from dnaapler. {sample}_replicons_audit.tsv beside it carries the raw numbers and a reason per contig. |
{sample}_medaka_model.txt |
[nanopore, hybrid] |
The Medaka model that was confirmed or inferred, written early so a bad model fails in seconds rather than after the assembler has run. Absent when Medaka is switched off, along with the rule that writes it. |
03.taxonomy — GTDB-Tk¶
One directory per sample, named by GTDB-Tk itself. The file to read is
classify/gtdbtk.bac120.summary.tsv (gtdbtk.ar53.summary.tsv for archaea): the
placement, the closest reference and the ANI to it.
MultiQC reads that summary, and — when the mobilome module is on — so does the step
that maps the species to an AMRFinderPlus --organism, which is what unlocks
point-mutation detection. See Taxonomy.
04.annotation¶
| Path | Contents |
|---|---|
bakta/{sample}/ |
The full Bakta annotation set — {sample}.gff3, .tsv, .faa, .fna, .gbff and more. Three later stages reach into this directory: eggNOG takes the .faa, antiSMASH the .gbff, dbCAN both the .faa and the .gff3. |
eggnog/{sample}/ |
{sample}.emapper.* — orthologous group per protein, with COG category, GO, KEGG KO and pathway, EC. Terminal: nothing else reads it. |
antismash/{sample}/ |
Secondary-metabolite clusters, with antiSMASH's own HTML report. Terminal. |
antismash/databases/ |
The shared antiSMASH reference database: downloaded here, or a symlink view of a copy you already hold. |
dbcan/{sample}/ |
CAZyme calls, gene clusters and substrate predictions. Terminal. |
dbcan/<db version>/ |
The shared dbCAN database, likewise. The folder is named from the download URL, so the version is visible on disk. The empty .verified.sha256 beside it is the marker written once the checksum matched, and its presence is what stops the download repeating. |
eggNOG is the slow tail of a BacFlux run. See Annotation.
05.amr¶
Two legs run independently, and they are meant to disagree at the edges: one sees the assembly, the other sees the reads.
abricate/{sample}/¶
One TSV per database — argannot, card, ecoh, ecoli_vf, megares, ncbi,
resfinder, vfdb — plus AMR_summary.txt, which collates a sample's eight tables.
This leg carries the EFSA thresholds: a hit needs ≥80% identity and ≥70% gene-length
coverage.
mapping/{sample}/ — [illumina, hybrid]¶
Trimmed reads mapped onto CARD's protein homolog model. Reads are immune to assembly collapse, so this leg can see determinants that sit on a contig the assembler destroyed.
| File | Contents |
|---|---|
{sample}_CARD_report.tsv |
The one to read. One row per CARD sequence that cleared the coverage gate, with CARD's own classification joined on: aro_accession, aro_name, covered_percent, category, resistance_mechanism, amr_gene_family, drug_class, reference_organism, note. category is what stops an efflux-pump subunit being counted as an acquired resistance gene. |
{sample}_covstats.tsv |
BBMap's raw coverage table, sorted by descending covered percent. The evidence behind the report. |
{sample}_AMR_legend.tsv |
Every feature covered ≥70%, with its row from CARD's aro_index.tsv. |
What this leg is actually screened at
BBMap is passed minid=0.76 — its own default (CARD_MIN_IDENTITY,
workflow/rules/shared/00_common.smk:394). The rule used to pass idfilter=0.99
instead, which BBMap does not apply to the primary alignment of a properly-paired
read, so 0.76 is what has been in force throughout. Read this as a sensitive
screen: its specificity comes from requiring reads to cover at least 70% of the
reference gene's length (CARD_MIN_COVERED, same file, line 395), not from
per-read identity. There is one mapping pass, and no "divergent" tier.
05.amr/card_db/ holds the CARD database this run used — downloaded there, or a
symlink view of the copy at directories.card_db. Either way it is temporary, and
goes once the mapping and the report have both read it. See
Antimicrobial resistance.
06.plasmids¶
| Path | Contents |
|---|---|
{sample}/platon/verified_plasmids.txt |
The terminal plasmid product on the default path: the contigs Platon called plasmid, each annotated with whether its best nucleotide hit also says "plasmid". That check is supplementary and never a filter — a mobile element on a genuinely chromosomal contig can push both signals the same wrong way. |
{sample}/platon/contigs_final.tsv |
Platon's per-contig table with its replicon-distribution score. Platon names every file after the input basename, hence contigs_final.*. |
{sample}/platon/contigs_final.chromosome.fasta |
The contigs Platon called chromosome. |
{sample}/{sample}_plasmid_concordance.tsv |
Optional. Written only when phage.caller: genomad. One row per contig joining Platon's call and geNomad's, with a confidence column: both callers agree → high, one only → medium, a real clash → low. Nothing is dropped; a disagreement is flagged and kept. |
See Plasmids.
07.phages¶
Which caller runs is set by phage.caller, and the choice changes what stage 06
holds as well as this one.
| Path | Contents |
|---|---|
virsorter/{sample}/ |
Default. VirSorter2's calls at a deliberately loose score cutoff of 0.5; the file CheckV grades is final-viral-combined.fa. |
genomad/{sample}/ |
Only when opted in. One geNomad run produces both the virus calls (contigs_final_summary/contigs_final_virus.fna) and the plasmid calls (contigs_final_summary/contigs_final_plasmid_summary.tsv) that stage 06's concordance table needs. |
checkv/{sample}/quality_summary.tsv |
The phage deliverable. Completeness, contamination and a quality tier per predicted viral sequence. A genome with no viral calls gets a header-only file rather than a failed run. |
vs2_db/, genomad_db/, checkv_db/ |
The caller's and CheckV's databases. Each is either downloaded here or built as a symlink view of a copy you already hold — BacFlux only ever reads your copy. |
See Prophages.
08.mobilome — opt-in¶
Written only when mobilome.run: true. That adds ten rules on the default path; the
module's other twelve belong to four optional layers, each of which stays off until
you configure a source for it. See Turning it on.
Databases and model sets sit at the top of the stage, fetched once and shared by every
sample: conjscan_models/, and — each only when its layer is configured —
icescan_models/, tncentral_db/, iceberg_db/, isosdb_db/.
Per sample, 08.mobilome/{sample}/ holds:
| File | Contents |
|---|---|
{sample}_amr_mobility.tsv |
The deliverable. One row per AMR gene: its mobile-element context, the element's identity where one is known, the contig-edge flags, a mobility tier from 1 to 6 and a confidence. |
{sample}_amr_mobility_audit.tsv |
Why every gene that got no context got none. |
{sample}_is_summary.tsv |
The honesty metric: how many insertion-sequence calls sit within mobilome.contig_boundary_bp of a contig end, and what fraction of the total that is. Read this before the table above. |
{sample}_is_elements.tsv, {sample}_is_discarded.tsv |
One tidy row per insertion sequence, and the dropped rows with a reason. |
{sample}_ice_candidates.tsv, {sample}_ice_discarded.tsv |
ICE/IME candidates with their anchors, boundaries and class; and the discard trail. |
{sample}_amrfinderplus.tsv, _amrfinderplus_mutations.tsv |
The AMR calls with coordinates and a method column; point mutations separately. |
{sample}_amrfinder_organism.txt, _amrfinder_organism_audit.tsv |
Which AMRFinderPlus --organism the GTDB-Tk placement mapped to, or none, and why. |
{sample}_replicon_calls.tsv |
Chromosome or plasmid, per contig, with the evidence for the call. |
{sample}_contig_lengths.tsv |
The yardstick every contig-edge flag is measured against. |
isescan/, conjscan/ |
The tools' own output trees, kept as raw evidence. icescan/ joins them when that optional second model set is switched on. |
{sample}_named_elements.tsv, {sample}_named_elements_discarded.tsv, {sample}_tncentral_blast.tsv |
Optional. Curated transposons and integrons — the layer that makes tier 4 reachable. |
{sample}_ice_candidates_named.tsv, {sample}_ice_naming.tsv, {sample}_iceberg_blast.tsv |
Optional. Curated names put on the ICE/IME candidates. Labels only: this layer cannot change any gene's tier. |
{sample}_is_copy_number.tsv, {sample}_is_copy_number_audit.tsv, {sample}_isosdb_covstats.tsv, {sample}_assembly_covstats.tsv |
Optional, [illumina, hybrid]. How many insertion-sequence copies the assembler collapsed, from read depth rather than from the assembly. |
conjscan_output_missing means the search did not run
A genome with no ICE or IME calls has usually been searched and found to carry no conjugation machinery, which is the normal result for an environmental isolate. But if the machinery search itself fails, the module records that and reports no calls — so the two look identical in the results table.
They are distinguished in {sample}_ice_discarded.tsv. If it carries the reason
conjscan_output_missing, nothing searched that genome: read the absence of ICE and
IME calls as unknown, not as absence. This is the same distinction the mobility
ladder makes between not_assessable and tier 1.
Every column of the mobility table, with real rows, is on Reading the output. What fragmentation does to a call, and what not to conclude from one, is on Draft assemblies.
09.report¶
| File | Contents |
|---|---|
multiqc_report.html |
fastp or NanoPlot, Qualimap, QUAST, CheckM, GTDB-Tk and Bakta for the whole batch, with sample names rewritten into readable panel labels. |
multiqc_config.yaml |
The generated config, kept so the renaming rules are inspectable. |
multiqc_data/ |
MultiQC's parsed numbers behind the report. |
Left alone, MultiQC names a sample after every directory component of the file it came
from. The generated config rewrites those into <what it is> | <sample> — so a panel
row reads assembly QC | S1, and a hybrid sample's two genomes appear separately as
completeness Illumina | S1 and completeness ONT | S1.
The report directory is deliberately not a declared Snakemake output, so anything you drop in it survives a re-run.
logs¶
One file per rule invocation, flat, with the sample appended where the rule runs per
sample — logs/annotation_S1.log, logs/multiqc.log. The stem is usually the rule's
own name, but not always: every mobilome rule logs under a mobilome_ prefix, so rule
isescan writes logs/mobilome_isescan_S1.log, and a handful elsewhere are shortened
— map_amr_db writes logs/map_amr_S1.log. The log is the first place to look when a
rule fails, and the only place some warnings go: the decontamination selector's
"N contigs from the BlobTools table were not found in the FASTA", for instance, is
written there rather than to the console.
There is no benchmarks/ directory: no rule declares Snakemake's benchmark:
directive, so no runtime or memory record is written anywhere.
Temporary files, and directories a re-run wipes¶
Some outputs are declared temporary: Snakemake deletes them as soon as every rule that needed them has finished. They are absent from a completed run, which is normal and not a failure.
| Gone by the end | Why it existed |
|---|---|
01.reads/{sample}/illumina/{sample}.{1,2}.fastq and {sample}_trim_R{1,2}.fastq |
The PhiX-free pairs and then the fastp-trimmed pairs. The trimmed ones survive until the last rule that reads them is done: the assembler, the coverage alignment, the CARD leg, and in hybrid the mapping that picks the Illumina pairs to keep. |
01.reads/phix/ |
The PhiX reference and its index, needed only while reads are being screened. |
02.assembly/{sample}/contaminants/{sample}_map.bam, the BlobTools JSON and coverage file |
Intermediates of the screen; the BlobTools table is kept. |
02.assembly/{sample}/eval/genomes/ |
Staging copies of the assemblies under their bin ids, for QUAST, CheckM and GTDB-Tk. |
02.assembly/{sample}/polypolish/ contents |
Alignments and the pre-correction draft. |
04.annotation/eggnog/{sample}_tmp/ |
emapper's scratch space. |
05.amr/card_db/, and 05.amr/card.tar.bz2 on the download path |
The CARD database, needed only until the mapping and the report have read it. |
08.mobilome/{sample}/assembly_depth_ref/, isosdb_ref/ |
BBMap indexes for the copy-number leg. |
09.report/multiqc_inputs/ |
Relabelled CheckM and GTDB-Tk copies staged for MultiQC. |
Nearly every tool directory on this page is a declared Snakemake directory output:
the per-sample trees written by Bakta, eggNOG, antiSMASH, dbCAN, QUAST, CheckM,
Qualimap, GTDB-Tk, Platon, the phage caller, CheckV, ISEScan and CONJscan, and every
database directory the workflow fetches. Snakemake deletes a directory output before
re-running the rule that makes it, so anything you put inside one will not survive
that rule re-running. Keep your own files beside them, not in them. 09.report/ is
the deliberate exception, which is why it is safe to drop things there.
See also¶
- Configuration — every key referred to above, and its default.
- Running BacFlux — dry runs,
--cores, and what a re-run rebuilds. - Reference databases — which databases you supply and which the workflow fetches into the output directory.
- Troubleshooting — an empty or missing output, and what it usually means.