JAL-1807 Bob's JalviewJS prototype first commit
[jalviewjs.git] / src / jalview / schemes / ResidueProperties.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.schemes;
22
23 import java.awt.Color;
24 import java.util.ArrayList;
25 import java.util.Enumeration;
26 import java.util.HashMap;
27 import java.util.Hashtable;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Vector;
31
32 import javajs.J2SRequireImport;
33
34 import jalview.analysis.scoremodels.FeatureScoreModel;
35 import jalview.analysis.scoremodels.PIDScoreModel;
36 import jalview.api.analysis.ScoreModelI;
37
38 // required because of the static defs
39
40 @J2SRequireImport({ScoreMatrix.class, PIDScoreModel.class, FeatureScoreModel.class})
41 public class ResidueProperties
42 {
43   public static Hashtable<String, ScoreModelI> scoreMatrices = new Hashtable();
44
45   // Stores residue codes/names and colours and other things
46   public static final int[] aaIndex; // aaHash version 2.1.1 and below
47
48   public static final int[] nucleotideIndex;
49
50   public static final int[] purinepyrimidineIndex;
51
52   public static final Map<String, Integer> aa3Hash = new HashMap<String, Integer>();
53
54   public static final Map<String, String> aa2Triplet = new HashMap<String, String>();
55
56   public static final Map<String, String> nucleotideName = new HashMap<String, String>();
57
58   static
59   {
60     aaIndex = new int[255];
61     for (int i = 0; i < 255; i++)
62     {
63       aaIndex[i] = 23;
64     }
65
66     aaIndex['A'] = 0;
67     aaIndex['R'] = 1;
68     aaIndex['N'] = 2;
69     aaIndex['D'] = 3;
70     aaIndex['C'] = 4;
71     aaIndex['Q'] = 5;
72     aaIndex['E'] = 6;
73     aaIndex['G'] = 7;
74     aaIndex['H'] = 8;
75     aaIndex['I'] = 9;
76     aaIndex['L'] = 10;
77     aaIndex['K'] = 11;
78     aaIndex['M'] = 12;
79     aaIndex['F'] = 13;
80     aaIndex['P'] = 14;
81     aaIndex['S'] = 15;
82     aaIndex['T'] = 16;
83     aaIndex['W'] = 17;
84     aaIndex['Y'] = 18;
85     aaIndex['V'] = 19;
86     aaIndex['B'] = 20;
87     aaIndex['Z'] = 21;
88     aaIndex['X'] = 22;
89     aaIndex['U'] = 22;
90     aaIndex['a'] = 0;
91     aaIndex['r'] = 1;
92     aaIndex['n'] = 2;
93     aaIndex['d'] = 3;
94     aaIndex['c'] = 4;
95     aaIndex['q'] = 5;
96     aaIndex['e'] = 6;
97     aaIndex['g'] = 7;
98     aaIndex['h'] = 8;
99     aaIndex['i'] = 9;
100     aaIndex['l'] = 10;
101     aaIndex['k'] = 11;
102     aaIndex['m'] = 12;
103     aaIndex['f'] = 13;
104     aaIndex['p'] = 14;
105     aaIndex['s'] = 15;
106     aaIndex['t'] = 16;
107     aaIndex['w'] = 17;
108     aaIndex['y'] = 18;
109     aaIndex['v'] = 19;
110     aaIndex['b'] = 20;
111     aaIndex['z'] = 21;
112     aaIndex['x'] = 22;
113     aaIndex['u'] = 22; // TODO: selenocystine triplet and codons needed. also
114     // extend subt. matrices
115   }
116
117   /**
118    * maximum (gap) index for matrices involving protein alphabet
119    */
120   public final static int maxProteinIndex = 23;
121
122   /**
123    * maximum (gap) index for matrices involving nucleotide alphabet
124    */
125   public final static int maxNucleotideIndex = 10;
126
127   static
128   {
129     nucleotideIndex = new int[255];
130     for (int i = 0; i < 255; i++)
131     {
132       nucleotideIndex[i] = 10; // non-nucleotide symbols are all non-gap gaps.
133     }
134
135     nucleotideIndex['A'] = 0;
136     nucleotideIndex['a'] = 0;
137     nucleotideIndex['C'] = 1;
138     nucleotideIndex['c'] = 1;
139     nucleotideIndex['G'] = 2;
140     nucleotideIndex['g'] = 2;
141     nucleotideIndex['T'] = 3;
142     nucleotideIndex['t'] = 3;
143     nucleotideIndex['U'] = 4;
144     nucleotideIndex['u'] = 4;
145     nucleotideIndex['I'] = 5;
146     nucleotideIndex['i'] = 5;
147     nucleotideIndex['X'] = 6;
148     nucleotideIndex['x'] = 6;
149     nucleotideIndex['R'] = 7;
150     nucleotideIndex['r'] = 7;
151     nucleotideIndex['Y'] = 8;
152     nucleotideIndex['y'] = 8;
153     nucleotideIndex['N'] = 9;
154     nucleotideIndex['n'] = 9;
155
156     nucleotideName.put("A", "Adenine");
157     nucleotideName.put("a", "Adenine");
158     nucleotideName.put("G", "Guanine");
159     nucleotideName.put("g", "Guanine");
160     nucleotideName.put("C", "Cytosine");
161     nucleotideName.put("c", "Cytosine");
162     nucleotideName.put("T", "Thymine");
163     nucleotideName.put("t", "Thymine");
164     nucleotideName.put("U", "Uracil");
165     nucleotideName.put("u", "Uracil");
166     nucleotideName.put("I", "Inosine");
167     nucleotideName.put("i", "Inosine");
168     nucleotideName.put("X", "Xanthine");
169     nucleotideName.put("x", "Xanthine");
170     nucleotideName.put("R", "Unknown Purine");
171     nucleotideName.put("r", "Unknown Purine");
172     nucleotideName.put("Y", "Unknown Pyrimidine");
173     nucleotideName.put("y", "Unknown Pyrimidine");
174     nucleotideName.put("N", "Unknown");
175     nucleotideName.put("n", "Unknown");
176     nucleotideName.put("W", "Weak nucleotide (A or T)");
177     nucleotideName.put("w", "Weak nucleotide (A or T)");
178     nucleotideName.put("S", "Strong nucleotide (G or C)");
179     nucleotideName.put("s", "Strong nucleotide (G or C)");
180     nucleotideName.put("M", "Amino (A or C)");
181     nucleotideName.put("m", "Amino (A or C)");
182     nucleotideName.put("K", "Keto (G or T)");
183     nucleotideName.put("k", "Keto (G or T)");
184     nucleotideName.put("B", "Not A (G or C or T)");
185     nucleotideName.put("b", "Not A (G or C or T)");
186     nucleotideName.put("H", "Not G (A or C or T)");
187     nucleotideName.put("h", "Not G (A or C or T)");
188     nucleotideName.put("D", "Not C (A or G or T)");
189     nucleotideName.put("d", "Not C (A or G or T)");
190     nucleotideName.put("V", "Not T (A or G or C");
191     nucleotideName.put("v", "Not T (A or G or C");
192
193   }
194
195   static
196   {
197     purinepyrimidineIndex = new int[255];
198     for (int i = 0; i < 255; i++)
199     {
200       purinepyrimidineIndex[i] = 3; // non-nucleotide symbols are all non-gap
201       // gaps.
202     }
203
204     purinepyrimidineIndex['A'] = 0;
205     purinepyrimidineIndex['a'] = 0;
206     purinepyrimidineIndex['C'] = 1;
207     purinepyrimidineIndex['c'] = 1;
208     purinepyrimidineIndex['G'] = 0;
209     purinepyrimidineIndex['g'] = 0;
210     purinepyrimidineIndex['T'] = 1;
211     purinepyrimidineIndex['t'] = 1;
212     purinepyrimidineIndex['U'] = 1;
213     purinepyrimidineIndex['u'] = 1;
214     purinepyrimidineIndex['I'] = 2;
215     purinepyrimidineIndex['i'] = 2;
216     purinepyrimidineIndex['X'] = 2;
217     purinepyrimidineIndex['x'] = 2;
218     purinepyrimidineIndex['R'] = 0;
219     purinepyrimidineIndex['r'] = 0;
220     purinepyrimidineIndex['Y'] = 1;
221     purinepyrimidineIndex['y'] = 1;
222     purinepyrimidineIndex['N'] = 2;
223     purinepyrimidineIndex['n'] = 2;
224   }
225
226   static
227   {
228     aa3Hash.put("ALA", new Integer(0));
229     aa3Hash.put("ARG", new Integer(1));
230     aa3Hash.put("ASN", new Integer(2));
231     aa3Hash.put("ASP", new Integer(3)); // D
232     aa3Hash.put("CYS", new Integer(4));
233     aa3Hash.put("GLN", new Integer(5)); // Q
234     aa3Hash.put("GLU", new Integer(6)); // E
235     aa3Hash.put("GLY", new Integer(7));
236     aa3Hash.put("HIS", new Integer(8));
237     aa3Hash.put("ILE", new Integer(9));
238     aa3Hash.put("LEU", new Integer(10));
239     aa3Hash.put("LYS", new Integer(11));
240     aa3Hash.put("MET", new Integer(12));
241     aa3Hash.put("PHE", new Integer(13));
242     aa3Hash.put("PRO", new Integer(14));
243     aa3Hash.put("SER", new Integer(15));
244     aa3Hash.put("THR", new Integer(16));
245     aa3Hash.put("TRP", new Integer(17));
246     aa3Hash.put("TYR", new Integer(18));
247     aa3Hash.put("VAL", new Integer(19));
248     // IUB Nomenclature for ambiguous peptides
249     aa3Hash.put("ASX", new Integer(20)); // "B";
250     aa3Hash.put("GLX", new Integer(21)); // X
251     aa3Hash.put("XAA", new Integer(22)); // X unknown
252     aa3Hash.put("-", new Integer(23));
253     aa3Hash.put("*", new Integer(23));
254     aa3Hash.put(".", new Integer(23));
255     aa3Hash.put(" ", new Integer(23));
256     aa3Hash.put("Gap", new Integer(23));
257   }
258
259   static
260   {
261     aa2Triplet.put("A", "ALA");
262     aa2Triplet.put("a", "ALA");
263     aa2Triplet.put("R", "ARG");
264     aa2Triplet.put("r", "ARG");
265     aa2Triplet.put("N", "ASN");
266     aa2Triplet.put("n", "ASN");
267     aa2Triplet.put("D", "ASP");
268     aa2Triplet.put("d", "ASP");
269     aa2Triplet.put("C", "CYS");
270     aa2Triplet.put("c", "CYS");
271     aa2Triplet.put("Q", "GLN");
272     aa2Triplet.put("q", "GLN");
273     aa2Triplet.put("E", "GLU");
274     aa2Triplet.put("e", "GLU");
275     aa2Triplet.put("G", "GLY");
276     aa2Triplet.put("g", "GLY");
277     aa2Triplet.put("H", "HIS");
278     aa2Triplet.put("h", "HIS");
279     aa2Triplet.put("I", "ILE");
280     aa2Triplet.put("i", "ILE");
281     aa2Triplet.put("L", "LEU");
282     aa2Triplet.put("l", "LEU");
283     aa2Triplet.put("K", "LYS");
284     aa2Triplet.put("k", "LYS");
285     aa2Triplet.put("M", "MET");
286     aa2Triplet.put("m", "MET");
287     aa2Triplet.put("F", "PHE");
288     aa2Triplet.put("f", "PHE");
289     aa2Triplet.put("P", "PRO");
290     aa2Triplet.put("p", "PRO");
291     aa2Triplet.put("S", "SER");
292     aa2Triplet.put("s", "SER");
293     aa2Triplet.put("T", "THR");
294     aa2Triplet.put("t", "THR");
295     aa2Triplet.put("W", "TRP");
296     aa2Triplet.put("w", "TRP");
297     aa2Triplet.put("Y", "TYR");
298     aa2Triplet.put("y", "TYR");
299     aa2Triplet.put("V", "VAL");
300     aa2Triplet.put("v", "VAL");
301   }
302
303   public static final String[] aa =
304   { "A", "R", "N", "D", "C", "Q", "E", "G", "H", "I", "L", "K", "M", "F",
305       "P", "S", "T", "W", "Y", "V", "B", "Z", "X", "_", "*", ".", " " };
306
307   public static final Color midBlue = new Color(100, 100, 255);
308
309   public static final Vector scaleColours = new Vector();
310
311   static
312   {
313     scaleColours.addElement(new Color(114, 0, 147));
314     scaleColours.addElement(new Color(156, 0, 98));
315     scaleColours.addElement(new Color(190, 0, 0));
316     scaleColours.addElement(Color.red);
317     scaleColours.addElement(new Color(255, 125, 0));
318     scaleColours.addElement(Color.orange);
319     scaleColours.addElement(new Color(255, 194, 85));
320     scaleColours.addElement(Color.yellow);
321     scaleColours.addElement(new Color(255, 255, 181));
322     scaleColours.addElement(Color.white);
323   }
324
325   public static final Color[] taylor =
326   { new Color(204, 255, 0), // A Greenish-yellowy-yellow
327       new Color(0, 0, 255), // R Blueish-bluey-blue
328       new Color(204, 0, 255), // N Blueish-reddy-blue
329       new Color(255, 0, 0), // D Reddish-reddy-red
330       new Color(255, 255, 0), // C Yellowish-yellowy-yellow
331       new Color(255, 0, 204), // Q Reddish-bluey-red
332       new Color(255, 0, 102), // E Blueish-reddy-red
333       new Color(255, 153, 0), // G Yellowy-reddy-yellow
334       new Color(0, 102, 255), // H Greenish-bluey-blue
335       new Color(102, 255, 0), // I Greenish-yellowy-green
336       new Color(51, 255, 0), // L Yellowish-greeny-green
337       new Color(102, 0, 255), // K Reddish-bluey-blue
338       new Color(0, 255, 0), // M Greenish-greeny-green
339       new Color(0, 255, 102), // F Blueish-greeny-green
340       new Color(255, 204, 0), // P Reddish-yellowy-yellow
341       new Color(255, 51, 0), // S Yellowish-reddy-red
342       new Color(255, 102, 0), // T Reddish-yellowy-red
343       new Color(0, 204, 255), // W Blueish-greeny-green
344       new Color(0, 255, 204), // Y Greenish-bluey-green
345       new Color(153, 255, 0), // V Yellowish-greeny-yellow
346       Color.white, // B
347       Color.white, // Z
348       Color.white, // X
349       Color.white, // -
350       Color.white, // *
351       Color.white // .
352   };
353
354   public static final Color[] nucleotide =
355   { new Color(100, 247, 63), // A
356       new Color(255, 179, 64), // C
357       new Color(235, 65, 60), // G
358       new Color(60, 136, 238), // T
359       new Color(60, 136, 238), // U
360       Color.white, // I (inosine)
361       Color.white, // X (xanthine)
362       Color.white, // R
363       Color.white, // Y
364       Color.white, // N
365       Color.white, // Gap
366   };
367
368   // Added for PurinePyrimidineColourScheme
369   public static final Color[] purinepyrimidine =
370   { new Color(255, 131, 250), // A, G, R purines purplish/orchid
371       new Color(64, 224, 208), // C,U, T, Y pyrimidines turquoise
372       Color.white, // all other nucleotides
373       Color.white // Gap
374   };
375
376   // Zappo
377   public static final Color[] zappo =
378   { Color.pink, // A
379       midBlue, // R
380       Color.green, // N
381       Color.red, // D
382       Color.yellow, // C
383       Color.green, // Q
384       Color.red, // E
385       Color.magenta, // G
386       midBlue,// Color.red, // H
387       Color.pink, // I
388       Color.pink, // L
389       midBlue, // K
390       Color.pink, // M
391       Color.orange, // F
392       Color.magenta, // P
393       Color.green, // S
394       Color.green, // T
395       Color.orange, // W
396       Color.orange, // Y
397       Color.pink, // V
398       Color.white, // B
399       Color.white, // Z
400       Color.white, // X
401       Color.white, // -
402       Color.white, // *
403       Color.white, // .
404       Color.white // ' '
405   };
406
407   // Dunno where I got these numbers from
408   public static final double[] hyd2 =
409   { 0.62, // A
410       0.29, // R
411       -0.90, // N
412       -0.74, // D
413       1.19, // C
414       0.48, // Q
415       -0.40, // E
416       1.38, // G
417       -1.50, // H
418       1.06, // I
419       0.64, // L
420       -0.78, // K
421       0.12, // M
422       -0.85, // F
423       -2.53, // P
424       -0.18, // S
425       -0.05, // T
426       1.08, // W
427       0.81, // Y
428       0.0, // V
429       0.26, // B
430       0.0, // Z
431       0.0 // X
432   };
433
434   public static final double[] helix =
435   { 1.42, 0.98, 0.67, 1.01, 0.70, 1.11, 1.51, 0.57, 1.00, 1.08, 1.21, 1.16,
436       1.45, 1.13, 0.57, 0.77, 0.83, 1.08, 0.69, 1.06, 0.84, 1.31, 1.00, 0.0 };
437
438   public static final double helixmin = 0.57;
439
440   public static final double helixmax = 1.51;
441
442   public static final double[] strand =
443   { 0.83, 0.93, 0.89, 0.54, 1.19, 1.10, 0.37, 0.75, 0.87, 1.60, 1.30, 0.74,
444       1.05, 1.38, 0.55, 0.75, 1.19, 1.37, 1.47, 1.70, 0.72, 0.74, 1.0, 0.0 };
445
446   public static final double strandmin = 0.37;
447
448   public static final double strandmax = 1.7;
449
450   public static final double[] turn =
451   { 0.66, 0.95, 1.56, 1.46, 1.19, 0.98, 0.74, 1.56, 0.95, 0.47, 0.59, 1.01,
452       0.60, 0.60, 1.52, 1.43, 0.96, 0.96, 1.14, 0.50, 1.51, 0.86, 1.00, 0,
453       0 };
454
455   public static final double turnmin = 0.47;
456
457   public static final double turnmax = 1.56;
458
459   public static final double[] buried =
460   { 1.7, 0.1, 0.4, 0.4, 4.6, 0.3, 0.3, 1.8, 0.8, 3.1, 2.4, 0.05, 1.9, 2.2,
461       0.6, 0.8, 0.7, 1.6, 0.5, 2.9, 0.4, 0.3, 1.358, 0.00 };
462
463   public static final double buriedmin = 0.05;
464
465   public static final double buriedmax = 4.6;
466
467   // This is hydropathy index
468   // Kyte, J., and Doolittle, R.F., J. Mol. Biol.
469   // 1157, 105-132, 1982
470   public static final double[] hyd =
471   { 1.8, -4.5, -3.5, -3.5, 2.5, -3.5, -3.5, -0.4, -3.2, 4.5, 3.8, -3.9,
472       1.9, 2.8, -1.6, -0.8, -0.7, -0.9, -1.3, 4.2, -3.5, -3.5, -0.49, 0.0 };
473
474   public static final double hydmax = 4.5;
475
476   public static final double hydmin = -3.9;
477
478   // public static final double hydmax = 1.38;
479   // public static final double hydmin = -2.53;
480   private static final int[][] BLOSUM62 =
481   {
482       { 4, -1, -2, -2, 0, -1, -1, 0, -2, -1, -1, -1, -1, -2, -1, 1, 0, -3,
483           -2, 0, -2, -1, 0, -4 },
484       { -1, 5, 0, -2, -3, 1, 0, -2, 0, -3, -2, 2, -1, -3, -2, -1, -1, -3,
485           -2, -3, -1, 0, -1, -4 },
486       { -2, 0, 6, 1, -3, 0, 0, 0, 1, -3, -3, 0, -2, -3, -2, 1, 0, -4, -2,
487           -3, 3, 0, -1, -4 },
488       { -2, -2, 1, 6, -3, 0, 2, -1, -1, -3, -4, -1, -3, -3, -1, 0, -1, -4,
489           -3, -3, 4, 1, -1, -4 },
490       { 0, 3, -3, -3, 9, -3, -4, -3, -3, -1, -1, -3, -1, -2, -3, -1, -1,
491           -2, -2, -1, -3, -3, -2, -4 },
492       { -1, 1, 0, 0, -3, 5, 2, -2, 0, -3, -2, 1, 0, -3, -1, 0, -1, -2, -1,
493           -2, 0, 3, -1, -4 },
494       { -1, 0, 0, 2, -4, 2, 5, -2, 0, -3, -3, 1, -2, -3, -1, 0, -1, -3, -2,
495           -2, 1, 4, -1, -4 },
496       { 0, -2, 0, -1, -3, -2, -2, 6, -2, -4, -4, -2, -3, -3, -2, 0, -2, -2,
497           -3, -3, -1, -2, -1, -4 },
498       { -2, 0, 1, -1, -3, 0, 0, -2, 8, -3, -3, -1, -2, -1, -2, -1, -2, -2,
499           2, -3, 0, 0, -1, -4 },
500       { -1, -3, -3, -3, -1, -3, -3, -4, -3, 4, 2, -3, 1, 0, -3, -2, -1, -3,
501           -1, 3, -3, -3, -1, -4 },
502       { -1, -2, -3, -4, -1, -2, -3, -4, -3, 2, 4, -2, 2, 0, -3, -2, -1, -2,
503           -1, 1, -4, -3, -1, -4 },
504       { -1, 2, 0, -1, -3, 1, 1, -2, -1, -3, -2, 5, -1, -3, -1, 0, -1, -3,
505           -2, -2, 0, 1, -1, -4 },
506       { -1, -1, -2, -3, -1, 0, -2, -3, -2, 1, 2, -1, 5, 0, -2, -1, -1, -1,
507           -1, 1, -3, -1, -1, -4 },
508       { -2, -3, -3, -3, -2, -3, -3, -3, -1, 0, 0, -3, 0, 6, -4, -2, -2, 1,
509           3, -1, -3, -3, -1, -4 },
510       { -1, -2, -2, -1, -3, -1, -1, -2, -2, -3, -3, -1, -2, -4, 7, -1, -1,
511           -4, -3, -2, -2, -1, -2, -4 },
512       { 1, -1, 1, 0, -1, 0, 0, 0, -1, -2, -2, 0, -1, -2, -1, 4, 1, -3, -2,
513           -2, 0, 0, 0, -4 },
514       { 0, -1, 0, -1, -1, -1, -1, -2, -2, -1, -1, -1, -1, -2, -1, 1, 5, -2,
515           -2, 0, -1, -1, 0, -4 },
516       { -3, -3, -4, -4, -2, -2, -3, -2, -2, -3, -2, -3, -1, 1, -4, -3, -2,
517           11, 2, -3, -4, -3, -2, -4 },
518       { -2, -2, -2, -3, -2, -1, -2, -3, 2, -1, -1, -2, -1, 3, -3, -2, -2,
519           2, 7, -1, -3, -2, -1, -4 },
520       { 0, -3, -3, -3, -1, -2, -2, -3, -3, 3, 1, -2, 1, -1, -2, -2, 0, -3,
521           -1, 4, -3, -2, -1, -4 },
522       { -2, -1, 3, 4, -3, 0, 1, -1, 0, -3, -4, 0, -3, -3, -2, 0, -1, -4,
523           -3, -3, 4, 1, -1, -4 },
524       { -1, 0, 0, 1, -3, 3, 4, -2, 0, -3, -3, 1, -1, -3, -1, 0, -1, -3, -2,
525           -2, 1, 4, -1, -4 },
526       { 0, -1, -1, -1, -2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -2, 0, 0,
527           -2, -1, -1, -1, -1, -1, -4 },
528       { -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4, -4,
529           -4, -4, -4, -4, -4, -4, 1 }, };
530
531   static final int[][] PAM250 =
532   {
533       { 2, -2, 0, 0, -2, 0, 0, 1, -1, -1, -2, -1, -1, -3, 1, 1, 1, -6, -3,
534           0, 0, 0, 0, -8 },
535       { -2, 6, 0, -1, -4, 1, -1, -3, 2, -2, -3, 3, 0, -4, 0, 0, -1, 2, -4,
536           -2, -1, 0, -1, -8 },
537       { 0, 0, 2, 2, -4, 1, 1, 0, 2, -2, -3, 1, -2, -3, 0, 1, 0, -4, -2, -2,
538           2, 1, 0, -8 },
539       { 0, -1, 2, 4, -5, 2, 3, 1, 1, -2, -4, 0, -3, -6, -1, 0, 0, -7, -4,
540           -2, 3, 3, -1, -8 },
541       { -2, -4, -4, -5, 12, -5, -5, -3, -3, -2, -6, -5, -5, -4, -3, 0, -2,
542           -8, 0, -2, -4, -5, -3, -8 },
543       { 0, 1, 1, 2, -5, 4, 2, -1, 3, -2, -2, 1, -1, -5, 0, -1, -1, -5, -4,
544           -2, 1, 3, -1, -8 },
545       { 0, -1, 1, 3, -5, 2, 4, 0, 1, -2, -3, 0, -2, -5, -1, 0, 0, -7, -4,
546           -2, 3, 3, -1, -8 },
547       { 1, -3, 0, 1, -3, -1, 0, 5, -2, -3, -4, -2, -3, -5, 0, 1, 0, -7, -5,
548           -1, 0, 0, -1, -8 },
549       { -1, 2, 2, 1, -3, 3, 1, -2, 6, -2, -2, 0, -2, -2, 0, -1, -1, -3, 0,
550           -2, 1, 2, -1, -8 },
551       { -1, -2, -2, -2, -2, -2, -2, -3, -2, 5, 2, -2, 2, 1, -2, -1, 0, -5,
552           -1, 4, -2, -2, -1, -8 },
553       { -2, -3, -3, -4, -6, -2, -3, -4, -2, 2, 6, -3, 4, 2, -3, -3, -2, -2,
554           -1, 2, -3, -3, -1, -8 },
555       { -1, 3, 1, 0, -5, 1, 0, -2, 0, -2, -3, 5, 0, -5, -1, 0, 0, -3, -4,
556           -2, 1, 0, -1, -8 },
557       { -1, 0, -2, -3, -5, -1, -2, -3, -2, 2, 4, 0, 6, 0, -2, -2, -1, -4,
558           -2, 2, -2, -2, -1, -8 },
559       { -3, -4, -3, -6, -4, -5, -5, -5, -2, 1, 2, -5, 0, 9, -5, -3, -3, 0,
560           7, -1, -4, -5, -2, -8 },
561       { 1, 0, 0, -1, -3, 0, -1, 0, 0, -2, -3, -1, -2, -5, 6, 1, 0, -6, -5,
562           -1, -1, 0, -1, -8 },
563       { 1, 0, 1, 0, 0, -1, 0, 1, -1, -1, -3, 0, -2, -3, 1, 2, 1, -2, -3,
564           -1, 0, 0, 0, -8 },
565       { 1, -1, 0, 0, -2, -1, 0, 0, -1, 0, -2, 0, -1, -3, 0, 1, 3, -5, -3,
566           0, 0, -1, 0, -8 },
567       { -6, 2, -4, -7, -8, -5, -7, -7, -3, -5, -2, -3, -4, 0, -6, -2, -5,
568           17, 0, -6, -5, -6, -4, -8 },
569       { -3, -4, -2, -4, 0, -4, -4, -5, 0, -1, -1, -4, -2, 7, -5, -3, -3, 0,
570           10, -2, -3, -4, -2, -8 },
571       { 0, -2, -2, -2, -2, -2, -2, -1, -2, 4, 2, -2, 2, -1, -1, -1, 0, -6,
572           -2, 4, -2, -2, -1, -8 },
573       { 0, -1, 2, 3, -4, 1, 3, 0, 1, -2, -3, 1, -2, -4, -1, 0, 0, -5, -3,
574           -2, 3, 2, -1, -8 },
575       { 0, 0, 1, 3, -5, 3, 3, 0, 2, -2, -3, 0, -2, -5, 0, 0, -1, -6, -4,
576           -2, 2, 3, -1, -8 },
577       { 0, -1, 0, -1, -3, -1, -1, -1, -1, -1, -1, -1, -1, -2, -1, 0, 0, -4,
578           -2, -1, -1, -1, -1, -8 },
579       { -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8, -8,
580           -8, -8, -8, -8, -8, -8, 1 }, };
581
582   public static final Hashtable ssHash = new Hashtable(); // stores the number
583   // value of the aa
584
585   static
586   {
587     ssHash.put("H", Color.magenta);
588     ssHash.put("E", Color.yellow);
589     ssHash.put("-", Color.white);
590     ssHash.put(".", Color.white);
591     ssHash.put("S", Color.cyan);
592     ssHash.put("T", Color.blue);
593     ssHash.put("G", Color.pink);
594     ssHash.put("I", Color.pink);
595     ssHash.put("B", Color.yellow);
596   }
597
598   /*
599    * new Color(60, 136, 238), // U Color.white, // I Color.white, // X
600    * Color.white, // R Color.white, // Y Color.white, // N Color.white, // Gap
601    */
602
603   // JBPNote: patch matrix for T/U equivalence when working with DNA or RNA.
604   // Will equate sequences if working with mixed nucleotide sets.
605   // treats T and U identically. R and Y weak equivalence with AG and CTU.
606   // N matches any other base weakly
607   //
608   static final int[][] DNA =
609   {
610   { 10, -8, -8, -8, -8, 1, 1, 1, -8, 1, 1 }, // A
611       { -8, 10, -8, -8, -8, 1, 1, -8, 1, 1, 1 }, // C
612       { -8, -8, 10, -8, -8, 1, 1, 1, -8, 1, 1 }, // G
613       { -8, -8, -8, 10, 10, 1, 1, -8, 1, 1, 1 }, // T
614       { -8, -8, -8, 10, 10, 1, 1, -8, 1, 1, 1 }, // U
615       { 1, 1, 1, 1, 1, 10, 0, 0, 0, 1, 1 }, // I
616       { 1, 1, 1, 1, 1, 0, 10, 0, 0, 1, 1 }, // X
617       { 1, -8, 1, -8, -8, 0, 0, 10, -8, 1, 1 }, // R
618       { -8, 1, -8, 1, 1, 0, 0, -8, 10, 1, 1 }, // Y
619       { 1, 1, 1, 1, 1, 1, 1, 1, 1, 10, 1 }, // N
620       { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, // -
621   };
622   /**
623    * register matrices in list
624    */
625   static
626   {
627     scoreMatrices.put("BLOSUM62", new ScoreMatrix("BLOSUM62", BLOSUM62, 0));
628     scoreMatrices.put("PAM250", new ScoreMatrix("PAM250", PAM250, 0));
629     scoreMatrices.put("DNA", new ScoreMatrix("DNA", DNA, 1));
630
631   }
632
633   public static final Color[] pidColours =
634   { midBlue, new Color(153, 153, 255),
635       // Color.lightGray,
636       new Color(204, 204, 255), };
637
638   public static final float[] pidThresholds =
639   { 80, 60, 40, };
640
641   public static Map<String, List<String>> codonHash = new HashMap<String, List<String>>();
642
643   private static List<String> Lys = new ArrayList<String>();
644
645   private static List<String> Asn = new ArrayList<String>();
646
647   private static List<String> Gln = new ArrayList<String>();
648
649   private static List<String> His = new ArrayList<String>();
650
651   private static List<String> Glu = new ArrayList<String>();
652
653   private static List<String> Asp = new ArrayList<String>();
654
655   private static List<String> Tyr = new ArrayList<String>();
656
657   private static List<String> Thr = new ArrayList<String>();
658
659   private static List<String> Pro = new ArrayList<String>();
660
661   private static List<String> Ala = new ArrayList<String>();
662
663   private static List<String> Ser = new ArrayList<String>();
664
665   private static List<String> Arg = new ArrayList<String>();
666
667   private static List<String> Gly = new ArrayList<String>();
668
669   private static List<String> Trp = new ArrayList<String>();
670
671   private static List<String> Cys = new ArrayList<String>();
672
673   private static List<String> Ile = new ArrayList<String>();
674
675   private static List<String> Met = new ArrayList<String>();
676
677   private static List<String> Leu = new ArrayList<String>();
678
679   private static List<String> Val = new ArrayList<String>();
680
681   private static List<String> Phe = new ArrayList<String>();
682
683   public static List<String> STOP = new ArrayList<String>();
684
685   public static String START = "ATG";
686
687   static
688   {
689     codonHash.put("K", Lys);
690     codonHash.put("N", Asn);
691     codonHash.put("Q", Gln);
692     codonHash.put("H", His);
693     codonHash.put("E", Glu);
694     codonHash.put("D", Asp);
695     codonHash.put("Y", Tyr);
696     codonHash.put("T", Thr);
697     codonHash.put("P", Pro);
698     codonHash.put("A", Ala);
699     codonHash.put("S", Ser);
700     codonHash.put("R", Arg);
701     codonHash.put("G", Gly);
702     codonHash.put("W", Trp);
703     codonHash.put("C", Cys);
704     codonHash.put("I", Ile);
705     codonHash.put("M", Met);
706     codonHash.put("L", Leu);
707     codonHash.put("V", Val);
708     codonHash.put("F", Phe);
709     codonHash.put("STOP", STOP);
710   }
711
712   /**
713    * Nucleotide Ambiguity Codes
714    */
715   public static final Map<String, String[]> ambiguityCodes = new Hashtable<String, String[]>();
716
717   /**
718    * Codon triplets with additional symbols for unambiguous codons that include
719    * ambiguity codes
720    */
721   public static final Hashtable<String, String> codonHash2 = new Hashtable<String, String>();
722
723   /**
724    * all ambiguity codes for a given base
725    */
726   public final static Hashtable<String, List<String>> _ambiguityCodes = new Hashtable<String, List<String>>();
727
728   static
729   {
730     /*
731      * Ambiguity codes as per http://www.chem.qmul.ac.uk/iubmb/misc/naseq.html
732      */
733     ambiguityCodes.put("R", new String[]
734     { "A", "G" });
735     ambiguityCodes.put("Y", new String[]
736     { "T", "C" });
737     ambiguityCodes.put("W", new String[]
738     { "A", "T" });
739     ambiguityCodes.put("S", new String[]
740     { "G", "C" });
741     ambiguityCodes.put("M", new String[]
742     { "A", "C" });
743     ambiguityCodes.put("K", new String[]
744     { "G", "T" });
745     ambiguityCodes.put("H", new String[]
746     { "A", "T", "C" });
747     ambiguityCodes.put("B", new String[]
748     { "G", "T", "C" });
749     ambiguityCodes.put("V", new String[]
750     { "G", "A", "C" });
751     ambiguityCodes.put("D", new String[]
752     { "G", "A", "T" });
753     ambiguityCodes.put("N", new String[]
754     { "G", "A", "T", "C" });
755
756     // Now build codon translation table
757     codonHash2.put("AAA", "K");
758     codonHash2.put("AAG", "K");
759     codonHash2.put("AAC", "N");
760     codonHash2.put("AAT", "N");
761
762     codonHash2.put("CAA", "Q");
763     codonHash2.put("CAG", "Q");
764     codonHash2.put("CAC", "H");
765     codonHash2.put("CAT", "H");
766
767     codonHash2.put("GAA", "E");
768     codonHash2.put("GAG", "E");
769     codonHash2.put("GAC", "D");
770     codonHash2.put("GAT", "D");
771
772     codonHash2.put("TAC", "Y");
773     codonHash2.put("TAT", "Y");
774
775     codonHash2.put("ACA", "T");
776     codonHash2.put("ACC", "T");
777     codonHash2.put("ACT", "T");
778     codonHash2.put("ACG", "T");
779
780     codonHash2.put("CCA", "P");
781     codonHash2.put("CCG", "P");
782     codonHash2.put("CCC", "P");
783     codonHash2.put("CCT", "P");
784
785     codonHash2.put("GCA", "A");
786     codonHash2.put("GCG", "A");
787     codonHash2.put("GCC", "A");
788     codonHash2.put("GCT", "A");
789
790     codonHash2.put("TCA", "S");
791     codonHash2.put("TCG", "S");
792     codonHash2.put("TCC", "S");
793     codonHash2.put("TCT", "S");
794     codonHash2.put("AGC", "S");
795     codonHash2.put("AGT", "S");
796
797     codonHash2.put("AGA", "R");
798     codonHash2.put("AGG", "R");
799     codonHash2.put("CGA", "R");
800     codonHash2.put("CGG", "R");
801     codonHash2.put("CGC", "R");
802     codonHash2.put("CGT", "R");
803
804     codonHash2.put("GGA", "G");
805     codonHash2.put("GGG", "G");
806     codonHash2.put("GGC", "G");
807     codonHash2.put("GGT", "G");
808
809     codonHash2.put("TGA", "*");
810     codonHash2.put("TAA", "*");
811     codonHash2.put("TAG", "*");
812
813     codonHash2.put("TGG", "W");
814
815     codonHash2.put("TGC", "C");
816     codonHash2.put("TGT", "C");
817
818     codonHash2.put("ATA", "I");
819     codonHash2.put("ATC", "I");
820     codonHash2.put("ATT", "I");
821
822     codonHash2.put("ATG", "M");
823
824     codonHash2.put("CTA", "L");
825     codonHash2.put("CTG", "L");
826     codonHash2.put("CTC", "L");
827     codonHash2.put("CTT", "L");
828     codonHash2.put("TTA", "L");
829     codonHash2.put("TTG", "L");
830
831     codonHash2.put("GTA", "V");
832     codonHash2.put("GTG", "V");
833     codonHash2.put("GTC", "V");
834     codonHash2.put("GTT", "V");
835
836     codonHash2.put("TTC", "F");
837     codonHash2.put("TTT", "F");
838
839     buildAmbiguityCodonSet();
840   }
841
842   /**
843    * programmatic generation of codons including ambiguity codes
844    */
845   public static void buildAmbiguityCodonSet()
846   {
847     if (_ambiguityCodes.size() > 0)
848     {
849       System.err
850               .println("Ignoring multiple calls to buildAmbiguityCodonSet");
851       return;
852     }
853     // Invert the ambiguity code set
854     for (Map.Entry<String, String[]> acode : ambiguityCodes.entrySet())
855     {
856       for (String r : acode.getValue())
857       {
858         List<String> codesfor = _ambiguityCodes.get(r);
859         if (codesfor == null)
860         {
861           _ambiguityCodes.put(r, codesfor = new ArrayList<String>());
862         }
863         if (!codesfor.contains(acode.getKey()))
864         {
865           codesfor.add(acode.getKey());
866         }
867         else
868         {
869           System.err
870                   .println("Inconsistency in the IUBMB ambiguity code nomenclature table: collision for "
871                           + acode.getKey() + " in residue " + r);
872         }
873       }
874     }
875     // and programmatically add in the ambiguity codes that yield the same amino
876     // acid
877     
878     
879     String[] unambcodons = codonHash2.keySet().toArray(
880             new String[codonHash2.size()]);
881     for (String codon : unambcodons)
882     {
883       String residue = codonHash2.get(codon);
884       String acodon[][] = new String[codon.length()][];
885       for (int i = 0, iSize = codon.length(); i < iSize; i++)
886       {
887         String _ac = "" + codon.charAt(i);
888         List<String> acodes = _ambiguityCodes.get(_ac);
889         if (acodes != null)
890         {
891           acodon[i] = acodes.toArray(new String[acodes.size()]);
892         }
893         else
894         {
895           acodon[i] = new String[]
896           {};
897         }
898       }
899       // enumerate all combinations and test for veracity of translation
900       int tpos[] = new int[codon.length()], cpos[] = new int[codon.length()];
901       for (int i = 0; i < tpos.length; i++)
902       {
903         tpos[i] = -1;
904       }
905       tpos[acodon.length - 1] = 0;
906       int ipos, j;
907       while (tpos[0] < acodon[0].length)
908       {
909         // make all codons for this combination
910         char allres[][] = new char[tpos.length][];
911         String _acodon = "";
912         char _anuc;
913         for (ipos = 0; ipos < tpos.length; ipos++)
914         {
915           if (acodon[ipos].length == 0 || tpos[ipos] < 0)
916           {
917             _acodon += codon.charAt(ipos);
918             allres[ipos] = new char[]
919             { codon.charAt(ipos) };
920           }
921           else
922           {
923             _acodon += acodon[ipos][tpos[ipos]];
924             String[] altbase = ambiguityCodes.get(acodon[ipos][tpos[ipos]]);
925             allres[ipos] = new char[altbase.length];
926             j = 0;
927             for (String ab : altbase)
928             {
929               allres[ipos][j++] = ab.charAt(0);
930             }
931           }
932         }
933         // test all codons for this combination
934         for (ipos = 0; ipos < cpos.length; ipos++)
935         {
936           cpos[ipos] = 0;
937         }
938         boolean valid = true;
939         do
940         {
941           String _codon = "";
942           for (j = 0; j < cpos.length; j++)
943           {
944             _codon += allres[j][cpos[j]];
945           }
946           String tr = codonHash2.get(_codon);
947           if (valid = (tr != null && tr.equals(residue)))
948           {
949             // advance to next combination
950             ipos = acodon.length - 1;
951             while (++cpos[ipos] >= allres[ipos].length && ipos > 0)
952             {
953               cpos[ipos] = 0;
954               ipos--;
955             }
956           }
957         } while (valid && cpos[0] < allres[0].length);
958         if (valid)
959         {
960           // Add this to the set of codons we will translate
961           // System.out.println("Adding ambiguity codon: " + _acodon + " for "
962           // + residue);
963           codonHash2.put(_acodon, residue);
964         }
965         else
966         {
967           // System.err.println("Rejecting ambiguity codon: " + _acodon
968           // + " for " + residue);
969         }
970         // next combination
971         ipos = acodon.length - 1;
972         while (++tpos[ipos] >= acodon[ipos].length && ipos > 0)
973         {
974           tpos[ipos] = -1;
975           ipos--;
976         }
977       }
978     }
979
980   }
981
982   static
983   {
984     Lys.add("AAA");
985     Lys.add("AAG");
986     Asn.add("AAC");
987     Asn.add("AAT");
988
989     Gln.add("CAA");
990     Gln.add("CAG");
991     His.add("CAC");
992     His.add("CAT");
993
994     Glu.add("GAA");
995     Glu.add("GAG");
996     Asp.add("GAC");
997     Asp.add("GAT");
998
999     Tyr.add("TAC");
1000     Tyr.add("TAT");
1001
1002     Thr.add("ACA");
1003     Thr.add("ACG");
1004     Thr.add("ACC");
1005     Thr.add("ACT");
1006
1007     Pro.add("CCA");
1008     Pro.add("CCG");
1009     Pro.add("CCC");
1010     Pro.add("CCT");
1011
1012     Ala.add("GCA");
1013     Ala.add("GCG");
1014     Ala.add("GCC");
1015     Ala.add("GCT");
1016
1017     Ser.add("TCA");
1018     Ser.add("TCG");
1019     Ser.add("TCC");
1020     Ser.add("TCT");
1021     Ser.add("AGC");
1022     Ser.add("AGT");
1023
1024     Arg.add("AGA");
1025     Arg.add("AGG");
1026     Arg.add("CGA");
1027     Arg.add("CGG");
1028     Arg.add("CGC");
1029     Arg.add("CGT");
1030
1031     Gly.add("GGA");
1032     Gly.add("GGG");
1033     Gly.add("GGC");
1034     Gly.add("GGT");
1035
1036     STOP.add("TGA");
1037     STOP.add("TAA");
1038     STOP.add("TAG");
1039
1040     Trp.add("TGG");
1041
1042     Cys.add("TGC");
1043     Cys.add("TGT");
1044
1045     Ile.add("ATA");
1046     Ile.add("ATC");
1047     Ile.add("ATT");
1048
1049     Met.add("ATG");
1050
1051     Leu.add("CTA");
1052     Leu.add("CTG");
1053     Leu.add("CTC");
1054     Leu.add("CTT");
1055     Leu.add("TTA");
1056     Leu.add("TTG");
1057
1058     Val.add("GTA");
1059     Val.add("GTG");
1060     Val.add("GTC");
1061     Val.add("GTT");
1062
1063     Phe.add("TTC");
1064     Phe.add("TTT");
1065   }
1066
1067   // Stores residue codes/names and colours and other things
1068   public static Hashtable propHash = new Hashtable();
1069
1070   public static Hashtable hydrophobic = new Hashtable();
1071
1072   public static Hashtable polar = new Hashtable();
1073
1074   public static Hashtable small = new Hashtable();
1075
1076   public static Hashtable positive = new Hashtable();
1077
1078   public static Hashtable negative = new Hashtable();
1079
1080   public static Hashtable charged = new Hashtable();
1081
1082   public static Hashtable aromatic = new Hashtable();
1083
1084   public static Hashtable aliphatic = new Hashtable();
1085
1086   public static Hashtable tiny = new Hashtable();
1087
1088   public static Hashtable proline = new Hashtable();
1089
1090   static
1091   {
1092     hydrophobic.put("I", new Integer(1));
1093     hydrophobic.put("L", new Integer(1));
1094     hydrophobic.put("V", new Integer(1));
1095     hydrophobic.put("C", new Integer(1));
1096     hydrophobic.put("A", new Integer(1));
1097     hydrophobic.put("G", new Integer(1));
1098     hydrophobic.put("M", new Integer(1));
1099     hydrophobic.put("F", new Integer(1));
1100     hydrophobic.put("Y", new Integer(1));
1101     hydrophobic.put("W", new Integer(1));
1102     hydrophobic.put("H", new Integer(1));
1103     hydrophobic.put("K", new Integer(1));
1104     hydrophobic.put("X", new Integer(1));
1105     hydrophobic.put("-", new Integer(1));
1106     hydrophobic.put("*", new Integer(1));
1107     hydrophobic.put("R", new Integer(0));
1108     hydrophobic.put("E", new Integer(0));
1109     hydrophobic.put("Q", new Integer(0));
1110     hydrophobic.put("D", new Integer(0));
1111     hydrophobic.put("N", new Integer(0));
1112     hydrophobic.put("S", new Integer(0));
1113     hydrophobic.put("T", new Integer(0));
1114     hydrophobic.put("P", new Integer(0));
1115   }
1116
1117   static
1118   {
1119     polar.put("Y", new Integer(1));
1120     polar.put("W", new Integer(1));
1121     polar.put("H", new Integer(1));
1122     polar.put("K", new Integer(1));
1123     polar.put("R", new Integer(1));
1124     polar.put("E", new Integer(1));
1125     polar.put("Q", new Integer(1));
1126     polar.put("D", new Integer(1));
1127     polar.put("N", new Integer(1));
1128     polar.put("S", new Integer(1));
1129     polar.put("T", new Integer(1));
1130     polar.put("X", new Integer(1));
1131     polar.put("-", new Integer(1));
1132     polar.put("*", new Integer(1));
1133     polar.put("I", new Integer(0));
1134     polar.put("L", new Integer(0));
1135     polar.put("V", new Integer(0));
1136     polar.put("C", new Integer(0));
1137     polar.put("A", new Integer(0));
1138     polar.put("G", new Integer(0));
1139     polar.put("M", new Integer(0));
1140     polar.put("F", new Integer(0));
1141     polar.put("P", new Integer(0));
1142   }
1143
1144   static
1145   {
1146     small.put("I", new Integer(0));
1147     small.put("L", new Integer(0));
1148     small.put("V", new Integer(1));
1149     small.put("C", new Integer(1));
1150     small.put("A", new Integer(1));
1151     small.put("G", new Integer(1));
1152     small.put("M", new Integer(0));
1153     small.put("F", new Integer(0));
1154     small.put("Y", new Integer(0));
1155     small.put("W", new Integer(0));
1156     small.put("H", new Integer(0));
1157     small.put("K", new Integer(0));
1158     small.put("R", new Integer(0));
1159     small.put("E", new Integer(0));
1160     small.put("Q", new Integer(0));
1161     small.put("D", new Integer(1));
1162     small.put("N", new Integer(1));
1163     small.put("S", new Integer(1));
1164     small.put("T", new Integer(1));
1165     small.put("P", new Integer(1));
1166     small.put("-", new Integer(1));
1167     small.put("*", new Integer(1));
1168   }
1169
1170   static
1171   {
1172     positive.put("I", new Integer(0));
1173     positive.put("L", new Integer(0));
1174     positive.put("V", new Integer(0));
1175     positive.put("C", new Integer(0));
1176     positive.put("A", new Integer(0));
1177     positive.put("G", new Integer(0));
1178     positive.put("M", new Integer(0));
1179     positive.put("F", new Integer(0));
1180     positive.put("Y", new Integer(0));
1181     positive.put("W", new Integer(0));
1182     positive.put("H", new Integer(1));
1183     positive.put("K", new Integer(1));
1184     positive.put("R", new Integer(1));
1185     positive.put("E", new Integer(0));
1186     positive.put("Q", new Integer(0));
1187     positive.put("D", new Integer(0));
1188     positive.put("N", new Integer(0));
1189     positive.put("S", new Integer(0));
1190     positive.put("T", new Integer(0));
1191     positive.put("P", new Integer(0));
1192     positive.put("-", new Integer(1));
1193     positive.put("*", new Integer(1));
1194   }
1195
1196   static
1197   {
1198     negative.put("I", new Integer(0));
1199     negative.put("L", new Integer(0));
1200     negative.put("V", new Integer(0));
1201     negative.put("C", new Integer(0));
1202     negative.put("A", new Integer(0));
1203     negative.put("G", new Integer(0));
1204     negative.put("M", new Integer(0));
1205     negative.put("F", new Integer(0));
1206     negative.put("Y", new Integer(0));
1207     negative.put("W", new Integer(0));
1208     negative.put("H", new Integer(0));
1209     negative.put("K", new Integer(0));
1210     negative.put("R", new Integer(0));
1211     negative.put("E", new Integer(1));
1212     negative.put("Q", new Integer(0));
1213     negative.put("D", new Integer(1));
1214     negative.put("N", new Integer(0));
1215     negative.put("S", new Integer(0));
1216     negative.put("T", new Integer(0));
1217     negative.put("P", new Integer(0));
1218     negative.put("-", new Integer(1));
1219     negative.put("*", new Integer(1));
1220   }
1221
1222   static
1223   {
1224     charged.put("I", new Integer(0));
1225     charged.put("L", new Integer(0));
1226     charged.put("V", new Integer(0));
1227     charged.put("C", new Integer(0));
1228     charged.put("A", new Integer(0));
1229     charged.put("G", new Integer(0));
1230     charged.put("M", new Integer(0));
1231     charged.put("F", new Integer(0));
1232     charged.put("Y", new Integer(0));
1233     charged.put("W", new Integer(0));
1234     charged.put("H", new Integer(1));
1235     charged.put("K", new Integer(1));
1236     charged.put("R", new Integer(1));
1237     charged.put("E", new Integer(1));
1238     charged.put("Q", new Integer(0));
1239     charged.put("D", new Integer(1));
1240     charged.put("N", new Integer(0)); // Asparagine is polar but not charged.
1241                                       // Alternative would be charged and
1242                                       // negative (in basic form)?
1243     charged.put("S", new Integer(0));
1244     charged.put("T", new Integer(0));
1245     charged.put("P", new Integer(0));
1246     charged.put("-", new Integer(1));
1247     charged.put("*", new Integer(1));
1248   }
1249
1250   static
1251   {
1252     aromatic.put("I", new Integer(0));
1253     aromatic.put("L", new Integer(0));
1254     aromatic.put("V", new Integer(0));
1255     aromatic.put("C", new Integer(0));
1256     aromatic.put("A", new Integer(0));
1257     aromatic.put("G", new Integer(0));
1258     aromatic.put("M", new Integer(0));
1259     aromatic.put("F", new Integer(1));
1260     aromatic.put("Y", new Integer(1));
1261     aromatic.put("W", new Integer(1));
1262     aromatic.put("H", new Integer(1));
1263     aromatic.put("K", new Integer(0));
1264     aromatic.put("R", new Integer(0));
1265     aromatic.put("E", new Integer(0));
1266     aromatic.put("Q", new Integer(0));
1267     aromatic.put("D", new Integer(0));
1268     aromatic.put("N", new Integer(0));
1269     aromatic.put("S", new Integer(0));
1270     aromatic.put("T", new Integer(0));
1271     aromatic.put("P", new Integer(0));
1272     aromatic.put("-", new Integer(1));
1273     aromatic.put("*", new Integer(1));
1274   }
1275
1276   static
1277   {
1278     aliphatic.put("I", new Integer(1));
1279     aliphatic.put("L", new Integer(1));
1280     aliphatic.put("V", new Integer(1));
1281     aliphatic.put("C", new Integer(0));
1282     aliphatic.put("A", new Integer(0));
1283     aliphatic.put("G", new Integer(0));
1284     aliphatic.put("M", new Integer(0));
1285     aliphatic.put("F", new Integer(0));
1286     aliphatic.put("Y", new Integer(0));
1287     aliphatic.put("W", new Integer(0));
1288     aliphatic.put("H", new Integer(0));
1289     aliphatic.put("K", new Integer(0));
1290     aliphatic.put("R", new Integer(0));
1291     aliphatic.put("E", new Integer(0));
1292     aliphatic.put("Q", new Integer(0));
1293     aliphatic.put("D", new Integer(0));
1294     aliphatic.put("N", new Integer(0));
1295     aliphatic.put("S", new Integer(0));
1296     aliphatic.put("T", new Integer(0));
1297     aliphatic.put("P", new Integer(0));
1298     aliphatic.put("-", new Integer(1));
1299     aliphatic.put("*", new Integer(1));
1300   }
1301
1302   static
1303   {
1304     tiny.put("I", new Integer(0));
1305     tiny.put("L", new Integer(0));
1306     tiny.put("V", new Integer(0));
1307     tiny.put("C", new Integer(0));
1308     tiny.put("A", new Integer(1));
1309     tiny.put("G", new Integer(1));
1310     tiny.put("M", new Integer(0));
1311     tiny.put("F", new Integer(0));
1312     tiny.put("Y", new Integer(0));
1313     tiny.put("W", new Integer(0));
1314     tiny.put("H", new Integer(0));
1315     tiny.put("K", new Integer(0));
1316     tiny.put("R", new Integer(0));
1317     tiny.put("E", new Integer(0));
1318     tiny.put("Q", new Integer(0));
1319     tiny.put("D", new Integer(0));
1320     tiny.put("N", new Integer(0));
1321     tiny.put("S", new Integer(1));
1322     tiny.put("T", new Integer(0));
1323     tiny.put("P", new Integer(0));
1324     tiny.put("-", new Integer(1));
1325     tiny.put("*", new Integer(1));
1326   }
1327
1328   static
1329   {
1330     proline.put("I", new Integer(0));
1331     proline.put("L", new Integer(0));
1332     proline.put("V", new Integer(0));
1333     proline.put("C", new Integer(0));
1334     proline.put("A", new Integer(0));
1335     proline.put("G", new Integer(0));
1336     proline.put("M", new Integer(0));
1337     proline.put("F", new Integer(0));
1338     proline.put("Y", new Integer(0));
1339     proline.put("W", new Integer(0));
1340     proline.put("H", new Integer(0));
1341     proline.put("K", new Integer(0));
1342     proline.put("R", new Integer(0));
1343     proline.put("E", new Integer(0));
1344     proline.put("Q", new Integer(0));
1345     proline.put("D", new Integer(0));
1346     proline.put("N", new Integer(0));
1347     proline.put("S", new Integer(0));
1348     proline.put("T", new Integer(0));
1349     proline.put("P", new Integer(1));
1350     proline.put("-", new Integer(1));
1351     proline.put("*", new Integer(1));
1352   }
1353
1354   static
1355   {
1356     propHash.put("hydrophobic", hydrophobic);
1357     propHash.put("small", small);
1358     propHash.put("positive", positive);
1359     propHash.put("negative", negative);
1360     propHash.put("charged", charged);
1361     propHash.put("aromatic", aromatic);
1362     propHash.put("aliphatic", aliphatic);
1363     propHash.put("tiny", tiny);
1364     propHash.put("proline", proline);
1365     propHash.put("polar", polar);
1366   }
1367   static
1368   {
1369     int[][] propMatrixF = new int[maxProteinIndex][maxProteinIndex], propMatrixPos = new int[maxProteinIndex][maxProteinIndex], propMatrixEpos = new int[maxProteinIndex][maxProteinIndex];
1370     for (int i = 0; i < maxProteinIndex; i++)
1371     {
1372       int maxF = 0, maxP = 0, maxEP = 0;
1373       String ic = "";
1374       if (aa.length > i)
1375       {
1376         ic += aa[i];
1377       }
1378       else
1379       {
1380         ic = "-";
1381       }
1382       for (int j = i + 1; j < maxProteinIndex; j++)
1383       {
1384         String jc = "";
1385         if (aa.length > j)
1386         {
1387           jc += aa[j];
1388         }
1389         else
1390         {
1391           jc = "-";
1392         }
1393         propMatrixF[i][j] = 0;
1394         propMatrixPos[i][j] = 0;
1395         propMatrixEpos[i][j] = 0;
1396         for (Enumeration<String> en = propHash.keys(); en
1397                 .hasMoreElements();)
1398         {
1399           String ph = en.nextElement();
1400           Map<String, Integer> pph = (Map<String, Integer>) propHash
1401                   .get(ph);
1402           if (pph.get(ic) != null && pph.get(jc) != null)
1403           {
1404             int icp = pph.get(ic).intValue(), jcp = pph.get(jc).intValue();
1405             // Still working on these definitions.
1406             propMatrixPos[i][j] += icp == jcp && icp > 0 ? 2 : 0;
1407             propMatrixPos[j][i] += icp == jcp && icp > 0 ? 2 : 0;
1408             propMatrixF[i][j] += icp == jcp ? 2 : 0;
1409             propMatrixF[j][i] += icp == jcp ? 2 : 0;
1410             propMatrixEpos[i][j] += icp == jcp ? (1 + icp * 2) : 0;
1411             propMatrixEpos[j][i] += icp == jcp ? (1 + icp * 2) : 0;
1412           }
1413         }
1414         if (maxF < propMatrixF[i][j])
1415         {
1416           maxF = propMatrixF[i][j];
1417         }
1418         if (maxP < propMatrixPos[i][j])
1419         {
1420           maxP = propMatrixPos[i][j];
1421         }
1422         if (maxEP < propMatrixEpos[i][j])
1423         {
1424           maxEP = propMatrixEpos[i][j];
1425         }
1426       }
1427       propMatrixF[i][i] = maxF;
1428       propMatrixPos[i][i] = maxP;
1429       propMatrixEpos[i][i] = maxEP;
1430     }
1431     // JAL-1512 comment out physicochemical score matrices for 2.8.1 release
1432     // scoreMatrices.put("Conservation Pos", new
1433     // ScoreMatrix("Conservation Pos",propMatrixPos,0));
1434     // scoreMatrices.put("Conservation Both", new
1435     // ScoreMatrix("Conservation Both",propMatrixF,0));
1436     // scoreMatrices.put("Conservation EnhPos", new
1437     // ScoreMatrix("Conservation EnhPos",propMatrixEpos,0));
1438     scoreMatrices.put("PID", new PIDScoreModel());
1439     scoreMatrices.put("Displayed Features", new FeatureScoreModel());
1440   }
1441
1442   private ResidueProperties()
1443   {
1444   }
1445
1446   public static double getHydmax()
1447   {
1448     return hydmax;
1449   }
1450
1451   public static double getHydmin()
1452   {
1453     return hydmin;
1454   }
1455
1456   public static double[] getHyd()
1457   {
1458     return hyd;
1459   }
1460
1461   public static Map<String, Integer> getAA3Hash()
1462   {
1463     return aa3Hash;
1464   }
1465
1466   public static int[][] getDNA()
1467   {
1468     return ResidueProperties.DNA;
1469   }
1470
1471   public static int[][] getBLOSUM62()
1472   {
1473     return ResidueProperties.BLOSUM62;
1474   }
1475
1476   public static int getPAM250(String A1, String A2)
1477   {
1478     return getPAM250(A1.charAt(0), A2.charAt(0));
1479   }
1480
1481   public static int getBLOSUM62(char c1, char c2)
1482   {
1483     int pog = 0;
1484
1485     try
1486     {
1487       int a = aaIndex[c1];
1488       int b = aaIndex[c2];
1489
1490       pog = ResidueProperties.BLOSUM62[a][b];
1491     } catch (Exception e)
1492     {
1493       // System.out.println("Unknown residue in " + A1 + " " + A2);
1494     }
1495
1496     return pog;
1497   }
1498
1499   public static Vector getCodons(String res)
1500   {
1501     if (codonHash.containsKey(res))
1502     {
1503       return (Vector) codonHash.get(res);
1504     }
1505
1506     return null;
1507   }
1508
1509   public static String codonTranslate(String lccodon)
1510   {
1511     if (false)
1512     {
1513       return _codonTranslate(lccodon);
1514     }
1515     String cdn = codonHash2.get(lccodon.toUpperCase());
1516     if (cdn != null && cdn.equals("*"))
1517     {
1518       return "STOP";
1519     }
1520     return cdn;
1521   }
1522
1523   public static String _codonTranslate(String lccodon)
1524   {
1525     String codon = lccodon.toUpperCase();
1526     // all base ambiguity codes yield an 'X' amino acid residue
1527     if (codon.indexOf('X') > -1 || codon.indexOf('N') > -1)
1528     {
1529       return "X";
1530     }
1531     for (String key : codonHash.keySet())
1532     {
1533       if (codonHash.get(key).contains(codon))
1534       {
1535         return key;
1536       }
1537     }
1538
1539     return null;
1540   }
1541
1542   public static int[][] getDefaultPeptideMatrix()
1543   {
1544     return ResidueProperties.getBLOSUM62();
1545   }
1546
1547   public static int[][] getDefaultDnaMatrix()
1548   {
1549     return ResidueProperties.getDNA();
1550   }
1551
1552   /**
1553    * get a ScoreMatrix based on its string name
1554    * 
1555    * @param pwtype
1556    * @return matrix in scoreMatrices with key pwtype or null
1557    */
1558   public static ScoreMatrix getScoreMatrix(String pwtype)
1559   {
1560     Object val = scoreMatrices.get(pwtype);
1561     if (val != null && val instanceof ScoreMatrix)
1562     {
1563       return (ScoreMatrix) val;
1564     }
1565     return null;
1566   }
1567
1568   /**
1569    * get a ScoreModel based on its string name
1570    * 
1571    * @param pwtype
1572    * @return scoremodel of type pwtype or null
1573    */
1574   public static ScoreModelI getScoreModel(String pwtype)
1575   {
1576     return scoreMatrices.get(pwtype);
1577   }
1578
1579   public static int getPAM250(char c, char d)
1580   {
1581     int a = aaIndex[c];
1582     int b = aaIndex[d];
1583
1584     int pog = ResidueProperties.PAM250[a][b];
1585
1586     return pog;
1587   }
1588
1589   public static Hashtable toDssp3State;
1590   static
1591   {
1592     toDssp3State = new Hashtable();
1593     toDssp3State.put("H", "H");
1594     toDssp3State.put("E", "E");
1595     toDssp3State.put("C", " ");
1596     toDssp3State.put(" ", " ");
1597     toDssp3State.put("T", " ");
1598     toDssp3State.put("B", "E");
1599     toDssp3State.put("G", "H");
1600     toDssp3State.put("I", "H");
1601     toDssp3State.put("X", " ");
1602   }
1603
1604   /**
1605    * translate from other dssp secondary structure alphabets to 3-state
1606    * 
1607    * @param ssstring
1608    * @return ssstring as a three-state secondary structure assignment.
1609    */
1610   public static String getDssp3state(String ssstring)
1611   {
1612     if (ssstring == null)
1613     {
1614       return null;
1615     }
1616     StringBuffer ss = new StringBuffer();
1617     for (int i = 0; i < ssstring.length(); i++)
1618     {
1619       String ssc = ssstring.substring(i, i + 1);
1620       if (toDssp3State.containsKey(ssc))
1621       {
1622         ss.append((String) toDssp3State.get(ssc));
1623       }
1624       else
1625       {
1626         ss.append(" ");
1627       }
1628     }
1629     return ss.toString();
1630   }
1631
1632   /**
1633    * Used by getRNASecStrucState
1634    * 
1635    */
1636   public static Hashtable<String, String> toRNAssState;
1637
1638   public static boolean RNAcloseParen[] = new boolean[255];
1639   static
1640   {
1641     toRNAssState = new Hashtable<String, String>();
1642     toRNAssState.put(")", "(");
1643     toRNAssState.put("(", "(");
1644     toRNAssState.put("]", "[");
1645     toRNAssState.put("[", "[");
1646     toRNAssState.put("{", "{");
1647     toRNAssState.put("}", "{");
1648     toRNAssState.put(">", ">");
1649     toRNAssState.put("<", ">");
1650     toRNAssState.put("A", "A");
1651     toRNAssState.put("a", "A");
1652     toRNAssState.put("B", "B");
1653     toRNAssState.put("b", "B");
1654     toRNAssState.put("C", "C");
1655     toRNAssState.put("c", "C");
1656     toRNAssState.put("D", "D");
1657     toRNAssState.put("d", "D");
1658     toRNAssState.put("E", "E");
1659     toRNAssState.put("e", "E");
1660     toRNAssState.put("F", "F");
1661     toRNAssState.put("f", "F");
1662     toRNAssState.put("G", "G");
1663     toRNAssState.put("g", "G");
1664     toRNAssState.put("H", "H");
1665     toRNAssState.put("h", "H");
1666     toRNAssState.put("I", "I");
1667     toRNAssState.put("i", "I");
1668     toRNAssState.put("J", "J");
1669     toRNAssState.put("j", "J");
1670     toRNAssState.put("K", "K");
1671     toRNAssState.put("k", "K");
1672     toRNAssState.put("L", "L");
1673     toRNAssState.put("l", "L");
1674     toRNAssState.put("M", "M");
1675     toRNAssState.put("m", "M");
1676     toRNAssState.put("N", "N");
1677     toRNAssState.put("n", "N");
1678     toRNAssState.put("O", "O");
1679     toRNAssState.put("o", "O");
1680     toRNAssState.put("P", "P");
1681     toRNAssState.put("p", "P");
1682     toRNAssState.put("Q", "Q");
1683     toRNAssState.put("q", "Q");
1684     toRNAssState.put("R", "R");
1685     toRNAssState.put("r", "R");
1686     toRNAssState.put("S", "S");
1687     toRNAssState.put("s", "S");
1688     toRNAssState.put("T", "T");
1689     toRNAssState.put("t", "T");
1690     toRNAssState.put("U", "U");
1691     toRNAssState.put("u", "U");
1692     toRNAssState.put("V", "V");
1693     toRNAssState.put("v", "V");
1694     toRNAssState.put("W", "W");
1695     toRNAssState.put("w", "W");
1696     toRNAssState.put("X", "X");
1697     toRNAssState.put("x", "X");
1698     toRNAssState.put("Y", "Y");
1699     toRNAssState.put("y", "Y");
1700     toRNAssState.put("Z", "Z");
1701     toRNAssState.put("z", "Z");
1702     for (int p = 0; p < RNAcloseParen.length; p++)
1703     {
1704       RNAcloseParen[p] = false;
1705     }
1706     for (String k : toRNAssState.keySet())
1707     {
1708       RNAcloseParen[k.charAt(0)] = k.charAt(0) != toRNAssState.get(k)
1709               .charAt(0);
1710     }
1711   }
1712
1713   /**
1714    * translate to RNA secondary structure representation
1715    * 
1716    * @param ssstring
1717    * @return ssstring as a RNA-state secondary structure assignment.
1718    */
1719   public static String getRNASecStrucState(String ssstring)
1720   {
1721     if (ssstring == null)
1722     {
1723       return null;
1724     }
1725     StringBuffer ss = new StringBuffer();
1726     for (int i = 0; i < ssstring.length(); i++)
1727     {
1728       String ssc = ssstring.substring(i, i + 1);
1729       if (toRNAssState.containsKey(ssc))
1730       {
1731         // valid ss character - so return it
1732         ss.append(ssc); // (String) toRNAssState.get(ssc));
1733       }
1734       else
1735       {
1736         ss.append(" ");
1737       }
1738     }
1739     return ss.toString();
1740   }
1741
1742   public static boolean isCloseParenRNA(char dc)
1743   {
1744     return RNAcloseParen[dc];
1745   }
1746
1747   // main method generates perl representation of residue property hash
1748   // / cut here
1749   
1750   /**
1751    * @j2sIgnore
1752    * 
1753    * @param args
1754    */
1755   public static void main(String[] args)
1756   {
1757     Hashtable aa = new Hashtable();
1758     System.out.println("my %aa = {");
1759     // invert property hashes
1760     Enumeration prop = propHash.keys();
1761     while (prop.hasMoreElements())
1762     {
1763       String pname = (String) prop.nextElement();
1764       Hashtable phash = (Hashtable) propHash.get(pname);
1765       Enumeration res = phash.keys();
1766       while (res.hasMoreElements())
1767       {
1768         String rname = (String) res.nextElement();
1769         Vector aprops = (Vector) aa.get(rname);
1770         if (aprops == null)
1771         {
1772           aprops = new Vector();
1773           aa.put(rname, aprops);
1774         }
1775         Integer hasprop = (Integer) phash.get(rname);
1776         if (hasprop.intValue() == 1)
1777         {
1778           aprops.addElement(pname);
1779         }
1780       }
1781     }
1782     Enumeration res = aa.keys();
1783     while (res.hasMoreElements())
1784     {
1785       String rname = (String) res.nextElement();
1786
1787       System.out.print("'" + rname + "' => [");
1788       Enumeration props = ((Vector) aa.get(rname)).elements();
1789       while (props.hasMoreElements())
1790       {
1791         System.out.print("'" + (String) props.nextElement() + "'");
1792         if (props.hasMoreElements())
1793         {
1794           System.out.println(", ");
1795         }
1796       }
1797       System.out.println("]" + (res.hasMoreElements() ? "," : ""));
1798     }
1799     System.out.println("};");
1800   }
1801   // to here
1802
1803   /**
1804    * Returns a list of residue characters for the specified inputs
1805    * 
1806    * @param nucleotide
1807    * @param includeAmbiguous
1808    * @return
1809    */
1810   public static List<String> getResidues(boolean nucleotide,
1811           boolean includeAmbiguous)
1812   {
1813     List<String> result = new ArrayList<String>();
1814     if (nucleotide)
1815     {
1816       for (String nuc : nucleotideName.keySet())
1817       {
1818         int val = nucleotideIndex[nuc.charAt(0)];
1819         if ((!includeAmbiguous && val > 4) || (val >= maxNucleotideIndex))
1820         {
1821           continue;
1822         }
1823         nuc = nuc.toUpperCase();
1824         if (!result.contains(nuc))
1825         {
1826           result.add(nuc);
1827         }
1828       }
1829     } else {
1830       /*
1831        * Peptide
1832        */
1833       for (String res : aa3Hash.keySet())
1834       {
1835         int index = aa3Hash.get(res).intValue();
1836         if ((!includeAmbiguous && index >= 20) || index >= maxProteinIndex)
1837         {
1838           continue;
1839         }
1840         res = res.toUpperCase();
1841         if (!result.contains(res))
1842         {
1843           result.add(res);
1844         }
1845       }
1846     }
1847
1848     return result;
1849   }
1850
1851 }