@gmod/bam 7.6.1 → 7.6.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/README.md +109 -98
- package/dist/bamFile.d.ts +13 -0
- package/dist/bamFile.js +44 -24
- package/dist/bamFile.js.map +1 -1
- package/dist/htsget.d.ts +16 -0
- package/dist/htsget.js +72 -52
- package/dist/htsget.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/util.d.ts +8 -0
- package/dist/util.js +14 -3
- package/dist/util.js.map +1 -1
- package/esm/bamFile.d.ts +13 -0
- package/esm/bamFile.js +44 -24
- package/esm/bamFile.js.map +1 -1
- package/esm/htsget.d.ts +16 -0
- package/esm/htsget.js +73 -53
- package/esm/htsget.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/util.d.ts +8 -0
- package/esm/util.js +14 -3
- package/esm/util.js.map +1 -1
- package/package.json +3 -3
- package/src/bamFile.ts +48 -27
- package/src/htsget.ts +117 -62
- package/src/index.ts +2 -0
- package/src/util.ts +16 -3
package/esm/htsget.js
CHANGED
|
@@ -1,91 +1,111 @@
|
|
|
1
1
|
import { unzip } from '@gmod/bgzf-filehandle';
|
|
2
2
|
import BamFile, { BAM_MAGIC } from "./bamFile.js";
|
|
3
3
|
import Chunk from "./chunk.js";
|
|
4
|
-
import {
|
|
5
|
-
import { appendInRange, concatUint8Array } from "./util.js";
|
|
4
|
+
import { appendInRange, concatUint8Array, parseRefSeqs } from "./util.js";
|
|
6
5
|
import { VirtualOffset } from "./virtualOffset.js";
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
// Errors carry a JSON body naming the error type, e.g. {"htsget":
|
|
7
|
+
// {"error":"InvalidAuthentication","message":"..."}}. Surface that rather than
|
|
8
|
+
// the raw payload, since 401/403 are the first thing a misconfigured token hits.
|
|
9
|
+
function htsgetErrorMessage(text) {
|
|
10
|
+
let parsed;
|
|
11
|
+
try {
|
|
12
|
+
parsed = JSON.parse(text);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// not JSON, fall through to the raw body
|
|
16
|
+
}
|
|
17
|
+
const err = parsed?.htsget;
|
|
18
|
+
return err?.error === undefined
|
|
19
|
+
? text
|
|
20
|
+
: err.message === undefined
|
|
21
|
+
? err.error
|
|
22
|
+
: `${err.error}: ${err.message}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Offset of the first alignment record in the concatenated ticket blocks.
|
|
26
|
+
*
|
|
27
|
+
* The spec has the client concatenate the blocks in ticket order to get a
|
|
28
|
+
* complete data stream, so whether the header is its own block is up to the
|
|
29
|
+
* server: htsnexus splits it into a leading `data:` url, while htsget-rs
|
|
30
|
+
* returns header and records together in a single url. Either way the
|
|
31
|
+
* concatenation starts with the BAM header, so seek past it rather than
|
|
32
|
+
* dropping blocks — a url count or class attribute can't tell the two layouts
|
|
33
|
+
* apart. Returns 0 when the stream has no header, which is what a server
|
|
34
|
+
* sending body-only blocks produces.
|
|
35
|
+
*/
|
|
36
|
+
function recordsOffset(uncba) {
|
|
37
|
+
const dataView = new DataView(uncba.buffer, uncba.byteOffset, uncba.byteLength);
|
|
38
|
+
if (uncba.byteLength < 8 || dataView.getInt32(0, true) !== BAM_MAGIC) {
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
const refs = parseRefSeqs(uncba, 8 + dataView.getInt32(4, true), n => n);
|
|
42
|
+
if (!refs) {
|
|
43
|
+
throw new Error('truncated BAM header in htsget response');
|
|
44
|
+
}
|
|
45
|
+
return refs.end;
|
|
46
|
+
}
|
|
47
|
+
async function fetchOk(fetchFn, url, opts) {
|
|
48
|
+
const res = await fetchFn(url, opts);
|
|
9
49
|
if (!res.ok) {
|
|
10
|
-
throw new Error(`HTTP ${res.status} fetching ${url}: ${await res.text()}`);
|
|
50
|
+
throw new Error(`HTTP ${res.status} fetching ${url}: ${htsgetErrorMessage(await res.text())}`);
|
|
11
51
|
}
|
|
12
52
|
return res;
|
|
13
53
|
}
|
|
14
|
-
async function fetchChunk({ url, headers }, opts) {
|
|
54
|
+
async function fetchChunk(fetchFn, { url, headers }, opts) {
|
|
15
55
|
// pass base64 data URLs straight to fetch; otherwise apply headers (minus
|
|
16
56
|
// referer, which isn't a permitted client-set header).
|
|
17
57
|
// https://stackoverflow.com/a/54123275/2129219
|
|
18
58
|
const { referer: _referer, ...rest } = headers ?? {};
|
|
19
59
|
const res = url.startsWith('data:')
|
|
20
|
-
? await fetchOk(url)
|
|
21
|
-
: await fetchOk(url, { ...opts, headers: rest });
|
|
60
|
+
? await fetchOk(fetchFn, url)
|
|
61
|
+
: await fetchOk(fetchFn, url, { ...opts, headers: rest });
|
|
22
62
|
return new Uint8Array(await res.arrayBuffer());
|
|
23
63
|
}
|
|
24
|
-
async function fetchAndConcat(arr, opts) {
|
|
64
|
+
async function fetchAndConcat(fetchFn, arr, opts) {
|
|
25
65
|
// Pipeline unzip after each fetch so decompression overlaps later fetches.
|
|
26
|
-
return concatUint8Array(await Promise.all(arr.map(async (c) => unzip(await fetchChunk(c, opts)))));
|
|
66
|
+
return concatUint8Array(await Promise.all(arr.map(async (c) => unzip(await fetchChunk(fetchFn, c, opts)))));
|
|
27
67
|
}
|
|
28
68
|
export default class HtsgetFile extends BamFile {
|
|
29
69
|
baseUrl;
|
|
30
70
|
trackId;
|
|
71
|
+
fetchFn;
|
|
31
72
|
constructor(args) {
|
|
32
73
|
super({ htsget: true, recordClass: args.recordClass });
|
|
33
74
|
this.baseUrl = args.baseUrl;
|
|
34
75
|
this.trackId = args.trackId;
|
|
76
|
+
this.fetchFn = args.fetch ?? ((input, init) => fetch(input, init));
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Requests a ticket and returns its data blocks decompressed and
|
|
80
|
+
* concatenated, which per the spec is a complete BAM stream.
|
|
81
|
+
*/
|
|
82
|
+
async fetchTicket(query, opts) {
|
|
83
|
+
const url = `${this.baseUrl}/${this.trackId}?${query}`;
|
|
84
|
+
const res = await fetchOk(this.fetchFn, url, { signal: opts?.signal });
|
|
85
|
+
const ticket = await res.json();
|
|
86
|
+
return fetchAndConcat(this.fetchFn, ticket.htsget.urls, {
|
|
87
|
+
signal: opts?.signal,
|
|
88
|
+
});
|
|
35
89
|
}
|
|
36
90
|
async getRecordsForRange(chr, min, max, opts) {
|
|
37
91
|
await this.getHeader(opts);
|
|
38
|
-
const base = `${this.baseUrl}/${this.trackId}`;
|
|
39
|
-
const url = `${base}?referenceName=${chr}&start=${min}&end=${max}&format=BAM`;
|
|
40
92
|
const chrId = this.chrToIndex?.[chr];
|
|
41
93
|
if (chrId === undefined) {
|
|
42
94
|
return [];
|
|
43
95
|
}
|
|
44
|
-
const
|
|
45
|
-
const data = await result.json();
|
|
46
|
-
const uncba = await fetchAndConcat(data.htsget.urls.slice(1), {
|
|
47
|
-
signal: opts?.signal,
|
|
48
|
-
});
|
|
96
|
+
const uncba = await this.fetchTicket(`referenceName=${chr}&start=${min}&end=${max}&format=BAM`, opts);
|
|
49
97
|
const zero = new VirtualOffset(0, 0);
|
|
50
|
-
const
|
|
51
|
-
return appendInRange(
|
|
98
|
+
const records = this.readBamFeatures(uncba.subarray(recordsOffset(uncba)), [], [], new Chunk(zero, zero, 0));
|
|
99
|
+
return appendInRange(records, chrId, min, max);
|
|
52
100
|
}
|
|
53
101
|
async getHeaderPre(opts = {}) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const dataView = new DataView(uncba.buffer, uncba.byteOffset, uncba.byteLength);
|
|
61
|
-
if (dataView.getInt32(0, true) !== BAM_MAGIC) {
|
|
62
|
-
throw new Error('Not a BAM file');
|
|
63
|
-
}
|
|
64
|
-
const headLen = dataView.getInt32(4, true);
|
|
65
|
-
const decoder = new TextDecoder();
|
|
66
|
-
const headerText = decoder.decode(uncba.subarray(8, 8 + headLen));
|
|
67
|
-
const samHeader = parseHeaderText(headerText);
|
|
68
|
-
// use the @SQ lines in the header to figure out the
|
|
69
|
-
// mapping between ref ref ID numbers and names
|
|
70
|
-
const idToName = [];
|
|
71
|
-
const nameToId = {};
|
|
72
|
-
const sqLines = samHeader.filter(l => l.tag === 'SQ');
|
|
73
|
-
for (const [refId, sqLine] of sqLines.entries()) {
|
|
74
|
-
let refName = '';
|
|
75
|
-
let length = 0;
|
|
76
|
-
for (const item of sqLine.data) {
|
|
77
|
-
if (item.tag === 'SN') {
|
|
78
|
-
refName = item.value;
|
|
79
|
-
}
|
|
80
|
-
else if (item.tag === 'LN') {
|
|
81
|
-
length = +item.value;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
nameToId[refName] = refId;
|
|
85
|
-
idToName[refId] = { refName, length };
|
|
102
|
+
// format is the only parameter the spec permits alongside class=header;
|
|
103
|
+
// servers SHOULD reject anything else with InvalidInput
|
|
104
|
+
const uncba = await this.fetchTicket('class=header&format=BAM', opts);
|
|
105
|
+
const samHeader = this.applyHeader(uncba);
|
|
106
|
+
if (!samHeader) {
|
|
107
|
+
throw new Error('Insufficient data for reference sequences');
|
|
86
108
|
}
|
|
87
|
-
this.chrToIndex = nameToId;
|
|
88
|
-
this.indexToChr = idToName;
|
|
89
109
|
return samHeader;
|
|
90
110
|
}
|
|
91
111
|
}
|
package/esm/htsget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"htsget.js","sourceRoot":"","sources":["../src/htsget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAE7C,OAAO,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"htsget.js","sourceRoot":"","sources":["../src/htsget.ts"],"names":[],"mappings":"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"}
|
package/esm/index.d.ts
CHANGED
package/esm/util.d.ts
CHANGED
|
@@ -36,11 +36,19 @@ export declare function parseRefSeqs(uncba: Uint8Array, start: number, renameRef
|
|
|
36
36
|
refName: string;
|
|
37
37
|
length: number;
|
|
38
38
|
}[];
|
|
39
|
+
end: number;
|
|
39
40
|
} | undefined;
|
|
40
41
|
/**
|
|
41
42
|
* The smallest of `current` and the `count` packed virtual offsets starting at
|
|
42
43
|
* `offset`, allocating at most one VirtualOffset rather than one per entry.
|
|
43
44
|
*
|
|
45
|
+
* 0:0 is skipped rather than treated as the minimum. No BAM record can live
|
|
46
|
+
* there — the magic and header occupy the start of the file — so it is the
|
|
47
|
+
* "unset" placeholder htslib leaves in linear-index windows ahead of a
|
|
48
|
+
* reference's first read (see test/data/HG00096_illumina_lowcov.bam.bai, whose
|
|
49
|
+
* first three windows are 0). Counting it collapses firstDataLine to 0:0 and
|
|
50
|
+
* makes callers size a header read from nothing.
|
|
51
|
+
*
|
|
44
52
|
* The index first pass exists only to find this minimum, and it visits every
|
|
45
53
|
* linear-index entry in the file to do it. Building a VirtualOffset per entry
|
|
46
54
|
* to compare and discard it is the bulk of that pass.
|
package/esm/util.js
CHANGED
|
@@ -126,13 +126,23 @@ export function parseRefSeqs(uncba, start, renameRefSeq) {
|
|
|
126
126
|
indexToChr.push({ refName, length: lRef });
|
|
127
127
|
p += 8 + lName;
|
|
128
128
|
}
|
|
129
|
-
|
|
129
|
+
// end is the offset just past the header, i.e. where alignment records start
|
|
130
|
+
return { chrToIndex, indexToChr, end: p };
|
|
130
131
|
}
|
|
131
|
-
// SYNC: ~/src/gmod/tabix-js/src/util.ts minVirtualOffset
|
|
132
|
+
// SYNC: ~/src/gmod/tabix-js/src/util.ts minVirtualOffset — but NOT the 0:0
|
|
133
|
+
// skip below, which is only sound for BAM. A tabix'd file with no header lines
|
|
134
|
+
// really does have its first record at 0:0.
|
|
132
135
|
/**
|
|
133
136
|
* The smallest of `current` and the `count` packed virtual offsets starting at
|
|
134
137
|
* `offset`, allocating at most one VirtualOffset rather than one per entry.
|
|
135
138
|
*
|
|
139
|
+
* 0:0 is skipped rather than treated as the minimum. No BAM record can live
|
|
140
|
+
* there — the magic and header occupy the start of the file — so it is the
|
|
141
|
+
* "unset" placeholder htslib leaves in linear-index windows ahead of a
|
|
142
|
+
* reference's first read (see test/data/HG00096_illumina_lowcov.bam.bai, whose
|
|
143
|
+
* first three windows are 0). Counting it collapses firstDataLine to 0:0 and
|
|
144
|
+
* makes callers size a header read from nothing.
|
|
145
|
+
*
|
|
136
146
|
* The index first pass exists only to find this minimum, and it visits every
|
|
137
147
|
* linear-index entry in the file to do it. Building a VirtualOffset per entry
|
|
138
148
|
* to compare and discard it is the bulk of that pass.
|
|
@@ -150,7 +160,8 @@ export function minVirtualOffset(bytes, offset, count, current) {
|
|
|
150
160
|
bytes[p + 3] * 0x100 +
|
|
151
161
|
bytes[p + 2];
|
|
152
162
|
const data = (bytes[p + 1] << 8) | bytes[p];
|
|
153
|
-
if (block
|
|
163
|
+
if ((block !== 0 || data !== 0) &&
|
|
164
|
+
(block < minBlock || (block === minBlock && data < minData))) {
|
|
154
165
|
minBlock = block;
|
|
155
166
|
minData = data;
|
|
156
167
|
found = true;
|
package/esm/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gmod/bam",
|
|
3
|
-
"version": "7.6.
|
|
3
|
+
"version": "7.6.2",
|
|
4
4
|
"packageManager": "pnpm@11.15.1",
|
|
5
5
|
"description": "Parser for BAM and BAM index (bai) files",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"build": "pnpm build:esm && pnpm build:es5",
|
|
40
40
|
"benchonly": "vitest bench",
|
|
41
41
|
"bench": "./scripts/build-both-branches.sh \"$BRANCH1\" \"$BRANCH2\" && vitest bench",
|
|
42
|
-
"version": "
|
|
42
|
+
"version": "git-cliff --tag v$npm_package_version --unreleased --prepend CHANGELOG.md && git add CHANGELOG.md"
|
|
43
43
|
},
|
|
44
44
|
"keywords": [
|
|
45
45
|
"bionode",
|
|
@@ -60,9 +60,9 @@
|
|
|
60
60
|
"eslint": "^10.4.1",
|
|
61
61
|
"eslint-plugin-import-x": "^4.16.2",
|
|
62
62
|
"eslint-plugin-unicorn": "^65.0.0",
|
|
63
|
+
"git-cliff": "^2.13.1",
|
|
63
64
|
"prettier": "^3.8.3",
|
|
64
65
|
"rimraf": "^6.1.3",
|
|
65
|
-
"standard-changelog": "^7.0.1",
|
|
66
66
|
"typescript": "^6.0.3",
|
|
67
67
|
"typescript-eslint": "^8.61.0",
|
|
68
68
|
"vitest": "^4.1.8"
|
package/src/bamFile.ts
CHANGED
|
@@ -37,6 +37,12 @@ export const BAM_MAGIC = 21840194
|
|
|
37
37
|
|
|
38
38
|
const blockLen = 1 << 16
|
|
39
39
|
|
|
40
|
+
// Ceiling on the header read. A million contigs is roughly 10MB of compressed
|
|
41
|
+
// @SQ lines and ref-seq table, so anything past this is a corrupt header
|
|
42
|
+
// claiming a huge n_ref rather than a real one, and growing the read further
|
|
43
|
+
// just downloads the file.
|
|
44
|
+
const maxHeaderReadLen = 32 * 1024 * 1024
|
|
45
|
+
|
|
40
46
|
function resolveFilehandle(
|
|
41
47
|
filehandle?: GenericFilehandle,
|
|
42
48
|
path?: string,
|
|
@@ -230,46 +236,61 @@ export default class BamFile<T extends BamRecordLike = BAMFeature> {
|
|
|
230
236
|
}
|
|
231
237
|
const indexData = await this.index.parse(opts)
|
|
232
238
|
|
|
233
|
-
//
|
|
234
|
-
//
|
|
235
|
-
|
|
239
|
+
// The records start at firstDataLine, so reading up to it plus the bgzf
|
|
240
|
+
// block straddling it covers the header. It is undefined when the index
|
|
241
|
+
// records no data at all (header-only BAM), and it undershoots when the
|
|
242
|
+
// index leaves offsets unset, so grow the read until the ref-seq table
|
|
243
|
+
// parses. Never readFile() here: on a remote BAM that is a whole-file
|
|
244
|
+
// download to read a header.
|
|
245
|
+
let readLen =
|
|
236
246
|
indexData.firstDataLine === undefined
|
|
237
|
-
?
|
|
247
|
+
? blockLen
|
|
238
248
|
: indexData.firstDataLine.blockPosition + blockLen
|
|
239
249
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
250
|
+
let samHeader
|
|
251
|
+
let atEof = false
|
|
252
|
+
while (samHeader === undefined && !atEof && readLen <= maxHeaderReadLen) {
|
|
253
|
+
const buffer = await this.bam.read(readLen, 0, { signal: opts.signal })
|
|
254
|
+
// a short read means readLen ran past the end of the file, so there are
|
|
255
|
+
// no more bytes to grow into
|
|
256
|
+
atEof = buffer.length < readLen
|
|
257
|
+
samHeader = this.applyHeader(await unzip(buffer))
|
|
258
|
+
readLen *= 2
|
|
259
|
+
}
|
|
260
|
+
if (samHeader === undefined) {
|
|
261
|
+
throw new Error('Insufficient data for reference sequences')
|
|
262
|
+
}
|
|
263
|
+
return samHeader
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Installs the header text and ref name/id maps from the start of a
|
|
268
|
+
* decompressed BAM stream, returning the parsed SAM header lines. Returns
|
|
269
|
+
* undefined if the stream is cut off partway through the ref-seq table, so
|
|
270
|
+
* the caller can retry with more data.
|
|
271
|
+
*/
|
|
272
|
+
protected applyHeader(uncba: Uint8Array) {
|
|
245
273
|
const dataView = new DataView(
|
|
246
274
|
uncba.buffer,
|
|
247
275
|
uncba.byteOffset,
|
|
248
276
|
uncba.byteLength,
|
|
249
277
|
)
|
|
250
|
-
|
|
251
278
|
if (dataView.getInt32(0, true) !== BAM_MAGIC) {
|
|
252
279
|
throw new Error('Not a BAM file')
|
|
253
280
|
}
|
|
254
281
|
const headLen = dataView.getInt32(4, true)
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
parsed = parseRefSeqs(uncba, refSeqStart, this.renameRefSeq)
|
|
266
|
-
}
|
|
267
|
-
if (!parsed) {
|
|
268
|
-
throw new Error('Insufficient data for reference sequences')
|
|
282
|
+
const parsed = parseRefSeqs(uncba, headLen + 8, this.renameRefSeq)
|
|
283
|
+
let samHeader
|
|
284
|
+
if (parsed) {
|
|
285
|
+
const headerText = new TextDecoder('utf8').decode(
|
|
286
|
+
uncba.subarray(8, 8 + headLen),
|
|
287
|
+
)
|
|
288
|
+
this.header = headerText
|
|
289
|
+
this.chrToIndex = parsed.chrToIndex
|
|
290
|
+
this.indexToChr = parsed.indexToChr
|
|
291
|
+
samHeader = parseHeaderText(headerText)
|
|
269
292
|
}
|
|
270
|
-
|
|
271
|
-
this.indexToChr = parsed.indexToChr
|
|
272
|
-
return parseHeaderText(this.header)
|
|
293
|
+
return samHeader
|
|
273
294
|
}
|
|
274
295
|
|
|
275
296
|
getHeader(opts?: BaseOpts) {
|