## Aggregation: a coverage track with a known answer -----------------------
## Two 200 bp windows over a signal that steps sharply inside the first.
##
## window 1 [ 1 .. 200] window 2 [401 .. 600]
## depth [ 1 .. 190] = 5
## [191 .. 400] = 200
## [401 .. 450] = 60
library(GenomicRanges)
win <- GRanges("chr1", IRanges(start = c(1, 401), width = 200),
Tm = c(70, 72))
cov <- GRanges("chr1", IRanges(start = c(1, 191, 401),
end = c(190, 400, 450)),
cov = c(5, 200, 60))
## Window 1 truly averages (5 * 190 + 200 * 10) / 200 = 14.75.
integrate_granges(win, cov, strategy = "overlap")$cov
## 102.5 60 the 10 bp feature counts as much as the 190 bp one
integrate_granges(win, cov, strategy = "overlap",
weight = "overlap")$cov
## 14.75 60 overlap-weighted mean recovers the true depth
integrate_granges(win, cov, strategy = "overlap", min_overlap = 20L)$cov
## 5 60 the threshold discards the short feature; bias reverses
## Window 2 is only a quarter covered. Weighting cannot show that, because
## it normalises by the covered bases; the coverage column can.
res <- integrate_granges(win, cov, strategy = "overlap",
weight = "overlap", report_coverage = TRUE)
res$cov # 14.75 60
res$covered_frac # 1.00 0.25
res$cov * res$covered_frac # 14.75 15 mean over the whole window
if (FALSE) {
library(GenomicRanges)
# -- Sample data ----------------------------------------------------------
set.seed(42)
gr_tm <- GRanges(
seqnames = c(rep("chr1", 60), rep("chr2", 30)),
ranges = IRanges(
start = c(sort(sample(1:249e6, 60)),
sort(sample(1:243e6, 30))),
width = sample(50:200, 90, replace = TRUE)
),
Tm = runif(90, 55, 85),
GC = runif(90, 30, 70)
)
gr_features <- GRanges(
seqnames = c(rep("chr1", 40), rep("chr2", 20)),
ranges = IRanges(
start = c(sort(sample(1:249e6, 40)),
sort(sample(1:243e6, 20))),
width = sample(500:5000, 60, replace = TRUE)
),
score = runif(60, 0, 100),
peak_type = sample(c("narrow", "broad"), 60, replace = TRUE),
signal = rnorm(60, 5, 2)
)
# Strategy 1: overlap - annotate Tm ranges with overlapping peak features
res_overlap <- integrate_granges(gr_tm, gr_features,
strategy = "overlap")
# Strategy 2: nearest - every Tm range gets its closest peak + distance
res_nearest <- integrate_granges(gr_tm, gr_features,
strategy = "nearest")
head(res_nearest$distance_to_feature)
# Strategy 3: window - 5 kb window around each probe
res_window <- integrate_granges(gr_tm, gr_features,
strategy = "window", window_size = 5000)
# Strategy 4: bin - 500 kb genome bins with mean Tm and aggregated signal
res_bin <- integrate_granges(gr_tm, gr_features,
strategy = "bin", bin_size = 5e5)
as.data.frame(res_bin) |> head()
# Use a subset of feature columns and add a prefix
integrate_granges(gr_tm, gr_features,
strategy = "overlap",
feature_cols = c("score", "peak_type"),
prefix = "chip_")
}
Run the code above in your browser using DataLab