///|
/// FragmentMapper demo example.
///
/// Demonstrates protein structure fragment mapping and classification
/// using the Bio.PDB.FragmentMapper module.
///
/// Run: moon run examples/fragment_mapper_demo/main.mbt
fn main {
// === 1. Classify DSSP secondary structure ===
println("=== 1. DSSP Secondary Structure Classification ===")
let ss_string = "HHHHHHLLLLLLEEEEELLLTTSSCC"
let classified = @bio.fm_classify_secondary_structure(ss_string)
println(" Input: " + ss_string)
let mut class_str = ""
for ft in classified {
class_str = class_str + ft.to_char()
}
println(" Output: " + class_str)
// Count types
let mut helix_count = 0
let mut sheet_count = 0
let mut loop_count = 0
let mut turn_count = 0
for ft in classified {
if ft == @bio.ft_helix() {
helix_count = helix_count + 1
} else if ft == @bio.ft_sheet() {
sheet_count = sheet_count + 1
} else if ft == @bio.ft_loop() {
loop_count = loop_count + 1
} else if ft == @bio.ft_turn() {
turn_count = turn_count + 1
}
}
println(
" Helix: " +
helix_count.to_string() +
", Sheet: " +
sheet_count.to_string() +
", Loop: " +
loop_count.to_string() +
", Turn: " +
turn_count.to_string(),
)
// === 2. Assign fragments from sequence + SS ===
println("\n=== 2. Fragment Assignment ===")
let sequence = "MVLSPADKTNVKAAWGKVGAHAGEYGAEALERMFLSFPTTKTYFPHFDLSHGSAQVKGHGKKVADALTNAVAHVDDMPNALSALSDLHAHKLR"
let ss = "HHHHHHHHHHHHHHHCCCCCHHHHHHHHHHHHCCCEEEEEEEECCCHHHHHHHHHHHHHHHHHHCCCCCCEEEEEECCCCCHHHHHH"
let result = @bio.fm_assign_fragments(sequence, ss)
println(" Sequence length: " + result.sequence_length.to_string())
println(" Number of fragments: " + result.num_fragments().to_string())
println(" Fragments:")
for frag in result.fragments {
let (start, end) = @bio.fm_fragment_boundaries(frag)
let frag_seq = @bio.fm_fragment_sequence(frag)
let frag_type = @bio.fm_fragment_type(frag)
println(
" " +
frag.id +
": type=" +
frag_type.to_string() +
", residues " +
start.to_string() +
"-" +
end.to_string() +
", length=" +
frag.length().to_string() +
", seq=" +
frag_seq,
)
}
// === 3. Merge adjacent fragments ===
println("\n=== 3. Merge Adjacent Fragments ===")
let merged = @bio.fm_merge_fragments(result.fragments)
println(
" Before merge: " + result.num_fragments().to_string() + " fragments",
)
println(" After merge: " + merged.length().to_string() + " fragments")
// === 4. Filter by length ===
println("\n=== 4. Filter by Length (min 5 residues) ===")
let filtered = @bio.fm_filter_by_length(merged, 5)
println(
" After filtering (>= 5 residues): " +
filtered.length().to_string() +
" fragments",
)
for frag in filtered {
println(
" " +
frag.id +
": type=" +
frag.fragment_type.to_string() +
", length=" +
frag.length().to_string(),
)
}
// === 5. Get fragment by ID ===
println("\n=== 5. Get Fragment by ID ===")
match @bio.fm_get_fragment(result, "fragment_0") {
Some(frag) =>
println(
" Found fragment_0: residues " +
frag.start_residue.to_string() +
"-" +
frag.end_residue.to_string() +
", type=" +
frag.fragment_type.to_string(),
)
None => println(" fragment_0 not found")
}
// === 6. Parse PDB content ===
println("\n=== 6. Parse PDB Content ===")
let pdb_content = "ATOM 1 N ALA A 1 11.104 6.134 10.298 1.00 20.00 N\n" +
"ATOM 2 CA ALA A 1 11.639 6.168 10.426 1.00 20.00 C\n" +
"ATOM 3 C ALA A 1 12.221 6.201 10.542 1.00 20.00 C\n" +
"ATOM 4 O ALA A 1 12.803 6.234 10.658 1.00 20.00 O\n" +
"ATOM 5 N GLY A 2 13.385 6.267 10.774 1.00 20.00 N\n" +
"ATOM 6 CA GLY A 2 13.968 6.300 10.891 1.00 20.00 C\n" +
"ATOM 7 C GLY A 2 14.549 6.333 11.007 1.00 20.00 C\n" +
"ATOM 8 O GLY A 2 15.131 6.366 11.123 1.00 20.00 O\n" +
"ATOM 9 N SER A 3 15.712 6.399 11.239 1.00 20.00 N\n" +
"ATOM 10 CA SER A 3 16.294 6.432 11.355 1.00 20.00 C\n" +
"END\n"
let pdb_result = @bio.fm_parse_fragments(pdb_content)
println(" Sequence: " + pdb_result.protein_sequence)
println(" Sequence length: " + pdb_result.sequence_length.to_string())
println(" Fragments: " + pdb_result.num_fragments().to_string())
for frag in pdb_result.fragments {
println(
" " +
frag.id +
": chain=" +
frag.chain_id +
", residues " +
frag.start_residue.to_string() +
"-" +
frag.end_residue.to_string() +
", atom_count=" +
frag.residues.length().to_string(),
)
}
// === 7. Coverage analysis ===
println("\n=== 7. Coverage Analysis ===")
let cov = @bio.fm_coverage(result)
let mut covered = 0
let mut total = 0
for _, val in cov {
if val > 0.0 {
covered = covered + 1
}
total = total + 1
}
println(" Total positions: " + total.to_string())
println(" Covered positions: " + covered.to_string())
if total > 0 {
let pct = covered.to_double() / total.to_double() * 100.0
println(" Coverage: " + pct.to_string() + "%")
}
println("\n=== Done ===")
}