cec9bc365e70a1db5e38cba02c246e277ac0442c
[jalview.git] / src / jalview / util / Comparison.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8)
3  * Copyright (C) 2012 J Procter, AM Waterhouse, LM Lui, J Engelhardt, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
10  *  
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.util;
19
20 import jalview.datamodel.*;
21
22 /**
23  * DOCUMENT ME!
24  * 
25  * @author $author$
26  * @version $Revision$
27  */
28 public class Comparison
29 {
30   /** DOCUMENT ME!! */
31   public static final String GapChars = " .-";
32
33   /**
34    * DOCUMENT ME!
35    * 
36    * @param ii
37    *          DOCUMENT ME!
38    * @param jj
39    *          DOCUMENT ME!
40    * 
41    * @return DOCUMENT ME!
42    */
43   public static final float compare(SequenceI ii, SequenceI jj)
44   {
45     return Comparison.compare(ii, jj, 0, ii.getLength() - 1);
46   }
47
48   /**
49    * this was supposed to be an ungapped pid calculation
50    * 
51    * @param ii
52    *          SequenceI
53    * @param jj
54    *          SequenceI
55    * @param start
56    *          int
57    * @param end
58    *          int
59    * @return float
60    */
61   public static float compare(SequenceI ii, SequenceI jj, int start, int end)
62   {
63     String si = ii.getSequenceAsString();
64     String sj = jj.getSequenceAsString();
65
66     int ilen = si.length() - 1;
67     int jlen = sj.length() - 1;
68
69     while (jalview.util.Comparison.isGap(si.charAt(start + ilen)))
70     {
71       ilen--;
72     }
73
74     while (jalview.util.Comparison.isGap(sj.charAt(start + jlen)))
75     {
76       jlen--;
77     }
78
79     int count = 0;
80     int match = 0;
81     float pid = -1;
82
83     if (ilen > jlen)
84     {
85       for (int j = 0; j < jlen; j++)
86       {
87         if (si.substring(start + j, start + j + 1).equals(
88                 sj.substring(start + j, start + j + 1)))
89         {
90           match++;
91         }
92
93         count++;
94       }
95
96       pid = (float) match / (float) ilen * 100;
97     }
98     else
99     {
100       for (int j = 0; j < jlen; j++)
101       {
102         if (si.substring(start + j, start + j + 1).equals(
103                 sj.substring(start + j, start + j + 1)))
104         {
105           match++;
106         }
107
108         count++;
109       }
110
111       pid = (float) match / (float) jlen * 100;
112     }
113
114     return pid;
115   }
116
117   /**
118    * this is a gapped PID calculation
119    * 
120    * @param s1
121    *          SequenceI
122    * @param s2
123    *          SequenceI
124    * @return float
125    */
126   public final static float PID(String seq1, String seq2)
127   {
128     return PID(seq1, seq2, 0, seq1.length());
129   }
130
131   static final int caseShift = 'a' - 'A';
132
133   // Another pid with region specification
134   public final static float PID(String seq1, String seq2, int start, int end)
135   {
136     return PID(seq1, seq2, start, end, true, false);
137   }
138
139   /**
140    * Calculate percent identity for a pair of sequences over a particular range,
141    * with different options for ignoring gaps.
142    * 
143    * @param seq1
144    * @param seq2
145    * @param start
146    *          - position in seqs
147    * @param end
148    *          - position in seqs
149    * @param wcGaps
150    *          - if true - gaps match any character, if false, do not match
151    *          anything
152    * @param ungappedOnly
153    *          - if true - only count PID over ungapped columns
154    * @return
155    */
156   public final static float PID(String seq1, String seq2, int start,
157           int end, boolean wcGaps, boolean ungappedOnly)
158   {
159     int s1len = seq1.length();
160     int s2len = seq2.length();
161
162     int len = Math.min(s1len, s2len);
163
164     if (end < len)
165     {
166       len = end;
167     }
168
169     if (len < start)
170     {
171       start = len - 1; // we just use a single residue for the difference
172     }
173
174     int elen = len - start, bad = 0;
175     char chr1;
176     char chr2;
177     boolean agap;
178     for (int i = start; i < len; i++)
179     {
180       chr1 = seq1.charAt(i);
181
182       chr2 = seq2.charAt(i);
183       agap = isGap(chr1) || isGap(chr2);
184       if ('a' <= chr1 && chr1 <= 'z')
185       {
186         // TO UPPERCASE !!!
187         // Faster than toUpperCase
188         chr1 -= caseShift;
189       }
190       if ('a' <= chr2 && chr2 <= 'z')
191       {
192         // TO UPPERCASE !!!
193         // Faster than toUpperCase
194         chr2 -= caseShift;
195       }
196
197       if (chr1 != chr2)
198       {
199         if (agap)
200         {
201           if (ungappedOnly)
202           {
203             elen--;
204           }
205           else if (!wcGaps)
206           {
207             bad++;
208           }
209         }
210         else
211         {
212           bad++;
213         }
214       }
215
216     }
217     if (elen < 1)
218     {
219       return 0f;
220     }
221     return ((float) 100 * (elen - bad)) / elen;
222   }
223
224   /**
225    * DOCUMENT ME!
226    * 
227    * @param c
228    *          DOCUMENT ME!
229    * 
230    * @return DOCUMENT ME!
231    */
232   public static final boolean isGap(char c)
233   {
234     return (c == '-' || c == '.' || c == ' ') ? true : false;
235   }
236
237   public static final boolean isNucleotide(SequenceI[] seqs)
238   {
239     int i = 0, iSize = seqs.length, j, jSize;
240     float nt = 0, aa = 0;
241     char c;
242     while (i < iSize)
243     {
244       jSize = seqs[i].getLength();
245       for (j = 0; j < jSize; j++)
246       {
247         c = seqs[i].getCharAt(j);
248         if ('a' <= c && c <= 'z')
249         {
250           c -= ('a' - 'A');
251         }
252
253         if (c == 'A' || c == 'G' || c == 'C' || c == 'T' || c == 'U')
254         {
255           nt++;
256         }
257         else if (!jalview.util.Comparison.isGap(seqs[i].getCharAt(j)))
258         {
259           aa++;
260         }
261       }
262       i++;
263     }
264
265     if ((nt / (nt + aa)) > 0.85f)
266     {
267       return true;
268     }
269     else
270     {
271       return false;
272     }
273
274   }
275 }