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  }