void testGithub224() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing github 224: crash during MMFF parameterization ." << std::endl; { ROMol *mol = SmilesToMol("[1*]C"); TEST_ASSERT(mol); MMFF::MMFFMolProperties *mmffMolProperties = new MMFF::MMFFMolProperties(*mol); TEST_ASSERT(mmffMolProperties); TEST_ASSERT(!mmffMolProperties->isValid()); delete mol; delete mmffMolProperties; } { ROMol *mol = SmilesToMol("[1*]c1ccc(S(=O)(=O)Nc2ccc([2*])cc2)cc1"); TEST_ASSERT(mol); MMFF::MMFFMolProperties *mmffMolProperties = new MMFF::MMFFMolProperties(*mol); TEST_ASSERT(mmffMolProperties); TEST_ASSERT(!mmffMolProperties->isValid()); delete mol; delete mmffMolProperties; } BOOST_LOG(rdErrorLog) << " done" << std::endl; }
ForceFields::PyMMFFMolProperties *GetMMFFMolProperties (ROMol &mol, std::string mmffVariant = "MMFF94", unsigned int mmffVerbosity = MMFF::MMFF_VERBOSITY_NONE) { MMFF::MMFFMolProperties *mmffMolProperties = new MMFF::MMFFMolProperties(mol, mmffVariant, mmffVerbosity); ForceFields::PyMMFFMolProperties *pyMP = NULL; if (mmffMolProperties && mmffMolProperties->isValid()) { pyMP = new ForceFields::PyMMFFMolProperties(mmffMolProperties); } return pyMP; }
void testGithub162() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing github 162: Incorrect SMILES after MMFF parameterization ." << std::endl; { ROMol *mol = SmilesToMol("C1=CNC=C1"); TEST_ASSERT(mol); TEST_ASSERT(mol->getAtomWithIdx(2)->getNumExplicitHs()==1); MMFF::MMFFMolProperties *mmffMolProperties = new MMFF::MMFFMolProperties(*mol); TEST_ASSERT(mmffMolProperties); TEST_ASSERT(mmffMolProperties->isValid()); TEST_ASSERT(mol->getAtomWithIdx(2)->getNumExplicitHs()==1); delete mol; delete mmffMolProperties; } BOOST_LOG(rdErrorLog) << " done" << std::endl; }
python::tuple getMMFFO3AForConfs( ROMol &prbMol, ROMol &refMol, int numThreads, python::object prbProps, python::object refProps, int refCid = -1, bool reflect = false, unsigned int maxIters = 50, unsigned int options = 0, python::list constraintMap = python::list(), python::list constraintWeights = python::list()) { MatchVectType *cMap = (python::len(constraintMap) ? _translateAtomMap(constraintMap) : NULL); RDNumeric::DoubleVector *cWts = NULL; if (cMap) { cWts = _translateWeights(constraintWeights); if (cWts) { if ((*cMap).size() != (*cWts).size()) { throw_value_error( "The number of weights should match the number of constraints"); } } for (unsigned int i = 0; i < (*cMap).size(); ++i) { if (((*cMap)[i].first < 0) || ((*cMap)[i].first >= rdcast<int>(prbMol.getNumAtoms())) || ((*cMap)[i].second < 0) || ((*cMap)[i].second >= rdcast<int>(refMol.getNumAtoms()))) { throw_value_error("Constrained atom idx out of range"); } if ((prbMol[(*cMap)[i].first]->getAtomicNum() == 1) || (refMol[(*cMap)[i].second]->getAtomicNum() == 1)) { throw_value_error("Constrained atoms must be heavy atoms"); } } } ForceFields::PyMMFFMolProperties *prbPyMMFFMolProperties = NULL; MMFF::MMFFMolProperties *prbMolProps = NULL; ForceFields::PyMMFFMolProperties *refPyMMFFMolProperties = NULL; MMFF::MMFFMolProperties *refMolProps = NULL; if (prbProps != python::object()) { prbPyMMFFMolProperties = python::extract<ForceFields::PyMMFFMolProperties *>(prbProps); prbMolProps = prbPyMMFFMolProperties->mmffMolProperties.get(); } else { prbMolProps = new MMFF::MMFFMolProperties(prbMol); if (!prbMolProps->isValid()) { throw_value_error("missing MMFF94 parameters for probe molecule"); } } if (refProps != python::object()) { refPyMMFFMolProperties = python::extract<ForceFields::PyMMFFMolProperties *>(refProps); refMolProps = refPyMMFFMolProperties->mmffMolProperties.get(); } else { refMolProps = new MMFF::MMFFMolProperties(refMol); if (!refMolProps->isValid()) { throw_value_error("missing MMFF94 parameters for reference molecule"); } } std::vector<boost::shared_ptr<O3A> > res; { NOGIL gil; getO3AForProbeConfs(prbMol, refMol, prbMolProps, refMolProps, res, numThreads, MolAlign::O3A::MMFF94, refCid, reflect, maxIters, options, cMap, cWts); } python::list pyres; for (unsigned int i = 0; i < res.size(); ++i) { pyres.append(new PyO3A(res[i])); } if (!prbPyMMFFMolProperties) delete prbMolProps; if (!refPyMMFFMolProperties) delete refMolProps; if (cMap) { delete cMap; } if (cWts) { delete cWts; } return python::tuple(pyres); }
void testMMFFParamGetters() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Test MMFF force-field parameter getters." << std::endl; { ROMol *mol = SmilesToMol("c1ccccc1CCNN"); TEST_ASSERT(mol); ROMol *molH = MolOps::addHs(*mol); TEST_ASSERT(molH); MMFF::MMFFMolProperties *mmffMolProperties = new MMFF::MMFFMolProperties(*molH); TEST_ASSERT(mmffMolProperties); TEST_ASSERT(mmffMolProperties->isValid()); unsigned int bondType; ForceFields::MMFF::MMFFBond mmffBondStretchParams[2]; TEST_ASSERT(mmffMolProperties->getMMFFBondStretchParams( *molH, 6, 7, bondType, mmffBondStretchParams[0])); TEST_ASSERT( (bondType == 0) && ((int)boost::math::round(mmffBondStretchParams[0].r0 * 1000) == 1508) && ((int)boost::math::round(mmffBondStretchParams[0].kb * 1000) == 4258)); TEST_ASSERT(!(mmffMolProperties->getMMFFBondStretchParams( *molH, 0, 7, bondType, mmffBondStretchParams[0]))); unsigned int angleType; ForceFields::MMFF::MMFFAngle mmffAngleBendParams; TEST_ASSERT(mmffMolProperties->getMMFFAngleBendParams( *molH, 6, 7, 8, angleType, mmffAngleBendParams)); TEST_ASSERT( (angleType == 0) && ((int)boost::math::round(mmffAngleBendParams.theta0 * 1000) == 108290) && ((int)boost::math::round(mmffAngleBendParams.ka * 1000) == 777)); TEST_ASSERT(!(mmffMolProperties->getMMFFAngleBendParams( *molH, 0, 7, 8, angleType, mmffAngleBendParams))); unsigned int stretchBendType; ForceFields::MMFF::MMFFStbn mmffStretchBendParams; TEST_ASSERT(mmffMolProperties->getMMFFStretchBendParams( *molH, 6, 7, 8, stretchBendType, mmffStretchBendParams, mmffBondStretchParams, mmffAngleBendParams)); TEST_ASSERT( (stretchBendType == 0) && ((int)boost::math::round(mmffStretchBendParams.kbaIJK * 1000) == 136) && ((int)boost::math::round(mmffStretchBendParams.kbaKJI * 1000) == 282) && ((int)boost::math::round(mmffAngleBendParams.theta0 * 1000) == 108290) && ((int)boost::math::round(mmffAngleBendParams.ka * 1000) == 777) && ((int)boost::math::round(mmffBondStretchParams[0].r0 * 1000) == 1508) && ((int)boost::math::round(mmffBondStretchParams[0].kb * 1000) == 4258) && ((int)boost::math::round(mmffBondStretchParams[1].r0 * 1000) == 1451) && ((int)boost::math::round(mmffBondStretchParams[1].kb * 1000) == 5084)); TEST_ASSERT(!(mmffMolProperties->getMMFFStretchBendParams( *molH, 0, 7, 8, stretchBendType, mmffStretchBendParams, mmffBondStretchParams, mmffAngleBendParams))); unsigned int torType; ForceFields::MMFF::MMFFTor mmffTorsionParams; TEST_ASSERT(mmffMolProperties->getMMFFTorsionParams( *molH, 6, 7, 8, 9, torType, mmffTorsionParams)); TEST_ASSERT( (torType == 0) && ((int)boost::math::round(mmffTorsionParams.V1 * 1000) == 0) && ((int)boost::math::round(mmffTorsionParams.V2 * 1000) == -300) && ((int)boost::math::round(mmffTorsionParams.V3 * 1000) == 500)); TEST_ASSERT(!(mmffMolProperties->getMMFFTorsionParams( *molH, 0, 7, 8, 9, torType, mmffTorsionParams))); ForceFields::MMFF::MMFFOop mmffOopBendParams; TEST_ASSERT(mmffMolProperties->getMMFFOopBendParams(*molH, 6, 5, 4, 0, mmffOopBendParams)); TEST_ASSERT(((int)boost::math::round(mmffOopBendParams.koop * 1000) == 40)); TEST_ASSERT(!(mmffMolProperties->getMMFFOopBendParams(*molH, 6, 5, 4, 1, mmffOopBendParams))); ForceFields::MMFF::MMFFVdWRijstarEps mmffVdWParams; RWMol *patt = SmartsToMol("NN[H]"); MatchVectType matchVect; TEST_ASSERT(SubstructMatch(*molH, (ROMol &)*patt, matchVect)); unsigned int nIdx = matchVect[0].second; unsigned int hIdx = matchVect[2].second; TEST_ASSERT(mmffMolProperties->getMMFFVdWParams(nIdx, hIdx, mmffVdWParams)); TEST_ASSERT( ((int)boost::math::round(mmffVdWParams.R_ij_starUnscaled * 1000) == 3321) && ((int)boost::math::round(mmffVdWParams.epsilonUnscaled * 1000) == 34) && ((int)boost::math::round(mmffVdWParams.R_ij_star * 1000) == 2657) && ((int)boost::math::round(mmffVdWParams.epsilon * 1000) == 17)); } }
void testMMFFBuilder1() { BOOST_LOG(rdErrorLog) << "-------------------------------------" << std::endl; BOOST_LOG(rdErrorLog) << " Testing MMFF builder tools." << std::endl; ROMol *mol, *mol2; ForceFields::ForceField *field; boost::shared_array<boost::uint8_t> nbrMat; mol = SmilesToMol("CC(O)C"); Conformer *conf = new Conformer(mol->getNumAtoms()); int cid = static_cast<int>(mol->addConformer(conf, true)); TEST_ASSERT(mol); MMFF::MMFFMolProperties *mmffMolProperties = new MMFF::MMFFMolProperties(*mol); TEST_ASSERT(mmffMolProperties); TEST_ASSERT(mmffMolProperties->isValid()); field = new ForceFields::ForceField(); MMFF::Tools::addBonds(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 3); nbrMat = MMFF::Tools::buildNeighborMatrix(*mol); // the neighbor matrix is an upper triangular matrix // position indices are as follows: // 0 1 2 3 // 4 5 6 // 7 8 // 9 TEST_ASSERT(MMFF::Tools::twoBitCellPos(mol->getNumAtoms(), 1, 1) == 4); TEST_ASSERT(MMFF::Tools::twoBitCellPos(mol->getNumAtoms(), 2, 1) == 5); TEST_ASSERT(MMFF::Tools::twoBitCellPos(mol->getNumAtoms(), 1, 2) == 5); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 0) == MMFF::Tools::RELATION_1_X); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 1) == MMFF::Tools::RELATION_1_2); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 2) == MMFF::Tools::RELATION_1_3); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 3) == MMFF::Tools::RELATION_1_3); MMFF::Tools::addAngles(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 6); // there are no non-bonded terms here: MMFF::Tools::addVdW(*mol, cid, mmffMolProperties, field, nbrMat); TEST_ASSERT(field->contribs().size() == 6); // and no torsions either, until we add Hs: MMFF::Tools::addTorsions(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 6); delete mol; delete field; delete mmffMolProperties; mol = SmilesToMol("CCOC"); Conformer *conf2 = new Conformer(mol->getNumAtoms()); cid = static_cast<int>(mol->addConformer(conf2, true)); TEST_ASSERT(mol); mmffMolProperties = new MMFF::MMFFMolProperties(*mol); TEST_ASSERT(mmffMolProperties); TEST_ASSERT(mmffMolProperties->isValid()); field = new ForceFields::ForceField(); MMFF::Tools::addBonds(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 3); nbrMat = MMFF::Tools::buildNeighborMatrix(*mol); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 0) == MMFF::Tools::RELATION_1_X); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 1) == MMFF::Tools::RELATION_1_2); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 2) == MMFF::Tools::RELATION_1_3); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 3) == MMFF::Tools::RELATION_1_4); MMFF::Tools::addAngles(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 5); MMFF::Tools::addVdW(*mol, cid, mmffMolProperties, field, nbrMat); TEST_ASSERT(field->contribs().size() == 6); MMFF::Tools::addTorsions(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 7); delete mol; delete field; delete mmffMolProperties; mol = SmilesToMol("CO"); Conformer *conf3 = new Conformer(mol->getNumAtoms()); cid = static_cast<int>(mol->addConformer(conf3, true)); TEST_ASSERT(mol); mmffMolProperties = new MMFF::MMFFMolProperties(*mol); TEST_ASSERT(mmffMolProperties); TEST_ASSERT(mmffMolProperties->isValid()); field = new ForceFields::ForceField(); MMFF::Tools::addBonds(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 1); nbrMat = MMFF::Tools::buildNeighborMatrix(*mol); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 0) == MMFF::Tools::RELATION_1_X); TEST_ASSERT(MMFF::Tools::getTwoBitCell(nbrMat, 1) == MMFF::Tools::RELATION_1_2); MMFF::Tools::addAngles(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 1); MMFF::Tools::addVdW(*mol, cid, mmffMolProperties, field, nbrMat); TEST_ASSERT(field->contribs().size() == 1); MMFF::Tools::addTorsions(*mol, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 1); mol2 = MolOps::addHs(*mol); TEST_ASSERT(mol2->getNumAtoms() == 6); delete field; delete mmffMolProperties; mmffMolProperties = new MMFF::MMFFMolProperties(*mol2); TEST_ASSERT(mmffMolProperties); TEST_ASSERT(mmffMolProperties->isValid()); field = new ForceFields::ForceField(); MMFF::Tools::addBonds(*mol2, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 5); nbrMat = MMFF::Tools::buildNeighborMatrix(*mol2); MMFF::Tools::addAngles(*mol2, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 12); MMFF::Tools::addVdW(*mol2, cid, mmffMolProperties, field, nbrMat); TEST_ASSERT(field->contribs().size() == 15); MMFF::Tools::addTorsions(*mol2, mmffMolProperties, field); TEST_ASSERT(field->contribs().size() == 18); delete mol2; delete mol; delete field; delete mmffMolProperties; BOOST_LOG(rdErrorLog) << " done" << std::endl; }
PyO3A *getMMFFO3A(ROMol &prbMol, ROMol &refMol, python::object prbProps, python::object refProps, int prbCid = -1, int refCid = -1, bool reflect = false, unsigned int maxIters = 50, unsigned int options = 0, python::list constraintMap = python::list(), python::list constraintWeights = python::list()) { MatchVectType *cMap = (python::len(constraintMap) ? _translateAtomMap(constraintMap) : nullptr); RDNumeric::DoubleVector *cWts = nullptr; if (cMap) { cWts = _translateWeights(constraintWeights); if (cWts) { if ((*cMap).size() != (*cWts).size()) { throw_value_error( "The number of weights should match the number of constraints"); } } for (auto &i : (*cMap)) { if ((i.first < 0) || (i.first >= rdcast<int>(prbMol.getNumAtoms())) || (i.second < 0) || (i.second >= rdcast<int>(refMol.getNumAtoms()))) { throw_value_error("Constrained atom idx out of range"); } if ((prbMol[i.first]->getAtomicNum() == 1) || (refMol[i.second]->getAtomicNum() == 1)) { throw_value_error("Constrained atoms must be heavy atoms"); } } } ForceFields::PyMMFFMolProperties *prbPyMMFFMolProperties = nullptr; MMFF::MMFFMolProperties *prbMolProps = nullptr; ForceFields::PyMMFFMolProperties *refPyMMFFMolProperties = nullptr; MMFF::MMFFMolProperties *refMolProps = nullptr; if (prbProps != python::object()) { prbPyMMFFMolProperties = python::extract<ForceFields::PyMMFFMolProperties *>(prbProps); prbMolProps = prbPyMMFFMolProperties->mmffMolProperties.get(); } else { prbMolProps = new MMFF::MMFFMolProperties(prbMol); if (!prbMolProps->isValid()) { throw_value_error("missing MMFF94 parameters for probe molecule"); } } if (refProps != python::object()) { refPyMMFFMolProperties = python::extract<ForceFields::PyMMFFMolProperties *>(refProps); refMolProps = refPyMMFFMolProperties->mmffMolProperties.get(); } else { refMolProps = new MMFF::MMFFMolProperties(refMol); if (!refMolProps->isValid()) { throw_value_error("missing MMFF94 parameters for reference molecule"); } } O3A *o3a; { NOGIL gil; o3a = new MolAlign::O3A(prbMol, refMol, prbMolProps, refMolProps, MolAlign::O3A::MMFF94, prbCid, refCid, reflect, maxIters, options, cMap, cWts); } auto *pyO3A = new PyO3A(o3a); if (!prbPyMMFFMolProperties) delete prbMolProps; if (!refPyMMFFMolProperties) delete refMolProps; if (cMap) { delete cMap; } if (cWts) { delete cWts; } return pyO3A; }