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