001package com.hfg.bio;
002
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.Collections;
006import java.util.Comparator;
007import java.util.Map;
008import java.util.Set;
009
010import com.hfg.chem.Charge;
011import com.hfg.chem.Element;
012import com.hfg.chem.IonizableGroup;
013import com.hfg.chem.Molecule;
014import com.hfg.exception.UnmodifyableObjectException;
015import com.hfg.util.CompareUtil;
016import com.hfg.util.collection.OrderedSet;
017import com.hfg.xml.XMLNode;
018import com.hfg.xml.XMLTag;
019import com.hfg.xml.XMLAttribute;
020import com.hfg.util.StringUtil;
021import com.hfg.util.collection.CollectionUtil;
022
023//------------------------------------------------------------------------------
024/**
025 Amino Acid. Estimated pKa values are from: Jack Kyte, "Structure in Protein Chemistry" (1995), Garland Publishing, Inc.
026 See <a href='http://www.chem.qmul.ac.uk/iupac/AminoAcid/A2021.html'>Nomenclature and Symbolism for Amino Acids and Peptides</a>.
027 <div>
028  @author J. Alex Taylor, hairyfatguy.com
029 </div>
030 */
031//------------------------------------------------------------------------------
032// com.hfg XML/HTML Coding Library
033//
034// This library is free software; you can redistribute it and/or
035// modify it under the terms of the GNU Lesser General Public
036// License as published by the Free Software Foundation; either
037// version 2.1 of the License, or (at your option) any later version.
038//
039// This library is distributed in the hope that it will be useful,
040// but WITHOUT ANY WARRANTY; without even the implied warranty of
041// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
042// Lesser General Public License for more details.
043//
044// You should have received a copy of the GNU Lesser General Public
045// License along with this library; if not, write to the Free Software
046// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
047//
048// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
049// jataylor@hairyfatguy.com
050//------------------------------------------------------------------------------
051
052public class AminoAcid extends Molecule
053{
054   // This declaration has to come before the public constants below.
055   private static final Set<AminoAcid> sValues = new OrderedSet<>(100);
056
057   //##########################################################################
058   // PUBLIC FIELDS
059   //##########################################################################
060
061   public static final AminoAcid ALANINE       = new AminoAcid("Alanine",       "Ala", 'A',  100);
062   public static final AminoAcid ARGININE      = new AminoAcid("Arginine",      "Arg", 'R',  200);
063   public static final AminoAcid ASPARAGINE    = new AminoAcid("Asparagine",    "Asn", 'N',  300);
064   public static final AminoAcid ASPARTIC_ACID = new AminoAcid("Aspartic Acid", "Asp", 'D',  400);
065   public static final AminoAcid CYSTEINE      = new AminoAcid("Cysteine",      "Cys", 'C',  500);
066   public static final AminoAcid GLUTAMIC_ACID = new AminoAcid("Glutamic Acid", "Glu", 'E',  600);
067   public static final AminoAcid GLUTAMINE     = new AminoAcid("Glutamine",     "Gln", 'Q',  700);
068   public static final AminoAcid GLYCINE       = new AminoAcid("Glycine",       "Gly", 'G',  800);
069   public static final AminoAcid HISTIDINE     = new AminoAcid("Histidine",     "His", 'H',  900);
070   public static final AminoAcid ISOLEUCINE    = new AminoAcid("Isoleucine",    "Ile", 'I', 1000);
071   public static final AminoAcid LEUCINE       = new AminoAcid("Leucine",       "Leu", 'L', 1100);
072   public static final AminoAcid LYSINE        = new AminoAcid("Lysine",        "Lys", 'K', 1200);
073   public static final AminoAcid METHIONINE    = new AminoAcid("Methionine",    "Met", 'M', 1300);
074   public static final AminoAcid PHENYLALANINE = new AminoAcid("Phenylalanine", "Phe", 'F', 1400);
075   public static final AminoAcid PROLINE       = new AminoAcid("Proline",       "Pro", 'P', 1500);
076   public static final AminoAcid SERINE        = new AminoAcid("Serine",        "Ser", 'S', 1600);
077   public static final AminoAcid THREONIE      = new AminoAcid("Threonine",     "Thr", 'T', 1700);
078   public static final AminoAcid TRYPTOPHAN    = new AminoAcid("Tryptophan",    "Trp", 'W', 1800);
079   public static final AminoAcid TYROSINE      = new AminoAcid("Tyrosine",      "Tyr", 'Y', 1900);
080   public static final AminoAcid VALINE        = new AminoAcid("Valine",        "Val", 'V', 2000);
081
082   /** http://www.albany.edu/faculty/cs812/bio366/selenocysteine_ppt.pdf */
083   public static final AminoAcid SELENOCYSTEINE = new AminoAcid("Selenocysteine", "SeC", 'U');
084   /** Zhang Y, Baranov PV, Atkins JF, Gladyshev VN (May 2005).
085    * "Pyrrolysine and selenocysteine use dissimilar decoding strategies".
086    * The Journal of Biological Chemistry. 280 (21): 20740–51. doi:10.1074/jbc.M501458200. PMID 15788401.
087    */
088   public static final AminoAcid PYRROLYSINE   = new AminoAcid("Pyrrolysine", "Pyl", 'O');
089
090   public static final AminoAcid ASP_ASN_AVG   = new AminoAcid("Asp/Asn avg", "Asx", 'B');
091   public static final AminoAcid GLU_GLN_AVG   = new AminoAcid("Glu/Gln avg", "Glx", 'Z');
092   /** The NCBI has starting using 'J' to represent Ile/Leu ambiguity */
093   public static final AminoAcid ILE_LEU_AVG   = new AminoAcid("Ile/Leu avg", "Ilx", 'J');
094
095
096   public static final AminoAcid UNDEFINED     = new AminoAcid("Undefined", "Unk", 'X', 2100);
097   public static final AminoAcid STOP          = new AminoAcid("Stop",      "*",   '*', 2200);
098
099   // D-amino acids
100   public static final AminoAcid D_ALANINE       = new AminoAcid("D-Alanine",       "DAL");
101   public static final AminoAcid D_ARGININE      = new AminoAcid("D-Arginine",      "DAR");
102   public static final AminoAcid D_ASPARAGINE    = new AminoAcid("D-Asparagine",    "DSG");
103   public static final AminoAcid D_ASPARTIC_ACID = new AminoAcid("D-Aspartic Acid", "DAS");
104   public static final AminoAcid D_CYSTEINE      = new AminoAcid("D-Cysteine",      "DCY");
105   public static final AminoAcid D_GLUTAMIC_ACID = new AminoAcid("D-Glutamic Acid", "DGL");
106   public static final AminoAcid D_GLUTAMINE     = new AminoAcid("D-Glutamine",     "DGN");
107   public static final AminoAcid D_HISTIDINE     = new AminoAcid("D-Histidine",     "DHI");
108   public static final AminoAcid D_ISOLEUCINE    = new AminoAcid("D-Isoleucine",    "DIL");
109   public static final AminoAcid D_LEUCINE       = new AminoAcid("D-Leucine",       "DLE");
110   public static final AminoAcid D_LYSINE        = new AminoAcid("D-Lysine",        "DLY");
111   public static final AminoAcid D_METHIONINE    = new AminoAcid("D-Methionine",    "MED");
112   public static final AminoAcid D_PHENYLALANINE = new AminoAcid("D-Phenylalanine", "DPN");
113   public static final AminoAcid D_PROLINE       = new AminoAcid("D-Proline",       "DPR");
114   public static final AminoAcid D_SERINE        = new AminoAcid("D-Serine",        "DSN");
115   public static final AminoAcid D_THREONIE      = new AminoAcid("D-Threonine",     "DTH");
116   public static final AminoAcid D_TRYPTOPHAN    = new AminoAcid("D-Tryptophan",    "DTR");
117   public static final AminoAcid D_TYROSINE      = new AminoAcid("D-Tyrosine",      "DTY");
118   public static final AminoAcid D_VALINE        = new AminoAcid("D-Valine",        "DVA");
119   public static final AminoAcid D_ISOVALINE     = new AminoAcid("D-Isovaline",     "DIV");
120
121
122   // Common modified amino acids
123   public static final AminoAcid ARG_N_METHYL        = new AminoAcid("Arginine, N-methyl");
124   public static final AminoAcid ASP_HYDROXY         = new AminoAcid("Aspartic acid, Hydroxy");
125   public static final AminoAcid CITRULLINE          = new AminoAcid("Citrulline");
126   public static final AminoAcid CYS_ACETAMIDOMETHYL = new AminoAcid("Cysteine, Acetamidomethyl",    "", 'c');
127   public static final AminoAcid CYS_AMINOETHYL      = new AminoAcid("Cysteine, Aminoethyl",    "", 'c');
128   public static final AminoAcid CYS_CARBAMIDOMETHYL = new AminoAcid("Cysteine, Carbamidomethyl", "CAC", 'c');
129   public static final AminoAcid CYS_CARBOXYMETHYL   = new AminoAcid("Cysteine, Carboxymethyl", "CMC", 'c');
130   public static final AminoAcid CYS_PYRIDYLETHYL    = new AminoAcid("Cysteine, Pyridylethyl", "", 'c');
131   public static final AminoAcid CYS_S_FARNESYL      = new AminoAcid("Cysteine, S-farnesyl", "", 'c');
132   public static final AminoAcid CYS_S_PALMITYL      = new AminoAcid("Cysteine, S-palmityl", "", 'c');
133   public static final AminoAcid CYS_S_HYDROXY       = new AminoAcid("Cysteine, S-hydroxy", "CSO", 'c');
134   public static final AminoAcid CYS_S_DIOXIDE       = new AminoAcid("Cysteine, S-dioxide", "CSW", 'c');
135   public static final AminoAcid CYS_S_PHOSPHO       = new AminoAcid("Cysteine, S-phospho", "CSP", 'c');
136   public static final AminoAcid CYS_2_HYDROXYETHYL_THIOCYSTEINE = new AminoAcid("S,S-(2-Hydroxyethyl)Thiocysteine", "CME");
137   public static final AminoAcid CYS_SULFONIC_ACID   = new AminoAcid("Cysteinesulfonic acid", "OCS");
138   public static final AminoAcid DEHYDROALANINE      = new AminoAcid("Dehydroalanine");
139   public static final AminoAcid THREE_SULFINOALANINE = new AminoAcid("3-Sulfinoalanine", "CSD");
140   public static final AminoAcid HOMOSERINE          = new AminoAcid("Homoserine");
141   public static final AminoAcid LYS_ACETYLATED      = new AminoAcid("Lysine, Acetylated", "ALY");
142   public static final AminoAcid LYS_HYDROXY         = new AminoAcid("Lysine, Hydroxy");
143   public static final AminoAcid LYS_N_METHYL        = new AminoAcid("Lysine, N-methyl");
144   public static final AminoAcid LYS_N_DIMETHYL      = new AminoAcid("Lysine, N-dimethyl", "MLY");
145   public static final AminoAcid LYS_N_TRIMETHYL     = new AminoAcid("Lysine, N-trimethyl", "M3L");
146   public static final AminoAcid LYS_NZ_CARBOXYLIC_ACID = new AminoAcid("Lysine, NZ-carboxylic acid", "KCX");
147   public static final AminoAcid MET_SULFONE         = new AminoAcid("Methionine Sulfone");
148   public static final AminoAcid MET_SULFOXIDE       = new AminoAcid("Methionine Sulfoxide");
149   public static final AminoAcid MET_S_DIXOY         = new AminoAcid("Methionine S-dioxy", "OMT");
150   public static final AminoAcid SELENOMETHIONINE    = new AminoAcid("Selenomethionine", "MSE");
151   public static final AminoAcid NORVALINE           = new AminoAcid("Norvaline", "NVA");
152   public static final AminoAcid NORLEUCINE          = new AminoAcid("Norleucine", "NLE");
153   public static final AminoAcid ORNITHINE           = new AminoAcid("Ornithine", "ORN", 'O');
154   public static final AminoAcid PRO_HYDROXY         = new AminoAcid("Proline, Hydroxy", "HYP");
155   public static final AminoAcid SARCOSINE           = new AminoAcid("Sarcosine", "SAR");
156   public static final AminoAcid SER_PHOSPHO         = new AminoAcid("Serine, Phospho", "SEP");
157   public static final AminoAcid THR_PHOSPHO         = new AminoAcid("Threonine, Phospho", "TPO");
158   public static final AminoAcid TYR_PHOSPHO         = new AminoAcid("Tyrosine, Phospho", "PTR");
159   public static final AminoAcid TYR_O_SULFO         = new AminoAcid("Tyrosine, O-sulfo", "TYS");
160   public static final AminoAcid ALPHA_AMINOBUTYRIC_ACID = new AminoAcid("Alpha-aminobutyric acid", "ABA");
161   public static final AminoAcid AMINO_MERCAPTO_BUTYRIC_ACID = new AminoAcid("2-Amino-4-mercapto-butyric acid", "HCS");
162   public static final AminoAcid ALPHA_AMINOISOBUTYRIC_ACID = new AminoAcid("Alpha-aminoisobutyric acid", "AIB");
163   public static final AminoAcid HIS_4_METHYL        = new AminoAcid("4-Methyl-histidine", "HIC");
164   public static final AminoAcid LLP                 = new AminoAcid("(2S)-2-amino-6-[[3-hydroxy-2-methyl-5-(phosphonooxymethyl)pyridin-4-yl]methylideneamino]hexanoic acid", "LLP");
165   public static final AminoAcid ASN_N_METHYL        = new AminoAcid("Asparagine, N-methyl", "MEN");
166
167   // Differing protonation states of histidine
168   public static final AminoAcid HISTIDINE_HID        = new AminoAcid("Histidine neutral δ-protonated (HID)", "HID");
169   public static final AminoAcid HISTIDINE_HIE        = new AminoAcid("Histidine neutral ε-protonated (HIE)", "HIE");
170   public static final AminoAcid HISTIDINE_HIP        = new AminoAcid("Histidine protonated on both sidechain nitrogens (HIP)", "HIP");
171
172
173   public static final Comparator<AminoAcid> AA_ORDINAL_COMPARATOR = GLYCINE.new AAOrdinalComparator();
174
175   static
176   {
177      GLYCINE.addAtoms(Element.CARBON, 2)
178         .addAtoms(Element.HYDROGEN, 3)
179         .addAtoms(Element.NITROGEN, 1)
180         .addAtoms(Element.OXYGEN, 1)
181         .lock()
182         .register();
183
184      ALANINE.addAtoms(Element.CARBON, 3)
185         .addAtoms(Element.HYDROGEN, 5)
186         .addAtoms(Element.NITROGEN, 1)
187         .addAtoms(Element.OXYGEN, 1)
188         .lock()
189         .register();
190
191      SERINE.addAtoms(Element.CARBON, 3)
192         .addAtoms(Element.HYDROGEN, 5)
193         .addAtoms(Element.NITROGEN, 1)
194         .addAtoms(Element.OXYGEN, 2)
195         .lock()
196         .register();
197
198      PROLINE.addAtoms(Element.CARBON, 5)
199         .addAtoms(Element.HYDROGEN, 7)
200         .addAtoms(Element.NITROGEN, 1)
201         .addAtoms(Element.OXYGEN, 1)
202         .lock()
203         .register();
204
205      VALINE.addAtoms(Element.CARBON, 5)
206         .addAtoms(Element.HYDROGEN, 9)
207         .addAtoms(Element.NITROGEN, 1)
208         .addAtoms(Element.OXYGEN, 1)
209         .lock()
210         .register();
211
212      THREONIE.addAtoms(Element.CARBON, 4)
213         .addAtoms(Element.HYDROGEN, 7)
214         .addAtoms(Element.NITROGEN, 1)
215         .addAtoms(Element.OXYGEN, 2)
216         .lock()
217         .register();
218
219      CYSTEINE.addAtoms(Element.CARBON, 3)
220         .addAtoms(Element.HYDROGEN, 5)
221         .addAtoms(Element.NITROGEN, 1)
222         .addAtoms(Element.OXYGEN, 1)
223         .addAtoms(Element.SULFUR, 1)
224//         .addSidechainKa(new IonizableGroup(5E-9, Charge.NEUTRAL)) // pKa 8.3
225         .addSidechainKa(new IonizableGroup(2.0E-9, Charge.NEUTRAL)) // pKa 8.7
226         .lock()
227         .register();
228
229      ISOLEUCINE.addAtoms(Element.CARBON, 6)
230         .addAtoms(Element.HYDROGEN, 11)
231         .addAtoms(Element.NITROGEN, 1)
232         .addAtoms(Element.OXYGEN, 1)
233         .lock()
234         .register();
235
236      LEUCINE.addAtoms(Element.CARBON, 6)
237         .addAtoms(Element.HYDROGEN, 11)
238         .addAtoms(Element.NITROGEN, 1)
239         .addAtoms(Element.OXYGEN, 1)
240         .lock()
241         .register();
242
243      ASPARAGINE.addAtoms(Element.CARBON, 4)
244         .addAtoms(Element.HYDROGEN, 6)
245         .addAtoms(Element.NITROGEN, 2)
246         .addAtoms(Element.OXYGEN, 2)
247         .lock()
248         .register();
249
250      ASPARTIC_ACID.addAtoms(Element.CARBON, 4)
251         .addAtoms(Element.HYDROGEN, 5)
252         .addAtoms(Element.NITROGEN, 1)
253         .addAtoms(Element.OXYGEN, 3)
254//         .addSidechainKa(new IonizableGroup(1.23E-4, Charge.NEUTRAL))   // pKa 3.9
255         .addSidechainKa(new IonizableGroup(1.0E-4, Charge.NEUTRAL))  // pKa 4.0
256         .lock()
257         .register();
258
259
260      GLUTAMINE.addAtoms(Element.CARBON, 5)
261         .addAtoms(Element.HYDROGEN, 8)
262         .addAtoms(Element.NITROGEN, 2)
263         .addAtoms(Element.OXYGEN, 2)
264         .lock()
265         .register();
266
267      LYSINE.addAtoms(Element.CARBON, 6)
268         .addAtoms(Element.HYDROGEN, 12)
269         .addAtoms(Element.NITROGEN, 2)
270         .addAtoms(Element.OXYGEN, 1)
271//         .addSidechainKa(new IonizableGroup(1.62E-11, Charge.POSITIVE))     // pKa 10.8
272         .addSidechainKa(new IonizableGroup(3.2E-11, Charge.POSITIVE))     // pKa 10.5
273         .lock()
274         .register();
275
276      GLUTAMIC_ACID.addAtoms(Element.CARBON, 5)
277         .addAtoms(Element.HYDROGEN, 7)
278         .addAtoms(Element.NITROGEN, 1)
279         .addAtoms(Element.OXYGEN, 3)
280//         .addSidechainKa(new IonizableGroup(5.62E-5, Charge.NEUTRAL))  // pKa 4.25
281         .addSidechainKa(new IonizableGroup(5.0E-5, Charge.NEUTRAL))  // pKa 4.3
282         .lock()
283         .register();
284
285      METHIONINE.addAtoms(Element.CARBON, 5)
286         .addAtoms(Element.HYDROGEN, 9)
287         .addAtoms(Element.NITROGEN, 1)
288         .addAtoms(Element.OXYGEN, 1)
289         .addAtoms(Element.SULFUR, 1)
290         .lock()
291         .register();
292
293      HISTIDINE.addAtoms(Element.CARBON, 6)
294         .addAtoms(Element.HYDROGEN, 7)
295         .addAtoms(Element.NITROGEN, 3)
296         .addAtoms(Element.OXYGEN, 1)
297//         .addSidechainKa(new IonizableGroup(3.16E-7, Charge.POSITIVE))   // pKa 6.5
298         .addSidechainKa(new IonizableGroup(4.0E-7, Charge.POSITIVE))   // pKa 6.4
299         .lock()
300         .register();
301
302      PHENYLALANINE.addAtoms(Element.CARBON, 9)
303         .addAtoms(Element.HYDROGEN, 9)
304         .addAtoms(Element.NITROGEN, 1)
305         .addAtoms(Element.OXYGEN, 1)
306         .lock()
307         .register();
308
309      ARGININE.addAtoms(Element.CARBON, 6)
310         .addAtoms(Element.HYDROGEN, 12)
311         .addAtoms(Element.NITROGEN, 4)
312         .addAtoms(Element.OXYGEN, 1)
313//         .addSidechainKa(new IonizableGroup(3.16E-13, Charge.POSITIVE)) // pKa 12.5
314         .addSidechainKa(new IonizableGroup(1.0E-13, Charge.POSITIVE)) // pKa 13
315         .lock()
316         .register();
317
318      TYROSINE.addAtoms(Element.CARBON, 9)
319         .addAtoms(Element.HYDROGEN, 9)
320         .addAtoms(Element.NITROGEN, 1)
321         .addAtoms(Element.OXYGEN, 2)
322//         .addSidechainKa(new IonizableGroup(1.12E-11, Charge.NEUTRAL))  // pKa 10.95
323         .addSidechainKa(new IonizableGroup(1.6E-10, Charge.NEUTRAL))  // pKa 9.8
324         .lock()
325         .register();
326
327      TRYPTOPHAN.addAtoms(Element.CARBON, 11)
328         .addAtoms(Element.HYDROGEN, 10)
329         .addAtoms(Element.NITROGEN, 2)
330         .addAtoms(Element.OXYGEN, 1)
331         .lock()
332         .register();
333
334
335
336      SELENOCYSTEINE.addSidechainKa(new IonizableGroup(2.0E-6, Charge.NEUTRAL)) // pKa 5.7
337         .addAtoms(Element.CARBON, 3)
338         .addAtoms(Element.HYDROGEN, 5)
339         .addAtoms(Element.NITROGEN, 1)
340         .addAtoms(Element.OXYGEN, 1)
341         .addAtoms(Element.SELENIUM, 1)
342         .lock()
343         .register();
344
345      PYRROLYSINE.addAtoms(Element.CARBON, 12)
346         .addAtoms(Element.HYDROGEN, 19)
347         .addAtoms(Element.NITROGEN, 3)
348         .addAtoms(Element.OXYGEN, 2)
349         .lock()
350         .register();
351
352
353      ASP_ASN_AVG.addAtoms(Element.CARBON, 4)
354         .addAtoms(Element.HYDROGEN, 5.5f)
355         .addAtoms(Element.NITROGEN, 1.5f)
356         .addAtoms(Element.OXYGEN, 2.5f);
357      ASP_ASN_AVG.mIsApproximation = true;
358      ASP_ASN_AVG.lock()
359         .register();
360
361
362      GLU_GLN_AVG.addAtoms(Element.CARBON, 5)
363         .addAtoms(Element.HYDROGEN, 7.5f)
364         .addAtoms(Element.NITROGEN, 1.5f)
365         .addAtoms(Element.OXYGEN, 2.5f);
366      GLU_GLN_AVG.mIsApproximation = true;
367      GLU_GLN_AVG.lock()
368         .register();
369
370      ILE_LEU_AVG.addAtoms(Element.CARBON, 6)
371         .addAtoms(Element.HYDROGEN, 11)
372         .addAtoms(Element.NITROGEN, 1)
373         .addAtoms(Element.OXYGEN, 1)
374         .lock()
375         .register();
376
377
378      UNDEFINED.lock()
379         .register();
380
381      STOP.lock()
382         .register();
383
384      // D-amino acids
385      D_ALANINE.addAtoms(Element.CARBON, 3)
386            .addAtoms(Element.HYDROGEN, 5)
387            .addAtoms(Element.NITROGEN, 1)
388            .addAtoms(Element.OXYGEN, 1)
389            .lock()
390            .register();
391
392      D_SERINE.addAtoms(Element.CARBON, 3)
393            .addAtoms(Element.HYDROGEN, 5)
394            .addAtoms(Element.NITROGEN, 1)
395            .addAtoms(Element.OXYGEN, 2)
396            .lock()
397            .register();
398
399      D_PROLINE.addAtoms(Element.CARBON, 5)
400            .addAtoms(Element.HYDROGEN, 7)
401            .addAtoms(Element.NITROGEN, 1)
402            .addAtoms(Element.OXYGEN, 1)
403            .lock()
404            .register();
405
406      D_VALINE.addAtoms(Element.CARBON, 5)
407            .addAtoms(Element.HYDROGEN, 9)
408            .addAtoms(Element.NITROGEN, 1)
409            .addAtoms(Element.OXYGEN, 1)
410            .lock()
411            .register();
412
413      D_ISOVALINE.addAtoms(Element.CARBON, 5)
414            .addAtoms(Element.HYDROGEN, 9)
415            .addAtoms(Element.NITROGEN, 1)
416            .addAtoms(Element.OXYGEN, 1)
417            .lock()
418            .register();
419
420      D_THREONIE.addAtoms(Element.CARBON, 4)
421            .addAtoms(Element.HYDROGEN, 7)
422            .addAtoms(Element.NITROGEN, 1)
423            .addAtoms(Element.OXYGEN, 2)
424            .lock()
425            .register();
426
427      D_CYSTEINE.addAtoms(Element.CARBON, 3)
428            .addAtoms(Element.HYDROGEN, 5)
429            .addAtoms(Element.NITROGEN, 1)
430            .addAtoms(Element.OXYGEN, 1)
431            .addAtoms(Element.SULFUR, 1)
432            .addSidechainKa(new IonizableGroup(2.0E-9, Charge.NEUTRAL)) // pKa 8.7
433            .lock()
434            .register();
435
436      D_ISOLEUCINE.addAtoms(Element.CARBON, 6)
437            .addAtoms(Element.HYDROGEN, 11)
438            .addAtoms(Element.NITROGEN, 1)
439            .addAtoms(Element.OXYGEN, 1)
440            .lock()
441            .register();
442
443      D_LEUCINE.addAtoms(Element.CARBON, 6)
444            .addAtoms(Element.HYDROGEN, 11)
445            .addAtoms(Element.NITROGEN, 1)
446            .addAtoms(Element.OXYGEN, 1)
447            .lock()
448            .register();
449
450      D_ASPARAGINE.addAtoms(Element.CARBON, 4)
451            .addAtoms(Element.HYDROGEN, 6)
452            .addAtoms(Element.NITROGEN, 2)
453            .addAtoms(Element.OXYGEN, 2)
454            .lock()
455            .register();
456
457      D_ASPARTIC_ACID.addAtoms(Element.CARBON, 4)
458            .addAtoms(Element.HYDROGEN, 5)
459            .addAtoms(Element.NITROGEN, 1)
460            .addAtoms(Element.OXYGEN, 3)
461            .addSidechainKa(new IonizableGroup(1.0E-4, Charge.NEUTRAL))  // pKa 4.0
462            .lock()
463            .register();
464
465
466      D_GLUTAMINE.addAtoms(Element.CARBON, 5)
467            .addAtoms(Element.HYDROGEN, 8)
468            .addAtoms(Element.NITROGEN, 2)
469            .addAtoms(Element.OXYGEN, 2)
470            .lock()
471            .register();
472
473      D_LYSINE.addAtoms(Element.CARBON, 6)
474            .addAtoms(Element.HYDROGEN, 12)
475            .addAtoms(Element.NITROGEN, 2)
476            .addAtoms(Element.OXYGEN, 1)
477            .addSidechainKa(new IonizableGroup(3.2E-11, Charge.POSITIVE))     // pKa 10.5
478            .lock()
479            .register();
480
481      D_GLUTAMIC_ACID.addAtoms(Element.CARBON, 5)
482            .addAtoms(Element.HYDROGEN, 7)
483            .addAtoms(Element.NITROGEN, 1)
484            .addAtoms(Element.OXYGEN, 3)
485            .addSidechainKa(new IonizableGroup(5.0E-5, Charge.NEUTRAL))  // pKa 4.3
486            .lock()
487            .register();
488
489      D_METHIONINE.addAtoms(Element.CARBON, 5)
490            .addAtoms(Element.HYDROGEN, 9)
491            .addAtoms(Element.NITROGEN, 1)
492            .addAtoms(Element.OXYGEN, 1)
493            .addAtoms(Element.SULFUR, 1)
494            .lock()
495            .register();
496
497      D_HISTIDINE.addAtoms(Element.CARBON, 6)
498            .addAtoms(Element.HYDROGEN, 7)
499            .addAtoms(Element.NITROGEN, 3)
500            .addAtoms(Element.OXYGEN, 1)
501            .addSidechainKa(new IonizableGroup(4.0E-7, Charge.POSITIVE))   // pKa 6.4
502            .lock()
503            .register();
504
505      D_PHENYLALANINE.addAtoms(Element.CARBON, 9)
506            .addAtoms(Element.HYDROGEN, 9)
507            .addAtoms(Element.NITROGEN, 1)
508            .addAtoms(Element.OXYGEN, 1)
509            .lock()
510            .register();
511
512      D_ARGININE.addAtoms(Element.CARBON, 6)
513            .addAtoms(Element.HYDROGEN, 12)
514            .addAtoms(Element.NITROGEN, 4)
515            .addAtoms(Element.OXYGEN, 1)
516            .addSidechainKa(new IonizableGroup(1.0E-13, Charge.POSITIVE)) // pKa 13
517            .lock()
518            .register();
519
520      D_TYROSINE.addAtoms(Element.CARBON, 9)
521            .addAtoms(Element.HYDROGEN, 9)
522            .addAtoms(Element.NITROGEN, 1)
523            .addAtoms(Element.OXYGEN, 2)
524            .addSidechainKa(new IonizableGroup(1.6E-10, Charge.NEUTRAL))  // pKa 9.8
525            .lock()
526            .register();
527
528      D_TRYPTOPHAN.addAtoms(Element.CARBON, 11)
529            .addAtoms(Element.HYDROGEN, 10)
530            .addAtoms(Element.NITROGEN, 2)
531            .addAtoms(Element.OXYGEN, 1)
532            .lock()
533            .register();
534
535
536
537
538
539      ARG_N_METHYL.addAtoms(Element.CARBON, 7)
540         .addAtoms(Element.HYDROGEN, 14)
541         .addAtoms(Element.NITROGEN, 4)
542         .addAtoms(Element.OXYGEN, 1)
543         .lock()
544         .register();
545
546      ASP_HYDROXY.addAtoms(Element.CARBON, 4)
547         .addAtoms(Element.HYDROGEN, 5)
548         .addAtoms(Element.NITROGEN, 1)
549         .addAtoms(Element.OXYGEN, 4)
550         .lock()
551         .register();
552
553      CITRULLINE.addAtoms(Element.CARBON, 6)
554         .addAtoms(Element.HYDROGEN, 11)
555         .addAtoms(Element.NITROGEN, 3)
556         .addAtoms(Element.OXYGEN, 2)
557         .lock()
558         .register();
559
560      CYS_ACETAMIDOMETHYL.addAtoms(Element.CARBON, 6)
561         .addAtoms(Element.HYDROGEN, 10)
562         .addAtoms(Element.NITROGEN, 2)
563         .addAtoms(Element.OXYGEN, 2)
564         .addAtoms(Element.SULFUR, 1)
565         .lock()
566         .register();
567
568      CYS_AMINOETHYL.addAtoms(Element.CARBON, 5)
569         .addAtoms(Element.HYDROGEN, 10)
570         .addAtoms(Element.NITROGEN, 2)
571         .addAtoms(Element.OXYGEN, 1)
572         .addAtoms(Element.SULFUR, 1)
573         .lock()
574         .register();
575
576      CYS_CARBAMIDOMETHYL.addAtoms(Element.CARBON, 5)
577         .addAtoms(Element.HYDROGEN, 8)
578         .addAtoms(Element.NITROGEN, 2)
579         .addAtoms(Element.OXYGEN, 2)
580         .addAtoms(Element.SULFUR, 1)
581         .lock()
582         .register();
583
584      CYS_CARBOXYMETHYL.addAtoms(Element.CARBON, 5)
585         .addAtoms(Element.HYDROGEN, 7)
586         .addAtoms(Element.NITROGEN, 1)
587         .addAtoms(Element.OXYGEN, 3)
588         .addAtoms(Element.SULFUR, 1)
589         .lock()
590         .register();
591
592      CYS_PYRIDYLETHYL.addAtoms(Element.CARBON, 10)
593         .addAtoms(Element.HYDROGEN, 12)
594         .addAtoms(Element.NITROGEN, 2)
595         .addAtoms(Element.OXYGEN, 1)
596         .addAtoms(Element.SULFUR, 1)
597         .lock()
598         .register();
599
600      CYS_S_FARNESYL.addAtoms(Element.CARBON, 18)
601         .addAtoms(Element.HYDROGEN, 29)
602         .addAtoms(Element.NITROGEN, 1)
603         .addAtoms(Element.OXYGEN, 1)
604         .addAtoms(Element.SULFUR, 1)
605         .lock()
606         .register();
607
608      CYS_S_PALMITYL.addAtoms(Element.CARBON, 19)
609         .addAtoms(Element.HYDROGEN, 35)
610         .addAtoms(Element.NITROGEN, 1)
611         .addAtoms(Element.OXYGEN, 2)
612         .addAtoms(Element.SULFUR, 1)
613         .lock()
614         .register();
615
616      DEHYDROALANINE.addAtoms(Element.CARBON, 3)
617         .addAtoms(Element.HYDROGEN, 3)
618         .addAtoms(Element.NITROGEN, 1)
619         .addAtoms(Element.OXYGEN, 1)
620         .lock()
621         .register();
622
623      HOMOSERINE.addAtoms(Element.CARBON, 4)
624         .addAtoms(Element.HYDROGEN, 7)
625         .addAtoms(Element.NITROGEN, 1)
626         .addAtoms(Element.OXYGEN, 2)
627         .lock()
628         .register();
629
630      LYS_ACETYLATED.addAtoms(Element.CARBON, 8)
631         .addAtoms(Element.HYDROGEN, 14)
632         .addAtoms(Element.NITROGEN, 2)
633         .addAtoms(Element.OXYGEN, 2)
634         .lock()
635         .register();
636
637      LYS_HYDROXY.addAtoms(Element.CARBON, 6)
638         .addAtoms(Element.HYDROGEN, 12)
639         .addAtoms(Element.NITROGEN, 2)
640         .addAtoms(Element.OXYGEN, 2)
641         .lock()
642         .register();
643
644      LYS_N_METHYL.addAtoms(Element.CARBON, 7)
645         .addAtoms(Element.HYDROGEN, 14)
646         .addAtoms(Element.NITROGEN, 2)
647         .addAtoms(Element.OXYGEN, 1)
648         .lock()
649         .register();
650
651      LYS_N_DIMETHYL.addAtoms(Element.CARBON, 8)
652            .addAtoms(Element.HYDROGEN, 15)
653            .addAtoms(Element.NITROGEN, 2)
654            .addAtoms(Element.OXYGEN, 1)
655            .lock()
656            .register();
657
658      LYS_N_TRIMETHYL.addAtoms(Element.CARBON, 9)
659         .addAtoms(Element.HYDROGEN, 18)
660         .addAtoms(Element.NITROGEN, 2)
661         .addAtoms(Element.OXYGEN, 1)
662         .lock()
663         .register();
664
665
666      MET_SULFONE.addAtoms(Element.CARBON, 5)
667         .addAtoms(Element.HYDROGEN, 9)
668         .addAtoms(Element.NITROGEN, 1)
669         .addAtoms(Element.OXYGEN, 3)
670         .addAtoms(Element.SULFUR, 1)
671         .lock()
672         .register();
673
674      MET_SULFOXIDE.addAtoms(Element.CARBON, 5)
675         .addAtoms(Element.HYDROGEN, 9)
676         .addAtoms(Element.NITROGEN, 1)
677         .addAtoms(Element.OXYGEN, 2)
678         .addAtoms(Element.SULFUR, 1)
679         .lock()
680         .register();
681
682      MET_S_DIXOY.addAtoms(Element.CARBON, 5)
683            .addAtoms(Element.HYDROGEN, 9)
684            .addAtoms(Element.NITROGEN, 1)
685            .addAtoms(Element.OXYGEN, 3)
686            .addAtoms(Element.SULFUR, 1)
687            .lock()
688            .register();
689
690      SELENOMETHIONINE.addAtoms(Element.CARBON, 5)
691            .addAtoms(Element.HYDROGEN, 9)
692            .addAtoms(Element.NITROGEN, 1)
693            .addAtoms(Element.OXYGEN, 1)
694            .addAtoms(Element.SELENIUM, 1)
695            .lock()
696            .register();
697
698      NORVALINE.addAtoms(Element.CARBON, 5)
699            .addAtoms(Element.HYDROGEN, 9)
700            .addAtoms(Element.NITROGEN, 1)
701            .addAtoms(Element.OXYGEN, 1)
702            .lock()
703            .register();
704
705      NORLEUCINE.addAtoms(Element.CARBON, 6)
706         .addAtoms(Element.HYDROGEN, 11)
707         .addAtoms(Element.NITROGEN, 1)
708         .addAtoms(Element.OXYGEN, 1)
709         .lock()
710         .register();
711
712      ORNITHINE.addAtoms(Element.CARBON, 5)
713         .addAtoms(Element.HYDROGEN, 10)
714         .addAtoms(Element.NITROGEN, 2)
715         .addAtoms(Element.OXYGEN, 1)
716         .lock()
717         .register();
718
719      PRO_HYDROXY.addAtoms(Element.CARBON, 5)
720         .addAtoms(Element.HYDROGEN, 7)
721         .addAtoms(Element.NITROGEN, 1)
722         .addAtoms(Element.OXYGEN, 2)
723         .lock()
724         .register();
725
726      SARCOSINE.addAtoms(Element.CARBON, 3)
727         .addAtoms(Element.HYDROGEN, 7)
728         .addAtoms(Element.NITROGEN, 1)
729         .addAtoms(Element.OXYGEN, 1)
730         .lock()
731         .register();
732
733      SER_PHOSPHO.addAtoms(Element.CARBON, 3)
734         .addAtoms(Element.HYDROGEN, 6)
735         .addAtoms(Element.NITROGEN, 1)
736         .addAtoms(Element.OXYGEN, 5)
737         .addAtoms(Element.PHOSPHOROUS, 1)
738         .lock()
739         .register();
740
741      THR_PHOSPHO.addAtoms(Element.CARBON, 4)
742         .addAtoms(Element.HYDROGEN, 8)
743         .addAtoms(Element.NITROGEN, 1)
744         .addAtoms(Element.OXYGEN, 5)
745         .addAtoms(Element.PHOSPHOROUS, 1)
746         .lock()
747         .register();
748
749      TYR_PHOSPHO.addAtoms(Element.CARBON, 9)
750         .addAtoms(Element.HYDROGEN, 10)
751         .addAtoms(Element.NITROGEN, 1)
752         .addAtoms(Element.OXYGEN, 5)
753         .addAtoms(Element.PHOSPHOROUS, 1)
754         .lock()
755         .register();
756
757      ALPHA_AMINOBUTYRIC_ACID.addAtoms(Element.CARBON, 4)
758         .addAtoms(Element.HYDROGEN, 7)
759         .addAtoms(Element.NITROGEN, 1)
760         .addAtoms(Element.OXYGEN, 1)
761         .lock()
762         .register();
763
764      CYS_S_HYDROXY.addAtoms(Element.CARBON, 3)
765            .addAtoms(Element.HYDROGEN, 5)
766            .addAtoms(Element.NITROGEN, 1)
767            .addAtoms(Element.OXYGEN, 2)
768            .addAtoms(Element.SULFUR, 1)
769            .lock()
770            .register();
771
772      CYS_S_DIOXIDE.addAtoms(Element.CARBON, 3)
773            .addAtoms(Element.HYDROGEN, 5)
774            .addAtoms(Element.NITROGEN, 1)
775            .addAtoms(Element.OXYGEN, 3)
776            .addAtoms(Element.SULFUR, 1)
777            .lock()
778            .register();
779
780      CYS_SULFONIC_ACID.addAtoms(Element.CARBON, 3)
781            .addAtoms(Element.HYDROGEN, 5)
782            .addAtoms(Element.NITROGEN, 1)
783            .addAtoms(Element.OXYGEN, 4)
784            .addAtoms(Element.SULFUR, 1)
785            .lock()
786            .register();
787
788      CYS_S_PHOSPHO.addAtoms(Element.CARBON, 3)
789            .addAtoms(Element.HYDROGEN, 6)
790            .addAtoms(Element.NITROGEN, 1)
791            .addAtoms(Element.OXYGEN, 4)
792            .addAtoms(Element.SULFUR, 1)
793            .addAtoms(Element.PHOSPHOROUS, 1)
794            .lock()
795            .register();
796
797      CYS_2_HYDROXYETHYL_THIOCYSTEINE.addAtoms(Element.CARBON, 5)
798         .addAtoms(Element.HYDROGEN, 9)
799         .addAtoms(Element.NITROGEN, 1)
800         .addAtoms(Element.OXYGEN, 2)
801         .addAtoms(Element.SULFUR, 2)
802            .lock()
803         .register();
804
805      THREE_SULFINOALANINE.addAtoms(Element.CARBON, 3)
806         .addAtoms(Element.HYDROGEN, 5)
807            .addAtoms(Element.NITROGEN, 1)
808         .addAtoms(Element.OXYGEN, 3)
809         .addAtoms(Element.SULFUR, 1)
810         .lock()
811         .register();
812
813
814      AMINO_MERCAPTO_BUTYRIC_ACID.addAtoms(Element.CARBON, 4)
815            .addAtoms(Element.HYDROGEN, 7)
816            .addAtoms(Element.NITROGEN, 1)
817            .addAtoms(Element.OXYGEN, 1)
818            .addAtoms(Element.SULFUR, 1)
819            .lock()
820            .register();
821
822      ALPHA_AMINOISOBUTYRIC_ACID.addAtoms(Element.CARBON, 4)
823            .addAtoms(Element.HYDROGEN, 7)
824            .addAtoms(Element.NITROGEN, 1)
825            .addAtoms(Element.OXYGEN, 1)
826            .lock()
827            .register();
828
829      HIS_4_METHYL.addAtoms(Element.CARBON, 7)
830            .addAtoms(Element.HYDROGEN, 9)
831            .addAtoms(Element.NITROGEN, 3)
832            .addAtoms(Element.OXYGEN, 1)
833            .lock()
834            .register();
835
836      LYS_NZ_CARBOXYLIC_ACID.addAtoms(Element.CARBON, 7)
837            .addAtoms(Element.HYDROGEN, 12)
838            .addAtoms(Element.NITROGEN, 2)
839            .addAtoms(Element.OXYGEN, 3)
840            .lock()
841            .register();
842
843      LLP.addAtoms(Element.CARBON, 14)
844            .addAtoms(Element.HYDROGEN, 20)
845            .addAtoms(Element.NITROGEN, 3)
846            .addAtoms(Element.OXYGEN, 6)
847            .addAtoms(Element.PHOSPHOROUS, 1)
848            .lock()
849            .register();
850
851      TYR_O_SULFO.addAtoms(Element.CARBON, 9)
852            .addAtoms(Element.HYDROGEN, 9)
853            .addAtoms(Element.NITROGEN, 1)
854            .addAtoms(Element.OXYGEN, 5)
855            .addAtoms(Element.SULFUR, 1)
856            .lock()
857            .register();
858
859      ASN_N_METHYL.addAtoms(Element.CARBON, 5)
860            .addAtoms(Element.HYDROGEN, 8)
861            .addAtoms(Element.NITROGEN, 2)
862            .addAtoms(Element.OXYGEN, 2)
863            .lock()
864            .register();
865
866
867      // Differing protonation states of histidine
868
869      HISTIDINE_HID.addAtoms(Element.CARBON, 6)
870            .addAtoms(Element.HYDROGEN, 7)
871            .addAtoms(Element.NITROGEN, 3)
872            .addAtoms(Element.OXYGEN, 1)
873            .lock()
874            .register();
875
876      HISTIDINE_HIE.addAtoms(Element.CARBON, 6)
877            .addAtoms(Element.HYDROGEN, 7)
878            .addAtoms(Element.NITROGEN, 3)
879            .addAtoms(Element.OXYGEN, 1)
880            .lock()
881            .register();
882
883      HISTIDINE_HIP.addAtoms(Element.CARBON, 6)
884            .addAtoms(Element.HYDROGEN, 8)
885            .addAtoms(Element.NITROGEN, 3)
886            .addAtoms(Element.OXYGEN, 1)
887            .lock()
888            .register();
889
890   }
891
892
893
894   //##########################################################################
895   // PRIVATE FIELDS
896   //##########################################################################
897
898   private String                      m3LetterCode;
899   private Character                   m1LetterCode;
900   private Collection<IonizableGroup>  mSidechainKas;
901   private boolean                     mIsApproximation;
902   private int                         mOrdinal = sDefaultOrdinal;
903
904   private static int sDefaultOrdinal = 100000;
905
906   //##########################################################################
907   // CONSTRUCTORS
908   //##########################################################################
909
910   //--------------------------------------------------------------------------
911   public AminoAcid(String inName)
912   {
913      super();
914      setName(inName);
915   }
916
917   //--------------------------------------------------------------------------
918   public AminoAcid(String inName, String in3LetterCode)
919   {
920      this(inName, in3LetterCode, null, sDefaultOrdinal);
921   }
922
923   //--------------------------------------------------------------------------
924   public AminoAcid(String inName, String in3LetterCode, char in1LetterCode)
925   {
926      this(inName, in3LetterCode, in1LetterCode, sDefaultOrdinal);
927   }
928
929   //--------------------------------------------------------------------------
930   private AminoAcid(String inName, String in3LetterCode, Character in1LetterCode, int inOrdinal)
931   {
932      this(inName);
933      m3LetterCode = in3LetterCode;
934      m1LetterCode = in1LetterCode;
935      mOrdinal = inOrdinal;
936   }
937
938   //--------------------------------------------------------------------------
939   public AminoAcid(String inName, Map<Element, Float> inElementalComposition)
940   {
941      super(inName, inElementalComposition);
942   }
943
944   //--------------------------------------------------------------------------
945   public AminoAcid(XMLNode inXML)
946   {
947      this(inXML.getAttributeValue(HfgBioXML.NAME_ATT));
948
949      if (! inXML.getTagName().equals(HfgBioXML.AA_TAG))
950      {
951         throw new RuntimeException("Cannot construct an " + this.getClass().getSimpleName() + " from a " + inXML.getTagName() + " tag!");
952      }
953
954      XMLNode sidechainKasTag = inXML.getOptionalSubtagByName(HfgBioXML.SIDECHAIN_KAS_TAG);
955      if (sidechainKasTag != null)
956      {
957         for (XMLNode subtag : sidechainKasTag.getXMLNodeSubtags())
958         {
959            addSidechainKa(new IonizableGroup(subtag));
960         }
961      }
962
963      if (inXML.hasAttribute(HfgBioXML.IS_APPROX_ATT))
964      {
965         if (inXML.getAttributeValue(HfgBioXML.IS_APPROX_ATT).equalsIgnoreCase("true"))
966         {
967            mIsApproximation = true;
968         }
969      }
970
971      m3LetterCode = inXML.getAttributeValue(HfgBioXML.THREE_LTR_CODE_ATT);
972
973      if (inXML.hasAttribute(HfgBioXML.ONE_LTR_CODE_ATT))
974      {
975         m1LetterCode = inXML.getAttributeValue(HfgBioXML.ONE_LTR_CODE_ATT).charAt(0);
976      }
977
978      XMLNode compTag = inXML.getOptionalSubtagByName(HfgBioXML.ELEMENTAL_COMP_TAG);
979      if (compTag != null)
980      {
981         for (XMLAttribute attr : compTag.getAttributes())
982         {
983            addAtoms(Element.valueOf(attr.getName()), Float.parseFloat(attr.getValue()));
984         }
985      }
986
987      // Set the ordinal value (isn't included in the XML)
988      for (AminoAcid aa : sValues)
989      {
990         if (aa.name().equals(name()))
991         {
992            mOrdinal = aa.mOrdinal;
993            break;
994         }
995      }
996   }
997
998
999   //##########################################################################
1000   // PUBLIC METHODS
1001   //##########################################################################
1002
1003
1004   //--------------------------------------------------------------------------
1005   /**
1006    Puts the AminoAcid into the Set of unique AminoAcids returned by AminoAcid.values().
1007    */
1008   public void register()
1009   {
1010      if (! isLocked())
1011      {
1012         throw new RuntimeException("Only locked AminoAcids can be added to the values list!");
1013      }
1014
1015      sValues.add(this);
1016   }
1017
1018   //--------------------------------------------------------------------------
1019   @Override
1020   public AminoAcid addAtoms(Element inElement, int inNum)
1021   {
1022      return (AminoAcid) super.addAtoms(inElement, inNum);
1023   }
1024
1025   //--------------------------------------------------------------------------
1026   @Override
1027   public AminoAcid lock()
1028   {
1029      return (AminoAcid) super.lock();
1030   }
1031
1032   //--------------------------------------------------------------------------
1033   @Override
1034   public String toString()
1035   {
1036      return m1LetterCode != null ? m1LetterCode + "" : name();
1037   }
1038
1039   //--------------------------------------------------------------------------
1040   /**
1041    Returns an unlocked copy of the AminoAcid.
1042    @return an unlocked copy of this AminoAcid
1043    */
1044   @Override
1045   public AminoAcid clone()
1046   {
1047      AminoAcid copy = (AminoAcid) super.clone();
1048
1049      if (mSidechainKas != null)
1050      {
1051         copy.mSidechainKas = new ArrayList<>(mSidechainKas);
1052      }
1053
1054      return copy;
1055   }
1056/*
1057   //--------------------------------------------------------------------------
1058   @Override
1059   public int hashCode()
1060   {
1061      int hashcode = mMatter.hashCode();
1062      if (mName != null)
1063      {
1064         hashcode = hashcode + 31 * mName.hashCode();
1065      }
1066
1067      return hashcode;
1068   }
1069*/
1070   //--------------------------------------------------------------------------
1071   @Override
1072   public boolean equals(Object inObj)
1073   {
1074      boolean result = false;
1075
1076      if (inObj != null
1077         && inObj instanceof AminoAcid)
1078      {
1079         result = (0 == compareTo(inObj));
1080      }
1081
1082      return result;
1083   }
1084
1085   //--------------------------------------------------------------------------
1086   public int compareTo(Object inObj)
1087   {
1088      int result = -1;
1089
1090      if (inObj != null)
1091      {
1092         if (inObj instanceof AminoAcid)
1093         {
1094            AminoAcid aa2 = (AminoAcid) inObj;
1095
1096            result = CompareUtil.compare(mOrdinal, aa2.mOrdinal);
1097            if (0 == result)
1098            {
1099               result = super.compareTo(inObj);
1100            }
1101         }
1102         else
1103         {
1104            result = CompareUtil.compare(hashCode(), inObj.hashCode());
1105         }
1106      }
1107
1108      return result;
1109   }
1110
1111
1112   //--------------------------------------------------------------------------
1113   /**
1114    Returns the AminoAcid whose name or 3-letter code matches the specified String.
1115    (1-letter codes aren't specific enough.)
1116    @param inString the name or 3-letter code for the AminoAcid to retrieve
1117    @return the AminoAcid whose name or 3-letter code matches the specified String
1118    */
1119   public static AminoAcid valueOf(String inString)
1120   {
1121      AminoAcid value = null;
1122
1123      if (StringUtil.isSet(inString))
1124      {
1125         for (AminoAcid aa : sValues)
1126         {
1127            if (aa.name().equalsIgnoreCase(inString)
1128                  || inString.equalsIgnoreCase(aa.getThreeLetterCode())) // 1-letter code isn't specific enough
1129            {
1130               value = aa;
1131               break;
1132            }
1133         }
1134      }
1135
1136      return value;
1137   }
1138
1139   //--------------------------------------------------------------------------
1140   public static AminoAcid[] values()
1141   {
1142      return sValues.toArray(new AminoAcid[sValues.size()]);
1143   }
1144
1145   //--------------------------------------------------------------------------
1146   public AminoAcid addSidechainKa(IonizableGroup inValue)
1147   {
1148      if (isLocked()) throw new UnmodifyableObjectException(name() + " is locked and cannot be modified!");
1149
1150      if (null == mSidechainKas)
1151      {
1152         mSidechainKas = new ArrayList<>();
1153      }
1154
1155      mSidechainKas.add(inValue);
1156
1157      return this;
1158   }
1159
1160   //--------------------------------------------------------------------------
1161   /**
1162    Sets the sidechain K<sub>a</sub>'s.
1163    @param inKas IonizableGroups present on the AminoAcid's sidechain
1164    */
1165   public void setSidechainKas(Collection<IonizableGroup> inKas)
1166   {
1167      if (isLocked()) throw new UnmodifyableObjectException(name() + " is locked and cannot be modified!");
1168
1169      mSidechainKas = inKas;
1170   }
1171
1172   //--------------------------------------------------------------------------
1173   /**
1174    Returns any defined sidechain K<sub>a</sub>'s.
1175    @return sidechain IonizableGroups
1176    */
1177   public Collection<IonizableGroup> getSidechainKas()
1178   {
1179      return (mSidechainKas != null ? Collections.unmodifiableCollection(mSidechainKas) : null);
1180   }
1181
1182
1183   //--------------------------------------------------------------------------
1184   public AminoAcid setThreeLetterCode(String inValue)
1185   {
1186      if (isLocked()) throw new UnmodifyableObjectException(name() + " is locked and cannot be modified!");
1187      m3LetterCode = inValue;
1188      return this;
1189   }
1190
1191   //--------------------------------------------------------------------------
1192   public String getThreeLetterCode()
1193   {
1194      return m3LetterCode;
1195   }
1196
1197   //--------------------------------------------------------------------------
1198   public AminoAcid setOneLetterCode(Character inValue)
1199   {
1200      if (isLocked()) throw new UnmodifyableObjectException(name() + " is locked and cannot be modified!");
1201      m1LetterCode = inValue;
1202      return this;
1203   }
1204
1205   //--------------------------------------------------------------------------
1206   public Character getOneLetterCode()
1207   {
1208      return m1LetterCode;
1209   }
1210
1211
1212   //--------------------------------------------------------------------------
1213   /**
1214    Some of the defined amino acids are an average of other amino acids. Use of
1215    these renders the calculated properties as approximations.
1216    @return whether or not the AminoAcid is an average of other amino acids
1217    */
1218   public boolean isApproximation()
1219   {
1220      return mIsApproximation;
1221   }
1222
1223
1224   //--------------------------------------------------------------------------
1225   @Override
1226   public XMLNode toXMLNode()
1227   {
1228      XMLNode node = super.toXMLNode();
1229      node.setTagName(HfgBioXML.AA_TAG);
1230
1231      if (CollectionUtil.hasValues(mSidechainKas))
1232      {
1233         XMLNode kasTag = new XMLTag(HfgBioXML.SIDECHAIN_KAS_TAG);
1234         node.addSubtag(kasTag);
1235         for (IonizableGroup grp : mSidechainKas)
1236         {
1237            kasTag.addSubtag(grp.toXMLNode());
1238         }
1239      }
1240
1241      if (mIsApproximation) node.setAttribute(HfgBioXML.IS_APPROX_ATT, "true");
1242      if (StringUtil.isSet(m3LetterCode)) node.setAttribute(HfgBioXML.THREE_LTR_CODE_ATT, m3LetterCode);
1243      if (m1LetterCode != null) node.setAttribute(HfgBioXML.ONE_LTR_CODE_ATT, m1LetterCode);
1244
1245      return node;
1246   }
1247
1248   private class AAOrdinalComparator implements Comparator<AminoAcid>
1249   {
1250      //-----------------------------------------------------------------------
1251      @Override
1252      public int compare(AminoAcid inObj1, AminoAcid inObj2)
1253      {
1254         return CompareUtil.compare(inObj1.mOrdinal, inObj2.mOrdinal);
1255      }
1256   }
1257}