react-msaview 3.1.11 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/index.js +32 -31
- package/dist/colorSchemes.d.ts +2 -2
- package/dist/colorSchemes.js +3 -4
- package/dist/colorSchemes.js.map +1 -1
- package/dist/components/Loading.d.ts +1 -1
- package/dist/components/Loading.js +4 -4
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/MSAView.d.ts +1 -1
- package/dist/components/MSAView.js +13 -9
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/ResizeHandles.d.ts +1 -1
- package/dist/components/ResizeHandles.js +2 -2
- package/dist/components/SequenceTextArea.js +4 -0
- package/dist/components/SequenceTextArea.js.map +1 -1
- package/dist/components/TextTrack.d.ts +1 -1
- package/dist/components/Track.d.ts +1 -1
- package/dist/components/VerticalScrollbar.d.ts +6 -0
- package/dist/components/VerticalScrollbar.js +65 -0
- package/dist/components/VerticalScrollbar.js.map +1 -0
- package/dist/components/dialogs/AddTrackDialog.d.ts +1 -1
- package/dist/components/dialogs/DomainDialog.d.ts +6 -0
- package/dist/components/dialogs/DomainDialog.js +19 -0
- package/dist/components/dialogs/DomainDialog.js.map +1 -0
- package/dist/components/dialogs/ExportSVGDialog.d.ts +1 -1
- package/dist/components/dialogs/FeatureDialog.d.ts +1 -1
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/InterProScanDialog.d.ts +4 -4
- package/dist/components/dialogs/InterProScanDialog.js +37 -8
- package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
- package/dist/components/dialogs/MetadataDialog.d.ts +1 -1
- package/dist/components/dialogs/SettingsDialog.d.ts +1 -1
- package/dist/components/dialogs/SettingsDialog.js +10 -1
- package/dist/components/dialogs/SettingsDialog.js.map +1 -1
- package/dist/components/dialogs/TabPanel.d.ts +6 -0
- package/dist/components/dialogs/TabPanel.js +6 -0
- package/dist/components/dialogs/TabPanel.js.map +1 -0
- package/dist/components/dialogs/TracklistDialog.d.ts +1 -1
- package/dist/components/dialogs/UserProvidedDomainsDialog.d.ts +7 -0
- package/dist/components/dialogs/UserProvidedDomainsDialog.js +58 -0
- package/dist/components/dialogs/UserProvidedDomainsDialog.js.map +1 -0
- package/dist/components/header/Header.d.ts +1 -1
- package/dist/components/header/Header.js +8 -5
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/HeaderInfoArea.d.ts +1 -1
- package/dist/components/header/HeaderMenu.d.ts +1 -1
- package/dist/components/header/HeaderMenuExtra.d.ts +1 -1
- package/dist/components/header/HeaderMenuExtra.js +54 -41
- package/dist/components/header/HeaderMenuExtra.js.map +1 -1
- package/dist/components/header/HeaderStatusArea.d.ts +1 -1
- package/dist/components/header/HeaderStatusArea.js +2 -1
- package/dist/components/header/HeaderStatusArea.js.map +1 -1
- package/dist/components/header/MultiAlignmentSelector.d.ts +1 -1
- package/dist/components/header/ZoomControls.js +31 -1
- package/dist/components/header/ZoomControls.js.map +1 -1
- package/dist/components/import/ImportForm.d.ts +1 -1
- package/dist/components/import/ImportForm.js +1 -1
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/import/ImportFormExamples.d.ts +1 -1
- package/dist/components/import/ImportFormExamples.js +10 -8
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/import/util.d.ts +2 -2
- package/dist/components/minimap/Minimap.d.ts +1 -1
- package/dist/components/minimap/Minimap.js +14 -15
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/minimap/MinimapSVG.d.ts +1 -1
- package/dist/components/minimap/MinimapSVG.js +1 -1
- package/dist/components/minimap/MinimapSVG.js.map +1 -1
- package/dist/components/msa/MSACanvas.d.ts +1 -1
- package/dist/components/msa/MSACanvas.js +3 -3
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.d.ts +3 -3
- package/dist/components/msa/MSACanvasBlock.js +4 -3
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.d.ts +2 -2
- package/dist/components/msa/MSAMouseoverCanvas.js +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/MSAPanel.d.ts +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.d.ts +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +2 -3
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderMSABlock.d.ts +2 -2
- package/dist/components/msa/renderMSABlock.js +12 -12
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.d.ts +1 -1
- package/dist/components/tree/TreeBranchMenu.d.ts +1 -1
- package/dist/components/tree/TreeCanvas.d.ts +1 -1
- package/dist/components/tree/TreeCanvas.js +13 -12
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.d.ts +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +2 -1
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/TreeNodeMenu.d.ts +1 -1
- package/dist/components/tree/TreeNodeMenu.js +2 -2
- package/dist/components/tree/TreeNodeMenu.js.map +1 -1
- package/dist/components/tree/TreePanel.d.ts +1 -1
- package/dist/components/tree/TreeRuler.d.ts +1 -1
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.d.ts +1 -1
- package/dist/components/tree/renderTreeCanvas.d.ts +3 -3
- package/dist/components/tree/renderTreeCanvas.js +25 -9
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/components/util.js +1 -1
- package/dist/components/util.js.map +1 -1
- package/dist/fetchUtils.d.ts +1 -1
- package/dist/fetchUtils.js.map +1 -1
- package/dist/launchInterProScan.d.ts +9 -3
- package/dist/launchInterProScan.js +57 -22
- package/dist/launchInterProScan.js.map +1 -1
- package/dist/model/DataModel.d.ts +5 -1
- package/dist/model/DataModel.js +10 -1
- package/dist/model/DataModel.js.map +1 -1
- package/dist/model/DialogQueue.d.ts +1 -1
- package/dist/model.d.ts +138 -43
- package/dist/model.js +235 -110
- package/dist/model.js.map +1 -1
- package/dist/parseNewick.js +1 -1
- package/dist/parseNewick.js.map +1 -1
- package/dist/parsers/ClustalMSA.d.ts +1 -1
- package/dist/parsers/FastaMSA.d.ts +1 -1
- package/dist/parsers/StockholmMSA.d.ts +1 -1
- package/dist/parsers/StockholmMSA.js.map +1 -1
- package/dist/renderToSvg.d.ts +2 -2
- package/dist/renderToSvg.js +3 -28
- package/dist/renderToSvg.js.map +1 -1
- package/dist/reparseTree.d.ts +1 -1
- package/dist/util.d.ts +2 -2
- package/dist/util.js +0 -2
- package/dist/util.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +5 -2
- package/src/colorSchemes.ts +3 -2
- package/src/components/Checkbox2.tsx +1 -1
- package/src/components/Loading.tsx +11 -5
- package/src/components/MSAView.tsx +27 -18
- package/src/components/ResizeHandles.tsx +3 -3
- package/src/components/SequenceTextArea.tsx +8 -0
- package/src/components/TextTrack.tsx +1 -1
- package/src/components/Track.tsx +1 -1
- package/src/components/VerticalScrollbar.tsx +85 -0
- package/src/components/dialogs/AddTrackDialog.tsx +2 -2
- package/src/components/dialogs/DomainDialog.tsx +38 -0
- package/src/components/dialogs/ExportSVGDialog.tsx +1 -1
- package/src/components/dialogs/FeatureDialog.tsx +3 -3
- package/src/components/dialogs/InterProScanDialog.tsx +49 -11
- package/src/components/dialogs/MetadataDialog.tsx +1 -1
- package/src/components/dialogs/SettingsDialog.tsx +38 -3
- package/src/components/dialogs/TabPanel.tsx +19 -0
- package/src/components/dialogs/TracklistDialog.tsx +1 -1
- package/src/components/dialogs/UserProvidedDomainsDialog.tsx +133 -0
- package/src/components/header/Header.tsx +9 -6
- package/src/components/header/HeaderInfoArea.tsx +1 -1
- package/src/components/header/HeaderMenu.tsx +1 -1
- package/src/components/header/HeaderMenuExtra.tsx +65 -48
- package/src/components/header/HeaderStatusArea.tsx +3 -2
- package/src/components/header/MultiAlignmentSelector.tsx +1 -1
- package/src/components/header/ZoomControls.tsx +34 -0
- package/src/components/import/ImportForm.tsx +3 -3
- package/src/components/import/ImportFormExamples.tsx +19 -17
- package/src/components/import/util.ts +2 -2
- package/src/components/minimap/Minimap.tsx +15 -22
- package/src/components/minimap/MinimapSVG.tsx +2 -2
- package/src/components/msa/MSACanvas.tsx +11 -4
- package/src/components/msa/MSACanvasBlock.tsx +5 -4
- package/src/components/msa/MSAMouseoverCanvas.tsx +2 -6
- package/src/components/msa/MSAPanel.tsx +1 -1
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +5 -6
- package/src/components/msa/renderMSABlock.ts +37 -17
- package/src/components/msa/renderMSAMouseover.ts +1 -1
- package/src/components/tree/TreeBranchMenu.tsx +1 -1
- package/src/components/tree/TreeCanvas.tsx +15 -16
- package/src/components/tree/TreeCanvasBlock.tsx +3 -2
- package/src/components/tree/TreeNodeMenu.tsx +3 -3
- package/src/components/tree/TreePanel.tsx +1 -1
- package/src/components/tree/TreeRuler.tsx +1 -1
- package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +1 -1
- package/src/components/tree/renderTreeCanvas.ts +32 -12
- package/src/components/util.ts +1 -1
- package/src/fetchUtils.ts +2 -2
- package/src/launchInterProScan.ts +69 -24
- package/src/model/DataModel.ts +10 -0
- package/src/model/DialogQueue.ts +1 -1
- package/src/model.ts +262 -143
- package/src/parseNewick.ts +1 -1
- package/src/parsers/ClustalMSA.ts +1 -1
- package/src/parsers/FastaMSA.ts +1 -1
- package/src/parsers/StockholmMSA.ts +1 -1
- package/src/renderToSvg.tsx +6 -30
- package/src/reparseTree.ts +1 -1
- package/src/util.ts +2 -4
- package/src/version.ts +1 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { observer } from 'mobx-react'
|
|
2
|
+
import React, { useEffect, useRef, useState } from 'react'
|
|
3
|
+
import type { MsaViewModel } from '../model'
|
|
4
|
+
import { clamp } from '../util'
|
|
5
|
+
|
|
6
|
+
const VerticalScrollbar = observer(({ model }: { model: MsaViewModel }) => {
|
|
7
|
+
const { msaAreaHeight, scrollY, totalHeight } = model
|
|
8
|
+
const [hovered, setHovered] = useState(false)
|
|
9
|
+
const scheduled = useRef(false)
|
|
10
|
+
const [mouseDown, setMouseDown] = useState<{
|
|
11
|
+
clientY: number
|
|
12
|
+
scrollY: number
|
|
13
|
+
}>()
|
|
14
|
+
const fill = 'rgba(66, 119, 127, 0.3)'
|
|
15
|
+
const unit = msaAreaHeight / totalHeight
|
|
16
|
+
const top = -scrollY
|
|
17
|
+
const bottom = top + msaAreaHeight
|
|
18
|
+
const t = top * unit
|
|
19
|
+
const b = bottom * unit
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
function fn(event: MouseEvent) {
|
|
22
|
+
if (mouseDown !== undefined) {
|
|
23
|
+
if (!scheduled.current) {
|
|
24
|
+
scheduled.current = true
|
|
25
|
+
window.requestAnimationFrame(() => {
|
|
26
|
+
model.setScrollY(
|
|
27
|
+
clamp(
|
|
28
|
+
-totalHeight,
|
|
29
|
+
mouseDown.scrollY - (event.clientY - mouseDown.clientY) / unit,
|
|
30
|
+
0,
|
|
31
|
+
),
|
|
32
|
+
)
|
|
33
|
+
scheduled.current = false
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function fn2() {
|
|
39
|
+
setMouseDown(undefined)
|
|
40
|
+
}
|
|
41
|
+
if (mouseDown !== undefined) {
|
|
42
|
+
document.addEventListener('mousemove', fn)
|
|
43
|
+
document.addEventListener('mouseup', fn2)
|
|
44
|
+
return () => {
|
|
45
|
+
document.removeEventListener('mousemove', fn)
|
|
46
|
+
document.removeEventListener('mousemove', fn2)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}, [model, unit, totalHeight, mouseDown])
|
|
50
|
+
return (
|
|
51
|
+
<div
|
|
52
|
+
style={{
|
|
53
|
+
position: 'relative',
|
|
54
|
+
width: 20,
|
|
55
|
+
height: msaAreaHeight,
|
|
56
|
+
borderLeft: '1px solid #555',
|
|
57
|
+
borderTop: '1px solid #555',
|
|
58
|
+
boxSizing: 'border-box',
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
<div
|
|
62
|
+
style={{
|
|
63
|
+
position: 'absolute',
|
|
64
|
+
top: Math.max(0, t),
|
|
65
|
+
left: 0,
|
|
66
|
+
background: hovered ? 'rgba(66,119,127,0.6)' : fill,
|
|
67
|
+
cursor: 'pointer',
|
|
68
|
+
boxSizing: 'border-box',
|
|
69
|
+
width: 20,
|
|
70
|
+
height: Math.max(b - t, 20),
|
|
71
|
+
zIndex: 100,
|
|
72
|
+
}}
|
|
73
|
+
onMouseOver={() => setHovered(true)}
|
|
74
|
+
onMouseOut={() => setHovered(false)}
|
|
75
|
+
onMouseDown={event => {
|
|
76
|
+
setMouseDown({
|
|
77
|
+
clientY: event.clientY,
|
|
78
|
+
scrollY: model.scrollY,
|
|
79
|
+
})
|
|
80
|
+
}}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
83
|
+
)
|
|
84
|
+
})
|
|
85
|
+
export default VerticalScrollbar
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
Typography,
|
|
9
9
|
} from '@mui/material'
|
|
10
10
|
import { Dialog, FileSelector } from '@jbrowse/core/ui'
|
|
11
|
-
import { FileLocation } from '@jbrowse/core/util/types'
|
|
11
|
+
import type { FileLocation } from '@jbrowse/core/util/types'
|
|
12
12
|
import { observer } from 'mobx-react'
|
|
13
|
-
import { MsaViewModel } from '../../model'
|
|
13
|
+
import type { MsaViewModel } from '../../model'
|
|
14
14
|
|
|
15
15
|
export default observer(function ({
|
|
16
16
|
model,
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { Dialog } from '@jbrowse/core/ui'
|
|
3
|
+
import { Tab, Tabs } from '@mui/material'
|
|
4
|
+
|
|
5
|
+
// locals
|
|
6
|
+
import InterProScanPanel from './InterProScanDialog'
|
|
7
|
+
import UserProvidedResultPanel from './UserProvidedDomainsDialog'
|
|
8
|
+
import TabPanel from './TabPanel'
|
|
9
|
+
import type { MsaViewModel } from '../../model'
|
|
10
|
+
|
|
11
|
+
export default function LaunchDomainViewDialog({
|
|
12
|
+
handleClose,
|
|
13
|
+
model,
|
|
14
|
+
}: {
|
|
15
|
+
handleClose: () => void
|
|
16
|
+
model: MsaViewModel
|
|
17
|
+
}) {
|
|
18
|
+
const [choice, setChoice] = useState(0)
|
|
19
|
+
return (
|
|
20
|
+
<Dialog
|
|
21
|
+
maxWidth="xl"
|
|
22
|
+
title="Launch protein view"
|
|
23
|
+
onClose={() => handleClose()}
|
|
24
|
+
open
|
|
25
|
+
>
|
|
26
|
+
<Tabs value={choice} onChange={(_, val) => setChoice(val)}>
|
|
27
|
+
<Tab value={0} label="Automatic lookup" />
|
|
28
|
+
<Tab value={1} label="Manual" />
|
|
29
|
+
</Tabs>
|
|
30
|
+
<TabPanel value={choice} index={0}>
|
|
31
|
+
<InterProScanPanel model={model} handleClose={handleClose} />
|
|
32
|
+
</TabPanel>
|
|
33
|
+
<TabPanel value={choice} index={1}>
|
|
34
|
+
<UserProvidedResultPanel model={model} handleClose={handleClose} />
|
|
35
|
+
</TabPanel>
|
|
36
|
+
</Dialog>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
@@ -4,7 +4,7 @@ import { Dialog } from '@jbrowse/core/ui'
|
|
|
4
4
|
import { Button, DialogContent } from '@mui/material'
|
|
5
5
|
|
|
6
6
|
// locals
|
|
7
|
-
import { MsaViewModel } from '../../model'
|
|
7
|
+
import type { MsaViewModel } from '../../model'
|
|
8
8
|
import { getPalette } from '../../ggplotPalettes'
|
|
9
9
|
|
|
10
10
|
const Toggles = observer(function ({ model }: { model: MsaViewModel }) {
|
|
@@ -44,7 +44,7 @@ const Table = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
44
44
|
<table>
|
|
45
45
|
<thead>
|
|
46
46
|
<tr>
|
|
47
|
-
<td
|
|
47
|
+
<td />
|
|
48
48
|
<td>accession</td>
|
|
49
49
|
<td>name</td>
|
|
50
50
|
<td>description</td>
|
|
@@ -75,7 +75,7 @@ const Table = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
75
75
|
height: 20,
|
|
76
76
|
background: palette[idx] || 'black',
|
|
77
77
|
}}
|
|
78
|
-
|
|
78
|
+
/>
|
|
79
79
|
</td>
|
|
80
80
|
</tr>
|
|
81
81
|
))}
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
import { observer } from 'mobx-react'
|
|
3
|
-
import { Dialog } from '@jbrowse/core/ui'
|
|
4
3
|
import { Button, DialogActions, DialogContent, Typography } from '@mui/material'
|
|
5
4
|
|
|
6
5
|
// locals
|
|
7
|
-
import { MsaViewModel } from '../../model'
|
|
6
|
+
import type { MsaViewModel } from '../../model'
|
|
7
|
+
import { getSession } from '@jbrowse/core/util'
|
|
8
|
+
import { launchInterProScan } from '../../launchInterProScan'
|
|
9
|
+
import { Dialog } from '@jbrowse/core/ui'
|
|
8
10
|
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
+
const InterProScanDialog = observer(function ({
|
|
12
|
+
handleClose,
|
|
11
13
|
model,
|
|
12
14
|
}: {
|
|
13
|
-
|
|
15
|
+
handleClose: () => void
|
|
14
16
|
model: MsaViewModel
|
|
15
17
|
}) {
|
|
16
18
|
const [vals, setVals] = useState([
|
|
@@ -146,10 +148,16 @@ const FeatureTypeDialog = observer(function ({
|
|
|
146
148
|
const [show, setShow] = useState(false)
|
|
147
149
|
|
|
148
150
|
return (
|
|
149
|
-
<Dialog
|
|
151
|
+
<Dialog
|
|
152
|
+
maxWidth="xl"
|
|
153
|
+
title="Query InterProScan API for domains"
|
|
154
|
+
onClose={() => handleClose()}
|
|
155
|
+
open
|
|
156
|
+
>
|
|
150
157
|
<DialogContent>
|
|
151
158
|
<Typography>
|
|
152
|
-
This will run InterProScan on all rows of the
|
|
159
|
+
This will run InterProScan via the InterProScan API on all rows of the
|
|
160
|
+
current MSA
|
|
153
161
|
</Typography>
|
|
154
162
|
<Button onClick={() => setShow(!show)}>
|
|
155
163
|
{show ? 'Hide' : 'Show'} advanced options
|
|
@@ -209,15 +217,45 @@ const FeatureTypeDialog = observer(function ({
|
|
|
209
217
|
) : null}
|
|
210
218
|
</DialogContent>
|
|
211
219
|
<DialogActions>
|
|
212
|
-
<Button
|
|
220
|
+
<Button
|
|
221
|
+
variant="contained"
|
|
222
|
+
color="secondary"
|
|
223
|
+
onClick={() => handleClose()}
|
|
224
|
+
>
|
|
213
225
|
Cancel
|
|
214
226
|
</Button>
|
|
215
227
|
<Button
|
|
216
228
|
variant="contained"
|
|
217
229
|
color="primary"
|
|
218
230
|
onClick={() => {
|
|
219
|
-
|
|
220
|
-
|
|
231
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
232
|
+
;(async () => {
|
|
233
|
+
try {
|
|
234
|
+
const { rows } = model
|
|
235
|
+
if (rows.length > 140) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
'Too many sequences, please run InterProScan offline',
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
await launchInterProScan({
|
|
241
|
+
algorithm: 'interproscan',
|
|
242
|
+
programs: programs,
|
|
243
|
+
seq: rows
|
|
244
|
+
.map(row => [row[0], row[1].replaceAll('-', '')])
|
|
245
|
+
.filter(f => !!f[1])
|
|
246
|
+
.map(row => `>${row[0]}\n${row[1]}`)
|
|
247
|
+
.join('\n'),
|
|
248
|
+
onProgress: arg => model.setStatus(arg),
|
|
249
|
+
model,
|
|
250
|
+
})
|
|
251
|
+
} catch (e) {
|
|
252
|
+
console.error(e)
|
|
253
|
+
getSession(model).notifyError(`${e}`, e)
|
|
254
|
+
} finally {
|
|
255
|
+
model.setStatus()
|
|
256
|
+
}
|
|
257
|
+
})()
|
|
258
|
+
handleClose()
|
|
221
259
|
}}
|
|
222
260
|
>
|
|
223
261
|
Send sequences to InterProScan
|
|
@@ -227,4 +265,4 @@ const FeatureTypeDialog = observer(function ({
|
|
|
227
265
|
)
|
|
228
266
|
})
|
|
229
267
|
|
|
230
|
-
export default
|
|
268
|
+
export default InterProScanDialog
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
|
|
9
9
|
|
|
10
10
|
// locals
|
|
11
|
-
import { MsaViewModel } from '../../model'
|
|
11
|
+
import type { MsaViewModel } from '../../model'
|
|
12
12
|
import SequenceTextArea from '../SequenceTextArea'
|
|
13
13
|
|
|
14
14
|
const MetadataDialog = observer(function ({
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
Typography,
|
|
13
13
|
} from '@mui/material'
|
|
14
14
|
|
|
15
|
-
import { MsaViewModel } from '../../model'
|
|
15
|
+
import type { MsaViewModel } from '../../model'
|
|
16
16
|
import colorSchemes from '../../colorSchemes'
|
|
17
17
|
import Checkbox2 from '../Checkbox2'
|
|
18
18
|
|
|
@@ -115,17 +115,40 @@ const MSASettings = observer(function MSASettings({
|
|
|
115
115
|
model: MsaViewModel
|
|
116
116
|
}) {
|
|
117
117
|
const { classes } = useStyles()
|
|
118
|
-
const {
|
|
118
|
+
const {
|
|
119
|
+
bgColor,
|
|
120
|
+
contrastLettering,
|
|
121
|
+
colWidth,
|
|
122
|
+
allowedGappyness,
|
|
123
|
+
drawMsaLetters,
|
|
124
|
+
colorSchemeName,
|
|
125
|
+
hideGaps,
|
|
126
|
+
rowHeight,
|
|
127
|
+
} = model
|
|
119
128
|
|
|
120
129
|
return (
|
|
121
130
|
<div>
|
|
122
131
|
<h1>MSA options</h1>
|
|
123
|
-
|
|
132
|
+
<Checkbox2
|
|
133
|
+
checked={drawMsaLetters}
|
|
134
|
+
onChange={() => model.setDrawMsaLetters(!drawMsaLetters)}
|
|
135
|
+
label="Draw letters"
|
|
136
|
+
/>
|
|
124
137
|
<Checkbox2
|
|
125
138
|
checked={bgColor}
|
|
126
139
|
onChange={() => model.setBgColor(!bgColor)}
|
|
127
140
|
label="Color background tiles of MSA?"
|
|
128
141
|
/>
|
|
142
|
+
<Checkbox2
|
|
143
|
+
checked={contrastLettering}
|
|
144
|
+
onChange={() => model.setContrastLettering(!contrastLettering)}
|
|
145
|
+
label="Use contrast lettering"
|
|
146
|
+
/>
|
|
147
|
+
<Checkbox2
|
|
148
|
+
checked={hideGaps}
|
|
149
|
+
onChange={() => model.setHideGaps(!hideGaps)}
|
|
150
|
+
label={`Hide columns that are ${100 - allowedGappyness}% gaps`}
|
|
151
|
+
/>
|
|
129
152
|
|
|
130
153
|
<div className={classes.flex}>
|
|
131
154
|
<Typography>Column width ({colWidth}px)</Typography>
|
|
@@ -147,6 +170,18 @@ const MSASettings = observer(function MSASettings({
|
|
|
147
170
|
onChange={(_, val) => model.setRowHeight(val as number)}
|
|
148
171
|
/>
|
|
149
172
|
</div>
|
|
173
|
+
{hideGaps ? (
|
|
174
|
+
<div className={classes.flex}>
|
|
175
|
+
<Typography>Allowed gappyness ({100 - allowedGappyness}%)</Typography>
|
|
176
|
+
<Slider
|
|
177
|
+
className={classes.field}
|
|
178
|
+
min={1}
|
|
179
|
+
max={100}
|
|
180
|
+
value={allowedGappyness}
|
|
181
|
+
onChange={(_, val) => model.setAllowedGappyness(val as number)}
|
|
182
|
+
/>
|
|
183
|
+
</div>
|
|
184
|
+
) : null}
|
|
150
185
|
|
|
151
186
|
<TextField
|
|
152
187
|
select
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
// this is from MUI example
|
|
4
|
+
export default function TabPanel({
|
|
5
|
+
children,
|
|
6
|
+
value,
|
|
7
|
+
index,
|
|
8
|
+
...other
|
|
9
|
+
}: {
|
|
10
|
+
children?: React.ReactNode
|
|
11
|
+
index: number
|
|
12
|
+
value: number
|
|
13
|
+
}) {
|
|
14
|
+
return (
|
|
15
|
+
<div role="tabpanel" hidden={value !== index} {...other}>
|
|
16
|
+
{value === index && <div>{children}</div>}
|
|
17
|
+
</div>
|
|
18
|
+
)
|
|
19
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import { observer } from 'mobx-react'
|
|
3
|
+
import {
|
|
4
|
+
Button,
|
|
5
|
+
DialogActions,
|
|
6
|
+
DialogContent,
|
|
7
|
+
FormControlLabel,
|
|
8
|
+
FormControl,
|
|
9
|
+
Radio,
|
|
10
|
+
RadioGroup,
|
|
11
|
+
TextField,
|
|
12
|
+
Typography,
|
|
13
|
+
} from '@mui/material'
|
|
14
|
+
import { getSession } from '@jbrowse/core/util'
|
|
15
|
+
import { Dialog } from '@jbrowse/core/ui'
|
|
16
|
+
|
|
17
|
+
// locals
|
|
18
|
+
import type { MsaViewModel } from '../../model'
|
|
19
|
+
import { jsonfetch } from '../../fetchUtils'
|
|
20
|
+
import type { InterProScanResponse } from '../../launchInterProScan'
|
|
21
|
+
|
|
22
|
+
const UserProvidedDomainsDialog = observer(function ({
|
|
23
|
+
handleClose,
|
|
24
|
+
model,
|
|
25
|
+
}: {
|
|
26
|
+
handleClose: () => void
|
|
27
|
+
model: MsaViewModel
|
|
28
|
+
}) {
|
|
29
|
+
const [file, setFile] = useState<File>()
|
|
30
|
+
const [choice, setChoice] = useState('file')
|
|
31
|
+
const [interProURL, setInterProURL] = useState('')
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Dialog
|
|
35
|
+
maxWidth="xl"
|
|
36
|
+
title="Open protein domains from file"
|
|
37
|
+
onClose={() => handleClose()}
|
|
38
|
+
open
|
|
39
|
+
>
|
|
40
|
+
<DialogContent>
|
|
41
|
+
<div>
|
|
42
|
+
<Typography>
|
|
43
|
+
Open a JSON file of InterProScan results that you run remotely on
|
|
44
|
+
EBI servers or locally
|
|
45
|
+
</Typography>
|
|
46
|
+
|
|
47
|
+
<div style={{ display: 'flex', margin: 30 }}>
|
|
48
|
+
<FormControl component="fieldset">
|
|
49
|
+
<RadioGroup
|
|
50
|
+
value={choice}
|
|
51
|
+
onChange={event => setChoice(event.target.value)}
|
|
52
|
+
>
|
|
53
|
+
<FormControlLabel value="url" control={<Radio />} label="URL" />
|
|
54
|
+
<FormControlLabel
|
|
55
|
+
value="file"
|
|
56
|
+
control={<Radio />}
|
|
57
|
+
label="File"
|
|
58
|
+
/>
|
|
59
|
+
</RadioGroup>
|
|
60
|
+
</FormControl>
|
|
61
|
+
{choice === 'url' ? (
|
|
62
|
+
<div>
|
|
63
|
+
<Typography>
|
|
64
|
+
Open a InterProScan JSON file remote URL
|
|
65
|
+
</Typography>
|
|
66
|
+
<TextField
|
|
67
|
+
label="URL"
|
|
68
|
+
value={interProURL}
|
|
69
|
+
onChange={event => setInterProURL(event.target.value)}
|
|
70
|
+
/>
|
|
71
|
+
</div>
|
|
72
|
+
) : null}
|
|
73
|
+
{choice === 'file' ? (
|
|
74
|
+
<div style={{ paddingTop: 20 }}>
|
|
75
|
+
<Typography>
|
|
76
|
+
Open a InterProScan JSON file file from your local drive
|
|
77
|
+
</Typography>
|
|
78
|
+
<Button variant="outlined" component="label">
|
|
79
|
+
Choose File
|
|
80
|
+
<input
|
|
81
|
+
type="file"
|
|
82
|
+
hidden
|
|
83
|
+
onChange={({ target }) => {
|
|
84
|
+
const file = target?.files?.[0]
|
|
85
|
+
if (file) {
|
|
86
|
+
setFile(file)
|
|
87
|
+
}
|
|
88
|
+
}}
|
|
89
|
+
/>
|
|
90
|
+
</Button>
|
|
91
|
+
</div>
|
|
92
|
+
) : null}
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</DialogContent>
|
|
96
|
+
<DialogActions>
|
|
97
|
+
<Button
|
|
98
|
+
variant="contained"
|
|
99
|
+
color="primary"
|
|
100
|
+
onClick={() => {
|
|
101
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
102
|
+
;(async () => {
|
|
103
|
+
try {
|
|
104
|
+
const ret: InterProScanResponse = file
|
|
105
|
+
? JSON.parse(await file.text())
|
|
106
|
+
: await jsonfetch(interProURL)
|
|
107
|
+
|
|
108
|
+
model.setInterProAnnotations(
|
|
109
|
+
Object.fromEntries(ret.results.map(r => [r.xref[0].id, r])),
|
|
110
|
+
)
|
|
111
|
+
model.setShowDomains(true)
|
|
112
|
+
getSession(model).notify(
|
|
113
|
+
'Loaded interproscan results',
|
|
114
|
+
'success',
|
|
115
|
+
)
|
|
116
|
+
} catch (e) {
|
|
117
|
+
console.error(e)
|
|
118
|
+
getSession(model).notifyError(`${e}`, e)
|
|
119
|
+
} finally {
|
|
120
|
+
model.setStatus()
|
|
121
|
+
}
|
|
122
|
+
})()
|
|
123
|
+
handleClose()
|
|
124
|
+
}}
|
|
125
|
+
>
|
|
126
|
+
Open results
|
|
127
|
+
</Button>
|
|
128
|
+
</DialogActions>
|
|
129
|
+
</Dialog>
|
|
130
|
+
)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
export default UserProvidedDomainsDialog
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import React, { lazy } from 'react'
|
|
1
|
+
import React, { lazy, useEffect } from 'react'
|
|
2
2
|
import { IconButton } from '@mui/material'
|
|
3
3
|
import { observer } from 'mobx-react'
|
|
4
|
+
import useMeasure from '@jbrowse/core/util/useMeasure'
|
|
4
5
|
|
|
5
6
|
// locals
|
|
6
|
-
import { MsaViewModel } from '../../model'
|
|
7
|
+
import type { MsaViewModel } from '../../model'
|
|
7
8
|
|
|
8
9
|
// icons
|
|
9
10
|
import Help from '@mui/icons-material/Help'
|
|
@@ -13,17 +14,19 @@ import ZoomControls from './ZoomControls'
|
|
|
13
14
|
import MultiAlignmentSelector from './MultiAlignmentSelector'
|
|
14
15
|
import HeaderInfoArea from './HeaderInfoArea'
|
|
15
16
|
import HeaderStatusArea from './HeaderStatusArea'
|
|
16
|
-
import HeaderMenu from './HeaderMenu'
|
|
17
17
|
import HeaderMenuExtra from './HeaderMenuExtra'
|
|
18
18
|
|
|
19
19
|
const AboutDialog = lazy(() => import('../dialogs/AboutDialog'))
|
|
20
20
|
|
|
21
21
|
const Header = observer(function ({ model }: { model: MsaViewModel }) {
|
|
22
|
+
const [ref, { height }] = useMeasure()
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
model.setHeaderHeight(height || 0)
|
|
25
|
+
}, [model, height])
|
|
22
26
|
return (
|
|
23
|
-
<div style={{ display: 'flex' }}>
|
|
24
|
-
<HeaderMenu model={model} />
|
|
25
|
-
<ZoomControls model={model} />
|
|
27
|
+
<div ref={ref} style={{ display: 'flex' }}>
|
|
26
28
|
<HeaderMenuExtra model={model} />
|
|
29
|
+
<ZoomControls model={model} />
|
|
27
30
|
<MultiAlignmentSelector model={model} />
|
|
28
31
|
<HeaderInfoArea model={model} />
|
|
29
32
|
<Spacer />
|
|
@@ -10,7 +10,7 @@ import List from '@mui/icons-material/List'
|
|
|
10
10
|
import Menu from '@mui/icons-material/Menu'
|
|
11
11
|
|
|
12
12
|
// locals
|
|
13
|
-
import { MsaViewModel } from '../../model'
|
|
13
|
+
import type { MsaViewModel } from '../../model'
|
|
14
14
|
|
|
15
15
|
// lazies
|
|
16
16
|
const SettingsDialog = lazy(() => import('../dialogs/SettingsDialog'))
|