ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/openbabel/phmodel.cpp
Revision: 2440
Committed: Wed Nov 16 19:42:11 2005 UTC (18 years, 8 months ago) by tim
File size: 10045 byte(s)
Log Message:
adding openbabel

File Contents

# User Rev Content
1 tim 2440 /**********************************************************************
2     phmodel.cpp - Read pH rules and assign charges.
3    
4     Copyright (C) 1998-2001 by OpenEye Scientific Software, Inc.
5     Some portions Copyright (C) 2001-2005 by Geoffrey R. Hutchison
6    
7     This file is part of the Open Babel project.
8     For more information, see <http://openbabel.sourceforge.net/>
9    
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation version 2 of the License.
13    
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17     GNU General Public License for more details.
18     ***********************************************************************/
19    
20     #include "mol.hpp"
21     #include "phmodel.hpp"
22     #include "phmodeldata.hpp"
23    
24     #ifdef WIN32
25     #pragma warning (disable : 4786)
26     #endif
27    
28     using namespace std;
29    
30     namespace OpenBabel
31     {
32    
33     // Global OBPhModel for assigning formal charges and hydrogen addition rules
34     OBPhModel phmodel;
35     extern OBAtomTyper atomtyper;
36    
37     OBPhModel::OBPhModel()
38     {
39     _init = false;
40     _dir = BABEL_DATADIR;
41     _envvar = "BABEL_DATADIR";
42     _filename = "phmodel.txt";
43     _subdir = "data";
44     _dataptr = PhModelData;
45     }
46    
47     OBPhModel::~OBPhModel()
48     {
49     vector<OBChemTsfm*>::iterator k;
50     for (k = _vtsfm.begin();k != _vtsfm.end();k++)
51     delete *k;
52    
53     vector<pair<OBSmartsPattern*,vector<double> > >::iterator m;
54     for (m = _vschrg.begin();m != _vschrg.end();m++)
55     delete m->first;
56     }
57    
58     void OBPhModel::ParseLine(const char *buffer)
59     {
60     vector<string> vs;
61     OBSmartsPattern *sp;
62    
63     if (buffer[0] == '#')
64     return;
65    
66     if (EQn(buffer,"TRANSFORM",7))
67     {
68     tokenize(vs,buffer);
69     if (vs.empty() || vs.size() < 4)
70     {
71     obErrorLog.ThrowError(__FUNCTION__, " Could not parse line in phmodel table from phmodel.txt", obInfo);
72     return;
73     }
74    
75     OBChemTsfm *tsfm = new OBChemTsfm;
76     if (!tsfm->Init(vs[1],vs[3]))
77     {
78     delete tsfm;
79     tsfm = NULL;
80     obErrorLog.ThrowError(__FUNCTION__, " Could not parse line in phmodel table from phmodel.txt", obInfo);
81     return;
82     }
83    
84     _vtsfm.push_back(tsfm);
85     }
86     else if (EQn(buffer,"SEEDCHARGE",10))
87     {
88     tokenize(vs,buffer);
89     if (vs.empty() || vs.size() < 2)
90     {
91     obErrorLog.ThrowError(__FUNCTION__, " Could not parse line in phmodel table from phmodel.txt", obInfo);
92     return;
93     }
94    
95     sp = new OBSmartsPattern;
96     if (!sp->Init(vs[1]) || (vs.size()-2) != sp->NumAtoms())
97     {
98     delete sp;
99     sp = NULL;
100     obErrorLog.ThrowError(__FUNCTION__, " Could not parse line in phmodel table from phmodel.txt", obInfo);
101     return;
102     }
103    
104     vector<double> vf;
105     vector<string>::iterator i;
106     for (i = vs.begin()+2;i != vs.end();i++)
107     vf.push_back(atof((char*)i->c_str()));
108    
109     _vschrg.push_back(pair<OBSmartsPattern*,vector<double> > (sp,vf));
110     }
111     }
112    
113     void OBPhModel::AssignSeedPartialCharge(OBMol &mol)
114     {
115     if (!_init)
116     Init();
117    
118     mol.SetPartialChargesPerceived();
119     if (!mol.AutomaticPartialCharge())
120     return;
121    
122     vector<pair<OBSmartsPattern*,vector<double> > >::iterator i;
123     for (i = _vschrg.begin();i != _vschrg.end();i++)
124     if (i->first->Match(mol))
125     {
126     _mlist = i->first->GetUMapList();
127     unsigned int k;
128     vector<vector<int> >::iterator j;
129    
130     for (j = _mlist.begin();j != _mlist.end();j++)
131     for (k = 0;k < j->size();k++)
132     mol.GetAtom((*j)[k])->SetPartialCharge(i->second[k]);
133     }
134     }
135    
136     void OBPhModel::CorrectForPH(OBMol &mol)
137     {
138     if (!_init)
139     Init();
140     if (mol.IsCorrectedForPH())
141     return;
142     if (!mol.AutomaticFormalCharge())
143     return;
144    
145     mol.SetCorrectedForPH();
146    
147     obErrorLog.ThrowError(__FUNCTION__,
148     "Ran OpenBabel::CorrectForPH", obAuditMsg);
149    
150     OBAtom *atom;
151     vector<OBNodeBase*>::iterator j;
152     for (atom = mol.BeginAtom(j);atom;atom = mol.NextAtom(j))
153     atom->SetFormalCharge(0);
154    
155     vector<OBChemTsfm*>::iterator i;
156     for (i = _vtsfm.begin();i != _vtsfm.end();i++)
157     (*i)->Apply(mol);
158    
159     atomtyper.CorrectAromaticNitrogens(mol);
160     }
161    
162     // Portions of this documentation adapted from the JOELib docs, written by
163     // Joerg Wegner
164     /** \class OBChemTsfm
165     \brief SMARTS based structural modification (chemical transformation)
166    
167     Transformation of chemical structures can be used for pH value correction
168     (i.e. via OBPhModel and OBMol::CorrectForPH()). The OBChemTsfm class
169     defines SMARTS based TRANSFORM patterns to delete atoms, change atom types,
170     atom formal charges, and bond types.
171    
172     For storing and converting chemical reaction files, use the OBReaction class.
173     **/
174     bool OBChemTsfm::Init(string &bgn,string &end)
175     {
176     if (!_bgn.Init(bgn))
177     return(false);
178     if (!end.empty())
179     if (!_end.Init(end))
180     return(false);
181    
182     //find atoms to be deleted
183     unsigned int i,j;
184     int vb;
185     bool found;
186     for (i = 0;i < _bgn.NumAtoms();i++)
187     if ((vb = _bgn.GetVectorBinding(i)))
188     {
189     found = false;
190     for (j = 0;j < _end.NumAtoms();j++)
191     if (vb == _end.GetVectorBinding(j))
192     {
193     found = true;
194     break;
195     }
196    
197     if (!found)
198     _vadel.push_back(i);
199     }
200    
201     //find elements to be changed
202     int ele;
203     for (i = 0;i < _bgn.NumAtoms();i++)
204     if ((vb = _bgn.GetVectorBinding(i)) != 0)
205     {
206     ele = _bgn.GetAtomicNum(i);
207     for (j = 0;j < _end.NumAtoms();j++)
208     if (vb == _end.GetVectorBinding(j))
209     if (ele != _end.GetAtomicNum(j))
210     {
211     _vele.push_back(pair<int,int> (i,_end.GetAtomicNum(j)));
212     break;
213     }
214     }
215    
216     //find charges to modify
217     int chrg;
218     for (i = 0;i < _bgn.NumAtoms();i++)
219     if ((vb = _bgn.GetVectorBinding(i)))
220     {
221     chrg = _bgn.GetCharge(i);
222     for (j = 0;j < _end.NumAtoms();j++)
223     if (vb == _end.GetVectorBinding(j))
224     if (chrg != _end.GetCharge(j))
225     _vchrg.push_back(pair<int,int> (i,_end.GetCharge(j)));
226     }
227    
228     //find bonds to be modified
229     //find bonds to be modified
230     int bsrc,bdst,bord,bvb1,bvb2;
231     int esrc,edst,eord,evb1,evb2;
232    
233     for (i = 0;i < _bgn.NumBonds();i++)
234     {
235     _bgn.GetBond(bsrc,bdst,bord,i);
236     bvb1 = _bgn.GetVectorBinding(bsrc);
237     bvb2 = _bgn.GetVectorBinding(bdst);
238     if (!bvb1 || !bvb2)
239     continue;
240    
241     for (j = 0;j < _end.NumBonds();j++)
242     {
243     _end.GetBond(esrc,edst,eord,j);
244     evb1 = _end.GetVectorBinding(esrc);
245     evb2 = _end.GetVectorBinding(edst);
246     if ((bvb1 == evb1 && bvb2 == evb2) || (bvb1 == evb2 && bvb2 == evb1))
247     {
248     if (bord == eord)
249     break; //nothing to modify if bond orders identical
250     _vbond.push_back(pair<pair<int,int>,int> (pair<int,int> (bsrc,bdst),eord));
251     break;
252     }
253     }
254     }
255    
256     //make sure there is some kind of transform to do here
257     if (_vadel.empty() && _vchrg.empty() && _vbond.empty())
258     return(false);
259    
260     return(true);
261     }
262    
263     bool OBChemTsfm::Apply(OBMol &mol)
264     {
265     if (!_bgn.Match(mol))
266     return(false);
267    
268     vector<vector<int> > mlist = _bgn.GetUMapList();
269    
270     obErrorLog.ThrowError(__FUNCTION__,
271     "Ran OpenBabel::OBChemTransform", obAuditMsg);
272    
273     if (!_vchrg.empty()) //modify charges
274     {
275     vector<vector<int> >::iterator i;
276     vector<pair<int,int> >::iterator j;
277    
278     for (i = mlist.begin();i != mlist.end();i++)
279     for (j = _vchrg.begin();j != _vchrg.end();j++)
280     if (j->first < (signed)i->size()) //goof proofing
281     mol.GetAtom((*i)[j->first])->SetFormalCharge(j->second);
282    
283     mol.UnsetImplicitValencePerceived();
284     }
285    
286     if (!_vbond.empty()) //modify bond orders
287     {
288     OBBond *bond;
289     vector<vector<int> >::iterator i;
290     vector<pair<pair<int,int>,int> >::iterator j;
291     for (i = mlist.begin();i != mlist.end();i++)
292     for (j = _vbond.begin();j != _vbond.end();j++)
293     {
294     bond = mol.GetBond((*i)[j->first.first],(*i)[j->first.second]);
295     if (!bond)
296     {
297     obErrorLog.ThrowError(__FUNCTION__, "unable to find bond", obDebug);
298     continue;
299     }
300    
301     bond->SetBO(j->second);
302     }
303     }
304    
305     if (!_vadel.empty() || !_vele.empty()) //delete atoms and change elements
306     {
307     vector<int>::iterator j;
308     vector<vector<int> >::iterator i;
309    
310     if (!_vele.empty())
311     {
312     vector<pair<int,int> >::iterator k;
313     for (i = mlist.begin();i != mlist.end();i++)
314     for (k = _vele.begin();k != _vele.end();k++)
315     mol.GetAtom((*i)[k->first])->SetAtomicNum(k->second);
316     }
317    
318     //make sure same atom isn't deleted twice
319     vector<bool> vda;
320     vector<OBNodeBase*> vdel;
321     vda.resize(mol.NumAtoms()+1,false);
322     for (i = mlist.begin();i != mlist.end();i++)
323     for (j = _vadel.begin();j != _vadel.end();j++)
324     if (!vda[(*i)[*j]])
325     {
326     vda[(*i)[*j]] = true;
327     vdel.push_back(mol.GetAtom((*i)[*j]));
328     }
329    
330     vector<OBNodeBase*>::iterator k;
331     for (k = vdel.begin();k != vdel.end();k++)
332     mol.DeleteAtom((OBAtom*)*k);
333     }
334    
335     return(true);
336     }
337    
338     } //namespace OpenBabel
339    
340     //! \file phmodel.cpp
341     //! \brief Read pH rules and assign charges.