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