///|
/// PDB structure parsing example.
///
/// Demonstrates parsing PDB files, accessing atoms/residues/chains,
/// and computing structural properties.
///
/// Run: moon run examples/pdb_demo/main.mbt
fn min_int(a : Int32, b : Int32) -> Int32 {
if a < b {
a
} else {
b
}
}
///|
fn main {
// Minimal PDB content (2 residues, 8 atoms)
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" +
"TER 9 ALA A 1\n" +
"END\n"
// === Parse PDB ===
let structure = @bio.parse_pdb(pdb_content)
println("=== PDB Structure ===")
println(" ID: \{structure.get_id()}")
println(" Models: \{structure.get_num_models()}")
println(" Chains: \{structure.get_num_chains()}")
println(" Residues: \{structure.get_num_residues()}")
println(" Atoms: \{structure.get_num_atoms()}")
// === Access chains ===
let chains = structure.get_chains()
println("\n=== Chains ===")
for i = 0; i < chains.length(); i = i + 1 {
let c = chains[i]
println(
" Chain \{c.get_id()}: \{c.get_num_residues()} residues, \{c.get_atoms().length()} atoms",
)
}
// === Access residues ===
let residues = structure.get_residues()
println("\n=== Residues ===")
for i = 0; i < residues.length(); i = i + 1 {
let r = residues[i]
println(
" [\{i}] \{r.resname} \{r.chainid}\{r.resseq}: \{r.get_num_atoms()} atoms",
)
let is_het = r.is_het()
println(" HETATM: \{is_het}")
// Get alpha carbon
let ca = r.get_ca()
match ca {
Some(atom) => {
let coord = atom.get_coord()
println(" CA: (\{coord.x}, \{coord.y}, \{coord.z})")
}
None => println(" CA: not found")
}
// Center of mass
let com = r.center_of_mass()
match com {
Some(v) => println(" COM: (\{v.x}, \{v.y}, \{v.z})")
None => println(" COM: N/A")
}
}
// === Atom distance ===
let atoms = structure.get_atoms()
if atoms.length() >= 2 {
let d = atoms[0].distance(atoms[1])
println("\n=== Atom Distance ===")
println(" \{atoms[0].name} -- \{atoms[1].name}: \{d}")
}
// === Write PDB ===
let pdb_out = @bio.write_pdb(structure)
println("\n=== Written PDB (first 5 lines) ===")
let lines = pdb_out.split("\n").to_array()
let limit = min_int(lines.length(), 5)
for i = 0; i < limit; i = i + 1 {
println(" \{lines[i].to_owned()}")
}
}