source: branches/autoquest-core-tasktrees-alignment/src/main/java/de/ugoe/cs/autoquest/tasktrees/alignment/algorithms/SmithWaterman.java @ 1733

Last change on this file since 1733 was 1733, checked in by rkrimmel, 10 years ago

Used Eclipse code cleanup

File size: 7.4 KB
Line 
1package de.ugoe.cs.autoquest.tasktrees.alignment.algorithms;
2
3import java.util.ArrayList;
4import java.util.logging.Level;
5
6import de.ugoe.cs.autoquest.tasktrees.alignment.matrix.SubstitutionMatrix;
7import de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.Constants;
8import de.ugoe.cs.util.console.Console;
9
10public class SmithWaterman implements AlignmentAlgorithm {
11
12        /**
13         * The first input
14         */
15        private int[] input1;
16
17        /**
18         * The second input String
19         */
20        private int[] input2;
21
22        /**
23         * The lengths of the input
24         */
25        private int length1, length2;
26
27        /**
28         * The score matrix. The true scores should be divided by the normalization
29         * factor.
30         */
31        private MatrixEntry[][] matrix;
32
33        private ArrayList<NumberSequence> alignment;
34
35        /**
36         * Substitution matrix to calculate scores
37         */
38        private SubstitutionMatrix submat;
39
40        @Override
41        public void align(NumberSequence input1, NumberSequence input2,
42                        SubstitutionMatrix submat, float threshold) {
43                this.input1 = input1.getSequence();
44                this.input2 = input2.getSequence();
45                length1 = input1.size();
46                length2 = input2.size();
47                this.submat = submat;
48
49                // System.out.println("Starting SmithWaterman algorithm with a "
50                // + submat.getClass() + " Substitution Matrix: " +
51                // submat.getClass().getCanonicalName());
52
53                matrix = new MatrixEntry[length1 + 1][length2 + 1];
54                alignment = new ArrayList<NumberSequence>();
55
56                for (int i = 0; i < (length1 + 1); i++) {
57                        for (int j = 0; j < (length2 + 1); j++) {
58                                matrix[i][j] = new MatrixEntry();
59                        }
60                }
61
62                buildMatrix();
63                traceback();
64
65        }
66
67        /**
68         * Build the score matrix using dynamic programming.
69         */
70        private void buildMatrix() {
71                if (submat.getGapPenalty() >= 0) {
72                        throw new Error("Indel score must be negative");
73                }
74
75                // it's a gap
76                matrix[0][0].setScore(0);
77                matrix[0][0].setPrevious(null); // starting point
78
79                // the first column
80                for (int j = 1; j < length2; j++) {
81                        matrix[0][j].setScore(0);
82                        matrix[0][j].setPrevious(matrix[0][j - 1]);
83                        matrix[0][j].setYvalue(input2[j]);
84                        matrix[0][j].setXvalue(Constants.GAP_SYMBOL);
85                }
86                // the first row
87
88                for (int j = 1; j < length1; j++) {
89                        matrix[j][0].setScore(0);
90                        matrix[j][0].setPrevious(matrix[j - 1][0]);
91                        matrix[j][0].setXvalue(input1[j]);
92                        matrix[j][0].setYvalue(Constants.GAP_SYMBOL);
93                }
94
95                for (int i = 1; i < length1; i++) {
96
97                        for (int j = 1; j < length2; j++) {
98                                final double diagScore = matrix[i - 1][j - 1].getScore()
99                                                + similarity(i, j);
100                                final double upScore = matrix[i][j - 1].getScore()
101                                                + submat.getGapPenalty();
102                                final double leftScore = matrix[i - 1][j].getScore()
103                                                + submat.getGapPenalty();
104
105                                matrix[i][j].setScore(Math.max(diagScore,
106                                                Math.max(upScore, Math.max(leftScore, 0))));
107
108                                // find the directions that give the maximum scores.
109                                // TODO: Multiple directions are ignored, we choose the first
110                                // maximum score
111                                // True if we had a match
112                                if (diagScore == matrix[i][j].getScore()) {
113                                        matrix[i][j].setPrevious(matrix[i - 1][j - 1]);
114                                        matrix[i][j].setXvalue(input1[i - 1]);
115                                        matrix[i][j].setYvalue(input2[j - 1]);
116                                }
117                                // true if we took an event from sequence x and not from y
118                                if (leftScore == matrix[i][j].getScore()) {
119                                        matrix[i][j].setXvalue(input1[i - 1]);
120                                        matrix[i][j].setYvalue(Constants.GAP_SYMBOL);
121                                        matrix[i][j].setPrevious(matrix[i - 1][j]);
122                                }
123                                // true if we took an event from sequence y and not from x
124                                if (upScore == matrix[i][j].getScore()) {
125                                        matrix[i][j].setXvalue(Constants.GAP_SYMBOL);
126                                        matrix[i][j].setYvalue(input2[j - 1]);
127                                        matrix[i][j].setPrevious(matrix[i][j - 1]);
128                                }
129                                if (0 == matrix[i][j].getScore()) {
130                                        matrix[i][j].setPrevious(matrix[0][0]);
131                                        matrix[i][j].setXvalue(-2);
132                                        matrix[i][j].setYvalue(-2);
133                                }
134                        }
135
136                        // Set the complete score cell
137
138                }
139        }
140
141        /*
142         * (non-Javadoc)
143         *
144         * @see
145         * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm
146         * #getAlignment()
147         */
148        @Override
149        public ArrayList<NumberSequence> getAlignment() {
150                return alignment;
151        }
152
153        /*
154         * (non-Javadoc)
155         *
156         * @see
157         * de.ugoe.cs.autoquest.tasktrees.alignment.algorithms.AlignmentAlgorithm
158         * #getAlignmentScore()
159         */
160        @Override
161        public double getAlignmentScore() {
162                return getMaxScore();
163        }
164
165        @Override
166        public ArrayList<Match> getMatches() {
167                // TODO Auto-generated method stub
168                return null;
169        }
170
171        /**
172         * Get the maximum value in the score matrix.
173         */
174        @Override
175        public double getMaxScore() {
176                double maxScore = 0;
177
178                // skip the first row and column
179                for (int i = 1; i <= length1; i++) {
180                        for (int j = 1; j < length2; j++) {
181                                if (matrix[i][j].getScore() > maxScore) {
182                                        maxScore = matrix[i][j].getScore();
183                                }
184                        }
185                }
186
187                return maxScore;
188        }
189
190        @Override
191        public void printAlignment() {
192                MatrixEntry tmp = matrix[length1 + 1][0];
193                String aligned1 = "";
194                String aligned2 = "";
195                int count = 0;
196                do {
197                        String append1 = "";
198                        String append2 = "";
199
200                        if (tmp.getXvalue() == Constants.GAP_SYMBOL) {
201                                append1 = "  ___";
202                        } else {
203                                append1 = String.format("%5d", tmp.getXvalue());
204                        }
205
206                        if (tmp.getYvalue() == Constants.GAP_SYMBOL) {
207                                append2 = "  ___";
208                        } else {
209                                append2 = String.format("%5d", tmp.getYvalue());
210                        }
211                        if (count != 0) {
212                                aligned1 = append1 + aligned1;
213                                aligned2 = append2 + aligned2;
214                        }
215
216                        tmp = tmp.getPrevious();
217                        count++;
218
219                } while (tmp != null);
220                System.out.println(aligned1);
221                System.out.println(aligned2);
222        }
223
224        /**
225         * print the dynmaic programming matrix
226         */
227        @Override
228        public void printDPMatrix() {
229                System.out.print("          ");
230                for (int i = 1; i <= length1; i++) {
231                        System.out.format("%5d", input1[i - 1]);
232                }
233                System.out.println();
234                for (int j = 0; j <= length2; j++) {
235                        if (j > 0) {
236                                System.out.format("%5d ", input2[j - 1]);
237                        } else {
238                                System.out.print("      ");
239                        }
240                        for (int i = 0; i <= length1; i++) {
241                                System.out.format("%4.1f ", matrix[i][j].getScore());
242                        }
243                        System.out.println();
244                }
245        }
246
247        public void setAlignment(ArrayList<NumberSequence> alignment) {
248                this.alignment = alignment;
249        }
250
251        /**
252         * Compute the similarity score of substitution The position of the first
253         * character is 1. A position of 0 represents a gap.
254         *
255         * @param i
256         *            Position of the character in str1
257         * @param j
258         *            Position of the character in str2
259         * @return Cost of substitution of the character in str1 by the one in str2
260         */
261        private double similarity(int i, int j) {
262                return submat.getScore(input1[i - 1], input2[j - 1]);
263        }
264
265        public void traceback() {
266                MatrixEntry tmp = matrix[length1][length2];
267                final int aligned1[] = new int[length1 + length2 + 2];
268                final int aligned2[] = new int[length1 + length2 + 2];
269                int count = 0;
270                do {
271                        if ((length1 + length2 + 2) == count) {
272                                Console.traceln(Level.WARNING,
273                                                "Traceback longer than both sequences summed up!");
274                                break;
275                        }
276                        aligned1[count] = tmp.getXvalue();
277                        aligned2[count] = tmp.getYvalue();
278
279                        tmp = tmp.getPrevious();
280                        count++;
281
282                } while (tmp != null);
283                count--;
284                // reverse order of the alignment
285                final int reversed1[] = new int[count];
286                final int reversed2[] = new int[count];
287
288                for (int i = count - 1; i > 0; i--) {
289                        reversed1[reversed1.length - i] = aligned1[i];
290                        reversed2[reversed2.length - i] = aligned2[i];
291                }
292
293                final NumberSequence ns1 = new NumberSequence(reversed1.length);
294                final NumberSequence ns2 = new NumberSequence(reversed2.length);
295                ns1.setSequence(reversed1);
296                ns2.setSequence(reversed2);
297
298                alignment.add(ns1);
299                alignment.add(ns2);
300        }
301
302}
Note: See TracBrowser for help on using the repository browser.