@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.
Files changed (255) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/craiIndex.d.ts +19 -12
  3. package/dist/craiIndex.js +63 -123
  4. package/dist/craiIndex.js.map +1 -1
  5. package/dist/cram-bundle.js +2 -17
  6. package/dist/cram-bundle.js.LICENSE.txt +17 -0
  7. package/dist/cramFile/codecs/_base.d.ts +26 -5
  8. package/dist/cramFile/codecs/_base.js +3 -39
  9. package/dist/cramFile/codecs/_base.js.map +1 -1
  10. package/dist/cramFile/codecs/beta.d.ts +7 -3
  11. package/dist/cramFile/codecs/beta.js +13 -31
  12. package/dist/cramFile/codecs/beta.js.map +1 -1
  13. package/dist/cramFile/codecs/byteArrayLength.d.ts +13 -7
  14. package/dist/cramFile/codecs/byteArrayLength.js +22 -41
  15. package/dist/cramFile/codecs/byteArrayLength.js.map +1 -1
  16. package/dist/cramFile/codecs/byteArrayStop.d.ts +9 -5
  17. package/dist/cramFile/codecs/byteArrayStop.js +25 -46
  18. package/dist/cramFile/codecs/byteArrayStop.js.map +1 -1
  19. package/dist/cramFile/codecs/dataSeriesTypes.d.ts +4 -0
  20. package/dist/cramFile/codecs/dataSeriesTypes.js +3 -0
  21. package/dist/cramFile/codecs/dataSeriesTypes.js.map +1 -0
  22. package/dist/cramFile/codecs/external.d.ts +10 -6
  23. package/dist/cramFile/codecs/external.js +26 -44
  24. package/dist/cramFile/codecs/external.js.map +1 -1
  25. package/dist/cramFile/codecs/gamma.d.ts +7 -3
  26. package/dist/cramFile/codecs/gamma.js +16 -34
  27. package/dist/cramFile/codecs/gamma.js.map +1 -1
  28. package/dist/cramFile/codecs/getBits.d.ts +7 -0
  29. package/dist/cramFile/codecs/getBits.js +26 -0
  30. package/dist/cramFile/codecs/getBits.js.map +1 -0
  31. package/dist/cramFile/codecs/huffman.d.ts +17 -13
  32. package/dist/cramFile/codecs/huffman.js +76 -85
  33. package/dist/cramFile/codecs/huffman.js.map +1 -1
  34. package/dist/cramFile/codecs/index.d.ts +4 -2
  35. package/dist/cramFile/codecs/index.js +12 -13
  36. package/dist/cramFile/codecs/index.js.map +1 -1
  37. package/dist/cramFile/codecs/subexp.d.ts +7 -3
  38. package/dist/cramFile/codecs/subexp.js +19 -36
  39. package/dist/cramFile/codecs/subexp.js.map +1 -1
  40. package/dist/cramFile/constants.d.ts +35 -35
  41. package/dist/cramFile/constants.js +1 -1
  42. package/dist/cramFile/constants.js.map +1 -1
  43. package/dist/cramFile/container/compressionScheme.d.ts +57 -11
  44. package/dist/cramFile/container/compressionScheme.js +37 -32
  45. package/dist/cramFile/container/compressionScheme.js.map +1 -1
  46. package/dist/cramFile/container/index.d.ts +23 -9
  47. package/dist/cramFile/container/index.js +74 -144
  48. package/dist/cramFile/container/index.js.map +1 -1
  49. package/dist/cramFile/encoding.d.ts +78 -0
  50. package/dist/cramFile/encoding.js +3 -0
  51. package/dist/cramFile/encoding.js.map +1 -0
  52. package/dist/cramFile/file.d.ts +91 -41
  53. package/dist/cramFile/file.js +234 -368
  54. package/dist/cramFile/file.js.map +1 -1
  55. package/dist/cramFile/filehandle.d.ts +2 -0
  56. package/dist/cramFile/filehandle.js +3 -0
  57. package/dist/cramFile/filehandle.js.map +1 -0
  58. package/dist/cramFile/index.d.ts +1 -1
  59. package/dist/cramFile/index.js +1 -1
  60. package/dist/cramFile/index.js.map +1 -1
  61. package/dist/cramFile/record.d.ts +61 -17
  62. package/dist/cramFile/record.js +153 -77
  63. package/dist/cramFile/record.js.map +1 -1
  64. package/dist/cramFile/sectionParsers.d.ts +99 -8
  65. package/dist/cramFile/sectionParsers.js +70 -80
  66. package/dist/cramFile/sectionParsers.js.map +1 -1
  67. package/dist/cramFile/slice/decodeRecord.d.ts +30 -2
  68. package/dist/cramFile/slice/decodeRecord.js +148 -118
  69. package/dist/cramFile/slice/decodeRecord.js.map +1 -1
  70. package/dist/cramFile/slice/index.d.ts +21 -14
  71. package/dist/cramFile/slice/index.js +286 -381
  72. package/dist/cramFile/slice/index.js.map +1 -1
  73. package/dist/cramFile/util.d.ts +11 -5
  74. package/dist/cramFile/util.js +19 -97
  75. package/dist/cramFile/util.js.map +1 -1
  76. package/dist/errors.d.ts +5 -10
  77. package/dist/errors.js +11 -62
  78. package/dist/errors.js.map +1 -1
  79. package/dist/index.d.ts +3 -3
  80. package/dist/index.js +3 -3
  81. package/dist/index.js.map +1 -1
  82. package/dist/indexedCramFile.d.ts +37 -12
  83. package/dist/indexedCramFile.js +114 -154
  84. package/dist/indexedCramFile.js.map +1 -1
  85. package/dist/io/index.d.ts +5 -5
  86. package/dist/io/index.js +9 -9
  87. package/dist/io/index.js.map +1 -1
  88. package/dist/rans/constants.js +3 -3
  89. package/dist/rans/constants.js.map +1 -1
  90. package/dist/rans/d04.js +15 -15
  91. package/dist/rans/d04.js.map +1 -1
  92. package/dist/rans/d14.js +21 -21
  93. package/dist/rans/d14.js.map +1 -1
  94. package/dist/rans/decoding.js +27 -30
  95. package/dist/rans/decoding.js.map +1 -1
  96. package/dist/rans/frequencies.js +11 -11
  97. package/dist/rans/frequencies.js.map +1 -1
  98. package/dist/rans/index.js +46 -49
  99. package/dist/rans/index.js.map +1 -1
  100. package/dist/sam.d.ts +8 -1
  101. package/dist/sam.js +7 -7
  102. package/dist/sam.js.map +1 -1
  103. package/dist/typescript.d.ts +3 -0
  104. package/dist/typescript.js +11 -0
  105. package/dist/typescript.js.map +1 -0
  106. package/dist/unzip-pako.js +1 -1
  107. package/dist/unzip-pako.js.map +1 -1
  108. package/dist/unzip.js +1 -1
  109. package/dist/unzip.js.map +1 -1
  110. package/errors.js +11 -62
  111. package/esm/craiIndex.d.ts +19 -12
  112. package/esm/craiIndex.js +8 -24
  113. package/esm/craiIndex.js.map +1 -1
  114. package/esm/cramFile/codecs/_base.d.ts +26 -5
  115. package/esm/cramFile/codecs/_base.js +1 -35
  116. package/esm/cramFile/codecs/_base.js.map +1 -1
  117. package/esm/cramFile/codecs/beta.d.ts +7 -3
  118. package/esm/cramFile/codecs/beta.js +4 -3
  119. package/esm/cramFile/codecs/beta.js.map +1 -1
  120. package/esm/cramFile/codecs/byteArrayLength.d.ts +13 -7
  121. package/esm/cramFile/codecs/byteArrayLength.js +1 -1
  122. package/esm/cramFile/codecs/byteArrayLength.js.map +1 -1
  123. package/esm/cramFile/codecs/byteArrayStop.d.ts +9 -5
  124. package/esm/cramFile/codecs/byteArrayStop.js +7 -9
  125. package/esm/cramFile/codecs/byteArrayStop.js.map +1 -1
  126. package/esm/cramFile/codecs/dataSeriesTypes.d.ts +4 -0
  127. package/esm/cramFile/codecs/dataSeriesTypes.js +2 -0
  128. package/esm/cramFile/codecs/dataSeriesTypes.js.map +1 -0
  129. package/esm/cramFile/codecs/external.d.ts +10 -6
  130. package/esm/cramFile/codecs/external.js +4 -3
  131. package/esm/cramFile/codecs/external.js.map +1 -1
  132. package/esm/cramFile/codecs/gamma.d.ts +7 -3
  133. package/esm/cramFile/codecs/gamma.js +5 -4
  134. package/esm/cramFile/codecs/gamma.js.map +1 -1
  135. package/esm/cramFile/codecs/getBits.d.ts +7 -0
  136. package/esm/cramFile/codecs/getBits.js +21 -0
  137. package/esm/cramFile/codecs/getBits.js.map +1 -0
  138. package/esm/cramFile/codecs/huffman.d.ts +17 -13
  139. package/esm/cramFile/codecs/huffman.js +22 -9
  140. package/esm/cramFile/codecs/huffman.js.map +1 -1
  141. package/esm/cramFile/codecs/index.d.ts +4 -2
  142. package/esm/cramFile/codecs/index.js +1 -1
  143. package/esm/cramFile/codecs/index.js.map +1 -1
  144. package/esm/cramFile/codecs/subexp.d.ts +7 -3
  145. package/esm/cramFile/codecs/subexp.js +7 -5
  146. package/esm/cramFile/codecs/subexp.js.map +1 -1
  147. package/esm/cramFile/constants.d.ts +35 -35
  148. package/esm/cramFile/constants.js.map +1 -1
  149. package/esm/cramFile/container/compressionScheme.d.ts +57 -11
  150. package/esm/cramFile/container/compressionScheme.js +15 -8
  151. package/esm/cramFile/container/compressionScheme.js.map +1 -1
  152. package/esm/cramFile/container/index.d.ts +23 -9
  153. package/esm/cramFile/container/index.js +11 -9
  154. package/esm/cramFile/container/index.js.map +1 -1
  155. package/esm/cramFile/encoding.d.ts +78 -0
  156. package/esm/cramFile/encoding.js +2 -0
  157. package/esm/cramFile/encoding.js.map +1 -0
  158. package/esm/cramFile/file.d.ts +91 -41
  159. package/esm/cramFile/file.js +59 -47
  160. package/esm/cramFile/file.js.map +1 -1
  161. package/esm/cramFile/filehandle.d.ts +2 -0
  162. package/esm/cramFile/filehandle.js +2 -0
  163. package/esm/cramFile/filehandle.js.map +1 -0
  164. package/esm/cramFile/index.d.ts +1 -1
  165. package/esm/cramFile/index.js.map +1 -1
  166. package/esm/cramFile/record.d.ts +61 -17
  167. package/esm/cramFile/record.js +83 -5
  168. package/esm/cramFile/record.js.map +1 -1
  169. package/esm/cramFile/sectionParsers.d.ts +99 -8
  170. package/esm/cramFile/sectionParsers.js +7 -17
  171. package/esm/cramFile/sectionParsers.js.map +1 -1
  172. package/esm/cramFile/slice/decodeRecord.d.ts +30 -2
  173. package/esm/cramFile/slice/decodeRecord.js +102 -70
  174. package/esm/cramFile/slice/decodeRecord.js.map +1 -1
  175. package/esm/cramFile/slice/index.d.ts +21 -14
  176. package/esm/cramFile/slice/index.js +77 -38
  177. package/esm/cramFile/slice/index.js.map +1 -1
  178. package/esm/cramFile/util.d.ts +11 -5
  179. package/esm/cramFile/util.js +11 -82
  180. package/esm/cramFile/util.js.map +1 -1
  181. package/esm/errors.d.ts +5 -10
  182. package/esm/errors.js +0 -5
  183. package/esm/errors.js.map +1 -1
  184. package/esm/index.d.ts +3 -3
  185. package/esm/index.js.map +1 -1
  186. package/esm/indexedCramFile.d.ts +37 -12
  187. package/esm/indexedCramFile.js +19 -8
  188. package/esm/indexedCramFile.js.map +1 -1
  189. package/esm/io/index.d.ts +5 -5
  190. package/esm/io/index.js +3 -3
  191. package/esm/io/index.js.map +1 -1
  192. package/esm/sam.d.ts +8 -1
  193. package/esm/sam.js.map +1 -1
  194. package/esm/typescript.d.ts +3 -0
  195. package/esm/typescript.js +7 -0
  196. package/esm/typescript.js.map +1 -0
  197. package/package.json +18 -11
  198. package/src/{craiIndex.js → craiIndex.ts} +37 -31
  199. package/src/cramFile/codecs/_base.ts +45 -0
  200. package/src/cramFile/codecs/beta.ts +34 -0
  201. package/src/cramFile/codecs/{byteArrayLength.js → byteArrayLength.ts} +27 -5
  202. package/src/cramFile/codecs/{byteArrayStop.js → byteArrayStop.ts} +25 -12
  203. package/src/cramFile/codecs/dataSeriesTypes.ts +39 -0
  204. package/src/cramFile/codecs/{external.js → external.ts} +28 -12
  205. package/src/cramFile/codecs/gamma.ts +42 -0
  206. package/src/cramFile/codecs/getBits.ts +28 -0
  207. package/src/cramFile/codecs/{huffman.js → huffman.ts} +48 -15
  208. package/src/cramFile/codecs/{index.js → index.ts} +9 -3
  209. package/src/cramFile/codecs/subexp.ts +45 -0
  210. package/src/cramFile/{constants.js → constants.ts} +0 -0
  211. package/src/cramFile/container/{compressionScheme.js → compressionScheme.ts} +50 -18
  212. package/src/cramFile/container/{index.js → index.ts} +13 -13
  213. package/src/cramFile/encoding.ts +98 -0
  214. package/src/cramFile/{file.js → file.ts} +136 -62
  215. package/src/cramFile/filehandle.ts +3 -0
  216. package/src/cramFile/{index.js → index.ts} +0 -0
  217. package/src/cramFile/{record.js → record.ts} +185 -14
  218. package/src/cramFile/{sectionParsers.js → sectionParsers.ts} +148 -20
  219. package/src/cramFile/slice/{decodeRecord.js → decodeRecord.ts} +158 -105
  220. package/src/cramFile/slice/{index.js → index.ts} +138 -63
  221. package/src/cramFile/{util.js → util.ts} +28 -17
  222. package/src/{errors.js → errors.ts} +0 -5
  223. package/src/{index.js → index.ts} +0 -0
  224. package/src/{indexedCramFile.js → indexedCramFile.ts} +79 -19
  225. package/src/io/{index.js → index.ts} +10 -5
  226. package/src/{sam.js → sam.ts} +7 -2
  227. package/src/typescript.ts +17 -0
  228. package/src/typings/binary-parser.d.ts +44 -0
  229. package/src/typings/bzip2.d.ts +7 -0
  230. package/src/typings/htscodecs.d.ts +6 -0
  231. package/dist/io/bufferCache.d.ts +0 -12
  232. package/dist/io/bufferCache.js +0 -112
  233. package/dist/io/bufferCache.js.map +0 -1
  234. package/dist/io/localFile.d.ts +0 -10
  235. package/dist/io/localFile.js +0 -108
  236. package/dist/io/localFile.js.map +0 -1
  237. package/dist/io/remoteFile.d.ts +0 -16
  238. package/dist/io/remoteFile.js +0 -143
  239. package/dist/io/remoteFile.js.map +0 -1
  240. package/esm/io/bufferCache.d.ts +0 -12
  241. package/esm/io/bufferCache.js +0 -54
  242. package/esm/io/bufferCache.js.map +0 -1
  243. package/esm/io/localFile.d.ts +0 -10
  244. package/esm/io/localFile.js +0 -31
  245. package/esm/io/localFile.js.map +0 -1
  246. package/esm/io/remoteFile.d.ts +0 -16
  247. package/esm/io/remoteFile.js +0 -64
  248. package/esm/io/remoteFile.js.map +0 -1
  249. package/src/cramFile/codecs/_base.js +0 -49
  250. package/src/cramFile/codecs/beta.js +0 -23
  251. package/src/cramFile/codecs/gamma.js +0 -30
  252. package/src/cramFile/codecs/subexp.js +0 -32
  253. package/src/io/bufferCache.js +0 -66
  254. package/src/io/localFile.js +0 -35
  255. 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 CramRecord from '../record'
