@gmod/tabix 1.5.1 → 1.5.4
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 +19 -0
- package/dist/chunk.js +1 -0
- package/dist/chunk.js.map +1 -0
- package/dist/csi.js +6 -1
- package/dist/csi.js.map +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/indexFile.js +1 -0
- package/dist/indexFile.js.map +1 -0
- package/dist/tabixIndexedFile.d.ts +1 -1
- package/dist/tabixIndexedFile.js +1 -0
- package/dist/tabixIndexedFile.js.map +1 -0
- package/dist/tbi.js +6 -1
- package/dist/tbi.js.map +1 -0
- package/dist/util.js +1 -0
- package/dist/util.js.map +1 -0
- package/dist/virtualOffset.js +1 -0
- package/dist/virtualOffset.js.map +1 -0
- package/esm/chunk.js +2 -4
- package/esm/chunk.js.map +1 -0
- package/esm/csi.js +16 -40
- package/esm/csi.js.map +1 -0
- package/esm/index.js +5 -12
- package/esm/index.js.map +1 -0
- package/esm/indexFile.js +6 -11
- package/esm/indexFile.js.map +1 -0
- package/esm/tabixIndexedFile.d.ts +1 -1
- package/esm/tabixIndexedFile.js +29 -34
- package/esm/tabixIndexedFile.js.map +1 -0
- package/esm/tbi.js +18 -42
- package/esm/tbi.js.map +1 -0
- package/esm/util.js +6 -13
- package/esm/util.js.map +1 -0
- package/esm/virtualOffset.js +3 -7
- package/esm/virtualOffset.js.map +1 -0
- package/package.json +17 -16
- package/src/chunk.ts +52 -0
- package/src/csi.ts +277 -0
- package/src/declare.d.ts +2 -0
- package/src/index.ts +5 -0
- package/src/indexFile.ts +79 -0
- package/src/tabixIndexedFile.ts +519 -0
- package/src/tbi.ts +250 -0
- package/src/util.ts +103 -0
- package/src/virtualOffset.ts +47 -0
package/esm/tbi.js
CHANGED
|
@@ -1,33 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
-
}) : function(o, v) {
|
|
12
|
-
o["default"] = v;
|
|
13
|
-
});
|
|
14
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
-
if (mod && mod.__esModule) return mod;
|
|
16
|
-
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
-
__setModuleDefault(result, mod);
|
|
19
|
-
return result;
|
|
20
|
-
};
|
|
21
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
|
-
};
|
|
24
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
-
const long_1 = __importDefault(require("long"));
|
|
26
|
-
const virtualOffset_1 = __importStar(require("./virtualOffset"));
|
|
27
|
-
const chunk_1 = __importDefault(require("./chunk"));
|
|
28
|
-
const bgzf_filehandle_1 = require("@gmod/bgzf-filehandle");
|
|
29
|
-
const util_1 = require("./util");
|
|
30
|
-
const indexFile_1 = __importDefault(require("./indexFile"));
|
|
1
|
+
import Long from 'long';
|
|
2
|
+
import VirtualOffset, { fromBytes } from './virtualOffset';
|
|
3
|
+
import Chunk from './chunk';
|
|
4
|
+
import { unzip } from '@gmod/bgzf-filehandle';
|
|
5
|
+
import { longToNumber, optimizeChunks, checkAbortSignal } from './util';
|
|
6
|
+
import IndexFile from './indexFile';
|
|
31
7
|
const TBI_MAGIC = 21578324; // TBI\1
|
|
32
8
|
const TAD_LIDX_SHIFT = 14;
|
|
33
9
|
/**
|
|
@@ -45,7 +21,7 @@ function reg2bins(beg, end) {
|
|
|
45
21
|
[4681 + (beg >> 14), 4681 + (end >> 14)],
|
|
46
22
|
];
|
|
47
23
|
}
|
|
48
|
-
class TabixIndex extends
|
|
24
|
+
export default class TabixIndex extends IndexFile {
|
|
49
25
|
async lineCount(refName, opts = {}) {
|
|
50
26
|
const indexData = await this.parse(opts);
|
|
51
27
|
if (!indexData) {
|
|
@@ -65,8 +41,8 @@ class TabixIndex extends indexFile_1.default {
|
|
|
65
41
|
// memoize
|
|
66
42
|
// fetch and parse the index
|
|
67
43
|
async _parse(opts = {}) {
|
|
68
|
-
const bytes = await
|
|
69
|
-
|
|
44
|
+
const bytes = await unzip((await this.filehandle.readFile(opts)));
|
|
45
|
+
checkAbortSignal(opts.signal);
|
|
70
46
|
// check TBI magic numbers
|
|
71
47
|
if (bytes.readUInt32LE(0) !== TBI_MAGIC /* "TBI\1" */) {
|
|
72
48
|
throw new Error('Not a TBI file');
|
|
@@ -127,11 +103,11 @@ class TabixIndex extends indexFile_1.default {
|
|
|
127
103
|
currOffset += 4;
|
|
128
104
|
const chunks = new Array(chunkCount);
|
|
129
105
|
for (let k = 0; k < chunkCount; k += 1) {
|
|
130
|
-
const u =
|
|
131
|
-
const v =
|
|
106
|
+
const u = fromBytes(bytes, currOffset);
|
|
107
|
+
const v = fromBytes(bytes, currOffset + 8);
|
|
132
108
|
currOffset += 16;
|
|
133
109
|
firstDataLine = this._findFirstData(firstDataLine, u);
|
|
134
|
-
chunks[k] = new
|
|
110
|
+
chunks[k] = new Chunk(u, v, bin);
|
|
135
111
|
}
|
|
136
112
|
binIndex[bin] = chunks;
|
|
137
113
|
}
|
|
@@ -141,7 +117,7 @@ class TabixIndex extends indexFile_1.default {
|
|
|
141
117
|
currOffset += 4;
|
|
142
118
|
const linearIndex = new Array(linearCount);
|
|
143
119
|
for (let k = 0; k < linearCount; k += 1) {
|
|
144
|
-
linearIndex[k] =
|
|
120
|
+
linearIndex[k] = fromBytes(bytes, currOffset);
|
|
145
121
|
currOffset += 8;
|
|
146
122
|
firstDataLine = this._findFirstData(firstDataLine, linearIndex[k]);
|
|
147
123
|
}
|
|
@@ -163,7 +139,7 @@ class TabixIndex extends indexFile_1.default {
|
|
|
163
139
|
};
|
|
164
140
|
}
|
|
165
141
|
parsePseudoBin(bytes, offset) {
|
|
166
|
-
const lineCount =
|
|
142
|
+
const lineCount = longToNumber(Long.fromBytesLE(bytes.slice(offset + 16, offset + 24), true));
|
|
167
143
|
return { lineCount };
|
|
168
144
|
}
|
|
169
145
|
_parseNameBytes(namesBytes) {
|
|
@@ -202,7 +178,7 @@ class TabixIndex extends indexFile_1.default {
|
|
|
202
178
|
? ba.linearIndex[min >> TAD_LIDX_SHIFT >= ba.linearIndex.length
|
|
203
179
|
? ba.linearIndex.length - 1
|
|
204
180
|
: min >> TAD_LIDX_SHIFT]
|
|
205
|
-
: new
|
|
181
|
+
: new VirtualOffset(0, 0);
|
|
206
182
|
if (!minOffset) {
|
|
207
183
|
console.warn('querying outside of possible tabix range');
|
|
208
184
|
}
|
|
@@ -215,7 +191,7 @@ class TabixIndex extends indexFile_1.default {
|
|
|
215
191
|
if (ba.binIndex[bin]) {
|
|
216
192
|
const binChunks = ba.binIndex[bin];
|
|
217
193
|
for (let c = 0; c < binChunks.length; ++c) {
|
|
218
|
-
chunks.push(new
|
|
194
|
+
chunks.push(new Chunk(binChunks[c].minv, binChunks[c].maxv, bin));
|
|
219
195
|
}
|
|
220
196
|
}
|
|
221
197
|
}
|
|
@@ -234,7 +210,7 @@ class TabixIndex extends indexFile_1.default {
|
|
|
234
210
|
}
|
|
235
211
|
}
|
|
236
212
|
}
|
|
237
|
-
return
|
|
213
|
+
return optimizeChunks(chunks, lowest);
|
|
238
214
|
}
|
|
239
215
|
}
|
|
240
|
-
|
|
216
|
+
//# sourceMappingURL=tbi.js.map
|
package/esm/tbi.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tbi.js","sourceRoot":"","sources":["../src/tbi.ts"],"names":[],"mappings":"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"}
|
package/esm/util.js
CHANGED
|
@@ -1,14 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.optimizeChunks = exports.canMergeBlocks = exports.abortBreakPoint = exports.checkAbortSignal = exports.longToNumber = void 0;
|
|
4
|
-
function longToNumber(long) {
|
|
1
|
+
export function longToNumber(long) {
|
|
5
2
|
if (long.greaterThan(Number.MAX_SAFE_INTEGER) ||
|
|
6
3
|
long.lessThan(Number.MIN_SAFE_INTEGER)) {
|
|
7
4
|
throw new Error('integer overflow');
|
|
8
5
|
}
|
|
9
6
|
return long.toNumber();
|
|
10
7
|
}
|
|
11
|
-
exports.longToNumber = longToNumber;
|
|
12
8
|
class AbortError extends Error {
|
|
13
9
|
}
|
|
14
10
|
/**
|
|
@@ -22,7 +18,7 @@ class AbortError extends Error {
|
|
|
22
18
|
* @param {AbortSignal} [signal] an AbortSignal, or anything with an `aborted` attribute
|
|
23
19
|
* @returns nothing
|
|
24
20
|
*/
|
|
25
|
-
function checkAbortSignal(signal) {
|
|
21
|
+
export function checkAbortSignal(signal) {
|
|
26
22
|
if (!signal) {
|
|
27
23
|
return;
|
|
28
24
|
}
|
|
@@ -39,24 +35,21 @@ function checkAbortSignal(signal) {
|
|
|
39
35
|
}
|
|
40
36
|
}
|
|
41
37
|
}
|
|
42
|
-
exports.checkAbortSignal = checkAbortSignal;
|
|
43
38
|
/**
|
|
44
39
|
* Skips to the next tick, then runs `checkAbortSignal`.
|
|
45
40
|
* Await this to inside an otherwise synchronous loop to
|
|
46
41
|
* provide a place to break when an abort signal is received.
|
|
47
42
|
* @param {AbortSignal} signal
|
|
48
43
|
*/
|
|
49
|
-
async function abortBreakPoint(signal) {
|
|
44
|
+
export async function abortBreakPoint(signal) {
|
|
50
45
|
await Promise.resolve();
|
|
51
46
|
checkAbortSignal(signal);
|
|
52
47
|
}
|
|
53
|
-
|
|
54
|
-
function canMergeBlocks(chunk1, chunk2) {
|
|
48
|
+
export function canMergeBlocks(chunk1, chunk2) {
|
|
55
49
|
return (chunk2.minv.blockPosition - chunk1.maxv.blockPosition < 65000 &&
|
|
56
50
|
chunk2.maxv.blockPosition - chunk1.minv.blockPosition < 5000000);
|
|
57
51
|
}
|
|
58
|
-
|
|
59
|
-
function optimizeChunks(chunks, lowest) {
|
|
52
|
+
export function optimizeChunks(chunks, lowest) {
|
|
60
53
|
const mergedChunks = [];
|
|
61
54
|
let lastChunk = null;
|
|
62
55
|
if (chunks.length === 0) {
|
|
@@ -95,4 +88,4 @@ function optimizeChunks(chunks, lowest) {
|
|
|
95
88
|
});
|
|
96
89
|
return mergedChunks;
|
|
97
90
|
}
|
|
98
|
-
|
|
91
|
+
//# sourceMappingURL=util.js.map
|
package/esm/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"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"}
|
package/esm/virtualOffset.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.fromBytes = void 0;
|
|
4
|
-
class VirtualOffset {
|
|
1
|
+
export default class VirtualOffset {
|
|
5
2
|
constructor(blockPosition, dataPosition) {
|
|
6
3
|
this.blockPosition = blockPosition; // < offset of the compressed data block
|
|
7
4
|
this.dataPosition = dataPosition; // < offset into the uncompressed data
|
|
@@ -26,8 +23,7 @@ class VirtualOffset {
|
|
|
26
23
|
return min;
|
|
27
24
|
}
|
|
28
25
|
}
|
|
29
|
-
|
|
30
|
-
function fromBytes(bytes, offset = 0, bigendian = false) {
|
|
26
|
+
export function fromBytes(bytes, offset = 0, bigendian = false) {
|
|
31
27
|
if (bigendian) {
|
|
32
28
|
throw new Error('big-endian virtual file offsets not implemented');
|
|
33
29
|
}
|
|
@@ -38,4 +34,4 @@ function fromBytes(bytes, offset = 0, bigendian = false) {
|
|
|
38
34
|
bytes[offset + 3] * 0x100 +
|
|
39
35
|
bytes[offset + 2], (bytes[offset + 1] << 8) | bytes[offset]);
|
|
40
36
|
}
|
|
41
|
-
|
|
37
|
+
//# sourceMappingURL=virtualOffset.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"virtualOffset.js","sourceRoot":"","sources":["../src/virtualOffset.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,OAAO,OAAO,aAAa;IAGhC,YAAY,aAAqB,EAAE,YAAoB;QACrD,IAAI,CAAC,aAAa,GAAG,aAAa,CAAA,CAAC,wCAAwC;QAC3E,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA,CAAC,sCAAsC;IACzE,CAAC;IAED,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,EAAE,CAAA;IACrD,CAAC;IAED,SAAS,CAAC,CAAgB;QACxB,OAAO,CACL,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC,aAAa,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAC3E,CAAA;IACH,CAAC;IAED,MAAM,CAAC,GAAG,CAAC,GAAG,IAAqB;QACjC,IAAI,GAAG,CAAA;QACP,IAAI,CAAC,GAAG,CAAC,CAAA;QACT,OAAO,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE;YACnB,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;SACd;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE;YAC9B,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;gBAC9B,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;aACd;SACF;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;AACD,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,MAAM,GAAG,CAAC,EAAE,SAAS,GAAG,KAAK;IACpE,IAAI,SAAS,EAAE;QACb,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;KACnE;IAED,OAAO,IAAI,aAAa,CACtB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,aAAa;QAC/B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,WAAW;QAC/B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,SAAS;QAC7B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,OAAO;QAC3B,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK;QACzB,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EACnB,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CACzC,CAAA;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gmod/tabix",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.4",
|
|
4
4
|
"description": "Read Tabix-indexed files, supports both .tbi and .csi indexes",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "GMOD/tabix-js",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
},
|
|
17
17
|
"files": [
|
|
18
18
|
"dist",
|
|
19
|
-
"esm"
|
|
19
|
+
"esm",
|
|
20
|
+
"src"
|
|
20
21
|
],
|
|
21
22
|
"scripts": {
|
|
22
23
|
"test": "jest",
|
|
@@ -41,28 +42,28 @@
|
|
|
41
42
|
"@gmod/bgzf-filehandle": "^1.3.3",
|
|
42
43
|
"abortable-promise-cache": "^1.4.1",
|
|
43
44
|
"es6-promisify": "^6.0.1",
|
|
44
|
-
"generic-filehandle": "^
|
|
45
|
+
"generic-filehandle": "^3.0.0",
|
|
45
46
|
"long": "^4.0.0",
|
|
46
47
|
"quick-lru": "^4.0.0"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
|
-
"@types/jest": "^
|
|
50
|
+
"@types/jest": "^28.1.6",
|
|
50
51
|
"@types/long": "^4.0.0",
|
|
51
|
-
"@types/node": "^
|
|
52
|
+
"@types/node": "^18.0.6",
|
|
52
53
|
"@types/quick-lru": "2.0.0",
|
|
53
|
-
"@typescript-eslint/eslint-plugin": "^5.7
|
|
54
|
-
"@typescript-eslint/parser": "^5.7
|
|
55
|
-
"
|
|
56
|
-
"eslint": "^7.0.0",
|
|
54
|
+
"@typescript-eslint/eslint-plugin": "^5.30.7",
|
|
55
|
+
"@typescript-eslint/parser": "^5.30.7",
|
|
56
|
+
"eslint": "^8.20.0",
|
|
57
57
|
"eslint-config-prettier": "^8.3.0",
|
|
58
58
|
"eslint-plugin-import": "^2.25.3",
|
|
59
|
-
"eslint-plugin-prettier": "^4.
|
|
60
|
-
"jest": "^
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"
|
|
59
|
+
"eslint-plugin-prettier": "^4.2.1",
|
|
60
|
+
"jest": "^28.1.3",
|
|
61
|
+
"jest-environment-jsdom": "^28.1.3",
|
|
62
|
+
"prettier": "^2.7.1",
|
|
63
|
+
"rimraf": "^3.0.2",
|
|
64
|
+
"standard-changelog": "^2.0.27",
|
|
65
|
+
"ts-jest": "^28.0.7",
|
|
66
|
+
"typescript": "^4.7.4"
|
|
66
67
|
},
|
|
67
68
|
"publishConfig": {
|
|
68
69
|
"access": "public"
|
package/src/chunk.ts
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import VirtualOffset from './virtualOffset'
|
|
2
|
+
|
|
3
|
+
// little class representing a chunk in the index
|
|
4
|
+
export default class Chunk {
|
|
5
|
+
public minv: VirtualOffset
|
|
6
|
+
public maxv: VirtualOffset
|
|
7
|
+
public bin: number
|
|
8
|
+
public _fetchedSize?: number
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {VirtualOffset} minv
|
|
12
|
+
* @param {VirtualOffset} maxv
|
|
13
|
+
* @param {number} bin
|
|
14
|
+
* @param {number} [fetchedSize]
|
|
15
|
+
*/
|
|
16
|
+
constructor(
|
|
17
|
+
minv: VirtualOffset,
|
|
18
|
+
maxv: VirtualOffset,
|
|
19
|
+
bin: number,
|
|
20
|
+
fetchedSize = undefined,
|
|
21
|
+
) {
|
|
22
|
+
this.minv = minv
|
|
23
|
+
this.maxv = maxv
|
|
24
|
+
this.bin = bin
|
|
25
|
+
this._fetchedSize = fetchedSize
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
toUniqueString() {
|
|
29
|
+
return `${this.minv}..${this.maxv} (bin ${
|
|
30
|
+
this.bin
|
|
31
|
+
}, fetchedSize ${this.fetchedSize()})`
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
toString() {
|
|
35
|
+
return this.toUniqueString()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
compareTo(b: Chunk) {
|
|
39
|
+
return (
|
|
40
|
+
this.minv.compareTo(b.minv) ||
|
|
41
|
+
this.maxv.compareTo(b.maxv) ||
|
|
42
|
+
this.bin - b.bin
|
|
43
|
+
)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
fetchedSize() {
|
|
47
|
+
if (this._fetchedSize !== undefined) {
|
|
48
|
+
return this._fetchedSize
|
|
49
|
+
}
|
|
50
|
+
return this.maxv.blockPosition + (1 << 16) - this.minv.blockPosition
|
|
51
|
+
}
|
|
52
|
+
}
|
package/src/csi.ts
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import Long from 'long'
|
|
2
|
+
import { unzip } from '@gmod/bgzf-filehandle'
|
|
3
|
+
|
|
4
|
+
import VirtualOffset, { fromBytes } from './virtualOffset'
|
|
5
|
+
import Chunk from './chunk'
|
|
6
|
+
import { longToNumber, optimizeChunks } from './util'
|
|
7
|
+
|
|
8
|
+
import IndexFile, { Options } from './indexFile'
|
|
9
|
+
|
|
10
|
+
const CSI1_MAGIC = 21582659 // CSI\1
|
|
11
|
+
const CSI2_MAGIC = 38359875 // CSI\2
|
|
12
|
+
|
|
13
|
+
function lshift(num: number, bits: number) {
|
|
14
|
+
return num * 2 ** bits
|
|
15
|
+
}
|
|
16
|
+
function rshift(num: number, bits: number) {
|
|
17
|
+
return Math.floor(num / 2 ** bits)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default class CSI extends IndexFile {
|
|
21
|
+
private maxBinNumber: number
|
|
22
|
+
private depth: number
|
|
23
|
+
private minShift: number
|
|
24
|
+
constructor(args: any) {
|
|
25
|
+
super(args)
|
|
26
|
+
this.maxBinNumber = 0
|
|
27
|
+
this.depth = 0
|
|
28
|
+
this.minShift = 0
|
|
29
|
+
}
|
|
30
|
+
async lineCount(refName: string, opts: Options = {}): Promise<number> {
|
|
31
|
+
const indexData = await this.parse(opts)
|
|
32
|
+
if (!indexData) {
|
|
33
|
+
return -1
|
|
34
|
+
}
|
|
35
|
+
const refId = indexData.refNameToId[refName]
|
|
36
|
+
const idx = indexData.indices[refId]
|
|
37
|
+
if (!idx) {
|
|
38
|
+
return -1
|
|
39
|
+
}
|
|
40
|
+
const { stats } = indexData.indices[refId]
|
|
41
|
+
if (stats) {
|
|
42
|
+
return stats.lineCount
|
|
43
|
+
}
|
|
44
|
+
return -1
|
|
45
|
+
}
|
|
46
|
+
async indexCov() {
|
|
47
|
+
throw new Error('CSI indexes do not support indexcov')
|
|
48
|
+
return []
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
parseAuxData(bytes: Buffer, offset: number, auxLength: number) {
|
|
52
|
+
if (auxLength < 30) {
|
|
53
|
+
return {
|
|
54
|
+
refIdToName: [],
|
|
55
|
+
refNameToId: {},
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const formatFlags = bytes.readInt32LE(offset)
|
|
60
|
+
const coordinateType =
|
|
61
|
+
formatFlags & 0x10000 ? 'zero-based-half-open' : '1-based-closed'
|
|
62
|
+
const format = (
|
|
63
|
+
{ 0: 'generic', 1: 'SAM', 2: 'VCF' } as {
|
|
64
|
+
[key: number]: string
|
|
65
|
+
}
|
|
66
|
+
)[formatFlags & 0xf]
|
|
67
|
+
if (!format) {
|
|
68
|
+
throw new Error(`invalid Tabix preset format flags ${formatFlags}`)
|
|
69
|
+
}
|
|
70
|
+
const columnNumbers = {
|
|
71
|
+
ref: bytes.readInt32LE(offset + 4),
|
|
72
|
+
start: bytes.readInt32LE(offset + 8),
|
|
73
|
+
end: bytes.readInt32LE(offset + 12),
|
|
74
|
+
}
|
|
75
|
+
const metaValue = bytes.readInt32LE(offset + 16)
|
|
76
|
+
const metaChar = metaValue ? String.fromCharCode(metaValue) : ''
|
|
77
|
+
const skipLines = bytes.readInt32LE(offset + 20)
|
|
78
|
+
const nameSectionLength = bytes.readInt32LE(offset + 24)
|
|
79
|
+
|
|
80
|
+
const { refIdToName, refNameToId } = this._parseNameBytes(
|
|
81
|
+
bytes.slice(offset + 28, offset + 28 + nameSectionLength),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
refIdToName,
|
|
86
|
+
refNameToId,
|
|
87
|
+
skipLines,
|
|
88
|
+
metaChar,
|
|
89
|
+
columnNumbers,
|
|
90
|
+
format,
|
|
91
|
+
coordinateType,
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
_parseNameBytes(namesBytes: Buffer) {
|
|
96
|
+
let currRefId = 0
|
|
97
|
+
let currNameStart = 0
|
|
98
|
+
const refIdToName = []
|
|
99
|
+
const refNameToId: { [key: string]: number } = {}
|
|
100
|
+
for (let i = 0; i < namesBytes.length; i += 1) {
|
|
101
|
+
if (!namesBytes[i]) {
|
|
102
|
+
if (currNameStart < i) {
|
|
103
|
+
let refName = namesBytes.toString('utf8', currNameStart, i)
|
|
104
|
+
refName = this.renameRefSeq(refName)
|
|
105
|
+
refIdToName[currRefId] = refName
|
|
106
|
+
refNameToId[refName] = currRefId
|
|
107
|
+
}
|
|
108
|
+
currNameStart = i + 1
|
|
109
|
+
currRefId += 1
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return { refNameToId, refIdToName }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// fetch and parse the index
|
|
116
|
+
|
|
117
|
+
async _parse(opts: Options = {}) {
|
|
118
|
+
const bytes = await unzip((await this.filehandle.readFile(opts)) as Buffer)
|
|
119
|
+
|
|
120
|
+
// check TBI magic numbers
|
|
121
|
+
let csiVersion
|
|
122
|
+
if (bytes.readUInt32LE(0) === CSI1_MAGIC) {
|
|
123
|
+
csiVersion = 1
|
|
124
|
+
} else if (bytes.readUInt32LE(0) === CSI2_MAGIC) {
|
|
125
|
+
csiVersion = 2
|
|
126
|
+
} else {
|
|
127
|
+
throw new Error('Not a CSI file')
|
|
128
|
+
// TODO: do we need to support big-endian CSI files?
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this.minShift = bytes.readInt32LE(4)
|
|
132
|
+
this.depth = bytes.readInt32LE(8)
|
|
133
|
+
this.maxBinNumber = ((1 << ((this.depth + 1) * 3)) - 1) / 7
|
|
134
|
+
const maxRefLength = 2 ** (this.minShift + this.depth * 3)
|
|
135
|
+
|
|
136
|
+
const auxLength = bytes.readInt32LE(12)
|
|
137
|
+
let aux: {
|
|
138
|
+
refIdToName: string[]
|
|
139
|
+
refNameToId: { [key: string]: number }
|
|
140
|
+
} = {
|
|
141
|
+
refIdToName: [],
|
|
142
|
+
refNameToId: {},
|
|
143
|
+
}
|
|
144
|
+
if (auxLength) {
|
|
145
|
+
aux = this.parseAuxData(bytes, 16, auxLength)
|
|
146
|
+
}
|
|
147
|
+
const refCount = bytes.readInt32LE(16 + auxLength)
|
|
148
|
+
|
|
149
|
+
// read the indexes for each reference sequence
|
|
150
|
+
let firstDataLine: VirtualOffset | undefined
|
|
151
|
+
let currOffset = 16 + auxLength + 4
|
|
152
|
+
const indices = new Array(refCount).fill(0).map(() => {
|
|
153
|
+
// the binning index
|
|
154
|
+
const binCount = bytes.readInt32LE(currOffset)
|
|
155
|
+
currOffset += 4
|
|
156
|
+
const binIndex: { [key: string]: Chunk[] } = {}
|
|
157
|
+
let stats // < provided by parsing a pseudo-bin, if present
|
|
158
|
+
for (let j = 0; j < binCount; j += 1) {
|
|
159
|
+
const bin = bytes.readUInt32LE(currOffset)
|
|
160
|
+
if (bin > this.maxBinNumber) {
|
|
161
|
+
// this is a fake bin that actually has stats information
|
|
162
|
+
// about the reference sequence in it
|
|
163
|
+
stats = this.parsePseudoBin(bytes, currOffset + 4)
|
|
164
|
+
currOffset += 4 + 8 + 4 + 16 + 16
|
|
165
|
+
} else {
|
|
166
|
+
const loffset = fromBytes(bytes, currOffset + 4)
|
|
167
|
+
firstDataLine = this._findFirstData(firstDataLine, loffset)
|
|
168
|
+
const chunkCount = bytes.readInt32LE(currOffset + 12)
|
|
169
|
+
currOffset += 16
|
|
170
|
+
const chunks = new Array(chunkCount)
|
|
171
|
+
for (let k = 0; k < chunkCount; k += 1) {
|
|
172
|
+
const u = fromBytes(bytes, currOffset)
|
|
173
|
+
const v = fromBytes(bytes, currOffset + 8)
|
|
174
|
+
currOffset += 16
|
|
175
|
+
// this._findFirstData(data, u)
|
|
176
|
+
chunks[k] = new Chunk(u, v, bin)
|
|
177
|
+
}
|
|
178
|
+
binIndex[bin] = chunks
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return { binIndex, stats }
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
...aux,
|
|
187
|
+
csi: true,
|
|
188
|
+
refCount,
|
|
189
|
+
maxBlockSize: 1 << 16,
|
|
190
|
+
firstDataLine,
|
|
191
|
+
csiVersion,
|
|
192
|
+
indices,
|
|
193
|
+
depth: this.depth,
|
|
194
|
+
maxBinNumber: this.maxBinNumber,
|
|
195
|
+
maxRefLength,
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
parsePseudoBin(bytes: Buffer, offset: number) {
|
|
200
|
+
const lineCount = longToNumber(
|
|
201
|
+
Long.fromBytesLE(
|
|
202
|
+
Array.prototype.slice.call(bytes, offset + 28, offset + 36),
|
|
203
|
+
true,
|
|
204
|
+
),
|
|
205
|
+
)
|
|
206
|
+
return { lineCount }
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async blocksForRange(
|
|
210
|
+
refName: string,
|
|
211
|
+
min: number,
|
|
212
|
+
max: number,
|
|
213
|
+
opts: Options = {},
|
|
214
|
+
) {
|
|
215
|
+
if (min < 0) {
|
|
216
|
+
min = 0
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const indexData = await this.parse(opts)
|
|
220
|
+
if (!indexData) {
|
|
221
|
+
return []
|
|
222
|
+
}
|
|
223
|
+
const refId = indexData.refNameToId[refName]
|
|
224
|
+
const ba = indexData.indices[refId]
|
|
225
|
+
if (!ba) {
|
|
226
|
+
return []
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// const { linearIndex, binIndex } = indexes
|
|
230
|
+
|
|
231
|
+
const overlappingBins = this.reg2bins(min, max) // List of bin #s that overlap min, max
|
|
232
|
+
const chunks: Chunk[] = []
|
|
233
|
+
|
|
234
|
+
// Find chunks in overlapping bins. Leaf bins (< 4681) are not pruned
|
|
235
|
+
for (const [start, end] of overlappingBins) {
|
|
236
|
+
for (let bin = start; bin <= end; bin++) {
|
|
237
|
+
if (ba.binIndex[bin]) {
|
|
238
|
+
const binChunks = ba.binIndex[bin]
|
|
239
|
+
for (let c = 0; c < binChunks.length; ++c) {
|
|
240
|
+
chunks.push(new Chunk(binChunks[c].minv, binChunks[c].maxv, bin))
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return optimizeChunks(chunks, new VirtualOffset(0, 0))
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* calculate the list of bins that may overlap with region [beg,end) (zero-based half-open)
|
|
251
|
+
*/
|
|
252
|
+
reg2bins(beg: number, end: number) {
|
|
253
|
+
beg -= 1 // < convert to 1-based closed
|
|
254
|
+
if (beg < 1) {
|
|
255
|
+
beg = 1
|
|
256
|
+
}
|
|
257
|
+
if (end > 2 ** 50) {
|
|
258
|
+
end = 2 ** 34
|
|
259
|
+
} // 17 GiB ought to be enough for anybody
|
|
260
|
+
end -= 1
|
|
261
|
+
let l = 0
|
|
262
|
+
let t = 0
|
|
263
|
+
let s = this.minShift + this.depth * 3
|
|
264
|
+
const bins = []
|
|
265
|
+
for (; l <= this.depth; s -= 3, t += lshift(1, l * 3), l += 1) {
|
|
266
|
+
const b = t + rshift(beg, s)
|
|
267
|
+
const e = t + rshift(end, s)
|
|
268
|
+
if (e - b + bins.length > this.maxBinNumber) {
|
|
269
|
+
throw new Error(
|
|
270
|
+
`query ${beg}-${end} is too large for current binning scheme (shift ${this.minShift}, depth ${this.depth}), try a smaller query or a coarser index binning scheme`,
|
|
271
|
+
)
|
|
272
|
+
}
|
|
273
|
+
bins.push([b, e])
|
|
274
|
+
}
|
|
275
|
+
return bins
|
|
276
|
+
}
|
|
277
|
+
}
|
package/src/declare.d.ts
ADDED