2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2)
3 * Copyright (C) 2014 The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
21 package jalview.analysis;
23 import java.util.ArrayList;
24 import java.util.Hashtable;
27 public class SecStrConsensus {
31 * Internal class to represent a simple base-pair.
33 * [JBPNote: ^^ is that Anne Menard or Ya(w)nn Ponty, I wonder ! ]
35 public static class SimpleBP{
43 public SimpleBP(int i5, int i3)
48 public void setBP5(int i5)
53 public void setBP3(int i3)
68 public String toString()
70 return "("+bp5+","+bp3+")";
75 public static int[] extractConsensus(ArrayList<ArrayList<SimpleBP>> bps)
77 // We do not currently know the length of the alignment
78 // => Estimate it as the biggest index of a base-pair plus one.
80 for (ArrayList<SimpleBP> strs : bps)
82 for (SimpleBP bp : strs)
85 maxlength = Math.max(1+Math.max(bp.bp5, bp.bp3), maxlength);
89 // Now we have a good estimate for length, allocate and initialize data
90 // to be fed to the dynamic programming procedure.
91 ArrayList<Hashtable<Integer,Double>> seq = new ArrayList<Hashtable<Integer,Double>>();
92 for (int i=0;i<maxlength;i++)
93 { seq.add(new Hashtable<Integer,Double>()); }
94 for (ArrayList<SimpleBP> strs : bps)
96 for (SimpleBP bp : strs)
100 Hashtable<Integer,Double> h = seq.get(i);
101 if (!h.containsKey(j))
105 h.put(j, h.get(j)+1.);
108 // At this point, seq contains, at each position i, a hashtable which associates,
109 // to each possible end j, the number of time a base-pair (i,j) occurs in the alignment
111 // We can now run the dynamic programming procedure on this data
112 double[][] mat = fillMatrix(seq);
113 ArrayList<SimpleBP> res = backtrack(mat,seq);
115 // Convert it to an array, ie finalres[i] = j >= 0 iff a base-pair (i,j) is present
116 // in the consensus, or -1 otherwise
117 int[] finalres = new int[seq.size()];
118 for (int i=0;i<seq.size();i++)
119 { finalres[i] = -1; }
120 for (SimpleBP bp : res)
122 finalres[bp.bp5] = bp.bp3;
123 finalres[bp.bp3] = bp.bp5;
129 private static boolean canBasePair(ArrayList<Hashtable<Integer,Double>> seq, int i, int k)
131 return seq.get(i).containsKey(k);
134 // Returns the score of a potential base-pair, ie the number of structures in which it is found.
135 private static double basePairScore(ArrayList<Hashtable<Integer,Double>> seq, int i, int k)
137 return seq.get(i).get(k);
141 private static double[][] fillMatrix(ArrayList<Hashtable<Integer,Double>> seq)
144 double[][] tab = new double[n][n];
145 for(int m=1;m<=n;m++)
147 for(int i=0;i<n-m+1;i++)
153 tab[i][j] = Math.max(tab[i][j], tab[i+1][j]);
154 for (int k=i+1;k<=j;k++)
156 if (canBasePair(seq,i,k))
161 fact1 = tab[i+1][k-1];
168 tab[i][j] = Math.max(tab[i][j],basePairScore(seq,i,k)+fact1+fact2);
177 private static ArrayList<SimpleBP> backtrack(double[][] tab,ArrayList<Hashtable<Integer,Double>> seq)
179 return backtrack(tab,seq,0,seq.size()-1);
182 private static ArrayList<SimpleBP> backtrack(double[][] tab,ArrayList<Hashtable<Integer,Double>> seq, int i, int j)
184 ArrayList<SimpleBP> result = new ArrayList<SimpleBP>();
187 ArrayList<Integer> indices = new ArrayList<Integer>();
189 for (int k=i+1;k<=j;k++)
193 for (int k : indices)
197 if (tab[i][j] == tab[i+1][j])
199 result = backtrack(tab, seq, i+1,j);
204 if (canBasePair(seq,i,k))
209 fact1 = tab[i+1][k-1];
216 if (tab[i][j]==basePairScore(seq,i,k)+fact1+fact2)
218 result = backtrack(tab, seq, i+1,k-1);
219 result.addAll(backtrack(tab, seq, k+1,j));
220 result.add(new SimpleBP(i,k));