.make_bed() builds a windowed BED around a focal point but never clamps the lower bound to 0, so features close to the start of a chromosome get negative coordinates.
R/utils_data.R:43:
if (!for_profile) {
if (tss == "center") {
bed[, focal_point := as.integer(apply(bed[,2:3], 1, mean))]
bed[, bed_start := focal_point-up]
bed[, bed_end := focal_point+down]
} else if (tss == "start") {
bed[, bed_start := start-up]
bed[, bed_end := start+down]
} else {
bed[, bed_start := end-up]
bed[, bed_end := end+down]
}
bed <- bed[, .(chr, bed_start, bed_end)]
data.table::setkey(x = bed, chr, bed_start, bed_end)
}
With the default up = 2500, any focal point < 2500 bp from the chromosome start yields bed_start < 0. The file is then written out verbatim by data.table::fwrite(...). Negative starts are invalid BED and downstream tools (bwtool / bedtools, which the header comment references) will error or silently skip those rows, so a handful of near-telomeric/near-start features quietly drop out of profile/aggregation plots.
Two smaller things in the same function worth folding in:
as.integer(apply(bed[,2:3], 1, mean)) truncates toward zero rather than rounding, so the center is off by up to 1 bp versus round().
- The
for_profile = TRUE path skips the bed[, .(chr, bed_start, bed_end)] projection entirely and writes whatever extra columns bed still carries, even though the comment on the first line states "bwtool tool requires only three columns."
Suggested fix: clamp with pmax(0L, ...) on the start (BED is 0-based, so 0 is the floor), e.g. bed[, bed_start := pmax(0L, focal_point - up)], and mirror it in the start/end branches.
.make_bed()builds a windowed BED around a focal point but never clamps the lower bound to 0, so features close to the start of a chromosome get negative coordinates.R/utils_data.R:43:With the default
up = 2500, any focal point < 2500 bp from the chromosome start yieldsbed_start < 0. The file is then written out verbatim bydata.table::fwrite(...). Negative starts are invalid BED and downstream tools (bwtool / bedtools, which the header comment references) will error or silently skip those rows, so a handful of near-telomeric/near-start features quietly drop out of profile/aggregation plots.Two smaller things in the same function worth folding in:
as.integer(apply(bed[,2:3], 1, mean))truncates toward zero rather than rounding, so the center is off by up to 1 bp versusround().for_profile = TRUEpath skips thebed[, .(chr, bed_start, bed_end)]projection entirely and writes whatever extra columnsbedstill carries, even though the comment on the first line states "bwtool tool requires only three columns."Suggested fix: clamp with
pmax(0L, ...)on the start (BED is 0-based, so 0 is the floor), e.g.bed[, bed_start := pmax(0L, focal_point - up)], and mirror it in thestart/endbranches.