github.com/biogo/biogo@v1.0.4/align/fitted_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 fitted_affine_type.got:17 17 func drawFittedAffineTableType(rSeq, qSeq Type, index alphabet.Index, table [][3]int, a FittedAffine) { 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 := pointerFittedAffineType(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 pointerFittedAffineType(rSeq, qSeq Type, i, j, l int, table [][3]int, index alphabet.Index, a FittedAffine, c int) string { 55 if j == 0 { 56 return "" 57 } 58 if i == 0 { 59 if l == left { 60 return "⬅ l" 61 } 62 return "" 63 } 64 rVal := index[rSeq[i-1]] 65 qVal := index[qSeq[j-1]] 66 if rVal < 0 || qVal < 0 { 67 return "" 68 } 69 switch p := i*c + j; table[p][l] { 70 case table[p-c][up] + a.Matrix[rVal][gap]: 71 return "⬆ u" 72 case table[p-1][left] + a.Matrix[gap][qVal]: 73 return "⬅ l" 74 75 case table[p-c][diag] + a.GapOpen + a.Matrix[rVal][gap]: 76 return "⬆ m" 77 case table[p-1][diag] + a.GapOpen + a.Matrix[gap][qVal]: 78 return "⬅ m" 79 80 case table[p-c-1][up] + a.Matrix[rVal][qVal]: 81 return "⬉ u" 82 case table[p-c-1][left] + a.Matrix[rVal][qVal]: 83 return "⬉ l" 84 case table[p-c-1][diag] + a.Matrix[rVal][qVal]: 85 return "⬉ m" 86 default: 87 return [3]string{"", "⬆ u", "⬅ l"}[l] 88 } 89 } 90 91 func (a FittedAffine) alignType(rSeq, qSeq Type, alpha alphabet.Alphabet) ([]feat.Pair, error) { 92 let := len(a.Matrix) 93 la := make([]int, 0, let*let) 94 for _, row := range a.Matrix { 95 if len(row) != let { 96 return nil, ErrMatrixNotSquare 97 } 98 la = append(la, row...) 99 } 100 101 index := alpha.LetterIndex() 102 r, c := rSeq.Len()+1, qSeq.Len()+1 103 table := make([][3]int, r*c) 104 table[0] = [3]int{ 105 diag: 0, 106 up: minInt, 107 left: minInt, 108 } 109 table[1] = [3]int{ 110 diag: minInt, 111 up: minInt, 112 } 113 table[1][left] = a.GapOpen + la[index[qSeq[0]]] 114 for j := range table[2:c] { 115 table[j+2] = [3]int{ 116 diag: minInt, 117 up: minInt, 118 left: table[j+1][left] + la[index[qSeq[j+1]]], 119 } 120 } 121 table[c] = [3]int{ 122 diag: minInt, 123 left: minInt, 124 } 125 for i := 2; i < r; i++ { 126 table[i*c] = [3]int{ 127 diag: minInt, 128 left: minInt, 129 } 130 } 131 132 for i := 1; i < r; i++ { 133 for j := 1; j < c; j++ { 134 var ( 135 rVal = index[rSeq[i-1]] 136 qVal = index[qSeq[j-1]] 137 ) 138 if rVal < 0 { 139 return nil, fmt.Errorf("align: illegal letter %q at position %d in rSeq", rSeq[i-1], i-1) 140 } 141 if qVal < 0 { 142 return nil, fmt.Errorf("align: illegal letter %q at position %d in qSeq", qSeq[j-1], j-1) 143 } 144 p := i*c + j 145 146 diagScore := table[p-c-1][diag] 147 upScore := table[p-c-1][up] 148 leftScore := table[p-c-1][left] 149 150 table[p][diag] = max3(diagScore, upScore, leftScore) + la[rVal*let+qVal] 151 152 table[p][up] = max2( 153 add(table[p-c][diag], a.GapOpen+la[rVal*let]), 154 add(table[p-c][up], la[rVal*let]), 155 ) 156 157 table[p][left] = max2( 158 add(table[p-1][diag], a.GapOpen+la[qVal]), 159 add(table[p-1][left], la[qVal]), 160 ) 161 } 162 } 163 if debugFittedAffine { 164 drawFittedAffineTableType(rSeq, qSeq, index, table, a) 165 } 166 167 var aln []feat.Pair 168 score, last, layer := 0, diag, diag 169 var ( 170 i int 171 j = c - 1 172 ) 173 max := minInt 174 for y := 1; y < r; y++ { 175 v := table[(y*c)+c-1][diag] 176 if v >= max { 177 i = y 178 max = v 179 } 180 } 181 maxI, maxJ := i, j 182 for i > 0 && j > 0 { 183 var ( 184 rVal = index[rSeq[i-1]] 185 qVal = index[qSeq[j-1]] 186 ) 187 switch p := i*c + j; table[p][layer] { 188 case table[p-c][up] + la[rVal*let]: 189 if last != up && p != len(table)-1 { 190 aln = append(aln, &featPair{ 191 a: feature{start: i, end: maxI}, 192 b: feature{start: j, end: maxJ}, 193 score: score, 194 }) 195 maxI, maxJ = i, j 196 score = 0 197 } 198 score += table[p][layer] - table[p-c][up] 199 i-- 200 layer = up 201 last = up 202 case table[p-1][left] + la[qVal]: 203 if last != left && p != len(table)-1 { 204 aln = append(aln, &featPair{ 205 a: feature{start: i, end: maxI}, 206 b: feature{start: j, end: maxJ}, 207 score: score, 208 }) 209 maxI, maxJ = i, j 210 score = 0 211 } 212 score += table[p][layer] - table[p-1][left] 213 j-- 214 layer = left 215 last = left 216 case table[p-c][diag] + a.GapOpen + la[rVal*let]: 217 if last != up && p != len(table)-1 { 218 aln = append(aln, &featPair{ 219 a: feature{start: i, end: maxI}, 220 b: feature{start: j, end: maxJ}, 221 score: score, 222 }) 223 maxI, maxJ = i, j 224 score = 0 225 } 226 score += table[p][layer] - table[p-c][diag] 227 i-- 228 layer = diag 229 last = up 230 case table[p-1][diag] + a.GapOpen + la[qVal]: 231 if last != left && p != len(table)-1 { 232 aln = append(aln, &featPair{ 233 a: feature{start: i, end: maxI}, 234 b: feature{start: j, end: maxJ}, 235 score: score, 236 }) 237 maxI, maxJ = i, j 238 score = 0 239 } 240 score += table[p][layer] - table[p-1][diag] 241 j-- 242 layer = diag 243 last = left 244 case table[p-c-1][up] + la[rVal*let+qVal]: 245 if last != diag { 246 aln = append(aln, &featPair{ 247 a: feature{start: i, end: maxI}, 248 b: feature{start: j, end: maxJ}, 249 score: score, 250 }) 251 maxI, maxJ = i, j 252 score = 0 253 } 254 score += table[p][layer] - table[p-c-1][up] 255 i-- 256 j-- 257 layer = up 258 last = diag 259 case table[p-c-1][left] + la[rVal*let+qVal]: 260 if last != diag { 261 aln = append(aln, &featPair{ 262 a: feature{start: i, end: maxI}, 263 b: feature{start: j, end: maxJ}, 264 score: score, 265 }) 266 maxI, maxJ = i, j 267 score = 0 268 } 269 score += table[p][layer] - table[p-c-1][left] 270 i-- 271 j-- 272 layer = left 273 last = diag 274 case table[p-c-1][diag] + la[rVal*let+qVal]: 275 if last != diag { 276 aln = append(aln, &featPair{ 277 a: feature{start: i, end: maxI}, 278 b: feature{start: j, end: maxJ}, 279 score: score, 280 }) 281 maxI, maxJ = i, j 282 score = 0 283 } 284 score += table[p][layer] - table[p-c-1][diag] 285 i-- 286 j-- 287 layer = diag 288 last = diag 289 290 default: 291 panic(fmt.Sprintf("align: fitted nw affine internal error: no path at row: %d col:%d layer:%s\n", i, j, "mul"[layer:layer+1])) 292 } 293 } 294 295 aln = append(aln, &featPair{ 296 a: feature{start: i, end: maxI}, 297 b: feature{start: j, end: maxJ}, 298 score: score, 299 }) 300 301 for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { 302 aln[i], aln[j] = aln[j], aln[i] 303 } 304 305 return aln, nil 306 }