@gmod/cram 1.6.3 → 1.7.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 +9 -0
- package/dist/craiIndex.d.ts +19 -12
- package/dist/craiIndex.js +63 -123
- package/dist/craiIndex.js.map +1 -1
- package/dist/cram-bundle.js +2 -17
- package/dist/cram-bundle.js.LICENSE.txt +17 -0
- package/dist/cramFile/codecs/_base.d.ts +26 -5
- package/dist/cramFile/codecs/_base.js +3 -39
- package/dist/cramFile/codecs/_base.js.map +1 -1
- package/dist/cramFile/codecs/beta.d.ts +7 -3
- package/dist/cramFile/codecs/beta.js +13 -31
- package/dist/cramFile/codecs/beta.js.map +1 -1
- package/dist/cramFile/codecs/byteArrayLength.d.ts +13 -7
- package/dist/cramFile/codecs/byteArrayLength.js +22 -41
- package/dist/cramFile/codecs/byteArrayLength.js.map +1 -1
- package/dist/cramFile/codecs/byteArrayStop.d.ts +9 -5
- package/dist/cramFile/codecs/byteArrayStop.js +25 -46
- package/dist/cramFile/codecs/byteArrayStop.js.map +1 -1
- package/dist/cramFile/codecs/dataSeriesTypes.d.ts +4 -0
- package/dist/cramFile/codecs/dataSeriesTypes.js +3 -0
- package/dist/cramFile/codecs/dataSeriesTypes.js.map +1 -0
- package/dist/cramFile/codecs/external.d.ts +10 -6
- package/dist/cramFile/codecs/external.js +26 -44
- package/dist/cramFile/codecs/external.js.map +1 -1
- package/dist/cramFile/codecs/gamma.d.ts +7 -3
- package/dist/cramFile/codecs/gamma.js +16 -34
- package/dist/cramFile/codecs/gamma.js.map +1 -1
- package/dist/cramFile/codecs/getBits.d.ts +7 -0
- package/dist/cramFile/codecs/getBits.js +26 -0
- package/dist/cramFile/codecs/getBits.js.map +1 -0
- package/dist/cramFile/codecs/huffman.d.ts +17 -13
- package/dist/cramFile/codecs/huffman.js +76 -85
- package/dist/cramFile/codecs/huffman.js.map +1 -1
- package/dist/cramFile/codecs/index.d.ts +4 -2
- package/dist/cramFile/codecs/index.js +12 -13
- package/dist/cramFile/codecs/index.js.map +1 -1
- package/dist/cramFile/codecs/subexp.d.ts +7 -3
- package/dist/cramFile/codecs/subexp.js +19 -36
- package/dist/cramFile/codecs/subexp.js.map +1 -1
- package/dist/cramFile/constants.d.ts +35 -35
- package/dist/cramFile/constants.js +1 -1
- package/dist/cramFile/constants.js.map +1 -1
- package/dist/cramFile/container/compressionScheme.d.ts +57 -11
- package/dist/cramFile/container/compressionScheme.js +37 -32
- package/dist/cramFile/container/compressionScheme.js.map +1 -1
- package/dist/cramFile/container/index.d.ts +23 -9
- package/dist/cramFile/container/index.js +74 -144
- package/dist/cramFile/container/index.js.map +1 -1
- package/dist/cramFile/encoding.d.ts +78 -0
- package/dist/cramFile/encoding.js +3 -0
- package/dist/cramFile/encoding.js.map +1 -0
- package/dist/cramFile/file.d.ts +91 -41
- package/dist/cramFile/file.js +234 -368
- package/dist/cramFile/file.js.map +1 -1
- package/dist/cramFile/filehandle.d.ts +2 -0
- package/dist/cramFile/filehandle.js +3 -0
- package/dist/cramFile/filehandle.js.map +1 -0
- package/dist/cramFile/index.d.ts +1 -1
- package/dist/cramFile/index.js +1 -1
- package/dist/cramFile/index.js.map +1 -1
- package/dist/cramFile/record.d.ts +61 -17
- package/dist/cramFile/record.js +153 -77
- package/dist/cramFile/record.js.map +1 -1
- package/dist/cramFile/sectionParsers.d.ts +99 -8
- package/dist/cramFile/sectionParsers.js +70 -80
- package/dist/cramFile/sectionParsers.js.map +1 -1
- package/dist/cramFile/slice/decodeRecord.d.ts +30 -2
- package/dist/cramFile/slice/decodeRecord.js +148 -118
- package/dist/cramFile/slice/decodeRecord.js.map +1 -1
- package/dist/cramFile/slice/index.d.ts +21 -14
- package/dist/cramFile/slice/index.js +286 -381
- package/dist/cramFile/slice/index.js.map +1 -1
- package/dist/cramFile/util.d.ts +11 -5
- package/dist/cramFile/util.js +19 -97
- package/dist/cramFile/util.js.map +1 -1
- package/dist/errors.d.ts +5 -10
- package/dist/errors.js +11 -62
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/indexedCramFile.d.ts +37 -12
- package/dist/indexedCramFile.js +114 -154
- package/dist/indexedCramFile.js.map +1 -1
- package/dist/io/index.d.ts +5 -5
- package/dist/io/index.js +9 -9
- package/dist/io/index.js.map +1 -1
- package/dist/rans/constants.js +3 -3
- package/dist/rans/constants.js.map +1 -1
- package/dist/rans/d04.js +15 -15
- package/dist/rans/d04.js.map +1 -1
- package/dist/rans/d14.js +21 -21
- package/dist/rans/d14.js.map +1 -1
- package/dist/rans/decoding.js +27 -30
- package/dist/rans/decoding.js.map +1 -1
- package/dist/rans/frequencies.js +11 -11
- package/dist/rans/frequencies.js.map +1 -1
- package/dist/rans/index.js +46 -49
- package/dist/rans/index.js.map +1 -1
- package/dist/sam.d.ts +8 -1
- package/dist/sam.js +7 -7
- package/dist/sam.js.map +1 -1
- package/dist/typescript.d.ts +3 -0
- package/dist/typescript.js +11 -0
- package/dist/typescript.js.map +1 -0
- package/dist/unzip-pako.js +1 -1
- package/dist/unzip-pako.js.map +1 -1
- package/dist/unzip.js +1 -1
- package/dist/unzip.js.map +1 -1
- package/errors.js +11 -62
- package/esm/craiIndex.d.ts +19 -12
- package/esm/craiIndex.js +8 -24
- package/esm/craiIndex.js.map +1 -1
- package/esm/cramFile/codecs/_base.d.ts +26 -5
- package/esm/cramFile/codecs/_base.js +1 -35
- package/esm/cramFile/codecs/_base.js.map +1 -1
- package/esm/cramFile/codecs/beta.d.ts +7 -3
- package/esm/cramFile/codecs/beta.js +4 -3
- package/esm/cramFile/codecs/beta.js.map +1 -1
- package/esm/cramFile/codecs/byteArrayLength.d.ts +13 -7
- package/esm/cramFile/codecs/byteArrayLength.js +1 -1
- package/esm/cramFile/codecs/byteArrayLength.js.map +1 -1
- package/esm/cramFile/codecs/byteArrayStop.d.ts +9 -5
- package/esm/cramFile/codecs/byteArrayStop.js +7 -9
- package/esm/cramFile/codecs/byteArrayStop.js.map +1 -1
- package/esm/cramFile/codecs/dataSeriesTypes.d.ts +4 -0
- package/esm/cramFile/codecs/dataSeriesTypes.js +2 -0
- package/esm/cramFile/codecs/dataSeriesTypes.js.map +1 -0
- package/esm/cramFile/codecs/external.d.ts +10 -6
- package/esm/cramFile/codecs/external.js +4 -3
- package/esm/cramFile/codecs/external.js.map +1 -1
- package/esm/cramFile/codecs/gamma.d.ts +7 -3
- package/esm/cramFile/codecs/gamma.js +5 -4
- package/esm/cramFile/codecs/gamma.js.map +1 -1
- package/esm/cramFile/codecs/getBits.d.ts +7 -0
- package/esm/cramFile/codecs/getBits.js +21 -0
- package/esm/cramFile/codecs/getBits.js.map +1 -0
- package/esm/cramFile/codecs/huffman.d.ts +17 -13
- package/esm/cramFile/codecs/huffman.js +22 -9
- package/esm/cramFile/codecs/huffman.js.map +1 -1
- package/esm/cramFile/codecs/index.d.ts +4 -2
- package/esm/cramFile/codecs/index.js +1 -1
- package/esm/cramFile/codecs/index.js.map +1 -1
- package/esm/cramFile/codecs/subexp.d.ts +7 -3
- package/esm/cramFile/codecs/subexp.js +7 -5
- package/esm/cramFile/codecs/subexp.js.map +1 -1
- package/esm/cramFile/constants.d.ts +35 -35
- package/esm/cramFile/constants.js.map +1 -1
- package/esm/cramFile/container/compressionScheme.d.ts +57 -11
- package/esm/cramFile/container/compressionScheme.js +15 -8
- package/esm/cramFile/container/compressionScheme.js.map +1 -1
- package/esm/cramFile/container/index.d.ts +23 -9
- package/esm/cramFile/container/index.js +11 -9
- package/esm/cramFile/container/index.js.map +1 -1
- package/esm/cramFile/encoding.d.ts +78 -0
- package/esm/cramFile/encoding.js +2 -0
- package/esm/cramFile/encoding.js.map +1 -0
- package/esm/cramFile/file.d.ts +91 -41
- package/esm/cramFile/file.js +59 -47
- package/esm/cramFile/file.js.map +1 -1
- package/esm/cramFile/filehandle.d.ts +2 -0
- package/esm/cramFile/filehandle.js +2 -0
- package/esm/cramFile/filehandle.js.map +1 -0
- package/esm/cramFile/index.d.ts +1 -1
- package/esm/cramFile/index.js.map +1 -1
- package/esm/cramFile/record.d.ts +61 -17
- package/esm/cramFile/record.js +83 -5
- package/esm/cramFile/record.js.map +1 -1
- package/esm/cramFile/sectionParsers.d.ts +99 -8
- package/esm/cramFile/sectionParsers.js +7 -17
- package/esm/cramFile/sectionParsers.js.map +1 -1
- package/esm/cramFile/slice/decodeRecord.d.ts +30 -2
- package/esm/cramFile/slice/decodeRecord.js +102 -70
- package/esm/cramFile/slice/decodeRecord.js.map +1 -1
- package/esm/cramFile/slice/index.d.ts +21 -14
- package/esm/cramFile/slice/index.js +77 -38
- package/esm/cramFile/slice/index.js.map +1 -1
- package/esm/cramFile/util.d.ts +11 -5
- package/esm/cramFile/util.js +11 -82
- package/esm/cramFile/util.js.map +1 -1
- package/esm/errors.d.ts +5 -10
- package/esm/errors.js +0 -5
- package/esm/errors.js.map +1 -1
- package/esm/index.d.ts +3 -3
- package/esm/index.js.map +1 -1
- package/esm/indexedCramFile.d.ts +37 -12
- package/esm/indexedCramFile.js +19 -8
- package/esm/indexedCramFile.js.map +1 -1
- package/esm/io/index.d.ts +5 -5
- package/esm/io/index.js +3 -3
- package/esm/io/index.js.map +1 -1
- package/esm/sam.d.ts +8 -1
- package/esm/sam.js.map +1 -1
- package/esm/typescript.d.ts +3 -0
- package/esm/typescript.js +7 -0
- package/esm/typescript.js.map +1 -0
- package/package.json +18 -11
- package/src/{craiIndex.js → craiIndex.ts} +37 -31
- package/src/cramFile/codecs/_base.ts +45 -0
- package/src/cramFile/codecs/beta.ts +34 -0
- package/src/cramFile/codecs/{byteArrayLength.js → byteArrayLength.ts} +27 -5
- package/src/cramFile/codecs/{byteArrayStop.js → byteArrayStop.ts} +25 -12
- package/src/cramFile/codecs/dataSeriesTypes.ts +39 -0
- package/src/cramFile/codecs/{external.js → external.ts} +28 -12
- package/src/cramFile/codecs/gamma.ts +42 -0
- package/src/cramFile/codecs/getBits.ts +28 -0
- package/src/cramFile/codecs/{huffman.js → huffman.ts} +48 -15
- package/src/cramFile/codecs/{index.js → index.ts} +9 -3
- package/src/cramFile/codecs/subexp.ts +45 -0
- package/src/cramFile/{constants.js → constants.ts} +0 -0
- package/src/cramFile/container/{compressionScheme.js → compressionScheme.ts} +50 -18
- package/src/cramFile/container/{index.js → index.ts} +13 -13
- package/src/cramFile/encoding.ts +98 -0
- package/src/cramFile/{file.js → file.ts} +136 -62
- package/src/cramFile/filehandle.ts +3 -0
- package/src/cramFile/{index.js → index.ts} +0 -0
- package/src/cramFile/{record.js → record.ts} +185 -14
- package/src/cramFile/{sectionParsers.js → sectionParsers.ts} +148 -20
- package/src/cramFile/slice/{decodeRecord.js → decodeRecord.ts} +158 -105
- package/src/cramFile/slice/{index.js → index.ts} +138 -63
- package/src/cramFile/{util.js → util.ts} +28 -17
- package/src/{errors.js → errors.ts} +0 -5
- package/src/{index.js → index.ts} +0 -0
- package/src/{indexedCramFile.js → indexedCramFile.ts} +79 -19
- package/src/io/{index.js → index.ts} +10 -5
- package/src/{sam.js → sam.ts} +7 -2
- package/src/typescript.ts +17 -0
- package/src/typings/binary-parser.d.ts +44 -0
- package/src/typings/bzip2.d.ts +7 -0
- package/src/typings/htscodecs.d.ts +6 -0
- package/dist/io/bufferCache.d.ts +0 -12
- package/dist/io/bufferCache.js +0 -112
- package/dist/io/bufferCache.js.map +0 -1
- package/dist/io/localFile.d.ts +0 -10
- package/dist/io/localFile.js +0 -108
- package/dist/io/localFile.js.map +0 -1
- package/dist/io/remoteFile.d.ts +0 -16
- package/dist/io/remoteFile.js +0 -143
- package/dist/io/remoteFile.js.map +0 -1
- package/esm/io/bufferCache.d.ts +0 -12
- package/esm/io/bufferCache.js +0 -54
- package/esm/io/bufferCache.js.map +0 -1
- package/esm/io/localFile.d.ts +0 -10
- package/esm/io/localFile.js +0 -31
- package/esm/io/localFile.js.map +0 -1
- package/esm/io/remoteFile.d.ts +0 -16
- package/esm/io/remoteFile.js +0 -64
- package/esm/io/remoteFile.js.map +0 -1
- package/src/cramFile/codecs/_base.js +0 -49
- package/src/cramFile/codecs/beta.js +0 -23
- package/src/cramFile/codecs/gamma.js +0 -30
- package/src/cramFile/codecs/subexp.js +0 -32
- package/src/io/bufferCache.js +0 -66
- package/src/io/localFile.js +0 -35
- package/src/io/remoteFile.js +0 -71
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { CramEncoding } from '../encoding'
|
|
2
|
+
|
|
3
|
+
export type DataType = 'int' | 'byte' | 'long' | 'byteArray'
|
|
4
|
+
|
|
5
|
+
export type DataSeriesEncodingKey =
|
|
6
|
+
| 'BF'
|
|
7
|
+
| 'CF'
|
|
8
|
+
| 'RI'
|
|
9
|
+
| 'RL'
|
|
10
|
+
| 'AP'
|
|
11
|
+
| 'RG'
|
|
12
|
+
| 'RN'
|
|
13
|
+
| 'MF'
|
|
14
|
+
| 'NS'
|
|
15
|
+
| 'NP'
|
|
16
|
+
| 'TS'
|
|
17
|
+
| 'NF'
|
|
18
|
+
| 'TL'
|
|
19
|
+
| 'FN'
|
|
20
|
+
| 'FC'
|
|
21
|
+
| 'FP'
|
|
22
|
+
| 'DL'
|
|
23
|
+
| 'BB'
|
|
24
|
+
| 'QQ'
|
|
25
|
+
| 'BS'
|
|
26
|
+
| 'IN'
|
|
27
|
+
| 'RS'
|
|
28
|
+
| 'PD'
|
|
29
|
+
| 'HC'
|
|
30
|
+
| 'SC'
|
|
31
|
+
| 'MQ'
|
|
32
|
+
| 'BA'
|
|
33
|
+
| 'QS'
|
|
34
|
+
| 'TC'
|
|
35
|
+
| 'TN'
|
|
36
|
+
// | 'TM'
|
|
37
|
+
// | 'TV'
|
|
38
|
+
|
|
39
|
+
export type DataSeriesEncodingMap = Record<DataSeriesEncodingKey, CramEncoding>
|
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
CramMalformedError,
|
|
4
|
-
CramBufferOverrunError,
|
|
5
|
-
} from '../../errors'
|
|
6
|
-
import CramCodec from './_base'
|
|
1
|
+
import { CramMalformedError, CramUnimplementedError } from '../../errors'
|
|
2
|
+
import CramCodec, { Cursor, Cursors } from './_base'
|
|
7
3
|
import { parseItf8 } from '../util'
|
|
4
|
+
import CramSlice from '../slice'
|
|
5
|
+
import { CramFileBlock } from '../file'
|
|
6
|
+
import { CramBufferOverrunError } from './getBits'
|
|
7
|
+
import { ExternalCramEncoding } from '../encoding'
|
|
8
8
|
|
|
9
|
-
export default class ExternalCodec extends CramCodec
|
|
10
|
-
|
|
9
|
+
export default class ExternalCodec extends CramCodec<
|
|
10
|
+
'int' | 'byte',
|
|
11
|
+
ExternalCramEncoding['parameters']
|
|
12
|
+
> {
|
|
13
|
+
private readonly _decodeData: (
|
|
14
|
+
contentBlock: CramFileBlock,
|
|
15
|
+
cursor: Cursor,
|
|
16
|
+
) => number
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
parameters: ExternalCramEncoding['parameters'],
|
|
20
|
+
dataType: 'int' | 'byte',
|
|
21
|
+
) {
|
|
11
22
|
super(parameters, dataType)
|
|
12
23
|
if (this.dataType === 'int') {
|
|
13
24
|
this._decodeData = this._decodeInt
|
|
@@ -20,7 +31,12 @@ export default class ExternalCodec extends CramCodec {
|
|
|
20
31
|
}
|
|
21
32
|
}
|
|
22
33
|
|
|
23
|
-
decode(
|
|
34
|
+
decode(
|
|
35
|
+
slice: CramSlice,
|
|
36
|
+
coreDataBlock: CramFileBlock,
|
|
37
|
+
blocksByContentId: Record<number, CramFileBlock>,
|
|
38
|
+
cursors: Cursors,
|
|
39
|
+
) {
|
|
24
40
|
const { blockContentId } = this.parameters
|
|
25
41
|
const contentBlock = blocksByContentId[blockContentId]
|
|
26
42
|
if (!contentBlock) {
|
|
@@ -32,16 +48,16 @@ export default class ExternalCodec extends CramCodec {
|
|
|
32
48
|
return this._decodeData(contentBlock, cursor)
|
|
33
49
|
}
|
|
34
50
|
|
|
35
|
-
_decodeInt(contentBlock, cursor) {
|
|
51
|
+
_decodeInt(contentBlock: CramFileBlock, cursor: Cursor) {
|
|
36
52
|
const [result, bytesRead] = parseItf8(
|
|
37
53
|
contentBlock.content,
|
|
38
54
|
cursor.bytePosition,
|
|
39
55
|
)
|
|
40
|
-
cursor.bytePosition
|
|
56
|
+
cursor.bytePosition = cursor.bytePosition + bytesRead
|
|
41
57
|
return result
|
|
42
58
|
}
|
|
43
59
|
|
|
44
|
-
_decodeByte(contentBlock, cursor) {
|
|
60
|
+
_decodeByte(contentBlock: CramFileBlock, cursor: Cursor) {
|
|
45
61
|
if (cursor.bytePosition >= contentBlock.content.length) {
|
|
46
62
|
throw new CramBufferOverrunError(
|
|
47
63
|
'attempted to read beyond end of block. this file seems truncated.',
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { CramUnimplementedError } from '../../errors'
|
|
2
|
+
import CramCodec, { Cursors } from './_base'
|
|
3
|
+
import { getBits } from './getBits'
|
|
4
|
+
import { GammaEncoding } from '../encoding'
|
|
5
|
+
import CramSlice from '../slice'
|
|
6
|
+
import { CramFileBlock } from '../file'
|
|
7
|
+
|
|
8
|
+
export default class GammaCodec extends CramCodec<
|
|
9
|
+
'int',
|
|
10
|
+
GammaEncoding['parameters']
|
|
11
|
+
> {
|
|
12
|
+
constructor(parameters: GammaEncoding['parameters'], dataType: 'int') {
|
|
13
|
+
super(parameters, dataType)
|
|
14
|
+
if (this.dataType !== 'int') {
|
|
15
|
+
throw new CramUnimplementedError(
|
|
16
|
+
`${this.dataType} decoding not yet implemented by GAMMA codec`,
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
decode(
|
|
22
|
+
slice: CramSlice,
|
|
23
|
+
coreDataBlock: CramFileBlock,
|
|
24
|
+
blocksByContentId: Record<number, CramFileBlock>,
|
|
25
|
+
cursors: Cursors,
|
|
26
|
+
) {
|
|
27
|
+
let length = 1
|
|
28
|
+
|
|
29
|
+
while (getBits(coreDataBlock.content, cursors.coreBlock, 1) === 0) {
|
|
30
|
+
length = length + 1
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const readBits = getBits(
|
|
34
|
+
coreDataBlock.content,
|
|
35
|
+
cursors.coreBlock,
|
|
36
|
+
length - 1,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
const value = readBits | (1 << (length - 1))
|
|
40
|
+
return value - this.parameters.offset
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export class CramBufferOverrunError extends Error {}
|
|
2
|
+
|
|
3
|
+
export function getBits(
|
|
4
|
+
data: Buffer,
|
|
5
|
+
cursor: { bytePosition: number; bitPosition: number },
|
|
6
|
+
numBits: number,
|
|
7
|
+
) {
|
|
8
|
+
let val = 0
|
|
9
|
+
if (
|
|
10
|
+
cursor.bytePosition + (7 - cursor.bitPosition + numBits) / 8 >
|
|
11
|
+
data.length
|
|
12
|
+
) {
|
|
13
|
+
throw new CramBufferOverrunError(
|
|
14
|
+
'read error during decoding. the file seems to be truncated.',
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
for (let dlen = numBits; dlen; dlen--) {
|
|
18
|
+
// get the next `dlen` bits in the input, put them in val
|
|
19
|
+
val <<= 1
|
|
20
|
+
val |= (data[cursor.bytePosition] >> cursor.bitPosition) & 1
|
|
21
|
+
cursor.bitPosition -= 1
|
|
22
|
+
if (cursor.bitPosition < 0) {
|
|
23
|
+
cursor.bytePosition += 1
|
|
24
|
+
}
|
|
25
|
+
cursor.bitPosition &= 7
|
|
26
|
+
}
|
|
27
|
+
return val
|
|
28
|
+
}
|
|
@@ -1,14 +1,36 @@
|
|
|
1
1
|
import { CramMalformedError } from '../../errors'
|
|
2
|
-
import CramCodec from './_base'
|
|
2
|
+
import CramCodec, { Cursor, Cursors } from './_base'
|
|
3
|
+
import { getBits } from './getBits'
|
|
4
|
+
import { HuffmanEncoding } from '../encoding'
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
import CramSlice from '../slice'
|
|
7
|
+
import { CramFileBlock } from '../file'
|
|
8
|
+
|
|
9
|
+
function numberOfSetBits(ii: number) {
|
|
5
10
|
let i = (ii - (ii >> 1)) & 0x55555555
|
|
6
11
|
i = (i & 0x33333333) + ((i >> 2) & 0x33333333)
|
|
7
12
|
return (((i + (i >> 4)) & 0x0f0f0f0f) * 0x01010101) >> 24
|
|
8
13
|
}
|
|
9
14
|
|
|
10
|
-
|
|
11
|
-
|
|
15
|
+
type Code = { bitLength: number; value: number; bitCode: number }
|
|
16
|
+
|
|
17
|
+
export default class HuffmanIntCodec extends CramCodec<
|
|
18
|
+
'byte' | 'int',
|
|
19
|
+
HuffmanEncoding['parameters']
|
|
20
|
+
> {
|
|
21
|
+
private codes: Record<number, Code> = {}
|
|
22
|
+
private codeBook: Record<number, number[]> = {}
|
|
23
|
+
private sortedByValue: Code[] = []
|
|
24
|
+
private sortedCodes: Code[] = []
|
|
25
|
+
private sortedValuesByBitCode: number[] = []
|
|
26
|
+
private sortedBitCodes: number[] = []
|
|
27
|
+
private sortedBitLengthsByBitCode: number[] = []
|
|
28
|
+
private bitCodeToValue: number[] = []
|
|
29
|
+
|
|
30
|
+
constructor(
|
|
31
|
+
parameters: HuffmanEncoding['parameters'],
|
|
32
|
+
dataType: 'byte' | 'int',
|
|
33
|
+
) {
|
|
12
34
|
super(parameters, dataType)
|
|
13
35
|
if (!['byte', 'int'].includes(this.dataType)) {
|
|
14
36
|
throw new TypeError(
|
|
@@ -28,7 +50,9 @@ export default class HuffmanIntCodec extends CramCodec {
|
|
|
28
50
|
|
|
29
51
|
buildCodeBook() {
|
|
30
52
|
// parse the parameters together into a `codes` data structure
|
|
31
|
-
let codes = new Array(
|
|
53
|
+
let codes: Array<{ symbol: number; bitLength: number }> = new Array(
|
|
54
|
+
this.parameters.numCodes,
|
|
55
|
+
)
|
|
32
56
|
for (let i = 0; i < this.parameters.numCodes; i += 1) {
|
|
33
57
|
codes[i] = {
|
|
34
58
|
symbol: this.parameters.symbols[i],
|
|
@@ -54,16 +78,20 @@ export default class HuffmanIntCodec extends CramCodec {
|
|
|
54
78
|
let codeLength = 0
|
|
55
79
|
let codeValue = -1
|
|
56
80
|
Object.entries(this.codeBook).forEach(([bitLength, symbols]) => {
|
|
57
|
-
|
|
81
|
+
const bitLengthInt = parseInt(bitLength, 10)
|
|
58
82
|
symbols.forEach(symbol => {
|
|
59
|
-
const code = {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
83
|
+
const code = {
|
|
84
|
+
bitLength: bitLengthInt,
|
|
85
|
+
value: symbol,
|
|
86
|
+
bitCode: 0,
|
|
87
|
+
}
|
|
88
|
+
codeValue = codeValue + 1
|
|
89
|
+
const delta = bitLengthInt - codeLength // new length?
|
|
90
|
+
codeValue = codeValue << delta // pad with 0's
|
|
63
91
|
code.bitCode = codeValue // calculated: huffman code
|
|
64
|
-
codeLength
|
|
92
|
+
codeLength = codeLength + delta // adjust current code length
|
|
65
93
|
|
|
66
|
-
if (numberOfSetBits(codeValue) >
|
|
94
|
+
if (numberOfSetBits(codeValue) > bitLengthInt) {
|
|
67
95
|
throw new CramMalformedError('Symbol out of range')
|
|
68
96
|
}
|
|
69
97
|
|
|
@@ -93,7 +121,12 @@ export default class HuffmanIntCodec extends CramCodec {
|
|
|
93
121
|
}
|
|
94
122
|
}
|
|
95
123
|
|
|
96
|
-
decode(
|
|
124
|
+
decode(
|
|
125
|
+
slice: CramSlice,
|
|
126
|
+
coreDataBlock: CramFileBlock,
|
|
127
|
+
blocksByContentId: Record<number, CramFileBlock>,
|
|
128
|
+
cursors: Cursors,
|
|
129
|
+
) {
|
|
97
130
|
return this._decode(slice, coreDataBlock, cursors.coreBlock)
|
|
98
131
|
}
|
|
99
132
|
|
|
@@ -106,7 +139,7 @@ export default class HuffmanIntCodec extends CramCodec {
|
|
|
106
139
|
return this.sortedCodes[0].value
|
|
107
140
|
}
|
|
108
141
|
|
|
109
|
-
_decode(slice, coreDataBlock, coreCursor) {
|
|
142
|
+
_decode(slice: CramSlice, coreDataBlock: CramFileBlock, coreCursor: Cursor) {
|
|
110
143
|
const input = coreDataBlock.content
|
|
111
144
|
|
|
112
145
|
let prevLen = 0
|
|
@@ -114,7 +147,7 @@ export default class HuffmanIntCodec extends CramCodec {
|
|
|
114
147
|
for (let i = 0; i < this.sortedCodes.length; i += 1) {
|
|
115
148
|
const length = this.sortedCodes[i].bitLength
|
|
116
149
|
bits <<= length - prevLen
|
|
117
|
-
bits |=
|
|
150
|
+
bits |= getBits(input, coreCursor, length - prevLen)
|
|
118
151
|
prevLen = length
|
|
119
152
|
{
|
|
120
153
|
const index = this.bitCodeToValue[bits]
|
|
@@ -7,6 +7,9 @@ import ByteArrayLengthCodec from './byteArrayLength'
|
|
|
7
7
|
import BetaCodec from './beta'
|
|
8
8
|
import GammaCodec from './gamma'
|
|
9
9
|
import SubexpCodec from './subexp'
|
|
10
|
+
import CramCodec from './_base'
|
|
11
|
+
import { CramEncoding } from '../encoding'
|
|
12
|
+
import { DataType } from './dataSeriesTypes'
|
|
10
13
|
|
|
11
14
|
const codecClasses = {
|
|
12
15
|
1: ExternalCodec,
|
|
@@ -20,11 +23,14 @@ const codecClasses = {
|
|
|
20
23
|
9: GammaCodec,
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
return codecClasses[id]
|
|
26
|
+
function getCodecClassWithId(id: number) {
|
|
27
|
+
return (codecClasses as any)[id]
|
|
25
28
|
}
|
|
26
29
|
|
|
27
|
-
export function instantiateCodec
|
|
30
|
+
export function instantiateCodec<TResult extends DataType = DataType>(
|
|
31
|
+
encodingData: CramEncoding,
|
|
32
|
+
dataType: DataType | 'ignore',
|
|
33
|
+
): CramCodec<TResult> {
|
|
28
34
|
const CodecClass = getCodecClassWithId(
|
|
29
35
|
dataType === 'ignore' ? 0 : encodingData.codecId,
|
|
30
36
|
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { CramUnimplementedError } from '../../errors'
|
|
2
|
+
import CramCodec, { Cursors } from './_base'
|
|
3
|
+
import { getBits } from './getBits'
|
|
4
|
+
import CramSlice from '../slice'
|
|
5
|
+
import { CramFileBlock } from '../file'
|
|
6
|
+
import { SubexpEncoding } from '../encoding'
|
|
7
|
+
|
|
8
|
+
export default class SubexpCodec extends CramCodec<
|
|
9
|
+
'int',
|
|
10
|
+
SubexpEncoding['parameters']
|
|
11
|
+
> {
|
|
12
|
+
constructor(parameters: SubexpEncoding['parameters'], dataType: 'int') {
|
|
13
|
+
super(parameters, dataType)
|
|
14
|
+
if (this.dataType !== 'int') {
|
|
15
|
+
throw new CramUnimplementedError(
|
|
16
|
+
`${this.dataType} decoding not yet implemented by SUBEXP codec`,
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
decode(
|
|
22
|
+
slice: CramSlice,
|
|
23
|
+
coreDataBlock: CramFileBlock,
|
|
24
|
+
blocksByContentId: Record<number, CramFileBlock>,
|
|
25
|
+
cursors: Cursors,
|
|
26
|
+
) {
|
|
27
|
+
let numLeadingOnes = 0
|
|
28
|
+
while (getBits(coreDataBlock.content, cursors.coreBlock, 1)) {
|
|
29
|
+
numLeadingOnes = numLeadingOnes + 1
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let b
|
|
33
|
+
let n
|
|
34
|
+
if (numLeadingOnes === 0) {
|
|
35
|
+
b = this.parameters.K
|
|
36
|
+
n = getBits(coreDataBlock.content, cursors.coreBlock, b)
|
|
37
|
+
} else {
|
|
38
|
+
b = numLeadingOnes + this.parameters.K - 1
|
|
39
|
+
const bits = getBits(coreDataBlock.content, cursors.coreBlock, b)
|
|
40
|
+
n = (1 << b) | bits
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return n - this.parameters.offset
|
|
44
|
+
}
|
|
45
|
+
}
|
|
File without changes
|
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import { CramMalformedError } from '../../errors'
|
|
2
1
|
import { instantiateCodec } from '../codecs'
|
|
2
|
+
import CramCodec from '../codecs/_base'
|
|
3
|
+
import { CramCompressionHeader, CramPreservationMap } from '../sectionParsers'
|
|
4
|
+
import { CramEncoding } from '../encoding'
|
|
5
|
+
import { CramMalformedError } from '../../errors'
|
|
6
|
+
import {
|
|
7
|
+
DataSeriesEncodingKey,
|
|
8
|
+
DataSeriesEncodingMap,
|
|
9
|
+
} from '../codecs/dataSeriesTypes'
|
|
3
10
|
|
|
4
11
|
// the hardcoded data type to be decoded for each core
|
|
5
12
|
// data field
|
|
@@ -34,12 +41,14 @@ const dataSeriesTypes = {
|
|
|
34
41
|
QS: 'byte',
|
|
35
42
|
QQ: 'byteArray',
|
|
36
43
|
TL: 'int',
|
|
37
|
-
TM: 'ignore',
|
|
38
|
-
TV: 'ignore',
|
|
39
|
-
}
|
|
44
|
+
// TM: 'ignore',
|
|
45
|
+
// TV: 'ignore',
|
|
46
|
+
} as const
|
|
47
|
+
|
|
48
|
+
export type DataSeriesTypes = typeof dataSeriesTypes
|
|
40
49
|
|
|
41
|
-
function parseSubstitutionMatrix(byteArray) {
|
|
42
|
-
const matrix = new Array(5)
|
|
50
|
+
function parseSubstitutionMatrix(byteArray: number[]) {
|
|
51
|
+
const matrix: string[][] = new Array(5)
|
|
43
52
|
for (let i = 0; i < 5; i += 1) {
|
|
44
53
|
matrix[i] = new Array(4)
|
|
45
54
|
}
|
|
@@ -72,25 +81,44 @@ function parseSubstitutionMatrix(byteArray) {
|
|
|
72
81
|
return matrix
|
|
73
82
|
}
|
|
74
83
|
|
|
84
|
+
type DataSeriesCache = {
|
|
85
|
+
[K in DataSeriesEncodingKey]?: CramCodec<DataSeriesTypes[K]>
|
|
86
|
+
}
|
|
87
|
+
|
|
75
88
|
export default class CramContainerCompressionScheme {
|
|
76
|
-
|
|
77
|
-
|
|
89
|
+
public readNamesIncluded: boolean
|
|
90
|
+
public APdelta: boolean
|
|
91
|
+
public referenceRequired: boolean
|
|
92
|
+
public tagIdsDictionary: Record<number, string[]>
|
|
93
|
+
public substitutionMatrix: string[][]
|
|
94
|
+
public dataSeriesCodecCache: DataSeriesCache = {}
|
|
95
|
+
public tagCodecCache: Record<string, CramCodec> = {}
|
|
96
|
+
public tagEncoding: Record<string, CramEncoding> = {}
|
|
97
|
+
public dataSeriesEncoding: DataSeriesEncodingMap
|
|
98
|
+
private preservation: CramPreservationMap
|
|
99
|
+
private _endPosition: number
|
|
100
|
+
private _size: number
|
|
101
|
+
|
|
102
|
+
constructor(content: CramCompressionHeader) {
|
|
103
|
+
// Object.assign(this, content)
|
|
78
104
|
// interpret some of the preservation map tags for convenient use
|
|
79
105
|
this.readNamesIncluded = content.preservation.RN
|
|
80
106
|
this.APdelta = content.preservation.AP
|
|
81
107
|
this.referenceRequired = !!content.preservation.RR
|
|
82
108
|
this.tagIdsDictionary = content.preservation.TD
|
|
83
109
|
this.substitutionMatrix = parseSubstitutionMatrix(content.preservation.SM)
|
|
84
|
-
|
|
85
|
-
this.
|
|
86
|
-
this.
|
|
110
|
+
this.dataSeriesEncoding = content.dataSeriesEncoding
|
|
111
|
+
this.tagEncoding = content.tagEncoding
|
|
112
|
+
this.preservation = content.preservation
|
|
113
|
+
this._size = content._size
|
|
114
|
+
this._endPosition = content._endPosition
|
|
87
115
|
}
|
|
88
116
|
|
|
89
117
|
/**
|
|
90
118
|
* @param {string} tagName three-character tag name
|
|
91
119
|
* @private
|
|
92
120
|
*/
|
|
93
|
-
getCodecForTag(tagName) {
|
|
121
|
+
getCodecForTag(tagName: string): CramCodec {
|
|
94
122
|
if (!this.tagCodecCache[tagName]) {
|
|
95
123
|
const encodingData = this.tagEncoding[tagName]
|
|
96
124
|
if (encodingData) {
|
|
@@ -108,12 +136,15 @@ export default class CramContainerCompressionScheme {
|
|
|
108
136
|
* @param {number} tagListId ID of the tag list to fetch from the tag dictionary
|
|
109
137
|
* @private
|
|
110
138
|
*/
|
|
111
|
-
getTagNames(tagListId) {
|
|
139
|
+
getTagNames(tagListId: number) {
|
|
112
140
|
return this.tagIdsDictionary[tagListId]
|
|
113
141
|
}
|
|
114
142
|
|
|
115
|
-
getCodecForDataSeries(
|
|
116
|
-
|
|
143
|
+
getCodecForDataSeries<TDataSeries extends DataSeriesEncodingKey>(
|
|
144
|
+
dataSeriesName: TDataSeries,
|
|
145
|
+
): CramCodec<DataSeriesTypes[TDataSeries]> | undefined {
|
|
146
|
+
let r: CramCodec<DataSeriesTypes[TDataSeries]> | undefined =
|
|
147
|
+
this.dataSeriesCodecCache[dataSeriesName]
|
|
117
148
|
if (r === undefined) {
|
|
118
149
|
const encodingData = this.dataSeriesEncoding[dataSeriesName]
|
|
119
150
|
if (encodingData) {
|
|
@@ -124,19 +155,20 @@ export default class CramContainerCompressionScheme {
|
|
|
124
155
|
)
|
|
125
156
|
}
|
|
126
157
|
r = instantiateCodec(encodingData, dataType)
|
|
127
|
-
this
|
|
158
|
+
// didn't find a way to make TS understand this
|
|
159
|
+
this.dataSeriesCodecCache[dataSeriesName] = r as CramCodec<any>
|
|
128
160
|
}
|
|
129
161
|
}
|
|
130
162
|
return r
|
|
131
163
|
}
|
|
132
164
|
|
|
133
165
|
toJSON() {
|
|
134
|
-
const data = {}
|
|
166
|
+
const data: any = {}
|
|
135
167
|
Object.keys(this).forEach(k => {
|
|
136
168
|
if (/Cache$/.test(k)) {
|
|
137
169
|
return
|
|
138
170
|
}
|
|
139
|
-
data[k] = this[k]
|
|
171
|
+
data[k] = (this as any)[k]
|
|
140
172
|
})
|
|
141
173
|
return data
|
|
142
174
|
}
|
|
@@ -3,15 +3,10 @@ import { CramMalformedError } from '../../errors'
|
|
|
3
3
|
import { itf8Size, parseItem, tinyMemoize } from '../util'
|
|
4
4
|
import CramSlice from '../slice'
|
|
5
5
|
import CramContainerCompressionScheme from './compressionScheme'
|
|
6
|
+
import CramFile from '../file'
|
|
6
7
|
|
|
7
8
|
export default class CramContainer {
|
|
8
|
-
constructor(
|
|
9
|
-
// cram file this container comes from
|
|
10
|
-
this.file = cramFile
|
|
11
|
-
// position of this container in the file
|
|
12
|
-
this.filePosition = position
|
|
13
|
-
// console.log(`container: ${this.filePosition}`)
|
|
14
|
-
}
|
|
9
|
+
constructor(public file: CramFile, public filePosition: number) {}
|
|
15
10
|
|
|
16
11
|
// memoize
|
|
17
12
|
getHeader() {
|
|
@@ -28,6 +23,9 @@ export default class CramContainer {
|
|
|
28
23
|
}
|
|
29
24
|
const sectionParsers = await this.file.getSectionParsers()
|
|
30
25
|
const block = await this.getFirstBlock()
|
|
26
|
+
if (block === undefined) {
|
|
27
|
+
return undefined
|
|
28
|
+
}
|
|
31
29
|
if (block.contentType !== 'COMPRESSION_HEADER') {
|
|
32
30
|
throw new CramMalformedError(
|
|
33
31
|
`invalid content type ${block.contentType} in what is supposed to be the compression header block`,
|
|
@@ -39,8 +37,10 @@ export default class CramContainer {
|
|
|
39
37
|
0,
|
|
40
38
|
block.contentPosition,
|
|
41
39
|
)
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
return {
|
|
41
|
+
...block,
|
|
42
|
+
parsedContent: content,
|
|
43
|
+
}
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
async getFirstBlock() {
|
|
@@ -55,16 +55,16 @@ export default class CramContainer {
|
|
|
55
55
|
if (!header) {
|
|
56
56
|
return undefined
|
|
57
57
|
}
|
|
58
|
-
return new CramContainerCompressionScheme(header.
|
|
58
|
+
return new CramContainerCompressionScheme(header.parsedContent)
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
getSlice(slicePosition, sliceSize) {
|
|
61
|
+
getSlice(slicePosition: number, sliceSize: number) {
|
|
62
62
|
// note: slicePosition is relative to the end of the container header
|
|
63
63
|
// TODO: perhaps we should cache slices?
|
|
64
64
|
return new CramSlice(this, slicePosition, sliceSize)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
async _readContainerHeader(position) {
|
|
67
|
+
async _readContainerHeader(position: number) {
|
|
68
68
|
const sectionParsers = await this.file.getSectionParsers()
|
|
69
69
|
const { cramContainerHeader1, cramContainerHeader2 } = sectionParsers
|
|
70
70
|
const { size: fileSize } = await this.file.stat()
|
|
@@ -77,7 +77,7 @@ export default class CramContainer {
|
|
|
77
77
|
// how much to buffer until you read numLandmarks
|
|
78
78
|
const bytes1 = Buffer.allocUnsafe(cramContainerHeader1.maxLength)
|
|
79
79
|
await this.file.read(bytes1, 0, cramContainerHeader1.maxLength, position)
|
|
80
|
-
const header1 = parseItem(bytes1, cramContainerHeader1.parser)
|
|
80
|
+
const header1 = parseItem(bytes1, cramContainerHeader1.parser) as any
|
|
81
81
|
const numLandmarksSize = itf8Size(header1.numLandmarks)
|
|
82
82
|
if (position + header1.length >= fileSize) {
|
|
83
83
|
console.warn(
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
export type NullEncoding = {
|
|
2
|
+
codecId: 0
|
|
3
|
+
parametersBytes: number
|
|
4
|
+
parameters: Record<string, never>
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type ExternalCramEncoding = {
|
|
8
|
+
codecId: 1
|
|
9
|
+
parametersBytes: number
|
|
10
|
+
parameters: {
|
|
11
|
+
blockContentId: number
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type GolombEncoding = {
|
|
16
|
+
codecId: 2
|
|
17
|
+
parametersBytes: number
|
|
18
|
+
parameters: {
|
|
19
|
+
offset: number
|
|
20
|
+
M: number
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export type HuffmanEncoding = {
|
|
25
|
+
codecId: 3
|
|
26
|
+
parametersBytes: number
|
|
27
|
+
parameters: {
|
|
28
|
+
numCodes: number
|
|
29
|
+
symbols: number[]
|
|
30
|
+
numLengths: number
|
|
31
|
+
bitLengths: number[]
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type ByteArrayLengthEncoding = {
|
|
36
|
+
codecId: 4
|
|
37
|
+
parametersBytes: number
|
|
38
|
+
parameters: {
|
|
39
|
+
lengthsEncoding: CramEncoding
|
|
40
|
+
valuesEncoding: CramEncoding
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type ByteArrayStopCramEncoding = {
|
|
45
|
+
codecId: 5
|
|
46
|
+
parametersBytes: number
|
|
47
|
+
parameters: {
|
|
48
|
+
stopByte: number
|
|
49
|
+
blockContentId: number
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type BetaEncoding = {
|
|
54
|
+
codecId: 6
|
|
55
|
+
parametersBytes: number
|
|
56
|
+
parameters: {
|
|
57
|
+
offset: number
|
|
58
|
+
length: number // int number of bits
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export type SubexpEncoding = {
|
|
63
|
+
codecId: 7
|
|
64
|
+
parametersBytes: number
|
|
65
|
+
parameters: {
|
|
66
|
+
offset: number
|
|
67
|
+
K: number
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export type GolombRiceEncoding = {
|
|
72
|
+
codecId: 8
|
|
73
|
+
parametersBytes: number
|
|
74
|
+
parameters: {
|
|
75
|
+
offset: number
|
|
76
|
+
log2m: number
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type GammaEncoding = {
|
|
81
|
+
codecId: 9
|
|
82
|
+
parametersBytes: number
|
|
83
|
+
parameters: {
|
|
84
|
+
offset: number
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export type CramEncoding =
|
|
89
|
+
| NullEncoding
|
|
90
|
+
| ExternalCramEncoding
|
|
91
|
+
| GolombEncoding
|
|
92
|
+
| HuffmanEncoding
|
|
93
|
+
| ByteArrayLengthEncoding
|
|
94
|
+
| ByteArrayStopCramEncoding
|
|
95
|
+
| BetaEncoding
|
|
96
|
+
| SubexpEncoding
|
|
97
|
+
| GolombRiceEncoding
|
|
98
|
+
| GammaEncoding
|