@gmod/bam 7.1.20 → 7.1.21
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/README.md +17 -9
- package/dist/bai.d.ts +2 -2
- package/dist/bai.js.map +1 -1
- package/dist/bamFile.d.ts +2 -1
- package/dist/bamFile.js +1 -0
- package/dist/bamFile.js.map +1 -1
- package/dist/chunk.d.ts +1 -1
- package/dist/htsget.d.ts +1 -1
- package/dist/htsget.js +13 -9
- package/dist/htsget.js.map +1 -1
- package/dist/indexFile.d.ts +2 -2
- package/dist/indexFile.js.map +1 -1
- package/dist/record.d.ts +10 -13
- package/dist/record.js +107 -120
- package/dist/record.js.map +1 -1
- package/dist/util.d.ts +2 -2
- package/dist/util.js +4 -7
- package/dist/util.js.map +1 -1
- package/esm/bai.d.ts +2 -2
- package/esm/bai.js +1 -1
- package/esm/bai.js.map +1 -1
- package/esm/bamFile.d.ts +2 -1
- package/esm/bamFile.js +1 -0
- package/esm/bamFile.js.map +1 -1
- package/esm/chunk.d.ts +1 -1
- package/esm/htsget.d.ts +1 -1
- package/esm/htsget.js +10 -9
- package/esm/htsget.js.map +1 -1
- package/esm/indexFile.d.ts +2 -2
- package/esm/indexFile.js.map +1 -1
- package/esm/record.d.ts +10 -13
- package/esm/record.js +107 -120
- package/esm/record.js.map +1 -1
- package/esm/util.d.ts +2 -2
- package/esm/util.js +4 -7
- package/esm/util.js.map +1 -1
- package/package.json +20 -25
- package/src/bai.ts +5 -7
- package/src/bamFile.ts +3 -1
- package/src/chunk.ts +1 -1
- package/src/htsget.ts +18 -14
- package/src/indexFile.ts +3 -2
- package/src/record.ts +130 -137
- package/src/util.ts +11 -11
package/src/record.ts
CHANGED
|
@@ -17,6 +17,8 @@ const ASCII_CIGAR_CODES = [
|
|
|
17
17
|
77, 73, 68, 78, 83, 72, 80, 61, 88, 63, 63, 63, 63, 63, 63, 63,
|
|
18
18
|
]
|
|
19
19
|
|
|
20
|
+
const textDecoder = new TextDecoder()
|
|
21
|
+
|
|
20
22
|
// Bitmask for ops that consume ref: M=0, D=2, N=3, P=6, ==7, X=8
|
|
21
23
|
// Binary: 0b111001101 = 0x1CD
|
|
22
24
|
const CIGAR_CONSUMES_REF_MASK = 0x1cd
|
|
@@ -27,55 +29,42 @@ export interface Bytes {
|
|
|
27
29
|
byteArray: Uint8Array
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
interface CIGAR_AND_LENGTH {
|
|
31
|
-
length_on_ref: number
|
|
32
|
-
NUMERIC_CIGAR: Uint32Array | number[]
|
|
33
|
-
}
|
|
34
|
-
|
|
35
32
|
export default class BamRecord {
|
|
36
33
|
public fileOffset: number
|
|
37
|
-
private
|
|
34
|
+
private _byteArray: Uint8Array
|
|
35
|
+
private _start: number
|
|
36
|
+
private _end: number
|
|
38
37
|
private _dataView: DataView
|
|
39
38
|
|
|
40
|
-
private _cachedFlags?: number
|
|
41
|
-
private _cachedRefId?: number
|
|
42
|
-
private _cachedStart?: number
|
|
43
39
|
private _cachedEnd?: number
|
|
44
40
|
private _cachedTags?: Record<string, unknown>
|
|
45
|
-
private
|
|
41
|
+
private _cachedLengthOnRef?: number
|
|
42
|
+
private _cachedNumericCigar?: Uint32Array | number[]
|
|
46
43
|
private _cachedNUMERIC_MD?: Uint8Array | null
|
|
47
44
|
private _cachedTagsStart?: number
|
|
48
45
|
|
|
49
|
-
constructor(args: { bytes: Bytes; fileOffset: number }) {
|
|
50
|
-
this.
|
|
46
|
+
constructor(args: { bytes: Bytes; fileOffset: number; dataView: DataView }) {
|
|
47
|
+
this._byteArray = args.bytes.byteArray
|
|
48
|
+
this._start = args.bytes.start
|
|
49
|
+
this._end = args.bytes.end
|
|
51
50
|
this.fileOffset = args.fileOffset
|
|
52
|
-
this._dataView =
|
|
51
|
+
this._dataView = args.dataView
|
|
53
52
|
}
|
|
54
53
|
|
|
55
54
|
get byteArray() {
|
|
56
|
-
return this.
|
|
55
|
+
return this._byteArray
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
get flags() {
|
|
60
|
-
|
|
61
|
-
this._cachedFlags =
|
|
62
|
-
(this._dataView.getInt32(this.bytes.start + 16, true) & 0xffff0000) >>
|
|
63
|
-
16
|
|
64
|
-
}
|
|
65
|
-
return this._cachedFlags
|
|
59
|
+
return (this._dataView.getInt32(this._start + 16, true) & 0xffff0000) >> 16
|
|
66
60
|
}
|
|
61
|
+
|
|
67
62
|
get ref_id() {
|
|
68
|
-
|
|
69
|
-
this._cachedRefId = this._dataView.getInt32(this.bytes.start + 4, true)
|
|
70
|
-
}
|
|
71
|
-
return this._cachedRefId
|
|
63
|
+
return this._dataView.getInt32(this._start + 4, true)
|
|
72
64
|
}
|
|
73
65
|
|
|
74
66
|
get start() {
|
|
75
|
-
|
|
76
|
-
this._cachedStart = this._dataView.getInt32(this.bytes.start + 8, true)
|
|
77
|
-
}
|
|
78
|
-
return this._cachedStart
|
|
67
|
+
return this._dataView.getInt32(this._start + 8, true)
|
|
79
68
|
}
|
|
80
69
|
|
|
81
70
|
get end() {
|
|
@@ -98,12 +87,13 @@ export default class BamRecord {
|
|
|
98
87
|
if (this.isSegmentUnmapped()) {
|
|
99
88
|
return null
|
|
100
89
|
} else {
|
|
90
|
+
const seqLen = this.seq_length
|
|
101
91
|
const p =
|
|
102
92
|
this.b0 +
|
|
103
93
|
this.read_name_length +
|
|
104
94
|
this.num_cigar_bytes +
|
|
105
|
-
|
|
106
|
-
return this.
|
|
95
|
+
((seqLen + 1) >> 1)
|
|
96
|
+
return this._byteArray.subarray(p, p + seqLen)
|
|
107
97
|
}
|
|
108
98
|
}
|
|
109
99
|
|
|
@@ -112,25 +102,27 @@ export default class BamRecord {
|
|
|
112
102
|
}
|
|
113
103
|
|
|
114
104
|
get b0() {
|
|
115
|
-
return this.
|
|
105
|
+
return this._start + 36
|
|
116
106
|
}
|
|
117
107
|
|
|
118
108
|
get tagsStart() {
|
|
119
109
|
if (this._cachedTagsStart === undefined) {
|
|
110
|
+
const seqLen = this.seq_length
|
|
120
111
|
this._cachedTagsStart =
|
|
121
112
|
this.b0 +
|
|
122
113
|
this.read_name_length +
|
|
123
114
|
this.num_cigar_bytes +
|
|
124
|
-
|
|
125
|
-
|
|
115
|
+
((seqLen + 1) >> 1) +
|
|
116
|
+
seqLen
|
|
126
117
|
}
|
|
127
118
|
return this._cachedTagsStart
|
|
128
119
|
}
|
|
120
|
+
|
|
129
121
|
// batch fromCharCode: fastest for typical name lengths (see benchmarks/string-building.bench.ts)
|
|
130
122
|
get name() {
|
|
131
123
|
const len = this.read_name_length - 1
|
|
132
124
|
const start = this.b0
|
|
133
|
-
const ba = this.
|
|
125
|
+
const ba = this._byteArray
|
|
134
126
|
const codes = new Array(len)
|
|
135
127
|
for (let i = 0; i < len; i++) {
|
|
136
128
|
codes[i] = ba[start + i]!
|
|
@@ -170,12 +162,12 @@ export default class BamRecord {
|
|
|
170
162
|
|
|
171
163
|
let p = this.tagsStart
|
|
172
164
|
|
|
173
|
-
const blockEnd = this.
|
|
174
|
-
const ba = this.
|
|
165
|
+
const blockEnd = this._end
|
|
166
|
+
const ba = this._byteArray
|
|
175
167
|
while (p < blockEnd) {
|
|
176
|
-
const currentTag1 = ba[p]
|
|
177
|
-
const currentTag2 = ba[p + 1]
|
|
178
|
-
const type = ba[p + 2]
|
|
168
|
+
const currentTag1 = ba[p]
|
|
169
|
+
const currentTag2 = ba[p + 1]
|
|
170
|
+
const type = ba[p + 2]
|
|
179
171
|
p += 3
|
|
180
172
|
|
|
181
173
|
const isMatch = currentTag1 === tag1 && currentTag2 === tag2
|
|
@@ -232,26 +224,21 @@ export default class BamRecord {
|
|
|
232
224
|
case 0x5a: // 'Z'
|
|
233
225
|
case 0x48: {
|
|
234
226
|
// 'H'
|
|
227
|
+
const start = p
|
|
228
|
+
while (p < blockEnd && ba[p] !== 0) {
|
|
229
|
+
p++
|
|
230
|
+
}
|
|
235
231
|
if (isMatch) {
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
p
|
|
239
|
-
}
|
|
240
|
-
if (raw) {
|
|
241
|
-
return ba.subarray(start, p)
|
|
242
|
-
}
|
|
243
|
-
const value = []
|
|
244
|
-
for (let i = start; i < p; i++) {
|
|
245
|
-
value.push(String.fromCharCode(ba[i]!))
|
|
246
|
-
}
|
|
247
|
-
return value.join('')
|
|
232
|
+
return raw
|
|
233
|
+
? ba.subarray(start, p)
|
|
234
|
+
: textDecoder.decode(ba.subarray(start, p))
|
|
248
235
|
}
|
|
249
|
-
|
|
236
|
+
p++ // advance past null terminator
|
|
250
237
|
break
|
|
251
238
|
}
|
|
252
239
|
case 0x42: {
|
|
253
240
|
// 'B'
|
|
254
|
-
const Btype = ba[p++]
|
|
241
|
+
const Btype = ba[p++]
|
|
255
242
|
const limit = this._dataView.getInt32(p, true)
|
|
256
243
|
p += 4
|
|
257
244
|
const absOffset = ba.byteOffset + p
|
|
@@ -331,9 +318,9 @@ export default class BamRecord {
|
|
|
331
318
|
private _computeTags() {
|
|
332
319
|
let p = this.tagsStart
|
|
333
320
|
|
|
334
|
-
const blockEnd = this.
|
|
335
|
-
const ba = this.
|
|
336
|
-
const tags
|
|
321
|
+
const blockEnd = this._end
|
|
322
|
+
const ba = this._byteArray
|
|
323
|
+
const tags: Record<string, unknown> = {}
|
|
337
324
|
while (p < blockEnd) {
|
|
338
325
|
const tag = String.fromCharCode(ba[p]!, ba[p + 1]!)
|
|
339
326
|
const type = ba[p + 2]!
|
|
@@ -375,21 +362,17 @@ export default class BamRecord {
|
|
|
375
362
|
case 0x5a: // 'Z'
|
|
376
363
|
case 0x48: {
|
|
377
364
|
// 'H'
|
|
378
|
-
const
|
|
379
|
-
while (p
|
|
380
|
-
|
|
381
|
-
if (cc !== 0) {
|
|
382
|
-
value.push(String.fromCharCode(cc))
|
|
383
|
-
} else {
|
|
384
|
-
break
|
|
385
|
-
}
|
|
365
|
+
const start = p
|
|
366
|
+
while (p < blockEnd && ba[p] !== 0) {
|
|
367
|
+
p++
|
|
386
368
|
}
|
|
387
|
-
tags[tag] =
|
|
369
|
+
tags[tag] = textDecoder.decode(ba.subarray(start, p))
|
|
370
|
+
p++ // advance past null terminator
|
|
388
371
|
break
|
|
389
372
|
}
|
|
390
373
|
case 0x42: {
|
|
391
374
|
// 'B'
|
|
392
|
-
const Btype = ba[p++]
|
|
375
|
+
const Btype = ba[p++]
|
|
393
376
|
const limit = this._dataView.getInt32(p, true)
|
|
394
377
|
p += 4
|
|
395
378
|
const absOffset = ba.byteOffset + p
|
|
@@ -520,13 +503,6 @@ export default class BamRecord {
|
|
|
520
503
|
return !!(this.flags & Constants.BAM_FSUPPLEMENTARY)
|
|
521
504
|
}
|
|
522
505
|
|
|
523
|
-
get cigarAndLength() {
|
|
524
|
-
if (this._cachedCigarAndLength === undefined) {
|
|
525
|
-
this._cachedCigarAndLength = this._computeCigarAndLength()
|
|
526
|
-
}
|
|
527
|
-
return this._cachedCigarAndLength
|
|
528
|
-
}
|
|
529
|
-
|
|
530
506
|
// Benchmark results for CIGAR parsing strategies (see benchmarks/cigar-lifecycle.bench.ts):
|
|
531
507
|
//
|
|
532
508
|
// Aligned data:
|
|
@@ -545,78 +521,94 @@ export default class BamRecord {
|
|
|
545
521
|
//
|
|
546
522
|
// Strategy: use plain array with |0 for small aligned (≤50 ops) and all unaligned,
|
|
547
523
|
// Uint32Array view only for large aligned CIGARs.
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
524
|
+
|
|
525
|
+
// CG tag pattern: first op is soft-clip consuming entire sequence, second op is N encoding length-on-ref
|
|
526
|
+
private _isCGTagPattern(p: number) {
|
|
527
|
+
const cigop = this._dataView.getInt32(p, true)
|
|
528
|
+
return (cigop & 0xf) === CIGAR_SOFT_CLIP && cigop >> 4 === this.seq_length
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
private _computeLengthOnRef(): number {
|
|
532
|
+
const flag_nc = this._dataView.getInt32(this._start + 16, true)
|
|
533
|
+
if (flag_nc & (Constants.BAM_FUNMAP << 16)) {
|
|
534
|
+
return 0
|
|
554
535
|
}
|
|
555
536
|
|
|
556
|
-
const numCigarOps =
|
|
557
|
-
|
|
537
|
+
const numCigarOps = flag_nc & 0xffff
|
|
538
|
+
const p = this.b0 + this.read_name_length
|
|
558
539
|
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
const lop = cigop >> 4
|
|
563
|
-
const op = cigop & 0xf
|
|
564
|
-
if (op === CIGAR_SOFT_CLIP && lop === this.seq_length) {
|
|
565
|
-
// if there is a CG the second CIGAR field will be a N tag the represents
|
|
566
|
-
// the length on ref
|
|
567
|
-
p += 4
|
|
568
|
-
const cigop = this._dataView.getInt32(p, true)
|
|
569
|
-
const lop = cigop >> 4
|
|
570
|
-
const op = cigop & 0xf
|
|
571
|
-
if (op !== CIGAR_REF_SKIP) {
|
|
540
|
+
if (this._isCGTagPattern(p)) {
|
|
541
|
+
const cigop2 = this._dataView.getInt32(p + 4, true)
|
|
542
|
+
if ((cigop2 & 0xf) !== CIGAR_REF_SKIP) {
|
|
572
543
|
console.warn('CG tag with no N tag')
|
|
573
544
|
}
|
|
574
|
-
|
|
575
|
-
return {
|
|
576
|
-
NUMERIC_CIGAR: cgArray,
|
|
577
|
-
length_on_ref: lop,
|
|
578
|
-
}
|
|
545
|
+
return cigop2 >> 4
|
|
579
546
|
}
|
|
580
547
|
|
|
581
|
-
const absOffset = this.
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
if (isAligned && numCigarOps > 50) {
|
|
548
|
+
const absOffset = this._byteArray.byteOffset + p
|
|
549
|
+
if (absOffset % 4 === 0 && numCigarOps > 50) {
|
|
585
550
|
const cigarView = new Uint32Array(
|
|
586
|
-
this.
|
|
551
|
+
this._byteArray.buffer,
|
|
587
552
|
absOffset,
|
|
588
553
|
numCigarOps,
|
|
589
554
|
)
|
|
555
|
+
this._cachedNumericCigar = cigarView
|
|
590
556
|
let lref = 0
|
|
591
557
|
for (let c = 0; c < numCigarOps; ++c) {
|
|
592
|
-
const
|
|
593
|
-
lref += (
|
|
594
|
-
}
|
|
595
|
-
return {
|
|
596
|
-
NUMERIC_CIGAR: cigarView,
|
|
597
|
-
length_on_ref: lref,
|
|
558
|
+
const co = cigarView[c]!
|
|
559
|
+
lref += (co >> 4) * ((CIGAR_CONSUMES_REF_MASK >> (co & 0xf)) & 1)
|
|
598
560
|
}
|
|
561
|
+
return lref
|
|
599
562
|
}
|
|
600
563
|
|
|
601
|
-
const cigarArray: number[] = new Array(numCigarOps)
|
|
602
564
|
let lref = 0
|
|
603
565
|
for (let c = 0; c < numCigarOps; ++c) {
|
|
604
|
-
const
|
|
605
|
-
|
|
606
|
-
lref += (cigop >> 4) * ((CIGAR_CONSUMES_REF_MASK >> (cigop & 0xf)) & 1)
|
|
566
|
+
const co = this._dataView.getInt32(p + c * 4, true)
|
|
567
|
+
lref += (co >> 4) * ((CIGAR_CONSUMES_REF_MASK >> (co & 0xf)) & 1)
|
|
607
568
|
}
|
|
608
|
-
return
|
|
609
|
-
|
|
610
|
-
|
|
569
|
+
return lref
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
private _computeNumericCigar(): Uint32Array | number[] {
|
|
573
|
+
const flag_nc = this._dataView.getInt32(this._start + 16, true)
|
|
574
|
+
if (flag_nc & (Constants.BAM_FUNMAP << 16)) {
|
|
575
|
+
return new Uint32Array(0)
|
|
611
576
|
}
|
|
577
|
+
|
|
578
|
+
const numCigarOps = flag_nc & 0xffff
|
|
579
|
+
const p = this.b0 + this.read_name_length
|
|
580
|
+
|
|
581
|
+
if (this._isCGTagPattern(p)) {
|
|
582
|
+
return (
|
|
583
|
+
(this.tags.CG as Uint32Array | number[] | undefined) ??
|
|
584
|
+
new Uint32Array(0)
|
|
585
|
+
)
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const absOffset = this._byteArray.byteOffset + p
|
|
589
|
+
if (absOffset % 4 === 0 && numCigarOps > 50) {
|
|
590
|
+
return new Uint32Array(this._byteArray.buffer, absOffset, numCigarOps)
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const cigarArray: number[] = new Array(numCigarOps)
|
|
594
|
+
for (let c = 0; c < numCigarOps; ++c) {
|
|
595
|
+
cigarArray[c] = this._dataView.getInt32(p + c * 4, true) | 0
|
|
596
|
+
}
|
|
597
|
+
return cigarArray
|
|
612
598
|
}
|
|
613
599
|
|
|
614
600
|
get length_on_ref() {
|
|
615
|
-
|
|
601
|
+
if (this._cachedLengthOnRef === undefined) {
|
|
602
|
+
this._cachedLengthOnRef = this._computeLengthOnRef()
|
|
603
|
+
}
|
|
604
|
+
return this._cachedLengthOnRef
|
|
616
605
|
}
|
|
617
606
|
|
|
618
607
|
get NUMERIC_CIGAR() {
|
|
619
|
-
|
|
608
|
+
if (this._cachedNumericCigar === undefined) {
|
|
609
|
+
this._cachedNumericCigar = this._computeNumericCigar()
|
|
610
|
+
}
|
|
611
|
+
return this._cachedNumericCigar
|
|
620
612
|
}
|
|
621
613
|
|
|
622
614
|
get CIGAR() {
|
|
@@ -649,25 +641,26 @@ export default class BamRecord {
|
|
|
649
641
|
|
|
650
642
|
get NUMERIC_SEQ() {
|
|
651
643
|
const p = this.b0 + this.read_name_length + this.num_cigar_bytes
|
|
652
|
-
return this.
|
|
644
|
+
return this._byteArray.subarray(p, p + this.num_seq_bytes)
|
|
653
645
|
}
|
|
654
646
|
|
|
655
647
|
get seq() {
|
|
656
|
-
const numeric = this.NUMERIC_SEQ
|
|
657
648
|
const len = this.seq_length
|
|
649
|
+
const seqStart = this.b0 + this.read_name_length + this.num_cigar_bytes
|
|
650
|
+
const numeric = this._byteArray
|
|
658
651
|
const buf = new Array(len)
|
|
659
652
|
let i = 0
|
|
660
653
|
const fullBytes = len >> 1
|
|
661
654
|
|
|
662
655
|
for (let j = 0; j < fullBytes; ++j) {
|
|
663
|
-
const sb = numeric[j]!
|
|
664
|
-
buf[i++] = SEQRET_DECODER[(sb & 0xf0) >> 4]
|
|
665
|
-
buf[i++] = SEQRET_DECODER[sb & 0x0f]
|
|
656
|
+
const sb = numeric[seqStart + j]!
|
|
657
|
+
buf[i++] = SEQRET_DECODER[(sb & 0xf0) >> 4]!
|
|
658
|
+
buf[i++] = SEQRET_DECODER[sb & 0x0f]!
|
|
666
659
|
}
|
|
667
660
|
|
|
668
661
|
if (i < len) {
|
|
669
|
-
const sb = numeric[fullBytes]!
|
|
670
|
-
buf[i] = SEQRET_DECODER[(sb & 0xf0) >> 4]
|
|
662
|
+
const sb = numeric[seqStart + fullBytes]!
|
|
663
|
+
buf[i] = SEQRET_DECODER[(sb & 0xf0) >> 4]!
|
|
671
664
|
}
|
|
672
665
|
|
|
673
666
|
return buf.join('')
|
|
@@ -691,40 +684,40 @@ export default class BamRecord {
|
|
|
691
684
|
}
|
|
692
685
|
|
|
693
686
|
get bin_mq_nl() {
|
|
694
|
-
return this._dataView.getInt32(this.
|
|
687
|
+
return this._dataView.getInt32(this._start + 12, true)
|
|
695
688
|
}
|
|
696
689
|
|
|
697
690
|
get flag_nc() {
|
|
698
|
-
return this._dataView.getInt32(this.
|
|
691
|
+
return this._dataView.getInt32(this._start + 16, true)
|
|
699
692
|
}
|
|
700
693
|
|
|
701
694
|
get seq_length() {
|
|
702
|
-
return this._dataView.getInt32(this.
|
|
695
|
+
return this._dataView.getInt32(this._start + 20, true)
|
|
703
696
|
}
|
|
704
697
|
|
|
705
698
|
get next_refid() {
|
|
706
|
-
return this._dataView.getInt32(this.
|
|
699
|
+
return this._dataView.getInt32(this._start + 24, true)
|
|
707
700
|
}
|
|
708
701
|
|
|
709
702
|
get next_pos() {
|
|
710
|
-
return this._dataView.getInt32(this.
|
|
703
|
+
return this._dataView.getInt32(this._start + 28, true)
|
|
711
704
|
}
|
|
712
705
|
|
|
713
706
|
get template_length() {
|
|
714
|
-
return this._dataView.getInt32(this.
|
|
707
|
+
return this._dataView.getInt32(this._start + 32, true)
|
|
715
708
|
}
|
|
716
709
|
|
|
717
710
|
seqAt(idx: number): string | undefined {
|
|
718
711
|
if (idx < this.seq_length) {
|
|
719
712
|
const byteIndex = idx >> 1
|
|
720
713
|
const sb =
|
|
721
|
-
this.
|
|
714
|
+
this._byteArray[
|
|
722
715
|
this.b0 + this.read_name_length + this.num_cigar_bytes + byteIndex
|
|
723
716
|
]!
|
|
724
717
|
|
|
725
718
|
return idx % 2 === 0
|
|
726
|
-
? SEQRET_DECODER[(sb & 0xf0) >> 4]
|
|
727
|
-
: SEQRET_DECODER[sb & 0x0f]
|
|
719
|
+
? SEQRET_DECODER[(sb & 0xf0) >> 4]!
|
|
720
|
+
: SEQRET_DECODER[sb & 0x0f]!
|
|
728
721
|
} else {
|
|
729
722
|
return undefined
|
|
730
723
|
}
|
|
@@ -733,10 +726,10 @@ export default class BamRecord {
|
|
|
733
726
|
toJSON() {
|
|
734
727
|
const data: Record<string, unknown> = {}
|
|
735
728
|
for (const k of Object.keys(this)) {
|
|
736
|
-
if (k.startsWith('_')
|
|
729
|
+
if (k.startsWith('_')) {
|
|
737
730
|
continue
|
|
738
731
|
}
|
|
739
|
-
// @ts-
|
|
732
|
+
// @ts-expect-error
|
|
740
733
|
data[k] = this[k]
|
|
741
734
|
}
|
|
742
735
|
|
package/src/util.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import Chunk from './chunk.ts'
|
|
2
1
|
import { longFromBytesToUnsigned } from './long.ts'
|
|
3
|
-
|
|
2
|
+
|
|
3
|
+
import type Chunk from './chunk.ts'
|
|
4
|
+
import type { Offset, VirtualOffset } from './virtualOffset.ts'
|
|
4
5
|
|
|
5
6
|
export function canMergeBlocks(chunk1: Chunk, chunk2: Chunk) {
|
|
6
7
|
return (
|
|
@@ -33,7 +34,7 @@ export interface BaseOpts {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
export function makeOpts(obj: AbortSignal | BaseOpts = {}): BaseOpts {
|
|
36
|
-
return 'aborted' in obj ?
|
|
37
|
+
return 'aborted' in obj ? { signal: obj } : obj
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
export function optimizeChunks(chunks: Chunk[], lowest?: Offset) {
|
|
@@ -126,23 +127,22 @@ export function parseNameBytes(
|
|
|
126
127
|
namesBytes: Uint8Array,
|
|
127
128
|
renameRefSeq: (arg: string) => string = s => s,
|
|
128
129
|
) {
|
|
130
|
+
const decoder = new TextDecoder()
|
|
129
131
|
let currRefId = 0
|
|
130
132
|
let currNameStart = 0
|
|
131
|
-
const refIdToName = []
|
|
133
|
+
const refIdToName: string[] = []
|
|
132
134
|
const refNameToId: Record<string, number> = {}
|
|
133
|
-
for (let i = 0; i < namesBytes.length; i
|
|
135
|
+
for (let i = 0; i < namesBytes.length; i++) {
|
|
134
136
|
if (!namesBytes[i]) {
|
|
135
137
|
if (currNameStart < i) {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
}
|
|
140
|
-
refName = renameRefSeq(refName)
|
|
138
|
+
const refName = renameRefSeq(
|
|
139
|
+
decoder.decode(namesBytes.subarray(currNameStart, i)),
|
|
140
|
+
)
|
|
141
141
|
refIdToName[currRefId] = refName
|
|
142
142
|
refNameToId[refName] = currRefId
|
|
143
143
|
}
|
|
144
144
|
currNameStart = i + 1
|
|
145
|
-
currRefId
|
|
145
|
+
currRefId++
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
148
|
return { refNameToId, refIdToName }
|