File: ooiEnergy.C

package info (click to toggle)
ball 1.5.0%2Bgit20180813.37fc53c-6
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 239,888 kB
  • sloc: cpp: 326,149; ansic: 4,208; python: 2,303; yacc: 1,778; lex: 1,099; xml: 958; sh: 322; makefile: 95
file content (300 lines) | stat: -rw-r--r-- 8,097 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
// -*- Mode: C++; tab-width: 2; -*-
// vi: set ts=2:
//

#include <BALL/SOLVATION/ooiEnergy.h>

#include <BALL/common.h>
#include <BALL/SYSTEM/path.h>
#include <BALL/COMMON/exception.h>
#include <BALL/DATATYPE/hashGrid.h>
#include <BALL/DATATYPE/string.h>
#include <BALL/DATATYPE/stringHashMap.h>
#include <BALL/STRUCTURE/geometricProperties.h>
#include <BALL/KERNEL/atom.h>
#include <BALL/KERNEL/bond.h>
#include <BALL/STRUCTURE/numericalSAS.h>
#include <BALL/FORMAT/parameters.h>
#include <BALL/FORMAT/parameterSection.h>
#include <BALL/MOLMEC/COMMON/typeRuleProcessor.h>

#define OOI_PARAMETER_FILENAME "solvation/Ooi.ini"

//#define BALL_DEBUG_OOI

using namespace std;

namespace BALL 
{
	namespace OoiEnergy
	{
		bool is_initialized = false;

		// a hash map to convert names to Ooi types
		StringHashMap<Atom::Type> type_map;

		// a type rule assignment processor
		TypeRuleProcessor type_rule;

		// free energy is calculated as
		// dG = \sum_i g_i A_i
		// where A_i is the atomic solvent accesible surface
		// area. The atomic radii are taken from the vector radius below.
		vector<float> radius;
		vector<float> g;

		// read the parameter files for calculateOoiEnergy 
		// and set up the basic data structures
		void init()
		{
			// extract the parameters from the file
			Path path;
			String filename = path.find(OOI_PARAMETER_FILENAME);
			if (filename == "")
			{
				filename = OOI_PARAMETER_FILENAME;
			}
			Parameters parameters(filename);

			ParameterSection parameter_section;
			if (!parameter_section.extractSection(parameters, "OoiParameters"))
			{
				Log.error() << "calculateOoiEnergy: cannot find section [OoiParameters] in file "
										<< parameters.getFilename() << "." << endl;
				return;
			}
			if (!parameter_section.hasVariable("g") || !parameter_section.hasVariable("radius"))
			{
				Log.error() << "OoiEnergy: section [OoiTypes] of file " 
										<< parameters.getFilename() 
										<< " requires at least the columns 'g' and 'radius'." << endl;
				return;
			}							

			ParameterSection type_section;
			if (!type_section.extractSection(parameters, "OoiTypes"))
			{
				Log.error() << "calculateOoiEnergy: cannot find section [OoiTypes] in file "
										<< parameters.getFilename() << "." << endl;
				return;
			}
			if (!type_section.hasVariable("type"))
			{
				Log.error() << "OoiEnergy: section [OoiTypes] of file " 
										<< parameters.getFilename() 
										<< " does not contain a variable column 'type'." << endl;
				return;
			}			

			// extract the parameters for each type
			Position radius_column = parameter_section.getColumnIndex("radius");
			Position g_column = parameter_section.getColumnIndex("g");
			Index max_index = -1;
			for (Size i = 0; i < parameter_section.getNumberOfKeys(); i++)
			{			
				String index_str(parameter_section.getKey(i));
				Index index;
				try
				{
					index = index_str.trim().toInt();
				} 
				catch (Exception::InvalidFormat&)
				{
					Log.error() << "calculateOoiEnergy: cannot convert to a number: " << index_str << endl;
					continue;
				}

				if (index < 0)
				{
					Log.error() << "calculateOoiEnergy: illegal atom type index: " << index << endl;
					continue;
				} 

				if (index > max_index)
				{
					max_index = index;
				}
			}

			if (max_index < 0)
			{
				Log.error() << "calculateOoiEnergy: could not find any atom type in file "
									  << parameters.getFilename() << endl;
				return;
			}
			
			
			// resize the vectors to hold all indices
			radius.resize((Size)max_index + 1);
			g.resize((Size)max_index + 1);

			// and read all values from the parameter section
			for (Size i = 0; i < parameter_section.getNumberOfKeys(); i++)
			{
				String index_str(parameter_section.getKey(i));
				Index index;
				try
				{
					index = index_str.trim().toInt();

					// we ignore illegal (negative) indices
					if (index >= 0)
					{
						radius[index] = parameter_section.getValue(i, radius_column).toFloat();
						g[index] = parameter_section.getValue(i, g_column).toFloat();
					}
				}
				catch (Exception::InvalidFormat&)
				{
					Log.error() << "calculateOoiEnergy: cannot convert to a number: " << index_str << endl;
				}
			}

			// extract all known types by iterating over all keys
		  // and construct the hash map type_map
			Position type_column = type_section.getColumnIndex("type");
			for (Size i = 0; i < type_section.getNumberOfKeys(); i++)
			{
				// retrieve the type and check for validity
				String index_str(type_section.getValue(i, type_column));
				try
				{
					Atom::Type type = index_str.trim().toInt();
					if (type >= (Atom::Type)radius.size())
					{
						Log.error() << "calculateOoiEnergy: illegal atom type: " << type 
												<< " while reading parameter file." << endl;
					} 
					else 
					{
						index_str = type_section.getValue(i, type_column);
						type_map.insert(type_section.getKey(i), (Atom::Type)index_str.trim().toInt());
					}
				}
				catch (Exception::InvalidFormat&)
				{
					Log.error() << "calculateOoiEnergy: cannot convert to a number: " << index_str << endl;
				}
			}
			
			// set up the type rule processor
			// from the rules in the INI file
			type_rule.initialize(parameters.getParameterFile(), "TypeRules");

			// we're done with the initialization
			is_initialized = true;
		}
	}

