@gmod/tabix 1.5.14 → 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.
Files changed (48) hide show
  1. package/CHANGELOG.md +9 -5
  2. package/README.md +182 -35
  3. package/dist/chunk.js +0 -1
  4. package/dist/chunk.js.map +1 -1
  5. package/dist/csi.d.ts +1 -1
  6. package/dist/csi.js +132 -128
  7. package/dist/csi.js.map +1 -1
  8. package/dist/indexFile.js +15 -41
  9. package/dist/indexFile.js.map +1 -1
  10. package/dist/tabix-bundle.js +2 -0
  11. package/dist/tabix-bundle.js.LICENSE.txt +8 -0
  12. package/dist/tabixIndexedFile.d.ts +49 -25
  13. package/dist/tabixIndexedFile.js +214 -195
  14. package/dist/tabixIndexedFile.js.map +1 -1
  15. package/dist/tbi.js +169 -173
  16. package/dist/tbi.js.map +1 -1
  17. package/dist/util.d.ts +7 -6
  18. package/dist/util.js +9 -19
  19. package/dist/util.js.map +1 -1
  20. package/dist/virtualOffset.d.ts +0 -1
  21. package/dist/virtualOffset.js +0 -13
  22. package/dist/virtualOffset.js.map +1 -1
  23. package/esm/chunk.js +0 -1
  24. package/esm/chunk.js.map +1 -1
  25. package/esm/csi.d.ts +1 -1
  26. package/esm/csi.js +4 -4
  27. package/esm/csi.js.map +1 -1
  28. package/esm/indexFile.js +1 -1
  29. package/esm/indexFile.js.map +1 -1
  30. package/esm/tabixIndexedFile.d.ts +49 -25
  31. package/esm/tabixIndexedFile.js +134 -90
  32. package/esm/tabixIndexedFile.js.map +1 -1
  33. package/esm/tbi.js +6 -5
  34. package/esm/tbi.js.map +1 -1
  35. package/esm/util.d.ts +7 -6
  36. package/esm/util.js +6 -5
  37. package/esm/util.js.map +1 -1
  38. package/esm/virtualOffset.d.ts +0 -1
  39. package/esm/virtualOffset.js +0 -13
  40. package/esm/virtualOffset.js.map +1 -1
  41. package/package.json +24 -19
  42. package/src/chunk.ts +0 -1
  43. package/src/csi.ts +6 -5
  44. package/src/indexFile.ts +1 -1
  45. package/src/tabixIndexedFile.ts +141 -106
  46. package/src/tbi.ts +7 -6
  47. package/src/util.ts +7 -6
  48. package/src/virtualOffset.ts +7 -21
package/CHANGELOG.md CHANGED
@@ -1,11 +1,15 @@
1
- ## [1.5.14](https://github.com/GMOD/tabix-js/compare/v1.5.13...v1.5.14) (2024-07-23)
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
- ### Reverts
5
4
 
