patch to fix occasional arrayoutofbounds exception when working with hidden columns...
[jalview.git] / src / jalview / util / Comparison.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.4)
3  * Copyright (C) 2008 AM Waterhouse, J Procter, G Barton, M Clamp, S Searle
4  * 
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
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
138     int s1len = seq1.length();
139     int s2len = seq2.length();
140
141     int len = Math.min(s1len, s2len);
142
143     if (end < len)
144     {
145       len = end;
146     }
147
148     if (len < start)
149     {
150       start = len - 1; // we just use a single residue for the difference
151     }
152
153     int bad = 0;
154     char chr1;
155     char chr2;
156
157     for (int i = start; i < len; i++)
158     {
159       chr1 = seq1.charAt(i);
160
161       chr2 = seq2.charAt(i);
162
163       if ('a' <= chr1 && chr1 <= 'z')
164       {
165         // TO UPPERCASE !!!
166         // Faster than toUpperCase
167         chr1 -= caseShift;
168       }
169       if ('a' <= chr2 && chr2 <= 'z')
170       {
171         // TO UPPERCASE !!!
172         // Faster than toUpperCase
173         chr2 -= caseShift;
174       }
175
176       if (chr1 != chr2 && !isGap(chr1) && !isGap(chr2))
177       {
178         bad++;
179       }
180     }
181
182     return ((float) 100 * (len - bad)) / len;
183   }
184
185   /**
186    * DOCUMENT ME!
187    * 
188    * @param c
189    *                DOCUMENT ME!
190    * 
191    * @return DOCUMENT ME!
192    */
193   public static final boolean isGap(char c)
194   {
195     return (c == '-' || c == '.' || c == ' ') ? true : false;
196   }
197
198   public static final boolean isNucleotide(SequenceI[] seqs)
199   {
200     int i = 0, iSize = seqs.length, j, jSize;
201     float nt = 0, aa = 0;
202     char c;
203     while (i < iSize)
204     {
205       jSize = seqs[i].getLength();
206       for (j = 0; j < jSize; j++)
207       {
208         c = seqs[i].getCharAt(j);
209         if ('a' <= c && c <= 'z')
210         {
211           c -= ('a' - 'A');
212         }
213
214         if (c == 'A' || c == 'G' || c == 'C' || c == 'T' || c == 'U')
215         {
216           nt++;
217         }
218         else if (!jalview.util.Comparison.isGap(seqs[i].getCharAt(j)))
219         {
220           aa++;
221         }
222       }
223       i++;
224     }
225
226     if ((nt / (nt + aa)) > 0.85f)
227     {
228       return true;
229     }
230     else
231     {
232       return false;
233     }
234
235   }
236 }