void testSFIssue2378119() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing SFIssue2378119." << std::endl; std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/MMFF/test_data"; { RWMol *mol = MolFileToMol(pathName + "/Issue2378119.mol"); TEST_ASSERT(mol); ForceFields::ForceField *field = MMFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); double e1 = field->calcEnergy(); TEST_ASSERT(e1 > 0.0 && e1 < 1.0e12); int needMore = field->minimize(200, 1.0e-6, 1.0e-3); TEST_ASSERT(!needMore); double e2 = field->calcEnergy(); TEST_ASSERT(e2 < e1); delete mol; delete field; } { RWMol *mol = MolFileToMol(pathName + "/Issue2378119.2.mol"); TEST_ASSERT(mol); ForceFields::ForceField *field = MMFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); double e1 = field->calcEnergy(); TEST_ASSERT(e1 == 0.0); int needMore = field->minimize(200, 1.0e-6, 1.0e-3); TEST_ASSERT(!needMore); double e2 = field->calcEnergy(); TEST_ASSERT(e2 == e1); delete mol; delete field; } { RWMol *mol = MolFileToMol(pathName + "/Issue2378119.2.mol"); TEST_ASSERT(mol); ForceFields::ForceField *field = MMFF::constructForceField(*mol, 100.0, -1, false); TEST_ASSERT(field); field->initialize(); double e1 = field->calcEnergy(); TEST_ASSERT(e1 > 0.0 && e1 < 1.0e12); int needMore = field->minimize(200, 1.0e-6, 1.0e-3); TEST_ASSERT(!needMore); double e2 = field->calcEnergy(); TEST_ASSERT(e2 < e1); delete mol; delete field; } BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void testIssue239(){ BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing Issue239." << std::endl; RWMol *mol; int needMore; ForceFields::ForceField *field; double e1,e2; std::string pathName=getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/UFF/test_data"; mol = MolFileToMol(pathName+"/Issue239.mol",false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); field=UFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); needMore = field->minimize(200,1e-6,1e-3); e1 = field->calcEnergy(); needMore = field->minimize(200,1e-6,1e-3); e2 = field->calcEnergy(); TEST_ASSERT(feq(e2,e1,0.1)); delete mol; delete field; BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void testUFFBuilderSpecialCases(){ BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing UFF special cases." << std::endl; RWMol *mol; std::string key; int needMore; RDGeom::Point3D v1,v2; ForceFields::ForceField *field; std::string pathName=getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/UFF/test_data"; // ---------- // Trigonal bipyramid // ---------- mol = MolFileToMol(pathName+"/tbp.mol",false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); const Conformer &conf = mol->getConformer(); field=UFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); needMore = field->minimize(200,1e-8,1e-4); TEST_ASSERT(!needMore); v1 = conf.getAtomPos(0).directionVector(conf.getAtomPos(1)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(2)); TEST_ASSERT(feq(v1.dotProduct(v2),-1.0,1e-3)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(3)); TEST_ASSERT(feq(v1.dotProduct(v2),0.0,1e-3)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(4)); TEST_ASSERT(feq(v1.dotProduct(v2),0.0,1e-3)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(5)); TEST_ASSERT(feq(v1.dotProduct(v2),0.0,1e-3)); v1 = conf.getAtomPos(0).directionVector(conf.getAtomPos(2)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(3)); TEST_ASSERT(feq(v1.dotProduct(v2),0.0,1e-3)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(4)); TEST_ASSERT(feq(v1.dotProduct(v2),0.0,1e-3)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(5)); TEST_ASSERT(feq(v1.dotProduct(v2),0.0,1e-3)); v1 = conf.getAtomPos(0).directionVector(conf.getAtomPos(3)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(4)); TEST_ASSERT(feq(v1.dotProduct(v2),-0.5,1e-3)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(5)); TEST_ASSERT(feq(v1.dotProduct(v2),-0.5,1e-3)); v1 = conf.getAtomPos(0).directionVector(conf.getAtomPos(4)); v2 = conf.getAtomPos(0).directionVector(conf.getAtomPos(5)); TEST_ASSERT(feq(v1.dotProduct(v2),-0.5,1e-3)); delete mol; delete field; BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void runMol(ROMol *mol,int checkEvery=10,bool verbose=true){ ForceFields::ForceField *field; std::cout << MolToMolBlock(*mol) << "$$$$" << std::endl; try{ field=UFF::constructForceField(*mol,2.5); } catch (...) { field=0; } if(field){ field->initialize(); int needMore=1; int nPasses=0; while(needMore){ #if 1 needMore = field->minimize(checkEvery); if(verbose) std::cerr << "\t" << ++nPasses << std::endl; #else needMore = field->minimize(1); std::cout << MolToMolBlock(mol) << "$$$$" << std::endl; #endif } std::cout << MolToMolBlock(*mol) << "$$$$" << std::endl; delete field; } else { std::cerr << "failed"; } }
void testIssue242() { // FIX: Changes to the forcefield (connected to Issue 408) have // made it so that this particular problem no longer manifests // in this molecule/embedding. A new test case is needed. BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing Issue242." << std::endl; RWMol *mol, *mol2; int needMore; ForceFields::ForceField *field = 0, *field2 = 0; std::string mb1,mb2; double e1,e2; std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/MMFF/test_data"; mol = MolFileToMol(pathName + "/Issue242-2.mol"); TEST_ASSERT(mol); mol2 = MolFileToMol(pathName + "/Issue242-2.mol"); TEST_ASSERT(mol2); TEST_ASSERT(DGeomHelpers::EmbedMolecule(*mol2, 30, 2370) >= 0); mb1 = MolToMolBlock(*mol); mb2 = MolToMolBlock(*mol2); //std::cout << mb1 << "------\n"; //std::cout << mb2 << "------\n"; field = MMFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); field2 = MMFF::constructForceField(*mol2); TEST_ASSERT(field2); field2->initialize(); e1 = field->calcEnergy(); e2 = field2->calcEnergy(); BOOST_LOG(rdInfoLog) << "E1: " << e1 << std::endl; BOOST_LOG(rdInfoLog) << "E2: " << e2 << std::endl; //TEST_ASSERT(feq(e2,e1,0.1)); needMore = field->minimize(200,1.0e-4); needMore = field2->minimize(200,1.0e-4); e1 = field->calcEnergy(); e2 = field2->calcEnergy(); BOOST_LOG(rdInfoLog) << "E1: " << e1 << std::endl; BOOST_LOG(rdInfoLog) << "E2: " << e2 << std::endl; TEST_ASSERT(feq(e2, e1, 0.1)); delete mol; delete mol2; delete field; delete field2; BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void testUFFMultiThread(){ BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Test UFF multithreading" << std::endl; ForceFields::ForceField *field; std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/UFF/test_data"; SDMolSupplier suppl(pathName + "/bulk.sdf"); std::vector<ROMol *> mols; while(!suppl.atEnd()&&mols.size()<100){ ROMol *mol=0; try{ mol=suppl.next(); } catch(...){ continue; } if(!mol) continue; mols.push_back(mol); } std::cerr<<"generating reference data"<<std::endl; std::vector<double> energies(mols.size(),0.0); for(unsigned int i=0;i<mols.size();++i){ ROMol mol(*mols[i]); ForceFields::ForceField *field = 0; try { field = UFF::constructForceField(mol); } catch (...) { field = 0; } TEST_ASSERT(field); field->initialize(); int failed = field->minimize(500); TEST_ASSERT(!failed); energies[i]=field->calcEnergy(); delete field; } boost::thread_group tg; std::cerr<<"processing"<<std::endl; unsigned int count=4; for(unsigned int i=0;i<count;++i){ std::cerr<<" launch :"<<i<<std::endl;std::cerr.flush(); tg.add_thread(new boost::thread(runblock_uff,mols,energies,count,i)); } tg.join_all(); BOOST_FOREACH(ROMol *mol,mols){ delete mol; } BOOST_LOG(rdErrorLog) << " done" << 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; }
int MMFFOptimizeMolecule(ROMol &mol, std::string mmffVariant = "MMFF94", int maxIters = 200, double nonBondedThresh = 100.0, int confId = -1, bool ignoreInterfragInteractions = true) { int res = -1; MMFF::MMFFMolProperties mmffMolProperties(mol, mmffVariant); if (mmffMolProperties.isValid()) { ForceFields::ForceField *ff = MMFF::constructForceField(mol, &mmffMolProperties, nonBondedThresh, confId, ignoreInterfragInteractions); ff->initialize(); res = ff->minimize(maxIters); delete ff; } return res; }
void testGithub308() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing github 308: crash during MMFF parameterization ." << std::endl; ROMol *mol = SmilesToMol("FF"); TEST_ASSERT(DGeomHelpers::EmbedMolecule(*mol) >= 0); int needMore; ForceFields::ForceField *field = 0; TEST_ASSERT(mol); MMFF::MMFFMolProperties mmffMolProperties(*mol); TEST_ASSERT(mmffMolProperties.isValid()); field = MMFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); needMore = field->minimize(200, 1.0e-6, 1.0e-3); TEST_ASSERT(!needMore); }
void testSFIssue1653802(){ BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing SFIssue1653802." << std::endl; RWMol *mol; int needMore; ForceFields::ForceField *field; std::string pathName=getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/UFF/test_data"; mol = MolFileToMol(pathName+"/cyclobutadiene.mol",false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); UFF::AtomicParamVect types; bool foundAll; boost::shared_array<boost::uint8_t> nbrMat; boost::tie(types,foundAll)=UFF::getAtomTypes(*mol); TEST_ASSERT(foundAll); TEST_ASSERT(types.size()==mol->getNumAtoms()); field=new ForceFields::ForceField(); UFF::Tools::addBonds(*mol,types,field); TEST_ASSERT(field->contribs().size()==8); nbrMat = UFF::Tools::buildNeighborMatrix(*mol); UFF::Tools::addAngles(*mol,types,field); TEST_ASSERT(field->contribs().size()==20); UFF::Tools::addTorsions(*mol,types,field); //std::cout << field->contribs().size() << std::endl; TEST_ASSERT(field->contribs().size()==36); UFF::Tools::addNonbonded(*mol,0,types,field,nbrMat); delete field; field = UFF::constructForceField(*mol); field->initialize(); needMore = field->minimize(200,1e-6,1e-3); TEST_ASSERT(!needMore); delete mol; delete field; BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void testMMFFBatch() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing bulk MMFF (regression to check that things run)." << std::endl; ROMol *mol; ForceFields::ForceField *field; std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/MMFF/test_data"; SDMolSupplier suppl(pathName + "/bulk.sdf"); int count = 0; mol = suppl.next(); while (mol && (!(suppl.atEnd()))) { ++count; std::string origMolBlock = MolToMolBlock(*mol); BOOST_LOG(rdErrorLog) << "Mol:" << count << std::endl; try { field = MMFF::constructForceField(*mol); } catch (...) { field = 0; } if (field) { field->initialize(); int failed = field->minimize(500); if (failed) { BOOST_LOG(rdErrorLog) << " not converged (code = " << failed << ")" << std::endl; std::cout << origMolBlock << "$$$$" << std::endl; std::cout << MolToMolBlock(*mol) << "$$$$" << std::endl; } delete field; } delete mol; mol = suppl.next(); } BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void testSFIssue1653802() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing SFIssue1653802." << std::endl; RWMol *mol; int needMore; ForceFields::ForceField *field; std::string pathName = getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/MMFF/test_data"; mol = MolFileToMol(pathName + "/cyclobutadiene.mol", false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); MMFF::MMFFMolProperties *mmffMolProperties = new MMFF::MMFFMolProperties(*mol); TEST_ASSERT(mmffMolProperties); boost::shared_array<boost::uint8_t> nbrMat; field = new ForceFields::ForceField(); MMFF::Tools::addBonds(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 8); nbrMat = MMFF::Tools::buildNeighborMatrix(*mol); MMFF::Tools::addAngles(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 20); MMFF::Tools::addTorsions(*mol, mmffMolProperties, field); // std::cout << field->contribs().size() << std::endl; TEST_ASSERT(field->contribs().size() == 36); MMFF::Tools::addVdW(*mol, 0, mmffMolProperties, field, nbrMat); delete field; field = MMFF::constructForceField(*mol); field->initialize(); needMore = field->minimize(200, 1.0e-6, 1.0e-3); TEST_ASSERT(!needMore); delete mol; delete field; delete mmffMolProperties; BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void testGitHubIssue62() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing GitHubIssue62." << std::endl; std::string pathName=getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/UFF/test_data"; { double energyValues[] = { 38.687, 174.698, 337.986, 115.248, 2.482, 1.918, 10.165, 98.469, 39.078, 267.236, 15.747, 202.121, 205.539, 20.044, 218.986, 79.627 }; SmilesMolSupplier smiSupplier(pathName + "/Issue62.smi"); SDWriter *sdfWriter = new SDWriter(pathName + "/Issue62.sdf"); for (unsigned int i = 0; i < smiSupplier.length(); ++i) { ROMol *mol = MolOps::addHs(*(smiSupplier[i])); TEST_ASSERT(mol); std::string molName = ""; if (mol->hasProp(common_properties::_Name)) { mol->getProp(common_properties::_Name, molName); } DGeomHelpers::EmbedMolecule(*mol); ForceFields::ForceField *field = UFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); int needMore = field->minimize(200, 1.e-6, 1.e-3); TEST_ASSERT(!needMore); sdfWriter->write(*mol); double e = field->calcEnergy(); BOOST_LOG(rdErrorLog) << molName << " " << e << std::endl; TEST_ASSERT(fabs(e - energyValues[i]) < 1.); } sdfWriter->close(); BOOST_LOG(rdErrorLog) << " done" << std::endl; } }
void testUFFBuilder2(){ BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing UFF builder+minimization." << std::endl; RWMol *mol; std::string key; int needMore; ForceFields::ForceField *field; std::string pathName=getenv("RDBASE"); pathName += "/Code/GraphMol/ForceFieldHelpers/UFF/test_data"; mol = MolFileToMol(pathName+"/small1.mol",false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); field=UFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); needMore = field->minimize(); TEST_ASSERT(!needMore); //std::cout << MolToMolBlock(mol); delete mol; delete field; mol = MolFileToMol(pathName+"/small2.mol",false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); field=UFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); needMore = field->minimize(150); TEST_ASSERT(!needMore); //std::cout << MolToMolBlock(mol); delete mol; delete field; mol = MolFileToMol(pathName+"/benzene.mol",false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); field=UFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); needMore = field->minimize(); TEST_ASSERT(!needMore); //std::cout << MolToMolBlock(mol); delete mol; delete field; mol = MolFileToMol(pathName+"/toluene.mol",false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); field=UFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); needMore = field->minimize(); TEST_ASSERT(!needMore); //std::cout << MolToMolBlock(mol); delete mol; delete field; mol = MolFileToMol(pathName+"/complex1.mol",false); TEST_ASSERT(mol); MolOps::sanitizeMol(*mol); field=UFF::constructForceField(*mol); TEST_ASSERT(field); field->initialize(); needMore = field->minimize(); TEST_ASSERT(!needMore); //std::cout << MolToMolBlock(mol); delete mol; delete field; BOOST_LOG(rdErrorLog) << " done" << std::endl; }
void testTorsionAngleM6() { std::cerr << "-------------------------------------" << std::endl; std::cerr << " Test CrystalFF torsional term." << std::endl; ForceFields::ForceField ff; Point3D p1, p2, p3, p4; RDGeom::PointPtrVect &ps = ff.positions(); ps.push_back(&p1); ps.push_back(&p2); ps.push_back(&p3); ps.push_back(&p4); ForceFields::CrystalFF::TorsionAngleContribM6 *contrib; // ------- ------- ------- ------- ------- ------- ------- // Basic SP3 - SP3 // ------- ------- ------- ------- ------- ------- ------- // [!#1:1][CX4H2:2]!@[CX4H2:3][!#1:4] 1 0.0 1 0.0 1 4.0 1 0.0 1 0.0 1 0.0 std::vector<int> signs(6, 1); std::vector<double> v(6, 0.0); v[2] = 4.0; contrib = new ForceFields::CrystalFF::TorsionAngleContribM6(&ff, 0, 1, 2, 3, v, signs); ff.contribs().push_back(ForceFields::ContribPtr(contrib)); p1.x = 0; p1.y = 1.5; p1.z = 0; p2.x = 0.0; p2.y = 0.0; p2.z = 0.0; p3.x = 1.5; p3.y = 0.0; p3.z = 0.0; p4.x = 1.5; p4.y = 0.0; p4.z = 1.5; ff.initialize(); ff.minimize(10, 1e-8, 1e-8); double cosPhi = ForceFields::MMFF::Utils::calcTorsionCosPhi( *(RDGeom::Point3D *)ff.positions()[0], *(RDGeom::Point3D *)ff.positions()[1], *(RDGeom::Point3D *)ff.positions()[2], *(RDGeom::Point3D *)ff.positions()[3]); TEST_ASSERT(RDKit::feq(cosPhi, 0.5, 1e-4)); // ------- ------- ------- ------- ------- ------- ------- // Basic SP2 - SP2 // ------- ------- ------- ------- ------- ------- ------- signs[1] = -1; v[2] = 0.0; v[1] = 7.0; ff.contribs().pop_back(); contrib = new ForceFields::CrystalFF::TorsionAngleContribM6(&ff, 0, 1, 2, 3, v, signs); ff.contribs().push_back(ForceFields::ContribPtr(contrib)); p1.x = 0; p1.y = 1.5; p1.z = 0.1; p2.x = 0.0; p2.y = 0.0; p2.z = 0.0; p3.x = 1.5; p3.y = 0.0; p3.z = 0.0; p4.x = 1.5; p4.y = 0.2; p4.z = 1.5; ff.initialize(); ff.minimize(10, 1e-8, 1e-8); cosPhi = ForceFields::MMFF::Utils::calcTorsionCosPhi( *(RDGeom::Point3D *)ff.positions()[0], *(RDGeom::Point3D *)ff.positions()[1], *(RDGeom::Point3D *)ff.positions()[2], *(RDGeom::Point3D *)ff.positions()[3]); TEST_ASSERT(RDKit::feq(cosPhi, 1.0, 1e-4)); }
PyObject *embedBoundsMatrix(python::object boundsMatArg,int maxIters=10, bool randomizeOnFailure=false,int numZeroFail=2, python::list weights=python::list(), int randomSeed=-1){ PyObject *boundsMatObj = boundsMatArg.ptr(); if(!PyArray_Check(boundsMatObj)) throw_value_error("Argument isn't an array"); PyArrayObject *boundsMat=reinterpret_cast<PyArrayObject *>(boundsMatObj); // get the dimensions of the array unsigned int nrows = boundsMat->dimensions[0]; unsigned int ncols = boundsMat->dimensions[1]; if(nrows!=ncols) throw_value_error("The array has to be square"); if(nrows<=0) throw_value_error("The array has to have a nonzero size"); if (boundsMat->descr->type_num != PyArray_DOUBLE) throw_value_error("Only double arrays are currently supported"); unsigned int dSize = nrows*nrows; double *cData = new double[dSize]; double *inData = reinterpret_cast<double *>(boundsMat->data); memcpy(static_cast<void *>(cData), static_cast<const void *>(inData), dSize*sizeof(double)); DistGeom::BoundsMatrix::DATA_SPTR sdata(cData); DistGeom::BoundsMatrix bm(nrows,sdata); RDGeom::Point3D *positions=new RDGeom::Point3D[nrows]; std::vector<RDGeom::Point *> posPtrs; for (unsigned int i = 0; i < nrows; i++) { posPtrs.push_back(&positions[i]); } RDNumeric::DoubleSymmMatrix distMat(nrows, 0.0); // ---- ---- ---- ---- ---- ---- ---- ---- ---- // start the embedding: bool gotCoords=false; for(int iter=0;iter<maxIters && !gotCoords;iter++){ // pick a random distance matrix DistGeom::pickRandomDistMat(bm,distMat,randomSeed); // and embed it: gotCoords=DistGeom::computeInitialCoords(distMat,posPtrs,randomizeOnFailure, numZeroFail,randomSeed); // update the seed: if(randomSeed>=0) randomSeed+=iter*999; } if(gotCoords){ std::map<std::pair<int,int>,double> weightMap; unsigned int nElems=PySequence_Size(weights.ptr()); for(unsigned int entryIdx=0;entryIdx<nElems;entryIdx++){ PyObject *entry=PySequence_GetItem(weights.ptr(),entryIdx); if(!PySequence_Check(entry) || PySequence_Size(entry)!=3){ throw_value_error("weights argument must be a sequence of 3-sequences"); } int idx1=PyInt_AsLong(PySequence_GetItem(entry,0)); int idx2=PyInt_AsLong(PySequence_GetItem(entry,1)); double w=PyFloat_AsDouble(PySequence_GetItem(entry,2)); weightMap[std::make_pair(idx1,idx2)]=w; } DistGeom::VECT_CHIRALSET csets; ForceFields::ForceField *field = DistGeom::constructForceField(bm,posPtrs,csets,0.0, 0.0, &weightMap); CHECK_INVARIANT(field,"could not build dgeom force field"); field->initialize(); if(field->calcEnergy()>1e-5){ int needMore=1; while(needMore){ needMore=field->minimize(); } } delete field; } else { throw_value_error("could not embed matrix"); } // ---- ---- ---- ---- ---- ---- ---- ---- ---- // construct the results matrix: npy_intp dims[2]; dims[0] = nrows; dims[1] = 3; PyArrayObject *res = (PyArrayObject *)PyArray_SimpleNew(2,dims,NPY_DOUBLE); double *resData=reinterpret_cast<double *>(res->data); for(unsigned int i=0;i<nrows;i++){ unsigned int iTab=i*3; for (unsigned int j = 0; j < 3; ++j) { resData[iTab + j]=positions[i][j]; //.x; } } delete [] positions; return PyArray_Return(res); }