Skip to content

Commit

Permalink
Reduce some work the BAM parser has to do
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Nov 12, 2024
1 parent 2f02d6b commit bdf1ab3
Show file tree
Hide file tree
Showing 14 changed files with 620 additions and 609 deletions.
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
"copy-to-clipboard": "^3.3.1",
"deepmerge": "^4.2.2",
"detect-node": "^2.1.0",
"dompurify": "^3.0.0",
"dompurify": "^3.2.0",
"escape-html": "^1.0.3",
"fast-deep-equal": "^3.1.3",
"generic-filehandle": "^3.0.0",
Expand Down
21 changes: 9 additions & 12 deletions packages/core/ui/SanitizedHTML.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,15 @@ export default function SanitizedHTML({
// see https://github.com/cure53/DOMPurify/issues/317
// only have to add this once, and can't do it globally because dompurify
// not yet initialized at global scope
dompurify.addHook(
'afterSanitizeAttributes',
(node: {
tagName: string
setAttribute: (arg0: string, arg1: string) => void
}) => {
if (node.tagName === 'A') {
node.setAttribute('rel', 'noopener noreferrer')
node.setAttribute('target', '_blank')
}
},
)
dompurify.addHook('afterSanitizeAttributes', node => {
// @ts-expect-error
if (node.tagName === 'A') {
// @ts-expect-error
node.setAttribute('rel', 'noopener noreferrer')
// @ts-expect-error
node.setAttribute('target', '_blank')
}
})
}

return (
Expand Down
2 changes: 1 addition & 1 deletion plugins/alignments/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"clean": "rimraf dist esm *.tsbuildinfo"
},
"dependencies": {
"@gmod/bam": "^3.0.0",
"@gmod/bam": "^4.0.1",
"@gmod/cram": "^3.0.3",
"@jbrowse/sv-core": "^2.16.1",
"@mui/icons-material": "^6.0.0",
Expand Down
4 changes: 2 additions & 2 deletions plugins/alignments/src/BamAdapter/BamSlightlyLazyFeature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ export default class BamSlightlyLazyFeature implements Feature {
this.record.tags.MD as string | undefined,
this.record.seq,
this.ref,
this.record.qualRaw,
this.record.qual,
)
}

get(field: string): any {
return field === 'mismatches'
? this.mismatches
: field === 'qual'
? this.record.qual
? this.record.qual?.join(' ')
: this.fields[field]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "TACACTGGTTCGGAGACGGTTCGTGACGAGCGCGCTATATGTCGGCATCTGCGCCGCATGAGCGGCCGCTGACCGGCGGCACGACTAATATAGTGCAAGA",
Expand Down Expand Up @@ -38,7 +38,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "ACACTGGTTCGGAGACGGTTCATGACGAGCGCGCTATATGTCGGCATCTGCGCCCCATGAGCGGCCCCTGTCCGGCGGCACGAATAATATAGTGCAAGAA",
Expand Down Expand Up @@ -66,7 +66,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "CTGGTTCGGAGACGGTTCATGACGACCGCGCTATATGTCGGCATCTGCGTCGCATGAGCGGCCGCTGTCCGGCGGCTCGAATAATATAGTGCAAGAAAAA",
Expand Down Expand Up @@ -94,7 +94,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "AGACGGTTCATGACGAGCGCGCTATATGTCGGCATCTGCGCCGCATGAGCGGCCGCTGTCCGGCGGCACGAATAATATAGTGCAAGAAAAACCGAAGACT",
Expand Down Expand Up @@ -122,7 +122,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "GACGGTTCATGACGAGCGCGCTATATGTCGGCATCTGCGCCCCATGAGCCGCCGCTGTCCGACGGCACGAATAATATAGTGCAAGAAAAACCGAAGACTA",
Expand Down Expand Up @@ -150,7 +150,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "TTCATGACGAGCGCGCTATATGACGGCATCTGCGCCGCATGAGCGGCCGCTGTCCGGCGGCACGAATAATATAGTGCAAGAAAAACCGAAGACTACGGTT",
Expand Down Expand Up @@ -178,7 +178,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "TCATGACGAGCGCGCTATATGTCGGCATCTGCGCCGCATCAGCGGCCGCTGTCCGGCGGCACGAATAATATAGTGCAAGAAAAACCGAAGACTACGGTTA",
Expand Down Expand Up @@ -206,7 +206,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "AGCGCGCTATATGTCGGCATCTGCGCCCCATGAGCGGCCGCTGTCCGGCGGCACGAATAATATAGTGCAAGAAAAACCGAAGACTACGGTTATATATGAT",
Expand Down Expand Up @@ -234,7 +234,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "CCCATGAGCGGCCGCTGTCCGGCGGCACGAATAATATAGTGCAAGAAAAACCTAAGACTACGGTTATATATGATGGAACGGCCCTCACAGCATTCTCACA",
Expand Down Expand Up @@ -262,7 +262,7 @@ exports[`adapter can fetch features from volvox.bam 1`] = `
"next_pos": undefined,
"next_ref": undefined,
"next_segment_position": undefined,
"pair_orientation": "",
"pair_orientation": undefined,
"refName": "ctgA",
"score": 37,
"seq": "CATGAGCGGCCGCTGTCCGGCGGCACGAATAATATAGTGCAAGAAAAACCGAAGACTACGGTTATATATGATGGAACGGCCCTCACAGCATTGTAACAGG",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import { CramRecord } from '@gmod/cram'
// locals
import CramAdapter from './CramAdapter'
import { readFeaturesToCIGAR, readFeaturesToMismatches } from './util'
import { mdToMismatches, parseCigar } from '../MismatchParser'
import { parseCigar } from '../MismatchParser'
import { mdToMismatches } from '../MismatchParser/mdToMismatches'

export default class CramSlightlyLazyFeature implements Feature {
// uses parameter properties to automatically create fields on the class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ export function SharedLinearPileupDisplayMixin(
},
)) as { feature: SimpleFeatureSerialized | undefined }

if (feature) {
if (isAlive(self) && feature) {
self.selectFeature(new SimpleFeature(feature))
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`more skip 1`] = `
[
{
"altbase": "G",
"base": "A",
"length": 1,
"qual": undefined,
"start": 6,
"type": "mismatch",
},
{
"altbase": "C",
"base": "A",
"length": 1,
"qual": undefined,
"start": 11,
"type": "mismatch",
},
{
"base": "1",
"length": 0,
"start": 31,
"type": "insertion",
},
{
"altbase": "G",
"base": "C",
"length": 1,
"qual": undefined,
"start": 32,
"type": "mismatch",
},
{
"altbase": "A",
"base": "C",
"length": 1,
"qual": undefined,
"start": 34,
"type": "mismatch",
},
{
"altbase": "C",
"base": "C",
"length": 1,
"qual": undefined,
"start": 40,
"type": "mismatch",
},
{
"altbase": "A",
"base": "C",
"length": 1,
"qual": undefined,
"start": 46,
"type": "mismatch",
},
{
"base": "*",
"length": 1,
"start": 48,
"type": "deletion",
},
{
"altbase": "A",
"base": "G",
"length": 1,
"qual": undefined,
"start": 52,
"type": "mismatch",
},
{
"altbase": "G",
"base": "G",
"length": 1,
"qual": undefined,
"start": 68,
"type": "mismatch",
},
{
"altbase": "G",
"base": "G",
"length": 1,
"qual": undefined,
"start": 70,
"type": "mismatch",
},
]
`;
98 changes: 98 additions & 0 deletions plugins/alignments/src/MismatchParser/cigarToMismatches.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { Mismatch } from '../shared/types'
import type { Buffer } from 'buffer'

export function cigarToMismatches(
ops: string[],
seq?: string,
ref?: string,
qual?: Buffer,
) {
let roffset = 0 // reference offset
let soffset = 0 // seq offset
const mismatches: Mismatch[] = []
const hasRefAndSeq = ref && seq
for (let i = 0; i < ops.length; i += 2) {
const len = +ops[i]!
const op = ops[i + 1]!

if (op === 'M' || op === '=' || op === 'E') {
if (hasRefAndSeq) {
for (let j = 0; j < len; j++) {
if (
// @ts-ignore in the full yarn build of the repo, this says that
// object is possibly undefined for some reason, ignored
seq[soffset + j].toUpperCase() !== ref[roffset + j].toUpperCase()
) {
mismatches.push({
start: roffset + j,
type: 'mismatch',
base: seq[soffset + j]!,
altbase: ref[roffset + j]!,
length: 1,
})
}
}
}
soffset += len
}
if (op === 'I') {
mismatches.push({
start: roffset,
type: 'insertion',
base: `${len}`,
length: 0,
})
soffset += len
} else if (op === 'D') {
mismatches.push({
start: roffset,
type: 'deletion',
base: '*',
length: len,
})
} else if (op === 'N') {
mismatches.push({
start: roffset,
type: 'skip',
base: 'N',
length: len,
})
} else if (op === 'X') {
const r = seq?.slice(soffset, soffset + len) || []
const q = qual?.subarray(soffset, soffset + len) || []

for (let j = 0; j < len; j++) {
mismatches.push({
start: roffset + j,
type: 'mismatch',
base: r[j]!,
qual: q[j]!,
length: 1,
})
}
soffset += len
} else if (op === 'H') {
mismatches.push({
start: roffset,
type: 'hardclip',
base: `H${len}`,
cliplen: len,
length: 1,
})
} else if (op === 'S') {
mismatches.push({
start: roffset,
type: 'softclip',
base: `S${len}`,
cliplen: len,
length: 1,
})
soffset += len
}

if (op !== 'I' && op !== 'S' && op !== 'H') {
roffset += len
}
}
return mismatches
}
35 changes: 35 additions & 0 deletions plugins/alignments/src/MismatchParser/getNextRefPos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// get relative reference sequence positions for positions given relative to
// the read sequence
export function getNextRefPos(cigarOps: string[], positions: number[]) {
let readPos = 0
let refPos = 0
let currPos = 0
const ret = []
for (let i = 0; i < cigarOps.length && currPos < positions.length; i += 2) {
const len = +cigarOps[i]!
const op = cigarOps[i + 1]!
if (op === 'S' || op === 'I') {
for (let i = 0; i < len && currPos < positions.length; i++) {
if (positions[currPos] === readPos + i) {
currPos++
}
}
readPos += len
} else if (op === 'D' || op === 'N') {
refPos += len
} else if (op === 'M' || op === 'X' || op === '=') {
for (let i = 0; i < len && currPos < positions.length; i++) {
if (positions[currPos] === readPos + i) {
ret.push({
ref: refPos + i,
idx: currPos,
})
currPos++
}
}
readPos += len
refPos += len
}
}
return ret
}
Loading

0 comments on commit bdf1ab3

Please sign in to comment.