@gmod/bam 3.0.2 → 4.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/src/record.ts CHANGED
@@ -53,10 +53,6 @@ export default class BamRecord {
53
53
  }
54
54
 
55
55
  get qual() {
56
- return this.qualRaw?.join(' ')
57
- }
58
-
59
- get qualRaw() {
60
56
  if (this.isSegmentUnmapped()) {
61
57
  return
62
58
  }
@@ -100,160 +96,124 @@ export default class BamRecord {
100
96
  const type = String.fromCharCode(byteArray[p + 2])
101
97
  p += 3
102
98
 
103
- let value
104
- switch (type) {
105
- case 'A': {
106
- value = String.fromCharCode(byteArray[p])
107
- p += 1
108
- break
109
- }
110
- case 'i': {
111
- value = byteArray.readInt32LE(p)
112
- p += 4
113
- break
114
- }
115
- case 'I': {
116
- value = byteArray.readUInt32LE(p)
117
- p += 4
118
- break
119
- }
120
- case 'c': {
121
- value = byteArray.readInt8(p)
122
- p += 1
123
- break
124
- }
125
- case 'C': {
126
- value = byteArray.readUInt8(p)
127
- p += 1
128
- break
129
- }
130
- case 's': {
131
- value = byteArray.readInt16LE(p)
132
- p += 2
133
- break
134
- }
135
- case 'S': {
136
- value = byteArray.readUInt16LE(p)
137
- p += 2
138
- break
139
- }
140
- case 'f': {
141
- value = byteArray.readFloatLE(p)
142
- p += 4
143
- break
144
- }
145
- case 'Z':
146
- case 'H': {
147
- value = ''
148
- while (p <= blockEnd) {
149
- const cc = byteArray[p++]
150
- if (cc === 0) {
151
- break
152
- } else {
153
- value += String.fromCharCode(cc)
154
- }
155
- }
156
- break
157
- }
158
- case 'B': {
159
- value = ''
99
+ if (type === 'A') {
100
+ tags[tag] = String.fromCharCode(byteArray[p])
101
+ p += 1
102
+ } else if (type === 'i') {
103
+ tags[tag] = byteArray.readInt32LE(p)
104
+ p += 4
105
+ } else if (type === 'I') {
106
+ tags[tag] = byteArray.readUInt32LE(p)
107
+ p += 4
108
+ } else if (type === 'c') {
109
+ tags[tag] = byteArray.readInt8(p)
110
+ p += 1
111
+ } else if (type === 'C') {
112
+ tags[tag] = byteArray.readUInt8(p)
113
+ p += 1
114
+ } else if (type === 's') {
115
+ tags[tag] = byteArray.readInt16LE(p)
116
+ p += 2
117
+ } else if (type === 'S') {
118
+ tags[tag] = byteArray.readUInt16LE(p)
119
+ p += 2
120
+ } else if (type === 'f') {
121
+ tags[tag] = byteArray.readFloatLE(p)
122
+ p += 4
123
+ } else if (type === 'Z' || type === 'H') {
124
+ const value = []
125
+ while (p <= blockEnd) {
160
126
  const cc = byteArray[p++]
161
- const Btype = String.fromCharCode(cc)
162
- const limit = byteArray.readInt32LE(p)
163
- p += 4
164
- if (Btype === 'i') {
165
- if (tag === 'CG') {
166
- for (let k = 0; k < limit; k++) {
167
- const cigop = byteArray.readInt32LE(p)
168
- const lop = cigop >> 4
169
- const op = CIGAR_DECODER[cigop & 0xf]
170
- value += lop + op
171
- p += 4
172
- }
173
- } else {
174
- for (let k = 0; k < limit; k++) {
175
- value += byteArray.readInt32LE(p)
176
- if (k + 1 < limit) {
177
- value += ','
178
- }
179
- p += 4
180
- }
181
- }
182
- }
183
- if (Btype === 'I') {
184
- if (tag === 'CG') {
185
- for (let k = 0; k < limit; k++) {
186
- const cigop = byteArray.readUInt32LE(p)
187
- const lop = cigop >> 4
188
- const op = CIGAR_DECODER[cigop & 0xf]
189
- value += lop + op
190
- p += 4
191
- }
192
- } else {
193
- for (let k = 0; k < limit; k++) {
194
- value += byteArray.readUInt32LE(p)
195
- if (k + 1 < limit) {
196
- value += ','
197
- }
198
- p += 4
199
- }
200
- }
127
+ if (cc !== 0) {
128
+ value.push(String.fromCharCode(cc))
129
+ } else {
130
+ break
201
131
  }
202
- if (Btype === 's') {
203
- for (let k = 0; k < limit; k++) {
204
- value += byteArray.readInt16LE(p)
205
- if (k + 1 < limit) {
206
- value += ','
207
- }
208
- p += 2
209
- }
210
- }
211
- if (Btype === 'S') {
132
+ }
133
+ tags[tag] = value.join('')
134
+ } else if (type === 'B') {
135
+ const cc = byteArray[p++]
136
+ const Btype = String.fromCharCode(cc)
137
+ const limit = byteArray.readInt32LE(p)
138
+ p += 4
139
+ if (Btype === 'i') {
140
+ if (tag === 'CG') {
141
+ const value = []
212
142
  for (let k = 0; k < limit; k++) {
213
- value += byteArray.readUInt16LE(p)
214
- if (k + 1 < limit) {
215
- value += ','
216
- }
217
- p += 2
143
+ const cigop = byteArray.readInt32LE(p)
144
+ const lop = cigop >> 4
145
+ const op = CIGAR_DECODER[cigop & 0xf]
146
+ value.push(lop + op)
147
+ p += 4
218
148
  }
219
- }
220
- if (Btype === 'c') {
149
+ tags[tag] = value.join('')
150
+ } else {
151
+ const value = []
221
152
  for (let k = 0; k < limit; k++) {
222
- value += byteArray.readInt8(p)
223
- if (k + 1 < limit) {
224
- value += ','
225
- }
226
- p += 1
153
+ value.push(byteArray.readInt32LE(p))
154
+ p += 4
227
155
  }
156
+ tags[tag] = value
228
157
  }
229
- if (Btype === 'C') {
158
+ } else if (Btype === 'I') {
159
+ if (tag === 'CG') {
160
+ const value = []
230
161
  for (let k = 0; k < limit; k++) {
231
- value += byteArray.readUInt8(p)
232
- if (k + 1 < limit) {
233
- value += ','
234
- }
235
- p += 1
162
+ const cigop = byteArray.readUInt32LE(p)
163
+ const lop = cigop >> 4
164
+ const op = CIGAR_DECODER[cigop & 0xf]
165
+ value.push(lop + op)
166
+ p += 4
236
167
  }
237
- }
238
- if (Btype === 'f') {
168
+ tags[tag] = value.join('')
169
+ } else {
170
+ const value = []
239
171
  for (let k = 0; k < limit; k++) {
240
- value += byteArray.readFloatLE(p)
241
- if (k + 1 < limit) {
242
- value += ','
243
- }
172
+ value.push(byteArray.readUInt32LE(p))
244
173
  p += 4
245
174
  }
175
+ tags[tag] = value
176
+ }
177
+ } else if (Btype === 's') {
178
+ const value = []
179
+ for (let k = 0; k < limit; k++) {
180
+ value.push(byteArray.readInt16LE(p))
181
+ p += 2
182
+ }
183
+ tags[tag] = value
184
+ } else if (Btype === 'S') {
185
+ const value = []
186
+ for (let k = 0; k < limit; k++) {
187
+ value.push(byteArray.readUInt16LE(p))
188
+ p += 2
189
+ }
190
+ tags[tag] = value
191
+ } else if (Btype === 'c') {
192
+ const value = []
193
+ for (let k = 0; k < limit; k++) {
194
+ value.push(byteArray.readInt8(p))
195
+ p += 1
246
196
  }
247
- break
197
+ tags[tag] = value
198
+ } else if (Btype === 'C') {
199
+ const value = []
200
+ for (let k = 0; k < limit; k++) {
201
+ value.push(byteArray.readUInt8(p))
202
+ p += 1
203
+ }
204
+ tags[tag] = value
205
+ } else if (Btype === 'f') {
206
+ const value = []
207
+ for (let k = 0; k < limit; k++) {
208
+ value.push(byteArray.readFloatLE(p))
209
+ p += 4
210
+ }
211
+ tags[tag] = value
248
212
  }
249
- default: {
250
- console.warn(`Unknown BAM tag type '${type}', tags may be incomplete`)
251
- value = undefined
252
- p = blockEnd
253
- } // stop parsing tags
213
+ } else {
214
+ console.error('Unknown BAM tag type', type)
215
+ break
254
216
  }
255
-
256
- tags[tag] = value
257
217
  }
258
218
  return tags
259
219
  }
@@ -331,7 +291,7 @@ export default class BamRecord {
331
291
 
332
292
  const numCigarOps = this.num_cigar_ops
333
293
  let p = this.b0 + this.read_name_length
334
- let CIGAR = ''
294
+ const CIGAR = []
335
295
 
336
296
  // check for CG tag by inspecting whether the CIGAR field contains a clip
337
297
  // that consumes entire seqLen
@@ -358,9 +318,9 @@ export default class BamRecord {
358
318
  cigop = this.byteArray.readInt32LE(p)
359
319
  lop = cigop >> 4
360
320
  op = CIGAR_DECODER[cigop & 0xf]
361
- CIGAR += lop + op
362
- // soft clip, hard clip, and insertion don't count toward
363
- // the length on the reference
321
+ CIGAR.push(lop + op)
322
+ // soft clip, hard clip, and insertion don't count toward the length on
323
+ // the reference
364
324
  if (op !== 'H' && op !== 'S' && op !== 'I') {
365
325
  lref += lop
366
326
  }
@@ -369,7 +329,7 @@ export default class BamRecord {
369
329
  }
370
330
 
371
331
  return {
372
- CIGAR,
332
+ CIGAR: CIGAR.join(''),
373
333
  length_on_ref: lref,
374
334
  }
375
335
  }
@@ -400,18 +360,18 @@ export default class BamRecord {
400
360
  const p = this.b0 + this.read_name_length + this.num_cigar_ops * 4
401
361
  const seqBytes = this.num_seq_bytes
402
362
  const len = this.seq_length
403
- let buf = ''
363
+ const buf = []
404
364
  let i = 0
405
365
  for (let j = 0; j < seqBytes; ++j) {
406
366
  const sb = byteArray[p + j]
407
- buf += SEQRET_DECODER[(sb & 0xf0) >> 4]
367
+ buf.push(SEQRET_DECODER[(sb & 0xf0) >> 4])
408
368
  i++
409
369
  if (i < len) {
410
- buf += SEQRET_DECODER[sb & 0x0f]
370
+ buf.push(SEQRET_DECODER[sb & 0x0f])
411
371
  i++
412
372
  }
413
373
  }
414
- return buf
374
+ return buf.join('')
415
375
  }
416
376
 
417
377
  // adapted from igv.js