use std::collections::HashSet;
use indexmap::map::{Iter, Keys};
use indexmap::IndexMap;
use crate::errors::{GroupError, SimBoxError};
use crate::select::Select;
use crate::structures::group::Group;
use crate::structures::shape::Shape;
use crate::system::System;
impl System {
pub fn group_create(&mut self, name: &str, query: &str) -> Result<(), GroupError> {
if !crate::auxiliary::name_is_valid(name) {
return Err(GroupError::InvalidName(name.to_string()));
}
let group = match Group::from_query(query, self) {
Ok(x) => x,
Err(e) => return Err(GroupError::InvalidQuery(e)),
};
self.groups.add(name, group)
}
pub fn group_create_from_geometry(
&mut self,
name: &str,
query: &str,
geometry: impl Shape,
) -> Result<(), GroupError> {
if !crate::auxiliary::name_is_valid(name) {
return Err(GroupError::InvalidName(name.to_string()));
}
if !self.has_box() {
return Err(GroupError::InvalidSimBox(SimBoxError::DoesNotExist));
}
if !self.get_box().unwrap().is_orthogonal() {
return Err(GroupError::InvalidSimBox(SimBoxError::NotOrthogonal));
}
let group = match Group::from_query_and_geometry(query, geometry, self) {
Ok(x) => x,
Err(e) => return Err(GroupError::InvalidQuery(e)),
};
self.groups.add(name, group)
}
pub fn group_create_from_geometries(
&mut self,
name: &str,
query: &str,
geometries: Vec<Box<dyn Shape>>,
) -> Result<(), GroupError> {
if !crate::auxiliary::name_is_valid(name) {
return Err(GroupError::InvalidName(name.to_string()));
}
if !self.has_box() {
return Err(GroupError::InvalidSimBox(SimBoxError::DoesNotExist));
}
if !self.get_box().unwrap().is_orthogonal() {
return Err(GroupError::InvalidSimBox(SimBoxError::NotOrthogonal));
}
let group = match Group::from_query_and_geometries(query, geometries, self) {
Ok(x) => x,
Err(e) => return Err(GroupError::InvalidQuery(e)),
};
self.groups.add(name, group)
}
#[inline(always)]
pub fn group_create_from_indices(
&mut self,
name: &str,
atom_indices: Vec<usize>,
) -> Result<(), GroupError> {
self.groups
.create_from_indices(name, atom_indices, self.get_n_atoms())
}
#[inline(always)]
pub fn group_create_from_ranges(
&mut self,
name: &str,
atom_ranges: Vec<(usize, usize)>,
) -> Result<(), GroupError> {
self.groups
.create_from_ranges(name, atom_ranges, self.get_n_atoms())
}
pub fn group_create_from_select(
&mut self,
name: &str,
select: Select,
) -> Result<(), GroupError> {
if !crate::auxiliary::name_is_valid(name) {
return Err(GroupError::InvalidName(name.to_string()));
}
let group = match Group::from_select(select, self) {
Ok(x) => x,
Err(e) => return Err(GroupError::InvalidQuery(e)),
};
self.groups.add(name, group)
}
pub fn atoms_split_by_resid(&mut self) -> (Result<(), GroupError>, Vec<String>) {
match self.group_split_by_resid("all") {
(Err(GroupError::NotFound(_)), _) => {
panic!("FATAL GROAN ERROR | System::atoms_split_by_resid | Default group 'all' does not exist.")
}
(result, vec) => (result, vec),
}
}
pub fn group_split_by_resid(&mut self, name: &str) -> (Result<(), GroupError>, Vec<String>) {
let mut groups: IndexMap<String, Vec<usize>> = IndexMap::new();
let iterator = match self.group_iter(name) {
Ok(x) => x,
Err(e) => return (Err(e), Vec::new()),
};
for atom in iterator {
let res = atom.get_residue_number();
let group_name = format!("resid {}", res);
match groups.get_mut(&group_name) {
Some(group) => group.push(atom.get_index()),
None => {
groups.insert(group_name, vec![atom.get_index()]);
}
}
}
let mut duplicate_names: HashSet<String> = HashSet::new();
for (group_name, atoms) in groups.iter() {
if self
.group_create_from_indices(group_name, atoms.clone())
.is_err()
{
duplicate_names.insert(group_name.to_string());
}
}
if duplicate_names.is_empty() {
(Ok(()), groups.keys().cloned().collect())
} else {
(
Err(GroupError::MultipleAlreadyExistWarning(Box::new(
duplicate_names,
))),
groups.keys().cloned().collect(),
)
}
}
pub fn atoms_split_by_resname(&mut self) -> (Result<(), GroupError>, Vec<String>) {
match self.group_split_by_resname("all") {
(Err(GroupError::NotFound(_)), _) => {
panic!("FATAL GROAN ERROR | System::atoms_split_by_resname | Default group 'all' does not exist.")
}
(result, vec) => (result, vec),
}
}
pub fn group_split_by_resname(&mut self, name: &str) -> (Result<(), GroupError>, Vec<String>) {
let mut groups: IndexMap<String, Vec<usize>> = IndexMap::new();
let iterator = match self.group_iter(name) {
Ok(x) => x,
Err(e) => return (Err(e), Vec::new()),
};
for atom in iterator {
let res = atom.get_residue_name();
let group_name = format!("resname {}", res);
match groups.get_mut(&group_name) {
Some(group) => group.push(atom.get_index()),
None => {
groups.insert(group_name, vec![atom.get_index()]);
}
}
}
let mut duplicate_names: HashSet<String> = HashSet::new();
for (group_name, atoms) in groups.iter() {
if self
.group_create_from_indices(group_name, atoms.clone())
.is_err()
{
duplicate_names.insert(group_name.to_string());
}
}
if duplicate_names.is_empty() {
(Ok(()), groups.keys().cloned().collect())
} else {
(
Err(GroupError::MultipleAlreadyExistWarning(Box::new(
duplicate_names,
))),
groups.keys().cloned().collect(),
)
}
}
#[inline(always)]
pub fn group_make_writable(&mut self, name: &str) -> Result<(), GroupError> {
self.groups.make_writable(name)
}
#[inline(always)]
pub fn group_make_nonwritable(&mut self, name: &str) -> Result<(), GroupError> {
self.groups.make_nonwritable(name)
}
#[allow(dead_code)]
#[inline(always)]
pub(crate) fn group_remove(&mut self, name: &str) -> Result<(), GroupError> {
self.groups.remove(name)
}
#[allow(dead_code)]
#[inline(always)]
pub(crate) fn group_rename(&mut self, old: &str, new: &str) -> Result<(), GroupError> {
self.groups.rename(old, new)
}
#[inline(always)]
pub fn group_exists(&self, name: &str) -> bool {
self.groups.exists(name)
}
#[inline(always)]
pub fn group_isin(&self, name: &str, index: usize) -> Result<bool, GroupError> {
self.groups.isin(name, index)
}
#[inline(always)]
pub fn group_get_n_atoms(&self, name: &str) -> Result<usize, GroupError> {
self.groups.get_n_atoms(name)
}
#[inline(always)]
pub fn group_union(
&mut self,
group1: &str,
group2: &str,
union: &str,
) -> Result<(), GroupError> {
self.groups.union(group1, group2, union)
}
#[inline(always)]
pub fn group_intersection(
&mut self,
group1: &str,
group2: &str,
intersection: &str,
) -> Result<(), GroupError> {
self.groups.intersection(group1, group2, intersection)
}
#[inline(always)]
pub fn group_extend(&mut self, group: &str, extend: &str) -> Result<(), GroupError> {
self.groups.extend(group, extend)
}
#[inline(always)]
pub fn group_names(&self) -> Vec<String> {
self.groups.names()
}
#[inline(always)]
pub fn group_names_writable(&self) -> Vec<String> {
self.groups.names_writable()
}
#[inline(always)]
pub fn group_isempty(&self, name: &str) -> Result<bool, GroupError> {
self.groups.is_empty(name)
}
#[inline(always)]
pub fn groups_member(&self, index: usize) -> Vec<String> {
self.groups.member(index)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(deny_unknown_fields, transparent))]
pub struct Groups(IndexMap<String, Group>);
impl Default for Groups {
fn default() -> Self {
Groups(IndexMap::new())
}
}
impl Groups {
pub fn update(&mut self, rhs: Groups) -> Result<(), GroupError> {
let mut duplicates = HashSet::new();
for (name, group) in rhs.0.into_iter() {
match self.add(&name, group) {
Ok(_) => (),
Err(GroupError::AlreadyExistsWarning(_)) => {
duplicates.insert(name);
},
Err(e) => panic!("FATAL GROAN ERROR | Groups::update | Unexpected error type `{}` returned by `Groups::add`.", e)
}
}
if !duplicates.is_empty() {
Err(GroupError::MultipleAlreadyExistWarning(Box::new(
duplicates,
)))
} else {
Ok(())
}
}
pub(super) fn make_default_groups(&mut self, n_atoms: usize) -> Result<(), GroupError> {
self.create_from_ranges("all", vec![(0, n_atoms)], n_atoms)?;
self.create_from_ranges("All", vec![(0, n_atoms)], n_atoms)?;
self.make_nonwritable("all")
.expect("FATAL GROAN ERROR | System::group_create_all | Group 'all' is not available immediately after its construction.");
self.make_nonwritable("All")
.expect("FATAL GROAN ERROR | System::group_create_all | Group 'All' is not available immediately after its construction.");
Ok(())
}
pub fn create_from_ranges(
&mut self,
name: &str,
atom_ranges: Vec<(usize, usize)>,
n_atoms: usize,
) -> Result<(), GroupError> {
if !crate::auxiliary::name_is_valid(name) {
return Err(GroupError::InvalidName(name.to_string()));
}
let group = Group::from_ranges(atom_ranges, n_atoms);
match self.0.insert(name.to_string(), group) {
None => Ok(()),
Some(_) => Err(GroupError::AlreadyExistsWarning(name.to_string())),
}
}
pub fn create_from_indices(
&mut self,
name: &str,
atom_indices: Vec<usize>,
n_atoms: usize,
) -> Result<(), GroupError> {
if !crate::auxiliary::name_is_valid(name) {
return Err(GroupError::InvalidName(name.to_string()));
}
let group = Group::from_indices(atom_indices, n_atoms);
match self.0.insert(name.to_string(), group) {
None => Ok(()),
Some(_) => Err(GroupError::AlreadyExistsWarning(name.to_string())),
}
}
#[inline(always)]
pub fn n_groups(&self) -> usize {
self.0.len()
}
#[inline(always)]
pub fn get(&self, name: &str) -> Result<&Group, GroupError> {
self.0
.get(name)
.ok_or(GroupError::NotFound(name.to_string()))
}
#[inline(always)]
pub fn get_mut(&mut self, name: &str) -> Result<&mut Group, GroupError> {
self.0
.get_mut(name)
.ok_or(GroupError::NotFound(name.to_string()))
}
#[inline(always)]
pub fn add(&mut self, name: &str, group: Group) -> Result<(), GroupError> {
if !crate::auxiliary::name_is_valid(name) {
return Err(GroupError::InvalidName(name.to_string()));
}
match self.0.insert(name.to_string(), group) {
None => Ok(()),
Some(_) => Err(GroupError::AlreadyExistsWarning(name.to_string())),
}
}
#[inline(always)]
pub fn exists(&self, name: &str) -> bool {
self.0.contains_key(name)
}
#[inline]
pub fn isin(&self, name: &str, index: usize) -> Result<bool, GroupError> {
Ok(self.get(name)?.get_atoms().isin(index))
}
#[inline]
pub fn get_n_atoms(&self, name: &str) -> Result<usize, GroupError> {
Ok(self.get(name)?.get_n_atoms())
}
#[inline]
pub fn make_writable(&mut self, name: &str) -> Result<(), GroupError> {
self.get_mut(name)?.print_ndx = true;
Ok(())
}
#[inline]
pub fn make_nonwritable(&mut self, name: &str) -> Result<(), GroupError> {
self.get_mut(name)?.print_ndx = false;
Ok(())
}
pub fn union(&mut self, group1: &str, group2: &str, union: &str) -> Result<(), GroupError> {
if !crate::auxiliary::name_is_valid(union) {
return Err(GroupError::InvalidName(union.to_string()));
}
let group1 = self.get(group1)?;
let group2 = self.get(group2)?;
let group = Group::union(group1, group2);
self.add(union, group)
}
pub fn intersection(
&mut self,
group1: &str,
group2: &str,
intersection: &str,
) -> Result<(), GroupError> {
if !crate::auxiliary::name_is_valid(intersection) {
return Err(GroupError::InvalidName(intersection.to_string()));
}
let group1 = self.get(group1)?;
let group2 = self.get(group2)?;
let group = Group::intersection(group1, group2);
self.add(intersection, group)
}
#[inline(always)]
pub fn extend(&mut self, group: &str, extend: &str) -> Result<(), GroupError> {
match self.union(group, extend, group) {
Ok(_) | Err(GroupError::AlreadyExistsWarning(_)) => Ok(()),
Err(e) => Err(e),
}
}
#[inline(always)]
pub fn names(&self) -> Vec<String> {
self.0.keys().map(|key| key.to_owned()).collect()
}
#[inline(always)]
pub(crate) fn names_iter(&self) -> Keys<'_, String, Group> {
self.0.keys()
}
pub fn names_writable(&self) -> Vec<String> {
self.0
.iter()
.filter(|(_, group)| group.print_ndx)
.map(|(key, _)| key.to_owned())
.collect()
}
#[inline]
pub fn is_empty(&self, name: &str) -> Result<bool, GroupError> {
Ok(self.get(name)?.get_atoms().is_empty())
}
pub fn member(&self, index: usize) -> Vec<String> {
self.0
.iter()
.filter(|(_, group)| group.get_atoms().isin(index))
.map(|(name, _)| name.to_owned())
.collect()
}
#[inline]
pub fn iter(&self) -> Iter<'_, String, Group> {
self.0.iter()
}
#[allow(dead_code)]
pub(crate) fn remove(&mut self, name: &str) -> Result<(), GroupError> {
if self.0.shift_remove(name).is_none() {
Err(GroupError::NotFound(name.to_owned()))
} else {
Ok(())
}
}
#[allow(dead_code)]
pub(crate) fn rename(&mut self, old: &str, new: &str) -> Result<(), GroupError> {
let group = match self.0.shift_remove(old) {
Some(x) => x,
None => return Err(GroupError::NotFound(old.to_owned())),
};
self.add(new, group)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::errors::SelectError;
use crate::structures::dimension::Dimension;
use crate::structures::element::Elements;
use crate::structures::shape::*;
use crate::structures::vector3d::Vector3D;
#[test]
fn group_create_basic() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.group_create("Membrane", "resname POPC").unwrap();
assert!(system.group_exists("Membrane"));
assert_eq!(system.group_get_n_atoms("Membrane").unwrap(), 6144);
for i in 61..=6204 {
assert!(system.group_isin("Membrane", i).unwrap());
}
system.group_create("Protein", "serial 1 to 61").unwrap();
assert!(system.group_exists("Protein"));
assert_eq!(system.group_get_n_atoms("Protein").unwrap(), 61);
for i in 0..=60 {
assert!(system.group_isin("Protein", i).unwrap());
}
}
#[test]
fn group_create_basic_fails() {
let mut system = System::from_file("test_files/example.gro").unwrap();
match system.group_create("Memb!rane", "resname POPC") {
Ok(_) => panic!("Group should have an invalid name but it was accepted."),
Err(e) => {
assert!(e.to_string().contains("Memb!rane"));
}
}
assert!(!system.group_exists("Memb!rane"));
match system.group_create("Membrane", "resname POPC &&") {
Ok(_) => panic!("Parsing should have failed but it succeeded."),
Err(e) => {
assert!(e.to_string().contains("missing argument"));
}
}
assert!(!system.group_exists("Membrane"));
match system.group_create("Membrane", "(resname POPC && resname POPE))") {
Ok(_) => panic!("Parsing should have failed but it succeeded."),
Err(e) => {
assert!(e.to_string().contains("unmatching parentheses"));
}
}
match system.group_create("MyProtein", "Protein") {
Ok(_) => panic!("Parsing should have failed but it succeeded."),
Err(GroupError::InvalidQuery(SelectError::GroupNotFound(_))) => (),
Err(e) => panic!("Incorrect error {} returned.", e),
}
}
#[test]
fn group_create_basic_overwrite() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.group_create("Membrane", "serial 1").unwrap();
match system.group_create("Membrane", "resname POPC") {
Ok(_) => panic!("Warning was not raised."),
Err(e) => {
assert!(e.to_string().contains("already existed"));
}
}
assert!(system.group_exists("Membrane"));
assert_eq!(system.group_get_n_atoms("Membrane").unwrap(), 6144);
for i in 61..=6204 {
assert!(system.group_isin("Membrane", i).unwrap());
}
}
#[test]
fn group_create_chain() {
let mut system = System::from_file("test_files/example.pdb").unwrap();
system.group_create("Chains A+B", "chain A B").unwrap();
assert!(system.group_exists("Chains A+B"));
assert_eq!(system.group_get_n_atoms("Chains A+B").unwrap(), 31);
for i in 0..=30 {
assert!(system.group_isin("Chains A+B", i).unwrap());
}
system.group_create("Chain C", "chain C").unwrap();
assert!(system.group_exists("Chain C"));
assert_eq!(system.group_get_n_atoms("Chain C").unwrap(), 19);
for i in 31..=49 {
assert!(system.group_isin("Chain C", i).unwrap());
}
}
#[test]
fn group_create_chain_from_gro() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.group_create("Chains A+B", "chain A B").unwrap();
assert!(system.group_exists("Chains A+B"));
assert_eq!(system.group_get_n_atoms("Chains A+B").unwrap(), 0);
}
#[test]
fn group_create_element_name() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.guess_elements(Elements::default()).unwrap();
system
.group_create("Elements", "element name carbon phosphorus")
.unwrap();
assert!(system.group_exists("Elements"));
assert_eq!(system.group_get_n_atoms("Elements").unwrap(), 5612);
system
.group_create("Elements2", "elname carbon phosphorus")
.unwrap();
assert!(system.group_exists("Elements2"));
assert_eq!(system.group_get_n_atoms("Elements2").unwrap(), 5612);
}
#[test]
fn group_create_element_symbol() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.guess_elements(Elements::default()).unwrap();
system
.group_create("Elements", "element symbol C P")
.unwrap();
assert!(system.group_exists("Elements"));
assert_eq!(system.group_get_n_atoms("Elements").unwrap(), 5612);
system.group_create("Elements2", "elsymbol C P").unwrap();
assert!(system.group_exists("Elements2"));
assert_eq!(system.group_get_n_atoms("Elements2").unwrap(), 5612);
}
#[test]
fn group_create_element_empty() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system
.group_create("Elements", "element name carbon phosphorus")
.unwrap();
assert!(system.group_exists("Elements"));
assert_eq!(system.group_get_n_atoms("Elements").unwrap(), 0);
system
.group_create("Elements2", "element symbol C P")
.unwrap();
assert!(system.group_exists("Elements2"));
assert_eq!(system.group_get_n_atoms("Elements2").unwrap(), 0);
}
#[test]
fn group_create_element_empty2() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.guess_elements(Elements::default()).unwrap();
system
.group_create("Empty Elements", "elname copper gold")
.unwrap();
assert!(system.group_exists("Empty Elements"));
assert_eq!(system.group_get_n_atoms("Empty Elements").unwrap(), 0);
system
.group_create("Empty Elements 2", "elsymbol Cu Au")
.unwrap();
assert!(system.group_exists("Empty Elements 2"));
assert_eq!(system.group_get_n_atoms("Empty Elements 2").unwrap(), 0);
}
#[test]
fn group_create_molwith_1() {
let mut system = System::from_file("test_files/aa_peptide.pdb").unwrap();
system
.add_bonds_from_pdb("test_files/aa_peptide.pdb")
.unwrap();
system
.group_create("Molecule", "molwith serial 292")
.unwrap();
assert_eq!(
system.get_n_atoms(),
system.group_get_n_atoms("Molecule").unwrap()
);
for (atom1, atom2) in system
.atoms_iter()
.zip(system.group_iter("Molecule").unwrap())
{
assert_eq!(atom1.get_atom_number(), atom2.get_atom_number());
}
}
#[test]
fn group_create_molwith_2() {
let mut system = System::from_file("test_files/conect.pdb").unwrap();
system.add_bonds_from_pdb("test_files/conect.pdb").unwrap();
system
.group_create("Molecule", "molecule with (resname LYS and name SC2)")
.unwrap();
assert_eq!(system.group_get_n_atoms("Molecule").unwrap(), 1);
for atom in system.group_iter("Molecule").unwrap() {
assert_eq!(atom.get_atom_number(), 50);
}
}
#[test]
fn group_create_molwith_3() {
let mut system = System::from_file("test_files/conect.pdb").unwrap();
system.add_bonds_from_pdb("test_files/conect.pdb").unwrap();
system
.group_create("Molecule", "mol with resname LYS and name SC2")
.unwrap();
assert_eq!(system.group_get_n_atoms("Molecule").unwrap(), 8);
let numbers = [5, 12, 22, 31, 36, 40, 47, 50];
for (a, atom) in system.group_iter("Molecule").unwrap().enumerate() {
assert_eq!(atom.get_atom_number(), numbers[a]);
}
}
#[test]
fn group_create_molwith_label() {
let mut system = System::from_file("test_files/conect.pdb").unwrap();
system.add_bonds_from_pdb("test_files/conect.pdb").unwrap();
system
.select_and_label("ReferenceAtom", "serial 17")
.unwrap();
system
.group_create("Molecule", "molecule with label ReferenceAtom")
.unwrap();
assert_eq!(system.group_get_n_atoms("Molecule").unwrap(), 49);
for (a, atom) in system.group_iter("Molecule").unwrap().enumerate() {
if (9..27).contains(&a) {
assert_eq!(atom.get_atom_number(), a + 2);
} else if a == 27 {
assert_eq!(atom.get_atom_number(), 10);
} else {
assert_eq!(atom.get_atom_number(), a + 1);
}
}
}
#[test]
fn group_create_macro_protein() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.group_create("Protein", "@protein").unwrap();
assert!(system.group_exists("Protein"));
assert_eq!(system.group_get_n_atoms("Protein").unwrap(), 61);
for i in 0..=60 {
assert!(system.group_isin("Protein", i).unwrap());
}
}
#[test]
fn group_create_macro_membrane() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.group_create("Membrane", "@membrane").unwrap();
assert!(system.group_exists("Membrane"));
assert_eq!(system.group_get_n_atoms("Membrane").unwrap(), 6144);
for i in 61..=6204 {
assert!(system.group_isin("Membrane", i).unwrap());
}
}
#[test]
fn group_create_macro_membrane_cdl() {
let mut system = System::from_file("test_files/lipids_cdl.gro").unwrap();
system.group_create("Membrane", "@membrane").unwrap();
assert!(system.group_exists("Membrane"));
assert_eq!(system.group_get_n_atoms("Membrane").unwrap(), 10);
for i in 5..=14 {
assert!(system.group_isin("Membrane", i).unwrap());
}
}
#[test]
fn group_create_macro_water() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.group_create("Water", "@water").unwrap();
assert!(system.group_exists("Water"));
assert_eq!(system.group_get_n_atoms("Water").unwrap(), 10399);
for i in 6205..=16603 {
assert!(system.group_isin("Water", i).unwrap());
}
}
#[test]
fn group_create_macro_water_all_atom() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.group_create("Water", "@water").unwrap();
assert!(system.group_exists("Water"));
assert_eq!(system.group_get_n_atoms("Water").unwrap(), 15273);
for i in 17515..=32787 {
assert!(system.group_isin("Water", i).unwrap());
}
}
#[test]
fn group_create_macro_ion() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.group_create("Ion", "@ion").unwrap();
assert!(system.group_exists("Ion"));
assert_eq!(system.group_get_n_atoms("Ion").unwrap(), 240);
for i in 16604..=16843 {
assert!(system.group_isin("Ion", i).unwrap());
}
}
#[test]
fn group_create_macro_ion_all_atom() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system.group_create("Ion", "@ion").unwrap();
assert!(system.group_exists("Ion"));
assert_eq!(system.group_get_n_atoms("Ion").unwrap(), 29);
for i in 32788..=32816 {
assert!(system.group_isin("Ion", i).unwrap());
}
}
#[test]
fn group_create_macro_dna() {
let mut system = System::from_file("test_files/protein_with_dna.pdb").unwrap();
system.group_create("DNA", "@dna").unwrap();
assert!(system.group_exists("DNA"));
assert_eq!(system.group_get_n_atoms("DNA").unwrap(), 169);
for i in 0..=168 {
assert!(system.group_isin("DNA", i).unwrap());
}
}
#[test]
fn group_create_macro_rna() {
let mut system = System::from_file("test_files/rna.pdb").unwrap();
system.group_create("RNA", "@rna").unwrap();
assert!(system.group_exists("RNA"));
assert_eq!(system.group_get_n_atoms("RNA").unwrap(), 1108);
for i in 0..=1107 {
assert!(system.group_isin("RNA", i).unwrap());
}
}
#[test]
fn group_create_complex() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system.group_create(
"Complex Group",
"((serial 1 - 15 or atomnum 13 14 15 16 || atomnum 62 64 to 70) && Protein ION) or
(resid 11179 to 13000 or resnum 5400) and (resname W or (resname GLY LEU and (name BB or atomname SC1)))").unwrap();
assert_eq!(system.group_get_n_atoms("Complex Group").unwrap(), 2);
let mut iter = system.group_iter("Complex Group").unwrap();
assert_eq!(iter.next().unwrap().get_atom_number(), 1);
assert_eq!(iter.next().unwrap().get_atom_number(), 11064);
}
#[test]
fn group_create_atom_numbers() {
let mut system = System::from_file("test_files/example_renumbered.gro").unwrap();
system.group_create("Serial 6", "serial 6").unwrap();
system.group_create("Atomid 6", "atomnum 6").unwrap();
system.group_create("Atomnum 6", "atomnum 6").unwrap();
assert_eq!(
system.group_get_n_atoms("Serial 6"),
system.group_get_n_atoms("Atomid 6")
);
assert_eq!(
system.group_get_n_atoms("Serial 6"),
system.group_get_n_atoms("Atomnum 6")
);
assert!(system.group_isin("Serial 6", 5).unwrap());
assert!(system.group_isin("Atomid 6", 5).unwrap());
assert!(system.group_isin("Atomnum 6", 5).unwrap());
system.group_create("Serial 10", "serial 10").unwrap();
for atom in system.group_iter("Serial 10").unwrap() {
assert_eq!(atom.get_atom_number(), 49);
}
system.group_create("Atomid 49", "atomnum 49").unwrap();
assert_eq!(system.group_get_n_atoms("Atomid 49").unwrap(), 3);
assert!(system.group_isin("Atomid 49", 9).unwrap());
assert!(system.group_isin("Atomid 49", 24).unwrap());
assert!(system.group_isin("Atomid 49", 48).unwrap());
system.group_create("Atomnum 133", "atomnum 133").unwrap();
assert_eq!(system.group_get_n_atoms("Atomnum 133").unwrap(), 1);
system.group_create("Atomid 10", "atomnum 10").unwrap();
assert_eq!(system.group_get_n_atoms("Atomid 10").unwrap(), 0);
}
#[test]
fn group_create_labeled_atoms() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.label_atom("MyAtom 1", 654).unwrap();
system.label_atom("AtomX", 2464).unwrap();
system.label_atom("Different one", 52).unwrap();
system
.group_create("group 1", "label 'MyAtom 1' AtomX 'Different one'")
.unwrap();
let mut group1_iterator = system.group_iter("group 1").unwrap();
assert_eq!(group1_iterator.next().unwrap().get_atom_number(), 53);
assert_eq!(group1_iterator.next().unwrap().get_atom_number(), 655);
assert_eq!(group1_iterator.next().unwrap().get_atom_number(), 2465);
assert!(group1_iterator.next().is_none());
system.group_create("group 2", "label r'Atom'").unwrap();
let mut group2_iterator = system.group_iter("group 2").unwrap();
assert_eq!(group2_iterator.next().unwrap().get_atom_number(), 655);
assert_eq!(group2_iterator.next().unwrap().get_atom_number(), 2465);
assert!(group2_iterator.next().is_none());
system.group_create("water", "resname W").unwrap();
system
.group_create("group 3", "water or label 'MyAtom 1'")
.unwrap();
assert_eq!(
system.group_get_n_atoms("water").unwrap() + 1,
system.group_get_n_atoms("group 3").unwrap()
);
}
#[test]
fn group_create_from_geometry_cylinder() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let cylinder = Cylinder::new([5.0, 8.0, 3.0].into(), 2.0, 6.0, Dimension::Y);
system
.group_create_from_geometry("Selected Membrane", "Membrane", cylinder.clone())
.unwrap();
assert!(system.group_exists("Selected Membrane"));
assert_eq!(system.group_get_n_atoms("Selected Membrane").unwrap(), 206);
for atom in system.group_iter("Selected Membrane").unwrap() {
assert_eq!(atom.get_residue_name(), "POPC");
assert!(cylinder.inside(atom.get_position().unwrap(), system.get_box().unwrap()));
}
}
#[test]
fn group_create_from_geometry_sphere() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let sphere = Sphere::new([0.5, 4.5, 3.5].into(), 4.6);
system
.group_create_from_geometry("Selected Water", "resname W", sphere.clone())
.unwrap();
assert!(system.group_exists("Selected Water"));
assert_eq!(system.group_get_n_atoms("Selected Water").unwrap(), 1881);
for atom in system.group_iter("Selected Water").unwrap() {
assert_eq!(atom.get_residue_name(), "W");
assert!(sphere.inside(atom.get_position().unwrap(), system.get_box().unwrap()));
}
}
#[test]
fn group_create_from_geometry_rectangular() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let rectangular = Rectangular::new([5.0, 0.0, 2.0].into(), 5.0, 4.0, 4.3);
system
.group_create_from_geometry("Selected Protein", "@protein", rectangular.clone())
.unwrap();
assert!(system.group_exists("Selected Protein"));
assert_eq!(system.group_get_n_atoms("Selected Protein").unwrap(), 25);
for atom in system.group_iter("Selected Protein").unwrap() {
let resname = atom.get_residue_name();
assert!(
resname == "VAL"
|| resname == "LEU"
|| resname == "ALA"
|| resname == "LYS"
|| resname == "CYS"
);
assert!(rectangular.inside(atom.get_position().unwrap(), system.get_box().unwrap()));
}
}
#[test]
fn group_create_from_geometry_triangular_prism() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let base1 = Vector3D::new(8.0, 8.0, 8.0);
let base2 = Vector3D::new(15.0, 12.0, 8.0);
let base3 = Vector3D::new(9.5, 7.3, 8.0);
let triangular_prism = TriangularPrism::new(base1, base2, base3, 5.4);
system
.group_create_from_geometry("Selected Water", "@water", triangular_prism.clone())
.unwrap();
assert!(system.group_exists("Selected Water"));
assert_eq!(system.group_get_n_atoms("Selected Water").unwrap(), 213);
for atom in system.group_iter("Selected Water").unwrap() {
let resname = atom.get_residue_name();
assert_eq!(resname, "W");
assert!(
triangular_prism.inside(atom.get_position().unwrap(), system.get_box().unwrap())
);
}
}
#[test]
fn group_create_from_geometry_fails() {
let mut system = System::from_file("test_files/example.gro").unwrap();
let cylinder = Cylinder::new([5.0, 8.0, 3.0].into(), 2.0, 6.0, Dimension::Y);
match system.group_create_from_geometry("Selected Me>brane", "Membrane", cylinder.clone()) {
Ok(()) => panic!("Function should have failed."),
Err(GroupError::InvalidName(name)) => assert_eq!(name, "Selected Me>brane"),
Err(e) => panic!(
"Function failed but incorrect error type `{}` has been returned.",
e
),
}
match system.group_create_from_geometry("Selected Membrane", "brane", cylinder.clone()) {
Ok(()) => panic!("Function should have failed."),
Err(GroupError::InvalidQuery(SelectError::GroupNotFound(group))) => {
assert_eq!(group, "brane")
}
Err(e) => panic!(
"Function failed but incorrect error type `{}` has been returned.",
e
),
}
system.reset_box();
match system.group_create_from_geometry("Selection", "serial 1 to 5", cylinder.clone()) {
Ok(()) => panic!("Function should have failed."),
Err(GroupError::InvalidSimBox(SimBoxError::DoesNotExist)) => (),
Err(e) => panic!(
"Function failed but incorrect error type `{}` has been returned.",
e
),
}
}
#[test]
fn group_create_from_geometry_atoms_without_positions() {
let mut system = System::from_file("test_files/example.gro").unwrap();
for atom in system.atoms_iter_mut() {
atom.reset_position();
}
let rectangular = Rectangular::new([5.0, 0.0, 2.0].into(), 5.0, 4.0, 4.3);
system
.group_create_from_geometry("No atoms", "all", rectangular)
.unwrap();
assert_eq!(system.group_get_n_atoms("No atoms").unwrap(), 0);
}
#[test]
fn group_create_from_geometries_simple() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let cylinder = Cylinder::new([5.0, 8.0, 3.0].into(), 2.0, 6.0, Dimension::Y);
system
.group_create_from_geometry("Cylinder 1", "Membrane", cylinder.clone())
.unwrap();
system
.group_create_from_geometries("Cylinder 2", "Membrane", vec![Box::from(cylinder)])
.unwrap();
assert_eq!(
system.group_get_n_atoms("Cylinder 1").unwrap(),
system.group_get_n_atoms("Cylinder 2").unwrap()
);
for (a1, a2) in system
.group_iter("Cylinder 1")
.unwrap()
.zip(system.group_iter("Cylinder 2").unwrap())
{
assert_eq!(a1.get_atom_number(), a2.get_atom_number());
}
let sphere = Sphere::new([0.5, 4.5, 3.5].into(), 4.6);
system
.group_create_from_geometry("Sphere 1", "resname W", sphere.clone())
.unwrap();
system
.group_create_from_geometries("Sphere 2", "resname W", vec![Box::from(sphere)])
.unwrap();
assert_eq!(
system.group_get_n_atoms("Sphere 1").unwrap(),
system.group_get_n_atoms("Sphere 2").unwrap()
);
for (a1, a2) in system
.group_iter("Sphere 1")
.unwrap()
.zip(system.group_iter("Sphere 2").unwrap())
{
assert_eq!(a1.get_atom_number(), a2.get_atom_number());
}
let rectangular = Rectangular::new([5.0, 0.0, 2.0].into(), 5.0, 4.0, 4.3);
system
.group_create_from_geometry("Rectangular 1", "@protein", rectangular.clone())
.unwrap();
system
.group_create_from_geometries("Rectangular 2", "@protein", vec![Box::from(rectangular)])
.unwrap();
assert_eq!(
system.group_get_n_atoms("Rectangular 1").unwrap(),
system.group_get_n_atoms("Rectangular 2").unwrap()
);
for (a1, a2) in system
.group_iter("Rectangular 1")
.unwrap()
.zip(system.group_iter("Rectangular 2").unwrap())
{
assert_eq!(a1.get_atom_number(), a2.get_atom_number());
}
}
#[test]
fn group_create_from_geometries_complex() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let rectangular = Rectangular::new([5.0, 0.0, 2.0].into(), 5.0, 4.0, 4.3);
let sphere = Sphere::new([5.5, 0.5, 2.0].into(), 4.6);
let cylinder = Cylinder::new([5.0, 8.0, 3.0].into(), 2.0, 8.0, Dimension::Y);
system
.group_create_from_geometries(
"Selected Membrane",
"@membrane",
vec![
Box::from(rectangular.clone()),
Box::from(sphere.clone()),
Box::from(cylinder.clone()),
],
)
.unwrap();
assert!(system.group_exists("Selected Membrane"));
assert_eq!(system.group_get_n_atoms("Selected Membrane").unwrap(), 50);
let expected_numbers: [usize; 50] = [
3327, 3329, 3422, 3423, 3424, 3425, 3494, 3495, 3496, 3626, 3627, 3628, 3842, 3843,
3844, 3845, 3850, 4130, 4132, 4134, 4694, 4695, 4696, 4697, 4698, 4699, 5105, 5110,
5234, 5235, 5236, 5237, 5238, 5242, 5450, 5451, 5452, 5453, 5454, 5455, 5458, 5459,
5462, 5463, 5464, 5465, 5466, 5470, 5563, 5564,
];
for (i, atom) in system.group_iter("Selected Membrane").unwrap().enumerate() {
assert_eq!(atom.get_atom_number(), expected_numbers[i]);
assert!(rectangular.inside(atom.get_position().unwrap(), system.get_box().unwrap()));
assert!(sphere.inside(atom.get_position().unwrap(), system.get_box().unwrap()));
assert!(cylinder.inside(atom.get_position().unwrap(), system.get_box().unwrap()));
}
}
#[test]
fn group_create_from_geometries_fails() {
let mut system = System::from_file("test_files/example.gro").unwrap();
let rectangular = Rectangular::new([5.0, 0.0, 2.0].into(), 5.0, 4.0, 4.3);
let sphere = Sphere::new([5.5, 0.5, 2.0].into(), 4.6);
let cylinder = Cylinder::new([5.0, 8.0, 3.0].into(), 2.0, 8.0, Dimension::Y);
match system.group_create_from_geometries(
"Selected Me>brane",
"Membrane",
vec![
Box::from(rectangular.clone()),
Box::from(sphere.clone()),
Box::from(cylinder.clone()),
],
) {
Ok(()) => panic!("Function should have failed."),
Err(GroupError::InvalidName(name)) => assert_eq!(name, "Selected Me>brane"),
Err(e) => panic!(
"Function failed but incorrect error type `{}` has been returned.",
e
),
}
match system.group_create_from_geometries(
"Selected Membrane",
"brane",
vec![
Box::from(rectangular.clone()),
Box::from(sphere.clone()),
Box::from(cylinder.clone()),
],
) {
Ok(()) => panic!("Function should have failed."),
Err(GroupError::InvalidQuery(SelectError::GroupNotFound(group))) => {
assert_eq!(group, "brane")
}
Err(e) => panic!(
"Function failed but incorrect error type `{}` has been returned.",
e
),
}
system.reset_box();
match system.group_create_from_geometries(
"Selected",
"serial 1 to 5",
vec![
Box::from(rectangular.clone()),
Box::from(sphere.clone()),
Box::from(cylinder.clone()),
],
) {
Ok(()) => panic!("Function should have failed."),
Err(GroupError::InvalidSimBox(SimBoxError::DoesNotExist)) => (),
Err(e) => panic!(
"Function failed but incorrect error type `{}` has been returned.",
e
),
}
}
#[test]
fn group_create_from_geometries_atoms_without_positions() {
let mut system = System::from_file("test_files/example.gro").unwrap();
for atom in system.atoms_iter_mut() {
atom.reset_position();
}
let rectangular = Rectangular::new([5.0, 0.0, 2.0].into(), 5.0, 4.0, 4.3);
let sphere = Sphere::new([5.5, 0.5, 2.0].into(), 4.6);
let cylinder = Cylinder::new([5.0, 8.0, 3.0].into(), 2.0, 8.0, Dimension::Y);
system
.group_create_from_geometries(
"No atoms",
"all",
vec![
Box::from(rectangular),
Box::from(sphere),
Box::from(cylinder),
],
)
.unwrap();
assert_eq!(system.group_get_n_atoms("No atoms").unwrap(), 0);
}
#[test]
fn group_create_open_ended_ranges() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.group_create("Group1", "resid < 380").unwrap();
assert!(system.group_exists("Group1"));
assert_eq!(system.group_get_n_atoms("Group1").unwrap(), 4261);
for i in 0..4261 {
assert!(system.group_isin("Group1", i).unwrap());
}
system.group_create("Group2", "resid <= 380").unwrap();
assert!(system.group_exists("Group2"));
assert_eq!(system.group_get_n_atoms("Group2").unwrap(), 4273);
for i in 0..4273 {
assert!(system.group_isin("Group2", i).unwrap());
}
system.group_create("Group3", "serial > 9143").unwrap();
assert!(system.group_exists("Group3"));
assert_eq!(system.group_get_n_atoms("Group3").unwrap(), 7701);
for i in 9143..16844 {
assert!(system.group_isin("Group3", i).unwrap());
}
system.group_create("Group4", "serial >= 9143").unwrap();
assert!(system.group_exists("Group4"));
assert_eq!(system.group_get_n_atoms("Group4").unwrap(), 7702);
for i in 9142..16844 {
assert!(system.group_isin("Group4", i).unwrap());
}
system
.group_create("Group 5", "serial <= 10000 10005-10010")
.unwrap();
assert!(system.group_exists("Group 5"));
assert_eq!(system.group_get_n_atoms("Group 5").unwrap(), 10006);
for i in 0..10000 {
assert!(system.group_isin("Group 5", i).unwrap());
}
for i in 10004..10010 {
assert!(system.group_isin("Group 5", i).unwrap());
}
}
#[test]
fn group_create_regex() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system
.group_create("LysLeuAla", "resname r'^[LA].*'")
.unwrap();
assert!(system.group_exists("LysLeuAla"));
assert_eq!(system.group_get_n_atoms("LysLeuAla").unwrap(), 36);
assert!(system.group_isin("LysLeuAla", 1).unwrap());
assert!(system.group_isin("LysLeuAla", 58).unwrap());
system
.group_create("Tails", "resname POPC and name r'^[CD][124][AB]'")
.unwrap();
assert!(system.group_exists("Tails"));
assert_eq!(system.group_get_n_atoms("Tails").unwrap(), 3072);
assert!(system.group_isin("Tails", 65).unwrap());
assert!(system.group_isin("Tails", 6204).unwrap());
system
.group_create("Group3", "resname r'^..PC' r'L'")
.unwrap();
assert!(system.group_exists("Group3"));
assert_eq!(system.group_get_n_atoms("Group3").unwrap(), 6203);
assert!(system.group_isin("Group3", 0).unwrap());
assert!(system.group_isin("Group3", 6204).unwrap());
}
#[test]
fn group_create_regex_with_operator() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system
.group_create(
"Selection",
"resname POPC and (name r'C[1234]A|C[1234]B' or name D2A)",
)
.unwrap();
assert!(system.group_exists("Selection"));
assert_eq!(system.group_get_n_atoms("Selection").unwrap(), 4096);
assert!(system.group_isin("Selection", 78).unwrap());
assert!(system.group_isin("Selection", 79).unwrap());
assert!(system.group_isin("Selection", 80).unwrap());
assert!(system.group_isin("Selection", 81).unwrap());
}
#[test]
fn group_create_regex_aa() {
let mut system = System::from_file("test_files/aa_membrane_peptide.gro").unwrap();
system
.group_create("Hydrogens", "name r'^[1-9]?H.*'")
.unwrap();
assert!(system.group_exists("Hydrogens"));
assert_eq!(system.group_get_n_atoms("Hydrogens").unwrap(), 20875);
assert!(system.group_isin("Hydrogens", 32787).unwrap());
assert!(system.group_isin("Hydrogens", 1).unwrap());
}
#[test]
fn group_create_regex_groups() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system.group_create("Regex1", "r'^Transmembrane'").unwrap();
assert!(system.group_exists("Regex1"));
assert_eq!(system.group_get_n_atoms("Regex1").unwrap(), 61);
assert!(system.group_isin("Regex1", 0).unwrap());
assert!(system.group_isin("Regex1", 60).unwrap());
assert!(!system.group_isin("Regex1", 61).unwrap());
system.group_create("Regex2", "r'^Transmembrane$'").unwrap();
assert!(system.group_exists("Regex2"));
assert_eq!(system.group_get_n_atoms("Regex2").unwrap(), 29);
assert!(system.group_isin("Regex2", 0).unwrap());
assert!(system.group_isin("Regex2", 59).unwrap());
assert!(!system.group_isin("Regex2", 60).unwrap());
system.group_create("Regex3", "group r'^P' ION").unwrap();
assert!(system.group_exists("Regex3"));
assert_eq!(system.group_get_n_atoms("Regex3").unwrap(), 6445);
assert!(system.group_isin("Regex3", 0).unwrap());
assert!(system.group_isin("Regex3", 16843).unwrap());
assert!(!system.group_isin("Regex3", 16603).unwrap());
assert!(!system.group_isin("Regex3", 6205).unwrap());
system
.group_create("Regex4", "group r'^P' r'^X' ION")
.unwrap();
assert!(system.group_exists("Regex4"));
assert_eq!(system.group_get_n_atoms("Regex4").unwrap(), 6445);
assert!(system.group_isin("Regex4", 0).unwrap());
assert!(system.group_isin("Regex4", 16843).unwrap());
assert!(!system.group_isin("Regex4", 16603).unwrap());
assert!(!system.group_isin("Regex4", 6205).unwrap());
match system.group_create("Regex5", "group r'X'") {
Ok(_) => panic!("Should have failed."),
Err(GroupError::InvalidQuery(SelectError::NoRegexMatch(e))) => assert_eq!(e, "X"),
Err(e) => panic!("Incorrect error type '{}' returned", e),
}
assert!(!system.group_exists("Regex5"));
}
#[test]
fn group_create_invalid_names() {
let mut system = System::from_file("test_files/example.gro").unwrap();
let names = vec![
"Invalid&name",
"Invalid| name",
"Invalid(name",
"Invalid)name",
"Invalidn@me",
"!nvalidname",
"Inval'idname",
"Inval\"idname",
" ",
"Inval=idname",
"Inval<idname",
">Invalidname",
];
for name in names {
assert_eq!(
system.group_create(name, "serial 1 to 3"),
Err(GroupError::InvalidName(name.to_string()))
);
assert!(!system.group_exists(name));
}
}
#[test]
fn group_create_from_indices() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system
.group_create_from_indices("Test", vec![1, 3, 3, 6, 8])
.unwrap();
assert!(system.group_exists("Test"));
assert_eq!(system.group_get_n_atoms("Test").unwrap(), 4);
match system.group_create_from_indices("Test", vec![1, 10, 11, 12, 13]) {
Err(GroupError::AlreadyExistsWarning(e)) => assert_eq!(e, "Test"),
Ok(_) => panic!("Warning should have been returned, but it was not."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert!(system.group_exists("Test"));
assert_eq!(system.group_get_n_atoms("Test").unwrap(), 5);
}
#[test]
fn group_create_from_indices_invalid_names() {
let mut system = System::from_file("test_files/example.gro").unwrap();
let names = vec![
"Invalid&name",
"Invalid| name",
"Invalid(name",
"Invalid)name",
"Invalidn@me",
"!nvalidname",
"Inval'idname",
"Inval\"idname",
" ",
"Inval=idname",
"Inval<idname",
">Invalidname",
];
for name in names {
assert_eq!(
system.group_create_from_indices(name, vec![1, 3, 3, 6, 8]),
Err(GroupError::InvalidName(name.to_string()))
);
assert!(!system.group_exists(name));
}
}
#[test]
fn group_create_from_ranges() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system
.group_create_from_ranges("Test", vec![(0, 15), (10, 20)])
.unwrap();
assert!(system.group_exists("Test"));
assert_eq!(system.group_get_n_atoms("Test").unwrap(), 21);
match system.group_create_from_ranges("Test", vec![(10, 15)]) {
Err(GroupError::AlreadyExistsWarning(e)) => assert_eq!(e, "Test"),
Ok(_) => panic!("Warning should have been returned, but it was not."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert!(system.group_exists("Test"));
assert_eq!(system.group_get_n_atoms("Test").unwrap(), 6);
}
#[test]
fn group_create_from_ranges_invalid_names() {
let mut system = System::from_file("test_files/example.gro").unwrap();
let names = vec![
"Invalid&name",
"Invalid| name",
"Invalid(name",
"Invalid)name",
"Invalidn@me",
"!nvalidname",
"Inval'idname",
"Inval\"idname",
" ",
"Inval=idname",
"Inval<idname",
">Invalidname",
];
for name in names {
assert_eq!(
system.group_create_from_ranges(name, vec![(0, 15), (10, 20)]),
Err(GroupError::InvalidName(name.to_string()))
);
assert!(!system.group_exists(name));
}
}
#[test]
fn group_isin_basic() {
let system = System::from_file("test_files/example.gro").unwrap();
for i in 0..system.get_n_atoms() {
assert!(system
.group_isin("all", i)
.expect("Group `all` does not exist but it should."));
}
}
#[test]
fn group_isin_advanced() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
for i in 0..=60 {
assert!(system
.group_isin("Transmembrane_all", i)
.expect("Group `Transmembrane_all` does not exist but it should."));
}
for i in 61..=6204 {
assert!(system
.group_isin("Membrane", i)
.expect("Group `Membrane` does not exist but it should."));
}
for i in 16604..=16843 {
assert!(system
.group_isin("ION", i)
.expect("Group `ION` does not exist but it should."));
}
}
#[test]
fn group_isin_fails() {
let system = System::from_file("test_files/example.gro").unwrap();
assert_eq!(
system.group_isin("Transmembrane_all", 100),
Err(GroupError::NotFound("Transmembrane_all".to_string()))
);
assert_eq!(
system.group_isin("Protein", 200),
Err(GroupError::NotFound("Protein".to_string()))
);
assert_eq!(
system.group_isin("ION", 250),
Err(GroupError::NotFound("ION".to_string()))
);
}
#[test]
fn split_by_resid() {
let mut system = System::from_file("test_files/example.gro").unwrap();
let (code, residues) = system.atoms_split_by_resid();
if code.is_err() {
panic!("Overlapping groups in atoms_split_by_resid.");
}
assert_eq!(residues.len(), 11180);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() > 0);
}
assert_eq!(system.group_get_n_atoms("resid 1").unwrap(), 1);
assert_eq!(system.group_get_n_atoms("resid 6").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resid 27").unwrap(), 3);
assert_eq!(system.group_get_n_atoms("resid 11180").unwrap(), 1);
for i in 1..=11180 {
let resname = format!("resid {}", i);
assert_eq!(residues[i - 1], resname);
}
}
#[test]
fn split_by_resid_warnings() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system
.read_ndx("test_files/index_group_by_res.ndx")
.unwrap();
let (code, residues) = system.atoms_split_by_resid();
match code {
Err(GroupError::MultipleAlreadyExistWarning(e)) => assert_eq!(
e,
Box::new(HashSet::from([
"resid 6".to_string(),
"resid 27".to_string(),
"resid 11180".to_string()
]))
),
Ok(_) => panic!("Warning should have been returned, but it was not."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert_eq!(residues.len(), 11180);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() > 0);
}
assert_eq!(system.group_get_n_atoms("resid 1").unwrap(), 1);
assert_eq!(system.group_get_n_atoms("resid 6").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resid 27").unwrap(), 3);
assert_eq!(system.group_get_n_atoms("resid 11180").unwrap(), 1);
}
#[test]
fn split_by_resid_broken() {
let mut system = System::from_file("test_files/example_shuffled_residues.gro").unwrap();
let (code, residues) = system.atoms_split_by_resid();
if code.is_err() {
panic!("Overlapping groups in atoms_split_by_resid.");
}
assert_eq!(residues.len(), 21);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() > 0);
}
let expected_n = [
2, 3, 2, 2, 3, 2, 1, 2, 2, 4, 2, 2, 1, 3, 2, 4, 3, 2, 2, 3, 3,
];
for i in 1..=21 {
let resname = format!("resid {}", i);
assert_eq!(
expected_n[i - 1],
system.group_get_n_atoms(&resname).unwrap()
);
}
assert_eq!(residues[0], "resid 20");
assert_eq!(residues[1], "resid 1");
assert_eq!(residues[20], "resid 21");
}
#[test]
fn group_split_by_resid() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let (code, residues) = system.group_split_by_resid("Protein");
if code.is_err() {
panic!("Error occured when using `System::group_split_by_resid`");
}
assert_eq!(residues.len(), 29);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() > 0);
}
assert_eq!(system.group_get_n_atoms("resid 1").unwrap(), 1);
assert_eq!(system.group_get_n_atoms("resid 2").unwrap(), 3);
assert_eq!(system.group_get_n_atoms("resid 15").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resid 29").unwrap(), 2);
for i in 1..=29 {
let resname = format!("resid {}", i);
assert_eq!(residues[i - 1], resname);
}
}
#[test]
fn group_split_by_resid_not_first_group() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let (code, residues) = system.group_split_by_resid("Membrane");
if code.is_err() {
panic!("Error occured when using `System::group_split_by_resid`");
}
assert_eq!(residues.len(), 512);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() == 12);
}
for i in 30..=541 {
let resname = format!("resid {}", i);
assert_eq!(residues[i - 30], resname);
}
}
#[test]
fn group_split_by_resid_warnings() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system
.read_ndx("test_files/index_group_by_res.ndx")
.unwrap();
let (code, residues) = system.group_split_by_resid("Protein");
match code {
Err(GroupError::MultipleAlreadyExistWarning(e)) => assert_eq!(
e,
Box::new(HashSet::from([
"resid 6".to_string(),
"resid 27".to_string(),
]))
),
Ok(_) => panic!("Warning should have been returned, but it was not."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert_eq!(residues.len(), 29);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() > 0);
}
assert_eq!(system.group_get_n_atoms("resid 1").unwrap(), 1);
assert_eq!(system.group_get_n_atoms("resid 2").unwrap(), 3);
assert_eq!(system.group_get_n_atoms("resid 15").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resid 29").unwrap(), 2);
for i in 1..=29 {
let resname = format!("resid {}", i);
assert_eq!(residues[i - 1], resname);
}
}
#[test]
fn group_split_by_resid_nonexistent() {
let mut system = System::from_file("test_files/example.gro").unwrap();
let (code, residues) = system.group_split_by_resid("Protein");
match code {
Err(GroupError::NotFound(e)) => assert_eq!(e, "Protein"),
Ok(_) => panic!("Function should have failed but it succeeded."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert_eq!(residues.len(), 0);
}
#[test]
fn split_by_resname() {
let mut system = System::from_file("test_files/example.gro").unwrap();
let (code, residues) = system.atoms_split_by_resname();
if code.is_err() {
panic!("Overlapping groups in atoms_split_by_resname.");
}
assert_eq!(residues.len(), 9);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() > 0);
}
assert_eq!(system.group_get_n_atoms("resname GLY").unwrap(), 1);
assert_eq!(system.group_get_n_atoms("resname LYS").unwrap(), 12);
assert_eq!(system.group_get_n_atoms("resname VAL").unwrap(), 22);
assert_eq!(system.group_get_n_atoms("resname LEU").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resname ALA").unwrap(), 22);
assert_eq!(system.group_get_n_atoms("resname CYS").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resname POPC").unwrap(), 6144);
assert_eq!(system.group_get_n_atoms("resname W").unwrap(), 10399);
assert_eq!(system.group_get_n_atoms("resname ION").unwrap(), 240);
}
#[test]
fn split_by_resname_warnings() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system
.read_ndx("test_files/index_group_by_resname.ndx")
.unwrap();
let (code, residues) = system.atoms_split_by_resname();
match code {
Err(GroupError::MultipleAlreadyExistWarning(e)) => assert_eq!(
e,
Box::new(HashSet::from([
"resname POPC".to_string(),
"resname LYS".to_string(),
"resname W".to_string()
]))
),
Ok(_) => panic!("Warning should have been returned, but it was not."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert_eq!(residues.len(), 9);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() > 0);
}
assert_eq!(system.group_get_n_atoms("resname GLY").unwrap(), 1);
assert_eq!(system.group_get_n_atoms("resname LYS").unwrap(), 12);
assert_eq!(system.group_get_n_atoms("resname VAL").unwrap(), 22);
assert_eq!(system.group_get_n_atoms("resname LEU").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resname ALA").unwrap(), 22);
assert_eq!(system.group_get_n_atoms("resname CYS").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resname POPC").unwrap(), 6144);
assert_eq!(system.group_get_n_atoms("resname W").unwrap(), 10399);
assert_eq!(system.group_get_n_atoms("resname ION").unwrap(), 240);
}
#[test]
fn group_split_by_resname() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let (code, residues) = system.group_split_by_resname("Protein");
if code.is_err() {
panic!("Error occured when using `System::group_split_by_resname`");
}
assert_eq!(residues.len(), 6);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() > 0);
}
assert_eq!(system.group_get_n_atoms("resname GLY").unwrap(), 1);
assert_eq!(system.group_get_n_atoms("resname LYS").unwrap(), 12);
assert_eq!(system.group_get_n_atoms("resname VAL").unwrap(), 22);
assert_eq!(system.group_get_n_atoms("resname LEU").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resname ALA").unwrap(), 22);
assert_eq!(system.group_get_n_atoms("resname CYS").unwrap(), 2);
}
#[test]
fn group_split_by_resname_not_first_group() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system
.group_create("Membrane + Water", "Membrane or resname W")
.unwrap();
let (code, residues) = system.group_split_by_resname("Membrane + Water");
if code.is_err() {
panic!("Error occured when using `System::group_split_by_resname`");
}
assert_eq!(residues.len(), 2);
assert_eq!(system.group_get_n_atoms("resname POPC").unwrap(), 6144);
assert_eq!(system.group_get_n_atoms("resname W").unwrap(), 10399);
}
#[test]
fn group_split_by_resname_warnings() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system
.read_ndx("test_files/index_group_by_resname.ndx")
.unwrap();
let (code, residues) = system.group_split_by_resname("Protein");
match code {
Err(GroupError::MultipleAlreadyExistWarning(e)) => {
assert_eq!(e, Box::new(HashSet::from(["resname LYS".to_string(),])))
}
Ok(_) => panic!("Warning should have been returned, but it was not."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert_eq!(residues.len(), 6);
for groupname in residues.iter() {
assert!(system.group_exists(groupname));
assert!(system.group_get_n_atoms(groupname).unwrap() > 0);
}
assert_eq!(system.group_get_n_atoms("resname GLY").unwrap(), 1);
assert_eq!(system.group_get_n_atoms("resname LYS").unwrap(), 12);
assert_eq!(system.group_get_n_atoms("resname VAL").unwrap(), 22);
assert_eq!(system.group_get_n_atoms("resname LEU").unwrap(), 2);
assert_eq!(system.group_get_n_atoms("resname ALA").unwrap(), 22);
assert_eq!(system.group_get_n_atoms("resname CYS").unwrap(), 2);
}
#[test]
fn group_split_by_resname_nonexistent() {
let mut system = System::from_file("test_files/example.gro").unwrap();
let (code, residues) = system.group_split_by_resname("Protein");
match code {
Err(GroupError::NotFound(e)) => assert_eq!(e, "Protein"),
Ok(_) => panic!("Function should have failed but it succeeded."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert_eq!(residues.len(), 0);
}
#[test]
fn group_make_writable() {
let mut system = System::from_file("test_files/example.gro").unwrap();
assert!(!system.get_groups().get("all").unwrap().print_ndx);
system.group_make_writable("all").unwrap();
assert!(system.get_groups().get("all").unwrap().print_ndx);
}
#[test]
fn group_make_writable_nonexistent() {
let mut system = System::from_file("test_files/example.gro").unwrap();
match system.group_make_writable("Protein") {
Ok(_) => panic!("Group should not exist."),
Err(e) => assert_eq!(e, GroupError::NotFound(String::from("Protein"))),
}
}
#[test]
fn group_make_nonwritable() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.group_create("Group", "resid 1").unwrap();
assert!(system.get_groups().get("Group").unwrap().print_ndx);
system.group_make_nonwritable("Group").unwrap();
assert!(!system.get_groups().get("Group").unwrap().print_ndx);
}
#[test]
fn group_make_nonwritable_nonexistent() {
let mut system = System::from_file("test_files/example.gro").unwrap();
match system.group_make_nonwritable("Protein") {
Ok(_) => panic!("Group should not exist."),
Err(e) => assert_eq!(e, GroupError::NotFound(String::from("Protein"))),
}
}
#[test]
fn group_union_simple() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system.group_union("Protein", "W", "Protein_W").unwrap();
assert!(system.group_exists("Protein_W"));
assert_eq!(
system.group_get_n_atoms("Protein_W").unwrap(),
system.group_get_n_atoms("Protein").unwrap() + system.group_get_n_atoms("W").unwrap()
);
}
#[test]
fn group_union_overlap() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system
.group_union("Membrane", "System", "Membrane_System")
.unwrap();
assert!(system.group_exists("Membrane_System"));
assert_eq!(
system.group_get_n_atoms("Membrane_System").unwrap(),
system.group_get_n_atoms("System").unwrap()
);
}
#[test]
fn group_union_already_exists() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_union("Protein", "ION", "W_ION") {
Err(GroupError::AlreadyExistsWarning(e)) => assert_eq!(e, "W_ION"),
Ok(_) => panic!("Warning should have been returned, but it was not."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert_eq!(
system.group_get_n_atoms("W_ION").unwrap(),
system.group_get_n_atoms("Protein").unwrap() + system.group_get_n_atoms("ION").unwrap()
);
}
#[test]
fn group_union_invalid_group1() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_union("Nonexistent", "ION", "Test") {
Err(GroupError::NotFound(e)) => assert_eq!(e, "Nonexistent"),
Ok(_) => panic!("Creating union should have failed, but it was successful."),
Err(e) => panic!(
"Failed successfully but incorrect error type `{:?}` was returned.",
e
),
}
assert!(!system.group_exists("Test"));
}
#[test]
fn group_union_invalid_group2() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_union("ION", "Nonexistent", "Test") {
Err(GroupError::NotFound(e)) => assert_eq!(e, "Nonexistent"),
Ok(_) => panic!("Creating union should have failed, but it was successful."),
Err(e) => panic!(
"Failed successfully but incorrect error type `{:?}` was returned.",
e
),
}
assert!(!system.group_exists("Test"));
}
#[test]
fn group_union_invalid_group_name() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_union("Protein", "W", "Protein()W") {
Err(GroupError::InvalidName(x)) => assert_eq!(x, "Protein()W"),
Ok(_) => panic!("Creating union should have failed but it was successful."),
Err(e) => panic!(
"Failed successfully but incorrect error type `{:?}` was returned.",
e
),
}
assert!(!system.group_exists("Protein()W"));
}
#[test]
fn group_intersection_simple() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system
.group_intersection("Protein", "Transmembrane", "Protein X Transmembrane")
.unwrap();
assert!(system.group_exists("Protein X Transmembrane"));
assert_eq!(
system.group_get_n_atoms("Protein X Transmembrane").unwrap(),
system.group_get_n_atoms("Transmembrane").unwrap()
);
}
#[test]
fn group_intersection_empty() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system
.group_intersection("Protein", "W", "Protein X W")
.unwrap();
assert!(system.group_exists("Protein X W"));
assert_eq!(system.group_get_n_atoms("Protein X W").unwrap(), 0);
}
#[test]
fn group_intersection_already_exists() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_intersection("Protein", "Transmembrane", "Other") {
Err(GroupError::AlreadyExistsWarning(e)) => assert_eq!(e, "Other"),
Ok(_) => panic!("Warning should have been returned, but it was not."),
Err(e) => panic!("Incorrect error type `{:?}` was returned.", e),
}
assert_eq!(
system.group_get_n_atoms("Other").unwrap(),
system.group_get_n_atoms("Transmembrane").unwrap()
);
}
#[test]
fn group_intersection_invalid_group1() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_intersection("Nonexistent", "ION", "Test") {
Err(GroupError::NotFound(e)) => assert_eq!(e, "Nonexistent"),
Ok(_) => panic!("Creating intersection should have failed, but it was successful."),
Err(e) => panic!(
"Failed successfully but incorrect error type `{:?}` was returned.",
e
),
}
assert!(!system.group_exists("Test"));
}
#[test]
fn group_intersection_invalid_group2() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_intersection("ION", "Nonexistent", "Test") {
Err(GroupError::NotFound(e)) => assert_eq!(e, "Nonexistent"),
Ok(_) => panic!("Creating intersection should have failed, but it was successful."),
Err(e) => panic!(
"Failed successfully but incorrect error type `{:?}` was returned.",
e
),
}
assert!(!system.group_exists("Test"));
}
#[test]
fn group_intersection_invalid_group_name() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_intersection("Protein", "Transmembrane", "@ProteinTransmembrane") {
Err(GroupError::InvalidName(x)) => assert_eq!(x, "@ProteinTransmembrane"),
Ok(_) => panic!("Creating intersection should have failed but it was successful."),
Err(e) => panic!(
"Failed successfully but incorrect error type `{:?}` was returned.",
e
),
}
assert!(!system.group_exists("@ProteinTransmembrane"));
}
#[test]
fn group_extend_simple() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let old_n_atoms = system.group_get_n_atoms("Protein").unwrap();
system.group_extend("Protein", "ION").unwrap();
assert_eq!(
system.group_get_n_atoms("Protein").unwrap(),
old_n_atoms + system.group_get_n_atoms("ION").unwrap()
);
}
#[test]
fn group_extend_overlap() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let old_n_atoms = system.group_get_n_atoms("Protein_Membrane").unwrap();
system.group_extend("Protein_Membrane", "Membrane").unwrap();
assert_eq!(
system.group_get_n_atoms("Protein_Membrane").unwrap(),
old_n_atoms
);
}
#[test]
fn group_names() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system.group_create("Custom Group", "resname LYS").unwrap();
let names = system.group_names();
assert_eq!(names.len(), 24);
for name in names {
assert!(system.group_exists(&name));
}
}
#[test]
fn group_names_writable() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system.group_create("Custom Group", "resname LYS").unwrap();
let names = system.group_names_writable();
assert_eq!(names.len(), 22);
for name in &names {
assert!(system.group_exists(name));
}
assert!(!names.contains(&"All".to_string()));
assert!(!names.contains(&"all".to_string()));
system.group_make_nonwritable("Custom Group").unwrap();
let new_names = system.group_names_writable();
assert_eq!(new_names.len(), 21);
assert!(!new_names.contains(&"Custom Group".to_string()));
}
#[test]
fn group_remove() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system.group_remove("Protein").unwrap();
assert!(!system.group_exists("Protein"));
}
#[test]
fn group_remove_nonexistent() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_remove("Proin") {
Err(GroupError::NotFound(e)) => assert_eq!("Proin", e),
Ok(_) => panic!("Function should have failed, but it was successful."),
Err(e) => panic!("Incorrect error type returned: {:?}", e),
}
}
#[test]
fn group_rename() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
system.group_rename("Protein", "My Protein Group").unwrap();
assert!(!system.group_exists("Protein"));
assert!(system.group_exists("My Protein Group"));
for index in 0..61 {
assert!(system.group_isin("My Protein Group", index).unwrap());
}
}
#[test]
fn group_rename_nonexistent() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_rename("Proin", "Protein") {
Err(GroupError::NotFound(e)) => assert_eq!("Proin", e),
Ok(_) => panic!("Function should have failed, but it was successful."),
Err(e) => panic!("Incorrect error type returned: {:?}", e),
}
}
#[test]
fn group_rename_overwrite() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
match system.group_rename("Protein", "Membrane") {
Err(GroupError::AlreadyExistsWarning(e)) => assert_eq!("Membrane", e),
Ok(_) => panic!("Function should have raised warning, but it did not."),
Err(e) => panic!("Incorrect error type returned: {:?}", e),
}
assert!(!system.group_exists("Protein"));
assert!(system.group_exists("Membrane"));
for index in 0..61 {
assert!(system.group_isin("Membrane", index).unwrap());
}
}
#[test]
fn group_isempty() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system
.group_create("Membrane", "@membrane and name PO4")
.unwrap();
system.group_create("Single", "serial 15").unwrap();
system.group_create("Empty", "resname NON").unwrap();
assert!(!system.group_isempty("Membrane").unwrap());
assert!(!system.group_isempty("Single").unwrap());
assert!(system.group_isempty("Empty").unwrap());
match system.group_isempty("Nonexistent") {
Ok(_) => panic!("Function should have failed."),
Err(GroupError::NotFound(x)) => assert_eq!(x, "Nonexistent"),
Err(e) => panic!("Incorrect error type returned: {:?}", e),
}
}
#[test]
fn groups_member() {
let mut system = System::from_file("test_files/example.gro").unwrap();
system.read_ndx("test_files/index.ndx").unwrap();
let expected_groups = vec![
"all",
"All",
"System",
"Protein",
"Protein-H",
"SideChain",
"SideChain-H",
"Prot-Masses",
"Transmembrane_all",
"Transmembrane",
"Protein_Membrane",
];
let groups = system.groups_member(1);
assert_eq!(expected_groups.len(), groups.len());
for (expected, result) in expected_groups.into_iter().zip(groups.iter()) {
assert_eq!(expected, result)
}
let groups = system.groups_member(16844);
assert!(groups.is_empty());
}
#[test]
fn groups_update_simple() {
let mut groups1 = Groups::default();
groups1
.add("Membrane", Group::from_indices(vec![1, 2, 3, 5], 100))
.unwrap();
groups1
.add("Protein", Group::from_indices(vec![4, 6, 10, 15, 20], 100))
.unwrap();
let groups2 = Groups::default();
groups1.update(groups2).unwrap();
assert_eq!(groups1.n_groups(), 2);
assert_eq!(groups1.get_n_atoms("Membrane").unwrap(), 4);
assert_eq!(groups1.get_n_atoms("Protein").unwrap(), 5);
let mut groups2 = Groups::default();
groups2
.add("Water", Group::from_indices(vec![21, 22, 24], 100))
.unwrap();
groups1.update(groups2).unwrap();
assert_eq!(groups1.n_groups(), 3);
assert_eq!(groups1.get_n_atoms("Membrane").unwrap(), 4);
assert_eq!(groups1.get_n_atoms("Protein").unwrap(), 5);
assert_eq!(groups1.get_n_atoms("Water").unwrap(), 3);
}
#[test]
fn groups_update_overwrite_single() {
let mut groups1 = Groups::default();
groups1
.add("Membrane", Group::from_indices(vec![1, 2, 3, 5], 100))
.unwrap();
groups1
.add("Protein", Group::from_indices(vec![4, 6, 10, 15, 20], 100))
.unwrap();
let mut groups2 = Groups::default();
groups2
.add("Protein", Group::from_indices(vec![4, 6], 100))
.unwrap();
match groups1.update(groups2) {
Ok(_) => panic!("Function should have returned a warning."),
Err(GroupError::MultipleAlreadyExistWarning(x)) => {
assert_eq!(x.len(), 1);
assert!(x.contains("Protein"));
}
Err(e) => panic!("Unexpected error type `{}` returned.", e),
}
assert_eq!(groups1.n_groups(), 2);
assert_eq!(groups1.get_n_atoms("Membrane").unwrap(), 4);
assert_eq!(groups1.get_n_atoms("Protein").unwrap(), 2);
}
#[test]
fn groups_update_overwrite_multiple() {
let mut groups1 = Groups::default();
groups1
.add("Membrane", Group::from_indices(vec![1, 2, 3, 5], 100))
.unwrap();
groups1
.add("Protein", Group::from_indices(vec![4, 6, 10, 15, 20], 100))
.unwrap();
let mut groups2 = Groups::default();
groups2
.add("Membrane", Group::from_indices(vec![], 100))
.unwrap();
groups2
.add("Protein", Group::from_indices(vec![4, 6], 100))
.unwrap();
match groups1.update(groups2) {
Ok(_) => panic!("Function should have returned a warning."),
Err(GroupError::MultipleAlreadyExistWarning(x)) => {
assert_eq!(x.len(), 2);
assert!(x.contains("Protein"));
assert!(x.contains("Membrane"));
}
Err(e) => panic!("Unexpected error type `{}` returned.", e),
}
assert_eq!(groups1.n_groups(), 2);
assert_eq!(groups1.get_n_atoms("Membrane").unwrap(), 0);
assert_eq!(groups1.get_n_atoms("Protein").unwrap(), 2);
}
}