--- title: "Reading VCFs and Building Mutational-Spectrum Catalogs" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Reading VCFs and Building Mutational-Spectrum Catalogs} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 8, fig.height = 3.5, dpi = 100, out.width = "100%" ) can_load <- function(pkg) { nzchar(system.file(package = pkg)) && isTRUE(tryCatch({ loadNamespace(pkg); TRUE }, error = function(e) FALSE)) } have_bsgenome <- can_load("BSgenome.Hsapiens.1000genomes.hs37d5") have_msigplot <- can_load("mSigPlot") eval_all <- have_bsgenome && have_msigplot knitr::opts_chunk$set(eval = eval_all) ``` This vignette walks through the four-step **mSigSpectra** pipeline — `read_vcf` → `split_vcf` → `annotate_sbs_or_dbs_vcf` / `annotate_id_vcf` → `vcf_to_sbs_catalog` / `vcf_to_dbs_catalog` / `vcf_to_id_catalog` — using a real Strelka VCF that ships with the package. It then plots each catalog with [`mSigPlot`](https://github.com/steverozen/mSigPlot). If you do not have the BSgenome package or `mSigPlot` installed, the chunks below will be skipped at render time. To install: ```r BiocManager::install("BSgenome.Hsapiens.1000genomes.hs37d5") remotes::install_github("steverozen/mSigPlot") ``` ## 1. Load packages ```{r load} library(mSigSpectra) library(mSigPlot) ``` ## 2. Locate test VCFs Three example VCFs ship with the package: a Strelka SBS file, a Strelka indel file, and a Mutect file (all small subsets, GRCh37 / hg19). ```{r files} sbs_file <- system.file( "extdata", "Strelka-SBS-GRCh37", "Strelka.SBS.GRCh37.s1.vcf", package = "mSigSpectra" ) id_file <- system.file( "extdata", "Strelka-ID-GRCh37", "Strelka.ID.GRCh37.s1.vcf", package = "mSigSpectra" ) mutect_file <- system.file( "extdata", "Mutect-GRCh37", "Mutect.GRCh37.s1.vcf", package = "mSigSpectra" ) ``` ## 3. Read the SBS VCF `read_vcf()` returns a `data.table` with whatever columns the VCF body contains. We pass `filter = "PASS"` to match the Strelka convention. ```{r read-sbs} sbs_vcf <- read_vcf(sbs_file, filter = "PASS") nrow(sbs_vcf) head(sbs_vcf[, c("CHROM", "POS", "REF", "ALT", "FILTER")]) ``` ## 4. Split into SBS / DBS / ID sub-tables `split_vcf()` partitions rows by `REF`/`ALT` length alone. For a "pure SBS" VCF you would expect everything in `$SBS`, but Strelka's SBS caller can emit adjacent SBS pairs that the indel caller does not see; mSigSpectra **does not** merge them into DBSs (see "Gotchas" in the README) — they stay as SBSs. ```{r split-sbs} sbs_split <- split_vcf(sbs_vcf, name_of_vcf = "Strelka.SBS.GRCh37.s1") sapply(sbs_split[c("SBS", "DBS", "ID")], nrow) ``` ## 5. Annotate the SBS rows `annotate_sbs_or_dbs_vcf()` adds: * `seq.bases` — the flanking sequence context (default `seq.21bases`). * For ref genomes with a shipped transcript-ranges table (GRCh37 / GRCh38 / GRCm38), the transcript-strand columns `trans.start.pos`, `trans.end.pos`, `trans.strand`, `trans.Ensembl.gene.ID`, `trans.gene.symbol`, plus `bothstrand` and `count` (number of overlapping transcripts). It returns a list with `annotated.vcf` (the table below) and `discarded.variants` (always `NULL` for SBS / DBS). ```{r annotate-sbs} sbs_ann <- annotate_sbs_or_dbs_vcf(sbs_split$SBS, ref_genome = "GRCh37")$annotated.vcf new_cols <- setdiff(colnames(sbs_ann), colnames(sbs_split$SBS)) new_cols ``` ## 6. Build SBS catalogs A catalog is a single-column numeric matrix with attributes (no S3 class). One call per resolution. ```{r build-sbs} cat96 <- vcf_to_sbs_catalog(sbs_ann, type = "SBS96", ref_genome = "GRCh37", region = "genome", sample_name = "s1") cat192 <- vcf_to_sbs_catalog(sbs_ann, type = "SBS192", ref_genome = "GRCh37", region = "transcript", sample_name = "s1") cat1536 <- vcf_to_sbs_catalog(sbs_ann, type = "SBS1536", ref_genome = "GRCh37", region = "genome", sample_name = "s1") dim(cat96) sum(cat96) catalog_attrs(cat96) ``` ## 7. Plot SBS catalogs ```{r plot-sbs96, fig.height=3.5} plot_SBS96(cat96, plot_title = "Strelka.SBS.GRCh37.s1 — SBS96") ``` ```{r plot-sbs192, fig.height=4} plot_SBS192(cat192, plot_title = "Strelka.SBS.GRCh37.s1 — SBS192 (stranded)") ``` ```{r plot-sbs1536, fig.height=8} plot_SBS1536(cat1536, plot_title = "Strelka.SBS.GRCh37.s1 — SBS1536") ``` ## 8. Build and plot ID catalogs The Strelka indel VCF goes through `annotate_id_vcf()`, which left-justifies each indel, extracts the local repeat / microhomology context, and emits the three classification strings (`COSMIC_83`, `Koh_89`, `Koh_476`). Like `annotate_sbs_or_dbs_vcf()` it returns a list of `annotated.vcf` + `discarded.variants`. ```{r id-pipeline} id_vcf <- read_vcf(id_file, filter = "PASS") id_split <- split_vcf(id_vcf, name_of_vcf = "Strelka.ID.GRCh37.s1") id_ann <- annotate_id_vcf(id_split$ID, ref_genome = "GRCh37")$annotated.vcf id_ann[1, c("CHROM", "POS", "REF", "ALT", "COSMIC_83", "Koh_89")] cat_id83 <- vcf_to_id_catalog(id_ann, type = "ID83", ref_genome = "GRCh37", region = "genome", sample_name = "s1") cat_id89 <- vcf_to_id_catalog(id_ann, type = "ID89", ref_genome = "GRCh37", region = "genome", sample_name = "s1") cat_id476 <- vcf_to_id_catalog(id_ann, type = "ID476", ref_genome = "GRCh37", region = "genome", sample_name = "s1") ``` ```{r plot-id83, fig.height=3.5} plot_ID83(cat_id83, plot_title = "Strelka.ID.GRCh37.s1 — ID83") ``` ```{r plot-id89, fig.height=4} plot_ID89(cat_id89, plot_title = "Strelka.ID.GRCh37.s1 — ID89") ``` ```{r plot-id476, fig.height=10} plot_ID476(cat_id476, plot_title = "Strelka.ID.GRCh37.s1 — ID476") ``` ## 9. Counts ↔ density Convert from raw counts (per category) to mutation density (per megabase of context) using the shipped k-mer abundances: ```{r density} cat96_density <- transform_catalog(cat96, target_counts_or_density = "density") attr(cat96_density, "counts_or_density") ``` ```{r plot-sbs96-density, fig.height=3.5} plot_SBS96(cat96_density, plot_title = "Strelka.SBS.GRCh37.s1 — SBS96 (density)") ``` ## 10. Collapse from finer to coarser resolutions ```{r collapse} cat96_from_1536 <- collapse_catalog(cat1536, to = "SBS96") all.equal(as.numeric(cat96_from_1536[, 1]), as.numeric(cat96[, 1])) ``` ## 11. Catalog I/O ICAMS-native CSV is the default and only output format today; SigProfiler and COSMIC formats are supported on input. ```{r io} out_path <- file.path(tempdir(), "Strelka.SBS.GRCh37.s1.SBS96.csv") write_catalog(cat96, out_path) cat96_back <- read_catalog(out_path, region = "genome") identical(as.numeric(cat96), as.numeric(cat96_back)) ``` ## See also * `?read_vcf` — the caller-agnostic reader. * `?annotate_sbs_or_dbs_vcf` — sequence context + transcript strand for SBS / DBS. * `?annotate_id_vcf` — indel justification + classification (COSMIC 83 / Koh 89 / Koh 476) + transcript strand. * `?vcf_to_sbs_catalog`, `?vcf_to_dbs_catalog`, `?vcf_to_id_catalog` — per-variant-type catalog builders. * `?transform_catalog` / `?collapse_catalog` — counts ↔ density and finer-to-coarser collapse. * `?check_and_remove_discarded_variants` — optional defensive QC. * The README's "Gotchas" section documents the cases this pipeline intentionally leaves to the user.