///|
fn nexus_integer_array_text(values : Array[Int32]) -> String {
let output = StringBuilder()
output.write_char('[')
for index = 0; index < values.length(); index = index + 1 {
if index > 0 {
output.write_string(", ")
}
output.write_string(values[index].to_string())
}
output.write_char(']')
output.to_string()
}
///|
fn main {
println("=== Biopython Bio.Align.nexus Demo ===")
let alignment = @src.align_nexus_parse(@src.align_nexus_example_text()) catch {
AlignNexusError(message) => abort("NEXUS parsing failed: " + message)
}
println("\n1. Parse an interleaved DATA matrix")
println(" " + alignment.summary())
println(
" datatype: " +
alignment.metadata.data_type.code() +
" (" +
alignment.metadata.data_type.molecule_type() +
")",
)
let match_character = match alignment.metadata.match_character {
Some(value) => value
None => "none"
}
println(
" missing=" +
alignment.metadata.missing_character +
", gap=" +
alignment.metadata.gap_character +
", matchchar=" +
match_character,
)
for sequence in alignment.sequences {
println(
" " +
sequence.id +
": " +
sequence.aligned_sequence +
" -> " +
sequence.sequence,
)
}
println("\n2. Inspect coordinate paths and residue mapping")
let path = alignment.coordinate_path()
for row = 0; row < alignment.num_sequences(); row = row + 1 {
println(
" " +
alignment.sequences[row].id +
": " +
nexus_integer_array_text(path[row]),
)
}
println(
" reference residue 5 -> query one residue " +
alignment.map_position(0, 1, 5).unwrap_or(-1).to_string(),
)
println(
" reference residue 7 -> query one residue " +
alignment.map_position(0, 1, 7).unwrap_or(-1).to_string() +
" (-1 denotes a gap)",
)
println("\n3. Calculate all-pairs statistics")
let counts = alignment.counts()
println(
" pairs=" +
counts.pairs.to_string() +
", aligned=" +
counts.aligned.to_string() +
", identities=" +
counts.identities.to_string() +
", gaps=" +
counts.gap_columns.to_string(),
)
let consensus = alignment.consensus(minimum_fraction=0.67) catch {
AlignNexusError(message) => abort("consensus failed: " + message)
}
println(" consensus: " + consensus)
println(
" occupancy at source gap column: " + alignment.occupancy()[4].to_string(),
)
println("\n4. Write canonical interleaved NEXUS and parse it again")
let canonical = @src.align_nexus_write(
alignment,
interleave=Some(true),
block_width=4,
) catch {
AlignNexusError(message) => abort("NEXUS serialization failed: " + message)
}
let round_trip = @src.align_nexus_parse(canonical) catch {
AlignNexusError(message) => abort("round-trip parsing failed: " + message)
}
println(" output bytes: " + canonical.length().to_string())
println(
" quoted IDs and rows preserved: " +
(round_trip.sequences == alignment.sequences).to_string(),
)
println(
" coordinate path preserved: " +
(round_trip.coordinate_path() == alignment.coordinate_path()).to_string(),
)
println("\n5. Remove all-gap source columns during construction")
let compact = @src.align_nexus_from_aligned(
["reference", "query"],
["A-C--GT", "ATC--GT"],
@src.AlignNexusDna,
) catch {
AlignNexusError(message) =>
abort("alignment construction failed: " + message)
}
println(
" source columns=" +
compact.source_alignment_length().to_string() +
", alignment columns=" +
compact.alignment_length().to_string() +
", removed=" +
compact.metadata.removed_all_gap_columns.to_string(),
)
println(" compact reference: " + compact.sequences[0].aligned_sequence)
}