@gmod/bam 7.1.0 → 7.1.2
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 +14 -0
- package/dist/bamFile.js +73 -7
- 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/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 +14 -0
- package/esm/bamFile.js +73 -7
- 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/util.js +50 -21
- package/esm/util.js.map +1 -1
- package/package.json +3 -3
- package/src/bai.ts +10 -15
- package/src/bamFile.ts +98 -12
- package/src/csi.ts +5 -4
- package/src/indexFile.ts +22 -1
- 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/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
|
|