@gmod/bam 8.5.1 → 8.7.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/README.md +30 -0
- package/dist/bamFile.d.ts +94 -1
- package/dist/bamFile.js +94 -3
- package/dist/bamFile.js.map +1 -1
- package/dist/htsget.d.ts +8 -1
- package/dist/htsget.js +4 -1
- package/dist/htsget.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/dist/mismatches.d.ts +130 -0
- package/dist/mismatches.js +404 -0
- package/dist/mismatches.js.map +1 -0
- package/dist/record.d.ts +46 -0
- package/dist/record.js +77 -10
- package/dist/record.js.map +1 -1
- package/dist/reference.d.ts +45 -0
- package/dist/reference.js +61 -0
- package/dist/reference.js.map +1 -0
- package/dist/seqAlphabet.d.ts +3 -0
- package/dist/seqAlphabet.js +14 -0
- package/dist/seqAlphabet.js.map +1 -0
- package/esm/bamFile.d.ts +94 -1
- package/esm/bamFile.js +94 -3
- package/esm/bamFile.js.map +1 -1
- package/esm/htsget.d.ts +8 -1
- package/esm/htsget.js +4 -1
- package/esm/htsget.js.map +1 -1
- package/esm/index.d.ts +5 -1
- package/esm/index.js +6 -0
- package/esm/index.js.map +1 -1
- package/esm/mismatches.d.ts +130 -0
- package/esm/mismatches.js +400 -0
- package/esm/mismatches.js.map +1 -0
- package/esm/record.d.ts +46 -0
- package/esm/record.js +70 -3
- package/esm/record.js.map +1 -1
- package/esm/reference.d.ts +45 -0
- package/esm/reference.js +55 -0
- package/esm/reference.js.map +1 -0
- package/esm/seqAlphabet.d.ts +3 -0
- package/esm/seqAlphabet.js +11 -0
- package/esm/seqAlphabet.js.map +1 -0
- package/package.json +1 -1
- package/src/bamFile.ts +178 -1
- package/src/htsget.ts +16 -2
- package/src/index.ts +26 -1
- package/src/mismatches.ts +629 -0
- package/src/record.ts +97 -3
- package/src/reference.ts +87 -0
- package/src/seqAlphabet.ts +10 -0
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MISMATCH_HARD_CLIP = exports.MISMATCH_SOFT_CLIP = exports.MISMATCH_REF_SKIP = exports.MISMATCH_DELETION = exports.MISMATCH_INSERTION = exports.MISMATCH_SUBST = void 0;
|
|
4
|
+
exports.forEachMismatchNumeric = forEachMismatchNumeric;
|
|
5
|
+
const cigar_ts_1 = require("./cigar.js");
|
|
6
|
+
const reference_ts_1 = require("./reference.js");
|
|
7
|
+
const seqAlphabet_ts_1 = require("./seqAlphabet.js");
|
|
8
|
+
/**
|
|
9
|
+
* The kind of difference a {@link Mismatch} reports, as the CIGAR-style char
|
|
10
|
+
* code it corresponds to. `@gmod/cram`'s `forEachMismatch` emits the same
|
|
11
|
+
* values (its `RF_*` constants), so one `switch` handles records from either
|
|
12
|
+
* format.
|
|
13
|
+
*
|
|
14
|
+
* Note these are char codes and NOT the packed-CIGAR op numbers in `cigar.ts`
|
|
15
|
+
* — `MISMATCH_DELETION` is 68 (`'D'`), where `CIGAR_DEL` is 2.
|
|
16
|
+
*/
|
|
17
|
+
exports.MISMATCH_SUBST = 88; // 'X'
|
|
18
|
+
exports.MISMATCH_INSERTION = 73; // 'I'
|
|
19
|
+
exports.MISMATCH_DELETION = 68; // 'D'
|
|
20
|
+
exports.MISMATCH_REF_SKIP = 78; // 'N'
|
|
21
|
+
exports.MISMATCH_SOFT_CLIP = 83; // 'S'
|
|
22
|
+
exports.MISMATCH_HARD_CLIP = 72; // 'H'
|
|
23
|
+
// M and = both mean "aligned to the reference", differing only in whether the
|
|
24
|
+
// file promises the bases match. Which is exactly the distinction MD (or the
|
|
25
|
+
// reference) exists to settle, so the walk treats them identically.
|
|
26
|
+
const CIGAR_M_EQ_MASK = (1 << cigar_ts_1.CIGAR_MATCH) | (1 << cigar_ts_1.CIGAR_EQUAL);
|
|
27
|
+
// A clip has no bases to report — its length travels in `clipLength`, which is
|
|
28
|
+
// what every consumer reads.
|
|
29
|
+
const NO_BASES = '';
|
|
30
|
+
function reportRefMismatch(callback, refPos, seqNibble, qual, refNibble) {
|
|
31
|
+
callback(exports.MISMATCH_SUBST, refPos, 1, seqAlphabet_ts_1.SEQRET_DECODER[seqNibble], qual, reference_ts_1.CHAR_CODE_FROM_NIBBLE[refNibble], 0);
|
|
32
|
+
}
|
|
33
|
+
// One base compared on its own: the ends of a run whose length or alignment
|
|
34
|
+
// leaves it without a partner in the same byte.
|
|
35
|
+
function compareRefBase(callback, numericSeq, qual, ref, seqIdx, refIdx, refPos) {
|
|
36
|
+
const seqNibble = (numericSeq[seqIdx >> 1] >> ((1 - (seqIdx & 1)) << 2)) & 0xf;
|
|
37
|
+
const refNibble = (0, reference_ts_1.referenceNibble)(ref, refIdx);
|
|
38
|
+
if (seqNibble !== refNibble) {
|
|
39
|
+
reportRefMismatch(callback, refPos, seqNibble, qual ? qual[seqIdx] : -1, refNibble);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The mismatch walk over a record's already-packed fields, for callers holding
|
|
44
|
+
* BAM's arrays without a {@link BamRecord} around them — a SAM parser, or a
|
|
45
|
+
* worker that was handed the typed arrays rather than the record.
|
|
46
|
+
* `record.forEachMismatch()` is this function with the record's own fields
|
|
47
|
+
* filled in, and is what most code should call.
|
|
48
|
+
*
|
|
49
|
+
* Nothing here allocates per difference except the `bases` string, and that
|
|
50
|
+
* only for substitutions and insertions.
|
|
51
|
+
*
|
|
52
|
+
* @param cigar packed CIGAR ops, i.e. `record.NUMERIC_CIGAR`
|
|
53
|
+
* @param numericSeq 4-bit packed SEQ, i.e. `record.NUMERIC_SEQ`
|
|
54
|
+
* @param seqLength bases in `numericSeq`; 0 for a read stored with `SEQ` of `*`
|
|
55
|
+
* @param md the MD tag's bytes (`record.NUMERIC_MD`), or undefined. Preferred
|
|
56
|
+
* over `ref` when present, being both cheaper and what the aligner asserted
|
|
57
|
+
* @param qual per-base quality scores, or null/undefined when the read has none
|
|
58
|
+
* @param ref reference bases to compare against when there is no MD tag. Bases
|
|
59
|
+
* the region does not cover are left uncompared
|
|
60
|
+
* @param refStart the record's own 0-based reference start
|
|
61
|
+
* @param windowStart 0-based half-open reference window to report within, in
|
|
62
|
+
* ABSOLUTE reference coordinates whatever `origin` is. Pass
|
|
63
|
+
* `-Infinity`/`Infinity` for the whole read; a viewport that clips the walk
|
|
64
|
+
* is what keeps a chromosome-spanning contig alignment from being walked in
|
|
65
|
+
* full for every screenful
|
|
66
|
+
* @param windowEnd
|
|
67
|
+
* @param origin what reported positions are relative to: 0 for reference
|
|
68
|
+
* positions, `refStart` for read-relative ones. See
|
|
69
|
+
* {@link MismatchOptions.origin}
|
|
70
|
+
* @param callback `(code, refPos, length, bases, qual, refBaseCode, clipLength)`
|
|
71
|
+
*/
|
|
72
|
+
function forEachMismatchNumeric(cigar, numericSeq, seqLength, md, qual, ref, refStart, windowStart, windowEnd, origin, callback) {
|
|
73
|
+
// The walk runs in read-relative offsets — `roffset` reference bases and
|
|
74
|
+
// `soffset` read bases consumed — and converts back at the callback, so the
|
|
75
|
+
// window is converted once here rather than per op.
|
|
76
|
+
//
|
|
77
|
+
// Clamped to int32 rather than left at the ±Infinity an unwindowed walk
|
|
78
|
+
// passes, because every op of the walk compares an offset against these and
|
|
79
|
+
// Infinity makes each of those a Float64 comparison. BAM positions are int32,
|
|
80
|
+
// so this cannot narrow a window anyone can express.
|
|
81
|
+
const winLo = windowStart <= -0x80000000 ? -0x80000000 : windowStart - refStart;
|
|
82
|
+
const winHi = windowEnd >= 0x7fffffff ? 0x7fffffff : windowEnd - refStart;
|
|
83
|
+
// What an offset is emitted as. Folding `origin` in here rather than at the
|
|
84
|
+
// callbacks keeps the cost of having the option at zero: every emit already
|
|
85
|
+
// added `refStart`, and now adds this instead.
|
|
86
|
+
const outBase = refStart - origin;
|
|
87
|
+
// Fast path for reads with no sequence (e.g. secondary alignments with SEQ='*')
|
|
88
|
+
if (seqLength === 0) {
|
|
89
|
+
let roffset = 0;
|
|
90
|
+
for (let i = 0, l = cigar.length; i < l; i++) {
|
|
91
|
+
// `roffset` only grows, and nothing at or past the window's right edge is
|
|
92
|
+
// reported, so the rest of the CIGAR cannot produce anything (see the
|
|
93
|
+
// same check in the main loop)
|
|
94
|
+
if (roffset >= winHi) {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
const packed = cigar[i];
|
|
98
|
+
const len = packed >>> 4;
|
|
99
|
+
const op = packed & 0xf;
|
|
100
|
+
// X consumes the reference exactly like M/=; without a sequence there are
|
|
101
|
+
// no bases to report for it, but it still has to advance — leaving it out
|
|
102
|
+
// shifted every later op left by the total X length, which is every indel
|
|
103
|
+
// in an --eqx CIGAR walked without a sequence.
|
|
104
|
+
if ((1 << op) & CIGAR_M_EQ_MASK || op === cigar_ts_1.CIGAR_DIFF) {
|
|
105
|
+
roffset += len;
|
|
106
|
+
}
|
|
107
|
+
else if (op === cigar_ts_1.CIGAR_INS) {
|
|
108
|
+
if (roffset >= winLo && roffset < winHi) {
|
|
109
|
+
callback(exports.MISMATCH_INSERTION, outBase + roffset, 0, '', -1, 0, len);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (op === cigar_ts_1.CIGAR_DEL) {
|
|
113
|
+
if (roffset < winHi && roffset + len > winLo) {
|
|
114
|
+
callback(exports.MISMATCH_DELETION, outBase + roffset, len, NO_BASES, -1, 0, 0);
|
|
115
|
+
}
|
|
116
|
+
roffset += len;
|
|
117
|
+
}
|
|
118
|
+
else if (op === cigar_ts_1.CIGAR_REF_SKIP) {
|
|
119
|
+
if (roffset < winHi && roffset + len > winLo) {
|
|
120
|
+
callback(exports.MISMATCH_REF_SKIP, outBase + roffset, len, NO_BASES, -1, 0, 0);
|
|
121
|
+
}
|
|
122
|
+
roffset += len;
|
|
123
|
+
}
|
|
124
|
+
else if (op === cigar_ts_1.CIGAR_SOFT_CLIP) {
|
|
125
|
+
if (roffset >= winLo && roffset < winHi) {
|
|
126
|
+
callback(exports.MISMATCH_SOFT_CLIP, outBase + roffset, 0, NO_BASES, -1, 0, len);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
else if (op === cigar_ts_1.CIGAR_HARD_CLIP) {
|
|
130
|
+
if (roffset >= winLo && roffset < winHi) {
|
|
131
|
+
callback(exports.MISMATCH_HARD_CLIP, outBase + roffset, 0, NO_BASES, -1, 0, len);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const mdLength = md?.length ?? 0;
|
|
138
|
+
const hasQual = !!qual;
|
|
139
|
+
const hasMD = md && mdLength > 0;
|
|
140
|
+
// Where the reference region sits in read-relative offsets, and the window
|
|
141
|
+
// narrowed to it. Only base COMPARISON is bounded by the region — an indel or
|
|
142
|
+
// a clip needs no reference base, so a region covering part of a read still
|
|
143
|
+
// reports every one of them.
|
|
144
|
+
//
|
|
145
|
+
// Ternaries rather than Math.max/Math.min, which matters more than it looks:
|
|
146
|
+
// an unwindowed walk has `winLo`/`winHi` at ±Infinity, so Math.min would hand
|
|
147
|
+
// back a Float64 and `cmpHi` would carry that all the way into `jHi`, the
|
|
148
|
+
// bound of the innermost (two-bases-per-byte) loop. This way an unwindowed
|
|
149
|
+
// walk keeps that bound a Smi, which measured ~8% of the reference path on
|
|
150
|
+
// dense short reads.
|
|
151
|
+
let refOffset = 0;
|
|
152
|
+
let cmpLo = 0;
|
|
153
|
+
let cmpHi = 0;
|
|
154
|
+
if (ref !== undefined) {
|
|
155
|
+
refOffset = refStart - ref.start;
|
|
156
|
+
const refLo = -refOffset;
|
|
157
|
+
const refHi = ref.length - refOffset;
|
|
158
|
+
cmpLo = winLo > refLo ? winLo : refLo;
|
|
159
|
+
cmpHi = winHi < refHi ? winHi : refHi;
|
|
160
|
+
}
|
|
161
|
+
let roffset = 0;
|
|
162
|
+
let soffset = 0;
|
|
163
|
+
let mdIdx = 0;
|
|
164
|
+
let mdMatchRemaining = 0;
|
|
165
|
+
if (hasMD) {
|
|
166
|
+
while (mdIdx < mdLength) {
|
|
167
|
+
const c = md[mdIdx];
|
|
168
|
+
if (c >= 48 && c <= 57) {
|
|
169
|
+
mdMatchRemaining = mdMatchRemaining * 10 + (c - 48);
|
|
170
|
+
mdIdx++;
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
for (let i = 0, l = cigar.length; i < l; i++) {
|
|
178
|
+
// Stop at the window's right edge rather than walking the rest of the
|
|
179
|
+
// CIGAR: `roffset` only grows, and every report below needs
|
|
180
|
+
// `roffset < winHi`, so nothing past here can produce anything. Matters for
|
|
181
|
+
// a whole chromosome stored as one BAM read, whose CIGAR runs to millions
|
|
182
|
+
// of ops for a screenful of them — and costs one compare per op otherwise,
|
|
183
|
+
// since an unwindowed walk has `winHi` at +Infinity.
|
|
184
|
+
if (roffset >= winHi) {
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
const packed = cigar[i];
|
|
188
|
+
const len = packed >>> 4;
|
|
189
|
+
const op = packed & 0xf;
|
|
190
|
+
if ((1 << op) & CIGAR_M_EQ_MASK) {
|
|
191
|
+
if (hasMD) {
|
|
192
|
+
let remaining = len;
|
|
193
|
+
let localOffset = 0;
|
|
194
|
+
while (remaining > 0) {
|
|
195
|
+
if (mdMatchRemaining >= remaining) {
|
|
196
|
+
mdMatchRemaining -= remaining;
|
|
197
|
+
localOffset += remaining;
|
|
198
|
+
remaining = 0;
|
|
199
|
+
}
|
|
200
|
+
else {
|
|
201
|
+
localOffset += mdMatchRemaining;
|
|
202
|
+
remaining -= mdMatchRemaining;
|
|
203
|
+
mdMatchRemaining = 0;
|
|
204
|
+
if (mdIdx < mdLength && md[mdIdx] >= 65 && md[mdIdx] <= 90) {
|
|
205
|
+
const pos = roffset + localOffset;
|
|
206
|
+
if (pos >= winLo && pos < winHi) {
|
|
207
|
+
const seqIdx = soffset + localOffset;
|
|
208
|
+
const sb = numericSeq[seqIdx >> 1];
|
|
209
|
+
const nibble = (sb >> ((1 - (seqIdx & 1)) << 2)) & 0xf;
|
|
210
|
+
callback(exports.MISMATCH_SUBST, outBase + pos, 1, seqAlphabet_ts_1.SEQRET_DECODER[nibble], hasQual ? qual[seqIdx] : -1, md[mdIdx], 0);
|
|
211
|
+
}
|
|
212
|
+
mdIdx++;
|
|
213
|
+
localOffset++;
|
|
214
|
+
remaining--;
|
|
215
|
+
mdMatchRemaining = 0;
|
|
216
|
+
while (mdIdx < mdLength) {
|
|
217
|
+
const c = md[mdIdx];
|
|
218
|
+
if (c >= 48 && c <= 57) {
|
|
219
|
+
mdMatchRemaining = mdMatchRemaining * 10 + (c - 48);
|
|
220
|
+
mdIdx++;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
break;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
else if (ref) {
|
|
234
|
+
// Only compare bases whose reference position falls in the window AND
|
|
235
|
+
// in the region. A whole-chromosome contig has M ops totalling ~250M
|
|
236
|
+
// bases; without this clip every one is compared (and `ref` would have
|
|
237
|
+
// to cover the whole chromosome).
|
|
238
|
+
const jLo = cmpLo > roffset ? cmpLo - roffset : 0;
|
|
239
|
+
const jHi = cmpHi < roffset + len ? cmpHi - roffset : len;
|
|
240
|
+
let j = jLo;
|
|
241
|
+
// A leading odd read index has no partner in its byte, so compare it
|
|
242
|
+
// alone and let the pair loop start on a byte boundary.
|
|
243
|
+
if (j < jHi && (soffset + j) & 1) {
|
|
244
|
+
compareRefBase(callback, numericSeq, qual, ref, soffset + j, refOffset + roffset + j, outBase + roffset + j);
|
|
245
|
+
j++;
|
|
246
|
+
}
|
|
247
|
+
// Two bases per byte load and compare. `even`/`odd` differ only in
|
|
248
|
+
// which reference parity they put on a byte boundary, so one of them
|
|
249
|
+
// always lines up with the read's packed sequence; the nibbles are
|
|
250
|
+
// unpacked only for the byte that actually differs.
|
|
251
|
+
const refIdx = refOffset + roffset + j;
|
|
252
|
+
const refPairs = refIdx & 1 ? ref.odd : ref.even;
|
|
253
|
+
let refByte = (refIdx + (refIdx & 1)) >> 1;
|
|
254
|
+
let seqByte = (soffset + j) >> 1;
|
|
255
|
+
for (; j + 1 < jHi; j += 2, refByte++, seqByte++) {
|
|
256
|
+
const seqPair = numericSeq[seqByte];
|
|
257
|
+
const refPair = refPairs[refByte];
|
|
258
|
+
if (seqPair !== refPair) {
|
|
259
|
+
const seqHi = (seqPair >> 4) & 0xf;
|
|
260
|
+
const refHi = (refPair >> 4) & 0xf;
|
|
261
|
+
if (seqHi !== refHi) {
|
|
262
|
+
reportRefMismatch(callback, outBase + roffset + j, seqHi, hasQual ? qual[soffset + j] : -1, refHi);
|
|
263
|
+
}
|
|
264
|
+
const seqLo = seqPair & 0xf;
|
|
265
|
+
const refLo = refPair & 0xf;
|
|
266
|
+
if (seqLo !== refLo) {
|
|
267
|
+
reportRefMismatch(callback, outBase + roffset + j + 1, seqLo, hasQual ? qual[soffset + j + 1] : -1, refLo);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (j < jHi) {
|
|
272
|
+
compareRefBase(callback, numericSeq, qual, ref, soffset + j, refOffset + roffset + j, outBase + roffset + j);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
soffset += len;
|
|
276
|
+
roffset += len;
|
|
277
|
+
}
|
|
278
|
+
else if (op === cigar_ts_1.CIGAR_INS) {
|
|
279
|
+
if (roffset >= winLo && roffset < winHi) {
|
|
280
|
+
// Optimized insertion base extraction - avoid string concat for common
|
|
281
|
+
// cases
|
|
282
|
+
let insertedBases;
|
|
283
|
+
if (len === 1) {
|
|
284
|
+
// Single base insertion - most common case
|
|
285
|
+
const sb = numericSeq[soffset >> 1];
|
|
286
|
+
const nibble = (sb >> ((1 - (soffset & 1)) << 2)) & 0xf;
|
|
287
|
+
insertedBases = seqAlphabet_ts_1.SEQRET_DECODER[nibble];
|
|
288
|
+
}
|
|
289
|
+
else if (len === 2) {
|
|
290
|
+
// Two base insertion - second most common
|
|
291
|
+
const seqIdx0 = soffset;
|
|
292
|
+
const sb0 = numericSeq[seqIdx0 >> 1];
|
|
293
|
+
const nibble0 = (sb0 >> ((1 - (seqIdx0 & 1)) << 2)) & 0xf;
|
|
294
|
+
const seqIdx1 = soffset + 1;
|
|
295
|
+
const sb1 = numericSeq[seqIdx1 >> 1];
|
|
296
|
+
const nibble1 = (sb1 >> ((1 - (seqIdx1 & 1)) << 2)) & 0xf;
|
|
297
|
+
insertedBases = seqAlphabet_ts_1.SEQRET_DECODER[nibble0] + seqAlphabet_ts_1.SEQRET_DECODER[nibble1];
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
const bases = new Array(len);
|
|
301
|
+
for (let j = 0; j < len; j++) {
|
|
302
|
+
const seqIdx = soffset + j;
|
|
303
|
+
const sb = numericSeq[seqIdx >> 1];
|
|
304
|
+
const nibble = (sb >> ((1 - (seqIdx & 1)) << 2)) & 0xf;
|
|
305
|
+
bases[j] = seqAlphabet_ts_1.SEQRET_DECODER[nibble];
|
|
306
|
+
}
|
|
307
|
+
insertedBases = bases.join('');
|
|
308
|
+
}
|
|
309
|
+
callback(exports.MISMATCH_INSERTION, outBase + roffset, 0, insertedBases, -1, 0, len);
|
|
310
|
+
}
|
|
311
|
+
soffset += len;
|
|
312
|
+
}
|
|
313
|
+
else if (op === cigar_ts_1.CIGAR_DEL) {
|
|
314
|
+
if (roffset < winHi && roffset + len > winLo) {
|
|
315
|
+
callback(exports.MISMATCH_DELETION, outBase + roffset, len, NO_BASES, -1, 0, 0);
|
|
316
|
+
}
|
|
317
|
+
// MD spells a deletion as ^ then the deleted reference bases, which are
|
|
318
|
+
// not a difference this reports (the D above already is) but do have to
|
|
319
|
+
// be stepped over, or every later position in the read reads off the
|
|
320
|
+
// wrong part of the tag.
|
|
321
|
+
// eslint-disable-next-line @typescript-eslint/no-confusing-non-null-assertion
|
|
322
|
+
if (hasMD && mdIdx < mdLength && md[mdIdx] === 94) {
|
|
323
|
+
mdIdx++;
|
|
324
|
+
while (mdIdx < mdLength && md[mdIdx] >= 65) {
|
|
325
|
+
mdIdx++;
|
|
326
|
+
}
|
|
327
|
+
mdMatchRemaining = 0;
|
|
328
|
+
while (mdIdx < mdLength) {
|
|
329
|
+
const c = md[mdIdx];
|
|
330
|
+
if (c >= 48 && c <= 57) {
|
|
331
|
+
mdMatchRemaining = mdMatchRemaining * 10 + (c - 48);
|
|
332
|
+
mdIdx++;
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
roffset += len;
|
|
340
|
+
}
|
|
341
|
+
else if (op === cigar_ts_1.CIGAR_REF_SKIP) {
|
|
342
|
+
if (roffset < winHi && roffset + len > winLo) {
|
|
343
|
+
callback(exports.MISMATCH_REF_SKIP, outBase + roffset, len, NO_BASES, -1, 0, 0);
|
|
344
|
+
}
|
|
345
|
+
roffset += len;
|
|
346
|
+
}
|
|
347
|
+
else if (op === cigar_ts_1.CIGAR_DIFF) {
|
|
348
|
+
for (let j = 0; j < len; j++) {
|
|
349
|
+
const seqIdx = soffset + j;
|
|
350
|
+
const sb = numericSeq[seqIdx >> 1];
|
|
351
|
+
const nibble = (sb >> ((1 - (seqIdx & 1)) << 2)) & 0xf;
|
|
352
|
+
// An X op says a substitution is here without saying what it replaces,
|
|
353
|
+
// so the reference base comes from MD or the region — and is 0, i.e.
|
|
354
|
+
// unknown, when the read carries neither.
|
|
355
|
+
let refBaseCode = 0;
|
|
356
|
+
if (hasMD) {
|
|
357
|
+
if (mdMatchRemaining === 0 && mdIdx < mdLength && md[mdIdx] >= 65) {
|
|
358
|
+
refBaseCode = md[mdIdx];
|
|
359
|
+
mdIdx++;
|
|
360
|
+
mdMatchRemaining = 0;
|
|
361
|
+
while (mdIdx < mdLength) {
|
|
362
|
+
const c = md[mdIdx];
|
|
363
|
+
if (c >= 48 && c <= 57) {
|
|
364
|
+
mdMatchRemaining = mdMatchRemaining * 10 + (c - 48);
|
|
365
|
+
mdIdx++;
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
else if (mdMatchRemaining > 0) {
|
|
373
|
+
mdMatchRemaining--;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
else if (ref) {
|
|
377
|
+
const refIdx = refOffset + roffset + j;
|
|
378
|
+
if (refIdx >= 0 && refIdx < ref.length) {
|
|
379
|
+
refBaseCode = reference_ts_1.CHAR_CODE_FROM_NIBBLE[(0, reference_ts_1.referenceNibble)(ref, refIdx)];
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
const pos = roffset + j;
|
|
383
|
+
if (pos >= winLo && pos < winHi) {
|
|
384
|
+
callback(exports.MISMATCH_SUBST, outBase + pos, 1, seqAlphabet_ts_1.SEQRET_DECODER[nibble], hasQual ? qual[seqIdx] : -1, refBaseCode, 0);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
soffset += len;
|
|
388
|
+
roffset += len;
|
|
389
|
+
}
|
|
390
|
+
else if (op === cigar_ts_1.CIGAR_SOFT_CLIP) {
|
|
391
|
+
if (roffset >= winLo && roffset < winHi) {
|
|
392
|
+
callback(exports.MISMATCH_SOFT_CLIP, outBase + roffset, 0, NO_BASES, -1, 0, len);
|
|
393
|
+
}
|
|
394
|
+
soffset += len;
|
|
395
|
+
}
|
|
396
|
+
else if (op === cigar_ts_1.CIGAR_HARD_CLIP) {
|
|
397
|
+
if (roffset >= winLo && roffset < winHi) {
|
|
398
|
+
callback(exports.MISMATCH_HARD_CLIP, outBase + roffset, 0, NO_BASES, -1, 0, len);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
// P (padding) consumes neither read nor reference and is not a difference
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
//# sourceMappingURL=mismatches.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mismatches.js","sourceRoot":"","sources":["../src/mismatches.ts"],"names":[],"mappings":"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"}
|
package/dist/record.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Mismatch, MismatchCallback, MismatchOptions } from './mismatches.ts';
|
|
2
|
+
import type { PackedReference } from './reference.ts';
|
|
1
3
|
export type NumericCigar = Uint32Array | Int32Array | number[];
|
|
2
4
|
export default class BamRecord {
|
|
3
5
|
fileOffset: number;
|
|
@@ -11,6 +13,7 @@ export default class BamRecord {
|
|
|
11
13
|
private _cachedNumericCigar?;
|
|
12
14
|
private _cachedNUMERIC_MD?;
|
|
13
15
|
private _cachedSeqStart?;
|
|
16
|
+
private _reference?;
|
|
14
17
|
constructor(byteArray: Uint8Array, start: number, end: number, fileOffset: number, dataView: DataView);
|
|
15
18
|
get byteArray(): Uint8Array<ArrayBufferLike>;
|
|
16
19
|
get flags(): number;
|
|
@@ -79,5 +82,48 @@ export default class BamRecord {
|
|
|
79
82
|
get next_pos(): number;
|
|
80
83
|
get template_length(): number;
|
|
81
84
|
seqAt(idx: number): string | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Bind reference bases for this read to resolve its substitutions against,
|
|
87
|
+
* for a read with no MD tag. `BamFile` calls this for you when it was given a
|
|
88
|
+
* `fetchReferenceSequence`; call it yourself when you have the bases from
|
|
89
|
+
* somewhere else.
|
|
90
|
+
*
|
|
91
|
+
* **`ref` must cover the whole read**, and this throws if it does not. The
|
|
92
|
+
* reason is that records are cached and shared between queries (ADR 0006), so
|
|
93
|
+
* a binding that varied by query would make one query's reads answer out of
|
|
94
|
+
* another's region. A region covering the read is the same data whichever
|
|
95
|
+
* query fetched it, so binding it is safe; a partial one is not, and the
|
|
96
|
+
* per-call `forEachMismatch(cb, {ref})` is where that belongs.
|
|
97
|
+
*/
|
|
98
|
+
setReference(ref: PackedReference | undefined): void;
|
|
99
|
+
/** the region {@link setReference} bound, if any */
|
|
100
|
+
get reference(): PackedReference | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* Report each difference between this read and the reference —
|
|
103
|
+
* substitutions, insertions, deletions, reference skips and clips — without
|
|
104
|
+
* allocating an object per difference. This is the intended way to read a
|
|
105
|
+
* record's differences; deriving them from `CIGAR` and `MD` yourself takes
|
|
106
|
+
* rather more of the format to interpret correctly (see {@link Mismatch}).
|
|
107
|
+
*
|
|
108
|
+
* Substitutions come from the MD tag when the read has one, and otherwise
|
|
109
|
+
* from comparing SEQ against reference bases — which have to come from
|
|
110
|
+
* {@link setReference}, `opts.ref`, or the file's `fetchReferenceSequence`.
|
|
111
|
+
* With neither MD nor reference, indels and clips are still reported in full
|
|
112
|
+
* and substitutions are not reported at all: nothing in the record says where
|
|
113
|
+
* they are.
|
|
114
|
+
*
|
|
115
|
+
* @param callback called as
|
|
116
|
+
* `(code, refPos, length, bases, qual, refBaseCode, clipLength)`
|
|
117
|
+
* @param opts optional reference window to restrict to, an `origin` the
|
|
118
|
+
* reported positions are relative to, and an optional per-call reference
|
|
119
|
+
* region; see {@link MismatchOptions}
|
|
120
|
+
*/
|
|
121
|
+
forEachMismatch(callback: MismatchCallback, opts?: MismatchOptions): void;
|
|
122
|
+
/**
|
|
123
|
+
* The same differences {@link forEachMismatch} reports, as an array of
|
|
124
|
+
* {@link Mismatch} objects. Convenient; allocates one object per difference,
|
|
125
|
+
* so the callback form is the one to reach for on a hot path.
|
|
126
|
+
*/
|
|
127
|
+
getMismatches(opts?: MismatchOptions): Mismatch[];
|
|
82
128
|
toJSON(): Record<string, unknown>;
|
|
83
129
|
}
|
package/dist/record.js
CHANGED
|
@@ -5,9 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const cigar_ts_1 = require("./cigar.js");
|
|
7
7
|
const constants_ts_1 = __importDefault(require("./constants.js"));
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
8
|
+
const mismatches_ts_1 = require("./mismatches.js");
|
|
9
|
+
const reference_ts_1 = require("./reference.js");
|
|
10
|
+
const seqAlphabet_ts_1 = require("./seqAlphabet.js");
|
|
11
11
|
// Both bases of a SEQ byte, precomputed for all 256 bytes so decoding advances a
|
|
12
12
|
// byte at a time. Two forms because `seq` has two strategies (see below): packed
|
|
13
13
|
// ASCII codes for a single Uint16Array store, and the 2-char string to append.
|
|
@@ -17,13 +17,13 @@ const SEQRET_PAIR_CODES = new Uint16Array(256);
|
|
|
17
17
|
const SEQRET_PAIR_STRINGS = new Array(256);
|
|
18
18
|
for (let hi = 0; hi < 16; hi++) {
|
|
19
19
|
for (let lo = 0; lo < 16; lo++) {
|
|
20
|
-
const h = SEQRET_CODES[hi];
|
|
21
|
-
const l = SEQRET_CODES[lo];
|
|
20
|
+
const h = seqAlphabet_ts_1.SEQRET_CODES[hi];
|
|
21
|
+
const l = seqAlphabet_ts_1.SEQRET_CODES[lo];
|
|
22
22
|
SEQRET_PAIR_CODES[(hi << 4) | lo] = LITTLE_ENDIAN
|
|
23
23
|
? h | (l << 8)
|
|
24
24
|
: (h << 8) | l;
|
|
25
25
|
SEQRET_PAIR_STRINGS[(hi << 4) | lo] =
|
|
26
|
-
SEQRET_DECODER[hi] + SEQRET_DECODER[lo];
|
|
26
|
+
seqAlphabet_ts_1.SEQRET_DECODER[hi] + seqAlphabet_ts_1.SEQRET_DECODER[lo];
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
// Read length at which building a byte buffer and calling TextDecoder once
|
|
@@ -325,6 +325,7 @@ class BamRecord {
|
|
|
325
325
|
_cachedNumericCigar;
|
|
326
326
|
_cachedNUMERIC_MD;
|
|
327
327
|
_cachedSeqStart;
|
|
328
|
+
_reference;
|
|
328
329
|
// Positional rather than an options object, because every argument is
|
|
329
330
|
// unpacked into a field immediately and nothing keeps the wrapper. The
|
|
330
331
|
// options form allocated two throwaway objects for each of the ~200k records
|
|
@@ -742,7 +743,7 @@ class BamRecord {
|
|
|
742
743
|
}
|
|
743
744
|
}
|
|
744
745
|
if (len & 1) {
|
|
745
|
-
seq += SEQRET_DECODER[(ba[p + nPairs] & 0xf0) >> 4];
|
|
746
|
+
seq += seqAlphabet_ts_1.SEQRET_DECODER[(ba[p + nPairs] & 0xf0) >> 4];
|
|
746
747
|
}
|
|
747
748
|
}
|
|
748
749
|
else {
|
|
@@ -754,7 +755,7 @@ class BamRecord {
|
|
|
754
755
|
pairs[j] = SEQRET_PAIR_CODES[ba[p + j]];
|
|
755
756
|
}
|
|
756
757
|
if (len & 1) {
|
|
757
|
-
out[len - 1] = SEQRET_CODES[(ba[p + nPairs] & 0xf0) >> 4];
|
|
758
|
+
out[len - 1] = seqAlphabet_ts_1.SEQRET_CODES[(ba[p + nPairs] & 0xf0) >> 4];
|
|
758
759
|
}
|
|
759
760
|
seq = textDecoder.decode(out.subarray(0, len));
|
|
760
761
|
}
|
|
@@ -809,13 +810,79 @@ class BamRecord {
|
|
|
809
810
|
if (idx < this.seq_length) {
|
|
810
811
|
const sb = this._byteArray[this.seqStart + (idx >> 1)];
|
|
811
812
|
return (idx & 1) === 0
|
|
812
|
-
? SEQRET_DECODER[(sb & 0xf0) >> 4]
|
|
813
|
-
: SEQRET_DECODER[sb & 0x0f];
|
|
813
|
+
? seqAlphabet_ts_1.SEQRET_DECODER[(sb & 0xf0) >> 4]
|
|
814
|
+
: seqAlphabet_ts_1.SEQRET_DECODER[sb & 0x0f];
|
|
814
815
|
}
|
|
815
816
|
else {
|
|
816
817
|
return undefined;
|
|
817
818
|
}
|
|
818
819
|
}
|
|
820
|
+
/**
|
|
821
|
+
* Bind reference bases for this read to resolve its substitutions against,
|
|
822
|
+
* for a read with no MD tag. `BamFile` calls this for you when it was given a
|
|
823
|
+
* `fetchReferenceSequence`; call it yourself when you have the bases from
|
|
824
|
+
* somewhere else.
|
|
825
|
+
*
|
|
826
|
+
* **`ref` must cover the whole read**, and this throws if it does not. The
|
|
827
|
+
* reason is that records are cached and shared between queries (ADR 0006), so
|
|
828
|
+
* a binding that varied by query would make one query's reads answer out of
|
|
829
|
+
* another's region. A region covering the read is the same data whichever
|
|
830
|
+
* query fetched it, so binding it is safe; a partial one is not, and the
|
|
831
|
+
* per-call `forEachMismatch(cb, {ref})` is where that belongs.
|
|
832
|
+
*/
|
|
833
|
+
setReference(ref) {
|
|
834
|
+
if (ref !== undefined && !(0, reference_ts_1.referenceCovers)(ref, this.start, this.end)) {
|
|
835
|
+
throw new Error(`reference region ${ref.start}-${ref.start + ref.length} does not cover the record at ${this.start}-${this.end}. Records are shared between queries, so only a region covering the whole read can be bound to one; pass a partial region per call instead, as forEachMismatch(cb, {ref})`);
|
|
836
|
+
}
|
|
837
|
+
this._reference = ref;
|
|
838
|
+
}
|
|
839
|
+
/** the region {@link setReference} bound, if any */
|
|
840
|
+
get reference() {
|
|
841
|
+
return this._reference;
|
|
842
|
+
}
|
|
843
|
+
/**
|
|
844
|
+
* Report each difference between this read and the reference —
|
|
845
|
+
* substitutions, insertions, deletions, reference skips and clips — without
|
|
846
|
+
* allocating an object per difference. This is the intended way to read a
|
|
847
|
+
* record's differences; deriving them from `CIGAR` and `MD` yourself takes
|
|
848
|
+
* rather more of the format to interpret correctly (see {@link Mismatch}).
|
|
849
|
+
*
|
|
850
|
+
* Substitutions come from the MD tag when the read has one, and otherwise
|
|
851
|
+
* from comparing SEQ against reference bases — which have to come from
|
|
852
|
+
* {@link setReference}, `opts.ref`, or the file's `fetchReferenceSequence`.
|
|
853
|
+
* With neither MD nor reference, indels and clips are still reported in full
|
|
854
|
+
* and substitutions are not reported at all: nothing in the record says where
|
|
855
|
+
* they are.
|
|
856
|
+
*
|
|
857
|
+
* @param callback called as
|
|
858
|
+
* `(code, refPos, length, bases, qual, refBaseCode, clipLength)`
|
|
859
|
+
* @param opts optional reference window to restrict to, an `origin` the
|
|
860
|
+
* reported positions are relative to, and an optional per-call reference
|
|
861
|
+
* region; see {@link MismatchOptions}
|
|
862
|
+
*/
|
|
863
|
+
forEachMismatch(callback, opts) {
|
|
864
|
+
(0, mismatches_ts_1.forEachMismatchNumeric)(this.NUMERIC_CIGAR, this.NUMERIC_SEQ, this.seq_length, this.NUMERIC_MD, this.qual, opts?.ref ?? this._reference, this.start, opts?.start ?? Number.NEGATIVE_INFINITY, opts?.end ?? Number.POSITIVE_INFINITY, opts?.origin ?? 0, callback);
|
|
865
|
+
}
|
|
866
|
+
/**
|
|
867
|
+
* The same differences {@link forEachMismatch} reports, as an array of
|
|
868
|
+
* {@link Mismatch} objects. Convenient; allocates one object per difference,
|
|
869
|
+
* so the callback form is the one to reach for on a hot path.
|
|
870
|
+
*/
|
|
871
|
+
getMismatches(opts) {
|
|
872
|
+
const out = [];
|
|
873
|
+
this.forEachMismatch((code, refPos, length, bases, qual, refBaseCode, clipLength) => {
|
|
874
|
+
out.push({
|
|
875
|
+
code,
|
|
876
|
+
refPos,
|
|
877
|
+
length,
|
|
878
|
+
bases,
|
|
879
|
+
qual,
|
|
880
|
+
refBaseCode,
|
|
881
|
+
clipLength,
|
|
882
|
+
});
|
|
883
|
+
}, opts);
|
|
884
|
+
return out;
|
|
885
|
+
}
|
|
819
886
|
// Most public BamRecord fields are getters on the prototype, so
|
|
820
887
|
// Object.keys(this) wouldn't include them — JSON.stringify needs an explicit
|
|
821
888
|
// list. Returns the meaningful BAM-spec fields. Return type is widened so
|