4
- import Constants from '../constants'
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
- function parseTagData(tagType, buffer) {
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
- cramRecord,
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 = cramRecord.alignmentStart - 1
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
- readFeature.data = decodeRFData(data1Schema)
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
- readFeature.data = [readFeature.data, decodeRFData(data2Schema)]
185
+ data = [data, decodeRFData(data2Schema)]
170
186
  }
171
187
 
172
188
  currentReadPos += readPosDelta
173
- readFeature.pos = currentReadPos
189
+ const pos = currentReadPos
174
190
 
175
191
  currentRefPos += readPosDelta
176
- readFeature.refPos = currentRefPos
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 += readFeature.data
196
+ currentRefPos += data
181
197
  } else if (code === 'I' || code === 'S') {
182
- currentRefPos -= readFeature.data.length
198
+ currentRefPos -= data.length
183
199
  } else if (code === 'i') {
184
200
  currentRefPos -= 1
185
201
  }
186
202
 
187
- readFeatures[i] = readFeature
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
- const cramRecord = new CramRecord()
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
- cramRecord.cramFlags = decodeDataSeries('CF')
228
+ const cramFlags = decodeDataSeries('CF') as number
229
+
230
+ if (!isMappedSliceHeader(sliceHeader.parsedContent)) {
231
+ throw new Error()
232
+ }
211
233
 
