epistack
Workflows
Standard Workflow
Visualize ChIP-seq coverage signal centered around merged peak regions, sorted and binned by peak scores.
library(GenomicRanges)
library(SummarizedExperiment)
library(epistack)
library(rtracklayer)
library(EnrichedHeatmap)
# 1. Load peak files
path_peaks <- c(
peak1 = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/Rep1_peaks_ucsc_chr6.bed",
peak2 = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/Rep2_peaks_ucsc_chr6.bed"
)
peaks <- lapply(path_peaks, import)
# 2. Merge peaks across replicates
merged_peaks <- GenomicRanges::union(peaks[[1]], peaks[[2]])
scores_rep1 <- double(length(merged_peaks))
scores_rep1[findOverlaps(peaks[[1]], merged_peaks, select = "first")] <- peaks[[1]]$score
scores_rep2 <- double(length(merged_peaks))
scores_rep2[findOverlaps(peaks[[2]], merged_peaks, select = "first")] <- peaks[[2]]$score
peak_type <- ifelse(
scores_rep1 != 0 & scores_rep2 != 0, "Both", ifelse(
scores_rep1 != 0, "Rep1 only", "Rep2 only"
)
)
mcols(merged_peaks) <- DataFrame(scores_rep1, scores_rep2, peak_type)
merged_peaks$mean_scores <- apply((mcols(merged_peaks)[, c("scores_rep1", "scores_rep2")]), 1, mean)
merged_peaks <- merged_peaks[order(merged_peaks$mean_scores, decreasing = TRUE), ]
# 3. Load aligned reads
path_reads <- c(
rep1 = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/H3K27ac_rep1_filtered_ucsc_chr6.bed",
rep2 = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/H3K27ac_rep2_filtered_ucsc_chr6.bed",
input = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/ES_input_filtered_ucsc_chr6.bed"
)
reads <- lapply(path_reads, import)
# 4. Generate coverage matrices around peak centers
coverage_matrices <- lapply(
reads,
function(x) {
normalizeToMatrix(
x,
resize(merged_peaks, width = 1, fix = "center"),
extend = 5000, w = 250,
mean_mode = "coverage"
)
}
)
xlabs <- c("-5kb", "peak center", "+5kb")
# 5. Construct a SummarizedExperiment object containing the data
merged_peaks_se <- SummarizedExperiment(
rowRanges = merged_peaks,
assays = coverage_matrices
)
# 6. Assign peak types as bins and plot the stacked profiles
rowRanges(merged_peaks_se)$bin <- rowRanges(merged_peaks_se)$peak_type
plotEpistack(
merged_peaks_se,
assays = c("rep1", "rep2", "input"),
tints = c("dodgerblue", "firebrick1", "grey"),
titles = c("Rep1", "Rep2" , "Input"),
x_labels = xlabs,
zlim = c(0, 4), ylim = c(0, 4),
metric_col = "mean_scores", metric_title = "Peak score",
metric_label = "score",
bin_palette = colorRampPalette(c("darkorchid1", "dodgerblue", "firebrick1")),
npix_height = 300
)
Note on inputs/outputs: Input is peak BED files and read alignment files, and output is a stacked genomic track visualization.
Promoter Epigenetics Expression
Visualize DNA methylation and ChIP-seq coverage at gene promoters (TSS) sorted and binned by gene expression levels.
library(GenomicRanges)
library(SummarizedExperiment)
... [vignette text truncated]
# 1. Read the declared user input files from the working directory
load(
system.file("extdata", "chr21_test_data.RData", package = "EnrichedHeatmap"),
verbose = TRUE
)
# 2. Extract TSS coordinates using GenomicRanges::promoters
tss <- promoters(genes, upstream = 0, downstream = 1)
tss$gene_id <- names(tss)
# 3. Merge expression data with TSS coordinates and sort them
expr <- data.frame(
gene_id = names(rpkm),
expr = rpkm
)
epidata <- addMetricAndArrangeGRanges(
tss,
expr,
gr_key = "gene_id",
order_key = "gene_id",
order_value = "expr"
)
# 4. Partition the genes into expression bins
epidata <- addBins(epidata, nbins = 5)
# 5. Extract DNA methylation and ChIP-seq signals around TSS
methstack <- normalizeToMatrix(
meth, epidata, value_column = "meth", extend = 5000, w = 250, mean_mode = "absolute"
)
h3k4me3stack <- normalizeToMatrix(
H3K4me3, epidata, value_column = "coverage", extend = 5000, w = 250, mean_mode = "coverage"
)
# 6. Assemble the data into a SummarizedExperiment object
epidata_se <- SummarizedExperiment(
rowRanges = epidata,
assays = list(DNAme = methstack, H3K4me3 = h3k4me3stack)
)
# 7. Plot the multi-track stacked profiles
plotEpistack(
epidata_se,
tints = c("dodgerblue", "orange"),
zlim = list(c(0, 1), c(0, 25)),
ylim = list(c(0, 1), c(0, 50)),
x_labels = c("-5kb", "TSS", "+5kb"),
legends = c("%mCpG", "Coverage"),
metric_col = "expr",
metric_title = "Gene expression",
metric_label = "log10(RPKM+1)",
metric_transfunc = function(x) log10(x + 1),
npix_height = 300
)
Note on inputs/outputs: Input is genomic coordinates, expression data, and epigenetic signal tracks, and output is a multi-track stacked profile plot.
When to Use
- Visualizing stacks of genomic tracks (e.g., ChIP-seq coverage, DNA methylation, ATAC-seq) centered at genomic regions of interest using
plotEpistack().
- Partitioning genomic regions into bins based on quantitative metrics using
addBins().
- Plotting individual panels of stacked profiles or average profiles using
plotStackProfile() and plotAverageProfile().
- Merging and sorting genomic ranges with associated quantitative metrics using
addMetricAndArrangeGRanges().
When NOT to Use
- For plotting non-centered, continuous genomic tracks across large chromosomal regions, use packages like
Gviz or Sushi because epistack is designed specifically for windowed, centered stack profiles.
- For general non-genomic heatmaps, use
ComplexHeatmap or pheatmap because epistack requires genomic coordinates (GRanges or RangedSummarizedExperiment).
Data Requirements
- Input format: A
RangedSummarizedExperiment object (e.g., stackepi) where assays contain matrices of genomic scores (e.g., coverage or methylation values) across windowed genomic bins.
- Row ranges:
GRanges object representing the centered genomic regions of interest (e.g., peaks, promoters, TSS).
- Metadata: A numeric column in
rowData (e.g., "exp", "mean_scores") to sort the features.
Key Parameters
- assay: Name of the assay in the
SummarizedExperiment to display as a heatmap.
- metric_col: Name of the column in
rowData containing the sorting metric.
- nbins: Number of bins to partition the genomic regions into when calling
addBins().
- ylim: Y-axis limits for the average profile plot.
- zlim: Limits for the heatmap intensity scale.
- x_labels: Character vector of labels for the X-axis (e.g.,
c("-5kb", "TSS", "+5kb")).
- tints: Color or vector of colors to tint the heatmaps.
- bin_palette: Palette function used to color-code the bins.
Best Practices
- Ensure all genomic tracks are aligned to the same genome assembly version before extracting coordinates and signals.
- Sort the
RangedSummarizedExperiment object by the metric of interest (e.g., using addMetricAndArrangeGRanges()) prior to plotting to ensure the stack profile displays a clear gradient.
- Use
addBins() to group genomic regions (e.g., high vs. low expression) to generate distinct average profiles in the lower panel of the epistack plot.
Common Pitfalls
- Mismatched row names or keys when merging expression data with GRanges: This will result in missing metric values. Fix by using
addMetricAndArrangeGRanges() with correct gr_key and order_key parameters.
- Inconsistent window sizes in the assay matrices: If the matrices in the assays have different numbers of columns,
plotEpistack() will fail. Fix by ensuring all matrices are generated with the same window parameters in normalizeToMatrix().
Alternatives
EnrichedHeatmap: For highly customizable enriched heatmaps with complex annotations.
ChIPseeker: For annotating and plotting ChIP-seq peaks relative to TSS.
Gviz: For plotting genomic tracks along genomic coordinates rather than centered stack profiles.
Citations
- Safia Saci, Guillaume Devailly. epistack: An R package to visualise stack profiles of epigenomic signals. 2021, .
References
1---2name: epistack3description: epistack4---56# epistack78## Workflows910### Standard Workflow1112Visualize ChIP-seq coverage signal centered around merged peak regions, sorted and binned by peak scores.1314```r15library(GenomicRanges)16library(SummarizedExperiment)17library(epistack)18library(rtracklayer)19library(EnrichedHeatmap)2021# 1. Load peak files22path_peaks <- c(23 peak1 = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/Rep1_peaks_ucsc_chr6.bed",24 peak2 = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/Rep2_peaks_ucsc_chr6.bed"25)26peaks <- lapply(path_peaks, import)2728# 2. Merge peaks across replicates29merged_peaks <- GenomicRanges::union(peaks[[1]], peaks[[2]])3031scores_rep1 <- double(length(merged_peaks))32scores_rep1[findOverlaps(peaks[[1]], merged_peaks, select = "first")] <- peaks[[1]]$score3334scores_rep2 <- double(length(merged_peaks))35scores_rep2[findOverlaps(peaks[[2]], merged_peaks, select = "first")] <- peaks[[2]]$score3637peak_type <- ifelse(38 scores_rep1 != 0 & scores_rep2 != 0, "Both", ifelse(39 scores_rep1 != 0, "Rep1 only", "Rep2 only"40 )41)4243mcols(merged_peaks) <- DataFrame(scores_rep1, scores_rep2, peak_type)44merged_peaks$mean_scores <- apply((mcols(merged_peaks)[, c("scores_rep1", "scores_rep2")]), 1, mean)45merged_peaks <- merged_peaks[order(merged_peaks$mean_scores, decreasing = TRUE), ]4647# 3. Load aligned reads48path_reads <- c(49 rep1 = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/H3K27ac_rep1_filtered_ucsc_chr6.bed",50 rep2 = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/H3K27ac_rep2_filtered_ucsc_chr6.bed",51 input = "https://raw.githubusercontent.com/Bioconductor/CSAMA2016/master/lab-5-chipseq/EpigeneticsCSAMA/inst/bedfiles/ES_input_filtered_ucsc_chr6.bed"52)53reads <- lapply(path_reads, import)5455# 4. Generate coverage matrices around peak centers56coverage_matrices <- lapply(57 reads,58 function(x) {59 normalizeToMatrix(60 x,61 resize(merged_peaks, width = 1, fix = "center"),62 extend = 5000, w = 250, 63 mean_mode = "coverage"64 )65 }66)67xlabs <- c("-5kb", "peak center", "+5kb")6869# 5. Construct a SummarizedExperiment object containing the data70merged_peaks_se <- SummarizedExperiment(71 rowRanges = merged_peaks,72 assays = coverage_matrices73)7475# 6. Assign peak types as bins and plot the stacked profiles76rowRanges(merged_peaks_se)$bin <- rowRanges(merged_peaks_se)$peak_type7778plotEpistack(79 merged_peaks_se,80 assays = c("rep1", "rep2", "input"),81 tints = c("dodgerblue", "firebrick1", "grey"), 82 titles = c("Rep1", "Rep2" , "Input"),83 x_labels = xlabs,84 zlim = c(0, 4), ylim = c(0, 4), 85 metric_col = "mean_scores", metric_title = "Peak score",86 metric_label = "score",87 bin_palette = colorRampPalette(c("darkorchid1", "dodgerblue", "firebrick1")),88 npix_height = 30089)90```91*Note on inputs/outputs*: Input is peak BED files and read alignment files, and output is a stacked genomic track visualization.9293### Promoter Epigenetics Expression9495Visualize DNA methylation and ChIP-seq coverage at gene promoters (TSS) sorted and binned by gene expression levels.9697```r98library(GenomicRanges)99library(SummarizedExperiment)100... [vignette text truncated]101# 1. Read the declared user input files from the working directory102load(103 system.file("extdata", "chr21_test_data.RData", package = "EnrichedHeatmap"),104 verbose = TRUE105)106107# 2. Extract TSS coordinates using GenomicRanges::promoters108tss <- promoters(genes, upstream = 0, downstream = 1)109tss$gene_id <- names(tss)110111# 3. Merge expression data with TSS coordinates and sort them112expr <- data.frame(113 gene_id = names(rpkm),114 expr = rpkm115)116epidata <- addMetricAndArrangeGRanges(117 tss,118 expr,119 gr_key = "gene_id",120 order_key = "gene_id",121 order_value = "expr"122)123124# 4. Partition the genes into expression bins125epidata <- addBins(epidata, nbins = 5)126127# 5. Extract DNA methylation and ChIP-seq signals around TSS128methstack <- normalizeToMatrix(129 meth, epidata, value_column = "meth", extend = 5000, w = 250, mean_mode = "absolute"130)131h3k4me3stack <- normalizeToMatrix(132 H3K4me3, epidata, value_column = "coverage", extend = 5000, w = 250, mean_mode = "coverage"133)134135# 6. Assemble the data into a SummarizedExperiment object136epidata_se <- SummarizedExperiment(137 rowRanges = epidata,138 assays = list(DNAme = methstack, H3K4me3 = h3k4me3stack)139)140141# 7. Plot the multi-track stacked profiles142plotEpistack(143 epidata_se,144 tints = c("dodgerblue", "orange"),145 zlim = list(c(0, 1), c(0, 25)),146 ylim = list(c(0, 1), c(0, 50)),147 x_labels = c("-5kb", "TSS", "+5kb"),148 legends = c("%mCpG", "Coverage"),149 metric_col = "expr",150 metric_title = "Gene expression",151 metric_label = "log10(RPKM+1)",152 metric_transfunc = function(x) log10(x + 1),153 npix_height = 300154)155```156*Note on inputs/outputs*: Input is genomic coordinates, expression data, and epigenetic signal tracks, and output is a multi-track stacked profile plot.157158## When to Use159- Visualizing stacks of genomic tracks (e.g., ChIP-seq coverage, DNA methylation, ATAC-seq) centered at genomic regions of interest using `plotEpistack()`.160- Partitioning genomic regions into bins based on quantitative metrics using `addBins()`.161- Plotting individual panels of stacked profiles or average profiles using `plotStackProfile()` and `plotAverageProfile()`.162- Merging and sorting genomic ranges with associated quantitative metrics using `addMetricAndArrangeGRanges()`.163164## When NOT to Use165- For plotting non-centered, continuous genomic tracks across large chromosomal regions, use packages like `Gviz` or `Sushi` because `epistack` is designed specifically for windowed, centered stack profiles.166- For general non-genomic heatmaps, use `ComplexHeatmap` or `pheatmap` because `epistack` requires genomic coordinates (`GRanges` or `RangedSummarizedExperiment`).167168## Data Requirements169- **Input format**: A `RangedSummarizedExperiment` object (e.g., `stackepi`) where assays contain matrices of genomic scores (e.g., coverage or methylation values) across windowed genomic bins.170- **Row ranges**: `GRanges` object representing the centered genomic regions of interest (e.g., peaks, promoters, TSS).171- **Metadata**: A numeric column in `rowData` (e.g., `"exp"`, `"mean_scores"`) to sort the features.172173## Key Parameters174- **assay**: Name of the assay in the `SummarizedExperiment` to display as a heatmap.175- **metric_col**: Name of the column in `rowData` containing the sorting metric.176- **nbins**: Number of bins to partition the genomic regions into when calling `addBins()`.177- **ylim**: Y-axis limits for the average profile plot.178- **zlim**: Limits for the heatmap intensity scale.179- **x_labels**: Character vector of labels for the X-axis (e.g., `c("-5kb", "TSS", "+5kb")`).180- **tints**: Color or vector of colors to tint the heatmaps.181- **bin_palette**: Palette function used to color-code the bins.182183## Best Practices184- Ensure all genomic tracks are aligned to the same genome assembly version before extracting coordinates and signals.185- Sort the `RangedSummarizedExperiment` object by the metric of interest (e.g., using `addMetricAndArrangeGRanges()`) prior to plotting to ensure the stack profile displays a clear gradient.186- Use `addBins()` to group genomic regions (e.g., high vs. low expression) to generate distinct average profiles in the lower panel of the epistack plot.187188## Common Pitfalls189- Mismatched row names or keys when merging expression data with GRanges: This will result in missing metric values. Fix by using `addMetricAndArrangeGRanges()` with correct `gr_key` and `order_key` parameters.190- Inconsistent window sizes in the assay matrices: If the matrices in the assays have different numbers of columns, `plotEpistack()` will fail. Fix by ensuring all matrices are generated with the same window parameters in `normalizeToMatrix()`.191192## Alternatives193- `EnrichedHeatmap`: For highly customizable enriched heatmaps with complex annotations.194- `ChIPseeker`: For annotating and plotting ChIP-seq peaks relative to TSS.195- `Gviz`: For plotting genomic tracks along genomic coordinates rather than centered stack profiles.196197## Citations198- Safia Saci, Guillaume Devailly. epistack: An R package to visualise stack profiles of epigenomic signals. 2021, <hal-03401251v2>.199200## References201- Homepage: https://bioconductor.org/packages/epistack202- Vignette: https://bioconductor.org/packages/release/bioc/vignettes/epistack/inst/doc/epistack.html