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