/* @source embaln.c ** ** General routines for alignment. ** Copyright (c) 1999 Alan Bleasby ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public License ** as published by the Free Software Foundation; either version 2 ** of the License, or (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ******************************************************************************/ #include "emboss.h" #include #include #define GAPO 26 #define GAPE 27 #define DIAG 0 #define LEFT 1 #define DOWN 2 /* @func embAlignPathCalc ***************************************************** ** ** Create path matrix for Needleman-Wunsch ** Nucleotides or proteins as needed. ** ** @param [r] a [const char *] first sequence ** @param [r] b [const char *] second sequence ** @param [r] lena [ajint] length of first sequence ** @param [r] lenb [ajint] length of second sequence ** @param [r] gapopen [float] gap opening penalty ** @param [r] gapextend [float] gap extension penalty ** @param [w] path [float *] path matrix ** @param [r] sub [float * const *] substitution matrix from AjPMatrixf ** @param [r] cvt [const AjPSeqCvt] Conversion array for AjPMatrixf ** @param [w] compass [ajint *] Path direction pointer array ** @param [r] show [AjBool] Display path matrix ** ** Optimised to keep a maximum value to avoid looping down or left ** to find the maximum. (il 29/07/99) ** ** @return [void] ******************************************************************************/ void embAlignPathCalc(const char *a, const char *b, ajint lena, ajint lenb, float gapopen, float gapextend, float *path, float * const *sub, const AjPSeqCvt cvt, ajint *compass, AjBool show) { ajint xpos; ajint i; ajint j; float match; float mscore; float fnew; float *maxa; float *maxb; float *oval; ajint *cnt; static AjPStr outstr = NULL; float bx; ajint bv; ajDebug("embAlignPathCalc\n"); /* Create stores for the maximum values in a row or column */ maxa = AJALLOC(lena*sizeof(float)); maxb = AJALLOC(lenb*sizeof(float)); oval = AJALLOC(lena*sizeof(float)); cnt = AJALLOC(lena*sizeof(ajint)); /* First initialise the first column and row */ for(i=0;i-1) { fnew=path[(i-1)*lenb+xpos-2]; fnew-=gapopen; if(maxa[i-1] < fnew) { oval[i-1] = maxa[i-1] = fnew; cnt[i-1] = 0; } ++cnt[i-1]; if( maxa[i-1]+match > mscore) { mscore = maxa[i-1]+match; path[i*lenb+xpos] = mscore; compass[i*lenb+xpos] = 1; /* Score comes from left */ } } /* And then bimble down Y axis */ if(i-2>-1) { fnew = path[(i-2)*lenb+xpos-1]; fnew-=gapopen; if(fnew>maxb[xpos-1]) { maxb[xpos-1]=bx=fnew; bv=0; } ++bv; if(maxb[xpos-1]+match > mscore) { mscore = maxb[xpos-1]+match; path[i*lenb+xpos] = mscore; compass[i*lenb+xpos] = 2; /* Score comes from bottom */ } } maxa[i-1]= oval[i-1] - ((float)cnt[i-1]*gapextend); maxb[xpos-1]= bx - ((float)bv*gapextend); i++; } ++xpos; } if(show) { for(i=lena-1;i>-1;--i) { ajStrDelReuse(&outstr); for(j=0;j 0.) ? result : 0.; compass[i*lenb] = 0; } for(i=0;i 0.) ? result : 0.; compass[j] = 0; } for(j=0;j-1) { fnew=path[(i-1)*lenb+xpos-2]; fnew-=gapopen; if(maxa[i-1] < fnew) { oval[i-1] = maxa[i-1] = fnew; cnt[i-1] = 0; } ++cnt[i-1]; if( maxa[i-1]+match > mscore) { mscore = maxa[i-1]+match; path[i*lenb+xpos] = mscore; compass[i*lenb+xpos] = 1; /* Score comes from left */ } } /* And then bimble down Y axis */ if(i-2>-1) { fnew = path[(i-2)*lenb+xpos-1]; fnew-=gapopen; if(fnew>maxb[xpos-1]) { maxb[xpos-1]=bx=fnew; bv=0; } ++bv; if(maxb[xpos-1]+match > mscore) { mscore = maxb[xpos-1]+match; path[i*lenb+xpos] = mscore; compass[i*lenb+xpos] = 2; /* Score comes from bottom */ } } maxa[i-1]= oval[i-1] - ((float)cnt[i-1]*gapextend); maxb[xpos-1]= bx - ((float)bv*gapextend); result = path[i*lenb+xpos]; if(result < 0.) path[i*lenb+xpos] = 0.; i++; } ++xpos; } if(show) { for(i=lena-1;i>-1;--i) { ajStrDelReuse(&outstr); for(j=0;j-1) for(jm=xpos-2;jm>-1;--jm) { tsc = path[(i-1)*lenb+jm]; pen = (float) -1.0 * (gapopen + ((xpos-jm-2)*gapextend)); tsc += pen + match; if(tsc>mscore) { mscore=tsc; path[i*lenb+xpos] = tsc; compass[i*lenb+xpos] = 1; /* Score comes from left */ } } /* And then bimble down Y axis */ if(i-2>-1) for(im=i-2;im>-1;--im) { tsc = path[im*lenb+xpos-1]; pen = (float) -1.0 * (gapopen + ((i-im-2)*gapextend)); tsc += pen + match; if(tsc>mscore) { mscore=tsc; path[i*lenb+xpos] = tsc; compass[i*lenb+xpos] = 2; /* Score comes from bottom */ } } } /* move along */ if(xpos+1 != lenb) { for(j=xpos+1;j-1) for(jm=j-2;jm>-1;--jm) { tsc = path[(ypos-1)*lenb+jm]; pen = (float) -1.0 * (gapopen + ((j-jm-2)*gapextend)); tsc += pen+match; if(tsc>mscore) { mscore = tsc; path[ypos*lenb+j] = tsc; /* Came from left */ compass[ypos*lenb+j]=1; } } /* Re-bimble down Y */ if(ypos-2>-1) { for(im=ypos-2;im>-1;--im) { tsc = path[im*lenb+j-1]; pen = (float) -1.0 * (gapopen+((ypos-im-2)*gapextend)); tsc += pen+match; if(tsc>mscore) { mscore=tsc; path[ypos*lenb+j]=tsc; compass[ypos*lenb+j]=2; /* from bottom */ } } } } } ++xpos; ++ypos; } if(show) { for(i=lena-1;i>-1;--i) { ajStrDelReuse(&outstr); for(j=0;j=pmax) { pmax = path[(lena-1)*lenb+i]; xpos = i; ypos = lena-1; } for(j=0;jpmax) { pmax=path[j*lenb+lenb-1]; xpos=lenb-1; ypos=j; } p = ajSeqChar(a); q = ajSeqChar(b); wscore = fmatrix[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos])]; /* ajDebug("Match %c %c %f\n",p[ypos],q[xpos],wscore);*/ while(xpos && ypos) { if(!compass[ypos*lenb+xpos]) /* diagonal */ { wscore += fmatrix[ajSeqCvtK(cvt,p[--ypos])] [ajSeqCvtK(cvt,q[--xpos])]; /*ajDebug("Match %c %c %f\n",p[ypos],q[xpos],wscore);*/ } else if(compass[ypos*lenb+xpos]==1) /* Left, gap(s) in vertical */ { score = path[ypos*lenb+xpos]; gapcnt = 0.; ix = xpos-2; match = fmatrix[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos])]; --ypos; t = ix+1; while(1) { bimble = path[ypos*lenb+ix]-gapopen-(gapcnt*gapextend)+match; if(!ix || fabs((double)score-(double)bimble)< errbounds) break; --ix; if(ix<0) ajFatal("NW: Error walking left"); ++gapcnt; } t -= (ajint)gapcnt; wscore += fmatrix[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[t-1])]; wscore -= (gapopen + (gapextend*gapcnt)); xpos = ix; continue; } else if(compass[ypos*lenb+xpos]==2) /* Down, gap(s) in horizontal */ { score=path[ypos*lenb+xpos]; gapcnt=0.; match = fmatrix[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos])]; --xpos; iy=ypos-2; t=iy+1; while(1) { bimble = path[iy*lenb+xpos]-gapopen-(gapcnt*gapextend)+match; if(!iy || fabs((double)score-(double)bimble)< errbounds) break; --iy; if(iy<0) ajFatal("NW: Error walking down"); ++gapcnt; } t -= (ajint)gapcnt; wscore += fmatrix[ajSeqCvtK(cvt,p[t-1])][ajSeqCvtK(cvt,q[xpos])]; wscore -= (gapopen + (gapextend*gapcnt)); ypos = iy; continue; } else ajFatal("Walk Error in NW"); } *start1 = ypos; *start2 = xpos; return wscore; } /* @func embAlignScoreSWMatrix ************************************************ ** ** Walk down a matrix for Smith Waterman. Form aligned strings. ** Nucleotides or proteins as needed. ** ** @param [r] path [const float*] path matrix ** @param [r] compass [const ajint*] Path direction pointer array ** @param [r] gapopen [float] gap opening penalty ** @param [r] gapextend [float] gap extension penalty ** @param [r] a [const AjPSeq] first sequence ** @param [r] b [const AjPSeq] second sequence ** @param [r] lena [ajint] length of first sequence ** @param [r] lenb [ajint] length of second sequence ** @param [r] sub [float * const *] substitution matrix from AjPMatrixf ** @param [r] cvt [const AjPSeqCvt] Conversion array for AjPMatrixf ** @param [w] start1 [ajint *] start of alignment in first sequence ** @param [w] start2 [ajint *] start of alignment in second sequence ** ** @return [float] Score of best matching segment ******************************************************************************/ float embAlignScoreSWMatrix(const float *path, const ajint *compass, float gapopen, float gapextend, const AjPSeq a, const AjPSeq b, ajint lena, ajint lenb, float * const *sub, const AjPSeqCvt cvt, ajint *start1, ajint *start2) { ajint i; ajint j; float pmax; float score; float match; float gapcnt; float bimble; float wscore; ajint ix = 0; ajint iy = 0; ajint t; ajint xpos = 0; ajint ypos = 0; const char *p; const char *q; float errbounds; ajDebug("embAlignScoreSWMatrix\n"); errbounds = gapextend; errbounds = 0.01; /* Get maximum path score and save position */ pmax = (float) (-1*INT_MAX); for(i=0;ipmax) { pmax=path[i*lenb+j]; xpos=j; ypos=i; } p = ajSeqChar(a); q = ajSeqChar(b); wscore = sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos])]; while(xpos && ypos) { if(!compass[ypos*lenb+xpos]) /* diagonal */ { if(path[(ypos-1)*lenb+xpos-1]<=0.) { *start1 = ypos; *start2 = xpos; ajDebug("break: trace done at ypos:%d xpos:%d\n", ypos, xpos); break; } wscore += sub[ajSeqCvtK(cvt,p[--ypos])][ajSeqCvtK(cvt,q[--xpos])]; continue; } else if(compass[ypos*lenb+xpos]==1) /* Left, gap(s) in vertical */ { score = path[ypos*lenb+xpos]; gapcnt = 0.; ix = xpos-2; match = sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos])]; --ypos; t = ix+1; while(1) { bimble =path[ypos*lenb+ix]-gapopen-(gapcnt*gapextend)+match; if(!ix || fabs((double)score-(double)bimble) 0) *start1 = ypos; if(xpos > 0) *start2 = xpos; ajDebug("ScoreSW ypos(start1):%d xpos(start2):%d iy:%d ix:%d\n", ypos, xpos, iy, ix); return wscore; } /* @func embAlignWalkSWMatrix ************************************************* ** ** Walk down a matrix for Smith Waterman. Form aligned strings. ** Nucleotides or proteins as needed. ** ** @param [r] path [const float*] path matrix ** @param [r] compass [const ajint*] Path direction pointer array ** @param [r] gapopen [float] gap opening penalty ** @param [r] gapextend [float] gap extension penalty ** @param [r] a [const AjPSeq] first sequence ** @param [r] b [const AjPSeq] second sequence ** @param [w] m [AjPStr *] alignment for first sequence ** @param [w] n [AjPStr *] alignment for second sequence ** @param [r] lena [ajint] length of first sequence ** @param [r] lenb [ajint] length of second sequence ** @param [r] sub [float * const *] substitution matrix from AjPMatrixf ** @param [r] cvt [const AjPSeqCvt] Conversion array for AjPMatrixf ** @param [w] start1 [ajint *] start of alignment in first sequence ** @param [w] start2 [ajint *] start of alignment in second sequence ** ** @return [void] ******************************************************************************/ void embAlignWalkSWMatrix(const float *path, const ajint *compass, float gapopen, float gapextend, const AjPSeq a, const AjPSeq b, AjPStr *m, AjPStr *n, ajint lena, ajint lenb, float * const *sub, const AjPSeqCvt cvt, ajint *start1, ajint *start2) { ajint i; ajint j; float pmax; float score; float match; float gapcnt; float bimble; ajint ix; ajint iy; ajint t; ajint xpos = 0; ajint ypos = 0; const char *p; const char *q; float ic; float errbounds; ajDebug("embAlignWalkSWMatrix\n"); errbounds = gapextend; errbounds = 0.01; /* Get maximum path score and save position */ pmax = (float) (-1*INT_MAX); for(i=0;ipmax) { pmax = path[i*lenb+j]; xpos = j; ypos = i; } p = ajSeqChar(a); q = ajSeqChar(b); ajStrAssK(m,p[ypos]); ajStrAssK(n,q[xpos]); while(xpos && ypos) { if(!compass[ypos*lenb+xpos]) /* diagonal */ { if(path[(ypos-1)*lenb+xpos-1]<=0.) break; ajStrInsertK(m,0,p[--ypos]); ajStrInsertK(n,0,q[--xpos]); continue; } else if(compass[ypos*lenb+xpos]==1) /* Left, gap(s) in vertical */ { score = path[ypos*lenb+xpos]; gapcnt = 0.; ix = xpos-2; match = sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos])]; --ypos; t=ix+1; while(1) { bimble = path[ypos*lenb+ix]-gapopen-(gapcnt*gapextend)+match; if(!ix || fabs((double)score-(double)bimble)=pmax) { pmax = path[(lena-1)*lenb+i]; xpos = i; ypos = lena-1; } for(j=0;jpmax) { pmax = path[j*lenb+lenb-1]; xpos = lenb-1; ypos = j; } p = ajSeqChar(a); q = ajSeqChar(b); ajStrInsertK(m,0,p[ypos]); ajStrInsertK(n,0,q[xpos]); while(xpos && ypos) { if(!compass[ypos*lenb+xpos]) /* diagonal */ { ajDebug("match %5d %5d '%c' '%c'\n", ypos, xpos, p[ypos-1], q[xpos-1]); ajStrInsertK(m,0,p[--ypos]); ajStrInsertK(n,0,q[--xpos]); continue; } else if(compass[ypos*lenb+xpos]==1) /* Left, gap(s) in vertical */ { score = path[ypos*lenb+xpos]; gapcnt = 0.; ix = xpos-2; match = sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos])]; --ypos; t = ix+1; while(1) { bimble = path[ypos*lenb+ix]-gapopen-(gapcnt*gapextend)+match; if(!ix || fabs((double)score-(double)bimble)< errbounds) break; --ix; if(ix<0) ajFatal("NW: Error walking left"); ++gapcnt; } for(ic=-1;icstart2) { for(i=0;istart1) { for(i=0;i0.0) ajStrAppC(&fm,":"); else ajStrAppC(&fm," "); } } /* Set pointers to sequence remainders */ for(i=0,apos=start1,bpos=start2;iblen) { ajStrAppC(&fa,&a[apos]); for(i=0;ialen) { ajStrAppC(&fb,&b[bpos]); for(i=0;i0.0) ajStrAppC(&fm,":"); else ajStrAppC(&fm," "); } } /* Get start residues */ p = ajStrStr(fa); q = ajStrStr(fb); acnt = begina+start1; bcnt = beginb+start2; len = ajStrLen(fa); pos = 0; if(mark) r=ajStrStr(fm); /* Add header stuff here */ ajFmtPrintF(outf,"Local: %s vs %s\n",namea,nameb); ajFmtPrintF(outf,"Score: %.2f\n\n",score); while(pos 0) { fnew = path[(i-1)*width+xpos-1]; fnew -= gapopen; if(maxa[i-1] < fnew) maxa[i-1] = fnew; else maxa[i-1] -= gapextend; } if(i>1) { if(xpos < width-1) { fnew=path[(i-2)*width+xpos+1]; fnew-=gapopen; if(fnew>maxb[i+xpos-1]) maxb[i+xpos-1] = fnew; else maxb[i+xpos-1] -= gapextend; } else maxb[i+xpos-1] -= gapextend; } /* Now parade back along X axis */ if( maxa[i-1]+match > mscore) { mscore = maxa[i-1]+match; path[i*width+xpos] = mscore; compass[i*width+xpos] = 1; /* Score comes from left */ ajDebug("CalcFast initd [%d] path: %.2f compass: %d\n", i*width+xpos, path[i*width+xpos], compass[i*width+xpos]); } /* And then bimble down Y axis */ if(maxb[i+xpos-1]+match > mscore) { mscore = maxb[i+xpos-1]+match; path[i*width+xpos] = mscore; compass[i*width+xpos] = 2; /* Score comes from bottom */ ajDebug("CalcFast inite [%d] path: %.2f compass: %d\n", i*width+xpos, path[i*width+xpos], compass[i*width+xpos]); } xpos++; } ++i; } max = -1000.0; if(show) { for(i=0;i max) max = path[i*width+j]; } ajDebug("%S\n", outstr); } } AJFREE(maxa); AJFREE(maxb); ajStrDelReuse(&outstr); return; } /* @func embAlignScoreSWMatrixFast ******************************************** ** ** Walk down a matrix for Smith Waterman. Form aligned strings. ** Nucleotides or proteins as needed. ** ** @param [r] path [const float*] path matrix ** @param [r] compass [const ajint*] Path direction pointer array ** @param [r] gapopen [float] gap opening penalty ** @param [r] gapextend [float] gap extension penalty ** @param [r] a [const AjPSeq] first sequence ** @param [r] b [const AjPSeq] second sequence ** @param [r] lena [ajint] length of first sequence ** @param [r] lenb [ajint] length of second sequence ** @param [r] sub [float * const *] substitution matrix from AjPMatrixf ** @param [r] cvt [const AjPSeqCvt] Conversion array for AjPMatrixf ** @param [w] start1 [ajint *] start of alignment in first sequence ** @param [w] start2 [ajint *] start of alignment in second sequence ** @param [r] pathwidth [ajint] width of path matrix ** ** @return [float] Score of best matching segment ******************************************************************************/ float embAlignScoreSWMatrixFast(const float *path, const ajint *compass, float gapopen, float gapextend, const AjPSeq a, const AjPSeq b, ajint lena, ajint lenb, float * const *sub, const AjPSeqCvt cvt, ajint *start1, ajint *start2, ajint pathwidth) { ajint i; ajint j; float pmax = -1000.0; float score = 0.; float wscore = 0.; float match = 0.; float gapcnt = 0.; float bimble = 0.; ajint ix; ajint iy; ajint t; ajint xpos = 0; ajint xpos2 = 0; ajint ypos = 0; const char *p; const char *q; ajint width; ajDebug("embAlignScoreSWMatrixFast\n"); width = pathwidth; if(lena < width) width = lena; if(lenb < width) width = lenb; /* ajDebug extra */ ajDebug("SeqA '%s' %d %d\n", ajSeqName(a), ajSeqLen(a), lena); ajDebug("SeqB '%s' %d %d\n", ajSeqName(b), ajSeqLen(b), lenb); ajDebug("start1: %d start2: %d width; %d\n", *start1, *start2, width); pmax = (float) (-1*INT_MAX); for(i=0;ipmax) { pmax = path[i*width+j]; xpos = j; ypos = i; ajDebug("pmax %.2f xpos: %d ypos: %d path[%d]\n", pmax, xpos, ypos, i*width+j); } p = ajSeqChar(a); q = ajSeqChar(b); p += (*start1); q += (*start2); xpos2 = ypos+xpos; wscore = sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos2])]; while(xpos>=0 && ypos && path[ypos*width+xpos] >0.) { ajDebug("(*) '%c' '%c' xpos: %d ypos: %d path[%d] %.2f\n", p[xpos], q[ypos], xpos, ypos, ypos*width+xpos, path[ypos*width+xpos]); if(!compass[ypos*width+xpos]) /* diagonal */ { if(path[(ypos-1)*width+xpos]<=0.0) break; if(path[(ypos-1)*width+xpos] + sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos2])] != path[(ypos)*width+xpos]) { ajDebug("(*) '%c' '%c' xpos: %d xpos2: %d ypos: %d path[%d]" " %.2f != %.2f + %.2f\n", p[xpos], q[ypos], xpos, xpos2, ypos, ypos*width+xpos, path[ypos*width+xpos], path[(ypos-1)*width+xpos], sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos2])]); ajFatal("SW: Error walking match"); } wscore += sub[ajSeqCvtK(cvt,p[--ypos])][ajSeqCvtK(cvt,q[--xpos2])]; continue; } else if(compass[ypos*width+xpos]==1) /* Left, gap(s) in vertical */ { score = path[ypos*width+xpos]; gapcnt = 0.; ix = xpos-1; match = sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos2])]; --ypos; t = xpos2-1; while(1) { ajDebug("(1) ypos: %d * %d + %d\n", ypos, width, ix); ajDebug("(1) path[%d] = %.2f gapcnt: %.0f\n", ypos*width+ix, path[ypos*width+ix], gapcnt); bimble = path[ypos*width+ix]-gapopen-(gapcnt*gapextend)+match; ajDebug("(1) fabs(%.2f - %.2f) = %.2f\n", score, bimble, fabs((double)score-(double)bimble)); if(fabs((double)score-(double)bimble)<0.1) break; --ix; if(ix<0) ajFatal("SW: Error walking left"); ++gapcnt; } if(score<=0.0) break; t -= (ajint)gapcnt+1; wscore += sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[t])]; wscore -= (gapopen + (gapextend*gapcnt)); xpos2 = t; xpos = ix; ajDebug("xpos => %d\n", xpos); continue; } else if(compass[ypos*width+xpos]==2) /* Down, gap(s) in horizontal */ { score = path[ypos*width+xpos]; gapcnt = 0.; match = sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos2])]; xpos++; iy = ypos-2; t = iy+1; while(1) { ajDebug("(2) %d * %d + xpos: %d\n", iy, width, xpos); ajDebug("(2) path[%d] = %.2f gapcnt: %.0f\n", iy*width+xpos, path[iy*width+xpos], gapcnt); bimble = path[iy*width+xpos]-gapopen-(gapcnt*gapextend)+match; ajDebug("(2) fabs(%.2f - %.2f) = %.2f\n", score, bimble, fabs((double)score-(double)bimble)); if(fabs((double)score-(double)bimble)<0.1) break; --iy; ++xpos; if(iy<0) { ajDebug("SW: Error walking down %d < 0 gapcnt: %d\n", iy, gapcnt); ajFatal("SW: Error walking down"); } ++gapcnt; } if(score<=0.0) break; t -= (ajint)gapcnt; wscore += sub[ajSeqCvtK(cvt,p[t])][ajSeqCvtK(cvt,q[xpos2])]; wscore -= (gapopen + (gapextend*gapcnt)); ypos = iy; ajDebug("ypos => %d\n", ypos); xpos2--; continue; } else ajFatal("Walk Error in SW"); } return wscore; } /* @func embAlignWalkSWMatrixFast ********************************************* ** ** Walk down a matrix for Smith Waterman. Form aligned strings. ** Nucleotides or proteins as needed. ** ** @param [r] path [const float*] path matrix ** @param [r] compass [const ajint*] Path direction pointer array ** @param [r] gapopen [float] gap opening penalty ** @param [r] gapextend [float] gap extension penalty ** @param [r] a [const AjPSeq] first sequence ** @param [r] b [const AjPSeq] second sequence ** @param [w] m [AjPStr *] alignment for first sequence ** @param [w] n [AjPStr *] alignment for second sequence ** @param [r] lena [ajint] length of first sequence ** @param [r] lenb [ajint] length of second sequence ** @param [r] sub [float * const *] substitution matrix from AjPMatrixf ** @param [r] cvt [const AjPSeqCvt] Conversion array for AjPMatrixf ** @param [w] start1 [ajint *] start of alignment in first sequence ** @param [w] start2 [ajint *] start of alignment in second sequence ** @param [r] width [ajint] width of path matrix ** ** @return [void] ******************************************************************************/ void embAlignWalkSWMatrixFast(const float *path, const ajint *compass, float gapopen, float gapextend, const AjPSeq a, const AjPSeq b, AjPStr *m, AjPStr *n, ajint lena, ajint lenb, float * const *sub, const AjPSeqCvt cvt, ajint *start1, ajint *start2, ajint width) { ajint i; ajint j; float pmax; float score; float match; float gapcnt; float bimble; ajint ix; ajint iy; ajint t; ajint xpos = 0; ajint xpos2 = 0; ajint ypos = 0; const char *p; const char *q; float ic; ajDebug("embAlignWalkSWMatrixFast\n"); /* Get maximum path score and save position */ pmax = (float) (-1*INT_MAX); for(i=0;ipmax) { pmax = path[i*width+j]; xpos = j; ypos = i; } p = ajSeqChar(a); q = ajSeqChar(b); p += (*start1); q += (*start2); xpos2 = xpos+ypos; ajStrAssK(m,p[ypos]); ajStrAssK(n,q[xpos2]); while(xpos>=0 && ypos && path[ypos*width+xpos] >0.) { if(!compass[ypos*width+xpos]) /* diagonal */ { if(path[(ypos-1)*width+xpos] + sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos2])] != path[(ypos)*width+xpos]) ajFatal("SW: Error walking match"); if(path[(ypos-1)*width+xpos]<=0.0) break; ajStrAppK(m,p[--ypos]); ajStrAppK(n,q[--xpos2]); continue; } else if(compass[ypos*width+xpos]==1) /* Left, gap(s) in vertical */ { score = path[ypos*width+xpos]; gapcnt = 0.; ix = xpos-1; match = sub[ajSeqCvtK(cvt,p[ypos])][ajSeqCvtK(cvt,q[xpos2])]; --ypos; t = xpos2-1; while(1) { bimble=path[ypos*width+ix]-gapopen-(gapcnt*gapextend)+match; if(fabs((double)score-(double)bimble)<0.1) break; --ix; if(ix<0) ajFatal("SW: Error walking left"); ++gapcnt; } if(score<=0.0) break; for(ic=-1;ic-1) { for(columnx=column-2;columnx>-1;--columnx) { score = path[(row-1)*seqlen+columnx]; score += fmscore; penalty = -(fmatrix[(row-1)][GAPO] * gapopen + ((column-columnx-2) * gapextend * fmatrix[(row-1)][GAPE])); score += penalty; if(score>currmax) { currmax=score; path[row*seqlen+column] = currmax; compass[row*seqlen+column] = LEFT; } } } /* And then bimble down Y axis */ if(row-2>-1) { for(rowx=row-2;rowx>-1;--rowx) { score = path[rowx*seqlen+(column-1)]; score += fmscore; penalty = -(fmatrix[rowx][GAPO] * gapopen + ((float) (row-rowx-2.) * gapextend * fmatrix[rowx][GAPE])); score += penalty; if(score>currmax) { currmax = score; path[row*seqlen+column] = currmax; compass[row*seqlen+column] = DOWN; } } } } ++column; } if(show) { for(row=proflen-1;row>-1;--row) { ajStrDelReuse(&outstr); for(column=0;column pathmax) { pathmax = path[row*seqlen+column]; xpos = column; ypos = row; } column = xpos; row = ypos; p = ajStrStr(cons); q = ajStrStr(seq); ajStrAssK(m,p[row]); ajStrAssK(n,q[column]); while(row && column) { direction = compass[row*seqlen+column]; if(direction == DIAG) { if(path[(row-1)*seqlen+(column-1)]<0.) break; ajStrInsertK(m,0,p[--row]); ajStrInsertK(n,0,q[--column]); continue; } else if(direction == LEFT) { targetscore = path[row*seqlen+column]; gapcnt = 0; colstep = column-2; currscore = -(float)INT_MAX; match = fmatrix[row][ajAZToInt(q[column])]; while(fabs(targetscore-currscore) > errbounds) { currscore = path[(row-1)*seqlen+colstep]; penalty = -(fmatrix[row-1][GAPO] * gapopen + fmatrix[row-1][GAPE] * (float)gapcnt * gapextend); currscore += penalty; currscore += match; ++gapcnt; if(currscore-penalty < 0.) break; --colstep; } for(i=0;i errbounds) { currscore = path[rowstep*seqlen+(column-1)]; penalty = -(fmatrix[rowstep][GAPO] * gapopen + fmatrix[rowstep][GAPE] * (float)gapcnt * gapextend); currscore += penalty; currscore += match; ++gapcnt; if(currscore-penalty < 0.) break; --rowstep; } for(i=0;i0.0) ajStrAppC(&fm,":"); else ajStrAppC(&fm," "); } } /* Get start residues */ p = ajStrStr(fa); q = ajStrStr(fb); acnt = begina+start1; bcnt = beginb+start2; len = ajStrLen(fa); pos = 0; if(mark) r = ajStrStr(fm); /* Add header stuff here */ ajFmtPrintF(outf,"Local: %s vs %s\n",namea,nameb); ajFmtPrintF(outf,"Score: %.2f\n\n",score); while(pos0.0) ++(*sim); } max = (lenm>lenn) ? lenm : lenn; *idx = *id / (float)max * 100.; *simx = *sim / (float)max * 100.; *id *= (100. / (float)(olen-gaps)); *sim *= (100. / (float)(olen-gaps)); ajStrDel(&fm); ajStrDel(&fn); return; } /* @func embAlignScoreProfileMatrix ******************************************* ** ** Score a profile path matrix for Smith Waterman. ** Nucleotides or proteins as needed. ** ** @param [r] path [const float*] path matrix ** @param [r] compass [const ajint*] Path direction pointer array ** @param [r] gapopen [float] gap opening coeff ** @param [r] gapextend [float] gap extension coeff ** @param [r] seq [const AjPStr] second sequence ** @param [r] proflen [ajint] length of consensus sequence ** @param [r] seqlen [ajint] length of test sequence ** @param [r] fmatrix [float * const *] profile ** @param [w] start1 [ajint *] start of alignment in consensus sequence ** @param [w] start2 [ajint *] start of alignment in test sequence ** ** @return [float] profile alignment score ******************************************************************************/ float embAlignScoreProfileMatrix(const float *path, const ajint *compass, float gapopen, float gapextend, const AjPStr seq, ajint proflen, ajint seqlen, float * const *fmatrix, ajint *start1, ajint *start2) { ajint i; float pathmax; float targetscore; float currscore; float wscore=0.; float match; ajint gapcnt; float penalty = 0.; ajint row = 0; ajint column = 0; ajint colstep; ajint rowstep; ajint direction = 0; ajint xpos = 0; ajint ypos = 0; const char *q; float errbounds=0.01; ajDebug("embAlignWalkProfileMatrix\n"); /* Get maximum path score and save position */ pathmax = -(float) INT_MAX; for(row=0;row pathmax) { pathmax = path[row*seqlen+column]; xpos = column; ypos = row; } column = xpos; row = ypos; q = ajStrStr(seq); wscore = fmatrix[row][ajAZToInt(q[column])]; while(row && column) { direction = compass[row*seqlen+column]; if(direction == DIAG) { if(path[(row-1)*seqlen+(column-1)]<0.) break; wscore += fmatrix[--row][ajAZToInt(q[--column])]; continue; } else if(direction == LEFT) { targetscore = path[row*seqlen+column]; gapcnt = 0; colstep = column-2; currscore = -(float)INT_MAX; match = fmatrix[row][ajAZToInt(q[column])]; while(fabs(targetscore-currscore) > errbounds) { currscore = path[(row-1)*seqlen+colstep]; penalty = -(fmatrix[row-1][GAPO] * gapopen + fmatrix[row-1][GAPE] * (float)gapcnt * gapextend); currscore += penalty; currscore += match; ++gapcnt; if(currscore-penalty < 0.) break; --colstep; } for(i=0;i errbounds) { currscore = path[rowstep*seqlen+(column-1)]; penalty = -(fmatrix[rowstep][GAPO] * gapopen + fmatrix[rowstep][GAPE] * (float)gapcnt * gapextend); currscore += penalty; currscore += match; ++gapcnt; if(currscore-penalty < 0.) break; --rowstep; } for(i=0;istart2) { for(i=0;istart2 start a: seqa 1..%d b: %d spaces seqb 1..%d\n", start1, nc, start1-nc); for(++nc;istart1) { for(i=0;iblen) { ajStrAppC(&fa,&a[apos]); for(i=0;ialen) { ajStrAppC(&fb,&b[bpos]); for(i=0;i0.0) ajStrAppC(&fm,":"); else ajStrAppC(&fm," "); } } /* Get start residues */ p = ajStrStr(fa); q = ajStrStr(fb); acnt = begina+start1; bcnt = beginb+start2; len = ajStrLen(fa); pos = 0; if(mark) r=ajStrStr(fm); /* Add header stuff here */ while(pos