pub mod atom_count;
pub mod bond_count;
pub mod connectivity;
pub mod constitutional;
pub mod ring_count;
pub mod topological;
use crate::error::MordredError;
use crate::molecule::Molecule;
pub trait Descriptor: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn calculate(&self, mol: &Molecule) -> Result<f64, MordredError>;
}
pub struct DescriptorSet {
descriptors: Vec<Box<dyn Descriptor>>,
}
impl DescriptorSet {
pub fn new() -> Self {
Self {
descriptors: Vec::new(),
}
}
pub fn all() -> Self {
let mut set = Self::new();
set.add_all_constitutional();
set.add_all_topological();
set.add_all_connectivity();
set.add_all_atom_counts();
set.add_all_bond_counts();
set.add_all_ring_counts();
set
}
pub fn add(&mut self, descriptor: Box<dyn Descriptor>) {
self.descriptors.push(descriptor);
}
pub fn add_all_constitutional(&mut self) {
self.add(Box::new(constitutional::AtomCount));
self.add(Box::new(constitutional::HeavyAtomCount));
self.add(Box::new(constitutional::BondCount));
self.add(Box::new(constitutional::MolecularWeight));
}
pub fn add_all_topological(&mut self) {
self.add(Box::new(topological::WienerIndex));
self.add(Box::new(topological::ZagrebIndex1));
self.add(Box::new(topological::ZagrebIndex2));
}
pub fn add_all_connectivity(&mut self) {
self.add(Box::new(connectivity::Chi0));
self.add(Box::new(connectivity::Chi1));
}
pub fn add_all_atom_counts(&mut self) {
self.add(Box::new(atom_count::CarbonCount));
self.add(Box::new(atom_count::NitrogenCount));
self.add(Box::new(atom_count::OxygenCount));
self.add(Box::new(atom_count::SulfurCount));
self.add(Box::new(atom_count::PhosphorusCount));
self.add(Box::new(atom_count::HalogenCount));
self.add(Box::new(atom_count::HeteroatomCount));
}
pub fn add_all_ring_counts(&mut self) {
self.add(Box::new(ring_count::RingCount));
for size in 3..=12 {
self.add(Box::new(ring_count::RingSizeCount::new(size)));
}
}
pub fn add_all_bond_counts(&mut self) {
self.add(Box::new(bond_count::SingleBondCount));
self.add(Box::new(bond_count::DoubleBondCount));
self.add(Box::new(bond_count::TripleBondCount));
self.add(Box::new(bond_count::AromaticBondCount));
}
pub fn calculate(&self, mol: &Molecule) -> Vec<(&str, Result<f64, MordredError>)> {
self.descriptors
.iter()
.map(|d| (d.name(), d.calculate(mol)))
.collect()
}
pub fn names(&self) -> Vec<&str> {
self.descriptors.iter().map(|d| d.name()).collect()
}
pub fn list(&self) -> Vec<(&str, &str)> {
self.descriptors
.iter()
.map(|d| (d.name(), d.description()))
.collect()
}
pub fn len(&self) -> usize {
self.descriptors.len()
}
pub fn is_empty(&self) -> bool {
self.descriptors.is_empty()
}
}
impl Default for DescriptorSet {
fn default() -> Self {
Self::all()
}
}