///|
fn coordinate_text(values : Array[Int32]) -> String {
let output = StringBuilder()
output.write_char('[')
for index in 0.. 0 {
output.write_string(", ")
}
output.write_string(values[index].to_string())
}
output.write_char(']')
output.to_string()
}
///|
fn main {
println("=== Biopython Bio.Align.emboss Demo ===")
let document = @src.align_emboss_parse(@src.align_emboss_example_text()) catch {
AlignEmbossError(message) => abort("EMBOSS parsing failed: " + message)
}
let alignment = document.alignments[0]
println("\n1. Parse report and alignment metadata")
println(" " + document.summary())
println(" " + alignment.summary())
println(
" matrix=" +
alignment.annotations.matrix +
", score=" +
alignment.annotations.score.unwrap_or(0.0).to_string(),
)
println("\n2. Preserve local coordinates and consensus")
for sequence in alignment.sequences {
println(
" " +
sequence.id +
": boundaries [" +
sequence.start.to_string() +
", " +
sequence.end.to_string() +
"), residues=" +
sequence.sequence.length().to_string(),
)
}
println(" consensus: " + alignment.consensus)
println("\n3. Map absolute residue coordinates")
match alignment.map_position(0, 1, 87) {
Some(position) =>
println(
" reference residue 87 maps to query residue " +
position.to_string() +
" (zero-based absolute coordinates)",
)
None => println(" reference residue 87 maps to a query gap")
}
let path = alignment.coordinate_path()
println(" reference path: " + coordinate_text(path[0]))
println(" query path: " + coordinate_text(path[1]))
println("\n4. Calculate pairwise EMBOSS statistics")
let counts = alignment.pair_counts(0, 1) catch {
AlignEmbossError(message) => abort("pair counting failed: " + message)
}
println(
" identities/mismatches/gaps: " +
counts.identities.to_string() +
"/" +
counts.mismatches.to_string() +
"/" +
(counts.insertions + counts.deletions).to_string(),
)
println(
" positives=" +
counts.positives.to_string() +
", identity=" +
counts.identity().to_string(),
)
println("\n5. Handle reverse-strand boundaries")
let annotations = @src.AlignEmbossAnnotations::create(4) catch {
AlignEmbossError(message) =>
abort("annotation construction failed: " + message)
}
let forward = @src.AlignEmbossSequence::create("target", "ACGT", 2, 6) catch {
AlignEmbossError(message) =>
abort("forward row construction failed: " + message)
}
let reverse = @src.AlignEmbossSequence::create("reverse", "ACGT", 20, 16) catch {
AlignEmbossError(message) =>
abort("reverse row construction failed: " + message)
}
let reverse_alignment = @src.AlignEmbossAlignment::create(
[forward, reverse],
annotations,
consensus="||||",
) catch {
AlignEmbossError(message) =>
abort("reverse alignment construction failed: " + message)
}
println(
" reverse columns 0..3 map to residues " +
reverse_alignment
.column_to_sequence_position(1, 0)
.unwrap_or(-1)
.to_string() +
".." +
reverse_alignment
.column_to_sequence_position(1, 3)
.unwrap_or(-1)
.to_string(),
)
println("\n6. Wrapped canonical serialization")
let serialized = @src.align_emboss_write(document, line_width=7) catch {
AlignEmbossError(message) => abort("EMBOSS writing failed: " + message)
}
let reparsed = @src.align_emboss_parse(serialized) catch {
AlignEmbossError(message) =>
abort("serialized EMBOSS parsing failed: " + message)
}
println(" serialized bytes: " + serialized.length().to_string())
println(
" round trip preserved report: " + (document == reparsed).to_string(),
)
println("\n=== Demo Complete ===")
}