@gmod/tabix 1.5.15 → 1.6.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 CHANGED
@@ -1,15 +1,15 @@
1
- ## [1.5.15](https://github.com/GMOD/tabix-js/compare/v1.5.14...v1.5.15) (2024-08-30)
1
+ # [1.6.0](https://github.com/GMOD/tabix-js/compare/v1.5.15...v1.6.0) (2024-11-30)
2
2
 
3
3
 
4
4
 
5
- ## [1.5.14](https://github.com/GMOD/tabix-js/compare/v1.5.13...v1.5.14) (2024-07-23)
5
+ ## [1.5.15](https://github.com/GMOD/tabix-js/compare/v1.5.14...v1.5.15) (2024-08-30)
6
6
 
7
+ ## [1.5.14](https://github.com/GMOD/tabix-js/compare/v1.5.13...v1.5.14) (2024-07-23)
7
8
 
8
9
  ### Reverts
9
10
 
10
- * Revert "Bump to eslint 9" ([9bd49b1](https://github.com/GMOD/tabix-js/commit/9bd49b1132f632b0e7847d9b95cf3cb08c424360))
11
-
12
-
11
+ - Revert "Bump to eslint 9"
12
+ ([9bd49b1](https://github.com/GMOD/tabix-js/commit/9bd49b1132f632b0e7847d9b95cf3cb08c424360))
13
13
 
14
14
  ## [1.5.13](https://github.com/GMOD/tabix-js/compare/v1.5.12...v1.5.13) (2024-01-09)
15
15
 
@@ -17,8 +17,8 @@
17
17
 
18
18
  ## [1.5.12](https://github.com/GMOD/tabix-js/compare/v1.5.11...v1.5.12) (2024-01-09)
19
19
 
20
- - Add missing abort signal to the @gmod/abortable-promise-cache fetch for tabix chunks
21
- (#143)
20
+ - Add missing abort signal to the @gmod/abortable-promise-cache fetch for tabix
21
+ chunks (#143)
22
22
 
23
23
  ## [1.5.11](https://github.com/GMOD/tabix-js/compare/v1.5.10...v1.5.11) (2023-07-10)
24
24
 
package/README.md CHANGED
@@ -27,8 +27,8 @@ import { TabixIndexedFile } from '@gmod/tabix'
27
27
  You can use tabix-js without NPM also with the tabix-bundle.js. See the example
28
28
  directory for usage with script tag [example/index.html](example/index.html)
29
29
 
30
- ```
31
- <script src="https://unpkg.com/@gmod/tabix/dist/tabix-bundle.js"></script>
30
+ ```html
31
+ <script src="https://unpkg.com/@gmod/tabix/dist/tabix-bundle.js"></script>
32
32
  ```
33
33
 
34
34
  ### TabixIndexedFile constructor
@@ -47,10 +47,10 @@ const tbiIndexed = new TabixIndexedFile({
47
47
 
48
48
  ```
49
49
 
50
- You can also use CSI indexes. Note also the usage of the renameRefSeqs callback.
51
- The renameRefSeqs callback makes it so that you can use
52
- file.getLines('1',0,100,...) even when the file itself contains names like
53
- 'chr1' (can also do the reverse by customizing the renameRefSeqs callback)
50
+ You can also use CSI indexes. Note also the usage of the `renameRefSeqs`
51
+ callback. The `renameRefSeqs` callback makes it so that you can use
52
+ `file.getLines('1',0,100,...)` even when the file itself contains names like
53
+ 'chr1' (can also do the reverse by customizing the `renameRefSeqs` callback)
54
54
 
55
55
  ```typescript
56
56
  // can also open tabix files that have a .csi index
@@ -64,9 +64,15 @@ const csiIndexed = new TabixIndexedFile({
64
64
 
65
65
  #### TabixIndexedFile constructor with remote files
66
66
 
67
- The basic usage of fetching remote files is done by supplying a
68
- [generic-filehandle](https://github.com/GMOD/generic-filehandle) module
69
- RemoteFile filehandle, as seen below
67
+ ```typescript
68
+ const remoteTbiIndexed = new TabixIndexedFile({
69
+ url: 'http://yourhost/file.vcf.gz',
70
+ tbiUrl: 'http://yourhost/file.vcf.gz.tbi', // can also be csiUrl
71
+ })
72
+ ```
73
+
74
+ You can also alternatively supply a filehandle-like object with the
75
+ [generic-filehandle](https://github.com/GMOD/generic-filehandle): example
70
76
 
71
77
  ```typescript
72
78
  // use a remote file or other filehandle, note RemoteFile comes from https://github.com/GMOD/generic-filehandle
@@ -77,9 +83,9 @@ const remoteTbiIndexed = new TabixIndexedFile({
77
83
  })
78
84
  ```
79
85
 
80
- This works in both the browser and in node.js, but note that in node.js you have
81
- to also supply a custom fetch function to the RemoteFile constructor e.g. like
82
- this
86
+ This works in both the browser and in node.js, but note that in node.js you may
87
+ have to also supply a custom fetch function to the RemoteFile constructor e.g.
88
+ like this
83
89
 
84
90
  ```typescript
85
91
  // for node.js you have to manually supply a fetch function e.g. node-fetch to RemoteFile
@@ -111,8 +117,8 @@ await tbiIndexed.getLines('ctgA', 200, 300, function (line, fileOffset) {
111
117
  After running this, your `lines` array would contain an array of lines from the
112
118
  file that match your query range
113
119
 
114
- You can also supply some extra arguments to getLines with this format, but these
115
- are sort of obscure and only used in some circumstances
120
+ You can also supply some extra arguments to `getLines` with this format, but
121
+ these are sort of obscure and only used in some circumstances
116
122
 
117
123
  ```typescript
118
124
  const lines = []
@@ -133,8 +139,8 @@ Notes about the returned values of `getLines`:
133
139
  - the callback is also called with a `fileOffset` that can be used to uniquely
134
140
  identify lines based on their virtual file offset where the line is found in
135
141
  the file
136
- - if getLines is called with an undefined `end` parameter it gets all lines from
137
- start going to the end of the contig e.g.
142
+ - if `getLines` is called with an undefined `end` parameter it gets all lines
143
+ from start going to the end of the contig e.g.
138
144
 
139
145
  ```typescript
140
146
  const lines = []
@@ -142,32 +148,164 @@ await tbiIndexed.getLines('ctgA', 0, undefined, line=>lines.push(line))`
142
148
  console.log(lines)
143
149
  ```
144
150
 
145
- ### lineCount
151
+ ## API (auto-generated)
152
+
153
+ ### TabixIndexedFile
154
+
155
+ <!-- Generated by documentation.js. Update this documentation by updating the source code. -->
156
+
157
+ ##### Table of Contents
158
+
159
+ - [constructor](#constructor)
160
+ - [Parameters](#parameters)
161
+ - [getLines](#getlines)
162
+ - [Parameters](#parameters-1)
163
+ - [getHeaderBuffer](#getheaderbuffer)
164
+ - [Parameters](#parameters-2)
165
+ - [getHeader](#getheader)
166
+ - [Parameters](#parameters-3)
167
+ - [getReferenceSequenceNames](#getreferencesequencenames)
168
+ - [Parameters](#parameters-4)
169
+ - [checkLine](#checkline)
170
+ - [Parameters](#parameters-5)
171
+ - [lineCount](#linecount)
172
+ - [Parameters](#parameters-6)
173
+ - [readChunk](#readchunk)
174
+ - [Parameters](#parameters-7)
175
+
176
+ #### constructor
177
+
178
+ ##### Parameters
179
+
180
+ - `args`
181
+ **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**&#x20;
182
+
183
+ - `args.path`
184
+ **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**&#x20;
185
+ - `args.filehandle` **filehandle?**&#x20;
186
+ - `args.url`
187
+ **[url](https://developer.mozilla.org/docs/Web/API/URL/URL)?**&#x20;
188
+ - `args.tbiPath`
189
+ **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**&#x20;
190
+ - `args.tbiUrl` **tbiUrl?**&#x20;
191
+ - `args.tbiFilehandle` **filehandle?**&#x20;
192
+ - `args.csiPath`
193
+ **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**&#x20;
194
+ - `args.csiUrl` **csiUrl?**&#x20;
195
+ - `args.csiFilehandle` **filehandle?**&#x20;
196
+ - `args.yieldTime`
197
+ **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)?**
198
+ yield to main thread after N milliseconds if reading features is taking a
199
+ long time to avoid hanging main thread (optional, default `500`)
200
+ - `args.renameRefSeqs`
201
+ **[function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)?**
202
+ optional function with sig `string => string` to transform reference
203
+ sequence names for the purpose of indexing and querying. note that the data
204
+ that is returned is not altered, just the names of the reference sequences
205
+ that are used for querying. (optional, default `n=>n`)
206
+ - `args.chunkCacheSize` (optional, default `5*2**20`)
207
+
208
+ #### getLines
209
+
210
+ ##### Parameters
211
+
212
+ - `refName`
213
+ **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
214
+ name of the reference sequence
215
+ - `s`
216
+ **([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)
217
+ |
218
+ [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**&#x20;
219
+ - `e`
220
+ **([number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)
221
+ |
222
+ [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**&#x20;
223
+ - `opts` **(GetLinesOpts | GetLinesCallback)** callback called for each line in
224
+ the region. can also pass a object param containing obj.lineCallback,
225
+ obj.signal, etc
226
+ - `start` start of the region (in 0-based half-open coordinates)
227
+ - `end` end of the region (in 0-based half-open coordinates)
228
+
229
+ Returns **any** promise that is resolved when the whole read is finished,
230
+ rejected on error
146
231
 
147
- ```typescript
148
- // get the approximate number of data lines in the
149
- // file for the given reference sequence, excluding header, comment, and whitespace lines
150
- // uses the extra bin from tabix
151
- const numLines = await tbiIndexed.lineCount('ctgA')
152
- // or const numLines = await tbiIndexed.lineCount('ctgA', { signal: aborter.signal })
153
- ```
232
+ #### getHeaderBuffer
154
233
 
155
- ### getHeader
234
+ get a buffer containing the "header" region of the file, which are the bytes up
235
+ to the first non-meta line
156
236
 
157
- ```typescript
158
- // get the "header text" string from the file, which is the first contiguous
159
- // set of lines in the file that all start with a "meta" character (usually #)
160
- const headerText = await tbiIndexed.getHeader()
161
- // or const headerText = await tbiIndexed.getHeader({ signal: aborter.signal })
162
- ```
237
+ ##### Parameters
163
238
 
164
- #### getHeaderBuffer
239
+ - `opts` **Options** (optional, default `{}`)
165
240
 
166
- ```typescript
167
- // or if you want a nodejs Buffer object instead, there is getHeaderBuffer()
168
- const headerBuffer = await tbiIndexed.getHeaderBuffer()
169
- // or const headerBuffer = await tbiIndexed.getHeaderBuffer({ signal: aborter.signal })
170
- ```
241
+ #### getHeader
242
+
243
+ get a string containing the "header" region of the file, is the portion up to
244
+ the first non-meta line
245
+
246
+ ##### Parameters
247
+
248
+ - `opts` **Options** (optional, default `{}`)
249
+
250
+ Returns
251
+ **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)**
252
+ for a string
253
+
254
+ #### getReferenceSequenceNames
255
+
256
+ get an array of reference sequence names, in the order in which they occur in
257
+ the file. reference sequence renaming is not applied to these names.
258
+
259
+ ##### Parameters
260
+
261
+ - `opts` **Options** (optional, default `{}`)
262
+
263
+ #### checkLine
264
+
265
+ ##### Parameters
266
+
267
+ - `metadata`
268
+ **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**
269
+ metadata object from the parsed index, containing columnNumbers, metaChar, and
270
+ format
271
+ - `regionRefName`
272
+ **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**&#x20;
273
+ - `regionStart`
274
+ **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
275
+ region start coordinate (0-based-half-open)
276
+ - `regionEnd`
277
+ **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)**
278
+ region end coordinate (0-based-half-open)
279
+ - `line`
280
+ **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**&#x20;
281
+
282
+ Returns
283
+ **[object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**
284
+ like `{startCoordinate, overlaps}`. overlaps is boolean, true if line is a data
285
+ line that overlaps the given region
286
+
287
+ #### lineCount
288
+
289
+ return the approximate number of data lines in the given reference sequence
290
+
291
+ ##### Parameters
292
+
293
+ - `refName`
294
+ **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**&#x20;
295
+ - `opts` **Options** (optional, default `{}`)
296
+ - `refSeq` reference sequence name
297
+
298
+ Returns **any** number of data lines present on that reference sequence
299
+
300
+ #### readChunk
301
+
302
+ read and uncompress the data in a chunk (composed of one or more contiguous
303
+ bgzip blocks) of the file
304
+
305
+ ##### Parameters
306
+
307
+ - `c` **Chunk**&#x20;
308
+ - `opts` **Options** (optional, default `{}`)
171
309
 
172
310
  ## Academic Use
173
311
 
package/dist/chunk.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"chunk.js","sourceRoot":"","sources":["../src/chunk.ts"],"names":[],"mappings":";;AAEA,iDAAiD;AACjD,MAAqB,KAAK;IAMxB,YACE,IAAmB,EACnB,IAAmB,EACnB,GAAW,EACX,WAAW,GAAG,SAAS;QAEvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,YAAY,GAAG,WAAW,CAAA;IACjC,CAAC;IAED,cAAc;QAEZ,OAAO,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,SAC/B,IAAI,CAAC,GACP,iBAAiB,IAAI,CAAC,WAAW,EAAE,GAAG,CAAA;IACxC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,cAAc,EAAE,CAAA;IAC9B,CAAC;IAED,SAAS,CAAC,CAAQ;QAChB,OAAO,CACL,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3B,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CACjB,CAAA;IACH,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC,YAAY,CAAA;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAA;IACtE,CAAC;CACF;AA3CD,wBA2CC"}
1
+ {"version":3,"file":"chunk.js","sourceRoot":"","sources":["../src/chunk.ts"],"names":[],"mappings":";;AAEA,iDAAiD;AACjD,MAAqB,KAAK;IAMxB,YACE,IAAmB,EACnB,IAAmB,EACnB,GAAW,EACX,WAAW,GAAG,SAAS;QAEvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAA;QACd,IAAI,CAAC,YAAY,GAAG,WAAW,CAAA;IACjC,CAAC;IAED,cAAc;QACZ,OAAO,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,SAC/B,IAAI,CAAC,GACP,iBAAiB,IAAI,CAAC,WAAW,EAAE,GAAG,CAAA;IACxC,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,CAAC,cAAc,EAAE,CAAA;IAC9B,CAAC;IAED,SAAS,CAAC,CAAQ;QAChB,OAAO,CACL,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3B,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CACjB,CAAA;IACH,CAAC;IAED,WAAW;QACT,IAAI,IAAI,CAAC,YAAY,KAAK,SAAS,EAAE,CAAC;YACpC,OAAO,IAAI,CAAC,YAAY,CAAA;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAA;IACtE,CAAC;CACF;AA1CD,wBA0CC"}
package/dist/csi.js CHANGED
@@ -15,22 +15,23 @@ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (
15
15
  }) : function(o, v) {
16
16
  o["default"] = v;
17
17
  });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27
- return new (P || (P = Promise))(function (resolve, reject) {
28
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31
- step((generator = generator.apply(thisArg, _arguments || [])).next());
32
- });
33
- };
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
34
35
  var __importDefault = (this && this.__importDefault) || function (mod) {
35
36
  return (mod && mod.__esModule) ? mod : { "default": mod };
36
37
  };
@@ -44,10 +45,10 @@ const indexFile_1 = __importDefault(require("./indexFile"));
44
45
  const CSI1_MAGIC = 21582659; // CSI\1
45
46
  const CSI2_MAGIC = 38359875; // CSI\2
46
47
  function lshift(num, bits) {
47
- return num * Math.pow(2, bits);
48
+ return num * 2 ** bits;
48
49
  }
49
50
  function rshift(num, bits) {
50
- return Math.floor(num / Math.pow(2, bits));
51
+ return Math.floor(num / 2 ** bits);
51
52
  }
52
53
  class CSI extends indexFile_1.default {
53
54
  constructor(args) {
@@ -56,23 +57,21 @@ class CSI extends indexFile_1.default {
56
57
  this.depth = 0;
57
58
  this.minShift = 0;
58
59
  }
59
- lineCount(refName_1) {
60
- return __awaiter(this, arguments, void 0, function* (refName, opts = {}) {
61
- const indexData = yield this.parse(opts);
62
- const refId = indexData.refNameToId[refName];
63
- if (refId === undefined) {
64
- return -1;
65
- }
66
- const idx = indexData.indices[refId];
67
- if (!idx) {
68
- return -1;
69
- }
70
- const { stats } = indexData.indices[refId];
71
- if (stats) {
72
- return stats.lineCount;
73
- }
60
+ async lineCount(refName, opts = {}) {
61
+ const indexData = await this.parse(opts);
62
+ const refId = indexData.refNameToId[refName];
63
+ if (refId === undefined) {
74
64
  return -1;
75
- });
65
+ }
66
+ const idx = indexData.indices[refId];
67
+ if (!idx) {
68
+ return -1;
69
+ }
70
+ const { stats } = indexData.indices[refId];
71
+ if (stats) {
72
+ return stats.lineCount;
73
+ }
74
+ return -1;
76
75
  }
77
76
  indexCov() {
78
77
  throw new Error('CSI indexes do not support indexcov');
@@ -124,110 +123,115 @@ class CSI extends indexFile_1.default {
124
123
  return { refNameToId, refIdToName };
125
124
  }
126
125
  // fetch and parse the index
127
- _parse() {
128
- return __awaiter(this, arguments, void 0, function* (opts = {}) {
129
- const bytes = yield (0, bgzf_filehandle_1.unzip)(yield this.filehandle.readFile(opts));
130
- // check TBI magic numbers
131
- let csiVersion;
132
- if (bytes.readUInt32LE(0) === CSI1_MAGIC) {
133
- csiVersion = 1;
134
- }
135
- else if (bytes.readUInt32LE(0) === CSI2_MAGIC) {
136
- csiVersion = 2;
137
- }
138
- else {
139
- throw new Error('Not a CSI file');
140
- // TODO: do we need to support big-endian CSI files?
141
- }
142
- this.minShift = bytes.readInt32LE(4);
143
- this.depth = bytes.readInt32LE(8);
144
- this.maxBinNumber = ((1 << ((this.depth + 1) * 3)) - 1) / 7;
145
- const maxRefLength = Math.pow(2, (this.minShift + this.depth * 3));
146
- const auxLength = bytes.readInt32LE(12);
147
- const aux = auxLength && auxLength >= 30
148
- ? this.parseAuxData(bytes, 16)
149
- : {
150
- refIdToName: [],
151
- refNameToId: {},
152
- metaChar: null,
153
- columnNumbers: { ref: 0, start: 1, end: 2 },
154
- coordinateType: 'zero-based-half-open',
155
- format: 'generic',
156
- };
157
- const refCount = bytes.readInt32LE(16 + auxLength);
158
- // read the indexes for each reference sequence
159
- let firstDataLine;
160
- let currOffset = 16 + auxLength + 4;
161
- const indices = new Array(refCount).fill(0).map(() => {
162
- // the binning index
163
- const binCount = bytes.readInt32LE(currOffset);
164
- currOffset += 4;
165
- const binIndex = {};
166
- let stats; // < provided by parsing a pseudo-bin, if present
167
- for (let j = 0; j < binCount; j += 1) {
168
- const bin = bytes.readUInt32LE(currOffset);
169
- if (bin > this.maxBinNumber) {
170
- // this is a fake bin that actually has stats information
171
- // about the reference sequence in it
172
- stats = this.parsePseudoBin(bytes, currOffset + 4);
173
- currOffset += 4 + 8 + 4 + 16 + 16;
174
- }
175
- else {
176
- const loffset = (0, virtualOffset_1.fromBytes)(bytes, currOffset + 4);
177
- firstDataLine = this._findFirstData(firstDataLine, loffset);
178
- const chunkCount = bytes.readInt32LE(currOffset + 12);
126
+ async _parse(opts = {}) {
127
+ const bytes = await (0, bgzf_filehandle_1.unzip)(await this.filehandle.readFile(opts));
128
+ // check TBI magic numbers
129
+ let csiVersion;
130
+ if (bytes.readUInt32LE(0) === CSI1_MAGIC) {
131
+ csiVersion = 1;
132
+ }
133
+ else if (bytes.readUInt32LE(0) === CSI2_MAGIC) {
134
+ csiVersion = 2;
135
+ }
136
+ else {
137
+ throw new Error('Not a CSI file');
138
+ // TODO: do we need to support big-endian CSI files?
139
+ }
140
+ this.minShift = bytes.readInt32LE(4);
141
+ this.depth = bytes.readInt32LE(8);
142
+ this.maxBinNumber = ((1 << ((this.depth + 1) * 3)) - 1) / 7;
143
+ const maxRefLength = 2 ** (this.minShift + this.depth * 3);
144
+ const auxLength = bytes.readInt32LE(12);
145
+ const aux = auxLength && auxLength >= 30
146
+ ? this.parseAuxData(bytes, 16)
147
+ : {
148
+ refIdToName: [],
149
+ refNameToId: {},
150
+ metaChar: null,
151
+ columnNumbers: { ref: 0, start: 1, end: 2 },
152
+ coordinateType: 'zero-based-half-open',
153
+ format: 'generic',
154
+ };
155
+ const refCount = bytes.readInt32LE(16 + auxLength);
156
+ // read the indexes for each reference sequence
157
+ let firstDataLine;
158
+ let currOffset = 16 + auxLength + 4;
159
+ const indices = new Array(refCount).fill(0).map(() => {
160
+ // the binning index
161
+ const binCount = bytes.readInt32LE(currOffset);
162
+ currOffset += 4;
163
+ const binIndex = {};
164
+ let stats; // < provided by parsing a pseudo-bin, if present
165
+ for (let j = 0; j < binCount; j += 1) {
166
+ const bin = bytes.readUInt32LE(currOffset);
167
+ if (bin > this.maxBinNumber) {
168
+ // this is a fake bin that actually has stats information
169
+ // about the reference sequence in it
170
+ stats = this.parsePseudoBin(bytes, currOffset + 4);
171
+ currOffset += 4 + 8 + 4 + 16 + 16;
172
+ }
173
+ else {
174
+ const loffset = (0, virtualOffset_1.fromBytes)(bytes, currOffset + 4);
175
+ firstDataLine = this._findFirstData(firstDataLine, loffset);
176
+ const chunkCount = bytes.readInt32LE(currOffset + 12);
177
+ currOffset += 16;
178
+ const chunks = new Array(chunkCount);
179
+ for (let k = 0; k < chunkCount; k += 1) {
180
+ const u = (0, virtualOffset_1.fromBytes)(bytes, currOffset);
181
+ const v = (0, virtualOffset_1.fromBytes)(bytes, currOffset + 8);
179
182
  currOffset += 16;
180
- const chunks = new Array(chunkCount);
181
- for (let k = 0; k < chunkCount; k += 1) {
182
- const u = (0, virtualOffset_1.fromBytes)(bytes, currOffset);
183
- const v = (0, virtualOffset_1.fromBytes)(bytes, currOffset + 8);
184
- currOffset += 16;
185
- // this._findFirstData(data, u)
186
- chunks[k] = new chunk_1.default(u, v, bin);
187
- }
188
- binIndex[bin] = chunks;
183
+ // this._findFirstData(data, u)
184
+ chunks[k] = new chunk_1.default(u, v, bin);
189
185
  }
186
+ binIndex[bin] = chunks;
190
187
  }
191
- return { binIndex, stats };
192
- });
193
- return Object.assign(Object.assign({}, aux), { csi: true, refCount, maxBlockSize: 1 << 16, firstDataLine,
194
- csiVersion,
195
- indices, depth: this.depth, maxBinNumber: this.maxBinNumber, maxRefLength });
188
+ }
189
+ return { binIndex, stats };
196
190
  });
191
+ return {
192
+ ...aux,
193
+ csi: true,
194
+ refCount,
195
+ maxBlockSize: 1 << 16,
196
+ firstDataLine,
197
+ csiVersion,
198
+ indices,
199
+ depth: this.depth,
200
+ maxBinNumber: this.maxBinNumber,
201
+ maxRefLength,
202
+ };
197
203
  }
198
204
  parsePseudoBin(bytes, offset) {
199
205
  const lineCount = (0, util_1.longToNumber)(long_1.default.fromBytesLE(bytes.slice(offset + 28, offset + 36), true));
200
206
  return { lineCount };
201
207
  }
202
- blocksForRange(refName_1, min_1, max_1) {
203
- return __awaiter(this, arguments, void 0, function* (refName, min, max, opts = {}) {
204
- if (min < 0) {
205
- min = 0;
206
- }
207
- const indexData = yield this.parse(opts);
208
- const refId = indexData.refNameToId[refName];
209
- if (refId === undefined) {
210
- return [];
211
- }
212
- const ba = indexData.indices[refId];
213
- if (!ba) {
214
- return [];
215
- }
216
- // const { linearIndex, binIndex } = indexes
217
- const overlappingBins = this.reg2bins(min, max); // List of bin #s that overlap min, max
218
- const chunks = [];
219
- // Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned
220
- for (const [start, end] of overlappingBins) {
221
- for (let bin = start; bin <= end; bin++) {
222
- if (ba.binIndex[bin]) {
223
- for (const c of ba.binIndex[bin]) {
224
- chunks.push(new chunk_1.default(c.minv, c.maxv, bin));
225
- }
208
+ async blocksForRange(refName, min, max, opts = {}) {
209
+ if (min < 0) {
210
+ min = 0;
211
+ }
212
+ const indexData = await this.parse(opts);
213
+ const refId = indexData.refNameToId[refName];
214
+ if (refId === undefined) {
215
+ return [];
216
+ }
217
+ const ba = indexData.indices[refId];
218
+ if (!ba) {
219
+ return [];
220
+ }
221
+ // const { linearIndex, binIndex } = indexes
222
+ const overlappingBins = this.reg2bins(min, max); // List of bin #s that overlap min, max
223
+ const chunks = [];
224
+ // Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned
225
+ for (const [start, end] of overlappingBins) {
226
+ for (let bin = start; bin <= end; bin++) {
227
+ if (ba.binIndex[bin]) {
228
+ for (const c of ba.binIndex[bin]) {
229
+ chunks.push(new chunk_1.default(c.minv, c.maxv, bin));
226
230
  }
227
231
  }
228
232
  }
229
- return (0, util_1.optimizeChunks)(chunks, new virtualOffset_1.default(0, 0));
230
- });
233
+ }
234
+ return (0, util_1.optimizeChunks)(chunks, new virtualOffset_1.default(0, 0));
231
235
  }
232
236
  /**
233
237
  * calculate the list of bins that may overlap with region [beg,end) (zero-based half-open)
@@ -237,8 +241,8 @@ class CSI extends indexFile_1.default {
237
241
  if (beg < 1) {
238
242
  beg = 1;
239
243
  }
240
- if (end > Math.pow(2, 50)) {
241
- end = Math.pow(2, 34);
244
+ if (end > 2 ** 50) {
245
+ end = 2 ** 34;
242
246
  } // 17 GiB ought to be enough for anybody
243
247
  end -= 1;
244
248
  let l = 0;