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 ffx.numerics.math.DoubleMath.dihedralAngle;
41  import static ffx.potential.bonded.AminoAcidUtils.ResiduePosition.FIRST_RESIDUE;
42  import static ffx.potential.bonded.AminoAcidUtils.ResiduePosition.LAST_RESIDUE;
43  import static ffx.potential.bonded.AminoAcidUtils.ResiduePosition.MIDDLE_RESIDUE;
44  import static ffx.potential.bonded.AminoAcidUtils.ResiduePosition.SINGLE_RESIDUE;
45  import static ffx.potential.bonded.BondedUtils.buildBond;
46  import static ffx.potential.bonded.BondedUtils.buildH;
47  import static ffx.potential.bonded.BondedUtils.buildHeavy;
48  import static ffx.potential.bonded.BondedUtils.buildHydrogenAtom;
49  import static ffx.potential.bonded.BondedUtils.findAtomType;
50  import static ffx.potential.bonded.BondedUtils.intxyz;
51  import static java.lang.String.format;
52  import static org.apache.commons.math3.util.FastMath.toDegrees;
53  
54  import ffx.numerics.math.Double3;
55  import ffx.potential.bonded.BondedUtils.MissingAtomTypeException;
56  import ffx.potential.bonded.BondedUtils.MissingHeavyAtomException;
57  import ffx.potential.parameters.AtomType;
58  import ffx.potential.parameters.ForceField;
59  import java.util.ArrayList;
60  import java.util.Arrays;
61  import java.util.HashMap;
62  import java.util.List;
63  import java.util.Optional;
64  import java.util.logging.Level;
65  import java.util.logging.Logger;
66  
67  /**
68   * Utilities for creating Amino Acid residues.
69   *
70   * @author Michael Schnieders
71   * @since 1.0
72   */
73  public class AminoAcidUtils {
74  
75    private static final Logger logger = Logger.getLogger(AminoAcidUtils.class.getName());
76  
77    /** Repeating atomic numbers of an amino acid chain. */
78    public static final int[] AAPATTERN = {7, 6, 6};
79    /** Constant <code>AA3toAA1</code> */
80    static final HashMap<AminoAcid3, AminoAcid1> AA3toAA1 = new HashMap<>();
81    /** Constant <code>AA1toAA3</code> */
82    public static final HashMap<AminoAcid1, AminoAcid3> AA1toAA3 = new HashMap<>();
83    /** List of values from the AminoAcid1 enum. */
84    public static final List<AminoAcid1> aminoAcid1List = Arrays.asList(AminoAcid1.values());
85    /** Constant <code>aminoAcidList</code> */
86    public static final List<AminoAcid3> aminoAcidList = Arrays.asList(AminoAcid3.values());
87  
88    /** Constant <code>AminoAcidBackboneAtoms</code> */
89    public enum AminoAcidBackboneAtoms {N, H, CA, HA, C, O}
90  
91    /** Constant <code>GlycineBackboneAtoms</code> */
92    public enum GlycineBackboneAtoms {N, H, CA, HA2, HA3, C, O}
93  
94    /** Constant <code>ProlineBackboneAtoms</code> */
95    public enum ProlineBackboneAtoms {N, CA, HA, C, O}
96  
97    /**
98     * Turn an Enum into String array.
99     *
100    * @param e The enum class.
101    * @return A String array with all the enum values.
102    */
103   public static String[] getNames(Class<? extends Enum<?>> e) {
104     return Arrays.stream(e.getEnumConstants()).map(Enum::name).toArray(String[]::new);
105   }
106 
107   /**
108    * Stoichiometry of side chains can be used for identification, accept for a couple cases:
109    * <p>
110    * 1. Proline and Valine
111    * <p>
112    * 2. (Iso)Leucine
113    * <p>
114    * 3. DNA Gaunine/RNA Adenine.
115    * <p>
116    * This Hashtable returns the 3-letter name for amino acids, a single character for nucleic acids,
117    * or an integer indicating a special case.
118    */
119   public static final HashMap<String, String> sidechainStoichiometry = new HashMap<>();
120 
121   static {
122     // Amino Acid Side Chains
123     sidechainStoichiometry.put("S1C3", "MET");
124     sidechainStoichiometry.put("S1C1", "CYS");
125     sidechainStoichiometry.put("O1C1", "SER");
126     sidechainStoichiometry.put("O1C2", "THR");
127     sidechainStoichiometry.put("O1C7", "TYR");
128     sidechainStoichiometry.put("O2C2", "ASP");
129     sidechainStoichiometry.put("O2C3", "GLU");
130     sidechainStoichiometry.put("O1N1C2", "ASN");
131     sidechainStoichiometry.put("O1N1C3", "GLN");
132     sidechainStoichiometry.put("N3C4", "ARG");
133     sidechainStoichiometry.put("N2C4", "HIS");
134     sidechainStoichiometry.put("N1C9", "TRP");
135     sidechainStoichiometry.put("N1C4", "LYS");
136     sidechainStoichiometry.put("C7", "PHE");
137     sidechainStoichiometry.put("H", "GLY");
138     sidechainStoichiometry.put("C1", "ALA");
139     // DNA
140     sidechainStoichiometry.put("O2N3C6", "DC");
141     sidechainStoichiometry.put("O1N5C7", "DA");
142     sidechainStoichiometry.put("O3N2C7", "DT");
143     // RNA
144     sidechainStoichiometry.put("O3N5C7", "G");
145     sidechainStoichiometry.put("O3N3C6", "C");
146     sidechainStoichiometry.put("O4N2C6", "U");
147     // SPECIAL CASES
148     sidechainStoichiometry.put("C3", "1"); // Proline / Valine
149     sidechainStoichiometry.put("C4", "2"); // (Iso)Leucine
150     sidechainStoichiometry.put("O2N5C7", "3"); // DNA Gaunine / RNA Adenine
151 
152     AminoAcid1[] aa1 = AminoAcid1.values();
153     AminoAcid3[] aa3 = AminoAcid3.values();
154     for (int i = 0; i < AminoAcid1.values().length; i++) {
155       AA1toAA3.put(aa1[i], aa3[i]);
156       AA3toAA1.put(aa3[i], aa1[i]);
157     }
158   }
159 
160   /** Private constructor. */
161   private AminoAcidUtils() {
162   }
163 
164   /**
165    * Assign atom types to an amino acid polymer.
166    *
167    * @param residues The residues to assign atom types to.
168    * @param forceField The ForceField to apply.
169    * @param bondList Created bonds are added to this List.
170    * @throws MissingHeavyAtomException A needed heavy atom was not found.
171    * @throws MissingAtomTypeException An atom type could not be found.
172    * @since 1.0
173    */
174   public static void assignAminoAcidAtomTypes(List<Residue> residues, ForceField forceField,
175       List<Bond> bondList) throws MissingHeavyAtomException, MissingAtomTypeException {
176     // Loop over amino acid residues.
177     int numberOfResidues = residues.size();
178     for (int residueNumber = 0; residueNumber < numberOfResidues; residueNumber++) {
179       Residue residue = residues.get(residueNumber);
180       Residue previousResidue = null;
181       Residue nextResidue = null;
182       if (residueNumber > 0) {
183         previousResidue = residues.get(residueNumber - 1);
184       }
185       if (residueNumber < numberOfResidues - 1) {
186         nextResidue = residues.get(residueNumber + 1);
187       }
188       assignAminoAcidAtomTypes(residue, previousResidue, nextResidue, forceField, bondList);
189     }
190   }
191 
192   /**
193    * assignAminoAcidAtomTypes.
194    *
195    * @param residue a {@link ffx.potential.bonded.Residue} object.
196    * @param previousResidue a {@link ffx.potential.bonded.Residue} object.
197    * @param nextResidue a {@link ffx.potential.bonded.Residue} object.
198    * @param forceField a {@link ForceField} object.
199    * @param bondList a {@link java.util.List} object.
200    * @throws ffx.potential.bonded.BondedUtils.MissingHeavyAtomException if any.
201    * @throws ffx.potential.bonded.BondedUtils.MissingAtomTypeException if any.
202    */
203   public static void assignAminoAcidAtomTypes(Residue residue, Residue previousResidue,
204       Residue nextResidue, ForceField forceField, List<Bond> bondList)
205       throws MissingHeavyAtomException, MissingAtomTypeException {
206 
207     String residueName = residue.getName().toUpperCase();
208 
209     ResiduePosition position = MIDDLE_RESIDUE;
210     if (previousResidue == null && nextResidue == null) {
211       position = SINGLE_RESIDUE;
212     } else if (previousResidue == null) {
213       position = FIRST_RESIDUE;
214     } else if (nextResidue == null) {
215       position = LAST_RESIDUE;
216       // If the last residue only contains a nitrogen turn it into an NH2 group.
217       Atom N = (Atom) residue.getAtomNode("N");
218       if (residue.getAtomNodeList().size() == 1 && N != null) {
219         residueName = "NH2";
220         residue.setName(residueName);
221       }
222     }
223 
224     AminoAcid3 aminoAcid = getAminoAcid(residueName);
225     int aminoAcidNumber = getAminoAcidNumber(residueName);
226     // Non-standard Amino Acid; use ALA backbone types.
227     boolean nonStandard = false;
228     if (aminoAcid == AminoAcid3.UNK) {
229       aminoAcidNumber = getAminoAcidNumber("ALA");
230       nonStandard = true;
231     }
232 
233     // Only the last residue in a chain should have an OXT/OT2 atom.
234     if (nextResidue != null) {
235       removeOXT_OT2(residue);
236     }
237 
238     // Only the first nitrogen should have H1, H2 and H3 atoms, unless it's an NME cap.
239     if (previousResidue != null) {
240       removeH1_H2_H3(aminoAcid, residue);
241     }
242 
243     // Check for missing heavy atoms. This check ignores special terminating groups like FOR, NH2,
244     // etc.
245     if (!nonStandard) {
246       try {
247         checkForMissingHeavyAtoms(aminoAcid, residue);
248       } catch (BondedUtils.MissingHeavyAtomException e) {
249         logger.log(Level.INFO, " {0} could not be parsed.", residue.toString());
250         throw e;
251       }
252     }
253 
254     Atom pC = null;
255     Atom pCA = null;
256     if (previousResidue != null) {
257       pC = (Atom) previousResidue.getAtomNode("C");
258       pCA = (Atom) previousResidue.getAtomNode("CA");
259     }
260 
261     // Backbone nitrogen atom.
262     boolean neutralNTerminus = false;
263     Atom N = (Atom) residue.getAtomNode("N");
264     if (N != null) {
265       N.setAtomType(findAtomType(AA_N[position.ordinal()][aminoAcidNumber], forceField));
266       if (position != FIRST_RESIDUE && position != SINGLE_RESIDUE) {
267         buildBond(pC, N, forceField, bondList);
268       } else {
269         // Check for neutral N-terminal.
270         // biotype    762  N     "Deprotonated N-Terminus"     -1
271         // biotype    763  H     "Deprotonated N-Terminus"     -1
272         neutralNTerminus = forceField.getBoolean("neutral-nterminus", false);
273         if (neutralNTerminus) {
274           // Biotype is 762
275           N.setAtomType(findAtomType(762, forceField));
276 
277         }
278       }
279     }
280 
281     Atom CA = null;
282     Atom C = null;
283     Atom O = null;
284     if (!(position == LAST_RESIDUE && aminoAcid == AminoAcid3.NH2)) {
285       // Backbone carbon alpha atom.
286       if (aminoAcid == AminoAcid3.ACE || aminoAcid == AminoAcid3.NME) {
287         CA = buildHeavy(residue, "CH3", N, AA_CA[position.ordinal()][aminoAcidNumber], forceField,
288             bondList);
289       } else {
290         CA = buildHeavy(residue, "CA", N, AA_CA[position.ordinal()][aminoAcidNumber], forceField,
291             bondList);
292       }
293 
294       // Backbone carbonyl carbon and carbonyl oxygen atoms.
295       if (!(position == LAST_RESIDUE && aminoAcid == AminoAcid3.NME)) {
296         C = buildHeavy(residue, "C", CA, AA_C[position.ordinal()][aminoAcidNumber], forceField,
297             bondList);
298         O = (Atom) residue.getAtomNode("O");
299         if (O == null) {
300           O = (Atom) residue.getAtomNode("OT1");
301         }
302         if (O == null) {
303           // Build the carbonyl oxygen; assume the final residue has beta-sheet psi
304           double psi = 135.0;
305           if (nextResidue != null && N != null) {
306             Atom nextN = (Atom) nextResidue.getAtomNode("N");
307             psi = toDegrees(
308                 dihedralAngle(N.getXYZ(null), CA.getXYZ(null), C.getXYZ(null), nextN.getXYZ(null)));
309           }
310           O = buildHeavy(residue, "O", C, 1.25, CA, 117.0, N, psi - 180.0, 0,
311               AA_O[position.ordinal()][aminoAcidNumber], forceField, bondList);
312         } else {
313           AtomType atomType = findAtomType(AA_O[position.ordinal()][aminoAcidNumber], forceField);
314           O.setAtomType(atomType);
315           buildBond(C, O, forceField, bondList);
316         }
317       }
318     }
319 
320     // Nitrogen hydrogen atoms.
321     AtomType atomType = findAtomType(AA_HN[position.ordinal()][aminoAcidNumber], forceField);
322     switch (position) {
323       case FIRST_RESIDUE, SINGLE_RESIDUE -> {
324         switch (aminoAcid) {
325           case PRO:
326             // Check for the presence of H1, H2 and H3.
327             List<Atom> resAtoms = residue.getAtomList();
328             Optional<Atom> H1 = resAtoms.stream().filter((Atom a) -> a.getName().equals("H1")).findAny();
329             Optional<Atom> H2 = resAtoms.stream().filter((Atom a) -> a.getName().equals("H2")).findAny();
330             Optional<Atom> H3 = resAtoms.stream().filter((Atom a) -> a.getName().equals("H3")).findAny();
331             // Delete the extra hydrogen.
332             if (H1.isPresent() && H2.isPresent() && H3.isPresent()) {
333               residue.deleteAtom(H1.get());
334               // Otherwise rename the H1 hydrogen to H2 or H3.
335             } else if (H1.isPresent()) {
336               if (H2.isPresent()) {
337                 H1.get().setName("H3");
338               } else {
339                 H1.get().setName("H2");
340               }
341             }
342             buildHydrogenAtom(residue, "H2", N, 1.02, CA, 109.5, C, 0.0, 0, atomType, forceField, bondList);
343             buildHydrogenAtom(residue, "H3", N, 1.02, CA, 109.5, C, -120.0, 0, atomType, forceField, bondList);
344             break;
345           case PCA:
346             buildHydrogenAtom(residue, "H", N, 1.02, CA, 109.5, C, -60.0, 0, atomType, forceField,
347                 bondList);
348             break;
349           case ACE:
350             break;
351           default:
352             if (neutralNTerminus) {
353               // Biotype is 763
354               atomType = findAtomType(763, forceField);
355               Atom h1 = (Atom) residue.getAtomNode("H1");
356               Atom h2 = (Atom) residue.getAtomNode("H2");
357               Atom h3 = (Atom) residue.getAtomNode("H3");
358               if (h3 == null) {
359                 // If H3 is not present, look for H.
360                 h3 = (Atom) residue.getAtomNode("H");
361               }
362               // Delete the extra hydrogen.
363               if (h1 != null && h2 != null && h3 != null) {
364                 residue.deleteAtom(h3);
365                 // Otherwise rename the H3 hydrogen to H1 or H2.
366               } else if (h3 != null) {
367                 if (h1 == null) {
368                   h3.setName("H1");
369                 } else {
370                   h3.setName("H2");
371                 }
372               }
373               buildHydrogenAtom(residue, "H1", N, 1.02, CA, 109.5, C, 180.0, 0, atomType, forceField,
374                   bondList);
375               buildHydrogenAtom(residue, "H2", N, 1.02, CA, 109.5, C, 60.0, 0, atomType, forceField,
376                   bondList);
377             } else {
378               buildHydrogenAtom(residue, "H1", N, 1.02, CA, 109.5, C, 180.0, 0, atomType, forceField,
379                   bondList);
380               buildHydrogenAtom(residue, "H2", N, 1.02, CA, 109.5, C, 60.0, 0, atomType, forceField,
381                   bondList);
382               buildHydrogenAtom(residue, "H3", N, 1.02, CA, 109.5, C, -60.0, 0, atomType, forceField,
383                   bondList);
384             }
385         }
386       }
387       case LAST_RESIDUE -> {
388         switch (aminoAcid) {
389           case NH2 -> {
390             buildHydrogenAtom(residue, "H1", N, 1.02, pC, 119.0, pCA, 0.0, 0, atomType, forceField,
391                 bondList);
392             buildHydrogenAtom(residue, "H2", N, 1.02, pC, 119.0, pCA, 180.0, 0, atomType, forceField,
393                 bondList);
394           }
395           case NME ->
396               buildHydrogenAtom(residue, "H", N, 1.02, pC, 118.0, CA, 121.0, 1, atomType, forceField,
397                   bondList);
398           default ->
399               buildHydrogenAtom(residue, "H", N, 1.02, pC, 119.0, CA, 119.0, 1, atomType, forceField,
400                   bondList);
401         }
402       }
403       // Mid-chain nitrogen hydrogen.
404       default ->
405           buildHydrogenAtom(residue, "H", N, 1.02, pC, 119.0, CA, 119.0, 1, atomType, forceField,
406               bondList);
407     }
408 
409     // C-alpha hydrogen atoms.
410     String haName = "HA";
411     if (aminoAcid == AminoAcid3.GLY) {
412       haName = "HA2";
413     }
414     atomType = findAtomType(AA_HA[position.ordinal()][aminoAcidNumber], forceField);
415     switch (position) {
416       case FIRST_RESIDUE -> {
417         switch (aminoAcid) {
418           case FOR ->
419               buildHydrogenAtom(residue, "H", C, 1.12, O, 0.0, null, 0.0, 0, atomType, forceField,
420                   bondList);
421           case ACE -> {
422             buildHydrogenAtom(residue, "H1", CA, 1.10, C, 109.5, O, 180.0, 0, atomType, forceField,
423                 bondList);
424             buildHydrogenAtom(residue, "H2", CA, 1.10, C, 109.5, O, 60.0, 0, atomType, forceField,
425                 bondList);
426             buildHydrogenAtom(residue, "H3", CA, 1.10, C, 109.5, O, -60.0, 0, atomType, forceField,
427                 bondList);
428           }
429           default -> buildHydrogenAtom(residue, haName, CA, 1.10, N, 109.5, C, 109.5, -1, atomType,
430               forceField, bondList);
431         }
432       }
433       case LAST_RESIDUE -> {
434         if (aminoAcid == AminoAcid3.NME) {
435           buildHydrogenAtom(residue, "H1", CA, 1.10, N, 109.5, pC, 180.0, 0, atomType, forceField,
436               bondList);
437           buildHydrogenAtom(residue, "H2", CA, 1.10, N, 109.5, pC, 60.0, 0, atomType, forceField,
438               bondList);
439           buildHydrogenAtom(residue, "H3", CA, 1.10, N, 109.5, pC, -60.0, 0, atomType, forceField,
440               bondList);
441         } else {
442           buildHydrogenAtom(residue, haName, CA, 1.10, N, 109.5, C, 109.5, -1, atomType, forceField,
443               bondList);
444         }
445       }
446       // MIDDLE_RESIDUE or SINGLE_RESIDUE.
447       default ->
448           buildHydrogenAtom(residue, haName, CA, 1.10, N, 109.5, C, 109.0, -1, atomType, forceField,
449               bondList);
450     }
451 
452     // Build the amino acid side chain.
453     assignAminoAcidSideChain(position, aminoAcid, residue, CA, N, C, forceField, bondList);
454 
455     // Build the terminal oxygen if the residue is not NH2 or NME.
456     if ((position == LAST_RESIDUE || position == SINGLE_RESIDUE) &&
457         !(aminoAcid == AminoAcid3.NH2 || aminoAcid == AminoAcid3.NME)) {
458       atomType = findAtomType(AA_O[2][aminoAcidNumber], forceField);
459 
460       Atom OXT = (Atom) residue.getAtomNode("OXT");
461       if (OXT == null) {
462         OXT = (Atom) residue.getAtomNode("OT2");
463         if (OXT != null) {
464           OXT.setName("OXT");
465         }
466       }
467       // Check for a neutral C-terminus.
468       boolean neutralCTerminus = false;
469       if (OXT == null) {
470         OXT = (Atom) residue.getAtomNode("OH");
471         if (OXT != null) {
472           neutralCTerminus = true;
473         }
474       }
475 
476       if (OXT == null) {
477         String resName = C.getResidueName();
478         int resSeq = C.getResidueNumber();
479         Character chainID = C.getChainID();
480         Character altLoc = C.getAltLoc();
481         String segID = C.getSegID();
482         double occupancy = C.getOccupancy();
483         double tempFactor = C.getTempFactor();
484         OXT = new Atom(0, "OXT", altLoc, new double[3], resName, resSeq, chainID, occupancy,
485             tempFactor, segID);
486         OXT.setAtomType(atomType);
487         residue.addMSNode(OXT);
488         intxyz(OXT, C, 1.25, CA, 117.0, O, 126.0, 1);
489       } else {
490         if (neutralCTerminus) {
491           // Biotype records for the AMOEBA 2018 force field.
492           // biotype    771  C     "Protonated C-Terminus  "    235
493           // biotype    772  O     "Protonated C-Terminus  "    236
494           // biotype    773  OH    "Protonated C-Terminus  "    237
495           // biotype    774  HO    "Protonated C-Terminus  "    238
496           C.setAtomType(findAtomType(771, forceField));
497           O.setAtomType(findAtomType(772, forceField));
498           OXT.setAtomType(findAtomType(773, forceField));
499           Atom HO = (Atom) residue.getAtomNode("HO");
500           atomType = findAtomType(774, forceField);
501           if (HO == null) {
502             buildHydrogenAtom(residue, "HO", OXT, 1.02, C, 120.0, O, 180.0, 0, atomType, forceField, bondList);
503           } else {
504             HO.setAtomType(findAtomType(774, forceField));
505             buildBond(OXT, HO, forceField, bondList);
506           }
507         } else {
508           OXT.setAtomType(atomType);
509         }
510       }
511       buildBond(C, OXT, forceField, bondList);
512     }
513 
514     // Do some checks on the current residue to make sure all atoms have been assigned an atom type.
515     List<Atom> resAtoms = residue.getAtomList();
516     for (Atom atom : resAtoms) {
517       atomType = atom.getAtomType();
518       if (atomType == null) {
519         /*
520          * Sometimes, with deuterons, a proton has been constructed in
521          * its place, so we have a "dummy" deuteron still hanging
522          * around.
523          */
524         String protonEq = atom.getName().replaceFirst("D", "H");
525         Atom correspH = (Atom) residue.getAtomNode(protonEq);
526         if (correspH == null || correspH.getAtomType() == null) {
527           MissingAtomTypeException missingAtomTypeException = new MissingAtomTypeException(residue, atom);
528           throw missingAtomTypeException;
529         } else {
530           correspH.setName(atom.getName());
531           atom.removeFromParent();
532           atom = correspH;
533           atomType = atom.getAtomType();
534         }
535       }
536       int numberOfBonds = atom.getNumBonds();
537       if (numberOfBonds != atomType.valence) {
538         if (atom == C && numberOfBonds == atomType.valence - 1 && position != LAST_RESIDUE) {
539           continue;
540         }
541         logger.warning(
542             format(" An atom for residue %s has the wrong number of bonds:\n %s", residueName,
543                 atom));
544         logger.info(format(" Expected: %d Actual: %d.", atomType.valence, numberOfBonds));
545         for (Bond bond : atom.getBonds()) {
546           logger.info(" " + bond.toString());
547         }
548       }
549     }
550   }
551 
552   /**
553    * This interface is used by the "Build" routines.
554    */
555   public interface SideChainType {
556 
557     /**
558      * This is already implemented by all enum instances.
559      */
560     String name();
561 
562     /**
563      * Returns Biotype of this atom.
564      *
565      * @return The integer biotype.
566      */
567     int getType();
568 
569   }
570 
571   /** Constant <code>AIB</code> */
572   public enum AIB implements SideChainType {
573     CB1(0), CB2(0), HB11(1), HB12(1), HB13(1), HB21(1), HB22(1), HB23(1);
574 
575     /**
576      * Biotype for this atom.
577      */
578     private final int biotype;
579 
580     /**
581      * {@inheritDoc}
582      */
583     public int getType() {
584       return biotype;
585     }
586 
587     /**
588      * Init the Atom.
589      *
590      * @param offset Biotype offset relative to the CB biotype.
591      */
592     AIB(int offset) {
593       biotype = offset + AA_CB[AminoAcid3.AIB.ordinal()];
594     }
595   }
596 
597   /** Constant <code>ALA</code> */
598   public enum ALA implements SideChainType {
599     CB(0), HB1(1), HB2(1), HB3(1);
600 
601     /**
602      * Biotype for this atom.
603      */
604     private final int biotype;
605 
606     /**
607      * {@inheritDoc}
608      */
609     public int getType() {
610       return biotype;
611     }
612 
613     /**
614      * Init the Atom.
615      *
616      * @param offset Biotype offset relative to the CB biotype.
617      */
618     ALA(int offset) {
619       biotype = offset + AA_CB[AminoAcid3.ALA.ordinal()];
620     }
621   }
622 
623   /** Constant <code>ARG</code> */
624   public enum ARG implements SideChainType {
625     CB(0), HB2(1), HB3(1), CG(2), HG2(3), HG3(3), CD(4), HD2(5), HD3(5), NE(6), HE(7), CZ(8), NH1(
626         9), HH11(10), HH12(10), NH2(9), HH21(10), HH22(10);
627 
628     /**
629      * Biotype for this atom.
630      */
631     private final int biotype;
632 
633     /**
634      * {@inheritDoc}
635      */
636     public int getType() {
637       return biotype;
638     }
639 
640     /**
641      * Init the Atom.
642      *
643      * @param offset Biotype offset relative to the CB biotype.
644      */
645     ARG(int offset) {
646       biotype = offset + AA_CB[AminoAcid3.ARG.ordinal()];
647     }
648   }
649 
650   /** Constant <code>ASN</code> */
651   public enum ASN implements SideChainType {
652     CB(0), HB2(1), HB3(1), CG(2), OD1(3), ND2(4), HD21(5), HD22(5);
653 
654     /**
655      * Biotype for this atom.
656      */
657     private final int biotype;
658 
659     /**
660      * {@inheritDoc}
661      */
662     public int getType() {
663       return biotype;
664     }
665 
666     /**
667      * Init the Atom.
668      *
669      * @param offset Biotype offset relative to the CB biotype.
670      */
671     ASN(int offset) {
672       biotype = offset + AA_CB[AminoAcid3.ASN.ordinal()];
673     }
674   }
675 
676   /** Constant <code>ASP</code> */
677   public enum ASP implements SideChainType {
678     CB(0), HB2(1), HB3(1), CG(2), OD1(3), OD2(3);
679 
680     /**
681      * Biotype for this atom.
682      */
683     private final int biotype;
684 
685     /**
686      * {@inheritDoc}
687      */
688     public int getType() {
689       return biotype;
690     }
691 
692     /**
693      * Init the Atom.
694      *
695      * @param offset Biotype offset relative to the CB biotype.
696      */
697     ASP(int offset) {
698       biotype = offset + AA_CB[AminoAcid3.ASP.ordinal()];
699     }
700   }
701 
702   /** Constant <code>ASH</code> */
703   public enum ASH implements SideChainType {
704     CB(0), HB2(1), HB3(1), CG(2), OD1(3), OD2(4), HD2(5);
705 
706     /**
707      * Biotype for this atom.
708      */
709     private final int biotype;
710 
711     /**
712      * {@inheritDoc}
713      */
714     public int getType() {
715       return biotype;
716     }
717 
718     /**
719      * Init the Atom.
720      *
721      * @param offset Biotype offset relative to the CB biotype.
722      */
723     ASH(int offset) {
724       biotype = offset + AA_CB[AminoAcid3.ASH.ordinal()];
725     }
726   }
727 
728   /** Constant <code>ASD</code> */
729   public enum ASD implements SideChainType {
730     CB(0), HB2(1), HB3(1), CG(2), OD1(3), OD2(3), HD1(4), HD2(4);
731 
732     /**
733      * Biotype for this atom.
734      */
735     private final int biotype;
736 
737     /**
738      * {@inheritDoc}
739      */
740     public int getType() {
741       return biotype;
742     }
743 
744     /**
745      * Init the Atom.
746      *
747      * @param offset Biotype offset relative to the CB biotype.
748      */
749     ASD(int offset) {
750       biotype = offset + AA_CB[AminoAcid3.ASD.ordinal()];
751     }
752   }
753 
754   /** Constant <code>CYS</code> */
755   public enum CYS implements SideChainType {
756     CB(0), HB2(1), HB3(1), SG(2), HG(3);
757 
758     /**
759      * Biotype for this atom.
760      */
761     private final int biotype;
762 
763     /**
764      * {@inheritDoc}
765      */
766     public int getType() {
767       return biotype;
768     }
769 
770     /**
771      * Init the Atom.
772      *
773      * @param offset Biotype offset relative to the CB biotype.
774      */
775     CYS(int offset) {
776       biotype = offset + AA_CB[AminoAcid3.CYS.ordinal()];
777     }
778   }
779 
780   /** Constant <code>CYS</code> */
781   public enum CYX implements SideChainType {
782     CB(0), HB2(1), HB3(1), SG(2);
783 
784     /**
785      * Biotype for this atom.
786      */
787     private final int biotype;
788 
789     /**
790      * {@inheritDoc}
791      */
792     public int getType() {
793       return biotype;
794     }
795 
796     /**
797      * Init the Atom.
798      *
799      * @param offset Biotype offset relative to the CB biotype.
800      */
801     CYX(int offset) {
802       biotype = offset + AA_CB[AminoAcid3.CYX.ordinal()];
803     }
804   }
805 
806   /** Constant <code>CYD</code> */
807   public enum CYD implements SideChainType {
808     CB(0), HB2(1), HB3(1), SG(2);
809 
810     /**
811      * Biotype for this atom.
812      */
813     private final int biotype;
814 
815     /**
816      * {@inheritDoc}
817      */
818     public int getType() {
819       return biotype;
820     }
821 
822     /**
823      * Init the Atom.
824      *
825      * @param offset Biotype offset relative to the CB biotype.
826      */
827     CYD(int offset) {
828       biotype = offset + AA_CB[AminoAcid3.CYD.ordinal()];
829     }
830   }
831 
832   /** Constant <code>GLU</code> */
833   public enum GLU implements SideChainType {
834     CB(0), HB2(1), HB3(1), CG(2), HG2(3), HG3(3), CD(4), OE1(5), OE2(5);
835 
836     /**
837      * Biotype for this atom.
838      */
839     private final int biotype;
840 
841     /**
842      * {@inheritDoc}
843      */
844     public int getType() {
845       return biotype;
846     }
847 
848     /**
849      * Init the Atom.
850      *
851      * @param offset Biotype offset relative to the CB biotype.
852      */
853     GLU(int offset) {
854       biotype = offset + AA_CB[AminoAcid3.GLU.ordinal()];
855     }
856   }
857 
858   /** Constant <code>GLH</code> */
859   public enum GLH implements SideChainType {
860     CB(0), HB2(1), HB3(1), CG(2), HG2(3), HG3(3), CD(4), OE1(5), OE2(6), HE2(7);
861 
862     /**
863      * Biotype for this atom.
864      */
865     private final int biotype;
866 
867     /**
868      * {@inheritDoc}
869      */
870     public int getType() {
871       return biotype;
872     }
873 
874     /**
875      * Init the Atom.
876      *
877      * @param offset Biotype offset relative to the CB biotype.
878      */
879     GLH(int offset) {
880       biotype = offset + AA_CB[AminoAcid3.GLH.ordinal()];
881     }
882   }
883 
884   /** Constant <code>GLD</code> */
885   public enum GLD implements SideChainType {
886     CB(0), HB2(1), HB3(1), CG(2), HG2(3), HG3(3), CD(4), OE1(5), OE2(5), HE1(6), HE2(6);
887 
888     /**
889      * Biotype for this atom.
890      */
891     private final int biotype;
892 
893     /**
894      * {@inheritDoc}
895      */
896     public int getType() {
897       return biotype;
898     }
899 
900     /**
901      * Init the Atom.
902      *
903      * @param offset Biotype offset relative to the CB biotype.
904      */
905     GLD(int offset) {
906       biotype = offset + AA_CB[AminoAcid3.GLD.ordinal()];
907     }
908   }
909 
910   /** Constant <code>GlutamineAtomNames</code> */
911   public enum GLN implements SideChainType {
912     CB(0), HB2(1), HB3(1), CG(2), HG2(3), HG3(3), CD(4), OE1(5), NE2(6), HE21(7), HE22(7);
913 
914     /**
915      * Biotype for this atom.
916      */
917     private final int biotype;
918 
919     /**
920      * {@inheritDoc}
921      */
922     public int getType() {
923       return biotype;
924     }
925 
926     /**
927      * Init the Atom.
928      *
929      * @param offset Biotype offset relative to the CB biotype.
930      */
931     GLN(int offset) {
932       biotype = offset + AA_CB[AminoAcid3.GLN.ordinal()];
933     }
934   }
935 
936   /** Constant <code>GLY</code> */
937   public enum GLY {HA2}
938 
939   /** Constant <code>HistidineAtoms</code> */
940   public enum HIS implements SideChainType {
941     CB(0), HB2(1), HB3(1), CG(2), ND1(3), HD1(4), CD2(5), HD2(6), CE1(7), HE1(8), NE2(9), HE2(10);
942 
943     /**
944      * Biotype for this atom.
945      */
946     private final int biotype;
947 
948     /**
949      * {@inheritDoc}
950      */
951     public int getType() {
952       return biotype;
953     }
954 
955     /**
956      * Init the Atom.
957      *
958      * @param offset Biotype offset relative to the CB biotype.
959      */
960     HIS(int offset) {
961       biotype = offset + AA_CB[AminoAcid3.HIS.ordinal()];
962     }
963   }
964 
965   /** Constant <code>HID</code> */
966   public enum HID implements SideChainType {
967     CB(0), HB2(1), HB3(1), CG(2), ND1(3), HD1(4), CD2(5), HD2(6), CE1(7), HE1(8), NE2(9);
968 
969     /**
970      * Biotype for this atom.
971      */
972     private final int biotype;
973 
974     /**
975      * {@inheritDoc}
976      */
977     public int getType() {
978       return biotype;
979     }
980 
981     /**
982      * Init the Atom.
983      *
984      * @param offset Biotype offset relative to the CB biotype.
985      */
986     HID(int offset) {
987       biotype = offset + AA_CB[AminoAcid3.HID.ordinal()];
988     }
989   }
990 
991   /** Constant <code>HIE</code> */
992   public enum HIE implements SideChainType {
993     CB(0), HB2(1), HB3(1), CG(2), ND1(3), CD2(4), HD2(5), CE1(6), HE1(7), NE2(8), HE2(9);
994 
995     /**
996      * Biotype for this atom.
997      */
998     private final int biotype;
999 
1000     /**
1001      * {@inheritDoc}
1002      */
1003     public int getType() {
1004       return biotype;
1005     }
1006 
1007     /**
1008      * Init the Atom.
1009      *
1010      * @param offset Biotype offset relative to the CB biotype.
1011      */
1012     HIE(int offset) {
1013       biotype = offset + AA_CB[AminoAcid3.HIE.ordinal()];
1014     }
1015   }
1016 
1017   /** Constant <code>ILE</code> */
1018   public enum ILE implements SideChainType {
1019     CB(0), HB(1), CG1(2), HG12(3), HG13(3), CG2(4), HG21(5), HG22(5), HG23(5), CD1(6), HD11(7), HD12(
1020         7), HD13(7);
1021 
1022     /**
1023      * Biotype for this atom.
1024      */
1025     private final int biotype;
1026 
1027     /**
1028      * {@inheritDoc}
1029      */
1030     public int getType() {
1031       return biotype;
1032     }
1033 
1034     /**
1035      * Init the Atom.
1036      *
1037      * @param offset Biotype offset relative to the CB biotype.
1038      */
1039     ILE(int offset) {
1040       biotype = offset + AA_CB[AminoAcid3.ILE.ordinal()];
1041     }
1042   }
1043 
1044   /** Constant <code>LEU</code> */
1045   public enum LEU implements SideChainType {
1046     CB(0), HB2(1), HB3(1), CG(2), HG(3), CD1(4), HD11(5), HD12(5), HD13(5), CD2(6), HD21(7), HD22(
1047         7), HD23(7);
1048 
1049     /**
1050      * Biotype for this atom.
1051      */
1052     private final int biotype;
1053 
1054     /**
1055      * {@inheritDoc}
1056      */
1057     public int getType() {
1058       return biotype;
1059     }
1060 
1061     /**
1062      * Init the Atom.
1063      *
1064      * @param offset Biotype offset relative to the CB biotype.
1065      */
1066     LEU(int offset) {
1067       biotype = offset + AA_CB[AminoAcid3.LEU.ordinal()];
1068     }
1069   }
1070 
1071   /** Constant <code>LYS</code> */
1072   public enum LYS implements SideChainType {
1073     CB(0), HB2(1), HB3(1), CG(2), HG2(3), HG3(3), CD(4), HD2(5), HD3(5), CE(6), HE2(7), HE3(7), NZ(
1074         8), HZ1(9), HZ2(9), HZ3(9);
1075 
1076     /**
1077      * Biotype for this atom.
1078      */
1079     private final int biotype;
1080 
1081     /**
1082      * {@inheritDoc}
1083      */
1084     public int getType() {
1085       return biotype;
1086     }
1087 
1088     /**
1089      * Init the Atom.
1090      *
1091      * @param offset Biotype offset relative to the CB biotype.
1092      */
1093     LYS(int offset) {
1094       biotype = offset + AA_CB[AminoAcid3.LYS.ordinal()];
1095     }
1096   }
1097 
1098   /** Constant <code>LYD</code> */
1099   public enum LYD implements SideChainType {
1100     CB(0), HB2(1), HB3(1), CG(2), HG2(3), HG3(3), CD(4), HD2(5), HD3(5), CE(6), HE2(7), HE3(7), NZ(
1101         8), HZ1(9), HZ2(9);
1102 
1103     /**
1104      * Biotype for this atom.
1105      */
1106     private final int biotype;
1107 
1108     /**
1109      * {@inheritDoc}
1110      */
1111     public int getType() {
1112       return biotype;
1113     }
1114 
1115     /**
1116      * Init the Atom.
1117      *
1118      * @param offset Biotype offset relative to the CB biotype.
1119      */
1120     LYD(int offset) {
1121       biotype = offset + AA_CB[AminoAcid3.LYD.ordinal()];
1122     }
1123   }
1124 
1125   /** Constant <code>MethionineAtomNames</code> */
1126   public enum MET implements SideChainType {
1127     CB(0), HB2(1), HB3(1), CG(2), HG2(3), HG3(3), SD(4), CE(5), HE1(6), HE2(6), HE3(6);
1128 
1129     /**
1130      * Biotype for this atom.
1131      */
1132     private final int biotype;
1133 
1134     /**
1135      * {@inheritDoc}
1136      */
1137     public int getType() {
1138       return biotype;
1139     }
1140 
1141     /**
1142      * Init the Atom.
1143      *
1144      * @param offset Biotype offset relative to the CB biotype.
1145      */
1146     MET(int offset) {
1147       biotype = offset + AA_CB[AminoAcid3.MET.ordinal()];
1148     }
1149   }
1150 
1151   /** Constant <code>ORN</code> */
1152   public enum ORN implements SideChainType {
1153     CB(0), HB2(1), HB3(2), CG(2), HG2(3), HG3(3), CD(4), HD2(5), HD3(5), NE(6), HE1(7), HE2(7), HE3(
1154         7);
1155 
1156     /**
1157      * Biotype for this atom.
1158      */
1159     private final int biotype;
1160 
1161     /**
1162      * {@inheritDoc}
1163      */
1164     public int getType() {
1165       return biotype;
1166     }
1167 
1168     /**
1169      * Init the Atom.
1170      *
1171      * @param offset Biotype offset relative to the CB biotype.
1172      */
1173     ORN(int offset) {
1174       biotype = offset + AA_CB[AminoAcid3.ORN.ordinal()];
1175     }
1176   }
1177 
1178   /** Constant <code>PCA</code> */
1179   public enum PCA implements SideChainType {
1180     CB(0), HB2(1), HB3(2), CG(2), HG2(3), HG3(3), CD(4), OE(5);
1181 
1182     /**
1183      * Biotype for this atom.
1184      */
1185     private final int biotype;
1186 
1187     /**
1188      * {@inheritDoc}
1189      */
1190     public int getType() {
1191       return biotype;
1192     }
1193 
1194     /**
1195      * Init the Atom.
1196      *
1197      * @param offset Biotype offset relative to the CB biotype.
1198      */
1199     PCA(int offset) {
1200       biotype = offset + AA_CB[AminoAcid3.PCA.ordinal()];
1201     }
1202   }
1203 
1204   /** Constant <code>PHE</code> */
1205   public enum PHE implements SideChainType {
1206     CB(0), HB2(1), HB3(1), CG(2), CD1(3), HD1(4), CD2(3), HD2(4), CE1(5), HE1(6), CE2(5), HE2(6), CZ(
1207         7), HZ(8);
1208 
1209     /**
1210      * Biotype for this atom.
1211      */
1212     private final int biotype;
1213 
1214     /**
1215      * {@inheritDoc}
1216      */
1217     public int getType() {
1218       return biotype;
1219     }
1220 
1221     /**
1222      * Init the Atom.
1223      *
1224      * @param offset Biotype offset relative to the CB biotype.
1225      */
1226     PHE(int offset) {
1227       biotype = offset + AA_CB[AminoAcid3.PHE.ordinal()];
1228     }
1229   }
1230 
1231   /** Constant <code>PRO</code> */
1232   public enum PRO implements SideChainType {
1233     CB(0), HB2(1), HB3(1), CG(2), HG2(3), HG3(3), CD(4), HD2(5), HD3(5);
1234 
1235     /**
1236      * Biotype for this atom.
1237      */
1238     private final int biotype;
1239 
1240     /**
1241      * {@inheritDoc}
1242      */
1243     public int getType() {
1244       return biotype;
1245     }
1246 
1247     /**
1248      * Init the Atom.
1249      *
1250      * @param offset Biotype offset relative to the CB biotype.
1251      */
1252     PRO(int offset) {
1253       biotype = offset + AA_CB[AminoAcid3.PRO.ordinal()];
1254     }
1255   }
1256 
1257   /** Constant <code>SER</code> */
1258   public enum SER implements SideChainType {
1259     CB(0), HB2(1), HB3(1), OG(2), HG(3);
1260 
1261     /**
1262      * Biotype for this atom.
1263      */
1264     private final int biotype;
1265 
1266     /**
1267      * {@inheritDoc}
1268      */
1269     public int getType() {
1270       return biotype;
1271     }
1272 
1273     /**
1274      * Init the Atom.
1275      *
1276      * @param offset Biotype offset relative to the CB biotype.
1277      */
1278     SER(int offset) {
1279       biotype = offset + AA_CB[AminoAcid3.SER.ordinal()];
1280     }
1281   }
1282 
1283   /** Constant <code>THR</code> */
1284   public enum THR implements SideChainType {
1285     CB(0), HB(1), OG1(2), HG1(3), CG2(4), HG21(5), HG22(5), HG23(5);
1286 
1287     /**
1288      * Biotype for this atom.
1289      */
1290     private final int biotype;
1291 
1292     /**
1293      * {@inheritDoc}
1294      */
1295     public int getType() {
1296       return biotype;
1297     }
1298 
1299     /**
1300      * Init the Atom.
1301      *
1302      * @param offset Biotype offset relative to the CB biotype.
1303      */
1304     THR(int offset) {
1305       biotype = offset + AA_CB[AminoAcid3.THR.ordinal()];
1306     }
1307   }
1308 
1309   /** Constant <code>TRP</code> */
1310   public enum TRP implements SideChainType {
1311     CB(0), HB2(1), HB3(1), CG(2), CD1(3), HD1(4), CD2(5), NE1(6), HE1(7), CE2(8), CE3(9), HE3(
1312         10), CZ2(11), HZ2(12), CZ3(13), HZ3(14), CH2(15), HH2(16);
1313 
1314     /**
1315      * Biotype for this atom.
1316      */
1317     private final int biotype;
1318 
1319     /**
1320      * {@inheritDoc}
1321      */
1322     public int getType() {
1323       return biotype;
1324     }
1325 
1326     /**
1327      * Init the Atom.
1328      *
1329      * @param offset Biotype offset relative to the CB biotype.
1330      */
1331     TRP(int offset) {
1332       biotype = offset + AA_CB[AminoAcid3.TRP.ordinal()];
1333     }
1334   }
1335 
1336   /** Constant <code>TYR</code> */
1337   public enum TYR implements SideChainType {
1338     CB(0), HB2(1), HB3(1), CG(2), CD1(3), HD1(4), CD2(3), HD2(4), CE1(5), HE1(6), CE2(5), HE2(6), CZ(
1339         7), OH(8), HH(9);
1340 
1341     /**
1342      * Biotype for this atom.
1343      */
1344     private final int biotype;
1345 
1346     /**
1347      * {@inheritDoc}
1348      */
1349     public int getType() {
1350       return biotype;
1351     }
1352 
1353     /**
1354      * Init the Atom.
1355      *
1356      * @param offset Biotype offset relative to the CB biotype.
1357      */
1358     TYR(int offset) {
1359       biotype = offset + AA_CB[AminoAcid3.TYR.ordinal()];
1360     }
1361   }
1362 
1363   /** Constant <code>TYD</code> */
1364   public enum TYD implements SideChainType {
1365     CB(0), HB2(1), HB3(1), CG(2), CD1(3), HD1(4), CD2(3), HD2(4), CE1(5), HE1(6), CE2(5), HE2(6), CZ(
1366         7), OH(8);
1367 
1368     /**
1369      * Biotype for this atom.
1370      */
1371     private final int biotype;
1372 
1373     /**
1374      * {@inheritDoc}
1375      */
1376     public int getType() {
1377       return biotype;
1378     }
1379 
1380     /**
1381      * Init the Atom.
1382      *
1383      * @param offset Biotype offset relative to the CB biotype.
1384      */
1385     TYD(int offset) {
1386       biotype = offset + AA_CB[AminoAcid3.TYD.ordinal()];
1387     }
1388   }
1389 
1390   /** Constant <code>VAL</code> */
1391   public enum VAL implements SideChainType {
1392     CB(0), HB(1), CG1(2), HG11(3), HG12(3), HG13(3), CG2(4), HG21(5), HG22(5), HG23(5);
1393 
1394     /**
1395      * Biotype for this atom.
1396      */
1397     private final int biotype;
1398 
1399     /**
1400      * {@inheritDoc}
1401      */
1402     public int getType() {
1403       return biotype;
1404     }
1405 
1406     /**
1407      * Init the Atom.
1408      *
1409      * @param offset Biotype offset relative to the CB biotype.
1410      */
1411     VAL(int offset) {
1412       biotype = offset + AA_CB[AminoAcid3.VAL.ordinal()];
1413     }
1414   }
1415 
1416   /**
1417    * buildAIB.
1418    *
1419    * @param res a {@link Residue} object.
1420    * @param CA a {@link Atom} object.
1421    * @param N a {@link Atom} object.
1422    * @param C a {@link Atom} object.
1423    * @param ff a {@link ForceField} object.
1424    * @param bonds a {@link List} object.
1425    * @return a {@link ffx.potential.bonded.Residue} object.
1426    */
1427   public static Residue buildAIB(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1428       List<Bond> bonds) {
1429     Atom CB1 = buildHeavy(res, AIB.CB1, CA, 1.54, N, 109.5, C, 107.8, -1, ff, bonds);
1430     Atom CB2 = buildHeavy(res, AIB.CB2, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1431     Atom HB11 = buildH(res, AIB.HB11, CB1, 1.11, CA, 109.4, N, 180.0, 0, ff, bonds);
1432     buildH(res, AIB.HB12, CB1, 1.11, CA, 109.4, HB11, 109.4, 1, ff, bonds);
1433     buildH(res, AIB.HB13, CB1, 1.11, CA, 109.4, HB11, 109.4, -1, ff, bonds);
1434     Atom HB21 = buildH(res, AIB.HB21, CB2, 1.11, CA, 109.4, N, 180.0, 0, ff, bonds);
1435     buildH(res, AIB.HB22, CB2, 1.11, CA, 109.4, HB21, 109.4, 1, ff, bonds);
1436     buildH(res, AIB.HB23, CB2, 1.11, CA, 109.4, HB21, 109.4, -1, ff, bonds);
1437     return res;
1438   }
1439 
1440   /**
1441    * buildGlycine.
1442    *
1443    * @param res a {@link ffx.potential.bonded.Residue} object.
1444    * @param CA a {@link ffx.potential.bonded.Atom} object.
1445    * @param N a {@link ffx.potential.bonded.Atom} object.
1446    * @param C a {@link ffx.potential.bonded.Atom} object.
1447    * @param position {@link ffx.potential.bonded.AminoAcidUtils.ResiduePosition} object.
1448    * @param ff a {@link ForceField} object.
1449    * @param bonds a {@link java.util.List} object.
1450    * @return a {@link ffx.potential.bonded.Residue} object.
1451    */
1452   public static Residue buildGlycine(Residue res, Atom CA, Atom N, Atom C, ResiduePosition position,
1453       ForceField ff, List<Bond> bonds) {
1454     int iCB = AA_CB[AminoAcid3.GLY.ordinal()];
1455     int k = switch (position) {
1456       case FIRST_RESIDUE -> AA_HA[0][iCB];
1457       case LAST_RESIDUE -> AA_HA[2][iCB];
1458       default -> AA_HA[1][iCB];
1459     };
1460     buildH(res, "HA3", CA, 1.10, N, 109.5, C, 109.5, 1, k, ff, bonds);
1461     return res;
1462   }
1463 
1464   /**
1465    * buildAlanine.
1466    *
1467    * @param res a {@link ffx.potential.bonded.Residue} object.
1468    * @param CA a {@link ffx.potential.bonded.Atom} object.
1469    * @param N a {@link ffx.potential.bonded.Atom} object.
1470    * @param C a {@link ffx.potential.bonded.Atom} object.
1471    * @param ff a {@link ForceField} object.
1472    * @param bonds a {@link java.util.List} object.
1473    * @return a {@link ffx.potential.bonded.Residue} object.
1474    */
1475   public static Residue buildAlanine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1476       List<Bond> bonds) {
1477     Atom CB = buildHeavy(res, ALA.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1478     Atom HB1 = buildH(res, ALA.HB1, CB, 1.11, CA, 109.4, N, 180.0, 0, ff, bonds);
1479     buildH(res, ALA.HB2, CB, 1.11, CA, 109.4, HB1, 109.4, 1, ff, bonds);
1480     buildH(res, ALA.HB3, CB, 1.11, CA, 109.4, HB1, 109.4, -1, ff, bonds);
1481     return res;
1482   }
1483 
1484   /**
1485    * buildArginine.
1486    *
1487    * @param res a {@link Residue} object.
1488    * @param CA a {@link Atom} object.
1489    * @param N a {@link Atom} object.
1490    * @param C a {@link Atom} object.
1491    * @param ff a {@link ForceField} object.
1492    * @param bonds a {@link List} object.
1493    * @return a {@link ffx.potential.bonded.Residue} object.
1494    */
1495   public static Residue buildArginine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1496       List<Bond> bonds) {
1497     Atom CB = buildHeavy(res, ARG.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1498     Atom CG = buildHeavy(res, ARG.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
1499     Atom CD = buildHeavy(res, ARG.CD, CG, 1.54, CB, 109.5, CA, 180, 0, ff, bonds);
1500     Atom NE = buildHeavy(res, ARG.NE, CD, 1.45, CG, 109.5, CB, 180, 0, ff, bonds);
1501     Atom CZ = buildHeavy(res, ARG.CZ, NE, 1.35, CD, 120.0, CG, 180, 0, ff, bonds);
1502     Atom NH1 = buildHeavy(res, ARG.NH1, CZ, 1.35, NE, 120.0, CD, 180, 0, ff, bonds);
1503     Atom NH2 = buildHeavy(res, ARG.NH2, CZ, 1.35, NE, 120.0, NH1, 120.0, 1, ff, bonds);
1504     buildH(res, ARG.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1505     buildH(res, ARG.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1506     buildH(res, ARG.HG2, CG, 1.11, CB, 109.4, CD, 109.4, 1, ff, bonds);
1507     buildH(res, ARG.HG3, CG, 1.11, CB, 109.4, CD, 109.4, -1, ff, bonds);
1508     buildH(res, ARG.HD2, CD, 1.11, CG, 109.4, NE, 109.4, 1, ff, bonds);
1509     buildH(res, ARG.HD3, CD, 1.11, CG, 109.4, NE, 109.4, -1, ff, bonds);
1510     buildH(res, ARG.HE, NE, 1.02, CD, 120.0, CZ, 120.0, 1, ff, bonds);
1511     Atom HH11 = buildH(res, ARG.HH11, NH1, 1.02, CZ, 120.0, NE, 180.0, 0, ff, bonds);
1512     buildH(res, ARG.HH12, NH1, 1.02, CZ, 120.0, HH11, 120.0, 1, ff, bonds);
1513     Atom HH21 = buildH(res, ARG.HH21, NH2, 1.02, CZ, 120.0, NE, 180.0, 0, ff, bonds);
1514     buildH(res, ARG.HH22, NH2, 1.02, CZ, 120.0, HH21, 120.0, 1, ff, bonds);
1515     return res;
1516   }
1517 
1518   /**
1519    * buildAsparagine.
1520    *
1521    * @param res a {@link Residue} object.
1522    * @param CA a {@link Atom} object.
1523    * @param N a {@link Atom} object.
1524    * @param C a {@link Atom} object.
1525    * @param ff a {@link ForceField} object.
1526    * @param bonds a {@link List} object.
1527    * @return a {@link ffx.potential.bonded.Residue} object.
1528    */
1529   public static Residue buildAsparagine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1530       List<Bond> bonds) {
1531     Atom CB = buildHeavy(res, ASN.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1532     Atom CG = buildHeavy(res, ASN.CG, CB, 1.51, CA, 107.8, N, 180, 0, ff, bonds);
1533     Atom OD1 = buildHeavy(res, ASN.OD1, CG, 1.22, CB, 122.5, CA, 180, 0, ff, bonds);
1534     Atom ND2 = buildHeavy(res, ASN.ND2, CG, 1.34, CB, 112.7, OD1, 124.0, 1, ff, bonds);
1535     buildH(res, ASN.HB2, CB, 1.11, CA, 109.4, CG, 107.9, 1, ff, bonds);
1536     buildH(res, ASN.HB3, CB, 1.11, CA, 109.4, CG, 107.9, -1, ff, bonds);
1537     Atom HD21 = buildH(res, ASN.HD21, ND2, 1.02, CG, 119.0, CB, 0.0, 0, ff, bonds);
1538     buildH(res, ASN.HD22, ND2, 1.02, CG, 119.0, HD21, 120.0, 1, ff, bonds);
1539     return res;
1540   }
1541 
1542   /**
1543    * buildAspartate.
1544    *
1545    * @param res a {@link Residue} object.
1546    * @param CA a {@link Atom} object.
1547    * @param N a {@link Atom} object.
1548    * @param C a {@link Atom} object.
1549    * @param ff a {@link ForceField} object.
1550    * @param bonds a {@link List} object.
1551    * @return a {@link ffx.potential.bonded.Residue} object.
1552    */
1553   public static Residue buildAspartate(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1554       List<Bond> bonds) {
1555     Atom CB = buildHeavy(res, ASP.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1556     Atom CG = buildHeavy(res, ASP.CG, CB, 1.51, CA, 107.8, N, 180, 0, ff, bonds);
1557     Atom OD1 = buildHeavy(res, ASP.OD1, CG, 1.25, CB, 117.0, CA, 0.0, 0, ff, bonds);
1558     buildHeavy(res, ASP.OD2, CG, 1.25, CB, 117.0, OD1, 126.0, 1, ff, bonds);
1559     buildH(res, ASP.HB2, CB, 1.11, CA, 109.4, CG, 107.9, 1, ff, bonds);
1560     buildH(res, ASP.HB3, CB, 1.11, CA, 109.4, CG, 107.9, -1, ff, bonds);
1561     return res;
1562   }
1563 
1564   /**
1565    * buildCysteine.
1566    *
1567    * @param res a {@link Residue} object.
1568    * @param CA a {@link Atom} object.
1569    * @param N a {@link Atom} object.
1570    * @param C a {@link Atom} object.
1571    * @param ff a {@link ForceField} object.
1572    * @param bonds a {@link List} object.
1573    * @return a {@link ffx.potential.bonded.Residue} object.
1574    */
1575   public static Residue buildCysteine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1576       List<Bond> bonds) {
1577     Atom CB = buildHeavy(res, CYS.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1578     Atom SG = buildHeavy(res, CYS.SG, CB, 1.82, CA, 109.0, N, 180, 0, ff, bonds);
1579     buildH(res, CYS.HB2, CB, 1.11, CA, 109.4, SG, 112.0, 1, ff, bonds);
1580     buildH(res, CYS.HB3, CB, 1.11, CA, 109.4, SG, 112.0, -1, ff, bonds);
1581     buildH(res, CYS.HG, SG, 1.34, CB, 96.0, CA, 180.0, 0, ff, bonds);
1582     return res;
1583   }
1584 
1585   /**
1586    * buildCystine.
1587    *
1588    * @param res a {@link Residue} object.
1589    * @param CA a {@link Atom} object.
1590    * @param N a {@link Atom} object.
1591    * @param C a {@link Atom} object.
1592    * @param ff a {@link ForceField} object.
1593    * @param bonds a {@link List} object.
1594    * @return a {@link ffx.potential.bonded.Residue} object.
1595    */
1596   public static Residue buildCystine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1597       List<Bond> bonds) {
1598     Atom CB = buildHeavy(res, CYX.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1599     Atom SG = buildHeavy(res, CYX.SG, CB, 1.82, CA, 109.0, N, 180, 0, ff, bonds);
1600     buildH(res, CYX.HB2, CB, 1.11, CA, 109.4, SG, 112.0, 1, ff, bonds);
1601     buildH(res, CYX.HB3, CB, 1.11, CA, 109.4, SG, 112.0, -1, ff, bonds);
1602     List<Atom> resAtoms = res.getAtomList();
1603     for (Atom atom : resAtoms) {
1604       atom.setResName("CYS");
1605     }
1606     res.setName("CYS");
1607     return res;
1608   }
1609 
1610   /**
1611    * buildDeprotonatedCysteine.
1612    *
1613    * @param res a {@link Residue} object.
1614    * @param CA a {@link Atom} object.
1615    * @param N a {@link Atom} object.
1616    * @param C a {@link Atom} object.
1617    * @param ff a {@link ForceField} object.
1618    * @param bonds a {@link List} object.
1619    * @return a {@link ffx.potential.bonded.Residue} object.
1620    */
1621   public static Residue buildDeprotonatedCysteine(Residue res, Atom CA, Atom N, Atom C,
1622       ForceField ff, List<Bond> bonds) {
1623     Atom CB = buildHeavy(res, CYD.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1624     Atom SG = buildHeavy(res, CYD.SG, CB, 1.82, CA, 109.0, N, 180, 0, ff, bonds);
1625     buildH(res, CYD.HB2, CB, 1.11, CA, 109.4, SG, 112.0, 1, ff, bonds);
1626     buildH(res, CYD.HB3, CB, 1.11, CA, 109.4, SG, 112.0, -1, ff, bonds);
1627     return res;
1628   }
1629 
1630   /**
1631    * buildDeprotonatedLysine.
1632    *
1633    * @param res a {@link Residue} object.
1634    * @param CA a {@link Atom} object.
1635    * @param N a {@link Atom} object.
1636    * @param C a {@link Atom} object.
1637    * @param ff a {@link ForceField} object.
1638    * @param bonds a {@link List} object.
1639    * @return a {@link ffx.potential.bonded.Residue} object.
1640    */
1641   public static Residue buildDeprotonatedLysine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1642       List<Bond> bonds) {
1643     Atom CB = buildHeavy(res, LYD.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1644     Atom CG = buildHeavy(res, LYD.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
1645     Atom CD = buildHeavy(res, LYD.CD, CG, 1.54, CB, 109.5, CA, 180, 0, ff, bonds);
1646     Atom CE = buildHeavy(res, LYD.CE, CD, 1.54, CG, 109.5, CB, 180, 0, ff, bonds);
1647     Atom NZ = buildHeavy(res, LYD.NZ, CE, 1.50, CD, 109.5, CG, 180, 0, ff, bonds);
1648     buildH(res, LYD.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1649     buildH(res, LYD.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1650     buildH(res, LYD.HG2, CG, 1.11, CB, 109.4, CD, 109.4, 1, ff, bonds);
1651     buildH(res, LYD.HG3, CG, 1.11, CB, 109.4, CD, 109.4, -1, ff, bonds);
1652     buildH(res, LYD.HD2, CD, 1.11, CG, 109.4, CE, 109.4, 1, ff, bonds);
1653     buildH(res, LYD.HD3, CD, 1.11, CG, 109.4, CE, 109.4, -1, ff, bonds);
1654     buildH(res, LYD.HE2, CE, 1.11, CD, 109.4, NZ, 108.8, 1, ff, bonds);
1655     buildH(res, LYD.HE3, CE, 1.11, CD, 109.4, NZ, 108.8, -1, ff, bonds);
1656     Atom HZ1 = buildH(res, LYD.HZ1, NZ, 1.02, CE, 109.5, CD, 180.0, 0, ff, bonds);
1657     buildH(res, LYD.HZ2, NZ, 1.02, CE, 109.5, HZ1, 109.5, 1, ff, bonds);
1658     return res;
1659   }
1660 
1661   /**
1662    * buildDeprotonatedTyrosine.
1663    *
1664    * @param res a {@link Residue} object.
1665    * @param CA a {@link Atom} object.
1666    * @param N a {@link Atom} object.
1667    * @param C a {@link Atom} object.
1668    * @param ff a {@link ForceField} object.
1669    * @param bonds a {@link List} object.
1670    * @return a {@link ffx.potential.bonded.Residue} object.
1671    */
1672   public static Residue buildDeprotonatedTyrosine(Residue res, Atom CA, Atom N, Atom C,
1673       ForceField ff, List<Bond> bonds) {
1674     Atom CB = buildHeavy(res, TYD.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1675     Atom CG = buildHeavy(res, TYD.CG, CB, 1.50, CA, 109.5, N, 62, 0, ff, bonds);
1676     Atom CD1 = buildHeavy(res, TYD.CD1, CG, 1.39, CB, 120.0, CA, 90, 0, ff, bonds);
1677     Atom CD2 = buildHeavy(res, TYD.CD2, CG, 1.39, CB, 120.0, CD1, 120.0, 1, ff, bonds);
1678     Atom CE1 = buildHeavy(res, TYD.CE1, CD1, 1.39, CG, 120.0, CB, 180, 0, ff, bonds);
1679     Atom CE2 = buildHeavy(res, TYD.CE2, CD2, 1.39, CG, 120.0, CB, 180, 0, ff, bonds);
1680     Atom CZ = buildHeavy(res, TYD.CZ, CE1, 1.39, CD1, 120.0, CG, 0.0, 0, ff, bonds);
1681     buildBond(CE2, CZ, ff, bonds);
1682     buildHeavy(res, TYD.OH, CZ, 1.36, CE2, 120.0, CE1, 120.0, 1, ff, bonds);
1683     buildH(res, TYD.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1684     buildH(res, TYD.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1685     buildH(res, TYD.HD1, CD1, 1.10, CG, 120.0, CE1, 120.0, 1, ff, bonds);
1686     buildH(res, TYD.HD2, CD2, 1.10, CG, 120.0, CE2, 120.0, 1, ff, bonds);
1687     buildH(res, TYD.HE1, CE1, 1.10, CD1, 120.0, CZ, 120.0, 1, ff, bonds);
1688     buildH(res, TYD.HE2, CE2, 1.10, CD2, 120.0, CZ, 120.0, 1, ff, bonds);
1689     return res;
1690   }
1691 
1692   /**
1693    * buildGlutamate.
1694    *
1695    * @param res a {@link Residue} object.
1696    * @param CA a {@link Atom} object.
1697    * @param N a {@link Atom} object.
1698    * @param C a {@link Atom} object.
1699    * @param ff a {@link ForceField} object.
1700    * @param bonds a {@link List} object.
1701    * @return a {@link ffx.potential.bonded.Residue} object.
1702    */
1703   public static Residue buildGlutamate(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1704       List<Bond> bonds) {
1705     Atom CB = buildHeavy(res, GLU.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1706     Atom CG = buildHeavy(res, GLU.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
1707     Atom CD = buildHeavy(res, GLU.CD, CG, 1.51, CB, 107.8, CA, 180, 0, ff, bonds);
1708     Atom OE1 = buildHeavy(res, GLU.OE1, CD, 1.25, CG, 117.0, CB, 180, 0, ff, bonds);
1709     buildHeavy(res, GLU.OE2, CD, 1.25, CG, 117.0, OE1, 126.0, 1, ff, bonds);
1710     buildH(res, GLU.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1711     buildH(res, GLU.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1712     buildH(res, GLU.HG2, CG, 1.11, CB, 109.4, CD, 107.9, 1, ff, bonds);
1713     buildH(res, GLU.HG3, CG, 1.11, CB, 109.4, CD, 107.9, -1, ff, bonds);
1714     return res;
1715   }
1716 
1717   /**
1718    * buildGlutamine.
1719    *
1720    * @param res a {@link Residue} object.
1721    * @param CA a {@link Atom} object.
1722    * @param N a {@link Atom} object.
1723    * @param C a {@link Atom} object.
1724    * @param ff a {@link ForceField} object.
1725    * @param bonds a {@link List} object.
1726    * @return a {@link ffx.potential.bonded.Residue} object.
1727    */
1728   public static Residue buildGlutamine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1729       List<Bond> bonds) {
1730     Atom CB = buildHeavy(res, GLN.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1731     Atom CG = buildHeavy(res, GLN.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
1732     Atom CD = buildHeavy(res, GLN.CD, CG, 1.51, CB, 107.8, CA, 180, 0, ff, bonds);
1733     Atom OE1 = buildHeavy(res, GLN.OE1, CD, 1.22, CG, 122.5, CB, 180, 0, ff, bonds);
1734     Atom NE2 = buildHeavy(res, GLN.NE2, CD, 1.34, CG, 112.7, OE1, 124.0, 1, ff, bonds);
1735     buildH(res, GLN.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1736     buildH(res, GLN.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1737     buildH(res, GLN.HG2, CG, 1.11, CB, 109.4, CD, 107.9, 1, ff, bonds);
1738     buildH(res, GLN.HG3, CG, 1.11, CB, 109.4, CD, 107.9, -1, ff, bonds);
1739     Atom HE21 = buildH(res, GLN.HE21, NE2, 1.02, CD, 119.0, CG, 0.0, 0, ff, bonds);
1740     buildH(res, GLN.HE22, NE2, 1.02, CD, 119.0, HE21, 120.0, 1, ff, bonds);
1741     return res;
1742   }
1743 
1744   /**
1745    * buildHistidine.
1746    *
1747    * @param res a {@link Residue} object.
1748    * @param CA a {@link Atom} object.
1749    * @param N a {@link Atom} object.
1750    * @param C a {@link Atom} object.
1751    * @param ff a {@link ForceField} object.
1752    * @param bonds a {@link List} object.
1753    * @return a {@link ffx.potential.bonded.Residue} object.
1754    */
1755   public static Residue buildHistidine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1756       List<Bond> bonds) {
1757     Atom CB = buildHeavy(res, HIS.CB, CA, 1.54, N, 109.5, C, 109.5, 1, ff, bonds);
1758     Atom CG = buildHeavy(res, HIS.CG, CB, 1.50, CA, 109.5, N, 180, 0, ff, bonds);
1759     Atom ND1 = buildHeavy(res, HIS.ND1, CG, 1.35, CB, 126.0, CA, 180, 0, ff, bonds);
1760     Atom CD2 = buildHeavy(res, HIS.CD2, CG, 1.35, CB, 126.0, ND1, 108.0, 1, ff, bonds);
1761     Atom CE1 = buildHeavy(res, HIS.CE1, ND1, 1.35, CG, 108.0, CD2, 0.0, 0, ff, bonds);
1762     Atom NE2 = buildHeavy(res, HIS.NE2, CD2, 1.35, CG, 108.0, ND1, 0.0, 0, ff, bonds);
1763     buildBond(NE2, CE1, ff, bonds);
1764     buildH(res, HIS.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1765     buildH(res, HIS.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1766     buildH(res, HIS.HD1, ND1, 1.02, CG, 126.0, CB, 0.0, 0, ff, bonds);
1767     buildH(res, HIS.HD2, CD2, 1.10, CG, 126.0, NE2, 126.0, 1, ff, bonds);
1768     buildH(res, HIS.HE1, CE1, 1.10, ND1, 126.0, NE2, 126.0, 1, ff, bonds);
1769     buildH(res, HIS.HE2, NE2, 1.02, CD2, 126.0, CE1, 126.0, 1, ff, bonds);
1770     return res;
1771   }
1772 
1773   /**
1774    * buildIsoleucine.
1775    *
1776    * @param res a {@link Residue} object.
1777    * @param CA a {@link Atom} object.
1778    * @param N a {@link Atom} object.
1779    * @param C a {@link Atom} object.
1780    * @param ff a {@link ForceField} object.
1781    * @param bonds a {@link List} object.
1782    * @return a {@link ffx.potential.bonded.Residue} object.
1783    */
1784   public static Residue buildIsoleucine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1785       List<Bond> bonds) {
1786     Atom CB = buildHeavy(res, ILE.CB, CA, 1.54, N, 109.5, C, 109.5, 1, ff, bonds);
1787     Atom CG1 = buildHeavy(res, ILE.CG1, CB, 1.54, CA, 109.5, N, 0, 0, ff, bonds);
1788     Atom CG2 = buildHeavy(res, ILE.CG2, CB, 1.54, CA, 109.5, CG1, 109.5, 1, ff, bonds);
1789     Atom CD1 = buildHeavy(res, ILE.CD1, CG1, 1.54, CB, 109.5, CA, 180, 0, ff, bonds);
1790     buildH(res, ILE.HB, CB, 1.11, CA, 109.4, CG2, 109.4, 1, ff, bonds);
1791     buildH(res, ILE.HG12, CG1, 1.11, CB, 109.4, CD1, 109.4, 1, ff, bonds);
1792     buildH(res, ILE.HG13, CG1, 1.11, CB, 109.4, CD1, 109.4, -1, ff, bonds);
1793     Atom HG21 = buildH(res, ILE.HG21, CG2, 1.11, CB, 110.0, CG1, 180.0, 0, ff, bonds);
1794     buildH(res, ILE.HG22, CG2, 1.11, CB, 110.0, HG21, 109.0, 1, ff, bonds);
1795     buildH(res, ILE.HG23, CG2, 1.11, CB, 110.0, HG21, 109.0, -1, ff, bonds);
1796     Atom HD11 = buildH(res, ILE.HD11, CD1, 1.11, CG1, 110.0, CB, 180.0, 0, ff, bonds);
1797     buildH(res, ILE.HD12, CD1, 1.11, CG1, 110.0, HD11, 109.0, 1, ff, bonds);
1798     buildH(res, ILE.HD13, CD1, 1.11, CG1, 110.0, HD11, 109.0, -1, ff, bonds);
1799     return res;
1800   }
1801 
1802   /**
1803    * buildLeucine.
1804    *
1805    * @param res a {@link Residue} object.
1806    * @param CA a {@link Atom} object.
1807    * @param N a {@link Atom} object.
1808    * @param C a {@link Atom} object.
1809    * @param ff a {@link ForceField} object.
1810    * @param bonds a {@link List} object.
1811    * @return a {@link ffx.potential.bonded.Residue} object.
1812    */
1813   public static Residue buildLeucine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1814       List<Bond> bonds) {
1815     Atom CB = buildHeavy(res, LEU.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1816     Atom CG = buildHeavy(res, LEU.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
1817     Atom CD1 = buildHeavy(res, LEU.CD1, CG, 1.54, CB, 109.5, CA, 180, 0, ff, bonds);
1818     Atom CD2 = buildHeavy(res, LEU.CD2, CG, 1.54, CB, 109.5, CD1, 109.5, -1, ff, bonds);
1819     buildH(res, LEU.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1820     buildH(res, LEU.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1821     buildH(res, LEU.HG, CG, 1.11, CB, 109.4, CD1, 109.4, 1, ff, bonds);
1822     Atom HD11 = buildH(res, LEU.HD11, CD1, 1.11, CG, 109.4, CB, 180.0, 0, ff, bonds);
1823     buildH(res, LEU.HD12, CD1, 1.11, CG, 109.4, HD11, 109.4, 1, ff, bonds);
1824     buildH(res, LEU.HD13, CD1, 1.11, CG, 109.4, HD11, 109.4, -1, ff, bonds);
1825     Atom HD21 = buildH(res, LEU.HD21, CD2, 1.11, CG, 109.4, CB, 180.0, 0, ff, bonds);
1826     buildH(res, LEU.HD22, CD2, 1.11, CG, 109.4, HD21, 109.4, 1, ff, bonds);
1827     buildH(res, LEU.HD23, CD2, 1.11, CG, 109.4, HD21, 109.4, -1, ff, bonds);
1828     return res;
1829   }
1830 
1831   /**
1832    * buildLysine.
1833    *
1834    * @param res a {@link Residue} object.
1835    * @param CA a {@link Atom} object.
1836    * @param N a {@link Atom} object.
1837    * @param C a {@link Atom} object.
1838    * @param ff a {@link ForceField} object.
1839    * @param bonds a {@link List} object.
1840    * @return a {@link ffx.potential.bonded.Residue} object.
1841    */
1842   public static Residue buildLysine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1843       List<Bond> bonds) {
1844     Atom CB = buildHeavy(res, LYS.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1845     Atom CG = buildHeavy(res, LYS.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
1846     Atom CD = buildHeavy(res, LYS.CD, CG, 1.54, CB, 109.5, CA, 180, 0, ff, bonds);
1847     Atom CE = buildHeavy(res, LYS.CE, CD, 1.54, CG, 109.5, CB, 180, 0, ff, bonds);
1848     Atom NZ = buildHeavy(res, LYS.NZ, CE, 1.50, CD, 109.5, CG, 180, 0, ff, bonds);
1849     buildH(res, LYS.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1850     buildH(res, LYS.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1851     buildH(res, LYS.HG2, CG, 1.11, CB, 109.4, CD, 109.4, 1, ff, bonds);
1852     buildH(res, LYS.HG3, CG, 1.11, CB, 109.4, CD, 109.4, -1, ff, bonds);
1853     buildH(res, LYS.HD2, CD, 1.11, CG, 109.4, CE, 109.4, 1, ff, bonds);
1854     buildH(res, LYS.HD3, CD, 1.11, CG, 109.4, CE, 109.4, -1, ff, bonds);
1855     buildH(res, LYS.HE2, CE, 1.11, CD, 109.4, NZ, 108.8, 1, ff, bonds);
1856     buildH(res, LYS.HE3, CE, 1.11, CD, 109.4, NZ, 108.8, -1, ff, bonds);
1857     Atom HZ1 = buildH(res, LYS.HZ1, NZ, 1.02, CE, 109.5, CD, 180.0, 0, ff, bonds);
1858     buildH(res, LYS.HZ2, NZ, 1.02, CE, 109.5, HZ1, 109.5, 1, ff, bonds);
1859     buildH(res, LYS.HZ3, NZ, 1.02, CE, 109.5, HZ1, 109.5, -1, ff, bonds);
1860     return res;
1861   }
1862 
1863   /**
1864    * buildMethionine.
1865    *
1866    * @param res a {@link Residue} object.
1867    * @param CA a {@link Atom} object.
1868    * @param N a {@link Atom} object.
1869    * @param C a {@link Atom} object.
1870    * @param ff a {@link ForceField} object.
1871    * @param bond a {@link List} object.
1872    * @return a {@link ffx.potential.bonded.Residue} object.
1873    */
1874   public static Residue buildMethionine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1875       List<Bond> bond) {
1876     Atom CB = buildHeavy(res, MET.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bond);
1877     Atom CG = buildHeavy(res, MET.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bond);
1878     Atom SD = buildHeavy(res, MET.SD, CG, 1.82, CB, 109.0, CA, 180, 0, ff, bond);
1879     Atom CE = buildHeavy(res, MET.CE, SD, 1.82, CG, 96.3, CB, 180, 0, ff, bond);
1880     buildH(res, MET.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bond);
1881     buildH(res, MET.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bond);
1882     buildH(res, MET.HG2, CG, 1.11, CB, 109.4, SD, 112.0, 1, ff, bond);
1883     buildH(res, MET.HG3, CG, 1.11, CB, 109.4, SD, 112.0, -1, ff, bond);
1884     Atom HE1 = buildH(res, MET.HE1, CE, 1.11, SD, 112.0, CG, 180.0, 0, ff, bond);
1885     buildH(res, MET.HE2, CE, 1.11, SD, 112.0, HE1, 109.4, 1, ff, bond);
1886     buildH(res, MET.HE3, CE, 1.11, SD, 112.0, HE1, 109.4, -1, ff, bond);
1887     return res;
1888   }
1889 
1890   /**
1891    * buildNeutralAsparticAcid.
1892    *
1893    * @param res a {@link Residue} object.
1894    * @param CA a {@link Atom} object.
1895    * @param N a {@link Atom} object.
1896    * @param C a {@link Atom} object.
1897    * @param ff a {@link ForceField} object.
1898    * @param bonds a {@link List} object.
1899    * @return a {@link ffx.potential.bonded.Residue} object.
1900    */
1901   public static Residue buildNeutralAsparticAcid(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1902       List<Bond> bonds) {
1903     Atom CB = buildHeavy(res, ASH.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1904     Atom CG = buildHeavy(res, ASH.CG, CB, 1.51, CA, 107.8, N, 180, 0, ff, bonds);
1905     Atom OD1 = buildHeavy(res, ASH.OD1, CG, 1.25, CB, 117.0, CA, 0.0, 0, ff, bonds);
1906     Atom OD2 = buildHeavy(res, ASH.OD2, CG, 1.25, CB, 117.0, OD1, 126.0, 1, ff, bonds);
1907     Atom HB2 = buildH(res, ASH.HB2, CB, 1.11, CA, 109.4, CG, 107.9, 1, ff, bonds);
1908     Atom HB3 = buildH(res, ASH.HB3, CB, 1.11, CA, 109.4, CG, 107.9, -1, ff, bonds);
1909     Atom HD2 = buildH(res, ASH.HD2, OD2, 0.98, CG, 108.7, OD1, 0.0, 0, ff, bonds);
1910     return res;
1911   }
1912 
1913   /**
1914    * buildTwoProtonAsparticAcid.
1915    *
1916    * @param res a {@link Residue} object.
1917    * @param CA a {@link Atom} object.
1918    * @param N a {@link Atom} object.
1919    * @param C a {@link Atom} object.
1920    * @param ff a {@link ForceField} object.
1921    * @param bonds a {@link List} object.
1922    * @return a {@link ffx.potential.bonded.Residue} object.
1923    */
1924   public static Residue buildTwoProtonAsparticAcid(Residue res, Atom CA, Atom N, Atom C,
1925       ForceField ff, List<Bond> bonds) {
1926     Atom CB = buildHeavy(res, ASD.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1927     Atom CG = buildHeavy(res, ASD.CG, CB, 1.51, CA, 107.8, N, 180, 0, ff, bonds);
1928     Atom OD1 = buildHeavy(res, ASD.OD1, CG, 1.25, CB, 117.0, CA, 0.0, 0, ff, bonds);
1929     Atom OD2 = buildHeavy(res, ASD.OD2, CG, 1.25, CB, 117.0, OD1, 126.0, 1, ff, bonds);
1930     buildH(res, ASD.HB2, CB, 1.11, CA, 109.4, CG, 107.9, 1, ff, bonds);
1931     buildH(res, ASD.HB3, CB, 1.11, CA, 109.4, CG, 107.9, -1, ff, bonds);
1932     buildH(res, ASD.HD1, OD1, 0.98, CG, 108.7, OD2, 0.0, 0, ff, bonds);
1933     buildH(res, ASD.HD2, OD2, 0.98, CG, 108.7, OD1, 0.0, 0, ff, bonds);
1934     return res;
1935   }
1936 
1937   /**
1938    * buildNeutralGlutamicAcid.
1939    *
1940    * @param res a {@link Residue} object.
1941    * @param CA a {@link Atom} object.
1942    * @param N a {@link Atom} object.
1943    * @param C a {@link Atom} object.
1944    * @param ff a {@link ForceField} object.
1945    * @param bonds a {@link List} object.
1946    * @return a {@link ffx.potential.bonded.Residue} object.
1947    */
1948   public static Residue buildNeutralGlutamicAcid(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
1949       List<Bond> bonds) {
1950     Atom CB = buildHeavy(res, GLH.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1951     Atom CG = buildHeavy(res, GLH.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
1952     Atom CD = buildHeavy(res, GLH.CD, CG, 1.51, CB, 107.8, CA, 180, 0, ff, bonds);
1953     Atom OE1 = buildHeavy(res, GLH.OE1, CD, 1.25, CG, 117.0, CB, 180, 0, ff, bonds);
1954     Atom OE2 = buildHeavy(res, GLH.OE2, CD, 1.25, CG, 117.0, OE1, 126.0, 1, ff, bonds);
1955     buildH(res, GLH.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1956     buildH(res, GLH.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1957     buildH(res, GLH.HG2, CG, 1.11, CB, 109.4, CD, 107.9, 1, ff, bonds);
1958     buildH(res, GLH.HG3, CG, 1.11, CB, 109.4, CD, 107.9, -1, ff, bonds);
1959     buildH(res, GLH.HE2, OE2, 0.98, CD, 108.7, OE1, 0.0, 0, ff, bonds);
1960     return res;
1961   }
1962 
1963   /**
1964    * buildTwoProtonGlutamicAcid.
1965    *
1966    * @param res a {@link Residue} object.
1967    * @param CA a {@link Atom} object.
1968    * @param N a {@link Atom} object.
1969    * @param C a {@link Atom} object.
1970    * @param ff a {@link ForceField} object.
1971    * @param bonds a {@link List} object.
1972    * @return a {@link ffx.potential.bonded.Residue} object.
1973    */
1974   public static Residue buildTwoProtonGlutamicAcid(Residue res, Atom CA, Atom N, Atom C,
1975       ForceField ff, List<Bond> bonds) {
1976     Atom CB = buildHeavy(res, GLD.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
1977     Atom CG = buildHeavy(res, GLD.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
1978     Atom CD = buildHeavy(res, GLD.CD, CG, 1.51, CB, 107.8, CA, 180, 0, ff, bonds);
1979     Atom OE1 = buildHeavy(res, GLD.OE1, CD, 1.25, CG, 117.0, CB, 180, 0, ff, bonds);
1980     Atom OE2 = buildHeavy(res, GLD.OE2, CD, 1.25, CG, 117.0, OE1, 126.0, 1, ff, bonds);
1981     buildH(res, GLD.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
1982     buildH(res, GLD.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
1983     buildH(res, GLD.HG2, CG, 1.11, CB, 109.4, CD, 107.9, 1, ff, bonds);
1984     buildH(res, GLD.HG3, CG, 1.11, CB, 109.4, CD, 107.9, -1, ff, bonds);
1985     buildH(res, GLD.HE1, OE1, 0.98, CD, 108.7, OE2, 0.0, 0, ff, bonds);
1986     buildH(res, GLD.HE2, OE2, 0.98, CD, 108.7, OE1, 0.0, 0, ff, bonds);
1987     return res;
1988   }
1989 
1990   /**
1991    * buildNeutralHistidineD.
1992    *
1993    * @param res a {@link Residue} object.
1994    * @param CA a {@link Atom} object.
1995    * @param N a {@link Atom} object.
1996    * @param C a {@link Atom} object.
1997    * @param ff a {@link ForceField} object.
1998    * @param bonds a {@link List} object.
1999    * @return a {@link ffx.potential.bonded.Residue} object.
2000    */
2001   public static Residue buildNeutralHistidineD(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2002       List<Bond> bonds) {
2003     Atom CB = buildHeavy(res, HID.CB, CA, 1.54, N, 109.5, C, 109.5, 1, ff, bonds);
2004     Atom CG = buildHeavy(res, HID.CG, CB, 1.50, CA, 109.5, N, 180, 0, ff, bonds);
2005     Atom ND1 = buildHeavy(res, HID.ND1, CG, 1.35, CB, 126.0, CA, 180, 0, ff, bonds);
2006     Atom CD2 = buildHeavy(res, HID.CD2, CG, 1.35, CB, 126.0, ND1, 108.0, 1, ff, bonds);
2007     Atom CE1 = buildHeavy(res, HID.CE1, ND1, 1.35, CG, 108.0, CD2, 0.0, 0, ff, bonds);
2008     Atom NE2 = buildHeavy(res, HID.NE2, CD2, 1.35, CG, 108.0, ND1, 0.0, 0, ff, bonds);
2009     buildBond(NE2, CE1, ff, bonds);
2010     buildH(res, HID.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
2011     buildH(res, HID.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
2012     buildH(res, HID.HD1, ND1, 1.02, CG, 126.0, CB, 0.0, 0, ff, bonds);
2013     buildH(res, HID.HD2, CD2, 1.10, CG, 126.0, NE2, 126.0, 1, ff, bonds);
2014     buildH(res, HID.HE1, CE1, 1.10, ND1, 126.0, NE2, 126.0, 1, ff, bonds);
2015     return res;
2016   }
2017 
2018   /**
2019    * buildNeutralHistidineE.
2020    *
2021    * @param res a {@link Residue} object.
2022    * @param CA a {@link Atom} object.
2023    * @param N a {@link Atom} object.
2024    * @param C a {@link Atom} object.
2025    * @param ff a {@link ForceField} object.
2026    * @param bonds a {@link List} object.
2027    * @return a {@link ffx.potential.bonded.Residue} object.
2028    */
2029   public static Residue buildNeutralHistidineE(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2030       List<Bond> bonds) {
2031     Atom CB = buildHeavy(res, HIE.CB, CA, 1.54, N, 109.5, C, 109.5, 1, ff, bonds);
2032     Atom CG = buildHeavy(res, HIE.CG, CB, 1.50, CA, 109.5, N, 180, 0, ff, bonds);
2033     Atom ND1 = buildHeavy(res, HIE.ND1, CG, 1.35, CB, 126.0, CA, 180, 0, ff, bonds);
2034     Atom CD2 = buildHeavy(res, HIE.CD2, CG, 1.35, CB, 126.0, ND1, 108.0, 1, ff, bonds);
2035     Atom CE1 = buildHeavy(res, HIE.CE1, ND1, 1.35, CG, 108.0, CD2, 0.0, 0, ff, bonds);
2036     Atom NE2 = buildHeavy(res, HIE.NE2, CD2, 1.35, CG, 108.0, ND1, 0.0, 0, ff, bonds);
2037     buildBond(NE2, CE1, ff, bonds);
2038     buildH(res, HIE.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
2039     buildH(res, HIE.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
2040     buildH(res, HIE.HD2, CD2, 1.10, CG, 126.0, NE2, 126.0, 1, ff, bonds);
2041     buildH(res, HIE.HE1, CE1, 1.10, ND1, 126.0, NE2, 126.0, 1, ff, bonds);
2042     buildH(res, HIE.HE2, NE2, 1.02, CD2, 126.0, CE1, 126.0, 1, ff, bonds);
2043     return res;
2044   }
2045 
2046   /**
2047    * buildOrnithine.
2048    *
2049    * @param res a {@link Residue} object.
2050    * @param CA a {@link Atom} object.
2051    * @param N a {@link Atom} object.
2052    * @param C a {@link Atom} object.
2053    * @param ff a {@link ForceField} object.
2054    * @param bonds a {@link List} object.
2055    * @return a {@link ffx.potential.bonded.Residue} object.
2056    */
2057   public static Residue buildOrnithine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2058       List<Bond> bonds) {
2059     Atom CB = buildHeavy(res, ORN.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
2060     Atom CG = buildHeavy(res, ORN.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
2061     Atom CD = buildHeavy(res, ORN.CD, CG, 1.54, CB, 109.5, CA, 180, 0, ff, bonds);
2062     Atom NE = buildHeavy(res, ORN.NE, CD, 1.50, CG, 109.5, CB, 180, 0, ff, bonds);
2063     buildH(res, ORN.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
2064     buildH(res, ORN.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
2065     buildH(res, ORN.HG2, CG, 1.11, CB, 109.4, CD, 109.4, 1, ff, bonds);
2066     buildH(res, ORN.HG3, CG, 1.11, CB, 109.4, CD, 109.4, -1, ff, bonds);
2067     buildH(res, ORN.HD2, CD, 1.11, CG, 109.4, NE, 109.4, 1, ff, bonds);
2068     buildH(res, ORN.HD3, CD, 1.11, CG, 109.4, NE, 109.4, -1, ff, bonds);
2069     Atom HE1 = buildH(res, ORN.HE1, NE, 1.02, CD, 109.5, CG, 180.0, 0, ff, bonds);
2070     buildH(res, ORN.HE2, NE, 1.02, CD, 109.5, HE1, 109.5, 1, ff, bonds);
2071     buildH(res, ORN.HE3, NE, 1.02, CD, 109.5, HE1, 109.5, -1, ff, bonds);
2072     return res;
2073   }
2074 
2075   /**
2076    * buildPCA.
2077    *
2078    * @param res a {@link Residue} object.
2079    * @param CA a {@link Atom} object.
2080    * @param N a {@link Atom} object.
2081    * @param C a {@link Atom} object.
2082    * @param ff a {@link ForceField} object.
2083    * @param bonds a {@link List} object.
2084    * @return a {@link ffx.potential.bonded.Residue} object.
2085    */
2086   public static Residue buildPCA(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2087       List<Bond> bonds) {
2088     Atom CB = buildHeavy(res, PCA.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
2089     Atom CG = buildHeavy(res, PCA.CG, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
2090     Atom CD = buildHeavy(res, PCA.CD, CG, 1.54, CB, 109.5, CA, 180, 0, ff, bonds);
2091     buildHeavy(res, PCA.OE, CD, 1.22, N, 126.0, CG, 126.0, 1, ff, bonds);
2092     buildH(res, PCA.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
2093     buildH(res, PCA.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
2094     buildH(res, PCA.HG2, CG, 1.11, CB, 109.4, CD, 109.4, 1, ff, bonds);
2095     buildH(res, PCA.HG3, CG, 1.11, CB, 109.4, CD, 109.4, -1, ff, bonds);
2096     return res;
2097   }
2098 
2099   /**
2100    * buildPhenylalanine.
2101    *
2102    * @param res a {@link Residue} object.
2103    * @param CA a {@link Atom} object.
2104    * @param N a {@link Atom} object.
2105    * @param C a {@link Atom} object.
2106    * @param ff a {@link ForceField} object.
2107    * @param bonds a {@link List} object.
2108    * @return a {@link ffx.potential.bonded.Residue} object.
2109    */
2110   public static Residue buildPhenylalanine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2111       List<Bond> bonds) {
2112     Atom CB = buildHeavy(res, PHE.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
2113     Atom CG = buildHeavy(res, PHE.CG, CB, 1.50, CA, 109.5, N, 180, 0, ff, bonds);
2114     Atom CD1 = buildHeavy(res, PHE.CD1, CG, 1.39, CB, 120.0, CA, 180, 0, ff, bonds);
2115     Atom CD2 = buildHeavy(res, PHE.CD2, CG, 1.39, CB, 120.0, CD1, 120.0, 1, ff, bonds);
2116     Atom CE1 = buildHeavy(res, PHE.CE1, CD1, 1.39, CG, 120.0, CB, 180, 0, ff, bonds);
2117     Atom CE2 = buildHeavy(res, PHE.CE2, CD2, 1.39, CG, 120.0, CB, 180, 0, ff, bonds);
2118     Atom CZ = buildHeavy(res, PHE.CZ, CE1, 1.39, CD1, 120.0, CG, 0.0, 0, ff, bonds);
2119     buildBond(CE2, CZ, ff, bonds);
2120     buildH(res, PHE.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
2121     buildH(res, PHE.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
2122     buildH(res, PHE.HD1, CD1, 1.11, CG, 120.0, CE1, 120.0, 1, ff, bonds);
2123     buildH(res, PHE.HD2, CD2, 1.11, CG, 120.0, CE2, 120.0, 1, ff, bonds);
2124     buildH(res, PHE.HE1, CE1, 1.11, CD1, 120.0, CZ, 120.0, 1, ff, bonds);
2125     buildH(res, PHE.HE2, CE2, 1.11, CD2, 120.0, CZ, 120.0, 1, ff, bonds);
2126     buildH(res, PHE.HZ, CZ, 1.11, CE1, 120.0, CE2, 120.0, 1, ff, bonds);
2127     return res;
2128   }
2129 
2130   /**
2131    * buildProline.
2132    *
2133    * @param res a {@link Residue} object.
2134    * @param CA a {@link Atom} object.
2135    * @param N a {@link Atom} object.
2136    * @param C a {@link Atom} object.
2137    * @param position a {@link ResiduePosition} object.
2138    * @param ff a {@link ForceField} object.
2139    * @param bonds a {@link List} object.
2140    * @return a {@link ffx.potential.bonded.Residue} object.
2141    */
2142   public static Residue buildProline(Residue res, Atom CA, Atom N, Atom C, ResiduePosition position,
2143       ForceField ff, List<Bond> bonds) {
2144     Atom CB = buildHeavy(res, PRO.CB, CA, 1.5247, N, 104.0, C, 109.5, 1, ff, bonds);
2145     Atom CG = buildHeavy(res, PRO.CG, CB, 1.5247, CA, 104.0, N, 30.0, 0, ff, bonds);
2146     int cdKey = position == FIRST_RESIDUE ? 469 : PRO.CD.getType();
2147     Atom CD = buildHeavy(res, PRO.CD.name(), N, 1.5247, CA, 104.0, CB, 0, 0, cdKey, ff, bonds);
2148     buildBond(CD, CG, ff, bonds);
2149     buildH(res, PRO.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
2150     buildH(res, PRO.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
2151     buildH(res, PRO.HG2, CG, 1.11, CB, 109.4, CD, 109.4, 1, ff, bonds);
2152     buildH(res, PRO.HG3, CG, 1.11, CB, 109.4, CD, 109.4, -1, ff, bonds);
2153     if (position == FIRST_RESIDUE) {
2154       buildH(res, PRO.HD2.name(), CD, 1.11, CG, 109.4, N, 109.4, 1, 470, ff, bonds);
2155       buildH(res, PRO.HD3.name(), CD, 1.11, CG, 109.4, N, 109.4, -1, 470, ff, bonds);
2156     } else {
2157       buildH(res, PRO.HD2, CD, 1.11, CG, 109.4, N, 109.4, 1, ff, bonds);
2158       buildH(res, PRO.HD3, CD, 1.11, CG, 109.4, N, 109.4, -1, ff, bonds);
2159     }
2160     return res;
2161   }
2162 
2163   /**
2164    * buildSerine.
2165    *
2166    * @param res a {@link Residue} object.
2167    * @param CA a {@link Atom} object.
2168    * @param N a {@link Atom} object.
2169    * @param C a {@link Atom} object.
2170    * @param ff a {@link ForceField} object.
2171    * @param bonds a {@link List} object.
2172    * @return a {@link ffx.potential.bonded.Residue} object.
2173    */
2174   public static Residue buildSerine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2175       List<Bond> bonds) {
2176     Atom CB = buildHeavy(res, SER.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
2177     Atom OG = buildHeavy(res, SER.OG, CB, 1.41, CA, 107.5, N, 180, 0, ff, bonds);
2178     buildH(res, SER.HB2, CB, 1.11, CA, 109.4, OG, 106.7, 1, ff, bonds);
2179     buildH(res, SER.HB3, CB, 1.11, CA, 109.4, OG, 106.7, -1, ff, bonds);
2180     buildH(res, SER.HG, OG, 0.94, CB, 106.9, CA, 180.0, 0, ff, bonds);
2181     return res;
2182   }
2183 
2184   /**
2185    * buildThreonine.
2186    *
2187    * @param res a {@link Residue} object.
2188    * @param CA a {@link Atom} object.
2189    * @param N a {@link Atom} object.
2190    * @param C a {@link Atom} object.
2191    * @param ff a {@link ForceField} object.
2192    * @param bonds a {@link List} object.
2193    * @return a {@link ffx.potential.bonded.Residue} object.
2194    */
2195   public static Residue buildThreonine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2196       List<Bond> bonds) {
2197     Atom CB = buildHeavy(res, THR.CB, CA, 1.54, N, 109.5, C, 109.5, 1, ff, bonds);
2198     Atom OG1 = buildHeavy(res, THR.OG1, CB, 1.41, CA, 107.5, N, 180, 0, ff, bonds);
2199     Atom CG2 = buildHeavy(res, THR.CG2, CB, 1.54, CA, 109.5, OG1, 107.7, 1, ff, bonds);
2200     buildH(res, THR.HB, CB, 1.11, CA, 109.4, OG1, 106.7, -1, ff, bonds);
2201     buildH(res, THR.HG1, OG1, 0.94, CB, 106.9, CA, 180.0, 0, ff, bonds);
2202     Atom HG21 = buildH(res, THR.HG21, CG2, 1.11, CB, 110.0, CA, 180.0, 0, ff, bonds);
2203     buildH(res, THR.HG22, CG2, 1.11, CB, 110.0, HG21, 109.0, 1, ff, bonds);
2204     buildH(res, THR.HG23, CG2, 1.11, CB, 110.0, HG21, 109.0, -1, ff, bonds);
2205     return res;
2206   }
2207 
2208   /**
2209    * buildTryptophan.
2210    *
2211    * @param res a {@link Residue} object.
2212    * @param CA a {@link Atom} object.
2213    * @param N a {@link Atom} object.
2214    * @param C a {@link Atom} object.
2215    * @param ff a {@link ForceField} object.
2216    * @param bond a {@link List} object.
2217    * @return a {@link ffx.potential.bonded.Residue} object.
2218    */
2219   public static Residue buildTryptophan(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2220       List<Bond> bond) {
2221     Atom CB = buildHeavy(res, TRP.CB, CA, 1.54, N, 109.5, C, 109.5, 1, ff, bond);
2222     Atom CG = buildHeavy(res, TRP.CG, CB, 1.50, CA, 109.5, N, 62, 0, ff, bond);
2223     Atom CD1 = buildHeavy(res, TRP.CD1, CG, 1.35, CB, 126.0, CA, -90, 0, ff, bond);
2224     Atom CD2 = buildHeavy(res, TRP.CD2, CG, 1.35, CB, 126.0, CD1, 108.0, 1, ff, bond);
2225     Atom NE1 = buildHeavy(res, TRP.NE1, CD1, 1.35, CG, 108.0, CD2, 0.0, 0, ff, bond);
2226     Atom CE2 = buildHeavy(res, TRP.CE2, NE1, 1.35, CD1, 108.0, CG, 0.0, 0, ff, bond);
2227     buildBond(CE2, CD2, ff, bond);
2228     Atom CE3 = buildHeavy(res, TRP.CE3, CD2, 1.35, CE2, 120.0, NE1, 180.0, 0, ff, bond);
2229     Atom CZ2 = buildHeavy(res, TRP.CZ2, CE2, 1.35, CD2, 120.0, CE3, 0.0, 0, ff, bond);
2230     Atom CZ3 = buildHeavy(res, TRP.CZ3, CE3, 1.35, CD2, 120.0, CE2, 0.0, 0, ff, bond);
2231     Atom CH2 = buildHeavy(res, TRP.CH2, CZ2, 1.35, CE2, 120.0, CD2, 0.0, 0, ff, bond);
2232     buildBond(CH2, CZ3, ff, bond);
2233     buildH(res, TRP.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bond);
2234     buildH(res, TRP.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bond);
2235     buildH(res, TRP.HD1, CD1, 1.10, CG, 126.0, NE1, 126.0, 1, ff, bond);
2236     buildH(res, TRP.HE1, NE1, 1.05, CD1, 126.0, CE2, 126.0, 1, ff, bond);
2237     buildH(res, TRP.HE3, CE3, 1.10, CD1, 120.0, CZ3, 120.0, 1, ff, bond);
2238     buildH(res, TRP.HZ2, CZ2, 1.10, CE2, 120.0, CH2, 120.0, 1, ff, bond);
2239     buildH(res, TRP.HZ3, CZ3, 1.10, CE3, 120.0, CH2, 120.0, 1, ff, bond);
2240     buildH(res, TRP.HH2, CH2, 1.10, CZ2, 120.0, CZ3, 120.0, 1, ff, bond);
2241     return res;
2242   }
2243 
2244   /**
2245    * buildTyrosine.
2246    *
2247    * @param res a {@link Residue} object.
2248    * @param CA a {@link Atom} object.
2249    * @param N a {@link Atom} object.
2250    * @param C a {@link Atom} object.
2251    * @param ff a {@link ForceField} object.
2252    * @param bonds a {@link List} object.
2253    * @return a {@link ffx.potential.bonded.Residue} object.
2254    */
2255   public static Residue buildTyrosine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2256       List<Bond> bonds) {
2257     Atom CB = buildHeavy(res, TYR.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
2258     Atom CG = buildHeavy(res, TYR.CG, CB, 1.50, CA, 109.5, N, 62, 0, ff, bonds);
2259     Atom CD1 = buildHeavy(res, TYR.CD1, CG, 1.39, CB, 120.0, CA, 90, 0, ff, bonds);
2260     Atom CD2 = buildHeavy(res, TYR.CD2, CG, 1.39, CB, 120.0, CD1, 120.0, 1, ff, bonds);
2261     Atom CE1 = buildHeavy(res, TYR.CE1, CD1, 1.39, CG, 120.0, CB, 180, 0, ff, bonds);
2262     Atom CE2 = buildHeavy(res, TYR.CE2, CD2, 1.39, CG, 120.0, CB, 180, 0, ff, bonds);
2263     Atom CZ = buildHeavy(res, TYR.CZ, CE1, 1.39, CD1, 120.0, CG, 0.0, 0, ff, bonds);
2264     buildBond(CE2, CZ, ff, bonds);
2265     Atom OH = buildHeavy(res, TYR.OH, CZ, 1.36, CE2, 120.0, CE1, 120.0, 1, ff, bonds);
2266     buildH(res, TYR.HB2, CB, 1.11, CA, 109.4, CG, 109.4, 1, ff, bonds);
2267     buildH(res, TYR.HB3, CB, 1.11, CA, 109.4, CG, 109.4, -1, ff, bonds);
2268     buildH(res, TYR.HD1, CD1, 1.10, CG, 120.0, CE1, 120.0, 1, ff, bonds);
2269     buildH(res, TYR.HD2, CD2, 1.10, CG, 120.0, CE2, 120.0, 1, ff, bonds);
2270     buildH(res, TYR.HE1, CE1, 1.10, CD1, 120.0, CZ, 120.0, 1, ff, bonds);
2271     buildH(res, TYR.HE2, CE2, 1.10, CD2, 120.0, CZ, 120.0, 1, ff, bonds);
2272     buildH(res, TYR.HH, OH, 0.97, CZ, 108.0, CE2, 0.0, 0, ff, bonds);
2273     return res;
2274   }
2275 
2276   /**
2277    * buildValine.
2278    *
2279    * @param res a {@link Residue} object.
2280    * @param CA a {@link Atom} object.
2281    * @param N a {@link Atom} object.
2282    * @param C a {@link Atom} object.
2283    * @param ff a {@link ForceField} object.
2284    * @param bonds a {@link List} object.
2285    * @return a {@link ffx.potential.bonded.Residue} object.
2286    */
2287   public static Residue buildValine(Residue res, Atom CA, Atom N, Atom C, ForceField ff,
2288       List<Bond> bonds) {
2289     Atom CB = buildHeavy(res, VAL.CB, CA, 1.54, N, 109.5, C, 107.8, 1, ff, bonds);
2290     Atom CG1 = buildHeavy(res, VAL.CG1, CB, 1.54, CA, 109.5, N, 180, 0, ff, bonds);
2291     Atom CG2 = buildHeavy(res, VAL.CG2, CB, 1.54, CA, 109.5, CG1, 109.5, -1, ff, bonds);
2292     buildH(res, VAL.HB, CB, 1.11, CA, 109.4, CG1, 109.4, 1, ff, bonds);
2293     Atom HG11 = buildH(res, VAL.HG11, CG1, 1.11, CB, 109.4, CA, 180.0, 0, ff, bonds);
2294     buildH(res, VAL.HG12, CG1, 1.11, CB, 109.4, HG11, 109.4, 1, ff, bonds);
2295     buildH(res, VAL.HG13, CG1, 1.11, CB, 109.4, HG11, 109.4, -1, ff, bonds);
2296     Atom HG21 = buildH(res, VAL.HG21, CG2, 1.11, CB, 109.4, CA, 180.0, 0, ff, bonds);
2297     buildH(res, VAL.HG22, CG2, 1.11, CB, 109.4, HG21, 109.4, 1, ff, bonds);
2298     buildH(res, VAL.HG23, CG2, 1.11, CB, 109.4, HG21, 109.4, -1, ff, bonds);
2299     return res;
2300   }
2301 
2302   /**
2303    * copyResidue.
2304    *
2305    * @param fromResidue a {@link ffx.potential.bonded.Residue} object.
2306    * @param toResidue a {@link ffx.potential.bonded.Residue} object.
2307    */
2308   public static void copyResidue(Residue fromResidue, Residue toResidue) {
2309     String resName = fromResidue.getName();
2310     AminoAcid3 res = AminoAcid3.valueOf(resName);
2311     List<String> atomNames = new ArrayList<>();
2312     switch (res) {
2313       case ALA -> {
2314         atomNames.addAll(Arrays.asList(getNames(ALA.class)));
2315         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2316       }
2317       case ASD -> {
2318         atomNames.addAll(Arrays.asList(getNames(ASD.class)));
2319         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2320       }
2321       case ASH -> {
2322         atomNames.addAll(Arrays.asList(getNames(ASH.class)));
2323         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2324       }
2325       case ASN -> {
2326         atomNames.addAll(Arrays.asList(getNames(ASN.class)));
2327         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2328       }
2329       case ASP -> {
2330         atomNames.addAll(Arrays.asList(getNames(ASP.class)));
2331         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2332       }
2333       case ARG -> {
2334         atomNames.addAll(Arrays.asList(getNames(ARG.class)));
2335         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2336       }
2337       case CYS -> {
2338         atomNames.addAll(Arrays.asList(getNames(CYS.class)));
2339         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2340       }
2341       case CYD -> {
2342         atomNames.addAll(Arrays.asList(getNames(CYD.class)));
2343         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2344       }
2345       case CYX -> {
2346         atomNames.addAll(Arrays.asList(getNames(CYX.class)));
2347         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2348       }
2349       case GLD -> {
2350         atomNames.addAll(Arrays.asList(getNames(GLD.class)));
2351         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2352       }
2353       case GLH -> {
2354         atomNames.addAll(Arrays.asList(getNames(GLH.class)));
2355         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2356       }
2357       case GLN -> {
2358         atomNames.addAll(Arrays.asList(getNames(GLN.class)));
2359         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2360       }
2361       case GLU -> {
2362         atomNames.addAll(Arrays.asList(getNames(GLU.class)));
2363         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2364       }
2365       case GLY -> {
2366         atomNames.addAll(Arrays.asList(getNames(GLY.class)));
2367         atomNames.addAll(Arrays.asList(getNames(GlycineBackboneAtoms.class)));
2368       }
2369       case HID -> {
2370         atomNames.addAll(Arrays.asList(getNames(HID.class)));
2371         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2372       }
2373       case HIE -> {
2374         atomNames.addAll(Arrays.asList(getNames(HIE.class)));
2375         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2376       }
2377       case HIS -> {
2378         atomNames.addAll(Arrays.asList(getNames(HIS.class)));
2379         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2380       }
2381       case ILE -> {
2382         atomNames.addAll(Arrays.asList(getNames(ILE.class)));
2383         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2384       }
2385       case LEU -> {
2386         atomNames.addAll(Arrays.asList(getNames(LEU.class)));
2387         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2388       }
2389       case LYD -> {
2390         atomNames.addAll(Arrays.asList(getNames(LYD.class)));
2391         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2392       }
2393       case LYS -> {
2394         atomNames.addAll(Arrays.asList(getNames(LYS.class)));
2395         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2396       }
2397       case MET -> {
2398         atomNames.addAll(Arrays.asList(getNames(MET.class)));
2399         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2400       }
2401       case PHE -> {
2402         atomNames.addAll(Arrays.asList(getNames(PHE.class)));
2403         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2404       }
2405       case PRO -> {
2406         atomNames.addAll(Arrays.asList(getNames(PRO.class)));
2407         atomNames.addAll(Arrays.asList(getNames(ProlineBackboneAtoms.class)));
2408       }
2409       case SER -> {
2410         atomNames.addAll(Arrays.asList(getNames(SER.class)));
2411         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2412       }
2413       case THR -> {
2414         atomNames.addAll(Arrays.asList(getNames(THR.class)));
2415         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2416       }
2417       case TRP -> {
2418         atomNames.addAll(Arrays.asList(getNames(TRP.class)));
2419         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2420       }
2421       case TYD -> {
2422         atomNames.addAll(Arrays.asList(getNames(TYD.class)));
2423         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2424       }
2425       case TYR -> {
2426         atomNames.addAll(Arrays.asList(getNames(TYR.class)));
2427         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2428       }
2429       case VAL -> {
2430         atomNames.addAll(Arrays.asList(getNames(VAL.class)));
2431         atomNames.addAll(Arrays.asList(getNames(AminoAcidBackboneAtoms.class)));
2432       }
2433       default -> atomNames = null;
2434     }
2435     for (String atomName : atomNames) {
2436       copyCoordinates(fromResidue, toResidue, atomName);
2437     }
2438   }
2439 
2440   /**
2441    * Only the first nitrogen should have H1, H2 and H3 atoms, unless it's an NME cap.
2442    *
2443    * @param aminoAcid 3-letter amino acid name.
2444    * @param residue the amino acid Residue.
2445    */
2446   public static void removeH1_H2_H3(AminoAcid3 aminoAcid, Residue residue) {
2447     if (aminoAcid != AminoAcid3.NME) {
2448       if (aminoAcid != AminoAcid3.NH2) {
2449         Atom H1 = (Atom) residue.getAtomNode("H1");
2450         if (H1 != null) {
2451           residue.deleteAtom(H1);
2452         }
2453         Atom H2 = (Atom) residue.getAtomNode("H2");
2454         if (H2 != null) {
2455           residue.deleteAtom(H2);
2456         }
2457       }
2458       Atom H3 = (Atom) residue.getAtomNode("H3");
2459       if (H3 != null) {
2460         residue.deleteAtom(H3);
2461       }
2462     }
2463   }
2464 
2465   /**
2466    * Only the last residue in a chain should have an OXT/OT2 atom.
2467    *
2468    * @param residue the amino acid residue.
2469    */
2470   public static void removeOXT_OT2(Residue residue) {
2471     Atom OXT = (Atom) residue.getAtomNode("OXT");
2472     if (OXT != null) {
2473       residue.deleteAtom(OXT);
2474     }
2475     Atom OT2 = (Atom) residue.getAtomNode("OT2");
2476     if (OT2 != null) {
2477       residue.deleteAtom(OT2);
2478     }
2479   }
2480 
2481   /**
2482    * Assign atom types to a single amino acid side chain.
2483    *
2484    * @param position The position of this amino acid in the chain.
2485    * @param aminoAcid The amino acid to use.
2486    * @param residue The residue node.
2487    * @param CA The C-alpha carbon of this residue.
2488    * @param N The peptide nitrogen of this residue.
2489    * @param C The peptide carbonyl carbon.
2490    * @param forceField a {@link ForceField} object.
2491    * @param bondList a {@link java.util.List} object.
2492    */
2493   private static void assignAminoAcidSideChain(ResiduePosition position, AminoAcid3 aminoAcid,
2494       Residue residue, Atom CA, Atom N, Atom C, ForceField forceField, List<Bond> bondList) {
2495     switch (aminoAcid) {
2496       case ALA -> buildAlanine(residue, CA, N, C, forceField, bondList);
2497       case GLY -> buildGlycine(residue, CA, N, C, position, forceField, bondList);
2498       case VAL -> buildValine(residue, CA, N, C, forceField, bondList);
2499       case LEU -> buildLeucine(residue, CA, N, C, forceField, bondList);
2500       case ILE -> buildIsoleucine(residue, CA, N, C, forceField, bondList);
2501       case SER -> buildSerine(residue, CA, N, C, forceField, bondList);
2502       case THR -> buildThreonine(residue, CA, N, C, forceField, bondList);
2503       case CYS -> buildCysteine(residue, CA, N, C, forceField, bondList);
2504       case CYX -> buildCystine(residue, CA, N, C, forceField, bondList);
2505       case CYD -> buildDeprotonatedCysteine(residue, CA, N, C, forceField, bondList);
2506       case PRO -> buildProline(residue, CA, N, C, position, forceField, bondList);
2507       case PHE -> buildPhenylalanine(residue, CA, N, C, forceField, bondList);
2508       case TYR -> buildTyrosine(residue, CA, N, C, forceField, bondList);
2509       case TYD -> buildDeprotonatedTyrosine(residue, CA, N, C, forceField, bondList);
2510       case TRP -> buildTryptophan(residue, CA, N, C, forceField, bondList);
2511       case HIS -> buildHistidine(residue, CA, N, C, forceField, bondList);
2512       case HID -> buildNeutralHistidineD(residue, CA, N, C, forceField, bondList);
2513       case HIE -> buildNeutralHistidineE(residue, CA, N, C, forceField, bondList);
2514       case ASP -> buildAspartate(residue, CA, N, C, forceField, bondList);
2515       case ASH -> buildNeutralAsparticAcid(residue, CA, N, C, forceField, bondList);
2516       case ASD -> buildTwoProtonAsparticAcid(residue, CA, N, C, forceField, bondList);
2517       case ASN -> buildAsparagine(residue, CA, N, C, forceField, bondList);
2518       case GLU -> buildGlutamate(residue, CA, N, C, forceField, bondList);
2519       case GLH -> buildNeutralGlutamicAcid(residue, CA, N, C, forceField, bondList);
2520       case GLD -> buildTwoProtonGlutamicAcid(residue, CA, N, C, forceField, bondList);
2521       case GLN -> buildGlutamine(residue, CA, N, C, forceField, bondList);
2522       case MET -> buildMethionine(residue, CA, N, C, forceField, bondList);
2523       case LYS -> buildLysine(residue, CA, N, C, forceField, bondList);
2524       case LYD -> buildDeprotonatedLysine(residue, CA, N, C, forceField, bondList);
2525       case ARG -> buildArginine(residue, CA, N, C, forceField, bondList);
2526       case ORN -> buildOrnithine(residue, CA, N, C, forceField, bondList);
2527       case AIB -> buildAIB(residue, CA, N, C, forceField, bondList);
2528       case PCA -> buildPCA(residue, CA, N, C, forceField, bondList);
2529       case UNK -> {
2530         String residueName = residue.getName();
2531         logger.log(Level.INFO, " Patching side-chain {0}", residueName);
2532         HashMap<String, AtomType> types = forceField.getAtomTypes(residueName);
2533         if (!types.isEmpty()) {
2534           boolean patched = true;
2535           List<Atom> residueAtoms = residue.getAtomList();
2536           // Assign atom types for side-chain atoms.
2537           for (Atom atom : residueAtoms) {
2538             String atomName = atom.getName().toUpperCase();
2539             AtomType type = atom.getAtomType();
2540             if (type == null) {
2541               type = types.get(atomName);
2542               atom.setAtomType(type);
2543               types.remove(atomName);
2544             }
2545           }
2546           // Create bonds between known atoms.
2547           for (Atom atom : residueAtoms) {
2548             String atomName = atom.getName();
2549             String[] bonds = forceField.getBonds(residueName, atomName);
2550             if (bonds != null) {
2551               for (String name : bonds) {
2552                 Atom atom2 = (Atom) residue.getAtomNode(name);
2553                 if (atom2 != null && !atom.isBonded(atom2)) {
2554                   buildBond(atom, atom2, forceField, bondList);
2555                 }
2556               }
2557             }
2558           }
2559 
2560           // Create missing hydrogen atoms.
2561           if (!types.isEmpty()) {
2562             // Create a hashmap of the molecule's atoms
2563             HashMap<String, Atom> atomMap = new HashMap<>();
2564             for (Atom atom : residueAtoms) {
2565               atomMap.put(atom.getName().toUpperCase(), atom);
2566             }
2567             for (String atomName : types.keySet()) {
2568               AtomType type = types.get(atomName);
2569               String[] bonds = forceField.getBonds(residueName, atomName.toUpperCase());
2570               if (bonds == null || bonds.length != 1) {
2571                 patched = false;
2572                 logger.log(Level.INFO, " Check biotype for hydrogen {0}.", type.name);
2573                 break;
2574               }
2575               // Get the heavy atom the hydrogen is bonded to.
2576               Atom ia = atomMap.get(bonds[0].toUpperCase());
2577               Atom hydrogen = new Atom(0, atomName, ia.getAltLoc(), new double[3],
2578                   ia.getResidueName(), ia.getResidueNumber(), ia.getChainID(), ia.getOccupancy(),
2579                   ia.getTempFactor(), ia.getSegID());
2580               logger.log(Level.FINE, " Created hydrogen {0}.", atomName);
2581               hydrogen.setAtomType(type);
2582               hydrogen.setHetero(true);
2583               residue.addMSNode(hydrogen);
2584               int valence = ia.getAtomType().valence;
2585               List<Bond> aBonds = ia.getBonds();
2586               int numBonds = aBonds.size();
2587               // Try to find the following configuration: ib-ia-ic
2588               Atom ib = null;
2589               Atom ic = null;
2590               Atom id = null;
2591               if (numBonds > 0) {
2592                 Bond bond = aBonds.get(0);
2593                 ib = bond.get1_2(ia);
2594               }
2595               if (numBonds > 1) {
2596                 Bond bond = aBonds.get(1);
2597                 ic = bond.get1_2(ia);
2598               }
2599               if (numBonds > 2) {
2600                 Bond bond = aBonds.get(2);
2601                 id = bond.get1_2(ia);
2602               }
2603 
2604               // Building the hydrogens depends on hybridization and the locations of other bonded
2605               // atoms.
2606               logger.log(Level.FINE, " Bonding {0} to {1} ({2} of {3}).",
2607                   new Object[] {atomName, ia.getName(), numBonds, valence});
2608               switch (valence) {
2609                 case 4 -> {
2610                   switch (numBonds) {
2611                     case 3 -> {
2612                       // Find the average coordinates of atoms ib, ic and id.
2613                       Double3 b = ib.getXYZ();
2614                       Double3 c = ic.getXYZ();
2615                       Double3 d = id.getXYZ();
2616                       Double3 a = b.add(c).addI(d).scaleI(1.0 / 3.0);
2617 
2618                       // Place the hydrogen at chiral position #1.
2619                       intxyz(hydrogen, ia, 1.0, ib, 109.5, ic, 109.5, 0);
2620                       Double3 e1 = hydrogen.getXYZ();
2621                       Double3 ret = a.sub(e1);
2622                       double l1 = ret.length();
2623 
2624                       // Place the hydrogen at chiral position #2.
2625                       intxyz(hydrogen, ia, 1.0, ib, 109.5, ic, 109.5, 1);
2626                       Double3 e2 = hydrogen.getXYZ();
2627                       ret = a.sub(e2);
2628                       double l2 = ret.length();
2629 
2630                       // Revert to #1 if it is farther from the average.
2631                       if (l1 > l2) {
2632                         hydrogen.setXYZ(e1.get());
2633                       }
2634                     }
2635                     case 2 -> intxyz(hydrogen, ia, 1.0, ib, 109.5, ic, 109.5, 0);
2636                     case 1 -> intxyz(hydrogen, ia, 1.0, ib, 109.5, null, 0.0, 0);
2637                     case 0 -> intxyz(hydrogen, ia, 1.0, null, 0.0, null, 0.0, 0);
2638                     default -> {
2639                       logger.log(Level.INFO, " Check biotype for hydrogen {0}.", atomName);
2640                       patched = false;
2641                     }
2642                   }
2643                 }
2644                 case 3 -> {
2645                   switch (numBonds) {
2646                     case 2 -> intxyz(hydrogen, ia, 1.0, ib, 120.0, ic, 180.0, 0);
2647                     case 1 -> intxyz(hydrogen, ia, 1.0, ib, 120.0, null, 0.0, 0);
2648                     case 0 -> intxyz(hydrogen, ia, 1.0, null, 0.0, null, 0.0, 0);
2649                     default -> {
2650                       logger.log(Level.INFO, " Check biotype for hydrogen {0}.", atomName);
2651                       patched = false;
2652                     }
2653                   }
2654                 }
2655                 case 2 -> {
2656                   switch (numBonds) {
2657                     case 1 -> intxyz(hydrogen, ia, 1.0, ib, 120.0, null, 0.0, 0);
2658                     case 0 -> intxyz(hydrogen, ia, 1.0, null, 0.0, null, 0.0, 0);
2659                     default -> {
2660                       logger.log(Level.INFO, " Check biotype for hydrogen {0}.", atomName);
2661                       patched = false;
2662                     }
2663                   }
2664                 }
2665                 case 1 -> {
2666                   if (numBonds == 0) {
2667                     intxyz(hydrogen, ia, 1.0, null, 0.0, null, 0.0, 0);
2668                   } else {
2669                     logger.log(Level.INFO, " Check biotype for hydrogen {0}.", atomName);
2670                     patched = false;
2671                   }
2672                 }
2673                 default -> {
2674                   logger.log(Level.INFO, " Check biotype for hydrogen {0}.", atomName);
2675                   patched = false;
2676                 }
2677               }
2678               if (!patched) {
2679                 break;
2680               } else {
2681                 buildBond(ia, hydrogen, forceField, bondList);
2682               }
2683             }
2684           }
2685           if (!patched) {
2686             logger.log(Level.SEVERE, format(" Could not patch %s.", residueName));
2687           } else {
2688             logger.log(Level.INFO, " Patch for {0} succeeded.", residueName);
2689             residueAtoms = residue.getAtomList();
2690             for (Atom atom : residueAtoms) {
2691               logger.info(atom.toString() + " -> " + atom.getAtomType().toString());
2692             }
2693           }
2694         } else {
2695           switch (position) {
2696             case FIRST_RESIDUE ->
2697                 buildH(residue, "HA2", CA, 1.10e0, N, 109.5e0, C, 109.5e0, 1, 355, forceField,
2698                     bondList);
2699             case LAST_RESIDUE ->
2700                 buildH(residue, "HA2", CA, 1.10e0, N, 109.5e0, C, 109.5e0, 1, 506, forceField,
2701                     bondList);
2702             default -> buildH(residue, "HA2", CA, 1.10e0, N, 109.5e0, C, 109.5e0, 1, 6, forceField,
2703                 bondList);
2704           }
2705         }
2706       }
2707     }
2708   }
2709 
2710   /**
2711    * Check for missing heavy atoms. This check ignores special terminating groups like FOR, NH2,
2712    * etc.
2713    *
2714    * @param aminoAcid a {@link AminoAcid3} object.
2715    * @param residue a {@link ffx.potential.bonded.Residue} object.
2716    * @throws ffx.potential.bonded.BondedUtils.MissingHeavyAtomException if any.
2717    */
2718   private static void checkForMissingHeavyAtoms(AminoAcid3 aminoAcid, Residue residue)
2719       throws MissingHeavyAtomException {
2720     int expected = aminoAcid.heavyAtoms;
2721     if (aminoAcid != AminoAcid3.GLY && expected >= 4) {
2722       int actual = 0;
2723       List<Atom> resAtoms = residue.getAtomList();
2724       for (Atom atom : resAtoms) {
2725         String label = atom.getName().toUpperCase();
2726         if (!(label.equalsIgnoreCase("OXT") || label.equalsIgnoreCase("OT2"))) {
2727           if (!label.startsWith("H") && !label.startsWith("D")) {
2728             actual++;
2729           }
2730         }
2731       }
2732       if (actual != expected) {
2733         Atom N = (Atom) residue.getAtomNode("N");
2734         if (N == null) {
2735           MissingHeavyAtomException e = new MissingHeavyAtomException("N", null, null);
2736           logger.warning(
2737               format(" Residue %c-%s is missing its N-terminal amide nitrogen", residue.getChainID(),
2738                   residue));
2739           throw e;
2740         }
2741         Atom CA = (Atom) residue.getAtomNode("CA");
2742         if (CA == null) {
2743           MissingHeavyAtomException e = new MissingHeavyAtomException("CA", null, null);
2744           logger.warning(
2745               format(" Residue %c-%s is missing its alpha carbon", residue.getChainID(), residue));
2746           throw e;
2747         }
2748         Atom C = (Atom) residue.getAtomNode("C");
2749         if (C == null) {
2750           MissingHeavyAtomException e = new MissingHeavyAtomException("C", null, null);
2751           logger.warning(format(" Residue %c-%s is missing its C-terminal carboxyl carbon",
2752               residue.getChainID(), residue));
2753           throw e;
2754         }
2755       }
2756     }
2757   }
2758 
2759   /**
2760    * Copy coordinates of an atom from one residue to another.
2761    *
2762    * @param fromResidue Use the coordinates from this residue.
2763    * @param toResidue Send the coordinates to this residue.
2764    * @param atomName The name of the atom whose coordinates will be updated.
2765    */
2766   private static void copyCoordinates(Residue fromResidue, Residue toResidue, String atomName) {
2767     Atom fromAtom;
2768     if (fromResidue.getAtomNode(atomName) != null) {
2769       fromAtom = (Atom) fromResidue.getAtomNode(atomName);
2770     } else {
2771       fromAtom = (Atom) fromResidue.getAtomNode("H1");
2772     }
2773 
2774     Atom toAtom = (Atom) toResidue.getAtomNode(atomName);
2775     toAtom.setXYZ(fromAtom.getXYZ(null));
2776   }
2777 
2778   /**
2779    * getAminoAcid.
2780    *
2781    * @param residueName a {@link String} object.
2782    * @return a {@link AminoAcid3} object.
2783    */
2784   public static AminoAcid3 getAminoAcid(String residueName) {
2785     for (AminoAcid3 aminoAcid : aminoAcidList) {
2786       if (aminoAcid.toString().equalsIgnoreCase(residueName)) {
2787         return aminoAcid;
2788       }
2789     }
2790     return AminoAcid3.UNK;
2791   }
2792 
2793   /**
2794    * This method takes a one letter amino acid code and converts it to a three letter amino acid
2795    * code. This method relies on the AminoAcid1 and AminoAcid3 enums having amino acids in exactly
2796    * the same order.
2797    *
2798    * @param residueName The one letter amino acid code.
2799    * @return The three letter amino acid code.
2800    */
2801   public static AminoAcid3 getAminoAcid3From1(String residueName) {
2802     for (AminoAcid1 aminoAcid : aminoAcid1List) {
2803       if (aminoAcid.toString().equalsIgnoreCase(residueName)) {
2804         int position = AminoAcid1.valueOf(residueName).ordinal();
2805         return AminoAcid3.values()[position];
2806       }
2807     }
2808     return AminoAcid3.UNK;
2809   }
2810 
2811   /**
2812    * getAminoAcidNumber.
2813    *
2814    * @param residueName a {@link String} object.
2815    * @return The index of the amino acid in the aminoAcidlist.
2816    */
2817   public static int getAminoAcidNumber(String residueName) {
2818     int aminoAcidNumber = -1;
2819     for (AminoAcid3 aminoAcid : aminoAcidList) {
2820       aminoAcidNumber++;
2821       if (aminoAcid.toString().equalsIgnoreCase(residueName)) {
2822         break;
2823       }
2824     }
2825     return aminoAcidNumber;
2826   }
2827 
2828   /**
2829    * The 20 standard amino acids.
2830    */
2831   public enum AA {
2832     GLYCINE, ALANINE, VALINE, LEUCINE, ISOLEUCINE, SERINE, THREONINE, CYSTEINE, PROLINE, PHENYLALANINE, TYROSINE, TRYPTOPHAN, ASPARTATE, ASPARAGINE, GLUTAMATE, GLUTAMINE, METHIONINE, LYSINE, ARGININE, HISTIDINE
2833   }
2834 
2835   /** Single letter amino acid codes (need to */
2836   public enum AminoAcid1 {
2837     G, A, V, L, I, S, T, C, X, c, P, F, Y, y, W, H, U, Z, D, // ASP
2838     d, // ASH
2839     p, // ASD (double protonation)
2840     N, E, // GLU
2841     e, // GLH
2842     q, // GLD (double protonation)
2843     Q, M, K, k, R, O, B, J, t, f, a, o, n, m, x
2844   }
2845 
2846   public enum AminoAcid3 {
2847     // TODO: Check GLY, SER, THR, CYS and CYD multipole assignment during MultiResidue use.
2848     GLY(4), ALA(5, true), VAL(7, true), LEU(8, true), ILE(8, true), SER(6), THR(7), CYS(6, false,
2849         true, false, false), CYX(6), CYD(6, false, false, false, false), PRO(7), PHE(11, true), TYR(
2850         12, true, false, false, false), TYD(12, true, false, false, false), TRP(14, true), HIS(10,
2851         true, true, true, false), HID(10, true, false, false, false), HIE(10, true, false, false,
2852         false), ASP(8, true, false, false, false), ASH(8, true, false, false, false), ASD(8, true,
2853         true, true, true), ASN(8, true), GLU(9, true, false, false, false), GLH(9, true, false,
2854         false, false), GLD(9, true, true, true, true), GLN(9, true), MET(8, true), LYS(9, true, true,
2855         false, false), LYD(9, true, false, false, false), ARG(11, true), ORN(8), AIB(6), PCA(8), H2N(
2856         0), FOR(0), ACE(0), COH(0), NH2(0), NME(0), UNK(0);
2857 
2858     public final int heavyAtoms;
2859     public final boolean useWithMultiResidue;
2860     public final boolean isConstantPhTitratable;
2861     public final boolean isConstantPhTautomer;
2862     public final boolean nonStandardProtonation;
2863 
2864     AminoAcid3(int heavyAtoms) {
2865       this.heavyAtoms = heavyAtoms;
2866       useWithMultiResidue = false;
2867       isConstantPhTitratable = false;
2868       isConstantPhTautomer = false;
2869       nonStandardProtonation = false;
2870     }
2871 
2872     AminoAcid3(int heavyAtoms, boolean useWithMultiResidue) {
2873       this.heavyAtoms = heavyAtoms;
2874       this.useWithMultiResidue = useWithMultiResidue;
2875       isConstantPhTitratable = false;
2876       isConstantPhTautomer = false;
2877       nonStandardProtonation = false;
2878     }
2879 
2880     AminoAcid3(int heavyAtoms, boolean useWithMultiResidue, boolean isConstantPhTitratable,
2881         boolean isConstantPhTautomer, boolean nonStandardProtonation) {
2882       this.heavyAtoms = heavyAtoms;
2883       this.useWithMultiResidue = useWithMultiResidue;
2884       this.isConstantPhTitratable = isConstantPhTitratable;
2885       this.isConstantPhTautomer = isConstantPhTautomer;
2886       this.nonStandardProtonation = nonStandardProtonation;
2887       if (nonStandardProtonation && !this.isConstantPhTitratable) {
2888         throw new IllegalArgumentException(
2889             format(" Amino acid class %s cannot be both nonstandard and non-titratable!", this));
2890       }
2891     }
2892   }
2893 
2894   /** The location of a residue within a chain. */
2895   public enum ResiduePosition {
2896     FIRST_RESIDUE, MIDDLE_RESIDUE, LAST_RESIDUE, SINGLE_RESIDUE
2897   }
2898 
2899   /**
2900    * Biotype keys for amino acid backbone atom types. These are consistent with parameter files from
2901    * TINKER v. 6.1 (June 2012). <br> xType[0][..] are for N-terminal residues. <br> xType[1][..] are
2902    * mid-chain residues. <br> xType[2][..] are for C-terminal residues.
2903    * <p>
2904    * GLY ALA VAL LEU ILE SER THR CYS CYX CYD PRO PHE TYR TYD TRP HIS HID HIE ASP ASH ASD ASN GLU GLH
2905    * GLD GLN MET LYS LYD ARG ORN AIB PCA H2N FOR ACE COH NH2 NME UNK
2906    */
2907   public static final int[][] AA_N = {
2908       {403, 409, 415, 421, 427, 433, 439, 445, 451, 457, 463, 471, 477, 483, 489, 495, 501, 507, 513,
2909           519, 519, 525, 531, 537, 537, 543, 549, 555, 561, 567, 573, 579, 391, 762, 0, 0, 0, 0, 0,
2910           403},
2911       {1, 7, 15, 27, 41, 55, 65, 77, 87, 96, 105, 116, 131, 147, 162, 185, 202, 218, 234, 244, 244,
2912           256, 268, 280, 280, 294, 308, 321, 337, 353, 370, 384, 391, 0, 0, 0, 0, 0, 0, 1},
2913       {584, 590, 596, 602, 608, 614, 620, 626, 632, 638, 644, 649, 655, 661, 667, 673, 679, 685, 691,
2914           697, 697, 703, 709, 715, 715, 721, 727, 733, 739, 745, 751, 757, 0, 0, 0, 0, 773, 775, 777,
2915           584},
2916       {403, 409, 415, 421, 427, 433, 439, 445, 451, 457, 463, 471, 477, 483, 489, 495, 501, 507, 513,
2917           519, 519, 525, 531, 537, 537, 543, 549, 555, 561, 567, 573, 579, 391, 762, 0, 0, 0, 0, 0,
2918           403}};
2919 
2920   /**
2921    * Constant <code>AA_CA</code>
2922    * <p>
2923    * GLY ALA VAL LEU ILE SER THR CYS CYX CYD PRO PHE TYR TYD TRP HIS HID HIE ASP ASH ASD ASN GLU GLH
2924    * GLD GLN MET LYS LYD ARG ORN AIB PCA H2N FOR ACE COH NH2 NME UNK
2925    */
2926   public static final int[][] AA_CA = {
2927       {404, 410, 416, 422, 428, 434, 440, 446, 452, 458, 464, 472, 478, 484, 490, 496, 502, 508, 514,
2928           520, 520, 526, 532, 538, 538, 544, 550, 556, 562, 568, 574, 580, 392, 0, 0, 767, 0, 0, 0,
2929           404},
2930       {2, 8, 16, 28, 42, 56, 66, 78, 88, 97, 106, 117, 132, 148, 163, 186, 203, 219, 235, 245, 245,
2931           257, 269, 281, 281, 295, 309, 322, 338, 354, 371, 385, 392, 0, 0, 0, 0, 0, 0, 2},
2932       {585, 591, 597, 603, 609, 615, 621, 627, 633, 639, 645, 650, 656, 662, 668, 674, 680, 686, 692,
2933           698, 698, 704, 710, 716, 716, 722, 728, 734, 740, 746, 752, 758, 0, 0, 0, 0, 0, 0, 779,
2934           585},
2935       {2, 8, 16, 28, 42, 56, 66, 78, 88, 97, 106, 117, 132, 148, 163, 186, 203, 219, 235, 245, 245,
2936           257, 269, 281, 281, 295, 309, 322, 338, 354, 371, 385, 392, 0, 0, 0, 0, 0, 0, 2}};
2937 
2938   /**
2939    * Constant <code>AA_C</code>
2940    * <p>
2941    * GLY ALA VAL LEU ILE SER THR CYS CYX CYD PRO PHE TYR TYD TRP HIS HID HIE ASP ASH ASD ASN GLU GLH
2942    * GLD GLN MET LYS LYD ARG ORN AIB PCA H2N FOR ACE COH NH2 NME UNK
2943    */
2944   public static final int[][] AA_C = {
2945       {405, 411, 417, 423, 429, 435, 441, 447, 453, 459, 465, 473, 479, 485, 491, 497, 503, 509, 515,
2946           521, 521, 527, 533, 539, 539, 545, 551, 557, 563, 569, 575, 581, 393, 0, 764, 769, 0, 0, 0,
2947           405},
2948       {3, 9, 17, 29, 43, 57, 67, 79, 89, 98, 107, 118, 133, 149, 164, 187, 204, 220, 236, 246, 246,
2949           258, 270, 282, 282, 296, 310, 323, 339, 355, 372, 386, 393, 0, 0, 0, 0, 0, 0, 3},
2950       {586, 592, 598, 604, 610, 616, 622, 628, 634, 640, 646, 651, 657, 663, 669, 675, 681, 687, 693,
2951           699, 699, 705, 711, 717, 717, 723, 729, 735, 741, 747, 753, 759, 0, 0, 0, 0, 771, 0, 0,
2952           586},
2953       {586, 592, 598, 604, 610, 616, 622, 628, 634, 640, 646, 651, 657, 663, 669, 675, 681, 687, 693,
2954           699, 699, 705, 711, 717, 717, 723, 729, 735, 741, 747, 753, 759, 0, 0, 0, 0, 771, 0, 0,
2955           586}};
2956 
2957   /**
2958    * Constant <code>AA_HN</code>
2959    * <p>
2960    * GLY ALA VAL LEU ILE SER THR CYS CYX CYD PRO PHE TYR TYD TRP HIS HID HIE ASP ASH ASD ASN GLU GLH
2961    * GLD GLN MET LYS LYD ARG ORN AIB PCA H2N FOR ACE COH NH2 NME UNK
2962    */
2963   public static final int[][] AA_HN = {
2964       {406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466, 474, 480, 486, 492, 498, 504, 510, 516,
2965           522, 522, 528, 534, 540, 540, 546, 552, 558, 564, 570, 576, 582, 394, 763, 0, 0, 0, 0, 0,
2966           406},
2967       {4, 10, 18, 30, 44, 58, 68, 80, 90, 99, 0, 119, 134, 150, 165, 188, 205, 221, 237, 247, 247,
2968           259, 271, 283, 283, 297, 311, 324, 340, 356, 373, 387, 394, 0, 0, 0, 0, 0, 0, 4},
2969       {587, 593, 599, 605, 611, 617, 623, 629, 635, 641, 0, 652, 658, 664, 670, 676, 682, 688, 694,
2970           700, 700, 706, 712, 718, 718, 724, 730, 736, 742, 748, 754, 760, 0, 0, 0, 0, 774, 776, 778,
2971           587},
2972       {406, 412, 418, 424, 430, 436, 442, 448, 454, 460, 466, 474, 480, 486, 492, 498, 504, 510, 516,
2973           522, 522, 528, 534, 540, 540, 546, 552, 558, 564, 570, 576, 582, 394, 763, 0, 0, 0, 0, 0,
2974           406}};
2975 
2976   /**
2977    * Constant <code>AA_O</code>
2978    * <p>
2979    * GLY ALA VAL LEU ILE SER THR CYS CYX CYD PRO PHE TYR TYD TRP HIS HID HIE ASP ASH ASD ASN GLU GLH
2980    * GLD GLN MET LYS LYD ARG ORN AIB PCA H2N FOR ACE COH NH2 NME UNK
2981    */
2982   public static final int[][] AA_O = {
2983       {407, 413, 419, 425, 431, 437, 443, 449, 455, 461, 467, 475, 481, 487, 493, 499, 505, 511, 517,
2984           523, 523, 529, 535, 541, 541, 547, 553, 559, 565, 571, 577, 583, 395, 0, 766, 770, 0, 0, 0,
2985           407},
2986       {5, 11, 19, 31, 45, 59, 69, 81, 91, 100, 108, 120, 135, 151, 166, 189, 206, 222, 238, 248, 248,
2987           260, 272, 284, 284, 298, 312, 325, 341, 357, 374, 388, 395, 0, 0, 0, 0, 0, 0, 5},
2988       {588, 594, 600, 606, 612, 618, 624, 630, 636, 642, 647, 653, 659, 665, 671, 677, 683, 689, 695,
2989           701, 701, 707, 713, 719, 719, 725, 731, 737, 743, 749, 755, 761, 0, 0, 0, 0, 772, 0, 0,
2990           588},
2991       {588, 594, 600, 606, 612, 618, 624, 630, 636, 642, 647, 653, 659, 665, 671, 677, 683, 689, 695,
2992           701, 701, 707, 713, 719, 719, 725, 731, 737, 743, 749, 755, 761, 0, 0, 0, 0, 772, 0, 0,
2993           588}};
2994 
2995   /**
2996    * Constant <code>AA_HA</code>
2997    * <p>
2998    * GLY ALA VAL LEU ILE SER THR CYS CYX CYD PRO PHE TYR TYD TRP HIS HID HIE ASP ASH ASD ASN GLU GLH
2999    * GLD GLN MET LYS LYD ARG ORN AIB PCA H2N FOR ACE COH NH2 NME UNK
3000    */
3001   public static final int[][] AA_HA = {
3002       {408, 414, 420, 426, 432, 438, 444, 450, 456, 462, 468, 476, 482, 488, 494, 500, 506, 512, 518,
3003           524, 524, 530, 536, 542, 542, 548, 554, 560, 566, 572, 578, 0, 396, 0, 765, 768, 0, 0, 0,
3004           408},
3005       {6, 12, 20, 32, 46, 60, 70, 82, 92, 101, 109, 121, 136, 152, 167, 190, 207, 223, 239, 249, 249,
3006           261, 273, 285, 285, 299, 313, 326, 342, 358, 375, 0, 396, 0, 0, 0, 0, 0, 0, 6},
3007       {589, 595, 601, 607, 613, 619, 625, 631, 637, 643, 648, 654, 660, 666, 672, 678, 684, 690, 696,
3008           702, 702, 708, 714, 720, 720, 726, 732, 738, 744, 750, 756, 0, 0, 0, 0, 0, 0, 0, 780, 589},
3009       {6, 12, 20, 32, 46, 60, 70, 82, 92, 101, 109, 121, 136, 152, 167, 190, 207, 223, 239, 249, 249,
3010           261, 273, 285, 285, 299, 313, 326, 342, 358, 375, 0, 396, 0, 0, 0, 0, 0, 0, 6}};
3011 
3012   /**
3013    * Constant <code>AA_CB</code>
3014    * <p>
3015    * GLY ALA VAL LEU ILE SER THR CYS CYX CYD PRO PHE TYR TYD TRP HIS HID HIE ASP ASH ASD ASN GLU GLH
3016    * GLD GLN MET LYS LYD ARG ORN AIB PCA H2N FOR ACE COH NH2 NME UNK
3017    */
3018   public static final int[] AA_CB = {0, 13, 21, 33, 47, 61, 71, 83, 93, 102, 110, 122, 137, 153, 168,
3019       191, 208, 224, 240, 250, 806, 262, 274, 286, 817, 300, 314, 327, 343, 359, 376, 389, 397, 0, 0,
3020       0, 0, 0, 0, 0};
3021 }