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.
Files changed (41) hide show
  1. package/README.md +36 -0
  2. package/dist/GraphGenomeView/components/FeatureDialog.d.ts +5 -0
  3. package/dist/GraphGenomeView/components/FeatureDialog.js +18 -0
  4. package/dist/GraphGenomeView/components/FeatureDialog.js.map +1 -0
  5. package/dist/GraphGenomeView/components/GraphGenomeView.d.ts +6 -0
  6. package/dist/GraphGenomeView/components/GraphGenomeView.js +17 -0
  7. package/dist/GraphGenomeView/components/GraphGenomeView.js.map +1 -0
  8. package/dist/GraphGenomeView/components/GraphPanel.d.ts +6 -0
  9. package/dist/GraphGenomeView/components/GraphPanel.js +17 -0
  10. package/dist/GraphGenomeView/components/GraphPanel.js.map +1 -0
  11. package/dist/GraphGenomeView/components/Header.d.ts +6 -0
  12. package/dist/GraphGenomeView/components/Header.js +59 -0
  13. package/dist/GraphGenomeView/components/Header.js.map +1 -0
  14. package/dist/GraphGenomeView/components/SettingsDialog.d.ts +7 -0
  15. package/dist/GraphGenomeView/components/SettingsDialog.js +24 -0
  16. package/dist/GraphGenomeView/components/SettingsDialog.js.map +1 -0
  17. package/dist/GraphGenomeView/index.d.ts +2 -0
  18. package/dist/GraphGenomeView/index.js +15 -0
  19. package/dist/GraphGenomeView/index.js.map +1 -0
  20. package/dist/GraphGenomeView/model.d.ts +80 -0
  21. package/dist/GraphGenomeView/model.js +96 -0
  22. package/dist/GraphGenomeView/model.js.map +1 -0
  23. package/dist/GraphGenomeView/util.d.ts +1 -0
  24. package/dist/GraphGenomeView/util.js +8 -0
  25. package/dist/GraphGenomeView/util.js.map +1 -0
  26. package/dist/index.d.ts +8 -0
  27. package/dist/index.js +24 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/jbrowse-plugin-graphgenomeviewer.umd.production.min.js +67 -0
  30. package/dist/jbrowse-plugin-graphgenomeviewer.umd.production.min.js.map +7 -0
  31. package/package.json +63 -0
  32. package/src/GraphGenomeView/components/FeatureDialog.tsx +51 -0
  33. package/src/GraphGenomeView/components/GraphGenomeView.tsx +32 -0
  34. package/src/GraphGenomeView/components/GraphPanel.tsx +37 -0
  35. package/src/GraphGenomeView/components/Header.tsx +90 -0
  36. package/src/GraphGenomeView/components/SettingsDialog.tsx +71 -0
  37. package/src/GraphGenomeView/index.ts +19 -0
  38. package/src/GraphGenomeView/model.ts +110 -0
  39. package/src/GraphGenomeView/util.ts +7 -0
  40. package/src/declare.d.ts +1 -0
  41. 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
+ ![](img/1.png)
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,5 @@
1
+ import React from 'react';
2
+ export default function FeatureDialog({ data, onClose, }: {
3
+ data: Record<string, unknown>;
4
+ onClose: () => void;
5
+ }): React.JSX.Element;
@@ -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,6 @@
1
+ import React from 'react';
2
+ import type { GraphGenomeViewModel } from '../model';
3
+ declare const GraphGenomeView: ({ model, }: {
4
+ model: GraphGenomeViewModel;
5
+ }) => React.JSX.Element;
6
+ export default GraphGenomeView;
@@ -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,6 @@
1
+ import React from 'react';
2
+ import type { GraphGenomeViewModel } from '../model';
3
+ declare const GraphPanel: ({ model, }: {
4
+ model: GraphGenomeViewModel;
5
+ }) => React.JSX.Element | null;
6
+ export default GraphPanel;
@@ -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,6 @@
1
+ import React from 'react';
2
+ import type { GraphGenomeViewModel } from '../model';
3
+ declare const Header: ({ model }: {
4
+ model: GraphGenomeViewModel;
5
+ }) => React.JSX.Element;
6
+ export default Header;
@@ -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,7 @@
1
+ import React from 'react';
2
+ import type { GraphGenomeViewModel } from '../model';
3
+ declare const SettingsDialog: ({ model, handleClose, }: {
4
+ model: GraphGenomeViewModel;
5
+ handleClose: () => void;
6
+ }) => React.JSX.Element;
7
+ export default SettingsDialog;
@@ -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,2 @@
1
+ import PluginManager from '@jbrowse/core/PluginManager';
2
+ export default function ProteinViewF(pluginManager: PluginManager): void;
@@ -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,8 @@
1
+ export async function myfetchtext(url) {
2
+ const res = await fetch(url);
3
+ if (!res.ok) {
4
+ throw new Error(`HTTP ${res.status} fetching ${url}`);
5
+ }
6
+ return res.text();
7
+ }
8
+ //# sourceMappingURL=util.js.map
@@ -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"}
@@ -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"}