2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ 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;
26 public class SecStrConsensus
30 * Internal class to represent a simple base-pair.
32 * @author Yawn [JBPNote: ^^ is that Anne Menard or Ya(w)nn Ponty, I wonder !
35 public static class SimpleBP
46 public SimpleBP(int i5, int i3)
52 public void setBP5(int i5)
57 public void setBP3(int i3)
72 public String toString()
74 return "(" + bp5 + "," + bp3 + ")";
79 public static int[] extractConsensus(ArrayList<ArrayList<SimpleBP>> bps)
81 // We do not currently know the length of the alignment
82 // => Estimate it as the biggest index of a base-pair plus one.
84 for (ArrayList<SimpleBP> strs : bps)
86 for (SimpleBP bp : strs)
89 maxlength = Math.max(1 + Math.max(bp.bp5, bp.bp3), maxlength);
93 // Now we have a good estimate for length, allocate and initialize data
94 // to be fed to the dynamic programming procedure.
95 ArrayList<Hashtable<Integer, Double>> seq = new ArrayList<Hashtable<Integer, Double>>();
96 for (int i = 0; i < maxlength; i++)
98 seq.add(new Hashtable<Integer, Double>());
100 for (ArrayList<SimpleBP> strs : bps)
102 for (SimpleBP bp : strs)
106 Hashtable<Integer, Double> h = seq.get(i);
107 if (!h.containsKey(j))
111 h.put(j, h.get(j) + 1.);
114 // At this point, seq contains, at each position i, a hashtable which
116 // to each possible end j, the number of time a base-pair (i,j) occurs in
119 // We can now run the dynamic programming procedure on this data
120 double[][] mat = fillMatrix(seq);
121 ArrayList<SimpleBP> res = backtrack(mat, seq);
123 // Convert it to an array, ie finalres[i] = j >= 0 iff a base-pair (i,j) is
125 // in the consensus, or -1 otherwise
126 int[] finalres = new int[seq.size()];
127 for (int i = 0; i < seq.size(); i++)
131 for (SimpleBP bp : res)
133 finalres[bp.bp5] = bp.bp3;
134 finalres[bp.bp3] = bp.bp5;
140 private static boolean canBasePair(
141 ArrayList<Hashtable<Integer, Double>> seq, int i, int k)
143 return seq.get(i).containsKey(k);
146 // Returns the score of a potential base-pair, ie the number of structures in
147 // which it is found.
148 private static double basePairScore(
149 ArrayList<Hashtable<Integer, Double>> seq, int i, int k)
151 return seq.get(i).get(k);
154 private static double[][] fillMatrix(
155 ArrayList<Hashtable<Integer, Double>> seq)
158 double[][] tab = new double[n][n];
159 for (int m = 1; m <= n; m++)
161 for (int i = 0; i < n - m + 1; i++)
167 tab[i][j] = Math.max(tab[i][j], tab[i + 1][j]);
168 for (int k = i + 1; k <= j; k++)
170 if (canBasePair(seq, i, k))
175 fact1 = tab[i + 1][k - 1];
180 fact2 = tab[k + 1][j];
182 tab[i][j] = Math.max(tab[i][j],
183 basePairScore(seq, i, k) + fact1 + fact2);
192 private static ArrayList<SimpleBP> backtrack(double[][] tab,
193 ArrayList<Hashtable<Integer, Double>> seq)
195 return backtrack(tab, seq, 0, seq.size() - 1);
198 private static ArrayList<SimpleBP> backtrack(double[][] tab,
199 ArrayList<Hashtable<Integer, Double>> seq, int i, int j)
201 ArrayList<SimpleBP> result = new ArrayList<SimpleBP>();
204 ArrayList<Integer> indices = new ArrayList<Integer>();
206 for (int k = i + 1; k <= j; k++)
210 for (int k : indices)
214 if (tab[i][j] == tab[i + 1][j])
216 result = backtrack(tab, seq, i + 1, j);
221 if (canBasePair(seq, i, k))
226 fact1 = tab[i + 1][k - 1];
231 fact2 = tab[k + 1][j];
233 if (tab[i][j] == basePairScore(seq, i, k) + fact1 + fact2)
235 result = backtrack(tab, seq, i + 1, k - 1);
236 result.addAll(backtrack(tab, seq, k + 1, j));
237 result.add(new SimpleBP(i, k));