update author list in license for (JAL-826)
[jalview.git] / src / jalview / util / Comparison.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, 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    * Calculate percent identity for a pair of sequences over a particular range, with different options for ignoring gaps.
140    * @param seq1
141    * @param seq2
142    * @param start - position in seqs
143    * @param end - position in seqs
144    * @param wcGaps - if true - gaps match any character, if false, do not match anything
145    * @param ungappedOnly - if true - only count PID over ungapped columns
146    * @return
147    */
148   public final static float PID(String seq1, String seq2, int start, int end, boolean wcGaps, boolean ungappedOnly)
149   {
150     int s1len = seq1.length();
151     int s2len = seq2.length();
152
153     int len = Math.min(s1len, s2len);
154
155     if (end < len)
156     {
157       len = end;
158     }
159
160     if (len < start)
161     {
162       start = len - 1; // we just use a single residue for the difference
163     }
164
165     int elen=len-start,bad = 0;
166     char chr1;
167     char chr2;
168     boolean agap;
169     for (int i = start; i < len; i++)
170     {
171       chr1 = seq1.charAt(i);
172
173       chr2 = seq2.charAt(i);
174       agap = isGap(chr1) || isGap(chr2);
175       if ('a' <= chr1 && chr1 <= 'z')
176       {
177         // TO UPPERCASE !!!
178         // Faster than toUpperCase
179         chr1 -= caseShift;
180       }
181       if ('a' <= chr2 && chr2 <= 'z')
182       {
183         // TO UPPERCASE !!!
184         // Faster than toUpperCase
185         chr2 -= caseShift;
186       }
187       
188       if (chr1 != chr2)
189       {
190         if (agap)
191         {
192                 if (ungappedOnly)
193                 {
194                         elen--;
195                 } else if (!wcGaps) {
196                         bad++;
197                 }
198         } else {
199                 bad++;
200         }
201       }
202       
203     }
204     if (elen<1) { return 0f; }
205     return ((float) 100 * (elen - bad)) / elen;
206   }
207
208   /**
209    * DOCUMENT ME!
210    * 
211    * @param c
212    *          DOCUMENT ME!
213    * 
214    * @return DOCUMENT ME!
215    */
216   public static final boolean isGap(char c)
217   {
218     return (c == '-' || c == '.' || c == ' ') ? true : false;
219   }
220
221   public static final boolean isNucleotide(SequenceI[] seqs)
222   {
223     int i = 0, iSize = seqs.length, j, jSize;
224     float nt = 0, aa = 0;
225     char c;
226     while (i < iSize)
227     {
228       jSize = seqs[i].getLength();
229       for (j = 0; j < jSize; j++)
230       {
231         c = seqs[i].getCharAt(j);
232         if ('a' <= c && c <= 'z')
233         {
234           c -= ('a' - 'A');
235         }
236
237         if (c == 'A' || c == 'G' || c == 'C' || c == 'T' || c == 'U')
238         {
239           nt++;
240         }
241         else if (!jalview.util.Comparison.isGap(seqs[i].getCharAt(j)))
242         {
243           aa++;
244         }
245       }
246       i++;
247     }
248
249     if ((nt / (nt + aa)) > 0.85f)
250     {
251       return true;
252     }
253     else
254     {
255       return false;
256     }
257
258   }
259 }