Merge remote-tracking branch 'origin/tasks/JAL-3035_remove_dasobert_dependency' into...
[jalview.git] / src / jalview / analysis / CodingUtils.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.analysis;
22
23 /**
24  * A utility class to provide encoding/decoding schemes for data.
25  * 
26  * @author gmcarstairs
27  *
28  */
29 public class CodingUtils
30 {
31
32   /*
33    * Number of bits used when encoding codon characters. 2 is enough for ACGT.
34    * To accommodate more (e.g. ambiguity codes), simply increase this number
35    * (and adjust unit tests to match).
36    */
37   private static final int CODON_ENCODING_BITSHIFT = 2;
38
39   /**
40    * Encode a codon from e.g. ['A', 'G', 'C'] to a number in the range 0 - 63.
41    * Converts lower to upper case, U to T, then assembles a binary value by
42    * encoding A/C/G/T as 00/01/10/11 respectively and shifting.
43    * 
44    * @param codon
45    * @return the encoded codon, or a negative number if unexpected characters
46    *         found
47    */
48   public static int encodeCodon(char[] codon)
49   {
50     if (codon == null)
51     {
52       return -1;
53     }
54     return encodeCodon(codon[2])
55             + (encodeCodon(codon[1]) << CODON_ENCODING_BITSHIFT)
56             + (encodeCodon(codon[0]) << (2 * CODON_ENCODING_BITSHIFT));
57   }
58
59   /**
60    * Encodes aA/cC/gG/tTuU as 0/1/2/3 respectively. Returns Integer.MIN_VALUE (a
61    * large negative value) for any other character.
62    * 
63    * @param c
64    * @return
65    */
66   public static int encodeCodon(char c)
67   {
68     int result = Integer.MIN_VALUE;
69     switch (c)
70     {
71     case 'A':
72     case 'a':
73       result = 0;
74       break;
75     case 'C':
76     case 'c':
77       result = 1;
78       break;
79     case 'G':
80     case 'g':
81       result = 2;
82       break;
83     case 'T':
84     case 't':
85     case 'U':
86     case 'u':
87       result = 3;
88       break;
89     }
90     return result;
91   }
92
93   /**
94    * Converts a binary encoded codon into an ['A', 'C', 'G'] (or 'T') triplet.
95    * 
96    * The two low-order bits encode for A/C/G/T as 0/1/2/3, etc.
97    * 
98    * @param encoded
99    * @return
100    */
101   public static char[] decodeCodon(int encoded)
102   {
103     char[] result = new char[3];
104     result[2] = decodeNucleotide(encoded & 3);
105     encoded = encoded >>> CODON_ENCODING_BITSHIFT;
106     result[1] = decodeNucleotide(encoded & 3);
107     encoded = encoded >>> CODON_ENCODING_BITSHIFT;
108     result[0] = decodeNucleotide(encoded & 3);
109     return result;
110   }
111
112   /**
113    * Convert value 0/1/2/3 to 'A'/'C'/'G'/'T'
114    * 
115    * @param i
116    * @return
117    */
118   public static char decodeNucleotide(int i)
119   {
120     char result = '0';
121     switch (i)
122     {
123     case 0:
124       result = 'A';
125       break;
126     case 1:
127       result = 'C';
128       break;
129     case 2:
130       result = 'G';
131       break;
132     case 3:
133       result = 'T';
134       break;
135     }
136     return result;
137   }
138
139 }