@jbrowse/plugin-alignments 1.7.7 → 1.7.8

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.
Files changed (31) hide show
  1. package/dist/BamAdapter/BamAdapter.d.ts +1 -1
  2. package/dist/BamAdapter/BamAdapter.js +3 -3
  3. package/dist/BamAdapter/MismatchParser.d.ts +2 -5
  4. package/dist/BamAdapter/MismatchParser.js +104 -44
  5. package/dist/BamAdapter/MismatchParser.test.js +6 -14
  6. package/dist/CramAdapter/CramAdapter.d.ts +10 -9
  7. package/dist/CramAdapter/CramAdapter.js +6 -6
  8. package/dist/CramAdapter/CramSlightlyLazyFeature.js +35 -30
  9. package/dist/LinearPileupDisplay/model.js +1 -1
  10. package/dist/LinearSNPCoverageDisplay/components/Tooltip.js +2 -3
  11. package/dist/LinearSNPCoverageDisplay/models/model.js +1 -1
  12. package/dist/PileupRenderer/PileupLayoutSession.d.ts +3 -0
  13. package/dist/PileupRenderer/PileupLayoutSession.js +3 -1
  14. package/dist/PileupRenderer/PileupRenderer.d.ts +1 -1
  15. package/dist/PileupRenderer/PileupRenderer.js +125 -162
  16. package/dist/PileupRenderer/configSchema.js +2 -2
  17. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.d.ts +4 -6
  18. package/dist/SNPCoverageAdapter/SNPCoverageAdapter.js +92 -96
  19. package/package.json +3 -3
  20. package/src/BamAdapter/BamAdapter.ts +3 -3
  21. package/src/BamAdapter/MismatchParser.test.ts +5 -7
  22. package/src/BamAdapter/MismatchParser.ts +69 -58
  23. package/src/CramAdapter/CramAdapter.ts +14 -10
  24. package/src/CramAdapter/CramSlightlyLazyFeature.ts +84 -91
  25. package/src/LinearPileupDisplay/model.ts +1 -1
  26. package/src/LinearSNPCoverageDisplay/components/Tooltip.tsx +32 -25
  27. package/src/LinearSNPCoverageDisplay/models/model.ts +1 -1
  28. package/src/PileupRenderer/PileupLayoutSession.ts +6 -1
  29. package/src/PileupRenderer/PileupRenderer.tsx +70 -68
  30. package/src/PileupRenderer/configSchema.ts +2 -2
  31. package/src/SNPCoverageAdapter/SNPCoverageAdapter.ts +84 -76
