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 }