github.com/biogo/biogo@v1.0.4/align/nw_affine_type.got (about) 1 // Copyright ©2011-2012 The bíogo Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package align 6 7 import ( 8 "github.com/biogo/biogo/alphabet" 9 "github.com/biogo/biogo/feat" 10 11 "fmt" 12 "os" 13 "text/tabwriter" 14 ) 15 16 //line nw_affine_type.got:17 17 func drawNWAffineTableType(rSeq, qSeq Type, index alphabet.Index, table [][3]int, a NWAffine) { 18 tw := tabwriter.NewWriter(os.Stdout, 0, 0, 0, ' ', tabwriter.AlignRight|tabwriter.Debug) 19 fmt.Printf("rSeq: %s\n", rSeq) 20 fmt.Printf("qSeq: %s\n", qSeq) 21 for l := 0; l < 3; l++ { 22 fmt.Fprintf(tw, "%c\tqSeq\t", "MUL"[l]) 23 for _, l := range qSeq { 24 fmt.Fprintf(tw, "%c\t", l) 25 } 26 fmt.Fprintln(tw) 27 28 r, c := rSeq.Len()+1, qSeq.Len()+1 29 fmt.Fprint(tw, "rSeq\t") 30 for i := 0; i < r; i++ { 31 if i != 0 { 32 fmt.Fprintf(tw, "%c\t", rSeq[i-1]) 33 } 34 35 for j := 0; j < c; j++ { 36 p := pointerNWAffineType(rSeq, qSeq, i, j, l, table, index, a, c) 37 var vi interface{} 38 if vi = table[i*c+j][l]; vi == minInt { 39 vi = "-Inf" 40 } 41 if p != "" { 42 fmt.Fprintf(tw, "%s % 4v\t", p, vi) 43 } else { 44 fmt.Fprintf(tw, "%v\t", vi) 45 } 46 } 47 fmt.Fprintln(tw) 48 } 49 fmt.Fprintln(tw) 50 } 51 tw.Flush() 52 } 53 54 func pointerNWAffineType(rSeq, qSeq Type, i, j, l int, table [][3]int, index alphabet.Index, a NWAffine, c int) string { 55 switch { 56 case i == 0 && j == 0: 57 return "" 58 case i == 0: 59 if j == 1 { 60 return "⬅ m" 61 } 62 return "⬅ l" 63 case j == 0: 64 if i == 1 { 65 return "⬆ m" 66 } 67 return "⬆ u" 68 } 69 rVal := index[rSeq[i-1]] 70 qVal := index[qSeq[j-1]] 71 if rVal < 0 || qVal < 0 { 72 return "" 73 } 74 switch p := i*c + j; table[p][l] { 75 case table[p-c][up] + a.Matrix[rVal][gap]: 76 return "⬆ u" 77 case table[p-1][left] + a.Matrix[gap][qVal]: 78 return "⬅ l" 79 80 case table[p-c][diag] + a.GapOpen + a.Matrix[rVal][gap]: 81 return "⬆ m" 82 case table[p-1][diag] + a.GapOpen + a.Matrix[gap][qVal]: 83 return "⬅ m" 84 85 case table[p-c-1][up] + a.Matrix[rVal][qVal]: 86 return "⬉ u" 87 case table[p-c-1][left] + a.Matrix[rVal][qVal]: 88 return "⬉ l" 89 case table[p-c-1][diag] + a.Matrix[rVal][qVal]: 90 return "⬉ m" 91 default: 92 return [3]string{"", "⬆ u", "⬅ l"}[l] 93 } 94 } 95 96 func (a NWAffine) alignType(rSeq, qSeq Type, alpha alphabet.Alphabet) ([]feat.Pair, error) { 97 let := len(a.Matrix) 98 if let < alpha.Len() { 99 return nil, ErrMatrixWrongSize{Size: let, Len: alpha.Len()} 100 } 101 la := make([]int, 0, let*let) 102 for _, row := range a.Matrix { 103 if len(row) != let { 104 return nil, ErrMatrixNotSquare 105 } 106 la = append(la, row...) 107 } 108 109 index := alpha.LetterIndex() 110 r, c := rSeq.Len()+1, qSeq.Len()+1 111 table := make([][3]int, r*c) 112 table[0] = [3]int{ 113 diag: 0, 114 up: minInt, 115 left: minInt, 116 } 117 table[1] = [3]int{ 118 diag: minInt, 119 up: minInt, 120 left: a.GapOpen + la[index[qSeq[0]]], 121 } 122 for j := range table[2:c] { 123 table[j+2] = [3]int{ 124 diag: minInt, 125 up: minInt, 126 left: table[j+1][left] + la[index[qSeq[j+1]]], 127 } 128 } 129 table[c] = [3]int{ 130 diag: minInt, 131 up: a.GapOpen + la[index[rSeq[0]]*let], 132 left: minInt, 133 } 134 for i := 2; i < r; i++ { 135 table[i*c] = [3]int{ 136 diag: minInt, 137 up: table[(i-1)*c][up] + la[index[rSeq[i-1]]*let], 138 left: minInt, 139 } 140 } 141 142 for i := 1; i < r; i++ { 143 for j := 1; j < c; j++ { 144 var ( 145 rVal = index[rSeq[i-1]] 146 qVal = index[qSeq[j-1]] 147 ) 148 if rVal < 0 { 149 return nil, fmt.Errorf("align: illegal letter %q at position %d in rSeq", rSeq[i-1], i-1) 150 } 151 if qVal < 0 { 152 return nil, fmt.Errorf("align: illegal letter %q at position %d in qSeq", qSeq[j-1], j-1) 153 } 154 p := i*c + j 155 156 diagScore := table[p-c-1][diag] 157 upScore := table[p-c-1][up] 158 leftScore := table[p-c-1][left] 159 160 table[p][diag] = max3(diagScore, upScore, leftScore) + la[rVal*let+qVal] 161 162 table[p][up] = max2( 163 add(table[p-c][diag], a.GapOpen+la[rVal*let]), 164 add(table[p-c][up], la[rVal*let]), 165 ) 166 167 table[p][left] = max2( 168 add(table[p-1][diag], a.GapOpen+la[qVal]), 169 add(table[p-1][left], la[qVal]), 170 ) 171 } 172 } 173 if debugNeedleAffine { 174 drawNWAffineTableType(rSeq, qSeq, index, table, a) 175 } 176 177 var ( 178 aln []feat.Pair 179 layer int 180 ) 181 score, last := 0, diag 182 i, j := r-1, c-1 183 t := table[i*c+j] 184 best := t[0] 185 for i, s := range t[1:] { 186 if s > best { 187 best, layer = s, i+1 188 } 189 } 190 maxI, maxJ := i, j 191 for i > 0 && j > 0 { 192 var ( 193 rVal = index[rSeq[i-1]] 194 qVal = index[qSeq[j-1]] 195 ) 196 switch p := i*c + j; table[p][layer] { 197 case table[p-c][up] + la[rVal*let]: 198 if last != up && p != len(table)-1 { 199 aln = append(aln, &featPair{ 200 a: feature{start: i, end: maxI}, 201 b: feature{start: j, end: maxJ}, 202 score: score, 203 }) 204 maxI, maxJ = i, j 205 score = 0 206 } 207 score += table[p][layer] - table[p-c][up] 208 i-- 209 layer = up 210 last = up 211 case table[p-1][left] + la[qVal]: 212 if last != left && p != len(table)-1 { 213 aln = append(aln, &featPair{ 214 a: feature{start: i, end: maxI}, 215 b: feature{start: j, end: maxJ}, 216 score: score, 217 }) 218 maxI, maxJ = i, j 219 score = 0 220 } 221 score += table[p][layer] - table[p-1][left] 222 j-- 223 layer = left 224 last = left 225 case table[p-c][diag] + a.GapOpen + la[rVal*let]: 226 if last != up && p != len(table)-1 { 227 aln = append(aln, &featPair{ 228 a: feature{start: i, end: maxI}, 229 b: feature{start: j, end: maxJ}, 230 score: score, 231 }) 232 maxI, maxJ = i, j 233 score = 0 234 } 235 score += table[p][layer] - table[p-c][diag] 236 i-- 237 layer = diag 238 last = up 239 case table[p-1][diag] + a.GapOpen + la[qVal]: 240 if last != left && p != len(table)-1 { 241 aln = append(aln, &featPair{ 242 a: feature{start: i, end: maxI}, 243 b: feature{start: j, end: maxJ}, 244 score: score, 245 }) 246 maxI, maxJ = i, j 247 score = 0 248 } 249 score += table[p][layer] - table[p-1][diag] 250 j-- 251 layer = diag 252 last = left 253 case table[p-c-1][up] + la[rVal*let+qVal]: 254 if last != diag { 255 aln = append(aln, &featPair{ 256 a: feature{start: i, end: maxI}, 257 b: feature{start: j, end: maxJ}, 258 score: score, 259 }) 260 maxI, maxJ = i, j 261 score = 0 262 } 263 score += table[p][layer] - table[p-c-1][up] 264 i-- 265 j-- 266 layer = up 267 last = diag 268 case table[p-c-1][left] + la[rVal*let+qVal]: 269 if last != diag { 270 aln = append(aln, &featPair{ 271 a: feature{start: i, end: maxI}, 272 b: feature{start: j, end: maxJ}, 273 score: score, 274 }) 275 maxI, maxJ = i, j 276 score = 0 277 } 278 score += table[p][layer] - table[p-c-1][left] 279 i-- 280 j-- 281 layer = left 282 last = diag 283 case table[p-c-1][diag] + la[rVal*let+qVal]: 284 if last != diag { 285 aln = append(aln, &featPair{ 286 a: feature{start: i, end: maxI}, 287 b: feature{start: j, end: maxJ}, 288 score: score, 289 }) 290 maxI, maxJ = i, j 291 score = 0 292 } 293 score += table[p][layer] - table[p-c-1][diag] 294 i-- 295 j-- 296 layer = diag 297 last = diag 298 299 default: 300 panic(fmt.Sprintf("align: nw affine internal error: no path at row: %d col:%d layer:%s\n", i, j, "mul"[layer:layer+1])) 301 } 302 } 303 304 aln = append(aln, &featPair{ 305 a: feature{start: i, end: maxI}, 306 b: feature{start: j, end: maxJ}, 307 score: score, 308 }) 309 if i != j { 310 switch 0 { 311 case i: 312 last = left 313 case j: 314 last = up 315 default: 316 panic(fmt.Sprintf("align: nw affine internal error: unexpected final segment: row: %d col: %d", i, j)) 317 } 318 aln = append(aln, &featPair{ 319 a: feature{start: 0, end: i}, 320 b: feature{start: 0, end: j}, 321 score: table[i*c+j][last], 322 }) 323 } 324 325 for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { 326 aln[i], aln[j] = aln[j], aln[i] 327 } 328 329 return aln, nil 330 }