Skip to content

Viral Genome Reconstruction

Amplicon coverage, Pangolin and Nextclade typing, per-sample QC and iVar variant calls for viral genomes, next to the pipeline's own MultiQC report.

Reviewed
Template version latest

The viralrecon template follows a standard nf-core/viralrecon amplicon run from reads to variant calls and lineage, one tab or tab group per step:

  • Overview: the run in four key figures, live findings and four figures, each linked to the tab that explains it
  • Data & QC: the MultiQC report, per-sample alignment and consensus QC, and mosdepth coverage per window and per amplicon
  • Variants: every call with its snpEff effect, its allele frequency and its read support (iVar on Illumina runs)
  • Lineage & Clustering: Pangolin lineages and Nextclade clades with their QC verdicts, and the samples grouped by the mutations they share

Works beyond SARS-CoV-2

The pipeline supports any viral genome in nf-core's reference-genomes config. This template was validated on SARS-CoV-2 ARTIC amplicon data, but the recipes and dashboard carry over to other viruses with the same iVar variant calling and Pangolin and Nextclade typing layout. The dashboard texts name no virus, primer scheme or reference.


Quick start

depictio ingest /path/to/runs \
  --template nf-core/viralrecon/latest

The results directory is the only thing you have to pass. The template reads a sequencing-runs layout, so point it at the parent of one or more run_* directories, each holding one viralrecon --outdir. Every run found there is aggregated into the same collections.

depictio config nextflow --install     # once per machine
nextflow run nf-core/viralrecon -r 3.0.0 -profile docker \
  --outdir runs/run_1 --depictio_data_root runs

No depictio ingest, and no template named: the pipeline ingests its own output, and the template is picked from the pipeline's own name and version. Write the run into a run_* directory and point --depictio_data_root at its parent. See Nextflow trigger.

Variable Required What it does
DATA_ROOT yes Parent of the run_* directories holding the viralrecon output (multiqc/, variants/).
IS_NANOPORE no Set automatically when the run's params.json records platform: nanopore. Repoints the coverage and typing collections at the artic_minion/ layout and drops the Illumina-only collections.

Override the auto-derived value

IS_NANOPORE is read from pipeline_info/params*.json and logged at resolution time. Pass --var IS_NANOPORE=true to force the nanopore route, for example when a DATA_ROOT aggregates runs whose parameters were not kept. See the routes in the Reference.

Aggregated data collections

The viralrecon DCs use metatype: "Aggregated". They are built by recipes that fan multiple per-sample files into a single delta table via glob_pattern. See Recipes for the underlying mechanism.


Reference

Recipe DCs fan per-sample files into one delta table via glob_pattern. The IS_NANOPORE route repoints the coverage and typing DCs at the artic_minion/ layout and drops variants_long and the views built on the variant calls, since an ARTIC run writes no variants_long_table.csv. summary_metrics stays, read from the ARTIC summary CSV with its share of reads mapped left empty.

Direct vs derived data collections

The template exposes two kinds of data collection, and the Origin column of the reference table below flags each one explicitly, so you can tell real measurements from views at a glance:

Origin What it is Examples
direct A real pipeline output, scanned straight off disk or lightly cleaned by a recipe that reads the raw files. This is the data. variants_long, pangolin_lineages, nextclade_results, mosdepth_amplicon_coverage
derived A reshape of one or more direct collections into the exact column layout an advanced visualization needs: a view, not new measurement (its recipe reads another collection via dc_ref). oncoplot_canonical, complex_heatmap_canonical, coverage_track_canonical, sankey_canonical, upset_canonical, variant_feature_matrix_canonical

Each derived collection names its source recipe in the reference table's Reads column.

Self-adapting layout

The dashboard adapts to whatever the run actually produced: components bound to pruned or unparsed data collections are hidden, tabs left with no real visualizations are dropped, and the rest are re-packed with no empty rows. One template therefore covers both the Illumina and nanopore/ARTIC routes without edits.

Template variables

Variables you provide when running the template: DATA_ROOT is the results directory given to depictio ingest, the others are set with --var NAME=value:

Variable Required Description
DATA_ROOT ✓ Root directory containing viralrecon pipeline output (multiqc/, variants/)

