Files

54 lines
1.6 KiB
Go
Raw Permalink Normal View History

// Package obisimilarity holds what the tools that compare nucleotide sequences
// by the length of their longest common subsequence (obiclust, obialign) have
// in common: the scoring of a pair against a threshold, with the lossless
// 4-mer filter that avoids most of the alignments, and the index that finds
// the sequences a given one can be similar to.
//
// The scoring follows the arithmetic of sumaclust and sumatra (integer
// truncations, floating point comparisons) so that the same pairs are
// accepted with the same scores.
package obisimilarity
// Table4 is the 4-mer occurrence table of a sequence: one saturating counter
// per word, and the number of occurrences that did not fit in the counters.
type Table4 struct {
Count [256]uint8
Overflow int
}
// NewTable4 counts the 4-mers of a sequence made of the letters a, c, g
// and t. The 2-bit code of a base is (letter>>1)&3, i.e. a=0, c=1, t=2, g=3.
func NewTable4(seq []byte) *Table4 {
t := new(Table4)
t.Fill(seq)
return t
}
// Fill counts the 4-mers of seq in a zeroed table.
func (t *Table4) Fill(seq []byte) {
if len(seq) < 4 {
return
}
w := uint(0)
for i, c := range seq {
w = (w<<2 | uint(c>>1)&3) & 0xFF
if i < 3 {
continue
}
if t.Count[w] < 255 {
t.Count[w]++
} else {
t.Overflow++
}
}
}
// minCommonWords is the minimum number of 4-mers that two sequences must
// share when the longest has length reflen and they have a common
// subsequence of length lcs.
func minCommonWords(reflen, lcs int) int {
nbfrag := (reflen-lcs)*2 + 1
smin := lcs / nbfrag
r := lcs - smin*nbfrag
return max(smin-2, 0)*r + max(smin-3, 0)*(nbfrag-r)
}