Skip to content

Commit

Permalink
Misc refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
cmdcolin committed Jul 9, 2024
1 parent ef982be commit ec09aa0
Show file tree
Hide file tree
Showing 13 changed files with 241 additions and 133 deletions.
7 changes: 6 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,12 @@ export default [
ignoreRestSiblings: true,
},
],

'no-console': [
'warn',
{
allow: ['error', 'warn'],
},
],
curly: 'error',
'no-extra-semi': 'off',
'unicorn/no-negated-condition': 'off',
Expand Down
16 changes: 7 additions & 9 deletions src/LaunchProteinView/components/AlphaFoldDBSearch.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useEffect, useState } from 'react'
import { observer } from 'mobx-react'
import { Button, DialogActions, DialogContent } from '@mui/material'
import { Button, DialogActions, DialogContent, Typography } from '@mui/material'
import { makeStyles } from 'tss-react/mui'
import {
AbstractTrackModel,
Expand Down Expand Up @@ -73,6 +73,7 @@ const AlphaFoldDBSearch = observer(function ({
? getDisplayName(selectedTranscript)
: getDisplayName(feature),
})

const url = uniprotId
? `https://alphafold.ebi.ac.uk/files/AF-${uniprotId}-F1-model_v4.cif`
: undefined
Expand All @@ -86,10 +87,6 @@ const AlphaFoldDBSearch = observer(function ({

useEffect(() => {
if (isoformSequences !== undefined) {
console.log(
{ structureSequence },
options.find(f => isoformSequences[f.id()]?.seq == structureSequence),
)
const ret =
options.find(
f =>
Expand All @@ -98,16 +95,16 @@ const AlphaFoldDBSearch = observer(function ({
) ?? options.find(f => !!isoformSequences[f.id()])
setUserSelection(ret?.id())
}
}, [options, structureSequence, userSelection, isoformSequences])
}, [options, structureSequence, isoformSequences])

return (
<>
<DialogContent className={classes.dialogContent}>
{e ? <ErrorMessage error={e} /> : null}
<div>
<Typography>
Automatically find AlphaFoldDB entry for given transcript{' '}
<HelpButton />
</div>
</Typography>
{isRemoteStructureSequenceLoading ? (
<LoadingEllipses
variant="h6"
Expand Down Expand Up @@ -161,8 +158,9 @@ const AlphaFoldDBSearch = observer(function ({
session.addView('ProteinView', {
type: 'ProteinView',
url,
seq2: protein,
seq2: protein?.seq,
feature: selectedTranscript?.toJSON(),
completeMatch:
connectedViewId: view.id,

Check failure on line 164 in src/LaunchProteinView/components/AlphaFoldDBSearch.tsx

View workflow job for this annotation

GitHub Actions / Test and typecheck on node 20.x and ubuntu-latest

',' expected.
displayName: `Protein view ${getGeneDisplayName(feature)} - ${getTranscriptDisplayName(selectedTranscript)}`,
})

Check failure on line 166 in src/LaunchProteinView/components/AlphaFoldDBSearch.tsx

View workflow job for this annotation

GitHub Actions / Test and typecheck on node 20.x and ubuntu-latest

Unexpected token. Did you mean `{'}'}` or `&rbrace;`?
Expand Down
28 changes: 21 additions & 7 deletions src/LaunchProteinView/components/AlphaFoldDBSearchStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { Link, Typography } from '@mui/material'
import React, { useState } from 'react'
import { Button, Link, Typography } from '@mui/material'
import { Feature } from '@jbrowse/core/util'

// locals
Expand Down Expand Up @@ -37,6 +37,7 @@ export default function AlphaFoldDBSearchStatus({
const url2 = uniprotId
? `https://www.uniprot.org/uniprotkb/${uniprotId}/entry`
: undefined
const [showAllProteinSequences, setShowAllProteinSequences] = useState(false)

return !uniprotId ? (
<Typography>
Expand All @@ -57,11 +58,24 @@ export default function AlphaFoldDBSearchStatus({
</a>
</Typography>
{structureSequence ? (
<MSATable
structureSequence={structureSequence}
structureName={uniprotId}
isoformSequences={isoformSequences}
/>
<div style={{ margin: 20 }}>
<Button
variant="contained"
color="primary"
onClick={() => setShowAllProteinSequences(!showAllProteinSequences)}
>
{showAllProteinSequences
? 'Hide all isoform protein sequences'
: 'Show all isoform protein sequences'}
</Button>
{showAllProteinSequences ? (
<MSATable
structureSequence={structureSequence}
structureName={uniprotId}
isoformSequences={isoformSequences}
/>
) : null}
</div>
) : (
<NotFound uniprotId={uniprotId} />
)}
Expand Down
43 changes: 29 additions & 14 deletions src/LaunchProteinView/components/HelpDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,41 @@ export default function HelpDialog({
handleClose: () => void
}) {
return (
<Dialog
open
maxWidth="lg"
onClose={handleClose}
title="Automatic protein structure lookup procedure"
>
<Dialog open maxWidth="lg" onClose={handleClose} title="Help">
<DialogContent>
<Typography2>
The automatic lookup performs the following steps:
<ol>
The procedure for the protein lookup is as follows:
<ul>
<li>
searches mygene.info for the transcript ID, in order to retrieve
the UniProt ID associated with a given transcript ID
(Automatic lookup) Searches mygene.info for the transcript ID, in
order to retrieve the UniProt ID associated with a given
transcript ID and then, the UniProt ID is used to lookup the
structure in AlphaFoldDB
</li>
<li>
Then, it uses that UniProt ID to lookup the structure in
AlphaFoldDB because every UniProt ID has been processed by
AlphaFold.
(Manual) Allows you to choose your own structure file from your
local machine (e.g. a PDB file predicted by e.g. ColabFold) or
supply a specific URL
</li>
</ol>
<li>
The residues from the structure are downloaded, and then you can
choose the transcript isoform from the selected gene that best
represents the structure. Asterisks are displayed if there is an
exact sequence match
</li>
<li>
The residues from the structure are finally aligned to the to the
selected transcript&apos;s protein sequence representation, and
this creates a mapping from the reference genome coordinates to
positions in the 3-D structure
</li>
<li>
Finally the molstar panel is opened, and this contains many
specialized features features, plus additional mouseover and
selection features supplied by the plugin to connect mouse click
actions and mouse hover with coordinates on the linear genome view
</li>
</ul>
</Typography2>
<Typography2>
If you run into challenges with this workflow e.g. your transcripts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export default function LaunchProteinViewDialog({
open
>
<Tabs value={choice} onChange={(_, val) => setChoice(val)}>
<Tab value={0} label="AlphaFoldDB search" />
<Tab value={0} label="Automatic lookup" />
<Tab value={1} label="Manual" />
</Tabs>
<TabPanel value={choice} index={0}>
Expand Down
100 changes: 66 additions & 34 deletions src/LaunchProteinView/components/MSATable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react'
import { TextField } from '@mui/material'
import React, { useState } from 'react'
import { Checkbox, FormControlLabel, TextField } from '@mui/material'
import { Feature, max } from '@jbrowse/core/util'
import { makeStyles } from 'tss-react/mui'

Expand All @@ -11,6 +11,9 @@ const useStyles = makeStyles()({
fontFamily: 'Courier New',
whiteSpace: 'pre',
},
margin: {
marginLeft: 20,
},
})

export default function MSATable({
Expand All @@ -23,42 +26,71 @@ export default function MSATable({
isoformSequences: Record<string, { feature: Feature; seq: string }>
}) {
const { classes } = useStyles()
const exactMatchIsoformAndStructureSeq = Object.entries(
isoformSequences,
).find(([_, val]) => structureSequence === val.seq.replace('*', ''))
const [showInFastaFormat, setShowInFastaFormat] = useState(false)
const removedStars = Object.fromEntries(
Object.entries(isoformSequences).map(([key, val]) => [
key,
{ ...val, seq: val.seq.replaceAll('*', '') },
]),
)
const exactMatchIsoformAndStructureSeq = Object.entries(removedStars).find(
([_, val]) => structureSequence === val.seq,
)
const sname = `${structureName || ''} (structure residues)`
const maxKeyLen = max([
structureName?.length ?? 0,
...Object.entries(isoformSequences).map(
sname.length,
...Object.entries(removedStars).map(
([_, val]) => getTranscriptDisplayName(val.feature).length,
),
])

const l1 = [
`${sname.padEnd(maxKeyLen)}${exactMatchIsoformAndStructureSeq ? '*' : ' '} ${structureSequence}`,
exactMatchIsoformAndStructureSeq
? `${getTranscriptDisplayName(exactMatchIsoformAndStructureSeq[1].feature).padEnd(maxKeyLen)}* ${exactMatchIsoformAndStructureSeq[1].seq}`
: undefined,
...Object.entries(removedStars)
.map(
([_, val]) =>
`${getTranscriptDisplayName(val.feature).padEnd(maxKeyLen)} ${val.seq}`,
)
.filter(([k]) => k !== exactMatchIsoformAndStructureSeq?.[0]),
]
.filter(f => !!f)
.join('\n')

const l2 = [
`>${sname}\n${structureSequence}`,
...Object.values(removedStars).map(
({ feature, seq }) => `>${getTranscriptDisplayName(feature)}\n${seq}`,
),
].join('\n')
return (
<TextField
variant="outlined"
multiline
minRows={5}
maxRows={10}
fullWidth
value={[
`${structureName.padEnd(maxKeyLen)}${exactMatchIsoformAndStructureSeq ? '*' : ' '} ${structureSequence}`,
exactMatchIsoformAndStructureSeq
? `${getTranscriptDisplayName(exactMatchIsoformAndStructureSeq[1].feature).padEnd(maxKeyLen)}* ${exactMatchIsoformAndStructureSeq[1].seq}`
: undefined,
...Object.entries(isoformSequences)
.map(
([_, val]) =>
`${getTranscriptDisplayName(val.feature).padEnd(maxKeyLen)} ${val.seq}`,
)
.filter(([k]) => k !== exactMatchIsoformAndStructureSeq?.[0]),
]
.filter(f => !!f)
.join('\n')}
InputProps={{
readOnly: true,
classes: {
input: classes.textAreaFont,
},
}}
/>
<>
<FormControlLabel
className={classes.margin}
control={
<Checkbox
onChange={event => setShowInFastaFormat(event.target.checked)}
checked={showInFastaFormat}
/>
}
label="Show in FASTA format?"
/>
<TextField
variant="outlined"
multiline
minRows={5}
maxRows={10}
fullWidth
value={showInFastaFormat ? l2 : l1}
InputProps={{
readOnly: true,
classes: {
input: classes.textAreaFont,
},
}}
/>
</>
)
}
3 changes: 2 additions & 1 deletion src/LaunchProteinView/components/TranscriptSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ export default function TranscriptSelector({
.map(f => (
<MenuItem value={f.id()} key={f.id()}>
{getGeneDisplayName(feature)} - {getTranscriptDisplayName(f)} (
{isoformSequences[f.id()].seq.length}aa) matches structure sequence*
{isoformSequences[f.id()].seq.length}aa) (matches structure
residues)
</MenuItem>
))}
{isoforms
Expand Down
Loading

0 comments on commit ec09aa0

Please sign in to comment.