Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimizations and usability improvements to synteny view #2679

Merged
merged 8 commits into from
Jan 27, 2022
25 changes: 13 additions & 12 deletions packages/core/util/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,18 @@ export async function bytesForRegions(regions: Region[], index: any) {
.reduce((a, b) => a + b.end - b.start, 0)
}

export type ViewSnap = {
bpPerPx: number
interRegionPaddingWidth: number
minimumBlockWidth: number
width: number
displayedRegions: {
start: number
end: number
refName: string
reversed: boolean
}[]
}
export function viewBpToPx({
refName,
coord,
Expand All @@ -1049,18 +1061,7 @@ export function viewBpToPx({
refName: string
coord: number
regionNumber?: number
self: {
bpPerPx: number
interRegionPaddingWidth: number
minimumBlockWidth: number
width: number
displayedRegions: {
start: number
end: number
refName: string
reversed: boolean
}[]
}
self: ViewSnap
}) {
let offsetBp = 0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export default class RefNameAliasAdapter
return results
.trim()
.split('\n')
.map((row: string) => {
.filter(f => !!f && !f.startsWith('#'))
.map(row => {
const [refName, ...aliases] = row.split('\t')
return { refName, aliases }
})
Expand Down
34 changes: 18 additions & 16 deletions plugins/dotplot-view/src/DotplotView/components/ImportForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,27 @@ const DotplotImportForm = observer(({ model }: { model: DotplotViewModel }) => {
])
model.setAssemblyNames([selected1, selected2])

const fileName =
trackData && 'uri' in trackData && trackData.uri
? trackData.uri.slice(trackData.uri.lastIndexOf('/') + 1)
: 'MyTrack'
if (trackData) {
const fileName =
trackData && 'uri' in trackData && trackData.uri
? trackData.uri.slice(trackData.uri.lastIndexOf('/') + 1)
: 'MyTrack'

const trackId = `${fileName}-${Date.now()}`
const trackId = `${fileName}-${Date.now()}`

session.addTrackConf({
trackId: trackId,
name: fileName,
assemblyNames: selected,
type: 'SyntenyTrack',
adapter: {
type: 'PAFAdapter',
pafLocation: trackData,
session.addTrackConf({
trackId: trackId,
name: fileName,
assemblyNames: selected,
},
})
model.toggleTrack(trackId)
type: 'SyntenyTrack',
adapter: {
type: 'PAFAdapter',
pafLocation: trackData,
assemblyNames: selected,
},
})
model.toggleTrack(trackId)
}
} catch (e) {
console.error(e)
setError(e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export function stateModelFactory(configSchema: any) {
return {
rpcDriverName: self.rpcDriverName,
displayModel: self,
highResolutionScaling: 2,
}
},
}))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ const Header = observer(
{ExtraButtons}
{!anyShowHeaders
? model.views.map(view => (
<div className={classes.searchContainer}>
<SearchBox key={view.id} model={view} showHelp={false} />
<div key={view.id} className={classes.searchContainer}>
<SearchBox model={view} showHelp={false} />
</div>
))
: null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { getConf } from '@jbrowse/core/configuration'
import { AnyConfigurationModel } from '@jbrowse/core/configuration/configurationSchema'
import { makeStyles } from '@material-ui/core/styles'
import { getEnv } from 'mobx-state-tree'
import { ResizeHandle } from '@jbrowse/core/ui'
import { LinearComparativeViewModel } from '../model'
import Header from './Header'

Expand Down Expand Up @@ -35,10 +36,17 @@ const Overlays = observer(({ model }: { model: LCV }) => {
<>
{model.tracks.map(track => {
const [display] = track.displays
const { height, RenderingComponent } = display
const { RenderingComponent } = display
const trackId = getConf(track, 'trackId')
return RenderingComponent ? (
<div className={classes.overlay} key={trackId} style={{ height }}>
<div
className={classes.overlay}
key={trackId}
style={{
height: model.middleComparativeHeight,
overflow: 'hidden',
}}
>
<RenderingComponent model={display} />
</div>
) : null
Expand All @@ -64,6 +72,17 @@ const MiddleComparativeView = observer(
<div className={classes.grid}>
<Overlays model={model} />
</div>
<ResizeHandle
onDrag={n =>
model.setMiddleComparativeHeight(
model.middleComparativeHeight + n,
)
}
style={{
height: 4,
background: '#ccc',
}}
/>
<ReactComponent model={views[1]} />
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default function stateModelFactory(pluginManager: PluginManager) {
showIntraviewLinks: true,
linkViews: false,
interactToggled: false,
middleComparativeHeight: 100,
tracks: types.array(
pluginManager.pluggableMstType('track', 'stateModel'),
),
Expand All @@ -60,6 +61,9 @@ export default function stateModelFactory(pluginManager: PluginManager) {
width: 800,
}))
.views(self => ({
get highResolutionScaling() {
return 2
},
get initialized() {
return self.views.length > 0
},
Expand Down Expand Up @@ -142,6 +146,11 @@ export default function stateModelFactory(pluginManager: PluginManager) {
self.headerHeight = height
},

setMiddleComparativeHeight(n: number) {
self.middleComparativeHeight = n
return self.middleComparativeHeight
},

toggleLinkViews() {
self.linkViews = !self.linkViews
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,15 @@ export function stateModelFactory(
)

.views(self => ({
get highResolutionScaling() {
return 1
},
renderProps() {
const parentView = getContainingView(self) as LinearSyntenyViewModel
return {
rpcDriverName: self.rpcDriverName,
displayModel: self,
config: getConf(self, 'renderer'),
width: parentView.width,
height: 100,
height: parentView.middleComparativeHeight,
highResolutionScaling: 2,
}
},
get rendererTypeName() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import React, { useRef, useMemo, useEffect } from 'react'
import { observer } from 'mobx-react'
import { isAlive } from 'mobx-state-tree'
import { getSnapshot, isAlive } from 'mobx-state-tree'
import SimpleFeature, {
SimpleFeatureSerialized,
Feature,
} from '@jbrowse/core/util/simpleFeature'
import { getConf } from '@jbrowse/core/configuration'
import { getContainingView } from '@jbrowse/core/util'
import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
import { getContainingView, viewBpToPx, ViewSnap } from '@jbrowse/core/util'
import { MismatchParser } from '@jbrowse/plugin-alignments'
import { interstitialYPos, overlayYPos, generateMatches } from '../../util'
import { LinearSyntenyViewModel } from '../../LinearSyntenyView/model'
Expand All @@ -19,11 +18,8 @@ type RectTuple = [number, number, number, number]

const { parseCigar } = MismatchParser

function px(
view: LinearGenomeViewModel,
arg: { refName: string; coord: number },
) {
return (view.bpToPx(arg) || {}).offsetPx || 0
function px(view: ViewSnap, arg: { refName: string; coord: number }) {
return (viewBpToPx({ ...arg, self: view }) || {}).offsetPx || 0
}

function layoutMatches(features: Feature[][]) {
Expand Down Expand Up @@ -116,21 +112,28 @@ function LinearSyntenyRendering(props: {
if (!ctx) {
return
}
ctx.clearRect(0, 0, width, height)
ctx.resetTransform()
ctx.scale(highResolutionScaling, highResolutionScaling)
ctx.clearRect(0, 0, width, height)
ctx.fillStyle = color
ctx.strokeStyle = color
const showIntraviewLinks = false
const middle = true
const hideTiny = false
const viewSnaps = views.map(view => ({
...getSnapshot(view),
width: view.width,
interRegionPaddingWidth: view.interRegionPaddingWidth,
minimumBlockWidth: view.minimumBlockWidth,
}))
matches.forEach(m => {
// we follow a path in the list of chunks, not from top to bottom, just
// in series following x1,y1 -> x2,y2
for (let i = 0; i < m.length - 1; i += 1) {
const { layout: c1, feature: f1, level: l1, refName: ref1 } = m[i]
const { layout: c2, feature: f2, level: l2, refName: ref2 } = m[i + 1]
const v1 = views[l1]
const v2 = views[l2]
const v1 = viewSnaps[l1]
const v2 = viewSnaps[l2]

if (!c1 || !c2) {
console.warn('received null layout for a overlay feature')
Expand Down Expand Up @@ -269,8 +272,9 @@ function LinearSyntenyRendering(props: {
<canvas
ref={ref}
data-testid="synteny_canvas"
width={width}
height={height}
style={{ width, height }}
width={width * highResolutionScaling}
height={height * highResolutionScaling}
/>
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ const ImportForm = observer(({ model }: { model: LinearSyntenyViewModel }) => {

const { assemblyNames, assemblyManager } = session
const [selected, setSelected] = useState([assemblyNames[0], assemblyNames[0]])
const [trackData, setTrackData] = useState<FileLocation>({
uri: '',
locationType: 'UriLocation',
})
const [trackData, setTrackData] = useState<FileLocation>()
const [numRows] = useState(2)
const [error, setError] = useState<unknown>()
const assemblyError = assemblyNames.length
Expand Down Expand Up @@ -72,24 +69,26 @@ const ImportForm = observer(({ model }: { model: LinearSyntenyViewModel }) => {

model.views.forEach(view => view.setWidth(model.width))

const name =
'uri' in trackData && trackData.uri
? trackData.uri.slice(trackData.uri.lastIndexOf('/') + 1)
: 'MyTrack'
if (trackData) {
const name =
'uri' in trackData
? trackData.uri.slice(trackData.uri.lastIndexOf('/') + 1)
: 'MyTrack'

const trackId = `${name}-${Date.now()}`
session.addTrackConf({
trackId,
name,
assemblyNames: selected,
type: 'SyntenyTrack',
adapter: {
type: 'PAFAdapter',
pafLocation: trackData,
const trackId = `${name}-${Date.now()}`
session.addTrackConf({
trackId,
name,
assemblyNames: selected,
},
})
model.toggleTrack(trackId)
type: 'SyntenyTrack',
adapter: {
type: 'PAFAdapter',
pafLocation: trackData,
assemblyNames: selected,
},
})
model.toggleTrack(trackId)
}
} catch (e) {
console.error(e)
setError(e)
Expand Down Expand Up @@ -169,13 +168,3 @@ const ImportForm = observer(({ model }: { model: LinearSyntenyViewModel }) => {
})

export default ImportForm

/* ability to add another assembly commented out for now
Add another assembly...
<IconButton
onClick={() => setNumRows(rows => rows + 1)}
color="primary"
>
<AddIcon />
</IconButton>
*/
2 changes: 1 addition & 1 deletion plugins/linear-comparative-view/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ function bpToPx(

// Returns either 0 or height depending on condition
export function interstitialYPos(cond: boolean, height: number) {
return cond ? 5 : height - 5
return cond ? 0 : height
}

export function* generateMatches(
Expand Down