View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2024.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.potential.bonded;
39  
40  import static java.lang.String.format;
41  
42  import ffx.potential.bonded.AminoAcidUtils.AminoAcid3;
43  import ffx.potential.parameters.ForceField;
44  import ffx.potential.parameters.RelativeSolvationType;
45  import java.util.HashMap;
46  import java.util.Map;
47  import java.util.logging.Logger;
48  
49  /**
50   * A relative solvation term for chemical perturbations.
51   *
52   * @author Michael J. Schnieders
53   * @author Jacob M. Litman
54   * @since 1.0
55   */
56  public class RelativeSolvation {
57  
58    private static final Logger logger = Logger.getLogger(RelativeSolvation.class.getName());
59    /** Look-up of non-standard energies. */
60    private final Map<String, Double> nonStdEnergies;
61    /** Solvation library in use. */
62    private final SolvationLibrary solvationLibrary;
63  
64    /**
65     * Constructor for RelativeSolvation.
66     *
67     * @param solvationLibrary a {@link ffx.potential.bonded.RelativeSolvation.SolvationLibrary}
68     *     object.
69     * @param forceField a {@link ffx.potential.parameters.ForceField} object.
70     */
71    public RelativeSolvation(SolvationLibrary solvationLibrary, ForceField forceField) {
72      this.solvationLibrary = solvationLibrary;
73      nonStdEnergies = new HashMap<>();
74      for (RelativeSolvationType rsType : forceField.getRelativeSolvationTypes().values()) {
75        String resName = rsType.getResName();
76        double e = rsType.getSolvEnergy();
77        if (nonStdEnergies.put(resName, e) != null) {
78          logger.warning(format(" Repeat relative solvation for %s", resName));
79        }
80      }
81    }
82  
83    /**
84     * Gets the solvation energy (de-solvation penalty) for a given residue, allowing for sequence
85     * optimization to include an estimate of energy relative to the unfolded state.
86     *
87     * @param residue Residue to check
88     * @param checkZeroes Throws an error if not in solvation energy library
89     * @return Solvation energy
90     * @throws java.lang.IllegalArgumentException if any.
91     * @throws java.lang.IllegalArgumentException if any.
92     */
93    public double getSolvationEnergy(Residue residue, boolean checkZeroes)
94        throws IllegalArgumentException {
95      String resName = "";
96      double energy;
97      Residue theRes =
98          (residue instanceof MultiResidue) ? ((MultiResidue) residue).getActive() : residue;
99      switch (theRes.getResidueType()) {
100       case AA -> {
101         if (theRes instanceof MultiResidue) {
102           resName = ((MultiResidue) theRes).getActive().getName();
103         } else {
104           resName = theRes.getName();
105         }
106         energy = getAASolvationEnergy(theRes);
107       }
108       case NA -> {
109         if (theRes instanceof MultiResidue) {
110           resName = ((MultiResidue) theRes).getActive().getName();
111         } else {
112           resName = theRes.getName();
113         }
114         energy = getNASolvationEnergy(theRes);
115       }
116       default -> energy = 0;
117     }
118     if (checkZeroes && energy == 0) {
119       throw new IllegalArgumentException(
120           format(" Zero de-solvation energy for residue %s: likely not in solvation library.",
121               resName));
122     }
123     return energy;
124   }
125 
126   /** {@inheritDoc} */
127   @Override
128   public String toString() {
129     return "Relative solvation library: " + solvationLibrary.toString();
130   }
131 
132   /**
133    * Returns amino acid solvation energy based on solvation library.
134    *
135    * @param residue a {@link ffx.potential.bonded.Residue} object.
136    * @return Solvation energy
137    */
138   private double getAASolvationEnergy(Residue residue) {
139     return switch (solvationLibrary) {
140       case WOLFENDEN -> getWolfendenSolvationEnergy(residue);
141       case CABANI -> getCabaniSolvationEnergy(residue);
142       case EXPLICIT -> getExplicitSolvationEnergy(residue);
143       case GK -> getGKSolvationEnergy(residue);
144       case MACCALLUM_SPC -> getMacCallumSPCSolvationEnergy(residue);
145       case MACCALLUM_TIP4P -> getMacCallumTIP4PSolvationEnergy(residue);
146       default -> 0;
147     };
148   }
149 
150   /**
151    * Will return relative solvation energies for nucleic acids; currently returns 0.
152    *
153    * @param residue a {@link ffx.potential.bonded.Residue} object.
154    * @return Relative solvation energy
155    */
156   private double getNASolvationEnergy(Residue residue) {
157     return 0;
158   }
159 
160   /**
161    * Will return solvation energies relative to glycine for capped monomers in GK solvent; currently
162    * wraps getExplicitSolvationEnergy.
163    *
164    * @param residue a {@link ffx.potential.bonded.Residue} object.
165    * @return Relative solvation energy
166    */
167   private double getGKSolvationEnergy(Residue residue) {
168     return getExplicitSolvationEnergy(residue);
169   }
170 
171   /**
172    * Will return solvation energies relative to glycine for capped monomers in AMOEBA solvent;
173    * currently approximates this with charging energies in AMOEBA solvent.
174    *
175    * @param residue a {@link ffx.potential.bonded.Residue} object.
176    * @return Relative solvation energy
177    */
178   private double getExplicitSolvationEnergy(Residue residue) {
179     AminoAcid3 name = residue.getAminoAcid3();
180     return switch (name) {
181       case ALA -> 0.58;
182       case CYS -> -0.85;
183       case CYD -> -69.82;
184       case ASP -> -69.45;
185       case ASH -> -4.00;
186       case GLU -> -71.40;
187       case GLH -> -3.61;
188       case PHE -> -1.59;
189       case GLY -> 0.67;
190       case HIS -> -45.36;
191       case HID -> -8.42;
192       case HIE -> -7.53;
193       case ILE -> 0.14;
194       case LYS -> -43.98;
195       case LYD -> +0.35;
196       case MET -> -3.48;
197       case ASN -> -5.89;
198       case PRO -> 7.82;
199       case GLN -> -6.89;
200       case ARG -> -42.57;
201       case SER -> -2.14;
202       case THR -> 0.58;
203       case VAL -> 0.10;
204       case TRP -> -4.64;
205       case TYR -> 1.76;
206       case TYD -> -41.71;
207       case UNK -> nonStdEnergies.getOrDefault(residue.getName().toUpperCase(), 0.0);
208       default -> 0;
209     };
210   }
211 
212   /**
213    * Returns absolute solvation energies for side chain analogs as calculated by MacCallum for OPLS
214    * in TIP4P solvent.
215    *
216    * @param residue a {@link ffx.potential.bonded.Residue} object.
217    * @return Solvation energy
218    */
219   private double getMacCallumTIP4PSolvationEnergy(Residue residue) {
220     AminoAcid3 name = residue.getAminoAcid3();
221     return switch (name) {
222       case ALA -> 9.8;
223       case CYS -> -0.5;
224       case ASP -> -30.5;
225       case GLU -> -19.0;
226       case PHE -> -1.2;
227       case HIS -> -28.0;
228       case ILE -> 12.2;
229       case LYS -> -13.6;
230       case LEU -> 13.7;
231       case MET -> -7.1;
232       case ASN -> -34.5;
233       case GLN -> -31.4;
234       case ARG -> -43.9;
235       case SER -> -20.2;
236       case THR -> -20.3;
237       case VAL -> 12.0;
238       case TRP -> -16.2;
239       case TYR -> -18.8;
240       case UNK -> nonStdEnergies.getOrDefault(residue.getName().toUpperCase(), 0.0);
241       default -> 0;
242     };
243   }
244 
245   /**
246    * Returns absolute solvation energies for side chain analogs as calculated by MacCallum for OPLS
247    * in SPC solvent.
248    *
249    * @param residue a {@link ffx.potential.bonded.Residue} object.
250    * @return Solvation energy
251    */
252   private double getMacCallumSPCSolvationEnergy(Residue residue) {
253     AminoAcid3 name = residue.getAminoAcid3();
254     return switch (name) {
255       case ALA -> 9.3;
256       case CYS -> -1.1;
257       case ASP -> -30.1;
258       case GLU -> -18.8;
259       case PHE -> -1.4;
260       case HIS -> -27.2;
261       case ILE -> 11.9;
262       case LYS -> -8.6;
263       case LEU -> 12.6;
264       case MET -> -5.1;
265       case ASN -> -34.3;
266       case GLN -> -30.8;
267       case ARG -> -46.3;
268       case SER -> -18.5;
269       case THR -> -19.3;
270       case VAL -> 11.3;
271       case TRP -> -15.1;
272       case TYR -> -18.2;
273       case UNK -> nonStdEnergies.getOrDefault(residue.getName().toUpperCase(), 0.0);
274       default -> 0;
275     };
276   }
277 
278   /**
279    * Returns absolute solvation energies for side chain analogs as experimentally measured by Cabani
280    * et al.
281    *
282    * @param residue a {@link ffx.potential.bonded.Residue} object.
283    * @return Solvation energy
284    */
285   private double getCabaniSolvationEnergy(Residue residue) {
286     AminoAcid3 name = residue.getAminoAcid3();
287     switch (name) {
288       case ALA:
289         return 8.4;
290       case CYS:
291         return -5.2;
292       case ASP:
293         return -28.1;
294       case GLU:
295         return -27.1;
296       case PHE:
297         return -3.7;
298       case HIS:
299         return -27.4;
300       case ILE:
301         return 8.7;
302       case LYS:
303         return -15.5;
304       case LEU:
305         return 9.7;
306       case MET:
307         return 9.0;
308       case ASN:
309         return -40.6;
310       case GLN:
311         return -18.7;
312       case ARG:
313         return -30.1;
314       case SER:
315         return -21.4;
316       case THR:
317         return -21.0;
318       case VAL:
319         return 8.2;
320       case TRP:
321         return -12.3;
322       case TYR:
323         return -25.7;
324       case UNK:
325         return nonStdEnergies.getOrDefault(residue.getName().toUpperCase(), 0.0);
326       case GLY:
327       case PRO:
328       default:
329         return 0;
330     }
331   }
332 
333   /**
334    * Returns absolute solvation energies for side chain analogs as experimentally measured by
335    * Wolfenden et al.
336    *
337    * @param residue a {@link ffx.potential.bonded.Residue} object.
338    * @return Solvation energy
339    */
340   private double getWolfendenSolvationEnergy(Residue residue) {
341     AminoAcid3 name = residue.getAminoAcid3();
342     switch (name) {
343       case ALA:
344         return 8.1;
345       case CYS:
346         return -5.1;
347       case ASP:
348         return -27.5;
349       case GLU:
350         return -26.6;
351       case PHE:
352         return -3.1;
353       case HIS:
354         return -42.1;
355       case ILE:
356         return 8.8;
357       case LYS:
358         return -18.0;
359       case LEU:
360         return 9.4;
361       case MET:
362         return -6.1;
363       case ASN:
364         return -39.9;
365       case GLN:
366         return -38.7;
367       case ARG:
368         return -44.8;
369       case SER:
370         return -20.8;
371       case THR:
372         return -20.1;
373       case VAL:
374         return 8.2;
375       case TRP:
376         return -24.3;
377       case TYR:
378         return -25.2;
379       case UNK:
380         return nonStdEnergies.getOrDefault(residue.getName().toUpperCase(), 0.0);
381       case GLY:
382       case PRO:
383       default:
384         return 0; // Not listed.
385     }
386   }
387 
388   /**
389    * Citations: Wolfenden et al: Wolfenden, R., Andersson, L., Cullis, P. M. and Southgate, C. C. B.
390    * (1981) AFFINITIES OF AMINO-ACID SIDE-CHAINS FOR SOLVENT WATER. Biochemistry. 20, 849-855
391    *
392    * <p>Cabani et al: Cabani, S., Gianni, P., Mollica, V. and Lepori, L. (1981) GROUP
393    * CONTRIBUTIONS TO THE THERMODYNAMIC PROPERTIES OF NON-IONIC ORGANIC SOLUTES IN DILUTE
394    * AQUEOUS-SOLUTION. Journal of Solution Chemistry. 10, 563-595
395    *
396    * <p>MacCallum OPLS libraries: Maccallum, J. L. and Tieleman, D. P. (2003) Calculation of the
397    * water-cyclohexane transfer free energies of neutral amino acid side-chain analogs using the OPLS
398    * all-atom force field. Journal of Computational Chemistry. 24, 1930-1935
399    */
400   public enum SolvationLibrary {
401     WOLFENDEN, CABANI, EXPLICIT, GK, MACCALLUM_SPC, MACCALLUM_TIP4P, OPLS_EXPLICIT, OPLS_GK, AUTO, NONE
402   }
403 }