1
/**********************************************************************
2
Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation version 2 of the License.
8
This program is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
GNU General Public License for more details.
12
***********************************************************************/
18
using namespace OpenEye;
23
void OEMol::FindChiralCenters()
25
if (HasChiralityPerceived()) return;
26
SetChiralityPerceived();
28
//do quick test to see if there are any possible chiral centers
29
bool mayHaveChiralCenter=false;
31
vector<OEAtom*>::iterator i;
32
for (atom = BeginAtom(i);atom;atom = NextAtom(i))
33
if (atom->GetHyb() == 3 && atom->GetHvyValence() >= 3)
35
mayHaveChiralCenter=true;
39
if (!mayHaveChiralCenter) return;
42
vector<OEBond*>::iterator j;
43
for (bond = BeginBond(j);bond;bond = NextBond(j))
44
if (bond->IsWedge() || bond->IsHash())
45
(bond->GetBeginAtom())->SetChiral();
50
vector<unsigned int> vgid;
52
vector<unsigned int> tlist;
53
vector<unsigned int>::iterator k;
54
#else //use Golender floating point method
56
GraphPotentials(*this,gp);
58
vector<float>::iterator k;
62
for (atom = BeginAtom(i);atom;atom = NextAtom(i))
63
if (atom->GetHyb() == 3 && atom->GetHvyValence() >= 3 && !atom->IsChiral())
68
for (nbr = atom->BeginNbrAtom(j);nbr;nbr = atom->NextNbrAtom(j))
70
for (k = tlist.begin();k != tlist.end();k++)
72
if (vgid[nbr->GetIdx()-1] == *k)
74
if (fabs(gp[nbr->GetIdx()]-*k) < 0.001)
79
if (ischiral) tlist.push_back(vgid[nbr->GetIdx()-1]);
81
if (ischiral) tlist.push_back(gp[nbr->GetIdx()]);
86
if (ischiral) atom->SetChiral();
90
void GetChirality(OEMol &mol, vector<int> &chirality)
92
chirality.resize(mol.NumAtoms()+1);
93
fill(chirality.begin(),chirality.end(),0);
96
vector<OEAtom*>::iterator i;
97
for (atom = mol.BeginAtom(i);atom;atom = mol.NextAtom(i))
100
float sv = CalcSignedVolume(mol,atom);
101
if (sv < 0.0f) chirality[atom->GetIdx()-1] = -1;
102
else if (sv > 0.0) chirality[atom->GetIdx()-1] = 1;
106
// Calculate the signed volume for an atom. If the atom has a valence of 3
107
// the coordinates of an attached hydrogen are calculated
109
float CalcSignedVolume(OEMol &mol,OEAtom *atm)
112
vector<int> nbr_atms;
113
vector<Vector> nbr_crds;
114
float hbrad = etab.CorrectedBondRad(1,0);
116
if (atm->GetHvyValence() < 3)
118
cerr << "Cannot calculate a signed volume for an atom with a heavy atom valence of " << atm->GetHvyValence() << endl;
122
// Create a vector with the coordinates of the neighbor atoms
124
vector<OEBond*>::iterator bint;
125
for (nbr = atm->BeginNbrAtom(bint);nbr;nbr = atm->NextNbrAtom(bint))
127
nbr_atms.push_back(nbr->GetIdx());
129
// sort the neighbor atoms to insure a consistent ordering
130
sort(nbr_atms.begin(),nbr_atms.end());
131
for (unsigned int i = 0; i < nbr_atms.size(); i++)
133
OEAtom *tmp_atm = mol.GetAtom(nbr_atms[i]);
134
nbr_crds.push_back(tmp_atm->GetVector());
137
// If we have three heavy atoms we need to calculate the position of the fourth
138
if (atm->GetHvyValence() == 3)
140
float bondlen = hbrad+etab.CorrectedBondRad(atm->GetAtomicNum(),atm->GetHyb());
141
atm->GetNewBondVector(tmp_crd,bondlen);
142
nbr_crds.push_back(tmp_crd);
145
return(signed_volume(nbr_crds[0],nbr_crds[1],nbr_crds[2],nbr_crds[3]));
148
// calculate a signed volume given a set of 4 coordinates
149
float signed_volume(const Vector &a, const Vector &b, const Vector &c, const Vector &d)
156
return(m.determinant());
159
// Calculate the Graph Potentials of a molecule
161
// V.E. and Rozenblit, A.B. Golender
162
// Logical and Combinatorial Algorithms for Drug Design
163
// for an example see
164
// Walters, W. P., Yalkowsky, S. H., JCICS, 1996, 36(5), 1015-1017
166
void GraphPotentials(OEMol &mol, vector<float> &pot)
170
vector<vector<float> > g,c,h;
171
construct_g_matrix(mol,g);
172
invert_matrix(g,det);
173
construct_c_matrix(mol,c);
175
pot.resize(mol.NumAtoms()+1);
177
for (unsigned int i = 0; i < mol.NumAtoms();i++) pot[i+1] = h[i][0];
181
// Construct the matrix G, which puts each atoms valence+1
182
// on the diagonal and and -1 on the off diagonal if two
183
// atoms are connected.
185
void construct_g_matrix(OEMol &mol, vector<vector<float> > &m)
190
vector<OEAtom*>::iterator aint,bint;
192
m.resize(mol.NumAtoms());
193
for (i = 0; i < m.size(); i++)
194
m[i].resize(mol.NumAtoms());
196
for (atm1 = mol.BeginAtom(aint),i=0;atm1;atm1 = mol.NextAtom(aint),i++)
197
for (atm2 = mol.BeginAtom(bint),j=0;atm2;atm2 = mol.NextAtom(bint),j++)
201
m[i][j] = atm1->GetValence() + 1;
202
m[i][j] += (float)atm1->GetAtomicNum()/10.0;
203
m[i][j] += (float)atm1->GetHyb()/100.0;
207
if (atm1->IsConnected(atm2))
215
// Construct the matrix C, which is simply a column vector
216
// consisting of the valence for each atom
217
void construct_c_matrix(OEMol &mol,vector<vector<float > > &m)
221
vector<OEAtom*>::iterator aint;
223
m.resize(mol.NumAtoms());
224
for (i = 0; i < m.size(); i++)
226
for (atm1 = mol.BeginAtom(aint),i=0;atm1;atm1 = mol.NextAtom(aint),i++)
228
m[i][0] = atm1->GetValence();