// Set the letter at position pos to l. func (self *Seq) Set(pos seq.Position, l alphabet.QLetter) { if pos.Ind != 0 || pos.Pos < self.offset || pos.Pos >= self.End() { panic("packed: index out of range") } p := pos.Pos + int(self.S.LeftPad) - self.offset pIndex, pOffset := p/4, uint(p%4) self.S.Letters[pIndex] &^= 0x3 << (2 * pOffset) self.S.Letters[pIndex] |= alphabet.Pack(self.alphabet.IndexOf(l.L)) << (2 * pOffset) }
// Pack bytes that conform to a into a slice of alphabet.Pack. Panics if a byte in s does not conform. func PackLetters(a alphabet.Nucleic, s ...alphabet.Letter) (p *Packing) { p = &Packing{ Letters: make([]alphabet.Pack, (len(s)+3)/4), RightPad: int8(4-len(s)&3) & 3, } for i, c := range s { if !a.IsValid(c) { panic("packed: invalid letter") } p.Letters[i/4] <<= 2 p.Letters[i/4] |= alphabet.Pack(a.IndexOf(c)) } if sc := uint(len(s)) & 3; sc != 0 { p.Letters[len(p.Letters)-1] <<= (4 - sc) << 1 } return }
// Append QLetters to the sequence. func (self *Seq) AppendQLetters(a ...alphabet.QLetter) (err error) { defer func() { if r := recover(); r != nil { _, pos := self.alphabet.AllValidQLetter(a) err = bio.NewError(fmt.Sprintf("Encoding error: %s %q at position %d.", r, a[pos], pos), 1, a) } }() i := 0 for ; self.S.RightPad > 0 && i < len(a); i, self.S.RightPad = i+1, self.S.RightPad-1 { if !self.alphabet.IsValid(a[i].L) { return bio.NewError(fmt.Sprintf("Invalid letter %q at position %d.", a[i], i), 0, nil) } self.S.Letters[len(self.S.Letters)-1] |= alphabet.Pack(self.alphabet.IndexOf(a[i].L)) << (4 - byte(self.S.RightPad)) } self.S.Letters = append(self.S.Letters, PackQLetters(self.alphabet, a[i:]...).Letters...) return }