void StereoCenterItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Molecule *mol = molecule(); painter->save(); painter->setPen(Qt::green); if (!mol) { // not connected: default behaviour (draw connectable box) MolInputItem::paint(painter, option, widget); painter->restore(); return; } const QList<Atom*> &atoms = mol->atoms(); OpenBabel::OBMol *obmol = mol->OBMol(); QPointF offset(-5.0, 5.0); #ifdef OPENBABEL2_TRUNK // need to calculate symmetry first std::vector<unsigned int> symmetry_classes; OpenBabel::OBGraphSym graphsym(obmol); graphsym.GetSymmetry(symmetry_classes); //std::vector<unsigned long> atomIds = FindTetrahedralAtoms(obmol, symmetry_classes); std::vector<OpenBabel::StereogenicUnit> units = FindStereogenicUnits(obmol, symmetry_classes); for (unsigned int i = 0; i < units.size(); ++i) { if (units.at(i).type == OpenBabel::OBStereo::Tetrahedral) { OpenBabel::OBAtom *obatom = obmol->GetAtomById(units.at(i).id); painter->drawEllipse(mapFromItem(mol, atoms[obatom->GetIndex()]->pos()), 10, 10); } else if (units.at(i).type == OpenBabel::OBStereo::CisTrans) { OpenBabel::OBBond *obbond = obmol->GetBondById(units.at(i).id); OpenBabel::OBAtom *obatom1 = obbond->GetBeginAtom(); OpenBabel::OBAtom *obatom2 = obbond->GetEndAtom(); painter->drawEllipse(mapFromItem(mol, atoms[obatom1->GetIndex()]->pos()), 10, 10); painter->drawEllipse(mapFromItem(mol, atoms[obatom2->GetIndex()]->pos()), 10, 10); } } #else using OpenBabel::OBMolAtomIter; FOR_ATOMS_OF_MOL(atom, obmol) if (atom->IsChiral()) painter->drawEllipse(mapFromItem(mol, atoms[atom->GetIdx()-1]->pos()), 10, 10); #endif // default behavious (draw the label()) MolInputItem::paint(painter, option, widget); painter->restore(); }
//-- // [rad] generate path and ident for bond void RelationBond::GetPathAndIdentBond(const std::string& refMoleculeId, std::string& refPath, std::string& refIdent) { refPath = m_vecSatisfiedClasses.front()->GetPrefix() + ":" + m_vecSatisfiedClasses.front()->GetName(); std::stringstream ssConv; OpenBabel::OBBond* pBond = m_pBond; OpenBabel::OBAtom* pAtomStart = pBond->GetBeginAtom(); OpenBabel::OBAtom* pAtomEnd = pBond->GetEndAtom(); ssConv << m_vecSatisfiedClasses.front()->GetName() << "_" << refMoleculeId << "_" << pAtomStart->GetIdx() << "_" << pAtomEnd->GetIdx(); refIdent = ""; ssConv >> refIdent; }
unsigned int Schuffenhauer::CalculateAcyclicBonds(OpenBabel::OBMol& mol) { unsigned int nbonds(0); OpenBabel::OBAtom* nbratom[2]; OpenBabel::OBBond* bond; std::vector<OpenBabel::OBBond*>::iterator bvi; for (bond = mol.BeginBond(bvi); bond; bond = mol.NextBond(bvi)) { nbratom[0] = bond->GetBeginAtom(); nbratom[1] = bond->GetEndAtom(); if (nbratom[0] && nbratom[1]) { if (!bond->IsInRing() && (nbratom[0]->GetValence() > 1) && (nbratom[1]->GetValence() > 1)) { ++nbonds; } } } return nbonds; }
bool Schuffenhauer::HasLinkerToHeteroAtom(OpenBabel::OBMol& mol, OpenBabel::OBRing* ring) { std::vector<OpenBabel::OBBond*>::iterator bvi; OpenBabel::OBBond* bond; OpenBabel::OBAtom* nbrAtom[2]; for (bond = mol.BeginBond(bvi); bond; bond = mol.NextBond(bvi)) { nbrAtom[0] = bond->GetBeginAtom(); nbrAtom[1] = bond->GetEndAtom(); if ( // Neighbours are real nbrAtom[0] && nbrAtom[1] && // Bond should be acyclic !bond->IsInRing() && // Both atoms have to be ring atoms nbrAtom[0]->IsInRing() && nbrAtom[1]->IsInRing() && // At least one of the atoms should be hetero (nbrAtom[0]->IsHeteroatom() || nbrAtom[1]->IsHeteroatom()) && // One of the atoms, but not both, should be part of this ring ((ring->IsMember(nbrAtom[0]) && !ring->IsMember(nbrAtom[1])) || (ring->IsMember(nbrAtom[1]) && !ring->IsMember(nbrAtom[0]))) ) { 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; }