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 package ffx.numerics.estimator;
39
40 import ffx.numerics.math.BootStrapStatistics;
41
42 import java.util.logging.Logger;
43
44 import static ffx.utilities.Constants.NS2SEC;
45 import static java.lang.String.format;
46 import static org.apache.commons.math3.util.FastMath.min;
47
48
49
50
51
52
53
54
55 public class FreeEnergyDifferenceReporter {
56
57 private static final Logger logger = Logger.getLogger(FreeEnergyDifferenceReporter.class.getName());
58
59
60
61
62 private final int nStates;
63
64
65
66
67
68 private final double[][] energiesLow;
69
70
71
72
73
74 private final double[][] energiesAt;
75
76
77
78
79
80 private final double[][] energiesHigh;
81
82
83
84
85
86 private final double[][] volume;
87
88
89
90
91 private final double[] lambdaValues;
92
93
94
95 private final double[] temperature;
96
97
98
99 private final double eps;
100
101
102
103 private final int nIterations;
104
105
106
107
108 final long MIN_BOOTSTRAP_TRIALS = 1000L;
109
110
111
112
113 private double forwardTotalFEDifference;
114
115
116
117 private double forwardTotalEnthalpyChange;
118
119
120
121 private double forwardTotalEntropyChange;
122
123
124
125 private double backwardTotalFEDifference;
126
127
128
129 private double backwardTotalEnthalpyChange;
130
131
132
133 private double backwardTotalEntropyChange;
134
135
136
137 private double barIterTotalFEDiff;
138
139
140
141 private double barBSTotalFEDiff;
142
143
144
145 private double barBSTotalEnthalpyChange;
146
147
148
149 private double barBSTotalEntropyChange;
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164 public FreeEnergyDifferenceReporter(int nStates, double[] lambdaValues, double[] temperature, double eps, int nIterations,
165 double[][] energiesLow, double[][] energiesAt, double[][] energiesHigh, double[][] volume) {
166 this.nStates = nStates;
167 this.energiesLow = energiesLow;
168 this.energiesAt = energiesAt;
169 this.energiesHigh = energiesHigh;
170 this.volume = volume;
171 this.lambdaValues = lambdaValues;
172 this.temperature = temperature;
173 this.eps = eps;
174 this.nIterations = nIterations;
175 }
176
177
178
179
180 public void report() {
181
182 double[] energyMean = new double[nStates];
183 double[] energySD = new double[nStates];
184 double[] energyVar = new double[nStates];
185 for (int state = 0; state < nStates; state++) {
186 BootStrapStatistics energyStats = new BootStrapStatistics(energiesAt[state]);
187 energyMean[state] = energyStats.mean;
188 energySD[state] = energyStats.sd;
189 energyVar[state] = energyStats.var;
190 }
191
192
193 BennettAcceptanceRatio bar = new BennettAcceptanceRatio(lambdaValues, energiesLow,
194 energiesAt, energiesHigh, temperature, eps, nIterations);
195
196 barIterTotalFEDiff = bar.getTotalFreeEnergyDifference();
197 double barIterFEDiffTotalUncertainty = bar.getTotalFEDifferenceUncertainty();
198 double[] barIterFEDifferences = bar.getFreeEnergyDifferences();
199 double[] barIterFEDiffUncertainties = bar.getFEDifferenceUncertainties();
200
201 EstimateBootstrapper barBS = new EstimateBootstrapper(bar);
202 EstimateBootstrapper forwardBS = new EstimateBootstrapper(bar.getInitialForwardsGuess());
203 EstimateBootstrapper backwardBS = new EstimateBootstrapper(bar.getInitialBackwardsGuess());
204
205 int numSnapshots = energiesAt[0].length;
206 int trials = (int) (1.0e8 / numSnapshots);
207 long bootstrap = min(MIN_BOOTSTRAP_TRIALS, trials);
208 logger.info(format(" Number of bootstrap trials: %d", bootstrap));
209
210 long time = -System.nanoTime();
211 forwardBS.bootstrap(bootstrap);
212 time += System.nanoTime();
213 logger.fine(format(" Forward FEP Bootstrap Complete: %7.4f sec", time * NS2SEC));
214 forwardTotalFEDifference = forwardBS.getTotalFreeEnergyDifference();
215 double forwardTotalFEDiffUncertainty = forwardBS.getTotalFEDifferenceUncertainty();
216 forwardTotalEnthalpyChange = forwardBS.getTotalEnthalpyChange();
217 double forwardTotalEnthalpyUncertainty = forwardBS.getTotalEnthalpyUncertainty();
218
219 time = -System.nanoTime();
220 backwardBS.bootstrap(bootstrap);
221 time += System.nanoTime();
222 logger.fine(format(" Backward FEP Bootstrap Complete: %7.4f sec", time * NS2SEC));
223 backwardTotalFEDifference = backwardBS.getTotalFreeEnergyDifference();
224 double backwardTotalFEDiffUncertainty = backwardBS.getTotalFEDifferenceUncertainty();
225 backwardTotalEnthalpyChange = backwardBS.getTotalEnthalpyChange();
226 double backwardTotalEnthalpyUncertainty = backwardBS.getTotalEnthalpyUncertainty();
227
228 time = -System.nanoTime();
229 barBS.bootstrap(bootstrap);
230 time += System.nanoTime();
231 logger.fine(format(" BAR Bootstrap Complete: %7.4f sec", time * NS2SEC));
232
233 barBSTotalFEDiff = barBS.getTotalFreeEnergyDifference();
234 double barBSTotalFEDiffUncertainty = barBS.getTotalFEDifferenceUncertainty();
235 barBSTotalEnthalpyChange = barBS.getTotalEnthalpyChange();
236 double barBSTotalEnthalpyUncertainty = barBS.getTotalEnthalpyUncertainty();
237
238 if (nStates > 2) {
239 logger.info("\n Window Free Energy Differences (kcal/mol)");
240 logger.info(" Forward FEP Backward FEP BAR Iteration BAR Bootstrap");
241 double[] forwardFEDifferences = forwardBS.getFreeEnergyDifferences();
242 double[] forwardFEDUncertainty = forwardBS.getFEDifferenceStdDevs();
243 double[] backwardFEDifferences = backwardBS.getFreeEnergyDifferences();
244 double[] backwardFEDUncertainty = backwardBS.getFEDifferenceStdDevs();
245 double[] barBSFE = barBS.getFreeEnergyDifferences();
246 double[] barBSUncertaintyFE = barBS.getFEDifferenceStdDevs();
247 for (int n = 0; n < nStates - 1; n++) {
248 logger.info(format(" %2d %10.4f +/- %6.4f %10.4f +/- %6.4f %10.4f +/- %6.4f %10.4f +/- %6.4f",
249 n, forwardFEDifferences[n], forwardFEDUncertainty[n],
250 backwardFEDifferences[n], backwardFEDUncertainty[n],
251 barIterFEDifferences[n], barIterFEDiffUncertainties[n],
252 barBSFE[n], barBSUncertaintyFE[n]));
253 }
254 }
255
256 logger.info("\n Total Free Energy Difference (kcal/mol)");
257 logger.info(" Forward FEP Backward FEP BAR Iteration BAR Bootstrap");
258 logger.info(format(" %10.4f +/- %6.4f %10.4f +/- %6.4f %10.4f +/- %6.4f %10.4f +/- %6.4f",
259 forwardTotalFEDifference, forwardTotalFEDiffUncertainty,
260 backwardTotalFEDifference, backwardTotalFEDiffUncertainty,
261 barIterTotalFEDiff, barIterFEDiffTotalUncertainty,
262 barBSTotalFEDiff, barBSTotalFEDiffUncertainty));
263
264 logger.info("\n Enthalpy from Potential Energy Averages (kcal/mol)\n");
265 for (int n = 0; n < nStates; n++) {
266 logger.info(format(" State %2d: %12.4f +/- %6.4f", n, energyMean[n], energySD[n]));
267 }
268 double enthalpyDiff = energyMean[nStates - 1] - energyMean[0];
269 double enthalpyDiffSD = Math.sqrt(energyVar[nStates - 1] + energyVar[0]);
270 logger.info(format(" Enthalpy via Direct Estimate: %12.4f +/- %6.4f", enthalpyDiff, enthalpyDiffSD));
271
272
273 if (nStates > 2) {
274 logger.info("\n Window Enthalpy Differences (kcal/mol)");
275 logger.info(" Forward FEP Backward FEP BAR Bootstrap");
276 double[] forwardEnthalpyDifferences = forwardBS.getEnthalpyChanges();
277 double[] forwardEnthalpyUncertainty = forwardBS.getEnthalpyStdDevs();
278 double[] backwardEnthalpyDifferences = backwardBS.getEnthalpyChanges();
279 double[] backwardEnthalpyUncertainty = backwardBS.getEnthalpyStdDevs();
280 double[] barBSenthalpy = barBS.getEnthalpyChanges();
281 double[] barBSenthalpyUncertainty = barBS.getEnthalpyStdDevs();
282 for (int n = 0; n < nStates - 1; n++) {
283 logger.info(format(" %2d %10.4f +/- %6.4f %10.4f +/- %6.4f %10.4f +/- %6.4f",
284 n, forwardEnthalpyDifferences[n], forwardEnthalpyUncertainty[n],
285 backwardEnthalpyDifferences[n], backwardEnthalpyUncertainty[n],
286 barBSenthalpy[n], barBSenthalpyUncertainty[n]));
287 }
288 }
289 logger.info("\n Total Enthalpy Difference (kcal/mol)");
290 logger.info(" Forward FEP Backward FEP BAR Bootstrap");
291 logger.info(format(" %10.4f +/- %6.4f %10.4f +/- %6.4f %10.4f +/- %6.4f",
292 forwardTotalEnthalpyChange, forwardTotalEnthalpyUncertainty,
293 backwardTotalEnthalpyChange, backwardTotalEnthalpyUncertainty,
294 barBSTotalEnthalpyChange, barBSTotalEnthalpyUncertainty));
295
296
297 if (nStates > 2) {
298 logger.info("\n Window Entropy Differences -T*dS (kcal/mol)");
299 logger.info(" Forward FEP Backward FEP BAR Bootstrap");
300 double[] forwardEntropyDifferences = forwardBS.getEntropyChanges();
301 double[] forwardEntropyUncertainty = forwardBS.getEntropyStdDevs();
302 double[] backwardEntropyDifferences = backwardBS.getEntropyChanges();
303 double[] backwardEntropyUncertainty = backwardBS.getEntropyStdDevs();
304 double[] barBSEntropy = barBS.getEntropyChanges();
305 double[] barBSEntropyUncertainty = barBS.getEntropyStdDevs();
306 for (int n = 0; n < nStates - 1; n++) {
307 logger.info(format(" %2d %10.4f +/- %6.4f %10.4f +/- %6.4f %10.4f +/- %6.4f",
308 n, forwardEntropyDifferences[n], forwardEntropyUncertainty[n],
309 backwardEntropyDifferences[n], backwardEntropyUncertainty[n],
310 barBSEntropy[n], barBSEntropyUncertainty[n]));
311 ;
312 }
313 }
314 forwardTotalEntropyChange = forwardBS.getTotalEntropyChange();
315 double forwardTotalEntropyUncertainty = forwardBS.getTotalEntropyUncertainty();
316 backwardTotalEntropyChange = backwardBS.getTotalEntropyChange();
317 double backwardTotalEntropyUncertainty = backwardBS.getTotalEntropyUncertainty();
318 barBSTotalEntropyChange = barBS.getTotalEntropyChange();
319 double barBSTotalEntropyUncertainty = barBS.getTotalEntropyUncertainty();
320 logger.info("\n Total Entropy Difference -T*dS (kcal/mol)");
321 logger.info(" Forward FEP Backward FEP BAR Bootstrap");
322 logger.info(format(" %10.4f +/- %6.4f %10.4f +/- %6.4f %10.4f +/- %6.4f",
323 forwardTotalEntropyChange, forwardTotalEntropyUncertainty,
324 backwardTotalEntropyChange, backwardTotalEntropyUncertainty,
325 barBSTotalEntropyChange, barBSTotalEntropyUncertainty));
326 }
327
328
329
330
331
332
333 public double getForwardTotalFEDifference() {
334 return forwardTotalFEDifference;
335 }
336
337
338
339
340
341
342 public double getForwardTotalEnthalpyChange() {
343 return forwardTotalEnthalpyChange;
344 }
345
346
347
348
349
350
351 public double getForwardTotalEntropyChange() {
352 return forwardTotalEntropyChange;
353 }
354
355
356
357
358
359
360 public double getBackwardTotalFEDifference() {
361 return backwardTotalFEDifference;
362 }
363
364
365
366
367
368
369 public double getBackwardTotalEnthalpyChange() {
370 return backwardTotalEnthalpyChange;
371 }
372
373
374
375
376
377
378 public double getBackwardTotalEntropyChange() {
379 return backwardTotalEntropyChange;
380 }
381
382
383
384
385
386
387 public double getBarIterTotalFEDiff() {
388 return barIterTotalFEDiff;
389 }
390
391
392
393
394
395
396 public double getBarBSTotalFEDiff() {
397 return barBSTotalFEDiff;
398 }
399
400
401
402
403
404
405 public double getBarBSTotalEnthalpyChange() {
406 return barBSTotalEnthalpyChange;
407 }
408
409
410
411
412
413
414 public double getBarBSTotalEntropyChange() {
415 return barBSTotalEntropyChange;
416 }
417 }