use std::fmt;
use colored::Colorize;
use hashbrown::HashSet;
use indexmap::IndexMap;
use crate::errors::ElementError;
use crate::prelude::{CellGrid, CellNeighbors};
use crate::structures::dimension::Dimension;
use crate::structures::element::Elements;
use crate::system::System;
const DEFAULT_RADIUS_FACTOR: f32 = 0.55;
impl System {
#[inline(always)]
pub fn guess_elements(&mut self, elements: Elements) -> Result<(), ElementError> {
self.guess_elements_partial(elements, true)
}
#[inline(always)]
pub fn guess_elements_unknown(&mut self, elements: Elements) -> Result<(), ElementError> {
self.guess_elements_partial(elements, false)
}
fn guess_elements_partial(
&mut self,
elements: Elements,
for_all: bool,
) -> Result<(), ElementError> {
self.validate_queries(&elements)?;
let mut no_elements = Vec::new();
let mut multiple_elements: IndexMap<Vec<String>, Vec<usize>> = IndexMap::new();
for a in 0..self.get_n_atoms() {
if !for_all {
let atom = self.get_atom(a).unwrap();
if atom.get_element_name().is_some() || atom.get_element_symbol().is_some() {
continue;
}
}
let matched_elements =
elements
.elements
.iter()
.try_fold(Vec::new(), |mut acc, (name, element)| {
if element.matches(a, self).expect(
"FATAL GROAN ERROR | System::guess_elements | Query should not be invalid.",
) {
acc.push(name.to_string());
}
Ok(acc)
})?;
if matched_elements.is_empty() {
no_elements.push(a + 1);
} else {
self.set_atom_properties(a, &matched_elements[0], &elements);
if matched_elements.len() > 1 {
multiple_elements
.entry(matched_elements)
.or_default()
.push(a + 1);
}
}
}
if !no_elements.is_empty() || !multiple_elements.is_empty() {
Err(ElementError::ElementGuessWarning(Box::new(
ElementGuessInfo {
no_elements,
multiple_elements,
},
)))
} else {
Ok(())
}
}
pub fn guess_properties(&mut self, elements: Elements) -> Result<(), ElementError> {
let mut info = PropertiesGuessInfo {
no_element: Vec::new(),
not_recognized: Vec::new(),
no_mass: Vec::new(),
no_vdw: Vec::new(),
no_max_bonds: Vec::new(),
no_min_bonds: Vec::new(),
};
for (a, atom) in self.atoms_iter_mut().enumerate() {
if let Some(elname) = atom.get_element_name() {
if let Some(element) = elements.elements.get(elname) {
match element.mass {
None => info.no_mass.push(a + 1),
Some(x) => atom.set_mass(x),
}
match element.vdw {
None => info.no_vdw.push(a + 1),
Some(x) => atom.set_vdw(x),
}
match element.expected_max_bonds {
None => info.no_max_bonds.push(a + 1),
Some(x) => atom.set_expected_max_bonds(x),
}
match element.expected_min_bonds {
None => info.no_min_bonds.push(a + 1),
Some(x) => atom.set_expected_min_bonds(x),
}
} else {
info.not_recognized.push(a + 1);
}
} else {
info.no_element.push(a + 1);
}
}
if info.is_empty() {
Ok(())
} else {
Err(ElementError::PropertiesGuessWarning(Box::new(info)))
}
}
pub fn guess_bonds(&mut self, radius_factor: Option<f32>) -> Result<(), ElementError> {
let n_atoms = self.get_n_atoms();
if n_atoms == 0 {
return Ok(());
}
let radius_factor = radius_factor.unwrap_or(DEFAULT_RADIUS_FACTOR);
let cell_grid = CellGrid::new(self, "all", self.get_cell_size(radius_factor))
.map_err(ElementError::BondGuessError)?;
let (bonds, no_vdw) = self.identify_bonds(&cell_grid, radius_factor);
self.assign_bonds(bonds);
let (too_many_bonds, too_few_bonds) = self.check_unexpected_bonds();
let info = BondsGuessInfo {
no_vdw,
too_many_bonds,
too_few_bonds,
};
if info.is_empty() {
Ok(())
} else {
Err(ElementError::BondsGuessWarning(Box::new(info)))
}
}
fn get_cell_size(&self, radius_factor: f32) -> f32 {
let max_vdw = self
.get_atoms()
.iter()
.filter_map(|atom| atom.get_vdw())
.fold(f32::NEG_INFINITY, |a, b| a.max(b));
2.0 * radius_factor * max_vdw
}
#[inline]
fn assign_bonds(&mut self, bonds: HashSet<(usize, usize)>) {
unsafe {
let atoms = self.get_atoms_mut();
for (index1, index2) in bonds {
atoms[index1].add_bonded(index2);
atoms[index2].add_bonded(index1);
}
}
self.reset_mol_references();
}
fn identify_bonds(
&self,
cell_grid: &CellGrid,
radius_factor: f32,
) -> (HashSet<(usize, usize)>, Vec<usize>) {
let mut no_vdw = Vec::new();
let mut bonds = HashSet::new();
for atom1 in self.get_atoms().iter() {
let vdw1 = match atom1.get_vdw() {
Some(x) => x,
None => {
no_vdw.push(atom1.get_index() + 1);
continue;
}
};
let pos = atom1
.get_position()
.expect("FATAL GROAN ERROR | System::identify_bonds | Atom should have position.")
.clone();
for atom2 in cell_grid.neighbors_iter(pos, CellNeighbors::default()) {
if atom1.get_index() == atom2.get_index() {
continue;
}
let vdw2 = match atom2.get_vdw() {
Some(x) => x,
None => continue,
};
let distance = atom1
.distance(atom2, Dimension::XYZ, self.get_box().unwrap())
.expect(
"FATAL GROAN ERROR | System::identify_bonds | Atoms should have positions.",
);
let limit = (vdw1 + vdw2) * radius_factor;
if distance < limit {
let (a, b) = (atom1.get_index(), atom2.get_index());
if a < b {
bonds.insert((a, b));
} else {
bonds.insert((b, a));
}
}
}
}
(bonds, no_vdw)
}
#[inline]
#[allow(clippy::type_complexity)]
fn check_unexpected_bonds(
&self,
) -> (IndexMap<usize, (usize, u8)>, IndexMap<usize, (usize, u8)>) {
let mut too_many_bonds = IndexMap::new();
let mut too_few_bonds = IndexMap::new();
for atom in self.atoms_iter() {
if let Some(limit) = atom.get_expected_max_bonds() {
if atom.get_n_bonded() > limit as usize
&& too_many_bonds
.insert(atom.get_index() + 1, (atom.get_n_bonded(), limit))
.is_some()
{
panic!("FATAL GROAN ERROR | System::guess_bonds | Atom should not be in the `too_many_bonds` map.")
}
}
if let Some(limit) = atom.get_expected_min_bonds() {
if atom.get_n_bonded() < limit as usize
&& too_few_bonds
.insert(atom.get_index() + 1, (atom.get_n_bonded(), limit))
.is_some()
{
panic!("FATAL GROAN ERROR | System::guess_bonds | Atom should not be in the `too_few_bonds` map.")
}
}
}
(too_many_bonds, too_few_bonds)
}
fn set_atom_properties(&mut self, atom_index: usize, element_name: &str, elements: &Elements) {
let atom = self
.get_atom_mut(atom_index)
.expect("FATAL GROAN ERROR | System::set_atom_properties | Atom should exist.");
let element = elements
.elements
.get(element_name)
.expect("FATAL GROAN ERROR | System::set_atom_properties | Element should exist.");
atom.set_element_name(element_name);
if let Some(ref symbol) = element.symbol {
atom.set_element_symbol(symbol);
}
if let Some(x) = atom.get_mass().or(element.mass) {
atom.set_mass(x)
};
if let Some(x) = atom.get_vdw().or(element.vdw) {
atom.set_vdw(x)
};
if let Some(x) = atom.get_expected_max_bonds().or(element.expected_max_bonds) {
atom.set_expected_max_bonds(x)
};
if let Some(x) = atom.get_expected_min_bonds().or(element.expected_min_bonds) {
atom.set_expected_min_bonds(x)
}
}
fn validate_queries(&self, elements: &Elements) -> Result<(), ElementError> {
for (_, element) in &elements.elements {
element.validate_select(self)?;
}
Ok(())
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct ElementGuessInfo {
no_elements: Vec<usize>,
multiple_elements: IndexMap<Vec<String>, Vec<usize>>,
}
impl fmt::Display for ElementGuessInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let no_elements_len = self.no_elements.len();
if no_elements_len > 0 {
writeln!(f, "\n> following atoms match no element:")?;
}
for (a, atom) in self.no_elements.iter().enumerate() {
write!(f, "{} ", atom.to_string().yellow())?;
if a >= 9 && no_elements_len != a + 1 {
writeln!(f, "and {} other atoms", no_elements_len - a - 1)?;
break;
}
}
for (matches, atoms) in self.multiple_elements.iter() {
let assigned = matches
.first()
.expect("FATAL GROAN ERROR | ElementGuessInfo::fmt | Element should exist.");
write!(
f,
"\n> following atoms have been identified as {} but also match",
assigned.to_string().yellow()
)?;
for (e, element) in matches.iter().skip(1).enumerate() {
write!(f, " {}", element.yellow())?;
if e >= 2 && matches.len() != e + 2 {
writeln!(f, " and {} other elements:", matches.len() - e - 2)?;
break;
}
}
if matches.len() <= 4 {
writeln!(f, ":")?;
}
for (a, atom) in atoms.iter().enumerate() {
write!(f, "{} ", atom.to_string().yellow())?;
if a >= 9 && atoms.len() != a + 1 {
writeln!(f, "and {} other atoms ", atoms.len() - a - 1)?;
break;
}
}
if atoms.len() <= 10 {
writeln!(f)?;
}
}
Ok(())
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct PropertiesGuessInfo {
no_element: Vec<usize>,
not_recognized: Vec<usize>,
no_mass: Vec<usize>,
no_vdw: Vec<usize>,
no_max_bonds: Vec<usize>,
no_min_bonds: Vec<usize>,
}
impl PropertiesGuessInfo {
fn is_empty(&self) -> bool {
self.no_element.is_empty()
&& self.no_mass.is_empty()
&& self.no_vdw.is_empty()
&& self.no_max_bonds.is_empty()
&& self.no_min_bonds.is_empty()
}
}
impl fmt::Display for PropertiesGuessInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let fields = [
&self.not_recognized,
&self.no_element,
&self.no_mass,
&self.no_vdw,
&self.no_max_bonds,
&self.no_min_bonds,
];
let strings = [
"\n> following atoms are assigned an unknown element - no properties were set for them:",
"\n> following atoms are not assigned an element - no properties were set for them:",
"\n> following atoms are assigned an element which does not contain information about mass:",
"\n> following atoms are assigned an element which does not contain information about van der Waals radius:",
"\n> following atoms are assigned an element which does not contain information about expected maximal number of bonds:",
"\n> following atoms are assigned an element which does not contain information about expected minimal number of bonds:",
];
for (field, string) in fields.iter().zip(strings.iter()) {
if !field.is_empty() {
writeln!(f, "{}", string)?;
} else {
continue;
}
for (a, atom) in field.iter().enumerate() {
write!(f, "{} ", atom.to_string().yellow())?;
if a >= 9 && field.len() != a + 1 {
writeln!(f, "and {} other atoms", field.len() - a - 1)?;
break;
}
}
if field.len() <= 10 {
writeln!(f)?;
}
}
Ok(())
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct BondsGuessInfo {
no_vdw: Vec<usize>,
too_many_bonds: IndexMap<usize, (usize, u8)>,
too_few_bonds: IndexMap<usize, (usize, u8)>,
}
impl BondsGuessInfo {
fn is_empty(&self) -> bool {
self.no_vdw.is_empty() && self.too_many_bonds.is_empty() && self.too_few_bonds.is_empty()
}
}
impl fmt::Display for BondsGuessInfo {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.no_vdw.is_empty() {
writeln!(f, "\n> following atoms do not have a van der Waals radius assigned - no bonds could be guessed for them:")?;
}
for (a, atom) in self.no_vdw.iter().enumerate() {
write!(f, "{} ", atom.to_string().yellow())?;
if a >= 9 && self.no_vdw.len() != a + 1 {
writeln!(f, "and {} other atoms", self.no_vdw.len() - a - 1)?;
break;
}
}
if self.no_vdw.len() <= 10 {
writeln!(f)?;
}
let fields = [&self.too_many_bonds, &self.too_few_bonds];
let strings = [
"\n> following atoms have a suspiciously high number of bonds:",
"\n> following atoms have a suspiciously low number of bonds:",
];
for (i, (field, string)) in fields.iter().zip(strings.iter()).enumerate() {
if !field.is_empty() {
writeln!(f, "{}", string)?;
} else {
continue;
}
for (a, (atom, (guessed, expected))) in field.iter().enumerate() {
if i == 0 {
writeln!(
f,
"{} (guessed {}, expected at most {})",
atom.to_string().yellow(),
guessed.to_string().yellow(),
expected.to_string().yellow()
)?;
} else {
writeln!(
f,
"{} (guessed {}, expected at least {})",
atom.to_string().yellow(),
guessed.to_string().yellow(),
expected.to_string().yellow()
)?;
}
if a >= 9 && field.len() != a + 1 {
writeln!(f, "and {} other atoms", field.len() - a - 1)?;
break;
}
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use crate::{errors::SelectError, structures::simbox::SimBox};
use super::*;
use float_cmp::assert_approx_eq;
#[test]
fn guess_elements() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.guess_elements(Elements::default()).unwrap();
for atom in system.atoms_iter() {
assert!(atom.get_element_name().is_some());
assert!(atom.get_element_symbol().is_some());
assert!(atom.get_mass().is_some());
}
let atom = system.get_atom(0).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "nitrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "N");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 14.0067);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.1625);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(1).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.0079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.10);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 1);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(360).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "carbon");
assert_eq!(atom.get_element_symbol().unwrap(), "C");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 12.0107);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.17);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(3081).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 15.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.15);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(14184).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "phosphorus");
assert_eq!(atom.get_element_symbol().unwrap(), "P");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 30.9738);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.1871);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 5);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(31541).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.0079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.10);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 1);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(17590).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 15.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.15);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(32795).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "sodium");
assert_eq!(atom.get_element_symbol().unwrap(), "Na");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 22.9897);
assert_eq!(atom.get_vdw(), None);
assert_eq!(atom.get_expected_max_bonds(), None);
assert_eq!(atom.get_expected_min_bonds(), None);
let atom = system.get_atom(32816).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "chlorine");
assert_eq!(atom.get_element_symbol().unwrap(), "Cl");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 35.453);
assert_eq!(atom.get_vdw(), None);
assert_eq!(atom.get_expected_max_bonds(), None);
assert_eq!(atom.get_expected_min_bonds(), None);
}
#[test]
fn guess_elements_prefilled() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.get_atom_mut(0).unwrap().set_mass(19.1);
system.get_atom_mut(0).unwrap().set_element_symbol("Uk");
system.get_atom_mut(0).unwrap().set_vdw(0.24);
system.get_atom_mut(360).unwrap().set_expected_max_bonds(7);
system.get_atom_mut(14184).unwrap().set_vdw(0.20);
system.get_atom_mut(32795).unwrap().set_mass(19.1);
system
.get_atom_mut(32795)
.unwrap()
.set_element_name("Unknown");
system.guess_elements(Elements::default()).unwrap();
for atom in system.atoms_iter() {
assert!(atom.get_element_name().is_some());
assert!(atom.get_element_symbol().is_some());
assert!(atom.get_mass().is_some());
}
let atom = system.get_atom(0).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "nitrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "N");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 19.1);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.24);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(1).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.0079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.1);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 1);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(360).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "carbon");
assert_eq!(atom.get_element_symbol().unwrap(), "C");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 12.0107);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.17);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 7);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(3081).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 15.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.15);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(14184).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "phosphorus");
assert_eq!(atom.get_element_symbol().unwrap(), "P");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 30.9738);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.20);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 5);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(31541).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.0079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.1);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 1);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(17590).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 15.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.15);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(32795).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "sodium");
assert_eq!(atom.get_element_symbol().unwrap(), "Na");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 19.1);
assert_eq!(atom.get_vdw(), None);
assert_eq!(atom.get_expected_max_bonds(), None);
assert_eq!(atom.get_expected_min_bonds(), None);
let atom = system.get_atom(32816).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "chlorine");
assert_eq!(atom.get_element_symbol().unwrap(), "Cl");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 35.453);
assert_eq!(atom.get_vdw(), None);
assert_eq!(atom.get_expected_max_bonds(), None);
assert_eq!(atom.get_expected_min_bonds(), None);
}
#[test]
fn guess_elements_unknown() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.get_atom_mut(0).unwrap().set_mass(19.1);
system.get_atom_mut(0).unwrap().set_element_symbol("Uk");
system.get_atom_mut(0).unwrap().set_vdw(0.24);
system.get_atom_mut(360).unwrap().set_expected_max_bonds(7);
system.get_atom_mut(14184).unwrap().set_vdw(0.20);
system.get_atom_mut(32795).unwrap().set_mass(19.1);
system
.get_atom_mut(32795)
.unwrap()
.set_element_name("Unknown");
system.guess_elements_unknown(Elements::default()).unwrap();
let atom = system.get_atom(0).unwrap();
println!("{:?}", atom);
assert!(atom.get_element_name().is_none());
assert_eq!(atom.get_element_symbol().unwrap(), "Uk");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 19.1);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.24);
assert!(atom.get_expected_max_bonds().is_none());
assert!(atom.get_expected_min_bonds().is_none());
let atom = system.get_atom(1).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.0079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.1);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 1);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(360).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "carbon");
assert_eq!(atom.get_element_symbol().unwrap(), "C");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 12.0107);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.17);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 7);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(3081).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 15.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.15);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(14184).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "phosphorus");
assert_eq!(atom.get_element_symbol().unwrap(), "P");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 30.9738);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.20);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 5);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(31541).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.0079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.1);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 1);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(17590).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 15.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.15);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(32795).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "Unknown");
assert!(atom.get_element_symbol().is_none());
assert_approx_eq!(f32, atom.get_mass().unwrap(), 19.1);
assert!(atom.get_vdw().is_none());
assert!(atom.get_expected_max_bonds().is_none());
assert!(atom.get_expected_min_bonds().is_none());
let atom = system.get_atom(32816).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "chlorine");
assert_eq!(atom.get_element_symbol().unwrap(), "Cl");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 35.453);
assert_eq!(atom.get_vdw(), None);
assert_eq!(atom.get_expected_max_bonds(), None);
assert_eq!(atom.get_expected_min_bonds(), None);
}
#[test]
fn guess_elements_with_warnings() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
let expected_no: Vec<usize> = vec![
383, 517, 651, 785, 919, 1053, 1187, 1321, 1455, 1589, 1723, 1857, 1991, 2125, 2259,
2393, 2527, 2661, 2795, 2929, 3063, 3197, 3331, 3465, 3599, 3733, 3867, 4001, 4135,
4269, 4403, 4537, 4671, 4805, 4939, 5073, 5207, 5341, 5475, 5609, 5743, 5877, 6011,
6145, 6279, 6413, 6547, 6681, 6815, 6949, 7083, 7217, 7351, 7485, 7619, 7753, 7887,
8021, 8155, 8289, 8423, 8557, 8691, 8825, 8959, 9093, 9227, 9361, 9495, 9629, 9763,
9897, 10031, 10165, 10299, 10433, 10567, 10701, 10835, 10969, 11103, 11237, 11371,
11505, 11639, 11773, 11907, 12041, 12175, 12309, 12443, 12577, 12711, 12845, 12979,
13113, 13247, 13381, 13515, 13649, 13783, 13917, 14051, 14185, 14319, 14453, 14587,
14721, 14855, 14989, 15123, 15257, 15391, 15525, 15659, 15793, 15927, 16061, 16195,
16329, 16463, 16597, 16731, 16865, 16999, 17133, 17267, 17401,
];
let expected_multiple1: Vec<usize> = vec![
32803, 32808, 32809, 32810, 32811, 32812, 32813, 32814, 32815, 32816, 32817,
];
let expected_multiple2: Vec<usize> = vec![32804, 32805, 32806, 32807];
match system
.guess_elements(Elements::from_file("test_files/elements_incomplete.yaml").unwrap())
{
Ok(_) => panic!("Function should have failed."),
Err(ElementError::ElementGuessWarning(x)) => {
assert_eq!(x.no_elements, expected_no);
let atoms = x
.multiple_elements
.get(&vec!["carbon".to_string(), "chlorine".to_string()])
.unwrap();
assert_eq!(*atoms, expected_multiple1);
let atoms = x
.multiple_elements
.get(&vec![
"carbon".to_string(),
"chlorine".to_string(),
"unknown".to_string(),
])
.unwrap();
assert_eq!(*atoms, expected_multiple2);
}
Err(e) => panic!(
"Function failed successfully but incorrect error type `{}` was returned.",
e
),
}
for (a, atom) in system.atoms_iter().enumerate() {
if expected_no.contains(&(a + 1)) {
assert!(atom.get_element_name().is_none());
assert!(atom.get_element_symbol().is_none());
assert!(atom.get_mass().is_none());
} else {
assert!(atom.get_element_name().is_some());
assert!(atom.get_element_symbol().is_some());
assert!(atom.get_mass().is_some());
}
}
let atom = system.get_atom(0).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "nitrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "N");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 14.0067);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.155);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 3);
let atom = system.get_atom(1).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.0079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.12);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 1);
let atom = system.get_atom(360).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "carbon");
assert_eq!(atom.get_element_symbol().unwrap(), "C");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 12.0107);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.17);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
let atom = system.get_atom(3081).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 15.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.152);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
let atom = system.get_atom(14184).unwrap();
assert_eq!(atom.get_element_name(), None);
assert_eq!(atom.get_element_symbol(), None);
assert_eq!(atom.get_mass(), None);
assert_eq!(atom.get_vdw(), None);
assert_eq!(atom.get_expected_max_bonds(), None);
let atom = system.get_atom(31541).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.0079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.12);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 1);
let atom = system.get_atom(17590).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 15.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.152);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
let atom = system.get_atom(32795).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "sodium");
assert_eq!(atom.get_element_symbol().unwrap(), "Na");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 22.9897);
assert_eq!(atom.get_vdw(), None);
assert_eq!(atom.get_expected_max_bonds(), None);
let atom = system.get_atom(32804).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "carbon");
assert_eq!(atom.get_element_symbol().unwrap(), "C");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 12.0107);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.17);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
let atom = system.get_atom(32816).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "carbon");
assert_eq!(atom.get_element_symbol().unwrap(), "C");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 12.0107);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.17);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
}
#[test]
fn guess_elements_invalid_query() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
match system
.guess_elements(Elements::from_file("test_files/elements_invalid_group.yaml").unwrap())
{
Ok(_) => panic!("Function should have failed."),
Err(ElementError::InvalidQuery(SelectError::GroupNotFound(x))) => {
assert_eq!(x, "Membrane");
}
Err(e) => panic!(
"Function failed successfully but incorrect error type `{}` was returned.",
e
),
}
for atom in system.atoms_iter() {
assert!(atom.get_element_name().is_none());
assert!(atom.get_element_symbol().is_none());
assert!(atom.get_mass().is_none());
assert!(atom.get_vdw().is_none());
assert!(atom.get_expected_max_bonds().is_none());
assert!(atom.get_position().is_some());
}
}
#[test]
fn guess_elements_complicated_groups() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system
.guess_elements(
Elements::from_file("test_files/elements_complicated_group.yaml").unwrap(),
)
.unwrap();
for (a, atom) in system.atoms_iter().enumerate() {
if a < 61 {
assert_eq!(atom.get_element_name().unwrap(), "protein element");
assert_eq!(atom.get_element_symbol().unwrap(), "P");
assert!(atom.get_mass().is_none());
assert!(atom.get_vdw().is_none());
assert!(atom.get_expected_max_bonds().is_none());
} else {
assert_eq!(atom.get_element_name().unwrap(), "other");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert!(atom.get_mass().is_none());
assert!(atom.get_vdw().is_none());
assert!(atom.get_expected_max_bonds().is_none());
}
}
}
#[test]
fn guess_properties_1() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
for atom in system.atoms_iter_mut() {
atom.set_element_name("carbon");
}
system
.guess_properties(
Elements::from_file("test_files/elements_properties_complete.yaml").unwrap(),
)
.unwrap();
for atom in system.atoms_iter() {
assert_approx_eq!(f32, atom.get_mass().unwrap(), 16.0107);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.21);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 3);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 3);
}
}
#[test]
fn guess_properties_2() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.guess_elements(Elements::default()).unwrap();
system
.guess_properties(
Elements::from_file("test_files/elements_properties_complete.yaml").unwrap(),
)
.unwrap();
for atom in system.atoms_iter() {
assert!(atom.get_element_name().is_some());
assert!(atom.get_element_symbol().is_some());
assert!(atom.get_mass().is_some());
assert!(atom.get_vdw().is_some());
assert!(atom.get_expected_max_bonds().is_some());
assert!(atom.get_expected_min_bonds().is_some());
}
let atom = system.get_atom(0).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "nitrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "N");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 17.0067);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.255);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 5);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 4);
let atom = system.get_atom(1).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.5079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.15);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(360).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "carbon");
assert_eq!(atom.get_element_symbol().unwrap(), "C");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 16.0107);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.21);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 3);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 3);
let atom = system.get_atom(3081).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 19.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.08);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 3);
let atom = system.get_atom(14184).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "phosphorus");
assert_eq!(atom.get_element_symbol().unwrap(), "P");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 32.9738);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.32);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 6);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 5);
let atom = system.get_atom(31541).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.5079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.15);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(17590).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 19.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.08);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 3);
let atom = system.get_atom(32795).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "sodium");
assert_eq!(atom.get_element_symbol().unwrap(), "Na");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 25.9897);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.21);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 0);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 0);
let atom = system.get_atom(32816).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "chlorine");
assert_eq!(atom.get_element_symbol().unwrap(), "Cl");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 37.453);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.20);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 0);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 0);
}
#[test]
fn guess_properties_with_warnings() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.guess_elements(Elements::default()).unwrap();
system.get_atom_mut(1).unwrap().reset_element_name();
let no_element: Vec<usize> = vec![2];
let not_recognized: Vec<usize> = vec![
32789, 32790, 32791, 32792, 32793, 32794, 32795, 32796, 32797, 32798, 32799, 32800,
32801, 32802,
];
let no_mass: Vec<usize> = vec![
32803, 32804, 32805, 32806, 32807, 32808, 32809, 32810, 32811, 32812, 32813, 32814,
32815, 32816, 32817,
];
let no_vdw: Vec<usize> = vec![
383, 517, 651, 785, 919, 1053, 1187, 1321, 1455, 1589, 1723, 1857, 1991, 2125, 2259,
2393, 2527, 2661, 2795, 2929, 3063, 3197, 3331, 3465, 3599, 3733, 3867, 4001, 4135,
4269, 4403, 4537, 4671, 4805, 4939, 5073, 5207, 5341, 5475, 5609, 5743, 5877, 6011,
6145, 6279, 6413, 6547, 6681, 6815, 6949, 7083, 7217, 7351, 7485, 7619, 7753, 7887,
8021, 8155, 8289, 8423, 8557, 8691, 8825, 8959, 9093, 9227, 9361, 9495, 9629, 9763,
9897, 10031, 10165, 10299, 10433, 10567, 10701, 10835, 10969, 11103, 11237, 11371,
11505, 11639, 11773, 11907, 12041, 12175, 12309, 12443, 12577, 12711, 12845, 12979,
13113, 13247, 13381, 13515, 13649, 13783, 13917, 14051, 14185, 14319, 14453, 14587,
14721, 14855, 14989, 15123, 15257, 15391, 15525, 15659, 15793, 15927, 16061, 16195,
16329, 16463, 16597, 16731, 16865, 16999, 17133, 17267, 17401, 32803, 32804, 32805,
32806, 32807, 32808, 32809, 32810, 32811, 32812, 32813, 32814, 32815, 32816, 32817,
];
let no_max_bonds: Vec<usize> = vec![
32803, 32804, 32805, 32806, 32807, 32808, 32809, 32810, 32811, 32812, 32813, 32814,
32815, 32816, 32817,
];
let no_min_bonds: Vec<usize> = vec![
383, 517, 651, 785, 919, 1053, 1187, 1321, 1455, 1589, 1723, 1857, 1991, 2125, 2259,
2393, 2527, 2661, 2795, 2929, 3063, 3197, 3331, 3465, 3599, 3733, 3867, 4001, 4135,
4269, 4403, 4537, 4671, 4805, 4939, 5073, 5207, 5341, 5475, 5609, 5743, 5877, 6011,
6145, 6279, 6413, 6547, 6681, 6815, 6949, 7083, 7217, 7351, 7485, 7619, 7753, 7887,
8021, 8155, 8289, 8423, 8557, 8691, 8825, 8959, 9093, 9227, 9361, 9495, 9629, 9763,
9897, 10031, 10165, 10299, 10433, 10567, 10701, 10835, 10969, 11103, 11237, 11371,
11505, 11639, 11773, 11907, 12041, 12175, 12309, 12443, 12577, 12711, 12845, 12979,
13113, 13247, 13381, 13515, 13649, 13783, 13917, 14051, 14185, 14319, 14453, 14587,
14721, 14855, 14989, 15123, 15257, 15391, 15525, 15659, 15793, 15927, 16061, 16195,
16329, 16463, 16597, 16731, 16865, 16999, 17133, 17267, 17401, 32803, 32804, 32805,
32806, 32807, 32808, 32809, 32810, 32811, 32812, 32813, 32814, 32815, 32816, 32817,
];
match system.guess_properties(
Elements::from_file("test_files/elements_properties_incomplete.yaml").unwrap(),
) {
Ok(_) => panic!("Function should have failed."),
Err(ElementError::PropertiesGuessWarning(x)) => {
assert_eq!(x.no_element, no_element);
assert_eq!(x.not_recognized, not_recognized);
assert_eq!(x.no_mass, no_mass);
assert_eq!(x.no_vdw, no_vdw);
assert_eq!(x.no_max_bonds, no_max_bonds);
assert_eq!(x.no_min_bonds, no_min_bonds);
}
Err(e) => panic!(
"Function failed successfully but incorrect error type `{}` was returned.",
e
),
}
let atom = system.get_atom(0).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "nitrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "N");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 17.0067);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.255);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 5);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 5);
let atom = system.get_atom(1).unwrap();
assert_eq!(atom.get_element_name(), None);
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.0079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.1);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 1);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(360).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "carbon");
assert_eq!(atom.get_element_symbol().unwrap(), "C");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 16.0107);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.21);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 3);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(3081).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 19.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.08);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(14184).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "phosphorus");
assert_eq!(atom.get_element_symbol().unwrap(), "P");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 32.9738);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.1871);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 6);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(31541).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "hydrogen");
assert_eq!(atom.get_element_symbol().unwrap(), "H");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 1.5079);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.15);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 2);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 1);
let atom = system.get_atom(17590).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "oxygen");
assert_eq!(atom.get_element_symbol().unwrap(), "O");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 19.9994);
assert_approx_eq!(f32, atom.get_vdw().unwrap(), 0.08);
assert_eq!(atom.get_expected_max_bonds().unwrap(), 4);
assert_eq!(atom.get_expected_min_bonds().unwrap(), 2);
let atom = system.get_atom(32795).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "sodium");
assert_eq!(atom.get_element_symbol().unwrap(), "Na");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 22.9897);
assert_eq!(atom.get_vdw(), None);
assert_eq!(atom.get_expected_max_bonds(), None);
assert_eq!(atom.get_expected_min_bonds(), None);
let atom = system.get_atom(32816).unwrap();
assert_eq!(atom.get_element_name().unwrap(), "chlorine");
assert_eq!(atom.get_element_symbol().unwrap(), "Cl");
assert_approx_eq!(f32, atom.get_mass().unwrap(), 35.453);
assert_eq!(atom.get_vdw(), None);
assert_eq!(atom.get_expected_max_bonds(), None);
assert_eq!(atom.get_expected_min_bonds(), None);
}
#[test]
fn guess_bonds() {
let mut system = System::from_file("test_files/aa_peptide.pdb").unwrap();
system.guess_elements(Elements::default()).unwrap();
system.guess_bonds(None).unwrap();
let mut system_from_pdb = System::from_file("test_files/aa_peptide.pdb").unwrap();
system_from_pdb
.add_bonds_from_pdb("test_files/aa_peptide.pdb")
.unwrap();
for (atom1, atom2) in system.atoms_iter().zip(system_from_pdb.atoms_iter()) {
assert_eq!(atom1.get_bonded(), atom2.get_bonded());
}
}
#[test]
fn guess_bonds_large() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.guess_elements(Elements::default()).unwrap();
let _ = system.guess_bonds(None);
let system_tpr = System::from_file("test_files/aa_membrane_peptide.tpr").unwrap();
for (a1, a2) in system.atoms_iter().zip(system_tpr.atoms_iter()) {
assert_eq!(a1.get_bonded(), a2.get_bonded());
}
}
#[test]
fn guess_bonds_warnings() {
let mut system = System::from_file("test_files/aa_peptide.pdb").unwrap();
system.guess_elements(Elements::default()).unwrap();
let mut elements_for_bonds = Elements::default();
elements_for_bonds.update(
Elements::from_file("test_files/elements_update_guess_bonds_warning.yaml").unwrap(),
);
match system.guess_properties(elements_for_bonds) {
Ok(_) | Err(_) => (),
}
system.get_atom_mut(1).unwrap().reset_vdw();
let no_vdw = vec![2];
let too_few_bonds = vec![
2, 12, 31, 50, 61, 72, 91, 110, 121, 132, 151, 170, 192, 211, 230, 241, 252, 271, 290,
301, 312, 331, 350, 361,
];
let too_many_bonds = vec![
1, 14, 33, 52, 63, 74, 93, 112, 123, 134, 153, 172, 188, 194, 213, 232, 243, 254, 273,
292, 303, 314, 333, 352,
];
match system.guess_bonds(None) {
Ok(_) => panic!("Function should have returned a warning."),
Err(ElementError::BondsGuessWarning(e)) => {
assert_eq!(e.no_vdw, no_vdw);
assert_eq!(
e.too_few_bonds.keys().cloned().collect::<Vec<usize>>(),
too_few_bonds
);
assert_eq!(
e.too_many_bonds.keys().cloned().collect::<Vec<usize>>(),
too_many_bonds
);
}
Err(e) => panic!("Incorrect warning type `{:?}` returned.", e),
}
let mut system_from_pdb = System::from_file("test_files/aa_peptide.pdb").unwrap();
system_from_pdb
.add_bonds_from_pdb("test_files/aa_peptide.pdb")
.unwrap();
for (atom1, atom2) in system.atoms_iter().zip(system_from_pdb.atoms_iter()) {
if atom1.get_atom_number() <= 2 {
continue;
}
assert_eq!(atom1.get_bonded(), atom2.get_bonded());
}
}
#[test]
fn guess_bonds_empty_system() {
let mut system = System::new(
"Empty system",
vec![],
Some(SimBox::from([10.0, 10.0, 10.0])),
);
system.guess_bonds(None).unwrap();
assert!(!system.has_bonds());
}
}