Skip to content

Commit

Permalink
Synteny import form
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Oct 31, 2022
1 parent 100947b commit 4f2fb91
Show file tree
Hide file tree
Showing 9 changed files with 575 additions and 281 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const Selector = observer(
<Paper style={{ padding: 12 }}>
<Typography paragraph>
Select a track from the select box below, the track will be shown when
you hit "Open".
you hit "Launch".
</Typography>

<Typography paragraph>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import LinkOffIcon from '@mui/icons-material/LinkOff'
import CropFreeIcon from '@mui/icons-material/CropFree'

import { LinearComparativeViewModel } from '../model'
import { TrackSelector as TrackSelectorIcon } from '@jbrowse/core/ui/Icons'

type LCV = LinearComparativeViewModel

Expand All @@ -34,6 +35,17 @@ const useStyles = makeStyles()(() => ({
},
}))

const TrackSelector = observer(({ model }: { model: LCV }) => {
return (
<IconButton
onClick={model.activateTrackSelector}
title="Open track selector"
>
<TrackSelectorIcon color="secondary" />
</IconButton>
)
})

const LinkViews = observer(({ model }: { model: LCV }) => {
return (
<IconButton
Expand Down Expand Up @@ -66,6 +78,7 @@ const Header = observer(
const anyShowHeaders = model.views.some(view => !view.hideHeader)
return (
<div className={classes.headerBar}>
<TrackSelector model={model} />
<LinkViews model={model} />
<SquareView model={model} />
{ExtraButtons}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ function stateModelFactory(pluginManager: PluginManager) {
*/
clearView() {
self.views = cast([])
self.tracks = cast([])
},
}))
.views(self => ({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
import React, { useState, useEffect } from 'react'
import { SnapshotIn } from 'mobx-state-tree'
import path from 'path'
import {
FormControlLabel,
Grid,
Paper,
Radio,
RadioGroup,
Typography,
} from '@mui/material'
import { ErrorMessage, FileSelector } from '@jbrowse/core/ui'
import { FileLocation } from '@jbrowse/core/util/types'
import { observer } from 'mobx-react'
import { AnyConfigurationModel } from '@jbrowse/core/configuration'

function getName(
sessionTrackData?: { uri: string } | { localPath: string } | { name: string },
) {
return sessionTrackData
? // @ts-ignore
sessionTrackData.uri ||
// @ts-ignore
sessionTrackData.localPath ||
// @ts-ignore
sessionTrackData.name
: undefined
}

function stripGz(fileName: string) {
return fileName.endsWith('.gz')
? fileName.slice(0, fileName.length - 3)
: fileName
}

function getAdapter({
radioOption,
assembly1,
assembly2,
fileLocation,
bed1Location,
bed2Location,
}: {
radioOption: string
assembly1: string
assembly2: string
fileLocation?: FileLocation
bed1Location?: FileLocation
bed2Location?: FileLocation
}) {
if (radioOption === '.paf') {
return {
type: 'PAFAdapter',
pafLocation: fileLocation,
queryAssembly: assembly1,
targetAssembly: assembly2,
}
} else if (radioOption === '.out') {
return {
type: 'MashMapAdapter',
outLocation: fileLocation,
queryAssembly: assembly1,
targetAssembly: assembly2,
}
} else if (radioOption === '.delta') {
return {
type: 'DeltaAdapter',
deltaLocation: fileLocation,
queryAssembly: assembly1,
targetAssembly: assembly2,
}
} else if (radioOption === '.chain') {
return {
type: 'ChainAdapter',
chainLocation: fileLocation,
queryAssembly: assembly1,
targetAssembly: assembly2,
}
} else if (radioOption === '.anchors') {
return {
type: 'MCScanAnchorsAdapter',
mcscanAnchorsLocation: fileLocation,
bed1Location,
bed2Location,
assemblyNames: [assembly1, assembly2],
}
} else if (radioOption === '.anchors.simple') {
return {
type: 'MCScanSimpleAnchorsAdapter',
mcscanSimpleAnchorsLocation: fileLocation,
bed1Location,
bed2Location,
assemblyNames: [assembly1, assembly2],
}
} else {
throw new Error('Unknown type')
}
}

type Conf = SnapshotIn<AnyConfigurationModel>

const OpenTrack = observer(
({
sessionTrackData,
assembly1,
assembly2,
setSessionTrackData,
}: {
sessionTrackData: Conf
assembly1: string
assembly2: string
setSessionTrackData: (arg: Conf) => void
}) => {
const [bed2Location, setBed2Location] = useState<FileLocation>()
const [bed1Location, setBed1Location] = useState<FileLocation>()
const [fileLocation, setFileLocation] = useState<FileLocation>()
const [value, setValue] = useState('')
const [error, setError] = useState<unknown>()
const fileName = getName(fileLocation)

const radioOption =
value || (fileName ? path.extname(stripGz(fileName)) : '')

useEffect(() => {
try {
if (fileLocation) {
const fn = fileName ? path.basename(fileName) : 'MyTrack'
const trackId = `${fn}-${Date.now()}`
setError(undefined)

setSessionTrackData({
trackId,
name: fn,
assemblyNames: [assembly2, assembly1],
type: 'SyntenyTrack',
adapter: getAdapter({
radioOption,
assembly1,
assembly2,
fileLocation,
bed1Location,
bed2Location,
}),
})
}
} catch (e) {
console.error(e)
setError(e)
}
}, [
fileName,
assembly1,
assembly2,
bed1Location,
bed2Location,
fileLocation,
radioOption,
setSessionTrackData,
])
return (
<Paper style={{ padding: 12 }}>
{error ? <ErrorMessage error={error} /> : null}
<Typography style={{ textAlign: 'center' }}>
Add a .paf, .out (MashMap), .delta (Mummer), .chain, .anchors or
.anchors.simple (MCScan) file to view in the dotplot. These file types
can also be gzipped. The first assembly should be the query sequence
(e.g. left column of the PAF) and the second assembly should be the
target sequence (e.g. right column of the PAF)
</Typography>
<RadioGroup
value={radioOption}
onChange={event => setValue(event.target.value)}
>
<Grid container justifyContent="center">
<Grid item>
<FormControlLabel value=".paf" control={<Radio />} label=".paf" />
</Grid>
<Grid item>
<FormControlLabel value=".out" control={<Radio />} label=".out" />
</Grid>
<Grid item>
<FormControlLabel
value=".delta"
control={<Radio />}
label=".delta"
/>
</Grid>
<Grid item>
<FormControlLabel
value=".chain"
control={<Radio />}
label=".chain"
/>
</Grid>
<Grid item>
<FormControlLabel
value=".anchors"
control={<Radio />}
label=".anchors"
/>
</Grid>
<Grid item>
<FormControlLabel
value=".anchors.simple"
control={<Radio />}
label=".anchors.simple"
/>
</Grid>
</Grid>
</RadioGroup>
<Grid container justifyContent="center">
<Grid item>
{value === '.anchors' || value === '.anchors.simple' ? (
<div>
<div style={{ margin: 20 }}>
Open the {value} and .bed files for both genome assemblies
from the MCScan (Python verson) pipeline{' '}
<a href="https://github.com/tanghaibao/jcvi/wiki/MCscan-(Python-version)">
(more info)
</a>
</div>
<div style={{ display: 'flex' }}>
<div>
<FileSelector
name=".anchors file"
description=""
location={fileLocation}
setLocation={loc => setFileLocation(loc)}
/>
</div>
<div>
<FileSelector
name="genome 1 .bed (left column of anchors file)"
description=""
location={bed1Location}
setLocation={loc => setBed1Location(loc)}
/>
</div>
<div>
<FileSelector
name="genome 2 .bed (right column of anchors file)"
description=""
location={bed2Location}
setLocation={loc => setBed2Location(loc)}
/>
</div>
</div>
</div>
) : (
<FileSelector
name={value ? value + ' location' : ''}
description=""
location={fileLocation}
setLocation={loc => setFileLocation(loc)}
/>
)}
</Grid>
</Grid>
</Paper>
)
},
)

export default OpenTrack
Loading

0 comments on commit 4f2fb91

Please sign in to comment.