///|
/// NeighborSearch example: KD-tree based spatial search for protein structures.
///
/// Run: moon run examples/neighbor_search_demo/main.mbt
fn main {
println("=== Neighbor Search Demo (KD-Tree) ===")
println("")
// === Create sample atoms ===
println("--- 1. Create Sample Atoms ---")
let atoms = [
@bio.Atom::new(
name="CA",
coord=@bio.Vector3::new(0.0, 0.0, 0.0),
resname="ALA",
),
@bio.Atom::new(
name="CB",
coord=@bio.Vector3::new(1.5, 0.0, 0.0),
resname="ALA",
),
@bio.Atom::new(
name="CG",
coord=@bio.Vector3::new(2.5, 0.5, 0.0),
resname="VAL",
),
@bio.Atom::new(
name="CA",
coord=@bio.Vector3::new(5.0, 0.0, 0.0),
resname="GLY",
),
@bio.Atom::new(
name="CB",
coord=@bio.Vector3::new(6.0, 0.5, 0.0),
resname="GLY",
),
@bio.Atom::new(
name="CA",
coord=@bio.Vector3::new(10.0, 0.0, 0.0),
resname="SER",
),
@bio.Atom::new(
name="OG",
coord=@bio.Vector3::new(10.5, 1.0, 0.0),
resname="SER",
),
@bio.Atom::new(
name="CA",
coord=@bio.Vector3::new(0.0, 5.0, 0.0),
resname="ASP",
),
@bio.Atom::new(
name="CA",
coord=@bio.Vector3::new(0.0, 0.0, 5.0),
resname="LYS",
),
]
println(" Created \{atoms.length()} atoms")
for i = 0; i < atoms.length(); i = i + 1 {
let a = atoms[i]
let c = a.coord
println(
" Atom \{i}: name=\{a.name}, res=\{a.resname}, pos=(\{c.x}, \{c.y}, \{c.z})",
)
}
println("")
// === Build KD-tree ===
println("--- 2. Build Neighbor Search (KD-tree) ---")
let ns = @bio.NeighborSearch::new(atoms)
println(" KD-tree built with \{ns.size()} atoms")
println("")
// === Radius search ===
println("--- 3. Radius Search ---")
let center1 = @bio.Vector3::new(0.0, 0.0, 0.0)
let radius = 3.0
let neighbors1 = ns.search(center1, radius)
println(" Center: (\{center1.x}, \{center1.y}, \{center1.z})")
println(" Radius: \{radius} A")
println(" Found \{neighbors1.length()} neighbors:")
for a in neighbors1 {
let d = a.coord.distance(center1)
println(" - \{a.name} (\{a.resname}): \{d} A")
}
println("")
// === Another radius search ===
let center2 = @bio.Vector3::new(5.5, 0.0, 0.0)
let radius2 = 2.0
let neighbors2 = ns.search(center2, radius2)
println(" Center: (\{center2.x}, \{center2.y}, \{center2.z})")
println(" Radius: \{radius2} A")
println(" Found \{neighbors2.length()} neighbors")
println("")
// === Nearest neighbor ===
println("--- 4. Nearest Neighbor Search ---")
let query = @bio.Vector3::new(3.0, 0.0, 0.0)
let nearest = ns.nearest(query)
println(" Query point: (\{query.x}, \{query.y}, \{query.z})")
match nearest {
Some(a) => {
let d = a.coord.distance(query)
println(" Nearest: \{a.name} (\{a.resname}), distance: \{d} A")
}
None => println(" No atoms found")
}
println("")
// === Atom-based radius search ===
println("--- 5. Atom-Based Radius Search ---")
let atom0 = atoms[0]
let atom_radius = 4.0
let atom_neighbors = ns.search_atom(atom0, atom_radius)
println(" Query atom: \{atom0.name} (\{atom0.resname})")
println(" Radius: \{atom_radius} A")
println(" Found \{atom_neighbors.length()} neighboring atoms")
println("")
// === Search all pairs within distance ===
println("--- 6. All Atom Pairs Within Distance ---")
let pair_radius = 2.5
let pairs = ns.search_all(pair_radius)
println(" Distance cutoff: \{pair_radius} A")
println(" Found \{pairs.length()} atom pairs:")
for i = 0; i < pairs.length(); i = i + 1 {
let (a, b) = pairs[i]
let d = a.distance(b)
println(" \{i+1}. \{a.name}-\{b.name}: \{d} A")
}
println("")
println("=== Demo Complete ===")
}