ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-2.0/src/openbabel/phmodel.cpp
Revision: 2518
Committed: Fri Dec 16 21:52:50 2005 UTC (18 years, 6 months ago) by tim
File size: 10026 byte(s)
Log Message:
changed __FUNCTION__ to __func__ to match C99 standard, and then added
an autoconf test to check for __func__ usability.  Changed some default
compile flags for the Sun architecture

File Contents

# Content
1 /**********************************************************************
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 STR_DEFINE(_dir, FRC_PATH);
41 _envvar = "FORCE_PARAM_PATH";
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(__func__, " 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(__func__, " 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(__func__, " 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(__func__, " 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(__func__,
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(__func__,
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(__func__, "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.