use super::info::AtomInfo;
use crate::info::constants::{is_amino_acid, is_carbohydrate, is_nucleotide};
use crate::selection::{AtomView, Selection};
use crate::AtomCollection;
use pdbtbx::Element;
pub struct ResidueAtoms<'a> {
pub start_idx: usize,
pub end_idx: usize,
pub res_id: i32,
pub res_name: String,
pub chain_id: String,
pub atoms: Selection,
pub parent: &'a AtomCollection,
}
impl<'a> ResidueAtoms<'a> {
pub fn coords(&self) -> Vec<&[f32; 3]> {
(self.start_idx..self.end_idx)
.map(|i| self.parent.get_coord(i))
.collect()
}
pub fn atom_names(&self) -> Vec<&String> {
(self.start_idx..self.end_idx)
.map(|i| self.parent.get_atom_name(i))
.collect()
}
pub fn elements(&self) -> Vec<&Element> {
(self.start_idx..self.end_idx)
.map(|i| self.parent.get_element(i))
.collect()
}
pub fn view(&self) -> AtomView {
self.parent.view(self.atoms.clone())
}
pub fn atom_count(&self) -> usize {
self.end_idx - self.start_idx
}
pub fn iter_atoms(&self) -> impl Iterator<Item = AtomInfo> + '_ {
(self.start_idx..self.end_idx).map(|i| AtomInfo {
index: i,
coords: self.parent.get_coord(i),
element: self.parent.get_element(i),
atom_name: self.parent.get_atom_name(i),
is_hetero: self.parent.get_is_hetero(i),
})
}
pub fn get_atom(&self, residue_atom_idx: usize) -> Option<AtomInfo> {
let abs_idx = self.start_idx + residue_atom_idx;
if abs_idx < self.end_idx {
Some(AtomInfo {
index: abs_idx,
coords: &self.parent.get_coord(abs_idx),
element: &self.parent.get_element(abs_idx),
atom_name: &self.parent.get_atom_name(abs_idx),
is_hetero: self.parent.get_is_hetero(abs_idx),
})
} else {
None
}
}
pub fn find_atom_by_name(&self, name: &str) -> Option<AtomInfo> {
(self.start_idx..self.end_idx)
.find(|&i| self.parent.get_atom_name(i) == name)
.map(|i| AtomInfo {
index: i,
coords: &self.parent.get_coord(i),
element: &self.parent.get_element(i),
atom_name: &self.parent.get_atom_name(i),
is_hetero: self.parent.get_is_hetero(i),
})
}
pub fn is_amino_acid(&self) -> bool {
is_amino_acid(&self.res_name)
}
pub fn is_carbohydrate(&self) -> bool {
is_carbohydrate(&self.res_name)
}
pub fn is_nucleotide(&self) -> bool {
is_nucleotide(&self.res_name)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::AtomCollection;
use ferritin_test_data::TestFile;
#[test]
fn test_iteration() {
let (prot_file, _temp) = TestFile::protein_01().create_temp().unwrap();
let (pdb, _) = pdbtbx::open(prot_file).unwrap();
let ac = AtomCollection::from(&pdb);
assert_eq!(ac.iter_residues_aminoacid().count(), 154);
let first_residue: ResidueAtoms = ac
.iter_residues_aminoacid()
.take(1)
.next()
.expect("Should have at least one amino acid residue");
assert_eq!(first_residue.start_idx, 0);
assert_eq!(first_residue.end_idx, 8); assert_eq!(first_residue.res_id, 0);
assert_eq!(first_residue.res_name, "MET");
assert_eq!(first_residue.chain_id, "A");
assert_eq!(first_residue.parent.get_size(), 1413);
}
}