jpayne@68
|
1 package icecream;
|
jpayne@68
|
2
|
jpayne@68
|
3 import aligner.AlignmentResult;
|
jpayne@68
|
4
|
jpayne@68
|
5 public final class IceCreamAlignerJava extends IceCreamAligner {
|
jpayne@68
|
6
|
jpayne@68
|
7 IceCreamAlignerJava(){}
|
jpayne@68
|
8
|
jpayne@68
|
9 /**
|
jpayne@68
|
10 * @param query
|
jpayne@68
|
11 * @param ref
|
jpayne@68
|
12 * @param rstart
|
jpayne@68
|
13 * @param rstop
|
jpayne@68
|
14 * @param minScore Quit early if score drops below this
|
jpayne@68
|
15 * @param minRatio Don't return results if max score is less than this fraction of max possible score
|
jpayne@68
|
16 * @return
|
jpayne@68
|
17 */
|
jpayne@68
|
18 @Override
|
jpayne@68
|
19 public AlignmentResult alignForward(final byte[] query, final byte[] ref, final int rstart, final int rstop, final int minScore,
|
jpayne@68
|
20 final float minRatio) {
|
jpayne@68
|
21 final int arrayLength=rstop-rstart+1;
|
jpayne@68
|
22
|
jpayne@68
|
23 //Stack allocated; faster.
|
jpayne@68
|
24 final int[] array1=new int[arrayLength+1], array2=new int[arrayLength+1];
|
jpayne@68
|
25
|
jpayne@68
|
26 final int minPassingScore=(int)(query.length*minRatio*pointsMatch);
|
jpayne@68
|
27 final int minPassingScore3=minPassingScore-query.length*pointsMatch;
|
jpayne@68
|
28
|
jpayne@68
|
29 int[] prev=array1, next=array2;
|
jpayne@68
|
30 int maxScore=-999999;
|
jpayne@68
|
31 int maxQpos=-1;
|
jpayne@68
|
32 int maxRpos=-1;
|
jpayne@68
|
33
|
jpayne@68
|
34 for(int i=0; i<=arrayLength-query.length; i++){prev[i]=0;}
|
jpayne@68
|
35 for(int i=arrayLength-query.length, score=0; i<=arrayLength; i++, score+=pointsDel) {
|
jpayne@68
|
36 prev[i]=score;
|
jpayne@68
|
37 }
|
jpayne@68
|
38
|
jpayne@68
|
39 int currentRstart=rstart;
|
jpayne@68
|
40 for(int qpos=0; qpos<query.length; qpos++){
|
jpayne@68
|
41 prev[0]=pointsIns*qpos;
|
jpayne@68
|
42
|
jpayne@68
|
43 final byte q=query[qpos];
|
jpayne@68
|
44 int maxScoreThisPass=-9999;
|
jpayne@68
|
45 final int remainingBases=(query.length-qpos);
|
jpayne@68
|
46 final int remainingPoints=remainingBases*pointsMatch;
|
jpayne@68
|
47 final int minViableScore=minPassingScore3-remainingPoints;
|
jpayne@68
|
48 // int minViableRstart=rstop+1;
|
jpayne@68
|
49 for(int rpos=currentRstart, apos=1+currentRstart-rstart; rpos<=rstop; rpos++, apos++){
|
jpayne@68
|
50 final byte r=ref[rpos];
|
jpayne@68
|
51 final boolean match=(q==r);
|
jpayne@68
|
52 final int vScore=prev[apos]+pointsIns;
|
jpayne@68
|
53 final int hScore=next[apos-1]+pointsDel;
|
jpayne@68
|
54 final int dScore=(match ? pointsMatch : pointsSub)+prev[apos-1];
|
jpayne@68
|
55
|
jpayne@68
|
56 //Slow branchy code
|
jpayne@68
|
57 // final int score=Tools.max(vScore, hScore, dScore);
|
jpayne@68
|
58 // next[apos]=score;
|
jpayne@68
|
59 // if(score>=maxScoreThisPass){
|
jpayne@68
|
60 // maxScoreThisPass=score;
|
jpayne@68
|
61 // if(score>=maxScore){
|
jpayne@68
|
62 // maxScore=score;
|
jpayne@68
|
63 // maxQpos=qpos;
|
jpayne@68
|
64 // maxRpos=rpos;
|
jpayne@68
|
65 // }
|
jpayne@68
|
66 // }
|
jpayne@68
|
67
|
jpayne@68
|
68 //Should be branchless conditional moves
|
jpayne@68
|
69 int score=(dScore>=vScore ? dScore : vScore);
|
jpayne@68
|
70 score=(hScore>score ? hScore : score);
|
jpayne@68
|
71 next[apos]=score;
|
jpayne@68
|
72 maxScoreThisPass=(score>maxScoreThisPass ? score : maxScoreThisPass);
|
jpayne@68
|
73
|
jpayne@68
|
74 // minViableRstart=((score<minViableScore || rpos>minViableRstart) ? minViableRstart : rpos);
|
jpayne@68
|
75 }
|
jpayne@68
|
76 iters+=arrayLength;
|
jpayne@68
|
77 if(maxScoreThisPass<minScore){//Aggressive early exit
|
jpayne@68
|
78 return null;
|
jpayne@68
|
79 }
|
jpayne@68
|
80
|
jpayne@68
|
81 {//Safe early exit
|
jpayne@68
|
82 if(maxScoreThisPass<minViableScore){return null;}
|
jpayne@68
|
83 }
|
jpayne@68
|
84
|
jpayne@68
|
85 int[] temp=prev;
|
jpayne@68
|
86 prev=next;
|
jpayne@68
|
87 next=temp;
|
jpayne@68
|
88 }
|
jpayne@68
|
89
|
jpayne@68
|
90 maxScore=-999999;
|
jpayne@68
|
91 for(int rpos=rstart, apos=1; rpos<=rstop; rpos++, apos++){//Grab high score from last iteration
|
jpayne@68
|
92 int score=prev[apos];
|
jpayne@68
|
93 if(score>=maxScore){
|
jpayne@68
|
94 maxScore=score;
|
jpayne@68
|
95 maxQpos=query.length;
|
jpayne@68
|
96 maxRpos=rpos;
|
jpayne@68
|
97 }
|
jpayne@68
|
98 }
|
jpayne@68
|
99
|
jpayne@68
|
100 maxScore=(maxScore-pointsSub*query.length)/(pointsMatch-pointsSub);//Rescale 0 to length
|
jpayne@68
|
101 final float ratio=maxScore/(float)query.length;
|
jpayne@68
|
102
|
jpayne@68
|
103 if(ratio<minRatio){return null;}
|
jpayne@68
|
104 return new AlignmentResult(maxScore, maxQpos, maxRpos, query.length, ref.length, rstart, rstop, ratio);
|
jpayne@68
|
105 }
|
jpayne@68
|
106
|
jpayne@68
|
107 /**
|
jpayne@68
|
108 * @param query
|
jpayne@68
|
109 * @param ref
|
jpayne@68
|
110 * @param qstart
|
jpayne@68
|
111 * @param rstart
|
jpayne@68
|
112 * @param rstop
|
jpayne@68
|
113 * @param minScore Quit early if score drops below this
|
jpayne@68
|
114 * @param minRatio Don't return results if max score is less than this fraction of max possible score
|
jpayne@68
|
115 * @return
|
jpayne@68
|
116 */
|
jpayne@68
|
117 @Override
|
jpayne@68
|
118 public AlignmentResult alignForwardShort(final byte[] query, final byte[] ref, final int rstart, final int rstop, final int minScore,
|
jpayne@68
|
119 final float minRatio) {
|
jpayne@68
|
120
|
jpayne@68
|
121 final int arrayLength=query.length;
|
jpayne@68
|
122
|
jpayne@68
|
123 //Stack allocated; faster.
|
jpayne@68
|
124 final int[] array1=new int[arrayLength+1], array2=new int[arrayLength+1];
|
jpayne@68
|
125
|
jpayne@68
|
126 final int minPassingScore=(int)(query.length*minRatio);
|
jpayne@68
|
127 final int minPassingScore3=minPassingScore-query.length;
|
jpayne@68
|
128
|
jpayne@68
|
129 int[] prev=array1, next=array2;
|
jpayne@68
|
130 int maxScore=-999999;
|
jpayne@68
|
131 int maxQpos=-1;
|
jpayne@68
|
132 int maxRpos=-1;
|
jpayne@68
|
133
|
jpayne@68
|
134 for(int i=0; i<prev.length; i++) {
|
jpayne@68
|
135 prev[i]=pointsIns*i;
|
jpayne@68
|
136 }
|
jpayne@68
|
137
|
jpayne@68
|
138 for(int rpos=rstart; rpos<=rstop; rpos++){
|
jpayne@68
|
139 if(rstop-rpos<arrayLength){prev[0]=next[0]+pointsDel;}
|
jpayne@68
|
140
|
jpayne@68
|
141 final byte r=ref[rpos];
|
jpayne@68
|
142 int score=0;
|
jpayne@68
|
143
|
jpayne@68
|
144 //In Java, the unsplit loop is faster
|
jpayne@68
|
145 //-XX:+UseSuperWord seems to have no impact on speed.
|
jpayne@68
|
146 //Might be worth packing the query and ref into int arrays and trying again.
|
jpayne@68
|
147 for(int qpos=0, apos=1; qpos<arrayLength; qpos++, apos++){
|
jpayne@68
|
148 final byte q=query[qpos];
|
jpayne@68
|
149 final boolean match=(q==r);
|
jpayne@68
|
150 final int vScore=prev[apos]+pointsIns;
|
jpayne@68
|
151 final int hScore=next[apos-1]+pointsDel;
|
jpayne@68
|
152 final int dScore=(match ? pointsMatch : pointsSub)+prev[apos-1];
|
jpayne@68
|
153
|
jpayne@68
|
154 score=(dScore>=vScore ? dScore : vScore);
|
jpayne@68
|
155 score=(hScore>score ? hScore : score);
|
jpayne@68
|
156
|
jpayne@68
|
157 next[apos]=score;
|
jpayne@68
|
158 }
|
jpayne@68
|
159
|
jpayne@68
|
160 // //Inner DV loop
|
jpayne@68
|
161 // for(int qpos=0, apos=1; qpos<arrayLength; qpos++, apos++){
|
jpayne@68
|
162 // final int q=query[qpos];
|
jpayne@68
|
163 // final boolean match=(q==r);
|
jpayne@68
|
164 // final int vScore=prev[apos]+pointsIns;
|
jpayne@68
|
165 // final int dScore=(match ? pointsMatch : pointsSub)+prev[apos-1];
|
jpayne@68
|
166 //
|
jpayne@68
|
167 // score=(dScore>=vScore ? dScore : vScore);
|
jpayne@68
|
168 //
|
jpayne@68
|
169 // next[apos]=score;
|
jpayne@68
|
170 // }
|
jpayne@68
|
171 //
|
jpayne@68
|
172 // //Inner I loop
|
jpayne@68
|
173 // for(int qpos=0, apos=1; qpos<arrayLength; qpos++, apos++){
|
jpayne@68
|
174 // final int hScore=next[apos-1]+pointsDel;
|
jpayne@68
|
175 //
|
jpayne@68
|
176 // score=next[apos];
|
jpayne@68
|
177 // score=(hScore>score ? hScore : score);
|
jpayne@68
|
178 //
|
jpayne@68
|
179 // next[apos]=score;
|
jpayne@68
|
180 // }
|
jpayne@68
|
181
|
jpayne@68
|
182 itersShort+=arrayLength;
|
jpayne@68
|
183
|
jpayne@68
|
184 if(score>=maxScore){
|
jpayne@68
|
185 maxScore=score;
|
jpayne@68
|
186 maxQpos=arrayLength-1;
|
jpayne@68
|
187 maxRpos=rpos;
|
jpayne@68
|
188 }
|
jpayne@68
|
189
|
jpayne@68
|
190 int[] temp=prev;
|
jpayne@68
|
191 prev=next;
|
jpayne@68
|
192 next=temp;
|
jpayne@68
|
193 }
|
jpayne@68
|
194
|
jpayne@68
|
195 maxScore=(maxScore-pointsSub*query.length)/(pointsMatch-pointsSub);//Rescale 0 to length
|
jpayne@68
|
196 final float ratio=maxScore/(float)query.length;
|
jpayne@68
|
197
|
jpayne@68
|
198 if(ratio<minRatio){return null;}
|
jpayne@68
|
199
|
jpayne@68
|
200 return new AlignmentResult(maxScore, maxQpos, maxRpos, query.length, ref.length, rstart, rstop, ratio);
|
jpayne@68
|
201 }
|
jpayne@68
|
202
|
jpayne@68
|
203 /*--------------------------------------------------------------*/
|
jpayne@68
|
204 /*---------------- Getters ----------------*/
|
jpayne@68
|
205 /*--------------------------------------------------------------*/
|
jpayne@68
|
206
|
jpayne@68
|
207 @Override
|
jpayne@68
|
208 long iters(){return iters;}
|
jpayne@68
|
209
|
jpayne@68
|
210 @Override
|
jpayne@68
|
211 long itersShort(){return itersShort;}
|
jpayne@68
|
212
|
jpayne@68
|
213 /*--------------------------------------------------------------*/
|
jpayne@68
|
214 /*---------------- Fields ----------------*/
|
jpayne@68
|
215 /*--------------------------------------------------------------*/
|
jpayne@68
|
216
|
jpayne@68
|
217 long iters = 0;
|
jpayne@68
|
218 long itersShort = 0;
|
jpayne@68
|
219
|
jpayne@68
|
220 /*--------------------------------------------------------------*/
|
jpayne@68
|
221 /*---------------- Constants ----------------*/
|
jpayne@68
|
222 /*--------------------------------------------------------------*/
|
jpayne@68
|
223
|
jpayne@68
|
224 public static final int pointsMatch = 1;
|
jpayne@68
|
225 public static final int pointsSub = -1;
|
jpayne@68
|
226 public static final int pointsDel = -2;
|
jpayne@68
|
227 public static final int pointsIns = -2;
|
jpayne@68
|
228
|
jpayne@68
|
229 }
|