forked from biogo/hts
-
Notifications
You must be signed in to change notification settings - Fork 0
/
strategy.go
83 lines (73 loc) · 2.05 KB
/
strategy.go
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}}
}