@gmod/bam 7.6.0 → 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/bai.js +2 -4
- package/dist/bai.js.map +1 -1
- package/dist/bamFile.d.ts +13 -0
- package/dist/bamFile.js +44 -24
- package/dist/bamFile.js.map +1 -1
- package/dist/csi.js +7 -8
- package/dist/csi.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 +19 -2
- package/dist/util.js +43 -8
- package/dist/util.js.map +1 -1
- package/esm/bai.js +3 -5
- package/esm/bai.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/csi.js +8 -9
- package/esm/csi.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 +19 -2
- package/esm/util.js +42 -7
- package/esm/util.js.map +1 -1
- package/package.json +3 -3
- package/src/bai.ts +3 -5
- package/src/bamFile.ts +48 -27
- package/src/csi.ts +8 -9
- package/src/htsget.ts +117 -62
- package/src/index.ts +2 -0
- package/src/util.ts +50 -10
package/esm/csi.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"csi.js","sourceRoot":"","sources":["../src/csi.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAE7C,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,SAAS,EAAE,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAC1D,OAAO,EACL,cAAc,EACd,
|
|
1
|
+
{"version":3,"file":"csi.js","sourceRoot":"","sources":["../src/csi.ts"],"names":[],"mappings":"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"}
|
package/esm/htsget.d.ts
CHANGED
|
@@ -2,14 +2,30 @@ import BamFile from './bamFile.ts';
|
|
|
2
2
|
import type { BamRecordClass, BamRecordLike } from './bamFile.ts';
|
|
3
3
|
import type BamRecord from './record.ts';
|
|
4
4
|
import type { BamOpts, BaseOpts } from './util.ts';
|
|
5
|
+
import type { Fetcher } from 'generic-filehandle2';
|
|
5
6
|
export default class HtsgetFile<T extends BamRecordLike = BamRecord> extends BamFile<T> {
|
|
6
7
|
private baseUrl;
|
|
7
8
|
private trackId;
|
|
9
|
+
private fetchFn;
|
|
8
10
|
constructor(args: {
|
|
9
11
|
trackId: string;
|
|
10
12
|
baseUrl: string;
|
|
11
13
|
recordClass?: BamRecordClass<T>;
|
|
14
|
+
/**
|
|
15
|
+
* fetch implementation used for every request, so an `Authorization: Bearer
|
|
16
|
+
* <token>` header can be added for servers that require one. It is also
|
|
17
|
+
* called with the data-block urls from the ticket, which may point at
|
|
18
|
+
* third-party hosts, so only attach credentials to hosts you trust — the
|
|
19
|
+
* spec has servers put whatever a data block needs in that url's own
|
|
20
|
+
* `headers` field, which is applied either way.
|
|
21
|
+
*/
|
|
22
|
+
fetch?: Fetcher;
|
|
12
23
|
});
|
|
24
|
+
/**
|
|
25
|
+
* Requests a ticket and returns its data blocks decompressed and
|
|
26
|
+
* concatenated, which per the spec is a complete BAM stream.
|
|
27
|
+
*/
|
|
28
|
+
private fetchTicket;
|
|
13
29
|
getRecordsForRange(chr: string, min: number, max: number, opts?: BamOpts): Promise<T[]>;
|
|
14
30
|
getHeaderPre(opts?: BaseOpts): Promise<{
|
|
15
31
|
tag: string;
|
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
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Chunk from './chunk.ts';
|
|
2
|
-
import
|
|
2
|
+
import { VirtualOffset } from './virtualOffset.ts';
|
|
3
|
+
import type { Offset } from './virtualOffset.ts';
|
|
3
4
|
export interface BamOpts {
|
|
4
5
|
viewAsPairs?: boolean;
|
|
5
6
|
pairAcrossChr?: boolean;
|
|
@@ -35,8 +36,24 @@ export declare function parseRefSeqs(uncba: Uint8Array, start: number, renameRef
|
|
|
35
36
|
refName: string;
|
|
36
37
|
length: number;
|
|
37
38
|
}[];
|
|
39
|
+
end: number;
|
|
38
40
|
} | undefined;
|
|
39
|
-
|
|
41
|
+
/**
|
|
42
|
+
* The smallest of `current` and the `count` packed virtual offsets starting at
|
|
43
|
+
* `offset`, allocating at most one VirtualOffset rather than one per entry.
|
|
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
|
+
*
|
|
52
|
+
* The index first pass exists only to find this minimum, and it visits every
|
|
53
|
+
* linear-index entry in the file to do it. Building a VirtualOffset per entry
|
|
54
|
+
* to compare and discard it is the bulk of that pass.
|
|
55
|
+
*/
|
|
56
|
+
export declare function minVirtualOffset(bytes: Uint8Array, offset: number, count: number, current: VirtualOffset | undefined): VirtualOffset | undefined;
|
|
40
57
|
export declare function parseNameBytes(namesBytes: Uint8Array, renameRefSeq?: (arg: string) => string): {
|
|
41
58
|
refNameToId: Record<string, number>;
|
|
42
59
|
refIdToName: string[];
|
package/esm/util.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import Chunk from "./chunk.js";
|
|
2
2
|
import { longFromBytesToUnsigned } from "./long.js";
|
|
3
|
+
import { VirtualOffset } from "./virtualOffset.js";
|
|
3
4
|
export function optimizeChunks(chunks, lowest) {
|
|
4
5
|
const n = chunks.length;
|
|
5
6
|
if (n === 0) {
|
|
@@ -125,14 +126,48 @@ export function parseRefSeqs(uncba, start, renameRefSeq) {
|
|
|
125
126
|
indexToChr.push({ refName, length: lRef });
|
|
126
127
|
p += 8 + lName;
|
|
127
128
|
}
|
|
128
|
-
|
|
129
|
+
// end is the offset just past the header, i.e. where alignment records start
|
|
130
|
+
return { chrToIndex, indexToChr, end: p };
|
|
129
131
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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.
|
|
135
|
+
/**
|
|
136
|
+
* The smallest of `current` and the `count` packed virtual offsets starting at
|
|
137
|
+
* `offset`, allocating at most one VirtualOffset rather than one per entry.
|
|
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
|
+
*
|
|
146
|
+
* The index first pass exists only to find this minimum, and it visits every
|
|
147
|
+
* linear-index entry in the file to do it. Building a VirtualOffset per entry
|
|
148
|
+
* to compare and discard it is the bulk of that pass.
|
|
149
|
+
*/
|
|
150
|
+
export function minVirtualOffset(bytes, offset, count, current) {
|
|
151
|
+
let minBlock = current ? current.blockPosition : Infinity;
|
|
152
|
+
let minData = current ? current.dataPosition : 0;
|
|
153
|
+
let found = false;
|
|
154
|
+
for (let i = 0; i < count; i++) {
|
|
155
|
+
const p = offset + i * 8;
|
|
156
|
+
const block = bytes[p + 7] * 0x10000000000 +
|
|
157
|
+
bytes[p + 6] * 0x100000000 +
|
|
158
|
+
bytes[p + 5] * 0x1000000 +
|
|
159
|
+
bytes[p + 4] * 0x10000 +
|
|
160
|
+
bytes[p + 3] * 0x100 +
|
|
161
|
+
bytes[p + 2];
|
|
162
|
+
const data = (bytes[p + 1] << 8) | bytes[p];
|
|
163
|
+
if ((block !== 0 || data !== 0) &&
|
|
164
|
+
(block < minBlock || (block === minBlock && data < minData))) {
|
|
165
|
+
minBlock = block;
|
|
166
|
+
minData = data;
|
|
167
|
+
found = true;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return found ? new VirtualOffset(minBlock, minData) : current;
|
|
136
171
|
}
|
|
137
172
|
// SYNC: ~/src/gmod/tabix-js/src/util.ts parseNameBytes uses indexOf(0) instead of byte scan
|
|
138
173
|
export function parseNameBytes(namesBytes, renameRefSeq = s => s) {
|
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,uBAAuB,EAAE,MAAM,WAAW,CAAA;
|
|
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/bai.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Chunk from './chunk.ts'
|
|
2
2
|
import IndexFile, { memoizeByRefId } from './indexFile.ts'
|
|
3
|
-
import { clampChunkEnds,
|
|
3
|
+
import { clampChunkEnds, minVirtualOffset, parsePseudoBin } from './util.ts'
|
|
4
4
|
import { fromBytes } from './virtualOffset.ts'
|
|
5
5
|
|
|
6
6
|
import type { ParsedIndexBase, RefIndex } from './indexFile.ts'
|
|
@@ -101,10 +101,8 @@ export default class BAI extends IndexFile<BaiParsed> {
|
|
|
101
101
|
// marks where the BAM header ends and data begins
|
|
102
102
|
const linearCount = dataView.getInt32(curr, true)
|
|
103
103
|
curr += 4
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
curr += 8
|
|
107
|
-
}
|
|
104
|
+
firstDataLine = minVirtualOffset(bytes, curr, linearCount, firstDataLine)
|
|
105
|
+
curr += 8 * linearCount
|
|
108
106
|
}
|
|
109
107
|
|
|
110
108
|
function getIndices(refId: number) {
|
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) {
|
package/src/csi.ts
CHANGED
|
@@ -4,7 +4,7 @@ import Chunk from './chunk.ts'
|
|
|
4
4
|
import IndexFile, { memoizeByRefId } from './indexFile.ts'
|
|
5
5
|
import {
|
|
6
6
|
clampChunkEnds,
|
|
7
|
-
|
|
7
|
+
minVirtualOffset,
|
|
8
8
|
parseNameBytes,
|
|
9
9
|
parsePseudoBin,
|
|
10
10
|
} from './util.ts'
|
|
@@ -118,15 +118,14 @@ export default class CSI extends IndexFile {
|
|
|
118
118
|
if (bin > this.maxBinNumber) {
|
|
119
119
|
curr += 28 + 16
|
|
120
120
|
} else {
|
|
121
|
-
|
|
121
|
+
// A bin's loffset is the smallest virtual offset of any record in it,
|
|
122
|
+
// so the minimum over loffsets is already the minimum over the bin's
|
|
123
|
+
// chunks — one read per bin instead of one per chunk. Checked against
|
|
124
|
+
// every .csi in test/data: same answer on all 19.
|
|
125
|
+
firstDataLine = minVirtualOffset(bytes, curr, 1, firstDataLine)
|
|
126
|
+
curr += 8 // loffset
|
|
122
127
|
const chunkCount = dataView.getInt32(curr, true)
|
|
123
|
-
curr += 4
|
|
124
|
-
for (let k = 0; k < chunkCount; k += 1) {
|
|
125
|
-
const u = fromBytes(bytes, curr)
|
|
126
|
-
curr += 8
|
|
127
|
-
curr += 8
|
|
128
|
-
firstDataLine = findFirstData(firstDataLine, u)
|
|
129
|
-
}
|
|
128
|
+
curr += 4 + 16 * chunkCount
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
}
|