jbrowse-plugin-msaview 2.2.7 → 2.2.11

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 (65) hide show
  1. package/dist/BgzipFastaMsaAdapter/configSchema.d.ts +2 -2
  2. package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js +1 -1
  3. package/dist/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.js.map +1 -1
  4. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js +2 -2
  5. package/dist/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.js.map +1 -1
  6. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js +29 -6
  7. package/dist/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.js.map +1 -1
  8. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js +16 -6
  9. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.js.map +1 -1
  10. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js +2 -2
  11. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.js.map +1 -1
  12. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.js +3 -2
  13. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.js.map +1 -1
  14. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js +7 -3
  15. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.js.map +1 -1
  16. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.d.ts +10 -0
  17. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js +77 -0
  18. package/dist/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.js.map +1 -0
  19. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js +1 -1
  20. package/dist/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.js.map +1 -1
  21. package/dist/LaunchMsaView/components/TranscriptSelector.d.ts +2 -1
  22. package/dist/LaunchMsaView/components/TranscriptSelector.js +7 -6
  23. package/dist/LaunchMsaView/components/TranscriptSelector.js.map +1 -1
  24. package/dist/LaunchMsaView/components/useTranscriptSelection.js +13 -7
  25. package/dist/LaunchMsaView/components/useTranscriptSelection.js.map +1 -1
  26. package/dist/LaunchMsaView/util.d.ts +2 -0
  27. package/dist/LaunchMsaView/util.js +18 -2
  28. package/dist/LaunchMsaView/util.js.map +1 -1
  29. package/dist/MsaViewPanel/doLaunchBlast.js +36 -15
  30. package/dist/MsaViewPanel/doLaunchBlast.js.map +1 -1
  31. package/dist/MsaViewPanel/model.d.ts +7 -0
  32. package/dist/MsaViewPanel/model.js.map +1 -1
  33. package/dist/index.d.ts +5 -5
  34. package/dist/index.js +21 -22
  35. package/dist/index.js.map +1 -1
  36. package/dist/jbrowse-plugin-msaview.umd.production.min.js +27 -27
  37. package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
  38. package/dist/utils/blastCache.d.ts +8 -2
  39. package/dist/utils/blastCache.js +19 -6
  40. package/dist/utils/blastCache.js.map +1 -1
  41. package/dist/utils/ncbiBlast.d.ts +13 -0
  42. package/dist/utils/ncbiBlast.js +13 -0
  43. package/dist/utils/ncbiBlast.js.map +1 -1
  44. package/dist/version.d.ts +1 -1
  45. package/dist/version.js +1 -1
  46. package/dist/version.js.map +1 -1
  47. package/package.json +7 -7
  48. package/src/LaunchMsaView/components/EnsemblGeneTree/EnsemblGeneTree.tsx +1 -0
  49. package/src/LaunchMsaView/components/ManualMSALoader/ManualMSALoader.tsx +2 -0
  50. package/src/LaunchMsaView/components/NCBIBlastQuery/CachedBlastResults.tsx +32 -6
  51. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastAutomaticPanel.tsx +19 -4
  52. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastManualPanel.tsx +9 -2
  53. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastMethodSelector.tsx +4 -3
  54. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastPanel.tsx +8 -4
  55. package/src/LaunchMsaView/components/NCBIBlastQuery/NCBIBlastRIDPanel.tsx +187 -0
  56. package/src/LaunchMsaView/components/PreLoadedMSA/PreLoadedMSADataPanel.tsx +1 -0
  57. package/src/LaunchMsaView/components/TranscriptSelector.tsx +10 -6
  58. package/src/LaunchMsaView/components/useTranscriptSelection.ts +16 -7
  59. package/src/LaunchMsaView/util.ts +20 -2
  60. package/src/MsaViewPanel/doLaunchBlast.ts +37 -14
  61. package/src/MsaViewPanel/model.ts +1 -0
  62. package/src/index.ts +1 -2
  63. package/src/utils/blastCache.ts +36 -3
  64. package/src/utils/ncbiBlast.ts +24 -0
  65. package/src/version.ts +1 -1
@@ -1,12 +1,12 @@
1
1
  import React, { useState } from 'react'
2
2
 
3
3
  import { Feature } from '@jbrowse/core/util'
4
- import { Button, MenuItem } from '@mui/material'
4
+ import { Button, MenuItem, TextField } from '@mui/material'
5
5
  import { makeStyles } from 'tss-react/mui'
6
6
 
7
7
  import ReadOnlyTextField2 from '../../components/ReadOnlyTextField2'
