func (s *SeedSequence) Shift(bases int) {
	s.segments[0] += bases
	if s.rc {
		s.inset -= bases
	} else {
		s.offset -= bases
	}
}
Shift adds or removes bases before the first seed, adjusting the offset to compensate
package seeds
import (
	"fmt"
	"github.com/jteutenberg/downpore/util"
	"log"
	"sort"
)
type SeedSequence struct {
	segments          []int  
	id                int
	name              *string
	length            int
	offset            int  
	inset             int  
	reverseComplement *SeedSequence
	rc                bool           
	Parent            *SeedSequence  
}
type SeedMatch struct {
	MatchA                 []int
	MatchB                 []int
	MismatchCount          int
	SeqA                   *SeedSequence
	SeqB                   *SeedSequence
	QueryID                int   
	ReverseComplementQuery bool  
}
func LoadSequence(segments []int,k int) *SeedSequence {
	s := SeedSequence{segments: segments}
	s.length = -k
	for i := 0; i < len(segments); i += 2 {
		s.length += segments[i]+k
	}
	return &s
}
func (s *SeedSequence) SubSequence(start, end, length, offset, inset int) *SeedSequence {
	subs := SeedSequence{segments: s.segments[start*2 : end*2+3], length: length, offset: offset, inset: inset, rc: s.rc, id: s.id, Parent: s}
	return &subs
}
func (s *SeedSequence) Trimmed(startOffset, startSeed, endOffset, endSeed, k int) (*SeedSequence, int) {
	for startSeed > 0 && startOffset >= s.segments[startSeed*2]+k {
		startOffset -= s.segments[startSeed*2] + k
		startSeed--
	}
	numSeeds := len(s.segments) / 2
	for endSeed < numSeeds-1 && endOffset >= s.segments[endSeed*2+2]+k {
		endOffset -= s.segments[endSeed*2+2] + k
		endSeed++
	}
	offset := s.GetSeedOffset(startSeed, k) - startOffset
	inset := s.GetSeedOffsetFromEnd(endSeed, k) - endOffset
	var trimmed *SeedSequence
	if s.rc {
		trimmed = s.SubSequence(startSeed, endSeed, s.length-offset-inset, s.offset+inset, s.inset+offset)
	} else {
		trimmed = s.SubSequence(startSeed, endSeed, s.length-offset-inset, s.offset+offset, s.inset+inset)
	}
	segments := make([]int, len(trimmed.segments), len(trimmed.segments))
	copy(segments, trimmed.segments)
	segments[0] = startOffset
	segments[len(trimmed.segments)-1] = endOffset
	trimmed.segments = segments
	return trimmed, startSeed
}
func (s *SeedSequence) Reduced(whitelist *util.IntSet, k int, minSeeds int, makeIndex bool) (reduced *SeedSequence, index []int) {
	count := 0
	n := len(s.segments)
	prev := -1
	for i := 1; i < n; i += 2 {
		next := s.segments[i]
		if next != prev && whitelist.Contains(uint(next)) {
			count++
			prev = next
		}
	}
	if count < minSeeds {
		return nil, nil
	}
	segs := make([]int, count*2+1)
	offset := s.segments[0]
	if makeIndex {
		index = make([]int, count)
	}
	prev = -1
	j := 0
	for i := 1; i < n; i += 2 {
		seed := s.segments[i]
		if prev != seed && whitelist.Contains(uint(seed)) {
			segs[j] = offset
			segs[j+1] = seed
			if makeIndex {
				index[j/2] = i / 2  
			}
			j += 2
			offset = s.segments[i+1]
			prev = seed
		} else {
			offset += s.segments[i+1] + k
		}
	}
	segs[j] = offset
	return &SeedSequence{segments: segs, length: s.length, offset: s.offset, inset: s.inset, rc: s.rc, id: s.id, Parent: s}, index
}
func ReverseComplement(seed uint, k uint) uint {
	rc := uint(0)
	for j := uint(0); j < k; j++ {
		rc = (rc << 2) | ((seed ^ 3) & 3)
		seed = seed >> 2
	}
	return rc
}
func (s *SeedSequence) ReverseComplement(k int, index *SeedIndex) *SeedSequence {
	if s.reverseComplement != nil {
		return s.reverseComplement
	}
	n := len(s.segments)
	seg := make([]int, n, n)
	n--
	for i, seed := range s.segments {
		if i&1 == 0 {
			seg[n-i] = seed
		} else {
			seed = index.seedMap[seed]
			rc := 0
			for j := 0; j < k; j++ {
				rc = (rc << 2) | ((seed ^ 3) & 3)
				seed = seed >> 2
			}
			seg[n-i] = int(index.kmerMap[rc])
		}
	}
	ns := SeedSequence{seg, s.id, nil, s.length, s.offset, s.inset, s, !s.rc, s.Parent}
	return &ns
}
func (s *SeedSequence) IsReverseComplement() bool {
	return s.rc
}