@gmod/tabix 1.5.11 → 1.5.13
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 +13 -4
- package/dist/chunk.d.ts +0 -6
- package/dist/chunk.js +1 -6
- package/dist/chunk.js.map +1 -1
- package/dist/csi.d.ts +6 -16
- package/dist/csi.js +4 -7
- package/dist/csi.js.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/indexFile.d.ts +2 -6
- package/dist/indexFile.js +4 -3
- package/dist/indexFile.js.map +1 -1
- package/dist/tabixIndexedFile.d.ts +2 -4
- package/dist/tabixIndexedFile.js +26 -47
- package/dist/tabixIndexedFile.js.map +1 -1
- package/dist/tbi.d.ts +3 -9
- package/dist/tbi.js +2 -3
- package/dist/tbi.js.map +1 -1
- package/dist/util.js +1 -6
- package/dist/util.js.map +1 -1
- package/dist/virtualOffset.js.map +1 -1
- package/esm/chunk.d.ts +0 -6
- package/esm/chunk.js +1 -6
- package/esm/chunk.js.map +1 -1
- package/esm/csi.d.ts +6 -16
- package/esm/csi.js +4 -5
- package/esm/csi.js.map +1 -1
- package/esm/index.d.ts +3 -4
- package/esm/index.js +3 -4
- package/esm/index.js.map +1 -1
- package/esm/indexFile.d.ts +2 -6
- package/esm/indexFile.js +4 -3
- package/esm/indexFile.js.map +1 -1
- package/esm/tabixIndexedFile.d.ts +2 -4
- package/esm/tabixIndexedFile.js +26 -47
- package/esm/tabixIndexedFile.js.map +1 -1
- package/esm/tbi.d.ts +3 -9
- package/esm/tbi.js +2 -3
- package/esm/tbi.js.map +1 -1
- package/esm/util.js +1 -6
- package/esm/util.js.map +1 -1
- package/esm/virtualOffset.js.map +1 -1
- package/package.json +14 -13
- package/src/chunk.ts +1 -6
- package/src/csi.ts +6 -7
- package/src/index.ts +3 -5
- package/src/indexFile.ts +4 -4
- package/src/tabixIndexedFile.ts +33 -52
- package/src/tbi.ts +5 -6
- package/src/util.ts +1 -5
package/esm/util.js
CHANGED
|
@@ -56,12 +56,7 @@ export function optimizeChunks(chunks, lowest) {
|
|
|
56
56
|
}
|
|
57
57
|
chunks.sort(function (c0, c1) {
|
|
58
58
|
const dif = c0.minv.blockPosition - c1.minv.blockPosition;
|
|
59
|
-
|
|
60
|
-
return dif;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
return c0.minv.dataPosition - c1.minv.dataPosition;
|
|
64
|
-
}
|
|
59
|
+
return dif !== 0 ? dif : c0.minv.dataPosition - c1.minv.dataPosition;
|
|
65
60
|
});
|
|
66
61
|
chunks.forEach(chunk => {
|
|
67
62
|
if (!lowest || chunk.maxv.compareTo(lowest) > 0) {
|
package/esm/util.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,IACE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,gBAAgB,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,EACtC;
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAGA,MAAM,UAAU,YAAY,CAAC,IAAU;IACrC,IACE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,gBAAgB,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,gBAAgB,CAAC,EACtC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAA;IACrC,CAAC;IACD,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAA;AACxB,CAAC;AAED,MAAM,UAAW,SAAQ,KAAK;CAE7B;AACD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoB;IACnD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAM;IACR,CAAC;IAED,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC;YACxC,qCAAqC;YACrC,MAAM,IAAI,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;QACjD,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,CAAA;YACnC,CAAC,CAAC,IAAI,GAAG,aAAa,CAAA;YACtB,MAAM,CAAC,CAAA;QACT,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAoB;IACxD,MAAM,OAAO,CAAC,OAAO,EAAE,CAAA;IACvB,gBAAgB,CAAC,MAAM,CAAC,CAAA;AAC1B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAa,EAAE,MAAa;IACzD,OAAO,CACL,MAAM,CAAC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,GAAG,KAAK;QAC7D,MAAM,CAAC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,GAAG,OAAO,CAChE,CAAA;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAe,EAAE,MAAqB;IACnE,MAAM,YAAY,GAAY,EAAE,CAAA;IAChC,IAAI,SAAS,GAAiB,IAAI,CAAA;IAElC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,MAAM,CAAA;IACf,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE;QAC1B,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC,IAAI,CAAC,aAAa,CAAA;QACzD,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAA;IACtE,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;QACrB,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;YAChD,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACvB,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBACxB,SAAS,GAAG,KAAK,CAAA;YACnB,CAAC;iBAAM,CAAC;gBACN,IAAI,cAAc,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;oBACrC,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;wBAC7C,SAAS,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAA;oBAC7B,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;oBACxB,SAAS,GAAG,KAAK,CAAA;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,YAAY,CAAA;AACrB,CAAC"}
|
package/esm/virtualOffset.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"virtualOffset.js","sourceRoot":"","sources":["../src/virtualOffset.ts"],"names":[],"mappings":"AACA,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;
|
|
1
|
+
{"version":3,"file":"virtualOffset.js","sourceRoot":"","sources":["../src/virtualOffset.ts"],"names":[],"mappings":"AACA,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,CAAC;YACpB,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;QACf,CAAC;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/B,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/B,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;YACf,CAAC;QACH,CAAC;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,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAA;IACpE,CAAC;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.13",
|
|
4
4
|
"description": "Read Tabix-indexed files, supports both .tbi and .csi indexes",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "GMOD/tabix-js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"scripts": {
|
|
23
23
|
"test": "jest",
|
|
24
24
|
"coverage": "npm test -- --coverage",
|
|
25
|
-
"lint": "eslint --ext .js,.ts src
|
|
25
|
+
"lint": "eslint --ext .js,.ts src",
|
|
26
26
|
"clean": "rimraf dist esm",
|
|
27
27
|
"prebuild": "npm run clean && npm run lint",
|
|
28
28
|
"build:esm": "tsc --target es2018 --outDir esm",
|
|
@@ -46,22 +46,23 @@
|
|
|
46
46
|
"quick-lru": "^4.0.0"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"@types/jest": "^29.5.
|
|
49
|
+
"@types/jest": "^29.5.11",
|
|
50
50
|
"@types/long": "^4.0.0",
|
|
51
|
-
"@types/node": "^
|
|
52
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
53
|
-
"@typescript-eslint/parser": "^
|
|
51
|
+
"@types/node": "^20.10.5",
|
|
52
|
+
"@typescript-eslint/eslint-plugin": "^6.15.0",
|
|
53
|
+
"@typescript-eslint/parser": "^6.15.0",
|
|
54
54
|
"eslint": "^8.40.0",
|
|
55
|
-
"eslint-config-prettier": "^
|
|
55
|
+
"eslint-config-prettier": "^9.1.0",
|
|
56
56
|
"eslint-plugin-import": "^2.27.5",
|
|
57
|
-
"eslint-plugin-prettier": "^
|
|
58
|
-
"
|
|
57
|
+
"eslint-plugin-prettier": "^5.0.1",
|
|
58
|
+
"eslint-plugin-unicorn": "^49.0.0",
|
|
59
|
+
"jest": "^29.7.0",
|
|
59
60
|
"jest-environment-jsdom": "^29.5.0",
|
|
60
|
-
"prettier": "^
|
|
61
|
+
"prettier": "^3.1.1",
|
|
61
62
|
"rimraf": "^5.0.1",
|
|
62
|
-
"standard-changelog": "^
|
|
63
|
-
"ts-jest": "^29.1.
|
|
64
|
-
"typescript": "^5.
|
|
63
|
+
"standard-changelog": "^5.0.0",
|
|
64
|
+
"ts-jest": "^29.1.1",
|
|
65
|
+
"typescript": "^5.3.3"
|
|
65
66
|
},
|
|
66
67
|
"publishConfig": {
|
|
67
68
|
"access": "public"
|
package/src/chunk.ts
CHANGED
|
@@ -7,12 +7,6 @@ export default class Chunk {
|
|
|
7
7
|
public bin: number
|
|
8
8
|
public _fetchedSize?: number
|
|
9
9
|
|
|
10
|
-
/**
|
|
11
|
-
* @param {VirtualOffset} minv
|
|
12
|
-
* @param {VirtualOffset} maxv
|
|
13
|
-
* @param {number} bin
|
|
14
|
-
* @param {number} [fetchedSize]
|
|
15
|
-
*/
|
|
16
10
|
constructor(
|
|
17
11
|
minv: VirtualOffset,
|
|
18
12
|
maxv: VirtualOffset,
|
|
@@ -26,6 +20,7 @@ export default class Chunk {
|
|
|
26
20
|
}
|
|
27
21
|
|
|
28
22
|
toUniqueString() {
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
29
24
|
return `${this.minv}..${this.maxv} (bin ${
|
|
30
25
|
this.bin
|
|
31
26
|
}, fetchedSize ${this.fetchedSize()})`
|
package/src/csi.ts
CHANGED
|
@@ -44,7 +44,7 @@ export default class CSI extends IndexFile {
|
|
|
44
44
|
}
|
|
45
45
|
return -1
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
indexCov() {
|
|
48
48
|
throw new Error('CSI indexes do not support indexcov')
|
|
49
49
|
}
|
|
50
50
|
|
|
@@ -85,7 +85,7 @@ export default class CSI extends IndexFile {
|
|
|
85
85
|
let currRefId = 0
|
|
86
86
|
let currNameStart = 0
|
|
87
87
|
const refIdToName = []
|
|
88
|
-
const refNameToId:
|
|
88
|
+
const refNameToId: Record<string, number> = {}
|
|
89
89
|
for (let i = 0; i < namesBytes.length; i += 1) {
|
|
90
90
|
if (!namesBytes[i]) {
|
|
91
91
|
if (currNameStart < i) {
|
|
@@ -104,7 +104,7 @@ export default class CSI extends IndexFile {
|
|
|
104
104
|
// fetch and parse the index
|
|
105
105
|
|
|
106
106
|
async _parse(opts: Options = {}) {
|
|
107
|
-
const bytes = await unzip(
|
|
107
|
+
const bytes = await unzip(await this.filehandle.readFile(opts))
|
|
108
108
|
|
|
109
109
|
// check TBI magic numbers
|
|
110
110
|
let csiVersion
|
|
@@ -142,7 +142,7 @@ export default class CSI extends IndexFile {
|
|
|
142
142
|
// the binning index
|
|
143
143
|
const binCount = bytes.readInt32LE(currOffset)
|
|
144
144
|
currOffset += 4
|
|
145
|
-
const binIndex:
|
|
145
|
+
const binIndex: Record<string, Chunk[]> = {}
|
|
146
146
|
let stats // < provided by parsing a pseudo-bin, if present
|
|
147
147
|
for (let j = 0; j < binCount; j += 1) {
|
|
148
148
|
const bin = bytes.readUInt32LE(currOffset)
|
|
@@ -224,9 +224,8 @@ export default class CSI extends IndexFile {
|
|
|
224
224
|
for (const [start, end] of overlappingBins) {
|
|
225
225
|
for (let bin = start; bin <= end; bin++) {
|
|
226
226
|
if (ba.binIndex[bin]) {
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
chunks.push(new Chunk(binChunks[c].minv, binChunks[c].maxv, bin))
|
|
227
|
+
for (const c of ba.binIndex[bin]) {
|
|
228
|
+
chunks.push(new Chunk(c.minv, c.maxv, bin))
|
|
230
229
|
}
|
|
231
230
|
}
|
|
232
231
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export { TabixIndexedFile, TBI, CSI }
|
|
1
|
+
export { default as TabixIndexedFile } from './tabixIndexedFile'
|
|
2
|
+
export { default as CSI } from './csi'
|
|
3
|
+
export { default as TBI } from './tbi'
|
package/src/indexFile.ts
CHANGED
|
@@ -9,7 +9,7 @@ export interface Options {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export interface IndexData {
|
|
12
|
-
refNameToId:
|
|
12
|
+
refNameToId: Record<string, number>
|
|
13
13
|
refIdToName: string[]
|
|
14
14
|
metaChar: string | null
|
|
15
15
|
columnNumbers: { ref: number; start: number; end: number }
|
|
@@ -39,8 +39,7 @@ export default abstract class IndexFile {
|
|
|
39
39
|
protected abstract _parse(opts: Options): Promise<IndexData>
|
|
40
40
|
|
|
41
41
|
public async getMetadata(opts: Options = {}) {
|
|
42
|
-
|
|
43
|
-
const { indices, ...rest } = await this.parse(opts)
|
|
42
|
+
const { indices: _indices, ...rest } = await this.parse(opts)
|
|
44
43
|
return rest
|
|
45
44
|
}
|
|
46
45
|
|
|
@@ -75,6 +74,7 @@ export default abstract class IndexFile {
|
|
|
75
74
|
}
|
|
76
75
|
|
|
77
76
|
async hasRefSeq(seqId: number, opts: Options = {}) {
|
|
78
|
-
|
|
77
|
+
const idx = await this.parse(opts)
|
|
78
|
+
return !!idx.indices[seqId]?.binIndex
|
|
79
79
|
}
|
|
80
80
|
}
|
package/src/tabixIndexedFile.ts
CHANGED
|
@@ -13,7 +13,7 @@ import CSI from './csi'
|
|
|
13
13
|
type GetLinesCallback = (line: string, fileOffset: number) => void
|
|
14
14
|
|
|
15
15
|
const decoder =
|
|
16
|
-
typeof TextDecoder !== 'undefined' ? new TextDecoder('
|
|
16
|
+
typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined
|
|
17
17
|
|
|
18
18
|
interface GetLinesOpts {
|
|
19
19
|
[key: string]: unknown
|
|
@@ -132,14 +132,14 @@ export default class TabixIndexedFile {
|
|
|
132
132
|
*/
|
|
133
133
|
async getLines(
|
|
134
134
|
refName: string,
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
s: number | undefined,
|
|
136
|
+
e: number | undefined,
|
|
137
137
|
opts: GetLinesOpts | GetLinesCallback,
|
|
138
138
|
) {
|
|
139
139
|
let signal: AbortSignal | undefined
|
|
140
140
|
let options: Options = {}
|
|
141
141
|
let callback: (line: string, lineOffset: number) => void
|
|
142
|
-
if (
|
|
142
|
+
if (opts === undefined) {
|
|
143
143
|
throw new TypeError('line callback must be provided')
|
|
144
144
|
}
|
|
145
145
|
if (typeof opts === 'function') {
|
|
@@ -147,6 +147,7 @@ export default class TabixIndexedFile {
|
|
|
147
147
|
} else {
|
|
148
148
|
options = opts
|
|
149
149
|
callback = opts.lineCallback
|
|
150
|
+
signal = opts.signal
|
|
150
151
|
}
|
|
151
152
|
if (refName === undefined) {
|
|
152
153
|
throw new TypeError('must provide a reference sequence name')
|
|
@@ -157,12 +158,8 @@ export default class TabixIndexedFile {
|
|
|
157
158
|
|
|
158
159
|
const metadata = await this.index.getMetadata(options)
|
|
159
160
|
checkAbortSignal(signal)
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
}
|
|
163
|
-
if (!end) {
|
|
164
|
-
end = metadata.maxRefLength
|
|
165
|
-
}
|
|
161
|
+
const start = s ?? 0
|
|
162
|
+
const end = e ?? metadata.maxRefLength
|
|
166
163
|
if (!(start <= end)) {
|
|
167
164
|
throw new TypeError(
|
|
168
165
|
'invalid start and end coordinates. start must be less than or equal to end',
|
|
@@ -177,8 +174,8 @@ export default class TabixIndexedFile {
|
|
|
177
174
|
|
|
178
175
|
// check the chunks for any that are over the size limit. if
|
|
179
176
|
// any are, don't fetch any of them
|
|
180
|
-
for (
|
|
181
|
-
const size =
|
|
177
|
+
for (const chunk of chunks) {
|
|
178
|
+
const size = chunk.fetchedSize()
|
|
182
179
|
if (size > this.chunkSizeLimit) {
|
|
183
180
|
throw new Error(
|
|
184
181
|
`Too much data. Chunk size ${size.toLocaleString()} bytes exceeds chunkSizeLimit of ${this.chunkSizeLimit.toLocaleString()}.`,
|
|
@@ -188,12 +185,12 @@ export default class TabixIndexedFile {
|
|
|
188
185
|
|
|
189
186
|
// now go through each chunk and parse and filter the lines out of it
|
|
190
187
|
let last = Date.now()
|
|
191
|
-
for (
|
|
188
|
+
for (const c of chunks) {
|
|
192
189
|
let previousStartCoordinate: number | undefined
|
|
193
|
-
const c = chunks[chunkNum]
|
|
194
190
|
const { buffer, cpositions, dpositions } = await this.chunkCache.get(
|
|
195
191
|
c.toString(),
|
|
196
192
|
c,
|
|
193
|
+
signal,
|
|
197
194
|
)
|
|
198
195
|
|
|
199
196
|
checkAbortSignal(signal)
|
|
@@ -205,7 +202,7 @@ export default class TabixIndexedFile {
|
|
|
205
202
|
break
|
|
206
203
|
}
|
|
207
204
|
const b = buffer.slice(blockStart, n)
|
|
208
|
-
const line = decoder?.decode(b)
|
|
205
|
+
const line = decoder?.decode(b) ?? b.toString()
|
|
209
206
|
|
|
210
207
|
if (dpositions) {
|
|
211
208
|
while (blockStart + c.minv.dataPosition >= dpositions[pos++]) {}
|
|
@@ -278,25 +275,15 @@ export default class TabixIndexedFile {
|
|
|
278
275
|
* non-meta line
|
|
279
276
|
*/
|
|
280
277
|
async getHeaderBuffer(opts: Options = {}) {
|
|
281
|
-
const { firstDataLine, metaChar, maxBlockSize } =
|
|
282
|
-
opts
|
|
283
|
-
)
|
|
278
|
+
const { firstDataLine, metaChar, maxBlockSize } =
|
|
279
|
+
await this.getMetadata(opts)
|
|
284
280
|
checkAbortSignal(opts.signal)
|
|
285
281
|
const maxFetch = (firstDataLine?.blockPosition || 0) + maxBlockSize
|
|
286
282
|
// TODO: what if we don't have a firstDataLine, and the header
|
|
287
283
|
// actually takes up more than one block? this case is not covered here
|
|
288
284
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
try {
|
|
292
|
-
bytes = await unzip(bytes)
|
|
293
|
-
} catch (e) {
|
|
294
|
-
console.error(e)
|
|
295
|
-
throw new Error(
|
|
296
|
-
//@ts-ignore
|
|
297
|
-
`error decompressing block ${e.code} at 0 (length ${maxFetch}) ${e}`,
|
|
298
|
-
)
|
|
299
|
-
}
|
|
285
|
+
const buf = await this._readRegion(0, maxFetch, opts)
|
|
286
|
+
const bytes = await unzip(buf)
|
|
300
287
|
|
|
301
288
|
// trim off lines after the last non-meta line
|
|
302
289
|
if (metaChar) {
|
|
@@ -312,7 +299,7 @@ export default class TabixIndexedFile {
|
|
|
312
299
|
lastNewline = i
|
|
313
300
|
}
|
|
314
301
|
}
|
|
315
|
-
|
|
302
|
+
return bytes.slice(0, lastNewline + 1)
|
|
316
303
|
}
|
|
317
304
|
return bytes
|
|
318
305
|
}
|
|
@@ -357,7 +344,7 @@ export default class TabixIndexedFile {
|
|
|
357
344
|
) {
|
|
358
345
|
const { columnNumbers, metaChar, coordinateType, format } = metadata
|
|
359
346
|
// skip meta lines
|
|
360
|
-
if (line.
|
|
347
|
+
if (metaChar && line.startsWith(metaChar)) {
|
|
361
348
|
return { overlaps: false }
|
|
362
349
|
}
|
|
363
350
|
|
|
@@ -412,17 +399,15 @@ export default class TabixIndexedFile {
|
|
|
412
399
|
} else if (format === 'VCF' && currentColumnNumber === 4) {
|
|
413
400
|
refSeq = line.slice(currentColumnStart, i)
|
|
414
401
|
} else if (currentColumnNumber === end) {
|
|
415
|
-
let endCoordinate
|
|
416
402
|
// this will never match if there is no end column
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
403
|
+
const endCoordinate =
|
|
404
|
+
format === 'VCF'
|
|
405
|
+
? this._getVcfEnd(
|
|
406
|
+
startCoordinate,
|
|
407
|
+
refSeq,
|
|
408
|
+
line.slice(currentColumnStart, i),
|
|
409
|
+
)
|
|
410
|
+
: parseInt(line.slice(currentColumnStart, i), 10)
|
|
426
411
|
if (endCoordinate <= regionStart) {
|
|
427
412
|
return { overlaps: false }
|
|
428
413
|
}
|
|
@@ -439,12 +424,12 @@ export default class TabixIndexedFile {
|
|
|
439
424
|
|
|
440
425
|
_getVcfEnd(startCoordinate: number, refSeq: string, info: any) {
|
|
441
426
|
let endCoordinate = startCoordinate + refSeq.length
|
|
442
|
-
// ignore TRA features as they specify CHR2 and END
|
|
443
|
-
//
|
|
444
|
-
//
|
|
445
|
-
//
|
|
446
|
-
// at the end of this one
|
|
447
|
-
const isTRA = info.
|
|
427
|
+
// ignore TRA features as they specify CHR2 and END as being on a different
|
|
428
|
+
// chromosome
|
|
429
|
+
//
|
|
430
|
+
// if CHR2 is on the same chromosome, still ignore it because there should
|
|
431
|
+
// be another pairwise feature at the end of this one
|
|
432
|
+
const isTRA = info.includes('SVTYPE=TRA')
|
|
448
433
|
if (info[0] !== '.' && !isTRA) {
|
|
449
434
|
let prevChar = ';'
|
|
450
435
|
for (let j = 0; j < info.length; j += 1) {
|
|
@@ -499,10 +484,6 @@ export default class TabixIndexedFile {
|
|
|
499
484
|
c.fetchedSize(),
|
|
500
485
|
opts,
|
|
501
486
|
)
|
|
502
|
-
|
|
503
|
-
return unzipChunkSlice(data, c)
|
|
504
|
-
} catch (e) {
|
|
505
|
-
throw new Error(`error decompressing c ${c.toString()} ${e}`)
|
|
506
|
-
}
|
|
487
|
+
return unzipChunkSlice(data, c)
|
|
507
488
|
}
|
|
508
489
|
}
|
package/src/tbi.ts
CHANGED
|
@@ -60,7 +60,7 @@ export default class TabixIndex extends IndexFile {
|
|
|
60
60
|
const formatFlags = bytes.readInt32LE(8)
|
|
61
61
|
const coordinateType =
|
|
62
62
|
formatFlags & 0x10000 ? 'zero-based-half-open' : '1-based-closed'
|
|
63
|
-
const formatOpts:
|
|
63
|
+
const formatOpts: Record<number, string> = {
|
|
64
64
|
0: 'generic',
|
|
65
65
|
1: 'SAM',
|
|
66
66
|
2: 'VCF',
|
|
@@ -94,7 +94,7 @@ export default class TabixIndex extends IndexFile {
|
|
|
94
94
|
// the binning index
|
|
95
95
|
const binCount = bytes.readInt32LE(currOffset)
|
|
96
96
|
currOffset += 4
|
|
97
|
-
const binIndex:
|
|
97
|
+
const binIndex: Record<number, Chunk[]> = {}
|
|
98
98
|
let stats
|
|
99
99
|
for (let j = 0; j < binCount; j += 1) {
|
|
100
100
|
const bin = bytes.readUInt32LE(currOffset)
|
|
@@ -167,7 +167,7 @@ export default class TabixIndex extends IndexFile {
|
|
|
167
167
|
let currRefId = 0
|
|
168
168
|
let currNameStart = 0
|
|
169
169
|
const refIdToName: string[] = []
|
|
170
|
-
const refNameToId:
|
|
170
|
+
const refNameToId: Record<string, number> = {}
|
|
171
171
|
for (let i = 0; i < namesBytes.length; i += 1) {
|
|
172
172
|
if (!namesBytes[i]) {
|
|
173
173
|
if (currNameStart < i) {
|
|
@@ -223,9 +223,8 @@ export default class TabixIndex extends IndexFile {
|
|
|
223
223
|
for (const [start, end] of overlappingBins) {
|
|
224
224
|
for (let bin = start; bin <= end; bin++) {
|
|
225
225
|
if (ba.binIndex[bin]) {
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
chunks.push(new Chunk(binChunks[c].minv, binChunks[c].maxv, bin))
|
|
226
|
+
for (const c of ba.binIndex[bin]) {
|
|
227
|
+
chunks.push(new Chunk(c.minv, c.maxv, bin))
|
|
229
228
|
}
|
|
230
229
|
}
|
|
231
230
|
}
|
package/src/util.ts
CHANGED
|
@@ -70,11 +70,7 @@ export function optimizeChunks(chunks: Chunk[], lowest: VirtualOffset) {
|
|
|
70
70
|
|
|
71
71
|
chunks.sort(function (c0, c1) {
|
|
72
72
|
const dif = c0.minv.blockPosition - c1.minv.blockPosition
|
|
73
|
-
|
|
74
|
-
return dif
|
|
75
|
-
} else {
|
|
76
|
-
return c0.minv.dataPosition - c1.minv.dataPosition
|
|
77
|
-
}
|
|
73
|
+
return dif !== 0 ? dif : c0.minv.dataPosition - c1.minv.dataPosition
|
|
78
74
|
})
|
|
79
75
|
|
|
80
76
|
chunks.forEach(chunk => {
|