	double calculateOoiEnergy(AtomContainer& atoms) 
	{
		using namespace OoiEnergy;

		// read and interpret the parameters 
		// this is only done the first time calculateOoiEnergy is called
		if (!is_initialized)
		{
			init();
			if (!is_initialized)
			{
				return 0;
			}
		}
		
		// assign radii and atom types for all atoms
		AtomIterator atom_it = atoms.beginAtom();
		for (; +atom_it; ++atom_it) 
		{
			// construct correct name, <RESNAME>:<ATOMNAME>
			String atom_name = atom_it->getFullName();
			
			// get the atom type from hash table
			// first, try a direct match
			Atom::Type atom_type = -1;
			if (type_map.has(atom_name))
			{
				atom_type = type_map[atom_name];
			} 
			else 
			{
				atom_name = atom_it->getFullName(Atom::NO_VARIANT_EXTENSIONS);
				if (type_map.has(atom_name))
				{
					atom_type = type_map[atom_name];
				} 
				else 
				{
					// try wildcard match
					atom_name = "*:" + atom_it->getName();
					if (type_map.has(atom_name))
					{
						atom_type = type_map[atom_name];
					}
				}
			}

			// if the atom type could not be determined, complain
			if (atom_type < 0)
			{
				// try to apply the type rule processor
				atom_it->setType(-1);
				type_rule(*atom_it);
				atom_type = atom_it->getType();
			}

			if (atom_type < 0)
			{
				Log.warn() << "calculateOOIEnergy: did not find a suitable type for " 
									 << atom_it->getFullName() << endl;

				// ignore this atom....
				atom_it->setType(-1);
				atom_it->setRadius(0.0);
			} 
			else 
			{
				// assign type and radius
				atom_it->setType(atom_type);
				atom_it->setRadius(radius[atom_type]);
			}
		}

		// calculate the atomic SAS areas
		// atom_SAS_areas hashes the atom pointer to the
		// surface area (in Angstrom^2)
		Options sas_options;

		NumericalSAS sas_computer;
		sas_computer.options[NumericalSAS::Option::NUMBER_OF_POINTS] = 1888;
		sas_computer.options[NumericalSAS::Option::PROBE_RADIUS    ] = 1.4;
		sas_computer.options[NumericalSAS::Option::COMPUTE_VOLUME  ] = false;

		sas_computer(atoms);
		HashMap<const Atom*,float>& atom_SAS_areas = sas_computer.getAtomAreas();

		// iterate over all atoms and add up the energies
		float energy = 0.0;
		for (atom_it = atoms.beginAtom(); +atom_it; ++atom_it) 
		{
			if (atom_SAS_areas.has(&*atom_it))
			{
				Atom::Type atom_type = atom_it->getType();
				if (atom_type >= 0)
				{
					// add the energy contribution of the atom
					float tmp = atom_SAS_areas[&*atom_it] * g[atom_type];
					energy += tmp;

					#ifdef BALL_DEBUG_OOI
						Log.info() << atom_it->getFullName() << " A = " << atom_SAS_areas[&*atom_it] 
    									 << " E = " << tmp << " kJ/mol" << endl;
					#endif
				}
			}		
		}

		// we're done.
		return energy;
	}

} // namespace BALL