jbrowse-plugin-msaview 2.5.1 → 2.5.2
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/dist/MsaViewPanel/afterCreateAutoruns.d.ts +15 -1
- package/dist/MsaViewPanel/afterCreateAutoruns.js +52 -26
- package/dist/MsaViewPanel/model.js +3 -1
- package/dist/jbrowse-plugin-msaview.umd.production.min.js +27 -27
- package/dist/jbrowse-plugin-msaview.umd.production.min.js.map +4 -4
- package/dist/utils/ncbiDomains.js +3 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +16 -16
- package/src/MsaViewPanel/afterCreateAutoruns.ts +54 -29
- package/src/MsaViewPanel/model.ts +3 -1
- package/src/utils/domainCache.ts +1 -2
- package/src/utils/ncbiDomains.ts +3 -1
- package/src/version.ts +1 -1
|
@@ -73,7 +73,9 @@ function parseFeature(featureXml) {
|
|
|
73
73
|
: noteName || quals.site_type || 'site';
|
|
74
74
|
const accession = isDomain ? cddId : `${cddId}:${name}`;
|
|
75
75
|
return {
|
|
76
|
-
signature: {
|
|
76
|
+
signature: {
|
|
77
|
+
entry: { name, description: quals.note ?? name, accession },
|
|
78
|
+
},
|
|
77
79
|
locations: [span],
|
|
78
80
|
};
|
|
79
81
|
}
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "2.5.
|
|
1
|
+
export declare const version = "2.5.2";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.5.
|
|
1
|
+
export const version = '2.5.2';
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "2.5.
|
|
2
|
+
"version": "2.5.2",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"name": "jbrowse-plugin-msaview",
|
|
5
5
|
"repository": {
|
|
@@ -21,37 +21,37 @@
|
|
|
21
21
|
"idb": "^8.0.3",
|
|
22
22
|
"pako-esm2": "^2.0.2",
|
|
23
23
|
"react-msaview": "^5.4.1",
|
|
24
|
-
"swr": "^2.4.
|
|
24
|
+
"swr": "^2.4.2"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@emotion/react": "^11.14.0",
|
|
28
28
|
"@eslint/js": "^10.0.1",
|
|
29
29
|
"@fal-works/esbuild-plugin-global-externals": "^2.1.2",
|
|
30
30
|
"@jbrowse/core": "^4.3.0",
|
|
31
|
-
"@jbrowse/mobx-state-tree": "^5.
|
|
31
|
+
"@jbrowse/mobx-state-tree": "^5.11.1",
|
|
32
32
|
"@jbrowse/plugin-linear-genome-view": "^4.3.0",
|
|
33
33
|
"@mui/icons-material": "^7.3.11",
|
|
34
34
|
"@mui/material": "^7.3.11",
|
|
35
35
|
"@mui/system": "^7.3.11",
|
|
36
|
-
"@mui/x-data-grid": "^8.
|
|
37
|
-
"@types/node": "^25.9.
|
|
38
|
-
"@types/react": "^19.2.
|
|
39
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
40
|
-
"@typescript-eslint/parser": "^8.
|
|
41
|
-
"esbuild": "^0.28.
|
|
42
|
-
"eslint": "^10.
|
|
43
|
-
"eslint-plugin-import-x": "^4.
|
|
36
|
+
"@mui/x-data-grid": "^8.29.1",
|
|
37
|
+
"@types/node": "^25.9.4",
|
|
38
|
+
"@types/react": "^19.2.17",
|
|
39
|
+
"@typescript-eslint/eslint-plugin": "^8.62.0",
|
|
40
|
+
"@typescript-eslint/parser": "^8.62.0",
|
|
41
|
+
"esbuild": "^0.28.1",
|
|
42
|
+
"eslint": "^10.5.0",
|
|
43
|
+
"eslint-plugin-import-x": "^4.17.0",
|
|
44
44
|
"eslint-plugin-react": "^7.37.5",
|
|
45
45
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
46
46
|
"eslint-plugin-unicorn": "^64.0.0",
|
|
47
|
-
"mobx": "^6.
|
|
47
|
+
"mobx": "^6.16.1",
|
|
48
48
|
"mobx-react": "^9.2.2",
|
|
49
49
|
"msa-parsers": "5.4.1",
|
|
50
50
|
"pixelmatch": "^7.2.0",
|
|
51
51
|
"pngjs": "^7.0.0",
|
|
52
|
-
"prettier": "^3.8.
|
|
52
|
+
"prettier": "^3.8.4",
|
|
53
53
|
"pretty-bytes": "^7.1.0",
|
|
54
|
-
"puppeteer": "^25.1
|
|
54
|
+
"puppeteer": "^25.2.1",
|
|
55
55
|
"react": "^19.2.7",
|
|
56
56
|
"react-dom": "^19.2.7",
|
|
57
57
|
"rimraf": "^6.1.3",
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"serve": "^14.2.6",
|
|
60
60
|
"tss-react": "^4.9.21",
|
|
61
61
|
"typescript": "^6.0.3",
|
|
62
|
-
"typescript-eslint": "^8.
|
|
63
|
-
"vitest": "^4.1.
|
|
62
|
+
"typescript-eslint": "^8.62.0",
|
|
63
|
+
"vitest": "^4.1.9"
|
|
64
64
|
},
|
|
65
65
|
"scripts": {
|
|
66
66
|
"clean": "rimraf dist",
|
|
@@ -282,46 +282,71 @@ export function autoConnectStructures(self: JBrowsePluginMsaViewModel) {
|
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
/**
|
|
286
|
+
* Mirror a connected 3D protein view's hovered residue onto the MSA's
|
|
287
|
+
* highlighted columns. Returns the autorun body and keeps a flag tracking
|
|
288
|
+
* whether the current highlight was set by THIS sync: when a protein hover ends
|
|
289
|
+
* we restore the declarative highlightColumns seed (or clear) rather than
|
|
290
|
+
* blindly wiping it.
|
|
291
|
+
*
|
|
292
|
+
* Without the flag this autorun fires once on creation — with the view connected
|
|
293
|
+
* to a *genome* LGV but no 3D protein structure attached — computes zero columns,
|
|
294
|
+
* and calls setHighlightedColumns(undefined), clobbering the seed that
|
|
295
|
+
* MSAModelF.afterCreate just set from the declarative `highlightColumns`. That is
|
|
296
|
+
* the bug that made the BRAF/TP53 genome-browser links open with no V600/R248
|
|
297
|
+
* column lit (SRC has no highlightColumns, so nothing was there to wipe).
|
|
298
|
+
*/
|
|
285
299
|
export function observeProteinHighlights(self: JBrowsePluginMsaViewModel) {
|
|
286
|
-
|
|
300
|
+
let proteinDriven = false
|
|
301
|
+
return () => {
|
|
302
|
+
const { connectedViewId, transcriptToMsaMap, querySeqName } = self
|
|
287
303
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
304
|
+
if (!connectedViewId || !transcriptToMsaMap) {
|
|
305
|
+
return
|
|
306
|
+
}
|
|
291
307
|
|
|
292
|
-
|
|
308
|
+
const columns = new Set<number>()
|
|
293
309
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
310
|
+
for (const view of getProteinViews(getSession(self).views)) {
|
|
311
|
+
for (const structure of view.structures) {
|
|
312
|
+
if (structure.connectedViewId !== connectedViewId) {
|
|
313
|
+
continue
|
|
314
|
+
}
|
|
299
315
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
316
|
+
const highlights = structure.hoverGenomeHighlights
|
|
317
|
+
if (!highlights || highlights.length === 0) {
|
|
318
|
+
continue
|
|
319
|
+
}
|
|
304
320
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
321
|
+
const { g2p } = transcriptToMsaMap
|
|
322
|
+
for (const highlight of highlights) {
|
|
323
|
+
for (let coord = highlight.start; coord < highlight.end; coord++) {
|
|
324
|
+
const proteinPos = g2p[coord]
|
|
325
|
+
if (proteinPos !== undefined) {
|
|
326
|
+
const col = self.seqPosToGlobalCol(querySeqName, proteinPos)
|
|
327
|
+
columns.add(col)
|
|
328
|
+
}
|
|
312
329
|
}
|
|
313
330
|
}
|
|
314
331
|
}
|
|
315
332
|
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const visibleColumns = Array.from(columns)
|
|
319
|
-
.map(col => self.globalColToVisibleCol(col))
|
|
320
|
-
.filter((col): col is number => col !== undefined)
|
|
321
333
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
334
|
+
const visibleColumns = Array.from(columns)
|
|
335
|
+
.map(col => self.globalColToVisibleCol(col))
|
|
336
|
+
.filter((col): col is number => col !== undefined)
|
|
337
|
+
|
|
338
|
+
if (visibleColumns.length > 0) {
|
|
339
|
+
self.setHighlightedColumns(visibleColumns)
|
|
340
|
+
proteinDriven = true
|
|
341
|
+
} else if (proteinDriven) {
|
|
342
|
+
// our protein-hover highlight ended — fall back to the declarative seed
|
|
343
|
+
// instead of wiping a column the URL/user asked to keep lit
|
|
344
|
+
self.setHighlightedColumns(
|
|
345
|
+
self.highlightColumns?.length ? self.highlightColumns : undefined,
|
|
346
|
+
)
|
|
347
|
+
proteinDriven = false
|
|
348
|
+
}
|
|
349
|
+
}
|
|
325
350
|
}
|
|
326
351
|
|
|
327
352
|
export function runCleanup() {
|
|
@@ -471,7 +471,6 @@ export default function stateModelFactory() {
|
|
|
471
471
|
highlightConnectedStructures,
|
|
472
472
|
autoConnectStructures,
|
|
473
473
|
autoLoadProteinDomains,
|
|
474
|
-
observeProteinHighlights,
|
|
475
474
|
]) {
|
|
476
475
|
addDisposer(
|
|
477
476
|
self,
|
|
@@ -480,7 +479,10 @@ export default function stateModelFactory() {
|
|
|
480
479
|
}),
|
|
481
480
|
)
|
|
482
481
|
}
|
|
482
|
+
// these two keep per-reaction state across runs (a "did I set it?" flag),
|
|
483
|
+
// so they're factories returning the autorun body rather than plain fns
|
|
483
484
|
addDisposer(self, autorun(syncGenomeHoverToMsaColumn(self)))
|
|
485
|
+
addDisposer(self, autorun(observeProteinHighlights(self)))
|
|
484
486
|
},
|
|
485
487
|
}))
|
|
486
488
|
}
|
package/src/utils/domainCache.ts
CHANGED
|
@@ -26,8 +26,7 @@ export async function getCachedDomains(accessions: string[]) {
|
|
|
26
26
|
const tx = db.transaction(STORE_NAME, 'readonly')
|
|
27
27
|
const results = await Promise.all(
|
|
28
28
|
accessions.map(
|
|
29
|
-
accession =>
|
|
30
|
-
tx.store.get(accession) as Promise<CachedDomain | undefined>,
|
|
29
|
+
accession => tx.store.get(accession) as Promise<CachedDomain | undefined>,
|
|
31
30
|
),
|
|
32
31
|
)
|
|
33
32
|
await tx.done
|
package/src/utils/ncbiDomains.ts
CHANGED
|
@@ -83,7 +83,9 @@ function parseFeature(featureXml: string): DomainMatch | undefined {
|
|
|
83
83
|
: noteName || quals.site_type || 'site'
|
|
84
84
|
const accession = isDomain ? cddId : `${cddId}:${name}`
|
|
85
85
|
return {
|
|
86
|
-
signature: {
|
|
86
|
+
signature: {
|
|
87
|
+
entry: { name, description: quals.note ?? name, accession },
|
|
88
|
+
},
|
|
87
89
|
locations: [span],
|
|
88
90
|
}
|
|
89
91
|
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '2.5.
|
|
1
|
+
export const version = '2.5.2'
|