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  }