OpenBabel::OBMol Schuffenhauer::Rule_1(OpenBabel::OBMol& oldMol) { if (oldMol.GetSSSR().size() <= _ringsToBeRetained) { return oldMol; } OpenBabel::OBMol newMol(oldMol); std::vector<OpenBabel::OBAtom*>::iterator avi; OpenBabel::OBBondIterator bi; OpenBabel::OBAtom* atom; OpenBabel::OBAtom* nbrAtom[2]; for (atom = newMol.BeginAtom(avi); atom; atom = newMol.NextAtom(avi)) { if ((atom->MemberOfRingSize() == 3) && (atom->IsNitrogen() || atom->IsOxygen()) && (atom->MemberOfRingCount() == 1) && (atom->GetHvyValence() == 2)) { nbrAtom[0] = atom->BeginNbrAtom(bi); nbrAtom[1] = atom->NextNbrAtom(bi); if (nbrAtom[0] && nbrAtom[1]) { newMol.DeleteAtom(atom); newMol.GetBond(nbrAtom[0], nbrAtom[1])->SetBondOrder(2); } } } return newMol; }
bool Oprea_1::CalculateScaffold(const OpenBabel::OBMol& mol, Options* o) { OpenBabel::OBMol m(mol); OpenBabel::OBAtom* atom; OpenBabel::OBAtom* nbrAtom[2]; OpenBabel::OBBondIterator bi; std::vector<OpenBabel::OBAtom*>::iterator avi; OpenBabel::OBBond* bond; std::vector<OpenBabel::OBBond*>::iterator bvi; bool removed(true); while (removed) { removed = false; for (atom = m.BeginAtom(avi); atom; atom = m.NextAtom(avi)) { if (IsEndStanding(atom, false, false)) { m.DeleteAtom(atom); removed = true; break; } } } // Make all atoms as neutral C and all bond orders equal to 1 m.BeginModify(); for (atom = m.BeginAtom(avi); atom; atom = m.NextAtom(avi)) { atom->SetAtomicNum(6); atom->SetFormalCharge(0); } for (bond = m.BeginBond(bvi); bond; bond = m.NextBond(bvi)) { bond->SetBondOrder(1); } m.EndModify(); // Transform all neighbouring linker atoms into a single bond removed = true; while (removed) { removed = false; for (atom = m.BeginAtom(avi); atom; atom = m.NextAtom(avi)) { if (!atom->IsInRing() && (atom->GetValence() == 2)) { nbrAtom[0] = atom->BeginNbrAtom(bi); nbrAtom[1] = atom->NextNbrAtom(bi); if (nbrAtom[0] && nbrAtom[1]) { m.BeginModify(); m.AddBond(nbrAtom[0]->GetIdx(), nbrAtom[1]->GetIdx(), 1); m.DeleteAtom(atom); m.EndModify(); removed = true; break; } } } } // Shrink all rings to their minimum size removed = true; while (removed) { removed = false; for (atom = m.BeginAtom(avi); atom; atom = m.NextAtom(avi)) { if ((atom->MemberOfRingSize() > 3) && (atom->GetValence() == 2)) { nbrAtom[0] = atom->BeginNbrAtom(bi); nbrAtom[1] = atom->NextNbrAtom(bi); if (nbrAtom[0] && nbrAtom[1]) { m.BeginModify(); m.AddBond(nbrAtom[0]->GetIdx(), nbrAtom[1]->GetIdx(), 1); m.DeleteAtom(atom); m.EndModify(); removed = true; break; } } } } if (!m.Empty()) { _smiles = _mol2can.WriteString(&m, true); } else { _smiles = "-"; return false; } return true; }
void Molecule::addHydrogens(Atom *a, const QList<unsigned long> &atomIds, const QList<unsigned long> &bondIds) { if (atomIds.size() != bondIds.size()) { qDebug() << "Error, addHydrogens called with atom & bond id lists of different size!"; } // Construct an OBMol, call AddHydrogens and translate the changes OpenBabel::OBMol obmol = OBMol(); if (a) { OpenBabel::OBAtom *obatom = obmol.GetAtom(a->index()+1); // Set implicit valence for unusual elements not handled by OpenBabel // PR#2803076 switch (obatom->GetAtomicNum()) { case 3: case 11: case 19: case 37: case 55: case 85: case 87: obatom->SetImplicitValence(1); obatom->SetHyb(1); obmol.SetImplicitValencePerceived(); break; case 4: case 12: case 20: case 38: case 56: case 88: obatom->SetImplicitValence(2); obatom->SetHyb(2); obmol.SetImplicitValencePerceived(); break; case 84: // Po obatom->SetImplicitValence(2); obatom->SetHyb(3); obmol.SetImplicitValencePerceived(); break; default: // do nothing break; } obmol.AddHydrogens(obatom); } else obmol.AddHydrogens(); // All new atoms in the OBMol must be the additional hydrogens unsigned int numberAtoms = numAtoms(); int j = 0; for (unsigned int i = numberAtoms+1; i <= obmol.NumAtoms(); ++i, ++j) { if (obmol.GetAtom(i)->IsHydrogen()) { OpenBabel::OBAtom *obatom = obmol.GetAtom(i); Atom *atom; if (atomIds.isEmpty()) atom = addAtom(); else if (j < atomIds.size()) atom = addAtom(atomIds.at(j)); else { qDebug() << "Error - not enough unique ids in addHydrogens."; break; } atom->setOBAtom(obatom); // Get the neighbor atom OpenBabel::OBBondIterator iter; OpenBabel::OBAtom *next = obatom->BeginNbrAtom(iter); Bond *bond; if (bondIds.isEmpty()) bond = addBond(); else // Already confirmed by atom ids bond = addBond(bondIds.at(j)); bond->setEnd(Molecule::atom(atom->index())); bond->setBegin(Molecule::atom(next->GetIdx()-1)); } } for (unsigned int i = 1; i <= numberAtoms; ++i) { // Warning -- OB atom index off-by-one here atom(i-1)->setPartialCharge(obmol.GetAtom(i)->GetPartialCharge()); } }
bool Oprea_2::CalculateScaffold(const OpenBabel::OBMol& mol, Options* o) { OpenBabel::OBMol m(mol); // Tag all HBD std::vector<bool> hbd(m.NumAtoms() + 1); for (OpenBabel::OBMolAtomIter atom(m); atom; ++atom) { if (atom->MatchesSMARTS("[NH,NH2,NH3,OH,nH]")) { hbd[atom->GetIdx()] = true; } else { hbd[atom->GetIdx()] = false; } } // Tag all HBA std::vector<bool> hba(m.NumAtoms() + 1); for (OpenBabel::OBMolAtomIter atom(m); atom; ++atom) { if (!atom->IsAmideNitrogen() && // No amide nitrogen !atom->IsAromatic() && // Not aromatic (atom->GetFormalCharge() <= 0) && // No + charge atom->MatchesSMARTS("[NH0]")) // No hydrogens { hba[atom->GetIdx()] = true; } else if (atom->IsNitrogen() && // Nitrogen atom->IsAromatic() && // Aromatic atom->MatchesSMARTS("[nH0]") && // No hydrogens (atom->GetHvyValence() <= 2) && // Maximal two non-H atoms connected (atom->GetFormalCharge() <= 0)) // No + charge { hba[atom->GetIdx()] = true; } else if (atom->IsOxygen() && // Oxygen (atom->GetFormalCharge() <= 0)) // No + charge { hba[atom->GetIdx()] = true; } else { hba[atom->GetIdx()] = false; } } // Mark the C(=O) or S(=O) also as HBA for (OpenBabel::OBMolAtomIter atom(m); atom; ++atom) { if (atom->MatchesSMARTS("C=O")) { hba[atom->GetIdx()] = true; } else if (atom->MatchesSMARTS("S=O")) { hba[atom->GetIdx()] = true; } } // Make all atoms as neutral C, N (HBD), or O (HBA) m.BeginModify(); std::vector<OpenBabel::OBAtom*>::iterator avi; OpenBabel::OBAtom* atom; for (atom = m.BeginAtom(avi); atom; atom = m.NextAtom(avi)) { if (hba[atom->GetIdx()]) { atom->SetAtomicNum(8); } else if (hbd[atom->GetIdx()]) { atom->SetAtomicNum(7); } else { atom->SetAtomicNum(6); } atom->SetFormalCharge(0); } m.EndModify(); // Remove all endstanding atoms OpenBabel::OBBondIterator bi; OpenBabel::OBBond* bond; std::vector<OpenBabel::OBBond*>::iterator bvi; bool removed(true); while (removed) { removed = false; for (atom = m.BeginAtom(avi); atom; atom = m.NextAtom(avi)) { if (IsEndStanding(atom, false, false)) { m.DeleteAtom(atom); removed = true; break; } } } // Set all bond orders equal to 1 m.BeginModify(); for (bond = m.BeginBond(bvi); bond; bond = m.NextBond(bvi)) { bond->SetBondOrder(1); } m.EndModify(); // Transform all neighbouring linker atoms into a single bond removed = true; OpenBabel::OBAtom* nbrAtom[2]; while (removed) { removed = false; for (atom = m.BeginAtom(avi); atom; atom = m.NextAtom(avi)) { if (!atom->IsInRing() && (atom->GetValence() == 2)) { m.BeginModify(); nbrAtom[0] = atom->BeginNbrAtom(bi); nbrAtom[1] = atom->NextNbrAtom(bi); if (nbrAtom[0] && nbrAtom[1]) { m.AddBond(nbrAtom[0]->GetIdx(), nbrAtom[1]->GetIdx(), 1); m.DeleteAtom(atom); m.EndModify(); removed = true; break; } } } } // Shrink all rings to their minimum size removed = true; while (removed) { removed = false; for (atom = m.BeginAtom(avi); atom; atom = m.NextAtom(avi)) { if ((atom->MemberOfRingSize() > 3) && (atom->GetValence() == 2)) { nbrAtom[0] = atom->BeginNbrAtom(bi); nbrAtom[1] = atom->NextNbrAtom(bi); if (nbrAtom[0] && nbrAtom[1]) { if (nbrAtom[0]->GetAtomicNum() == atom->GetAtomicNum()) { m.BeginModify(); m.AddBond(nbrAtom[0]->GetIdx(), nbrAtom[1]->GetIdx(), 1); m.DeleteAtom(atom); m.EndModify(); removed = true; break; } else if (nbrAtom[1]->GetAtomicNum() == atom->GetAtomicNum()) { m.BeginModify(); m.AddBond(nbrAtom[0]->GetIdx(), nbrAtom[1]->GetIdx(), 1); m.DeleteAtom(atom); m.EndModify(); removed = true; break; } } } } } if (!m.Empty()) { _smiles = _mol2can.WriteString(&m, true); } else { _smiles = "-"; return false; } return true; }