@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
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
import Long from 'long'
|
|
2
2
|
import { CramMalformedError } from '../../errors'
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
BamFlagsDecoder,
|
|
5
|
+
CramFlagsDecoder,
|
|
6
|
+
MateFlagsDecoder,
|
|
7
|
+
ReadFeature,
|
|
8
|
+
} from '../record'
|
|
9
|
+
import CramSlice, { SliceHeader } from './index'
|
|
10
|
+
import { isMappedSliceHeader } from '../sectionParsers'
|
|
11
|
+
import CramContainerCompressionScheme, {
|
|
12
|
+
DataSeriesTypes,
|
|
13
|
+
} from '../container/compressionScheme'
|
|
14
|
+
import { CramFileBlock } from '../file'
|
|
15
|
+
import { Cursors, DataTypeMapping } from '../codecs/_base'
|
|
16
|
+
import { DataSeriesEncodingKey } from '../codecs/dataSeriesTypes'
|
|
17
|
+
|
|
5
18
|
/**
|
|
6
19
|
* given a Buffer, read a string up to the first null character
|
|
7
20
|
* @private
|
|
8
21
|
*/
|
|
9
|
-
function readNullTerminatedString(buffer) {
|
|
22
|
+
function readNullTerminatedString(buffer: Uint8Array) {
|
|
10
23
|
let r = ''
|
|
11
24
|
for (let i = 0; i < buffer.length && buffer[i] !== 0; i++) {
|
|
12
25
|
r += String.fromCharCode(buffer[i])
|
|
@@ -18,11 +31,11 @@ function readNullTerminatedString(buffer) {
|
|
|
18
31
|
* parse a BAM tag's array value from a binary buffer
|
|
19
32
|
* @private
|
|
20
33
|
*/
|
|
21
|
-
function parseTagValueArray(buffer) {
|
|
34
|
+
function parseTagValueArray(buffer: Buffer) {
|
|
22
35
|
const arrayType = String.fromCharCode(buffer[0])
|
|
23
36
|
const length = Int32Array.from(buffer.slice(1))[0]
|
|
24
37
|
|
|
25
|
-
const array = new Array(length)
|
|
38
|
+
const array: number[] = new Array(length)
|
|
26
39
|
buffer = buffer.slice(5)
|
|
27
40
|
|
|
28
41
|
if (arrayType === 'c') {
|
|
@@ -66,7 +79,8 @@ function parseTagValueArray(buffer) {
|
|
|
66
79
|
|
|
67
80
|
return array
|
|
68
81
|
}
|
|
69
|
-
|
|
82
|
+
|
|
83
|
+
function parseTagData(tagType: string, buffer: any) {
|
|
70
84
|
if (tagType === 'Z') {
|
|
71
85
|
return readNullTerminatedString(buffer)
|
|
72
86
|
}
|
|
@@ -89,7 +103,7 @@ function parseTagData(tagType, buffer) {
|
|
|
89
103
|
return new Int8Array(buffer.buffer)[0]
|
|
90
104
|
}
|
|
91
105
|
if (tagType === 'C') {
|
|
92
|
-
return buffer[0]
|
|
106
|
+
return buffer[0] as number
|
|
93
107
|
}
|
|
94
108
|
if (tagType === 'f') {
|
|
95
109
|
return new Float32Array(buffer.buffer)[0]
|
|
@@ -108,17 +122,20 @@ function parseTagData(tagType, buffer) {
|
|
|
108
122
|
}
|
|
109
123
|
|
|
110
124
|
function decodeReadFeatures(
|
|
111
|
-
|
|
112
|
-
readFeatureCount,
|
|
113
|
-
decodeDataSeries,
|
|
114
|
-
compressionScheme,
|
|
115
|
-
majorVersion,
|
|
125
|
+
alignmentStart: number,
|
|
126
|
+
readFeatureCount: number,
|
|
127
|
+
decodeDataSeries: any,
|
|
128
|
+
compressionScheme: CramContainerCompressionScheme,
|
|
129
|
+
majorVersion: number,
|
|
116
130
|
) {
|
|
117
131
|
let currentReadPos = 0
|
|
118
|
-
let currentRefPos =
|
|
119
|
-
const readFeatures = new Array(readFeatureCount)
|
|
132
|
+
let currentRefPos = alignmentStart - 1
|
|
133
|
+
const readFeatures: ReadFeature[] = new Array(readFeatureCount)
|
|
120
134
|
|
|
121
|
-
function decodeRFData([type, dataSeriesName]
|
|
135
|
+
function decodeRFData([type, dataSeriesName]: readonly [
|
|
136
|
+
type: string,
|
|
137
|
+
dataSeriesName: string,
|
|
138
|
+
]) {
|
|
122
139
|
const data = decodeDataSeries(dataSeriesName)
|
|
123
140
|
if (type === 'character') {
|
|
124
141
|
return String.fromCharCode(data)
|
|
@@ -140,122 +157,139 @@ function decodeReadFeatures(
|
|
|
140
157
|
|
|
141
158
|
const readPosDelta = decodeDataSeries('FP')
|
|
142
159
|
|
|
143
|
-
const readFeature = { code }
|
|
144
160
|
// map of operator name -> data series name
|
|
145
161
|
const data1Schema = {
|
|
146
|
-
B: ['character', 'BA'],
|
|
147
|
-
S: ['string', majorVersion > 1 ? 'SC' : 'IN'], // IN if cram v1, SC otherwise
|
|
148
|
-
X: ['number', 'BS'],
|
|
149
|
-
D: ['number', 'DL'],
|
|
150
|
-
I: ['string', 'IN'],
|
|
151
|
-
i: ['character', 'BA'],
|
|
152
|
-
b: ['string', 'BB'],
|
|
153
|
-
q: ['numArray', 'QQ'],
|
|
154
|
-
Q: ['number', 'QS'],
|
|
155
|
-
H: ['number', 'HC'],
|
|
156
|
-
P: ['number', 'PD'],
|
|
157
|
-
N: ['number', 'RS'],
|
|
162
|
+
B: ['character', 'BA'] as const,
|
|
163
|
+
S: ['string', majorVersion > 1 ? 'SC' : 'IN'] as const, // IN if cram v1, SC otherwise
|
|
164
|
+
X: ['number', 'BS'] as const,
|
|
165
|
+
D: ['number', 'DL'] as const,
|
|
166
|
+
I: ['string', 'IN'] as const,
|
|
167
|
+
i: ['character', 'BA'] as const,
|
|
168
|
+
b: ['string', 'BB'] as const,
|
|
169
|
+
q: ['numArray', 'QQ'] as const,
|
|
170
|
+
Q: ['number', 'QS'] as const,
|
|
171
|
+
H: ['number', 'HC'] as const,
|
|
172
|
+
P: ['number', 'PD'] as const,
|
|
173
|
+
N: ['number', 'RS'] as const,
|
|
158
174
|
}[code]
|
|
159
175
|
|
|
160
176
|
if (!data1Schema) {
|
|
161
177
|
throw new CramMalformedError(`invalid read feature code "${code}"`)
|
|
162
178
|
}
|
|
163
179
|
|
|
164
|
-
|
|
180
|
+
let data = decodeRFData(data1Schema)
|
|
165
181
|
|
|
166
182
|
// if this is a tag with two data items, make the data an array and add the second item
|
|
167
|
-
const data2Schema = { B: ['number', 'QS'] }[code]
|
|
183
|
+
const data2Schema = { B: ['number', 'QS'] as const }[code]
|
|
168
184
|
if (data2Schema) {
|
|
169
|
-
|
|
185
|
+
data = [data, decodeRFData(data2Schema)]
|
|
170
186
|
}
|
|
171
187
|
|
|
172
188
|
currentReadPos += readPosDelta
|
|
173
|
-
|
|
189
|
+
const pos = currentReadPos
|
|
174
190
|
|
|
175
191
|
currentRefPos += readPosDelta
|
|
176
|
-
|
|
192
|
+
const refPos = currentRefPos
|
|
177
193
|
|
|
178
194
|
// for gapping features, adjust the reference position for read features that follow
|
|
179
195
|
if (code === 'D' || code === 'N') {
|
|
180
|
-
currentRefPos +=
|
|
196
|
+
currentRefPos += data
|
|
181
197
|
} else if (code === 'I' || code === 'S') {
|
|
182
|
-
currentRefPos -=
|
|
198
|
+
currentRefPos -= data.length
|
|
183
199
|
} else if (code === 'i') {
|
|
184
200
|
currentRefPos -= 1
|
|
185
201
|
}
|
|
186
202
|
|
|
187
|
-
readFeatures[i] =
|
|
203
|
+
readFeatures[i] = { code, pos, refPos, data }
|
|
188
204
|
}
|
|
189
205
|
return readFeatures
|
|
190
206
|
}
|
|
191
207
|
|
|
208
|
+
export type DataSeriesDecoder = <T extends DataSeriesEncodingKey>(
|
|
209
|
+
dataSeriesName: T,
|
|
210
|
+
) => DataTypeMapping[DataSeriesTypes[T]]
|
|
211
|
+
|
|
192
212
|
export default function decodeRecord(
|
|
193
|
-
slice,
|
|
194
|
-
decodeDataSeries,
|
|
195
|
-
compressionScheme,
|
|
196
|
-
sliceHeader,
|
|
197
|
-
coreDataBlock,
|
|
198
|
-
blocksByContentId,
|
|
199
|
-
cursors,
|
|
200
|
-
majorVersion,
|
|
201
|
-
recordNumber,
|
|
213
|
+
slice: CramSlice,
|
|
214
|
+
decodeDataSeries: DataSeriesDecoder,
|
|
215
|
+
compressionScheme: CramContainerCompressionScheme,
|
|
216
|
+
sliceHeader: SliceHeader,
|
|
217
|
+
coreDataBlock: CramFileBlock,
|
|
218
|
+
blocksByContentId: Record<number, CramFileBlock>,
|
|
219
|
+
cursors: Cursors,
|
|
220
|
+
majorVersion: number,
|
|
221
|
+
recordNumber: number,
|
|
202
222
|
) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
cramRecord.flags = decodeDataSeries('BF')
|
|
223
|
+
let flags = decodeDataSeries('BF') as number
|
|
206
224
|
|
|
207
225
|
// note: the C data type of compressionFlags is byte in cram v1
|
|
208
226
|
// and int32 in cram v2+, but that does not matter for us here
|
|
209
227
|
// in javascript land.
|
|
210
|
-
|
|
228
|
+
const cramFlags = decodeDataSeries('CF') as number
|
|
229
|
+
|
|
230
|
+
if (!isMappedSliceHeader(sliceHeader.parsedContent)) {
|
|
231
|
+
throw new Error()
|
|
232
|
+
}
|
|
211
233
|
|
|
212
|
-
|
|
213
|
-
|
|
234
|
+
let sequenceId
|
|
235
|
+
if (majorVersion > 1 && sliceHeader.parsedContent.refSeqId === -2) {
|
|
236
|
+
sequenceId = decodeDataSeries('RI')
|
|
214
237
|
} else {
|
|
215
|
-
|
|
238
|
+
sequenceId = sliceHeader.parsedContent.refSeqId
|
|
216
239
|
}
|
|
217
240
|
|
|
218
|
-
|
|
241
|
+
const readLength = decodeDataSeries('RL')
|
|
219
242
|
// if APDelta, will calculate the true start in a second pass
|
|
220
|
-
|
|
243
|
+
let alignmentStart = decodeDataSeries('AP')
|
|
221
244
|
if (compressionScheme.APdelta) {
|
|
222
|
-
|
|
245
|
+
alignmentStart = alignmentStart + cursors.lastAlignmentStart
|
|
223
246
|
}
|
|
224
|
-
cursors.lastAlignmentStart =
|
|
225
|
-
|
|
247
|
+
cursors.lastAlignmentStart = alignmentStart
|
|
248
|
+
const readGroupId = decodeDataSeries('RG')
|
|
226
249
|
|
|
250
|
+
let readName
|
|
227
251
|
if (compressionScheme.readNamesIncluded) {
|
|
228
|
-
|
|
252
|
+
readName = readNullTerminatedString(decodeDataSeries('RN'))
|
|
229
253
|
}
|
|
230
254
|
|
|
255
|
+
let mateToUse
|
|
256
|
+
let templateSize
|
|
257
|
+
let mateRecordNumber
|
|
231
258
|
// mate record
|
|
232
|
-
if (
|
|
259
|
+
if (CramFlagsDecoder.isDetached(cramFlags)) {
|
|
233
260
|
// note: the MF is a byte in 1.0, int32 in 2+, but once again this doesn't matter for javascript
|
|
234
|
-
const mate = {}
|
|
235
|
-
|
|
261
|
+
// const mate: any = {}
|
|
262
|
+
const mateFlags = decodeDataSeries('MF') as number
|
|
263
|
+
let mateReadName
|
|
236
264
|
if (!compressionScheme.readNamesIncluded) {
|
|
237
|
-
|
|
238
|
-
|
|
265
|
+
mateReadName = readNullTerminatedString(decodeDataSeries('RN'))
|
|
266
|
+
readName = mateReadName
|
|
239
267
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
if (
|
|
243
|
-
|
|
268
|
+
const mateSequenceId = decodeDataSeries('NS') as number
|
|
269
|
+
const mateAlignmentStart = decodeDataSeries('NP') as number
|
|
270
|
+
if (mateFlags || mateSequenceId > -1) {
|
|
271
|
+
mateToUse = {
|
|
272
|
+
mateFlags,
|
|
273
|
+
mateSequenceId,
|
|
274
|
+
mateAlignmentStart,
|
|
275
|
+
mateReadName,
|
|
276
|
+
}
|
|
244
277
|
}
|
|
245
|
-
|
|
278
|
+
|
|
279
|
+
templateSize = decodeDataSeries('TS')
|
|
246
280
|
|
|
247
281
|
// set mate unmapped if needed
|
|
248
|
-
if (
|
|
249
|
-
|
|
282
|
+
if (MateFlagsDecoder.isUnmapped(mateFlags)) {
|
|
283
|
+
flags = BamFlagsDecoder.setMateUnmapped(flags)
|
|
250
284
|
}
|
|
251
285
|
// set mate reversed if needed
|
|
252
|
-
if (
|
|
253
|
-
|
|
286
|
+
if (MateFlagsDecoder.isOnNegativeStrand(mateFlags)) {
|
|
287
|
+
flags = BamFlagsDecoder.setMateReverseComplemented(flags)
|
|
254
288
|
}
|
|
255
289
|
|
|
256
290
|
// detachedCount++
|
|
257
|
-
} else if (
|
|
258
|
-
|
|
291
|
+
} else if (CramFlagsDecoder.isWithMateDownstream(cramFlags)) {
|
|
292
|
+
mateRecordNumber = (decodeDataSeries('NF') as number) + recordNumber + 1
|
|
259
293
|
}
|
|
260
294
|
|
|
261
295
|
// TODO: the aux tag parsing will have to be refactored if we want to support
|
|
@@ -266,6 +300,7 @@ export default function decodeRecord(
|
|
|
266
300
|
throw new CramMalformedError('invalid TL index')
|
|
267
301
|
}
|
|
268
302
|
|
|
303
|
+
const tags: Record<string, any> = {}
|
|
269
304
|
// TN = tag names
|
|
270
305
|
const TN = compressionScheme.getTagNames(TLindex)
|
|
271
306
|
const ntags = TN.length
|
|
@@ -287,15 +322,20 @@ export default function decodeRecord(
|
|
|
287
322
|
blocksByContentId,
|
|
288
323
|
cursors,
|
|
289
324
|
)
|
|
290
|
-
|
|
325
|
+
tags[tagName] = parseTagData(tagType, tagData)
|
|
291
326
|
}
|
|
292
327
|
|
|
293
|
-
|
|
328
|
+
let readFeatures
|
|
329
|
+
let lengthOnRef
|
|
330
|
+
let mappingQuality
|
|
331
|
+
let qualityScores: number[] | undefined | null
|
|
332
|
+
let readBases = undefined
|
|
333
|
+
if (!BamFlagsDecoder.isSegmentUnmapped(flags)) {
|
|
294
334
|
// reading read features
|
|
295
|
-
const
|
|
335
|
+
const readFeatureCount = decodeDataSeries('FN') as number
|
|
296
336
|
if (readFeatureCount) {
|
|
297
|
-
|
|
298
|
-
|
|
337
|
+
readFeatures = decodeReadFeatures(
|
|
338
|
+
alignmentStart,
|
|
299
339
|
readFeatureCount,
|
|
300
340
|
decodeDataSeries,
|
|
301
341
|
compressionScheme,
|
|
@@ -304,56 +344,69 @@ export default function decodeRecord(
|
|
|
304
344
|
}
|
|
305
345
|
|
|
306
346
|
// compute the read's true span on the reference sequence, and the end coordinate of the alignment on the reference
|
|
307
|
-
|
|
308
|
-
if (
|
|
309
|
-
|
|
347
|
+
lengthOnRef = readLength
|
|
348
|
+
if (readFeatures) {
|
|
349
|
+
for (const { code, data } of readFeatures) {
|
|
310
350
|
if (code === 'D' || code === 'N') {
|
|
311
351
|
lengthOnRef += data
|
|
312
352
|
} else if (code === 'I' || code === 'S') {
|
|
313
|
-
lengthOnRef
|
|
353
|
+
lengthOnRef = lengthOnRef - data.length
|
|
314
354
|
} else if (code === 'i') {
|
|
315
|
-
lengthOnRef
|
|
355
|
+
lengthOnRef = lengthOnRef - 1
|
|
316
356
|
}
|
|
317
|
-
}
|
|
357
|
+
}
|
|
318
358
|
}
|
|
319
359
|
if (Number.isNaN(lengthOnRef)) {
|
|
320
360
|
console.warn(
|
|
321
361
|
`${
|
|
322
|
-
|
|
323
|
-
`${cramRecord.sequenceId}:${cramRecord.alignmentStart}`
|
|
362
|
+
readName || `${sequenceId}:${alignmentStart}`
|
|
324
363
|
} record has invalid read features`,
|
|
325
364
|
)
|
|
326
|
-
lengthOnRef =
|
|
365
|
+
lengthOnRef = readLength
|
|
327
366
|
}
|
|
328
|
-
cramRecord.lengthOnRef = lengthOnRef
|
|
329
367
|
|
|
330
368
|
// mapping quality
|
|
331
|
-
|
|
332
|
-
if (
|
|
333
|
-
|
|
334
|
-
for (let i = 0; i <
|
|
335
|
-
|
|
369
|
+
mappingQuality = decodeDataSeries('MQ') as number
|
|
370
|
+
if (CramFlagsDecoder.isPreservingQualityScores(cramFlags)) {
|
|
371
|
+
qualityScores = new Array(readLength)
|
|
372
|
+
for (let i = 0; i < qualityScores.length; i++) {
|
|
373
|
+
qualityScores[i] = decodeDataSeries('QS')
|
|
336
374
|
}
|
|
337
|
-
cramRecord.qualityScores = bases
|
|
338
375
|
}
|
|
339
|
-
} else if (
|
|
340
|
-
|
|
341
|
-
|
|
376
|
+
} else if (CramFlagsDecoder.isDecodeSequenceAsStar(cramFlags)) {
|
|
377
|
+
readBases = null
|
|
378
|
+
qualityScores = null
|
|
342
379
|
} else {
|
|
343
|
-
const bases = new Array(
|
|
380
|
+
const bases = new Array(readLength) as number[]
|
|
344
381
|
for (let i = 0; i < bases.length; i += 1) {
|
|
345
382
|
bases[i] = decodeDataSeries('BA')
|
|
346
383
|
}
|
|
347
|
-
|
|
384
|
+
readBases = String.fromCharCode(...bases)
|
|
348
385
|
|
|
349
|
-
if (
|
|
386
|
+
if (CramFlagsDecoder.isPreservingQualityScores(cramFlags)) {
|
|
387
|
+
qualityScores = new Array(readLength)
|
|
350
388
|
for (let i = 0; i < bases.length; i += 1) {
|
|
351
|
-
|
|
389
|
+
qualityScores[i] = decodeDataSeries('QS')
|
|
352
390
|
}
|
|
353
|
-
|
|
354
|
-
cramRecord.qualityScores = bases
|
|
355
391
|
}
|
|
356
392
|
}
|
|
357
393
|
|
|
358
|
-
return
|
|
394
|
+
return {
|
|
395
|
+
readLength,
|
|
396
|
+
sequenceId,
|
|
397
|
+
cramFlags,
|
|
398
|
+
flags,
|
|
399
|
+
alignmentStart,
|
|
400
|
+
readGroupId,
|
|
401
|
+
readName,
|
|
402
|
+
mateToUse,
|
|
403
|
+
templateSize,
|
|
404
|
+
mateRecordNumber,
|
|
405
|
+
readFeatures,
|
|
406
|
+
lengthOnRef,
|
|
407
|
+
mappingQuality,
|
|
408
|
+
qualityScores,
|
|
409
|
+
readBases,
|
|
410
|
+
tags,
|
|
411
|
+
}
|
|
359
412
|
}
|