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