Standalone reporting tool for the LRSomatic Nextflow pipeline. Generates a self-contained HTML report per sample with:
- Summary header: purity, ploidy, coverage, N50, variant counts
- Circos plot: somatic SNVs (6-class SBS colours), non-BND SVs, ASCAT copy number, translocation links
- Interactive variant table: VEP-annotated somatic small variants, optionally filtered to a gene panel, with VAF, depth and phasing
- Interactive SV table: Severus structural variants annotated with gene overlaps, sharing the same gene-panel filter
- Phasing: per-chromosome WhatsHap statistics (germline)
- QC details: mosdepth coverage, samtools flagstat, cramino read stats
S=/path/to/CCS15-ONT
Rscript bin/render_report.R \
--sample-dir $S \
--sample-id CCS15-ONT \
--sex male \
--reference auto # auto-detects t2t vs hg38 from VCF headersThe output file CCS15-ONT_report.html will be written to the current directory.
Matched and tumour-only runs take the same command: the run mode and every input file are discovered from the sample directory.
Tables render unfiltered. Add --gene-panel lymphoid (or a path to your own TSV) to have a
panel selected when the report opens — see Gene panels.
--sample-dir Path to the sample output directory (required)
--sample-id Sample identifier (default: directory name)
--reference t2t | hg38 | auto (default: auto)
--sex male | female | XY | XX (required)
--gene-panel none | builtin panel name (e.g. lymphoid) | path to a custom TSV
(default: none — tables render unfiltered)
--output Output HTML path (default: <sample-id>_report.html in current dir)
--title Report title
Changed in v1.1.0:
--modeand--somatic-vcfwere removed. Run mode is derived from whether normal-side QC is present, and the VCF supplying VAF is now discovered (see below), so neither needs to be declared. Scripts passing them will fail on an unknown option.--gene-panelnow defaults tononeinstead oflymphoid: reports open unfiltered unless a panel is asked for. Pass--gene-panel lymphoidto restore the old default.
Reports are unfiltered by default. --gene-panel only chooses which panel is selected when
the report opens; the rendered HTML always contains every variant and every builtin panel, so a
reader can switch panels (or paste a custom gene list) in the browser without re-rendering.
Built-in panels live in assets/gene_lists/. Each is a TSV with a gene column (HGNC symbols).
| Panel | Description |
|---|---|
lymphoid |
~70 recurrently mutated genes in B-cell lymphomas (DLBCL, FL, CLL, MCL, BL, MALT) |
--gene-panel lymphoid # open with the builtin lymphoid panel applied
--gene-panel /path/to/my_genes.tsv # must have a 'gene' column or be a single-column fileA --gene-panel value that is neither none, a builtin name, nor an existing file is an error —
a typo will not silently produce an unfiltered report.
The --sample-dir must be the root of a single-sample LRSomatic output. Files are discovered
recursively by their distinctive filename suffix, so they can be nested in any directory
structure underneath it — for example:
CCS15-ONT/
├── *_SOMATIC_VEP.vcf.gz VEP-annotated somatic small variants
├── variants/phased/somatic_smallvariants.vcf.gz VAF / depth / phasing source
├── severus_somatic.vcf.gz Severus SV calls
├── *_SV_VEP.vcf.gz VEP-annotated SVs
├── *.segments_raw.txt, *.purityploidy.txt ASCAT
├── *.mosdepth.summary.txt, *.mosdepth.global.dist.txt mosdepth (tumour)
├── *_cramino.txt, *.flagstat, *.stats cramino / samtools (tumour)
├── qc/whatshap_stats/*_whatshap_stats.tsv phasing statistics (germline)
├── wakhan/ Wakhan copy-number solutions
└── **/normal/** same QC file set, normal side
(matched mode; e.g. qc/normal/)
Normal-side QC is picked up from any normal/ directory in the tree, wherever the pipeline
nests it, and is also what determines the run mode.
Small variants come from the VEP annotation only. *_SOMATIC_VEP.vcf.gz defines the
variant set; VAF, depth, genotype and phase set are joined from the VCF that VEP annotated —
variants/phased/somatic_smallvariants.vcf.gz. Runs predating variants/phased/ fall back to
variants/clairs{,to}/somatic.vcf.gz (then any non-germline VCF in those directories), which
yields VAF and depth but no phase set. If none is found the table still renders, without
those columns.
VEP writes indels at a different position and sometimes in a different allele notation than
the VCF it was given, so the join is made on a normalised key — see variant_key() in
R/parse_smallvariants.R.
*_SOMATIC_VEP.vcf.gz ships in two formats. Usually it is VEP default text output despite
the .vcf.gz name. If VEP was run with --vcf it is a genuine VCF with a CSQ field, and
may be a merged multi-caller VCF carrying germline calls (DeepVariant, Clair3) alongside
somatic ones, tagged in INFO/CALLER; the report then keeps only PASS records from a
somatic caller (ClairS, ClairS-TO, DeepSomatic). Both formats are detected automatically.
Missing files are handled gracefully: the corresponding report section shows a "not available" notice.
There is no methylation section. The only methylation output the pipeline publishes is
methylation/<type>/modkit_pileup/<id>.bed.gz — measured at 38–42 GB gzipped per sample,
unfiltered and with no tabix index, which cannot be read at render time.
modkit pileup already runs with --bgzf, so emitting a tabix -p bed index next to the
.bed.gz would be enough to unblock this: region queries on an indexed pileup measured
~0.16 s per Mb, making a binned genome-wide profile or per-locus lookup practical.
--reference |
Cytobands source | chr1 length |
|---|---|---|
t2t |
CHM13v2.0 | 248,387,328 bp |
hg38 |
GRCh38 (UCSC) | 248,956,422 bp |
Auto-detection reads ##contig lines from the VEP somatic VCF.
Install in your R environment if missing:
install.packages(c("data.table", "dplyr", "tidyr", "DT", "htmltools",
"optparse", "quarto", "yaml", "ggplot2", "svglite"))
BiocManager::install(c("circlize", "ComplexHeatmap", "GenomicRanges"))
# paletteer, prismatic are optional (not required by this version)Tested with R 4.4.1 and Quarto 1.5.57.
lrsomatic_report/
├── bin/render_report.R CLI entrypoint
├── R/
│ ├── utils.R Shared helpers (gene panel, Extra-field parser)
│ ├── references.R Cytoband + chrom-length loading, reference auto-detection
│ ├── locate_outputs.R Discover per-tool output files in a sample directory
│ ├── parse_smallvariants.R VEP text + raw caller VCF parsers; build variant table
│ ├── parse_severus.R Severus VCF + gene TSV parsers; build SV table
│ ├── parse_ascat.R ASCAT segments + purity/ploidy parsers
│ ├── parse_qc.R Mosdepth, cramino, flagstat parsers
│ └── circos.R draw_circos() — generates the circos SVG
├── templates/per_sample.qmd Quarto template (HTML report)
├── assets/
│ ├── references/{t2t,hg38}/ Cytobands + chrom lengths (bundled, no network needed)
│ └── gene_lists/ lymphoid.tsv + README
└── tests/ Unit tests (testthat)
- v2: Cohort report (oncoprint, recurrence tables across multiple samples)
- v2: Nextflow module wrapping this CLI as a final pipeline step
- v2: Wakhan haplotype-resolved copy-number integration