use chematic_core::{Molecule, AtomIdx};
use chematic_smiles::canonical::canonical_atom_order;
use std::collections::HashMap;
pub fn isotope_layer(mol: &Molecule) -> Option<String> {
let canonical_order = canonical_atom_order(mol);
let mut inchi_index: HashMap<AtomIdx, usize> = HashMap::new();
let mut inchi_num = 0;
for &canon_idx in &canonical_order {
let atom_idx = AtomIdx(canon_idx as u32);
let atom = mol.atom(atom_idx);
if atom.element.atomic_number() != 1 {
inchi_num += 1;
inchi_index.insert(atom_idx, inchi_num);
}
}
let isotopes: Vec<(usize, u16)> = canonical_order
.iter()
.filter_map(|&canon_idx| {
let atom_idx = AtomIdx(canon_idx as u32);
if let Some(&inchi_idx) = inchi_index.get(&atom_idx) {
let atom = mol.atom(atom_idx);
if let Some(mass) = atom.isotope {
return Some((inchi_idx, mass));
}
}
None
})
.collect();
if isotopes.is_empty() {
return None;
}
let result = isotopes
.iter()
.map(|(idx, mass)| format!("{}+{}", idx, mass))
.collect::<Vec<_>>()
.join(",");
Some(result)
}
#[cfg(test)]
mod tests {
use super::*;
use chematic_smiles::parse;
#[test]
fn test_isotope_none() {
let mol = parse("c1ccccc1").expect("benzene");
assert_eq!(isotope_layer(&mol), None);
}
#[test]
fn test_isotope_deuterium() {
let mol = parse("C").expect("methane");
let i_layer = isotope_layer(&mol);
assert_eq!(i_layer, None);
}
}