use crate::descriptor::Descriptor;
use crate::error::MordredError;
use crate::molecule::Molecule;
pub struct Chi0;
impl Descriptor for Chi0 {
fn name(&self) -> &str {
"Chi0"
}
fn description(&self) -> &str {
"Zero-order Randic connectivity index"
}
fn calculate(&self, mol: &Molecule) -> Result<f64, MordredError> {
let mut sum = 0.0f64;
for idx in mol.graph.node_indices() {
let delta = mol.total_degree(idx);
if delta > 0 {
sum += 1.0 / (delta as f64).sqrt();
}
}
Ok(sum)
}
}
pub struct Chi1;
impl Descriptor for Chi1 {
fn name(&self) -> &str {
"Chi1"
}
fn description(&self) -> &str {
"First-order Randic connectivity index"
}
fn calculate(&self, mol: &Molecule) -> Result<f64, MordredError> {
let mut sum = 0.0f64;
for (a, b, _) in mol.bonds() {
let da = mol.total_degree(a);
let db = mol.total_degree(b);
if da > 0 && db > 0 {
sum += 1.0 / ((da * db) as f64).sqrt();
}
}
Ok(sum)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::molecule::parse_smiles;
#[test]
fn test_chi0_methane() {
let mol = parse_smiles("C").unwrap();
let val = Chi0.calculate(&mol).unwrap();
assert!((val - 0.5).abs() < 1e-6);
}
#[test]
fn test_chi0_ethane() {
let mol = parse_smiles("CC").unwrap();
let val = Chi0.calculate(&mol).unwrap();
assert!((val - 1.0).abs() < 1e-6);
}
#[test]
fn test_chi1_ethane() {
let mol = parse_smiles("CC").unwrap();
let val = Chi1.calculate(&mol).unwrap();
assert!((val - 0.25).abs() < 1e-6);
}
#[test]
fn test_chi1_propane() {
let mol = parse_smiles("CCC").unwrap();
let val = Chi1.calculate(&mol).unwrap();
assert!((val - 0.5).abs() < 1e-6);
}
}