@gmod/bam 7.6.2 → 7.7.1
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/dist/bai.d.ts +6 -3
- package/dist/bai.js +37 -16
- package/dist/bai.js.map +1 -1
- package/dist/bamFile.d.ts +3 -3
- package/dist/bamFile.js +39 -12
- package/dist/bamFile.js.map +1 -1
- package/dist/chunk.d.ts +0 -1
- package/dist/chunk.js +0 -5
- package/dist/chunk.js.map +1 -1
- package/dist/csi.d.ts +0 -2
- package/dist/csi.js +4 -11
- package/dist/csi.js.map +1 -1
- package/dist/indexFile.d.ts +2 -3
- package/dist/indexFile.js.map +1 -1
- package/dist/sam.js +8 -3
- package/dist/sam.js.map +1 -1
- package/dist/util.d.ts +3 -3
- package/dist/util.js +35 -4
- package/dist/util.js.map +1 -1
- package/dist/virtualOffset.d.ts +8 -3
- package/dist/virtualOffset.js +0 -3
- package/dist/virtualOffset.js.map +1 -1
- package/esm/bai.d.ts +6 -3
- package/esm/bai.js +37 -16
- package/esm/bai.js.map +1 -1
- package/esm/bamFile.d.ts +3 -3
- package/esm/bamFile.js +39 -12
- package/esm/bamFile.js.map +1 -1
- package/esm/chunk.d.ts +0 -1
- package/esm/chunk.js +0 -5
- package/esm/chunk.js.map +1 -1
- package/esm/csi.d.ts +0 -2
- package/esm/csi.js +4 -11
- package/esm/csi.js.map +1 -1
- package/esm/indexFile.d.ts +2 -3
- package/esm/indexFile.js.map +1 -1
- package/esm/sam.js +8 -3
- package/esm/sam.js.map +1 -1
- package/esm/util.d.ts +3 -3
- package/esm/util.js +35 -4
- package/esm/util.js.map +1 -1
- package/esm/virtualOffset.d.ts +8 -3
- package/esm/virtualOffset.js +0 -3
- package/esm/virtualOffset.js.map +1 -1
- package/package.json +1 -1
- package/src/bai.ts +50 -20
- package/src/bamFile.ts +38 -11
- package/src/chunk.ts +0 -8
- package/src/csi.ts +4 -10
- package/src/indexFile.ts +2 -3
- package/src/sam.ts +8 -3
- package/src/util.ts +42 -7
- package/src/virtualOffset.ts +9 -8
- package/dist/long.d.ts +0 -1
- package/dist/long.js +0 -17
- package/dist/long.js.map +0 -1
- package/esm/long.d.ts +0 -1
- package/esm/long.js +0 -14
- package/esm/long.js.map +0 -1
- package/src/long.ts +0 -16
package/esm/sam.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sam.js","sourceRoot":"","sources":["../src/sam.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACjC,MAAM,IAAI,GAA8D,EAAE,CAAA;IAC1E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACzC,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC,IAAI,CAAC;gBACR,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;gBACjB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;oBACnB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;oBACxB,
|
|
1
|
+
{"version":3,"file":"sam.js","sourceRoot":"","sources":["../src/sam.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACjC,MAAM,IAAI,GAA8D,EAAE,CAAA;IAC1E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACzC,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC,IAAI,CAAC;gBACR,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;gBACjB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;oBACnB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;oBACxB,qEAAqE;oBACrE,mEAAmE;oBACnE,uEAAuE;oBACvE,kEAAkE;oBAClE,gEAAgE;oBAChE,OAAO,CAAC,KAAK,CAAC,CAAC;wBACb,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;wBACvB,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAA;gBACnD,CAAC,CAAC;aACH,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
|
package/esm/util.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Chunk from './chunk.ts';
|
|
2
2
|
import { VirtualOffset } from './virtualOffset.ts';
|
|
3
|
-
import type {
|
|
3
|
+
import type { OffsetCoords } from './virtualOffset.ts';
|
|
4
4
|
export interface BamOpts {
|
|
5
5
|
viewAsPairs?: boolean;
|
|
6
6
|
pairAcrossChr?: boolean;
|
|
@@ -25,11 +25,11 @@ export interface BaseOpts {
|
|
|
25
25
|
*/
|
|
26
26
|
onProgress?: (bytesDownloaded: number, totalBytes?: number) => void;
|
|
27
27
|
}
|
|
28
|
-
export declare function optimizeChunks(chunks: Chunk[], lowest?:
|
|
28
|
+
export declare function optimizeChunks(chunks: Chunk[], lowest?: OffsetCoords): Chunk[];
|
|
29
29
|
export declare function parsePseudoBin(bytes: Uint8Array, offset: number): {
|
|
30
30
|
lineCount: number;
|
|
31
31
|
};
|
|
32
|
-
export declare function clampChunkEnds(chunks: Chunk[], extraBoundaries?: number
|
|
32
|
+
export declare function clampChunkEnds(chunks: Chunk[], extraBoundaries?: ArrayLike<number>): void;
|
|
33
33
|
export declare function parseRefSeqs(uncba: Uint8Array, start: number, renameRefSeq: (s: string) => string): {
|
|
34
34
|
chrToIndex: Record<string, number>;
|
|
35
35
|
indexToChr: {
|
package/esm/util.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import Chunk from "./chunk.js";
|
|
2
|
-
import { longFromBytesToUnsigned } from "./long.js";
|
|
3
2
|
import { VirtualOffset } from "./virtualOffset.js";
|
|
4
3
|
export function optimizeChunks(chunks, lowest) {
|
|
5
4
|
const n = chunks.length;
|
|
@@ -60,9 +59,20 @@ export function optimizeChunks(chunks, lowest) {
|
|
|
60
59
|
}
|
|
61
60
|
return mergedChunks;
|
|
62
61
|
}
|
|
62
|
+
// The pseudo-bin's mapped-record count, a little-endian uint64. Read as two
|
|
63
|
+
// 32-bit halves rather than via BigInt: exact up to Number.MAX_SAFE_INTEGER,
|
|
64
|
+
// which is far past any real record count, and allocates nothing.
|
|
63
65
|
export function parsePseudoBin(bytes, offset) {
|
|
66
|
+
const low = bytes[offset] |
|
|
67
|
+
(bytes[offset + 1] << 8) |
|
|
68
|
+
(bytes[offset + 2] << 16) |
|
|
69
|
+
(bytes[offset + 3] << 24);
|
|
70
|
+
const high = bytes[offset + 4] |
|
|
71
|
+
(bytes[offset + 5] << 8) |
|
|
72
|
+
(bytes[offset + 6] << 16) |
|
|
73
|
+
(bytes[offset + 7] << 24);
|
|
64
74
|
return {
|
|
65
|
-
lineCount:
|
|
75
|
+
lineCount: (high >>> 0) * 2 ** 32 + (low >>> 0),
|
|
66
76
|
};
|
|
67
77
|
}
|
|
68
78
|
// Tighten each chunk's endPosition (default: a full max-size BGZF block past
|
|
@@ -73,9 +83,30 @@ export function parsePseudoBin(bytes, offset) {
|
|
|
73
83
|
// least the true block end, so the clamped fetch still contains the whole block.
|
|
74
84
|
// Shrinks both the byte estimate and the actual fetch with no extra I/O.
|
|
75
85
|
export function clampChunkEnds(chunks, extraBoundaries = []) {
|
|
76
|
-
|
|
86
|
+
if (chunks.length === 0) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// A plain array, sized once and filled by index. Not a Float64Array: this
|
|
90
|
+
// runs once per reference, and an assembly with tens of thousands of unplaced
|
|
91
|
+
// scaffolds (cho.bam.bai has 28751 references) pays the allocation that many
|
|
92
|
+
// times over, where each individual boundary list is a handful of entries.
|
|
93
|
+
// The small-allocation cost dominates the faster typed sort by a wide margin
|
|
94
|
+
// at that shape. Filling by index still avoids the intermediate array that
|
|
95
|
+
// mapping the linear index to block positions used to build.
|
|
96
|
+
// Pre-sized and filled by index. Measured against both alternatives on five
|
|
97
|
+
// real .bai shapes (min of 21, interleaved, sign-stable over 3 runs):
|
|
98
|
+
// building with push instead is 5-8% slower here, and a Float64Array is
|
|
99
|
+
// faster to sort but allocates per reference, which costs 1.7x on an
|
|
100
|
+
// assembly with 28751 scaffolds. Filling by index also avoids the
|
|
101
|
+
// intermediate array that mapping the linear index used to build.
|
|
102
|
+
const boundaries = new Array(extraBoundaries.length + chunks.length * 2);
|
|
103
|
+
let n = 0;
|
|
104
|
+
for (let i = 0, l = extraBoundaries.length; i < l; i++) {
|
|
105
|
+
boundaries[n++] = extraBoundaries[i];
|
|
106
|
+
}
|
|
77
107
|
for (const c of chunks) {
|
|
78
|
-
boundaries
|
|
108
|
+
boundaries[n++] = c.minv.blockPosition;
|
|
109
|
+
boundaries[n++] = c.maxv.blockPosition;
|
|
79
110
|
}
|
|
80
111
|
boundaries.sort((a, b) => a - b);
|
|
81
112
|
for (const c of chunks) {
|
package/esm/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
package/esm/virtualOffset.d.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The two coordinates a virtual offset packs, without the `blockPos:dataPos`
|
|
3
|
+
* string form. What every consumer that only compares positions needs — the
|
|
4
|
+
* BAI linear index stores these as raw numbers and materializes no object.
|
|
5
|
+
*/
|
|
6
|
+
export interface OffsetCoords {
|
|
2
7
|
blockPosition: number;
|
|
3
8
|
dataPosition: number;
|
|
9
|
+
}
|
|
10
|
+
export interface Offset extends OffsetCoords {
|
|
4
11
|
toString(): string;
|
|
5
|
-
compareTo(arg: Offset): number;
|
|
6
12
|
}
|
|
7
13
|
export declare class VirtualOffset {
|
|
8
14
|
blockPosition: number;
|
|
9
15
|
dataPosition: number;
|
|
10
16
|
constructor(blockPosition: number, dataPosition: number);
|
|
11
17
|
toString(): string;
|
|
12
|
-
compareTo(b: VirtualOffset): number;
|
|
13
18
|
}
|
|
14
19
|
export declare function fromBytes(bytes: Uint8Array, offset?: number): VirtualOffset;
|
package/esm/virtualOffset.js
CHANGED
|
@@ -8,9 +8,6 @@ export class VirtualOffset {
|
|
|
8
8
|
toString() {
|
|
9
9
|
return `${this.blockPosition}:${this.dataPosition}`;
|
|
10
10
|
}
|
|
11
|
-
compareTo(b) {
|
|
12
|
-
return (this.blockPosition - b.blockPosition || this.dataPosition - b.dataPosition);
|
|
13
|
-
}
|
|
14
11
|
}
|
|
15
12
|
export function fromBytes(bytes, offset = 0) {
|
|
16
13
|
return new VirtualOffset(bytes[offset + 7] * 0x10000000000 +
|
package/esm/virtualOffset.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualOffset.js","sourceRoot":"","sources":["../src/virtualOffset.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"virtualOffset.js","sourceRoot":"","sources":["../src/virtualOffset.ts"],"names":[],"mappings":"AAcA,MAAM,OAAO,aAAa;IACjB,aAAa,CAAQ;IACrB,YAAY,CAAQ;IAC3B,YAAY,aAAqB,EAAE,YAAoB;QACrD,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA,CAAC,wCAAwC;QAC3E,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA,CAAC,sCAAsC;IACzE,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,EAAE,CAAA;IACrD,CAAC;CACF;AACD,MAAM,UAAU,SAAS,CAAC,KAAiB,EAAE,MAAM,GAAG,CAAC;IACrD,OAAO,IAAI,aAAa,CACtB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,aAAa;QAChC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,WAAW;QAChC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,SAAS;QAC9B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,OAAO;QAC5B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,GAAG,KAAK;QAC1B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,EACpB,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAE,CAC3C,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
package/src/bai.ts
CHANGED
|
@@ -7,10 +7,21 @@ import type { ParsedIndexBase, RefIndex } from './indexFile.ts'
|
|
|
7
7
|
import type { BaseOpts } from './util.ts'
|
|
8
8
|
import type { VirtualOffset } from './virtualOffset.ts'
|
|
9
9
|
|
|
10
|
+
// The linear index as two parallel Float64Arrays rather than an array of
|
|
11
|
+
// VirtualOffset objects. A human-sized reference has one entry per 16kb window
|
|
12
|
+
// — ~15k for chr1 — and an object apiece costs roughly an order of magnitude
|
|
13
|
+
// more memory than the packed form, retained for as long as memoizeByRefId
|
|
14
|
+
// holds the reference. Both consumers want the raw numbers anyway: indexCov and
|
|
15
|
+
// clampChunkEnds read blockPosition only, and getLowestChunk builds the one
|
|
16
|
+
// VirtualOffset a query actually needs. Same shape as bgzf-filehandle's
|
|
17
|
+
// GziIndex, for the same reason.
|
|
10
18
|
interface BaiRefIndex extends RefIndex {
|
|
11
|
-
|
|
19
|
+
linearBlockPositions: Float64Array
|
|
20
|
+
linearDataPositions: Float64Array
|
|
12
21
|
}
|
|
13
22
|
|
|
23
|
+
const EMPTY_POSITIONS = new Float64Array(0)
|
|
24
|
+
|
|
14
25
|
interface BaiParsed extends ParsedIndexBase<BaiRefIndex> {
|
|
15
26
|
bai: true
|
|
16
27
|
}
|
|
@@ -142,19 +153,33 @@ export default class BAI extends IndexFile<BaiParsed> {
|
|
|
142
153
|
|
|
143
154
|
const linearCount = dataView.getInt32(curr, true)
|
|
144
155
|
curr += 4
|
|
145
|
-
|
|
156
|
+
// Share one empty array rather than allocating a pair per reference. An
|
|
157
|
+
// assembly with tens of thousands of unplaced scaffolds (cho.bam.bai:
|
|
158
|
+
// 28751 references, 205 linear entries between them) reaches here once
|
|
159
|
+
// per reference, and almost every one of those has an empty linear index.
|
|
160
|
+
const linearBlockPositions =
|
|
161
|
+
linearCount === 0 ? EMPTY_POSITIONS : new Float64Array(linearCount)
|
|
162
|
+
const linearDataPositions =
|
|
163
|
+
linearCount === 0 ? EMPTY_POSITIONS : new Float64Array(linearCount)
|
|
146
164
|
for (let j = 0; j < linearCount; j++) {
|
|
147
|
-
|
|
165
|
+
// a virtual offset is a 48-bit block position in the high bytes and a
|
|
166
|
+
// 16-bit data position in the low two
|
|
167
|
+
linearBlockPositions[j] =
|
|
168
|
+
bytes[curr + 7]! * 0x10000000000 +
|
|
169
|
+
bytes[curr + 6]! * 0x100000000 +
|
|
170
|
+
bytes[curr + 5]! * 0x1000000 +
|
|
171
|
+
bytes[curr + 4]! * 0x10000 +
|
|
172
|
+
bytes[curr + 3]! * 0x100 +
|
|
173
|
+
bytes[curr + 2]!
|
|
174
|
+
linearDataPositions[j] = (bytes[curr + 1]! << 8) | bytes[curr]!
|
|
148
175
|
curr += 8
|
|
149
176
|
}
|
|
150
177
|
|
|
151
|
-
clampChunkEnds(
|
|
152
|
-
Object.values(binIndex).flat(),
|
|
153
|
-
linearIndex.map(v => v.blockPosition),
|
|
154
|
-
)
|
|
178
|
+
clampChunkEnds(Object.values(binIndex).flat(), linearBlockPositions)
|
|
155
179
|
return {
|
|
156
180
|
binIndex,
|
|
157
|
-
|
|
181
|
+
linearBlockPositions,
|
|
182
|
+
linearDataPositions,
|
|
158
183
|
stats,
|
|
159
184
|
}
|
|
160
185
|
}
|
|
@@ -162,7 +187,6 @@ export default class BAI extends IndexFile<BaiParsed> {
|
|
|
162
187
|
return {
|
|
163
188
|
bai: true,
|
|
164
189
|
firstDataLine,
|
|
165
|
-
maxBlockSize: 1 << 16,
|
|
166
190
|
indices: memoizeByRefId(getIndices),
|
|
167
191
|
refCount,
|
|
168
192
|
}
|
|
@@ -182,17 +206,18 @@ export default class BAI extends IndexFile<BaiParsed> {
|
|
|
182
206
|
if (!seqIdx) {
|
|
183
207
|
return []
|
|
184
208
|
}
|
|
185
|
-
const {
|
|
186
|
-
|
|
209
|
+
const { linearBlockPositions, stats } = seqIdx
|
|
210
|
+
const nintv = linearBlockPositions.length
|
|
211
|
+
if (nintv === 0) {
|
|
187
212
|
return []
|
|
188
213
|
}
|
|
189
|
-
const e = end === undefined ? (
|
|
214
|
+
const e = end === undefined ? (nintv - 1) * v : roundUp(end, v)
|
|
190
215
|
const s = start === undefined ? 0 : roundDown(start, v)
|
|
191
216
|
const depths: IndexCovEntry[] = range
|
|
192
217
|
? new Array((e - s) / v)
|
|
193
|
-
: new Array(
|
|
194
|
-
const totalSize =
|
|
195
|
-
if (e > (
|
|
218
|
+
: new Array(nintv - 1)
|
|
219
|
+
const totalSize = linearBlockPositions[nintv - 1]!
|
|
220
|
+
if (e > (nintv - 1) * v) {
|
|
196
221
|
throw new Error('query outside of range of linear index')
|
|
197
222
|
}
|
|
198
223
|
// Scale the block-delta into a read count as we go, rather than building the
|
|
@@ -200,9 +225,9 @@ export default class BAI extends IndexFile<BaiParsed> {
|
|
|
200
225
|
// multiply-then-divide order: hoisting lineCount/totalSize into a factor
|
|
201
226
|
// reassociates the arithmetic and shifts scores by an ulp.
|
|
202
227
|
const lineCount = stats?.lineCount ?? 0
|
|
203
|
-
let currentPos =
|
|
228
|
+
let currentPos = linearBlockPositions[s / v]!
|
|
204
229
|
for (let i = s / v, j = 0; i < e / v; i++, j++) {
|
|
205
|
-
const nextPos =
|
|
230
|
+
const nextPos = linearBlockPositions[i + 1]!
|
|
206
231
|
depths[j] = {
|
|
207
232
|
score: ((nextPos - currentPos) * lineCount) / totalSize,
|
|
208
233
|
start: i * v,
|
|
@@ -221,8 +246,13 @@ export default class BAI extends IndexFile<BaiParsed> {
|
|
|
221
246
|
// contain alignments in the region. Linear index entries are monotonically
|
|
222
247
|
// non-decreasing, so the first entry at minLin is the minimum.
|
|
223
248
|
protected getLowestChunk(refIndex: BaiRefIndex, min: number) {
|
|
224
|
-
const {
|
|
225
|
-
const
|
|
226
|
-
return
|
|
249
|
+
const { linearBlockPositions, linearDataPositions } = refIndex
|
|
250
|
+
const i = Math.min(min >> BAI_LINEAR_SHIFT, linearBlockPositions.length - 1)
|
|
251
|
+
return i < 0
|
|
252
|
+
? undefined
|
|
253
|
+
: {
|
|
254
|
+
blockPosition: linearBlockPositions[i]!,
|
|
255
|
+
dataPosition: linearDataPositions[i]!,
|
|
256
|
+
}
|
|
227
257
|
}
|
|
228
258
|
}
|
package/src/bamFile.ts
CHANGED
|
@@ -232,7 +232,14 @@ export default class BamFile<T extends BamRecordLike = BAMFeature> {
|
|
|
232
232
|
|
|
233
233
|
async getHeaderPre(opts: BaseOpts = {}) {
|
|
234
234
|
if (!this.index) {
|
|
235
|
-
|
|
235
|
+
// Only reachable via `new BamFile({htsget: true})` used directly rather
|
|
236
|
+
// than through HtsgetFile, which overrides this. Throwing rather than
|
|
237
|
+
// returning undefined keeps `| undefined` off getHeader()'s public type,
|
|
238
|
+
// and makes that misuse loud instead of silently answering every query
|
|
239
|
+
// with zero records (getSeqId would find no chrToIndex).
|
|
240
|
+
throw new Error(
|
|
241
|
+
'no index to read a header from: use HtsgetFile for htsget sources',
|
|
242
|
+
)
|
|
236
243
|
}
|
|
237
244
|
const indexData = await this.index.parse(opts)
|
|
238
245
|
|
|
@@ -512,13 +519,26 @@ export default class BamFile<T extends BamRecordLike = BAMFeature> {
|
|
|
512
519
|
const chunks = res[i]!
|
|
513
520
|
for (let j = 0, jl = chunks.length; j < jl; j++) {
|
|
514
521
|
const m = chunks[j]!
|
|
515
|
-
|
|
522
|
+
// Key on the virtual-offset span — the same key _cachedChunkFeatures
|
|
523
|
+
// uses. Chunk.toString() also folds in `bin` and fetchedSize(), which
|
|
524
|
+
// keeps two chunks covering an identical span apart here even though
|
|
525
|
+
// the cache below collapses them, so their records came back twice.
|
|
526
|
+
map.set(chunkCacheKey(m), m)
|
|
516
527
|
}
|
|
517
528
|
}
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
529
|
+
const mateChunks = [...map.values()]
|
|
530
|
+
|
|
531
|
+
// Bounded for the reason ADR 0008 bounds the main query path: a viewAsPairs
|
|
532
|
+
// query over a busy region resolves to many distinct mate chunks, and an
|
|
533
|
+
// unbounded fan-out inflates every one of them at once. Same inline pool
|
|
534
|
+
// shape as _fetchChunkFeatures — ADR 0009 measured extracting a shared
|
|
535
|
+
// mapConcurrent helper at ~11% on the hot path, so it stays inline.
|
|
536
|
+
const mateFeatLists = new Array<T[]>(mateChunks.length)
|
|
537
|
+
let next = 0
|
|
538
|
+
const readNext = async () => {
|
|
539
|
+
while (next < mateChunks.length) {
|
|
540
|
+
const ci = next++
|
|
541
|
+
const features = await this._cachedChunkFeatures(mateChunks[ci]!, opts)
|
|
522
542
|
const mateRecs = [] as T[]
|
|
523
543
|
for (let i = 0, l = features.length; i < l; i++) {
|
|
524
544
|
const feature = features[i]!
|
|
@@ -529,9 +549,11 @@ export default class BamFile<T extends BamRecordLike = BAMFeature> {
|
|
|
529
549
|
mateRecs.push(feature)
|
|
530
550
|
}
|
|
531
551
|
}
|
|
532
|
-
|
|
533
|
-
}
|
|
534
|
-
|
|
552
|
+
mateFeatLists[ci] = mateRecs
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
const workers = Math.min(MAX_CONCURRENT_CHUNK_READS, mateChunks.length)
|
|
556
|
+
await Promise.all(Array.from({ length: workers }, () => readNext()))
|
|
535
557
|
return mateFeatLists.flat()
|
|
536
558
|
}
|
|
537
559
|
|
|
@@ -559,10 +581,15 @@ export default class BamFile<T extends BamRecordLike = BAMFeature> {
|
|
|
559
581
|
}
|
|
560
582
|
}
|
|
561
583
|
|
|
584
|
+
// cpositions/dpositions are `ArrayLike`, not `number[]`, because the wasm
|
|
585
|
+
// decompressor produces them as Float64Arrays — @gmod/bgzf-filehandle spreads
|
|
586
|
+
// them into plain arrays on the way out, and this signature is what lets that
|
|
587
|
+
// copy be dropped there without a change here. Only indexed reads and
|
|
588
|
+
// `.length` are used below either way.
|
|
562
589
|
readBamFeatures(
|
|
563
590
|
ba: Uint8Array,
|
|
564
|
-
cpositions: number
|
|
565
|
-
dpositions: number
|
|
591
|
+
cpositions: ArrayLike<number>,
|
|
592
|
+
dpositions: ArrayLike<number>,
|
|
566
593
|
chunk: Chunk,
|
|
567
594
|
) {
|
|
568
595
|
let blockStart = 0
|
package/src/chunk.ts
CHANGED
|
@@ -29,14 +29,6 @@ export default class Chunk {
|
|
|
29
29
|
}, fetchedSize ${this.fetchedSize()})`
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
compareTo(b: Chunk) {
|
|
33
|
-
return (
|
|
34
|
-
this.minv.compareTo(b.minv) ||
|
|
35
|
-
this.maxv.compareTo(b.maxv) ||
|
|
36
|
-
this.bin - b.bin
|
|
37
|
-
)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
32
|
fetchedSize() {
|
|
41
33
|
return this.endPosition - this.minv.blockPosition
|
|
42
34
|
}
|
package/src/csi.ts
CHANGED
|
@@ -83,16 +83,12 @@ export default class CSI extends IndexFile {
|
|
|
83
83
|
bytes.byteOffset,
|
|
84
84
|
bytes.byteLength,
|
|
85
85
|
)
|
|
86
|
-
|
|
86
|
+
// CSI\1 and CSI\2 are parsed identically here — v2 only adds fields this
|
|
87
|
+
// reader doesn't consume — so the version is validated, not retained.
|
|
87
88
|
const magic = dataView.getUint32(0, true)
|
|
88
|
-
|
|
89
|
-
if (magic === CSI1_MAGIC) {
|
|
90
|
-
csiVersion = 1
|
|
91
|
-
} else if (magic === CSI2_MAGIC) {
|
|
92
|
-
csiVersion = 2
|
|
93
|
-
} else {
|
|
94
|
-
throw new Error(`Not a CSI file ${magic}`)
|
|
89
|
+
if (magic !== CSI1_MAGIC && magic !== CSI2_MAGIC) {
|
|
95
90
|
// TODO: do we need to support big-endian CSI files?
|
|
91
|
+
throw new Error(`Not a CSI file ${magic}`)
|
|
96
92
|
}
|
|
97
93
|
|
|
98
94
|
this.minShift = dataView.getInt32(4, true)
|
|
@@ -170,12 +166,10 @@ export default class CSI extends IndexFile {
|
|
|
170
166
|
}
|
|
171
167
|
|
|
172
168
|
return {
|
|
173
|
-
csiVersion,
|
|
174
169
|
firstDataLine,
|
|
175
170
|
indices: memoizeByRefId(getIndices),
|
|
176
171
|
refCount,
|
|
177
172
|
csi: true,
|
|
178
|
-
maxBlockSize: 1 << 16,
|
|
179
173
|
...aux,
|
|
180
174
|
}
|
|
181
175
|
}
|
package/src/indexFile.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { optimizeChunks } from './util.ts'
|
|
|
4
4
|
|
|
5
5
|
import type Chunk from './chunk.ts'
|
|
6
6
|
import type { BaseOpts } from './util.ts'
|
|
7
|
-
import type {
|
|
7
|
+
import type { OffsetCoords, VirtualOffset } from './virtualOffset.ts'
|
|
8
8
|
import type { GenericFilehandle } from 'generic-filehandle2'
|
|
9
9
|
|
|
10
10
|
export interface Region {
|
|
@@ -21,7 +21,6 @@ export interface RefIndex {
|
|
|
21
21
|
export interface ParsedIndexBase<R extends RefIndex = RefIndex> {
|
|
22
22
|
firstDataLine: VirtualOffset | undefined
|
|
23
23
|
refCount: number
|
|
24
|
-
maxBlockSize: number
|
|
25
24
|
indices: (refId: number) => R | undefined
|
|
26
25
|
}
|
|
27
26
|
|
|
@@ -84,7 +83,7 @@ export default abstract class IndexFile<
|
|
|
84
83
|
protected abstract getLowestChunk(
|
|
85
84
|
refIndex: RefIndex,
|
|
86
85
|
min: number,
|
|
87
|
-
):
|
|
86
|
+
): OffsetCoords | undefined
|
|
88
87
|
|
|
89
88
|
async blocksForRange(
|
|
90
89
|
refId: number,
|
package/src/sam.ts
CHANGED
|
@@ -8,9 +8,14 @@ export function parseHeaderText(text: string) {
|
|
|
8
8
|
tag: tag.slice(1),
|
|
9
9
|
data: fields.map(f => {
|
|
10
10
|
const r = f.indexOf(':')
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
// A field with no colon is not a TAG:VALUE pair — @CO lines are free
|
|
12
|
+
// text, one comment per line (`samtools view -H c2#pad.3.0.cram`).
|
|
13
|
+
// Without this branch `slice(0, -1)` silently drops the comment's last
|
|
14
|
+
// character into the tag. Same shape @gmod/cram's parseHeaderText
|
|
15
|
+
// returns, so both feed a consumer's header parser identically.
|
|
16
|
+
return r === -1
|
|
17
|
+
? { tag: f, value: '' }
|
|
18
|
+
: { tag: f.slice(0, r), value: f.slice(r + 1) }
|
|
14
19
|
}),
|
|
15
20
|
})
|
|
16
21
|
}
|
package/src/util.ts
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import Chunk from './chunk.ts'
|
|
2
|
-
import { longFromBytesToUnsigned } from './long.ts'
|
|
3
2
|
import { VirtualOffset } from './virtualOffset.ts'
|
|
4
3
|
|
|
5
|
-
import type {
|
|
4
|
+
import type { OffsetCoords } from './virtualOffset.ts'
|
|
6
5
|
|
|
7
6
|
export interface BamOpts {
|
|
8
7
|
viewAsPairs?: boolean
|
|
@@ -30,7 +29,7 @@ export interface BaseOpts {
|
|
|
30
29
|
onProgress?: (bytesDownloaded: number, totalBytes?: number) => void
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
export function optimizeChunks(chunks: Chunk[], lowest?:
|
|
32
|
+
export function optimizeChunks(chunks: Chunk[], lowest?: OffsetCoords) {
|
|
34
33
|
const n = chunks.length
|
|
35
34
|
if (n === 0) {
|
|
36
35
|
return chunks
|
|
@@ -102,9 +101,22 @@ export function optimizeChunks(chunks: Chunk[], lowest?: Offset) {
|
|
|
102
101
|
return mergedChunks
|
|
103
102
|
}
|
|
104
103
|
|
|
104
|
+
// The pseudo-bin's mapped-record count, a little-endian uint64. Read as two
|
|
105
|
+
// 32-bit halves rather than via BigInt: exact up to Number.MAX_SAFE_INTEGER,
|
|
106
|
+
// which is far past any real record count, and allocates nothing.
|
|
105
107
|
export function parsePseudoBin(bytes: Uint8Array, offset: number) {
|
|
108
|
+
const low =
|
|
109
|
+
bytes[offset]! |
|
|
110
|
+
(bytes[offset + 1]! << 8) |
|
|
111
|
+
(bytes[offset + 2]! << 16) |
|
|
112
|
+
(bytes[offset + 3]! << 24)
|
|
113
|
+
const high =
|
|
114
|
+
bytes[offset + 4]! |
|
|
115
|
+
(bytes[offset + 5]! << 8) |
|
|
116
|
+
(bytes[offset + 6]! << 16) |
|
|
117
|
+
(bytes[offset + 7]! << 24)
|
|
106
118
|
return {
|
|
107
|
-
lineCount:
|
|
119
|
+
lineCount: (high >>> 0) * 2 ** 32 + (low >>> 0),
|
|
108
120
|
}
|
|
109
121
|
}
|
|
110
122
|
|
|
@@ -117,11 +129,34 @@ export function parsePseudoBin(bytes: Uint8Array, offset: number) {
|
|
|
117
129
|
// Shrinks both the byte estimate and the actual fetch with no extra I/O.
|
|
118
130
|
export function clampChunkEnds(
|
|
119
131
|
chunks: Chunk[],
|
|
120
|
-
extraBoundaries: number
|
|
132
|
+
extraBoundaries: ArrayLike<number> = [],
|
|
121
133
|
) {
|
|
122
|
-
|
|
134
|
+
if (chunks.length === 0) {
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
// A plain array, sized once and filled by index. Not a Float64Array: this
|
|
138
|
+
// runs once per reference, and an assembly with tens of thousands of unplaced
|
|
139
|
+
// scaffolds (cho.bam.bai has 28751 references) pays the allocation that many
|
|
140
|
+
// times over, where each individual boundary list is a handful of entries.
|
|
141
|
+
// The small-allocation cost dominates the faster typed sort by a wide margin
|
|
142
|
+
// at that shape. Filling by index still avoids the intermediate array that
|
|
143
|
+
// mapping the linear index to block positions used to build.
|
|
144
|
+
// Pre-sized and filled by index. Measured against both alternatives on five
|
|
145
|
+
// real .bai shapes (min of 21, interleaved, sign-stable over 3 runs):
|
|
146
|
+
// building with push instead is 5-8% slower here, and a Float64Array is
|
|
147
|
+
// faster to sort but allocates per reference, which costs 1.7x on an
|
|
148
|
+
// assembly with 28751 scaffolds. Filling by index also avoids the
|
|
149
|
+
// intermediate array that mapping the linear index used to build.
|
|
150
|
+
const boundaries = new Array<number>(
|
|
151
|
+
extraBoundaries.length + chunks.length * 2,
|
|
152
|
+
)
|
|
153
|
+
let n = 0
|
|
154
|
+
for (let i = 0, l = extraBoundaries.length; i < l; i++) {
|
|
155
|
+
boundaries[n++] = extraBoundaries[i]!
|
|
156
|
+
}
|
|
123
157
|
for (const c of chunks) {
|
|
124
|
-
boundaries
|
|
158
|
+
boundaries[n++] = c.minv.blockPosition
|
|
159
|
+
boundaries[n++] = c.maxv.blockPosition
|
|
125
160
|
}
|
|
126
161
|
boundaries.sort((a, b) => a - b)
|
|
127
162
|
|
package/src/virtualOffset.ts
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The two coordinates a virtual offset packs, without the `blockPos:dataPos`
|
|
3
|
+
* string form. What every consumer that only compares positions needs — the
|
|
4
|
+
* BAI linear index stores these as raw numbers and materializes no object.
|
|
5
|
+
*/
|
|
6
|
+
export interface OffsetCoords {
|
|
2
7
|
blockPosition: number
|
|
3
8
|
dataPosition: number
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface Offset extends OffsetCoords {
|
|
4
12
|
toString(): string
|
|
5
|
-
compareTo(arg: Offset): number
|
|
6
13
|
}
|
|
7
14
|
|
|
8
15
|
export class VirtualOffset {
|
|
@@ -16,12 +23,6 @@ export class VirtualOffset {
|
|
|
16
23
|
toString() {
|
|
17
24
|
return `${this.blockPosition}:${this.dataPosition}`
|
|
18
25
|
}
|
|
19
|
-
|
|
20
|
-
compareTo(b: VirtualOffset) {
|
|
21
|
-
return (
|
|
22
|
-
this.blockPosition - b.blockPosition || this.dataPosition - b.dataPosition
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
26
|
}
|
|
26
27
|
export function fromBytes(bytes: Uint8Array, offset = 0) {
|
|
27
28
|
return new VirtualOffset(
|
package/dist/long.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function longFromBytesToUnsigned(source: Uint8Array, i?: number): number;
|
package/dist/long.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.longFromBytesToUnsigned = longFromBytesToUnsigned;
|
|
4
|
-
const TWO_PWR_32_DBL = 2 ** 32;
|
|
5
|
-
// avoids dependency on long.js
|
|
6
|
-
function longFromBytesToUnsigned(source, i = 0) {
|
|
7
|
-
const low = source[i] |
|
|
8
|
-
(source[i + 1] << 8) |
|
|
9
|
-
(source[i + 2] << 16) |
|
|
10
|
-
(source[i + 3] << 24);
|
|
11
|
-
const high = source[i + 4] |
|
|
12
|
-
(source[i + 5] << 8) |
|
|
13
|
-
(source[i + 6] << 16) |
|
|
14
|
-
(source[i + 7] << 24);
|
|
15
|
-
return (high >>> 0) * TWO_PWR_32_DBL + (low >>> 0);
|
|
16
|
-
}
|
|
17
|
-
//# sourceMappingURL=long.js.map
|
package/dist/long.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"long.js","sourceRoot":"","sources":["../src/long.ts"],"names":[],"mappings":";;AAGA,0DAYC;AAfD,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,CAAA;AAE9B,+BAA+B;AAC/B,SAAgB,uBAAuB,CAAC,MAAkB,EAAE,CAAC,GAAG,CAAC;IAC/D,MAAM,GAAG,GACP,MAAM,CAAC,CAAC,CAAE;QACV,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC;QACrB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC;QACtB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC,CAAA;IACxB,MAAM,IAAI,GACR,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE;QACd,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC;QACrB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC;QACtB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC,CAAA;IACxB,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,cAAc,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAA;AACpD,CAAC"}
|
package/esm/long.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function longFromBytesToUnsigned(source: Uint8Array, i?: number): number;
|
package/esm/long.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
const TWO_PWR_32_DBL = 2 ** 32;
|
|
2
|
-
// avoids dependency on long.js
|
|
3
|
-
export function longFromBytesToUnsigned(source, i = 0) {
|
|
4
|
-
const low = source[i] |
|
|
5
|
-
(source[i + 1] << 8) |
|
|
6
|
-
(source[i + 2] << 16) |
|
|
7
|
-
(source[i + 3] << 24);
|
|
8
|
-
const high = source[i + 4] |
|
|
9
|
-
(source[i + 5] << 8) |
|
|
10
|
-
(source[i + 6] << 16) |
|
|
11
|
-
(source[i + 7] << 24);
|
|
12
|
-
return (high >>> 0) * TWO_PWR_32_DBL + (low >>> 0);
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=long.js.map
|
package/esm/long.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"long.js","sourceRoot":"","sources":["../src/long.ts"],"names":[],"mappings":"AAAA,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,CAAA;AAE9B,+BAA+B;AAC/B,MAAM,UAAU,uBAAuB,CAAC,MAAkB,EAAE,CAAC,GAAG,CAAC;IAC/D,MAAM,GAAG,GACP,MAAM,CAAC,CAAC,CAAE;QACV,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC;QACrB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC;QACtB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC,CAAA;IACxB,MAAM,IAAI,GACR,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE;QACd,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,CAAC,CAAC;QACrB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC;QACtB,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAE,IAAI,EAAE,CAAC,CAAA;IACxB,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC,GAAG,cAAc,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,CAAA;AACpD,CAAC"}
|