6
- * Revert "Bump to eslint 9" ([9bd49b1](https://github.com/GMOD/tabix-js/commit/9bd49b1132f632b0e7847d9b95cf3cb08c424360))
5
+ ## [1.5.15](https://github.com/GMOD/tabix-js/compare/v1.5.14...v1.5.15) (2024-08-30)
7
6
 
7
+ ## [1.5.14](https://github.com/GMOD/tabix-js/compare/v1.5.13...v1.5.14) (2024-07-23)
8
+
9
+ ### Reverts
8
10
 
11
+ - Revert "Bump to eslint 9"
12
+ ([9bd49b1](https://github.com/GMOD/tabix-js/commit/9bd49b1132f632b0e7847d9b95cf3cb08c424360))
9
13
 
10
14
  ## [1.5.13](https://github.com/GMOD/tabix-js/compare/v1.5.12...v1.5.13) (2024-01-09)
11
15
 
@@ -13,8 +17,8 @@
13
17
 
14
18
  ## [1.5.12](https://github.com/GMOD/tabix-js/compare/v1.5.11...v1.5.12) (2024-01-09)
15
19
 
16
- - Add missing abort signal to the @gmod/abortable-promise-cache fetch for tabix chunks
17
- (#143)
20
+ - Add missing abort signal to the @gmod/abortable-promise-cache fetch for tabix
21
+ chunks (#143)
18
22
 
19
23
  ## [1.5.11](https://github.com/GMOD/tabix-js/compare/v1.5.10...v1.5.11) (2023-07-10)
20
24
 
package/README.md CHANGED
@@ -22,6 +22,15 @@ const { TabixIndexedFile } = require('@gmod/tabix')
22
22
  import { TabixIndexedFile } from '@gmod/tabix'
23
23
  ```
24
24
 
25
+ ### Single file bundle
26
+
27
+ You can use tabix-js without NPM also with the tabix-bundle.js. See the example
28
+ directory for usage with script tag [example/index.html](example/index.html)
29
+
30
+ ```html
31
+ <script src="https://unpkg.com/@gmod/tabix/dist/tabix-bundle.js"></script>
32
+ ```
33
+
25
34
  ### TabixIndexedFile constructor
26
35
 
27
36
  Basic usage of TabixIndexedFile under node.js supplies a path and optionally a
@@ -38,10 +47,10 @@ const tbiIndexed = new TabixIndexedFile({
38
47
 
39
48
  ```
40
49
 
41
- You can also use CSI indexes. Note also the usage of the renameRefSeqs callback.
42
- The renameRefSeqs callback makes it so that you can use
43
- file.getLines('1',0,100,...) even when the file itself contains names like
44
- '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)
45
54
 
46
55
  ```typescript
47
56
  // can also open tabix files that have a .csi index
@@ -55,9 +64,15 @@ const csiIndexed = new TabixIndexedFile({
55
64
 
56
65
  #### TabixIndexedFile constructor with remote files
57
66
 
58
- The basic usage of fetching remote files is done by supplying a
59
- [generic-filehandle](https://github.com/GMOD/generic-filehandle) module
60
- 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
61
76
 
62
77
  ```typescript
63
78
  // use a remote file or other filehandle, note RemoteFile comes from https://github.com/GMOD/generic-filehandle
@@ -68,9 +83,9 @@ const remoteTbiIndexed = new TabixIndexedFile({
68
83
  })
69
84
  ```
70
85
 
71
- This works in both the browser and in node.js, but note that in node.js you have
72
- to also supply a custom fetch function to the RemoteFile constructor e.g. like
73
- 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
74
89
 
75
90
  ```typescript
76
91
  // for node.js you have to manually supply a fetch function e.g. node-fetch to RemoteFile
@@ -102,8 +117,8 @@ await tbiIndexed.getLines('ctgA', 200, 300, function (line, fileOffset) {
102
117
  After running this, your `lines` array would contain an array of lines from the
103
118
  file that match your query range
104
119
 
105
- You can also supply some extra arguments to getLines with this format, but these
106
- 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
107
122
 
108
123
  ```typescript
109
124
  const lines = []
@@ -124,8 +139,8 @@ Notes about the returned values of `getLines`:
124
139
  - the callback is also called with a `fileOffset` that can be used to uniquely
125
140
  identify lines based on their virtual file offset where the line is found in
126
141
  the file
127
- - if getLines is called with an undefined `end` parameter it gets all lines from
128
- 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.
129
144
 
130
145
  ```typescript
131
146
  const lines = []
@@ -133,32 +148,164 @@ await tbiIndexed.getLines('ctgA', 0, undefined, line=>lines.push(line))`
133
148
  console.log(lines)
134
149
  ```
135
150
 
136
- ### 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
137
231
 
138
- ```typescript
139
- // get the approximate number of data lines in the
140
- // file for the given reference sequence, excluding header, comment, and whitespace lines
141
- // uses the extra bin from tabix
142
- const numLines = await tbiIndexed.lineCount('ctgA')
143
- // or const numLines = await tbiIndexed.lineCount('ctgA', { signal: aborter.signal })
144
- ```
232
+ #### getHeaderBuffer
145
233
 
146
- ### getHeader
234
+ get a buffer containing the "header" region of the file, which are the bytes up
235
+ to the first non-meta line
147
236
 
148
- ```typescript
149
- // get the "header text" string from the file, which is the first contiguous
150
- // set of lines in the file that all start with a "meta" character (usually #)
151
- const headerText = await tbiIndexed.getHeader()
152
- // or const headerText = await tbiIndexed.getHeader({ signal: aborter.signal })
153
- ```
237
+ ##### Parameters
154
238
 
155
- #### getHeaderBuffer
239
+ - `opts` **Options** (optional, default `{}`)
156
240
 
157
- ```typescript
158
- // or if you want a nodejs Buffer object instead, there is getHeaderBuffer()
159
- const headerBuffer = await tbiIndexed.getHeaderBuffer()
160
- // or const headerBuffer = await tbiIndexed.getHeaderBuffer({ signal: aborter.signal })
161
- ```
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 `{}`)
162
309
 
163
310
  ## Academic Use
164
311
 
package/dist/chunk.js CHANGED
@@ -9,7 +9,6 @@ class Chunk {
9
9
  this._fetchedSize = fetchedSize;
10
10
  }
11
11
  toUniqueString() {
12
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
13
12
  return `${this.minv}..${this.maxv} (bin ${this.bin}, fetchedSize ${this.fetchedSize()})`;
14
13
  }
15
14
  toString() {
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;QACZ,4EAA4E;QAC5E,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.d.ts CHANGED
@@ -85,5 +85,5 @@ export default class CSI extends IndexFile {
85
85
  /**
86
86
  * calculate the list of bins that may overlap with region [beg,end) (zero-based half-open)
87
87
  */
88
- reg2bins(beg: number, end: number): number[][];
88
+ reg2bins(beg: number, end: number): (readonly [number, number])[];
89
89
  }
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
- if (!indexData) {
63
- return -1;
64
- }
65
- const refId = indexData.refNameToId[refName];
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
- if (!indexData) {
209
- return [];
210
- }
211
- const refId = indexData.refNameToId[refName];
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;