1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
|
// Copyright ©2015 The bíogo Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package index
import (
"github.com/biogo/hts/bgzf"
)
// MergeStrategy represents a chunk compression strategy.
type MergeStrategy func([]bgzf.Chunk) []bgzf.Chunk
var (
// Identity leaves the []bgzf.Chunk unaltered.
Identity MergeStrategy = identity
// Adjacent merges contiguous bgzf.Chunks.
Adjacent MergeStrategy = adjacent
// Squash merges all bgzf.Chunks into a single bgzf.Chunk.
Squash MergeStrategy = squash
)
// CompressorStrategy returns a MergeStrategy that will merge bgzf.Chunks
// that have a distance between BGZF block starts less than or equal
// to near.
func CompressorStrategy(near int64) MergeStrategy {
return func(chunks []bgzf.Chunk) []bgzf.Chunk {
if len(chunks) == 0 {
return nil
}
for c := 1; c < len(chunks); c++ {
leftChunk := chunks[c-1]
rightChunk := &chunks[c]
if leftChunk.End.File+near >= rightChunk.Begin.File {
rightChunk.Begin = leftChunk.Begin
if vOffset(leftChunk.End) > vOffset(rightChunk.End) {
rightChunk.End = leftChunk.End
}
chunks = append(chunks[:c-1], chunks[c:]...)
c--
}
}
return chunks
}
}
func identity(chunks []bgzf.Chunk) []bgzf.Chunk { return chunks }
func adjacent(chunks []bgzf.Chunk) []bgzf.Chunk {
if len(chunks) == 0 {
return nil
}
for c := 1; c < len(chunks); c++ {
leftChunk := chunks[c-1]
rightChunk := &chunks[c]
leftEndOffset := vOffset(leftChunk.End)
if leftEndOffset >= vOffset(rightChunk.Begin) {
rightChunk.Begin = leftChunk.Begin
if leftEndOffset > vOffset(rightChunk.End) {
rightChunk.End = leftChunk.End
}
chunks = append(chunks[:c-1], chunks[c:]...)
c--
}
}
return chunks
}
func squash(chunks []bgzf.Chunk) []bgzf.Chunk {
if len(chunks) == 0 {
return nil
}
left := chunks[0].Begin
right := chunks[0].End
for _, c := range chunks[1:] {
if vOffset(c.End) > vOffset(right) {
right = c.End
}
}
return []bgzf.Chunk{{Begin: left, End: right}}
}
|