Files
rdkit/Code/GraphMol/ForceFieldHelpers/CrystalFF/testCrystalFF.cpp
nmaeder a45d4d9857 New contribs for DG (#7711)
* add angles and distances

* add Inversions

* add torsiona angle contribs

* use new contribs in test

* use new inversion and torsion contribs in dg

* use new distance contribs in dg

* use new angle constraints in dg

* use new constraints in FF tests

* update docstrings

* remove unused import

* include new contribs

* cleanup includes

* make changes requested by @greglandrum

* use std::move instead of release
2024-08-21 06:06:58 +02:00

239 lines
7.5 KiB
C++

//
// Copyright (C) 2015 Sereina Riniker
//
// @@ All Rights Reserved @@
// This file is part of the RDKit.
// The contents are covered by the terms of the BSD license
// which is included in the file license.txt, found at the root
// of the RDKit source tree.
//
#include <RDGeneral/test.h>
#include <RDGeneral/utils.h>
#include <Geometry/point.h>
#include <GraphMol/RDKitBase.h>
#include <GraphMol/SmilesParse/SmilesParse.h>
#include <ForceField/MMFF/Params.h>
#include <ForceField/MMFF/TorsionAngle.h>
#include <GraphMol/ForceFieldHelpers/CrystalFF/TorsionAngleContribs.h>
#include <GraphMol/ForceFieldHelpers/CrystalFF/TorsionPreferences.h>
#include <GraphMol/MolOps.h>
#include <GraphMol/MolTransforms/MolTransforms.h>
#include <ForceField/ForceField.h>
#include <iostream>
#include <string>
#include <cmath>
using namespace RDGeom;
using namespace RDKit;
void testTorsionAngleContribs() {
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);
// ------- ------- ------- ------- ------- ------- -------
// 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;
auto contrib = new ForceFields::CrystalFF::TorsionAngleContribs(&ff);
contrib->addContrib(0, 1, 2, 3, v, signs);
ff.contribs().emplace_back(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::TorsionAngleContribs(&ff);
contrib->addContrib(0, 1, 2, 3, v, signs);
ff.contribs().emplace_back(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));
}
void testTorsionPrefs() {
ROMol *mol;
mol = SmilesToMol("CCCC");
TEST_ASSERT(mol);
ForceFields::CrystalFF::CrystalFFDetails details;
ForceFields::CrystalFF::getExperimentalTorsions(*mol, details, true, false,
false, false, 1, false);
TEST_ASSERT(details.expTorsionAtoms.size() == 1);
TEST_ASSERT(details.expTorsionAngles.size() == 1);
TEST_ASSERT(details.expTorsionAtoms[0][0] == 0);
TEST_ASSERT(details.expTorsionAtoms[0][3] == 3);
TEST_ASSERT(details.expTorsionAngles[0].first.size() == 6);
TEST_ASSERT(details.expTorsionAngles[0].second.size() == 6);
std::vector<std::tuple<unsigned int, std::vector<unsigned int>,
const ForceFields::CrystalFF::ExpTorsionAngle *>>
torsionBonds;
ForceFields::CrystalFF::getExperimentalTorsions(
*mol, details, torsionBonds, true, false, false, false, 2, false);
TEST_ASSERT(torsionBonds.size() == 1);
TEST_ASSERT(std::get<0>(torsionBonds[0]) == 1);
TEST_ASSERT(std::get<2>(torsionBonds[0])->smarts ==
"[!#1:1][CX4H2:2]!@;-[CX4H2:3][!#1:4]");
TEST_ASSERT(std::get<2>(torsionBonds[0])->torsionIdx == 229);
delete mol;
mol = SmilesToMol("CCCCC");
TEST_ASSERT(mol);
ForceFields::CrystalFF::getExperimentalTorsions(
*mol, details, torsionBonds, true, false, false, false, 2, false);
TEST_ASSERT(details.expTorsionAtoms.size() == 2);
TEST_ASSERT(details.expTorsionAngles.size() == 2);
TEST_ASSERT(torsionBonds.size() == 2);
TEST_ASSERT(std::get<0>(torsionBonds[0]) == 1);
TEST_ASSERT(std::get<0>(torsionBonds[1]) == 2);
delete mol;
}
void testTorsionPrefsSmallRings() {
ROMol *mol;
ForceFields::CrystalFF::CrystalFFDetails details;
mol = SmilesToMol("C1COCC1");
TEST_ASSERT(mol);
// small ring torsion turned off
ForceFields::CrystalFF::getExperimentalTorsions(*mol, details, true, false,
false, false, 1, false);
TEST_ASSERT(details.expTorsionAtoms.size() == 0);
TEST_ASSERT(details.expTorsionAngles.size() == 0);
// small ring torsion turned on
ForceFields::CrystalFF::getExperimentalTorsions(*mol, details, true, true,
false, false, 1, false);
TEST_ASSERT(details.expTorsionAtoms.size() > 0);
TEST_ASSERT(details.expTorsionAngles.size() > 0);
delete mol;
}
void testTorsionPrefsBridgedSmallRings() {
// test bridged system does not trigger any small ring torsion
ROMol *mol;
ForceFields::CrystalFF::CrystalFFDetails details;
mol = SmilesToMol("O[C@H]1C[C@H]2CC[C@]1(C)C2(C)C");
TEST_ASSERT(mol);
// small ring torsion turned off
ForceFields::CrystalFF::getExperimentalTorsions(*mol, details, true, true,
false, false, 1, false);
TEST_ASSERT(details.expTorsionAtoms.size() == 0);
TEST_ASSERT(details.expTorsionAngles.size() == 0);
delete mol;
}
void testTorsionPrefsMacrocycles() {
ROMol *mol;
ForceFields::CrystalFF::CrystalFFDetails details;
mol = SmilesToMol("C1COCCCCCCC1");
TEST_ASSERT(mol);
// macrocycle ring torsion turned off
ForceFields::CrystalFF::getExperimentalTorsions(*mol, details, true, false,
false, false, 1, false);
TEST_ASSERT(details.expTorsionAtoms.size() == 0);
TEST_ASSERT(details.expTorsionAngles.size() == 0);
// macrocycle ring torsion turned on
ForceFields::CrystalFF::getExperimentalTorsions(*mol, details, true, false,
true, false, 1, false);
TEST_ASSERT(details.expTorsionAtoms.size() > 0);
TEST_ASSERT(details.expTorsionAngles.size() > 0);
delete mol;
}
int main() {
RDLog::InitLogs();
BOOST_LOG(rdInfoLog)
<< "********************************************************\n";
BOOST_LOG(rdInfoLog) << "Testing Crystal ForceField\n";
BOOST_LOG(rdInfoLog) << "\t---------------------------------\n";
BOOST_LOG(rdInfoLog) << "\t SMARTS parsing\n";
testTorsionAngleContribs();
BOOST_LOG(rdInfoLog) << "\t---------------------------------\n";
BOOST_LOG(rdInfoLog) << "\t Seeing if non-ring torsions are applied\n";
testTorsionPrefs();
BOOST_LOG(rdInfoLog) << "\t---------------------------------\n";
BOOST_LOG(rdInfoLog) << "\t Seeing if small ring torsions are applied\n";
testTorsionPrefsSmallRings();
BOOST_LOG(rdInfoLog) << "\t---------------------------------\n";
BOOST_LOG(rdInfoLog) << "\t Seeing if macrocycle ring torsions are applied\n";
testTorsionPrefsMacrocycles();
return 0;
}