#[cfg(test)]
#[allow(clippy::module_inception)]
mod tests {
use crate::ff::typifier::mmff::MMFFTypifier;
use molrs::system::molgraph::{Atom, PropValue};
use molrs::{AtomId, Atomistic};
fn atom(sym: &str) -> Atom {
let mut a = Atom::new();
a.set("element", sym);
a
}
fn atom_xyz(sym: &str, x: f64, y: f64, z: f64) -> Atom {
Atom::xyz(sym, x, y, z)
}
fn bond_order(mol: &mut Atomistic, a: AtomId, b: AtomId, order: f64) {
if let Ok(bid) = mol.add_bond(a, b) {
let _ = mol.set_bond_prop(bid, "order", PropValue::F64(order));
}
}
fn test_typifier() -> MMFFTypifier {
MMFFTypifier::mmff94().expect("load MMFF94")
}
#[test]
fn test_load_mmff_params() {
let typifier = test_typifier();
let params = typifier.params();
assert!(
params.props.len() > 80,
"expected >80 atom props, got {}",
params.props.len()
);
let p1 = params.get_prop(1).expect("type 1 should exist");
assert_eq!(p1.atno, 6);
assert_eq!(p1.crd, 4);
assert_eq!(p1.val, 4);
}
#[test]
fn test_ethane_atom_types() {
let typifier = test_typifier();
let mut mol = Atomistic::new();
let c1 = mol.add_atom(atom("C"));
let c2 = mol.add_atom(atom("C"));
bond_order(&mut mol, c1, c2, 1.0);
for _ in 0..3 {
let h = mol.add_atom(atom("H"));
bond_order(&mut mol, c1, h, 1.0);
}
for _ in 0..3 {
let h = mol.add_atom(atom("H"));
bond_order(&mut mol, c2, h, 1.0);
}
let frame = typifier.typify(&mol).expect("typify ethane").to_frame();
let types = frame
.get("atoms")
.unwrap()
.get_string("type")
.expect("atoms.type column");
assert_eq!(types[0], "1", "C1 should be MMFF type 1 (CR)");
assert_eq!(types[1], "1", "C2 should be MMFF type 1 (CR)");
for (i, t) in types.iter().enumerate().skip(2) {
assert_eq!(t, "5", "H at row {i} should be type 5 (HC)");
}
}
#[test]
fn test_benzene_atom_types() {
let typifier = test_typifier();
let mut mol = Atomistic::new();
let cs: Vec<AtomId> = (0..6).map(|_| mol.add_atom(atom("C"))).collect();
for i in 0..6 {
bond_order(&mut mol, cs[i], cs[(i + 1) % 6], 1.5);
}
for &c in &cs {
let h = mol.add_atom(atom("H"));
bond_order(&mut mol, c, h, 1.0);
}
let frame = typifier.typify(&mol).expect("typify benzene").to_frame();
let types = frame
.get("atoms")
.unwrap()
.get_string("type")
.expect("atoms.type column");
for (i, t) in types.iter().take(6).enumerate() {
assert_eq!(t, "2", "benzene C at row {i}: front-end types it sp2 (2)");
}
}
#[test]
fn test_bond_type_normal() {
let typifier = test_typifier();
assert_eq!(typifier.typify_bond(1, 1, 1.0), 0);
}
#[test]
fn test_bond_type_aromatic() {
let typifier = test_typifier();
assert_eq!(typifier.typify_bond(37, 37, 1.5), 1);
}
#[test]
fn test_angle_type_normal() {
let typifier = test_typifier();
assert_eq!(typifier.typify_angle(0, 0), 0);
}
#[test]
fn test_angle_type_one_delocalized() {
let typifier = test_typifier();
assert_eq!(typifier.typify_angle(1, 0), 1);
assert_eq!(typifier.typify_angle(0, 1), 1);
}
#[test]
fn test_angle_type_both_delocalized() {
let typifier = test_typifier();
assert_eq!(typifier.typify_angle(1, 1), 2);
}
#[test]
fn test_torsion_type_normal() {
let typifier = test_typifier();
assert_eq!(typifier.typify_dihedral(0, 0, 0), 0);
}
#[test]
fn test_torsion_type_central_delocalized() {
let typifier = test_typifier();
assert_eq!(typifier.typify_dihedral(0, 1, 0), 1);
}
#[test]
fn test_build_ethane_frame() {
let typifier = test_typifier();
let mut mol = Atomistic::new();
let c1 = mol.add_atom(atom_xyz("C", 0.0, 0.0, 0.0));
let c2 = mol.add_atom(atom_xyz("C", 1.54, 0.0, 0.0));
bond_order(&mut mol, c1, c2, 1.0);
let h_positions = [
(c1, [0.0, 1.0, 0.0]),
(c1, [0.0, -0.5, 0.87]),
(c1, [0.0, -0.5, -0.87]),
(c2, [1.54, 1.0, 0.0]),
(c2, [1.54, -0.5, 0.87]),
(c2, [1.54, -0.5, -0.87]),
];
for (c, [hx, hy, hz]) in h_positions {
let h = mol.add_atom(atom_xyz("H", hx, hy, hz));
bond_order(&mut mol, c, h, 1.0);
}
let frame = typifier.typify(&mol).expect("typify").to_frame();
let atoms = frame.get("atoms").expect("atoms block");
assert_eq!(atoms.nrows(), Some(8));
assert!(atoms.contains_key("type"));
assert!(atoms.contains_key("charge"));
let bonds = frame.get("bonds").expect("bonds block");
assert_eq!(bonds.nrows(), Some(7));
assert!(bonds.contains_key("type"));
let angles = frame.get("angles").expect("angles block");
assert_eq!(angles.nrows(), Some(12));
let dihedrals = frame.get("dihedrals").expect("dihedrals block");
assert_eq!(dihedrals.nrows(), Some(9));
assert!(!frame.contains_key("pairs"));
}
}