8
- import TextField2 from '../../components/TextField2'
9
8
  import {
9
+ featureMatchesId,
10
10
  getGeneDisplayName,
11
11
  getId,
12
12
  getTranscriptDisplayName,
@@ -25,6 +25,7 @@ const useStyles = makeStyles()({
25
25
  export default function TranscriptSelector({
26
26
  feature,
27
27
  options,
28
+ selectedId,
28
29
  selectedTranscript,
29
30
  onTranscriptChange,
30
31
  proteinSequence,
@@ -32,6 +33,7 @@ export default function TranscriptSelector({
32
33
  }: {
33
34
  feature: Feature
34
35
  options: Feature[]
36
+ selectedId: string
35
37
  selectedTranscript: Feature | undefined
36
38
  onTranscriptChange: (transcriptId: string) => void
37
39
  proteinSequence: string | undefined
@@ -43,18 +45,20 @@ export default function TranscriptSelector({
43
45
  return (
44
46
  <>
45
47
  <div className={classes.flex}>
46
- <TextField2
48
+ <TextField
47
49
  variant="outlined"
48
50
  label={`Choose isoform of ${getGeneDisplayName(feature)}`}
49
51
  select
50
52
  className={classes.minWidth}
51
- value={getId(selectedTranscript)}
53
+ value={selectedId}
52
54
  onChange={event => {
53
55
  onTranscriptChange(event.target.value)
54
56
  }}
55
57
  >
56
58
  {options.map(val => {
57
- const inSet = validSet ? validSet.has(getId(val)) : true
59
+ const inSet = validSet
60
+ ? [...validSet].some(id => featureMatchesId(val, id))
61
+ : true
58
62
  const { len, mod } = getTranscriptLength(val)
59
63
  return (
60
64
  <MenuItem value={getId(val)} key={val.id()} disabled={!inSet}>
@@ -64,7 +68,7 @@ export default function TranscriptSelector({
64
68
  </MenuItem>
65
69
  )
66
70
  })}
67
- </TextField2>
71
+ </TextField>
68
72
  <div style={{ alignContent: 'center', marginLeft: 20 }}>
69
73
  <Button
70
74
  variant="contained"
@@ -1,10 +1,14 @@
1
1
  import { useEffect, useMemo, useState } from 'react'
2
2
 
3
- import { getId, getSortedTranscriptFeatures } from '../util'
3
+ import { featureMatchesId, getId, getSortedTranscriptFeatures } from '../util'
4
4
  import { useFeatureSequence } from './useFeatureSequence'
5
5
 
6
6
  import type { Feature } from '@jbrowse/core/util'
7
7
 
8
+ function featureInValidIds(feature: Feature, validIds: string[]): boolean {
9
+ return validIds.some(id => featureMatchesId(feature, id))
10
+ }
11
+
8
12
  export function useTranscriptSelection({
9
13
  feature,
10
14
  view,
@@ -14,8 +18,8 @@ export function useTranscriptSelection({
14
18
  view: { assemblyNames?: string[] } | undefined
15
19
  validIds?: string[]
16
20
  }) {
17
- const options = getSortedTranscriptFeatures(feature)
18
- const [selectedId, setSelectedId] = useState(getId(options[0]))
21
+ const options = useMemo(() => getSortedTranscriptFeatures(feature), [feature])
22
+ const [selectedId, setSelectedId] = useState(() => getId(options[0]))
19
23
  const selectedTranscript = options.find(val => getId(val) === selectedId)
20
24
  const { proteinSequence, error } = useFeatureSequence({
21
25
  view,
@@ -28,10 +32,15 @@ export function useTranscriptSelection({
28
32
  )
29
33
 
30
34
  useEffect(() => {
31
- if (validIds && validIds.length > 0 && !validIds.includes(selectedId)) {
32
- const validOption = options.find(opt => validIds.includes(getId(opt)))
33
- if (validOption) {
34
- setSelectedId(getId(validOption))
35
+ if (validIds && validIds.length > 0) {
36
+ const currentFeature = options.find(opt => getId(opt) === selectedId)
37
+ if (currentFeature && !featureInValidIds(currentFeature, validIds)) {
38
+ const validOption = options.find(opt =>
39
+ featureInValidIds(opt, validIds),
40
+ )
41
+ if (validOption) {
42
+ setSelectedId(getId(validOption))
43
+ }
35
44
  }
36
45
  }
37
46
  }, [validIds, options, selectedId])
@@ -38,7 +38,24 @@ export function getTranscriptLength(feature: Feature) {
38
38
  }
39
39
  }
40
40
  export function getId(val?: Feature): string {
41
- return val?.get('name') ?? val?.get('id') ?? ''
41
+ return val?.id() ?? ''
42
+ }
43
+
44
+ export function getMatchableIds(val?: Feature): string[] {
45
+ if (!val) {
46
+ return []
47
+ }
48
+ const ids = [
49
+ val.id(),
50
+ val.get('name'),
51
+ val.get('id'),
52
+ val.get('transcript_id'),
53
+ ].filter((id): id is string => !!id)
54
+ return [...new Set(ids)]
55
+ }
56
+
57
+ export function featureMatchesId(feature: Feature, id: string): boolean {
58
+ return getMatchableIds(feature).includes(id)
42
59
  }
43
60
 
44
61
  export function getTranscriptDisplayName(val?: Feature) {
@@ -59,7 +76,8 @@ export function getGeneDisplayName(val?: Feature) {
59
76
  }
60
77
 
61
78
  export function getSortedTranscriptFeatures(feature: Feature) {
62
- return getTranscriptFeatures(feature).toSorted(
79
+ const transcripts = getTranscriptFeatures(feature)
80
+ return transcripts.toSorted(
63
81
  (a, b) => getTranscriptLength(b).len - getTranscriptLength(a).len,
64
82
  )
65
83
  }
@@ -3,7 +3,7 @@ import { makeId, strip } from '../LaunchMsaView/components/util'
3
3
  import { cleanProteinSequence } from '../LaunchMsaView/util'
4
4
  import { saveBlastResult } from '../utils/blastCache'
5
5
  import { launchMSA } from '../utils/msa'
6
- import { queryBlast } from '../utils/ncbiBlast'
6
+ import { queryBlast, queryBlastFromRid } from '../utils/ncbiBlast'
7
7
  import { fetchTaxonomyInfo } from '../utils/taxonomyNames'
8
8
 
9
9
  import type { TaxonomyInfo } from '../utils/taxonomyNames'
@@ -21,21 +21,39 @@ export async function doLaunchBlast({
21
21
  msaAlgorithm,
22
22
  proteinSequence,
23
23
  selectedTranscript,
24
+ rid: existingRid,
24
25
  } = self.blastParams!
25
26
  const cleanedSeq = cleanProteinSequence(proteinSequence)
26
27
 
27
- const { hits, rid } = await queryBlast({
28
- query: cleanedSeq,
29
- blastDatabase,
30
- blastProgram,
31
- baseUrl,
32
- onProgress: arg => {
33
- self.setProgress(arg)
34
- },
35
- onRid: r => {
36
- self.setRid(r)
37
- },
38
- })
28
+ let hits
29
+ let rid: string
30
+ if (existingRid) {
31
+ self.setRid(existingRid)
32
+ const result = await queryBlastFromRid({
33
+ rid: existingRid,
34
+ baseUrl,
35
+ onProgress: arg => {
36
+ self.setProgress(arg)
37
+ },
38
+ })
39
+ hits = result.hits
40
+ rid = result.rid
41
+ } else {
42
+ const result = await queryBlast({
43
+ query: cleanedSeq,
44
+ blastDatabase,
45
+ blastProgram,
46
+ baseUrl,
47
+ onProgress: arg => {
48
+ self.setProgress(arg)
49
+ },
50
+ onRid: r => {
51
+ self.setRid(r)
52
+ },
53
+ })
54
+ hits = result.hits
55
+ rid = result.rid
56
+ }
39
57
 
40
58
  self.setProgress('Fetching species taxonomy info...')
41
59
  const taxids = hits
@@ -79,7 +97,12 @@ export async function doLaunchBlast({
79
97
  treeMetadata: treeMetadataJson,
80
98
  rid,
81
99
  geneId: selectedTranscript?.get('parentId'),
82
- transcriptId: selectedTranscript?.get('id'),
100
+ transcriptId: selectedTranscript?.id(),
101
+ transcriptName:
102
+ selectedTranscript?.get('name') ?? selectedTranscript?.get('id'),
103
+ geneName:
104
+ selectedTranscript?.get('gene_name') ??
105
+ selectedTranscript?.get('parentId'),
83
106
  })
84
107
 
85
108
  return {
@@ -94,6 +94,7 @@ export interface BlastParams {
94
94
  blastProgram: string
95
95
  selectedTranscript?: Feature
96
96
  proteinSequence: string
97
+ rid?: string
97
98
  }
98
99
 
99
100
  /**
package/src/index.ts CHANGED
@@ -36,8 +36,7 @@ export default class MsaViewPlugin extends Plugin {
36
36
  }
37
37
  }
38
38
 
39
- // @ts-expect-error
40
- rootConfigurationSchema(pluginManager: PluginManager) {
39
+ rootConfigurationSchema = (pluginManager: PluginManager) => {
41
40
  return {
42
41
  msa: ConfigurationSchema('MSA', {
43
42
  datasets: types.maybe(
@@ -17,6 +17,8 @@ export interface CachedBlastResult {
17
17
  timestamp: number
18
18
  geneId?: string
19
19
  transcriptId?: string
20
+ transcriptName?: string
21
+ geneName?: string
20
22
  }
21
23
 
22
24
  async function getDB() {
@@ -36,21 +38,33 @@ function createCacheKey(
36
38
  proteinSequence: string,
37
39
  blastDatabase: string,
38
40
  blastProgram: string,
41
+ transcriptId?: string,
39
42
  ) {
40
- return `${blastDatabase}:${blastProgram}:${proteinSequence.slice(0, 100)}`
43
+ const seqKey = proteinSequence.slice(0, 100)
44
+ if (transcriptId) {
45
+ return `${blastDatabase}:${blastProgram}:${transcriptId}:${seqKey}`
46
+ }
47
+ return `${blastDatabase}:${blastProgram}:${seqKey}`
41
48
  }
42
49
 
43
50
  export async function getCachedBlastResult({
44
51
  proteinSequence,
45
52
  blastDatabase,
46
53
  blastProgram,
54
+ transcriptId,
47
55
  }: {
48
56
  proteinSequence: string
49
57
  blastDatabase: string
50
58
  blastProgram: string
59
+ transcriptId?: string
51
60
  }) {
52
61
  const db = await getDB()
53
- const id = createCacheKey(proteinSequence, blastDatabase, blastProgram)
62
+ const id = createCacheKey(
63
+ proteinSequence,
64
+ blastDatabase,
65
+ blastProgram,
66
+ transcriptId,
67
+ )
54
68
  return db.get(STORE_NAME, id)
55
69
  }
56
70
 
@@ -65,6 +79,8 @@ export async function saveBlastResult({
65
79
  rid,
66
80
  geneId,
67
81
  transcriptId,
82
+ transcriptName,
83
+ geneName,
68
84
  }: {
69
85
  proteinSequence: string
70
86
  blastDatabase: string
@@ -76,9 +92,16 @@ export async function saveBlastResult({
76
92
  rid: string
77
93
  geneId?: string
78
94
  transcriptId?: string
95
+ transcriptName?: string
96
+ geneName?: string
79
97
  }) {
80
98
  const db = await getDB()
81
- const id = createCacheKey(proteinSequence, blastDatabase, blastProgram)
99
+ const id = createCacheKey(
100
+ proteinSequence,
101
+ blastDatabase,
102
+ blastProgram,
103
+ transcriptId,
104
+ )
82
105
  const entry: CachedBlastResult = {
83
106
  id,
84
107
  proteinSequence,
@@ -92,6 +115,8 @@ export async function saveBlastResult({
92
115
  timestamp: Date.now(),
93
116
  geneId,
94
117
  transcriptId,
118
+ transcriptName,
119
+ geneName,
95
120
  }
96
121
  await db.put(STORE_NAME, entry)
97
122
  return entry
@@ -103,6 +128,14 @@ export async function getAllCachedResults() {
103
128
  return results.toSorted((a, b) => b.timestamp - a.timestamp)
104
129
  }
105
130
 
131
+ export async function getCachedResultsByGeneId(geneId: string) {
132
+ const db = await getDB()
133
+ const results = await db.getAll(STORE_NAME)
134
+ return results
135
+ .filter(r => r.geneId === geneId)
136
+ .toSorted((a, b) => b.timestamp - a.timestamp)
137
+ }
138
+
106
139
  export async function deleteCachedResult(id: string) {
107
140
  const db = await getDB()
108
141
  await db.delete(STORE_NAME, id)
@@ -1,6 +1,30 @@
1
1
  import { jsonfetch, textfetch, timeout } from './fetch'
2
2
  import { BlastResults } from './types'
3
3
 
4
+ export async function queryBlastFromRid({
5
+ rid,
6
+ baseUrl,
7
+ onProgress,
8
+ }: {
9
+ rid: string
10
+ baseUrl: string
11
+ onProgress: (arg: string) => void
12
+ }) {
13
+ onProgress(`Checking BLAST status for RID: ${rid}...`)
14
+ await waitForRid({
15
+ rid,
16
+ onProgress,
17
+ baseUrl,
18
+ })
19
+ const ret = await jsonfetch<BlastResults>(
20
+ `${baseUrl}?CMD=Get&RID=${rid}&FORMAT_TYPE=JSON2_S&FORMAT_OBJECT=Alignment`,
21
+ )
22
+ return {
23
+ rid,
24
+ hits: ret.BlastOutput2[0]?.report.results.search.hits ?? [],
25
+ }
26
+ }
27
+
4
28
  export async function queryBlast({
5
29
  query,
6
30
  blastDatabase,
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = '2.2.7'
1
+ export const version = '2.2.11'