jpayne@68: package aligner; jpayne@68: jpayne@68: import java.util.Arrays; jpayne@68: jpayne@68: import shared.KillSwitch; jpayne@68: import shared.Tools; jpayne@68: jpayne@68: /** jpayne@68: * Based on MSA9PBA, but reduced to a single matrix. */ jpayne@68: public final class SingleStateAlignerPacBioAdapter { jpayne@68: jpayne@68: jpayne@68: public SingleStateAlignerPacBioAdapter(int maxRows_, int maxColumns_, int qlen){ jpayne@68: // assert(maxColumns_>=200); jpayne@68: // assert(maxRows_>=200); jpayne@68: maxRows=maxRows_; jpayne@68: maxColumns=maxColumns_; jpayne@68: packed=new int[maxRows+1][maxColumns+1]; jpayne@68: jpayne@68: insScoreArray=KillSwitch.allocInt1D(5); jpayne@68: delScoreArray=KillSwitch.allocInt1D(5); jpayne@68: matchScoreArray=KillSwitch.allocInt1D(5); jpayne@68: subScoreArray=KillSwitch.allocInt1D(5); jpayne@68: jpayne@68: Arrays.fill(insScoreArray, POINTSoff_INS|MODE_INS); jpayne@68: Arrays.fill(delScoreArray, POINTSoff_DEL|MODE_DEL); jpayne@68: Arrays.fill(matchScoreArray, POINTSoff_MATCH|MODE_MATCH); jpayne@68: Arrays.fill(subScoreArray, POINTSoff_SUB|MODE_SUB); jpayne@68: jpayne@68: insScoreArray[MODE_INS]=POINTSoff_INS2|MODE_INS; jpayne@68: delScoreArray[MODE_DEL]=POINTSoff_DEL2|MODE_DEL; jpayne@68: matchScoreArray[MODE_MATCH]=POINTSoff_MATCH2|MODE_MATCH; jpayne@68: subScoreArray[MODE_SUB]=POINTSoff_SUB2|MODE_SUB; jpayne@68: jpayne@68: vertLimit=new int[maxRows+1]; jpayne@68: horizLimit=new int[maxColumns+1]; jpayne@68: Arrays.fill(vertLimit, BADoff); jpayne@68: Arrays.fill(horizLimit, BADoff); jpayne@68: jpayne@68: // for(int i=0; i0){ jpayne@68: packed[0][i]|=calcDelScoreOffset(qbases); //Forces consumption of query jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** return new int[] {rows, maxCol, maxState, maxScore, maxStart}; jpayne@68: * Will not fill areas that cannot match minScore */ jpayne@68: public final int[] fillLimited(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int minScore){ jpayne@68: return fillLimitedX(read, ref, refStartLoc, refEndLoc, minScore); jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** return new int[] {rows, maxCol, maxState, maxScore, maxStart}; jpayne@68: * Will not fill areas that cannot match minScore */ jpayne@68: private final int[] fillLimitedX(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int minScore){ jpayne@68: return fillUnlimited(read, ref, refStartLoc, refEndLoc, minScore); jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** return new int[] {rows, maxCol, maxState, maxScore, maxStart}; jpayne@68: * Does not require a min score (ie, same as old method) */ jpayne@68: private final int[] fillUnlimited(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, final int minScore){ jpayne@68: rows=read.length; jpayne@68: columns=refEndLoc-refStartLoc+1; jpayne@68: jpayne@68: //temporary, for finding a bug jpayne@68: if(rows>maxRows || columns>maxColumns){ jpayne@68: throw new RuntimeException("rows="+rows+", maxRows="+maxRows+", cols="+columns+", maxCols="+maxColumns+"\n"+new String(read)+"\n"); jpayne@68: } jpayne@68: jpayne@68: assert(rows<=maxRows) : "Check that values are in-bounds before calling this function: "+rows+", "+maxRows; jpayne@68: assert(columns<=maxColumns) : "Check that values are in-bounds before calling this function: "+columns+", "+maxColumns; jpayne@68: jpayne@68: assert(refStartLoc>=0) : "Check that values are in-bounds before calling this function: "+refStartLoc; jpayne@68: assert(refEndLoc=delScore ? diagScore : delScore; jpayne@68: score=score>=insScore ? score : insScore; jpayne@68: jpayne@68: packed[row][col]=score; jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: jpayne@68: int maxCol=-1; jpayne@68: int maxState=-1; jpayne@68: int maxStart=-1; jpayne@68: int maxScore=Integer.MIN_VALUE; jpayne@68: jpayne@68: for(int col=1; col<=columns; col++){ jpayne@68: int x=packed[rows][col]; jpayne@68: if((x&SCOREMASK)>maxScore){ jpayne@68: maxScore=x; jpayne@68: maxCol=col; jpayne@68: maxState=x&MODEMASK; jpayne@68: maxStart=x&STARTMASK; jpayne@68: } jpayne@68: } jpayne@68: maxScore>>=SCOREOFFSET; jpayne@68: jpayne@68: // System.err.println("Returning "+rows+", "+maxCol+", "+maxState+", "+maxScore+"; minScore="+minScore); jpayne@68: return maxScore0 && col>0){ jpayne@68: state=(packed[row][col]&MODEMASK); jpayne@68: if(state==MODE_MATCH){ jpayne@68: col--; jpayne@68: row--; jpayne@68: out[outPos]='m'; jpayne@68: }else if(state==MODE_SUB){ jpayne@68: col--; jpayne@68: row--; jpayne@68: out[outPos]='S'; jpayne@68: }else if(state==MODE_DEL){ jpayne@68: col--; jpayne@68: out[outPos]='D'; jpayne@68: }else if(state==MODE_INS){ jpayne@68: row--; jpayne@68: out[outPos]='I'; jpayne@68: }else{ jpayne@68: assert(false) : state; jpayne@68: } jpayne@68: outPos++; jpayne@68: } jpayne@68: jpayne@68: assert(row==0 || col==0); jpayne@68: if(col!=row){ jpayne@68: while(row>0){ jpayne@68: out[outPos]='X'; jpayne@68: outPos++; jpayne@68: row--; jpayne@68: col--; jpayne@68: } jpayne@68: if(col>0){ jpayne@68: //do nothing jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: //Shrink and reverse the string jpayne@68: byte[] out2=new byte[outPos]; jpayne@68: for(int i=0; i=0 && maxState=0 && maxRow=0 && maxColdifC){ jpayne@68: score+=POINTSoff_NOREF; jpayne@68: difR--; jpayne@68: } jpayne@68: jpayne@68: row+=difR; jpayne@68: col+=difR; jpayne@68: jpayne@68: } jpayne@68: jpayne@68: assert(refStartLoc<=refEndLoc); jpayne@68: assert(row==rows); jpayne@68: jpayne@68: jpayne@68: final int bestRefStop=refStartLoc+col-1; jpayne@68: jpayne@68: while(row>0 && col>0){ jpayne@68: state=(packed[row][col]&MODEMASK); jpayne@68: if(state==MODE_MATCH){ jpayne@68: col--; jpayne@68: row--; jpayne@68: }else if(state==MODE_SUB){ jpayne@68: col--; jpayne@68: row--; jpayne@68: }else if(state==MODE_DEL){ jpayne@68: col--; jpayne@68: }else if(state==MODE_INS){ jpayne@68: row--; jpayne@68: }else{ jpayne@68: assert(false) : state; jpayne@68: } jpayne@68: } jpayne@68: // assert(false) : row+", "+col; jpayne@68: if(row>col){ jpayne@68: col-=row; jpayne@68: } jpayne@68: jpayne@68: final int bestRefStart=refStartLoc+col; jpayne@68: jpayne@68: score>>=SCOREOFFSET; jpayne@68: // System.err.println("t2\t"+score+", "+maxScore+", "+maxStart+", "+bestRefStart); jpayne@68: int[] rvec; jpayne@68: if(bestRefStartrefEndLoc){ //Suggest extra padding in cases of overflow jpayne@68: int padLeft=Tools.max(0, refStartLoc-bestRefStart); jpayne@68: int padRight=Tools.max(0, bestRefStop-refEndLoc); jpayne@68: rvec=new int[] {score, bestRefStart, bestRefStop, padLeft, padRight}; jpayne@68: }else{ jpayne@68: rvec=new int[] {score, bestRefStart, bestRefStop}; jpayne@68: } jpayne@68: return rvec; jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** Will not fill areas that cannot match minScore. jpayne@68: * @return {score, bestRefStart, bestRefStop} */ jpayne@68: public final int[] fillAndScoreLimited(byte[] read, byte[] ref, int refStartLoc, int refEndLoc, int minScore){ jpayne@68: int a=Tools.max(0, refStartLoc); jpayne@68: int b=Tools.min(ref.length-1, refEndLoc); jpayne@68: assert(b>=a); jpayne@68: jpayne@68: if(b-a>=maxColumns){ jpayne@68: System.err.println("Warning: Max alignment columns exceeded; restricting range. "+(b-a+1)+" > "+maxColumns); jpayne@68: assert(false) : refStartLoc+", "+refEndLoc; jpayne@68: b=Tools.min(ref.length-1, a+maxColumns-1); jpayne@68: } jpayne@68: int[] max=fillLimited(read, ref, a, b, minScore); jpayne@68: // return max==null ? null : new int[] {max[3], 0, max[1]}; jpayne@68: jpayne@68: int[] score=(max==null ? null : score(read, ref, a, b, max[0], max[1], max[2]/*, max[3], max[4]*/)); jpayne@68: jpayne@68: return score; jpayne@68: } jpayne@68: jpayne@68: public static final String toString(byte[] ref, int startLoc, int stopLoc){ jpayne@68: StringBuilder sb=new StringBuilder(stopLoc-startLoc+1); jpayne@68: for(int i=startLoc; i<=stopLoc; i++){sb.append((char)ref[i]);} jpayne@68: return sb.toString(); jpayne@68: } jpayne@68: jpayne@68: public static int calcDelScore(int len){ jpayne@68: if(len<=0){return 0;} jpayne@68: int score=POINTS_DEL; jpayne@68: if(len>1){ jpayne@68: score+=(len-1)*POINTS_DEL2; jpayne@68: } jpayne@68: return score; jpayne@68: } jpayne@68: jpayne@68: private static int calcDelScoreOffset(int len){ jpayne@68: if(len<=0){return 0;} jpayne@68: int score=POINTSoff_DEL; jpayne@68: if(len>1){ jpayne@68: score+=(len-1)*POINTSoff_DEL2; jpayne@68: } jpayne@68: return score; jpayne@68: } jpayne@68: jpayne@68: public static int calcInsScore(int len){ jpayne@68: if(len<=0){return 0;} jpayne@68: int score=POINTS_INS; jpayne@68: jpayne@68: if(len>1){ jpayne@68: score+=(len-1)*POINTS_INS2; jpayne@68: } jpayne@68: return score; jpayne@68: } jpayne@68: jpayne@68: private static int calcInsScoreOffset(int len){ jpayne@68: if(len<=0){return 0;} jpayne@68: int score=POINTSoff_INS; jpayne@68: jpayne@68: if(len>1){ jpayne@68: score+=(len-1)*POINTSoff_INS2; jpayne@68: } jpayne@68: return score; jpayne@68: } jpayne@68: jpayne@68: jpayne@68: private final int maxRows; jpayne@68: public final int maxColumns; jpayne@68: jpayne@68: private final int[][] packed; jpayne@68: jpayne@68: private final int[] vertLimit; jpayne@68: private final int[] horizLimit; jpayne@68: jpayne@68: private final int[] insScoreArray; jpayne@68: private final int[] delScoreArray; jpayne@68: private final int[] matchScoreArray; jpayne@68: private final int[] subScoreArray; jpayne@68: jpayne@68: public static final int MODEBITS=3; jpayne@68: public static final int STARTBITS=9; jpayne@68: public static final int LOWBITS=MODEBITS+STARTBITS; jpayne@68: public static final int SCOREBITS=32-STARTBITS; jpayne@68: public static final int MAX_START=((1<