@gmod/tabix 1.5.4 → 1.5.5

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.
@@ -8,50 +8,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
- var __generator = (this && this.__generator) || function (thisArg, body) {
12
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
13
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14
- function verb(n) { return function (v) { return step([n, v]); }; }
15
- function step(op) {
16
- if (f) throw new TypeError("Generator is already executing.");
17
- while (_) try {
18
- 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;
19
- if (y = 0, t) op = [op[0] & 2, t.value];
20
- switch (op[0]) {
21
- case 0: case 1: t = op; break;
22
- case 4: _.label++; return { value: op[1], done: false };
23
- case 5: _.label++; y = op[1]; op = [0]; continue;
24
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
25
- default:
26
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30
- if (t[2]) _.ops.pop();
31
- _.trys.pop(); continue;
32
- }
33
- op = body.call(thisArg, _);
34
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36
- }
37
- };
38
11
  var __importDefault = (this && this.__importDefault) || function (mod) {
39
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
40
13
  };
41
14
  Object.defineProperty(exports, "__esModule", { value: true });
42
- var abortable_promise_cache_1 = __importDefault(require("abortable-promise-cache"));
43
- var quick_lru_1 = __importDefault(require("quick-lru"));
44
- var generic_filehandle_1 = require("generic-filehandle");
45
- var bgzf_filehandle_1 = require("@gmod/bgzf-filehandle");
46
- var util_1 = require("./util");
47
- var tbi_1 = __importDefault(require("./tbi"));
48
- var csi_1 = __importDefault(require("./csi"));
15
+ const abortable_promise_cache_1 = __importDefault(require("abortable-promise-cache"));
16
+ const quick_lru_1 = __importDefault(require("quick-lru"));
17
+ const generic_filehandle_1 = require("generic-filehandle");
18
+ const bgzf_filehandle_1 = require("@gmod/bgzf-filehandle");
19
+ const util_1 = require("./util");
20
+ const tbi_1 = __importDefault(require("./tbi"));
21
+ const csi_1 = __importDefault(require("./csi"));
49
22
  function timeout(time) {
50
- return new Promise(function (resolve) {
23
+ return new Promise(resolve => {
51
24
  setTimeout(resolve, time);
52
25
  });
53
26
  }
54
- var TabixIndexedFile = /** @class */ (function () {
27
+ class TabixIndexedFile {
55
28
  /**
56
29
  * @param {object} args
57
30
  * @param {string} [args.path]
@@ -67,8 +40,7 @@ var TabixIndexedFile = /** @class */ (function () {
67
40
  * @param {number} [args.chunkCacheSize] maximum size in bytes of the chunk cache. default 5MB
68
41
  * @param {number} [args.blockCacheSize] maximum size in bytes of the block cache. default 5MB
69
42
  */
70
- function TabixIndexedFile(_a) {
71
- var path = _a.path, filehandle = _a.filehandle, tbiPath = _a.tbiPath, tbiFilehandle = _a.tbiFilehandle, csiPath = _a.csiPath, csiFilehandle = _a.csiFilehandle, _b = _a.chunkSizeLimit, chunkSizeLimit = _b === void 0 ? 50000000 : _b, _c = _a.renameRefSeqs, renameRefSeqs = _c === void 0 ? function (n) { return n; } : _c, _d = _a.chunkCacheSize, chunkCacheSize = _d === void 0 ? 5 * Math.pow(2, 20) : _d;
43
+ constructor({ path, filehandle, tbiPath, tbiFilehandle, csiPath, csiFilehandle, chunkSizeLimit = 50000000, renameRefSeqs = n => n, chunkCacheSize = 5 * Math.pow(2, 20), }) {
72
44
  if (filehandle) {
73
45
  this.filehandle = filehandle;
74
46
  }
@@ -81,31 +53,31 @@ var TabixIndexedFile = /** @class */ (function () {
81
53
  if (tbiFilehandle) {
82
54
  this.index = new tbi_1.default({
83
55
  filehandle: tbiFilehandle,
84
- renameRefSeqs: renameRefSeqs,
56
+ renameRefSeqs,
85
57
  });
86
58
  }
87
59
  else if (csiFilehandle) {
88
60
  this.index = new csi_1.default({
89
61
  filehandle: csiFilehandle,
90
- renameRefSeqs: renameRefSeqs,
62
+ renameRefSeqs,
91
63
  });
92
64
  }
93
65
  else if (tbiPath) {
94
66
  this.index = new tbi_1.default({
95
67
  filehandle: new generic_filehandle_1.LocalFile(tbiPath),
96
- renameRefSeqs: renameRefSeqs,
68
+ renameRefSeqs,
97
69
  });
98
70
  }
99
71
  else if (csiPath) {
100
72
  this.index = new csi_1.default({
101
73
  filehandle: new generic_filehandle_1.LocalFile(csiPath),
102
- renameRefSeqs: renameRefSeqs,
74
+ renameRefSeqs,
103
75
  });
104
76
  }
105
77
  else if (path) {
106
78
  this.index = new tbi_1.default({
107
- filehandle: new generic_filehandle_1.LocalFile("".concat(path, ".tbi")),
108
- renameRefSeqs: renameRefSeqs,
79
+ filehandle: new generic_filehandle_1.LocalFile(`${path}.tbi`),
80
+ renameRefSeqs,
109
81
  });
110
82
  }
111
83
  else {
@@ -127,133 +99,110 @@ var TabixIndexedFile = /** @class */ (function () {
127
99
  * @param {function|object} lineCallback callback called for each line in the region. can also pass a object param containing obj.lineCallback, obj.signal, etc
128
100
  * @returns {Promise} resolved when the whole read is finished, rejected on error
129
101
  */
130
- TabixIndexedFile.prototype.getLines = function (refName, start, end, opts) {
131
- return __awaiter(this, void 0, void 0, function () {
132
- var signal, options, callback, metadata, chunks, i, size, last, chunkNum, previousStartCoordinate, c, _a, buffer, cpositions, dpositions, lines, blockStart, pos, i, line, _b, startCoordinate, overlaps;
133
- return __generator(this, function (_c) {
134
- switch (_c.label) {
135
- case 0:
136
- options = {};
137
- if (typeof opts === 'undefined') {
138
- throw new TypeError('line callback must be provided');
139
- }
140
- if (typeof opts === 'function') {
141
- callback = opts;
142
- }
143
- else {
144
- options = opts;
145
- callback = opts.lineCallback;
146
- }
147
- if (refName === undefined) {
148
- throw new TypeError('must provide a reference sequence name');
149
- }
150
- if (!callback) {
151
- throw new TypeError('line callback must be provided');
152
- }
153
- return [4 /*yield*/, this.index.getMetadata(options)];
154
- case 1:
155
- metadata = _c.sent();
156
- (0, util_1.checkAbortSignal)(signal);
157
- if (!start) {
158
- start = 0;
159
- }
160
- if (!end) {
161
- end = metadata.maxRefLength;
162
- }
163
- if (!(start <= end)) {
164
- throw new TypeError('invalid start and end coordinates. start must be less than or equal to end');
165
- }
166
- if (start === end) {
167
- return [2 /*return*/];
168
- }
169
- return [4 /*yield*/, this.index.blocksForRange(refName, start, end, options)];
170
- case 2:
171
- chunks = _c.sent();
172
- (0, util_1.checkAbortSignal)(signal);
173
- // check the chunks for any that are over the size limit. if
174
- // any are, don't fetch any of them
175
- for (i = 0; i < chunks.length; i += 1) {
176
- size = chunks[i].fetchedSize();
177
- if (size > this.chunkSizeLimit) {
178
- throw new Error("Too much data. Chunk size ".concat(size.toLocaleString(), " bytes exceeds chunkSizeLimit of ").concat(this.chunkSizeLimit.toLocaleString(), "."));
179
- }
180
- }
181
- last = Date.now();
182
- chunkNum = 0;
183
- _c.label = 3;
184
- case 3:
185
- if (!(chunkNum < chunks.length)) return [3 /*break*/, 9];
186
- previousStartCoordinate = void 0;
187
- c = chunks[chunkNum];
188
- return [4 /*yield*/, this.chunkCache.get(c.toString(), c, signal)];
189
- case 4:
190
- _a = _c.sent(), buffer = _a.buffer, cpositions = _a.cpositions, dpositions = _a.dpositions;
191
- lines = (typeof TextDecoder !== 'undefined'
192
- ? new TextDecoder('utf-8').decode(buffer)
193
- : buffer.toString()).split('\n');
194
- lines.pop();
195
- (0, util_1.checkAbortSignal)(signal);
196
- blockStart = c.minv.dataPosition;
197
- pos = void 0;
198
- i = 0;
199
- _c.label = 5;
200
- case 5:
201
- if (!(i < lines.length)) return [3 /*break*/, 8];
202
- line = lines[i];
203
- for (pos = 0; blockStart >= dpositions[pos]; pos += 1) { }
204
- _b = this.checkLine(metadata, refName, start, end, line), startCoordinate = _b.startCoordinate, overlaps = _b.overlaps;
205
- // do a small check just to make sure that the lines are really sorted by start coordinate
206
- if (previousStartCoordinate !== undefined &&
207
- startCoordinate !== undefined &&
208
- previousStartCoordinate > startCoordinate) {
209
- throw new Error("Lines not sorted by start coordinate (".concat(previousStartCoordinate, " > ").concat(startCoordinate, "), this file is not usable with Tabix."));
210
- }
211
- previousStartCoordinate = startCoordinate;
212
- if (overlaps) {
213
- callback(line.trim(),
214
- // cpositions[pos] refers to actual file offset of a bgzip block boundaries
215
- //
216
- // we multiply by (1 <<8) in order to make sure each block has a "unique"
217
- // address space so that data in that block could never overlap
218
- //
219
- // then the blockStart-dpositions is an uncompressed file offset from
220
- // that bgzip block boundary, and since the cpositions are multiplied by
221
- // (1 << 8) these uncompressed offsets get a unique space
222
- cpositions[pos] * (1 << 8) + (blockStart - dpositions[pos]));
223
- }
224
- else if (startCoordinate !== undefined && startCoordinate >= end) {
225
- // the lines were overlapping the region, but now have stopped, so
226
- // we must be at the end of the relevant data and we can stop
227
- // processing data now
228
- return [2 /*return*/];
229
- }
230
- blockStart += line.length + 1;
231
- if (!(last - Date.now() > 500)) return [3 /*break*/, 7];
102
+ getLines(refName, start, end, opts) {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ let signal;
105
+ let options = {};
106
+ let callback;
107
+ if (typeof opts === 'undefined') {
108
+ throw new TypeError('line callback must be provided');
109
+ }
110
+ if (typeof opts === 'function') {
111
+ callback = opts;
112
+ }
113
+ else {
114
+ options = opts;
115
+ callback = opts.lineCallback;
116
+ }
117
+ if (refName === undefined) {
118
+ throw new TypeError('must provide a reference sequence name');
119
+ }
120
+ if (!callback) {
121
+ throw new TypeError('line callback must be provided');
122
+ }
123
+ const metadata = yield this.index.getMetadata(options);
124
+ (0, util_1.checkAbortSignal)(signal);
125
+ if (!start) {
126
+ start = 0;
127
+ }
128
+ if (!end) {
129
+ end = metadata.maxRefLength;
130
+ }
131
+ if (!(start <= end)) {
132
+ throw new TypeError('invalid start and end coordinates. start must be less than or equal to end');
133
+ }
134
+ if (start === end) {
135
+ return;
136
+ }
137
+ const chunks = yield this.index.blocksForRange(refName, start, end, options);
138
+ (0, util_1.checkAbortSignal)(signal);
139
+ // check the chunks for any that are over the size limit. if
140
+ // any are, don't fetch any of them
141
+ for (let i = 0; i < chunks.length; i += 1) {
142
+ const size = chunks[i].fetchedSize();
143
+ if (size > this.chunkSizeLimit) {
144
+ throw new Error(`Too much data. Chunk size ${size.toLocaleString()} bytes exceeds chunkSizeLimit of ${this.chunkSizeLimit.toLocaleString()}.`);
145
+ }
146
+ }
147
+ // now go through each chunk and parse and filter the lines out of it
148
+ let last = Date.now();
149
+ for (let chunkNum = 0; chunkNum < chunks.length; chunkNum += 1) {
150
+ let previousStartCoordinate;
151
+ const c = chunks[chunkNum];
152
+ const { buffer, cpositions, dpositions } = yield this.chunkCache.get(c.toString(), c, signal);
153
+ const lines = (typeof TextDecoder !== 'undefined'
154
+ ? new TextDecoder('utf-8').decode(buffer)
155
+ : buffer.toString()).split('\n');
156
+ lines.pop();
157
+ (0, util_1.checkAbortSignal)(signal);
158
+ let blockStart = c.minv.dataPosition;
159
+ let pos;
160
+ for (let i = 0; i < lines.length; i += 1) {
161
+ const line = lines[i];
162
+ for (pos = 0; blockStart >= dpositions[pos]; pos += 1) { }
163
+ // filter the line for whether it is within the requested range
164
+ const { startCoordinate, overlaps } = this.checkLine(metadata, refName, start, end, line);
165
+ // do a small check just to make sure that the lines are really sorted by start coordinate
166
+ if (previousStartCoordinate !== undefined &&
167
+ startCoordinate !== undefined &&
168
+ previousStartCoordinate > startCoordinate) {
169
+ throw new Error(`Lines not sorted by start coordinate (${previousStartCoordinate} > ${startCoordinate}), this file is not usable with Tabix.`);
170
+ }
171
+ previousStartCoordinate = startCoordinate;
172
+ if (overlaps) {
173
+ callback(line.trim(),
174
+ // cpositions[pos] refers to actual file offset of a bgzip block boundaries
175
+ //
176
+ // we multiply by (1 <<8) in order to make sure each block has a "unique"
177
+ // address space so that data in that block could never overlap
178
+ //
179
+ // then the blockStart-dpositions is an uncompressed file offset from
180
+ // that bgzip block boundary, and since the cpositions are multiplied by
181
+ // (1 << 8) these uncompressed offsets get a unique space
182
+ cpositions[pos] * (1 << 8) + (blockStart - dpositions[pos]));
183
+ }
184
+ else if (startCoordinate !== undefined && startCoordinate >= end) {
185
+ // the lines were overlapping the region, but now have stopped, so
186
+ // we must be at the end of the relevant data and we can stop
187
+ // processing data now
188
+ return;
189
+ }
190
+ blockStart += line.length + 1;
191
+ // yield if we have emitted beyond the yield limit
192
+ if (last - Date.now() > 500) {
232
193
  last = Date.now();
233
194
  (0, util_1.checkAbortSignal)(signal);
234
- return [4 /*yield*/, timeout(1)];
235
- case 6:
236
- _c.sent();
237
- _c.label = 7;
238
- case 7:
239
- i += 1;
240
- return [3 /*break*/, 5];
241
- case 8:
242
- chunkNum += 1;
243
- return [3 /*break*/, 3];
244
- case 9: return [2 /*return*/];
195
+ yield timeout(1);
196
+ }
245
197
  }
246
- });
198
+ }
247
199
  });
248
- };
249
- TabixIndexedFile.prototype.getMetadata = function (opts) {
250
- if (opts === void 0) { opts = {}; }
251
- return __awaiter(this, void 0, void 0, function () {
252
- return __generator(this, function (_a) {
253
- return [2 /*return*/, this.index.getMetadata(opts)];
254
- });
200
+ }
201
+ getMetadata(opts = {}) {
202
+ return __awaiter(this, void 0, void 0, function* () {
203
+ return this.index.getMetadata(opts);
255
204
  });
256
- };
205
+ }
257
206
  /**
258
207
  * get a buffer containing the "header" region of
259
208
  * the file, which are the bytes up to the first
@@ -261,78 +210,58 @@ var TabixIndexedFile = /** @class */ (function () {
261
210
  *
262
211
  * @returns {Promise} for a buffer
263
212
  */
264
- TabixIndexedFile.prototype.getHeaderBuffer = function (opts) {
265
- if (opts === void 0) { opts = {}; }
266
- return __awaiter(this, void 0, void 0, function () {
267
- var _a, firstDataLine, metaChar, maxBlockSize, maxFetch, bytes, e_1, lastNewline, newlineByte, metaByte, i;
268
- return __generator(this, function (_b) {
269
- switch (_b.label) {
270
- case 0: return [4 /*yield*/, this.getMetadata(opts)];
271
- case 1:
272
- _a = _b.sent(), firstDataLine = _a.firstDataLine, metaChar = _a.metaChar, maxBlockSize = _a.maxBlockSize;
273
- (0, util_1.checkAbortSignal)(opts.signal);
274
- maxFetch = firstDataLine && firstDataLine.blockPosition
275
- ? firstDataLine.blockPosition + maxBlockSize
276
- : maxBlockSize;
277
- return [4 /*yield*/, this._readRegion(0, maxFetch, opts)];
278
- case 2:
279
- bytes = _b.sent();
280
- (0, util_1.checkAbortSignal)(opts.signal);
281
- _b.label = 3;
282
- case 3:
283
- _b.trys.push([3, 5, , 6]);
284
- return [4 /*yield*/, (0, bgzf_filehandle_1.unzip)(bytes)];
285
- case 4:
286
- bytes = _b.sent();
287
- return [3 /*break*/, 6];
288
- case 5:
289
- e_1 = _b.sent();
290
- console.error(e_1);
291
- throw new Error(
292
- //@ts-ignore
293
- "error decompressing block ".concat(e_1.code, " at 0 (length ").concat(maxFetch, ") ").concat(e_1));
294
- case 6:
295
- // trim off lines after the last non-meta line
296
- if (metaChar) {
297
- lastNewline = -1;
298
- newlineByte = '\n'.charCodeAt(0);
299
- metaByte = metaChar.charCodeAt(0);
300
- for (i = 0; i < bytes.length; i += 1) {
301
- if (i === lastNewline + 1 && bytes[i] !== metaByte) {
302
- break;
303
- }
304
- if (bytes[i] === newlineByte) {
305
- lastNewline = i;
306
- }
307
- }
308
- bytes = bytes.slice(0, lastNewline + 1);
309
- }
310
- return [2 /*return*/, bytes];
213
+ getHeaderBuffer(opts = {}) {
214
+ return __awaiter(this, void 0, void 0, function* () {
215
+ const { firstDataLine, metaChar, maxBlockSize } = yield this.getMetadata(opts);
216
+ (0, util_1.checkAbortSignal)(opts.signal);
217
+ const maxFetch = firstDataLine && firstDataLine.blockPosition
218
+ ? firstDataLine.blockPosition + maxBlockSize
219
+ : maxBlockSize;
220
+ // TODO: what if we don't have a firstDataLine, and the header
221
+ // actually takes up more than one block? this case is not covered here
222
+ let bytes = yield this._readRegion(0, maxFetch, opts);
223
+ (0, util_1.checkAbortSignal)(opts.signal);
224
+ try {
225
+ bytes = yield (0, bgzf_filehandle_1.unzip)(bytes);
226
+ }
227
+ catch (e) {
228
+ console.error(e);
229
+ throw new Error(
230
+ //@ts-ignore
231
+ `error decompressing block ${e.code} at 0 (length ${maxFetch}) ${e}`);
232
+ }
233
+ // trim off lines after the last non-meta line
234
+ if (metaChar) {
235
+ // trim backward from the end
236
+ let lastNewline = -1;
237
+ const newlineByte = '\n'.charCodeAt(0);
238
+ const metaByte = metaChar.charCodeAt(0);
239
+ for (let i = 0; i < bytes.length; i += 1) {
240
+ if (i === lastNewline + 1 && bytes[i] !== metaByte) {
241
+ break;
242
+ }
243
+ if (bytes[i] === newlineByte) {
244
+ lastNewline = i;
245
+ }
311
246
  }
312
- });
247
+ bytes = bytes.slice(0, lastNewline + 1);
248
+ }
249
+ return bytes;
313
250
  });
314
- };
251
+ }
315
252
  /**
316
253
  * get a string containing the "header" region of the
317
254
  * file, is the portion up to the first non-meta line
318
255
  *
319
256
  * @returns {Promise} for a string
320
257
  */
321
- TabixIndexedFile.prototype.getHeader = function (opts) {
322
- if (opts === void 0) { opts = {}; }
323
- return __awaiter(this, void 0, void 0, function () {
324
- var bytes;
325
- return __generator(this, function (_a) {
326
- switch (_a.label) {
327
- case 0: return [4 /*yield*/, this.getHeaderBuffer(opts)];
328
- case 1:
329
- bytes = _a.sent();
330
- (0, util_1.checkAbortSignal)(opts.signal);
331
- return [2 /*return*/, bytes.toString('utf8')];
332
- }
333
- });
258
+ getHeader(opts = {}) {
259
+ return __awaiter(this, void 0, void 0, function* () {
260
+ const bytes = yield this.getHeaderBuffer(opts);
261
+ (0, util_1.checkAbortSignal)(opts.signal);
262
+ return bytes.toString('utf8');
334
263
  });
335
- };
264
+ }
336
265
  /**
337
266
  * get an array of reference sequence names, in the order in which
338
267
  * they occur in the file.
@@ -341,20 +270,12 @@ var TabixIndexedFile = /** @class */ (function () {
341
270
  *
342
271
  * @returns {Promise} for an array of string sequence names
343
272
  */
344
- TabixIndexedFile.prototype.getReferenceSequenceNames = function (opts) {
345
- if (opts === void 0) { opts = {}; }
346
- return __awaiter(this, void 0, void 0, function () {
347
- var metadata;
348
- return __generator(this, function (_a) {
349
- switch (_a.label) {
350
- case 0: return [4 /*yield*/, this.getMetadata(opts)];
351
- case 1:
352
- metadata = _a.sent();
353
- return [2 /*return*/, metadata.refIdToName];
354
- }
355
- });
273
+ getReferenceSequenceNames(opts = {}) {
274
+ return __awaiter(this, void 0, void 0, function* () {
275
+ const metadata = yield this.getMetadata(opts);
276
+ return metadata.refIdToName;
356
277
  });
357
- };
278
+ }
358
279
  /**
359
280
  * @param {object} metadata metadata object from the parsed index,
360
281
  * containing columnNumbers, metaChar, and format
@@ -365,14 +286,13 @@ var TabixIndexedFile = /** @class */ (function () {
365
286
  * @returns {object} like `{startCoordinate, overlaps}`. overlaps is boolean,
366
287
  * true if line is a data line that overlaps the given region
367
288
  */
368
- TabixIndexedFile.prototype.checkLine = function (_a, regionRefName, regionStart, regionEnd, line) {
369
- var columnNumbers = _a.columnNumbers, metaChar = _a.metaChar, coordinateType = _a.coordinateType, format = _a.format;
289
+ checkLine({ columnNumbers, metaChar, coordinateType, format, }, regionRefName, regionStart, regionEnd, line) {
370
290
  // skip meta lines
371
291
  if (line.charAt(0) === metaChar) {
372
292
  return { overlaps: false };
373
293
  }
374
294
  // check ref/start/end using column metadata from index
375
- var ref = columnNumbers.ref, start = columnNumbers.start, end = columnNumbers.end;
295
+ let { ref, start, end } = columnNumbers;
376
296
  if (!ref) {
377
297
  ref = 0;
378
298
  }
@@ -385,15 +305,15 @@ var TabixIndexedFile = /** @class */ (function () {
385
305
  if (format === 'VCF') {
386
306
  end = 8;
387
307
  }
388
- var maxColumn = Math.max(ref, start, end);
308
+ const maxColumn = Math.max(ref, start, end);
389
309
  // this code is kind of complex, but it is fairly fast.
390
310
  // basically, we want to avoid doing a split, because if the lines are really long
391
311
  // that could lead to us allocating a bunch of extra memory, which is slow
392
- var currentColumnNumber = 1; // cols are numbered starting at 1 in the index metadata
393
- var currentColumnStart = 0;
394
- var refSeq = '';
395
- var startCoordinate = -Infinity;
396
- for (var i = 0; i < line.length + 1; i += 1) {
312
+ let currentColumnNumber = 1; // cols are numbered starting at 1 in the index metadata
313
+ let currentColumnStart = 0;
314
+ let refSeq = '';
315
+ let startCoordinate = -Infinity;
316
+ for (let i = 0; i < line.length + 1; i += 1) {
397
317
  if (line[i] === '\t' || i === line.length) {
398
318
  if (currentColumnNumber === ref) {
399
319
  if (this.renameRefSeq(line.slice(currentColumnStart, i)) !==
@@ -408,12 +328,12 @@ var TabixIndexedFile = /** @class */ (function () {
408
328
  startCoordinate -= 1;
409
329
  }
410
330
  if (startCoordinate >= regionEnd) {
411
- return { startCoordinate: startCoordinate, overlaps: false };
331
+ return { startCoordinate, overlaps: false };
412
332
  }
413
333
  if (end === 0 || end === start) {
414
334
  // if we have no end, we assume the feature is 1 bp long
415
335
  if (startCoordinate + 1 <= regionStart) {
416
- return { startCoordinate: startCoordinate, overlaps: false };
336
+ return { startCoordinate, overlaps: false };
417
337
  }
418
338
  }
419
339
  }
@@ -421,9 +341,7 @@ var TabixIndexedFile = /** @class */ (function () {
421
341
  refSeq = line.slice(currentColumnStart, i);
422
342
  }
423
343
  else if (currentColumnNumber === end) {
424
- var endCoordinate
425
- // this will never match if there is no end column
426
- = void 0;
344
+ let endCoordinate;
427
345
  // this will never match if there is no end column
428
346
  if (format === 'VCF') {
429
347
  endCoordinate = this._getVcfEnd(startCoordinate, refSeq, line.slice(currentColumnStart, i));
@@ -442,21 +360,21 @@ var TabixIndexedFile = /** @class */ (function () {
442
360
  }
443
361
  }
444
362
  }
445
- return { startCoordinate: startCoordinate, overlaps: true };
446
- };
447
- TabixIndexedFile.prototype._getVcfEnd = function (startCoordinate, refSeq, info) {
448
- var endCoordinate = startCoordinate + refSeq.length;
363
+ return { startCoordinate, overlaps: true };
364
+ }
365
+ _getVcfEnd(startCoordinate, refSeq, info) {
366
+ let endCoordinate = startCoordinate + refSeq.length;
449
367
  // ignore TRA features as they specify CHR2 and END
450
368
  // as being on a different chromosome
451
369
  // if CHR2 is on the same chromosome, still ignore it
452
370
  // because there should be another pairwise feature
453
371
  // at the end of this one
454
- var isTRA = info.indexOf('SVTYPE=TRA') !== -1;
372
+ const isTRA = info.indexOf('SVTYPE=TRA') !== -1;
455
373
  if (info[0] !== '.' && !isTRA) {
456
- var prevChar = ';';
457
- for (var j = 0; j < info.length; j += 1) {
374
+ let prevChar = ';';
375
+ for (let j = 0; j < info.length; j += 1) {
458
376
  if (prevChar === ';' && info.slice(j, j + 4) === 'END=') {
459
- var valueEnd = info.indexOf(';', j);
377
+ let valueEnd = info.indexOf(';', j);
460
378
  if (valueEnd === -1) {
461
379
  valueEnd = info.length;
462
380
  }
@@ -470,61 +388,42 @@ var TabixIndexedFile = /** @class */ (function () {
470
388
  return startCoordinate + 1;
471
389
  }
472
390
  return endCoordinate;
473
- };
391
+ }
474
392
  /**
475
393
  * return the approximate number of data lines in the given reference sequence
476
394
  * @param {string} refSeq reference sequence name
477
395
  * @returns {Promise} for number of data lines present on that reference sequence
478
396
  */
479
- TabixIndexedFile.prototype.lineCount = function (refName, opts) {
480
- if (opts === void 0) { opts = {}; }
481
- return __awaiter(this, void 0, void 0, function () {
482
- return __generator(this, function (_a) {
483
- return [2 /*return*/, this.index.lineCount(refName, opts)];
484
- });
397
+ lineCount(refName, opts = {}) {
398
+ return __awaiter(this, void 0, void 0, function* () {
399
+ return this.index.lineCount(refName, opts);
485
400
  });
486
- };
487
- TabixIndexedFile.prototype._readRegion = function (position, compressedSize, opts) {
488
- if (opts === void 0) { opts = {}; }
489
- return __awaiter(this, void 0, void 0, function () {
490
- var _a, bytesRead, buffer;
491
- return __generator(this, function (_b) {
492
- switch (_b.label) {
493
- case 0: return [4 /*yield*/, this.filehandle.read(Buffer.alloc(compressedSize), 0, compressedSize, position, opts)];
494
- case 1:
495
- _a = _b.sent(), bytesRead = _a.bytesRead, buffer = _a.buffer;
496
- return [2 /*return*/, bytesRead < compressedSize ? buffer.slice(0, bytesRead) : buffer];
497
- }
498
- });
401
+ }
402
+ _readRegion(position, compressedSize, opts = {}) {
403
+ return __awaiter(this, void 0, void 0, function* () {
404
+ const { bytesRead, buffer } = yield this.filehandle.read(Buffer.alloc(compressedSize), 0, compressedSize, position, opts);
405
+ return bytesRead < compressedSize ? buffer.slice(0, bytesRead) : buffer;
499
406
  });
500
- };
407
+ }
501
408
  /**
502
409
  * read and uncompress the data in a chunk (composed of one or more
503
410
  * contiguous bgzip blocks) of the file
504
411
  * @param {Chunk} chunk
505
412
  * @returns {Promise} for a string chunk of the file
506
413
  */
507
- TabixIndexedFile.prototype.readChunk = function (chunk, opts) {
508
- if (opts === void 0) { opts = {}; }
509
- return __awaiter(this, void 0, void 0, function () {
510
- var compressedData;
511
- return __generator(this, function (_a) {
512
- switch (_a.label) {
513
- case 0: return [4 /*yield*/, this._readRegion(chunk.minv.blockPosition, chunk.fetchedSize(), opts)];
514
- case 1:
515
- compressedData = _a.sent();
516
- try {
517
- return [2 /*return*/, (0, bgzf_filehandle_1.unzipChunkSlice)(compressedData, chunk)];
518
- }
519
- catch (e) {
520
- throw new Error("error decompressing chunk ".concat(chunk.toString(), " ").concat(e));
521
- }
522
- return [2 /*return*/];
523
- }
524
- });
414
+ readChunk(chunk, opts = {}) {
415
+ return __awaiter(this, void 0, void 0, function* () {
416
+ // fetch the uncompressed data, uncompress carefully a block at a time,
417
+ // and stop when done
418
+ const compressedData = yield this._readRegion(chunk.minv.blockPosition, chunk.fetchedSize(), opts);
419
+ try {
420
+ return (0, bgzf_filehandle_1.unzipChunkSlice)(compressedData, chunk);
421
+ }
422
+ catch (e) {
423
+ throw new Error(`error decompressing chunk ${chunk.toString()} ${e}`);
424
+ }
525
425
  });
526
- };
527
- return TabixIndexedFile;
528
- }());
426
+ }
427
+ }
529
428
  exports.default = TabixIndexedFile;
530
429
  //# sourceMappingURL=tabixIndexedFile.js.map