Auto-detected (set from the run's metadata / params.json; the route flags drive Conditional routes below): IS_NANOPORE

Data collections

14 data collections — 2 required 12 optional · 8 direct 6 derived.

Origin tells you whether a collection is real pipeline data or a reshape of it: direct = a pipeline output (scanned, or a recipe that reads raw files); derived = a recipe that reshapes one or more direct collections into the layout a visualization needs (no new measurement). Reads shows what produces it: a recipe .py transform, whose name links to its source on GitHub, or a raw file scanned off disk. (A direct collection can still have a recipe — one that merely parses/cleans the raw file; derived means the recipe reshapes another collection.)

Tag Origin Type Reads Status
multiqc_data direct MultiQC MultiQC file multiqc/multiqc_data/multiqc.parquet required
summary_metrics direct Table recipe multiqc/summary_metrics.py required
variants_long direct Table recipe ivar/variants_long.py optional
pangolin_lineages direct Table recipe pangolin/pangolin_lineages.py optional
nextclade_results direct Table recipe nextclade/nextclade_results.py optional
mosdepth_amplicon_coverage direct Table file variants/bowtie2/mosdepth/amplicon/all_samples.mosdepth.coverage.tsv optional
mosdepth_genome_coverage direct Table file variants/bowtie2/mosdepth/genome/all_samples.mosdepth.coverage.tsv optional
mosdepth_amplicon_heatmap direct Table file variants/bowtie2/mosdepth/amplicon/all_samples.mosdepth.heatmap.tsv optional
oncoplot_canonical derived Table recipe nf-core/viralrecon/oncoplot_canonical.py optional
complex_heatmap_canonical derived Table recipe mosdepth/complex_heatmap_canonical.py optional
coverage_track_canonical derived Table recipe mosdepth/coverage_track_canonical.py optional
sankey_canonical derived Table recipe nf-core/viralrecon/sankey_canonical.py optional
upset_canonical derived Table recipe nf-core/viralrecon/upset_canonical.py optional
variant_feature_matrix_canonical derived Table recipe nf-core/viralrecon/variant_feature_matrix_canonical.py optional

Conditional routes

Rows are data collections; columns are the variables you set or params.json flags auto-detected from the run. Each filled cell is the effect of setting that variable; an empty cell means that variable leaves the collection unchanged. (5 collections are unaffected by any variable — present on every run.)

+ included− removed⇄ repointed

Data collection IS_NANOPORE
variants_long −
pangolin_lineages ⇄
nextclade_results ⇄
mosdepth_amplicon_coverage ⇄
mosdepth_genome_coverage ⇄
mosdepth_amplicon_heatmap ⇄
oncoplot_canonical −
upset_canonical −
variant_feature_matrix_canonical −

12 links — selecting a value in the source collection filters the target. The join column is shown after the source.

Recipes

Each recipe reshapes raw pipeline output into a tidy table. The name links to its source; Output lists the validated OUTPUT_SCHEMA columns.

Recipe Transforms Output
ivar/variants_long.py Clean and normalize viralrecon variants_long_table.csv for dashboard consumption. sample, CHROM, POS, REF, ALT, FILTER, DP, REF_DP, ALT_DP, AF, GENE, AA, EFFECT, FUNCLASS, mutation_label
mosdepth/complex_heatmap_canonical.py Canonical-schema ComplexHeatmap DC for viralrecon amplicon coverage. sample
mosdepth/coverage_track_canonical.py Canonical-schema Coverage Track DC for viralrecon. chromosome, position, value
multiqc/summary_metrics.py Parse viralrecon summary_variants_metrics_mqc.csv into a clean per-sample metrics table. sample, num_reads_mapped, pct_reads_mapped, coverage_median, pct_genome_covered_1x, pct_genome_covered_10x, num_variants_snp, num_variants_indel, num_variants_total, lineage
nextclade/nextclade_results.py Extract and clean Nextclade clade assignment results from viralrecon output. sample, clade, Nextclade_pango, totalSubstitutions, totalDeletions, totalInsertions, totalFrameShifts, totalMissing, totalNonACGTNs, alignmentScore, coverage, qc_overallScore, qc_overallStatus
nf-core/viralrecon/oncoplot_canonical.py Canonical-schema Oncoplot DC for viralrecon variants. sample_id, gene, mutation_type
nf-core/viralrecon/sankey_canonical.py Canonical-schema Sankey DC for viralrecon lineage / clade typing. sample, qc_status, lineage, clade
nf-core/viralrecon/upset_canonical.py Canonical-schema UpSet DC for viralrecon variants. mutation_label
nf-core/viralrecon/variant_feature_matrix_canonical.py Canonical-schema sample × variant feature matrix for live PCA embedding. sample_id
pangolin/pangolin_lineages.py Extract and clean Pangolin lineage assignments from viralrecon output. sample, lineage, conflict, ambiguity_score, scorpio_call, scorpio_support, pangolin_version, qc_status

Dashboard tabs

One dashboard: the Overview, then five child tabs in two groups, read as a funnel from the reads to the lineage of each consensus genome. Each tab below carries the same icon and colour the dashboard gives it, so the page and the app read alike.

Group Tabs
Data & QC MultiQC, Sample QC, Coverage & Depth
Genomes Variants, Lineage & Clustering

Each child tab opens with a short intro and a strip of four cards, then at most three open sections; tables and details follow, collapsed. The run summary, summary_metrics, is the source of every cross-DC link, so a filter on it reaches every tab. The persistent Sample filters (lineage, then sample id) and QC thresholds (genome at 10x, median depth, reads mapped, variants called) sit in the left panel and narrow every tab. The Sample sheet, the run summary table, is pinned, collapsed, to the bottom of every child tab.

Nanopore (ARTIC) runs

A nanopore run keeps the Overview's Key figures, the persistent filters and the Sample sheet: the run summary is read from the ARTIC summary CSV, which has every column but the share of reads mapped, left empty. Coverage, lineage and clade are read from artic_minion/. The ARTIC route writes no variant long table, so the Variants tab, the PCA and the UpSet drop, and so do the Overview's missense row and its allele frequency figure.

Viral genomes, from reads to variants, consensus and lineage.

Overview dashboard

Overview dashboard

A short hero links the run parameters. About this dashboard says how to move through the tabs, The run lists the samples, platform and protocol, reference, primer scheme and callers, and Pipeline walks the six steps from trimming to typing, each linked to its parameters and its tab. The findings are live values: they follow the filters, and a route that lacks their data drops them.

Filters and components

Filters · the left panel starts collapsed. Key figures and Findings each have a filter bar (sample id and a genome-at-10x range) that narrows that section only.

Section What it holds
Top Hero, About this dashboard, The run, Pipeline
Key figures 4 headline cards on the run summary: samples, median depth, genome at 10x, variants per sample
Findings Live result rows, then 4 figures: depth against genome at 10x, depth per amplicon, allele frequency along the genome, and the flow from QC verdict to lineage and clade
How to read this dashboard The tabs by group, each with its question

Data & QC · Did reads trim, align and cover the genome in every sample?

MultiQC dashboard

MultiQC dashboard

MultiQC panels only: general statistics, the samples that failed mapping, fastp filtered reads, Bowtie 2 alignments and the mosdepth cumulative coverage open. The read and alignment panels and the variant and assembly panels follow, collapsed. Its sample filter reads the MultiQC report.

Filters and components

Filters · Sample ID, read from the MultiQC report.

Section What it holds
QC overview 5 MultiQC panels
Read & alignment details (collapsed) 6 MultiQC panels
Variant & assembly details (collapsed) 7 MultiQC panels

Data & QC · Did each sample yield a well-covered, trustworthy consensus genome?

Sample QC dashboard

Sample QC dashboard

The median Reads mapped against the 1,000-read floor, the share of reads mapped, the Median depth and the Genome at 10x. Then median depth against genome covered at 10x, one point per sample, beside a record card for the sample you pick, the Nextclade substitutions against deletions per consensus genome, and the genome covered at 1x and 10x per sample.

Filters and components

Filters · SNPs and indels called on summary_metrics, and missing bases on nextclade_results, all as ranges, plus the sample filters.

Section What it holds
QC at a glance 4 cards
Diagnostics Median depth against genome covered at 10x + a sample record card, Substitutions against deletions (Nextclade)
Breadth per sample Genome covered at 1x and 10x per sample

Data & QC · Where along the genome does each sample lose depth?

Coverage & Depth dashboard

Coverage & Depth dashboard

The median depth per 200 bp window, the windows under 10x, the median amplicon depth and the amplicons under 10x in at least one sample; 10x is the depth under which the consensus masks a position. Then the genome track, one lane per sample, the amplicon track and the clustered amplicon heatmap. A run without a primer scheme keeps only the window cards and the genome track.

Filters and components

Filters · window depth on mosdepth_genome_coverage, and the amplicon and amplicon depth on mosdepth_amplicon_coverage.

Section What it holds
Coverage at a glance 4 cards
Along the genome 1 advanced visualization
Per amplicon 2 advanced visualizations
Amplicon table (collapsed) Depth per sample and amplicon

Genomes · Which mutations does each sample carry, and how well supported?

Variants dashboard

Variants dashboard

The calls by functional class, the distinct mutations, the median allele frequency against the 0.75 consensus cut-off and the median read depth. Then the allele frequency of every call along the genome, the allele frequency histogram beside the read support scatter, and the mutation matrix per sample and gene. The per-gene lollipops, the calls per gene and per sample, and the variant table are collapsed.

Filters and components

Filters · Gene, Effect, Functional class, allele frequency and read depth on variants_long, plus a collapsed Matrix filter on the mutation type that narrows the mutation matrix only.

Section What it holds
Calls at a glance 4 cards
Along the genome 1 advanced visualization
Support Allele frequency of the calls, Read support per call
Co-occurrence 1 advanced visualization (mutation matrix)
Genes and effects (collapsed) 1 advanced visualization + Calls per gene, Calls per sample
Variant table (collapsed) Variant calls

Genomes · Which lineage and clade is each sample, and do they agree?

Lineage & Clustering dashboard

Lineage & Clustering dashboard

The distinct Pangolin lineages, the distinct Nextclade clades, the median Nextclade QC score and the median missing bases. Then the flow from Pangolin QC verdict to lineage to clade, the PCA of the samples by the mutations they share, and the UpSet of the mutations shared across lineages. A lasso on the PCA makes an analysis group.

Filters and components

Filters · Lineage, Clade, and the Pangolin and Nextclade QC verdicts.

Section What it holds
Typing at a glance 4 cards
Classification flow 1 advanced visualization
Variant profiles 2 advanced visualizations (PCA, UpSet)
Calls per lineage and clade (collapsed) Samples per lineage, Samples per clade
Typing tables (collapsed) Pangolin lineage calls + a lineage record card, Nextclade clade calls

Every per-sample table (run summary, amplicon depth, Pangolin, Nextclade, variant calls) selects rows on sample, and the depth against breadth scatter, the Nextclade scatter, the allele frequency track, the read support scatter and the PCA select points on it. summary_metrics links sample to every per-sample collection, so a pick narrows the rest of the tab. The record cards wait for a pick, and a lasso on the PCA becomes an analysis group.


Running the pipeline

Depictio reads the output of nf-core/viralrecon, it does not run the pipeline. Run the pipeline first, using the iVar variant caller the template targets, and write it into a run_* directory:

nextflow run nf-core/viralrecon -r 3.0.0 \
  --input samplesheet.csv \
  --platform illumina \
  --protocol amplicon \
  --variant_caller ivar \
  --outdir runs/run_1 \
  -profile docker

Then point Depictio at the parent of the run directories:

depictio ingest runs/ \
  --template nf-core/viralrecon/latest

A later run written to runs/run_2 is aggregated into the same collections on the next ingest. A nanopore ARTIC run (--platform nanopore) needs no extra flag: Depictio reads platform: nanopore from the run's params.json and sets IS_NANOPORE itself.

See nf-co.re/viralrecon/usage for full pipeline documentation.


Required data structure

Point depictio ingest at the directory holding the run_* directories. Depictio scans each run recursively and matches on file name. Not all files are required: optional collections that a run did not write (no Pangolin output with --skip_pangolin, for example) are skipped, and the dashboard hides the components bound to them.

The tree below shows the Illumina layout. On IS_NANOPORE the coverage and typing collections are read from artic_minion/ instead.

<DATA_ROOT>/
└── run_1/                                        # one viralrecon --outdir per run_* directory
    ├── pipeline_info/params*.json                # read to set IS_NANOPORE
    ├── multiqc/
    │   ├── multiqc_data/
    │   │   └── multiqc.parquet
    │   └── summary_variants_metrics_mqc.csv      # the hub: one row per sample
    └── variants/
        └── ivar/                                 # artic_minion/ on IS_NANOPORE
            ├── consensus/
            │   └── bcftools/
            │       ├── pangolin/*.pangolin.csv   # Pangolin lineage, one file per sample
            │       └── nextclade/*.csv           # Nextclade clade, one file per sample
            ├── variants_long_table.csv           # iVar variant calls
            └── *.mosdepth.{coverage,heatmap}.tsv # amplicon and genome coverage

Validation runs

The nf-core AWS megatests do not publish the aggregated files this template reads (multiqc.parquet, variants_long_table.csv, the Pangolin and Nextclade reports, summary_variants_metrics_mqc.csv). The repository therefore ships download_test_data.sh, which runs nf-core/viralrecon with its test_illumina profile into a sequencing-runs layout (Nextflow 24.10 or later, and Docker or Singularity):

bash depictio/projects/nf-core/viralrecon/3.0.0/download_test_data.sh /tmp/viralrecon_test

The run lands in /tmp/viralrecon_test/run_1, so ingest its parent:

depictio ingest /tmp/viralrecon_test \
  --template nf-core/viralrecon/latest

Do not pass --project when ingesting: the dashboard is attached to the project by name, so renaming it breaks a later depictio dashboard import. Re-ingesting accumulates dashboards, so delete the project before repeating a run.


Additional resources


Authorship

Developers Wrote the template, its recipes and its dashboards. weber8thomas
Reviewers Ran it on real data and signed off on the status above. Depictio team
Maintainers Keep it working as nf-core/viralrecon releases. weber8thomas

Reviewing a template on your own data, or taking over a role here, is a contribution in itself: the contributing guide says what each one involves.