@gmod/bam 7.1.1 → 7.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/bai.js +10 -14
- package/dist/bai.js.map +1 -1
- package/dist/bamFile.d.ts +5 -0
- package/dist/bamFile.js +17 -0
- package/dist/bamFile.js.map +1 -1
- package/dist/csi.js +5 -4
- package/dist/csi.js.map +1 -1
- package/dist/indexFile.d.ts +6 -0
- package/dist/indexFile.js +11 -0
- package/dist/indexFile.js.map +1 -1
- package/dist/record.d.ts +1 -0
- package/dist/record.js +59 -0
- package/dist/record.js.map +1 -1
- package/dist/util.js +50 -21
- package/dist/util.js.map +1 -1
- package/esm/bai.js +10 -14
- package/esm/bai.js.map +1 -1
- package/esm/bamFile.d.ts +5 -0
- package/esm/bamFile.js +17 -0
- package/esm/bamFile.js.map +1 -1
- package/esm/csi.js +5 -4
- package/esm/csi.js.map +1 -1
- package/esm/indexFile.d.ts +6 -0
- package/esm/indexFile.js +11 -0
- package/esm/indexFile.js.map +1 -1
- package/esm/record.d.ts +1 -0
- package/esm/record.js +59 -0
- package/esm/record.js.map +1 -1
- package/esm/util.js +50 -21
- package/esm/util.js.map +1 -1
- package/package.json +2 -2
- package/src/bai.ts +10 -15
- package/src/bamFile.ts +21 -0
- package/src/csi.ts +5 -4
- package/src/indexFile.ts +22 -1
- package/src/record.ts +62 -0
- package/src/util.ts +55 -20
package/src/csi.ts
CHANGED
|
@@ -215,12 +215,13 @@ export default class CSI extends IndexFile {
|
|
|
215
215
|
|
|
216
216
|
const chunks = []
|
|
217
217
|
// Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned
|
|
218
|
+
const { binIndex } = ba
|
|
218
219
|
for (const [start, end] of overlappingBins) {
|
|
219
220
|
for (let bin = start; bin <= end; bin++) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
for (
|
|
223
|
-
chunks.push(
|
|
221
|
+
const binChunks = binIndex[bin]
|
|
222
|
+
if (binChunks) {
|
|
223
|
+
for (let i = 0, l = binChunks.length; i < l; i++) {
|
|
224
|
+
chunks.push(binChunks[i]!)
|
|
224
225
|
}
|
|
225
226
|
}
|
|
226
227
|
}
|
package/src/indexFile.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import Chunk from './chunk.ts'
|
|
2
|
-
import { BaseOpts } from './util.ts'
|
|
2
|
+
import { BaseOpts, optimizeChunks } from './util.ts'
|
|
3
3
|
|
|
4
4
|
import type { GenericFilehandle } from 'generic-filehandle2'
|
|
5
5
|
|
|
6
|
+
export interface Region {
|
|
7
|
+
refId: number
|
|
8
|
+
start: number
|
|
9
|
+
end: number
|
|
10
|
+
}
|
|
11
|
+
|
|
6
12
|
export default abstract class IndexFile {
|
|
7
13
|
public filehandle: GenericFilehandle
|
|
8
14
|
public renameRefSeq: (s: string) => string
|
|
@@ -30,4 +36,19 @@ export default abstract class IndexFile {
|
|
|
30
36
|
end: number,
|
|
31
37
|
opts?: BaseOpts,
|
|
32
38
|
): Promise<Chunk[]>
|
|
39
|
+
|
|
40
|
+
async estimatedBytesForRegions(regions: Region[], opts?: BaseOpts) {
|
|
41
|
+
const blockResults = await Promise.all(
|
|
42
|
+
regions.map(r => this.blocksForRange(r.refId, r.start, r.end, opts)),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
// Deduplicate and merge overlapping blocks across all regions
|
|
46
|
+
const mergedBlocks = optimizeChunks(blockResults.flat())
|
|
47
|
+
|
|
48
|
+
let total = 0
|
|
49
|
+
for (const block of mergedBlocks) {
|
|
50
|
+
total += block.fetchedSize()
|
|
51
|
+
}
|
|
52
|
+
return total
|
|
53
|
+
}
|
|
33
54
|
}
|
package/src/record.ts
CHANGED
|
@@ -98,6 +98,68 @@ export default class BamRecord {
|
|
|
98
98
|
return str
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
get NUMERIC_MD() {
|
|
102
|
+
let p =
|
|
103
|
+
this.b0 +
|
|
104
|
+
this.read_name_length +
|
|
105
|
+
this.num_cigar_bytes +
|
|
106
|
+
this.num_seq_bytes +
|
|
107
|
+
this.seq_length
|
|
108
|
+
|
|
109
|
+
const blockEnd = this.bytes.end
|
|
110
|
+
while (p < blockEnd) {
|
|
111
|
+
const tag =
|
|
112
|
+
String.fromCharCode(this.byteArray[p]!) +
|
|
113
|
+
String.fromCharCode(this.byteArray[p + 1]!)
|
|
114
|
+
const type = String.fromCharCode(this.byteArray[p + 2]!)
|
|
115
|
+
p += 3
|
|
116
|
+
|
|
117
|
+
if (tag === 'MD' && type === 'Z') {
|
|
118
|
+
const start = p
|
|
119
|
+
while (p < blockEnd && this.byteArray[p] !== 0) {
|
|
120
|
+
p++
|
|
121
|
+
}
|
|
122
|
+
return this.byteArray.subarray(start, p)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
switch (type) {
|
|
126
|
+
case 'A':
|
|
127
|
+
p += 1
|
|
128
|
+
break
|
|
129
|
+
case 'i':
|
|
130
|
+
case 'I':
|
|
131
|
+
case 'f':
|
|
132
|
+
p += 4
|
|
133
|
+
break
|
|
134
|
+
case 'c':
|
|
135
|
+
case 'C':
|
|
136
|
+
p += 1
|
|
137
|
+
break
|
|
138
|
+
case 's':
|
|
139
|
+
case 'S':
|
|
140
|
+
p += 2
|
|
141
|
+
break
|
|
142
|
+
case 'Z':
|
|
143
|
+
case 'H':
|
|
144
|
+
while (p <= blockEnd && this.byteArray[p++] !== 0) {}
|
|
145
|
+
break
|
|
146
|
+
case 'B': {
|
|
147
|
+
const Btype = String.fromCharCode(this.byteArray[p++]!)
|
|
148
|
+
const limit = this._dataView.getInt32(p, true)
|
|
149
|
+
p += 4
|
|
150
|
+
if (Btype === 'i' || Btype === 'I' || Btype === 'f') {
|
|
151
|
+
p += limit << 2
|
|
152
|
+
} else if (Btype === 's' || Btype === 'S') {
|
|
153
|
+
p += limit << 1
|
|
154
|
+
} else if (Btype === 'c' || Btype === 'C') {
|
|
155
|
+
p += limit
|
|
156
|
+
}
|
|
157
|
+
break
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return undefined
|
|
162
|
+
}
|
|
101
163
|
get tags() {
|
|
102
164
|
let p =
|
|
103
165
|
this.b0 +
|
package/src/util.ts
CHANGED
|
@@ -25,33 +25,68 @@ export function makeOpts(obj: AbortSignal | BaseOpts = {}): BaseOpts {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export function optimizeChunks(chunks: Chunk[], lowest?: Offset) {
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (chunks.length === 0) {
|
|
28
|
+
const n = chunks.length
|
|
29
|
+
if (n === 0) {
|
|
32
30
|
return chunks
|
|
33
31
|
}
|
|
34
32
|
|
|
35
|
-
chunks
|
|
33
|
+
// Pre-filter chunks below lowest threshold before sorting
|
|
34
|
+
let filtered: Chunk[]
|
|
35
|
+
if (lowest) {
|
|
36
|
+
const lowestBlock = lowest.blockPosition
|
|
37
|
+
const lowestData = lowest.dataPosition
|
|
38
|
+
filtered = []
|
|
39
|
+
for (let i = 0; i < n; i++) {
|
|
40
|
+
const chunk = chunks[i]!
|
|
41
|
+
const maxv = chunk.maxv
|
|
42
|
+
const cmp =
|
|
43
|
+
maxv.blockPosition - lowestBlock || maxv.dataPosition - lowestData
|
|
44
|
+
if (cmp > 0) {
|
|
45
|
+
filtered.push(chunk)
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
if (filtered.length === 0) {
|
|
49
|
+
return filtered
|
|
50
|
+
}
|
|
51
|
+
} else {
|
|
52
|
+
filtered = chunks
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
filtered.sort((c0, c1) => {
|
|
36
56
|
const dif = c0.minv.blockPosition - c1.minv.blockPosition
|
|
37
|
-
return dif
|
|
57
|
+
return dif !== 0 ? dif : c0.minv.dataPosition - c1.minv.dataPosition
|
|
38
58
|
})
|
|
39
59
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
60
|
+
const mergedChunks: Chunk[] = []
|
|
61
|
+
let lastChunk = filtered[0]!
|
|
62
|
+
mergedChunks.push(lastChunk)
|
|
63
|
+
|
|
64
|
+
let lastMinBlock = lastChunk.minv.blockPosition
|
|
65
|
+
let lastMaxBlock = lastChunk.maxv.blockPosition
|
|
66
|
+
|
|
67
|
+
for (let i = 1; i < filtered.length; i++) {
|
|
68
|
+
const chunk = filtered[i]!
|
|
69
|
+
const chunkMinBlock = chunk.minv.blockPosition
|
|
70
|
+
const chunkMaxBlock = chunk.maxv.blockPosition
|
|
71
|
+
// Inlined canMergeBlocks: check if chunks are close enough to merge
|
|
72
|
+
if (
|
|
73
|
+
chunkMinBlock - lastMaxBlock < 65000 &&
|
|
74
|
+
chunkMaxBlock - lastMinBlock < 5000000
|
|
75
|
+
) {
|
|
76
|
+
const chunkMaxv = chunk.maxv
|
|
77
|
+
const lastMaxv = lastChunk.maxv
|
|
78
|
+
const cmp =
|
|
79
|
+
chunkMaxBlock - lastMaxBlock ||
|
|
80
|
+
chunkMaxv.dataPosition - lastMaxv.dataPosition
|
|
81
|
+
if (cmp > 0) {
|
|
82
|
+
lastChunk.maxv = chunkMaxv
|
|
83
|
+
lastMaxBlock = chunkMaxBlock
|
|
54
84
|
}
|
|
85
|
+
} else {
|
|
86
|
+
mergedChunks.push(chunk)
|
|
87
|
+
lastChunk = chunk
|
|
88
|
+
lastMinBlock = chunkMinBlock
|
|
89
|
+
lastMaxBlock = chunkMaxBlock
|
|
55
90
|
}
|
|
56
91
|
}
|
|
57
92
|
|