github.com/biogo/biogo@v1.0.4/align/fitted_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_type.got:17 17 func drawFittedTableType(rSeq, qSeq Type, index alphabet.Index, table []int, a [][]int) { 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 fmt.Fprint(tw, "\tqSeq\t") 22 for _, l := range qSeq { 23 fmt.Fprintf(tw, "%c\t", l) 24 } 25 fmt.Fprintln(tw) 26 27 r, c := rSeq.Len()+1, qSeq.Len()+1 28 fmt.Fprint(tw, "rSeq\t") 29 for i := 0; i < r; i++ { 30 if i != 0 { 31 fmt.Fprintf(tw, "%c\t", rSeq[i-1]) 32 } 33 34 for j := 0; j < c; j++ { 35 p := pointerFittedType(rSeq, qSeq, i, j, table, index, a, c) 36 if p != "" { 37 fmt.Fprintf(tw, "%s % 3v\t", p, table[i*c+j]) 38 } else { 39 fmt.Fprintf(tw, "%v\t", table[i*c+j]) 40 } 41 } 42 fmt.Fprintln(tw) 43 } 44 tw.Flush() 45 } 46 47 func pointerFittedType(rSeq, qSeq Type, i, j int, table []int, index alphabet.Index, a [][]int, c int) string { 48 if i == 0 || j == 0 { 49 return "" 50 } 51 rVal := index[rSeq[i-1]] 52 qVal := index[qSeq[j-1]] 53 if rVal < 0 || qVal < 0 { 54 return "" 55 } 56 switch p := i*c + j; table[p] { 57 case table[p-c-1] + a[rVal][qVal]: 58 return "⬉" 59 case table[p-c] + a[rVal][gap]: 60 return "⬆" 61 case table[p-1] + a[gap][qVal]: 62 return "⬅" 63 default: 64 return "" 65 } 66 } 67 68 func (a Fitted) alignType(rSeq, qSeq Type, alpha alphabet.Alphabet) ([]feat.Pair, error) { 69 let := len(a) 70 la := make([]int, 0, let*let) 71 for _, row := range a { 72 if len(row) != let { 73 return nil, ErrMatrixNotSquare 74 } 75 la = append(la, row...) 76 } 77 78 index := alpha.LetterIndex() 79 r, c := rSeq.Len()+1, qSeq.Len()+1 80 table := make([]int, r*c) 81 for j := range table[1:c] { 82 table[j+1] = table[j] + la[index[qSeq[j]]] 83 } 84 85 for i := 1; i < r; i++ { 86 for j := 1; j < c; j++ { 87 var ( 88 rVal = index[rSeq[i-1]] 89 qVal = index[qSeq[j-1]] 90 ) 91 if rVal < 0 { 92 return nil, fmt.Errorf("align: illegal letter %q at position %d in rSeq", rSeq[i-1], i-1) 93 } 94 if qVal < 0 { 95 return nil, fmt.Errorf("align: illegal letter %q at position %d in qSeq", qSeq[j-1], j-1) 96 } 97 p := i*c + j 98 99 diagScore := table[p-c-1] + la[rVal*let+qVal] 100 upScore := table[p-c] + la[rVal*let] 101 leftScore := table[p-1] + la[qVal] 102 103 table[p] = max3(diagScore, upScore, leftScore) 104 } 105 } 106 if debugFitted { 107 drawFittedTableType(rSeq, qSeq, index, table, a) 108 } 109 110 var aln []feat.Pair 111 score, last := 0, diag 112 max := minInt 113 var ( 114 i int 115 j = c - 1 116 qVal int 117 ) 118 for { 119 qVal = index[qSeq[j-1]] 120 if qVal >= 0 { 121 break 122 } 123 j-- 124 } 125 for y := 1; y < r; y++ { 126 v := table[(y*c)+c-1] 127 rVal := index[rSeq[y-1]] 128 if rVal < 0 { 129 continue 130 } 131 if v >= max && la[rVal*let+qVal] >= 0 { 132 i = y 133 max = v 134 } 135 } 136 maxI, maxJ := i, j 137 for i > 0 && j > 0 { 138 var ( 139 rVal = index[rSeq[i-1]] 140 qVal = index[qSeq[j-1]] 141 ) 142 switch p := i*c + j; table[p] { 143 case table[p-c-1] + la[rVal*let+qVal]: 144 if last != diag { 145 aln = append(aln, &featPair{ 146 a: feature{start: i, end: maxI}, 147 b: feature{start: j, end: maxJ}, 148 score: score, 149 }) 150 maxI, maxJ = i, j 151 score = 0 152 } 153 score += table[p] - table[p-c-1] 154 i-- 155 j-- 156 last = diag 157 case table[p-c] + la[rVal*let]: 158 if last != up && p != len(table)-1 { 159 aln = append(aln, &featPair{ 160 a: feature{start: i, end: maxI}, 161 b: feature{start: j, end: maxJ}, 162 score: score, 163 }) 164 maxI, maxJ = i, j 165 score = 0 166 } 167 score += table[p] - table[p-c] 168 i-- 169 last = up 170 case table[p-1] + la[qVal]: 171 if last != left && p != len(table)-1 { 172 aln = append(aln, &featPair{ 173 a: feature{start: i, end: maxI}, 174 b: feature{start: j, end: maxJ}, 175 score: score, 176 }) 177 maxI, maxJ = i, j 178 score = 0 179 } 180 score += table[p] - table[p-1] 181 j-- 182 last = left 183 default: 184 panic(fmt.Sprintf("align: fitted nw internal error: no path at row: %d col:%d\n", i, j)) 185 } 186 } 187 188 aln = append(aln, &featPair{ 189 a: feature{start: i, end: maxI}, 190 b: feature{start: j, end: maxJ}, 191 score: score, 192 }) 193 194 for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { 195 aln[i], aln[j] = aln[j], aln[i] 196 } 197 198 return aln, nil 199 }