1 package align2; 2 import java.util.Arrays; 3 4 import dna.AminoAcid; 5 import shared.KillSwitch; 6 import shared.Shared; 7 import shared.Tools; 8 import stream.SiteScore; 9 10 /** 11 * Modification of MultiStateAligner9ts to replace fixed affine steps with an array */ 12 public final class MultiStateAligner11tsJNI extends MSA{ 13 14 static { Shared.loadJNI()15 Shared.loadJNI(); 16 } 17 fillUnlimitedJNI(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int[] result, long[] iterationsUnlimited, int[] packed, int[] POINTSoff_SUB_ARRAY, int[] POINTSoff_INS_ARRAY, int maxRows, int maxColumns)18 private native void fillUnlimitedJNI(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int[] result, long[] iterationsUnlimited, int[] packed, int[] POINTSoff_SUB_ARRAY, int[] POINTSoff_INS_ARRAY, int maxRows, int maxColumns); 19 fillLimitedXJNI(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int minScore, int[] result, long[] iterationsLimited, int[] packed, int[] POINTSoff_SUB_ARRAY, int[] POINTSoff_INS_ARRAY, int maxRows, int maxColumns, int bandwidth, float bandwidthRatio, int[] vertLimit, int[] horizLimit, byte[] baseToNumber, int[] POINTSoff_INS_ARRAY_C)20 private native void fillLimitedXJNI(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int minScore, int[] result, long[] iterationsLimited, int[] packed, int[] POINTSoff_SUB_ARRAY, int[] POINTSoff_INS_ARRAY, int maxRows, int maxColumns, int bandwidth, float bandwidthRatio, int[] vertLimit, int[] horizLimit, byte[] baseToNumber, int[] POINTSoff_INS_ARRAY_C); 21 main(String[] args)22 public static void main(String[] args){ 23 byte[] read=args[0].getBytes(); 24 byte[] ref=args[1].getBytes(); 25 byte[] original=ref; 26 27 MultiStateAligner11tsJNI msa=new MultiStateAligner11tsJNI(read.length, ref.length); 28 System.out.println("Initial: "); 29 //printMatrix(msa.packed, read.length, ref.length, TIMEMASK, SCOREOFFSET); 30 31 int[] max=msa.fillLimited(read, ref, 0, ref.length-1, 0, null); 32 33 System.out.println("Max: "+Arrays.toString(max)); 34 35 System.out.println("Final: "); 36 //printMatrix(msa.packed, read.length, ref.length, TIMEMASK, SCOREOFFSET); 37 38 byte[] out=msa.traceback(read, ref, 0, ref.length-1, max[0], max[1], max[2], false); 39 40 int[] score=null; 41 score=msa.score(read, ref, 0, ref.length-1, max[0], max[1], max[2], false); 42 43 System.out.println(new String(ref)); 44 System.out.println(new String(read)); 45 System.out.println(new String(out)); 46 System.out.println("Score: "+Arrays.toString(score)); 47 } 48 MultiStateAligner11tsJNI(int maxRows_, int maxColumns_)49 public MultiStateAligner11tsJNI(int maxRows_, int maxColumns_){ 50 super(maxRows_, maxColumns_); 51 52 packed=KillSwitch.allocInt1D(3*(maxRows+1)*(maxColumns+1)); 53 grefbuffer=KillSwitch.allocByte1D(maxColumns+2); 54 vertLimit=KillSwitch.allocInt1D(maxRows+1); 55 horizLimit=KillSwitch.allocInt1D(maxColumns+1); 56 57 Arrays.fill(vertLimit, BADoff); 58 Arrays.fill(horizLimit, BADoff); 59 60 for(int matrix=0; matrix<3; matrix++){ 61 for(int i=1; i<=maxRows; i++){ 62 for(int j=0; j<maxColumns+1; j++){ 63 packed[(matrix)*(maxRows+1)*(maxColumns+1)+(i)*(maxColumns+1)+(j)]|=BADoff; 64 } 65 } 66 for(int i=0; i<=maxRows; i++){ 67 int prevScore=(i<2 ? 0 : packed[(matrix)*(maxRows+1)*(maxColumns+1)+(i-1)*(maxColumns+1)+(0)]); 68 int score=prevScore+POINTSoff_INS_ARRAY[i]; 69 packed[(matrix)*(maxRows+1)*(maxColumns+1)+(i)*(maxColumns+1)+(0)]=score; 70 } 71 } 72 } 73 74 @Override fillLimited(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int minScore, int[] gaps)75 public final int[] fillLimited(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int minScore, int[] gaps){ 76 if(gaps==null){return fillLimitedX(read, ref, refStartLoc, refEndLoc, minScore);} 77 else{ 78 byte[] gref=makeGref(ref, gaps, refStartLoc, refEndLoc); 79 80 if(verbose && greflimit>0 && greflimit<500){ 81 System.err.println(new String(gref, 0, greflimit)); 82 } 83 84 assert(gref!=null) : "Excessively long read:\n"+new String(read); 85 return fillLimitedX(read, gref, 0, greflimit, minScore); 86 } 87 } 88 89 /** return new int[] {rows, maxC, maxS, max}; 90 * Will not fill areas that cannot match minScore */ fillLimitedX(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int minScore)91 private final int[] fillLimitedX(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int minScore){ 92 if(verbose){System.err.println("fillLimitedX");} 93 rows=read.length; 94 columns=refEndLoc-refStartLoc+1; 95 96 final int halfband=(bandwidth<1 && bandwidthRatio<=0) ? 0 : 97 Tools.max(Tools.min(bandwidth<1 ? 9999999 : bandwidth, bandwidthRatio<=0 ? 9999999 : 8+(int)(rows*bandwidthRatio)), (columns-rows+8))/2; 98 99 if(minScore<1 || (columns+rows<90) || ((halfband<1 || halfband*3>columns) && (columns>read.length+Tools.min(170, read.length+20)))){ 100 return fillUnlimited(read, ref, refStartLoc, refEndLoc); 101 } 102 103 minScore-=120; //Increases quality trivially 104 105 //Create arrays for passing values to and from native library 106 int[] result = KillSwitch.allocInt1D(5); 107 long[] iterationsLimitedArray = new long[1]; 108 109 //Put values into array for passing to native library 110 iterationsLimitedArray[0] = iterationsLimited; 111 112 fillLimitedXJNI(read,ref,refStartLoc,refEndLoc,minScore,result,iterationsLimitedArray,packed,POINTSoff_SUB_ARRAY,POINTSoff_INS_ARRAY,maxRows,maxColumns,bandwidth,bandwidthRatio,vertLimit,horizLimit,AminoAcid.baseToNumber,POINTSoff_INS_ARRAY_C); 113 114 //Retrieve variables from native library that were updated there 115 iterationsLimited = iterationsLimitedArray[0]; 116 117 if(result[4]==1){ 118 return null; 119 } 120 121 //return new int[] {rows, maxCol, maxState, maxScore}; 122 return new int[] {result[0], result[1], result[2], result[3]}; 123 } 124 125 @Override fillUnlimited(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int[] gaps)126 public final int[] fillUnlimited(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int[] gaps){ 127 if(gaps==null){return fillUnlimited(read, ref, refStartLoc, refEndLoc);} 128 else{ 129 byte[] gref=makeGref(ref, gaps, refStartLoc, refEndLoc); 130 assert(gref!=null) : "Excessively long read:\n"+new String(read); 131 return fillUnlimited(read, gref, 0, greflimit); 132 } 133 } 134 135 /** return new int[] {rows, maxC, maxS, max}; 136 * Does not require a min score (ie, same as old method) */ fillUnlimited(byte[] read, byte[] ref, int refStartLoc, int refEndLoc)137 private final int[] fillUnlimited(byte[] read, byte[] ref, int refStartLoc, int refEndLoc){ 138 139 //Create arrays for passing values to and from native library 140 int[] result = KillSwitch.allocInt1D(4); 141 long[] iterationsUnlimitedArray = new long[1]; 142 iterationsUnlimitedArray[0] = iterationsUnlimited; 143 144 fillUnlimitedJNI(read,ref,refStartLoc,refEndLoc,result,iterationsUnlimitedArray,packed,POINTSoff_SUB_ARRAY,POINTSoff_INS_ARRAY,maxRows,maxColumns); 145 146 //Retrieve variables from native library that were updated there 147 long myiterationsUnlimited = iterationsUnlimitedArray[0]; 148 149 //return new int[] {rows, maxCol, maxState, maxScore}; 150 return new int[] {result[0], result[1], result[2], result[3]}; 151 } 152 153 @Override 154 @Deprecated 155 /** return new int[] {rows, maxC, maxS, max}; */ fillQ(byte[] read, byte[] ref, byte[] baseScores, int refStartLoc, int refEndLoc)156 public final int[] fillQ(byte[] read, byte[] ref, byte[] baseScores, int refStartLoc, int refEndLoc){ 157 assert(false) : "Needs to be redone to work with score cutoffs. Not difficult."; 158 rows=read.length; 159 columns=refEndLoc-refStartLoc+1; 160 161 assert(rows<=maxRows) : "Check that values are in-bounds before calling this function: "+rows+", "+maxRows; 162 assert(columns<=maxColumns) : "Check that values are in-bounds before calling this function: "+columns+", "+maxColumns; 163 164 assert(refStartLoc>=0) : "Check that values are in-bounds before calling this function: "+refStartLoc; 165 assert(refEndLoc<ref.length) : "Check that values are in-bounds before calling this function: "+refEndLoc+", "+ref.length; 166 167 for(int row=1; row<=rows; row++){ 168 for(int col=1; col<=columns; col++){ 169 final boolean match=(read[row-1]==ref[refStartLoc+col-1]); 170 final boolean prevMatch=(row<2 || col<2 ? false : read[row-2]==ref[refStartLoc+col-2]); 171 {//Calculate match and sub scores 172 final int scoreFromDiag=packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&SCOREMASK; 173 final int scoreFromDel=packed[(MODE_DEL)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&SCOREMASK; 174 final int scoreFromIns=packed[(MODE_INS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&SCOREMASK; 175 final int streak=(packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&TIMEMASK); 176 {//Calculate match/sub score 177 if(match){ 178 int scoreMS=scoreFromDiag+(prevMatch ? POINTSoff_MATCH2 : POINTSoff_MATCH); 179 int scoreD=scoreFromDel+POINTSoff_MATCH; 180 int scoreI=scoreFromIns+POINTSoff_MATCH; 181 182 int score; 183 int time; 184 if(scoreMS>=scoreD && scoreMS>=scoreI){ 185 score=scoreMS; 186 time=(prevMatch ? streak+1 : 1); 187 }else if(scoreD>=scoreI){ 188 score=scoreD; 189 time=1; 190 }else{ 191 score=scoreI; 192 time=1; 193 } 194 score+=(((int)baseScores[row-1])<<SCOREOFFSET); //modifier 195 196 if(time>MAX_TIME){time=MAX_TIME-MASK5;} 197 assert(score>=MINoff_SCORE) : "Score overflow - use MSA2 instead"; 198 assert(score<=MAXoff_SCORE) : "Score overflow - use MSA2 instead"; 199 packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col)]=(score|time); 200 assert((score&SCOREMASK)==score); 201 assert((time&TIMEMASK)==time); 202 203 }else{ 204 int scoreMS=scoreFromDiag+(prevMatch ? (streak<=1 ? POINTSoff_SUBR : POINTSoff_SUB) : 205 POINTSoff_SUB_ARRAY[streak+1]); 206 int scoreD=scoreFromDel+POINTSoff_SUB; //+2 to move it as close as possible to the deletion / insertion 207 int scoreI=scoreFromIns+POINTSoff_SUB; 208 209 int score; 210 int time; 211 byte prevState; 212 if(scoreMS>=scoreD && scoreMS>=scoreI){ 213 score=scoreMS; 214 time=(prevMatch ? 1 : streak+1); 215 prevState=MODE_MS; 216 }else if(scoreD>=scoreI){ 217 score=scoreD; 218 time=1; 219 prevState=MODE_DEL; 220 }else{ 221 score=scoreI; 222 time=1; 223 prevState=MODE_INS; 224 } 225 226 if(time>MAX_TIME){time=MAX_TIME-MASK5;} 227 assert(score>=MINoff_SCORE) : "Score overflow - use MSA2 instead"; 228 assert(score<=MAXoff_SCORE) : "Score overflow - use MSA2 instead"; 229 packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col)]=(score|time); 230 assert((score&SCOREMASK)==score); 231 assert((time&TIMEMASK)==time); 232 } 233 } 234 } 235 236 {//Calculate DEL score 237 final int streak=packed[(MODE_DEL)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col-1)]&TIMEMASK; 238 final int scoreFromDiag=packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col-1)]&SCOREMASK; 239 final int scoreFromDel=packed[(MODE_DEL)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col-1)]&SCOREMASK; 240 241 int scoreMS=scoreFromDiag+POINTSoff_DEL; 242 int scoreD=scoreFromDel+(streak==0 ? POINTSoff_DEL : 243 streak<LIMIT_FOR_COST_3 ? POINTSoff_DEL2 : 244 streak<LIMIT_FOR_COST_4 ? POINTSoff_DEL3 : 245 streak<LIMIT_FOR_COST_5 ? POINTSoff_DEL4 : 246 ((streak&MASK5)==0 ? POINTSoff_DEL5 : 0)); 247 248 int score; 249 int time; 250 byte prevState; 251 if(scoreMS>=scoreD){ 252 score=scoreMS; 253 time=1; 254 prevState=MODE_MS; 255 }else{ 256 score=scoreD; 257 time=streak+1; 258 prevState=MODE_DEL; 259 } 260 261 if(time>MAX_TIME){time=MAX_TIME-MASK5;} 262 assert(score>=MINoff_SCORE) : "Score overflow - use MSA2 instead"; 263 assert(score<=MAXoff_SCORE) : "Score overflow - use MSA2 instead"; 264 packed[(MODE_DEL)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col)]=(score|time); 265 assert((score&SCOREMASK)==score); 266 assert((time&TIMEMASK)==time); 267 } 268 269 {//Calculate INS score 270 final int streak=packed[(MODE_INS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col)]&TIMEMASK; 271 final int scoreFromDiag=packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col)]&SCOREMASK; 272 final int scoreFromIns=packed[(MODE_INS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col)]&SCOREMASK; 273 274 int scoreMS=scoreFromDiag+POINTSoff_INS; 275 int scoreI=scoreFromIns+POINTSoff_INS_ARRAY[streak+1]; 276 277 int score; 278 int time; 279 byte prevState; 280 if(scoreMS>=scoreI){ 281 score=scoreMS; 282 time=1; 283 prevState=MODE_MS; 284 }else{ 285 score=scoreI; 286 time=streak+1; 287 prevState=MODE_INS; 288 } 289 290 if(time>MAX_TIME){time=MAX_TIME-MASK5;} 291 assert(score>=MINoff_SCORE) : "Score overflow - use MSA2 instead"; 292 assert(score<=MAXoff_SCORE) : "Score overflow - use MSA2 instead"; 293 packed[(MODE_INS)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col)]=(score|time); 294 assert((score&SCOREMASK)==score); 295 assert((time&TIMEMASK)==time); 296 } 297 } 298 } 299 300 int maxCol=-1; 301 int maxState=-1; 302 int maxScore=Integer.MIN_VALUE; 303 304 for(int state=0; state<3; state++){ 305 for(int col=1; col<=columns; col++){ 306 int x=packed[(state)*(maxRows+1)*(maxColumns+1)+(rows)*(maxColumns+1)+(col)]&SCOREMASK; 307 if(x>maxScore){ 308 maxScore=x; 309 maxCol=col; 310 maxState=state; 311 } 312 } 313 } 314 maxScore>>=SCOREOFFSET; 315 316 return new int[] {rows, maxCol, maxState, maxScore}; 317 } 318 319 @Override 320 /** @return {score, bestRefStart, bestRefStop} */ 321 /** Generates the match string */ 322 public final byte[] traceback(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int row, int col, int state, boolean gapped){ 323 if(gapped){ 324 final byte[] gref=grefbuffer; 325 int gstart=translateToGappedCoordinate(refStartLoc, gref); 326 int gstop=translateToGappedCoordinate(refEndLoc, gref); 327 byte[] out=traceback2(read, gref, gstart, gstop, row, col, state); 328 return out; 329 }else{ 330 return traceback2(read, ref, refStartLoc, refEndLoc, row, col, state); 331 } 332 } 333 334 @Override 335 /** Generates the match string */ 336 public final byte[] traceback2(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int row, int col, int state){ 337 assert(refStartLoc<=refEndLoc) : refStartLoc+", "+refEndLoc; 338 assert(row==rows); 339 340 byte[] out=new byte[row+col-1]; //TODO if an out of bound crash occurs, try removing the "-1". 341 int outPos=0; 342 343 int gaps=0; 344 345 if(state==MODE_INS){ 346 } 347 348 while(row>0 && col>0){ 349 final int time=packed[(state)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col)]&TIMEMASK; 350 final byte prev; 351 352 if(state==MODE_MS){ 353 if(time>1){prev=(byte)state;} 354 else{ 355 final int scoreFromDiag=packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&SCOREMASK; 356 final int scoreFromDel=packed[(MODE_DEL)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&SCOREMASK; 357 final int scoreFromIns=packed[(MODE_INS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&SCOREMASK; 358 if(scoreFromDiag>=scoreFromDel && scoreFromDiag>=scoreFromIns){prev=MODE_MS;} 359 else if(scoreFromDel>=scoreFromIns){prev=MODE_DEL;} 360 else{prev=MODE_INS;} 361 } 362 363 byte c=read[row-1]; 364 byte r=ref[refStartLoc+col-1]; 365 if(c==r){ 366 out[outPos]='m'; 367 }else{ 368 if(!AminoAcid.isFullyDefined(c)){ 369 out[outPos]='N'; 370 }else if(!AminoAcid.isFullyDefined(r)){ 371 out[outPos]='N'; 372 }else{ 373 out[outPos]='S'; 374 } 375 } 376 377 row--; 378 col--; 379 }else if(state==MODE_DEL){ 380 if(time>1){prev=(byte)state;} 381 else{ 382 final int scoreFromDiag=packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col-1)]&SCOREMASK; 383 final int scoreFromDel=packed[(MODE_DEL)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col-1)]&SCOREMASK; 384 if(scoreFromDiag>=scoreFromDel){prev=MODE_MS;} 385 else{prev=MODE_DEL;} 386 } 387 388 byte r=ref[refStartLoc+col-1]; 389 if(r==GAPC){ 390 out[outPos]='-'; 391 gaps++; 392 }else{ 393 out[outPos]='D'; 394 } 395 col--; 396 }else{ 397 if(time>1){prev=(byte)state;} 398 else{ 399 final int scoreFromDiag=packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col)]&SCOREMASK; 400 final int scoreFromIns=packed[(MODE_INS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col)]&SCOREMASK; 401 if(scoreFromDiag>=scoreFromIns){prev=MODE_MS;} 402 else{prev=MODE_INS;} 403 } 404 405 assert(state==MODE_INS) : state; 406 if(col==0){ 407 out[outPos]='X'; 408 }else if(col>=columns){ 409 out[outPos]='Y'; 410 }else{ 411 out[outPos]='I'; 412 } 413 row--; 414 } 415 416 state=prev; 417 outPos++; 418 } 419 420 assert(row==0 || col==0); 421 if(col!=row){ 422 while(row>0){ 423 out[outPos]='X'; 424 outPos++; 425 row--; 426 col--; 427 } 428 if(col>0){ 429 //do nothing 430 } 431 } 432 433 byte[] out2=new byte[outPos]; 434 for(int i=0; i<outPos; i++){ 435 out2[i]=out[outPos-i-1]; 436 } 437 out=null; 438 439 if(gaps==0){return out2;} 440 441 byte[] out3=new byte[out2.length+gaps*(GAPLEN-1)]; 442 for(int i=0, j=0; i<out2.length; i++){ 443 byte c=out2[i]; 444 if(c!=GAPC){ 445 out3[j]=c; 446 j++; 447 }else{ 448 int lim=j+GAPLEN; 449 for(; j<lim; j++){ 450 out3[j]='D'; 451 } 452 } 453 } 454 return out3; 455 } 456 457 @Override 458 /** @return {score, bestRefStart, bestRefStop} */ 459 public final int[] score(final byte[] read, final byte[] ref, final int refStartLoc, final int refEndLoc, 460 final int maxRow, final int maxCol, final int maxState, boolean gapped){ 461 if(gapped){ 462 if(verbose){ 463 System.err.println("score():"); 464 System.err.println("origin="+grefRefOrigin+", "+refStartLoc+", "+refEndLoc+", "+maxRow+", "+maxCol); 465 } 466 final byte[] gref=grefbuffer; 467 int gstart=translateToGappedCoordinate(refStartLoc, gref); 468 int gstop=translateToGappedCoordinate(refEndLoc, gref); 469 470 assert(translateFromGappedCoordinate(gstart, gref)==refStartLoc); //TODO: Remove slow assertions 471 assert(translateFromGappedCoordinate(gstop, gref)==refEndLoc); 472 473 assert(gstart==0) : gstart; //TODO: skip translation if this is always zero 474 475 if(verbose){System.err.println("gstart, gstop: "+gstart+", "+gstop);} 476 int[] out=score2(read, gref, gstart, gstop, maxRow, maxCol, maxState); 477 if(verbose){System.err.println("got score "+Arrays.toString(out));} 478 479 assert(out[1]==translateToGappedCoordinate(translateFromGappedCoordinate(out[1], gref), gref)) : 480 "Verifying: "+out[1]+" -> "+translateFromGappedCoordinate(out[1], gref)+" -> "+ 481 translateToGappedCoordinate(translateFromGappedCoordinate(out[1], gref), gref); 482 assert(out[2]==translateToGappedCoordinate(translateFromGappedCoordinate(out[2], gref), gref)); 483 484 out[1]=translateFromGappedCoordinate(out[1], gref); 485 out[2]=translateFromGappedCoordinate(out[2], gref); 486 if(verbose){System.err.println("returning score "+Arrays.toString(out));} 487 return out; 488 }else{ 489 return score2(read, ref, refStartLoc, refEndLoc, maxRow, maxCol, maxState); 490 } 491 } 492 493 @Override 494 /** @return {score, bestRefStart, bestRefStop, maxRow, maxCol, maxState}, <br> 495 * or {score, bestRefStart, bestRefStop, maxRow, maxCol, maxState, padLeft, padRight} <br> 496 * if more padding is needed */ 497 public final int[] score2(final byte[] read, final byte[] ref, final int refStartLoc, final int refEndLoc, 498 final int maxRow, final int maxCol, final int maxState){ 499 int row=maxRow; 500 int col=maxCol; 501 int state=maxState; 502 503 assert(maxState>=0 && maxState<3) : 504 maxState+", "+maxRow+", "+maxCol+"\n"+new String(read)+"\n"+toString(ref, refStartLoc, refEndLoc); 505 //assert(maxRow>=0 && maxRow<packed[0].length) : 506 // maxState+", "+maxRow+", "+maxCol+"\n"+new String(read)+"\n"+toString(ref, refStartLoc, refEndLoc); 507 //assert(maxCol>=0 && maxCol<packed[0][0].length) : 508 // maxState+", "+maxRow+", "+maxCol+"\n"+new String(read)+"\n"+toString(ref, refStartLoc, refEndLoc); 509 510 int score=packed[(maxState)*(maxRows+1)*(maxColumns+1)+(maxRow)*(maxColumns+1)+(maxCol)]&SCOREMASK; //Or zero, if it is to be recalculated 511 512 if(row<rows){ 513 int difR=rows-row; 514 int difC=columns-col; 515 516 while(difR>difC){ 517 score+=POINTSoff_NOREF; 518 difR--; 519 } 520 521 row+=difR; 522 col+=difR; 523 } 524 525 assert(refStartLoc<=refEndLoc); 526 assert(row==rows); 527 528 final int bestRefStop=refStartLoc+col-1; 529 530 if(verbose){System.err.println("Scoring.");} 531 532 int stateTime=0; 533 534 while(row>0 && col>0){ 535 if(verbose){System.err.println("state="+state+", row="+row+", col="+col);} 536 537 final int time=packed[(state)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col)]&TIMEMASK; 538 final byte prev; 539 540 if(state==MODE_MS){ 541 if(time>1){prev=(byte)state;} 542 else{ 543 final int scoreFromDiag=packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&SCOREMASK; 544 final int scoreFromDel=packed[(MODE_DEL)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&SCOREMASK; 545 final int scoreFromIns=packed[(MODE_INS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col-1)]&SCOREMASK; 546 if(scoreFromDiag>=scoreFromDel && scoreFromDiag>=scoreFromIns){prev=MODE_MS;} 547 else if(scoreFromDel>=scoreFromIns){prev=MODE_DEL;} 548 else{prev=MODE_INS;} 549 } 550 row--; 551 col--; 552 }else if(state==MODE_DEL){ 553 if(time>1){prev=(byte)state;} 554 else{ 555 final int scoreFromDiag=packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col-1)]&SCOREMASK; 556 final int scoreFromDel=packed[(MODE_DEL)*(maxRows+1)*(maxColumns+1)+(row)*(maxColumns+1)+(col-1)]&SCOREMASK; 557 if(scoreFromDiag>=scoreFromDel){prev=MODE_MS;} 558 else{prev=MODE_DEL;} 559 } 560 col--; 561 }else{ 562 assert(state==MODE_INS); 563 if(time>1){prev=(byte)state;} 564 else{ 565 final int scoreFromDiag=packed[(MODE_MS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col)]&SCOREMASK; 566 final int scoreFromIns=packed[(MODE_INS)*(maxRows+1)*(maxColumns+1)+(row-1)*(maxColumns+1)+(col)]&SCOREMASK; 567 if(scoreFromDiag>=scoreFromIns){prev=MODE_MS;} 568 else{prev=MODE_INS;} 569 } 570 row--; 571 } 572 573 if(col<0){ 574 if(verbose){ 575 System.err.println("Warning, column went below 0 at row="+row); 576 } 577 break; //prevents an out of bounds access 578 } 579 580 if(state==prev){stateTime++;}else{stateTime=0;} 581 state=prev; 582 583 if(verbose){System.err.println("state2="+state+", time="+time+", stateTime="+stateTime+", row2="+row+", col2="+col+"\n");} 584 } 585 if(row>col){ 586 col-=row; 587 } 588 589 final int bestRefStart=refStartLoc+col; 590 591 score>>=SCOREOFFSET; 592 593 if(verbose){ 594 System.err.println("bestRefStart="+bestRefStart+", refStartLoc="+refStartLoc); 595 System.err.println("bestRefStop="+bestRefStop+", refEndLoc="+refEndLoc); 596 } 597 598 int padLeft=0; 599 int padRight=0; 600 if(bestRefStart<refStartLoc){ 601 padLeft=Tools.max(0, refStartLoc-bestRefStart); 602 }else if(bestRefStart==refStartLoc && state==MODE_INS){ 603 padLeft=stateTime; 604 } 605 if(bestRefStop>refEndLoc){ 606 padRight=Tools.max(0, bestRefStop-refEndLoc); 607 }else if(bestRefStop==refEndLoc && maxState==MODE_INS){ 608 padRight=packed[(maxState)*(maxRows+1)*(maxColumns+1)+(maxRow)*(maxColumns+1)+(maxCol)]&TIMEMASK; 609 } 610 611 int[] rvec; 612 if(padLeft>0 || padRight>0){ //Suggest extra padding in cases of overflow 613 rvec=new int[] {score, bestRefStart, bestRefStop, maxRow, maxCol, maxState, padLeft, padRight}; 614 }else{ 615 rvec=new int[] {score, bestRefStart, bestRefStop, maxRow, maxCol, maxState}; 616 } 617 return rvec; 618 } 619 620 /** 621 * Fills grefbuffer 622 * @param ref 623 * @param a 624 * @param b 625 * @param gaps 626 * @return gref 627 */ 628 private final byte[] makeGref(byte[] ref, int[] gaps, int refStartLoc, int refEndLoc){ 629 assert(gaps!=null && gaps.length>0); 630 631 assert(refStartLoc<=gaps[0]) : refStartLoc+", "+refEndLoc+", "+Arrays.toString(gaps); 632 assert(refEndLoc>=gaps[gaps.length-1]); 633 634 final int g0_old=gaps[0]; 635 final int gN_old=gaps[gaps.length-1]; 636 gaps[0]=Tools.min(gaps[0], refStartLoc); 637 gaps[gaps.length-1]=Tools.max(gN_old, refEndLoc); 638 grefRefOrigin=gaps[0]; 639 640 if(verbose){System.err.println("\ngaps2: "+Arrays.toString(gaps));} 641 642 byte[] gref=grefbuffer; 643 644 int gpos=0; 645 for(int i=0; i<gaps.length; i+=2){ 646 int x=gaps[i]; 647 int y=gaps[i+1]; 648 649 for(int r=x; r<=y; r++, gpos++){ 650 //TODO: if out of bounds, use an 'N' 651 assert(gpos<gref.length) : 652 "\ngpos="+gpos+", gref.length="+gref.length+/*", read.length="+read.length+*/", gaps2="+Arrays.toString(gaps)+ 653 "\ni="+i+", r="+r+", x="+x+", y="+y+ 654 "\nGapTools.calcGrefLen("+gaps[0]+", "+gaps[gaps.length-1]+", gaps)="+GapTools.calcGrefLen(gaps[0], gaps[gaps.length-1], gaps)+ 655 "\nGapTools.calcGrefLen("+gaps[0]+", "+gaps[gaps.length-1]+", gaps)="+GapTools.calcGrefLen(gaps[0], gaps[gaps.length-1], gaps)+ 656 "\n"+refStartLoc+", "+refEndLoc+", "+greflimit+", "+GREFLIMIT2_CUSHION+"\n"+new String(gref)+"\n"/*+new String(read)+"\n"*/; 657 gref[gpos]=ref[r]; 658 } 659 660 if(i+2<gaps.length){ 661 int z=gaps[i+2]; 662 assert(z>y); 663 int gap=z-y-1; 664 assert(gap>=MINGAP) : gap+"\t"+MINGAP; 665 if(gap<MINGAP){ 666 assert(false) : "TODO - just fill in normally"; 667 }else{ 668 int rem=gap%GAPLEN; 669 int lim=y+GAPBUFFER+rem; 670 671 int div=(gap-GAPBUFFER2)/GAPLEN; 672 if(verbose){ 673 System.err.println("div = "+div); 674 } 675 assert(div>0); 676 677 for(int r=y+1; r<=lim; r++, gpos++){ 678 gref[gpos]=ref[r]; 679 } 680 for(int g=0; g<div; g++, gpos++){ 681 gref[gpos]=GAPC; 682 } 683 for(int r=z-GAPBUFFER; r<z; r++, gpos++){ 684 gref[gpos]=ref[r]; 685 } 686 } 687 } 688 } 689 690 greflimit=gpos; 691 692 assert(gref[gpos-1]==ref[refEndLoc]); 693 { 694 final int lim=Tools.min(gref.length, greflimit+GREFLIMIT2_CUSHION); 695 if(lim>gref.length){ 696 System.err.println("gref buffer overflow: "+lim+" > "+gref.length); 697 return null; 698 } 699 for(int i=greflimit, r=refEndLoc+1; i<lim; i++, r++){ 700 gref[i]=(r<ref.length ? ref[r] : (byte)'N'); 701 greflimit2=i; 702 } 703 } 704 705 if(verbose){ 706 System.err.println("gref:\n"+new String(gref)); 707 } 708 709 gaps[0]=g0_old; 710 gaps[gaps.length-1]=gN_old; 711 712 if(verbose){ 713 System.err.println("\ngaps3: "+Arrays.toString(gaps)); 714 } 715 716 return gref; 717 } 718 719 private final int translateFromGappedCoordinate(int point, byte[] gref){ 720 if(verbose){System.err.println("translateFromGappedCoordinate("+point+"), gro="+grefRefOrigin+", grl="+greflimit);} 721 if(point<=0){return grefRefOrigin+point;} 722 for(int i=0, j=grefRefOrigin; i<greflimit2; i++){ 723 byte c=gref[i]; 724 assert(point>=i) : "\n"+grefRefOrigin+"\n"+point+"\n"+new String(gref)+"\n"; 725 726 if(i==point){ 727 if(verbose){System.err.println(" -> "+j);} 728 return j; 729 } 730 731 j+=(c==GAPC ? GAPLEN : 1); 732 } 733 734 System.err.println(grefRefOrigin); 735 System.err.println(point); 736 System.err.println(new String(gref)); 737 738 throw new RuntimeException("Out of bounds."); 739 } 740 741 private final int translateToGappedCoordinate(int point, byte[] gref){ 742 if(verbose){System.err.println("translateToGappedCoordinate("+point+"), gro="+grefRefOrigin+", grl="+greflimit);} 743 if(point<=grefRefOrigin){return point-grefRefOrigin;} 744 for(int i=0, j=grefRefOrigin; i<greflimit2; i++){ 745 assert(point>=j) : "\n"+grefRefOrigin+"\n"+point+"\n"+new String(gref)+"\n"; 746 byte c=gref[i]; 747 748 if(j==point){ 749 if(verbose){System.err.println(" -> "+i);} 750 return i; 751 } 752 753 j+=(c==GAPC ? GAPLEN : 1); 754 } 755 756 System.err.println(grefRefOrigin); 757 System.err.println(point); 758 System.err.println(new String(gref)); 759 760 throw new RuntimeException("Out of bounds."); 761 } 762 763 /** Calculates score based on an array from Index */ 764 private final int calcAffineScore(int[] locArray){ 765 int score=0; 766 int lastLoc=-2; //Last true location 767 int lastValue=-1; 768 int timeInMode=0; 769 770 for(int i=0; i<locArray.length; i++){ 771 int loc=locArray[i]; 772 773 if(loc>0){//match 774 if(loc==lastValue){//contiguous match 775 score+=POINTS_MATCH2; 776 }else if(loc==lastLoc || lastLoc<0){//match after a sub, or first match 777 score+=POINTS_MATCH; 778 }else if(loc<lastLoc){//deletion 779 assert(lastLoc>=0); 780 score+=POINTS_MATCH; 781 score+=POINTS_DEL; 782 int dif=lastLoc-loc+1; 783 if(dif>MINGAP){ 784 int rem=dif%GAPLEN; 785 int div=(dif-GAPBUFFER2)/GAPLEN; 786 score+=(div*POINTS_GAP); 787 assert(rem+GAPBUFFER2<dif); 788 dif=rem+GAPBUFFER2; 789 assert(dif>LIMIT_FOR_COST_4); //and probably LIMIT_FOR_COST_5 790 } 791 if(dif>LIMIT_FOR_COST_5){ 792 score+=((dif-LIMIT_FOR_COST_5+MASK5)/TIMESLIP)*POINTS_DEL5; 793 dif=LIMIT_FOR_COST_5; 794 } 795 if(dif>LIMIT_FOR_COST_4){ 796 score+=(dif-LIMIT_FOR_COST_4)*POINTS_DEL4; 797 dif=LIMIT_FOR_COST_4; 798 } 799 if(dif>LIMIT_FOR_COST_3){ 800 score+=(dif-LIMIT_FOR_COST_3)*POINTS_DEL3; 801 dif=LIMIT_FOR_COST_3; 802 } 803 if(dif>1){ 804 score+=(dif-1)*POINTS_DEL2; 805 } 806 timeInMode=1; 807 }else if(loc>lastLoc){//insertion 808 assert(lastLoc>=0); 809 score+=(POINTS_MATCH+POINTS_INS_ARRAY_C[lastLoc-loc]); 810 timeInMode=1; 811 }else{ 812 assert(false); 813 } 814 lastLoc=loc; 815 }else{//substitution 816 if(lastValue<0 && timeInMode>0){//contiguous 817 timeInMode++; 818 score+=(POINTS_SUB_ARRAY[timeInMode]); 819 }else{ 820 score+=POINTS_SUB; 821 timeInMode=1; 822 } 823 } 824 lastValue=loc; 825 } 826 assert(score<=maxQuality(locArray.length)); 827 return score; 828 } 829 830 @Override 831 public final int calcAffineScore(final int[] locArray, final byte[] baseScores, final byte bases[]){ 832 int score=0; 833 int lastLoc=-3; //Last true location 834 int lastValue=-1; 835 int timeInMode=0; 836 837 for(int i=0; i<locArray.length; i++){ 838 final int loc=locArray[i]; 839 840 if(loc>0){//match 841 if(loc==lastValue){//contiguous match 842 score+=(POINTS_MATCH2+baseScores[i]); 843 }else if(loc==lastLoc || lastLoc<0){//match after a sub, or first match 844 score+=(POINTS_MATCH+baseScores[i]); 845 }else if(loc<lastLoc){//deletion 846 assert(lastLoc>=0); 847 score+=(POINTS_MATCH+baseScores[i]); 848 score+=POINTS_DEL; 849 int dif=lastLoc-loc+1; 850 if(dif>MINGAP){ 851 int rem=dif%GAPLEN; 852 int div=(dif-GAPBUFFER2)/GAPLEN; 853 score+=(div*POINTS_GAP); 854 assert(rem+GAPBUFFER2<dif); 855 dif=rem+GAPBUFFER2; 856 assert(dif>LIMIT_FOR_COST_4); //and probably LIMIT_FOR_COST_5 857 } 858 if(dif>LIMIT_FOR_COST_5){ 859 score+=((dif-LIMIT_FOR_COST_5+MASK5)/TIMESLIP)*POINTS_DEL5; 860 dif=LIMIT_FOR_COST_5; 861 } 862 if(dif>LIMIT_FOR_COST_4){ 863 score+=(dif-LIMIT_FOR_COST_4)*POINTS_DEL4; 864 dif=LIMIT_FOR_COST_4; 865 } 866 if(dif>LIMIT_FOR_COST_3){ 867 score+=(dif-LIMIT_FOR_COST_3)*POINTS_DEL3; 868 dif=LIMIT_FOR_COST_3; 869 } 870 if(dif>1){ 871 score+=(dif-1)*POINTS_DEL2; 872 } 873 timeInMode=1; 874 }else if(loc>lastLoc){//insertion 875 assert(lastLoc>=0); 876 score+=(POINTS_MATCH+baseScores[i]+POINTS_INS_ARRAY_C[Tools.min(loc-lastLoc, 5)]); 877 timeInMode=1; 878 }else{ 879 assert(false); 880 } 881 lastLoc=loc; 882 }else if(loc==-1){//substitution 883 if(lastValue<0 && timeInMode>0){//contiguous 884 timeInMode++; 885 score+=(POINTS_SUB_ARRAY[timeInMode]); 886 }else{ 887 score+=POINTS_SUB; 888 timeInMode=1; 889 } 890 }else{ 891 assert(loc==-2) : "\ni="+i+", loc="+loc+", score="+score+", lastLoc="+lastLoc+", lastValue="+lastValue 892 +", time="+timeInMode+", length="+locArray.length+"\nbases=\n"+new String(bases) 893 +"\nlocs[]=\n"+Arrays.toString(locArray)+"\n"+new String(bases)+"\n" 894 +"If this happens please ensure that the reference has a startpad of Ns longer than readlength.";//N (no-call or no-ref) 895 timeInMode=0; 896 score+=POINTS_NOCALL; 897 } 898 lastValue=loc; 899 } 900 assert(score<=maxQuality(locArray.length)); 901 return score; 902 } 903 904 @Override 905 public final int calcAffineScore(int[] locArray, byte[] baseScores, byte[] bases, int minContig){ 906 assert(minContig>1) : minContig; 907 908 int contig=0; 909 int maxContig=0; 910 911 int score=0; 912 int lastLoc=-3; //Last true location 913 int lastValue=-1; 914 int timeInMode=0; 915 916 for(int i=0; i<locArray.length; i++){ 917 int loc=locArray[i]; 918 919 if(loc>0){//match 920 if(loc==lastValue){//contiguous match 921 contig++; 922 score+=(POINTS_MATCH2+baseScores[i]); 923 }else if(loc==lastLoc || lastLoc<0){//match after a sub, or first match 924 maxContig=Tools.max(maxContig, contig); 925 contig=1; 926 score+=(POINTS_MATCH+baseScores[i]); 927 }else if(loc<lastLoc){//deletion 928 maxContig=Tools.max(maxContig, contig); 929 contig=0; 930 assert(lastLoc>=0); 931 score+=(POINTS_MATCH+baseScores[i]); 932 score+=POINTS_DEL; 933 int dif=lastLoc-loc+1; 934 if(dif>MINGAP){ 935 int rem=dif%GAPLEN; 936 int div=(dif-GAPBUFFER2)/GAPLEN; 937 score+=(div*POINTS_GAP); 938 assert(rem+GAPBUFFER2<dif); 939 dif=rem+GAPBUFFER2; 940 assert(dif>LIMIT_FOR_COST_4); //and probably LIMIT_FOR_COST_5 941 } 942 if(dif>LIMIT_FOR_COST_5){ 943 score+=((dif-LIMIT_FOR_COST_5+MASK5)/TIMESLIP)*POINTS_DEL5; 944 dif=LIMIT_FOR_COST_5; 945 } 946 if(dif>LIMIT_FOR_COST_4){ 947 score+=(dif-LIMIT_FOR_COST_4)*POINTS_DEL4; 948 dif=LIMIT_FOR_COST_4; 949 } 950 if(dif>LIMIT_FOR_COST_3){ 951 score+=(dif-LIMIT_FOR_COST_3)*POINTS_DEL3; 952 dif=LIMIT_FOR_COST_3; 953 } 954 if(dif>1){ 955 score+=(dif-1)*POINTS_DEL2; 956 } 957 timeInMode=1; 958 }else if(loc>lastLoc){//insertion 959 maxContig=Tools.max(maxContig, contig); 960 contig=0; 961 assert(lastLoc>=0); 962 score+=(POINTS_MATCH+baseScores[i]+POINTS_INS_ARRAY_C[Tools.min(loc-lastLoc, 5)]); 963 timeInMode=1; 964 }else{ 965 assert(false); 966 } 967 lastLoc=loc; 968 }else if(loc==-1){//substitution 969 if(lastValue<0 && timeInMode>0){//contiguous 970 timeInMode++; 971 score+=(POINTS_SUB_ARRAY[timeInMode]); 972 }else{ 973 score+=POINTS_SUB; 974 timeInMode=1; 975 } 976 }else{ 977 assert(loc==-2) : loc+"\n"+Arrays.toString(locArray)+"\n"+Arrays.toString(baseScores)+"\n"+new String(bases)+"\n" 978 +"If this happens please ensure that the reference has a startpad of Ns longer than readlength.";//N (no-call or no-ref) 979 timeInMode=0; 980 score+=POINTS_NOCALL; 981 } 982 lastValue=loc; 983 } 984 assert(score<=maxQuality(locArray.length)); 985 if(Tools.max(contig, maxContig)<minContig){score=Tools.min(score, -50*locArray.length);} 986 return score; 987 } 988 989 @Override 990 public final int scoreNoIndels(byte[] read, byte[] ref, final int refStart){ 991 return scoreNoIndels(read, ref, refStart, null); 992 } 993 @Override 994 public final int scoreNoIndels(byte[] read, byte[] ref, final int refStart, final SiteScore ss){ 995 int score=0; 996 int mode=-1; 997 int timeInMode=0; 998 999 //This block handles cases where the read runs outside the reference 1000 //Of course, padding the reference with 'N' would be better, but... 1001 int readStart=0; 1002 int readStop=read.length; 1003 final int refStop=refStart+read.length; 1004 boolean semiperfect=true; 1005 int norefs=0; 1006 1007 if(refStart<0){ 1008 readStart=0-refStart; 1009 score+=POINTS_NOREF*readStart; 1010 norefs+=readStart; 1011 } 1012 if(refStop>ref.length){ 1013 int dif=(refStop-ref.length); 1014 readStop-=dif; 1015 score+=POINTS_NOREF*dif; 1016 norefs+=dif; 1017 } 1018 1019 for(int i=readStart; i<readStop; i++){ 1020 byte c=read[i]; 1021 byte r=ref[refStart+i]; 1022 1023 if(c==r && c!='N'){ 1024 if(mode==MODE_MS){ 1025 timeInMode++; 1026 score+=POINTS_MATCH2; 1027 }else{ 1028 timeInMode=0; 1029 score+=POINTS_MATCH; 1030 } 1031 mode=MODE_MS; 1032 }else if(c<0 || c=='N'){ 1033 score+=POINTS_NOCALL; 1034 semiperfect=false; 1035 }else if(r<0 || r=='N'){ 1036 score+=POINTS_NOREF; 1037 norefs++; 1038 }else{ 1039 if(mode==MODE_SUB){timeInMode++;} 1040 else{timeInMode=0;} 1041 1042 score+=(POINTS_SUB_ARRAY[timeInMode+1]); 1043 mode=MODE_SUB; 1044 semiperfect=false; 1045 } 1046 } 1047 1048 return score; 1049 } 1050 1051 @Override 1052 public final byte[] genMatchNoIndels(byte[] read, byte[] ref, final int refStart){ 1053 if(read==null || ref==null){return null;} 1054 1055 final byte[] match=new byte[read.length]; 1056 1057 for(int i=0, j=refStart; i<read.length; i++, j++){ 1058 byte c=read[i]; 1059 byte r=(j<0 || j>=ref.length) ? (byte)'N' : ref[j]; 1060 1061 if(c=='N' || r=='N'){match[i]='N';} 1062 else if(c==r){match[i]='m';} 1063 else{match[i]='S';} 1064 1065 } 1066 1067 return match; 1068 } 1069 1070 @Override 1071 public final int scoreNoIndels(byte[] read, byte[] ref, byte[] baseScores, final int refStart){ 1072 return scoreNoIndels(read, ref, baseScores, refStart, null); 1073 } 1074 @Override 1075 public final int scoreNoIndels(byte[] read, byte[] ref, byte[] baseScores, final int refStart, SiteScore ss){ 1076 int score=0; 1077 int mode=-1; 1078 int timeInMode=0; 1079 int norefs=0; 1080 1081 //This block handles cases where the read runs outside the reference 1082 //Of course, padding the reference with 'N' would be better, but... 1083 int readStart=0; 1084 int readStop=read.length; 1085 final int refStop=refStart+read.length; 1086 boolean semiperfect=true; 1087 1088 if(refStart<0){ 1089 readStart=0-refStart; 1090 score+=POINTS_NOREF*readStart; 1091 norefs+=readStart; 1092 } 1093 if(refStop>ref.length){ 1094 int dif=(refStop-ref.length); 1095 readStop-=dif; 1096 score+=POINTS_NOREF*dif; 1097 norefs+=dif; 1098 } 1099 1100 for(int i=readStart; i<readStop; i++){ 1101 byte c=read[i]; 1102 byte r=ref[refStart+i]; 1103 1104 if(c==r && c!='N'){ 1105 if(mode==MODE_MS){ 1106 timeInMode++; 1107 score+=POINTS_MATCH2; 1108 }else{ 1109 timeInMode=0; 1110 score+=POINTS_MATCH; 1111 } 1112 score+=baseScores[i]; 1113 mode=MODE_MS; 1114 }else if(c<0 || c=='N'){ 1115 score+=POINTS_NOCALL; 1116 semiperfect=false; 1117 }else if(r<0 || r=='N'){ 1118 score+=POINTS_NOREF; 1119 norefs++; 1120 }else{ 1121 if(mode==MODE_SUB){timeInMode++;} 1122 else{timeInMode=0;} 1123 1124 score+=(POINTS_SUB_ARRAY[timeInMode+1]); 1125 mode=MODE_SUB; 1126 semiperfect=false; 1127 } 1128 } 1129 1130 return score; 1131 } 1132 1133 @Override 1134 public final int scoreNoIndelsAndMakeMatchString(byte[] read, byte[] ref, byte[] baseScores, final int refStart, byte[][] matchReturn){ 1135 int score=0; 1136 int mode=-1; 1137 int timeInMode=0; 1138 1139 assert(refStart<=ref.length) : refStart+", "+ref.length; 1140 1141 //This block handles cases where the read runs outside the reference 1142 //Of course, padding the reference with 'N' would be better, but... 1143 int readStart=0; 1144 int readStop=read.length; 1145 final int refStop=refStart+read.length; 1146 if(refStart<0 || refStop>ref.length){return -99999;} 1147 if(refStart<0){ 1148 readStart=0-refStart; 1149 score+=POINTS_NOREF*readStart; 1150 } 1151 if(refStop>ref.length){ 1152 int dif=(refStop-ref.length); 1153 System.err.println(new String(read)+"\ndif="+dif+", ref.length="+ref.length+", refStop="+refStop); 1154 readStop-=dif; 1155 score+=POINTS_NOREF*dif; 1156 } 1157 assert(refStart+readStop<=ref.length) : "readStart="+readStart+", readStop="+readStop+ 1158 ", refStart="+refStart+", refStop="+refStop+", ref.length="+ref.length+", read.length="+read.length; 1159 1160 assert(matchReturn!=null); 1161 assert(matchReturn.length==1); 1162 if(matchReturn[0]==null || matchReturn[0].length!=read.length){ 1163 assert(matchReturn[0]==null || matchReturn[0].length<read.length) : matchReturn[0].length+"!="+read.length; 1164 matchReturn[0]=new byte[read.length]; 1165 } 1166 final byte[] match=matchReturn[0]; 1167 1168 for(int i=readStart; i<readStop; i++){ 1169 byte c=read[i]; 1170 byte r=ref[refStart+i]; 1171 1172 assert(r!='.' && c!='.'); 1173 1174 if(c==r && c!='N'){ 1175 if(mode==MODE_MS){ 1176 timeInMode++; 1177 score+=POINTS_MATCH2; 1178 }else{ 1179 timeInMode=0; 1180 score+=POINTS_MATCH; 1181 } 1182 score+=baseScores[i]; 1183 match[i]='m'; 1184 mode=MODE_MS; 1185 }else if(c<0 || c=='N'){ 1186 score+=POINTS_NOCALL; 1187 match[i]='N'; 1188 }else if(r<0 || r=='N'){ 1189 score+=POINTS_NOREF; 1190 match[i]='N'; 1191 }else{ 1192 match[i]='S'; 1193 if(mode==MODE_SUB){timeInMode++;} 1194 else{timeInMode=0;} 1195 1196 score+=(POINTS_SUB_ARRAY[timeInMode+1]); 1197 mode=MODE_SUB; 1198 } 1199 } 1200 1201 return score; 1202 } 1203 1204 @Override 1205 public final int scoreNoIndelsAndMakeMatchString(byte[] read, byte[] ref, final int refStart, byte[][] matchReturn){ 1206 int score=0; 1207 int mode=-1; 1208 int timeInMode=0; 1209 1210 assert(refStart<=ref.length) : refStart+", "+ref.length; 1211 1212 //This block handles cases where the read runs outside the reference 1213 //Of course, padding the reference with 'N' would be better, but... 1214 int readStart=0; 1215 int readStop=read.length; 1216 final int refStop=refStart+read.length; 1217 if(refStart<0 || refStop>ref.length){return -99999;} 1218 if(refStart<0){ 1219 readStart=0-refStart; 1220 score+=POINTS_NOREF*readStart; 1221 } 1222 if(refStop>ref.length){ 1223 int dif=(refStop-ref.length); 1224 System.err.println(new String(read)+"\ndif="+dif+", ref.length="+ref.length+", refStop="+refStop); 1225 readStop-=dif; 1226 score+=POINTS_NOREF*dif; 1227 } 1228 assert(refStart+readStop<=ref.length) : "readStart="+readStart+", readStop="+readStop+ 1229 ", refStart="+refStart+", refStop="+refStop+", ref.length="+ref.length+", read.length="+read.length; 1230 1231 assert(matchReturn!=null); 1232 assert(matchReturn.length==1); 1233 if(matchReturn[0]==null || matchReturn[0].length!=read.length){ 1234 assert(matchReturn[0]==null || matchReturn[0].length<read.length) : matchReturn[0].length+"!="+read.length; 1235 matchReturn[0]=new byte[read.length]; 1236 } 1237 final byte[] match=matchReturn[0]; 1238 1239 for(int i=readStart; i<readStop; i++){ 1240 byte c=read[i]; 1241 byte r=ref[refStart+i]; 1242 1243 assert(r!='.' && c!='.'); 1244 1245 if(c==r && c!='N'){ 1246 if(mode==MODE_MS){ 1247 timeInMode++; 1248 score+=POINTS_MATCH2; 1249 }else{ 1250 timeInMode=0; 1251 score+=POINTS_MATCH; 1252 } 1253 match[i]='m'; 1254 mode=MODE_MS; 1255 }else if(c<0 || c=='N'){ 1256 score+=POINTS_NOCALL; 1257 match[i]='N'; 1258 }else if(r<0 || r=='N'){ 1259 score+=POINTS_NOREF; 1260 match[i]='N'; 1261 }else{ 1262 match[i]='S'; 1263 if(mode==MODE_SUB){timeInMode++;} 1264 else{timeInMode=0;} 1265 1266 if(AFFINE_ARRAYS){ 1267 score+=(POINTS_SUB_ARRAY[timeInMode+1]); 1268 }else{ 1269 if(timeInMode==0){score+=POINTS_SUB;} 1270 else if(timeInMode<LIMIT_FOR_COST_3){score+=POINTS_SUB2;} 1271 else{score+=POINTS_SUB3;} 1272 } 1273 mode=MODE_SUB; 1274 } 1275 } 1276 1277 return score; 1278 } 1279 1280 @Override 1281 public final int maxQuality(int numBases){ 1282 return POINTS_MATCH+(numBases-1)*(POINTS_MATCH2); 1283 } 1284 1285 @Override 1286 public final int maxQuality(byte[] baseScores){ 1287 return POINTS_MATCH+(baseScores.length-1)*(POINTS_MATCH2)+Tools.sumInt(baseScores); 1288 } 1289 1290 @Override 1291 public final int maxImperfectScore(int numBases){ 1292 int maxQ=maxQuality(numBases); 1293 int maxI=maxQ+Tools.min(POINTS_DEL, POINTS_INS-POINTS_MATCH2); 1294 assert(maxI<(maxQ-(POINTS_MATCH2+POINTS_MATCH2)+(POINTS_MATCH+POINTS_SUB))); 1295 return maxI; 1296 } 1297 1298 @Override 1299 public final int maxImperfectScore(byte[] baseScores){ 1300 int maxQ=maxQuality(baseScores); 1301 int maxI=maxQ+Tools.min(POINTS_DEL, POINTS_INS-POINTS_MATCH2); 1302 assert(maxI<(maxQ-(POINTS_MATCH2+POINTS_MATCH2)+(POINTS_MATCH+POINTS_SUB))); 1303 return maxI; 1304 } 1305 1306 @Override 1307 public int calcDelScore(int len, boolean approximateGaps){ 1308 if(len<=0){return 0;} 1309 int score=POINTS_DEL; 1310 1311 if(approximateGaps && len>MINGAP){ 1312 int rem=len%GAPLEN; 1313 int div=(len-GAPBUFFER2)/GAPLEN; 1314 score+=(div*POINTS_GAP); 1315 assert(rem+GAPBUFFER2<len); 1316 len=rem+GAPBUFFER2; 1317 assert(len>LIMIT_FOR_COST_4); //and probably LIMIT_FOR_COST_5 1318 } 1319 1320 if(len>LIMIT_FOR_COST_5){ 1321 score+=((len-LIMIT_FOR_COST_5+MASK5)/TIMESLIP)*POINTS_DEL5; 1322 len=LIMIT_FOR_COST_5; 1323 } 1324 if(len>LIMIT_FOR_COST_4){ 1325 score+=(len-LIMIT_FOR_COST_4)*POINTS_DEL4; 1326 len=LIMIT_FOR_COST_4; 1327 } 1328 if(len>LIMIT_FOR_COST_3){ 1329 score+=(len-LIMIT_FOR_COST_3)*POINTS_DEL3; 1330 len=LIMIT_FOR_COST_3; 1331 } 1332 if(len>1){ 1333 score+=(len-1)*POINTS_DEL2; 1334 } 1335 return score; 1336 } 1337 1338 private static int calcDelScoreOffset(int len){ 1339 if(len<=0){return 0;} 1340 int score=POINTSoff_DEL; 1341 1342 if(len>LIMIT_FOR_COST_5){ 1343 score+=((len-LIMIT_FOR_COST_5+MASK5)/TIMESLIP)*POINTSoff_DEL5; 1344 len=LIMIT_FOR_COST_5; 1345 } 1346 if(len>LIMIT_FOR_COST_4){ 1347 score+=(len-LIMIT_FOR_COST_4)*POINTSoff_DEL4; 1348 len=LIMIT_FOR_COST_4; 1349 } 1350 if(len>LIMIT_FOR_COST_3){ 1351 score+=(len-LIMIT_FOR_COST_3)*POINTSoff_DEL3; 1352 len=LIMIT_FOR_COST_3; 1353 } 1354 if(len>1){ 1355 score+=(len-1)*POINTSoff_DEL2; 1356 } 1357 return score; 1358 } 1359 1360 @Override 1361 public int calcInsScore(int len){ 1362 if(len<=0){return 0;} 1363 if(AFFINE_ARRAYS){ 1364 return POINTS_INS_ARRAY_C[len]; 1365 }else{ 1366 int score=POINTS_INS; 1367 1368 if(len>LIMIT_FOR_COST_4){ 1369 score+=(len-LIMIT_FOR_COST_4)*POINTS_INS4; 1370 len=LIMIT_FOR_COST_4; 1371 } 1372 if(len>LIMIT_FOR_COST_3){ 1373 score+=(len-LIMIT_FOR_COST_3)*POINTS_INS3; 1374 len=LIMIT_FOR_COST_3; 1375 } 1376 if(len>1){ 1377 score+=(len-1)*POINTS_INS2; 1378 } 1379 return score; 1380 } 1381 } 1382 1383 private static int calcInsScoreOffset(int len){ 1384 if(len<=0){return 0;} 1385 if(AFFINE_ARRAYS){ 1386 return POINTSoff_INS_ARRAY_C[len]; 1387 }else{ 1388 int score=POINTSoff_INS; 1389 if(len>LIMIT_FOR_COST_4){ 1390 score+=(len-LIMIT_FOR_COST_4)*POINTSoff_INS4; 1391 len=LIMIT_FOR_COST_4; 1392 } 1393 if(len>LIMIT_FOR_COST_3){ 1394 score+=(len-LIMIT_FOR_COST_3)*POINTSoff_INS3; 1395 len=LIMIT_FOR_COST_3; 1396 } 1397 if(len>1){ 1398 score+=(len-1)*POINTSoff_INS2; 1399 } 1400 return score; 1401 } 1402 } 1403 1404 private final int[]packed; 1405 private final byte[] grefbuffer; 1406 private int greflimit=-1; 1407 private int greflimit2=-1; 1408 private int grefRefOrigin=-1; 1409 1410 @Override 1411 /**DO NOT MODIFY*/ 1412 public final byte[] getGrefbuffer(){ 1413 return grefbuffer; 1414 } 1415 1416 public final int[] vertLimit; 1417 public final int[] horizLimit; 1418 1419 @Override 1420 public CharSequence showVertLimit(){ 1421 StringBuilder sb=new StringBuilder(); 1422 for(int i=0; i<=rows; i++){sb.append(vertLimit[i]>>SCOREOFFSET).append(",");} 1423 return sb; 1424 } 1425 1426 @Override 1427 public CharSequence showHorizLimit(){ 1428 StringBuilder sb=new StringBuilder(); 1429 for(int i=0; i<=columns; i++){sb.append(horizLimit[i]>>SCOREOFFSET).append(",");} 1430 return sb; 1431 } 1432 1433 public static float minIdToMinRatio(double minid){ 1434 if(minid>1){minid=minid/100;} 1435 assert(minid>0 && minid<=1) : "Min identity should be between 0 and 1. Values above 1 will be assumed to be percent and divided by 100."; 1436 double matchdif=POINTS_MATCH-POINTS_MATCH2; 1437 double match=POINTS_MATCH2; 1438 double sub=-POINTS_MATCH2+0.5*(matchdif+POINTS_SUB)+0.5*POINTS_SUB2; 1439 double del=0.1*(matchdif+POINTS_DEL)+0.2*POINTS_DEL2+0.4*POINTS_DEL3+0.3*POINTS_DEL4; 1440 double ins=-POINTS_MATCH2+0.4*(matchdif+POINTS_INS)+0.3*(POINTS_INS2)+0.3*(POINTS_INS3); 1441 double badAvg=.7*sub+.2*del+.1*ins; 1442 double badFraction=1-minid; 1443 double minratio=(match+badFraction*badAvg)/match; 1444 assert(minratio<=1); 1445 minratio=Tools.max(0.1, minratio); 1446 return (float)minratio; 1447 } 1448 1449 public static final int TIMEBITS=11; 1450 public static final int SCOREBITS=32-TIMEBITS; 1451 public static final int MAX_TIME=((1<<TIMEBITS)-1); 1452 public static final int MAX_SCORE=((1<<(SCOREBITS-1))-1)-2000; 1453 public static final int MIN_SCORE=0-MAX_SCORE; //Keeps it 1 point above "BAD". 1454 1455 public static final int SCOREOFFSET=TIMEBITS; 1456 1457 public static final int TIMEMASK=~((-1)<<TIMEBITS); 1458 public static final int SCOREMASK=(~((-1)<<SCOREBITS))<<SCOREOFFSET; 1459 1460 public static final int POINTS_NOREF=0; 1461 public static final int POINTS_NOCALL=0; 1462 public static final int POINTS_MATCH=70; 1463 public static final int POINTS_MATCH2=100; //Note: Changing to 90 substantially reduces false positives 1464 public static final int POINTS_COMPATIBLE=50; 1465 public static final int POINTS_SUB=-127; 1466 public static final int POINTS_SUBR=-147; //increased penalty if prior match streak was at most 1 1467 public static final int POINTS_SUB2=-51; 1468 public static final int POINTS_SUB3=-25; 1469 public static final int POINTS_MATCHSUB=-10; 1470 public static final int POINTS_INS=-395; 1471 public static final int POINTS_INS2=-39; 1472 public static final int POINTS_INS3=-23; 1473 public static final int POINTS_INS4=-8; 1474 public static final int POINTS_DEL=-472; 1475 public static final int POINTS_DEL2=-33; 1476 public static final int POINTS_DEL3=-9; 1477 public static final int POINTS_DEL4=-1; 1478 public static final int POINTS_DEL5=-1; 1479 public static final int POINTS_DEL_REF_N=-10; 1480 public static final int POINTS_GAP=0-GAPCOST; 1481 1482 public static final int TIMESLIP=4; 1483 public static final int MASK5=TIMESLIP-1; 1484 static{assert(Integer.bitCount(TIMESLIP)==1);} 1485 1486 private static final int BARRIER_I1=2; 1487 private static final int BARRIER_D1=3; 1488 1489 public static final int LIMIT_FOR_COST_3=5; 1490 public static final int LIMIT_FOR_COST_4=20; 1491 public static final int LIMIT_FOR_COST_5=80; 1492 1493 public static final int BAD=MIN_SCORE-1; 1494 1495 public static final int POINTSoff_NOREF=(POINTS_NOREF<<SCOREOFFSET); 1496 public static final int POINTSoff_NOCALL=(POINTS_NOCALL<<SCOREOFFSET); 1497 public static final int POINTSoff_MATCH=(POINTS_MATCH<<SCOREOFFSET); 1498 public static final int POINTSoff_MATCH2=(POINTS_MATCH2<<SCOREOFFSET); 1499 public static final int POINTSoff_COMPATIBLE=(POINTS_COMPATIBLE<<SCOREOFFSET); 1500 public static final int POINTSoff_SUB=(POINTS_SUB<<SCOREOFFSET); 1501 public static final int POINTSoff_SUBR=(POINTS_SUBR<<SCOREOFFSET); 1502 public static final int POINTSoff_SUB2=(POINTS_SUB2<<SCOREOFFSET); 1503 public static final int POINTSoff_SUB3=(POINTS_SUB3<<SCOREOFFSET); 1504 public static final int POINTSoff_MATCHSUB=(POINTS_MATCHSUB<<SCOREOFFSET); 1505 public static final int POINTSoff_INS=(POINTS_INS<<SCOREOFFSET); 1506 public static final int POINTSoff_INS2=(POINTS_INS2<<SCOREOFFSET); 1507 public static final int POINTSoff_INS3=(POINTS_INS3<<SCOREOFFSET); 1508 public static final int POINTSoff_INS4=(POINTS_INS4<<SCOREOFFSET); 1509 public static final int POINTSoff_DEL=(POINTS_DEL<<SCOREOFFSET); 1510 public static final int POINTSoff_DEL2=(POINTS_DEL2<<SCOREOFFSET); 1511 public static final int POINTSoff_DEL3=(POINTS_DEL3<<SCOREOFFSET); 1512 public static final int POINTSoff_DEL4=(POINTS_DEL4<<SCOREOFFSET); 1513 public static final int POINTSoff_DEL5=(POINTS_DEL5<<SCOREOFFSET); 1514 public static final int POINTSoff_GAP=(POINTS_GAP<<SCOREOFFSET); 1515 public static final int POINTSoff_DEL_REF_N=(POINTS_DEL_REF_N<<SCOREOFFSET); 1516 public static final int BADoff=(BAD<<SCOREOFFSET); 1517 public static final int MAXoff_SCORE=MAX_SCORE<<SCOREOFFSET; 1518 public static final int MINoff_SCORE=MIN_SCORE<<SCOREOFFSET; 1519 1520 public static final boolean AFFINE_ARRAYS=true; 1521 public static final int[] POINTS_INS_ARRAY; 1522 public static final int[] POINTSoff_INS_ARRAY; 1523 public static final int[] POINTS_INS_ARRAY_C; 1524 public static final int[] POINTSoff_INS_ARRAY_C; 1525 1526 public static final int[] POINTS_SUB_ARRAY; 1527 public static final int[] POINTSoff_SUB_ARRAY; 1528 public static final int[] POINTS_SUB_ARRAY_C; 1529 public static final int[] POINTSoff_SUB_ARRAY_C; 1530 1531 static{ 1532 POINTS_INS_ARRAY=new int[604]; 1533 POINTSoff_INS_ARRAY=new int[604]; 1534 POINTS_INS_ARRAY_C=new int[604]; 1535 POINTSoff_INS_ARRAY_C=new int[604]; 1536 1537 for(int i=1; i<POINTS_INS_ARRAY.length; i++){ 1538 int pts, ptsoff; 1539 if(i>LIMIT_FOR_COST_4){ 1540 pts=POINTS_INS4; 1541 ptsoff=POINTSoff_INS4; 1542 }else if(i>LIMIT_FOR_COST_3){ 1543 pts=POINTS_INS3; 1544 ptsoff=POINTSoff_INS3; 1545 }else if(i>1){ 1546 pts=POINTS_INS2; 1547 ptsoff=POINTSoff_INS2; 1548 }else{ 1549 pts=POINTS_INS; 1550 ptsoff=POINTSoff_INS; 1551 } 1552 POINTS_INS_ARRAY[i]=pts; 1553 POINTSoff_INS_ARRAY[i]=ptsoff; 1554 POINTS_INS_ARRAY_C[i]=Tools.max(MIN_SCORE, pts+POINTS_INS_ARRAY_C[i-1]); 1555 POINTSoff_INS_ARRAY_C[i]=Tools.max(MINoff_SCORE, ptsoff+POINTSoff_INS_ARRAY_C[i-1]); 1556 } 1557 1558 POINTS_SUB_ARRAY=new int[604]; 1559 POINTSoff_SUB_ARRAY=new int[604]; 1560 POINTS_SUB_ARRAY_C=new int[604]; 1561 POINTSoff_SUB_ARRAY_C=new int[604]; 1562 1563 for(int i=1; i<POINTS_SUB_ARRAY.length; i++){ 1564 int pts, ptsoff; 1565 if(i>LIMIT_FOR_COST_3){ 1566 pts=POINTS_SUB3; 1567 ptsoff=POINTSoff_SUB3; 1568 }else if(i>1){ 1569 pts=POINTS_SUB2; 1570 ptsoff=POINTSoff_SUB2; 1571 }else{ 1572 pts=POINTS_SUB; 1573 ptsoff=POINTSoff_SUB; 1574 } 1575 POINTS_SUB_ARRAY[i]=pts; 1576 POINTSoff_SUB_ARRAY[i]=ptsoff; 1577 POINTS_SUB_ARRAY_C[i]=Tools.max(MIN_SCORE, pts+POINTS_SUB_ARRAY_C[i-1]); 1578 POINTSoff_SUB_ARRAY_C[i]=Tools.max(MINoff_SCORE, ptsoff+POINTSoff_SUB_ARRAY_C[i-1]); 1579 } 1580 } 1581 1582 @Override 1583 public final int POINTS_NOREF(){return POINTS_NOREF;} 1584 @Override 1585 public final int POINTS_NOCALL(){return POINTS_NOCALL;} 1586 @Override 1587 public final int POINTS_MATCH(){return POINTS_MATCH;} 1588 @Override 1589 public final int POINTS_MATCH2(){return POINTS_MATCH2;} 1590 @Override 1591 public final int POINTS_COMPATIBLE(){return POINTS_COMPATIBLE;} 1592 @Override 1593 public final int POINTS_SUB(){return POINTS_SUB;} 1594 @Override 1595 public final int POINTS_SUBR(){return POINTS_SUBR;} 1596 @Override 1597 public final int POINTS_SUB2(){return POINTS_SUB2;} 1598 @Override 1599 public final int POINTS_SUB3(){return POINTS_SUB3;} 1600 @Override 1601 public final int POINTS_MATCHSUB(){return POINTS_MATCHSUB;} 1602 @Override 1603 public final int POINTS_INS(){return POINTS_INS;} 1604 @Override 1605 public final int POINTS_INS2(){return POINTS_INS2;} 1606 @Override 1607 public final int POINTS_INS3(){return POINTS_INS3;} 1608 @Override 1609 public final int POINTS_INS4(){return POINTS_INS4;} 1610 @Override 1611 public final int POINTS_DEL(){return POINTS_DEL;} 1612 @Override 1613 public final int POINTS_DEL2(){return POINTS_DEL2;} 1614 @Override 1615 public final int POINTS_DEL3(){return POINTS_DEL3;} 1616 @Override 1617 public final int POINTS_DEL4(){return POINTS_DEL4;} 1618 @Override 1619 public final int POINTS_DEL5(){return POINTS_DEL5;} 1620 @Override 1621 public final int POINTS_DEL_REF_N(){return POINTS_DEL_REF_N;} 1622 @Override 1623 public final int POINTS_GAP(){return POINTS_GAP;} 1624 1625 @Override 1626 public final int TIMESLIP(){return TIMESLIP;} 1627 @Override 1628 public final int MASK5(){return MASK5;} 1629 @Override 1630 public final int SCOREOFFSET(){return SCOREOFFSET();} 1631 1632 @Override 1633 final int BARRIER_I1(){return BARRIER_I1;} 1634 @Override 1635 final int BARRIER_D1(){return BARRIER_D1;} 1636 1637 @Override 1638 public final int LIMIT_FOR_COST_3(){return LIMIT_FOR_COST_3;} 1639 @Override 1640 public final int LIMIT_FOR_COST_4(){return LIMIT_FOR_COST_4;} 1641 @Override 1642 public final int LIMIT_FOR_COST_5(){return LIMIT_FOR_COST_5;} 1643 1644 @Override 1645 public final int BAD(){return BAD;} 1646 1647 private int rows; 1648 private int columns; 1649 1650 } 1651