// handles stereochem markers set by the Mol file parser and // converts them to the RD standard: void DetectAtomStereoChemistry(RWMol &mol, const Conformer *conf) { PRECONDITION(conf, "no conformer"); // make sure we've calculated the implicit valence on each atom: for (RWMol::AtomIterator atomIt = mol.beginAtoms(); atomIt != mol.endAtoms(); ++atomIt) { (*atomIt)->calcImplicitValence(false); } for (RWMol::BondIterator bondIt = mol.beginBonds(); bondIt != mol.endBonds(); ++bondIt) { Bond *bond = *bondIt; if (bond->getBondDir() != Bond::UNKNOWN) { Bond::BondDir dir = bond->getBondDir(); // the bond is marked as chiral: if (dir == Bond::BEGINWEDGE || dir == Bond::BEGINDASH) { Atom *atom = bond->getBeginAtom(); if (atom->getImplicitValence() == -1) { atom->calcExplicitValence(); atom->calcImplicitValence(); } Atom::ChiralType code = FindAtomStereochemistry(mol, bond, conf); atom->setChiralTag(code); // within the RD representation, if a three-coordinate atom // is chiral and has an implicit H, that H needs to be made explicit: if (atom->getDegree() == 3 && !atom->getNumExplicitHs() && atom->getNumImplicitHs() == 1) { atom->setNumExplicitHs(1); // recalculated number of implicit Hs: atom->updatePropertyCache(); } } } } }
void CleanupMolecule() { // an example of doing some cleaning up of a molecule before // calling the sanitizeMol function() // build: C1CC1C(:O):O RWMol *mol = new RWMol(); // add atoms and bonds: mol->addAtom(new Atom(6)); // atom 0 mol->addAtom(new Atom(6)); // atom 1 mol->addAtom(new Atom(6)); // atom 2 mol->addAtom(new Atom(6)); // atom 3 mol->addAtom(new Atom(8)); // atom 4 mol->addAtom(new Atom(8)); // atom 5 mol->addBond(3, 4, Bond::AROMATIC); // bond 0 mol->addBond(3, 5, Bond::AROMATIC); // bond 1 mol->addBond(3, 2, Bond::SINGLE); // bond 2 mol->addBond(2, 1, Bond::SINGLE); // bond 3 mol->addBond(1, 0, Bond::SINGLE); // bond 4 mol->addBond(0, 2, Bond::SINGLE); // bond 5 // instead of calling sanitize mol, which would generate an error, // we'll perceive the rings, then take care of aromatic bonds // that aren't in a ring, then sanitize: MolOps::findSSSR(*mol); for (ROMol::BondIterator bondIt = mol->beginBonds(); bondIt != mol->endBonds(); ++bondIt) { if (((*bondIt)->getIsAromatic() || (*bondIt)->getBondType() == Bond::AROMATIC) && !mol->getRingInfo()->numBondRings((*bondIt)->getIdx())) { // remove the aromatic flag on the bond: (*bondIt)->setIsAromatic(false); // and cleanup its attached atoms as well (they were // also marked aromatic when the bond was added) (*bondIt)->getBeginAtom()->setIsAromatic(false); (*bondIt)->getEndAtom()->setIsAromatic(false); // NOTE: this isn't really reasonable: (*bondIt)->setBondType(Bond::SINGLE); } } // now it's safe to sanitize: RDKit::MolOps::sanitizeMol(*mol); // Get the canonical SMILES, include stereochemistry: std::string smiles; smiles = MolToSmiles(*(static_cast<ROMol *>(mol)), true); BOOST_LOG(rdInfoLog) << " fixed SMILES: " << smiles << std::endl; }
void testProps() { BOOST_LOG(rdInfoLog) << "-----------------------\n properties" << std::endl; string smi = "C1COC1"; RWMol *m = SmilesToMol(smi, 0, false); m = SmilesToMol(smi, 0, false); for (ROMol::AtomIterator ai = m->beginAtoms(); ai != m->endAtoms(); ++ai) { unsigned int v = 1; (*ai)->setProp("foo", v, true); } m = SmilesToMol(smi, 0, false); for (ROMol::BondIterator ai = m->beginBonds(); ai != m->endBonds(); ++ai) { unsigned int v = 1; (*ai)->setProp("foo", v, true); } m = SmilesToMol(smi, 0, false); for (ROMol::AtomIterator ai = m->beginAtoms(); ai != m->endAtoms(); ++ai) { unsigned int v = 1; (*ai)->setProp("foo", v, true); (*ai)->setProp("bar", v, true); } m = SmilesToMol(smi, 0, false); for (ROMol::AtomIterator ai = m->beginAtoms(); ai != m->endAtoms(); ++ai) { unsigned int v = 1; (*ai)->setProp("foo", v, true); (*ai)->setProp("bar", v, true); (*ai)->setProp("baz", v, true); } m = SmilesToMol(smi, 0, false); for (ROMol::AtomIterator ai = m->beginAtoms(); ai != m->endAtoms(); ++ai) { unsigned int v = 1; (*ai)->setProp("foo", v, false); } m = SmilesToMol(smi, 0, false); for (ROMol::AtomIterator ai = m->beginAtoms(); ai != m->endAtoms(); ++ai) { unsigned int v = 1; (*ai)->setProp("foo", v, false); (*ai)->setProp("bar", v, false); } m = SmilesToMol(smi, 0, false); for (ROMol::AtomIterator ai = m->beginAtoms(); ai != m->endAtoms(); ++ai) { unsigned int v = 1; (*ai)->setProp("foo", v, false); (*ai)->setProp("bar", v, false); (*ai)->setProp("baz", v, false); } BOOST_LOG(rdInfoLog) << "Finished" << std::endl; }
bool permuteDummiesAndKekulize(RWMol &mol, const INT_VECT &allAtms, boost::dynamic_bitset<> dBndCands, INT_VECT &questions, unsigned int maxBackTracks) { boost::dynamic_bitset<> atomsInPlay(mol.getNumAtoms()); for (int allAtm : allAtms) { atomsInPlay[allAtm] = 1; } bool kekulized = false; QuestionEnumerator qEnum(questions); while (!kekulized && questions.size()) { boost::dynamic_bitset<> dBndAdds(mol.getNumBonds()); INT_VECT done; #if 1 // reset the state: all aromatic bonds are remarked to single: for (RWMol::BondIterator bi = mol.beginBonds(); bi != mol.endBonds(); ++bi) { if ((*bi)->getIsAromatic() && (*bi)->getBondType() != Bond::SINGLE && atomsInPlay[(*bi)->getBeginAtomIdx()] && atomsInPlay[(*bi)->getEndAtomIdx()]) { (*bi)->setBondType(Bond::SINGLE); } } #endif // pick a new permutation of the questionable atoms: const INT_VECT &switchOff = qEnum.next(); if (!switchOff.size()) break; boost::dynamic_bitset<> tCands = dBndCands; for (int it : switchOff) { tCands[it] = 0; } #if 0 std::cerr<<"permute: "; for (boost::dynamic_bitset<>::size_type i = 0; i < tCands.size(); ++i){ std::cerr << tCands[i]; } std::cerr<<std::endl; #endif // try kekulizing again: kekulized = kekulizeWorker(mol, allAtms, tCands, dBndAdds, done, maxBackTracks); } return kekulized; }
bool StripSmallFragments(RWMol &mol, bool verbose) { const bool sanitize=false; std::vector<boost::shared_ptr<ROMol> > frags = MolOps::getMolFrags(mol, sanitize); if (frags.size() <= 1) return false; size_t maxFragSize = 0; size_t maxFragIdx = 0; for(size_t i=0; i<frags.size(); ++i) { const unsigned int fragSize = frags[i].get()->getNumAtoms(); if(fragSize >= maxFragSize) { maxFragSize = fragSize; maxFragIdx = i; } } if(verbose) { std::string name = "<no name>"; mol.getPropIfPresent(common_properties::_Name, name); for(size_t i=0; i<frags.size(); ++i) { if (i != maxFragIdx) { BOOST_LOG(rdWarningLog) << name << " removed fragment i="<<i<<" with " << frags[i].get()->getNumAtoms() << " atoms" << std::endl; } } } // we need to save chirality for checking later bool checkChiral = false; if(mol.hasProp(RDKit::common_properties::_MolFileChiralFlag)) { unsigned int chiralflag = mol.getProp<unsigned int>( RDKit::common_properties::_MolFileChiralFlag); frags[maxFragIdx].get()->setProp<unsigned int>( RDKit::common_properties::_MolFileChiralFlag, chiralflag); checkChiral = chiralflag != 0; } mol = *frags[maxFragIdx].get(); // We need to see if the mol file's chirality possibly came from this // fragment. if (checkChiral) { bool ischiral = false; RWMol copy(mol); try { MolOps::sanitizeMol(copy); ClearSingleBondDirFlags(copy); const Conformer &conf = copy.getConformer(); DetectBondStereoChemistry(copy, &conf); MolOps::assignStereochemistry(copy, true, true, true); for (ROMol::AtomIterator atIt =copy.beginAtoms(); atIt != copy.endAtoms(); ++atIt) { if((*atIt)->hasProp(common_properties::_ChiralityPossible)) { ischiral = true; checkChiral = false; break; } } } catch (...) { } // are chiral tags set if(checkChiral) { for (ROMol::AtomIterator atIt = mol.beginAtoms(); atIt != mol.endAtoms(); ++atIt) { if ( (*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CW || (*atIt)->getChiralTag() == Atom::CHI_TETRAHEDRAL_CCW ) { ischiral = true; break; } } for (ROMol::BondIterator bondIt = mol.beginBonds(); bondIt != mol.endBonds(); ++bondIt) { if ((*bondIt)->getBondDir() == Bond::BEGINDASH || (*bondIt)->getBondDir() == Bond::BEGINWEDGE) { ischiral = true; break; } } } if (!ischiral) { mol.setProp<unsigned int>(RDKit::common_properties::_MolFileChiralFlag, 0); } } return true; }