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  }