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

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

Added automatically created javadoc, still needs to be commented properly though

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