Skip to content

Commit

Permalink
Refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Nov 26, 2024
1 parent d8ec45b commit 6d81694
Show file tree
Hide file tree
Showing 21 changed files with 233 additions and 186 deletions.
2 changes: 1 addition & 1 deletion component_tests/cgv/cypress/e2e/basic.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ describe('JBrowse embedded circular view', () => {
it('track loads', () => {
cy.visit('/')

cy.findByTestId('chord-1148282975-vcf-63101', { timeout: 30000 })
cy.findByTestId('chord--2069028604-vcf-62853', { timeout: 30000 })
})
})
16 changes: 7 additions & 9 deletions packages/core/util/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,27 +152,25 @@ export function isSessionModel(thing: unknown): thing is AbstractSessionModel {
}

/** abstract interface for a session allows editing configurations */
export interface SessionWithConfigEditingModel extends AbstractSessionModel {
export interface SessionWithConfigEditing extends AbstractSessionModel {
editConfiguration(configuration: AnyConfigurationModel): void
}
export function isSessionModelWithConfigEditing(
thing: unknown,
): thing is SessionWithConfigEditingModel {
return isSessionModel(thing) && 'editConfiguration' in thing
t: unknown,
): t is SessionWithConfigEditing {
return isSessionModel(t) && 'editConfiguration' in t
}

/** abstract interface for a session allows adding tracks */
export interface SessionWithConfigEditingModel extends AbstractSessionModel {
export interface SessionWithAddTracks extends AbstractSessionModel {
addTrackConf(
configuration: AnyConfigurationModel | SnapshotIn<AnyConfigurationModel>,
): void
}
export function isSessionWithAddTracks(
thing: unknown,
): thing is SessionWithConfigEditingModel {
export function isSessionWithAddTracks(t: unknown): t is SessionWithAddTracks {
return (
// @ts-expect-error
isSessionModel(thing) && 'addTrackConf' in thing && !thing.disableAddTracks
isSessionModel(t) && 'addTrackConf' in t && !t.disableAddTracks
)
}

Expand Down
2 changes: 1 addition & 1 deletion packages/sv-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"@jbrowse/core": "^2.17.0",
"@mui/icons-material": "^6.0.0",
"@mui/material": "^6.0.0",
"@gmod/vcf": "^5.0.0"
"@gmod/vcf": "^5.0.9"
},
"peerDependencies": {
"mobx": "^6.0.0",
Expand Down
95 changes: 9 additions & 86 deletions packages/sv-core/src/BreakendSingleLevelOptionDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,17 @@
import React, { useState } from 'react'

import { Dialog } from '@jbrowse/core/ui'
import { getSession, useLocalStorage, when } from '@jbrowse/core/util'
import { useLocalStorage } from '@jbrowse/core/util'
import { Button, DialogActions, DialogContent, TextField } from '@mui/material'
import { observer } from 'mobx-react'
import { getSnapshot } from 'mobx-state-tree'

// locals
import Checkbox2 from './Checkbox2'

// types
import { navToSingleLevelBreak } from './util'
import type { AbstractSessionModel, Feature } from '@jbrowse/core/util'
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
import { singleLevelSnapshotFromBreakendFeature } from './util'

interface Display {
id: string
[key: string]: unknown
}
interface Track {
id: string
displays: Display[]
[key: string]: unknown
}

function stripIds(arr: Track[]) {
return arr.map(({ id, displays, ...rest }) => ({
...rest,
displays: displays.map(({ id, ...rest }) => rest),
}))
}

const BreakendSingleLevelOptionDialog = observer(function ({
session,
Expand Down Expand Up @@ -89,73 +71,14 @@ const BreakendSingleLevelOptionDialog = observer(function ({
if (!assembly) {
throw new Error(`assembly ${assemblyName} not found`)
}
const w = +windowSize
if (Number.isNaN(w)) {
throw new Error('windowSize not a number')
}
const { snap, coverage } =
singleLevelSnapshotFromBreakendFeature({
feature,
assemblyName,
session,
})
const {
refName,
pos: startPos,
mateRefName,
matePos: endPos,
} = coverage
let viewInStack = session.views.find(
f => f.id === stableViewId,
) as { views: LinearGenomeViewModel[] } | undefined

if (!viewInStack) {
viewInStack = session.addView('BreakpointSplitView', {
...snap,
views: [
{
...snap.views[0],
tracks: view?.tracks
? stripIds(getSnapshot(view.tracks))
: [],
},
],
}) as unknown as { views: LinearGenomeViewModel[] }
} else {
viewInStack.views[0]?.setDisplayedRegions(
snap.views[0]!.displayedRegions,
)
// @ts-expect-error
viewInStack.setDisplayName(snap.displayName)
}
const lgv = viewInStack.views[0]!
await when(() => lgv.initialized)
console.log(
'wtf',
snap,
view?.displayedRegions,
startPos,
endPos,
refName,
mateRefName,
)
const l0 = lgv.bpToPx({
coord: Math.max(0, startPos - w),
refName,
})
const r0 = lgv.bpToPx({
coord: endPos + w,
refName: mateRefName,
await navToSingleLevelBreak({
feature,
assemblyName,
session,
stableViewId,
tracks: view?.tracks,
windowSize: +windowSize || 0,
})
console.log({ l0, r0 })
if (l0 && r0) {
lgv.moveTo(
{ ...l0, offset: l0.offsetPx },
{ ...r0, offset: r0.offsetPx },
)
} else {
getSession(lgv).notify('Unable to navigate to breakpoint')
}
} catch (e) {
console.error(e)
session.notifyError(`${e}`, e)
Expand Down
183 changes: 182 additions & 1 deletion packages/sv-core/src/util.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
import { parseBreakend } from '@gmod/vcf'
import { gatherOverlaps } from '@jbrowse/core/util'
import { gatherOverlaps, getSession, when } from '@jbrowse/core/util'
// types
import { transaction } from 'mobx'
import { getSnapshot } from 'mobx-state-tree'
import type { Assembly } from '@jbrowse/core/assemblyManager/assembly'
import type { AbstractSessionModel, Feature } from '@jbrowse/core/util'
import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'

export interface Display {
id: string
[key: string]: unknown
}

export interface Track {
id: string
displays: Display[]
[key: string]: unknown
}

function stripIds(arr: Track[]) {
return arr.map(({ id, displays, ...rest }) => ({
...rest,
displays: displays.map(({ id, ...rest }) => rest),
}))
}

export function getBreakendCoveringRegions({
feature,
Expand Down Expand Up @@ -94,3 +115,163 @@ export function singleLevelSnapshotFromBreakendFeature({
},
}
}

export async function navToSingleLevelBreak({
stableViewId,
feature,
assemblyName,
session,
tracks,
windowSize = 0,
}: {
stableViewId?: string
feature: Feature
assemblyName: string
windowSize?: number
session: AbstractSessionModel
tracks?: any
}) {
const { snap, coverage } = singleLevelSnapshotFromBreakendFeature({
feature,
assemblyName,
session,
})
const { refName, pos: startPos, mateRefName, matePos: endPos } = coverage
let viewInStack = session.views.find(f => f.id === stableViewId) as
| { views: any[] }
| undefined

if (!viewInStack) {
viewInStack = session.addView('BreakpointSplitView', {
...snap,
views: [
{
...snap.views[0],
tracks: tracks ? stripIds(getSnapshot(tracks)) : [],
},
],
}) as unknown as { views: LinearGenomeViewModel[] }
} else {
viewInStack.views[0]?.setDisplayedRegions(snap.views[0]!.displayedRegions)
// @ts-expect-error
viewInStack.setDisplayName(snap.displayName)
}
const lgv = viewInStack.views[0]!
await when(() => lgv.initialized)

const l0 = lgv.bpToPx({
coord: Math.max(0, startPos - windowSize),
refName,
})
const r0 = lgv.bpToPx({
coord: endPos + windowSize,
refName: mateRefName,
})
if (l0 && r0) {
lgv.moveTo({ ...l0, offset: l0.offsetPx }, { ...r0, offset: r0.offsetPx })
} else {
getSession(lgv).notify('Unable to navigate to breakpoint')
}
}

export async function navToMultiLevelBreak({
stableViewId,
feature,
assemblyName,
session,
tracks,
}: {
stableViewId?: string
feature: Feature
assemblyName: string
windowSize?: number
session: AbstractSessionModel
tracks?: any
}) {
const bpPerPx = 10

const { assemblyManager } = session
const assembly = assemblyManager.get(assemblyName)
if (!assembly) {
throw new Error(`assembly ${assemblyName} not found`)
}
if (!assembly.regions) {
throw new Error(`assembly ${assemblyName} regions not loaded`)
}
const {
refName,
pos: startPos,
mateRefName,
matePos: endPos,
} = getBreakendCoveringRegions({
feature,
assembly,
})

const topRegion = assembly.regions.find(f => f.refName === refName)!
const bottomRegion = assembly.regions.find(f => f.refName === mateRefName)!
const topMarkedRegion = [{ ...topRegion }, { ...topRegion }]
const bottomMarkedRegion = [{ ...bottomRegion }, { ...bottomRegion }]
topMarkedRegion[0]!.end = startPos
topMarkedRegion[1]!.start = startPos
bottomMarkedRegion[0]!.end = endPos
bottomMarkedRegion[1]!.start = endPos
const snap = {
type: 'BreakpointSplitView',
views: [
{
type: 'LinearGenomeView',
displayedRegions: topMarkedRegion,
hideHeader: true,
bpPerPx,
offsetPx: (topRegion.start + feature.get('start')) / bpPerPx,
},
{
type: 'LinearGenomeView',
displayedRegions: bottomMarkedRegion,
hideHeader: true,
bpPerPx,
tracks,
offsetPx: (bottomRegion.start + endPos) / bpPerPx,
},
],
displayName: `${
feature.get('name') || feature.get('id') || 'breakend'
} split detail`,
}

let viewInStack = session.views.find(f => f.id === stableViewId) as
| { views: any[] }
| undefined

if (!viewInStack) {
viewInStack = session.addView('BreakpointSplitView', {
...snap,
id: stableViewId,
views: [
{
...snap.views[0],
tracks: tracks ? stripIds(getSnapshot(tracks)) : [],
},
{
...snap.views[1],
tracks: (tracks ? stripIds(getSnapshot(tracks)) : []).reverse(),
},
],
}) as unknown as { views: LinearGenomeViewModel[] }
} else {
// re-nav existing view
transaction(() => {
for (let i = 0; i < viewInStack!.views.length; i++) {
const s = snap.views[i]
if (s) {
viewInStack!.views[i].setDisplayedRegions(s.displayedRegions)
viewInStack!.views[i].scrollTo(s.offsetPx - 800)
viewInStack!.views[i].zoomTo(s.bpPerPx)
}
}
// @ts-expect-error
viewInStack!.setDisplayName(snap.displayName)
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Link, Typography } from '@mui/material'

// types
import type { AlignmentFeatureWidgetModel } from './stateModelFactory'
import type { ViewType } from '@jbrowse/core/pluggableElementTypes'
import type { SimpleFeatureSerialized } from '@jbrowse/core/util'

// lazies
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { getSAFeatures } from './getSAFeatures'

import type { ReducedFeature } from './getSAFeatures'
import type { AlignmentFeatureWidgetModel } from './stateModelFactory'
import type { ViewType } from '@jbrowse/core/pluggableElementTypes'
import type { SimpleFeatureSerialized } from '@jbrowse/core/util'

// locals
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ import LaunchBreakpointSplitViewPanel from './LaunchSupplementaryAlignmentBreakp
import SupplementaryAlignmentsLocStrings from './SupplementaryAlignmentsLocStrings'

import type { AlignmentFeatureWidgetModel } from './stateModelFactory'
import type { ViewType } from '@jbrowse/core/pluggableElementTypes'

// locals

import type { SimpleFeatureSerialized } from '@jbrowse/core/util'

export default function SupplementaryAlignments(props: {
Expand Down
Loading

0 comments on commit 6d81694

Please sign in to comment.