jbrowse-plugin-msaview 2.0.6 → 2.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.
Files changed (181) hide show
  1. package/dist/AddHighlightModel/GenomeMouseoverHighlight.js +3 -3
  2. package/dist/AddHighlightModel/GenomeMouseoverHighlight.js.map +1 -1
  3. package/dist/AddHighlightModel/MsaToGenomeHighlight.js +3 -1
  4. package/dist/AddHighlightModel/MsaToGenomeHighlight.js.map +1 -1
  5. package/dist/ExternalLink.d.ts +3 -0
  6. package/dist/ExternalLink.js +11 -0
  7. package/dist/ExternalLink.js.map +1 -0
  8. package/dist/LaunchMsaView/components/{NewNCBIBlastQuery/NcbiBlastPanel.d.ts → EnsemblGeneTree/EnsemblGeneTree.d.ts} +2 -2
  9. package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js +76 -0
  10. package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js.map +1 -0
  11. package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeLaunchView.d.ts +13 -0
  12. package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeLaunchView.js +12 -0
  13. package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeLaunchView.js.map +1 -0
  14. package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.d.ts +6 -0
  15. package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.js +25 -0
  16. package/dist/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.js.map +1 -0
  17. package/dist/LaunchMsaView/components/EnsemblGeneTree/gatherSequencesFromTree.d.ts +2 -0
  18. package/dist/LaunchMsaView/components/EnsemblGeneTree/gatherSequencesFromTree.js +20 -0
  19. package/dist/LaunchMsaView/components/EnsemblGeneTree/gatherSequencesFromTree.js.map +1 -0
  20. package/dist/LaunchMsaView/components/EnsemblGeneTree/types.d.ts +24 -0
  21. package/dist/LaunchMsaView/components/EnsemblGeneTree/types.js +2 -0
  22. package/dist/LaunchMsaView/components/EnsemblGeneTree/types.js.map +1 -0
  23. package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.d.ts +10 -0
  24. package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.js +27 -0
  25. package/dist/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.js.map +1 -0
  26. package/dist/LaunchMsaView/components/EnsemblGeneTree/util.d.ts +4 -0
  27. package/dist/LaunchMsaView/components/EnsemblGeneTree/util.js +38 -0
  28. package/dist/LaunchMsaView/components/EnsemblGeneTree/util.js.map +1 -0
  29. package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js +22 -16
  30. package/dist/LaunchMsaView/components/LaunchMsaViewDialog.js.map +1 -1
  31. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.d.ts +8 -0
  32. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +103 -0
  33. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js.map +1 -0
  34. package/dist/LaunchMsaView/components/ManualMSALoader/fetchGeneList.d.ts +1 -0
  35. package/dist/LaunchMsaView/components/ManualMSALoader/fetchGeneList.js +12 -0
  36. package/dist/LaunchMsaView/components/ManualMSALoader/fetchGeneList.js.map +1 -0
  37. package/dist/LaunchMsaView/components/ManualMSALoader/launchView.d.ts +14 -0
  38. package/dist/LaunchMsaView/components/ManualMSALoader/launchView.js +12 -0
  39. package/dist/LaunchMsaView/components/ManualMSALoader/launchView.js.map +1 -0
  40. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.d.ts +10 -0
  41. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js +89 -0
  42. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js.map +1 -0
  43. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.d.ts +10 -0
  44. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js +55 -0
  45. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js.map +1 -0
  46. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.d.ts +5 -0
  47. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.js +11 -0
  48. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.js.map +1 -0
  49. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.d.ts +7 -0
  50. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js +30 -0
  51. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js.map +1 -0
  52. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.d.ts +5 -0
  53. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.js +26 -0
  54. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.js.map +1 -0
  55. package/dist/LaunchMsaView/components/{NewNCBIBlastQuery/ncbiBlastLaunchView.d.ts → NCBIBlastQuery/blastLaunchView.d.ts} +2 -1
  56. package/dist/LaunchMsaView/components/{NewNCBIBlastQuery/ncbiBlastLaunchView.js → NCBIBlastQuery/blastLaunchView.js} +3 -6
  57. package/dist/LaunchMsaView/components/NCBIBlastQuery/blastLaunchView.js.map +1 -0
  58. package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.d.ts +1 -0
  59. package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.js +2 -0
  60. package/dist/LaunchMsaView/components/NCBIBlastQuery/consts.js.map +1 -0
  61. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +18 -19
  62. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js.map +1 -1
  63. package/dist/LaunchMsaView/components/TabPanel.d.ts +6 -0
  64. package/dist/LaunchMsaView/components/TabPanel.js +6 -0
  65. package/dist/LaunchMsaView/components/TabPanel.js.map +1 -0
  66. package/dist/LaunchMsaView/components/TranscriptSelector.d.ts +10 -0
  67. package/dist/LaunchMsaView/components/TranscriptSelector.js +45 -0
  68. package/dist/LaunchMsaView/components/TranscriptSelector.js.map +1 -0
  69. package/dist/LaunchMsaView/components/calculateProteinSequence.d.ts +17 -0
  70. package/dist/LaunchMsaView/components/calculateProteinSequence.js +39 -0
  71. package/dist/LaunchMsaView/components/calculateProteinSequence.js.map +1 -0
  72. package/dist/LaunchMsaView/components/fetchSeq.d.ts +8 -0
  73. package/dist/LaunchMsaView/components/fetchSeq.js +23 -0
  74. package/dist/LaunchMsaView/components/fetchSeq.js.map +1 -0
  75. package/dist/LaunchMsaView/components/types.d.ts +10 -0
  76. package/dist/LaunchMsaView/components/types.js +2 -0
  77. package/dist/LaunchMsaView/components/types.js.map +1 -0
  78. package/dist/LaunchMsaView/components/{NewNCBIBlastQuery/useFeatureSequence.d.ts → useFeatureSequence.d.ts} +3 -6
  79. package/dist/LaunchMsaView/components/{NewNCBIBlastQuery/useFeatureSequence.js → useFeatureSequence.js} +13 -23
  80. package/dist/LaunchMsaView/components/useFeatureSequence.js.map +1 -0
  81. package/dist/LaunchMsaView/components/util.js.map +1 -0
  82. package/dist/LaunchMsaView/util.d.ts +5 -1
  83. package/dist/LaunchMsaView/util.js +15 -1
  84. package/dist/LaunchMsaView/util.js.map +1 -1
  85. package/dist/MsaViewPanel/components/LoadingBLAST.d.ts +2 -1
  86. package/dist/MsaViewPanel/components/LoadingBLAST.js +6 -6
  87. package/dist/MsaViewPanel/components/LoadingBLAST.js.map +1 -1
  88. package/dist/MsaViewPanel/components/MsaViewPanel.js +1 -1
  89. package/dist/MsaViewPanel/components/MsaViewPanel.js.map +1 -1
  90. package/dist/MsaViewPanel/components/RIDLink.d.ts +2 -1
  91. package/dist/MsaViewPanel/components/RIDLink.js +6 -9
  92. package/dist/MsaViewPanel/components/RIDLink.js.map +1 -1
  93. package/dist/MsaViewPanel/doLaunchBlast.js +18 -20
  94. package/dist/MsaViewPanel/doLaunchBlast.js.map +1 -1
  95. package/dist/MsaViewPanel/model.d.ts +15 -12
  96. package/dist/MsaViewPanel/model.js.map +1 -1
  97. package/dist/ReadOnlyTextField2.d.ts +4 -0
  98. package/dist/ReadOnlyTextField2.js +20 -0
  99. package/dist/ReadOnlyTextField2.js.map +1 -0
  100. package/dist/index.d.ts +15 -0
  101. package/dist/index.js +17 -0
  102. package/dist/index.js.map +1 -1
  103. package/dist/jbrowse-plugin-msaview.umd.production.min.js +33 -31
  104. package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
  105. package/dist/utils/fetch.d.ts +1 -1
  106. package/dist/utils/fetch.js.map +1 -1
  107. package/dist/utils/ncbiBlast.d.ts +2 -2
  108. package/dist/utils/ncbiBlast.js +29 -15
  109. package/dist/utils/ncbiBlast.js.map +1 -1
  110. package/dist/utils/types.d.ts +20 -0
  111. package/dist/utils/types.js +2 -0
  112. package/dist/utils/types.js.map +1 -0
  113. package/package.json +3 -3
  114. package/src/AddHighlightModel/GenomeMouseoverHighlight.tsx +3 -3
  115. package/src/AddHighlightModel/MsaToGenomeHighlight.tsx +2 -1
  116. package/src/ExternalLink.tsx +15 -0
  117. package/src/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.tsx +127 -0
  118. package/src/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeLaunchView.ts +30 -0
  119. package/src/LaunchMsaView/components/EnsemblGeneTree/ensemblGeneTreeUtils.ts +46 -0
  120. package/src/LaunchMsaView/components/EnsemblGeneTree/gatherSequencesFromTree.ts +22 -0
  121. package/src/LaunchMsaView/components/EnsemblGeneTree/types.ts +28 -0
  122. package/src/LaunchMsaView/components/EnsemblGeneTree/useGeneTree.ts +29 -0
  123. package/src/LaunchMsaView/components/EnsemblGeneTree/util.ts +45 -0
  124. package/src/LaunchMsaView/components/LaunchMsaViewDialog.tsx +36 -21
  125. package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +219 -0
  126. package/src/LaunchMsaView/components/ManualMSALoader/fetchGeneList.ts +13 -0
  127. package/src/LaunchMsaView/components/ManualMSALoader/launchView.ts +34 -0
  128. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.tsx +226 -0
  129. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.tsx +111 -0
  130. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.tsx +34 -0
  131. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.tsx +82 -0
  132. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBISettingsDialog.tsx +75 -0
  133. package/src/LaunchMsaView/components/{NewNCBIBlastQuery/ncbiBlastLaunchView.ts → NCBIBlastQuery/blastLaunchView.ts} +4 -5
  134. package/src/LaunchMsaView/components/NCBIBlastQuery/consts.ts +1 -0
  135. package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +28 -44
  136. package/src/LaunchMsaView/components/TabPanel.tsx +19 -0
  137. package/src/LaunchMsaView/components/TranscriptSelector.tsx +99 -0
  138. package/src/LaunchMsaView/components/calculateProteinSequence.ts +68 -0
  139. package/src/LaunchMsaView/components/fetchSeq.ts +37 -0
  140. package/src/LaunchMsaView/components/types.ts +11 -0
  141. package/src/LaunchMsaView/components/{NewNCBIBlastQuery/useFeatureSequence.ts → useFeatureSequence.ts} +20 -42
  142. package/src/LaunchMsaView/util.ts +22 -2
  143. package/src/MsaViewPanel/components/LoadingBLAST.tsx +26 -8
  144. package/src/MsaViewPanel/components/MsaViewPanel.tsx +5 -1
  145. package/src/MsaViewPanel/components/RIDLink.tsx +8 -8
  146. package/src/MsaViewPanel/doLaunchBlast.ts +29 -30
  147. package/src/MsaViewPanel/model.ts +1 -0
  148. package/src/ReadOnlyTextField2.tsx +33 -0
  149. package/src/index.ts +23 -0
  150. package/src/utils/fetch.ts +2 -2
  151. package/src/utils/ncbiBlast.ts +40 -30
  152. package/src/utils/types.ts +14 -0
  153. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/NcbiBlastPanel.js +0 -85
  154. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/NcbiBlastPanel.js.map +0 -1
  155. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/calculateProteinSequence.d.ts +0 -26
  156. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/calculateProteinSequence.js +0 -48
  157. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/calculateProteinSequence.js.map +0 -1
  158. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/index.d.ts +0 -1
  159. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/index.js +0 -2
  160. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/index.js.map +0 -1
  161. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/ncbiBlastLaunchView.js.map +0 -1
  162. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/useFeatureSequence.js.map +0 -1
  163. package/dist/LaunchMsaView/components/NewNCBIBlastQuery/util.js.map +0 -1
  164. package/dist/LaunchMsaView/components/TabUtils.d.ts +0 -8
  165. package/dist/LaunchMsaView/components/TabUtils.js +0 -7
  166. package/dist/LaunchMsaView/components/TabUtils.js.map +0 -1
  167. package/dist/LaunchMsaView/components/tabUtil.d.ts +0 -4
  168. package/dist/LaunchMsaView/components/tabUtil.js +0 -7
  169. package/dist/LaunchMsaView/components/tabUtil.js.map +0 -1
  170. package/dist/OpenInNewIcon.d.ts +0 -3
  171. package/dist/OpenInNewIcon.js +0 -8
  172. package/dist/OpenInNewIcon.js.map +0 -1
  173. package/src/LaunchMsaView/components/NewNCBIBlastQuery/NcbiBlastPanel.tsx +0 -171
  174. package/src/LaunchMsaView/components/NewNCBIBlastQuery/calculateProteinSequence.ts +0 -92
  175. package/src/LaunchMsaView/components/NewNCBIBlastQuery/index.tsx +0 -1
  176. package/src/LaunchMsaView/components/TabUtils.tsx +0 -25
  177. package/src/LaunchMsaView/components/tabUtil.ts +0 -6
  178. package/src/OpenInNewIcon.tsx +0 -14
  179. /package/dist/LaunchMsaView/components/{NewNCBIBlastQuery/util.d.ts → util.d.ts} +0 -0
  180. /package/dist/LaunchMsaView/components/{NewNCBIBlastQuery/util.js → util.js} +0 -0
  181. /package/src/LaunchMsaView/components/{NewNCBIBlastQuery/util.ts → util.ts} +0 -0
