Skip to content

Commit

Permalink
Fix ability to use LGV synteny track on inverted alignments (#3366)
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Dec 1, 2022
1 parent 1578544 commit 8435cbc
Show file tree
Hide file tree
Showing 12 changed files with 1,331 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,43 @@ import {
import { types } from 'mobx-state-tree'
import { when } from 'mobx'

// locals
import { LinearSyntenyViewModel } from '../LinearSyntenyView/model'

type LSV = LinearSyntenyViewModel

const { parseCigar } = MismatchParser

function findPosInCigar(cigar: string[], x: number) {
let featX = 0
let mateX = 0
for (let i = 0; i < cigar.length; i += 2) {
const len = +cigar[i]
const op = cigar[i + 1]
const min = Math.min(len, x - featX)

if (featX >= x) {
break
} else if (op === 'I') {
mateX += len
} else if (op === 'D') {
featX += min
} else if (op === 'M') {
mateX += min
featX += min
}
}
return [featX, mateX]
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
async function navToSynteny(feature: Feature, self: any) {
const session = getSession(self)
const track = getContainingTrack(self)
const view = getContainingView(self)
const reg = view.dynamicBlocks.contentBlocks[0]
const cigar = parseCigar(feature.get('cg') || '')
const cigar = parseCigar(feature.get('cg'))
const strand = feature.get('strand')
const regStart = reg.start
const regEnd = reg.end
const featStart = feature.get('start')
Expand All @@ -42,33 +70,15 @@ async function navToSynteny(feature: Feature, self: any) {
let rFeatEnd = featStart

if (cigar.length) {
for (let i = 0; i < cigar.length && rFeatStart < regStart; i += 2) {
const len = +cigar[i]
const op = cigar[i + 1]
if (op === 'I') {
rMateStart += len
} else if (op === 'D') {
rFeatStart += len
} else if (op === 'M') {
const l2 = Math.min(len, regStart - rFeatStart)
const [featStartX, mateStartX] = findPosInCigar(cigar, regStart - featStart)
const [featEndX, mateEndX] = findPosInCigar(cigar, regEnd - featStart)

rMateStart += l2
rFeatStart += l2
}
}
for (let i = 0; i < cigar.length && rFeatEnd < regEnd; i += 2) {
const len = +cigar[i]
const op = cigar[i + 1]
if (op === 'I') {
rMateEnd += len
} else if (op === 'D') {
rFeatEnd += len
} else if (op === 'M') {
const l2 = Math.min(len, regEnd - rFeatEnd)
rMateEnd += l2
rFeatEnd += l2
}
}
// avoid multiply by 0 with strand undefined
const flipper = strand === -1 ? -1 : 1
rFeatStart = featStart + featStartX
rFeatEnd = featStart + featEndX
rMateStart = mateStart + mateStartX * flipper
rMateEnd = mateStart + mateEndX * flipper
} else {
rFeatEnd = featEnd
rMateEnd = mateEnd
Expand Down Expand Up @@ -101,20 +111,20 @@ async function navToSynteny(feature: Feature, self: any) {
],
},
],
})
}) as LSV
const f = (n: number) => Math.floor(n)
const l1 = `${featRef}:${f(rFeatStart)}-${f(rFeatEnd)}`
const l2 = `${mateRef}:${f(rMateStart)}-${f(rMateEnd)}`
const l2 = `${mateRef}:${f(rMateStart)}-${f(rMateEnd)}${
strand === -1 ? '[rev]' : ''
}`
await when(() => view2.width !== undefined)
// @ts-ignore
view2.views[0].navToLocString(l1, featAsm)
// @ts-ignore
view2.views[1].navToLocString(l2, mateAsm)
}

