@gmod/cram 2.0.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/README.md +0 -4
- package/dist/craiIndex.js +1 -1
- package/dist/craiIndex.js.map +1 -1
- package/dist/cram-bundle.js +1 -1
- package/dist/cram-bundle.js.LICENSE.txt +0 -2
- package/dist/cramFile/codecs/byteArrayLength.js +1 -1
- package/dist/cramFile/codecs/byteArrayLength.js.map +1 -1
- package/dist/cramFile/codecs/byteArrayStop.d.ts +0 -1
- package/dist/cramFile/codecs/external.js +1 -1
- package/dist/cramFile/codecs/external.js.map +1 -1
- package/dist/cramFile/codecs/getBits.d.ts +0 -1
- package/dist/cramFile/codecs/getBits.js +2 -2
- package/dist/cramFile/codecs/getBits.js.map +1 -1
- package/dist/cramFile/codecs/huffman.js +2 -1
- package/dist/cramFile/codecs/huffman.js.map +1 -1
- package/dist/cramFile/codecs/index.js +1 -2
- package/dist/cramFile/codecs/index.js.map +1 -1
- package/dist/cramFile/container/compressionScheme.d.ts +0 -3
- package/dist/cramFile/container/compressionScheme.js +0 -4
- package/dist/cramFile/container/compressionScheme.js.map +1 -1
- package/dist/cramFile/container/index.d.ts +57 -5
- package/dist/cramFile/container/index.js +15 -9
- package/dist/cramFile/container/index.js.map +1 -1
- package/dist/cramFile/file.d.ts +24 -61
- package/dist/cramFile/file.js +23 -28
- package/dist/cramFile/file.js.map +1 -1
- package/dist/cramFile/record.d.ts +1 -1
- package/dist/cramFile/sectionParsers.d.ts +195 -49
- package/dist/cramFile/sectionParsers.js +622 -304
- package/dist/cramFile/sectionParsers.js.map +1 -1
- package/dist/cramFile/slice/decodeRecord.js +1 -1
- package/dist/cramFile/slice/decodeRecord.js.map +1 -1
- package/dist/cramFile/slice/index.d.ts +23 -1
- package/dist/cramFile/slice/index.js +9 -6
- package/dist/cramFile/slice/index.js.map +1 -1
- package/dist/cramFile/util.d.ts +6 -6
- package/dist/cramFile/util.js +93 -12
- package/dist/cramFile/util.js.map +1 -1
- package/dist/indexedCramFile.d.ts +0 -3
- package/dist/indexedCramFile.js +4 -16
- package/dist/indexedCramFile.js.map +1 -1
- package/dist/io/index.d.ts +1 -3
- package/dist/io/index.js +3 -16
- package/dist/io/index.js.map +1 -1
- package/dist/rans/d04.js +1 -1
- package/dist/rans/d04.js.map +1 -1
- package/dist/rans/d14.js +1 -1
- package/dist/rans/d14.js.map +1 -1
- package/dist/rans/frequencies.js +2 -3
- package/dist/rans/frequencies.js.map +1 -1
- package/dist/rans/index.js +1 -1
- package/dist/rans/index.js.map +1 -1
- package/dist/sam.js +1 -2
- package/dist/sam.js.map +1 -1
- package/dist/typescript.d.ts +0 -1
- package/dist/typescript.js +0 -8
- package/dist/typescript.js.map +1 -1
- package/dist/unzip-pako.d.ts +0 -1
- package/dist/unzip-pako.js +1 -2
- package/dist/unzip-pako.js.map +1 -1
- package/dist/unzip.d.ts +0 -1
- package/esm/craiIndex.js +1 -1
- package/esm/craiIndex.js.map +1 -1
- package/esm/cramFile/codecs/byteArrayLength.js +1 -1
- package/esm/cramFile/codecs/byteArrayLength.js.map +1 -1
- package/esm/cramFile/codecs/byteArrayStop.d.ts +0 -1
- package/esm/cramFile/codecs/external.js +1 -1
- package/esm/cramFile/codecs/external.js.map +1 -1
- package/esm/cramFile/codecs/getBits.d.ts +0 -1
- package/esm/cramFile/codecs/huffman.js +2 -1
- package/esm/cramFile/codecs/huffman.js.map +1 -1
- package/esm/cramFile/container/compressionScheme.d.ts +0 -3
- package/esm/cramFile/container/compressionScheme.js +0 -4
- package/esm/cramFile/container/compressionScheme.js.map +1 -1
- package/esm/cramFile/container/index.d.ts +57 -5
- package/esm/cramFile/container/index.js +15 -9
- package/esm/cramFile/container/index.js.map +1 -1
- package/esm/cramFile/file.d.ts +24 -61
- package/esm/cramFile/file.js +22 -25
- package/esm/cramFile/file.js.map +1 -1
- package/esm/cramFile/record.d.ts +1 -1
- package/esm/cramFile/sectionParsers.d.ts +195 -49
- package/esm/cramFile/sectionParsers.js +620 -303
- package/esm/cramFile/sectionParsers.js.map +1 -1
- package/esm/cramFile/slice/index.d.ts +23 -1
- package/esm/cramFile/slice/index.js +10 -7
- package/esm/cramFile/slice/index.js.map +1 -1
- package/esm/cramFile/util.d.ts +6 -6
- package/esm/cramFile/util.js +87 -6
- package/esm/cramFile/util.js.map +1 -1
- package/esm/indexedCramFile.d.ts +0 -3
- package/esm/indexedCramFile.js +3 -15
- package/esm/indexedCramFile.js.map +1 -1
- package/esm/io/index.d.ts +1 -3
- package/esm/io/index.js +2 -11
- package/esm/io/index.js.map +1 -1
- package/esm/typescript.d.ts +0 -1
- package/esm/typescript.js +1 -6
- package/esm/typescript.js.map +1 -1
- package/esm/unzip-pako.d.ts +0 -1
- package/esm/unzip.d.ts +0 -1
- package/package.json +9 -15
- package/src/craiIndex.ts +1 -1
- package/src/cramFile/codecs/byteArrayLength.ts +1 -2
- package/src/cramFile/codecs/external.ts +1 -1
- package/src/cramFile/codecs/huffman.ts +2 -1
- package/src/cramFile/container/compressionScheme.ts +1 -8
- package/src/cramFile/container/index.ts +21 -10
- package/src/cramFile/file.ts +28 -43
- package/src/cramFile/record.ts +1 -1
- package/src/cramFile/sectionParsers.ts +668 -390
- package/src/cramFile/slice/index.ts +11 -5
- package/src/cramFile/util.ts +90 -91
- package/src/indexedCramFile.ts +3 -25
- package/src/io/index.ts +2 -12
- package/src/typescript.ts +0 -7
- package/src/typings/binary-parser.d.ts +0 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gmod/cram",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "read CRAM files with pure Javascript",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "GMOD/cram-js",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"scripts": {
|
|
24
24
|
"test": "jest",
|
|
25
|
-
"lint": "eslint src test",
|
|
25
|
+
"lint": "eslint --report-unused-disable-directives --max-warnings 0 src test",
|
|
26
26
|
"docs": "documentation readme --shallow src/indexedCramFile.ts --section=IndexedCramFile; documentation readme --shallow src/cramFile/file.ts --section=CramFile; documentation readme --shallow src/craiIndex.ts --section=CraiIndex; documentation readme --shallow errors.ts '--section=Exception Classes'; documentation readme --shallow src/cramFile/file.ts --section=CramFile; documentation readme --shallow src/cramFile/record.ts --section=CramRecord",
|
|
27
27
|
"prebuild": "npm run clean",
|
|
28
28
|
"clean": "rimraf dist esm",
|
|
@@ -42,9 +42,8 @@
|
|
|
42
42
|
"biojs"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@gmod/
|
|
45
|
+
"@gmod/abortable-promise-cache": "^2.0.0",
|
|
46
46
|
"@jkbonfield/htscodecs": "^0.5.1",
|
|
47
|
-
"abortable-promise-cache": "^1.2.0",
|
|
48
47
|
"buffer-crc32": "^1.0.0",
|
|
49
48
|
"bzip2": "^0.1.1",
|
|
50
49
|
"long": "^4.0.0",
|
|
@@ -54,30 +53,25 @@
|
|
|
54
53
|
"xz-decompress": "^0.2.1"
|
|
55
54
|
},
|
|
56
55
|
"devDependencies": {
|
|
57
|
-
"@babel/plugin-transform-modules-commonjs": "^7.18.2",
|
|
58
|
-
"@babel/preset-typescript": "^7.17.12",
|
|
59
56
|
"@gmod/indexedfasta": "^2.1.0",
|
|
60
57
|
"@types/jest": "^29.5.12",
|
|
61
|
-
"@types/long": "^4.0.
|
|
58
|
+
"@types/long": "^4.0.0",
|
|
62
59
|
"@types/md5": "^2.3.2",
|
|
63
60
|
"@types/pako": "^1.0.3",
|
|
64
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
65
|
-
"@typescript-eslint/parser": "^
|
|
61
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
62
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
66
63
|
"buffer": "^6.0.3",
|
|
67
64
|
"documentation": "^14.0.3",
|
|
68
|
-
"eslint": "^8.
|
|
65
|
+
"eslint": "^9.8.0",
|
|
69
66
|
"eslint-config-prettier": "^9.0.0",
|
|
70
|
-
"eslint-plugin-import": "^2.25.4",
|
|
71
67
|
"eslint-plugin-prettier": "^5.1.3",
|
|
72
|
-
"eslint-plugin-unicorn": "^
|
|
73
|
-
"glob": "^10.3.1",
|
|
68
|
+
"eslint-plugin-unicorn": "^55.0.0",
|
|
74
69
|
"jest": "^29.3.1",
|
|
75
70
|
"mock-fs": "^5.2.0",
|
|
76
71
|
"prettier": "^3.2.5",
|
|
77
|
-
"rimraf": "^
|
|
72
|
+
"rimraf": "^6.0.1",
|
|
78
73
|
"ts-jest": "^29.1.2",
|
|
79
74
|
"typescript": "^5.0.3",
|
|
80
|
-
"url": "^0.11.0",
|
|
81
75
|
"webpack": "^5.90.3",
|
|
82
76
|
"webpack-cli": "^5.0.1"
|
|
83
77
|
},
|
package/src/craiIndex.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { tinyMemoize } from '../util'
|
|
2
|
-
|
|
3
1
|
import CramCodec, { Cursors } from './_base'
|
|
4
2
|
import { ByteArrayLengthEncoding, CramEncoding } from '../encoding'
|
|
5
3
|
import CramSlice from '../slice'
|
|
6
4
|
import { CramFileBlock } from '../file'
|
|
7
5
|
import { DataType } from './dataSeriesTypes'
|
|
6
|
+
import { tinyMemoize } from '../util'
|
|
8
7
|
|
|
9
8
|
type CramCodecFactory = <TData extends DataType = DataType>(
|
|
10
9
|
encodingData: CramEncoding,
|
|
@@ -42,7 +42,7 @@ export default class ExternalCodec extends CramCodec<
|
|
|
42
42
|
const contentBlock = blocksByContentId[blockContentId]
|
|
43
43
|
if (!contentBlock) {
|
|
44
44
|
throw new CramMalformedError(
|
|
45
|
-
`no block found with content ID ${blockContentId}`,
|
|
45
|
+
`no block found with content ID ${blockContentId}}`,
|
|
46
46
|
)
|
|
47
47
|
}
|
|
48
48
|
const cursor = cursors.externalBlocks.getCursor(blockContentId)
|
|
@@ -46,7 +46,8 @@ export default class HuffmanIntCodec extends CramCodec<
|
|
|
46
46
|
this.buildCodes()
|
|
47
47
|
this.buildCaches()
|
|
48
48
|
|
|
49
|
-
// if this is a degenerate zero-length huffman code, special-case the
|
|
49
|
+
// if this is a degenerate zero-length huffman code, special-case the
|
|
50
|
+
// decoding
|
|
50
51
|
if (this.sortedCodes[0].bitLength === 0) {
|
|
51
52
|
this._decode = this._decodeZeroLengthCode
|
|
52
53
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { instantiateCodec } from '../codecs'
|
|
2
2
|
import CramCodec from '../codecs/_base'
|
|
3
|
-
import { CramCompressionHeader
|
|
3
|
+
import { CramCompressionHeader } from '../sectionParsers'
|
|
4
4
|
import { CramEncoding } from '../encoding'
|
|
5
5
|
import { CramMalformedError } from '../../errors'
|
|
6
6
|
import {
|
|
@@ -95,12 +95,8 @@ export default class CramContainerCompressionScheme {
|
|
|
95
95
|
public tagCodecCache: Record<string, CramCodec> = {}
|
|
96
96
|
public tagEncoding: Record<string, CramEncoding> = {}
|
|
97
97
|
public dataSeriesEncoding: DataSeriesEncodingMap
|
|
98
|
-
private preservation: CramPreservationMap
|
|
99
|
-
private _endPosition: number
|
|
100
|
-
private _size: number
|
|
101
98
|
|
|
102
99
|
constructor(content: CramCompressionHeader) {
|
|
103
|
-
// Object.assign(this, content)
|
|
104
100
|
// interpret some of the preservation map tags for convenient use
|
|
105
101
|
this.readNamesIncluded = content.preservation.RN
|
|
106
102
|
this.APdelta = content.preservation.AP
|
|
@@ -109,9 +105,6 @@ export default class CramContainerCompressionScheme {
|
|
|
109
105
|
this.substitutionMatrix = parseSubstitutionMatrix(content.preservation.SM)
|
|
110
106
|
this.dataSeriesEncoding = content.dataSeriesEncoding
|
|
111
107
|
this.tagEncoding = content.tagEncoding
|
|
112
|
-
this.preservation = content.preservation
|
|
113
|
-
this._size = content._size
|
|
114
|
-
this._endPosition = content._endPosition
|
|
115
108
|
}
|
|
116
109
|
|
|
117
110
|
/**
|
|
@@ -4,6 +4,7 @@ import { itf8Size, parseItem, tinyMemoize } from '../util'
|
|
|
4
4
|
import CramSlice from '../slice'
|
|
5
5
|
import CramContainerCompressionScheme from './compressionScheme'
|
|
6
6
|
import CramFile from '../file'
|
|
7
|
+
import { getSectionParsers } from '../sectionParsers'
|
|
7
8
|
|
|
8
9
|
export default class CramContainer {
|
|
9
10
|
constructor(
|
|
@@ -11,20 +12,21 @@ export default class CramContainer {
|
|
|
11
12
|
public filePosition: number,
|
|
12
13
|
) {}
|
|
13
14
|
|
|
14
|
-
// memoize
|
|
15
15
|
getHeader() {
|
|
16
16
|
return this._readContainerHeader(this.filePosition)
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
// memoize
|
|
20
19
|
async getCompressionHeaderBlock() {
|
|
21
20
|
const containerHeader = await this.getHeader()
|
|
22
21
|
|
|
23
|
-
// if there are no records in the container, there will be no compression
|
|
24
|
-
|
|
22
|
+
// if there are no records in the container, there will be no compression
|
|
23
|
+
// header
|
|
24
|
+
if (!containerHeader?.numRecords) {
|
|
25
25
|
return null
|
|
26
26
|
}
|
|
27
|
-
const
|
|
27
|
+
const { majorVersion } = await this.file.getDefinition()
|
|
28
|
+
const sectionParsers = getSectionParsers(majorVersion)
|
|
29
|
+
|
|
28
30
|
const block = await this.getFirstBlock()
|
|
29
31
|
if (block === undefined) {
|
|
30
32
|
return undefined
|
|
@@ -34,6 +36,7 @@ export default class CramContainer {
|
|
|
34
36
|
`invalid content type ${block.contentType} in what is supposed to be the compression header block`,
|
|
35
37
|
)
|
|
36
38
|
}
|
|
39
|
+
|
|
37
40
|
const content = parseItem(
|
|
38
41
|
block.content,
|
|
39
42
|
sectionParsers.cramCompressionHeader.parser,
|
|
@@ -48,16 +51,20 @@ export default class CramContainer {
|
|
|
48
51
|
|
|
49
52
|
async getFirstBlock() {
|
|
50
53
|
const containerHeader = await this.getHeader()
|
|
54
|
+
if (!containerHeader) {
|
|
55
|
+
return undefined
|
|
56
|
+
}
|
|
51
57
|
return this.file.readBlock(containerHeader._endPosition)
|
|
52
58
|
}
|
|
53
59
|
|
|
54
|
-
// parses the compression header data into a CramContainerCompressionScheme
|
|
55
|
-
//
|
|
60
|
+
// parses the compression header data into a CramContainerCompressionScheme
|
|
61
|
+
// object
|
|
56
62
|
async getCompressionScheme() {
|
|
57
63
|
const header = await this.getCompressionHeaderBlock()
|
|
58
64
|
if (!header) {
|
|
59
65
|
return undefined
|
|
60
66
|
}
|
|
67
|
+
|
|
61
68
|
return new CramContainerCompressionScheme(header.parsedContent)
|
|
62
69
|
}
|
|
63
70
|
|
|
@@ -68,11 +75,15 @@ export default class CramContainer {
|
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
async _readContainerHeader(position: number) {
|
|
71
|
-
const
|
|
78
|
+
const { majorVersion } = await this.file.getDefinition()
|
|
79
|
+
const sectionParsers = getSectionParsers(majorVersion)
|
|
72
80
|
const { cramContainerHeader1, cramContainerHeader2 } = sectionParsers
|
|
73
81
|
const { size: fileSize } = await this.file.stat()
|
|
74
82
|
|
|
75
83
|
if (position >= fileSize) {
|
|
84
|
+
console.warn(
|
|
85
|
+
`position:${position}>=fileSize:${fileSize} in cram container`,
|
|
86
|
+
)
|
|
76
87
|
return undefined
|
|
77
88
|
}
|
|
78
89
|
|
|
@@ -80,11 +91,11 @@ export default class CramContainer {
|
|
|
80
91
|
// how much to buffer until you read numLandmarks
|
|
81
92
|
const bytes1 = Buffer.allocUnsafe(cramContainerHeader1.maxLength)
|
|
82
93
|
await this.file.read(bytes1, 0, cramContainerHeader1.maxLength, position)
|
|
83
|
-
const header1 = parseItem(bytes1, cramContainerHeader1.parser)
|
|
94
|
+
const header1 = parseItem(bytes1, cramContainerHeader1.parser)
|
|
84
95
|
const numLandmarksSize = itf8Size(header1.numLandmarks)
|
|
85
96
|
if (position + header1.length >= fileSize) {
|
|
86
97
|
console.warn(
|
|
87
|
-
|
|
98
|
+
`container header at ${position} indicates that the container has length ${header1.length}, which extends beyond the length of the file. Skipping this container.`,
|
|
88
99
|
)
|
|
89
100
|
return undefined
|
|
90
101
|
}
|
package/src/cramFile/file.ts
CHANGED
|
@@ -2,7 +2,6 @@ import { unzip } from '../unzip'
|
|
|
2
2
|
import crc32 from 'buffer-crc32'
|
|
3
3
|
import QuickLRU from 'quick-lru'
|
|
4
4
|
import htscodecs from '@jkbonfield/htscodecs'
|
|
5
|
-
import { Parser } from '@gmod/binary-parser'
|
|
6
5
|
// @ts-expect-error
|
|
7
6
|
import bzip2 from 'bzip2'
|
|
8
7
|
import { XzReadableStream } from 'xz-decompress'
|
|
@@ -11,7 +10,7 @@ import ransuncompress from '../rans'
|
|
|
11
10
|
import {
|
|
12
11
|
BlockHeader,
|
|
13
12
|
CompressionMethod,
|
|
14
|
-
cramFileDefinition
|
|
13
|
+
cramFileDefinition,
|
|
15
14
|
getSectionParsers,
|
|
16
15
|
} from './sectionParsers'
|
|
17
16
|
|
|
@@ -32,25 +31,20 @@ function bufferToStream(buf: Buffer) {
|
|
|
32
31
|
})
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
//source:https://abdulapopoola.com/2019/01/20/check-endianness-with-javascript/
|
|
34
|
+
// source:https://abdulapopoola.com/2019/01/20/check-endianness-with-javascript/
|
|
36
35
|
function getEndianness() {
|
|
37
36
|
const uInt32 = new Uint32Array([0x11223344])
|
|
38
37
|
const uInt8 = new Uint8Array(uInt32.buffer)
|
|
39
38
|
|
|
40
39
|
if (uInt8[0] === 0x44) {
|
|
41
|
-
return 0 //little-endian
|
|
40
|
+
return 0 // little-endian
|
|
42
41
|
} else if (uInt8[0] === 0x11) {
|
|
43
|
-
return 1 //big-endian
|
|
42
|
+
return 1 // big-endian
|
|
44
43
|
} else {
|
|
45
|
-
return 2 //mixed-endian?
|
|
44
|
+
return 2 // mixed-endian?
|
|
46
45
|
}
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
// export type CramFileSource =
|
|
50
|
-
// | { url: string; path?: undefined; filehandle?: undefined }
|
|
51
|
-
// | { path: string; url?: undefined; filehandle?: undefined }
|
|
52
|
-
// | { filehandle: Filehandle; url?: undefined; path?: undefined }
|
|
53
|
-
|
|
54
48
|
export interface CramFileSource {
|
|
55
49
|
filehandle?: Filehandle
|
|
56
50
|
url?: string
|
|
@@ -110,15 +104,7 @@ export default class CramFile {
|
|
|
110
104
|
}
|
|
111
105
|
|
|
112
106
|
// can just read this object like a filehandle
|
|
113
|
-
read(
|
|
114
|
-
buffer: Buffer,
|
|
115
|
-
offset: number,
|
|
116
|
-
length: number,
|
|
117
|
-
position: number,
|
|
118
|
-
): Promise<{
|
|
119
|
-
bytesRead: number
|
|
120
|
-
buffer: Buffer
|
|
121
|
-
}> {
|
|
107
|
+
read(buffer: Buffer, offset: number, length: number, position: number) {
|
|
122
108
|
return this.file.read(buffer, offset, length, position)
|
|
123
109
|
}
|
|
124
110
|
|
|
@@ -129,10 +115,10 @@ export default class CramFile {
|
|
|
129
115
|
|
|
130
116
|
// memoized
|
|
131
117
|
async getDefinition() {
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
118
|
+
const { maxLength, parser } = cramFileDefinition()
|
|
119
|
+
const headbytes = Buffer.allocUnsafe(maxLength)
|
|
120
|
+
await this.file.read(headbytes, 0, maxLength, 0)
|
|
121
|
+
const definition = parser(headbytes).value
|
|
136
122
|
if (definition.majorVersion !== 2 && definition.majorVersion !== 3) {
|
|
137
123
|
throw new CramUnimplementedError(
|
|
138
124
|
`CRAM version ${definition.majorVersion} not supported`,
|
|
@@ -169,21 +155,16 @@ export default class CramFile {
|
|
|
169
155
|
return this.header
|
|
170
156
|
}
|
|
171
157
|
|
|
172
|
-
// memoize
|
|
173
|
-
async getSectionParsers() {
|
|
174
|
-
const { majorVersion } = await this.getDefinition()
|
|
175
|
-
return getSectionParsers(majorVersion)
|
|
176
|
-
}
|
|
177
|
-
|
|
178
158
|
async getContainerById(containerNumber: number) {
|
|
179
|
-
const
|
|
159
|
+
const { majorVersion } = await this.getDefinition()
|
|
160
|
+
const sectionParsers = getSectionParsers(majorVersion)
|
|
180
161
|
let position = sectionParsers.cramFileDefinition.maxLength
|
|
181
162
|
const { size: fileSize } = await this.file.stat()
|
|
182
163
|
const { cramContainerHeader1 } = sectionParsers
|
|
183
164
|
|
|
184
165
|
// skip with a series of reads to the proper container
|
|
185
166
|
let currentContainer
|
|
186
|
-
for (let i = 0; i <= containerNumber; i
|
|
167
|
+
for (let i = 0; i <= containerNumber; i++) {
|
|
187
168
|
// if we are about to go off the end of the file
|
|
188
169
|
// and have not found that container, it does not exist
|
|
189
170
|
if (position + cramContainerHeader1.maxLength + 8 >= fileSize) {
|
|
@@ -197,13 +178,12 @@ export default class CramFile {
|
|
|
197
178
|
`container ${containerNumber} not found in file`,
|
|
198
179
|
)
|
|
199
180
|
}
|
|
200
|
-
// if this is the first container, read all the blocks in the
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
// in htslib
|
|
181
|
+
// if this is the first container, read all the blocks in the container
|
|
182
|
+
// to determine its length, because we cannot trust the container
|
|
183
|
+
// header's given length due to a bug somewhere in htslib
|
|
204
184
|
if (i === 0) {
|
|
205
185
|
position = currentHeader._endPosition
|
|
206
|
-
for (let j = 0; j < currentHeader.numBlocks; j
|
|
186
|
+
for (let j = 0; j < currentHeader.numBlocks; j++) {
|
|
207
187
|
const block = await this.readBlock(position)
|
|
208
188
|
if (block === undefined) {
|
|
209
189
|
return undefined
|
|
@@ -239,7 +219,8 @@ export default class CramFile {
|
|
|
239
219
|
* @returns {Promise[number]} the number of containers in the file
|
|
240
220
|
*/
|
|
241
221
|
async containerCount(): Promise<number | undefined> {
|
|
242
|
-
const
|
|
222
|
+
const { majorVersion } = await this.getDefinition()
|
|
223
|
+
const sectionParsers = getSectionParsers(majorVersion)
|
|
243
224
|
const { size: fileSize } = await this.file.stat()
|
|
244
225
|
const { cramContainerHeader1 } = sectionParsers
|
|
245
226
|
|
|
@@ -256,7 +237,7 @@ export default class CramFile {
|
|
|
256
237
|
// header's given length due to a bug somewhere in htslib
|
|
257
238
|
if (containerCount === 0) {
|
|
258
239
|
position = currentHeader._endPosition
|
|
259
|
-
for (let j = 0; j < currentHeader.numBlocks; j
|
|
240
|
+
for (let j = 0; j < currentHeader.numBlocks; j++) {
|
|
260
241
|
const block = await this.readBlock(position)
|
|
261
242
|
if (block === undefined) {
|
|
262
243
|
return undefined
|
|
@@ -278,7 +259,8 @@ export default class CramFile {
|
|
|
278
259
|
}
|
|
279
260
|
|
|
280
261
|
async readBlockHeader(position: number) {
|
|
281
|
-
const
|
|
262
|
+
const { majorVersion } = await this.getDefinition()
|
|
263
|
+
const sectionParsers = getSectionParsers(majorVersion)
|
|
282
264
|
const { cramBlockHeader } = sectionParsers
|
|
283
265
|
const { size: fileSize } = await this.file.stat()
|
|
284
266
|
|
|
@@ -292,7 +274,10 @@ export default class CramFile {
|
|
|
292
274
|
}
|
|
293
275
|
|
|
294
276
|
async _parseSection<T>(
|
|
295
|
-
section: {
|
|
277
|
+
section: {
|
|
278
|
+
maxLength: number
|
|
279
|
+
parser: (buffer: Buffer, offset: number) => { offset: number; value: T }
|
|
280
|
+
},
|
|
296
281
|
position: number,
|
|
297
282
|
size = section.maxLength,
|
|
298
283
|
preReadBuffer = undefined,
|
|
@@ -363,9 +348,9 @@ export default class CramFile {
|
|
|
363
348
|
}
|
|
364
349
|
}
|
|
365
350
|
|
|
366
|
-
async readBlock(position: number)
|
|
351
|
+
async readBlock(position: number) {
|
|
367
352
|
const { majorVersion } = await this.getDefinition()
|
|
368
|
-
const sectionParsers =
|
|
353
|
+
const sectionParsers = getSectionParsers(majorVersion)
|
|
369
354
|
const blockHeader = await this.readBlockHeader(position)
|
|
370
355
|
if (blockHeader === undefined) {
|
|
371
356
|
return undefined
|
package/src/cramFile/record.ts
CHANGED