bool _hAccDelocalized(OpenBabel::OBAtom* a) { if (a->GetAtomicNum() != 7) { return false; } if (a->IsAromatic() && a->GetImplicitValence() == 3) { return true; } std::vector<OpenBabel::OBBond*>::iterator bi1; for (OpenBabel::OBBond* b1 = a->BeginBond(bi1); b1; b1 = a->NextBond(bi1)) { OpenBabel::OBAtom* aa = b1->GetNbrAtom(a); if (aa->IsAromatic() && a->GetImplicitValence() == 3) { return true; } if (aa->GetAtomicNum() == 6) { std::vector<OpenBabel::OBBond*>::iterator bi2; for (OpenBabel::OBBond* b2 = aa->BeginBond(bi2); b2; b2 = aa->NextBond(bi2)) { OpenBabel::OBAtom* aaa = b2->GetNbrAtom(aa); if (aaa == a) { continue; } if (b2->GetBO() == 2) { if (aaa->GetAtomicNum() == 8) return true; if (aaa->GetAtomicNum() == 7) return true; if (aaa->GetAtomicNum() == 16) return true; } } } else if (aa->GetAtomicNum() == 16) { std::vector<OpenBabel::OBBond*>::iterator bi2; for (OpenBabel::OBBond* b2 = aa->BeginBond(bi2); b2; b2 = aa->NextBond(bi2)) { OpenBabel::OBAtom* aaa = b2->GetNbrAtom(aa); if (aaa == a) { continue; } if ((b2->GetBO() == 2) && (aaa->GetAtomicNum() == 8)) { return true; } } } } return false; }
OpenBabel::OBMol Schuffenhauer::RemoveRing(OpenBabel::OBMol& oldMol, std::vector<OpenBabel::OBRing*>& rings, unsigned int ringIdx) { OpenBabel::OBMol newMol(oldMol); // Make list of the ring bonds std::set<OpenBabel::OBBond*> ringBonds; OpenBabel::OBBond* bond; std::vector<OpenBabel::OBBond*>::iterator bvi; for (bond = newMol.BeginBond(bvi); bond; bond = newMol.NextBond(bvi)) { if (rings[ringIdx]->IsMember(bond)) { ringBonds.insert(bond); } } // Make list of delocalizable bonds (aromatic, single and flanked by two double bonds) std::set<OpenBabel::OBBond*> delocalizableBonds; std::set<OpenBabel::OBBond*>::iterator bli; OpenBabel::OBBondIterator bi; OpenBabel::OBAtom* atom; OpenBabel::OBBond* nbrBond; unsigned int n; for (bli = ringBonds.begin(); bli != ringBonds.end(); ++bli) { bond = *bli; if ((bond->GetBondOrder() == 1) && bond->IsAromatic()) { n = 0; atom = bond->GetBeginAtom(); for (nbrBond = atom->BeginBond(bi); nbrBond; nbrBond = atom->NextBond(bi)) { if ((nbrBond != bond) && ringBonds.count(nbrBond) && (nbrBond->GetBondOrder() == 2)) { ++n; } } atom = bond->GetEndAtom(); for (nbrBond = atom->BeginBond(bi); nbrBond; nbrBond = atom->NextBond(bi)) { if ((nbrBond != bond) && ringBonds.count(nbrBond) && (nbrBond->GetBondOrder() == 2)) { ++n; } } } if (n == 2) { delocalizableBonds.insert(bond); } } // Make list of bonds which form the fusion with other rings std::set<OpenBabel::OBBond*> fusionBonds; for (bli = ringBonds.begin(); bli != ringBonds.end(); ++bli) { bond = *bli; for (unsigned int i(0); i < rings.size(); ++i) { if (i != ringIdx) { if (rings[i]->IsMember(bond)) { fusionBonds.insert(bond); } } } } // Make list of bonds which are the fusion between aromatic and non-aromatic std::set<OpenBabel::OBBond*> aromaticNonaromaticFusionBonds; if (rings[ringIdx]->IsAromatic()) { for (bli = fusionBonds.begin(); bli != fusionBonds.end(); ++bli) { bond = *bli; for (unsigned int i(0); i < rings.size(); ++i) { if (i != ringIdx) { if (rings[i]->IsMember(bond) && !rings[i]->IsAromatic()) { aromaticNonaromaticFusionBonds.insert(bond); } } } } } // Make list of bonds which are the fusion between aromatic and aromatic std::set<OpenBabel::OBBond*> aromaticAromaticFusionBonds; if (rings[ringIdx]->IsAromatic()) { for (bli = fusionBonds.begin(); bli != fusionBonds.end(); ++bli) { bond = *bli; for (unsigned int i(0); i < rings.size(); ++i) { if (i != ringIdx) { if (rings[i]->IsMember(bond) && rings[i]->IsAromatic()) { aromaticAromaticFusionBonds.insert(bond); } } } } } // Remove ring std::set<OpenBabel::OBBond*> bondsToBeDeleted; std::set<OpenBabel::OBAtom*> atomsToBeDeleted; OpenBabel::OBAtom* nbrAtom[2]; for (bli = ringBonds.begin(); bli != ringBonds.end(); ++bli) { bond = *bli; if (fusionBonds.count(bond)) { continue; } else { bondsToBeDeleted.insert(bond); nbrAtom[0] = bond->GetBeginAtom(); nbrAtom[1] = bond->GetEndAtom(); if (nbrAtom[0] && nbrAtom[1]) { if (nbrAtom[0]->MemberOfRingCount() == 1) { atomsToBeDeleted.insert(nbrAtom[0]); } if (nbrAtom[1]->MemberOfRingCount() == 1) { atomsToBeDeleted.insert(nbrAtom[1]); } } } } newMol.BeginModify(); for (bli = bondsToBeDeleted.begin(); bli != bondsToBeDeleted.end(); ++bli) { newMol.DeleteBond(*bli); } newMol.EndModify(); newMol.BeginModify(); std::set<OpenBabel::OBAtom*>::iterator ali; for (ali = atomsToBeDeleted.begin(); ali != atomsToBeDeleted.end(); ++ali) { newMol.DeleteAtom(*ali); } newMol.EndModify(); // Correct the bond orders of the ex-fusion bond(s) newMol.BeginModify(); for (bond = newMol.BeginBond(bvi); bond; bond = newMol.NextBond(bvi)) { if (aromaticNonaromaticFusionBonds.count(bond)) { bond->SetBondOrder(2); } else if (aromaticAromaticFusionBonds.count(bond) && delocalizableBonds.count(bond)) { bond->SetBondOrder(2); } } newMol.EndModify(); // Remove single atoms that originate from exocyclic bonds at ring (void) RemoveSidechains(&newMol); // Check if there are atoms with valences that are not allowed std::vector<OpenBabel::OBAtom*>::iterator avi; for (atom = newMol.BeginAtom(avi); atom; atom = newMol.NextAtom(avi)) { if (atom->IsCarbon() && (atom->BOSum() > 4)) { newMol.Clear(); break; } else if (atom->IsNitrogen() && (atom->BOSum() > 3)) { newMol.Clear(); break; } else if (atom->IsOxygen() && (atom->BOSum() > 2)) { newMol.Clear(); break; } } // Check if there are no discontinuous fragments if (newMol.Separate().size() > 1) { newMol.Clear(); } return newMol; }