github.com/vertgenlab/gonomics@v1.0.0/genomeGraph/localAlignment.go (about)

     1  package genomeGraph
     2  
     3  import (
     4  	"log"
     5  
     6  	"github.com/vertgenlab/gonomics/align"
     7  	"github.com/vertgenlab/gonomics/cigar"
     8  	"github.com/vertgenlab/gonomics/dna"
     9  )
    10  
    11  var HumanChimpTwoScoreMatrixNoGap = [][]int64{
    12  	{90, -330, -236, -356},
    13  	{-330, 100, -318, -236},
    14  	{-236, -318, 100, -330},
    15  	{-356, -236, -330, 90},
    16  }
    17  
    18  func reverseCigar(alpha []align.Cigar) {
    19  	for i, j := 0, len(alpha)-1; i < j; i, j = i+1, j-1 {
    20  		alpha[i], alpha[j] = alpha[j], alpha[i]
    21  	}
    22  }
    23  
    24  func reverseCigarPointer(alpha []cigar.Cigar) {
    25  	for i, j := 0, len(alpha)-1; i < j; i, j = i+1, j-1 {
    26  		alpha[i], alpha[j] = alpha[j], alpha[i]
    27  	}
    28  }
    29  
    30  func swMatrixSetup(size int64) ([][]int64, [][]rune) {
    31  	m := make([][]int64, size)
    32  	trace := make([][]rune, size)
    33  	for idx := range m {
    34  		m[idx] = make([]int64, size)
    35  		trace[idx] = make([]rune, size)
    36  	}
    37  	return m, trace
    38  }
    39  
    40  func initialZeroMatrix(m [][]int64, alphaLen int, betaLen int) {
    41  	for i := 0; i < alphaLen+1; i++ {
    42  		m[i][0] = 0
    43  	}
    44  	for j := 0; j < betaLen+1; j++ {
    45  		m[0][j] = 0
    46  	}
    47  }
    48  
    49  func initialTraceMatrix(trace [][]rune, alphaLen int, betaLen int) {
    50  	for i := 1; i < alphaLen+1; i++ {
    51  		trace[i][0] = 'D'
    52  	}
    53  	for j := 1; j < betaLen+1; j++ {
    54  		trace[0][j] = 'I'
    55  	}
    56  }
    57  
    58  func SmithWaterman(alpha []dna.Base, beta []dna.Base, scores [][]int64, gapPen int64, m [][]int64, trace [][]rune) (int64, []cigar.Cigar, int64, int64, int64, int64) {
    59  	//check if size of alpha is larger than m
    60  	var currMax int64
    61  	var maxI int64
    62  	var maxJ int64
    63  	var i, j, routeIdx int64
    64  	//setting up the first rows and columns
    65  	//seting up the rest of the matrix
    66  	initialZeroMatrix(m, len(alpha), len(beta))
    67  	for i = 1; i < int64(len(alpha)+1); i++ {
    68  		for j = 1; j < int64(len(beta)+1); j++ {
    69  			m[i][j], trace[i][j] = tripleMaxTrace(m[i-1][j-1], m[i-1][j-1]+scores[alpha[i-1]][beta[j-1]], m[i][j-1]+gapPen, m[i-1][j]+gapPen)
    70  			if m[i][j] > currMax {
    71  				currMax = m[i][j]
    72  				maxI = int64(i)
    73  				maxJ = int64(j)
    74  			}
    75  			if m[i][j] < 0 {
    76  				m[i][j] = 0
    77  			}
    78  		}
    79  	}
    80  	var minI, minJ int64
    81  	var curr cigar.Cigar
    82  	var route []cigar.Cigar
    83  	route = append(route, cigar.Cigar{RunLength: 0, Op: trace[maxI][maxJ]})
    84  	for i, j, routeIdx = maxI, maxJ, 0; m[i][j] > 0; {
    85  		if route[routeIdx].RunLength == 0 {
    86  			route[routeIdx].RunLength = 1
    87  			route[routeIdx].Op = trace[i][j]
    88  		} else if route[routeIdx].Op == trace[i][j] {
    89  			route[routeIdx].RunLength += 1
    90  		} else {
    91  			curr = cigar.Cigar{RunLength: 0, Op: trace[i][j]}
    92  			route = append(route, curr)
    93  			routeIdx++
    94  		}
    95  		switch trace[i][j] {
    96  		case '=':
    97  			i, j = i-1, j-1
    98  			//refStart = refStart + 1
    99  		case 'X':
   100  			i, j = i-1, j-1
   101  		case 'I':
   102  			j -= 1
   103  		case 'D':
   104  			i -= 1
   105  			//refStart = refStart + 1
   106  		default:
   107  			log.Fatalf("Error: unexpected traceback")
   108  		}
   109  		minI = i
   110  		minJ = j
   111  	}
   112  	reverseCigarPointer(route)
   113  	return m[maxI][maxJ], route, minI, maxI, minJ, maxJ
   114  }
   115  
   116  func tripleMaxTrace(prev int64, a int64, b int64, c int64) (int64, rune) {
   117  	if a >= b && a >= c {
   118  		if a > prev {
   119  			return a, '='
   120  		} else {
   121  			return a, 'X'
   122  		}
   123  	} else if b >= c {
   124  		return b, 'I'
   125  	} else {
   126  		return c, 'D'
   127  	}
   128  }
   129  
   130  func LeftLocal(alpha []dna.Base, beta []dna.Base, scores [][]int64, gapPen int64, m [][]int64, trace [][]rune) (int64, []cigar.Cigar, int, int, int, int) {
   131  	//check if size of alpha is larger than m
   132  	var i, j, routeIdx int
   133  	initialZeroMatrix(m, len(alpha), len(beta))
   134  	for i = 1; i < len(alpha)+1; i++ {
   135  		for j = 1; j < len(beta)+1; j++ {
   136  			m[i][j], trace[i][j] = tripleMaxTrace(m[i-1][j-1], m[i-1][j-1]+scores[alpha[i-1]][beta[j-1]], m[i][j-1]+gapPen, m[i-1][j]+gapPen)
   137  			if m[i][j] < 0 {
   138  				m[i][j] = 0
   139  			}
   140  		}
   141  	}
   142  	var minI, minJ = len(alpha), len(beta)
   143  	var route []cigar.Cigar
   144  	//traceback starts in top corner
   145  	for i, j, routeIdx = len(alpha), len(beta), 0; m[i][j] > 0; {
   146  		//if route[routeIdx].RunLength == 0 {
   147  		if len(route) == 0 {
   148  			curr := cigar.Cigar{RunLength: 1, Op: trace[i][j]}
   149  			route = append(route, curr)
   150  		} else if route[routeIdx].Op == trace[i][j] {
   151  			route[routeIdx].RunLength += 1
   152  		} else {
   153  			curr := cigar.Cigar{RunLength: 1, Op: trace[i][j]}
   154  			route = append(route, curr)
   155  			routeIdx++
   156  		}
   157  		switch trace[i][j] {
   158  		case '=':
   159  			i, j = i-1, j-1
   160  		case 'X':
   161  			i, j = i-1, j-1
   162  		case 'I':
   163  			j -= 1
   164  		case 'D':
   165  			i -= 1
   166  		default:
   167  			log.Fatalf("Error: unexpected traceback %c\n", trace[i][j])
   168  		}
   169  		minI = i
   170  		minJ = j
   171  	}
   172  	//TODO: double check if this is tracing back in the correct directions
   173  	reverseCigarPointer(route)
   174  	return m[len(alpha)][len(beta)], route, minI, len(alpha), minJ, len(beta)
   175  }
   176  
   177  func RightLocal(alpha []dna.Base, beta []dna.Base, scores [][]int64, gapPen int64, m [][]int64, trace [][]rune) (int64, []cigar.Cigar, int, int, int, int) {
   178  	//check if size of alpha is larger than m
   179  	var currMax int64
   180  	var maxI int
   181  	var maxJ int
   182  	var i, j, routeIdx int
   183  	//setting up the first rows and columns
   184  	//seting up the rest of the matrix
   185  	for i = 0; i < len(alpha)+1; i++ {
   186  		for j = 0; j < len(beta)+1; j++ {
   187  			if i == 0 && j == 0 {
   188  				m[i][j] = 0
   189  			} else if i == 0 {
   190  				m[i][j] = m[i][j-1] + gapPen
   191  				trace[i][j] = 'I'
   192  			} else if j == 0 {
   193  				m[i][j] = m[i-1][j] + gapPen
   194  				trace[i][j] = 'D'
   195  			} else {
   196  				m[i][j], trace[i][j] = tripleMaxTrace(m[i-1][j-1], m[i-1][j-1]+scores[alpha[i-1]][beta[j-1]], m[i][j-1]+gapPen, m[i-1][j]+gapPen)
   197  			}
   198  			if m[i][j] > currMax {
   199  				currMax = m[i][j]
   200  				maxI = i
   201  				maxJ = j
   202  			}
   203  		}
   204  	}
   205  	var route []cigar.Cigar
   206  	//traceback starts in top corner
   207  	for i, j, routeIdx = maxI, maxJ, 0; i > 0 || j > 0; {
   208  		//if route[routeIdx].RunLength == 0 {
   209  		if len(route) == 0 {
   210  			curr := cigar.Cigar{RunLength: 1, Op: trace[i][j]}
   211  			route = append(route, curr)
   212  		} else if route[routeIdx].Op == trace[i][j] {
   213  			route[routeIdx].RunLength += 1
   214  		} else {
   215  			curr := cigar.Cigar{RunLength: 1, Op: trace[i][j]}
   216  			route = append(route, curr)
   217  			routeIdx++
   218  		}
   219  		switch trace[i][j] {
   220  		case '=':
   221  			i, j = i-1, j-1
   222  		case 'X':
   223  			i, j = i-1, j-1
   224  		case 'I':
   225  			j -= 1
   226  		case 'D':
   227  			i -= 1
   228  		default:
   229  			log.Fatalf("Error: unexpected traceback with %c\n", trace[i][j])
   230  		}
   231  	}
   232  	reverseCigarPointer(route)
   233  	return m[maxI][maxJ], route, 0, maxI, 0, maxJ
   234  }