@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 CHANGED
@@ -1,19 +1,17 @@
1
- ## [7.1.3](https://github.com/GMOD/bam-js/compare/v7.1.2...v7.1.3) (2025-12-12)
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.2](https://github.com/GMOD/bam-js/compare/v7.1.1...v7.1.2) (2025-12-12)
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)
@@ -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> | undefined;
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
- NUMERIC_CIGAR: Uint32Array<ArrayBufferLike>;
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
- return ((this._dataView.getInt32(this.bytes.start + 16, true) & 0xffff0000) >> 16);
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
- let p = this.b0 +
76
- this.read_name_length +
77
- this.num_cigar_bytes +
78
- this.num_seq_bytes +
79
- this.seq_length;
80
- const blockEnd = this.bytes.end;
81
- while (p < blockEnd) {
82
- const tag = String.fromCharCode(this.byteArray[p]) +
83
- String.fromCharCode(this.byteArray[p + 1]);
84
- const type = String.fromCharCode(this.byteArray[p + 2]);
85
- p += 3;
86
- if (tag === 'MD' && type === 'Z') {
87
- const start = p;
88
- while (p < blockEnd && this.byteArray[p] !== 0) {
89
- p++;
90
- }
91
- return this.byteArray.subarray(start, p);
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
- else if (Btype === 'c' || Btype === 'C') {
125
- p += limit;
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(this.byteArray[p]) +
143
- String.fromCharCode(this.byteArray[p + 1]);
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(this.byteArray[p]);
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 'H': {
191
+ case 0x5a: // 'Z'
192
+ case 0x48: {
193
+ // 'H'
181
194
  const value = [];
182
195
  while (p <= blockEnd) {
183
- const cc = this.byteArray[p++];
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 'B': {
195
- const cc = this.byteArray[p++];
196
- const Btype = String.fromCharCode(cc);
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 = this.byteArray.byteOffset + p;
200
- if (Btype === 'i') {
212
+ const absOffset = ba.byteOffset + p;
213
+ if (Btype === 0x69) {
214
+ // 'i'
201
215
  if (absOffset % 4 === 0) {
202
- tags[tag] = new Int32Array(this.byteArray.buffer, absOffset, limit);
216
+ tags[tag] = new Int32Array(ba.buffer, absOffset, limit);
203
217
  }
204
218
  else {
205
- const bytes = this.byteArray.slice(p, p + (limit << 2));
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 === 'I') {
224
+ else if (Btype === 0x49) {
225
+ // 'I'
211
226
  if (absOffset % 4 === 0) {
212
- tags[tag] = new Uint32Array(this.byteArray.buffer, absOffset, limit);
227
+ tags[tag] = new Uint32Array(ba.buffer, absOffset, limit);
213
228
  }
214
229
  else {
215
- const bytes = this.byteArray.slice(p, p + (limit << 2));
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 === 's') {
235
+ else if (Btype === 0x73) {
236
+ // 's'
221
237
  if (absOffset % 2 === 0) {
222
- tags[tag] = new Int16Array(this.byteArray.buffer, absOffset, limit);
238
+ tags[tag] = new Int16Array(ba.buffer, absOffset, limit);
223
239
  }
224
240
  else {
225
- const bytes = this.byteArray.slice(p, p + (limit << 1));
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 === 'S') {
246
+ else if (Btype === 0x53) {
247
+ // 'S'
231
248
  if (absOffset % 2 === 0) {
232
- tags[tag] = new Uint16Array(this.byteArray.buffer, absOffset, limit);
249
+ tags[tag] = new Uint16Array(ba.buffer, absOffset, limit);
233
250
  }
234
251
  else {
235
- const bytes = this.byteArray.slice(p, p + (limit << 1));
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 === 'c') {
241
- tags[tag] = new Int8Array(this.byteArray.buffer, absOffset, limit);
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 === 'C') {
245
- tags[tag] = new Uint8Array(this.byteArray.buffer, absOffset, limit);
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 === 'f') {
267
+ else if (Btype === 0x66) {
268
+ // 'f'
249
269
  if (absOffset % 4 === 0) {
250
- tags[tag] = new Float32Array(this.byteArray.buffer, absOffset, limit);
270
+ tags[tag] = new Float32Array(ba.buffer, absOffset, limit);
251
271
  }
252
272
  else {
253
- const bytes = this.byteArray.slice(p, p + (limit << 2));
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
- else {
349
- const absOffset = this.byteArray.byteOffset + p;
350
- const cigarView = absOffset % 4 === 0
351
- ? new Uint32Array(this.byteArray.buffer, absOffset, numCigarOps)
352
- : new Uint32Array(this.byteArray.slice(p, p + (numCigarOps << 2)).buffer, 0, numCigarOps);
353
- let lref = 0;
354
- for (let c = 0; c < numCigarOps; ++c) {
355
- const cigop = cigarView[c];
356
- const op = cigop & 0xf;
357
- if (!((1 << op) & CIGAR_SKIP_MASK)) {
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
- const seqBytes = this.byteArray.subarray(p, p + this.num_seq_bytes);
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