// Convert a Kmer into a string of bases func Format(kmer Kmer, k int, alpha alphabet.Alphabet) (string, error) { if alpha.Len() != 4 { return "", ErrBadAlphabet } kmertext := make([]byte, k) for i := k - 1; i >= 0; i, kmer = i-1, kmer>>2 { kmertext[i] = byte(alpha.Letter(int(kmer & 3))) } return string(kmertext), nil }
func makeTable(alpha alphabet.Alphabet, alnmat mat) align.SW { match := alnmat[0] mismatch := alnmat[1] gap := alnmat[2] sw := make(align.SW, alpha.Len()) for i := range sw { row := make([]int, alpha.Len()) for j := range row { row[j] = mismatch } row[i] = match sw[i] = row } for i := range sw { sw[0][i] = gap sw[i][0] = gap } return sw }
// Match generates a penalty matrix for a. // Perfect matches have penalty match. // Gaps have penalty gap. // Everything else has penalty mismatch. // For example, Match(alphabet.DNA, 0, 1, -1) generates the original Needleman-Wunsch penalty matrix. func Match(a alphabet.Alphabet, gap, match, mismatch int) [][]int { l := a.Len() arr := make([]int, l*l) g := a.IndexOf(a.Gap()) for i := 0; i < l; i++ { for j := 0; j < l; j++ { score := mismatch switch { case i == g, j == g: score = gap case i == j: score = match } arr[i*l+j] = score } } x := make([][]int, l) for i := 0; i < l; i++ { x[i] = arr[i*l : (i+1)*l] } return x }
func (a Fitted) alignQLetters(rSeq, qSeq alphabet.QLetters, alpha alphabet.Alphabet) ([]feat.Pair, error) { let := len(a) la := make([]int, 0, let*let) for _, row := range a { if len(row) != let { return nil, ErrMatrixNotSquare } la = append(la, row...) } index := alpha.LetterIndex() r, c := rSeq.Len()+1, qSeq.Len()+1 table := make([]int, r*c) for j := range table[1:c] { table[j+1] = table[j] + la[index[qSeq[j].L]] } for i := 1; i < r; i++ { for j := 1; j < c; j++ { var ( rVal = index[rSeq[i-1].L] qVal = index[qSeq[j-1].L] ) if rVal < 0 { return nil, fmt.Errorf("align: illegal letter %q at position %d in rSeq", rSeq[i-1].L, i-1) } if qVal < 0 { return nil, fmt.Errorf("align: illegal letter %q at position %d in qSeq", qSeq[j-1].L, j-1) } p := i*c + j diagScore := table[p-c-1] + la[rVal*let+qVal] upScore := table[p-c] + la[rVal*let] leftScore := table[p-1] + la[qVal] table[p] = max3(diagScore, upScore, leftScore) } } if debugFitted { drawFittedTableQLetters(rSeq, qSeq, index, table, a) } var aln []feat.Pair score, last := 0, diag max := minInt var ( i int j = c - 1 qVal int ) for { qVal = index[qSeq[j-1].L] if qVal >= 0 { break } j-- } for y := 1; y < r; y++ { v := table[(y*c)+c-1] rVal := index[rSeq[y-1].L] if rVal < 0 { continue } if v >= max && la[rVal*let+qVal] >= 0 { i = y max = v } } maxI, maxJ := i, j for i > 0 && j > 0 { var ( rVal = index[rSeq[i-1].L] qVal = index[qSeq[j-1].L] ) switch p := i*c + j; table[p] { case table[p-c-1] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-c-1] i-- j-- last = diag case table[p-c] + la[rVal*let]: if last != up && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-c] i-- last = up case table[p-1] + la[qVal]: if last != left && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-1] j-- last = left default: panic(fmt.Sprintf("align: fitted nw internal error: no path at row: %d col:%d\n", i, j)) } } aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { aln[i], aln[j] = aln[j], aln[i] } return aln, nil }
func (a SWAffine) alignLetters(rSeq, qSeq alphabet.Letters, alpha alphabet.Alphabet) ([]feat.Pair, error) { let := len(a.Matrix) if let < alpha.Len() { return nil, ErrMatrixWrongSize{Size: let, Len: alpha.Len()} } la := make([]int, 0, let*let) for _, row := range a.Matrix { if len(row) != let { return nil, ErrMatrixNotSquare } la = append(la, row...) } r, c := rSeq.Len()+1, qSeq.Len()+1 table := make([][3]int, r*c) var ( index = alpha.LetterIndex() maxS, maxI, maxJ = 0, 0, 0 score int scores [3]int ) for i := 1; i < r; i++ { for j := 1; j < c; j++ { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) if rVal < 0 || qVal < 0 { continue } p := i*c + j scores = [3]int{ diag: table[p-c-1][diag], up: table[p-c-1][up], left: table[p-c-1][left], } score = max(&scores) matched := score == scores[diag] score += la[rVal*let+qVal] switch { case score > 0: if score >= maxS && matched { maxS, maxI, maxJ = score, i, j } default: score = 0 } table[p][diag] = score score = max2( table[p-c][diag]+a.GapOpen+la[rVal*let], table[p-c][up]+la[rVal*let], ) if score < 0 { score = 0 } table[p][up] = score score = max2( table[p-1][diag]+a.GapOpen+la[qVal], table[p-1][left]+la[qVal], ) if score < 0 { score = 0 } table[p][left] = score } } if debugSmithAffine { drawSWAffineTableLetters(rSeq, qSeq, index, table, a) } var aln []feat.Pair score, last, layer := 0, diag, diag i, j := maxI, maxJ loop: for i > 0 && j > 0 { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) if rVal < 0 || qVal < 0 { continue } switch p := i*c + j; table[p][layer] { case 0: break loop case table[p-c][up] + la[rVal*let]: if last != up && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c][up] i-- layer = up last = up case table[p-1][left] + la[qVal]: if last != left && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-1][left] j-- layer = left last = left case table[p-c][diag] + a.GapOpen + la[rVal*let]: if last != up && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c][diag] i-- layer = diag last = up case table[p-1][diag] + a.GapOpen + la[qVal]: if last != left && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-1][diag] j-- layer = diag last = left case table[p-c-1][diag] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c-1][diag] i-- j-- layer = diag last = diag case table[p-c-1][up] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c-1][up] i-- j-- layer = up last = diag case table[p-c-1][left] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c-1][left] i-- j-- layer = left last = diag default: panic(fmt.Sprintf("align: sw affine internal error: no path at row: %d col:%d layer:%s\n", i, j, "mul"[layer:layer+1])) } } aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { aln[i], aln[j] = aln[j], aln[i] } return aln, nil }
func (a SW) alignLetters(rSeq, qSeq alphabet.Letters, alpha alphabet.Alphabet) ([]feat.Pair, error) { let := len(a) la := make([]int, 0, let*let) for _, row := range a { if len(row) != let { return nil, ErrMatrixNotSquare } la = append(la, row...) } r, c := rSeq.Len()+1, qSeq.Len()+1 table := make([]int, r*c) var ( index = alpha.LetterIndex() maxS, maxI, maxJ = 0, 0, 0 score int scores [3]int ) for i := 1; i < r; i++ { for j := 1; j < c; j++ { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) if rVal < 0 || qVal < 0 { continue } p := i*c + j scores = [3]int{ diag: table[p-c-1] + la[rVal*let+qVal], up: table[p-c] + la[rVal*let], left: table[p-1] + la[qVal], } score = max(&scores) switch { case score > 0: if score >= maxS && score == scores[diag] { maxS, maxI, maxJ = score, i, j } default: score = 0 } table[p] = score } } if debugSmith { drawSWTableLetters(rSeq, qSeq, index, table, a) } var aln []feat.Pair score, last := 0, diag i, j := maxI, maxJ loop: for i > 0 && j > 0 { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) if rVal < 0 || qVal < 0 { continue } switch p := i*c + j; table[p] { case 0: break loop case table[p-c-1] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-c-1] i-- j-- last = diag case table[p-c] + la[rVal*let]: if last != up { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-c] i-- last = up case table[p-1] + la[qVal]: if last != left { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-1] j-- last = left default: panic(fmt.Sprintf("align: sw internal error: no path at row: %d col:%d\n", i, j)) } } aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { aln[i], aln[j] = aln[j], aln[i] } return aln, nil }
func (a SW) alignQLetters(rSeq, qSeq alphabet.QLetters, alpha alphabet.Alphabet) ([]feat.Pair, error) { let := len(a) if let < alpha.Len() { return nil, ErrMatrixWrongSize{Size: let, Len: alpha.Len()} } la := make([]int, 0, let*let) for _, row := range a { if len(row) != let { return nil, ErrMatrixNotSquare } la = append(la, row...) } r, c := rSeq.Len()+1, qSeq.Len()+1 table := make([]int, r*c) var ( index = alpha.LetterIndex() maxS, maxI, maxJ = 0, 0, 0 score int ) for i := 1; i < r; i++ { for j := 1; j < c; j++ { var ( rVal = index[rSeq[i-1].L] qVal = index[qSeq[j-1].L] ) if rVal < 0 { return nil, fmt.Errorf("align: illegal letter %q at position %d in rSeq", rSeq[i-1].L, i-1) } if qVal < 0 { return nil, fmt.Errorf("align: illegal letter %q at position %d in qSeq", qSeq[j-1].L, j-1) } p := i*c + j diagScore := table[p-c-1] + la[rVal*let+qVal] upScore := table[p-c] + la[rVal*let] leftScore := table[p-1] + la[qVal] score = max3(diagScore, upScore, leftScore) switch { case score > 0: if score >= maxS && score == diagScore { maxS, maxI, maxJ = score, i, j } default: score = 0 } table[p] = score } } if debugSmith { drawSWTableQLetters(rSeq, qSeq, index, table, a) } var aln []feat.Pair score, last := 0, diag i, j := maxI, maxJ loop: for i > 0 && j > 0 { var ( rVal = index[rSeq[i-1].L] qVal = index[qSeq[j-1].L] ) switch p := i*c + j; table[p] { case 0: break loop case table[p-c-1] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-c-1] i-- j-- last = diag case table[p-c] + la[rVal*let]: if last != up { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-c] i-- last = up case table[p-1] + la[qVal]: if last != left { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-1] j-- last = left default: panic(fmt.Sprintf("align: sw internal error: no path at row: %d col:%d\n", i, j)) } } aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { aln[i], aln[j] = aln[j], aln[i] } return aln, nil }
func (a NWAffine) alignLetters(rSeq, qSeq alphabet.Letters, alpha alphabet.Alphabet) ([]feat.Pair, error) { let := len(a.Matrix) la := make([]int, 0, let*let) for _, row := range a.Matrix { if len(row) != let { return nil, ErrMatrixNotSquare } la = append(la, row...) } index := alpha.LetterIndex() r, c := rSeq.Len()+1, qSeq.Len()+1 table := make([][3]int, r*c) table[0] = [3]int{ diag: 0, up: minInt, left: minInt, } table[1] = [3]int{ diag: minInt, up: minInt, left: a.GapOpen + la[index[qSeq[0]]], } for j := range table[2:c] { table[j+2] = [3]int{ diag: minInt, up: minInt, left: table[j+1][left] + la[index[qSeq[j+1]]], } } table[c] = [3]int{ diag: minInt, up: a.GapOpen + la[index[rSeq[0]]*let], left: minInt, } for i := 2; i < r; i++ { table[i*c] = [3]int{ diag: minInt, up: table[(i-1)*c][up] + la[index[rSeq[i-1]]*let], left: minInt, } } var scores [3]int for i := 1; i < r; i++ { for j := 1; j < c; j++ { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) if rVal < 0 || qVal < 0 { continue } p := i*c + j scores = [3]int{ diag: table[p-c-1][diag], up: table[p-c-1][up], left: table[p-c-1][left], } table[p][diag] = max(&scores) + la[rVal*let+qVal] table[p][up] = max2( add(table[p-c][diag], a.GapOpen+la[rVal*let]), add(table[p-c][up], la[rVal*let]), ) table[p][left] = max2( add(table[p-1][diag], a.GapOpen+la[qVal]), add(table[p-1][left], la[qVal]), ) } } if debugNeedleAffine { drawNWAffineTableLetters(rSeq, qSeq, index, table, a) } var ( aln []feat.Pair layer int ) score, last := 0, diag i, j := r-1, c-1 t := table[i*c+j] best := t[0] for i, s := range t[1:] { if s > best { best, layer = s, i+1 } } maxI, maxJ := i, j for i > 0 && j > 0 { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) if rVal < 0 || qVal < 0 { continue } switch p := i*c + j; table[p][layer] { case table[p-c][up] + la[rVal*let]: if last != up && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c][up] i-- layer = up last = up case table[p-1][left] + la[qVal]: if last != left && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-1][left] j-- layer = left last = left case table[p-c][diag] + a.GapOpen + la[rVal*let]: if last != up && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c][diag] i-- layer = diag last = up case table[p-1][diag] + a.GapOpen + la[qVal]: if last != left && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-1][diag] j-- layer = diag last = left case table[p-c-1][up] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c-1][up] i-- j-- layer = up last = diag case table[p-c-1][left] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c-1][left] i-- j-- layer = left last = diag case table[p-c-1][diag] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c-1][diag] i-- j-- layer = diag last = diag default: panic(fmt.Sprintf("align: nw affine internal error: no path at row: %d col:%d layer:%s\n", i, j, "mul"[layer:layer+1])) } } aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) if i != j { aln = append(aln, &featPair{ a: feature{start: 0, end: i}, b: feature{start: 0, end: j}, score: table[i*c+j][last], }) } for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { aln[i], aln[j] = aln[j], aln[i] } return aln, nil }
func (a FittedAffine) alignLetters(rSeq, qSeq alphabet.Letters, alpha alphabet.Alphabet) ([]feat.Pair, error) { let := len(a.Matrix) la := make([]int, 0, let*let) for _, row := range a.Matrix { if len(row) != let { return nil, ErrMatrixNotSquare } la = append(la, row...) } index := alpha.LetterIndex() r, c := rSeq.Len()+1, qSeq.Len()+1 table := make([][3]int, r*c) table[0] = [3]int{ diag: 0, up: minInt, left: minInt, } table[1] = [3]int{ diag: minInt, up: minInt, } table[1][left] = a.GapOpen + la[index[qSeq[0]]] for j := range table[2:c] { table[j+2] = [3]int{ diag: minInt, up: minInt, left: table[j+1][left] + la[index[qSeq[j+1]]], } } table[c] = [3]int{ diag: minInt, left: minInt, } for i := 2; i < r; i++ { table[i*c] = [3]int{ diag: minInt, left: minInt, } } for i := 1; i < r; i++ { for j := 1; j < c; j++ { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) if rVal < 0 { return nil, fmt.Errorf("align: illegal letter %q at position %d in rSeq", rSeq[i-1], i-1) } if qVal < 0 { return nil, fmt.Errorf("align: illegal letter %q at position %d in qSeq", qSeq[j-1], j-1) } p := i*c + j diagScore := table[p-c-1][diag] upScore := table[p-c-1][up] leftScore := table[p-c-1][left] table[p][diag] = max3(diagScore, upScore, leftScore) + la[rVal*let+qVal] table[p][up] = max2( add(table[p-c][diag], a.GapOpen+la[rVal*let]), add(table[p-c][up], la[rVal*let]), ) table[p][left] = max2( add(table[p-1][diag], a.GapOpen+la[qVal]), add(table[p-1][left], la[qVal]), ) } } if debugFittedAffine { drawFittedAffineTableLetters(rSeq, qSeq, index, table, a) } var aln []feat.Pair score, last, layer := 0, diag, diag var ( i int j = c - 1 ) max := minInt for y := 1; y < r; y++ { v := table[(y*c)+c-1][diag] if v >= max { i = y max = v } } maxI, maxJ := i, j for i > 0 && j > 0 { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) switch p := i*c + j; table[p][layer] { case table[p-c][up] + la[rVal*let]: if last != up && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c][up] i-- layer = up last = up case table[p-1][left] + la[qVal]: if last != left && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-1][left] j-- layer = left last = left case table[p-c][diag] + a.GapOpen + la[rVal*let]: if last != up && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c][diag] i-- layer = diag last = up case table[p-1][diag] + a.GapOpen + la[qVal]: if last != left && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-1][diag] j-- layer = diag last = left case table[p-c-1][up] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c-1][up] i-- j-- layer = up last = diag case table[p-c-1][left] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c-1][left] i-- j-- layer = left last = diag case table[p-c-1][diag] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p][layer] - table[p-c-1][diag] i-- j-- layer = diag last = diag default: 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])) } } aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { aln[i], aln[j] = aln[j], aln[i] } return aln, nil }
func (a NW) alignLetters(rSeq, qSeq alphabet.Letters, alpha alphabet.Alphabet) ([]feat.Pair, error) { let := len(a) if let < alpha.Len() { return nil, ErrMatrixWrongSize{Size: let, Len: alpha.Len()} } la := make([]int, 0, let*let) for _, row := range a { if len(row) != let { return nil, ErrMatrixNotSquare } la = append(la, row...) } index := alpha.LetterIndex() r, c := rSeq.Len()+1, qSeq.Len()+1 table := make([]int, r*c) for j := range table[1:c] { table[j+1] = table[j] + la[index[qSeq[j]]] } for i := 1; i < r; i++ { table[i*c] = table[(i-1)*c] + la[index[rSeq[i-1]]*let] } var scores [3]int for i := 1; i < r; i++ { for j := 1; j < c; j++ { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) if rVal < 0 || qVal < 0 { continue } p := i*c + j scores = [3]int{ diag: table[p-c-1] + la[rVal*let+qVal], up: table[p-c] + la[rVal*let], left: table[p-1] + la[qVal], } table[p] = max(&scores) } } if debugNeedle { drawNWTableLetters(rSeq, qSeq, index, table, a) } var aln []feat.Pair score, last := 0, diag i, j := r-1, c-1 maxI, maxJ := i, j for i > 0 && j > 0 { var ( rVal = index[rSeq[i-1]] qVal = index[qSeq[j-1]] ) if rVal < 0 || qVal < 0 { continue } switch p := i*c + j; table[p] { case table[p-c-1] + la[rVal*let+qVal]: if last != diag { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-c-1] i-- j-- last = diag case table[p-c] + la[rVal*let]: if last != up && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-c] i-- last = up case table[p-1] + la[qVal]: if last != left && p != len(table)-1 { aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) maxI, maxJ = i, j score = 0 } score += table[p] - table[p-1] j-- last = left default: panic(fmt.Sprintf("align: nw internal error: no path at row: %d col:%d\n", i, j)) } } aln = append(aln, &featPair{ a: feature{start: i, end: maxI}, b: feature{start: j, end: maxJ}, score: score, }) if i != j { aln = append(aln, &featPair{ a: feature{start: 0, end: i}, b: feature{start: 0, end: j}, score: table[i*c+j], }) } for i, j := 0, len(aln)-1; i < j; i, j = i+1, j-1 { aln[i], aln[j] = aln[j], aln[i] } return aln, nil }
func genCode(w io.Writer, m string, a alphabet.Alphabet) error { f, err := os.Open(m) if err != nil { return err } b, err := ioutil.ReadAll(f) if err != nil { return err } s := string(b) var ( ind = a.LetterIndex() ref []string perm []int mat [][]int row int lastBlank bool ) for _, l := range strings.Split(s, "\n") { nsl := noSpace(l) switch { case len(l) == 0: if !lastBlank { lastBlank = true fmt.Fprintln(w, "\t//") } case l[0] == ' ': ref = strings.Fields(nsl) perm = make([]int, a.Len()) for i, l := range ref { li := ind[l[0]] if li < 0 { continue } perm[li] = i } mat = make([][]int, a.Len()) for j := range mat { mat[j] = make([]int, a.Len()) } fallthrough case l[0] == '#': lastBlank = false fmt.Fprintf(w, "\t// %s\n", l) default: lastBlank = false fmt.Fprintf(w, "\t// %s\n", l) for col, f := range strings.Fields(nsl)[1:] { mat[ind[ref[row][0]]][ind[ref[col][0]]], err = strconv.Atoi(f) if err != nil { return err } } row++ } } fmt.Fprintf(w, "\t%s = [][]int{\n\t\t/* ", strings.Replace(m, ".", "_", -1)) for j := range mat { fmt.Printf("%c ", toUpper(a.Letter(j))) } fmt.Fprintln(w, "*/") for i := range mat { fmt.Printf("\t\t/* %c */ {", toUpper(a.Letter(i))) for j, e := range mat[i] { fmt.Fprint(w, e) if j < len(mat[i])-1 { fmt.Print(", ") } } fmt.Fprintln(w, "},") } fmt.Fprintln(w, "\t}") return nil }