@@ -30,22 +30,16 @@ function isInterbase(type: string) {
30
30
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
31
31
  function inc(bin: any, strand: number, type: string, field: string) {
32
32
  let thisBin = bin[type][field]
33
- if (!thisBin) {
33
+ if (thisBin === undefined) {
34
34
  thisBin = bin[type][field] = {
35
35
  total: 0,
36
- strands: { '-1': 0, '0': 0, '1': 0 },
36
+ '-1': 0,
37
+ '0': 0,
38
+ '1': 0,
37
39
  }
38
40
  }
39
41
  thisBin.total++
40
- thisBin.strands[strand]++
41
- }
42
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
- function dec(bin: any, strand: number, type: string, field: string) {
44
- if (!bin[type][field]) {
45
- bin[type][field] = { total: 0, strands: { '-1': 0, '0': 0, '1': 0 } }
46
- }
47
- bin[type][field].total--
48
- bin[type][field].strands[strand]--
42
+ thisBin[strand]++
49
43
  }
50
44
 
51
45
  export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
@@ -173,42 +167,51 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
173
167
 
174
168
  const bins = [] as {
175
169
  total: number
170
+ ref: number
171
+ '-1': 0
172
+ '0': 0
173
+ '1': 0
176
174
  lowqual: BinType
177
175
  cov: BinType
178
176
  delskips: BinType
179
177
  noncov: BinType
180
- ref: BinType
181
178
  }[]
182
179
 
183
180
  for (let i = 0; i < features.length; i++) {
184
181
  const feature = features[i]
185
- const ops = parseCigar(feature.get('CIGAR'))
186
182
  const fstart = feature.get('start')
187
183
  const fend = feature.get('end')
188
- const fstrand = feature.get('strand')
184
+ const fstrand = feature.get('strand') as -1 | 0 | 1
189
185
 
190
- for (let j = fstart; j < fend; j++) {
186
+ for (let j = fstart; j < fend + 1; j++) {
191
187
  const i = j - region.start
192
188
  if (i >= 0 && i < binMax) {
193
- const bin = bins[i] || {
194
- total: 0,
195
- lowqual: {} as BinType,
196
- cov: {} as BinType,
197
- delskips: {} as BinType,
198
- noncov: {} as BinType,
199
- ref: {} as BinType,
189
+ if (bins[i] === undefined) {
190
+ bins[i] = {
191
+ total: 0,
192
+ ref: 0,
193
+ '-1': 0,
194
+ '0': 0,
195
+ '1': 0,
196
+ lowqual: {} as BinType,
197
+ cov: {} as BinType,
198
+ delskips: {} as BinType,
199
+ noncov: {} as BinType,
200
+ }
200
201
  }
201
202
  if (j !== fend) {
202
- bin.total++
203
- inc(bin, fstrand, 'ref', 'ref')
203
+ bins[i].total++
204
+ bins[i].ref++
205
+ bins[i][fstrand]++
204
206
  }
205
- bins[i] = bin
206
207
  }
207
208
  }
208
209
 
209
210
  if (colorBy?.type === 'modifications') {
210
211
  const seq = feature.get('seq') as string
211
212
  const mm = (getTagAlt(feature, 'MM', 'Mm') as string) || ''
213
+ const ops = parseCigar(feature.get('CIGAR'))
214
+ const fend = feature.get('end')
212
215
 
213
216
  getModificationPositions(mm, seq, fstrand).forEach(
214
217
  ({ type, positions }) => {
@@ -217,7 +220,13 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
217
220
  const epos = pos + fstart - region.start
218
221
  if (epos >= 0 && epos < bins.length && pos + fstart < fend) {
219
222
  const bin = bins[epos]
220
- inc(bin, fstrand, 'cov', mod)
223
+ if (bin) {
224
+ inc(bin, fstrand, 'cov', mod)
225
+ } else {
226
+ console.warn(
227
+ 'Undefined position in modifications snpcoverage encountered',
228
+ )
229
+ }
221
230
  }
222
231
  }
223
232
  },
@@ -235,6 +244,7 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
235
244
  const seq = feature.get('seq')
236
245
  const mm = getTagAlt(feature, 'MM', 'Mm') || ''
237
246
  const methBins = new Array(region.end - region.start).fill(0)
247
+ const ops = parseCigar(feature.get('CIGAR'))
238
248
 
239
249
  getModificationPositions(mm, seq, fstrand).forEach(
240
250
  ({ type, positions }) => {
@@ -263,13 +273,17 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
263
273
  if (methBins[i] || methBins[i + 1]) {
264
274
  inc(bin, fstrand, 'cov', 'meth')
265
275
  inc(bin1, fstrand, 'cov', 'meth')
266
- dec(bin, fstrand, 'ref', 'ref')
267
- dec(bin1, fstrand, 'ref', 'ref')
276
+ bins[i].ref--
277
+ bins[i][fstrand]--
278
+ bins[i + 1].ref--
279
+ bins[i + 1][fstrand]--
268
280
  } else {
269
281
  inc(bin, fstrand, 'cov', 'unmeth')
270
282
  inc(bin1, fstrand, 'cov', 'unmeth')
271
- dec(bin, fstrand, 'ref', 'ref')
272
- dec(bin1, fstrand, 'ref', 'ref')
283
+ bins[i].ref--
284
+ bins[i][fstrand]--
285
+ bins[i + 1].ref--
286
+ bins[i + 1][fstrand]--
273
287
  }
274
288
  }
275
289
  }
@@ -277,56 +291,50 @@ export default class SNPCoverageAdapter extends BaseFeatureDataAdapter {
277
291
  }
278
292
 
279
293
  // normal SNP based coloring
280
- else {
281
- const mismatches = feature.get('mismatches') as Mismatch[] | undefined
282
-
283
- if (mismatches) {
284
- for (let i = 0; i < mismatches.length; i++) {
285
- const mismatch = mismatches[i]
286
- const mstart = fstart + mismatch.start
287
- for (let j = mstart; j < mstart + mismatchLen(mismatch); j++) {
288
- const epos = j - region.start
289
- if (epos >= 0 && epos < bins.length) {
290
- const bin = bins[epos]
291
- const { base, type } = mismatch
292
- const interbase = isInterbase(type)
293
- if (!interbase) {
294
- dec(bin, fstrand, 'ref', 'ref')
295
- } else {
296
- inc(bin, fstrand, 'noncov', type)
297
- }
294
+ const mismatches = (feature.get('mismatches') as Mismatch[]) || []
295
+ const colorSNPs =
296
+ colorBy?.type !== 'modifications' && colorBy?.type !== 'methylation'
297
+
298
+ for (let i = 0; i < mismatches.length; i++) {
299
+ const mismatch = mismatches[i]
300
+ const mstart = fstart + mismatch.start
301
+ const mlen = mismatchLen(mismatch)
302
+ const mend = mstart + mlen
303
+ for (let j = mstart; j < mstart + mlen; j++) {
304
+ const epos = j - region.start
305
+ if (epos >= 0 && epos < bins.length) {
306
+ const bin = bins[epos]
307
+ const { base, type } = mismatch
308
+ const interbase = isInterbase(type)
309
+ if (!interbase) {
310
+ bin.ref--
311
+ bin[fstrand]--
312
+ } else {
313
+ inc(bin, fstrand, 'noncov', type)
314
+ }
298
315
 
299
- if (type === 'deletion' || type === 'skip') {
300
- inc(bin, fstrand, 'delskips', type)
301
- bin.total--
302
- } else if (!interbase) {
303
- inc(bin, fstrand, 'cov', base)
304
- }
305
- }
316
+ if (type === 'deletion' || type === 'skip') {
317
+ inc(bin, fstrand, 'delskips', type)
318
+ bin.total--
319
+ } else if (!interbase && colorSNPs) {
320
+ inc(bin, fstrand, 'cov', base)
306
321
  }
307
322
  }
323
+ }
308
324
 
309
- mismatches
310
- .filter(mismatch => mismatch.type === 'skip')
311
- .forEach(mismatch => {
312
- const mstart = feature.get('start') + mismatch.start
313
- const start = mstart
314
- const end = mstart + mismatch.length
315
- const strand = feature.get('strand')
316
- const hash = `${start}_${end}_${strand}`
317
- if (!skipmap[hash]) {
318
- skipmap[hash] = {
319
- feature: feature,
320
- start,
321
- end,
322
- strand,
323
- xs: getTag(feature, 'XS') || getTag(feature, 'TS'),
324
- score: 1,
325
- }
326
- } else {
327
- skipmap[hash].score++
328
- }
329
- })
325
+ if (mismatch.type === 'skip') {
326
+ const hash = `${mstart}_${mend}_${fstrand}`
327
+ if (skipmap[hash] === undefined) {
328
+ skipmap[hash] = {
329
+ feature: feature,
330
+ start: mstart,
331
+ end: mend,
332
+ strand: fstrand,
333
+ xs: getTag(feature, 'XS') || getTag(feature, 'TS'),
334
+ score: 0,
335
+ }
336
+ }
337
+ skipmap[hash].score++
330
338
  }
331
339
  }
332
340
  }