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