///|
/// GenomicRanges advanced operations demo.
///
/// Demonstrates GRanges construction, interval operations, set operations,
/// overlap detection, distance calculations, and advanced features like
/// precede, follow, and coverage.
///
/// Run: moon run examples/genomic_ranges_demo/main.mbt
fn main {
println("=== GenomicRanges Demo ===")
println("")
println("1. GRanges Construction")
let seqnames = ["chr1", "chr1", "chr2"]
let ranges = [(1, 10), (5, 15), (20, 30)]
let strands = [@bio.strand_plus(), @bio.strand_minus(), @bio.strand_star()]
let gr = @bio.granges(seqnames, ranges, strands)
let mut i = 0
while i < @bio.granges_length(gr) {
let strand_char = @bio.strand_to_char(gr.strands[i])
println(
" \{gr.seqnames[i]}:\{gr.starts[i]}-\{gr.ends[i]}(\{strand_char}) w=\{gr.widths[i]}",
)
i = i + 1
}
println("")
println("2. Interval Operations")
let shifted = @bio.granges_shift(gr, 5)
println("After shift(5):")
i = 0
while i < @bio.granges_length(shifted) {
let strand_char = @bio.strand_to_char(shifted.strands[i])
println(
" \{shifted.seqnames[i]}:\{shifted.starts[i]}-\{shifted.ends[i]}(\{strand_char})",
)
i = i + 1
}
let narrowed = @bio.granges_narrow(gr, 3, 8)
println("After narrow(3,8):")
i = 0
while i < @bio.granges_length(narrowed) {
let strand_char = @bio.strand_to_char(narrowed.strands[i])
println(
" \{narrowed.seqnames[i]}:\{narrowed.starts[i]}-\{narrowed.ends[i]}(\{strand_char})",
)
i = i + 1
}
let resized = @bio.granges_resize(gr, 15, "center")
println("After resize(15, center):")
i = 0
while i < @bio.granges_length(resized) {
let strand_char = @bio.strand_to_char(resized.strands[i])
println(
" \{resized.seqnames[i]}:\{resized.starts[i]}-\{resized.ends[i]}(\{strand_char})",
)
i = i + 1
}
let flanked = @bio.granges_flank(gr, 3, true, false)
println("After flank(3, start):")
i = 0
while i < @bio.granges_length(flanked) {
let strand_char = @bio.strand_to_char(flanked.strands[i])
println(
" \{flanked.seqnames[i]}:\{flanked.starts[i]}-\{flanked.ends[i]}(\{strand_char})",
)
i = i + 1
}
println("")
println("3. Reduce & Disjoin")
let reduced = @bio.granges_reduce(gr, 0)
println("After reduce:")
i = 0
while i < @bio.granges_length(reduced) {
let strand_char = @bio.strand_to_char(reduced.strands[i])
println(
" \{reduced.seqnames[i]}:\{reduced.starts[i]}-\{reduced.ends[i]}(\{strand_char})",
)
i = i + 1
}
let disjoined = @bio.granges_disjoin(gr)
println("After disjoin:")
i = 0
while i < @bio.granges_length(disjoined) {
let strand_char = @bio.strand_to_char(disjoined.strands[i])
println(
" \{disjoined.seqnames[i]}:\{disjoined.starts[i]}-\{disjoined.ends[i]}(\{strand_char})",
)
i = i + 1
}
println("")
println("4. Set Operations")
let gr1 = @bio.granges(["chr1", "chr1"], [(1, 10), (20, 30)], [
@bio.strand_plus(),
@bio.strand_minus(),
])
let gr2 = @bio.granges(["chr1"], [(5, 25)], [@bio.strand_star()])
let union_result = @bio.granges_union(gr1, gr2)
println("A union B:")
i = 0
while i < @bio.granges_length(union_result) {
let strand_char = @bio.strand_to_char(union_result.strands[i])
println(
" \{union_result.seqnames[i]}:\{union_result.starts[i]}-\{union_result.ends[i]}(\{strand_char})",
)
i = i + 1
}
let intersect_result = @bio.granges_intersect(gr1, gr2)
println("A intersect B:")
i = 0
while i < @bio.granges_length(intersect_result) {
let strand_char = @bio.strand_to_char(intersect_result.strands[i])
println(
" \{intersect_result.seqnames[i]}:\{intersect_result.starts[i]}-\{intersect_result.ends[i]}(\{strand_char})",
)
i = i + 1
}
let diff_result = @bio.granges_setdiff(gr1, gr2)
println("A setdiff B:")
i = 0
while i < @bio.granges_length(diff_result) {
let strand_char = @bio.strand_to_char(diff_result.strands[i])
println(
" \{diff_result.seqnames[i]}:\{diff_result.starts[i]}-\{diff_result.ends[i]}(\{strand_char})",
)
i = i + 1
}
println("")
println("5. Overlap Detection")
let query = @bio.granges(["chr1", "chr1"], [(1, 5), (3, 8)], [
@bio.strand_plus(),
@bio.strand_minus(),
])
let subject = @bio.granges(["chr1", "chr1"], [(2, 4), (6, 10)], [
@bio.strand_star(),
@bio.strand_plus(),
])
let counts = @bio.count_overlaps(query, subject)
println("count_overlaps: \{Repr(counts)}")
let overlaps = @bio.find_overlaps(query, subject)
println("find_overlaps: \{Repr(overlaps)}")
println("")
println("6. Distance & Nearest")
let gr_a = @bio.granges(["chr1", "chr1"], [(1, 10), (20, 30)], [
@bio.strand_plus(),
@bio.strand_minus(),
])
let gr_b = @bio.granges(["chr1", "chr1"], [(12, 15), (25, 28)], [
@bio.strand_star(),
@bio.strand_plus(),
])
let distances = @bio.granges_distance(gr_a, gr_b)
println("distances: \{Repr(distances)}")
let indices = @bio.nearest(gr_a, gr_b)
println("nearest indices: \{Repr(indices)}")
println("")
println("7. Precede & Follow")
let gr_query = @bio.granges(
["chr1", "chr1", "chr2"],
[(5, 10), (25, 30), (50, 55)],
[@bio.strand_plus(), @bio.strand_plus(), @bio.strand_plus()],
)
let gr_subject = @bio.granges(
["chr1", "chr1", "chr1", "chr2"],
[(1, 3), (15, 20), (35, 40), (60, 65)],
[
@bio.strand_plus(),
@bio.strand_plus(),
@bio.strand_plus(),
@bio.strand_plus(),
],
)
let precede_indices = @bio.precede(gr_query, gr_subject)
println("precede indices: \{Repr(precede_indices)}")
let follow_indices = @bio.follow(gr_query, gr_subject)
println("follow indices: \{Repr(follow_indices)}")
println("")
println("8. Coverage Calculation")
let gr_cov = @bio.granges(
["chr1", "chr1", "chr1"],
[(5, 10), (8, 15), (20, 25)],
[@bio.strand_plus(), @bio.strand_plus(), @bio.strand_plus()],
)
let seqlengths : Map[String, Int32] = Map([], capacity=1)
seqlengths["chr1"] = 30
let coverage = @bio.coverage_granges(gr_cov, seqlengths)
println("Coverage for chr1 (length 30):")
let cov_array = coverage["chr1"]
println(" Coverage array (chr1): \{Repr(cov_array)}")
println("")
println("9. Distance to Nearest")
let gr_dn = @bio.granges(
["chr1", "chr1", "chr1"],
[(1, 5), (15, 20), (30, 35)],
[@bio.strand_plus(), @bio.strand_plus(), @bio.strand_plus()],
)
let distances_to_nearest = @bio.distance_to_nearest(gr_dn)
println("Distance to nearest for each range:")
i = 0
while i < gr_dn.starts.length() {
println(
" Range \{i} (\{gr_dn.starts[i]}-\{gr_dn.ends[i]}): distance = \{distances_to_nearest[i]}",
)
i = i + 1
}
}