Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.analysis

File StructureFrequency.java

 

Coverage histogram

../../img/srcFileCovDistChart6.png
35% of files have more coverage

Code metrics

90
182
5
1
490
337
59
0.32
36.4
5
11.8

Classes

Class Line # Actions
StructureFrequency 42 182 59 122
0.559566856%
 

Contributing tests

This file is covered by 1 test. .

Source view

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    import jalview.datamodel.AlignmentAnnotation;
24    import jalview.datamodel.Annotation;
25    import jalview.datamodel.SequenceFeature;
26    import jalview.datamodel.SequenceI;
27    import jalview.util.Comparison;
28    import jalview.util.Format;
29   
30    import java.util.ArrayList;
31    import java.util.Hashtable;
32   
33    /**
34    * Takes in a vector or array of sequences and column start and column end and
35    * returns a new Hashtable[] of size maxSeqLength, if Hashtable not supplied.
36    * This class is used extensively in calculating alignment colourschemes that
37    * depend on the amount of conservation in each alignment column.
38    *
39    * @author $author$
40    * @version $Revision$
41    */
 
42    public class StructureFrequency
43    {
44    public static final int STRUCTURE_PROFILE_LENGTH = 74;
45   
46    // No need to store 1000s of strings which are not
47    // visible to the user.
48    public static final String MAXCOUNT = "C";
49   
50    public static final String MAXRESIDUE = "R";
51   
52    public static final String PID_GAPS = "G";
53   
54    public static final String PID_NOGAPS = "N";
55   
56    public static final String PROFILE = "P";
57   
58    public static final String PAIRPROFILE = "B";
59   
60    /**
61    * Returns the 3' position of a base pair
62    *
63    * @param pairs
64    * Secondary structure annotation
65    * @param indice
66    * 5' position of a base pair
67    * @return 3' position of a base pair
68    */
 
69  90 toggle public static int findPair(SequenceFeature[] pairs, int indice)
70    {
71   
72  855 for (int i = 0; i < pairs.length; i++)
73    {
74  855 if (pairs[i].getBegin() == indice)
75   
76    {
77   
78  90 return pairs[i].getEnd();
79   
80    }
81    }
82  0 return -1;
83    }
84   
85    /**
86    * Method to calculate a 'base pair consensus row', very similar to nucleotide
87    * consensus but takes into account a given structure
88    *
89    * @param sequences
90    * @param start
91    * @param end
92    * @param result
93    * @param profile
94    * @param rnaStruc
95    */
 
96  5 toggle public static final void calculate(SequenceI[] sequences, int start,
97    int end, Hashtable[] result, boolean profile,
98    AlignmentAnnotation rnaStruc)
99    {
100   
101  5 Hashtable residueHash;
102  5 String maxResidue;
103  5 char[] struc = rnaStruc.getRNAStruc().toCharArray();
104   
105  5 SequenceFeature[] rna = rnaStruc._rnasecstr;
106  5 char c, s, cEnd;
107  5 int bpEnd = -1;
108  5 int jSize = sequences.length;
109  5 int[] values;
110  5 int[][] pairs;
111  5 float percentage;
112   
113  470 for (int i = start; i < end; i++) // foreach column
114    {
115  465 int canonicalOrWobblePairCount = 0, canonical = 0;
116  465 int otherPairCount = 0;
117  465 int nongap = 0;
118  465 maxResidue = "-";
119  465 values = new int[255];
120  465 pairs = new int[255][255];
121  465 bpEnd = -1;
122  465 if (i < struc.length)
123    {
124  465 s = struc[i];
125    }
126    else
127    {
128  0 s = '-';
129    }
130  465 if (s == '.' || s == ' ')
131    {
132  285 s = '-';
133    }
134   
135  465 if (!Rna.isOpeningParenthesis(s))
136    {
137  375 if (s == '-')
138    {
139  285 values['-']++;
140    }
141    }
142    else
143    {
144  90 bpEnd = findPair(rna, i);
145   
146  90 if (bpEnd > -1)
147    {
148  5580 for (int j = 0; j < jSize; j++) // foreach row
149    {
150  5490 if (sequences[j] == null)
151    {
152  0 System.err.println(
153    "WARNING: Consensus skipping null sequence - possible race condition.");
154  0 continue;
155    }
156   
157  5490 c = sequences[j].getCharAt(i);
158  5490 cEnd = sequences[j].getCharAt(bpEnd);
159   
160  5490 if (Comparison.isGap(c) || Comparison.isGap(cEnd))
161    {
162  10 values['-']++;
163  10 continue;
164    }
165  5480 nongap++;
166    /*
167    * ensure upper-case for counting purposes
168    */
169  5480 if ('a' <= c && 'z' >= c)
170    {
171  0 c += 'A' - 'a';
172    }
173  5480 if ('a' <= cEnd && 'z' >= cEnd)
174    {
175  0 cEnd += 'A' - 'a';
176    }
177  5480 if (Rna.isCanonicalOrWobblePair(c, cEnd))
178    {
179  4865 canonicalOrWobblePairCount++;
180  4865 if (Rna.isCanonicalPair(c, cEnd))
181    {
182  4315 canonical++;
183    }
184    }
185    else
186    {
187  615 otherPairCount++;
188    }
189  5480 pairs[c][cEnd]++;
190    }
191    }
192    }
193   
194  465 residueHash = new Hashtable();
195  465 if (profile)
196    {
197    // TODO 1-dim array with jsize in [0], nongapped in [1]; or Pojo
198  465 residueHash.put(PROFILE,
199    new int[][]
200    { values, new int[] { jSize, (jSize - values['-']) } });
201   
202  465 residueHash.put(PAIRPROFILE, pairs);
203    }
204  465 values['('] = canonicalOrWobblePairCount;
205  465 values['['] = canonical;
206  465 values['{'] = otherPairCount;
207    /*
208    * the count is the number of valid pairs (as a percentage, determines
209    * the relative size of the profile logo)
210    */
211  465 int count = canonicalOrWobblePairCount;
212   
213    /*
214    * display '(' if most pairs are canonical, or as
215    * '[' if there are more wobble pairs.
216    */
217  465 if (canonicalOrWobblePairCount > 0 || otherPairCount > 0)
218    {
219  90 if (canonicalOrWobblePairCount >= otherPairCount)
220    {
221  90 maxResidue = (canonicalOrWobblePairCount - canonical) < canonical
222    ? "("
223    : "[";
224    }
225    else
226    {
227  0 maxResidue = "{";
228    }
229    }
230  465 residueHash.put(MAXCOUNT, new Integer(count));
231  465 residueHash.put(MAXRESIDUE, maxResidue);
232   
233  465 percentage = ((float) count * 100) / jSize;
234  465 residueHash.put(PID_GAPS, new Float(percentage));
235   
236  465 percentage = ((float) count * 100) / nongap;
237  465 residueHash.put(PID_NOGAPS, new Float(percentage));
238   
239  465 if (result[i] == null)
240    {
241  375 result[i] = residueHash;
242    }
243  465 if (bpEnd > 0)
244    {
245  90 values[')'] = values['('];
246  90 values[']'] = values['['];
247  90 values['}'] = values['{'];
248  90 values['('] = 0;
249  90 values['['] = 0;
250  90 values['{'] = 0;
251  90 maxResidue = maxResidue.equals("(") ? ")"
252  0 : maxResidue.equals("[") ? "]" : "}";
253   
254  90 residueHash = new Hashtable();
255  90 if (profile)
256    {
257  90 residueHash.put(PROFILE,
258    new int[][]
259    { values, new int[] { jSize, (jSize - values['-']) } });
260   
261  90 residueHash.put(PAIRPROFILE, pairs);
262    }
263   
264  90 residueHash.put(MAXCOUNT, new Integer(count));
265  90 residueHash.put(MAXRESIDUE, maxResidue);
266   
267  90 percentage = ((float) count * 100) / jSize;
268  90 residueHash.put(PID_GAPS, new Float(percentage));
269   
270  90 percentage = ((float) count * 100) / nongap;
271  90 residueHash.put(PID_NOGAPS, new Float(percentage));
272   
273  90 result[bpEnd] = residueHash;
274    }
275    }
276    }
277   
278    /**
279    * Compute all or part of the annotation row from the given consensus
280    * hashtable
281    *
282    * @param consensus
283    * - pre-allocated annotation row
284    * @param hconsensus
285    * @param iStart
286    * @param width
287    * @param ignoreGapsInConsensusCalculation
288    * @param includeAllConsSymbols
289    */
 
290  5 toggle public static void completeConsensus(AlignmentAnnotation consensus,
291    Hashtable[] hconsensus, int iStart, int width,
292    boolean ignoreGapsInConsensusCalculation,
293    boolean includeAllConsSymbols, long nseq)
294    {
295  5 float tval, value;
296  5 if (consensus == null || consensus.annotations == null
297    || consensus.annotations.length < width)
298    {
299    // called with a bad alignment annotation row - wait for it to be
300    // initialised properly
301  0 return;
302    }
303  5 String fmtstr = "%3.1f";
304  5 int precision = 2;
305  5 while (nseq > 100)
306    {
307  0 precision++;
308  0 nseq /= 10;
309    }
310  5 if (precision > 2)
311    {
312  0 fmtstr = "%" + (2 + precision) + "." + precision + "f";
313    }
314  5 Format fmt = new Format(fmtstr);
315   
316  470 for (int i = iStart; i < width; i++)
317    {
318  465 Hashtable hci;
319  ? if (i >= hconsensus.length || ((hci = hconsensus[i]) == null))
320    {
321    // happens if sequences calculated over were shorter than alignment
322    // width
323  0 consensus.annotations[i] = null;
324  0 continue;
325    }
326  465 value = 0;
327  465 Float fv;
328  465 if (ignoreGapsInConsensusCalculation)
329    {
330  0 fv = (Float) hci.get(StructureFrequency.PID_NOGAPS);
331    }
332    else
333    {
334  465 fv = (Float) hci.get(StructureFrequency.PID_GAPS);
335    }
336  465 if (fv == null)
337    {
338  0 consensus.annotations[i] = null;
339    // data has changed below us .. give up and
340  0 continue;
341    }
342  465 value = fv.floatValue();
343  465 String maxRes = hci.get(StructureFrequency.MAXRESIDUE).toString();
344  465 String mouseOver = hci.get(StructureFrequency.MAXRESIDUE) + " ";
345  465 if (maxRes.length() > 1)
346    {
347  0 mouseOver = "[" + maxRes + "] ";
348  0 maxRes = "+";
349    }
350  465 int[][] profile = (int[][]) hci.get(StructureFrequency.PROFILE);
351  465 int[][] pairs = (int[][]) hci.get(StructureFrequency.PAIRPROFILE);
352   
353  465 if (pairs != null && includeAllConsSymbols) // Just responsible for the
354    // tooltip
355    // TODO Update tooltips for Structure row
356    {
357  0 mouseOver = "";
358   
359    /*
360    * TODO It's not sure what is the purpose of the alphabet and wheter it
361    * is useful for structure?
362    *
363    * if (alphabet != null) { for (int c = 0; c < alphabet.length; c++) {
364    * tval = ((float) profile[0][alphabet[c]]) 100f / (float)
365    * profile[1][ignoreGapsInConsensusCalculation ? 1 : 0]; mouseOver +=
366    * ((c == 0) ? "" : "; ") + alphabet[c] + " " + ((int) tval) + "%"; } }
367    * else {
368    */
369  0 int[][] ca = new int[625][];
370  0 float[] vl = new float[625];
371  0 int x = 0;
372  0 for (int c = 65; c < 90; c++)
373    {
374  0 for (int d = 65; d < 90; d++)
375    {
376  0 ca[x] = new int[] { c, d };
377  0 vl[x] = pairs[c][d];
378  0 x++;
379    }
380    }
381  0 jalview.util.QuickSort.sort(vl, ca);
382  0 int p = 0;
383   
384    /*
385    * profile[1] is {total, ungappedTotal}
386    */
387  0 final int divisor = profile[1][ignoreGapsInConsensusCalculation ? 1
388    : 0];
389  0 for (int c = 624; c > 0; c--)
390    {
391  0 if (vl[c] > 0)
392    {
393  0 tval = (vl[c] * 100f / divisor);
394  0 mouseOver += ((p == 0) ? "" : "; ") + (char) ca[c][0]
395    + (char) ca[c][1] + " " + fmt.form(tval) + "%";
396  0 p++;
397   
398    }
399    }
400   
401    // }
402    }
403    else
404    {
405  465 mouseOver += (fmt.form(value) + "%");
406    }
407  465 consensus.annotations[i] = new Annotation(maxRes, mouseOver, ' ',
408    value);
409    }
410    }
411   
412    /**
413    * get the sorted base-pair profile for the given position of the consensus
414    *
415    * @param hconsensus
416    * @return profile of the given column
417    */
 
418  0 toggle public static int[] extractProfile(Hashtable hconsensus,
419    boolean ignoreGapsInConsensusCalculation)
420    {
421  0 int[] rtnval = new int[STRUCTURE_PROFILE_LENGTH]; // 2*(5*5)+2
422  0 int[][] profile = (int[][]) hconsensus.get(StructureFrequency.PROFILE);
423  0 int[][] pairs = (int[][]) hconsensus
424    .get(StructureFrequency.PAIRPROFILE);
425   
426  0 if (profile == null)
427    {
428  0 return null;
429    }
430   
431    // TODO fix the object length, also do it in completeConsensus
432    // Object[] ca = new Object[625];
433  0 int[][] ca = new int[625][];
434  0 float[] vl = new float[625];
435  0 int x = 0;
436  0 for (int c = 65; c < 90; c++)
437    {
438  0 for (int d = 65; d < 90; d++)
439    {
440  0 ca[x] = new int[] { c, d };
441  0 vl[x] = pairs[c][d];
442  0 x++;
443    }
444    }
445  0 jalview.util.QuickSort.sort(vl, ca);
446   
447  0 int valuesCount = 0;
448  0 rtnval[1] = 0;
449  0 int offset = 2;
450  0 final int divisor = profile[1][ignoreGapsInConsensusCalculation ? 1
451    : 0];
452  0 for (int c = 624; c > 0; c--)
453    {
454  0 if (vl[c] > 0)
455    {
456  0 rtnval[offset++] = ca[c][0];
457  0 rtnval[offset++] = ca[c][1];
458  0 rtnval[offset] = (int) (vl[c] * 100f / divisor);
459  0 rtnval[1] += rtnval[offset++];
460  0 valuesCount++;
461    }
462    }
463  0 rtnval[0] = valuesCount;
464   
465    // insert profile type code in position 0
466  0 int[] result = new int[rtnval.length + 1];
467  0 result[0] = AlignmentAnnotation.STRUCTURE_PROFILE;
468  0 System.arraycopy(rtnval, 0, result, 1, rtnval.length);
469  0 return result;
470    }
471   
 
472  0 toggle public static void main(String args[])
473    {
474    // Short test to see if checkBpType works
475  0 ArrayList<String> test = new ArrayList<String>();
476  0 test.add("A");
477  0 test.add("c");
478  0 test.add("g");
479  0 test.add("T");
480  0 test.add("U");
481  0 for (String i : test)
482    {
483  0 for (String j : test)
484    {
485  0 System.out.println(i + "-" + j + ": "
486    + Rna.isCanonicalOrWobblePair(i.charAt(0), j.charAt(0)));
487    }
488    }
489    }
490    }