@gmod/bam 1.1.17 → 2.0.0
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 +65 -25
- package/README.md +108 -57
- package/dist/bai.d.ts +34 -15
- package/dist/bai.js +180 -273
- package/dist/bai.js.map +1 -1
- package/dist/bamFile.d.ts +33 -27
- package/dist/bamFile.js +353 -572
- package/dist/bamFile.js.map +1 -1
- package/dist/chunk.d.ts +4 -8
- package/dist/chunk.js +13 -21
- package/dist/chunk.js.map +1 -1
- package/dist/csi.d.ts +74 -10
- package/dist/csi.js +157 -256
- package/dist/csi.js.map +1 -1
- package/dist/errors.js +12 -57
- package/dist/errors.js.map +1 -1
- package/dist/htsget.d.ts +5 -8
- package/dist/htsget.js +120 -209
- package/dist/htsget.js.map +1 -1
- package/dist/index.d.ts +5 -6
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/indexFile.d.ts +0 -6
- package/dist/indexFile.js +3 -77
- package/dist/indexFile.js.map +1 -1
- package/dist/nullIndex.d.ts +7 -0
- package/dist/nullIndex.js +33 -0
- package/dist/nullIndex.js.map +1 -0
- package/dist/record.d.ts +2 -2
- package/dist/record.js +200 -193
- package/dist/record.js.map +1 -1
- package/dist/sam.js +12 -10
- package/dist/sam.js.map +1 -1
- package/dist/util.d.ts +13 -1
- package/dist/util.js +55 -58
- package/dist/util.js.map +1 -1
- package/dist/virtualOffset.js +13 -20
- package/dist/virtualOffset.js.map +1 -1
- package/esm/bai.d.ts +34 -15
- package/esm/bai.js +86 -91
- package/esm/bai.js.map +1 -1
- package/esm/bamFile.d.ts +33 -27
- package/esm/bamFile.js +124 -120
- package/esm/bamFile.js.map +1 -1
- package/esm/chunk.d.ts +4 -8
- package/esm/chunk.js +2 -8
- package/esm/chunk.js.map +1 -1
- package/esm/csi.d.ts +74 -10
- package/esm/csi.js +85 -93
- package/esm/csi.js.map +1 -1
- package/esm/htsget.d.ts +5 -8
- package/esm/htsget.js +68 -43
- package/esm/htsget.js.map +1 -1
- package/esm/index.d.ts +5 -6
- package/esm/index.js +5 -6
- package/esm/index.js.map +1 -1
- package/esm/indexFile.d.ts +0 -6
- package/esm/indexFile.js +0 -22
- package/esm/indexFile.js.map +1 -1
- package/esm/nullIndex.d.ts +7 -0
- package/esm/nullIndex.js +16 -0
- package/esm/nullIndex.js.map +1 -0
- package/esm/record.d.ts +2 -2
- package/esm/record.js +34 -24
- package/esm/record.js.map +1 -1
- package/esm/sam.js +9 -7
- package/esm/sam.js.map +1 -1
- package/esm/util.d.ts +13 -1
- package/esm/util.js +40 -14
- package/esm/util.js.map +1 -1
- package/package.json +19 -20
- package/src/bai.ts +99 -102
- package/src/bamFile.ts +174 -198
- package/src/chunk.ts +6 -20
- package/src/csi.ts +102 -111
- package/src/htsget.ts +81 -61
- package/src/index.ts +5 -7
- package/src/indexFile.ts +0 -27
- package/src/nullIndex.ts +18 -0
- package/src/record.ts +34 -24
- package/src/sam.ts +9 -7
- package/src/util.ts +54 -13
- package/src/declare.d.ts +0 -2
package/dist/bamFile.js
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
2
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
14
3
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
15
4
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -19,33 +8,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
19
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
20
9
|
});
|
|
21
10
|
};
|
|
22
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
23
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
24
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
25
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
26
|
-
function step(op) {
|
|
27
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
28
|
-
while (_) try {
|
|
29
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
30
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
31
|
-
switch (op[0]) {
|
|
32
|
-
case 0: case 1: t = op; break;
|
|
33
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
34
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
35
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
36
|
-
default:
|
|
37
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
38
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
39
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
40
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
41
|
-
if (t[2]) _.ops.pop();
|
|
42
|
-
_.trys.pop(); continue;
|
|
43
|
-
}
|
|
44
|
-
op = body.call(thisArg, _);
|
|
45
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
46
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
11
|
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
50
12
|
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
51
13
|
var m = o[Symbol.asyncIterator], i;
|
|
@@ -57,7 +19,7 @@ var __await = (this && this.__await) || function (v) { return this instanceof __
|
|
|
57
19
|
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
|
|
58
20
|
var i, p;
|
|
59
21
|
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
|
|
60
|
-
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done:
|
|
22
|
+
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }
|
|
61
23
|
};
|
|
62
24
|
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
|
|
63
25
|
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
@@ -70,120 +32,82 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
|
|
|
70
32
|
function reject(value) { resume("throw", value); }
|
|
71
33
|
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
|
|
72
34
|
};
|
|
73
|
-
var __values = (this && this.__values) || function(o) {
|
|
74
|
-
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
|
|
75
|
-
if (m) return m.call(o);
|
|
76
|
-
if (o && typeof o.length === "number") return {
|
|
77
|
-
next: function () {
|
|
78
|
-
if (o && i >= o.length) o = void 0;
|
|
79
|
-
return { value: o && o[i++], done: !o };
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
83
|
-
};
|
|
84
35
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
85
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
86
37
|
};
|
|
87
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
88
39
|
exports.BAM_MAGIC = void 0;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
//locals
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
40
|
+
const buffer_1 = require("buffer");
|
|
41
|
+
const buffer_crc32_1 = __importDefault(require("buffer-crc32"));
|
|
42
|
+
const bgzf_filehandle_1 = require("@gmod/bgzf-filehandle");
|
|
43
|
+
const generic_filehandle_1 = require("generic-filehandle");
|
|
44
|
+
const abortable_promise_cache_1 = __importDefault(require("abortable-promise-cache"));
|
|
45
|
+
const quick_lru_1 = __importDefault(require("quick-lru"));
|
|
46
|
+
// locals
|
|
47
|
+
const bai_1 = __importDefault(require("./bai"));
|
|
48
|
+
const csi_1 = __importDefault(require("./csi"));
|
|
49
|
+
const record_1 = __importDefault(require("./record"));
|
|
50
|
+
const sam_1 = require("./sam");
|
|
51
|
+
const util_1 = require("./util");
|
|
101
52
|
exports.BAM_MAGIC = 21840194;
|
|
102
|
-
|
|
103
|
-
function flat(arr) {
|
|
104
|
-
var _a;
|
|
105
|
-
return (_a = []).concat.apply(_a, arr);
|
|
106
|
-
}
|
|
53
|
+
const blockLen = 1 << 16;
|
|
107
54
|
function gen2array(gen) {
|
|
108
|
-
var gen_1, gen_1_1;
|
|
109
|
-
var e_1,
|
|
110
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if (!(gen_1_1 = _b.sent(), !gen_1_1.done)) return [3 /*break*/, 5];
|
|
124
|
-
x = gen_1_1.value;
|
|
125
|
-
out.push(x);
|
|
126
|
-
_b.label = 4;
|
|
127
|
-
case 4: return [3 /*break*/, 2];
|
|
128
|
-
case 5: return [3 /*break*/, 12];
|
|
129
|
-
case 6:
|
|
130
|
-
e_1_1 = _b.sent();
|
|
131
|
-
e_1 = { error: e_1_1 };
|
|
132
|
-
return [3 /*break*/, 12];
|
|
133
|
-
case 7:
|
|
134
|
-
_b.trys.push([7, , 10, 11]);
|
|
135
|
-
if (!(gen_1_1 && !gen_1_1.done && (_a = gen_1.return))) return [3 /*break*/, 9];
|
|
136
|
-
return [4 /*yield*/, _a.call(gen_1)];
|
|
137
|
-
case 8:
|
|
138
|
-
_b.sent();
|
|
139
|
-
_b.label = 9;
|
|
140
|
-
case 9: return [3 /*break*/, 11];
|
|
141
|
-
case 10:
|
|
142
|
-
if (e_1) throw e_1.error;
|
|
143
|
-
return [7 /*endfinally*/];
|
|
144
|
-
case 11: return [7 /*endfinally*/];
|
|
145
|
-
case 12: return [2 /*return*/, out];
|
|
55
|
+
var _a, gen_1, gen_1_1;
|
|
56
|
+
var _b, e_1, _c, _d;
|
|
57
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
let out = [];
|
|
59
|
+
try {
|
|
60
|
+
for (_a = true, gen_1 = __asyncValues(gen); gen_1_1 = yield gen_1.next(), _b = gen_1_1.done, !_b;) {
|
|
61
|
+
_d = gen_1_1.value;
|
|
62
|
+
_a = false;
|
|
63
|
+
try {
|
|
64
|
+
const x = _d;
|
|
65
|
+
out = out.concat(x);
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
_a = true;
|
|
69
|
+
}
|
|
146
70
|
}
|
|
147
|
-
}
|
|
71
|
+
}
|
|
72
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
73
|
+
finally {
|
|
74
|
+
try {
|
|
75
|
+
if (!_a && !_b && (_c = gen_1.return)) yield _c.call(gen_1);
|
|
76
|
+
}
|
|
77
|
+
finally { if (e_1) throw e_1.error; }
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
148
80
|
});
|
|
149
81
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
82
|
+
class NullFilehandle {
|
|
83
|
+
read() {
|
|
84
|
+
throw new Error('never called');
|
|
85
|
+
}
|
|
86
|
+
stat() {
|
|
87
|
+
throw new Error('never called');
|
|
88
|
+
}
|
|
89
|
+
readFile() {
|
|
90
|
+
throw new Error('never called');
|
|
91
|
+
}
|
|
92
|
+
close() {
|
|
93
|
+
throw new Error('never called');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
class BamFile {
|
|
97
|
+
constructor({ bamFilehandle, bamPath, bamUrl, baiPath, baiFilehandle, baiUrl, csiPath, csiFilehandle, csiUrl, htsget, yieldThreadTime = 100, renameRefSeqs = n => n, }) {
|
|
98
|
+
this.htsget = false;
|
|
161
99
|
this.featureCache = new abortable_promise_cache_1.default({
|
|
162
|
-
//@ts-ignore
|
|
163
100
|
cache: new quick_lru_1.default({
|
|
164
101
|
maxSize: 50,
|
|
165
102
|
}),
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
return __generator(this, function (_c) {
|
|
172
|
-
switch (_c.label) {
|
|
173
|
-
case 0: return [4 /*yield*/, this._readChunk({
|
|
174
|
-
chunk: chunk,
|
|
175
|
-
opts: __assign(__assign({}, opts), { signal: signal }),
|
|
176
|
-
})];
|
|
177
|
-
case 1:
|
|
178
|
-
_b = _c.sent(), data = _b.data, cpositions = _b.cpositions, dpositions = _b.dpositions;
|
|
179
|
-
return [4 /*yield*/, this.readBamFeatures(data, cpositions, dpositions, chunk)];
|
|
180
|
-
case 2:
|
|
181
|
-
feats = _c.sent();
|
|
182
|
-
return [2 /*return*/, feats];
|
|
183
|
-
}
|
|
184
|
-
});
|
|
103
|
+
fill: (args, signal) => __awaiter(this, void 0, void 0, function* () {
|
|
104
|
+
const { chunk, opts } = args;
|
|
105
|
+
const { data, cpositions, dpositions } = yield this._readChunk({
|
|
106
|
+
chunk,
|
|
107
|
+
opts: Object.assign(Object.assign({}, opts), { signal }),
|
|
185
108
|
});
|
|
186
|
-
|
|
109
|
+
return this.readBamFeatures(data, cpositions, dpositions, chunk);
|
|
110
|
+
}),
|
|
187
111
|
});
|
|
188
112
|
this.renameRefSeq = renameRefSeqs;
|
|
189
113
|
if (bamFilehandle) {
|
|
@@ -195,6 +119,10 @@ var BamFile = /** @class */ (function () {
|
|
|
195
119
|
else if (bamUrl) {
|
|
196
120
|
this.bam = new generic_filehandle_1.RemoteFile(bamUrl);
|
|
197
121
|
}
|
|
122
|
+
else if (htsget) {
|
|
123
|
+
this.htsget = true;
|
|
124
|
+
this.bam = new NullFilehandle();
|
|
125
|
+
}
|
|
198
126
|
else {
|
|
199
127
|
throw new Error('unable to initialize bam');
|
|
200
128
|
}
|
|
@@ -217,473 +145,326 @@ var BamFile = /** @class */ (function () {
|
|
|
217
145
|
this.index = new bai_1.default({ filehandle: new generic_filehandle_1.RemoteFile(baiUrl) });
|
|
218
146
|
}
|
|
219
147
|
else if (bamPath) {
|
|
220
|
-
this.index = new bai_1.default({ filehandle: new generic_filehandle_1.LocalFile(
|
|
148
|
+
this.index = new bai_1.default({ filehandle: new generic_filehandle_1.LocalFile(`${bamPath}.bai`) });
|
|
221
149
|
}
|
|
222
150
|
else if (bamUrl) {
|
|
223
|
-
this.index = new bai_1.default({ filehandle: new generic_filehandle_1.RemoteFile(
|
|
151
|
+
this.index = new bai_1.default({ filehandle: new generic_filehandle_1.RemoteFile(`${bamUrl}.bai`) });
|
|
152
|
+
}
|
|
153
|
+
else if (htsget) {
|
|
154
|
+
this.htsget = true;
|
|
224
155
|
}
|
|
225
156
|
else {
|
|
226
157
|
throw new Error('unable to infer index format');
|
|
227
158
|
}
|
|
228
|
-
this.fetchSizeLimit = fetchSizeLimit || 500000000; // 500MB
|
|
229
|
-
this.chunkSizeLimit = chunkSizeLimit || 300000000; // 300MB
|
|
230
159
|
this.yieldThreadTime = yieldThreadTime;
|
|
231
160
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
case 2:
|
|
249
|
-
res = _b.sent();
|
|
250
|
-
bytesRead = res.bytesRead;
|
|
251
|
-
(buffer = res.buffer);
|
|
252
|
-
if (!bytesRead) {
|
|
253
|
-
throw new Error('Error reading header');
|
|
254
|
-
}
|
|
255
|
-
if (bytesRead < ret) {
|
|
256
|
-
buffer = buffer.subarray(0, bytesRead);
|
|
257
|
-
}
|
|
258
|
-
else {
|
|
259
|
-
buffer = buffer.subarray(0, ret);
|
|
260
|
-
}
|
|
261
|
-
return [3 /*break*/, 5];
|
|
262
|
-
case 3: return [4 /*yield*/, this.bam.readFile(opts)];
|
|
263
|
-
case 4:
|
|
264
|
-
buffer = (_b.sent());
|
|
265
|
-
_b.label = 5;
|
|
266
|
-
case 5: return [4 /*yield*/, (0, bgzf_filehandle_1.unzip)(buffer)];
|
|
267
|
-
case 6:
|
|
268
|
-
uncba = _b.sent();
|
|
269
|
-
if (uncba.readInt32LE(0) !== exports.BAM_MAGIC) {
|
|
270
|
-
throw new Error('Not a BAM file');
|
|
271
|
-
}
|
|
272
|
-
headLen = uncba.readInt32LE(4);
|
|
273
|
-
this.header = uncba.toString('utf8', 8, 8 + headLen);
|
|
274
|
-
return [4 /*yield*/, this._readRefSeqs(headLen + 8, 65535, opts)];
|
|
275
|
-
case 7:
|
|
276
|
-
_a = _b.sent(), chrToIndex = _a.chrToIndex, indexToChr = _a.indexToChr;
|
|
277
|
-
this.chrToIndex = chrToIndex;
|
|
278
|
-
this.indexToChr = indexToChr;
|
|
279
|
-
return [2 /*return*/, (0, sam_1.parseHeaderText)(this.header)];
|
|
161
|
+
getHeaderPre(origOpts) {
|
|
162
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
163
|
+
const opts = (0, util_1.makeOpts)(origOpts);
|
|
164
|
+
if (!this.index) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const indexData = yield this.index.parse(opts);
|
|
168
|
+
const ret = indexData.firstDataLine
|
|
169
|
+
? indexData.firstDataLine.blockPosition + 65535
|
|
170
|
+
: undefined;
|
|
171
|
+
let buffer;
|
|
172
|
+
if (ret) {
|
|
173
|
+
const s = ret + blockLen;
|
|
174
|
+
const res = yield this.bam.read(buffer_1.Buffer.alloc(s), 0, s, 0, opts);
|
|
175
|
+
if (!res.bytesRead) {
|
|
176
|
+
throw new Error('Error reading header');
|
|
280
177
|
}
|
|
281
|
-
|
|
178
|
+
buffer = res.buffer.subarray(0, Math.min(res.bytesRead, ret));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
buffer = (yield this.bam.readFile(opts));
|
|
182
|
+
}
|
|
183
|
+
const uncba = yield (0, bgzf_filehandle_1.unzip)(buffer);
|
|
184
|
+
if (uncba.readInt32LE(0) !== exports.BAM_MAGIC) {
|
|
185
|
+
throw new Error('Not a BAM file');
|
|
186
|
+
}
|
|
187
|
+
const headLen = uncba.readInt32LE(4);
|
|
188
|
+
this.header = uncba.toString('utf8', 8, 8 + headLen);
|
|
189
|
+
const { chrToIndex, indexToChr } = yield this._readRefSeqs(headLen + 8, 65535, opts);
|
|
190
|
+
this.chrToIndex = chrToIndex;
|
|
191
|
+
this.indexToChr = indexToChr;
|
|
192
|
+
return (0, sam_1.parseHeaderText)(this.header);
|
|
282
193
|
});
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
case 0: return [4 /*yield*/, this.getHeader(opts)];
|
|
290
|
-
case 1:
|
|
291
|
-
_a.sent();
|
|
292
|
-
return [2 /*return*/, this.header];
|
|
293
|
-
}
|
|
194
|
+
}
|
|
195
|
+
getHeader(opts) {
|
|
196
|
+
if (!this.headerP) {
|
|
197
|
+
this.headerP = this.getHeaderPre(opts).catch(e => {
|
|
198
|
+
this.headerP = undefined;
|
|
199
|
+
throw e;
|
|
294
200
|
});
|
|
201
|
+
}
|
|
202
|
+
return this.headerP;
|
|
203
|
+
}
|
|
204
|
+
getHeaderText(opts = {}) {
|
|
205
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
206
|
+
yield this.getHeader(opts);
|
|
207
|
+
return this.header;
|
|
295
208
|
});
|
|
296
|
-
}
|
|
209
|
+
}
|
|
297
210
|
// the full length of the refseq block is not given in advance so this grabs
|
|
298
211
|
// a chunk and doubles it if all refseqs haven't been processed
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
lName = uncba.readInt32LE(p);
|
|
325
|
-
refName = this.renameRefSeq(uncba.toString('utf8', p + 4, p + 4 + lName - 1));
|
|
326
|
-
lRef = uncba.readInt32LE(p + lName + 4);
|
|
327
|
-
chrToIndex[refName] = i;
|
|
328
|
-
indexToChr.push({ refName: refName, length: lRef });
|
|
329
|
-
p = p + 8 + lName;
|
|
330
|
-
if (p > uncba.length) {
|
|
331
|
-
console.warn("BAM header is very big. Re-fetching ".concat(refSeqBytes, " bytes."));
|
|
332
|
-
return [2 /*return*/, this._readRefSeqs(start, refSeqBytes * 2, opts)];
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
return [2 /*return*/, { chrToIndex: chrToIndex, indexToChr: indexToChr }];
|
|
212
|
+
_readRefSeqs(start, refSeqBytes, opts) {
|
|
213
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
214
|
+
if (start > refSeqBytes) {
|
|
215
|
+
return this._readRefSeqs(start, refSeqBytes * 2, opts);
|
|
216
|
+
}
|
|
217
|
+
const size = refSeqBytes + blockLen;
|
|
218
|
+
const { bytesRead, buffer } = yield this.bam.read(buffer_1.Buffer.alloc(size), 0, refSeqBytes, 0, opts);
|
|
219
|
+
if (!bytesRead) {
|
|
220
|
+
throw new Error('Error reading refseqs from header');
|
|
221
|
+
}
|
|
222
|
+
const uncba = yield (0, bgzf_filehandle_1.unzip)(buffer.subarray(0, Math.min(bytesRead, refSeqBytes)));
|
|
223
|
+
const nRef = uncba.readInt32LE(start);
|
|
224
|
+
let p = start + 4;
|
|
225
|
+
const chrToIndex = {};
|
|
226
|
+
const indexToChr = [];
|
|
227
|
+
for (let i = 0; i < nRef; i += 1) {
|
|
228
|
+
const lName = uncba.readInt32LE(p);
|
|
229
|
+
const refName = this.renameRefSeq(uncba.toString('utf8', p + 4, p + 4 + lName - 1));
|
|
230
|
+
const lRef = uncba.readInt32LE(p + lName + 4);
|
|
231
|
+
chrToIndex[refName] = i;
|
|
232
|
+
indexToChr.push({ refName, length: lRef });
|
|
233
|
+
p = p + 8 + lName;
|
|
234
|
+
if (p > uncba.length) {
|
|
235
|
+
console.warn(`BAM header is very big. Re-fetching ${refSeqBytes} bytes.`);
|
|
236
|
+
return this._readRefSeqs(start, refSeqBytes * 2, opts);
|
|
336
237
|
}
|
|
337
|
-
}
|
|
238
|
+
}
|
|
239
|
+
return { chrToIndex, indexToChr };
|
|
338
240
|
});
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
pairAcrossChr: false,
|
|
344
|
-
maxInsertSize: 200000,
|
|
345
|
-
}; }
|
|
346
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
347
|
-
var _a;
|
|
348
|
-
return __generator(this, function (_b) {
|
|
349
|
-
switch (_b.label) {
|
|
350
|
-
case 0:
|
|
351
|
-
_a = flat;
|
|
352
|
-
return [4 /*yield*/, gen2array(this.streamRecordsForRange(chr, min, max, opts))];
|
|
353
|
-
case 1: return [2 /*return*/, _a.apply(void 0, [_b.sent()])];
|
|
354
|
-
}
|
|
355
|
-
});
|
|
241
|
+
}
|
|
242
|
+
getRecordsForRange(chr, min, max, opts) {
|
|
243
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
244
|
+
return gen2array(this.streamRecordsForRange(chr, min, max, opts));
|
|
356
245
|
});
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
return __asyncGenerator(this, arguments, function streamRecordsForRange_1() {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
case 1: return [4 /*yield*/, __await(this.index.blocksForRange(chrId, min - 1, max, opts))];
|
|
371
|
-
case 2:
|
|
372
|
-
chunks = _a.sent();
|
|
373
|
-
if (!chunks) {
|
|
374
|
-
throw new Error('Error in index fetch');
|
|
375
|
-
}
|
|
376
|
-
_a.label = 3;
|
|
377
|
-
case 3:
|
|
378
|
-
i = 0;
|
|
379
|
-
_a.label = 4;
|
|
380
|
-
case 4:
|
|
381
|
-
if (!(i < chunks.length)) return [3 /*break*/, 7];
|
|
382
|
-
return [4 /*yield*/, __await((0, util_1.abortBreakPoint)(signal))];
|
|
383
|
-
case 5:
|
|
384
|
-
_a.sent();
|
|
385
|
-
size = chunks[i].fetchedSize();
|
|
386
|
-
if (size > this.chunkSizeLimit) {
|
|
387
|
-
throw new Error("Too many BAM features. BAM chunk size ".concat(size, " bytes exceeds chunkSizeLimit of ").concat(this.chunkSizeLimit));
|
|
388
|
-
}
|
|
389
|
-
_a.label = 6;
|
|
390
|
-
case 6:
|
|
391
|
-
i += 1;
|
|
392
|
-
return [3 /*break*/, 4];
|
|
393
|
-
case 7:
|
|
394
|
-
totalSize = chunks
|
|
395
|
-
.map(function (s) { return s.fetchedSize(); })
|
|
396
|
-
.reduce(function (a, b) { return a + b; }, 0);
|
|
397
|
-
if (totalSize > this.fetchSizeLimit) {
|
|
398
|
-
throw new Error("data size of ".concat(totalSize.toLocaleString(), " bytes exceeded fetch size limit of ").concat(this.fetchSizeLimit.toLocaleString(), " bytes"));
|
|
399
|
-
}
|
|
400
|
-
return [5 /*yield**/, __values(__asyncDelegator(__asyncValues(this._fetchChunkFeatures(chunks, chrId, min, max, opts))))];
|
|
401
|
-
case 8: return [4 /*yield*/, __await.apply(void 0, [_a.sent()])];
|
|
402
|
-
case 9:
|
|
403
|
-
_a.sent();
|
|
404
|
-
return [2 /*return*/];
|
|
405
|
-
}
|
|
406
|
-
});
|
|
246
|
+
}
|
|
247
|
+
streamRecordsForRange(chr, min, max, opts) {
|
|
248
|
+
var _a;
|
|
249
|
+
return __asyncGenerator(this, arguments, function* streamRecordsForRange_1() {
|
|
250
|
+
yield __await(this.getHeader(opts));
|
|
251
|
+
const chrId = (_a = this.chrToIndex) === null || _a === void 0 ? void 0 : _a[chr];
|
|
252
|
+
if (chrId === undefined || !this.index) {
|
|
253
|
+
yield yield __await([]);
|
|
254
|
+
}
|
|
255
|
+
else {
|
|
256
|
+
const chunks = yield __await(this.index.blocksForRange(chrId, min - 1, max, opts));
|
|
257
|
+
yield __await(yield* __asyncDelegator(__asyncValues(this._fetchChunkFeatures(chunks, chrId, min, max, opts))));
|
|
258
|
+
}
|
|
407
259
|
});
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
return __asyncGenerator(this, arguments, function _fetchChunkFeatures_1() {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
return [4 /*yield*/, __await(this.featureCache.get(c.toString(), {
|
|
424
|
-
chunk: c,
|
|
425
|
-
opts: opts,
|
|
426
|
-
}, opts.signal))];
|
|
427
|
-
case 2:
|
|
428
|
-
records = (_b.sent());
|
|
429
|
-
recs = [];
|
|
430
|
-
for (i_1 = 0; i_1 < records.length; i_1 += 1) {
|
|
431
|
-
feature = records[i_1];
|
|
432
|
-
if (feature.seq_id() === chrId) {
|
|
433
|
-
if (feature.get('start') >= max) {
|
|
434
|
-
// past end of range, can stop iterating
|
|
435
|
-
done = true;
|
|
436
|
-
break;
|
|
437
|
-
}
|
|
438
|
-
else if (feature.get('end') >= min) {
|
|
439
|
-
// must be in range
|
|
440
|
-
recs.push(feature);
|
|
441
|
-
}
|
|
442
|
-
}
|
|
260
|
+
}
|
|
261
|
+
_fetchChunkFeatures(chunks, chrId, min, max, opts = {}) {
|
|
262
|
+
return __asyncGenerator(this, arguments, function* _fetchChunkFeatures_1() {
|
|
263
|
+
const { viewAsPairs } = opts;
|
|
264
|
+
const feats = [];
|
|
265
|
+
let done = false;
|
|
266
|
+
for (const chunk of chunks) {
|
|
267
|
+
const records = yield __await(this.featureCache.get(chunk.toString(), { chunk, opts }, opts.signal));
|
|
268
|
+
const recs = [];
|
|
269
|
+
for (const feature of records) {
|
|
270
|
+
if (feature.seq_id() === chrId) {
|
|
271
|
+
if (feature.get('start') >= max) {
|
|
272
|
+
// past end of range, can stop iterating
|
|
273
|
+
done = true;
|
|
274
|
+
break;
|
|
443
275
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
case 4:
|
|
448
|
-
_b.sent();
|
|
449
|
-
if (done) {
|
|
450
|
-
return [3 /*break*/, 6];
|
|
276
|
+
else if (feature.get('end') >= min) {
|
|
277
|
+
// must be in range
|
|
278
|
+
recs.push(feature);
|
|
451
279
|
}
|
|
452
|
-
|
|
453
|
-
case 5:
|
|
454
|
-
i++;
|
|
455
|
-
return [3 /*break*/, 1];
|
|
456
|
-
case 6:
|
|
457
|
-
(0, util_1.checkAbortSignal)(opts.signal);
|
|
458
|
-
if (!viewAsPairs) return [3 /*break*/, 9];
|
|
459
|
-
return [4 /*yield*/, __await(this.fetchPairs(chrId, feats, opts))];
|
|
460
|
-
case 7: return [4 /*yield*/, _b.sent()];
|
|
461
|
-
case 8:
|
|
462
|
-
_b.sent();
|
|
463
|
-
_b.label = 9;
|
|
464
|
-
case 9: return [2 /*return*/];
|
|
280
|
+
}
|
|
465
281
|
}
|
|
466
|
-
|
|
282
|
+
feats.push(recs);
|
|
283
|
+
yield yield __await(recs);
|
|
284
|
+
if (done) {
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
(0, util_1.checkAbortSignal)(opts.signal);
|
|
289
|
+
if (viewAsPairs) {
|
|
290
|
+
yield yield __await(this.fetchPairs(chrId, feats, opts));
|
|
291
|
+
}
|
|
467
292
|
});
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
}
|
|
490
|
-
(0, object_entries_ponyfill_1.default)(readNames).forEach(function (_a) {
|
|
491
|
-
var k = _a[0], v = _a[1];
|
|
492
|
-
if (v === 1) {
|
|
493
|
-
unmatedPairs[k] = true;
|
|
494
|
-
}
|
|
495
|
-
});
|
|
496
|
-
});
|
|
497
|
-
matePromises = [];
|
|
498
|
-
feats.map(function (ret) {
|
|
499
|
-
for (var i = 0; i < ret.length; i++) {
|
|
500
|
-
var f = ret[i];
|
|
501
|
-
var name_2 = f.name();
|
|
502
|
-
var start = f.get('start');
|
|
503
|
-
var pnext = f._next_pos();
|
|
504
|
-
var rnext = f._next_refid();
|
|
505
|
-
if (unmatedPairs[name_2] &&
|
|
506
|
-
(pairAcrossChr ||
|
|
507
|
-
(rnext === chrId && Math.abs(start - pnext) < maxInsertSize))) {
|
|
508
|
-
matePromises.push(_this.index.blocksForRange(rnext, pnext, pnext + 1, opts));
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
});
|
|
512
|
-
_c = flat;
|
|
513
|
-
return [4 /*yield*/, Promise.all(matePromises)];
|
|
514
|
-
case 1:
|
|
515
|
-
mateChunks = _c.apply(void 0, [_e.sent()])
|
|
516
|
-
.sort()
|
|
517
|
-
.filter(function (item, pos, ary) { return !pos || item.toString() !== ary[pos - 1].toString(); });
|
|
518
|
-
mateTotalSize = mateChunks
|
|
519
|
-
.map(function (s) { return s.fetchedSize(); })
|
|
520
|
-
.reduce(function (a, b) { return a + b; }, 0);
|
|
521
|
-
if (mateTotalSize > this.fetchSizeLimit) {
|
|
522
|
-
throw new Error("data size of ".concat(mateTotalSize.toLocaleString(), " bytes exceeded fetch size limit of ").concat(this.fetchSizeLimit.toLocaleString(), " bytes"));
|
|
523
|
-
}
|
|
524
|
-
mateFeatPromises = mateChunks.map(function (c) { return __awaiter(_this, void 0, void 0, function () {
|
|
525
|
-
var _a, data, cpositions, dpositions, chunk, feats, mateRecs, i, feature;
|
|
526
|
-
return __generator(this, function (_b) {
|
|
527
|
-
switch (_b.label) {
|
|
528
|
-
case 0: return [4 /*yield*/, this._readChunk({
|
|
529
|
-
chunk: c,
|
|
530
|
-
opts: opts,
|
|
531
|
-
})];
|
|
532
|
-
case 1:
|
|
533
|
-
_a = _b.sent(), data = _a.data, cpositions = _a.cpositions, dpositions = _a.dpositions, chunk = _a.chunk;
|
|
534
|
-
return [4 /*yield*/, this.readBamFeatures(data, cpositions, dpositions, chunk)];
|
|
535
|
-
case 2:
|
|
536
|
-
feats = _b.sent();
|
|
537
|
-
mateRecs = [];
|
|
538
|
-
for (i = 0; i < feats.length; i += 1) {
|
|
539
|
-
feature = feats[i];
|
|
540
|
-
if (unmatedPairs[feature.get('name')] && !readIds[feature.id()]) {
|
|
541
|
-
mateRecs.push(feature);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
return [2 /*return*/, mateRecs];
|
|
545
|
-
}
|
|
546
|
-
});
|
|
547
|
-
}); });
|
|
548
|
-
_d = flat;
|
|
549
|
-
return [4 /*yield*/, Promise.all(mateFeatPromises)];
|
|
550
|
-
case 2: return [2 /*return*/, _d.apply(void 0, [_e.sent()])];
|
|
293
|
+
}
|
|
294
|
+
fetchPairs(chrId, feats, opts) {
|
|
295
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
296
|
+
const { pairAcrossChr, maxInsertSize = 200000 } = opts;
|
|
297
|
+
const unmatedPairs = {};
|
|
298
|
+
const readIds = {};
|
|
299
|
+
feats.map(ret => {
|
|
300
|
+
const readNames = {};
|
|
301
|
+
for (const element of ret) {
|
|
302
|
+
const name = element.name();
|
|
303
|
+
const id = element.id();
|
|
304
|
+
if (!readNames[name]) {
|
|
305
|
+
readNames[name] = 0;
|
|
306
|
+
}
|
|
307
|
+
readNames[name]++;
|
|
308
|
+
readIds[id] = 1;
|
|
309
|
+
}
|
|
310
|
+
for (const [k, v] of Object.entries(readNames)) {
|
|
311
|
+
if (v === 1) {
|
|
312
|
+
unmatedPairs[k] = true;
|
|
313
|
+
}
|
|
551
314
|
}
|
|
552
315
|
});
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
return [4 /*yield*/, (0, bgzf_filehandle_1.unzipChunkSlice)(buffer.subarray(0, Math.min(bytesRead, size)), chunk)];
|
|
567
|
-
case 2:
|
|
568
|
-
_c = _d.sent(), data = _c.buffer, cpositions = _c.cpositions, dpositions = _c.dpositions;
|
|
569
|
-
return [2 /*return*/, { data: data, cpositions: cpositions, dpositions: dpositions, chunk: chunk }];
|
|
316
|
+
const matePromises = [];
|
|
317
|
+
feats.map(ret => {
|
|
318
|
+
for (const f of ret) {
|
|
319
|
+
const name = f.name();
|
|
320
|
+
const start = f.get('start');
|
|
321
|
+
const pnext = f._next_pos();
|
|
322
|
+
const rnext = f._next_refid();
|
|
323
|
+
if (this.index &&
|
|
324
|
+
unmatedPairs[name] &&
|
|
325
|
+
(pairAcrossChr ||
|
|
326
|
+
(rnext === chrId && Math.abs(start - pnext) < maxInsertSize))) {
|
|
327
|
+
matePromises.push(this.index.blocksForRange(rnext, pnext, pnext + 1, opts));
|
|
328
|
+
}
|
|
570
329
|
}
|
|
571
330
|
});
|
|
331
|
+
// filter out duplicate chunks (the blocks are lists of chunks, blocks are
|
|
332
|
+
// concatenated, then filter dup chunks)
|
|
333
|
+
const map = new Map();
|
|
334
|
+
const res = yield Promise.all(matePromises);
|
|
335
|
+
for (const m of res.flat()) {
|
|
336
|
+
if (!map.has(m.toString())) {
|
|
337
|
+
map.set(m.toString(), m);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
const mateFeatPromises = yield Promise.all([...map.values()].map((c) => __awaiter(this, void 0, void 0, function* () {
|
|
341
|
+
const { data, cpositions, dpositions, chunk } = yield this._readChunk({
|
|
342
|
+
chunk: c,
|
|
343
|
+
opts,
|
|
344
|
+
});
|
|
345
|
+
const mateRecs = [];
|
|
346
|
+
for (const feature of yield this.readBamFeatures(data, cpositions, dpositions, chunk)) {
|
|
347
|
+
if (unmatedPairs[feature.get('name')] && !readIds[feature.id()]) {
|
|
348
|
+
mateRecs.push(feature);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
return mateRecs;
|
|
352
|
+
})));
|
|
353
|
+
return mateFeatPromises.flat();
|
|
572
354
|
});
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
576
|
-
|
|
577
|
-
return
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
355
|
+
}
|
|
356
|
+
_readRegion(position, size, opts = {}) {
|
|
357
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
358
|
+
const { bytesRead, buffer } = yield this.bam.read(buffer_1.Buffer.alloc(size), 0, size, position, opts);
|
|
359
|
+
return buffer.subarray(0, Math.min(bytesRead, size));
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
_readChunk({ chunk, opts }) {
|
|
363
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
364
|
+
const buffer = yield this._readRegion(chunk.minv.blockPosition, chunk.fetchedSize(), opts);
|
|
365
|
+
const { buffer: data, cpositions, dpositions, } = yield (0, bgzf_filehandle_1.unzipChunkSlice)(buffer, chunk);
|
|
366
|
+
return { data, cpositions, dpositions, chunk };
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
readBamFeatures(ba, cpositions, dpositions, chunk) {
|
|
370
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
371
|
+
let blockStart = 0;
|
|
372
|
+
const sink = [];
|
|
373
|
+
let pos = 0;
|
|
374
|
+
let last = +Date.now();
|
|
375
|
+
while (blockStart + 4 < ba.length) {
|
|
376
|
+
const blockSize = ba.readInt32LE(blockStart);
|
|
377
|
+
const blockEnd = blockStart + 4 + blockSize - 1;
|
|
378
|
+
// increment position to the current decompressed status
|
|
379
|
+
if (dpositions) {
|
|
380
|
+
while (blockStart + chunk.minv.dataPosition >= dpositions[pos++]) { }
|
|
381
|
+
pos--;
|
|
382
|
+
}
|
|
383
|
+
// only try to read the feature if we have all the bytes for it
|
|
384
|
+
if (blockEnd < ba.length) {
|
|
385
|
+
const feature = new record_1.default({
|
|
386
|
+
bytes: {
|
|
387
|
+
byteArray: ba,
|
|
388
|
+
start: blockStart,
|
|
389
|
+
end: blockEnd,
|
|
390
|
+
},
|
|
391
|
+
// the below results in an automatically calculated file-offset based
|
|
392
|
+
// ID if the info for that is available, otherwise crc32 of the
|
|
393
|
+
// features
|
|
394
|
+
//
|
|
395
|
+
// cpositions[pos] refers to actual file offset of a bgzip block
|
|
396
|
+
// boundaries
|
|
397
|
+
//
|
|
398
|
+
// we multiply by (1 <<8) in order to make sure each block has a
|
|
399
|
+
// "unique" address space so that data in that block could never
|
|
400
|
+
// overlap
|
|
401
|
+
//
|
|
402
|
+
// then the blockStart-dpositions is an uncompressed file offset from
|
|
403
|
+
// that bgzip block boundary, and since the cpositions are multiplied
|
|
404
|
+
// by (1 << 8) these uncompressed offsets get a unique space
|
|
405
|
+
//
|
|
406
|
+
// this has an extra chunk.minv.dataPosition added on because it
|
|
407
|
+
// blockStart starts at 0 instead of chunk.minv.dataPosition
|
|
408
|
+
//
|
|
409
|
+
// the +1 is just to avoid any possible uniqueId 0 but this does not
|
|
410
|
+
// realistically happen
|
|
411
|
+
fileOffset: cpositions.length > 0
|
|
412
|
+
? cpositions[pos] * (1 << 8) +
|
|
413
|
+
(blockStart - dpositions[pos]) +
|
|
414
|
+
chunk.minv.dataPosition +
|
|
415
|
+
1
|
|
416
|
+
: // must be slice, not subarray for buffer polyfill on web
|
|
417
|
+
buffer_crc32_1.default.signed(ba.slice(blockStart, blockEnd)),
|
|
418
|
+
});
|
|
419
|
+
sink.push(feature);
|
|
420
|
+
if (this.yieldThreadTime && +Date.now() - last > this.yieldThreadTime) {
|
|
421
|
+
yield (0, util_1.timeout)(1);
|
|
630
422
|
last = +Date.now();
|
|
631
|
-
|
|
632
|
-
case 3:
|
|
633
|
-
blockStart = blockEnd + 1;
|
|
634
|
-
return [3 /*break*/, 1];
|
|
635
|
-
case 4: return [2 /*return*/, sink];
|
|
423
|
+
}
|
|
636
424
|
}
|
|
637
|
-
|
|
425
|
+
blockStart = blockEnd + 1;
|
|
426
|
+
}
|
|
427
|
+
return sink;
|
|
638
428
|
});
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
return [2 /*return*/, this.index.hasRefSeq(refId)];
|
|
646
|
-
});
|
|
429
|
+
}
|
|
430
|
+
hasRefSeq(seqName) {
|
|
431
|
+
var _a, _b;
|
|
432
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
433
|
+
const seqId = (_a = this.chrToIndex) === null || _a === void 0 ? void 0 : _a[seqName];
|
|
434
|
+
return seqId === undefined ? false : (_b = this.index) === null || _b === void 0 ? void 0 : _b.hasRefSeq(seqId);
|
|
647
435
|
});
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
return [2 /*return*/, this.index.lineCount(refId)];
|
|
655
|
-
});
|
|
436
|
+
}
|
|
437
|
+
lineCount(seqName) {
|
|
438
|
+
var _a;
|
|
439
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
440
|
+
const seqId = (_a = this.chrToIndex) === null || _a === void 0 ? void 0 : _a[seqName];
|
|
441
|
+
return seqId === undefined || !this.index ? 0 : this.index.lineCount(seqId);
|
|
656
442
|
});
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
return [2 /*return*/, this.index.indexCov(seqId, start, end)];
|
|
668
|
-
}
|
|
669
|
-
});
|
|
443
|
+
}
|
|
444
|
+
indexCov(seqName, start, end) {
|
|
445
|
+
var _a;
|
|
446
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
447
|
+
if (!this.index) {
|
|
448
|
+
return [];
|
|
449
|
+
}
|
|
450
|
+
yield this.index.parse();
|
|
451
|
+
const seqId = (_a = this.chrToIndex) === null || _a === void 0 ? void 0 : _a[seqName];
|
|
452
|
+
return seqId === undefined ? [] : this.index.indexCov(seqId, start, end);
|
|
670
453
|
});
|
|
671
|
-
}
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
});
|
|
454
|
+
}
|
|
455
|
+
blocksForRange(seqName, start, end, opts) {
|
|
456
|
+
var _a;
|
|
457
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
458
|
+
if (!this.index) {
|
|
459
|
+
return [];
|
|
460
|
+
}
|
|
461
|
+
yield this.index.parse();
|
|
462
|
+
const seqId = (_a = this.chrToIndex) === null || _a === void 0 ? void 0 : _a[seqName];
|
|
463
|
+
return seqId === undefined
|
|
464
|
+
? []
|
|
465
|
+
: this.index.blocksForRange(seqId, start, end, opts);
|
|
684
466
|
});
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
}());
|
|
467
|
+
}
|
|
468
|
+
}
|
|
688
469
|
exports.default = BamFile;
|
|
689
470
|
//# sourceMappingURL=bamFile.js.map
|