@@ -0,0 +1,219 @@
1
+ import React, { useState } from 'react'
2
+
3
+ import { ErrorMessage, FileSelector } from '@jbrowse/core/ui'
4
+ import {
5
+ AbstractTrackModel,
6
+ Feature,
7
+ FileLocation,
8
+ getContainingView,
9
+ getSession,
10
+ } from '@jbrowse/core/util'
11
+ import { openLocation } from '@jbrowse/core/util/io'
12
+ import {
13
+ Button,
14
+ DialogActions,
15
+ DialogContent,
16
+ FormControl,
17
+ FormControlLabel,
18
+ Radio,
19
+ RadioGroup,
20
+ } from '@mui/material'
21
+ import { observer } from 'mobx-react'
22
+ import { makeStyles } from 'tss-react/mui'
23
+
24
+ import { launchView } from './launchView'
25
+ import TextField2 from '../../../TextField2'
26
+ import { getGeneDisplayName, getId, getTranscriptFeatures } from '../../util'
27
+ import TranscriptSelector from '../TranscriptSelector'
28
+ import { useFeatureSequence } from '../useFeatureSequence'
29
+
30
+ import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
31
+
32
+ const useStyles = makeStyles()({
33
+ dialogContent: {
34
+ width: '80em',
35
+ },
36
+ textAreaFont: {
37
+ fontFamily: 'Courier New',
38
+ },
39
+ })
40
+
41
+ const ManualMSALoader = observer(function PreLoadedMSA2({
42
+ model,
43
+ feature,
44
+ handleClose,
45
+ }: {
46
+ model: AbstractTrackModel
47
+ feature: Feature
48
+ handleClose: () => void
49
+ }) {
50
+ const session = getSession(model)
51
+ const view = getContainingView(model) as LinearGenomeViewModel
52
+ const { classes } = useStyles()
53
+ const [launchViewError, setLaunchViewError] = useState<unknown>()
54
+ const [inputMethod, setInputMethod] = useState<'file' | 'text'>('file')
55
+ const [msaText, setMsaText] = useState('')
56
+ const [treeText, setTreeText] = useState('')
57
+ const [msaFileLocation, setMsaFileLocation] = useState<FileLocation>()
58
+ const [treeFileLocation, setTreeFileLocation] = useState<FileLocation>()
59
+ const options = getTranscriptFeatures(feature)
60
+ const [userSelection, setUserSelection] = useState(getId(options[0]))
61
+ const ret = options.find(val => userSelection === getId(val))
62
+ const selectedTranscript = options.find(val => getId(val) === userSelection)!
63
+ const { proteinSequence, error: error2 } = useFeatureSequence({
64
+ view,
65
+ feature: selectedTranscript,
66
+ })
67
+
68
+ const e = launchViewError ?? error2
69
+ return (
70
+ <>
71
+ <DialogContent className={classes.dialogContent}>
72
+ {e ? <ErrorMessage error={e} /> : null}
73
+ <FormControl component="fieldset">
74
+ <RadioGroup
75
+ row
76
+ value={inputMethod}
77
+ onChange={event => {
78
+ setInputMethod(event.target.value as 'file' | 'text')
79
+ }}
80
+ >
81
+ <FormControlLabel
82
+ value="file"
83
+ control={<Radio />}
84
+ label="Open files"
85
+ />
86
+ <FormControlLabel
87
+ value="text"
88
+ control={<Radio />}
89
+ label="Paste text"
90
+ />
91
+ </RadioGroup>
92
+ </FormControl>
93
+
94
+ <div style={{ marginBottom: 30 }}>
95
+ {inputMethod === 'file' ? (
96
+ <div style={{ maxWidth: 500 }}>
97
+ <FileSelector
98
+ name="MSA File .aln (Clustal), .fa/.mfa (aligned FASTA), .stock (Stockholm), etc)"
99
+ inline
100
+ location={msaFileLocation}
101
+ setLocation={setMsaFileLocation}
102
+ />
103
+ <FileSelector
104
+ name="Tree file .nh (Newick) or .asn (NCBI COBALT ASN.1)"
105
+ inline
106
+ location={treeFileLocation}
107
+ setLocation={setTreeFileLocation}
108
+ />
109
+ </div>
110
+ ) : (
111
+ <>
112
+ <TextField2
113
+ variant="outlined"
114
+ name="MSA"
115
+ multiline
116
+ minRows={5}
117
+ style={{ marginBottom: '20px' }}
118
+ maxRows={10}
119
+ fullWidth
120
+ placeholder="Paste MSA here"
121
+ value={msaText}
122
+ onChange={event => {
123
+ setMsaText(event.target.value)
124
+ }}
125
+ />
126
+ <TextField2
127
+ variant="outlined"
128
+ name="Tree"
129
+ multiline
130
+ minRows={5}
131
+ maxRows={10}
132
+ fullWidth
133
+ placeholder="Paste newick tree (optional)"
134
+ value={treeText}
135
+ onChange={event => {
136
+ setTreeText(event.target.value)
137
+ }}
138
+ />
139
+ </>
140
+ )}
141
+ </div>
142
+
143
+ <TranscriptSelector
144
+ feature={feature}
145
+ options={options}
146
+ selectedTranscriptId={userSelection}
147
+ onTranscriptChange={setUserSelection}
148
+ proteinSequence={proteinSequence}
149
+ />
150
+ </DialogContent>
151
+
152
+ <DialogActions>
153
+ <Button
154
+ color="primary"
155
+ variant="contained"
156
+ disabled={
157
+ !ret ||
158
+ (inputMethod === 'file' && !msaFileLocation) ||
159
+ (inputMethod === 'text' && !msaText.trim())
160
+ }
161
+ onClick={() => {
162
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
163
+ ;(async () => {
164
+ try {
165
+ if (!ret) {
166
+ return
167
+ }
168
+
169
+ setLaunchViewError(undefined)
170
+ launchView({
171
+ session,
172
+ newViewTitle: getGeneDisplayName(ret),
173
+ view,
174
+ feature: ret,
175
+ data:
176
+ inputMethod === 'file'
177
+ ? {
178
+ msa: msaFileLocation
179
+ ? await openLocation(msaFileLocation).readFile(
180
+ 'utf8',
181
+ )
182
+ : '',
183
+ tree: treeFileLocation
184
+ ? await openLocation(treeFileLocation).readFile(
185
+ 'utf8',
186
+ )
187
+ : undefined,
188
+ }
189
+ : {
190
+ msa: msaText,
191
+ tree: treeText,
192
+ },
193
+ })
194
+
195
+ handleClose()
196
+ } catch (e) {
197
+ console.error(e)
198
+ setLaunchViewError(e)
199
+ }
200
+ })()
201
+ }}
202
+ >
203
+ Submit
204
+ </Button>
205
+ <Button
206
+ color="secondary"
207
+ variant="contained"
208
+ onClick={() => {
209
+ handleClose()
210
+ }}
211
+ >
212
+ Cancel
213
+ </Button>
214
+ </DialogActions>
215
+ </>
216
+ )
217
+ })
218
+
219
+ export default ManualMSALoader
@@ -0,0 +1,13 @@
1
+ export async function fetchGeneList() {
2
+ const res = await fetch(
3
+ 'https://jbrowse.org/demos/msaview/knownCanonical/list.txt',
4
+ )
5
+ if (!res.ok) {
6
+ throw new Error(`HTTP ${res.status} fetching list ${await res.text()}`)
7
+ }
8
+ const result = await res.text()
9
+ return result
10
+ .split('\n')
11
+ .map(f => f.trim())
12
+ .filter(f => !!f)
13
+ }
@@ -0,0 +1,34 @@
1
+ import { AbstractSessionModel, Feature, FileLocation } from '@jbrowse/core/util'
2
+
3
+ import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
4
+
5
+ export function launchView({
6
+ session,
7
+ newViewTitle,
8
+ view,
9
+ feature,
10
+ msaFileLocation,
11
+ treeFileLocation,
12
+ data,
13
+ }: {
14
+ session: AbstractSessionModel
15
+ newViewTitle: string
16
+ view: LinearGenomeViewModel
17
+ feature: Feature
18
+ msaFileLocation?: FileLocation
19
+ treeFileLocation?: FileLocation
20
+ data?: {
21
+ msa: string
22
+ tree?: string
23
+ }
24
+ }) {
25
+ session.addView('MsaView', {
26
+ type: 'MsaView',
27
+ displayName: newViewTitle,
28
+ connectedViewId: view.id,
29
+ connectedFeature: feature.toJSON(),
30
+ msaFileLocation,
31
+ treeFileLocation,
32
+ data,
33
+ })
34
+ }
@@ -0,0 +1,226 @@
1
+ import React, { useEffect, useState } from 'react'
2
+
3
+ import { ErrorMessage } from '@jbrowse/core/ui'
4
+ import {
5
+ AbstractTrackModel,
6
+ Feature,
7
+ getContainingView,
8
+ } from '@jbrowse/core/util'
9
+ import {
10
+ Button,
11
+ DialogActions,
12
+ DialogContent,
13
+ MenuItem,
14
+ Typography,
15
+ } from '@mui/material'
16
+ import { observer } from 'mobx-react'
17
+ import { makeStyles } from 'tss-react/mui'
18
+
19
+ import { blastLaunchView } from './blastLaunchView'
20
+ import TextField2 from '../../../TextField2'
21
+ import {
22
+ getGeneDisplayName,
23
+ getId,
24
+ getTranscriptDisplayName,
25
+ getTranscriptFeatures,
26
+ } from '../../util'
27
+ import TranscriptSelector from '../TranscriptSelector'
28
+ import { useFeatureSequence } from '../useFeatureSequence'
29
+
30
+ import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
31
+
32
+ const useStyles = makeStyles()({
33
+ dialogContent: {
34
+ width: '80em',
35
+ },
36
+ textAreaFont: {
37
+ fontFamily: 'Courier New',
38
+ },
39
+ })
40
+
41
+ const blastDatabaseOptions = ['nr', 'nr_cluster_seq'] as const
42
+ const msaAlgorithms = ['clustalo', 'muscle', 'kalign', 'mafft'] as const
43
+ const blastPrograms = ['blastp', 'quick-blastp'] as const
44
+
45
+ type blastDatabaseOptionsT = (typeof blastDatabaseOptions)[number]
46
+ type msaAlgorithmsT = (typeof msaAlgorithms)[number]
47
+ type blastProgramsT = (typeof blastPrograms)[number]
48
+
49
+ const NCBIBlastAutomaticPanel = observer(function ({
50
+ handleClose,
51
+ feature,
52
+ model,
53
+ children,
54
+ baseUrl,
55
+ }: {
56
+ model: AbstractTrackModel
57
+ feature: Feature
58
+ baseUrl: string
59
+ handleClose: () => void
60
+ children: React.ReactNode
61
+ }) {
62
+ const { classes } = useStyles()
63
+ const view = getContainingView(model) as LinearGenomeViewModel
64
+ const [launchViewError, setLaunchViewError] = useState<unknown>()
65
+ const [selectedBlastDatabase, setSelectedBlastDatabase] =
66
+ useState<blastDatabaseOptionsT>('nr')
67
+ const [selectedMsaAlgorithm, setSelectedMsaAlgorithm] =
68
+ useState<msaAlgorithmsT>('clustalo')
69
+ const options = getTranscriptFeatures(feature)
70
+ const [selectedTranscriptId, setSelectedTranscriptId] = useState(
71
+ getId(options[0]),
72
+ )
73
+ const [selectedBlastProgram, setSelectedBlastProgram] =
74
+ useState<blastProgramsT>('blastp')
75
+ const selectedTranscript = options.find(
76
+ val => getId(val) === selectedTranscriptId,
77
+ )!
78
+ const { error, proteinSequence } = useFeatureSequence({
79
+ view,
80
+ feature: selectedTranscript,
81
+ })
82
+
83
+ useEffect(() => {
84
+ if (selectedBlastDatabase === 'nr_cluster_seq') {
85
+ setSelectedBlastProgram('blastp')
86
+ }
87
+ }, [selectedBlastDatabase])
88
+ const e = error ?? launchViewError
89
+ return (
90
+ <>
91
+ <DialogContent className={classes.dialogContent}>
92
+ {children}
93
+ {e ? <ErrorMessage error={e} /> : null}
94
+ <TextField2
95
+ variant="outlined"
96
+ label="BLAST database"
97
+ style={{ width: 150 }}
98
+ select
99
+ value={selectedBlastDatabase}
100
+ onChange={event => {
101
+ setSelectedBlastDatabase(
102
+ event.target.value as (typeof blastDatabaseOptions)[number],
103
+ )
104
+ }}
105
+ >
106
+ {blastDatabaseOptions.map(val => (
107
+ <MenuItem value={val} key={val}>
108
+ {val}
109
+ </MenuItem>
110
+ ))}
111
+ </TextField2>
112
+
113
+ <TextField2
114
+ variant="outlined"
115
+ label="MSA Algorithm"
116
+ style={{ width: 150 }}
117
+ select
118
+ value={selectedMsaAlgorithm}
119
+ onChange={event => {
120
+ setSelectedMsaAlgorithm(
121
+ event.target.value as (typeof msaAlgorithms)[number],
122
+ )
123
+ }}
124
+ >
125
+ {msaAlgorithms.map(val => (
126
+ <MenuItem value={val} key={val}>
127
+ {val}
128
+ </MenuItem>
129
+ ))}
130
+ </TextField2>
131
+
132
+ <div style={{ display: 'flex' }}>
133
+ <TextField2
134
+ variant="outlined"
135
+ label="BLAST program"
136
+ disabled={selectedBlastDatabase === 'nr_cluster_seq'}
137
+ style={{ width: 150 }}
138
+ select
139
+ value={selectedBlastProgram}
140
+ onChange={event => {
141
+ setSelectedBlastProgram(
142
+ event.target.value as (typeof blastPrograms)[number],
143
+ )
144
+ }}
145
+ >
146
+ {blastPrograms.map(val => (
147
+ <MenuItem value={val} key={val}>
148
+ {val}
149
+ </MenuItem>
150
+ ))}
151
+ </TextField2>
152
+ {selectedBlastDatabase === 'nr_cluster_seq' ? (
153
+ <Typography
154
+ variant="subtitle2"
155
+ style={{ marginLeft: 4, alignContent: 'center' }}
156
+ >
157
+ Can only use blastp on nr_cluster_seq
158
+ </Typography>
159
+ ) : null}
160
+ </div>
161
+
162
+ <TranscriptSelector
163
+ feature={feature}
164
+ options={options}
165
+ selectedTranscriptId={selectedTranscriptId}
166
+ onTranscriptChange={setSelectedTranscriptId}
167
+ proteinSequence={proteinSequence}
168
+ />
169
+
170
+ <Typography style={{ marginTop: 20 }}>
171
+ This panel will automatically submit a query to NCBI. Using blastp can
172
+ take 10+ minutes to run, quick-blastp is generally a lot faster but is
173
+ not available for the clustered database. After completion, all the
174
+ hits will be run through a multiple sequence alignment. Note: we are
175
+ not able to currently run NCBI COBALT automatically on the BLAST
176
+ results, even though that is the method NCBI uses on their website. If
177
+ you need a COBALT alignment, please use the manual approach of
178
+ submitting BLAST yourself and downloading the resulting files
179
+ </Typography>
180
+ </DialogContent>
181
+ <DialogActions>
182
+ <Button
183
+ color="primary"
184
+ variant="contained"
185
+ onClick={() => {
186
+ try {
187
+ setLaunchViewError(undefined)
188
+ blastLaunchView({
189
+ feature: selectedTranscript,
190
+ view,
191
+ newViewTitle: `BLAST - ${getGeneDisplayName(feature)} - ${getTranscriptDisplayName(selectedTranscript)}`,
192
+ blastParams: {
193
+ baseUrl,
194
+ blastProgram: selectedBlastProgram,
195
+ blastDatabase: selectedBlastDatabase,
196
+ msaAlgorithm: selectedMsaAlgorithm,
197
+ selectedTranscript,
198
+ proteinSequence,
199
+ },
200
+ })
201
+ } catch (e) {
202
+ console.error(e)
203
+ setLaunchViewError(e)
204
+ }
205
+
206
+ handleClose()
207
+ }}
208
+ disabled={!proteinSequence}
209
+ >
210
+ Submit
211
+ </Button>
212
+ <Button
213
+ color="secondary"
214
+ variant="contained"
215
+ onClick={() => {
216
+ handleClose()
217
+ }}
218
+ >
219
+ Cancel
220
+ </Button>
221
+ </DialogActions>
222
+ </>
223
+ )
224
+ })
225
+
226
+ export default NCBIBlastAutomaticPanel
@@ -0,0 +1,111 @@
1
+ import React, { useState } from 'react'
2
+
3
+ import { ErrorMessage } from '@jbrowse/core/ui'
4
+ import { getContainingView, shorten2 } from '@jbrowse/core/util'
5
+ import { Button, DialogActions, DialogContent, Typography } from '@mui/material'
6
+ import { observer } from 'mobx-react'
7
+ import { makeStyles } from 'tss-react/mui'
8
+
9
+ import ExternalLink from '../../../ExternalLink'
10
+ import { getId, getTranscriptFeatures } from '../../util'
11
+ import TranscriptSelector from '../TranscriptSelector'
12
+ import { useFeatureSequence } from '../useFeatureSequence'
13
+
14
+ import type { AbstractTrackModel, Feature } from '@jbrowse/core/util'
15
+ import type { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view'
16
+
17
+ const useStyles = makeStyles()({
18
+ dialogContent: {
19
+ width: '80em',
20
+ },
21
+ textAreaFont: {
22
+ fontFamily: 'Courier New',
23
+ },
24
+ ncbiLink: {
25
+ wordBreak: 'break-all',
26
+ margin: 30,
27
+ maxWidth: 600,
28
+ },
29
+ })
30
+
31
+ const NCBIBlastManualPanel = observer(function ({
32
+ handleClose,
33
+ feature,
34
+ model,
35
+ children,
36
+ baseUrl,
37
+ }: {
38
+ children: React.ReactNode
39
+ model: AbstractTrackModel
40
+ feature: Feature
41
+ baseUrl: string
42
+ handleClose: () => void
43
+ }) {
44
+ const { classes } = useStyles()
45
+ const view = getContainingView(model) as LinearGenomeViewModel
46
+ const options = getTranscriptFeatures(feature)
47
+ const [userSelection, setUserSelection] = useState(getId(options[0]))
48
+ const selectedTranscript = options.find(val => getId(val) === userSelection)!
49
+ const { proteinSequence, error } = useFeatureSequence({
50
+ view,
51
+ feature: selectedTranscript,
52
+ })
53
+
54
+ const s2 = proteinSequence.replaceAll('*', '').replaceAll('&', '')
55
+ const link = `${baseUrl}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${s2}`
56
+ const link2 = `${baseUrl}?PAGE_TYPE=BlastSearch&PAGE=Proteins&PROGRAM=blastp&QUERY=${shorten2(s2, 10)}`
57
+
58
+ return (
59
+ <>
60
+ <DialogContent className={classes.dialogContent}>
61
+ {children}
62
+ {error ? <ErrorMessage error={error} /> : null}
63
+
64
+ <TranscriptSelector
65
+ feature={feature}
66
+ options={options}
67
+ selectedTranscriptId={userSelection}
68
+ onTranscriptChange={setUserSelection}
69
+ proteinSequence={proteinSequence}
70
+ />
71
+
72
+ {proteinSequence ? (
73
+ <div className={classes.ncbiLink}>
74
+ Link to NCBI BLAST: <ExternalLink href={link}>{link2}</ExternalLink>
75
+ </div>
76
+ ) : null}
77
+
78
+ <Typography style={{ marginTop: 20 }}>
79
+ Click the link above and run your BLAST query, and once you have
80
+ results, click "Multiple Alignment" at the top of the results page to
81
+ be redirected to COBALT, NCBI's multiple sequence aligner. Once COBALT
82
+ completes, you can download an MSA (.aln file) and optionally a Newick
83
+ tree (.nh) and paste the results into JBrowse
84
+ </Typography>
85
+ </DialogContent>
86
+
87
+ <DialogActions>
88
+ <Button
89
+ color="primary"
90
+ variant="contained"
91
+ onClick={() => {
92
+ handleClose()
93
+ }}
94
+ >
95
+ Submit
96
+ </Button>
97
+ <Button
98
+ color="secondary"
99
+ variant="contained"
100
+ onClick={() => {
101
+ handleClose()
102
+ }}
103
+ >
104
+ Close
105
+ </Button>
106
+ </DialogActions>
107
+ </>
108
+ )
109
+ })
110
+
111
+ export default NCBIBlastManualPanel
@@ -0,0 +1,34 @@
1
+ import React from 'react'
2
+
3
+ import { FormControl, FormControlLabel, Radio, RadioGroup } from '@mui/material'
4
+
5
+ export default function NCBIBlastMethodSelector({
6
+ lookupMethod,
7
+ setLookupMethod,
8
+ }: {
9
+ lookupMethod: string
10
+ setLookupMethod: (method: string) => void
11
+ }) {
12
+ return (
13
+ <FormControl component="fieldset">
14
+ <RadioGroup
15
+ row
16
+ value={lookupMethod}
17
+ onChange={event => {
18
+ setLookupMethod(event.target.value)
19
+ }}
20
+ >
21
+ <FormControlLabel
22
+ value="automatic"
23
+ control={<Radio />}
24
+ label="Run NCBI BLAST and load results automatically"
25
+ />
26
+ <FormControlLabel
27
+ value="manual"
28
+ control={<Radio />}
29
+ label="Link to NCBI BLAST and import results manually"
30
+ />
31
+ </RadioGroup>
32
+ </FormControl>
33
+ )
34
+ }