jbrowse-plugin-graphgenomeviewer 1.0.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/README.md +36 -0
- package/dist/GraphGenomeView/components/FeatureDialog.d.ts +5 -0
- package/dist/GraphGenomeView/components/FeatureDialog.js +18 -0
- package/dist/GraphGenomeView/components/FeatureDialog.js.map +1 -0
- package/dist/GraphGenomeView/components/GraphGenomeView.d.ts +6 -0
- package/dist/GraphGenomeView/components/GraphGenomeView.js +17 -0
- package/dist/GraphGenomeView/components/GraphGenomeView.js.map +1 -0
- package/dist/GraphGenomeView/components/GraphPanel.d.ts +6 -0
- package/dist/GraphGenomeView/components/GraphPanel.js +17 -0
- package/dist/GraphGenomeView/components/GraphPanel.js.map +1 -0
- package/dist/GraphGenomeView/components/Header.d.ts +6 -0
- package/dist/GraphGenomeView/components/Header.js +59 -0
- package/dist/GraphGenomeView/components/Header.js.map +1 -0
- package/dist/GraphGenomeView/components/SettingsDialog.d.ts +7 -0
- package/dist/GraphGenomeView/components/SettingsDialog.js +24 -0
- package/dist/GraphGenomeView/components/SettingsDialog.js.map +1 -0
- package/dist/GraphGenomeView/index.d.ts +2 -0
- package/dist/GraphGenomeView/index.js +15 -0
- package/dist/GraphGenomeView/index.js.map +1 -0
- package/dist/GraphGenomeView/model.d.ts +80 -0
- package/dist/GraphGenomeView/model.js +96 -0
- package/dist/GraphGenomeView/model.js.map +1 -0
- package/dist/GraphGenomeView/util.d.ts +1 -0
- package/dist/GraphGenomeView/util.js +8 -0
- package/dist/GraphGenomeView/util.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/jbrowse-plugin-graphgenomeviewer.umd.production.min.js +67 -0
- package/dist/jbrowse-plugin-graphgenomeviewer.umd.production.min.js.map +7 -0
- package/package.json +63 -0
- package/src/GraphGenomeView/components/FeatureDialog.tsx +51 -0
- package/src/GraphGenomeView/components/GraphGenomeView.tsx +32 -0
- package/src/GraphGenomeView/components/GraphPanel.tsx +37 -0
- package/src/GraphGenomeView/components/Header.tsx +90 -0
- package/src/GraphGenomeView/components/SettingsDialog.tsx +71 -0
- package/src/GraphGenomeView/index.ts +19 -0
- package/src/GraphGenomeView/model.ts +110 -0
- package/src/GraphGenomeView/util.ts +7 -0
- package/src/declare.d.ts +1 -0
- package/src/index.ts +28 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# jbrowse-plugin-graphgenomeviewer
|
|
2
|
+
|
|
3
|
+
WIP for displaying graph genome as a view in JBrowse 2
|
|
4
|
+
|
|
5
|
+
## Screenshot
|
|
6
|
+
|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
## Concept
|
|
10
|
+
|
|
11
|
+
The code adds:
|
|
12
|
+
|
|
13
|
+
- a simple file selector for the user to open .gfa files to display alognside
|
|
14
|
+
the genome browser (these are meant to be locus-specific smallish GFA, not
|
|
15
|
+
full assembly graphs)
|
|
16
|
+
- alternatively, can configure a "GFA server" which will use the `vg chunk`
|
|
17
|
+
command to extract the region into a web based bandage-like graph genome
|
|
18
|
+
viewer https://github.com/cmdcolin/graphgenomeviewer
|
|
19
|
+
|
|
20
|
+
## Thanks
|
|
21
|
+
|
|
22
|
+
To the StableGenomics team for their PAG workshop helping explain some vg
|
|
23
|
+
toolkit commands and concepts https://github.com/StableGenomics/PangPAG
|
|
24
|
+
|
|
25
|
+
## TODOs
|
|
26
|
+
|
|
27
|
+
Shortlist of TODOs
|
|
28
|
+
|
|
29
|
+
- Easier navigation between the linear genome view and graph genome panel
|
|
30
|
+
- Ability to launch a synteny-style view from the graph
|
|
31
|
+
- Ability to use decompose graph into VCF track
|
|
32
|
+
- Ability to show paths/walks
|
|
33
|
+
- Debug issue where vg chunk GFA output not loadable in bandage
|
|
34
|
+
- Improve scalability
|
|
35
|
+
- Bi-directional mouseover from genome to graph and back
|
|
36
|
+
- Less chunk-y-ness from the vg chunk graph (?)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Dialog } from '@jbrowse/core/ui';
|
|
3
|
+
export default function FeatureDialog({ data, onClose, }) {
|
|
4
|
+
return (React.createElement(Dialog, { open: true, title: "Feature details", onClose: onClose },
|
|
5
|
+
React.createElement("div", null, "Attributes"),
|
|
6
|
+
Object.entries(data)
|
|
7
|
+
.filter(entry => !['source', 'target', 'linkNum', 'tags'].includes(entry[0]))
|
|
8
|
+
.map(([key, value]) => (React.createElement("div", { key: `${key}_${value}`, style: { display: 'flex', maxHeight: 150, margin: 3 } },
|
|
9
|
+
React.createElement("div", { style: { backgroundColor: '#dda', minWidth: 100 } }, key),
|
|
10
|
+
React.createElement("div", { style: { wordBreak: 'break-word', overflow: 'auto' } }, String(value))))),
|
|
11
|
+
React.createElement("hr", null),
|
|
12
|
+
data.tags && Object.keys(data.tags).length > 0 ? (React.createElement(React.Fragment, null,
|
|
13
|
+
React.createElement("div", null, "Tags"),
|
|
14
|
+
Object.entries(data.tags).map(([key, value]) => (React.createElement("div", { key: `${key}_${value}`, style: { display: 'flex', maxHeight: 150, margin: 3 } },
|
|
15
|
+
React.createElement("div", { style: { backgroundColor: '#dda', minWidth: 100 } }, key),
|
|
16
|
+
React.createElement("div", { style: { wordBreak: 'break-word', overflow: 'auto' } }, String(value))))))) : null));
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=FeatureDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FeatureDialog.js","sourceRoot":"","sources":["../../../src/GraphGenomeView/components/FeatureDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAEzC,MAAM,CAAC,OAAO,UAAU,aAAa,CAAC,EACpC,IAAI,EACJ,OAAO,GAIR;IACC,OAAO,CACL,oBAAC,MAAM,IAAC,IAAI,QAAC,KAAK,EAAC,iBAAiB,EAAC,OAAO,EAAE,OAAO;QACnD,8CAAqB;QACpB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;aAClB,MAAM,CACL,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CACrE;aACA,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CACrB,6BACE,GAAG,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE,EACtB,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE;YAErD,6BAAK,KAAK,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAG,GAAG,CAAO;YACnE,6BAAK,KAAK,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,IACtD,MAAM,CAAC,KAAK,CAAC,CACV,CACF,CACP,CAAC;QACJ,+BAAM;QACL,IAAI,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAChD;YACE,wCAAe;YACd,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAC/C,6BACE,GAAG,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE,EACtB,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,EAAE;gBAErD,6BAAK,KAAK,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,IACnD,GAAG,CACA;gBACN,6BAAK,KAAK,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,EAAE,IACtD,MAAM,CAAC,KAAK,CAAC,CACV,CACF,CACP,CAAC,CACD,CACJ,CAAC,CAAC,CAAC,IAAI,CACD,CACV,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ErrorMessage } from '@jbrowse/core/ui';
|
|
3
|
+
import { observer } from 'mobx-react';
|
|
4
|
+
import GraphPanel from './GraphPanel';
|
|
5
|
+
import Header from './Header';
|
|
6
|
+
const GraphGenomeView = observer(function ({ model, }) {
|
|
7
|
+
const { error } = model;
|
|
8
|
+
return (React.createElement("div", { style: {
|
|
9
|
+
padding: 10,
|
|
10
|
+
} },
|
|
11
|
+
React.createElement(Header, { model: model }),
|
|
12
|
+
React.createElement("div", null,
|
|
13
|
+
error ? React.createElement(ErrorMessage, { error: error }) : null,
|
|
14
|
+
React.createElement(GraphPanel, { model: model }))));
|
|
15
|
+
});
|
|
16
|
+
export default GraphGenomeView;
|
|
17
|
+
//# sourceMappingURL=GraphGenomeView.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GraphGenomeView.js","sourceRoot":"","sources":["../../../src/GraphGenomeView/components/GraphGenomeView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,OAAO,UAAU,MAAM,cAAc,CAAA;AACrC,OAAO,MAAM,MAAM,UAAU,CAAA;AAI7B,MAAM,eAAe,GAAG,QAAQ,CAAC,UAAU,EACzC,KAAK,GAGN;IACC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;IACvB,OAAO,CACL,6BACE,KAAK,EAAE;YACL,OAAO,EAAE,EAAE;SACZ;QAED,oBAAC,MAAM,IAAC,KAAK,EAAE,KAAK,GAAI;QACxB;YACG,KAAK,CAAC,CAAC,CAAC,oBAAC,YAAY,IAAC,KAAK,EAAE,KAAK,GAAI,CAAC,CAAC,CAAC,IAAI;YAC9C,oBAAC,UAAU,IAAC,KAAK,EAAE,KAAK,GAAI,CACxB,CACF,CACP,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,eAAe,eAAe,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Graph } from 'graphgenomeviewer';
|
|
3
|
+
import { observer } from 'mobx-react';
|
|
4
|
+
import FeatureDialog from './FeatureDialog';
|
|
5
|
+
const GraphPanel = observer(function ({ model, }) {
|
|
6
|
+
const { graph } = model;
|
|
7
|
+
const [featureData, setFeatureData] = useState();
|
|
8
|
+
return graph ? (React.createElement(React.Fragment, null,
|
|
9
|
+
featureData ? (React.createElement(FeatureDialog, { data: featureData, onClose: () => {
|
|
10
|
+
setFeatureData(undefined);
|
|
11
|
+
} })) : null,
|
|
12
|
+
React.createElement(Graph, { graph: graph, onFeatureClick: data => {
|
|
13
|
+
setFeatureData(data);
|
|
14
|
+
} }))) : null;
|
|
15
|
+
});
|
|
16
|
+
export default GraphPanel;
|
|
17
|
+
//# sourceMappingURL=GraphPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GraphPanel.js","sourceRoot":"","sources":["../../../src/GraphGenomeView/components/GraphPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEvC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,OAAO,aAAa,MAAM,iBAAiB,CAAA;AAI3C,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,EACpC,KAAK,GAGN;IACC,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;IACvB,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,EAA2B,CAAA;IACzE,OAAO,KAAK,CAAC,CAAC,CAAC,CACb;QACG,WAAW,CAAC,CAAC,CAAC,CACb,oBAAC,aAAa,IACZ,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,GAAG,EAAE;gBACZ,cAAc,CAAC,SAAS,CAAC,CAAA;YAC3B,CAAC,GACD,CACH,CAAC,CAAC,CAAC,IAAI;QACR,oBAAC,KAAK,IACJ,KAAK,EAAE,KAAK,EACZ,cAAc,EAAE,IAAI,CAAC,EAAE;gBACrB,cAAc,CAAC,IAAI,CAAC,CAAA;YACtB,CAAC,GACD,CACD,CACJ,CAAC,CAAC,CAAC,IAAI,CAAA;AACV,CAAC,CAAC,CAAA;AAEF,eAAe,UAAU,CAAA"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { FileSelector } from '@jbrowse/core/ui';
|
|
3
|
+
import { getSession } from '@jbrowse/core/util';
|
|
4
|
+
import { openLocation } from '@jbrowse/core/util/io';
|
|
5
|
+
import { Button, IconButton, TextField } from '@mui/material';
|
|
6
|
+
import { observer } from 'mobx-react';
|
|
7
|
+
import { Settings } from '@mui/icons-material';
|
|
8
|
+
import SettingsDialog from './SettingsDialog';
|
|
9
|
+
const Header = observer(function ({ model }) {
|
|
10
|
+
const { mode } = model;
|
|
11
|
+
const [val, setVal] = useState('GRCh38#chr21:1000-2000');
|
|
12
|
+
const [loc, setLoc] = useState();
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
if (!loc) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if ('uri' in loc && loc.uri) {
|
|
18
|
+
model.setGfaUrl(loc.uri);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
22
|
+
;
|
|
23
|
+
(async () => {
|
|
24
|
+
try {
|
|
25
|
+
model.setError(undefined);
|
|
26
|
+
const data = await openLocation(loc).readFile('utf8');
|
|
27
|
+
model.setResultData(data);
|
|
28
|
+
}
|
|
29
|
+
catch (e) {
|
|
30
|
+
console.error(e);
|
|
31
|
+
model.setError(e);
|
|
32
|
+
}
|
|
33
|
+
})();
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return (React.createElement("div", { style: { display: 'flex' } },
|
|
37
|
+
mode === 'files' ? (React.createElement("div", { style: { maxWidth: 500 } },
|
|
38
|
+
React.createElement(FileSelector, { name: "GFA path", inline: true, location: loc, setLocation: loc => {
|
|
39
|
+
setLoc(loc);
|
|
40
|
+
} }))) : (React.createElement("div", null,
|
|
41
|
+
React.createElement(TextField, { type: "text", variant: "outlined", margin: "normal", size: "small", value: val, style: { minWidth: 500 }, onChange: event => {
|
|
42
|
+
setVal(event.target.value);
|
|
43
|
+
} }),
|
|
44
|
+
React.createElement(Button, { variant: "contained", type: "submit" }, "Submit"))),
|
|
45
|
+
React.createElement("div", { style: { flexGrow: 1 } }),
|
|
46
|
+
React.createElement("div", null,
|
|
47
|
+
React.createElement(IconButton, { onClick: () => {
|
|
48
|
+
getSession(model).queueDialog(handleClose => [
|
|
49
|
+
SettingsDialog,
|
|
50
|
+
{
|
|
51
|
+
handleClose,
|
|
52
|
+
model,
|
|
53
|
+
},
|
|
54
|
+
]);
|
|
55
|
+
} },
|
|
56
|
+
React.createElement(Settings, null)))));
|
|
57
|
+
});
|
|
58
|
+
export default Header;
|
|
59
|
+
//# sourceMappingURL=Header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Header.js","sourceRoot":"","sources":["../../../src/GraphGenomeView/components/Header.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Dialog } from '@jbrowse/core/ui';
|
|
3
|
+
import { Button, DialogActions, DialogContent, FormControl, FormControlLabel, Radio, RadioGroup, } from '@mui/material';
|
|
4
|
+
import { observer } from 'mobx-react';
|
|
5
|
+
const SettingsDialog = observer(function ({ model, handleClose, }) {
|
|
6
|
+
const { mode } = model;
|
|
7
|
+
return (React.createElement(Dialog, { open: true, maxWidth: "xl", title: "Settings", onClose: handleClose },
|
|
8
|
+
React.createElement(DialogContent, { style: { minWidth: 800 } },
|
|
9
|
+
React.createElement(FormControl, { component: "fieldset" },
|
|
10
|
+
React.createElement(RadioGroup, { value: mode, onChange: event => {
|
|
11
|
+
model.setMode(event.target.value);
|
|
12
|
+
} },
|
|
13
|
+
React.createElement(FormControlLabel, { value: "files", control: React.createElement(Radio, null), label: "Use GFA files" }),
|
|
14
|
+
React.createElement(FormControlLabel, { value: "server", control: React.createElement(Radio, null), label: "Use GFA server" })))),
|
|
15
|
+
React.createElement(DialogActions, null,
|
|
16
|
+
React.createElement(Button, { variant: "contained", onClick: () => {
|
|
17
|
+
handleClose();
|
|
18
|
+
} }, "Submit"),
|
|
19
|
+
React.createElement(Button, { variant: "contained", color: "secondary", onClick: () => {
|
|
20
|
+
handleClose();
|
|
21
|
+
} }, "Cancel"))));
|
|
22
|
+
});
|
|
23
|
+
export default SettingsDialog;
|
|
24
|
+
//# sourceMappingURL=SettingsDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsDialog.js","sourceRoot":"","sources":["../../../src/GraphGenomeView/components/SettingsDialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AACzC,OAAO,EACL,MAAM,EACN,aAAa,EACb,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,KAAK,EACL,UAAU,GACX,MAAM,eAAe,CAAA;AACtB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAIrC,MAAM,cAAc,GAAG,QAAQ,CAAC,UAAU,EACxC,KAAK,EACL,WAAW,GAIZ;IACC,MAAM,EAAE,IAAI,EAAE,GAAG,KAAK,CAAA;IACtB,OAAO,CACL,oBAAC,MAAM,IAAC,IAAI,QAAC,QAAQ,EAAC,IAAI,EAAC,KAAK,EAAC,UAAU,EAAC,OAAO,EAAE,WAAW;QAC9D,oBAAC,aAAa,IAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE;YACrC,oBAAC,WAAW,IAAC,SAAS,EAAC,UAAU;gBAC/B,oBAAC,UAAU,IACT,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,KAAK,CAAC,EAAE;wBAChB,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;oBACnC,CAAC;oBAED,oBAAC,gBAAgB,IACf,KAAK,EAAC,OAAO,EACb,OAAO,EAAE,oBAAC,KAAK,OAAG,EAClB,KAAK,EAAC,eAAe,GACrB;oBACF,oBAAC,gBAAgB,IACf,KAAK,EAAC,QAAQ,EACd,OAAO,EAAE,oBAAC,KAAK,OAAG,EAClB,KAAK,EAAC,gBAAgB,GACtB,CACS,CACD,CACA;QAChB,oBAAC,aAAa;YACZ,oBAAC,MAAM,IACL,OAAO,EAAC,WAAW,EACnB,OAAO,EAAE,GAAG,EAAE;oBACZ,WAAW,EAAE,CAAA;gBACf,CAAC,aAGM;YACT,oBAAC,MAAM,IACL,OAAO,EAAC,WAAW,EACnB,KAAK,EAAC,WAAW,EACjB,OAAO,EAAE,GAAG,EAAE;oBACZ,WAAW,EAAE,CAAA;gBACf,CAAC,aAGM,CACK,CACT,CACV,CAAA;AACH,CAAC,CAAC,CAAA;AAEF,eAAe,cAAc,CAAA"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { lazy } from 'react';
|
|
2
|
+
import { ViewType } from '@jbrowse/core/pluggableElementTypes';
|
|
3
|
+
import stateModelF from './model';
|
|
4
|
+
const ReactComponent = lazy(() => import('./components/GraphGenomeView'));
|
|
5
|
+
export default function ProteinViewF(pluginManager) {
|
|
6
|
+
pluginManager.addViewType(() => {
|
|
7
|
+
return new ViewType({
|
|
8
|
+
name: 'GraphGenomeView',
|
|
9
|
+
displayName: 'Graph genome view',
|
|
10
|
+
stateModel: stateModelF(),
|
|
11
|
+
ReactComponent,
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/GraphGenomeView/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAG5B,OAAO,EAAE,QAAQ,EAAE,MAAM,qCAAqC,CAAA;AAE9D,OAAO,WAAW,MAAM,SAAS,CAAA;AAEjC,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,8BAA8B,CAAC,CAAC,CAAA;AAEzE,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,aAA4B;IAC/D,aAAa,CAAC,WAAW,CAAC,GAAG,EAAE;QAC7B,OAAO,IAAI,QAAQ,CAAC;YAClB,IAAI,EAAE,iBAAiB;YACvB,WAAW,EAAE,mBAAmB;YAChC,UAAU,EAAE,WAAW,EAAE;YACzB,cAAc;SACf,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { Instance } from 'mobx-state-tree';
|
|
2
|
+
export default function stateModelFactory(): import("mobx-state-tree").IModelType<{
|
|
3
|
+
id: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").ISimpleType<string>, [undefined]>;
|
|
4
|
+
displayName: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
5
|
+
minimized: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
6
|
+
} & {
|
|
7
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
8
|
+
genomicRegionLocString: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
9
|
+
gfaUrl: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<string>>;
|
|
10
|
+
mode: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
11
|
+
}, {
|
|
12
|
+
width: number;
|
|
13
|
+
} & {
|
|
14
|
+
menuItems(): import("@jbrowse/core/ui").MenuItem[];
|
|
15
|
+
} & {
|
|
16
|
+
setDisplayName(name: string): void;
|
|
17
|
+
setWidth(newWidth: number): void;
|
|
18
|
+
setMinimized(flag: boolean): void;
|
|
19
|
+
} & {
|
|
20
|
+
/**
|
|
21
|
+
* #volatile
|
|
22
|
+
*/
|
|
23
|
+
resultData: string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* #volatile
|
|
26
|
+
*/
|
|
27
|
+
error: unknown;
|
|
28
|
+
} & {
|
|
29
|
+
/**
|
|
30
|
+
* #getter
|
|
31
|
+
*/
|
|
32
|
+
readonly graph: {
|
|
33
|
+
nodes: {
|
|
34
|
+
id: string;
|
|
35
|
+
length: number;
|
|
36
|
+
sequence: string;
|
|
37
|
+
tags: Record<string, string | number>;
|
|
38
|
+
}[];
|
|
39
|
+
links: {
|
|
40
|
+
source: string;
|
|
41
|
+
target: string;
|
|
42
|
+
strand1?: string;
|
|
43
|
+
strand2?: string;
|
|
44
|
+
cigar: string;
|
|
45
|
+
tags: Record<string, string>;
|
|
46
|
+
}[];
|
|
47
|
+
paths: {
|
|
48
|
+
name: string;
|
|
49
|
+
path: string;
|
|
50
|
+
rest: string[];
|
|
51
|
+
}[];
|
|
52
|
+
header: Record<string, string | number>[];
|
|
53
|
+
id: string;
|
|
54
|
+
} | undefined;
|
|
55
|
+
} & {
|
|
56
|
+
/**
|
|
57
|
+
* #action
|
|
58
|
+
*/
|
|
59
|
+
setMode(arg: string): void;
|
|
60
|
+
/**
|
|
61
|
+
* #action
|
|
62
|
+
*/
|
|
63
|
+
setError(arg: unknown): void;
|
|
64
|
+
/**
|
|
65
|
+
* #action
|
|
66
|
+
*/
|
|
67
|
+
setResultData(arg: string): void;
|
|
68
|
+
/**
|
|
69
|
+
* #action
|
|
70
|
+
*/
|
|
71
|
+
setGenomicRegionLocString(arg: string): void;
|
|
72
|
+
/**
|
|
73
|
+
* #action
|
|
74
|
+
*/
|
|
75
|
+
setGfaUrl(url: string): void;
|
|
76
|
+
} & {
|
|
77
|
+
afterAttach(): void;
|
|
78
|
+
}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
|
|
79
|
+
export type GraphGenomeViewStateModel = ReturnType<typeof stateModelFactory>;
|
|
80
|
+
export type GraphGenomeViewModel = Instance<GraphGenomeViewStateModel>;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { BaseViewModel } from '@jbrowse/core/pluggableElementTypes';
|
|
2
|
+
import { parseGFA } from 'graphgenomeviewer';
|
|
3
|
+
import { autorun } from 'mobx';
|
|
4
|
+
import { addDisposer, types } from 'mobx-state-tree';
|
|
5
|
+
import { myfetchtext } from './util';
|
|
6
|
+
export default function stateModelFactory() {
|
|
7
|
+
return types.compose('GraphGenomeView', BaseViewModel, types
|
|
8
|
+
.model({
|
|
9
|
+
/**
|
|
10
|
+
* #property
|
|
11
|
+
*/
|
|
12
|
+
type: 'GraphGenomeView',
|
|
13
|
+
/**
|
|
14
|
+
* #property
|
|
15
|
+
*/
|
|
16
|
+
genomicRegionLocString: types.maybe(types.string),
|
|
17
|
+
/**
|
|
18
|
+
* #property
|
|
19
|
+
*/
|
|
20
|
+
gfaUrl: types.maybe(types.string),
|
|
21
|
+
/**
|
|
22
|
+
* #property
|
|
23
|
+
*/
|
|
24
|
+
mode: 'files',
|
|
25
|
+
})
|
|
26
|
+
.volatile(() => ({
|
|
27
|
+
/**
|
|
28
|
+
* #volatile
|
|
29
|
+
*/
|
|
30
|
+
resultData: undefined,
|
|
31
|
+
/**
|
|
32
|
+
* #volatile
|
|
33
|
+
*/
|
|
34
|
+
error: undefined,
|
|
35
|
+
}))
|
|
36
|
+
.views(self => ({
|
|
37
|
+
/**
|
|
38
|
+
* #getter
|
|
39
|
+
*/
|
|
40
|
+
get graph() {
|
|
41
|
+
return self.resultData ? parseGFA(self.resultData) : undefined;
|
|
42
|
+
},
|
|
43
|
+
}))
|
|
44
|
+
.actions(self => ({
|
|
45
|
+
/**
|
|
46
|
+
* #action
|
|
47
|
+
*/
|
|
48
|
+
setMode(arg) {
|
|
49
|
+
self.mode = arg;
|
|
50
|
+
},
|
|
51
|
+
/**
|
|
52
|
+
* #action
|
|
53
|
+
*/
|
|
54
|
+
setError(arg) {
|
|
55
|
+
self.error = arg;
|
|
56
|
+
},
|
|
57
|
+
/**
|
|
58
|
+
* #action
|
|
59
|
+
*/
|
|
60
|
+
setResultData(arg) {
|
|
61
|
+
self.resultData = arg;
|
|
62
|
+
},
|
|
63
|
+
/**
|
|
64
|
+
* #action
|
|
65
|
+
*/
|
|
66
|
+
setGenomicRegionLocString(arg) {
|
|
67
|
+
self.genomicRegionLocString = arg;
|
|
68
|
+
},
|
|
69
|
+
/**
|
|
70
|
+
* #action
|
|
71
|
+
*/
|
|
72
|
+
setGfaUrl(url) {
|
|
73
|
+
self.gfaUrl = url;
|
|
74
|
+
},
|
|
75
|
+
}))
|
|
76
|
+
.actions(self => ({
|
|
77
|
+
afterAttach() {
|
|
78
|
+
addDisposer(self, autorun(async () => {
|
|
79
|
+
if (!self.gfaUrl) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
self.setError(undefined);
|
|
84
|
+
const url = self.gfaUrl;
|
|
85
|
+
const data = await myfetchtext(url);
|
|
86
|
+
self.setResultData(data);
|
|
87
|
+
}
|
|
88
|
+
catch (e) {
|
|
89
|
+
self.setError(e);
|
|
90
|
+
console.error(e);
|
|
91
|
+
}
|
|
92
|
+
}));
|
|
93
|
+
},
|
|
94
|
+
})));
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/GraphGenomeView/model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC9B,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAEpD,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAIpC,MAAM,CAAC,OAAO,UAAU,iBAAiB;IACvC,OAAO,KAAK,CAAC,OAAO,CAClB,iBAAiB,EACjB,aAAa,EACb,KAAK;SACF,KAAK,CAAC;QACL;;WAEG;QACH,IAAI,EAAE,iBAAiB;QAEvB;;WAEG;QACH,sBAAsB,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QAEjD;;WAEG;QACH,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;QACjC;;WAEG;QACH,IAAI,EAAE,OAAO;KACd,CAAC;SACD,QAAQ,CAAC,GAAG,EAAE,CAAC,CAAC;QACf;;WAEG;QACH,UAAU,EAAE,SAA+B;QAC3C;;WAEG;QACH,KAAK,EAAE,SAAoB;KAC5B,CAAC,CAAC;SACF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACd;;WAEG;QACH,IAAI,KAAK;YACP,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;QAChE,CAAC;KACF,CAAC,CAAC;SACF,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB;;WAEG;QACH,OAAO,CAAC,GAAW;YACjB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAA;QACjB,CAAC;QACD;;WAEG;QACH,QAAQ,CAAC,GAAY;YACnB,IAAI,CAAC,KAAK,GAAG,GAAG,CAAA;QAClB,CAAC;QACD;;WAEG;QACH,aAAa,CAAC,GAAW;YACvB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAA;QACvB,CAAC;QACD;;WAEG;QACH,yBAAyB,CAAC,GAAW;YACnC,IAAI,CAAC,sBAAsB,GAAG,GAAG,CAAA;QACnC,CAAC;QACD;;WAEG;QACH,SAAS,CAAC,GAAW;YACnB,IAAI,CAAC,MAAM,GAAG,GAAG,CAAA;QACnB,CAAC;KACF,CAAC,CAAC;SACF,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChB,WAAW;YACT,WAAW,CACT,IAAI,EACJ,OAAO,CAAC,KAAK,IAAI,EAAE;gBACjB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;oBACjB,OAAM;gBACR,CAAC;gBACD,IAAI,CAAC;oBACH,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;oBACxB,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAA;oBACvB,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,CAAC,CAAA;oBACnC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAA;gBAC1B,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;oBAChB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;gBAClB,CAAC;YACH,CAAC,CAAC,CACH,CAAA;QACH,CAAC;KACF,CAAC,CAAC,CACN,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function myfetchtext(url: string): Promise<string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../../src/GraphGenomeView/util.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAA;IAC5B,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,aAAa,GAAG,EAAE,CAAC,CAAA;IACvD,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAA;AACnB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import Plugin from '@jbrowse/core/Plugin';
|
|
2
|
+
import PluginManager from '@jbrowse/core/PluginManager';
|
|
3
|
+
export default class GraphGenomeViewer extends Plugin {
|
|
4
|
+
name: string;
|
|
5
|
+
version: any;
|
|
6
|
+
install(pluginManager: PluginManager): void;
|
|
7
|
+
configure(pluginManager: PluginManager): void;
|
|
8
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import Plugin from '@jbrowse/core/Plugin';
|
|
2
|
+
import { isAbstractMenuManager } from '@jbrowse/core/util';
|
|
3
|
+
import HubIcon from '@mui/icons-material/Hub';
|
|
4
|
+
import { version } from '../package.json';
|
|
5
|
+
import GraphGenomeViewF from './GraphGenomeView';
|
|
6
|
+
export default class GraphGenomeViewer extends Plugin {
|
|
7
|
+
name = 'GraphGenomeViewer';
|
|
8
|
+
version = version;
|
|
9
|
+
install(pluginManager) {
|
|
10
|
+
GraphGenomeViewF(pluginManager);
|
|
11
|
+
}
|
|
12
|
+
configure(pluginManager) {
|
|
13
|
+
if (isAbstractMenuManager(pluginManager.rootModel)) {
|
|
14
|
+
pluginManager.rootModel.appendToSubMenu(['Add'], {
|
|
15
|
+
label: 'Graph genome viewer',
|
|
16
|
+
icon: HubIcon,
|
|
17
|
+
onClick: (session) => {
|
|
18
|
+
session.addView('GraphGenomeView', {});
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,sBAAsB,CAAA;AAEzC,OAAO,EAAwB,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAChF,OAAO,OAAO,MAAM,yBAAyB,CAAA;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AACzC,OAAO,gBAAgB,MAAM,mBAAmB,CAAA;AAEhD,MAAM,CAAC,OAAO,OAAO,iBAAkB,SAAQ,MAAM;IACnD,IAAI,GAAG,mBAAmB,CAAA;IAC1B,OAAO,GAAG,OAAO,CAAA;IAEjB,OAAO,CAAC,aAA4B;QAClC,gBAAgB,CAAC,aAAa,CAAC,CAAA;IACjC,CAAC;IAED,SAAS,CAAC,aAA4B;QACpC,IAAI,qBAAqB,CAAC,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC;YACnD,aAAa,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,EAAE;gBAC/C,KAAK,EAAE,qBAAqB;gBAC5B,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,CAAC,OAA6B,EAAE,EAAE;oBACzC,OAAO,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAA;gBACxC,CAAC;aACF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;CACF"}
|