@jbrowse/plugin-variants 2.0.0 → 2.1.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/ChordVariantDisplay/index.js +9 -9
- package/dist/ChordVariantDisplay/index.js.map +1 -1
- package/dist/ChordVariantDisplay/models/ChordVariantDisplay.js +23 -25
- package/dist/ChordVariantDisplay/models/ChordVariantDisplay.js.map +1 -1
- package/dist/LinearVariantDisplay/configSchema.js +3 -3
- package/dist/LinearVariantDisplay/configSchema.js.map +1 -1
- package/dist/LinearVariantDisplay/index.d.ts +3 -2
- package/dist/LinearVariantDisplay/index.js +17 -5
- package/dist/LinearVariantDisplay/index.js.map +1 -1
- package/dist/LinearVariantDisplay/model.js +24 -72
- package/dist/LinearVariantDisplay/model.js.map +1 -1
- package/dist/StructuralVariantChordRenderer/ReactComponent.js +57 -103
- package/dist/StructuralVariantChordRenderer/ReactComponent.js.map +1 -1
- package/dist/StructuralVariantChordRenderer/index.js +7 -7
- package/dist/StructuralVariantChordRenderer/index.js.map +1 -1
- package/dist/VariantFeatureWidget/AnnotGrid.d.ts +5 -0
- package/dist/VariantFeatureWidget/AnnotGrid.js +22 -0
- package/dist/VariantFeatureWidget/AnnotGrid.js.map +1 -0
- package/dist/VariantFeatureWidget/BreakendOptionDialog.js +23 -40
- package/dist/VariantFeatureWidget/BreakendOptionDialog.js.map +1 -1
- package/dist/VariantFeatureWidget/BreakendPanel.d.ts +7 -0
- package/dist/VariantFeatureWidget/BreakendPanel.js +82 -0
- package/dist/VariantFeatureWidget/BreakendPanel.js.map +1 -0
- package/dist/VariantFeatureWidget/VariantAnnPanel.d.ts +5 -0
- package/dist/VariantFeatureWidget/VariantAnnPanel.js +25 -0
- package/dist/VariantFeatureWidget/VariantAnnPanel.js.map +1 -0
- package/dist/VariantFeatureWidget/VariantCsqPanel.d.ts +5 -0
- package/dist/VariantFeatureWidget/VariantCsqPanel.js +25 -0
- package/dist/VariantFeatureWidget/VariantCsqPanel.js.map +1 -0
- package/dist/VariantFeatureWidget/VariantFeatureWidget.js +23 -184
- package/dist/VariantFeatureWidget/VariantFeatureWidget.js.map +1 -1
- package/dist/VariantFeatureWidget/VariantSampleGrid.d.ts +2 -0
- package/dist/VariantFeatureWidget/VariantSampleGrid.js +83 -0
- package/dist/VariantFeatureWidget/VariantSampleGrid.js.map +1 -0
- package/dist/VariantFeatureWidget/index.d.ts +2 -0
- package/dist/VariantFeatureWidget/index.js +41 -4
- package/dist/VariantFeatureWidget/index.js.map +1 -1
- package/dist/VariantTrack/index.d.ts +3 -0
- package/dist/VariantTrack/index.js +19 -0
- package/dist/VariantTrack/index.js.map +1 -0
- package/dist/VcfAdapter/VcfAdapter.js +85 -221
- package/dist/VcfAdapter/VcfAdapter.js.map +1 -1
- package/dist/VcfAdapter/configSchema.js +1 -1
- package/dist/VcfAdapter/configSchema.js.map +1 -1
- package/dist/VcfAdapter/index.d.ts +3 -1
- package/dist/VcfAdapter/index.js +32 -3
- package/dist/VcfAdapter/index.js.map +1 -1
- package/dist/VcfTabixAdapter/VcfFeature.js +76 -107
- package/dist/VcfTabixAdapter/VcfFeature.js.map +1 -1
- package/dist/VcfTabixAdapter/VcfTabixAdapter.js +88 -231
- package/dist/VcfTabixAdapter/VcfTabixAdapter.js.map +1 -1
- package/dist/VcfTabixAdapter/configSchema.js +2 -2
- package/dist/VcfTabixAdapter/configSchema.js.map +1 -1
- package/dist/VcfTabixAdapter/index.d.ts +3 -0
- package/dist/VcfTabixAdapter/index.js +34 -2
- package/dist/VcfTabixAdapter/index.js.map +1 -1
- package/dist/extensionPoints.d.ts +3 -0
- package/dist/extensionPoints.js +51 -0
- package/dist/extensionPoints.js.map +1 -0
- package/dist/index.js +24 -162
- package/dist/index.js.map +1 -1
- package/esm/LinearVariantDisplay/index.d.ts +3 -2
- package/esm/LinearVariantDisplay/index.js +17 -2
- package/esm/LinearVariantDisplay/index.js.map +1 -1
- package/esm/VariantFeatureWidget/AnnotGrid.d.ts +5 -0
- package/esm/VariantFeatureWidget/AnnotGrid.js +16 -0
- package/esm/VariantFeatureWidget/AnnotGrid.js.map +1 -0
- package/esm/VariantFeatureWidget/BreakendPanel.d.ts +7 -0
- package/esm/VariantFeatureWidget/BreakendPanel.js +53 -0
- package/esm/VariantFeatureWidget/BreakendPanel.js.map +1 -0
- package/esm/VariantFeatureWidget/VariantAnnPanel.d.ts +5 -0
- package/esm/VariantFeatureWidget/VariantAnnPanel.js +19 -0
- package/esm/VariantFeatureWidget/VariantAnnPanel.js.map +1 -0
- package/esm/VariantFeatureWidget/VariantCsqPanel.d.ts +5 -0
- package/esm/VariantFeatureWidget/VariantCsqPanel.js +19 -0
- package/esm/VariantFeatureWidget/VariantCsqPanel.js.map +1 -0
- package/esm/VariantFeatureWidget/VariantFeatureWidget.js +13 -104
- package/esm/VariantFeatureWidget/VariantFeatureWidget.js.map +1 -1
- package/esm/VariantFeatureWidget/VariantSampleGrid.d.ts +2 -0
- package/esm/VariantFeatureWidget/VariantSampleGrid.js +57 -0
- package/esm/VariantFeatureWidget/VariantSampleGrid.js.map +1 -0
- package/esm/VariantFeatureWidget/index.d.ts +2 -0
- package/esm/VariantFeatureWidget/index.js +11 -0
- package/esm/VariantFeatureWidget/index.js.map +1 -1
- package/esm/VariantTrack/index.d.ts +3 -0
- package/esm/VariantTrack/index.js +14 -0
- package/esm/VariantTrack/index.js.map +1 -0
- package/esm/VcfAdapter/VcfAdapter.js +9 -7
- package/esm/VcfAdapter/VcfAdapter.js.map +1 -1
- package/esm/VcfAdapter/index.d.ts +3 -1
- package/esm/VcfAdapter/index.js +9 -1
- package/esm/VcfAdapter/index.js.map +1 -1
- package/esm/VcfTabixAdapter/VcfFeature.js +1 -1
- package/esm/VcfTabixAdapter/VcfFeature.js.map +1 -1
- package/esm/VcfTabixAdapter/VcfTabixAdapter.js +1 -7
- package/esm/VcfTabixAdapter/VcfTabixAdapter.js.map +1 -1
- package/esm/VcfTabixAdapter/index.d.ts +3 -0
- package/esm/VcfTabixAdapter/index.js +9 -0
- package/esm/VcfTabixAdapter/index.js.map +1 -1
- package/esm/extensionPoints.d.ts +3 -0
- package/esm/extensionPoints.js +49 -0
- package/esm/extensionPoints.js.map +1 -0
- package/esm/index.js +12 -95
- package/esm/index.js.map +1 -1
- package/package.json +7 -8
- package/src/LinearVariantDisplay/index.ts +19 -2
- package/src/VariantFeatureWidget/AnnotGrid.tsx +28 -0
- package/src/VariantFeatureWidget/BreakendPanel.tsx +94 -0
- package/src/VariantFeatureWidget/VariantAnnPanel.tsx +31 -0
- package/src/VariantFeatureWidget/VariantCsqPanel.tsx +31 -0
- package/src/VariantFeatureWidget/VariantFeatureWidget.tsx +13 -198
- package/src/VariantFeatureWidget/VariantSampleGrid.tsx +105 -0
- package/src/VariantFeatureWidget/__snapshots__/VariantFeatureWidget.test.js.snap +6 -0
- package/src/VariantFeatureWidget/index.ts +15 -0
- package/src/VariantTrack/index.ts +26 -0
- package/src/VcfAdapter/VcfAdapter.ts +15 -16
- package/src/VcfAdapter/index.ts +14 -1
- package/src/VcfTabixAdapter/VcfFeature.ts +1 -1
- package/src/VcfTabixAdapter/VcfTabixAdapter.ts +1 -7
- package/src/VcfTabixAdapter/index.ts +15 -0
- package/src/__snapshots__/index.test.js.snap +4 -4
- package/src/extensionPoints.ts +74 -0
- package/src/index.ts +12 -155
package/esm/index.js
CHANGED
|
@@ -1,109 +1,26 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { createBaseTrackConfig, createBaseTrackModel, } from '@jbrowse/core/pluggableElementTypes/models';
|
|
6
|
-
import TrackType from '@jbrowse/core/pluggableElementTypes/TrackType';
|
|
7
|
-
import WidgetType from '@jbrowse/core/pluggableElementTypes/WidgetType';
|
|
1
|
+
import VcfAdapterF from './VcfAdapter';
|
|
2
|
+
import VcfTabixAdapterF from './VcfTabixAdapter';
|
|
3
|
+
import ExtensionPointsF from './extensionPoints';
|
|
4
|
+
import VariantTrackF from './VariantTrack';
|
|
8
5
|
import Plugin from '@jbrowse/core/Plugin';
|
|
9
|
-
import { BaseLinearDisplayComponent } from '@jbrowse/plugin-linear-genome-view';
|
|
10
6
|
import ChordVariantDisplay from './ChordVariantDisplay';
|
|
11
|
-
import
|
|
7
|
+
import LinearVariantDisplayF from './LinearVariantDisplay';
|
|
12
8
|
import StructuralVariantChordRendererFactory from './StructuralVariantChordRenderer';
|
|
13
|
-
import
|
|
14
|
-
import { configSchema as vcfTabixAdapterConfigSchema } from './VcfTabixAdapter';
|
|
15
|
-
import { configSchema as vcfAdapterConfigSchema } from './VcfAdapter';
|
|
16
|
-
import { makeIndex, makeIndexType, getFileName, } from '@jbrowse/core/util/tracks';
|
|
9
|
+
import VariantFeatureWidgetF from './VariantFeatureWidget';
|
|
17
10
|
export default class VariantsPlugin extends Plugin {
|
|
18
11
|
constructor() {
|
|
19
12
|
super(...arguments);
|
|
20
13
|
this.name = 'VariantsPlugin';
|
|
21
14
|
}
|
|
22
15
|
install(pluginManager) {
|
|
23
|
-
pluginManager
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
pluginManager
|
|
29
|
-
return (file, index, adapterHint) => {
|
|
30
|
-
const regexGuess = /\.vcf\.b?gz$/i;
|
|
31
|
-
const adapterName = 'VcfTabixAdapter';
|
|
32
|
-
const fileName = getFileName(file);
|
|
33
|
-
const indexName = index && getFileName(index);
|
|
34
|
-
const obj = {
|
|
35
|
-
type: adapterName,
|
|
36
|
-
vcfGzLocation: file,
|
|
37
|
-
index: {
|
|
38
|
-
location: index || makeIndex(file, '.tbi'),
|
|
39
|
-
indexType: makeIndexType(indexName, 'CSI', 'TBI'),
|
|
40
|
-
},
|
|
41
|
-
};
|
|
42
|
-
if (regexGuess.test(fileName) && !adapterHint) {
|
|
43
|
-
return obj;
|
|
44
|
-
}
|
|
45
|
-
else if (adapterHint === adapterName) {
|
|
46
|
-
return obj;
|
|
47
|
-
}
|
|
48
|
-
return adapterGuesser(file, index, adapterHint);
|
|
49
|
-
};
|
|
50
|
-
});
|
|
51
|
-
pluginManager.addToExtensionPoint('Core-guessTrackTypeForLocation', (trackTypeGuesser) => {
|
|
52
|
-
return (adapterName) => {
|
|
53
|
-
if (adapterName === 'VcfTabixAdapter' ||
|
|
54
|
-
adapterName === 'VcfAdapter') {
|
|
55
|
-
return 'VariantTrack';
|
|
56
|
-
}
|
|
57
|
-
return trackTypeGuesser(adapterName);
|
|
58
|
-
};
|
|
59
|
-
});
|
|
60
|
-
pluginManager.addAdapterType(() => new AdapterType({
|
|
61
|
-
name: 'VcfAdapter',
|
|
62
|
-
configSchema: vcfAdapterConfigSchema,
|
|
63
|
-
getAdapterClass: () => import('./VcfAdapter/VcfAdapter').then(r => r.default),
|
|
64
|
-
}));
|
|
65
|
-
pluginManager.addToExtensionPoint('Core-guessAdapterForLocation', (adapterGuesser) => {
|
|
66
|
-
return (file, index, adapterHint) => {
|
|
67
|
-
const regexGuess = /\.vcf$/i;
|
|
68
|
-
const adapterName = 'VcfAdapter';
|
|
69
|
-
const fileName = getFileName(file);
|
|
70
|
-
if (regexGuess.test(fileName) || adapterHint === adapterName) {
|
|
71
|
-
return {
|
|
72
|
-
type: adapterName,
|
|
73
|
-
vcfLocation: file,
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
return adapterGuesser(file, index, adapterHint);
|
|
77
|
-
};
|
|
78
|
-
});
|
|
16
|
+
VcfAdapterF(pluginManager);
|
|
17
|
+
VcfTabixAdapterF(pluginManager);
|
|
18
|
+
VariantFeatureWidgetF(pluginManager);
|
|
19
|
+
VariantTrackF(pluginManager);
|
|
20
|
+
ExtensionPointsF(pluginManager);
|
|
21
|
+
LinearVariantDisplayF(pluginManager);
|
|
79
22
|
pluginManager.addRendererType(() => pluginManager.jbrequire(StructuralVariantChordRendererFactory));
|
|
80
|
-
pluginManager.addTrackType(() => {
|
|
81
|
-
const configSchema = ConfigurationSchema('VariantTrack', {}, { baseConfiguration: createBaseTrackConfig(pluginManager) });
|
|
82
|
-
return new TrackType({
|
|
83
|
-
name: 'VariantTrack',
|
|
84
|
-
configSchema,
|
|
85
|
-
stateModel: createBaseTrackModel(pluginManager, 'VariantTrack', configSchema),
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
23
|
pluginManager.addDisplayType(() => pluginManager.jbrequire(ChordVariantDisplay));
|
|
89
|
-
pluginManager.addDisplayType(() => {
|
|
90
|
-
const configSchema = linearVariantDisplayConfigSchemaFactory(pluginManager);
|
|
91
|
-
return new DisplayType({
|
|
92
|
-
name: 'LinearVariantDisplay',
|
|
93
|
-
configSchema,
|
|
94
|
-
stateModel: linearVariantDisplayModelFactory(configSchema),
|
|
95
|
-
trackType: 'VariantTrack',
|
|
96
|
-
viewType: 'LinearGenomeView',
|
|
97
|
-
ReactComponent: BaseLinearDisplayComponent,
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
pluginManager.addWidgetType(() => new WidgetType({
|
|
101
|
-
name: 'VariantFeatureWidget',
|
|
102
|
-
heading: 'Feature details',
|
|
103
|
-
configSchema: variantFeatureWidgetConfigSchema,
|
|
104
|
-
stateModel: variantFeatureWidgetStateModelFactory(pluginManager),
|
|
105
|
-
ReactComponent: lazy(() => import('./VariantFeatureWidget/VariantFeatureWidget')),
|
|
106
|
-
}));
|
|
107
24
|
}
|
|
108
25
|
}
|
|
109
26
|
export { default as VcfFeature } from './VcfTabixAdapter/VcfFeature';
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,cAAc,CAAA;AACtC,OAAO,gBAAgB,MAAM,mBAAmB,CAAA;AAChD,OAAO,gBAAgB,MAAM,mBAAmB,CAAA;AAChD,OAAO,aAAa,MAAM,gBAAgB,CAAA;AAC1C,OAAO,MAAM,MAAM,sBAAsB,CAAA;AAEzC,OAAO,mBAAmB,MAAM,uBAAuB,CAAA;AACvD,OAAO,qBAAqB,MAAM,wBAAwB,CAAA;AAC1D,OAAO,qCAAqC,MAAM,kCAAkC,CAAA;AACpF,OAAO,qBAAqB,MAAM,wBAAwB,CAAA;AAE1D,MAAM,CAAC,OAAO,OAAO,cAAe,SAAQ,MAAM;IAAlD;;QACE,SAAI,GAAG,gBAAgB,CAAA;IAkBzB,CAAC;IAhBC,OAAO,CAAC,aAA4B;QAClC,WAAW,CAAC,aAAa,CAAC,CAAA;QAC1B,gBAAgB,CAAC,aAAa,CAAC,CAAA;QAC/B,qBAAqB,CAAC,aAAa,CAAC,CAAA;QACpC,aAAa,CAAC,aAAa,CAAC,CAAA;QAC5B,gBAAgB,CAAC,aAAa,CAAC,CAAA;QAC/B,qBAAqB,CAAC,aAAa,CAAC,CAAA;QAEpC,aAAa,CAAC,eAAe,CAAC,GAAG,EAAE,CACjC,aAAa,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAC/D,CAAA;QAED,aAAa,CAAC,cAAc,CAAC,GAAG,EAAE,CAChC,aAAa,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAC7C,CAAA;IACH,CAAC;CACF;AAED,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,8BAA8B,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jbrowse/plugin-variants",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.2",
|
|
4
4
|
"description": "JBrowse 2 variant adapters, tracks, etc.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"jbrowse",
|
|
@@ -37,20 +37,19 @@
|
|
|
37
37
|
"clean": "rimraf dist esm *.tsbuildinfo"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@babel/runtime": "^7.17.9",
|
|
41
40
|
"@flatten-js/interval-tree": "^1.0.15",
|
|
42
41
|
"@gmod/bgzf-filehandle": "^1.4.3",
|
|
43
42
|
"@gmod/tabix": "^1.5.2",
|
|
44
43
|
"@gmod/vcf": "^5.0.5",
|
|
45
44
|
"@mui/icons-material": "^5.0.2",
|
|
46
45
|
"@mui/x-data-grid": "^5.0.1",
|
|
47
|
-
"generic-filehandle": "^
|
|
46
|
+
"generic-filehandle": "^3.0.0"
|
|
48
47
|
},
|
|
49
48
|
"peerDependencies": {
|
|
50
|
-
"@jbrowse/core": "^
|
|
51
|
-
"@jbrowse/plugin-alignments": "^
|
|
52
|
-
"@jbrowse/plugin-circular-view": "^
|
|
53
|
-
"@jbrowse/plugin-linear-genome-view": "^
|
|
49
|
+
"@jbrowse/core": "^2.0.0",
|
|
50
|
+
"@jbrowse/plugin-alignments": "^2.0.0",
|
|
51
|
+
"@jbrowse/plugin-circular-view": "^2.0.0",
|
|
52
|
+
"@jbrowse/plugin-linear-genome-view": "^2.0.0",
|
|
54
53
|
"@mui/material": "^5.0.0",
|
|
55
54
|
"mobx": "^6.0.0",
|
|
56
55
|
"mobx-react": "^7.0.0",
|
|
@@ -66,5 +65,5 @@
|
|
|
66
65
|
"distModule": "esm/index.js",
|
|
67
66
|
"srcModule": "src/index.ts",
|
|
68
67
|
"module": "esm/index.js",
|
|
69
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "449b17325c9a4a97181f7ddddf48e80219f03b8d"
|
|
70
69
|
}
|
|
@@ -1,2 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import PluginManager from '@jbrowse/core/PluginManager'
|
|
2
|
+
import { LinearVariantDisplayConfigFactory } from './configSchema'
|
|
3
|
+
import { BaseLinearDisplayComponent } from '@jbrowse/plugin-linear-genome-view'
|
|
4
|
+
import DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType'
|
|
5
|
+
import stateModelFactory from './model'
|
|
6
|
+
|
|
7
|
+
export default (pluginManager: PluginManager) => {
|
|
8
|
+
pluginManager.addDisplayType(() => {
|
|
9
|
+
const configSchema = LinearVariantDisplayConfigFactory(pluginManager)
|
|
10
|
+
return new DisplayType({
|
|
11
|
+
name: 'LinearVariantDisplay',
|
|
12
|
+
configSchema,
|
|
13
|
+
stateModel: stateModelFactory(configSchema),
|
|
14
|
+
trackType: 'VariantTrack',
|
|
15
|
+
viewType: 'LinearGenomeView',
|
|
16
|
+
ReactComponent: BaseLinearDisplayComponent,
|
|
17
|
+
})
|
|
18
|
+
})
|
|
19
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { DataGrid } from '@mui/x-data-grid'
|
|
4
|
+
|
|
5
|
+
export default function VariantAnnotPanel({
|
|
6
|
+
rows,
|
|
7
|
+
columns,
|
|
8
|
+
}: {
|
|
9
|
+
rows: any
|
|
10
|
+
columns: any[]
|
|
11
|
+
}) {
|
|
12
|
+
const rowHeight = 25
|
|
13
|
+
const hideFooter = rows.length < 100
|
|
14
|
+
const headerHeight = 80
|
|
15
|
+
return rows.length ? (
|
|
16
|
+
<div
|
|
17
|
+
style={{
|
|
18
|
+
height:
|
|
19
|
+
Math.min(rows.length, 100) * rowHeight +
|
|
20
|
+
headerHeight +
|
|
21
|
+
(hideFooter ? 0 : 50),
|
|
22
|
+
width: '100%',
|
|
23
|
+
}}
|
|
24
|
+
>
|
|
25
|
+
<DataGrid rowHeight={rowHeight} rows={rows} columns={columns} />
|
|
26
|
+
</div>
|
|
27
|
+
) : null
|
|
28
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React, { useState } from 'react'
|
|
3
|
+
import { Link, Typography } from '@mui/material'
|
|
4
|
+
import SimpleFeature, {
|
|
5
|
+
SimpleFeatureSerialized,
|
|
6
|
+
} from '@jbrowse/core/util/simpleFeature'
|
|
7
|
+
import { getSession } from '@jbrowse/core/util'
|
|
8
|
+
import { getEnv } from 'mobx-state-tree'
|
|
9
|
+
import { BaseCard } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
|
|
10
|
+
import BreakendOptionDialog from './BreakendOptionDialog'
|
|
11
|
+
|
|
12
|
+
export default function BreakendPanel(props: {
|
|
13
|
+
locStrings: string[]
|
|
14
|
+
model: any
|
|
15
|
+
feature: SimpleFeatureSerialized
|
|
16
|
+
}) {
|
|
17
|
+
const { model, locStrings, feature } = props
|
|
18
|
+
const session = getSession(model)
|
|
19
|
+
const { pluginManager } = getEnv(session)
|
|
20
|
+
const [breakpointDialog, setBreakpointDialog] = useState(false)
|
|
21
|
+
let viewType
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
viewType = pluginManager.getViewType('BreakpointSplitView')
|
|
25
|
+
} catch (e) {
|
|
26
|
+
// ignore
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const simpleFeature = new SimpleFeature(feature)
|
|
30
|
+
return (
|
|
31
|
+
<BaseCard {...props} title="Breakends">
|
|
32
|
+
<Typography>Link to linear view of breakend endpoints</Typography>
|
|
33
|
+
<ul>
|
|
34
|
+
{locStrings.map(locString => (
|
|
35
|
+
<li key={`${JSON.stringify(locString)}`}>
|
|
36
|
+
<Link
|
|
37
|
+
href="#"
|
|
38
|
+
onClick={event => {
|
|
39
|
+
event.preventDefault()
|
|
40
|
+
const { view } = model
|
|
41
|
+
try {
|
|
42
|
+
if (view) {
|
|
43
|
+
view.navToLocString?.(locString)
|
|
44
|
+
} else {
|
|
45
|
+
throw new Error(
|
|
46
|
+
'No view associated with this feature detail panel anymore',
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
} catch (e) {
|
|
50
|
+
console.error(e)
|
|
51
|
+
session.notify(`${e}`)
|
|
52
|
+
}
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
{`LGV - ${locString}`}
|
|
56
|
+
</Link>
|
|
57
|
+
</li>
|
|
58
|
+
))}
|
|
59
|
+
</ul>
|
|
60
|
+
{viewType ? (
|
|
61
|
+
<div>
|
|
62
|
+
<Typography>
|
|
63
|
+
Launch split views with breakend source and target
|
|
64
|
+
</Typography>
|
|
65
|
+
<ul>
|
|
66
|
+
{locStrings.map(locString => (
|
|
67
|
+
<li key={`${JSON.stringify(locString)}`}>
|
|
68
|
+
<Link
|
|
69
|
+
href="#"
|
|
70
|
+
onClick={event => {
|
|
71
|
+
event.preventDefault()
|
|
72
|
+
setBreakpointDialog(true)
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
{`${feature.refName}:${feature.start} // ${locString} (split view)`}
|
|
76
|
+
</Link>
|
|
77
|
+
</li>
|
|
78
|
+
))}
|
|
79
|
+
</ul>
|
|
80
|
+
{breakpointDialog ? (
|
|
81
|
+
<BreakendOptionDialog
|
|
82
|
+
model={model}
|
|
83
|
+
feature={simpleFeature}
|
|
84
|
+
viewType={viewType}
|
|
85
|
+
handleClose={() => {
|
|
86
|
+
setBreakpointDialog(false)
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
) : null}
|
|
90
|
+
</div>
|
|
91
|
+
) : null}
|
|
92
|
+
</BaseCard>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { BaseCard } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
|
|
4
|
+
import AnnotGrid from './AnnotGrid'
|
|
5
|
+
|
|
6
|
+
export default function VariantAnnPanel({
|
|
7
|
+
feature,
|
|
8
|
+
descriptions,
|
|
9
|
+
}: {
|
|
10
|
+
feature: any
|
|
11
|
+
descriptions: any
|
|
12
|
+
}) {
|
|
13
|
+
const annFields = (descriptions?.INFO?.ANN?.Description?.match(
|
|
14
|
+
/.*Functional annotations:'(.*)'$/,
|
|
15
|
+
)?.[1].split('|') || []) as string[]
|
|
16
|
+
const ann = (feature.INFO.ANN || []) as string[]
|
|
17
|
+
|
|
18
|
+
const rows =
|
|
19
|
+
ann.map((elt, id) => ({
|
|
20
|
+
id,
|
|
21
|
+
...Object.fromEntries(elt.split('|').map((e, i) => [annFields[i], e])),
|
|
22
|
+
})) || []
|
|
23
|
+
const columns = annFields.map(c => ({
|
|
24
|
+
field: c,
|
|
25
|
+
}))
|
|
26
|
+
return ann.length ? (
|
|
27
|
+
<BaseCard title="ANN table">
|
|
28
|
+
<AnnotGrid rows={rows} columns={columns} />
|
|
29
|
+
</BaseCard>
|
|
30
|
+
) : null
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { BaseCard } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
|
|
4
|
+
import AnnotGrid from './AnnotGrid'
|
|
5
|
+
|
|
6
|
+
export default function VariantCsqPanel({
|
|
7
|
+
feature,
|
|
8
|
+
descriptions,
|
|
9
|
+
}: {
|
|
10
|
+
feature: any
|
|
11
|
+
descriptions: any
|
|
12
|
+
}) {
|
|
13
|
+
const csqFields = (descriptions?.INFO?.CSQ?.Description?.match(
|
|
14
|
+
/.*Format: (.*)/,
|
|
15
|
+
)?.[1].split('|') || []) as string[]
|
|
16
|
+
|
|
17
|
+
const csq = (feature.INFO.CSQ || []) as string[]
|
|
18
|
+
const rows =
|
|
19
|
+
csq.map((elt, id) => ({
|
|
20
|
+
id,
|
|
21
|
+
...Object.fromEntries(elt.split('|').map((e, i) => [csqFields[i], e])),
|
|
22
|
+
})) || []
|
|
23
|
+
const columns = csqFields.map(c => ({
|
|
24
|
+
field: c,
|
|
25
|
+
}))
|
|
26
|
+
return csq.length ? (
|
|
27
|
+
<BaseCard title="CSQ table">
|
|
28
|
+
<AnnotGrid rows={rows} columns={columns} />
|
|
29
|
+
</BaseCard>
|
|
30
|
+
) : null
|
|
31
|
+
}
|
|
@@ -1,204 +1,15 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import React
|
|
3
|
-
import {
|
|
4
|
-
Divider,
|
|
5
|
-
Link,
|
|
6
|
-
Paper,
|
|
7
|
-
FormControlLabel,
|
|
8
|
-
Checkbox,
|
|
9
|
-
TextField,
|
|
10
|
-
Typography,
|
|
11
|
-
} from '@mui/material'
|
|
12
|
-
import SimpleFeature, {
|
|
13
|
-
SimpleFeatureSerialized,
|
|
14
|
-
} from '@jbrowse/core/util/simpleFeature'
|
|
15
|
-
import { DataGrid } from '@mui/x-data-grid'
|
|
2
|
+
import React from 'react'
|
|
16
3
|
import { observer } from 'mobx-react'
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
FeatureDetails,
|
|
21
|
-
BaseCard,
|
|
22
|
-
} from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
|
|
23
|
-
import BreakendOptionDialog from './BreakendOptionDialog'
|
|
4
|
+
import { Divider, Paper } from '@mui/material'
|
|
5
|
+
import { FeatureDetails } from '@jbrowse/core/BaseFeatureWidget/BaseFeatureDetail'
|
|
24
6
|
import { parseBreakend } from '@gmod/vcf'
|
|
25
7
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const { samples = {} } = feature
|
|
32
|
-
const preFilteredRows: any = Object.entries(samples)
|
|
33
|
-
if (!preFilteredRows.length) {
|
|
34
|
-
return null
|
|
35
|
-
}
|
|
36
|
-
const infoFields = ['sample', ...Object.keys(preFilteredRows[0][1])].map(
|
|
37
|
-
field => ({
|
|
38
|
-
field,
|
|
39
|
-
}),
|
|
40
|
-
)
|
|
41
|
-
let error
|
|
42
|
-
let rows = []
|
|
43
|
-
const filters = Object.keys(filter)
|
|
44
|
-
|
|
45
|
-
// catch some error thrown from regex
|
|
46
|
-
// note: maps all values into a string, if this is not done rows are not
|
|
47
|
-
// sortable by the data-grid
|
|
48
|
-
try {
|
|
49
|
-
rows = preFilteredRows
|
|
50
|
-
.map((row: any) => ({
|
|
51
|
-
...Object.fromEntries(
|
|
52
|
-
Object.entries(row[1]).map(entry => [entry[0], String(entry[1])]),
|
|
53
|
-
),
|
|
54
|
-
sample: row[0],
|
|
55
|
-
id: row[0],
|
|
56
|
-
}))
|
|
57
|
-
.filter((row: any) => {
|
|
58
|
-
return filters.length
|
|
59
|
-
? filters.every(key => {
|
|
60
|
-
const val = row[key]
|
|
61
|
-
const currFilter = filter[key]
|
|
62
|
-
return currFilter ? val.match(new RegExp(currFilter, 'i')) : true
|
|
63
|
-
})
|
|
64
|
-
: true
|
|
65
|
-
})
|
|
66
|
-
} catch (e) {
|
|
67
|
-
error = e
|
|
68
|
-
}
|
|
69
|
-
// disableSelectionOnClick helps avoid
|
|
70
|
-
// https://github.com/mui-org/material-ui-x/issues/1197
|
|
71
|
-
return (
|
|
72
|
-
<BaseCard {...props} title="Samples">
|
|
73
|
-
{error ? <Typography color="error">{`${error}`}</Typography> : null}
|
|
74
|
-
|
|
75
|
-
<FormControlLabel
|
|
76
|
-
control={
|
|
77
|
-
<Checkbox
|
|
78
|
-
checked={showFilters}
|
|
79
|
-
onChange={() => setShowFilters(f => !f)}
|
|
80
|
-
/>
|
|
81
|
-
}
|
|
82
|
-
label="Show sample filters"
|
|
83
|
-
/>
|
|
84
|
-
{showFilters ? (
|
|
85
|
-
<>
|
|
86
|
-
<Typography>
|
|
87
|
-
These filters can use a plain text search or regex style query, e.g.
|
|
88
|
-
in the genotype field, entering 1 will query for all genotypes that
|
|
89
|
-
include the first alternate allele e.g. 0|1 or 1|1, entering
|
|
90
|
-
[1-9]\d* will find any non-zero allele e.g. 0|2 or 2/33
|
|
91
|
-
</Typography>
|
|
92
|
-
{infoFields.map(({ field }) => {
|
|
93
|
-
return (
|
|
94
|
-
<TextField
|
|
95
|
-
key={`filter-${field}`}
|
|
96
|
-
placeholder={`Filter ${field}`}
|
|
97
|
-
value={filter[field] || ''}
|
|
98
|
-
onChange={event =>
|
|
99
|
-
setFilter({ ...filter, [field]: event.target.value })
|
|
100
|
-
}
|
|
101
|
-
/>
|
|
102
|
-
)
|
|
103
|
-
})}
|
|
104
|
-
</>
|
|
105
|
-
) : null}
|
|
106
|
-
<div style={{ height: 600, width: '100%', overflow: 'auto' }}>
|
|
107
|
-
<DataGrid
|
|
108
|
-
rows={rows}
|
|
109
|
-
columns={infoFields}
|
|
110
|
-
disableSelectionOnClick
|
|
111
|
-
rowHeight={25}
|
|
112
|
-
disableColumnMenu
|
|
113
|
-
/>
|
|
114
|
-
</div>
|
|
115
|
-
</BaseCard>
|
|
116
|
-
)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function BreakendPanel(props: {
|
|
120
|
-
locStrings: string[]
|
|
121
|
-
model: any
|
|
122
|
-
feature: SimpleFeatureSerialized
|
|
123
|
-
}) {
|
|
124
|
-
const { model, locStrings, feature } = props
|
|
125
|
-
const session = getSession(model)
|
|
126
|
-
const { pluginManager } = getEnv(session)
|
|
127
|
-
const [breakpointDialog, setBreakpointDialog] = useState(false)
|
|
128
|
-
let viewType
|
|
129
|
-
|
|
130
|
-
try {
|
|
131
|
-
viewType = pluginManager.getViewType('BreakpointSplitView')
|
|
132
|
-
} catch (e) {
|
|
133
|
-
// ignore
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const simpleFeature = new SimpleFeature(feature)
|
|
137
|
-
return (
|
|
138
|
-
<BaseCard {...props} title="Breakends">
|
|
139
|
-
<Typography>Link to linear view of breakend endpoints</Typography>
|
|
140
|
-
<ul>
|
|
141
|
-
{locStrings.map(locString => (
|
|
142
|
-
<li key={`${JSON.stringify(locString)}`}>
|
|
143
|
-
<Link
|
|
144
|
-
href="#"
|
|
145
|
-
onClick={event => {
|
|
146
|
-
event.preventDefault()
|
|
147
|
-
const { view } = model
|
|
148
|
-
try {
|
|
149
|
-
if (view) {
|
|
150
|
-
view.navToLocString?.(locString)
|
|
151
|
-
} else {
|
|
152
|
-
throw new Error(
|
|
153
|
-
'No view associated with this feature detail panel anymore',
|
|
154
|
-
)
|
|
155
|
-
}
|
|
156
|
-
} catch (e) {
|
|
157
|
-
console.error(e)
|
|
158
|
-
session.notify(`${e}`)
|
|
159
|
-
}
|
|
160
|
-
}}
|
|
161
|
-
>
|
|
162
|
-
{`LGV - ${locString}`}
|
|
163
|
-
</Link>
|
|
164
|
-
</li>
|
|
165
|
-
))}
|
|
166
|
-
</ul>
|
|
167
|
-
{viewType ? (
|
|
168
|
-
<div>
|
|
169
|
-
<Typography>
|
|
170
|
-
Launch split views with breakend source and target
|
|
171
|
-
</Typography>
|
|
172
|
-
<ul>
|
|
173
|
-
{locStrings.map(locString => (
|
|
174
|
-
<li key={`${JSON.stringify(locString)}`}>
|
|
175
|
-
<Link
|
|
176
|
-
href="#"
|
|
177
|
-
onClick={event => {
|
|
178
|
-
event.preventDefault()
|
|
179
|
-
setBreakpointDialog(true)
|
|
180
|
-
}}
|
|
181
|
-
>
|
|
182
|
-
{`${feature.refName}:${feature.start} // ${locString} (split view)`}
|
|
183
|
-
</Link>
|
|
184
|
-
</li>
|
|
185
|
-
))}
|
|
186
|
-
</ul>
|
|
187
|
-
{breakpointDialog ? (
|
|
188
|
-
<BreakendOptionDialog
|
|
189
|
-
model={model}
|
|
190
|
-
feature={simpleFeature}
|
|
191
|
-
viewType={viewType}
|
|
192
|
-
handleClose={() => {
|
|
193
|
-
setBreakpointDialog(false)
|
|
194
|
-
}}
|
|
195
|
-
/>
|
|
196
|
-
) : null}
|
|
197
|
-
</div>
|
|
198
|
-
) : null}
|
|
199
|
-
</BaseCard>
|
|
200
|
-
)
|
|
201
|
-
}
|
|
8
|
+
// locals
|
|
9
|
+
import VariantSampleGrid from './VariantSampleGrid'
|
|
10
|
+
import VariantCsqPanel from './VariantCsqPanel'
|
|
11
|
+
import VariantAnnPanel from './VariantAnnPanel'
|
|
12
|
+
import BreakendPanel from './BreakendPanel'
|
|
202
13
|
|
|
203
14
|
function VariantFeatureDetails(props: any) {
|
|
204
15
|
const { model } = props
|
|
@@ -224,6 +35,10 @@ function VariantFeatureDetails(props: any) {
|
|
|
224
35
|
{...props}
|
|
225
36
|
/>
|
|
226
37
|
<Divider />
|
|
38
|
+
<VariantCsqPanel feature={rest} descriptions={descriptions} />
|
|
39
|
+
<Divider />
|
|
40
|
+
<VariantAnnPanel feature={rest} descriptions={descriptions} />
|
|
41
|
+
<Divider />
|
|
227
42
|
{feat.type === 'breakend' ? (
|
|
228
43
|
<BreakendPanel
|
|
229
44
|
feature={feat}
|
|
@@ -240,7 +55,7 @@ function VariantFeatureDetails(props: any) {
|
|
|
240
55
|
locStrings={[`${feat.INFO.CHR2[0]}:${feat.INFO.END}`]}
|
|
241
56
|
/>
|
|
242
57
|
) : null}
|
|
243
|
-
<
|
|
58
|
+
<VariantSampleGrid feature={feat} {...props} />
|
|
244
59
|
</Paper>
|
|
245
60
|
)
|
|
246
61
|
}
|