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