///|
fn chain_coordinate_path_text(
coordinates : Array[@src.AlignChainCoordinate],
) -> String {
let output = StringBuilder()
for index = 0; index < coordinates.length(); index = index + 1 {
if index > 0 {
output.write_string(" -> ")
}
output.write_string(
"(" +
coordinates[index].target.to_string() +
", " +
coordinates[index].query.to_string() +
")",
)
}
output.to_string()
}
///|
fn main {
println("=== Biopython Bio.Align.chain Demo ===")
let alignments = @src.align_chain_parse_all(@src.align_chain_example_text()) catch {
AlignChainError(message) => abort("Chain parsing failed: " + message)
}
let alignment = alignments[0]
println("\n1. Parse consecutive UCSC Chain records")
println(" records: " + alignments.length().to_string())
for record in alignments {
println(" " + record.summary())
}
println("\n2. Inspect absolute coordinates and canonical blocks")
println(" operations: " + alignment.operation_path())
println(" coordinates: " + chain_coordinate_path_text(alignment.coordinates))
let blocks = alignment.blocks() catch {
AlignChainError(message) =>
abort("Chain block reconstruction failed: " + message)
}
for index = 0; index < blocks.length(); index = index + 1 {
let block = blocks[index]
println(
" block " +
(index + 1).to_string() +
": size=" +
block.size.to_string() +
", dt=" +
block.target_gap.to_string() +
", dq=" +
block.query_gap.to_string(),
)
}
println("\n3. Calculate coordinate-only counts")
let counts = alignment.counts()
println(
" aligned=" +
counts.aligned.to_string() +
", target-gap bases=" +
counts.target_gap_bases.to_string() +
", query-gap bases=" +
counts.query_gap_bases.to_string(),
)
println(
" alignment length=" +
alignment.alignment_length().to_string() +
", aligned blocks=" +
counts.aligned_blocks.to_string(),
)
println("\n4. Map residues and intervals in both directions")
println(
" target 42530895 -> query " +
alignment.map_target_position(42530895).unwrap_or(-1).to_string(),
)
println(
" query 180 -> target " +
alignment.map_query_position(180).unwrap_or(-1).to_string(),
)
let pieces = alignment.map_target_range(42530950, 42532030) catch {
AlignChainError(message) => abort("Chain range mapping failed: " + message)
}
for piece in pieces {
println(
" target[" +
piece.target_start.to_string() +
", " +
piece.target_end.to_string() +
") -> query[" +
piece.query_start.to_string() +
", " +
piece.query_end.to_string() +
")",
)
}
println("\n5. Invert and round-trip canonical Chain output")
let inverted = alignment.invert() catch {
AlignChainError(message) => abort("Chain inversion failed: " + message)
}
println(" inverted: " + inverted.summary())
let canonical = @src.align_chain_write_all(alignments) catch {
AlignChainError(message) => abort("Chain serialization failed: " + message)
}
let round_trip = @src.align_chain_parse_all(canonical) catch {
AlignChainError(message) =>
abort("Chain round-trip parsing failed: " + message)
}
println(" output bytes: " + canonical.length().to_string())
println(" round-trip preserved: " + (round_trip == alignments).to_string())
}