double AlignMolecule(ROMol &prbMol, const ROMol &refMol, int prbCid = -1, int refCid = -1, python::object atomMap = python::list(), python::object weights = python::list(), bool reflect = false, unsigned int maxIters = 50) { MatchVectType *aMap = _translateAtomMap(atomMap); unsigned int nAtms; if (aMap) { nAtms = aMap->size(); } else { nAtms = prbMol.getNumAtoms(); } RDNumeric::DoubleVector *wtsVec = _translateWeights(weights); if (wtsVec) { if (wtsVec->size() != nAtms) { throw_value_error("Incorrect number of weights specified"); } } double rmsd; { NOGIL gil; rmsd = MolAlign::alignMol(prbMol, refMol, prbCid, refCid, aMap, wtsVec, reflect, maxIters); } if (aMap) { delete aMap; } if (wtsVec) { delete wtsVec; } return rmsd; }
void testMMFFO3AConstraintsAndLocalOnly() { std::string rdbase = getenv("RDBASE"); std::string sdf = rdbase + "/Code/GraphMol/MolAlign/test_data/ref_e2.sdf"; SDMolSupplier supplier(sdf, true, false); const int refNum = 23; const int prbNum = 32; ROMol *refMol = supplier[refNum]; ROMol *prbMol = supplier[prbNum]; unsigned int refNAtoms = refMol->getNumAtoms(); std::vector<double> refLogpContribs(refNAtoms); std::vector<double> refMRContribs(refNAtoms); std::vector<unsigned int> refAtomTypes(refNAtoms); std::vector<std::string> refAtomTypeLabels(refNAtoms); Descriptors::getCrippenAtomContribs(*refMol, refLogpContribs, refMRContribs, true, &refAtomTypes, &refAtomTypeLabels); unsigned int prbNAtoms = prbMol->getNumAtoms(); std::vector<double> prbLogpContribs(prbNAtoms); std::vector<double> prbMRContribs(prbNAtoms); std::vector<unsigned int> prbAtomTypes(prbNAtoms); std::vector<std::string> prbAtomTypeLabels(prbNAtoms); Descriptors::getCrippenAtomContribs(*prbMol, prbLogpContribs, prbMRContribs, true, &prbAtomTypes, &prbAtomTypeLabels); RWMol *patt = SmartsToMol("S"); MatchVectType matchVect; TEST_ASSERT(SubstructMatch(*refMol, (ROMol &)*patt, matchVect)); delete patt; unsigned int refSIdx = matchVect[0].second; matchVect.clear(); patt = SmartsToMol("O"); TEST_ASSERT(SubstructMatch(*prbMol, (ROMol &)*patt, matchVect)); delete patt; unsigned int prbOIdx = matchVect[0].second; std::vector<double> distOS(2); distOS[0] = 2.7; distOS[1] = 0.4; std::vector<double> weights(2); weights[0] = 0.1; weights[1] = 100.0; for (unsigned int i = 0; i < 2; ++i) { MatchVectType constraintMap; constraintMap.push_back(std::make_pair(prbOIdx, refSIdx)); RDNumeric::DoubleVector constraintWeights(1); constraintWeights[0] = weights[i]; MolAlign::O3A *o3a = new MolAlign::O3A(*prbMol, *refMol, &prbLogpContribs, &refLogpContribs, MolAlign::O3A::CRIPPEN, -1, -1, false, 50, 0, &constraintMap, &constraintWeights); TEST_ASSERT(o3a); o3a->align(); delete o3a; o3a = new MolAlign::O3A(*prbMol, *refMol, &prbLogpContribs, &refLogpContribs, MolAlign::O3A::CRIPPEN, -1, -1, false, 50, MolAlign::O3_LOCAL_ONLY); TEST_ASSERT(o3a); o3a->align(); delete o3a; double d = (prbMol->getConformer().getAtomPos(prbOIdx) - refMol->getConformer().getAtomPos(refSIdx)).length(); TEST_ASSERT(feq(d, distOS[i], 0.1)); } }
void testDativeMatch() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Test dative-bond matching" << std::endl; { std::string smi = "[Cu]->[Fe]"; ROMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); // make sure a self-match works MatchVectType match; TEST_ASSERT(SubstructMatch(*mol, *mol, match)); TEST_ASSERT(match.size() == mol->getNumAtoms()); { // reverse the order and make sure that works std::string sma = "[Fe]<-[Cu]"; ROMol *qmol = SmilesToMol(sma); TEST_ASSERT(qmol); MatchVectType match; TEST_ASSERT(SubstructMatch(*mol, *qmol, match)); TEST_ASSERT(match.size() == qmol->getNumAtoms()); delete qmol; } { // reverse the direction and make sure that does not work. std::string sma = "[Fe]->[Cu]"; ROMol *qmol = SmilesToMol(sma); TEST_ASSERT(qmol); MatchVectType match; TEST_ASSERT(!SubstructMatch(*mol, *qmol, match)); delete qmol; } delete mol; } BOOST_LOG(rdErrorLog) << " done" << std::endl; }
PyObject *getMolAlignTransform(const ROMol &prbMol, const ROMol &refMol, int prbCid = -1, int refCid = -1, python::object atomMap = python::list(), python::object weights = python::list(), bool reflect = false, unsigned int maxIters = 50) { MatchVectType *aMap = _translateAtomMap(atomMap); unsigned int nAtms; if (aMap) { nAtms = aMap->size(); } else { nAtms = prbMol.getNumAtoms(); } RDNumeric::DoubleVector *wtsVec = _translateWeights(weights); if (wtsVec) { if (wtsVec->size() != nAtms) { throw_value_error("Incorrect number of weights specified"); } } RDGeom::Transform3D trans; double rmsd; { NOGIL gil; rmsd = MolAlign::getAlignmentTransform( prbMol, refMol, trans, prbCid, refCid, aMap, wtsVec, reflect, maxIters); } if (aMap) { delete aMap; } if (wtsVec) { delete wtsVec; } return generateRmsdTransPyTuple(rmsd, trans); }
void test4() { std::cout << " ----------------- Test 4" << std::endl; MatchVectType matchV; std::vector<MatchVectType> matches; int n; bool updateLabel = true; bool takeOwnership = true; RWMol *m, *q1, *q2; auto *a6 = new Atom(6); auto *a8 = new Atom(8); m = new RWMol(); m->addAtom(a6); m->addAtom(a6); m->addAtom(a8); m->addAtom(a6); m->addAtom(a6); m->addBond(1, 0, Bond::SINGLE); m->addBond(1, 2, Bond::SINGLE); m->addBond(1, 3, Bond::SINGLE); m->addBond(2, 4, Bond::SINGLE); // this will be the recursive query q1 = new RWMol(); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addAtom(new QueryAtom(8), updateLabel, takeOwnership); q1->addBond(0, 1, Bond::UNSPECIFIED); // here's the main query q2 = new RWMol(); auto *qA = new QueryAtom(6); auto *rsq = new RecursiveStructureQuery(q1); qA->expandQuery(rsq, Queries::COMPOSITE_AND); // std::cout << "post expand: " << qA->getQuery() << std::endl; q2->addAtom(qA, true, true); // std::cout << "mol: " << q2->getAtomWithIdx(0)->getQuery() << std::endl; q2->addAtom(new QueryAtom(6), true, true); q2->addBond(0, 1, Bond::UNSPECIFIED); bool found = SubstructMatch(*m, *q2, matchV); CHECK_INVARIANT(found, ""); CHECK_INVARIANT(matchV.size() == 2, ""); TEST_ASSERT(matchV[0].first == 0); TEST_ASSERT(matchV[0].second == 1); TEST_ASSERT(matchV[1].first == 1); TEST_ASSERT(matchV[1].second == 0 || matchV[1].second == 3); n = SubstructMatch(*m, *q2, matches, true); TEST_ASSERT(n == 2); TEST_ASSERT(matches.size() == (size_t)n); TEST_ASSERT(matches[0].size() == 2); TEST_ASSERT(matches[1].size() == 2); TEST_ASSERT(matches[0][0].second == matches[1][0].second); TEST_ASSERT(matches[0][1].second != matches[1][1].second); delete m; delete a6; delete a8; delete q2; std::cout << "Done\n" << std::endl; }
void testSubstructMatchDMAP() { BOOST_LOG(rdInfoLog) << "-----------------------\n" << "testSubstructMatchDMAP" << std::endl; RWMol *mol = SmilesToMol("C(C)Nc1cc[nH+]cc1"); RWMol *query = SmartsToMol("[#7+]"); ResonanceMolSupplier *resMolSuppl; unsigned int n; MatchVectType p; resMolSuppl = new ResonanceMolSupplier((ROMol &)*mol); std::vector<MatchVectType> matchVect; n = SubstructMatch(*mol, *query, matchVect, false, true, false, false); TEST_ASSERT((n == 1) && (matchVect.size() == 1)); p = matchVect[0]; TEST_ASSERT((p.size() == 1) && (p[0].second == 6)); matchVect.clear(); n = SubstructMatch(*resMolSuppl, *query, matchVect, false, true, false, false); TEST_ASSERT((n == 2) && (matchVect.size() == 2)); std::vector<unsigned int> v; p = matchVect[0]; TEST_ASSERT(p.size() == 1); v.push_back(p[0].second); p = matchVect[1]; TEST_ASSERT(p.size() == 1); v.push_back(p[0].second); std::sort(v.begin(), v.end()); TEST_ASSERT(v[0] == 2); TEST_ASSERT(v[1] == 6); delete mol; delete query; delete resMolSuppl; }
double getAlignmentTransform(const ROMol &prbMol, const ROMol &refMol, RDGeom::Transform3D &trans, int prbCid, int refCid, const MatchVectType *atomMap, const RDNumeric::DoubleVector *weights, bool reflect, unsigned int maxIterations) { RDGeom::Point3DConstPtrVect refPoints, prbPoints; const Conformer &prbCnf = prbMol.getConformer(prbCid); const Conformer &refCnf = refMol.getConformer(refCid); if (atomMap == 0) { // we have to figure out the mapping between the two molecule MatchVectType match; if (SubstructMatch(refMol, prbMol, match)) { MatchVectType::const_iterator mi; for (mi = match.begin(); mi != match.end(); mi++) { prbPoints.push_back(&prbCnf.getAtomPos(mi->first)); refPoints.push_back(&refCnf.getAtomPos(mi->second)); } } else { throw MolAlignException("No sub-structure match found between the probe and query mol"); } } else { MatchVectType::const_iterator mi; for (mi = atomMap->begin(); mi != atomMap->end(); mi++) { prbPoints.push_back(&prbCnf.getAtomPos(mi->first)); refPoints.push_back(&refCnf.getAtomPos(mi->second)); } } double ssr = RDNumeric::Alignments::AlignPoints(refPoints, prbPoints, trans, weights, reflect, maxIterations); ssr /= (prbPoints.size()); return sqrt(ssr); }
ROMol *prepareMol(const ROMol &mol, const FragCatParams *fparams, MatchVectType &aToFmap) { PRECONDITION(fparams,""); // get a mapping of the functional groups onto the molecule INT_VECT fgBonds; MatchVectType aidToFid = findFuncGroupsOnMol(mol, fparams, fgBonds); // get the core piece of molecule (i.e. the part of the molecule // without the functional groups). This basically the part of the molecule // that does not contain the function group bonds given by "fgBonds" INT_VECT cBonds; int bid, nbds = mol.getNumBonds(); for (bid = 0; bid < nbds; bid++) { if (std::find(fgBonds.begin(), fgBonds.end(), bid) == fgBonds.end()) { cBonds.push_back(bid); } } INT_MAP_INT aIdxMap; // a map from atom id in mol to the new atoms id in coreMol ROMol *coreMol = Subgraphs::pathToSubmol(mol, cBonds, false, aIdxMap); // now map the functional groups on mol to coreMol using aIdxMap MatchVectType::iterator mati; int newID; for (mati = aidToFid.begin(); mati != aidToFid.end(); mati++) { newID = aIdxMap[mati->first]; aToFmap.push_back(std::pair<int, int>(newID, mati->second)); } return coreMol; }
//************************************************************************************* // // Adds 2D coordinates to a molecule using the Depict.dll // // ARGUMENTS: // mol: the molecule to be altered // tempFilename: (OPTIONAL) the name of the temporary file // // RETURNS: // 1 on success, 0 otherwise // // Here's the process by which this works (it's kind of contorted): // 1) convert the mol to SMILES // 2) use the DLL to convert the SMILES to a mol file (on disk) // 3) parse the mol file into a temporary molecule // 4) do a substructure match from the old molecule to the // temp one (which may have a different atom numbering or additional // atoms added). // 5) Update the positions of the atoms on the old molecule. // 6) Free the temp molecule. // // NOTES: // - *FIX:* at the moment we're not doing anything to clear up the // temp file created in this process. It'll always have the same // name unless the user explicitly asks that we do something different. // - To use the DLL, it's essential that the COMBICHEM_ROOT and COMBICHEM_RELEASE // environment variables be set. If this isn't done, this whole process // will fail. // - See the notes above about failures when opening the DLL. // //************************************************************************************* int Add2DCoordsToMolDLL(ROMol &mol,std::string tempFilename){ std::string smi=MolToSmiles(mol,true); int tmp = SmilesToMolFileDLL(smi,tempFilename); int res = -1; if(tmp){ // build another mol from that mol file: RWMol *tmpMol = MolFileToMol(tempFilename,false); // match it up with the starting mol: // (We need to do this because the depict.dll conversion // to a mol file may have added Hs) MatchVectType matchVect; bool hasMatch=SubstructMatch(tmpMol,&mol,matchVect); if(hasMatch){ const Conformer &conf = tmpMol->getCoformer(0); Coformer *nconf = new Coformer(mol.getNumAtoms()); for(MatchVectType::const_iterator mvi=matchVect.begin(); mvi!=matchVect.end();mvi++){ nconf->setAtomPos(conf.getAtomPos(mvi->first)); } confId = (int)mol.addConformer(nconf, true); } delete tmpMol; } return res; }
bool StructCheckTautomer::applyTautomer(unsigned it) { if (Options.FromTautomer.size() <= it || Options.ToTautomer.size() <= it) { if (Options.Verbose) BOOST_LOG(rdInfoLog) << "ERROR: incorrect Tautomer index it=" << it << "\n"; return false; } const ROMol &fromTautomer = *Options.FromTautomer[it]; const ROMol &toTautomer = *Options.ToTautomer[it]; if (toTautomer.getNumAtoms() != fromTautomer.getNumAtoms()) { if (Options.Verbose) BOOST_LOG(rdInfoLog) << "ERROR: incorrect data toTautomer.getNumAtoms() " "!= fromTautomer.getNumAtoms()\n"; // incorrect data // throw(.....); return false; } const unsigned nta = toTautomer.getNumAtoms(); const unsigned ntb = toTautomer.getNumBonds(); MatchVectType match; // The format is (queryAtomIdx, molAtomIdx) std::vector<unsigned> atomIdxMap( Mol.getNumAtoms()); // matched tau atom indeces if (!SubstructMatch(Mol, *Options.FromTautomer[it], match)) // SSMatch(mp, from_tautomer, SINGLE_MATCH); return false; if (Options.Verbose) BOOST_LOG(rdInfoLog) << "found match for from_tautomer with " << nta << " atoms\n"; // init for (unsigned i = 0; i < Mol.getNumAtoms(); i++) atomIdxMap[i] = -1; for (MatchVectType::const_iterator mit = match.begin(); mit != match.end(); mit++) { unsigned tai = mit->first; // From and To Tautomer Atom index unsigned mai = mit->second; // Mol Atom index atomIdxMap[mai] = tai; } // scan for completely mapped bonds and replace bond order with mapped bond // from to_tautomer for (RDKit::BondIterator_ bond = Mol.beginBonds(); bond != Mol.endBonds(); bond++) { unsigned ti = atomIdxMap[(*bond)->getBeginAtomIdx()]; unsigned tj = atomIdxMap[(*bond)->getEndAtomIdx()]; if (-1 == ti || -1 == tj) continue; const Bond *tb = toTautomer.getBondBetweenAtoms(ti, tj); if (tb && (*bond)->getBondType() != tb->getBondType()) { (*bond)->setBondType(tb->getBondType()); } } // apply charge/radical fixes if any for (unsigned i = 0; i < match.size(); i++) { Atom &atom = *Mol.getAtomWithIdx(match[i].second); const Atom &ta = *toTautomer.getAtomWithIdx(match[i].first); atom.setFormalCharge(ta.getFormalCharge()); atom.setNumRadicalElectrons(ta.getNumRadicalElectrons()); } return true; }
void test2(){ std::cout << " ----------------- Test 2" << std::endl; MatchVectType matchV; std::vector< MatchVectType > matches; unsigned int n; RWMol *m,*q1; m = new RWMol(); m->addAtom(new Atom(6)); m->addAtom(new Atom(6)); m->addAtom(new Atom(8)); m->addBond(0,1,Bond::SINGLE); m->addBond(1,2,Bond::SINGLE); q1 = new RWMol(); q1->addAtom(new QueryAtom(6)); q1->addAtom(new QueryAtom(8)); q1->addBond(0,1,Bond::SINGLE); n = SubstructMatch(*m,*q1,matchV); TEST_ASSERT(n); TEST_ASSERT(matchV.size()==2); TEST_ASSERT(matchV[0].first==0); TEST_ASSERT(matchV[0].second==1); TEST_ASSERT(matchV[1].first==1); TEST_ASSERT(matchV[1].second==2); n = SubstructMatch(*m,*q1,matches,false); CHECK_INVARIANT(n==1,""); CHECK_INVARIANT(matches.size()==n,""); CHECK_INVARIANT(matches[0].size()==2,""); n = SubstructMatch(*m,*q1,matches,true); CHECK_INVARIANT(n==1,""); CHECK_INVARIANT(matches.size()==n,""); CHECK_INVARIANT(matches[0].size()==2,""); CHECK_INVARIANT(SubstructMatch(*m,*q1,matchV),""); CHECK_INVARIANT(matchV.size()==2,""); delete m; m = new RWMol(); m->addAtom(new Atom(6)); m->addAtom(new Atom(6)); m->addAtom(new Atom(8)); m->addBond(0,1,Bond::SINGLE); m->addBond(1,2,Bond::DOUBLE); matches.clear(); n = SubstructMatch(*m,*q1,matches,false); CHECK_INVARIANT(n==0,""); CHECK_INVARIANT(matches.size()==n,""); n = SubstructMatch(*m,*q1,matches,true); CHECK_INVARIANT(n==0,""); CHECK_INVARIANT(matches.size()==n,""); CHECK_INVARIANT(!SubstructMatch(*m,*q1,matchV),""); std::cout << "Done\n" << std::endl; }
void testRecursiveSerialNumbers(){ std::cout << " ----------------- Testing serial numbers on recursive queries" << std::endl; MatchVectType matchV; std::vector< MatchVectType > matches; int n; RWMol *m,*q1,*q2; Atom *a6 = new Atom(6); Atom *a8 = new Atom(8); m = new RWMol(); m->addAtom(a6); m->addAtom(a6); m->addAtom(a8); m->addAtom(a6); m->addAtom(a6); m->addBond(1,0,Bond::SINGLE); m->addBond(1,2,Bond::SINGLE); m->addBond(1,3,Bond::SINGLE); m->addBond(2,4,Bond::SINGLE); { // this will be the recursive query q1 = new RWMol(); q1->addAtom(new QueryAtom(6),true); q1->addAtom(new QueryAtom(8),true); q1->addBond(0,1,Bond::UNSPECIFIED); // here's the main query q2 = new RWMol(); QueryAtom *qA = new QueryAtom(6); RecursiveStructureQuery *rsq = new RecursiveStructureQuery(new RWMol(*q1),1); qA->expandQuery(rsq,Queries::COMPOSITE_AND); //std::cout << "post expand: " << qA->getQuery() << std::endl; q2->addAtom(qA,true,true); //std::cout << "mol: " << q2->getAtomWithIdx(0)->getQuery() << std::endl; q2->addAtom(new QueryAtom(8),true,true); q2->addBond(0,1,Bond::UNSPECIFIED); qA = new QueryAtom(6); rsq = new RecursiveStructureQuery(new RWMol(*q1),1); qA->expandQuery(rsq,Queries::COMPOSITE_AND); q2->addAtom(qA,true,true); q2->addBond(1,2,Bond::UNSPECIFIED); bool found = SubstructMatch(*m,*q2,matchV); CHECK_INVARIANT(found,""); CHECK_INVARIANT(matchV.size()==3,""); n = SubstructMatch(*m,*q2,matches,true); TEST_ASSERT(n==1); TEST_ASSERT(matches.size()==1); TEST_ASSERT(matches[0].size()==3); delete q1; delete q2; } delete m; std::cout << "Done\n" << std::endl; }
void test4() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << "FeatureDef functionality testing." << std::endl; ROMol *testMol; MatchVectType mv; std::string inText; int res; MolChemicalFeatureDef::CollectionType featureDefs; MolChemicalFeatureDef::CollectionType::const_iterator featDefIt; MolChemicalFeatureDef::CollectionType::value_type featDef; inText = "DefineFeature HDonor1 [N,O;!H0]\n" " Family HBondDonor\n" " Weights 1.0\n" "EndFeature\n" "DefineFeature HAcceptor1 [N,O]\n" " Family HAcceptor\n" " Weights 1.0\n" "EndFeature\n"; res = parseFeatureData(inText, featureDefs); TEST_ASSERT(!res); TEST_ASSERT(featureDefs.size() == 2); featDefIt = featureDefs.begin(); featDef = *featDefIt; TEST_ASSERT(featDef->getSmarts() == "[N,O;!H0]"); TEST_ASSERT(featDef->getPattern()); TEST_ASSERT(featDef->getPattern()->getNumAtoms() == 1); TEST_ASSERT(featDef->getNumWeights() == 1); featDef = *(++featureDefs.begin()); TEST_ASSERT(featDef->getSmarts() == "[N,O]"); TEST_ASSERT(featDef->getPattern()); TEST_ASSERT(featDef->getPattern()->getNumAtoms() == 1); TEST_ASSERT(featDef->getNumWeights() == 1); testMol = SmilesToMol("COCN"); TEST_ASSERT(testMol); featDef = *featureDefs.begin(); TEST_ASSERT(SubstructMatch(*testMol, *featDef->getPattern(), mv)); TEST_ASSERT(mv.size() == 1); TEST_ASSERT(mv[0].first == 0); TEST_ASSERT(mv[0].second == 3); featDef = *(++featureDefs.begin()); TEST_ASSERT(SubstructMatch(*testMol, *featDef->getPattern(), mv)); TEST_ASSERT(mv.size() == 1); TEST_ASSERT(mv[0].first == 0); TEST_ASSERT(mv[0].second == 1 || mv[0].second == 3); delete testMol; BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void test5QueryRoot() { std::cout << " ----------------- Test 5 QueryRoot" << std::endl; MatchVectType matchV; std::vector<MatchVectType> matches; int n; bool updateLabel = true; bool takeOwnership = true; RWMol *m, *q1, *q2; auto *a6 = new Atom(6); auto *a8 = new Atom(8); // CC(OC)C m = new RWMol(); m->addAtom(a6); m->addAtom(a6); m->addAtom(a8); m->addAtom(a6); m->addAtom(a6); m->addBond(0, 1, Bond::SINGLE); m->addBond(1, 2, Bond::SINGLE); m->addBond(1, 4, Bond::SINGLE); m->addBond(2, 3, Bond::SINGLE); // this will be the recursive query q1 = new RWMol(); q1->addAtom(new QueryAtom(8), updateLabel, takeOwnership); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addBond(0, 1, Bond::UNSPECIFIED); q1->setProp(common_properties::_queryRootAtom, 1); // here's the main query q2 = new RWMol(); auto *qA = new QueryAtom(); auto *rsq = new RecursiveStructureQuery(q1); qA->setQuery(rsq); q2->addAtom(qA, true, true); q2->addAtom(new QueryAtom(6), true, true); q2->addBond(0, 1, Bond::UNSPECIFIED); bool found = SubstructMatch(*m, *q2, matchV); CHECK_INVARIANT(found, ""); CHECK_INVARIANT(matchV.size() == 2, ""); n = SubstructMatch(*m, *q2, matches, true); CHECK_INVARIANT(n == 2, ""); CHECK_INVARIANT(matches[0].size() == 2, ""); delete m; delete a6; delete a8; delete q2; std::cout << "Done\n" << std::endl; }
void testCrippenO3AConstraints() { ROMol *m = SmilesToMol("n1ccc(cc1)-c1ccccc1"); TEST_ASSERT(m); ROMol *m1 = MolOps::addHs(*m); delete m; TEST_ASSERT(m1); DGeomHelpers::EmbedMolecule(*m1); MMFF::sanitizeMMFFMol((RWMol &)(*m1)); MMFF::MMFFMolProperties mp(*m1); TEST_ASSERT(mp.isValid()); ForceFields::ForceField *field = MMFF::constructForceField(*m1, &mp); field->initialize(); field->minimize(); RWMol *patt = SmartsToMol("nccc-cccc"); MatchVectType matchVect; TEST_ASSERT(SubstructMatch(*m1, (ROMol &)*patt, matchVect)); unsigned int nIdx = matchVect[0].second; unsigned int cIdx = matchVect[matchVect.size() - 1].second; MolTransforms::setDihedralDeg(m1->getConformer(), matchVect[2].second, matchVect[3].second, matchVect[4].second, matchVect[5].second, 0.0); ROMol m2(*m1); MolAlign::randomTransform(m2); ROMol m3(m2); unsigned int prbNAtoms = m2.getNumAtoms(); std::vector<double> prbLogpContribs(prbNAtoms); std::vector<double> prbMRContribs(prbNAtoms); std::vector<unsigned int> prbAtomTypes(prbNAtoms); std::vector<std::string> prbAtomTypeLabels(prbNAtoms); Descriptors::getCrippenAtomContribs(m2, prbLogpContribs, prbMRContribs, true, &prbAtomTypes, &prbAtomTypeLabels); MolAlign::O3A *o3a = new MolAlign::O3A(m2, *m1, &prbLogpContribs, &prbLogpContribs, MolAlign::O3A::CRIPPEN); TEST_ASSERT(o3a); o3a->align(); delete o3a; double d = (m2.getConformer().getAtomPos(cIdx) - m1->getConformer().getAtomPos(cIdx)).length(); TEST_ASSERT(feq(d, 0.0, 1)); MatchVectType constraintMap; constraintMap.push_back(std::make_pair(cIdx, nIdx)); o3a = new MolAlign::O3A(m3, *m1, &prbLogpContribs, &prbLogpContribs, MolAlign::O3A::CRIPPEN, -1, -1, false, 50, 0, &constraintMap); TEST_ASSERT(o3a); o3a->align(); delete o3a; d = (m3.getConformer().getAtomPos(cIdx) - m1->getConformer().getAtomPos(cIdx)).length(); TEST_ASSERT(feq(d, 7.0, 1.0)); delete m1; }
void testCrippenO3AConstraintsAndLocalOnly() { std::string rdbase = getenv("RDBASE"); std::string sdf = rdbase + "/Code/GraphMol/MolAlign/test_data/ref_e2.sdf"; SDMolSupplier supplier(sdf, true, false); const int refNum = 23; const int prbNum = 32; ROMol *refMol = supplier[refNum]; ROMol *prbMol = supplier[prbNum]; MMFF::MMFFMolProperties refMP(*refMol); TEST_ASSERT(refMP.isValid()); MMFF::MMFFMolProperties prbMP(*prbMol); TEST_ASSERT(prbMP.isValid()); RWMol *patt = SmartsToMol("S"); MatchVectType matchVect; TEST_ASSERT(SubstructMatch(*refMol, (ROMol &)*patt, matchVect)); delete patt; unsigned int refSIdx = matchVect[0].second; matchVect.clear(); patt = SmartsToMol("O"); TEST_ASSERT(SubstructMatch(*prbMol, (ROMol &)*patt, matchVect)); delete patt; unsigned int prbOIdx = matchVect[0].second; std::vector<double> distOS(2); distOS[0] = 3.2; distOS[1] = 0.3; std::vector<double> weights(2); weights[0] = 10.0; weights[1] = 100.0; for (unsigned int i = 0; i < 2; ++i) { MatchVectType constraintMap; constraintMap.push_back(std::make_pair(prbOIdx, refSIdx)); RDNumeric::DoubleVector constraintWeights(1); constraintWeights[0] = weights[i]; MolAlign::O3A *o3a = new MolAlign::O3A(*prbMol, *refMol, &prbMP, &refMP, MolAlign::O3A::MMFF94, -1, -1, false, 50, 0, &constraintMap, &constraintWeights); TEST_ASSERT(o3a); o3a->align(); delete o3a; o3a = new MolAlign::O3A(*prbMol, *refMol, &prbMP, &refMP, MolAlign::O3A::MMFF94, -1, -1, false, 50, MolAlign::O3_LOCAL_ONLY); TEST_ASSERT(o3a); o3a->align(); delete o3a; double d = (prbMol->getConformer().getAtomPos(prbOIdx) - refMol->getConformer().getAtomPos(refSIdx)).length(); TEST_ASSERT(feq(d, distOS[i], 0.1)); } }
void test6() { std::cout << " ----------------- Test 6 (Issue71 related)" << std::endl; MatchVectType matchV; std::vector<MatchVectType> matches; int n; bool updateLabel = true; bool takeOwnership = true; RWMol *m, *q1; auto *a6 = new Atom(6); m = new RWMol(); m->addAtom(a6); m->addAtom(a6); m->addAtom(a6); m->addBond(0, 1, Bond::SINGLE); m->addBond(1, 2, Bond::SINGLE); m->addBond(0, 2, Bond::SINGLE); q1 = new RWMol(); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addBond(0, 1, Bond::UNSPECIFIED); q1->addBond(1, 2, Bond::UNSPECIFIED); bool found = SubstructMatch(*m, *q1, matchV); CHECK_INVARIANT(found, ""); CHECK_INVARIANT(matchV.size() == 3, ""); n = SubstructMatch(*m, *q1, matches, true); CHECK_INVARIANT(n == 1, ""); CHECK_INVARIANT(matches[0].size() == 3, ""); // close the loop and try again (we should still match) q1->addBond(0, 2, Bond::UNSPECIFIED); found = SubstructMatch(*m, *q1, matchV); CHECK_INVARIANT(found, ""); CHECK_INVARIANT(matchV.size() == 3, ""); n = SubstructMatch(*m, *q1, matches, true); CHECK_INVARIANT(n == 1, ""); CHECK_INVARIANT(matches[0].size() == 3, ""); delete m; delete a6; delete q1; std::cout << "Done\n" << std::endl; }
void test5QueryRoot(){ std::cout << " ----------------- Test 5 QueryRoot" << std::endl; MatchVectType matchV; std::vector< MatchVectType > matches; int n; RWMol *m,*q1,*q2; Atom *a6 = new Atom(6); Atom *a8 = new Atom(8); // CC(OC)C m = new RWMol(); m->addAtom(a6); m->addAtom(a6); m->addAtom(a8); m->addAtom(a6); m->addAtom(a6); m->addBond(0,1,Bond::SINGLE); m->addBond(1,2,Bond::SINGLE); m->addBond(1,4,Bond::SINGLE); m->addBond(2,3,Bond::SINGLE); // this will be the recursive query q1 = new RWMol(); q1->addAtom(new QueryAtom(8),true); q1->addAtom(new QueryAtom(6),true); q1->addBond(0,1,Bond::UNSPECIFIED); q1->setProp("_queryRootAtom",1); // here's the main query q2 = new RWMol(); QueryAtom *qA = new QueryAtom(); RecursiveStructureQuery *rsq = new RecursiveStructureQuery(q1); qA->setQuery(rsq); q2->addAtom(qA,true,true); q2->addAtom(new QueryAtom(6),true,true); q2->addBond(0,1,Bond::UNSPECIFIED); bool found = SubstructMatch(*m,*q2,matchV); CHECK_INVARIANT(found,""); CHECK_INVARIANT(matchV.size()==2,""); n = SubstructMatch(*m,*q2,matches,true); CHECK_INVARIANT(n==2,""); CHECK_INVARIANT(matches[0].size()==2,""); std::cout << "Done\n" << std::endl; }
void test2AtomMap() { std::string rdbase = getenv("RDBASE"); std::string fname1 = rdbase + "/Code/GraphMol/MolAlign/test_data/1oir.mol"; ROMol *m1 = MolFileToMol(fname1); std::string fname2 = rdbase + "/Code/GraphMol/MolAlign/test_data/1oir_conf.mol"; ROMol *m2 = MolFileToMol(fname2); MatchVectType atomMap; atomMap.push_back(std::pair<int, int>(18, 27)); atomMap.push_back(std::pair<int, int>(13, 23)); atomMap.push_back(std::pair<int, int>(21, 14)); atomMap.push_back(std::pair<int, int>(24, 7)); atomMap.push_back(std::pair<int, int>(9, 19)); atomMap.push_back(std::pair<int, int>(16, 30)); double rmsd = MolAlign::alignMol(*m2, *m1, 0, 0, &atomMap); TEST_ASSERT(RDKit::feq(rmsd, 0.8525)); delete m1; delete m2; }
MatchVectType *_translateAtomMap(python::object atomMap) { PySequenceHolder<python::object> aMapSeq(atomMap); MatchVectType *aMap; aMap = 0; unsigned int i, nAtms = aMapSeq.size(); if (nAtms > 0) { aMap = new MatchVectType; for (i = 0; i < nAtms; ++i) { PySequenceHolder<int> item(aMapSeq[i]); if (item.size() != 2) { delete aMap; aMap = 0; throw_value_error("Incorrect format for atomMap"); } aMap->push_back(std::pair<int, int>(item[0], item[1])); } } return aMap; }
void test7() { std::cout << " ----------------- Test 7 (leak check)" << std::endl; MatchVectType matchV; int n; RWMol *m, *q1; auto *a6 = new Atom(6); bool updateLabel = true; bool takeOwnership = true; m = new RWMol(); m->addAtom(a6); m->addAtom(a6); m->addAtom(a6); m->addBond(0, 1, Bond::SINGLE); m->addBond(1, 2, Bond::SINGLE); m->addBond(0, 2, Bond::SINGLE); q1 = new RWMol(); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addBond(0, 1, Bond::UNSPECIFIED); q1->addBond(1, 2, Bond::UNSPECIFIED); bool found = SubstructMatch(*m, *q1, matchV); CHECK_INVARIANT(found, ""); CHECK_INVARIANT(matchV.size() == 3, ""); std::vector<MatchVectType> matches; for (int i = 0; i < 300000; i++) { n = SubstructMatch(*m, *q1, matches, true, true); CHECK_INVARIANT(n == 1, ""); CHECK_INVARIANT(matches[0].size() == 3, ""); if (!(i % 500)) std::cout << i << std::endl; } delete m; delete a6; delete q1; std::cout << "Done\n" << std::endl; }
bool check(MatchVectType v, MatchVectType match) { dump("v", v); dump("match", match); for (size_t i = 0; i < v.size(); ++i) { if (v[i].first != match[i].first) { return false; } if (v[i].second != match[i].second) { return false; } } return true; }
void test3Weights() { std::string rdbase = getenv("RDBASE"); std::string fname1 = rdbase + "/Code/GraphMol/MolAlign/test_data/1oir.mol"; ROMol *m1 = MolFileToMol(fname1); std::string fname2 = rdbase + "/Code/GraphMol/MolAlign/test_data/1oir_conf.mol"; ROMol *m2 = MolFileToMol(fname2); MatchVectType atomMap; atomMap.push_back(std::pair<int, int>(18, 27)); atomMap.push_back(std::pair<int, int>(13, 23)); atomMap.push_back(std::pair<int, int>(21, 14)); atomMap.push_back(std::pair<int, int>(24, 7)); atomMap.push_back(std::pair<int, int>(9, 19)); atomMap.push_back(std::pair<int, int>(16, 30)); RDNumeric::DoubleVector wts(6); wts.setVal(0, 1.0); wts.setVal(1, 1.0); wts.setVal(2, 1.0); wts.setVal(3, 1.0); wts.setVal(4, 1.0); wts.setVal(5, 2.0); double rmsd = MolAlign::alignMol(*m2, *m1, 0, 0, &atomMap, &wts); TEST_ASSERT(RDKit::feq(rmsd, 0.9513)); delete m1; delete m2; }
void test8(){ std::cout << " ----------------- Test 8 (molgraph cache)" << std::endl; MatchVectType matchV; int n; RWMol *m,*q1; Atom *a6 = new Atom(6); m = new RWMol(); m->addAtom(a6); m->addAtom(a6); m->addAtom(a6); m->addBond(0,1,Bond::SINGLE); m->addBond(1,2,Bond::SINGLE); m->addBond(0,2,Bond::SINGLE); q1 = new RWMol(); q1->addAtom(new QueryAtom(6),true); q1->addAtom(new QueryAtom(6),true); q1->addAtom(new QueryAtom(6),true); q1->addBond(0,1,Bond::UNSPECIFIED); q1->addBond(1,2,Bond::UNSPECIFIED); bool found = SubstructMatch(*m,*q1,matchV); CHECK_INVARIANT(found,""); CHECK_INVARIANT(matchV.size()==3,""); std::vector< MatchVectType > matches; for(int i=0;i<30000;i++){ n = SubstructMatch(*m,*q1,matches,true,true); CHECK_INVARIANT(n==1,""); CHECK_INVARIANT(matches[0].size()==3,""); if(! (i%500) ) std::cout << i << std::endl; } std::cout << "Done\n" << std::endl; }
MatchVectType findFuncGroupsOnMol(const ROMol &mol, const FragCatParams *params, INT_VECT &fgBonds) { PRECONDITION(params,"bad params"); fgBonds.clear(); std::pair<int, int> amat; MatchVectType aidFgrps; std::vector<MatchVectType> fgpMatches; std::vector<MatchVectType>::const_iterator mati; MatchVectType::const_iterator mi; int aid; //const ROMol *fgrp; INT_VECT_CI bi; aidFgrps.clear(); int fid = 0; const MOL_SPTR_VECT &fgrps = params->getFuncGroups(); MOL_SPTR_VECT::const_iterator fgci; for (fgci = fgrps.begin(); fgci != fgrps.end(); fgci++) { const ROMol *fgrp = fgci->get(); std::string fname; (*fgci)->getProp(common_properties::_Name, fname); //std::cout << "Groups number: " << fname << "\n"; //(*fgci)->debugMol(std::cout); //mol->debugMol(std::cout); // match this functional group onto the molecule SubstructMatch(mol, *fgrp, fgpMatches); // loop over all the matches we get for this fgroup for (mati = fgpMatches.begin(); mati != fgpMatches.end(); mati++) { //FIX: we will assume that the first atom in fgrp is always the connection // atom amat = mati->front(); aid = amat.second; //FIX: is this correct - the second entry in the pair is the atom ID from mol // grab the list of atom Ids from mol that match the functional group INT_VECT bondIds, maids; for (mi = mati->begin(); mi != mati->end(); mi++) { maids.push_back(mi->second); } // create a list of bond IDs from these atom ID // these are the bond in mol that are part of portion that matches the // functional group bondIds = Subgraphs::bondListFromAtomList(mol, maids); // now check if all these bonds have been covered as part of larger // functional group that was dealt with earlier // FIX: obviously we assume here that the function groups in params // come in decreasing order of size. bool allDone = true; for (bi = bondIds.begin(); bi != bondIds.end(); bi++) { if (std::find(fgBonds.begin(), fgBonds.end(), (*bi)) == fgBonds.end()) { allDone = false; fgBonds.push_back(*bi); } } if (!allDone) { // this functional group mapping onto mol is not part of a larger func // group mapping so record it aidFgrps.push_back(std::pair<int, int>(aid, fid)); } } fid++; } return aidFgrps; }
void testGitHubIssue688() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Test GitHub issue 688: partially specified " "chiral substructure queries don't work properly" << std::endl; { std::string smi = "C1CC[C@](Cl)(N)O1"; ROMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); // mol->debugMol(std::cerr); std::string sma = "C1CC[C@](N)O1"; ROMol *qmol = SmartsToMol(sma); TEST_ASSERT(qmol); // qmol->updatePropertyCache(); // qmol->debugMol(std::cerr); MatchVectType match; TEST_ASSERT(SubstructMatch(*mol, *qmol, match, true, false)); TEST_ASSERT(match.size() == qmol->getNumAtoms()); TEST_ASSERT(SubstructMatch(*mol, *qmol, match, true, true)); TEST_ASSERT(match.size() == qmol->getNumAtoms()); delete mol; delete qmol; } { std::string smi = "C1CC[C@](Cl)(N)O1"; ROMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); // mol->debugMol(std::cerr); std::string sma = "C1CC[C@@](N)O1"; ROMol *qmol = SmartsToMol(sma); TEST_ASSERT(qmol); // qmol->updatePropertyCache(); // qmol->debugMol(std::cerr); MatchVectType match; TEST_ASSERT(SubstructMatch(*mol, *qmol, match, true, false)); TEST_ASSERT(match.size() == qmol->getNumAtoms()); TEST_ASSERT(!SubstructMatch(*mol, *qmol, match, true, true)); delete mol; delete qmol; } { std::string smi = "N[C@]1(Cl)CCCO1"; ROMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); // mol->debugMol(std::cerr); std::string sma = "N[C@]1CCCO1"; ROMol *qmol = SmartsToMol(sma); TEST_ASSERT(qmol); // qmol->updatePropertyCache(); // qmol->debugMol(std::cerr); // std::cerr << MolToSmiles(*qmol, true) << std::endl; MatchVectType match; TEST_ASSERT(SubstructMatch(*mol, *qmol, match, true, false)); TEST_ASSERT(match.size() == qmol->getNumAtoms()); TEST_ASSERT(SubstructMatch(*mol, *qmol, match, true, true)); TEST_ASSERT(match.size() == qmol->getNumAtoms()); delete mol; delete qmol; } { std::string smi = "N[C@]1(Cl)CCCO1"; ROMol *mol = SmilesToMol(smi); TEST_ASSERT(mol); // mol->debugMol(std::cerr); std::string sma = "N[C@@]1CCCO1"; ROMol *qmol = SmartsToMol(sma); TEST_ASSERT(qmol); // qmol->updatePropertyCache(); // qmol->debugMol(std::cerr); // std::cerr << MolToSmiles(*qmol, true) << std::endl; MatchVectType match; TEST_ASSERT(SubstructMatch(*mol, *qmol, match, true, false)); TEST_ASSERT(match.size() == qmol->getNumAtoms()); TEST_ASSERT(!SubstructMatch(*mol, *qmol, match, true, true)); delete mol; delete qmol; } BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void test5() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << "FeatureFactory testing." << std::endl; ROMol *testMol; MatchVectType mv; std::string inText; FeatSPtrList featSPtrs; boost::shared_ptr<MolChemicalFeature> featSPtr; MolChemicalFeatureFactory *factory; MolChemicalFeatureDef::CollectionType::value_type featDef; inText = "DefineFeature HDonor1 [N,O;!H0]\n" " Family HBondDonor\n" " Weights 1.0\n" "EndFeature\n" "DefineFeature HAcceptor1 [N,O]\n" " Family HBondAcceptor\n" " Weights 1.0\n" "EndFeature\n"; factory = buildFeatureFactory(inText); TEST_ASSERT(factory); TEST_ASSERT(factory->getNumFeatureDefs() == 2); testMol = SmilesToMol("COCN"); TEST_ASSERT(testMol); featDef = *factory->beginFeatureDefs(); TEST_ASSERT(SubstructMatch(*testMol, *featDef->getPattern(), mv)); BOOST_LOG(rdErrorLog) << "1" << std::endl; TEST_ASSERT(mv.size() == 1); TEST_ASSERT(mv[0].first == 0); TEST_ASSERT(mv[0].second == 3); featDef = *(++factory->beginFeatureDefs()); TEST_ASSERT(SubstructMatch(*testMol, *featDef->getPattern(), mv)); BOOST_LOG(rdErrorLog) << "2" << std::endl; TEST_ASSERT(mv.size() == 1); TEST_ASSERT(mv[0].first == 0); TEST_ASSERT(mv[0].second == 1 || mv[0].second == 3); // Test using the factory to find features: featSPtrs = factory->getFeaturesForMol(*testMol); BOOST_LOG(rdErrorLog) << "3" << std::endl; TEST_ASSERT(featSPtrs.size() == 3); featSPtr = *featSPtrs.begin(); TEST_ASSERT(featSPtr->getFamily() == "HBondDonor"); TEST_ASSERT(featSPtr->getType() == "HDonor1"); featSPtr = *(++featSPtrs.begin()); TEST_ASSERT(featSPtr->getFamily() == "HBondAcceptor"); TEST_ASSERT(featSPtr->getType() == "HAcceptor1"); featSPtr = *(++featSPtrs.begin()); TEST_ASSERT(featSPtr->getFamily() == "HBondAcceptor"); TEST_ASSERT(featSPtr->getType() == "HAcceptor1"); // Test limiting stuff with includeOnly featSPtrs = factory->getFeaturesForMol(*testMol, "HBondAcceptor"); BOOST_LOG(rdErrorLog) << "4" << std::endl; TEST_ASSERT(featSPtrs.size() == 2); featSPtr = *featSPtrs.begin(); TEST_ASSERT(featSPtr->getFamily() == "HBondAcceptor"); TEST_ASSERT(featSPtr->getType() == "HAcceptor1"); featSPtr = *(++featSPtrs.begin()); TEST_ASSERT(featSPtr->getFamily() == "HBondAcceptor"); TEST_ASSERT(featSPtr->getType() == "HAcceptor1"); featSPtrs = factory->getFeaturesForMol(*testMol, "HBondDonor"); BOOST_LOG(rdErrorLog) << "5" << std::endl; TEST_ASSERT(featSPtrs.size() == 1); featSPtr = *featSPtrs.begin(); TEST_ASSERT(featSPtr->getFamily() == "HBondDonor"); TEST_ASSERT(featSPtr->getType() == "HDonor1"); featSPtrs = factory->getFeaturesForMol(*testMol, "NotPresent"); BOOST_LOG(rdErrorLog) << "6" << std::endl; TEST_ASSERT(featSPtrs.size() == 0); delete testMol; delete factory; BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void test3() { std::cout << " ----------------- Test 3" << std::endl; MatchVectType matchV; std::vector<MatchVectType> matches; unsigned int n; RWMol *m, *q1; m = new RWMol(); bool updateLabel = true; bool takeOwnership = true; m->addAtom(new Atom(6), updateLabel, takeOwnership); m->addAtom(new Atom(6), updateLabel, takeOwnership); m->addAtom(new Atom(8), updateLabel, takeOwnership); m->addBond(0, 1, Bond::SINGLE); m->addBond(1, 2, Bond::SINGLE); q1 = new RWMol(); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addAtom(new QueryAtom(8), updateLabel, takeOwnership); q1->addBond(0, 1, Bond::UNSPECIFIED); n = SubstructMatch(*m, *q1, matches, false); CHECK_INVARIANT(n == 1, ""); CHECK_INVARIANT(matches.size() == n, ""); CHECK_INVARIANT(matches[0].size() == 2, ""); n = SubstructMatch(*m, *q1, matches, true); CHECK_INVARIANT(n == 1, ""); CHECK_INVARIANT(matches.size() == n, ""); CHECK_INVARIANT(matches[0].size() == 2, ""); CHECK_INVARIANT(SubstructMatch(*m, *q1, matchV), ""); CHECK_INVARIANT(matchV.size() == 2, ""); delete m; m = new RWMol(); m->addAtom(new Atom(6), updateLabel, takeOwnership); m->addAtom(new Atom(6), updateLabel, takeOwnership); m->addAtom(new Atom(8), updateLabel, takeOwnership); m->addBond(0, 1, Bond::SINGLE); m->addBond(1, 2, Bond::DOUBLE); matches.clear(); n = SubstructMatch(*m, *q1, matches, false); CHECK_INVARIANT(n == 1, ""); CHECK_INVARIANT(matches.size() == n, ""); CHECK_INVARIANT(matches[0].size() == 2, ""); n = SubstructMatch(*m, *q1, matches, true); CHECK_INVARIANT(n == 1, ""); CHECK_INVARIANT(matches.size() == n, ""); CHECK_INVARIANT(matches[0].size() == 2, ""); CHECK_INVARIANT(SubstructMatch(*m, *q1, matchV), ""); CHECK_INVARIANT(matchV.size() == 2, ""); delete q1; q1 = new RWMol(); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addAtom(new QueryAtom(6), updateLabel, takeOwnership); q1->addBond(0, 1, Bond::UNSPECIFIED); n = SubstructMatch(*m, *q1, matches, false); TEST_ASSERT(n == 2); TEST_ASSERT(matches.size() == n); TEST_ASSERT(matches[0].size() == 2); TEST_ASSERT(matches[1].size() == 2); TEST_ASSERT(matches[0][0].second != matches[1][0].second); TEST_ASSERT(matches[0][1].second != matches[1][1].second); n = SubstructMatch(*m, *q1, matches, true); TEST_ASSERT(n == 1); TEST_ASSERT(matches.size() == n); delete m; delete q1; std::cout << "Done\n" << std::endl; }
void test1(){ std::cout << " ----------------- Test 1" << std::endl; MatchVectType matchV; std::vector< MatchVectType > matches; unsigned int n; RWMol *m,*q1; m = new RWMol(); m->addAtom(new Atom(8)); m->addAtom(new Atom(6)); m->addAtom(new Atom(6)); m->addBond(0,1,Bond::SINGLE); m->addBond(1,2,Bond::SINGLE); q1 = new RWMol(); q1->addAtom(new QueryAtom(6)); q1->addAtom(new QueryAtom(6)); q1->addBond(0,1,Bond::SINGLE); n = SubstructMatch(*m,*q1,matches,false); CHECK_INVARIANT(n==2,""); CHECK_INVARIANT(matches.size()==n,""); CHECK_INVARIANT(matches[0].size()==2,""); TEST_ASSERT(matches[0][0].first==0); TEST_ASSERT(matches[0][0].second==1||matches[0][0].second==2); TEST_ASSERT(matches[0][1].first==1); TEST_ASSERT(matches[0][1].second!=matches[0][0].second); TEST_ASSERT(matches[1][1].second==1||matches[0][1].second==2); TEST_ASSERT(matches[1][0].first==0); TEST_ASSERT(matches[1][0].second==1||matches[1][0].second==2); TEST_ASSERT(matches[1][0].second!=matches[0][0].second); TEST_ASSERT(matches[1][0].second==matches[0][1].second); TEST_ASSERT(matches[1][1].first==1); TEST_ASSERT(matches[1][1].second!=matches[1][0].second); TEST_ASSERT(matches[1][1].second==matches[0][0].second); n = SubstructMatch(*m,*q1,matches,true); CHECK_INVARIANT(n==1,""); CHECK_INVARIANT(matches.size()==n,""); CHECK_INVARIANT(matches[0].size()==2,""); TEST_ASSERT(matches[0][0].first==0); TEST_ASSERT(matches[0][0].second==1||matches[0][0].second==2); TEST_ASSERT(matches[0][1].first==1); TEST_ASSERT(matches[0][1].second!=matches[0][0].second); TEST_ASSERT(matches[0][1].second==1||matches[0][1].second==2); CHECK_INVARIANT(SubstructMatch(*m,*q1,matchV),""); CHECK_INVARIANT(matchV.size()==2,""); // make sure we reset the match vectors. // build a query we won't match: q1->addAtom(new QueryAtom(6)); q1->addBond(1,2,Bond::SINGLE); q1->addAtom(new QueryAtom(6)); q1->addBond(2,3,Bond::SINGLE); TEST_ASSERT(!SubstructMatch(*m,*q1,matchV)); TEST_ASSERT(matchV.size()==0); n = SubstructMatch(*m,*q1,matches,false); TEST_ASSERT(n==0); TEST_ASSERT(matches.size()==0); std::cout << "Done\n" << std::endl; }
void addTorsions(const ROMol &mol, MMFFMolProperties *mmffMolProperties, ForceFields::ForceField *field, const std::string &torsionBondSmarts) { PRECONDITION(field, "bad ForceField"); PRECONDITION(mmffMolProperties, "bad MMFFMolProperties"); PRECONDITION(mmffMolProperties->isValid(), "missing atom types - invalid force-field"); std::ostream &oStream = mmffMolProperties->getMMFFOStream(); ROMol::ADJ_ITER nbr1Idx; ROMol::ADJ_ITER end1Nbrs; ROMol::ADJ_ITER nbr2Idx; ROMol::ADJ_ITER end2Nbrs; double totalTorsionEnergy = 0.0; RDGeom::PointPtrVect points; if (mmffMolProperties->getMMFFVerbosity()) { if (mmffMolProperties->getMMFFVerbosity() == MMFF_VERBOSITY_HIGH) { oStream << "\n" "T O R S I O N A L\n\n" "--------------ATOMS--------------- ---ATOM TYPES--- " "FF TORSION -----FORCE Params-----\n" " I J K L I J K L " "CLASS ANGLE ENERGY V1 V2 V3\n" "-------------------------------------------------------------" "-----------------------------------------------------" << std::endl; } points = field->positions(); } std::vector<MatchVectType> matchVect; const ROMol *defaultQuery = DefaultTorsionBondSmarts::query(); const ROMol *query = (torsionBondSmarts == DefaultTorsionBondSmarts::string()) ? defaultQuery : SmartsToMol(torsionBondSmarts); TEST_ASSERT(query); unsigned int nHits = SubstructMatch(mol, *query, matchVect); if (query != defaultQuery) delete query; for (unsigned int i = 0; i < nHits; ++i) { MatchVectType match = matchVect[i]; TEST_ASSERT(match.size() == 2); int idx2 = match[0].second; int idx3 = match[1].second; const Bond *bond = mol.getBondBetweenAtoms(idx2, idx3); TEST_ASSERT(bond); const Atom *jAtom = mol.getAtomWithIdx(idx2); const Atom *kAtom = mol.getAtomWithIdx(idx3); if (((jAtom->getHybridization() == Atom::SP2) || (jAtom->getHybridization() == Atom::SP3)) && ((kAtom->getHybridization() == Atom::SP2) || (kAtom->getHybridization() == Atom::SP3))) { ROMol::OEDGE_ITER beg1, end1; boost::tie(beg1, end1) = mol.getAtomBonds(jAtom); while (beg1 != end1) { const Bond *tBond1 = mol[*beg1].get(); if (tBond1 != bond) { int idx1 = tBond1->getOtherAtomIdx(idx2); ROMol::OEDGE_ITER beg2, end2; boost::tie(beg2, end2) = mol.getAtomBonds(kAtom); while (beg2 != end2) { const Bond *tBond2 = mol[*beg2].get(); if ((tBond2 != bond) && (tBond2 != tBond1)) { int idx4 = tBond2->getOtherAtomIdx(idx3); // make sure this isn't a three-membered ring: if (idx4 != idx1) { // we now have a torsion involving atoms (bonds): // bIdx - (tBond1) - idx1 - (bond) - idx2 - (tBond2) - eIdx unsigned int torType; MMFFTor mmffTorParams; if (mmffMolProperties->getMMFFTorsionParams( mol, idx1, idx2, idx3, idx4, torType, mmffTorParams)) { TorsionAngleContrib *contrib = new TorsionAngleContrib( field, idx1, idx2, idx3, idx4, &mmffTorParams); field->contribs().push_back(ForceFields::ContribPtr(contrib)); if (mmffMolProperties->getMMFFVerbosity()) { const Atom *iAtom = mol.getAtomWithIdx(idx1); const Atom *lAtom = mol.getAtomWithIdx(idx4); unsigned int iAtomType = mmffMolProperties->getMMFFAtomType(idx1); unsigned int jAtomType = mmffMolProperties->getMMFFAtomType(idx2); unsigned int kAtomType = mmffMolProperties->getMMFFAtomType(idx3); unsigned int lAtomType = mmffMolProperties->getMMFFAtomType(idx4); const RDGeom::Point3D p1((*(points[idx1]))[0], (*(points[idx1]))[1], (*(points[idx1]))[2]); const RDGeom::Point3D p2((*(points[idx2]))[0], (*(points[idx2]))[1], (*(points[idx2]))[2]); const RDGeom::Point3D p3((*(points[idx3]))[0], (*(points[idx3]))[1], (*(points[idx3]))[2]); const RDGeom::Point3D p4((*(points[idx4]))[0], (*(points[idx4]))[1], (*(points[idx4]))[2]); const double cosPhi = MMFF::Utils::calcTorsionCosPhi(p1, p2, p3, p4); const double torsionEnergy = MMFF::Utils::calcTorsionEnergy( mmffTorParams.V1, mmffTorParams.V2, mmffTorParams.V3, cosPhi); if (mmffMolProperties->getMMFFVerbosity() == MMFF_VERBOSITY_HIGH) { oStream << std::left << std::setw(2) << iAtom->getSymbol() << " #" << std::setw(5) << idx1 + 1 << std::setw(2) << jAtom->getSymbol() << " #" << std::setw(5) << idx2 + 1 << std::setw(2) << kAtom->getSymbol() << " #" << std::setw(5) << idx3 + 1 << std::setw(2) << lAtom->getSymbol() << " #" << std::setw(5) << idx4 + 1 << std::right << std::setw(5) << iAtomType << std::setw(5) << jAtomType << std::setw(5) << kAtomType << std::setw(5) << lAtomType << std::setw(6) << torType << " " << std::fixed << std::setprecision(3) << std::setw(10) << RAD2DEG * acos(cosPhi) << std::setw(10) << torsionEnergy << std::setw(10) << mmffTorParams.V1 << std::setw(10) << mmffTorParams.V2 << std::setw(10) << mmffTorParams.V3 << std::endl; } totalTorsionEnergy += torsionEnergy; } } } } beg2++; } } beg1++; } } } if (mmffMolProperties->getMMFFVerbosity()) { if (mmffMolProperties->getMMFFVerbosity() == MMFF_VERBOSITY_HIGH) { oStream << std::endl; } oStream << "TOTAL TORSIONAL ENERGY =" << std::right << std::setw(16) << std::fixed << std::setprecision(4) << totalTorsionEnergy << std::endl; } }