/**
* #stateModel LGVSyntenyDisplay
* extends `LinearBasicDisplay`, displays location of "synteny" feature in a
* extends `LinearPileupDisplay`, displays location of "synteny" feature in a
* plain LGV, allowing linking out to external synteny views
*/
function stateModelFactory(schema: AnyConfigurationSchemaType) {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
120 changes: 120 additions & 0 deletions products/jbrowse-web/src/__snapshots__/jbrowseModel.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,44 @@ exports[`JBrowse model creates with non-empty snapshot 1`] = `
"type": "ReferenceSequenceTrack",
},
},
{
"name": "volvox-rev-del",
"sequence": {
"adapter": {
"faiLocation": {
"internetAccountId": undefined,
"internetAccountPreAuthorization": undefined,
"locationType": "UriLocation",
"uri": "volvox-rev-del.fa.fai",
},
"fastaLocation": {
"internetAccountId": undefined,
"internetAccountPreAuthorization": undefined,
"locationType": "UriLocation",
"uri": "volvox-rev-del.fa",
},
"metadataLocation": {
"internetAccountId": undefined,
"internetAccountPreAuthorization": undefined,
"locationType": "UriLocation",
"uri": "/path/to/fa.metadata.yaml",
},
"type": "IndexedFastaAdapter",
},
"displays": [
{
"displayId": "volvox-rev-del-ReferenceSequenceTrack-LinearReferenceSequenceDisplay",
"type": "LinearReferenceSequenceDisplay",
},
{
"displayId": "volvox-rev-del-ReferenceSequenceTrack-LinearGCContentDisplay",
"type": "LinearGCContentDisplay",
},
],
"trackId": "volvox-rev-del-ReferenceSequenceTrack",
"type": "ReferenceSequenceTrack",
},
},
],
"configuration": {},
"connections": [],
Expand Down Expand Up @@ -2424,6 +2462,9 @@ exports[`JBrowse model creates with non-empty snapshot 1`] = `
"volvox",
"volvox",
],
"category": [
"Synteny",
],
"displays": [
{
"displayId": "volvox_fake_synteny_alt-DotplotDisplay",
Expand Down Expand Up @@ -2464,6 +2505,9 @@ exports[`JBrowse model creates with non-empty snapshot 1`] = `
"volvox",
"volvox",
],
"category": [
"Synteny",
],
"displays": [
{
"displayId": "volvox_fake_synteny-DotplotDisplay",
Expand Down Expand Up @@ -3173,6 +3217,9 @@ exports[`JBrowse model creates with non-empty snapshot 1`] = `
"volvox",
"volvox_del",
],
"category": [
"Synteny",
],
"displays": [
{
"displayId": "volvox_del.paf-1658813720770-DotplotDisplay",
Expand Down Expand Up @@ -3211,6 +3258,9 @@ exports[`JBrowse model creates with non-empty snapshot 1`] = `
"volvox",
"volvox_ins",
],
"category": [
"Synteny",
],
"displays": [
{
"displayId": "volvox_ins.paf-1658813720770-DotplotDisplay",
Expand Down Expand Up @@ -3293,6 +3343,76 @@ exports[`JBrowse model creates with non-empty snapshot 1`] = `
"trackId": "variant_effect_demo_jannovar",
"type": "VariantTrack",
},
{
"adapter": {
"assemblyNames": [
"volvox-rev-del",
"volvox",
],
"pafLocation": {
"internetAccountId": undefined,
"internetAccountPreAuthorization": undefined,
"locationType": "UriLocation",
"uri": "volvox-rev-del.paf",
},
"type": "PAFAdapter",
},
"assemblyNames": [
"volvox-rev-del",
"volvox",
],
"category": [
"Synteny",
],
"displays": [
{
"displayId": "volvox-rev-del-DotplotDisplay",
"type": "DotplotDisplay",
},
{
"displayId": "volvox-rev-del-LinearComparativeDisplay",
"type": "LinearComparativeDisplay",
},
{
"displayId": "volvox-rev-del-LinearSyntenyDisplay",
"type": "LinearSyntenyDisplay",
},
{
"displayId": "volvox-rev-del-LGVSyntenyDisplay",
"type": "LGVSyntenyDisplay",
},
],
"name": "volvox-rev-del",
"trackId": "volvox-rev-del",
"type": "SyntenyTrack",
},
{
"adapter": {
"gffLocation": {
"internetAccountId": undefined,
"internetAccountPreAuthorization": undefined,
"locationType": "UriLocation",
"uri": "volvox-rev-del.gff",
},
"type": "Gff3Adapter",
},
"assemblyNames": [
"volvox-rev-del",
],
"displays": [
{
"displayId": "volvox-rev-del-annotations-LinearBasicDisplay",
"type": "LinearBasicDisplay",
},
{
"displayId": "volvox-rev-del-annotations-LinearArcDisplay",
"type": "LinearArcDisplay",
},
],
"name": "volvox-rev-del-annotations",
"trackId": "volvox-rev-del-annotations",
"type": "FeatureTrack",
},
],
}
`;
Loading

0 comments on commit 8435cbc

Please sign in to comment.