Skip to content

Instantly share code, notes, and snippets.

@TVect
Created July 3, 2023 03:32
Show Gist options
  • Select an option

  • Save TVect/9ea7d6b4fbd8c1fef0a09423c2465976 to your computer and use it in GitHub Desktop.

Select an option

Save TVect/9ea7d6b4fbd8c1fef0a09423c2465976 to your computer and use it in GitHub Desktop.
使用 openbabel 做固定部分结构的分子构象搜索. 来源于 https://www.insilico.jp/blog/2021/11/14/partial_conformation_search/
#include <fstream>
#include <iostream>
#include <string>
#include <openbabel/mol.h>
#include <openbabel/obconversion.h>
#include <openbabel/forcefield.h>
#include <openbabel/parsmart.h>
#include <openbabel/generic.h>
using namespace std;
using namespace OpenBabel;
int main(int argc, char* argv[]) {
// 力場の設定
string ff = "MMFF94";
OBForceField* pFF = OBForceField::FindForceField(ff);
if (!pFF) {
cerr << "指定の力場が見つかりませんでした" << endl;
return -1;
}
pFF->SetLogFile(&cout);
pFF->SetLogLevel(OBFF_LOGLVL_NONE);
// ファイルオープン
ifstream ifs("Donepezil.sdf");
if (ifs.fail()) {
cerr << "ファイルが見つかりませんでした" << endl;
return -1;
}
// 参照分子の読み込み
OBConversion conv;
conv.SetInAndOutFormats("SDF", "SDF");
OBMol mol;
conv.Read(&mol, &ifs);
ifs.close();
mol.DeleteHydrogens(); // 水素を外す
// 母核構造のマッチング
OBSmartsPattern smp;
smp.Init("O=C1CCc2c1cccc2");
smp.Match(mol);
vector<vector<int> > mlist = smp.GetUMapList();
// 拘束原子の設定
OBFFConstraints constraints;
for (int i = 0; i < mlist[0].size(); i++) {
cout << mlist[0][i] << std::endl;
constraints.AddAtomConstraint(mlist[0][i]);
}
// 分子をセットアップ(部分電荷などの計算)
if (!pFF->Setup(mol, constraints)) {
cerr << "分子の設定に失敗しました" << endl;
return -1;
}
// ランダムにコンホメーション発生
pFF->RandomRotorSearch(10, 0);
pFF->GetConformers(mol);
mol.AddHydrogens(); // 水素を付加
char s[99];
ofstream ofs("out.sdf");
for (int i = 0; i < mol.NumConformers(); i++) {
mol.SetConformer(i);
if (!pFF->Setup(mol, constraints)) {
cerr << "分子の設定に失敗しました" << endl;
return -1;
}
pFF->ConjugateGradients(5000);
pFF->GetCoordinates(mol);
sprintf(s, "%f", pFF->Energy());
string Unit = pFF->GetUnit();
cout << s << Unit << std::endl;
auto pd = new OBPairData;
pd->SetAttribute("Energy");
pd->SetValue(s);
mol.SetData(pd);
conv.Write(&mol, &ofs);
mol.DeleteData(pd);
}
ofs.close();
return 0;
}
from openbabel import openbabel, pybel
pFF = openbabel.OBForceField.FindType("MMFF94")
if not pFF:
print("Error: force field not found")
exit()
pFF.SetLogToStdOut()
pFF.SetLogLevel(0)
mol = next(pybel.readfile("SDF", "./Donepezil.sdf"))
print(mol.write("smi"))
ob_mol = mol.OBMol
ob_mol.DeleteHydrogens()
smp = openbabel.OBSmartsPattern()
smp.Init("O=C1CCc2c1cc(*)cc2")
smp.Match(ob_mol)
mlist = smp.GetUMapList()
constraints = openbabel.OBFFConstraints()
for item in mlist[0]:
constraints.AddAtomConstraint(item)
pFF.Setup(ob_mol, constraints)
pFF.RandomRotorSearch(10, 0)
pFF.GetConformers(ob_mol)
ob_mol.AddHydrogens()
output_file = pybel.Outputfile("sdf", "output_pcs.sdf", overwrite=True)
for i in range(10):
ob_mol.SetConformer(i)
pFF.Setup(ob_mol, constraints)
pFF.ConjugateGradients(5000)
pFF.GetCoordinates(ob_mol)
energy = pFF.Energy()
unit = pFF.GetUnit()
print(f"{i} energy: {round(energy, 4)} unit: {unit}")
new_mol = pybel.Molecule(ob_mol)
new_mol.data["energy"] = round(energy, 4)
output_file.write(new_mol)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment