react-msaview 5.10.0 → 6.1.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 +99 -99
- package/bundle/index.js.map +4 -4
- package/dist/clustalX.js +22 -22
- package/dist/clustalX.js.map +1 -1
- package/dist/columnCounts.d.ts +7 -0
- package/dist/columnCounts.js +18 -0
- package/dist/columnCounts.js.map +1 -1
- package/dist/components/CopyButton.d.ts +9 -0
- package/dist/components/CopyButton.js +23 -0
- package/dist/components/CopyButton.js.map +1 -0
- package/dist/components/DragHandle.d.ts +25 -0
- package/dist/components/DragHandle.js +49 -0
- package/dist/components/DragHandle.js.map +1 -0
- package/dist/components/Loading.js +2 -2
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/MSAView.js +2 -2
- package/dist/components/MSAView.js.map +1 -1
- package/dist/components/ResizeHandles.d.ts +4 -2
- package/dist/components/ResizeHandles.js +35 -54
- package/dist/components/ResizeHandles.js.map +1 -1
- package/dist/components/SequenceTextArea.js +3 -10
- package/dist/components/SequenceTextArea.js.map +1 -1
- package/dist/components/VerticalScrollbar.js +11 -25
- package/dist/components/VerticalScrollbar.js.map +1 -1
- package/dist/components/dialogs/FeatureDialog.js +3 -3
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/InterProScanDialog.js +52 -129
- package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
- package/dist/components/dialogs/{UserProvidedDomainsDialog.d.ts → InterProScanFileDialog.d.ts} +2 -2
- package/dist/components/dialogs/{UserProvidedDomainsDialog.js → InterProScanFileDialog.js} +6 -10
- package/dist/components/dialogs/InterProScanFileDialog.js.map +1 -0
- package/dist/components/dialogs/TrackInfoDialog.d.ts +2 -4
- package/dist/components/dialogs/TrackInfoDialog.js +8 -14
- package/dist/components/dialogs/TrackInfoDialog.js.map +1 -1
- package/dist/components/header/FileMenu.js +3 -3
- package/dist/components/header/FileMenu.js.map +1 -1
- package/dist/components/header/GappynessSlider.js +1 -1
- package/dist/components/header/GappynessSlider.js.map +1 -1
- package/dist/components/header/{getDomainsMenu.d.ts → getAnnotationsMenu.d.ts} +1 -1
- package/dist/components/header/{getDomainsMenu.js → getAnnotationsMenu.js} +10 -9
- package/dist/components/header/getAnnotationsMenu.js.map +1 -0
- package/dist/components/header/settingsMenuItems.js +15 -0
- package/dist/components/header/settingsMenuItems.js.map +1 -1
- package/dist/components/import/ImportForm.js +1 -1
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/import/ImportFormExamples.js +66 -57
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/minimap/Minimap.js +40 -23
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/minimap/MinimapSVG.d.ts +2 -1
- package/dist/components/minimap/MinimapSVG.js +3 -4
- package/dist/components/minimap/MinimapSVG.js.map +1 -1
- package/dist/components/minimap/minimapLayout.d.ts +10 -1
- package/dist/components/minimap/minimapLayout.js +15 -10
- package/dist/components/minimap/minimapLayout.js.map +1 -1
- package/dist/components/msa/{DomainLegend.d.ts → AnnotationLegend.d.ts} +2 -2
- package/dist/components/msa/{DomainLegend.js → AnnotationLegend.js} +4 -4
- package/dist/components/msa/AnnotationLegend.js.map +1 -0
- package/dist/components/msa/MSACanvas.js +9 -3
- package/dist/components/msa/MSACanvas.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +12 -3
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js +1 -2
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/MSAPanel.js +2 -2
- package/dist/components/msa/MSAPanel.js.map +1 -1
- package/dist/components/msa/domainBandCursor.d.ts +17 -0
- package/dist/components/msa/domainBandCursor.js +39 -0
- package/dist/components/msa/domainBandCursor.js.map +1 -0
- package/dist/components/msa/msaRaster.d.ts +63 -0
- package/dist/components/msa/msaRaster.js +252 -0
- package/dist/components/msa/msaRaster.js.map +1 -0
- package/dist/components/msa/renderMSABlock.d.ts +2 -1
- package/dist/components/msa/renderMSABlock.js +27 -41
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.js +1 -2
- package/dist/components/msa/renderMSAMouseover.js.map +1 -1
- package/dist/components/msa/tileColor.d.ts +6 -0
- package/dist/components/msa/tileColor.js +35 -0
- package/dist/components/msa/tileColor.js.map +1 -0
- package/dist/components/renderCtx.d.ts +1 -1
- package/dist/components/tracks/TrackBlocks.d.ts +14 -0
- package/dist/components/tracks/TrackBlocks.js +65 -0
- package/dist/components/tracks/TrackBlocks.js.map +1 -0
- package/dist/components/tracks/{renderTracksSvg.d.ts → drawTracks.d.ts} +22 -10
- package/dist/components/tracks/drawTracks.js +193 -0
- package/dist/components/tracks/drawTracks.js.map +1 -0
- package/dist/components/tree/TreeCanvas.js +8 -2
- package/dist/components/tree/TreeCanvas.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +7 -4
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/TreeRuler.js +5 -2
- package/dist/components/tree/TreeRuler.js.map +1 -1
- package/dist/components/tree/renderTreeCanvas.js +5 -2
- package/dist/components/tree/renderTreeCanvas.js.map +1 -1
- package/dist/constants.d.ts +3 -0
- package/dist/constants.js +8 -0
- package/dist/constants.js.map +1 -1
- package/dist/ggplotPalettes.d.ts +0 -1
- package/dist/ggplotPalettes.js +0 -3
- package/dist/ggplotPalettes.js.map +1 -1
- package/dist/hierarchy.d.ts +2 -6
- package/dist/hierarchy.js +4 -6
- package/dist/hierarchy.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/launchInterProScan.d.ts +0 -23
- package/dist/launchInterProScan.js +2 -5
- package/dist/launchInterProScan.js.map +1 -1
- package/dist/measureTextCanvas.js +21 -6
- package/dist/measureTextCanvas.js.map +1 -1
- package/dist/model/DataModel.d.ts +1 -4
- package/dist/model/DataModel.js +8 -10
- package/dist/model/DataModel.js.map +1 -1
- package/dist/model.d.ts +86 -107
- package/dist/model.js +238 -162
- package/dist/model.js.map +1 -1
- package/dist/neighborJoining.js +34 -18
- package/dist/neighborJoining.js.map +1 -1
- package/dist/renderTestEnv.d.ts +43 -0
- package/dist/renderTestEnv.js +88 -0
- package/dist/renderTestEnv.js.map +1 -0
- package/dist/renderToSvg.js +3 -3
- package/dist/renderToSvg.js.map +1 -1
- package/dist/rowCoordinateCalculations.d.ts +13 -17
- package/dist/rowCoordinateCalculations.js +45 -39
- package/dist/rowCoordinateCalculations.js.map +1 -1
- package/dist/sequenceLogo.d.ts +28 -0
- package/dist/sequenceLogo.js +47 -0
- package/dist/sequenceLogo.js.map +1 -0
- package/dist/types.d.ts +6 -11
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +5 -5
- package/src/clustalX.ts +22 -22
- package/src/colSpace.test.ts +27 -0
- package/src/columnCounts.test.ts +15 -0
- package/src/columnCounts.ts +19 -0
- package/src/components/CopyButton.tsx +44 -0
- package/src/components/DragHandle.tsx +81 -0
- package/src/components/Loading.tsx +10 -1
- package/src/components/MSAView.tsx +2 -3
- package/src/components/ResizeHandles.tsx +70 -87
- package/src/components/SequenceTextArea.tsx +3 -16
- package/src/components/VerticalScrollbar.tsx +20 -33
- package/src/components/dialogs/FeatureDialog.tsx +3 -4
- package/src/components/dialogs/InterProScanDialog.tsx +54 -131
- package/src/components/dialogs/{UserProvidedDomainsDialog.tsx → InterProScanFileDialog.tsx} +6 -14
- package/src/components/dialogs/TrackInfoDialog.tsx +18 -20
- package/src/components/header/FileMenu.tsx +3 -3
- package/src/components/header/GappynessSlider.tsx +4 -1
- package/src/components/header/{getDomainsMenu.ts → getAnnotationsMenu.ts} +10 -9
- package/src/components/header/settingsMenuItems.ts +18 -0
- package/src/components/import/ImportForm.tsx +1 -1
- package/src/components/import/ImportFormExamples.tsx +82 -133
- package/src/components/minimap/Minimap.tsx +67 -32
- package/src/components/minimap/MinimapSVG.tsx +32 -31
- package/src/components/minimap/minimapLayout.test.ts +60 -0
- package/src/components/minimap/minimapLayout.ts +15 -10
- package/src/components/msa/{DomainLegend.tsx → AnnotationLegend.tsx} +7 -3
- package/src/components/msa/MSACanvas.tsx +24 -11
- package/src/components/msa/MSACanvasBlock.tsx +13 -3
- package/src/components/msa/MSAMouseoverCanvas.tsx +1 -3
- package/src/components/msa/MSAPanel.tsx +2 -2
- package/src/components/msa/domainBandCursor.ts +41 -0
- package/src/components/msa/msaRaster.test.ts +145 -0
- package/src/components/msa/msaRaster.ts +350 -0
- package/src/components/msa/renderMSABlock.ts +34 -43
- package/src/components/msa/renderMSAMouseover.ts +1 -3
- package/src/components/msa/tileColor.ts +37 -0
- package/src/components/renderCtx.ts +2 -0
- package/src/components/tracks/TrackBlocks.tsx +111 -0
- package/src/components/tracks/drawTracks.ts +323 -0
- package/src/components/tree/TreeCanvas.tsx +16 -4
- package/src/components/tree/TreeCanvasBlock.tsx +18 -11
- package/src/components/tree/TreeRuler.tsx +7 -2
- package/src/components/tree/renderTreeCanvas.test.ts +15 -7
- package/src/components/tree/renderTreeCanvas.ts +5 -1
- package/src/constants.ts +10 -0
- package/src/domainBands.test.ts +24 -0
- package/src/domainLetterColor.test.ts +80 -0
- package/src/ggplotPalettes.ts +0 -4
- package/src/hierarchy.test.ts +7 -7
- package/src/hierarchy.ts +6 -9
- package/src/impgRender.test.tsx +2 -57
- package/src/index.ts +4 -1
- package/src/largeTree.test.ts +39 -4
- package/src/launchInterProScan.ts +3 -30
- package/src/loadErrorDisplay.test.tsx +102 -0
- package/src/measureTextCanvas.ts +22 -6
- package/src/model/DataModel.ts +11 -11
- package/src/model.ts +262 -172
- package/src/neighborJoining.ts +36 -18
- package/src/renderDomainsSvg.test.tsx +2 -57
- package/src/renderMinimapSvg.test.tsx +55 -0
- package/src/renderSequenceLogoSvg.test.tsx +176 -0
- package/src/renderTestEnv.ts +96 -0
- package/src/renderToSvg.tsx +3 -3
- package/src/rowCoordinateCalculations.ts +48 -44
- package/src/sequenceLogo.test.ts +88 -0
- package/src/sequenceLogo.ts +63 -0
- package/src/types.ts +17 -16
- package/src/version.ts +1 -1
- package/src/viewChrome.test.tsx +134 -0
- package/dist/components/ConservationTrack.d.ts +0 -8
- package/dist/components/ConservationTrack.js +0 -49
- package/dist/components/ConservationTrack.js.map +0 -1
- package/dist/components/TextTrack.d.ts +0 -8
- package/dist/components/TextTrack.js +0 -58
- package/dist/components/TextTrack.js.map +0 -1
- package/dist/components/dialogs/DomainDialog.d.ts +0 -6
- package/dist/components/dialogs/DomainDialog.js +0 -19
- package/dist/components/dialogs/DomainDialog.js.map +0 -1
- package/dist/components/dialogs/UserProvidedDomainsDialog.js.map +0 -1
- package/dist/components/header/SettingsMenu.d.ts +0 -6
- package/dist/components/header/SettingsMenu.js +0 -40
- package/dist/components/header/SettingsMenu.js.map +0 -1
- package/dist/components/header/getDomainsMenu.js.map +0 -1
- package/dist/components/msa/DomainLegend.js.map +0 -1
- package/dist/components/tracks/renderTracksSvg.js +0 -126
- package/dist/components/tracks/renderTracksSvg.js.map +0 -1
- package/src/components/ConservationTrack.tsx +0 -99
- package/src/components/TextTrack.tsx +0 -103
- package/src/components/dialogs/DomainDialog.tsx +0 -45
- package/src/components/header/SettingsMenu.tsx +0 -57
- package/src/components/tracks/renderTracksSvg.ts +0 -247
|
@@ -1,48 +1,30 @@
|
|
|
1
|
-
import React, { useCallback
|
|
1
|
+
import React, { useCallback } from 'react'
|
|
2
2
|
|
|
3
3
|
import { observer } from 'mobx-react'
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import DragHandle from './DragHandle.tsx'
|
|
6
6
|
|
|
7
7
|
import type { MsaViewModel } from '../model.ts'
|
|
8
|
-
|
|
9
|
-
const handleBg = 'rgba(200,200,200)'
|
|
10
|
-
const handleBgHover = 'rgba(150,150,150)'
|
|
8
|
+
import type { TrackKind } from '../types.ts'
|
|
11
9
|
|
|
12
10
|
export const VerticalResizeHandle = observer(function ({
|
|
13
11
|
model,
|
|
14
12
|
}: {
|
|
15
13
|
model: MsaViewModel
|
|
16
14
|
}) {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
(delta: number, startWidth: number) => {
|
|
23
|
-
model.setTreeAreaWidth(startWidth + delta)
|
|
24
|
-
},
|
|
25
|
-
[model],
|
|
26
|
-
),
|
|
15
|
+
const onDrag = useCallback(
|
|
16
|
+
(delta: number, startWidth: number) => {
|
|
17
|
+
model.setTreeAreaWidth(startWidth + delta)
|
|
18
|
+
},
|
|
19
|
+
[model],
|
|
27
20
|
)
|
|
28
|
-
|
|
29
21
|
return (
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}}
|
|
37
|
-
onMouseLeave={() => {
|
|
38
|
-
setHovered(false)
|
|
39
|
-
}}
|
|
40
|
-
style={{
|
|
41
|
-
cursor: 'ew-resize',
|
|
42
|
-
width: resizeHandleWidth,
|
|
43
|
-
background: hovered ? handleBgHover : handleBg,
|
|
44
|
-
position: 'relative',
|
|
45
|
-
}}
|
|
22
|
+
<DragHandle
|
|
23
|
+
axis="x"
|
|
24
|
+
variant="resizer"
|
|
25
|
+
getStart={() => model.treeAreaWidth}
|
|
26
|
+
onDrag={onDrag}
|
|
27
|
+
style={{ width: model.resizeHandleWidth }}
|
|
46
28
|
/>
|
|
47
29
|
)
|
|
48
30
|
})
|
|
@@ -52,78 +34,79 @@ export const HorizontalResizeHandle = observer(function ({
|
|
|
52
34
|
}: {
|
|
53
35
|
model: MsaViewModel
|
|
54
36
|
}) {
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
(delta: number, startHeight: number) => {
|
|
61
|
-
model.setHeight(startHeight + delta)
|
|
62
|
-
},
|
|
63
|
-
[model],
|
|
64
|
-
),
|
|
37
|
+
const onDrag = useCallback(
|
|
38
|
+
(delta: number, startHeight: number) => {
|
|
39
|
+
model.setHeight(startHeight + delta)
|
|
40
|
+
},
|
|
41
|
+
[model],
|
|
65
42
|
)
|
|
66
|
-
|
|
67
43
|
return (
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
}}
|
|
75
|
-
onMouseLeave={() => {
|
|
76
|
-
setHovered(false)
|
|
77
|
-
}}
|
|
78
|
-
style={{
|
|
79
|
-
cursor: 'ns-resize',
|
|
80
|
-
width: '100%',
|
|
81
|
-
height: resizeHandleWidth,
|
|
82
|
-
background: hovered ? handleBgHover : handleBg,
|
|
83
|
-
position: 'relative',
|
|
84
|
-
}}
|
|
44
|
+
<DragHandle
|
|
45
|
+
axis="y"
|
|
46
|
+
variant="resizer"
|
|
47
|
+
getStart={() => model.height}
|
|
48
|
+
onDrag={onDrag}
|
|
49
|
+
style={{ width: '100%', height: model.resizeHandleWidth }}
|
|
85
50
|
/>
|
|
86
51
|
)
|
|
87
52
|
})
|
|
88
53
|
|
|
89
|
-
|
|
54
|
+
// The height behind each resizable track kind. Both bar tracks read one height
|
|
55
|
+
// so conservation and property conservation stay directly comparable; the logo
|
|
56
|
+
// keeps its own, being taller by default. Text tracks are absent: they are one
|
|
57
|
+
// alignment row tall and follow rowHeight, so the zoom controls already size
|
|
58
|
+
// them.
|
|
59
|
+
const trackHeights: Partial<
|
|
60
|
+
Record<
|
|
61
|
+
TrackKind,
|
|
62
|
+
{
|
|
63
|
+
get: (model: MsaViewModel) => number
|
|
64
|
+
set: (model: MsaViewModel, height: number) => void
|
|
65
|
+
}
|
|
66
|
+
>
|
|
67
|
+
> = {
|
|
68
|
+
bar: {
|
|
69
|
+
get: model => model.conservationTrackHeight,
|
|
70
|
+
set: (model, height) => {
|
|
71
|
+
model.setConservationTrackHeight(height)
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
logo: {
|
|
75
|
+
get: model => model.sequenceLogoTrackHeight,
|
|
76
|
+
set: (model, height) => {
|
|
77
|
+
model.setSequenceLogoTrackHeight(height)
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const TrackResizeHandle = observer(function ({
|
|
90
83
|
model,
|
|
84
|
+
kind,
|
|
91
85
|
}: {
|
|
92
86
|
model: MsaViewModel
|
|
87
|
+
kind: TrackKind
|
|
93
88
|
}) {
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
model.setConservationTrackHeight(Math.max(10, startHeight + delta))
|
|
101
|
-
},
|
|
102
|
-
[model],
|
|
103
|
-
),
|
|
89
|
+
const height = trackHeights[kind]
|
|
90
|
+
const onDrag = useCallback(
|
|
91
|
+
(delta: number, startHeight: number) => {
|
|
92
|
+
height?.set(model, Math.max(10, startHeight + delta))
|
|
93
|
+
},
|
|
94
|
+
[model, height],
|
|
104
95
|
)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
onMouseEnter={() => {
|
|
112
|
-
setHovered(true)
|
|
113
|
-
}}
|
|
114
|
-
onMouseLeave={() => {
|
|
115
|
-
setHovered(false)
|
|
116
|
-
}}
|
|
96
|
+
return height ? (
|
|
97
|
+
<DragHandle
|
|
98
|
+
axis="y"
|
|
99
|
+
variant="resizer"
|
|
100
|
+
getStart={() => height.get(model)}
|
|
101
|
+
onDrag={onDrag}
|
|
117
102
|
style={{
|
|
118
103
|
position: 'absolute',
|
|
119
104
|
bottom: 0,
|
|
120
105
|
left: 0,
|
|
121
|
-
cursor: 'ns-resize',
|
|
122
106
|
width: '100%',
|
|
123
|
-
height: resizeHandleWidth,
|
|
107
|
+
height: model.resizeHandleWidth,
|
|
124
108
|
zIndex: 1,
|
|
125
|
-
background: hovered ? handleBgHover : handleBg,
|
|
126
109
|
}}
|
|
127
110
|
/>
|
|
128
|
-
)
|
|
111
|
+
) : null
|
|
129
112
|
})
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import React, { useState } from 'react'
|
|
2
2
|
|
|
3
3
|
import { makeStyles } from '@jbrowse/core/util/tss-react'
|
|
4
|
-
import {
|
|
4
|
+
import { TextField } from '@mui/material'
|
|
5
5
|
import { getUngappedSequence } from 'msa-parsers'
|
|
6
6
|
|
|
7
|
-
import copy from '../vendor/copyToClipboard.ts'
|
|
8
7
|
import Checkbox2 from './Checkbox2.tsx'
|
|
8
|
+
import CopyButton from './CopyButton.tsx'
|
|
9
9
|
|
|
10
10
|
const useStyles = makeStyles()({
|
|
11
11
|
textAreaFont: {
|
|
@@ -21,7 +21,6 @@ const useStyles = makeStyles()({
|
|
|
21
21
|
|
|
22
22
|
export default function SequenceTextArea({ str }: { str: [string, string][] }) {
|
|
23
23
|
const { classes } = useStyles()
|
|
24
|
-
const [copied, setCopied] = useState(false)
|
|
25
24
|
const [showGaps, setShowGaps] = useState(false)
|
|
26
25
|
const [showEmpty, setShowEmpty] = useState(false)
|
|
27
26
|
|
|
@@ -32,19 +31,7 @@ export default function SequenceTextArea({ str }: { str: [string, string][] }) {
|
|
|
32
31
|
.join('\n')
|
|
33
32
|
return (
|
|
34
33
|
<>
|
|
35
|
-
<
|
|
36
|
-
color="primary"
|
|
37
|
-
variant="contained"
|
|
38
|
-
onClick={() => {
|
|
39
|
-
copy(disp)
|
|
40
|
-
setCopied(true)
|
|
41
|
-
setTimeout(() => {
|
|
42
|
-
setCopied(false)
|
|
43
|
-
}, 500)
|
|
44
|
-
}}
|
|
45
|
-
>
|
|
46
|
-
{copied ? 'Copied!' : 'Copy to clipboard'}
|
|
47
|
-
</Button>
|
|
34
|
+
<CopyButton text={disp} />
|
|
48
35
|
<Checkbox2
|
|
49
36
|
label="Show gaps"
|
|
50
37
|
checked={showGaps}
|
|
@@ -1,61 +1,48 @@
|
|
|
1
|
-
import React, { useCallback
|
|
1
|
+
import React, { useCallback } from 'react'
|
|
2
2
|
|
|
3
|
-
import { clamp } from '@jbrowse/core/util'
|
|
4
3
|
import { observer } from 'mobx-react'
|
|
5
4
|
|
|
6
|
-
import
|
|
5
|
+
import DragHandle from './DragHandle.tsx'
|
|
7
6
|
|
|
8
7
|
import type { MsaViewModel } from '../model.ts'
|
|
9
8
|
|
|
9
|
+
const width = 20
|
|
10
|
+
|
|
10
11
|
const VerticalScrollbar = observer(({ model }: { model: MsaViewModel }) => {
|
|
11
12
|
const { msaAreaHeight, scrollY, totalHeight } = model
|
|
12
|
-
const [hovered, setHovered] = useState(false)
|
|
13
|
-
const fill = 'rgba(66, 119, 127, 0.3)'
|
|
14
13
|
const unit = msaAreaHeight / totalHeight
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
model.setScrollY(clamp(startScroll - delta / unit, model.maxScrollY, 0))
|
|
24
|
-
},
|
|
25
|
-
[model, unit],
|
|
26
|
-
),
|
|
14
|
+
const t = -scrollY * unit
|
|
15
|
+
const b = (-scrollY + msaAreaHeight) * unit
|
|
16
|
+
|
|
17
|
+
const onDrag = useCallback(
|
|
18
|
+
(delta: number, startScroll: number) => {
|
|
19
|
+
model.setScrollY(startScroll - delta / unit)
|
|
20
|
+
},
|
|
21
|
+
[model, unit],
|
|
27
22
|
)
|
|
23
|
+
|
|
28
24
|
return (
|
|
29
25
|
<div
|
|
30
26
|
style={{
|
|
31
27
|
position: 'relative',
|
|
32
|
-
width
|
|
28
|
+
width,
|
|
33
29
|
height: msaAreaHeight,
|
|
34
30
|
borderLeft: '1px solid #555',
|
|
35
31
|
borderTop: '1px solid #555',
|
|
36
32
|
boxSizing: 'border-box',
|
|
37
33
|
}}
|
|
38
34
|
>
|
|
39
|
-
<
|
|
35
|
+
<DragHandle
|
|
36
|
+
axis="y"
|
|
37
|
+
variant="thumb"
|
|
38
|
+
getStart={() => model.scrollY}
|
|
39
|
+
onDrag={onDrag}
|
|
40
40
|
style={{
|
|
41
|
-
position: 'absolute',
|
|
42
41
|
top: Math.max(0, t),
|
|
43
42
|
left: 0,
|
|
44
|
-
background: hovered ? 'rgba(66,119,127,0.6)' : fill,
|
|
45
|
-
cursor: 'pointer',
|
|
46
43
|
boxSizing: 'border-box',
|
|
47
|
-
width
|
|
44
|
+
width,
|
|
48
45
|
height: Math.max(b - t, 20),
|
|
49
|
-
zIndex: 100,
|
|
50
|
-
}}
|
|
51
|
-
onMouseOver={() => {
|
|
52
|
-
setHovered(true)
|
|
53
|
-
}}
|
|
54
|
-
onMouseOut={() => {
|
|
55
|
-
setHovered(false)
|
|
56
|
-
}}
|
|
57
|
-
onMouseDown={event => {
|
|
58
|
-
startDrag(event, model.scrollY)
|
|
59
46
|
}}
|
|
60
47
|
/>
|
|
61
48
|
</div>
|
|
@@ -43,10 +43,9 @@ const Toggles = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
43
43
|
})
|
|
44
44
|
|
|
45
45
|
const FeatureTable = observer(function ({ model }: { model: MsaViewModel }) {
|
|
46
|
-
const {
|
|
47
|
-
model
|
|
46
|
+
const { annotationTypes, annotations, fillPalette } = model
|
|
48
47
|
const counts = new Map<string, number>()
|
|
49
|
-
for (const annot of
|
|
48
|
+
for (const annot of annotations) {
|
|
50
49
|
counts.set(annot.accession, (counts.get(annot.accession) ?? 0) + 1)
|
|
51
50
|
}
|
|
52
51
|
return (
|
|
@@ -64,7 +63,7 @@ const FeatureTable = observer(function ({ model }: { model: MsaViewModel }) {
|
|
|
64
63
|
</TableRow>
|
|
65
64
|
</TableHead>
|
|
66
65
|
<TableBody>
|
|
67
|
-
{[...
|
|
66
|
+
{[...annotationTypes.values()].map(
|
|
68
67
|
({ accession, name, description }) => (
|
|
69
68
|
<TableRow key={accession}>
|
|
70
69
|
<TableCell padding="checkbox">
|
|
@@ -10,6 +10,57 @@ import { launchInterProScan } from '../../launchInterProScan.ts'
|
|
|
10
10
|
|
|
11
11
|
import type { MsaViewModel } from '../../model.ts'
|
|
12
12
|
|
|
13
|
+
const FAMILIES = 'Families, domains, sites & repeats'
|
|
14
|
+
const FEATURES = 'Other sequence features'
|
|
15
|
+
const STRUCTURAL = 'Structural domains'
|
|
16
|
+
const OTHER = 'Other category'
|
|
17
|
+
|
|
18
|
+
// The analyses the EBI iprscan5 endpoint accepts, all on by default. Static, so
|
|
19
|
+
// it lives out here rather than being rebuilt on every render of the dialog.
|
|
20
|
+
const interProScanPrograms = [
|
|
21
|
+
{
|
|
22
|
+
name: 'NCBIfam',
|
|
23
|
+
category: FAMILIES,
|
|
24
|
+
description: 'NCBI RefSeq FAMs including TIGRFAMs',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'SFLD',
|
|
28
|
+
category: FAMILIES,
|
|
29
|
+
description: 'Structure function linkage database',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'Phobius',
|
|
33
|
+
category: FEATURES,
|
|
34
|
+
description:
|
|
35
|
+
'A combined transmembrane topology and signal peptide predictor',
|
|
36
|
+
},
|
|
37
|
+
{ name: 'SignalP', category: FEATURES },
|
|
38
|
+
{ name: 'SignalP_EUK', category: OTHER },
|
|
39
|
+
{ name: 'SignalP_GRAM_POSITIVE', category: OTHER },
|
|
40
|
+
{ name: 'SignalP_GRAM_NEGATIVE', category: OTHER },
|
|
41
|
+
{ name: 'SuperFamily', category: STRUCTURAL },
|
|
42
|
+
{ name: 'Panther', category: FAMILIES },
|
|
43
|
+
{ name: 'Gene3d', category: STRUCTURAL },
|
|
44
|
+
{ name: 'HAMAP', category: FAMILIES },
|
|
45
|
+
{ name: 'PrositeProfiles', category: FAMILIES },
|
|
46
|
+
{ name: 'PrositePatterns', category: FAMILIES },
|
|
47
|
+
{ name: 'Coils', category: FEATURES },
|
|
48
|
+
{ name: 'SMART', category: FAMILIES },
|
|
49
|
+
{
|
|
50
|
+
name: 'CDD',
|
|
51
|
+
category: FAMILIES,
|
|
52
|
+
description: 'Conserved Domains Database',
|
|
53
|
+
},
|
|
54
|
+
{ name: 'PRINTS', category: FAMILIES },
|
|
55
|
+
{ name: 'PfamA', category: FAMILIES },
|
|
56
|
+
{ name: 'MobiDBLite', category: FEATURES },
|
|
57
|
+
{ name: 'PIRSF', category: OTHER },
|
|
58
|
+
{ name: 'TMHMM', category: FEATURES },
|
|
59
|
+
{ name: 'AntiFam', category: OTHER },
|
|
60
|
+
{ name: 'FunFam', category: OTHER },
|
|
61
|
+
{ name: 'PIRSR', category: FAMILIES },
|
|
62
|
+
].map(program => ({ ...program, checked: true }))
|
|
63
|
+
|
|
13
64
|
const InterProScanDialog = observer(function ({
|
|
14
65
|
handleClose,
|
|
15
66
|
model,
|
|
@@ -17,134 +68,7 @@ const InterProScanDialog = observer(function ({
|
|
|
17
68
|
handleClose: () => void
|
|
18
69
|
model: MsaViewModel
|
|
19
70
|
}) {
|
|
20
|
-
const [vals, setVals] = useState(
|
|
21
|
-
{
|
|
22
|
-
name: 'NCBIfam',
|
|
23
|
-
description: 'NCBI RefSeq FAMs including TIGRFAMs',
|
|
24
|
-
category: 'Families, domains, sites & repeats',
|
|
25
|
-
checked: true,
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
name: 'SFLD',
|
|
29
|
-
description: 'Structure function linkage database',
|
|
30
|
-
category: 'Families, domains, sites & repeats',
|
|
31
|
-
checked: true,
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
name: 'Phobius',
|
|
35
|
-
checked: true,
|
|
36
|
-
description:
|
|
37
|
-
'A combined transmembrane topology and signal peptide predictor',
|
|
38
|
-
category: 'Other sequence features',
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: 'SignalP',
|
|
42
|
-
checked: true,
|
|
43
|
-
category: 'Other sequence features',
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
name: 'SignalP_EUK',
|
|
47
|
-
category: 'Other category',
|
|
48
|
-
checked: true,
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: 'SignalP_GRAM_POSITIVE',
|
|
52
|
-
category: 'Other category',
|
|
53
|
-
checked: true,
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: 'SignalP_GRAM_NEGATIVE',
|
|
57
|
-
checked: true,
|
|
58
|
-
category: 'Other category',
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: 'SuperFamily',
|
|
62
|
-
category: 'Structural domains',
|
|
63
|
-
checked: true,
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: 'Panther',
|
|
67
|
-
category: 'Families, domains, sites & repeats',
|
|
68
|
-
checked: true,
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: 'Gene3d',
|
|
72
|
-
category: 'Structural domains',
|
|
73
|
-
checked: true,
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
name: 'HAMAP',
|
|
77
|
-
category: 'Families, domains, sites & repeats',
|
|
78
|
-
checked: true,
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
name: 'PrositeProfiles',
|
|
82
|
-
category: 'Families, domains, sites & repeats',
|
|
83
|
-
checked: true,
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
name: 'PrositePatterns',
|
|
87
|
-
category: 'Families, domains, sites & repeats',
|
|
88
|
-
checked: true,
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
name: 'Coils',
|
|
92
|
-
category: 'Other sequence features',
|
|
93
|
-
checked: true,
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
name: 'SMART',
|
|
97
|
-
category: 'Families, domains, sites & repeats',
|
|
98
|
-
checked: true,
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
name: 'CDD',
|
|
102
|
-
description: 'Conserved Domains Database',
|
|
103
|
-
category: 'Families, domains, sites & repeats',
|
|
104
|
-
checked: true,
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
name: 'PRINTS',
|
|
108
|
-
category: 'Families, domains, sites & repeats',
|
|
109
|
-
checked: true,
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
name: 'PfamA',
|
|
113
|
-
category: 'Families, domains, sites & repeats',
|
|
114
|
-
checked: true,
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: 'MobiDBLite',
|
|
118
|
-
checked: true,
|
|
119
|
-
category: 'Other sequence features',
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
name: 'PIRSF',
|
|
123
|
-
checked: true,
|
|
124
|
-
category: 'Other category',
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
name: 'TMHMM',
|
|
128
|
-
checked: true,
|
|
129
|
-
category: 'Other sequence features',
|
|
130
|
-
},
|
|
131
|
-
|
|
132
|
-
{
|
|
133
|
-
name: 'AntiFam',
|
|
134
|
-
checked: true,
|
|
135
|
-
category: 'Other category',
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
name: 'FunFam',
|
|
139
|
-
checked: true,
|
|
140
|
-
category: 'Other category',
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
name: 'PIRSR',
|
|
144
|
-
checked: true,
|
|
145
|
-
category: 'Families, domains, sites & repeats',
|
|
146
|
-
},
|
|
147
|
-
])
|
|
71
|
+
const [vals, setVals] = useState(interProScanPrograms)
|
|
148
72
|
|
|
149
73
|
const programs = vals.filter(e => e.checked).map(e => e.name)
|
|
150
74
|
const [show, setShow] = useState(false)
|
|
@@ -197,12 +121,11 @@ const InterProScanDialog = observer(function ({
|
|
|
197
121
|
<tbody>
|
|
198
122
|
{vals
|
|
199
123
|
.toSorted((a, b) => a.category.localeCompare(b.category))
|
|
200
|
-
.map(({ name, checked, category }) => (
|
|
124
|
+
.map(({ name, checked, category, description }) => (
|
|
201
125
|
<tr key={name}>
|
|
202
126
|
<td>
|
|
203
127
|
<input
|
|
204
128
|
type="checkbox"
|
|
205
|
-
key={name}
|
|
206
129
|
checked={checked}
|
|
207
130
|
onChange={() => {
|
|
208
131
|
setVals(
|
|
@@ -215,7 +138,7 @@ const InterProScanDialog = observer(function ({
|
|
|
215
138
|
}}
|
|
216
139
|
/>
|
|
217
140
|
</td>
|
|
218
|
-
<td>{name}</td>
|
|
141
|
+
<td title={description}>{name}</td>
|
|
219
142
|
<td>{category}</td>
|
|
220
143
|
</tr>
|
|
221
144
|
))}
|
|
@@ -14,13 +14,14 @@ import {
|
|
|
14
14
|
Typography,
|
|
15
15
|
} from '@mui/material'
|
|
16
16
|
import { observer } from 'mobx-react'
|
|
17
|
+
import { interProScanResponseToAnnotations } from 'msa-parsers'
|
|
17
18
|
|
|
18
19
|
import { jsonfetch } from '../../fetchUtils.ts'
|
|
19
20
|
|
|
20
|
-
import type { InterProScanResponse } from '../../launchInterProScan.ts'
|
|
21
21
|
import type { MsaViewModel } from '../../model.ts'
|
|
22
|
+
import type { InterProScanResponse } from 'msa-parsers'
|
|
22
23
|
|
|
23
|
-
const
|
|
24
|
+
const InterProScanFileDialog = observer(function ({
|
|
24
25
|
handleClose,
|
|
25
26
|
model,
|
|
26
27
|
}: {
|
|
@@ -34,7 +35,7 @@ const UserProvidedDomainsDialog = observer(function ({
|
|
|
34
35
|
return (
|
|
35
36
|
<Dialog
|
|
36
37
|
maxWidth="xl"
|
|
37
|
-
title="Open
|
|
38
|
+
title="Open InterProScan results"
|
|
38
39
|
onClose={() => {
|
|
39
40
|
handleClose()
|
|
40
41
|
}}
|
|
@@ -112,16 +113,7 @@ const UserProvidedDomainsDialog = observer(function ({
|
|
|
112
113
|
? JSON.parse(await file.text())
|
|
113
114
|
: await jsonfetch(interProURL)
|
|
114
115
|
|
|
115
|
-
|
|
116
|
-
// row to attach to, and keying it `undefined` would draw a
|
|
117
|
-
// phantom row's worth of domains
|
|
118
|
-
model.setDomains(
|
|
119
|
-
Object.fromEntries(
|
|
120
|
-
ret.results
|
|
121
|
-
.map(r => [r.xref[0]?.id, r] as const)
|
|
122
|
-
.filter(e => e[0] !== undefined),
|
|
123
|
-
),
|
|
124
|
-
)
|
|
116
|
+
model.setAnnotations(interProScanResponseToAnnotations(ret))
|
|
125
117
|
getSession(model).notify(
|
|
126
118
|
'Loaded interproscan results',
|
|
127
119
|
'success',
|
|
@@ -143,4 +135,4 @@ const UserProvidedDomainsDialog = observer(function ({
|
|
|
143
135
|
)
|
|
144
136
|
})
|
|
145
137
|
|
|
146
|
-
export default
|
|
138
|
+
export default InterProScanFileDialog
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react'
|
|
2
2
|
|
|
3
3
|
import { Dialog } from '@jbrowse/core/ui'
|
|
4
4
|
import { makeStyles } from '@jbrowse/core/util/tss-react'
|
|
5
|
-
import { Button, DialogActions, DialogContent } from '@mui/material'
|
|
5
|
+
import { Button, DialogActions, DialogContent, Typography } from '@mui/material'
|
|
6
6
|
import { observer } from 'mobx-react'
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import CopyButton from '../CopyButton.tsx'
|
|
9
|
+
|
|
10
|
+
import type { BasicTrack } from '../../types.ts'
|
|
9
11
|
|
|
10
12
|
const useStyles = makeStyles()(theme => ({
|
|
11
13
|
textArea: {
|
|
@@ -20,10 +22,10 @@ const TrackInfoDialog = observer(function ({
|
|
|
20
22
|
model,
|
|
21
23
|
onClose,
|
|
22
24
|
}: {
|
|
23
|
-
model:
|
|
25
|
+
model: BasicTrack['model']
|
|
24
26
|
onClose: () => void
|
|
25
27
|
}) {
|
|
26
|
-
const
|
|
28
|
+
const { name, data } = model
|
|
27
29
|
const { classes } = useStyles()
|
|
28
30
|
return (
|
|
29
31
|
<Dialog
|
|
@@ -31,23 +33,19 @@ const TrackInfoDialog = observer(function ({
|
|
|
31
33
|
onClose={onClose}
|
|
32
34
|
fullWidth
|
|
33
35
|
maxWidth="lg"
|
|
34
|
-
title={`Track info - ${
|
|
36
|
+
title={`Track info - ${name}`}
|
|
35
37
|
>
|
|
36
38
|
<DialogContent>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
>
|
|
48
|
-
{label}
|
|
49
|
-
</Button>
|
|
50
|
-
<pre className={classes.textArea}>{model.data}</pre>
|
|
39
|
+
{/* the bar tracks (conservation) are computed per column and carry no
|
|
40
|
+
text of their own, so there is nothing to show or copy for them */}
|
|
41
|
+
{data === undefined ? (
|
|
42
|
+
<Typography>This track has no text data.</Typography>
|
|
43
|
+
) : (
|
|
44
|
+
<>
|
|
45
|
+
<CopyButton text={data} />
|
|
46
|
+
<pre className={classes.textArea}>{data}</pre>
|
|
47
|
+
</>
|
|
48
|
+
)}
|
|
51
49
|
</DialogContent>
|
|
52
50
|
<DialogActions>
|
|
53
51
|
<Button variant="contained" onClick={onClose} color="secondary">
|