@gmod/bam 1.1.17 → 2.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/CHANGELOG.md +65 -25
- package/README.md +108 -57
- package/dist/bai.d.ts +34 -15
- package/dist/bai.js +180 -273
- package/dist/bai.js.map +1 -1
- package/dist/bamFile.d.ts +33 -27
- package/dist/bamFile.js +353 -572
- package/dist/bamFile.js.map +1 -1
- package/dist/chunk.d.ts +4 -8
- package/dist/chunk.js +13 -21
- package/dist/chunk.js.map +1 -1
- package/dist/csi.d.ts +74 -10
- package/dist/csi.js +157 -256
- package/dist/csi.js.map +1 -1
- package/dist/errors.js +12 -57
- package/dist/errors.js.map +1 -1
- package/dist/htsget.d.ts +5 -8
- package/dist/htsget.js +120 -209
- package/dist/htsget.js.map +1 -1
- package/dist/index.d.ts +5 -6
- package/dist/index.js +11 -11
- package/dist/index.js.map +1 -1
- package/dist/indexFile.d.ts +0 -6
- package/dist/indexFile.js +3 -77
- package/dist/indexFile.js.map +1 -1
- package/dist/nullIndex.d.ts +7 -0
- package/dist/nullIndex.js +33 -0
- package/dist/nullIndex.js.map +1 -0
- package/dist/record.d.ts +2 -2
- package/dist/record.js +200 -193
- package/dist/record.js.map +1 -1
- package/dist/sam.js +12 -10
- package/dist/sam.js.map +1 -1
- package/dist/util.d.ts +13 -1
- package/dist/util.js +55 -58
- package/dist/util.js.map +1 -1
- package/dist/virtualOffset.js +13 -20
- package/dist/virtualOffset.js.map +1 -1
- package/esm/bai.d.ts +34 -15
- package/esm/bai.js +86 -91
- package/esm/bai.js.map +1 -1
- package/esm/bamFile.d.ts +33 -27
- package/esm/bamFile.js +124 -120
- package/esm/bamFile.js.map +1 -1
- package/esm/chunk.d.ts +4 -8
- package/esm/chunk.js +2 -8
- package/esm/chunk.js.map +1 -1
- package/esm/csi.d.ts +74 -10
- package/esm/csi.js +85 -93
- package/esm/csi.js.map +1 -1
- package/esm/htsget.d.ts +5 -8
- package/esm/htsget.js +68 -43
- package/esm/htsget.js.map +1 -1
- package/esm/index.d.ts +5 -6
- package/esm/index.js +5 -6
- package/esm/index.js.map +1 -1
- package/esm/indexFile.d.ts +0 -6
- package/esm/indexFile.js +0 -22
- package/esm/indexFile.js.map +1 -1
- package/esm/nullIndex.d.ts +7 -0
- package/esm/nullIndex.js +16 -0
- package/esm/nullIndex.js.map +1 -0
- package/esm/record.d.ts +2 -2
- package/esm/record.js +34 -24
- package/esm/record.js.map +1 -1
- package/esm/sam.js +9 -7
- package/esm/sam.js.map +1 -1
- package/esm/util.d.ts +13 -1
- package/esm/util.js +40 -14
- package/esm/util.js.map +1 -1
- package/package.json +19 -20
- package/src/bai.ts +99 -102
- package/src/bamFile.ts +174 -198
- package/src/chunk.ts +6 -20
- package/src/csi.ts +102 -111
- package/src/htsget.ts +81 -61
- package/src/index.ts +5 -7
- package/src/indexFile.ts +0 -27
- package/src/nullIndex.ts +18 -0
- package/src/record.ts +34 -24
- package/src/sam.ts +9 -7
- package/src/util.ts +54 -13
- package/src/declare.d.ts +0 -2
package/dist/record.js
CHANGED
|
@@ -4,19 +4,19 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const constants_1 = __importDefault(require("./constants"));
|
|
8
|
+
const SEQRET_DECODER = '=ACMGRSVTWYHKDBN'.split('');
|
|
9
|
+
const CIGAR_DECODER = 'MIDNSHP=X???????'.split('');
|
|
10
10
|
/**
|
|
11
11
|
* Class of each BAM record returned by this API.
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
class BamRecord {
|
|
14
|
+
constructor(args) {
|
|
15
15
|
this.data = {};
|
|
16
16
|
this._tagList = [];
|
|
17
17
|
this._allTagsParsed = false;
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
const { bytes, fileOffset } = args;
|
|
19
|
+
const { byteArray, start } = bytes;
|
|
20
20
|
this.data = {};
|
|
21
21
|
this.bytes = bytes;
|
|
22
22
|
this._id = fileOffset;
|
|
@@ -24,7 +24,7 @@ var BamRecord = /** @class */ (function () {
|
|
|
24
24
|
this.data.start = byteArray.readInt32LE(start + 8);
|
|
25
25
|
this.flags = (byteArray.readInt32LE(start + 16) & 0xffff0000) >> 16;
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
get(field) {
|
|
28
28
|
//@ts-ignore
|
|
29
29
|
if (this[field]) {
|
|
30
30
|
//@ts-ignore
|
|
@@ -36,26 +36,25 @@ var BamRecord = /** @class */ (function () {
|
|
|
36
36
|
return this.data[field];
|
|
37
37
|
}
|
|
38
38
|
return this._get(field.toLowerCase());
|
|
39
|
-
}
|
|
40
|
-
|
|
39
|
+
}
|
|
40
|
+
end() {
|
|
41
41
|
return this.get('start') + this.get('length_on_ref');
|
|
42
|
-
}
|
|
43
|
-
|
|
42
|
+
}
|
|
43
|
+
seq_id() {
|
|
44
44
|
return this._refID;
|
|
45
|
-
}
|
|
45
|
+
}
|
|
46
46
|
// same as get(), except requires lower-case arguments. used
|
|
47
47
|
// internally to save lots of calls to field.toLowerCase()
|
|
48
|
-
|
|
48
|
+
_get(field) {
|
|
49
49
|
if (field in this.data) {
|
|
50
50
|
return this.data[field];
|
|
51
51
|
}
|
|
52
52
|
this.data[field] = this._parseTag(field);
|
|
53
53
|
return this.data[field];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
var _this = this;
|
|
54
|
+
}
|
|
55
|
+
_tags() {
|
|
57
56
|
this._parseAllTags();
|
|
58
|
-
|
|
57
|
+
let tags = ['seq'];
|
|
59
58
|
if (!this.isSegmentUnmapped()) {
|
|
60
59
|
tags.push('start', 'end', 'strand', 'score', 'qual', 'MQ', 'CIGAR', 'length_on_ref', 'template_length');
|
|
61
60
|
}
|
|
@@ -63,143 +62,151 @@ var BamRecord = /** @class */ (function () {
|
|
|
63
62
|
tags.push('next_segment_position', 'pair_orientation');
|
|
64
63
|
}
|
|
65
64
|
tags = tags.concat(this._tagList || []);
|
|
66
|
-
Object.keys(this.data)
|
|
65
|
+
for (const k of Object.keys(this.data)) {
|
|
67
66
|
if (k[0] !== '_' && k !== 'next_seq_id') {
|
|
68
67
|
tags.push(k);
|
|
69
68
|
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return tags.filter(
|
|
73
|
-
if ((t in
|
|
69
|
+
}
|
|
70
|
+
const seen = {};
|
|
71
|
+
return tags.filter(t => {
|
|
72
|
+
if ((t in this.data && this.data[t] === undefined) ||
|
|
74
73
|
t === 'CG' ||
|
|
75
74
|
t === 'cg') {
|
|
76
75
|
return false;
|
|
77
76
|
}
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
const lt = t.toLowerCase();
|
|
78
|
+
const s = seen[lt];
|
|
80
79
|
seen[lt] = true;
|
|
81
80
|
return !s;
|
|
82
81
|
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return
|
|
86
|
-
}
|
|
87
|
-
|
|
82
|
+
}
|
|
83
|
+
parent() {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
children() {
|
|
88
87
|
return this.get('subfeatures');
|
|
89
|
-
}
|
|
90
|
-
|
|
88
|
+
}
|
|
89
|
+
id() {
|
|
91
90
|
return this._id;
|
|
92
|
-
}
|
|
91
|
+
}
|
|
93
92
|
// special parsers
|
|
94
93
|
/**
|
|
95
94
|
* Mapping quality score.
|
|
96
95
|
*/
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
mq() {
|
|
97
|
+
const mq = (this.get('_bin_mq_nl') & 0xff00) >> 8;
|
|
99
98
|
return mq === 255 ? undefined : mq;
|
|
100
|
-
}
|
|
101
|
-
|
|
99
|
+
}
|
|
100
|
+
score() {
|
|
102
101
|
return this.get('mq');
|
|
103
|
-
}
|
|
104
|
-
|
|
102
|
+
}
|
|
103
|
+
qual() {
|
|
105
104
|
var _a;
|
|
106
105
|
return (_a = this.qualRaw()) === null || _a === void 0 ? void 0 : _a.join(' ');
|
|
107
|
-
}
|
|
108
|
-
|
|
106
|
+
}
|
|
107
|
+
qualRaw() {
|
|
109
108
|
if (this.isSegmentUnmapped()) {
|
|
110
|
-
return
|
|
109
|
+
return;
|
|
111
110
|
}
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
const { start, byteArray } = this.bytes;
|
|
112
|
+
const p = start +
|
|
114
113
|
36 +
|
|
115
114
|
this.get('_l_read_name') +
|
|
116
115
|
this.get('_n_cigar_op') * 4 +
|
|
117
116
|
this.get('_seq_bytes');
|
|
118
|
-
|
|
117
|
+
const lseq = this.get('seq_length');
|
|
119
118
|
return byteArray.subarray(p, p + lseq);
|
|
120
|
-
}
|
|
121
|
-
|
|
119
|
+
}
|
|
120
|
+
strand() {
|
|
122
121
|
return this.isReverseComplemented() ? -1 : 1;
|
|
123
|
-
}
|
|
124
|
-
|
|
122
|
+
}
|
|
123
|
+
multi_segment_next_segment_strand() {
|
|
125
124
|
if (this.isMateUnmapped()) {
|
|
126
|
-
return
|
|
125
|
+
return;
|
|
127
126
|
}
|
|
128
127
|
return this.isMateReverseComplemented() ? -1 : 1;
|
|
129
|
-
}
|
|
130
|
-
|
|
128
|
+
}
|
|
129
|
+
name() {
|
|
131
130
|
return this.get('_read_name');
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
}
|
|
132
|
+
_read_name() {
|
|
133
|
+
const nl = this.get('_l_read_name');
|
|
134
|
+
const { byteArray, start } = this.bytes;
|
|
136
135
|
return byteArray.toString('ascii', start + 36, start + 36 + nl - 1);
|
|
137
|
-
}
|
|
136
|
+
}
|
|
138
137
|
/**
|
|
139
138
|
* Get the value of a tag, parsing the tags as far as necessary.
|
|
140
139
|
* Only called if we have not already parsed that field.
|
|
141
140
|
*/
|
|
142
|
-
|
|
141
|
+
_parseTag(tagName) {
|
|
143
142
|
// if all of the tags have been parsed and we're still being
|
|
144
143
|
// called, we already know that we have no such tag, because
|
|
145
144
|
// it would already have been cached.
|
|
146
145
|
if (this._allTagsParsed) {
|
|
147
|
-
return
|
|
146
|
+
return;
|
|
148
147
|
}
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
const { byteArray, start } = this.bytes;
|
|
149
|
+
let p = this._tagOffset ||
|
|
151
150
|
start +
|
|
152
151
|
36 +
|
|
153
152
|
this.get('_l_read_name') +
|
|
154
153
|
this.get('_n_cigar_op') * 4 +
|
|
155
154
|
this.get('_seq_bytes') +
|
|
156
155
|
this.get('seq_length');
|
|
157
|
-
|
|
158
|
-
|
|
156
|
+
const blockEnd = this.bytes.end;
|
|
157
|
+
let lcTag;
|
|
159
158
|
while (p < blockEnd && lcTag !== tagName) {
|
|
160
|
-
|
|
159
|
+
const tag = String.fromCharCode(byteArray[p], byteArray[p + 1]);
|
|
161
160
|
lcTag = tag.toLowerCase();
|
|
162
|
-
|
|
161
|
+
const type = String.fromCharCode(byteArray[p + 2]);
|
|
163
162
|
p += 3;
|
|
164
|
-
|
|
163
|
+
let value;
|
|
165
164
|
switch (type) {
|
|
166
|
-
case 'A':
|
|
165
|
+
case 'A': {
|
|
167
166
|
value = String.fromCharCode(byteArray[p]);
|
|
168
167
|
p += 1;
|
|
169
168
|
break;
|
|
170
|
-
|
|
169
|
+
}
|
|
170
|
+
case 'i': {
|
|
171
171
|
value = byteArray.readInt32LE(p);
|
|
172
172
|
p += 4;
|
|
173
173
|
break;
|
|
174
|
-
|
|
174
|
+
}
|
|
175
|
+
case 'I': {
|
|
175
176
|
value = byteArray.readUInt32LE(p);
|
|
176
177
|
p += 4;
|
|
177
178
|
break;
|
|
178
|
-
|
|
179
|
+
}
|
|
180
|
+
case 'c': {
|
|
179
181
|
value = byteArray.readInt8(p);
|
|
180
182
|
p += 1;
|
|
181
183
|
break;
|
|
182
|
-
|
|
184
|
+
}
|
|
185
|
+
case 'C': {
|
|
183
186
|
value = byteArray.readUInt8(p);
|
|
184
187
|
p += 1;
|
|
185
188
|
break;
|
|
186
|
-
|
|
189
|
+
}
|
|
190
|
+
case 's': {
|
|
187
191
|
value = byteArray.readInt16LE(p);
|
|
188
192
|
p += 2;
|
|
189
193
|
break;
|
|
190
|
-
|
|
194
|
+
}
|
|
195
|
+
case 'S': {
|
|
191
196
|
value = byteArray.readUInt16LE(p);
|
|
192
197
|
p += 2;
|
|
193
198
|
break;
|
|
194
|
-
|
|
199
|
+
}
|
|
200
|
+
case 'f': {
|
|
195
201
|
value = byteArray.readFloatLE(p);
|
|
196
202
|
p += 4;
|
|
197
203
|
break;
|
|
204
|
+
}
|
|
198
205
|
case 'Z':
|
|
199
|
-
case 'H':
|
|
206
|
+
case 'H': {
|
|
200
207
|
value = '';
|
|
201
208
|
while (p <= blockEnd) {
|
|
202
|
-
|
|
209
|
+
const cc = byteArray[p++];
|
|
203
210
|
if (cc === 0) {
|
|
204
211
|
break;
|
|
205
212
|
}
|
|
@@ -208,24 +215,25 @@ var BamRecord = /** @class */ (function () {
|
|
|
208
215
|
}
|
|
209
216
|
}
|
|
210
217
|
break;
|
|
218
|
+
}
|
|
211
219
|
case 'B': {
|
|
212
220
|
value = '';
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
221
|
+
const cc = byteArray[p++];
|
|
222
|
+
const Btype = String.fromCharCode(cc);
|
|
223
|
+
const limit = byteArray.readInt32LE(p);
|
|
216
224
|
p += 4;
|
|
217
225
|
if (Btype === 'i') {
|
|
218
226
|
if (tag === 'CG') {
|
|
219
|
-
for (
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
227
|
+
for (let k = 0; k < limit; k++) {
|
|
228
|
+
const cigop = byteArray.readInt32LE(p);
|
|
229
|
+
const lop = cigop >> 4;
|
|
230
|
+
const op = CIGAR_DECODER[cigop & 0xf];
|
|
223
231
|
value += lop + op;
|
|
224
232
|
p += 4;
|
|
225
233
|
}
|
|
226
234
|
}
|
|
227
235
|
else {
|
|
228
|
-
for (
|
|
236
|
+
for (let k = 0; k < limit; k++) {
|
|
229
237
|
value += byteArray.readInt32LE(p);
|
|
230
238
|
if (k + 1 < limit) {
|
|
231
239
|
value += ',';
|
|
@@ -236,16 +244,16 @@ var BamRecord = /** @class */ (function () {
|
|
|
236
244
|
}
|
|
237
245
|
if (Btype === 'I') {
|
|
238
246
|
if (tag === 'CG') {
|
|
239
|
-
for (
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
247
|
+
for (let k = 0; k < limit; k++) {
|
|
248
|
+
const cigop = byteArray.readUInt32LE(p);
|
|
249
|
+
const lop = cigop >> 4;
|
|
250
|
+
const op = CIGAR_DECODER[cigop & 0xf];
|
|
243
251
|
value += lop + op;
|
|
244
252
|
p += 4;
|
|
245
253
|
}
|
|
246
254
|
}
|
|
247
255
|
else {
|
|
248
|
-
for (
|
|
256
|
+
for (let k = 0; k < limit; k++) {
|
|
249
257
|
value += byteArray.readUInt32LE(p);
|
|
250
258
|
if (k + 1 < limit) {
|
|
251
259
|
value += ',';
|
|
@@ -255,7 +263,7 @@ var BamRecord = /** @class */ (function () {
|
|
|
255
263
|
}
|
|
256
264
|
}
|
|
257
265
|
if (Btype === 's') {
|
|
258
|
-
for (
|
|
266
|
+
for (let k = 0; k < limit; k++) {
|
|
259
267
|
value += byteArray.readInt16LE(p);
|
|
260
268
|
if (k + 1 < limit) {
|
|
261
269
|
value += ',';
|
|
@@ -264,7 +272,7 @@ var BamRecord = /** @class */ (function () {
|
|
|
264
272
|
}
|
|
265
273
|
}
|
|
266
274
|
if (Btype === 'S') {
|
|
267
|
-
for (
|
|
275
|
+
for (let k = 0; k < limit; k++) {
|
|
268
276
|
value += byteArray.readUInt16LE(p);
|
|
269
277
|
if (k + 1 < limit) {
|
|
270
278
|
value += ',';
|
|
@@ -273,7 +281,7 @@ var BamRecord = /** @class */ (function () {
|
|
|
273
281
|
}
|
|
274
282
|
}
|
|
275
283
|
if (Btype === 'c') {
|
|
276
|
-
for (
|
|
284
|
+
for (let k = 0; k < limit; k++) {
|
|
277
285
|
value += byteArray.readInt8(p);
|
|
278
286
|
if (k + 1 < limit) {
|
|
279
287
|
value += ',';
|
|
@@ -282,7 +290,7 @@ var BamRecord = /** @class */ (function () {
|
|
|
282
290
|
}
|
|
283
291
|
}
|
|
284
292
|
if (Btype === 'C') {
|
|
285
|
-
for (
|
|
293
|
+
for (let k = 0; k < limit; k++) {
|
|
286
294
|
value += byteArray.readUInt8(p);
|
|
287
295
|
if (k + 1 < limit) {
|
|
288
296
|
value += ',';
|
|
@@ -291,7 +299,7 @@ var BamRecord = /** @class */ (function () {
|
|
|
291
299
|
}
|
|
292
300
|
}
|
|
293
301
|
if (Btype === 'f') {
|
|
294
|
-
for (
|
|
302
|
+
for (let k = 0; k < limit; k++) {
|
|
295
303
|
value += byteArray.readFloatLE(p);
|
|
296
304
|
if (k + 1 < limit) {
|
|
297
305
|
value += ',';
|
|
@@ -301,10 +309,11 @@ var BamRecord = /** @class */ (function () {
|
|
|
301
309
|
}
|
|
302
310
|
break;
|
|
303
311
|
}
|
|
304
|
-
default:
|
|
305
|
-
console.warn(
|
|
312
|
+
default: {
|
|
313
|
+
console.warn(`Unknown BAM tag type '${type}', tags may be incomplete`);
|
|
306
314
|
value = undefined;
|
|
307
|
-
p = blockEnd;
|
|
315
|
+
p = blockEnd;
|
|
316
|
+
} // stop parsing tags
|
|
308
317
|
}
|
|
309
318
|
this._tagOffset = p;
|
|
310
319
|
this._tagList.push(tag);
|
|
@@ -314,84 +323,84 @@ var BamRecord = /** @class */ (function () {
|
|
|
314
323
|
this.data[lcTag] = value;
|
|
315
324
|
}
|
|
316
325
|
this._allTagsParsed = true;
|
|
317
|
-
return
|
|
318
|
-
}
|
|
319
|
-
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
_parseAllTags() {
|
|
320
329
|
this._parseTag('');
|
|
321
|
-
}
|
|
322
|
-
|
|
330
|
+
}
|
|
331
|
+
_parseCigar(cigar) {
|
|
323
332
|
return (
|
|
324
333
|
//@ts-ignore
|
|
325
334
|
cigar
|
|
326
335
|
.match(/\d+\D/g)
|
|
327
336
|
//@ts-ignore
|
|
328
|
-
.map(
|
|
329
|
-
}
|
|
337
|
+
.map(op => [op.match(/\D/)[0].toUpperCase(), Number.parseInt(op, 10)]));
|
|
338
|
+
}
|
|
330
339
|
/**
|
|
331
340
|
* @returns {boolean} true if the read is paired, regardless of whether both segments are mapped
|
|
332
341
|
*/
|
|
333
|
-
|
|
342
|
+
isPaired() {
|
|
334
343
|
return !!(this.flags & constants_1.default.BAM_FPAIRED);
|
|
335
|
-
}
|
|
344
|
+
}
|
|
336
345
|
/** @returns {boolean} true if the read is paired, and both segments are mapped */
|
|
337
|
-
|
|
346
|
+
isProperlyPaired() {
|
|
338
347
|
return !!(this.flags & constants_1.default.BAM_FPROPER_PAIR);
|
|
339
|
-
}
|
|
348
|
+
}
|
|
340
349
|
/** @returns {boolean} true if the read itself is unmapped; conflictive with isProperlyPaired */
|
|
341
|
-
|
|
350
|
+
isSegmentUnmapped() {
|
|
342
351
|
return !!(this.flags & constants_1.default.BAM_FUNMAP);
|
|
343
|
-
}
|
|
352
|
+
}
|
|
344
353
|
/** @returns {boolean} true if the read itself is unmapped; conflictive with isProperlyPaired */
|
|
345
|
-
|
|
354
|
+
isMateUnmapped() {
|
|
346
355
|
return !!(this.flags & constants_1.default.BAM_FMUNMAP);
|
|
347
|
-
}
|
|
356
|
+
}
|
|
348
357
|
/** @returns {boolean} true if the read is mapped to the reverse strand */
|
|
349
|
-
|
|
358
|
+
isReverseComplemented() {
|
|
350
359
|
return !!(this.flags & constants_1.default.BAM_FREVERSE);
|
|
351
|
-
}
|
|
360
|
+
}
|
|
352
361
|
/** @returns {boolean} true if the mate is mapped to the reverse strand */
|
|
353
|
-
|
|
362
|
+
isMateReverseComplemented() {
|
|
354
363
|
return !!(this.flags & constants_1.default.BAM_FMREVERSE);
|
|
355
|
-
}
|
|
364
|
+
}
|
|
356
365
|
/** @returns {boolean} true if this is read number 1 in a pair */
|
|
357
|
-
|
|
366
|
+
isRead1() {
|
|
358
367
|
return !!(this.flags & constants_1.default.BAM_FREAD1);
|
|
359
|
-
}
|
|
368
|
+
}
|
|
360
369
|
/** @returns {boolean} true if this is read number 2 in a pair */
|
|
361
|
-
|
|
370
|
+
isRead2() {
|
|
362
371
|
return !!(this.flags & constants_1.default.BAM_FREAD2);
|
|
363
|
-
}
|
|
372
|
+
}
|
|
364
373
|
/** @returns {boolean} true if this is a secondary alignment */
|
|
365
|
-
|
|
374
|
+
isSecondary() {
|
|
366
375
|
return !!(this.flags & constants_1.default.BAM_FSECONDARY);
|
|
367
|
-
}
|
|
376
|
+
}
|
|
368
377
|
/** @returns {boolean} true if this read has failed QC checks */
|
|
369
|
-
|
|
378
|
+
isFailedQc() {
|
|
370
379
|
return !!(this.flags & constants_1.default.BAM_FQCFAIL);
|
|
371
|
-
}
|
|
380
|
+
}
|
|
372
381
|
/** @returns {boolean} true if the read is an optical or PCR duplicate */
|
|
373
|
-
|
|
382
|
+
isDuplicate() {
|
|
374
383
|
return !!(this.flags & constants_1.default.BAM_FDUP);
|
|
375
|
-
}
|
|
384
|
+
}
|
|
376
385
|
/** @returns {boolean} true if this is a supplementary alignment */
|
|
377
|
-
|
|
386
|
+
isSupplementary() {
|
|
378
387
|
return !!(this.flags & constants_1.default.BAM_FSUPPLEMENTARY);
|
|
379
|
-
}
|
|
380
|
-
|
|
388
|
+
}
|
|
389
|
+
cigar() {
|
|
381
390
|
if (this.isSegmentUnmapped()) {
|
|
382
|
-
return
|
|
391
|
+
return;
|
|
383
392
|
}
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
393
|
+
const { byteArray, start } = this.bytes;
|
|
394
|
+
const numCigarOps = this.get('_n_cigar_op');
|
|
395
|
+
let p = start + 36 + this.get('_l_read_name');
|
|
396
|
+
const seqLen = this.get('seq_length');
|
|
397
|
+
let cigar = '';
|
|
398
|
+
let lref = 0;
|
|
390
399
|
// check for CG tag by inspecting whether the CIGAR field
|
|
391
400
|
// contains a clip that consumes entire seqLen
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
401
|
+
let cigop = byteArray.readInt32LE(p);
|
|
402
|
+
let lop = cigop >> 4;
|
|
403
|
+
let op = CIGAR_DECODER[cigop & 0xf];
|
|
395
404
|
if (op === 'S' && lop === seqLen) {
|
|
396
405
|
// if there is a CG the second CIGAR field will
|
|
397
406
|
// be a N tag the represents the length on ref
|
|
@@ -406,7 +415,7 @@ var BamRecord = /** @class */ (function () {
|
|
|
406
415
|
return this.get('CG');
|
|
407
416
|
}
|
|
408
417
|
else {
|
|
409
|
-
for (
|
|
418
|
+
for (let c = 0; c < numCigarOps; ++c) {
|
|
410
419
|
cigop = byteArray.readInt32LE(p);
|
|
411
420
|
lop = cigop >> 4;
|
|
412
421
|
op = CIGAR_DECODER[cigop & 0xf];
|
|
@@ -421,9 +430,9 @@ var BamRecord = /** @class */ (function () {
|
|
|
421
430
|
this.data.length_on_ref = lref;
|
|
422
431
|
return cigar;
|
|
423
432
|
}
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
|
|
433
|
+
}
|
|
434
|
+
_flags() { }
|
|
435
|
+
length_on_ref() {
|
|
427
436
|
if (this.data.length_on_ref) {
|
|
428
437
|
return this.data.length_on_ref;
|
|
429
438
|
}
|
|
@@ -431,31 +440,31 @@ var BamRecord = /** @class */ (function () {
|
|
|
431
440
|
this.get('cigar'); // the length_on_ref is set as a side effect
|
|
432
441
|
return this.data.length_on_ref;
|
|
433
442
|
}
|
|
434
|
-
}
|
|
435
|
-
|
|
443
|
+
}
|
|
444
|
+
_n_cigar_op() {
|
|
436
445
|
return this.get('_flag_nc') & 0xffff;
|
|
437
|
-
}
|
|
438
|
-
|
|
446
|
+
}
|
|
447
|
+
_l_read_name() {
|
|
439
448
|
return this.get('_bin_mq_nl') & 0xff;
|
|
440
|
-
}
|
|
449
|
+
}
|
|
441
450
|
/**
|
|
442
451
|
* number of bytes in the sequence field
|
|
443
452
|
*/
|
|
444
|
-
|
|
453
|
+
_seq_bytes() {
|
|
445
454
|
return (this.get('seq_length') + 1) >> 1;
|
|
446
|
-
}
|
|
447
|
-
|
|
455
|
+
}
|
|
456
|
+
getReadBases() {
|
|
448
457
|
return this.seq();
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
for (
|
|
458
|
-
|
|
458
|
+
}
|
|
459
|
+
seq() {
|
|
460
|
+
const { byteArray, start } = this.bytes;
|
|
461
|
+
const p = start + 36 + this.get('_l_read_name') + this.get('_n_cigar_op') * 4;
|
|
462
|
+
const seqBytes = this.get('_seq_bytes');
|
|
463
|
+
const len = this.get('seq_length');
|
|
464
|
+
let buf = '';
|
|
465
|
+
let i = 0;
|
|
466
|
+
for (let j = 0; j < seqBytes; ++j) {
|
|
467
|
+
const sb = byteArray[p + j];
|
|
459
468
|
buf += SEQRET_DECODER[(sb & 0xf0) >> 4];
|
|
460
469
|
i++;
|
|
461
470
|
if (i < len) {
|
|
@@ -464,16 +473,16 @@ var BamRecord = /** @class */ (function () {
|
|
|
464
473
|
}
|
|
465
474
|
}
|
|
466
475
|
return buf;
|
|
467
|
-
}
|
|
476
|
+
}
|
|
468
477
|
// adapted from igv.js
|
|
469
|
-
|
|
478
|
+
getPairOrientation() {
|
|
470
479
|
if (!this.isSegmentUnmapped() &&
|
|
471
480
|
!this.isMateUnmapped() &&
|
|
472
481
|
this._refID === this._next_refid()) {
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
482
|
+
const s1 = this.isReverseComplemented() ? 'R' : 'F';
|
|
483
|
+
const s2 = this.isMateReverseComplemented() ? 'R' : 'F';
|
|
484
|
+
let o1 = ' ';
|
|
485
|
+
let o2 = ' ';
|
|
477
486
|
if (this.isRead1()) {
|
|
478
487
|
o1 = '1';
|
|
479
488
|
o2 = '2';
|
|
@@ -482,8 +491,8 @@ var BamRecord = /** @class */ (function () {
|
|
|
482
491
|
o1 = '2';
|
|
483
492
|
o2 = '1';
|
|
484
493
|
}
|
|
485
|
-
|
|
486
|
-
|
|
494
|
+
const tmp = [];
|
|
495
|
+
const isize = this.template_length();
|
|
487
496
|
if (isize > 0) {
|
|
488
497
|
tmp[0] = s1;
|
|
489
498
|
tmp[1] = o1;
|
|
@@ -498,39 +507,37 @@ var BamRecord = /** @class */ (function () {
|
|
|
498
507
|
}
|
|
499
508
|
return tmp.join('');
|
|
500
509
|
}
|
|
501
|
-
return
|
|
502
|
-
}
|
|
503
|
-
|
|
510
|
+
return '';
|
|
511
|
+
}
|
|
512
|
+
_bin_mq_nl() {
|
|
504
513
|
return this.bytes.byteArray.readInt32LE(this.bytes.start + 12);
|
|
505
|
-
}
|
|
506
|
-
|
|
514
|
+
}
|
|
515
|
+
_flag_nc() {
|
|
507
516
|
return this.bytes.byteArray.readInt32LE(this.bytes.start + 16);
|
|
508
|
-
}
|
|
509
|
-
|
|
517
|
+
}
|
|
518
|
+
seq_length() {
|
|
510
519
|
return this.bytes.byteArray.readInt32LE(this.bytes.start + 20);
|
|
511
|
-
}
|
|
512
|
-
|
|
520
|
+
}
|
|
521
|
+
_next_refid() {
|
|
513
522
|
return this.bytes.byteArray.readInt32LE(this.bytes.start + 24);
|
|
514
|
-
}
|
|
515
|
-
|
|
523
|
+
}
|
|
524
|
+
_next_pos() {
|
|
516
525
|
return this.bytes.byteArray.readInt32LE(this.bytes.start + 28);
|
|
517
|
-
}
|
|
518
|
-
|
|
526
|
+
}
|
|
527
|
+
template_length() {
|
|
519
528
|
return this.bytes.byteArray.readInt32LE(this.bytes.start + 32);
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
Object.keys(this).forEach(function (k) {
|
|
529
|
+
}
|
|
530
|
+
toJSON() {
|
|
531
|
+
const data = {};
|
|
532
|
+
for (const k of Object.keys(this)) {
|
|
525
533
|
if (k.charAt(0) === '_' || k === 'bytes') {
|
|
526
|
-
|
|
534
|
+
continue;
|
|
527
535
|
}
|
|
528
536
|
//@ts-ignore
|
|
529
|
-
data[k] =
|
|
530
|
-
}
|
|
537
|
+
data[k] = this[k];
|
|
538
|
+
}
|
|
531
539
|
return data;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
}());
|
|
540
|
+
}
|
|
541
|
+
}
|
|
535
542
|
exports.default = BamRecord;
|
|
536
543
|
//# sourceMappingURL=record.js.map
|