212
- if (majorVersion > 1 && sliceHeader.content.refSeqId === -2) {
213
- cramRecord.sequenceId = decodeDataSeries('RI')
234
+ let sequenceId
235
+ if (majorVersion > 1 && sliceHeader.parsedContent.refSeqId === -2) {
236
+ sequenceId = decodeDataSeries('RI')
214
237
  } else {
215
- cramRecord.sequenceId = sliceHeader.content.refSeqId
238
+ sequenceId = sliceHeader.parsedContent.refSeqId
216
239
  }
217
240
 
218
- cramRecord.readLength = decodeDataSeries('RL')
241
+ const readLength = decodeDataSeries('RL')
219
242
  // if APDelta, will calculate the true start in a second pass
220
- cramRecord.alignmentStart = decodeDataSeries('AP')
243
+ let alignmentStart = decodeDataSeries('AP')
221
244
  if (compressionScheme.APdelta) {
222
- cramRecord.alignmentStart += cursors.lastAlignmentStart
245
+ alignmentStart = alignmentStart + cursors.lastAlignmentStart
223
246
  }
224
- cursors.lastAlignmentStart = cramRecord.alignmentStart
225
- cramRecord.readGroupId = decodeDataSeries('RG')
247
+ cursors.lastAlignmentStart = alignmentStart
248
+ const readGroupId = decodeDataSeries('RG')
226
249
 
250
+ let readName
227
251
  if (compressionScheme.readNamesIncluded) {
228
- cramRecord.readName = readNullTerminatedString(decodeDataSeries('RN'))
252
+ readName = readNullTerminatedString(decodeDataSeries('RN'))
229
253
  }
230
254
 
255
+ let mateToUse
256
+ let templateSize
257
+ let mateRecordNumber
231
258
  // mate record
232
- if (cramRecord.isDetached()) {
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
- mate.flags = decodeDataSeries('MF')
261
+ // const mate: any = {}
262
+ const mateFlags = decodeDataSeries('MF') as number
263
+ let mateReadName
236
264
  if (!compressionScheme.readNamesIncluded) {
237
- mate.readName = readNullTerminatedString(decodeDataSeries('RN'))
238
- cramRecord.readName = mate.readName
265
+ mateReadName = readNullTerminatedString(decodeDataSeries('RN'))
266
+ readName = mateReadName
239
267
  }
240
- mate.sequenceId = decodeDataSeries('NS')
241
- mate.alignmentStart = decodeDataSeries('NP')
242
- if (mate.flags || mate.sequenceId > -1) {
243
- cramRecord.mate = mate
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
- cramRecord.templateSize = decodeDataSeries('TS')
278
+
279
+ templateSize = decodeDataSeries('TS')
246
280
 
247
281
  // set mate unmapped if needed
248
- if (mate.flags & Constants.CRAM_M_UNMAP) {
249
- cramRecord.flags |= Constants.BAM_FMUNMAP
282
+ if (MateFlagsDecoder.isUnmapped(mateFlags)) {
283
+ flags = BamFlagsDecoder.setMateUnmapped(flags)
250
284
  }
251
285
  // set mate reversed if needed
252
- if (mate.flags & Constants.CRAM_M_REVERSE) {
253
- cramRecord.flags |= Constants.BAM_FMREVERSE
286
+ if (MateFlagsDecoder.isOnNegativeStrand(mateFlags)) {
287
+ flags = BamFlagsDecoder.setMateReverseComplemented(flags)
254
288
  }
255
289
 
256
290
  // detachedCount++
257
- } else if (cramRecord.hasMateDownStream()) {
258
- cramRecord.mateRecordNumber = decodeDataSeries('NF') + recordNumber + 1
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
- cramRecord.tags[tagName] = parseTagData(tagType, tagData)
325
+ tags[tagName] = parseTagData(tagType, tagData)
291
326
  }
292
327
 
293
- if (!cramRecord.isSegmentUnmapped()) {
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 /* int */ readFeatureCount = decodeDataSeries('FN')
335
+ const readFeatureCount = decodeDataSeries('FN') as number
296
336
  if (readFeatureCount) {
297
- cramRecord.readFeatures = decodeReadFeatures(
298
- cramRecord,
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
- let lengthOnRef = cramRecord.readLength
308
- if (cramRecord.readFeatures) {
309
- cramRecord.readFeatures.forEach(({ code, data }) => {
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 -= data.length
353
+ lengthOnRef = lengthOnRef - data.length
314
354
  } else if (code === 'i') {
315
- lengthOnRef -= 1
355
+ lengthOnRef = lengthOnRef - 1
316
356
  }
317
- })
357
+ }
318
358
  }
319
359
  if (Number.isNaN(lengthOnRef)) {
320
360
  console.warn(
321
361
  `${
322
- cramRecord.readName ||
323
- `${cramRecord.sequenceId}:${cramRecord.alignmentStart}`
362
+ readName || `${sequenceId}:${alignmentStart}`
324
363
  } record has invalid read features`,
325
364
  )
326
- lengthOnRef = cramRecord.readLength
365
+ lengthOnRef = readLength
327
366
  }
328
- cramRecord.lengthOnRef = lengthOnRef
329
367
 
330
368
  // mapping quality
331
- cramRecord.mappingQuality = decodeDataSeries('MQ')
332
- if (cramRecord.isPreservingQualityScores()) {
333
- const bases = new Array(cramRecord.readLength)
334
- for (let i = 0; i < bases.length; i += 1) {
335
- bases[i] = decodeDataSeries('QS')
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 (cramRecord.isUnknownBases()) {
340
- cramRecord.readBases = null
341
- cramRecord.qualityScores = null
376
+ } else if (CramFlagsDecoder.isDecodeSequenceAsStar(cramFlags)) {
377
+ readBases = null
378
+ qualityScores = null
342
379
  } else {
343
- const bases = new Array(cramRecord.readLength)
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
- cramRecord.readBases = String.fromCharCode(...bases)
384
+ readBases = String.fromCharCode(...bases)
348
385
 
349
- if (cramRecord.isPreservingQualityScores()) {
386
+ if (CramFlagsDecoder.isPreservingQualityScores(cramFlags)) {
387
+ qualityScores = new Array(readLength)
350
388
  for (let i = 0; i < bases.length; i += 1) {
351
- bases[i] = decodeDataSeries('QS')
389
+ qualityScores[i] = decodeDataSeries('QS')
352
390
  }
353
-
354
- cramRecord.qualityScores = bases
355
391
  }
356
392
  }
357
393
 
358
- return cramRecord
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
  }