@gmod/bam 7.1.3 → 7.1.5
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 +4 -6
- package/dist/cigar.d.ts +9 -0
- package/dist/cigar.js +13 -0
- package/dist/cigar.js.map +1 -0
- package/dist/record.d.ts +12 -20
- package/dist/record.js +148 -163
- package/dist/record.js.map +1 -1
- package/esm/cigar.d.ts +9 -0
- package/esm/cigar.js +10 -0
- package/esm/cigar.js.map +1 -0
- package/esm/record.d.ts +12 -20
- package/esm/record.js +145 -160
- package/esm/record.js.map +1 -1
- package/package.json +1 -1
- package/src/cigar.ts +9 -0
- package/src/record.ts +170 -201
package/CHANGELOG.md
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
## [7.1.
|
|
1
|
+
## [7.1.5](https://github.com/GMOD/bam-js/compare/v7.1.4...v7.1.5) (2025-12-13)
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
## [7.1.
|
|
5
|
+
## [7.1.4](https://github.com/GMOD/bam-js/compare/v7.1.3...v7.1.4) (2025-12-13)
|
|
6
6
|
|
|
7
|
+
## [7.1.3](https://github.com/GMOD/bam-js/compare/v7.1.2...v7.1.3) (2025-12-12)
|
|
7
8
|
|
|
9
|
+
## [7.1.2](https://github.com/GMOD/bam-js/compare/v7.1.1...v7.1.2) (2025-12-12)
|
|
8
10
|
|
|
9
11
|
## [7.1.1](https://github.com/GMOD/bam-js/compare/v7.1.0...v7.1.1) (2025-12-12)
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
13
|
# [7.1.0](https://github.com/GMOD/bam-js/compare/v7.0.6...v7.1.0) (2025-12-11)
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
15
|
## [7.0.6](https://github.com/GMOD/bam-js/compare/v7.0.5...v7.0.6) (2025-11-28)
|
|
18
16
|
|
|
19
17
|
## [7.0.5](https://github.com/GMOD/bam-js/compare/v7.0.4...v7.0.5) (2025-11-27)
|
package/dist/cigar.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const CIGAR_MATCH = 0;
|
|
2
|
+
export declare const CIGAR_INS = 1;
|
|
3
|
+
export declare const CIGAR_DEL = 2;
|
|
4
|
+
export declare const CIGAR_REF_SKIP = 3;
|
|
5
|
+
export declare const CIGAR_SOFT_CLIP = 4;
|
|
6
|
+
export declare const CIGAR_HARD_CLIP = 5;
|
|
7
|
+
export declare const CIGAR_PAD = 6;
|
|
8
|
+
export declare const CIGAR_EQUAL = 7;
|
|
9
|
+
export declare const CIGAR_DIFF = 8;
|
package/dist/cigar.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CIGAR_DIFF = exports.CIGAR_EQUAL = exports.CIGAR_PAD = exports.CIGAR_HARD_CLIP = exports.CIGAR_SOFT_CLIP = exports.CIGAR_REF_SKIP = exports.CIGAR_DEL = exports.CIGAR_INS = exports.CIGAR_MATCH = void 0;
|
|
4
|
+
exports.CIGAR_MATCH = 0;
|
|
5
|
+
exports.CIGAR_INS = 1;
|
|
6
|
+
exports.CIGAR_DEL = 2;
|
|
7
|
+
exports.CIGAR_REF_SKIP = 3;
|
|
8
|
+
exports.CIGAR_SOFT_CLIP = 4;
|
|
9
|
+
exports.CIGAR_HARD_CLIP = 5;
|
|
10
|
+
exports.CIGAR_PAD = 6;
|
|
11
|
+
exports.CIGAR_EQUAL = 7;
|
|
12
|
+
exports.CIGAR_DIFF = 8;
|
|
13
|
+
//# sourceMappingURL=cigar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cigar.js","sourceRoot":"","sources":["../src/cigar.ts"],"names":[],"mappings":";;;AAAa,QAAA,WAAW,GAAG,CAAC,CAAA;AACf,QAAA,SAAS,GAAG,CAAC,CAAA;AACb,QAAA,SAAS,GAAG,CAAC,CAAA;AACb,QAAA,cAAc,GAAG,CAAC,CAAA;AAClB,QAAA,eAAe,GAAG,CAAC,CAAA;AACnB,QAAA,eAAe,GAAG,CAAC,CAAA;AACnB,QAAA,SAAS,GAAG,CAAC,CAAA;AACb,QAAA,WAAW,GAAG,CAAC,CAAA;AACf,QAAA,UAAU,GAAG,CAAC,CAAA"}
|
package/dist/record.d.ts
CHANGED
|
@@ -3,10 +3,18 @@ interface Bytes {
|
|
|
3
3
|
end: number;
|
|
4
4
|
byteArray: Uint8Array;
|
|
5
5
|
}
|
|
6
|
+
interface CIGAR_AND_LENGTH {
|
|
7
|
+
length_on_ref: number;
|
|
8
|
+
NUMERIC_CIGAR: Uint32Array;
|
|
9
|
+
}
|
|
6
10
|
export default class BamRecord {
|
|
7
11
|
fileOffset: number;
|
|
8
12
|
private bytes;
|
|
9
13
|
private _dataView;
|
|
14
|
+
private _cachedFlags?;
|
|
15
|
+
private _cachedTags?;
|
|
16
|
+
private _cachedCigarAndLength?;
|
|
17
|
+
private _cachedNUMERIC_MD?;
|
|
10
18
|
constructor(args: {
|
|
11
19
|
bytes: Bytes;
|
|
12
20
|
fileOffset: number;
|
|
@@ -19,43 +27,27 @@ export default class BamRecord {
|
|
|
19
27
|
get id(): number;
|
|
20
28
|
get mq(): number | undefined;
|
|
21
29
|
get score(): number | undefined;
|
|
22
|
-
get qual(): Uint8Array<ArrayBufferLike> |
|
|
30
|
+
get qual(): Uint8Array<ArrayBufferLike> | null;
|
|
23
31
|
get strand(): 1 | -1;
|
|
24
32
|
get b0(): number;
|
|
25
33
|
get name(): string;
|
|
26
34
|
get NUMERIC_MD(): Uint8Array<ArrayBufferLike> | undefined;
|
|
27
35
|
get tags(): Record<string, unknown>;
|
|
28
|
-
|
|
29
|
-
* @returns {boolean} true if the read is paired, regardless of whether both
|
|
30
|
-
* segments are mapped
|
|
31
|
-
*/
|
|
36
|
+
private _computeTags;
|
|
32
37
|
isPaired(): boolean;
|
|
33
|
-
/** @returns {boolean} true if the read is paired, and both segments are mapped */
|
|
34
38
|
isProperlyPaired(): boolean;
|
|
35
|
-
/** @returns {boolean} true if the read itself is unmapped; conflictive with isProperlyPaired */
|
|
36
39
|
isSegmentUnmapped(): boolean;
|
|
37
|
-
/** @returns {boolean} true if the read itself is unmapped; conflictive with isProperlyPaired */
|
|
38
40
|
isMateUnmapped(): boolean;
|
|
39
|
-
/** @returns {boolean} true if the read is mapped to the reverse strand */
|
|
40
41
|
isReverseComplemented(): boolean;
|
|
41
|
-
/** @returns {boolean} true if the mate is mapped to the reverse strand */
|
|
42
42
|
isMateReverseComplemented(): boolean;
|
|
43
|
-
/** @returns {boolean} true if this is read number 1 in a pair */
|
|
44
43
|
isRead1(): boolean;
|
|
45
|
-
/** @returns {boolean} true if this is read number 2 in a pair */
|
|
46
44
|
isRead2(): boolean;
|
|
47
|
-
/** @returns {boolean} true if this is a secondary alignment */
|
|
48
45
|
isSecondary(): boolean;
|
|
49
|
-
/** @returns {boolean} true if this read has failed QC checks */
|
|
50
46
|
isFailedQc(): boolean;
|
|
51
|
-
/** @returns {boolean} true if the read is an optical or PCR duplicate */
|
|
52
47
|
isDuplicate(): boolean;
|
|
53
|
-
/** @returns {boolean} true if this is a supplementary alignment */
|
|
54
48
|
isSupplementary(): boolean;
|
|
55
|
-
get cigarAndLength():
|
|
56
|
-
|
|
57
|
-
length_on_ref: number;
|
|
58
|
-
};
|
|
49
|
+
get cigarAndLength(): CIGAR_AND_LENGTH;
|
|
50
|
+
private _computeCigarAndLength;
|
|
59
51
|
get length_on_ref(): number;
|
|
60
52
|
get NUMERIC_CIGAR(): Uint32Array<ArrayBufferLike>;
|
|
61
53
|
get CIGAR(): string;
|
package/dist/record.js
CHANGED
|
@@ -3,20 +3,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const cigar_ts_1 = require("./cigar.js");
|
|
6
7
|
const constants_ts_1 = __importDefault(require("./constants.js"));
|
|
7
8
|
const SEQRET_DECODER = '=ACMGRSVTWYHKDBN'.split('');
|
|
8
9
|
const ASCII_CIGAR_CODES = [
|
|
9
10
|
77, 73, 68, 78, 83, 72, 80, 61, 88, 63, 63, 63, 63, 63, 63, 63,
|
|
10
11
|
];
|
|
11
|
-
// const CIGAR_MATCH = 0
|
|
12
|
-
const CIGAR_INS = 1;
|
|
13
|
-
// const CIGAR_DEL = 2
|
|
14
|
-
const CIGAR_REF_SKIP = 3;
|
|
15
|
-
const CIGAR_SOFT_CLIP = 4;
|
|
16
|
-
const CIGAR_HARD_CLIP = 5;
|
|
17
|
-
// const CIGAR_PAD = 6
|
|
18
12
|
// ops that don't consume reference: INS, SOFT_CLIP, HARD_CLIP
|
|
19
|
-
const CIGAR_SKIP_MASK = (1 << CIGAR_INS) | (1 << CIGAR_SOFT_CLIP) | (1 << CIGAR_HARD_CLIP);
|
|
13
|
+
const CIGAR_SKIP_MASK = (1 << cigar_ts_1.CIGAR_INS) | (1 << cigar_ts_1.CIGAR_SOFT_CLIP) | (1 << cigar_ts_1.CIGAR_HARD_CLIP);
|
|
20
14
|
class BamRecord {
|
|
21
15
|
constructor(args) {
|
|
22
16
|
this.bytes = args.bytes;
|
|
@@ -27,7 +21,12 @@ class BamRecord {
|
|
|
27
21
|
return this.bytes.byteArray;
|
|
28
22
|
}
|
|
29
23
|
get flags() {
|
|
30
|
-
|
|
24
|
+
if (this._cachedFlags === undefined) {
|
|
25
|
+
this._cachedFlags =
|
|
26
|
+
(this._dataView.getInt32(this.bytes.start + 16, true) & 0xffff0000) >>
|
|
27
|
+
16;
|
|
28
|
+
}
|
|
29
|
+
return this._cachedFlags;
|
|
31
30
|
}
|
|
32
31
|
get ref_id() {
|
|
33
32
|
return this._dataView.getInt32(this.bytes.start + 4, true);
|
|
@@ -50,13 +49,15 @@ class BamRecord {
|
|
|
50
49
|
}
|
|
51
50
|
get qual() {
|
|
52
51
|
if (this.isSegmentUnmapped()) {
|
|
53
|
-
return;
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const p = this.b0 +
|
|
56
|
+
this.read_name_length +
|
|
57
|
+
this.num_cigar_bytes +
|
|
58
|
+
this.num_seq_bytes;
|
|
59
|
+
return this.byteArray.subarray(p, p + this.seq_length);
|
|
54
60
|
}
|
|
55
|
-
const p = this.b0 +
|
|
56
|
-
this.read_name_length +
|
|
57
|
-
this.num_cigar_bytes +
|
|
58
|
-
this.num_seq_bytes;
|
|
59
|
-
return this.byteArray.subarray(p, p + this.seq_length);
|
|
60
61
|
}
|
|
61
62
|
get strand() {
|
|
62
63
|
return this.isReverseComplemented() ? -1 : 1;
|
|
@@ -72,115 +73,127 @@ class BamRecord {
|
|
|
72
73
|
return str;
|
|
73
74
|
}
|
|
74
75
|
get NUMERIC_MD() {
|
|
75
|
-
|
|
76
|
-
this.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
switch (type) {
|
|
94
|
-
case 'A':
|
|
95
|
-
p += 1;
|
|
96
|
-
break;
|
|
97
|
-
case 'i':
|
|
98
|
-
case 'I':
|
|
99
|
-
case 'f':
|
|
100
|
-
p += 4;
|
|
101
|
-
break;
|
|
102
|
-
case 'c':
|
|
103
|
-
case 'C':
|
|
104
|
-
p += 1;
|
|
105
|
-
break;
|
|
106
|
-
case 's':
|
|
107
|
-
case 'S':
|
|
108
|
-
p += 2;
|
|
109
|
-
break;
|
|
110
|
-
case 'Z':
|
|
111
|
-
case 'H':
|
|
112
|
-
while (p <= blockEnd && this.byteArray[p++] !== 0) { }
|
|
113
|
-
break;
|
|
114
|
-
case 'B': {
|
|
115
|
-
const Btype = String.fromCharCode(this.byteArray[p++]);
|
|
116
|
-
const limit = this._dataView.getInt32(p, true);
|
|
117
|
-
p += 4;
|
|
118
|
-
if (Btype === 'i' || Btype === 'I' || Btype === 'f') {
|
|
119
|
-
p += limit << 2;
|
|
120
|
-
}
|
|
121
|
-
else if (Btype === 's' || Btype === 'S') {
|
|
122
|
-
p += limit << 1;
|
|
76
|
+
if (this._cachedNUMERIC_MD === undefined) {
|
|
77
|
+
let p = this.b0 +
|
|
78
|
+
this.read_name_length +
|
|
79
|
+
this.num_cigar_bytes +
|
|
80
|
+
this.num_seq_bytes +
|
|
81
|
+
this.seq_length;
|
|
82
|
+
const blockEnd = this.bytes.end;
|
|
83
|
+
const ba = this.byteArray;
|
|
84
|
+
while (p < blockEnd) {
|
|
85
|
+
const tag1 = ba[p];
|
|
86
|
+
const tag2 = ba[p + 1];
|
|
87
|
+
const type = ba[p + 2];
|
|
88
|
+
p += 3;
|
|
89
|
+
// 'M' = 0x4D, 'D' = 0x44, 'Z' = 0x5A
|
|
90
|
+
if (tag1 === 0x4d && tag2 === 0x44 && type === 0x5a) {
|
|
91
|
+
const start = p;
|
|
92
|
+
while (p < blockEnd && ba[p] !== 0) {
|
|
93
|
+
p++;
|
|
123
94
|
}
|
|
124
|
-
|
|
125
|
-
|
|
95
|
+
this._cachedNUMERIC_MD = ba.subarray(start, p);
|
|
96
|
+
}
|
|
97
|
+
switch (type) {
|
|
98
|
+
case 0x41: // 'A'
|
|
99
|
+
p += 1;
|
|
100
|
+
break;
|
|
101
|
+
case 0x69: // 'i'
|
|
102
|
+
case 0x49: // 'I'
|
|
103
|
+
case 0x66: // 'f'
|
|
104
|
+
p += 4;
|
|
105
|
+
break;
|
|
106
|
+
case 0x63: // 'c'
|
|
107
|
+
case 0x43: // 'C'
|
|
108
|
+
p += 1;
|
|
109
|
+
break;
|
|
110
|
+
case 0x73: // 's'
|
|
111
|
+
case 0x53: // 'S'
|
|
112
|
+
p += 2;
|
|
113
|
+
break;
|
|
114
|
+
case 0x5a: // 'Z'
|
|
115
|
+
case 0x48: // 'H'
|
|
116
|
+
while (p <= blockEnd && ba[p++] !== 0) { }
|
|
117
|
+
break;
|
|
118
|
+
case 0x42: {
|
|
119
|
+
// 'B'
|
|
120
|
+
const Btype = ba[p++];
|
|
121
|
+
const limit = this._dataView.getInt32(p, true);
|
|
122
|
+
p += 4;
|
|
123
|
+
if (Btype === 0x69 || Btype === 0x49 || Btype === 0x66) {
|
|
124
|
+
p += limit << 2;
|
|
125
|
+
}
|
|
126
|
+
else if (Btype === 0x73 || Btype === 0x53) {
|
|
127
|
+
p += limit << 1;
|
|
128
|
+
}
|
|
129
|
+
else if (Btype === 0x63 || Btype === 0x43) {
|
|
130
|
+
p += limit;
|
|
131
|
+
}
|
|
132
|
+
break;
|
|
126
133
|
}
|
|
127
|
-
break;
|
|
128
134
|
}
|
|
129
135
|
}
|
|
130
136
|
}
|
|
131
|
-
return undefined;
|
|
137
|
+
return this._cachedNUMERIC_MD === null ? undefined : this._cachedNUMERIC_MD;
|
|
132
138
|
}
|
|
133
139
|
get tags() {
|
|
140
|
+
if (this._cachedTags === undefined) {
|
|
141
|
+
this._cachedTags = this._computeTags();
|
|
142
|
+
}
|
|
143
|
+
return this._cachedTags;
|
|
144
|
+
}
|
|
145
|
+
_computeTags() {
|
|
134
146
|
let p = this.b0 +
|
|
135
147
|
this.read_name_length +
|
|
136
148
|
this.num_cigar_bytes +
|
|
137
149
|
this.num_seq_bytes +
|
|
138
150
|
this.seq_length;
|
|
139
151
|
const blockEnd = this.bytes.end;
|
|
152
|
+
const ba = this.byteArray;
|
|
140
153
|
const tags = {};
|
|
141
154
|
while (p < blockEnd) {
|
|
142
|
-
const tag = String.fromCharCode(
|
|
143
|
-
|
|
144
|
-
const type = String.fromCharCode(this.byteArray[p + 2]);
|
|
155
|
+
const tag = String.fromCharCode(ba[p], ba[p + 1]);
|
|
156
|
+
const type = ba[p + 2];
|
|
145
157
|
p += 3;
|
|
146
158
|
switch (type) {
|
|
147
|
-
case 'A'
|
|
148
|
-
tags[tag] = String.fromCharCode(
|
|
159
|
+
case 0x41: // 'A'
|
|
160
|
+
tags[tag] = String.fromCharCode(ba[p]);
|
|
149
161
|
p += 1;
|
|
150
162
|
break;
|
|
151
|
-
case 'i'
|
|
163
|
+
case 0x69: // 'i'
|
|
152
164
|
tags[tag] = this._dataView.getInt32(p, true);
|
|
153
165
|
p += 4;
|
|
154
166
|
break;
|
|
155
|
-
case 'I'
|
|
167
|
+
case 0x49: // 'I'
|
|
156
168
|
tags[tag] = this._dataView.getUint32(p, true);
|
|
157
169
|
p += 4;
|
|
158
170
|
break;
|
|
159
|
-
case 'c'
|
|
171
|
+
case 0x63: // 'c'
|
|
160
172
|
tags[tag] = this._dataView.getInt8(p);
|
|
161
173
|
p += 1;
|
|
162
174
|
break;
|
|
163
|
-
case 'C'
|
|
175
|
+
case 0x43: // 'C'
|
|
164
176
|
tags[tag] = this._dataView.getUint8(p);
|
|
165
177
|
p += 1;
|
|
166
178
|
break;
|
|
167
|
-
case 's'
|
|
179
|
+
case 0x73: // 's'
|
|
168
180
|
tags[tag] = this._dataView.getInt16(p, true);
|
|
169
181
|
p += 2;
|
|
170
182
|
break;
|
|
171
|
-
case 'S'
|
|
183
|
+
case 0x53: // 'S'
|
|
172
184
|
tags[tag] = this._dataView.getUint16(p, true);
|
|
173
185
|
p += 2;
|
|
174
186
|
break;
|
|
175
|
-
case 'f'
|
|
187
|
+
case 0x66: // 'f'
|
|
176
188
|
tags[tag] = this._dataView.getFloat32(p, true);
|
|
177
189
|
p += 4;
|
|
178
190
|
break;
|
|
179
|
-
case 'Z'
|
|
180
|
-
case
|
|
191
|
+
case 0x5a: // 'Z'
|
|
192
|
+
case 0x48: {
|
|
193
|
+
// 'H'
|
|
181
194
|
const value = [];
|
|
182
195
|
while (p <= blockEnd) {
|
|
183
|
-
const cc =
|
|
196
|
+
const cc = ba[p++];
|
|
184
197
|
if (cc !== 0) {
|
|
185
198
|
value.push(String.fromCharCode(cc));
|
|
186
199
|
}
|
|
@@ -191,66 +204,73 @@ class BamRecord {
|
|
|
191
204
|
tags[tag] = value.join('');
|
|
192
205
|
break;
|
|
193
206
|
}
|
|
194
|
-
case
|
|
195
|
-
|
|
196
|
-
const Btype =
|
|
207
|
+
case 0x42: {
|
|
208
|
+
// 'B'
|
|
209
|
+
const Btype = ba[p++];
|
|
197
210
|
const limit = this._dataView.getInt32(p, true);
|
|
198
211
|
p += 4;
|
|
199
|
-
const absOffset =
|
|
200
|
-
if (Btype ===
|
|
212
|
+
const absOffset = ba.byteOffset + p;
|
|
213
|
+
if (Btype === 0x69) {
|
|
214
|
+
// 'i'
|
|
201
215
|
if (absOffset % 4 === 0) {
|
|
202
|
-
tags[tag] = new Int32Array(
|
|
216
|
+
tags[tag] = new Int32Array(ba.buffer, absOffset, limit);
|
|
203
217
|
}
|
|
204
218
|
else {
|
|
205
|
-
const bytes =
|
|
219
|
+
const bytes = ba.slice(p, p + (limit << 2));
|
|
206
220
|
tags[tag] = new Int32Array(bytes.buffer, bytes.byteOffset, limit);
|
|
207
221
|
}
|
|
208
222
|
p += limit << 2;
|
|
209
223
|
}
|
|
210
|
-
else if (Btype ===
|
|
224
|
+
else if (Btype === 0x49) {
|
|
225
|
+
// 'I'
|
|
211
226
|
if (absOffset % 4 === 0) {
|
|
212
|
-
tags[tag] = new Uint32Array(
|
|
227
|
+
tags[tag] = new Uint32Array(ba.buffer, absOffset, limit);
|
|
213
228
|
}
|
|
214
229
|
else {
|
|
215
|
-
const bytes =
|
|
230
|
+
const bytes = ba.slice(p, p + (limit << 2));
|
|
216
231
|
tags[tag] = new Uint32Array(bytes.buffer, bytes.byteOffset, limit);
|
|
217
232
|
}
|
|
218
233
|
p += limit << 2;
|
|
219
234
|
}
|
|
220
|
-
else if (Btype ===
|
|
235
|
+
else if (Btype === 0x73) {
|
|
236
|
+
// 's'
|
|
221
237
|
if (absOffset % 2 === 0) {
|
|
222
|
-
tags[tag] = new Int16Array(
|
|
238
|
+
tags[tag] = new Int16Array(ba.buffer, absOffset, limit);
|
|
223
239
|
}
|
|
224
240
|
else {
|
|
225
|
-
const bytes =
|
|
241
|
+
const bytes = ba.slice(p, p + (limit << 1));
|
|
226
242
|
tags[tag] = new Int16Array(bytes.buffer, bytes.byteOffset, limit);
|
|
227
243
|
}
|
|
228
244
|
p += limit << 1;
|
|
229
245
|
}
|
|
230
|
-
else if (Btype ===
|
|
246
|
+
else if (Btype === 0x53) {
|
|
247
|
+
// 'S'
|
|
231
248
|
if (absOffset % 2 === 0) {
|
|
232
|
-
tags[tag] = new Uint16Array(
|
|
249
|
+
tags[tag] = new Uint16Array(ba.buffer, absOffset, limit);
|
|
233
250
|
}
|
|
234
251
|
else {
|
|
235
|
-
const bytes =
|
|
252
|
+
const bytes = ba.slice(p, p + (limit << 1));
|
|
236
253
|
tags[tag] = new Uint16Array(bytes.buffer, bytes.byteOffset, limit);
|
|
237
254
|
}
|
|
238
255
|
p += limit << 1;
|
|
239
256
|
}
|
|
240
|
-
else if (Btype ===
|
|
241
|
-
|
|
257
|
+
else if (Btype === 0x63) {
|
|
258
|
+
// 'c'
|
|
259
|
+
tags[tag] = new Int8Array(ba.buffer, absOffset, limit);
|
|
242
260
|
p += limit;
|
|
243
261
|
}
|
|
244
|
-
else if (Btype ===
|
|
245
|
-
|
|
262
|
+
else if (Btype === 0x43) {
|
|
263
|
+
// 'C'
|
|
264
|
+
tags[tag] = new Uint8Array(ba.buffer, absOffset, limit);
|
|
246
265
|
p += limit;
|
|
247
266
|
}
|
|
248
|
-
else if (Btype ===
|
|
267
|
+
else if (Btype === 0x66) {
|
|
268
|
+
// 'f'
|
|
249
269
|
if (absOffset % 4 === 0) {
|
|
250
|
-
tags[tag] = new Float32Array(
|
|
270
|
+
tags[tag] = new Float32Array(ba.buffer, absOffset, limit);
|
|
251
271
|
}
|
|
252
272
|
else {
|
|
253
|
-
const bytes =
|
|
273
|
+
const bytes = ba.slice(p, p + (limit << 2));
|
|
254
274
|
tags[tag] = new Float32Array(bytes.buffer, bytes.byteOffset, limit);
|
|
255
275
|
}
|
|
256
276
|
p += limit << 2;
|
|
@@ -264,58 +284,49 @@ class BamRecord {
|
|
|
264
284
|
}
|
|
265
285
|
return tags;
|
|
266
286
|
}
|
|
267
|
-
/**
|
|
268
|
-
* @returns {boolean} true if the read is paired, regardless of whether both
|
|
269
|
-
* segments are mapped
|
|
270
|
-
*/
|
|
271
287
|
isPaired() {
|
|
272
288
|
return !!(this.flags & constants_ts_1.default.BAM_FPAIRED);
|
|
273
289
|
}
|
|
274
|
-
/** @returns {boolean} true if the read is paired, and both segments are mapped */
|
|
275
290
|
isProperlyPaired() {
|
|
276
291
|
return !!(this.flags & constants_ts_1.default.BAM_FPROPER_PAIR);
|
|
277
292
|
}
|
|
278
|
-
/** @returns {boolean} true if the read itself is unmapped; conflictive with isProperlyPaired */
|
|
279
293
|
isSegmentUnmapped() {
|
|
280
294
|
return !!(this.flags & constants_ts_1.default.BAM_FUNMAP);
|
|
281
295
|
}
|
|
282
|
-
/** @returns {boolean} true if the read itself is unmapped; conflictive with isProperlyPaired */
|
|
283
296
|
isMateUnmapped() {
|
|
284
297
|
return !!(this.flags & constants_ts_1.default.BAM_FMUNMAP);
|
|
285
298
|
}
|
|
286
|
-
/** @returns {boolean} true if the read is mapped to the reverse strand */
|
|
287
299
|
isReverseComplemented() {
|
|
288
300
|
return !!(this.flags & constants_ts_1.default.BAM_FREVERSE);
|
|
289
301
|
}
|
|
290
|
-
/** @returns {boolean} true if the mate is mapped to the reverse strand */
|
|
291
302
|
isMateReverseComplemented() {
|
|
292
303
|
return !!(this.flags & constants_ts_1.default.BAM_FMREVERSE);
|
|
293
304
|
}
|
|
294
|
-
/** @returns {boolean} true if this is read number 1 in a pair */
|
|
295
305
|
isRead1() {
|
|
296
306
|
return !!(this.flags & constants_ts_1.default.BAM_FREAD1);
|
|
297
307
|
}
|
|
298
|
-
/** @returns {boolean} true if this is read number 2 in a pair */
|
|
299
308
|
isRead2() {
|
|
300
309
|
return !!(this.flags & constants_ts_1.default.BAM_FREAD2);
|
|
301
310
|
}
|
|
302
|
-
/** @returns {boolean} true if this is a secondary alignment */
|
|
303
311
|
isSecondary() {
|
|
304
312
|
return !!(this.flags & constants_ts_1.default.BAM_FSECONDARY);
|
|
305
313
|
}
|
|
306
|
-
/** @returns {boolean} true if this read has failed QC checks */
|
|
307
314
|
isFailedQc() {
|
|
308
315
|
return !!(this.flags & constants_ts_1.default.BAM_FQCFAIL);
|
|
309
316
|
}
|
|
310
|
-
/** @returns {boolean} true if the read is an optical or PCR duplicate */
|
|
311
317
|
isDuplicate() {
|
|
312
318
|
return !!(this.flags & constants_ts_1.default.BAM_FDUP);
|
|
313
319
|
}
|
|
314
|
-
/** @returns {boolean} true if this is a supplementary alignment */
|
|
315
320
|
isSupplementary() {
|
|
316
321
|
return !!(this.flags & constants_ts_1.default.BAM_FSUPPLEMENTARY);
|
|
317
322
|
}
|
|
318
323
|
get cigarAndLength() {
|
|
324
|
+
if (this._cachedCigarAndLength === undefined) {
|
|
325
|
+
this._cachedCigarAndLength = this._computeCigarAndLength();
|
|
326
|
+
}
|
|
327
|
+
return this._cachedCigarAndLength;
|
|
328
|
+
}
|
|
329
|
+
_computeCigarAndLength() {
|
|
319
330
|
if (this.isSegmentUnmapped()) {
|
|
320
331
|
return {
|
|
321
332
|
length_on_ref: 0,
|
|
@@ -329,14 +340,14 @@ class BamRecord {
|
|
|
329
340
|
const cigop = this._dataView.getInt32(p, true);
|
|
330
341
|
const lop = cigop >> 4;
|
|
331
342
|
const op = cigop & 0xf;
|
|
332
|
-
if (op === CIGAR_SOFT_CLIP && lop === this.seq_length) {
|
|
343
|
+
if (op === cigar_ts_1.CIGAR_SOFT_CLIP && lop === this.seq_length) {
|
|
333
344
|
// if there is a CG the second CIGAR field will be a N tag the represents
|
|
334
345
|
// the length on ref
|
|
335
346
|
p += 4;
|
|
336
347
|
const cigop = this._dataView.getInt32(p, true);
|
|
337
348
|
const lop = cigop >> 4;
|
|
338
349
|
const op = cigop & 0xf;
|
|
339
|
-
if (op !== CIGAR_REF_SKIP) {
|
|
350
|
+
if (op !== cigar_ts_1.CIGAR_REF_SKIP) {
|
|
340
351
|
console.warn('CG tag with no N tag');
|
|
341
352
|
}
|
|
342
353
|
const cgArray = this.tags.CG;
|
|
@@ -345,24 +356,22 @@ class BamRecord {
|
|
|
345
356
|
length_on_ref: lop,
|
|
346
357
|
};
|
|
347
358
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
lref += cigop >> 4;
|
|
359
|
-
}
|
|
359
|
+
const absOffset = this.byteArray.byteOffset + p;
|
|
360
|
+
const cigarView = absOffset % 4 === 0
|
|
361
|
+
? new Uint32Array(this.byteArray.buffer, absOffset, numCigarOps)
|
|
362
|
+
: new Uint32Array(this.byteArray.slice(p, p + (numCigarOps << 2)).buffer, 0, numCigarOps);
|
|
363
|
+
let lref = 0;
|
|
364
|
+
for (let c = 0; c < numCigarOps; ++c) {
|
|
365
|
+
const cigop = cigarView[c];
|
|
366
|
+
const op = cigop & 0xf;
|
|
367
|
+
if (!((1 << op) & CIGAR_SKIP_MASK)) {
|
|
368
|
+
lref += cigop >> 4;
|
|
360
369
|
}
|
|
361
|
-
return {
|
|
362
|
-
NUMERIC_CIGAR: cigarView,
|
|
363
|
-
length_on_ref: lref,
|
|
364
|
-
};
|
|
365
370
|
}
|
|
371
|
+
return {
|
|
372
|
+
NUMERIC_CIGAR: cigarView,
|
|
373
|
+
length_on_ref: lref,
|
|
374
|
+
};
|
|
366
375
|
}
|
|
367
376
|
get length_on_ref() {
|
|
368
377
|
return this.cigarAndLength.length_on_ref;
|
|
@@ -395,8 +404,7 @@ class BamRecord {
|
|
|
395
404
|
}
|
|
396
405
|
get NUMERIC_SEQ() {
|
|
397
406
|
const p = this.b0 + this.read_name_length + this.num_cigar_bytes;
|
|
398
|
-
|
|
399
|
-
return new Uint8Array(seqBytes.buffer, seqBytes.byteOffset, this.num_seq_bytes);
|
|
407
|
+
return this.byteArray.subarray(p, p + this.num_seq_bytes);
|
|
400
408
|
}
|
|
401
409
|
get seq() {
|
|
402
410
|
const numeric = this.NUMERIC_SEQ;
|
|
@@ -493,27 +501,4 @@ class BamRecord {
|
|
|
493
501
|
}
|
|
494
502
|
}
|
|
495
503
|
exports.default = BamRecord;
|
|
496
|
-
function cacheGetter(ctor, prop) {
|
|
497
|
-
const desc = Object.getOwnPropertyDescriptor(ctor.prototype, prop);
|
|
498
|
-
if (!desc) {
|
|
499
|
-
throw new Error('OH NO, NO PROPERTY DESCRIPTOR');
|
|
500
|
-
}
|
|
501
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
502
|
-
const getter = desc.get;
|
|
503
|
-
if (!getter) {
|
|
504
|
-
throw new Error('OH NO, NOT A GETTER');
|
|
505
|
-
}
|
|
506
|
-
Object.defineProperty(ctor.prototype, prop, {
|
|
507
|
-
get() {
|
|
508
|
-
const ret = getter.call(this);
|
|
509
|
-
Object.defineProperty(this, prop, { value: ret });
|
|
510
|
-
return ret;
|
|
511
|
-
},
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
cacheGetter(BamRecord, 'tags');
|
|
515
|
-
cacheGetter(BamRecord, 'cigarAndLength');
|
|
516
|
-
cacheGetter(BamRecord, 'seq');
|
|
517
|
-
cacheGetter(BamRecord, 'qual');
|
|
518
|
-
cacheGetter(BamRecord, 'end');
|
|
519
504
|
//# sourceMappingURL=record.js.map
|