@gmod/cram 2.0.0 → 2.0.2
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 +4 -0
- package/dist/craiIndex.d.ts +2 -2
- package/dist/craiIndex.js +5 -9
- package/dist/craiIndex.js.map +1 -1
- package/dist/cram-bundle.js +1 -1
- package/dist/cramFile/codecs/_base.d.ts +6 -6
- package/dist/cramFile/codecs/beta.js.map +1 -1
- package/dist/cramFile/codecs/byteArrayLength.js.map +1 -1
- package/dist/cramFile/codecs/byteArrayStop.js.map +1 -1
- package/dist/cramFile/codecs/external.js +1 -0
- package/dist/cramFile/codecs/external.js.map +1 -1
- package/dist/cramFile/codecs/gamma.js.map +1 -1
- package/dist/cramFile/codecs/getBits.js.map +1 -1
- package/dist/cramFile/codecs/huffman.d.ts +0 -1
- package/dist/cramFile/codecs/huffman.js +1 -3
- package/dist/cramFile/codecs/huffman.js.map +1 -1
- package/dist/cramFile/codecs/index.js.map +1 -1
- package/dist/cramFile/codecs/subexp.js.map +1 -1
- package/dist/cramFile/container/compressionScheme.js +1 -1
- package/dist/cramFile/container/compressionScheme.js.map +1 -1
- package/dist/cramFile/container/index.js.map +1 -1
- package/dist/cramFile/encoding.d.ts +20 -20
- package/dist/cramFile/file.d.ts +14 -7
- package/dist/cramFile/file.js.map +1 -1
- package/dist/cramFile/filehandle.d.ts +1 -2
- package/dist/cramFile/index.d.ts +1 -2
- package/dist/cramFile/index.js +3 -3
- package/dist/cramFile/index.js.map +1 -1
- package/dist/cramFile/record.d.ts +6 -6
- package/dist/cramFile/record.js +7 -4
- package/dist/cramFile/record.js.map +1 -1
- package/dist/cramFile/sectionParsers.d.ts +9 -8
- package/dist/cramFile/sectionParsers.js +10 -11
- package/dist/cramFile/sectionParsers.js.map +1 -1
- package/dist/cramFile/slice/decodeRecord.js +7 -11
- package/dist/cramFile/slice/decodeRecord.js.map +1 -1
- package/dist/cramFile/slice/index.js +24 -22
- package/dist/cramFile/slice/index.js.map +1 -1
- package/dist/cramFile/util.d.ts +1 -0
- package/dist/cramFile/util.js +1 -1
- package/dist/cramFile/util.js.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +7 -30
- package/dist/index.js.map +1 -1
- package/dist/indexedCramFile.d.ts +6 -6
- package/dist/indexedCramFile.js +13 -18
- package/dist/indexedCramFile.js.map +1 -1
- package/dist/io/index.d.ts +2 -1
- package/dist/io/index.js +4 -3
- package/dist/io/index.js.map +1 -1
- package/dist/rans/d04.js.map +1 -1
- package/dist/rans/d14.js.map +1 -1
- package/dist/rans/decoding.js.map +1 -1
- package/dist/rans/frequencies.js.map +1 -1
- package/dist/rans/index.js.map +1 -1
- package/dist/sam.d.ts +5 -6
- package/dist/sam.js +20 -7
- package/dist/sam.js.map +1 -1
- package/dist/typescript.js.map +1 -1
- package/dist/unzip.d.ts +2 -2
- package/dist/unzip.js +1 -1
- package/dist/unzip.js.map +1 -1
- package/esm/craiIndex.d.ts +2 -2
- package/esm/craiIndex.js +5 -9
- package/esm/craiIndex.js.map +1 -1
- package/esm/cramFile/codecs/_base.d.ts +6 -6
- package/esm/cramFile/codecs/beta.js.map +1 -1
- package/esm/cramFile/codecs/byteArrayLength.js.map +1 -1
- package/esm/cramFile/codecs/byteArrayStop.js.map +1 -1
- package/esm/cramFile/codecs/external.js +1 -0
- package/esm/cramFile/codecs/external.js.map +1 -1
- package/esm/cramFile/codecs/gamma.js.map +1 -1
- package/esm/cramFile/codecs/getBits.js.map +1 -1
- package/esm/cramFile/codecs/huffman.d.ts +0 -1
- package/esm/cramFile/codecs/huffman.js +1 -3
- package/esm/cramFile/codecs/huffman.js.map +1 -1
- package/esm/cramFile/codecs/index.js.map +1 -1
- package/esm/cramFile/codecs/subexp.js.map +1 -1
- package/esm/cramFile/container/compressionScheme.js +1 -1
- package/esm/cramFile/container/compressionScheme.js.map +1 -1
- package/esm/cramFile/container/index.js.map +1 -1
- package/esm/cramFile/encoding.d.ts +20 -20
- package/esm/cramFile/file.d.ts +14 -7
- package/esm/cramFile/file.js.map +1 -1
- package/esm/cramFile/filehandle.d.ts +1 -2
- package/esm/cramFile/index.d.ts +1 -2
- package/esm/cramFile/index.js +1 -2
- package/esm/cramFile/index.js.map +1 -1
- package/esm/cramFile/record.d.ts +6 -6
- package/esm/cramFile/record.js +7 -4
- package/esm/cramFile/record.js.map +1 -1
- package/esm/cramFile/sectionParsers.d.ts +9 -8
- package/esm/cramFile/sectionParsers.js +10 -11
- package/esm/cramFile/sectionParsers.js.map +1 -1
- package/esm/cramFile/slice/decodeRecord.js +7 -11
- package/esm/cramFile/slice/decodeRecord.js.map +1 -1
- package/esm/cramFile/slice/index.js +24 -22
- package/esm/cramFile/slice/index.js.map +1 -1
- package/esm/cramFile/util.d.ts +1 -0
- package/esm/cramFile/util.js +1 -1
- package/esm/cramFile/util.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/indexedCramFile.d.ts +6 -6
- package/esm/indexedCramFile.js +13 -18
- package/esm/indexedCramFile.js.map +1 -1
- package/esm/io/index.d.ts +2 -1
- package/esm/io/index.js +2 -1
- package/esm/io/index.js.map +1 -1
- package/esm/rans/d04.js.map +1 -1
- package/esm/rans/d14.js.map +1 -1
- package/esm/rans/decoding.js.map +1 -1
- package/esm/rans/frequencies.js.map +1 -1
- package/esm/rans/index.js.map +1 -1
- package/esm/sam.d.ts +5 -6
- package/esm/sam.js +20 -7
- package/esm/sam.js.map +1 -1
- package/esm/typescript.js.map +1 -1
- package/esm/unzip.d.ts +2 -2
- package/esm/unzip.js +1 -2
- package/esm/unzip.js.map +1 -1
- package/package.json +11 -11
- package/src/craiIndex.ts +8 -13
- package/src/cramFile/codecs/_base.ts +3 -3
- package/src/cramFile/codecs/external.ts +1 -0
- package/src/cramFile/codecs/huffman.ts +7 -8
- package/src/cramFile/container/compressionScheme.ts +1 -1
- package/src/cramFile/encoding.ts +10 -10
- package/src/cramFile/file.ts +5 -5
- package/src/cramFile/filehandle.ts +1 -3
- package/src/cramFile/index.ts +1 -2
- package/src/cramFile/record.ts +13 -10
- package/src/cramFile/sectionParsers.ts +8 -9
- package/src/cramFile/slice/decodeRecord.ts +15 -17
- package/src/cramFile/slice/index.ts +26 -23
- package/src/cramFile/util.ts +1 -1
- package/src/index.ts +3 -5
- package/src/indexedCramFile.ts +19 -23
- package/src/io/index.ts +3 -1
- package/src/sam.ts +28 -14
- package/src/typings/binary-parser.d.ts +1 -1
- package/src/unzip.ts +1 -2
package/esm/sam.js
CHANGED
|
@@ -1,16 +1,29 @@
|
|
|
1
1
|
export function parseHeaderText(text) {
|
|
2
2
|
const lines = text.split(/\r?\n/);
|
|
3
3
|
const data = [];
|
|
4
|
-
|
|
4
|
+
for (const line of lines) {
|
|
5
5
|
const [tag, ...fields] = line.split(/\t/);
|
|
6
|
-
const parsedFields = fields.map(f => {
|
|
7
|
-
const [fieldTag, value] = f.split(':', 2);
|
|
8
|
-
return { tag: fieldTag, value };
|
|
9
|
-
});
|
|
10
6
|
if (tag) {
|
|
11
|
-
data.push({
|
|
7
|
+
data.push({
|
|
8
|
+
tag: tag.slice(1),
|
|
9
|
+
data: fields.map(f => {
|
|
10
|
+
const r = f.indexOf(':');
|
|
11
|
+
return r !== -1
|
|
12
|
+
? {
|
|
13
|
+
tag: f.slice(0, r),
|
|
14
|
+
value: f.slice(r + 1),
|
|
15
|
+
}
|
|
16
|
+
: // @CO lines are not comma separated.
|
|
17
|
+
// See "samtools view -H c2\#pad.3.0.cram"
|
|
18
|
+
// so, just store value tag itself
|
|
19
|
+
{
|
|
20
|
+
tag: f,
|
|
21
|
+
value: undefined,
|
|
22
|
+
};
|
|
23
|
+
}),
|
|
24
|
+
});
|
|
12
25
|
}
|
|
13
|
-
}
|
|
26
|
+
}
|
|
14
27
|
return data;
|
|
15
28
|
}
|
|
16
29
|
//# sourceMappingURL=sam.js.map
|
package/esm/sam.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sam.js","sourceRoot":"","sources":["../src/sam.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sam.js","sourceRoot":"","sources":["../src/sam.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACjC,MAAM,IAAI,GAMJ,EAAE,CAAA;IACR,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QACzC,IAAI,GAAG,EAAE,CAAC;YACR,IAAI,CAAC,IAAI,CAAC;gBACR,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;gBACjB,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;oBACnB,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;oBACxB,OAAO,CAAC,KAAK,CAAC,CAAC;wBACb,CAAC,CAAC;4BACE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;4BAClB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC;yBACtB;wBACH,CAAC,CAAC,qCAAqC;4BACrC,0CAA0C;4BAC1C,kCAAkC;4BAClC;gCACE,GAAG,EAAE,CAAC;gCACN,KAAK,EAAE,SAAS;6BACjB,CAAA;gBACP,CAAC,CAAC;aACH,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
|
package/esm/typescript.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../src/typescript.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB,CAAI,CAAuB;IACzD,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,EAAE;
|
|
1
|
+
{"version":3,"file":"typescript.js","sourceRoot":"","sources":["../src/typescript.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,gBAAgB,CAAI,CAAuB;IACzD,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAA;IAC/C,CAAC;IACD,OAAO,CAAC,CAAA;AACV,CAAC"}
|
package/esm/unzip.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export { gunzipSync as unzip };
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
export { gunzipSync as unzip } from 'zlib';
|
package/esm/unzip.js
CHANGED
package/esm/unzip.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unzip.js","sourceRoot":"","sources":["../src/unzip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAA
|
|
1
|
+
{"version":3,"file":"unzip.js","sourceRoot":"","sources":["../src/unzip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,IAAI,KAAK,EAAE,MAAM,MAAM,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gmod/cram",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.2",
|
|
4
4
|
"description": "read CRAM files with pure Javascript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "GMOD/cram-js",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@gmod/binary-parser": "^1.3.5",
|
|
46
46
|
"@jkbonfield/htscodecs": "^0.5.1",
|
|
47
47
|
"abortable-promise-cache": "^1.2.0",
|
|
48
|
-
"buffer-crc32": "^0.
|
|
48
|
+
"buffer-crc32": "^1.0.0",
|
|
49
49
|
"bzip2": "^0.1.1",
|
|
50
50
|
"long": "^4.0.0",
|
|
51
51
|
"md5": "^2.2.1",
|
|
@@ -57,28 +57,28 @@
|
|
|
57
57
|
"@babel/plugin-transform-modules-commonjs": "^7.18.2",
|
|
58
58
|
"@babel/preset-typescript": "^7.17.12",
|
|
59
59
|
"@gmod/indexedfasta": "^2.1.0",
|
|
60
|
-
"@types/
|
|
61
|
-
"@types/jest": "^29.2.4",
|
|
60
|
+
"@types/jest": "^29.5.12",
|
|
62
61
|
"@types/long": "^4.0.2",
|
|
63
62
|
"@types/md5": "^2.3.2",
|
|
64
63
|
"@types/pako": "^1.0.3",
|
|
65
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
66
|
-
"@typescript-eslint/parser": "^
|
|
64
|
+
"@typescript-eslint/eslint-plugin": "^7.0.2",
|
|
65
|
+
"@typescript-eslint/parser": "^7.0.2",
|
|
67
66
|
"buffer": "^6.0.3",
|
|
68
|
-
"documentation": "^14.0.
|
|
67
|
+
"documentation": "^14.0.3",
|
|
69
68
|
"eslint": "^8.30.0",
|
|
70
69
|
"eslint-config-prettier": "^9.0.0",
|
|
71
70
|
"eslint-plugin-import": "^2.25.4",
|
|
72
|
-
"eslint-plugin-prettier": "^5.
|
|
71
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
72
|
+
"eslint-plugin-unicorn": "^51.0.1",
|
|
73
73
|
"glob": "^10.3.1",
|
|
74
74
|
"jest": "^29.3.1",
|
|
75
75
|
"mock-fs": "^5.2.0",
|
|
76
|
-
"prettier": "^3.
|
|
76
|
+
"prettier": "^3.2.5",
|
|
77
77
|
"rimraf": "^5.0.1",
|
|
78
|
-
"ts-jest": "^29.
|
|
78
|
+
"ts-jest": "^29.1.2",
|
|
79
79
|
"typescript": "^5.0.3",
|
|
80
80
|
"url": "^0.11.0",
|
|
81
|
-
"webpack": "5.
|
|
81
|
+
"webpack": "^5.90.3",
|
|
82
82
|
"webpack-cli": "^5.0.1"
|
|
83
83
|
},
|
|
84
84
|
"publishConfig": {
|
package/src/craiIndex.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { Filehandle } from './cramFile/filehandle'
|
|
|
8
8
|
|
|
9
9
|
const BAI_MAGIC = 21578050 // BAI\1
|
|
10
10
|
|
|
11
|
-
export
|
|
11
|
+
export interface Slice {
|
|
12
12
|
start: number
|
|
13
13
|
span: number
|
|
14
14
|
containerStart: number
|
|
@@ -19,10 +19,6 @@ export type Slice = {
|
|
|
19
19
|
type ParsedIndex = Record<string, Slice[]>
|
|
20
20
|
|
|
21
21
|
function addRecordToIndex(index: ParsedIndex, record: number[]) {
|
|
22
|
-
if (record.some(el => el === undefined)) {
|
|
23
|
-
throw new CramMalformedError('invalid .crai index file')
|
|
24
|
-
}
|
|
25
|
-
|
|
26
22
|
const [seqId, start, span, containerStart, sliceStart, sliceBytes] = record
|
|
27
23
|
|
|
28
24
|
if (!index[seqId]) {
|
|
@@ -61,7 +57,7 @@ export default class CraiIndex {
|
|
|
61
57
|
this.filehandle = open(args.url, args.path, args.filehandle)
|
|
62
58
|
this._parseCache = new AbortablePromiseCache<unknown, ParsedIndex>({
|
|
63
59
|
cache: new QuickLRU({ maxSize: 1 }),
|
|
64
|
-
fill: (
|
|
60
|
+
fill: (_data, _signal) => this.parseIndex(),
|
|
65
61
|
})
|
|
66
62
|
}
|
|
67
63
|
|
|
@@ -90,8 +86,7 @@ export default class CraiIndex {
|
|
|
90
86
|
// because some .crai files can be pretty large.
|
|
91
87
|
let currentRecord: number[] = []
|
|
92
88
|
let currentString = ''
|
|
93
|
-
for (
|
|
94
|
-
const charCode = uncompressedBuffer[i]
|
|
89
|
+
for (const charCode of uncompressedBuffer) {
|
|
95
90
|
if (
|
|
96
91
|
(charCode >= 48 && charCode <= 57) /* 0-9 */ ||
|
|
97
92
|
(!currentString && charCode === 45) /* leading - */
|
|
@@ -158,7 +153,7 @@ export default class CraiIndex {
|
|
|
158
153
|
seqId: number,
|
|
159
154
|
queryStart: number,
|
|
160
155
|
queryEnd: number,
|
|
161
|
-
) {
|
|
156
|
+
): Promise<Slice[]> {
|
|
162
157
|
const seqEntries = (await this.getIndex())[seqId]
|
|
163
158
|
if (!seqEntries) {
|
|
164
159
|
return []
|
|
@@ -175,10 +170,10 @@ export default class CraiIndex {
|
|
|
175
170
|
} // entry is behind query
|
|
176
171
|
return 0 // entry overlaps query
|
|
177
172
|
}
|
|
178
|
-
const bins = []
|
|
179
|
-
for (
|
|
180
|
-
if (compare(
|
|
181
|
-
bins.push(
|
|
173
|
+
const bins = [] as Slice[]
|
|
174
|
+
for (const entry of seqEntries) {
|
|
175
|
+
if (compare(entry) === 0) {
|
|
176
|
+
bins.push(entry)
|
|
182
177
|
}
|
|
183
178
|
}
|
|
184
179
|
return bins
|
|
@@ -2,19 +2,19 @@ import CramSlice from '../slice'
|
|
|
2
2
|
import { CramFileBlock } from '../file'
|
|
3
3
|
import { DataType } from './dataSeriesTypes'
|
|
4
4
|
|
|
5
|
-
export
|
|
5
|
+
export interface DataTypeMapping {
|
|
6
6
|
byte: number
|
|
7
7
|
int: number
|
|
8
8
|
long: number
|
|
9
9
|
byteArray: Uint8Array
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
export
|
|
12
|
+
export interface Cursor {
|
|
13
13
|
bitPosition: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
|
|
14
14
|
bytePosition: number
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export
|
|
17
|
+
export interface Cursors {
|
|
18
18
|
lastAlignmentStart: number
|
|
19
19
|
coreBlock: Cursor
|
|
20
20
|
externalBlocks: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/unbound-method */
|
|
1
2
|
import { CramMalformedError } from '../../errors'
|
|
2
3
|
import CramCodec, { Cursor, Cursors } from './_base'
|
|
3
4
|
import { getBits } from './getBits'
|
|
@@ -12,7 +13,11 @@ function numberOfSetBits(ii: number) {
|
|
|
12
13
|
return (((i + (i >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
interface Code {
|
|
17
|
+
bitLength: number
|
|
18
|
+
value: number
|
|
19
|
+
bitCode: number
|
|
20
|
+
}
|
|
16
21
|
|
|
17
22
|
export default class HuffmanIntCodec extends CramCodec<
|
|
18
23
|
'byte' | 'int',
|
|
@@ -20,7 +25,6 @@ export default class HuffmanIntCodec extends CramCodec<
|
|
|
20
25
|
> {
|
|
21
26
|
private codes: Record<number, Code> = {}
|
|
22
27
|
private codeBook: Record<number, number[]> = {}
|
|
23
|
-
private sortedByValue: Code[] = []
|
|
24
28
|
private sortedCodes: Code[] = []
|
|
25
29
|
private sortedValuesByBitCode: number[] = []
|
|
26
30
|
private sortedBitCodes: number[] = []
|
|
@@ -50,7 +54,7 @@ export default class HuffmanIntCodec extends CramCodec<
|
|
|
50
54
|
|
|
51
55
|
buildCodeBook() {
|
|
52
56
|
// parse the parameters together into a `codes` data structure
|
|
53
|
-
let codes
|
|
57
|
+
let codes = new Array<{ symbol: number; bitLength: number }>(
|
|
54
58
|
this.parameters.numCodes,
|
|
55
59
|
)
|
|
56
60
|
for (let i = 0; i < this.parameters.numCodes; i += 1) {
|
|
@@ -105,11 +109,6 @@ export default class HuffmanIntCodec extends CramCodec<
|
|
|
105
109
|
(a, b) => a.bitLength - b.bitLength || a.bitCode - b.bitCode,
|
|
106
110
|
)
|
|
107
111
|
|
|
108
|
-
// this.sortedValues = this.parameters.values.sort((a,b) => a-b)
|
|
109
|
-
this.sortedByValue = Object.values(this.codes).sort(
|
|
110
|
-
(a, b) => a.value - b.value,
|
|
111
|
-
)
|
|
112
|
-
|
|
113
112
|
this.sortedValuesByBitCode = this.sortedCodes.map(c => c.value)
|
|
114
113
|
this.sortedBitCodes = this.sortedCodes.map(c => c.bitCode)
|
|
115
114
|
this.sortedBitLengthsByBitCode = this.sortedCodes.map(c => c.bitLength)
|
package/src/cramFile/encoding.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface NullEncoding {
|
|
2
2
|
codecId: 0
|
|
3
3
|
parametersBytes: number
|
|
4
4
|
parameters: Record<string, never>
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
export
|
|
7
|
+
export interface ExternalCramEncoding {
|
|
8
8
|
codecId: 1
|
|
9
9
|
parametersBytes: number
|
|
10
10
|
parameters: {
|
|
@@ -12,7 +12,7 @@ export type ExternalCramEncoding = {
|
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
export
|
|
15
|
+
export interface GolombEncoding {
|
|
16
16
|
codecId: 2
|
|
17
17
|
parametersBytes: number
|
|
18
18
|
parameters: {
|
|
@@ -21,7 +21,7 @@ export type GolombEncoding = {
|
|
|
21
21
|
}
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export
|
|
24
|
+
export interface HuffmanEncoding {
|
|
25
25
|
codecId: 3
|
|
26
26
|
parametersBytes: number
|
|
27
27
|
parameters: {
|
|
@@ -32,7 +32,7 @@ export type HuffmanEncoding = {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
export
|
|
35
|
+
export interface ByteArrayLengthEncoding {
|
|
36
36
|
codecId: 4
|
|
37
37
|
parametersBytes: number
|
|
38
38
|
parameters: {
|
|
@@ -41,7 +41,7 @@ export type ByteArrayLengthEncoding = {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export
|
|
44
|
+
export interface ByteArrayStopCramEncoding {
|
|
45
45
|
codecId: 5
|
|
46
46
|
parametersBytes: number
|
|
47
47
|
parameters: {
|
|
@@ -50,7 +50,7 @@ export type ByteArrayStopCramEncoding = {
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export
|
|
53
|
+
export interface BetaEncoding {
|
|
54
54
|
codecId: 6
|
|
55
55
|
parametersBytes: number
|
|
56
56
|
parameters: {
|
|
@@ -59,7 +59,7 @@ export type BetaEncoding = {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
export
|
|
62
|
+
export interface SubexpEncoding {
|
|
63
63
|
codecId: 7
|
|
64
64
|
parametersBytes: number
|
|
65
65
|
parameters: {
|
|
@@ -68,7 +68,7 @@ export type SubexpEncoding = {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
export
|
|
71
|
+
export interface GolombRiceEncoding {
|
|
72
72
|
codecId: 8
|
|
73
73
|
parametersBytes: number
|
|
74
74
|
parameters: {
|
|
@@ -77,7 +77,7 @@ export type GolombRiceEncoding = {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
export
|
|
80
|
+
export interface GammaEncoding {
|
|
81
81
|
codecId: 9
|
|
82
82
|
parametersBytes: number
|
|
83
83
|
parameters: {
|
package/src/cramFile/file.ts
CHANGED
|
@@ -51,7 +51,7 @@ function getEndianness() {
|
|
|
51
51
|
// | { path: string; url?: undefined; filehandle?: undefined }
|
|
52
52
|
// | { filehandle: Filehandle; url?: undefined; path?: undefined }
|
|
53
53
|
|
|
54
|
-
export
|
|
54
|
+
export interface CramFileSource {
|
|
55
55
|
filehandle?: Filehandle
|
|
56
56
|
url?: string
|
|
57
57
|
path?: string
|
|
@@ -64,9 +64,9 @@ export type SeqFetch = (
|
|
|
64
64
|
) => Promise<string>
|
|
65
65
|
|
|
66
66
|
export type CramFileArgs = CramFileSource & {
|
|
67
|
-
checkSequenceMD5
|
|
67
|
+
checkSequenceMD5?: boolean
|
|
68
68
|
cacheSize?: number
|
|
69
|
-
seqFetch
|
|
69
|
+
seqFetch?: SeqFetch
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export type CramFileBlock = BlockHeader & {
|
|
@@ -80,9 +80,9 @@ export type CramFileBlock = BlockHeader & {
|
|
|
80
80
|
export default class CramFile {
|
|
81
81
|
private file: Filehandle
|
|
82
82
|
public validateChecksums: boolean
|
|
83
|
-
public fetchReferenceSequenceCallback
|
|
83
|
+
public fetchReferenceSequenceCallback?: SeqFetch
|
|
84
84
|
public options: {
|
|
85
|
-
checkSequenceMD5
|
|
85
|
+
checkSequenceMD5?: boolean
|
|
86
86
|
cacheSize: number
|
|
87
87
|
}
|
|
88
88
|
public featureCache: QuickLRU<string, Promise<CramRecord[]>>
|
package/src/cramFile/index.ts
CHANGED
package/src/cramFile/record.ts
CHANGED
|
@@ -2,13 +2,13 @@ import Constants from './constants'
|
|
|
2
2
|
import CramContainerCompressionScheme from './container/compressionScheme'
|
|
3
3
|
import decodeRecord from './slice/decodeRecord'
|
|
4
4
|
|
|
5
|
-
export
|
|
5
|
+
export interface RefRegion {
|
|
6
6
|
start: number
|
|
7
7
|
end: number
|
|
8
8
|
seq: string
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export
|
|
11
|
+
export interface ReadFeature {
|
|
12
12
|
code: string
|
|
13
13
|
pos: number
|
|
14
14
|
refPos: number
|
|
@@ -36,7 +36,7 @@ function decodeReadSequence(
|
|
|
36
36
|
|
|
37
37
|
if (!cramRecord.readFeatures) {
|
|
38
38
|
return refRegion.seq
|
|
39
|
-
.
|
|
39
|
+
.slice(regionSeqOffset, regionSeqOffset + (cramRecord.lengthOnRef || 0))
|
|
40
40
|
.toUpperCase()
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -91,18 +91,21 @@ function decodeReadSequence(
|
|
|
91
91
|
}
|
|
92
92
|
} else if (currentReadFeature < cramRecord.readFeatures.length) {
|
|
93
93
|
// put down a chunk of sequence up to the next read feature
|
|
94
|
-
const chunk = refRegion.seq.
|
|
94
|
+
const chunk = refRegion.seq.slice(
|
|
95
95
|
regionPos,
|
|
96
|
-
|
|
96
|
+
regionPos +
|
|
97
|
+
cramRecord.readFeatures[currentReadFeature].pos -
|
|
98
|
+
bases.length -
|
|
99
|
+
1,
|
|
97
100
|
)
|
|
98
101
|
bases += chunk
|
|
99
102
|
regionPos += chunk.length
|
|
100
103
|
}
|
|
101
104
|
} else {
|
|
102
105
|
// put down a chunk of reference up to the full read length
|
|
103
|
-
const chunk = refRegion.seq.
|
|
106
|
+
const chunk = refRegion.seq.slice(
|
|
104
107
|
regionPos,
|
|
105
|
-
cramRecord.readLength - bases.length,
|
|
108
|
+
regionPos + cramRecord.readLength - bases.length,
|
|
106
109
|
)
|
|
107
110
|
bases += chunk
|
|
108
111
|
regionPos += chunk.length
|
|
@@ -152,7 +155,7 @@ function decodeBaseSubstitution(
|
|
|
152
155
|
}
|
|
153
156
|
}
|
|
154
157
|
|
|
155
|
-
export
|
|
158
|
+
export interface MateRecord {
|
|
156
159
|
readName?: string
|
|
157
160
|
sequenceId: number
|
|
158
161
|
alignmentStart: number
|
|
@@ -208,7 +211,7 @@ type FlagsEncoder<Type> = {
|
|
|
208
211
|
}
|
|
209
212
|
|
|
210
213
|
function makeFlagsHelper<T>(
|
|
211
|
-
x:
|
|
214
|
+
x: readonly (readonly [number, T])[],
|
|
212
215
|
): FlagsDecoder<T> & FlagsEncoder<T> {
|
|
213
216
|
const r: any = {}
|
|
214
217
|
for (const [code, name] of x) {
|
|
@@ -494,7 +497,7 @@ export default class CramRecord {
|
|
|
494
497
|
toJSON() {
|
|
495
498
|
const data: any = {}
|
|
496
499
|
Object.keys(this).forEach(k => {
|
|
497
|
-
if (k.
|
|
500
|
+
if (k.startsWith('_')) {
|
|
498
501
|
return
|
|
499
502
|
}
|
|
500
503
|
data[k] = (this as any)[k]
|
|
@@ -85,7 +85,7 @@ const cramTagDictionary = new Parser().itf8('size').buffer('ents', {
|
|
|
85
85
|
const str = buffer.toString('utf8', stringStart, stringEnd)
|
|
86
86
|
const tags = []
|
|
87
87
|
for (let i = 0; i < str.length; i += 3) {
|
|
88
|
-
tags.push(str.
|
|
88
|
+
tags.push(str.slice(i, i + 3))
|
|
89
89
|
}
|
|
90
90
|
return tags
|
|
91
91
|
}
|
|
@@ -113,7 +113,7 @@ const parseByteAsBool = new Parser().uint8(null, {
|
|
|
113
113
|
formatter: /* istanbul ignore next */ val => !!val,
|
|
114
114
|
})
|
|
115
115
|
|
|
116
|
-
export
|
|
116
|
+
export interface CramPreservationMap {
|
|
117
117
|
MI: boolean
|
|
118
118
|
UI: boolean
|
|
119
119
|
PI: boolean
|
|
@@ -155,9 +155,8 @@ const cramPreservationMap = new Parser()
|
|
|
155
155
|
|
|
156
156
|
/* istanbul ignore next */
|
|
157
157
|
function formatMap<T>(data: { ents: { key: string; value: T }[] }) {
|
|
158
|
-
const map:
|
|
159
|
-
for (
|
|
160
|
-
const { key, value } = data.ents[i]
|
|
158
|
+
const map: Record<string, T> = {}
|
|
159
|
+
for (const { key, value } of data.ents) {
|
|
161
160
|
if (map[key]) {
|
|
162
161
|
console.warn(`duplicate key ${key} in map`)
|
|
163
162
|
}
|
|
@@ -172,7 +171,7 @@ const unversionedParsers = {
|
|
|
172
171
|
cramBlockCrc32,
|
|
173
172
|
}
|
|
174
173
|
|
|
175
|
-
export
|
|
174
|
+
export interface MappedSliceHeader {
|
|
176
175
|
refSeqId: number
|
|
177
176
|
refSeqStart: number
|
|
178
177
|
refSeqSpan: number
|
|
@@ -185,7 +184,7 @@ export type MappedSliceHeader = {
|
|
|
185
184
|
md5: TupleOf<number, 16>
|
|
186
185
|
}
|
|
187
186
|
|
|
188
|
-
export
|
|
187
|
+
export interface UnmappedSliceHeader {
|
|
189
188
|
numRecords: number
|
|
190
189
|
recordCounter: number
|
|
191
190
|
numBlocks: number
|
|
@@ -279,7 +278,7 @@ const versionedParsers = {
|
|
|
279
278
|
return { parser, maxLength: maxLengthFunc }
|
|
280
279
|
},
|
|
281
280
|
|
|
282
|
-
cramEncoding(
|
|
281
|
+
cramEncoding(_majorVersion: number) {
|
|
283
282
|
const parser = new Parser()
|
|
284
283
|
.namely('cramEncoding')
|
|
285
284
|
.itf8('codecId')
|
|
@@ -425,7 +424,7 @@ export type CompressionMethod =
|
|
|
425
424
|
| 'fqzcomp'
|
|
426
425
|
| 'tok3'
|
|
427
426
|
|
|
428
|
-
export
|
|
427
|
+
export interface BlockHeader {
|
|
429
428
|
compressionMethod: CompressionMethod
|
|
430
429
|
contentType:
|
|
431
430
|
| 'FILE_HEADER'
|
|
@@ -224,23 +224,21 @@ export default function decodeRecord(
|
|
|
224
224
|
majorVersion: number,
|
|
225
225
|
recordNumber: number,
|
|
226
226
|
) {
|
|
227
|
-
let flags = decodeDataSeries('BF')
|
|
227
|
+
let flags = decodeDataSeries('BF')
|
|
228
228
|
|
|
229
229
|
// note: the C data type of compressionFlags is byte in cram v1
|
|
230
230
|
// and int32 in cram v2+, but that does not matter for us here
|
|
231
231
|
// in javascript land.
|
|
232
|
-
const cramFlags = decodeDataSeries('CF')
|
|
232
|
+
const cramFlags = decodeDataSeries('CF')
|
|
233
233
|
|
|
234
234
|
if (!isMappedSliceHeader(sliceHeader.parsedContent)) {
|
|
235
|
-
throw new Error()
|
|
235
|
+
throw new Error('slice header not mapped')
|
|
236
236
|
}
|
|
237
237
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
sequenceId = sliceHeader.parsedContent.refSeqId
|
|
243
|
-
}
|
|
238
|
+
const sequenceId =
|
|
239
|
+
majorVersion > 1 && sliceHeader.parsedContent.refSeqId === -2
|
|
240
|
+
? decodeDataSeries('RI')
|
|
241
|
+
: sliceHeader.parsedContent.refSeqId
|
|
244
242
|
|
|
245
243
|
const readLength = decodeDataSeries('RL')
|
|
246
244
|
// if APDelta, will calculate the true start in a second pass
|
|
@@ -263,14 +261,14 @@ export default function decodeRecord(
|
|
|
263
261
|
if (CramFlagsDecoder.isDetached(cramFlags)) {
|
|
264
262
|
// note: the MF is a byte in 1.0, int32 in 2+, but once again this doesn't matter for javascript
|
|
265
263
|
// const mate: any = {}
|
|
266
|
-
const mateFlags = decodeDataSeries('MF')
|
|
264
|
+
const mateFlags = decodeDataSeries('MF')
|
|
267
265
|
let mateReadName
|
|
268
266
|
if (!compressionScheme.readNamesIncluded) {
|
|
269
267
|
mateReadName = readNullTerminatedString(decodeDataSeries('RN'))
|
|
270
268
|
readName = mateReadName
|
|
271
269
|
}
|
|
272
|
-
const mateSequenceId = decodeDataSeries('NS')
|
|
273
|
-
const mateAlignmentStart = decodeDataSeries('NP')
|
|
270
|
+
const mateSequenceId = decodeDataSeries('NS')
|
|
271
|
+
const mateAlignmentStart = decodeDataSeries('NP')
|
|
274
272
|
if (mateFlags || mateSequenceId > -1) {
|
|
275
273
|
mateToUse = {
|
|
276
274
|
mateFlags,
|
|
@@ -293,7 +291,7 @@ export default function decodeRecord(
|
|
|
293
291
|
|
|
294
292
|
// detachedCount++
|
|
295
293
|
} else if (CramFlagsDecoder.isWithMateDownstream(cramFlags)) {
|
|
296
|
-
mateRecordNumber =
|
|
294
|
+
mateRecordNumber = decodeDataSeries('NF') + recordNumber + 1
|
|
297
295
|
}
|
|
298
296
|
|
|
299
297
|
// TODO: the aux tag parsing will have to be refactored if we want to support
|
|
@@ -311,8 +309,8 @@ export default function decodeRecord(
|
|
|
311
309
|
|
|
312
310
|
for (let i = 0; i < ntags; i += 1) {
|
|
313
311
|
const tagId = TN[i]
|
|
314
|
-
const tagName = tagId.
|
|
315
|
-
const tagType = tagId.
|
|
312
|
+
const tagName = tagId.slice(0, 2)
|
|
313
|
+
const tagType = tagId.slice(2, 3)
|
|
316
314
|
|
|
317
315
|
const tagCodec = compressionScheme.getCodecForTag(tagId)
|
|
318
316
|
if (!tagCodec) {
|
|
@@ -336,7 +334,7 @@ export default function decodeRecord(
|
|
|
336
334
|
let readBases = undefined
|
|
337
335
|
if (!BamFlagsDecoder.isSegmentUnmapped(flags)) {
|
|
338
336
|
// reading read features
|
|
339
|
-
const readFeatureCount = decodeDataSeries('FN')
|
|
337
|
+
const readFeatureCount = decodeDataSeries('FN')
|
|
340
338
|
if (readFeatureCount) {
|
|
341
339
|
readFeatures = decodeReadFeatures(
|
|
342
340
|
alignmentStart,
|
|
@@ -370,7 +368,7 @@ export default function decodeRecord(
|
|
|
370
368
|
}
|
|
371
369
|
|
|
372
370
|
// mapping quality
|
|
373
|
-
mappingQuality = decodeDataSeries('MQ')
|
|
371
|
+
mappingQuality = decodeDataSeries('MQ')
|
|
374
372
|
if (CramFlagsDecoder.isPreservingQualityScores(cramFlags)) {
|
|
375
373
|
qualityScores = new Array(readLength)
|
|
376
374
|
for (let i = 0; i < qualityScores.length; i++) {
|