@jbrowse/plugin-wiggle 3.0.5 → 3.2.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 (91) hide show
  1. package/dist/BigWigAdapter/BigWigAdapter.js +1 -1
  2. package/dist/BigWigAdapter/configSchema.js +14 -1
  3. package/dist/LinearWiggleDisplay/model.d.ts +10 -10
  4. package/dist/MultiDensityRenderer/MultiDensityRenderer.js +2 -2
  5. package/dist/MultiLineRenderer/MultiLineRenderer.js +2 -2
  6. package/dist/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialog.d.ts +6 -0
  7. package/dist/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialog.js +29 -0
  8. package/dist/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogAuto.d.ts +7 -0
  9. package/dist/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogAuto.js +76 -0
  10. package/dist/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogManual.d.ts +7 -0
  11. package/dist/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogManual.js +155 -0
  12. package/dist/MultiLinearWiggleDisplay/components/ClusterDialog/types.d.ts +7 -0
  13. package/dist/MultiLinearWiggleDisplay/components/ClusterDialog/types.js +2 -0
  14. package/dist/MultiLinearWiggleDisplay/components/SourcesGrid.js +2 -2
  15. package/dist/MultiLinearWiggleDisplay/model.d.ts +15 -9
  16. package/dist/MultiLinearWiggleDisplay/model.js +44 -14
  17. package/dist/MultiLinearWiggleDisplay/types.d.ts +14 -0
  18. package/dist/MultiLinearWiggleDisplay/types.js +2 -0
  19. package/dist/MultiRowLineRenderer/MultiRowLineRenderer.js +2 -2
  20. package/dist/MultiRowXYPlotRenderer/MultiRowXYPlotRenderer.js +2 -2
  21. package/dist/MultiXYPlotRenderer/MultiXYPlotRenderer.js +3 -3
  22. package/dist/WiggleBaseRenderer.d.ts +1 -0
  23. package/dist/WiggleBaseRenderer.js +3 -3
  24. package/dist/WiggleRPC/MultiWiggleClusterScoreMatrix.d.ts +14 -0
  25. package/dist/WiggleRPC/MultiWiggleClusterScoreMatrix.js +34 -0
  26. package/dist/WiggleRPC/MultiWiggleGetScoreMatrix.d.ts +6 -0
  27. package/dist/WiggleRPC/MultiWiggleGetScoreMatrix.js +22 -0
  28. package/dist/WiggleRPC/cluster.d.ts +17 -0
  29. package/dist/WiggleRPC/cluster.js +84 -0
  30. package/dist/WiggleRPC/getScoreMatrix.d.ts +6 -0
  31. package/dist/WiggleRPC/getScoreMatrix.js +35 -0
  32. package/dist/WiggleRPC/rpcMethods.d.ts +2 -0
  33. package/dist/WiggleRPC/rpcMethods.js +2 -0
  34. package/dist/WiggleRPC/type.d.ts +0 -0
  35. package/dist/WiggleRPC/type.js +1 -0
  36. package/dist/WiggleRPC/types.d.ts +13 -0
  37. package/dist/WiggleRPC/types.js +2 -0
  38. package/dist/drawDensity.d.ts +1 -0
  39. package/dist/drawDensity.js +12 -2
  40. package/dist/drawLine.d.ts +1 -0
  41. package/dist/drawLine.js +9 -3
  42. package/dist/drawXY.js +16 -10
  43. package/dist/index.js +2 -0
  44. package/dist/shared/SharedWiggleMixin.d.ts +8 -8
  45. package/dist/shared/SharedWiggleMixin.js +11 -8
  46. package/esm/BigWigAdapter/BigWigAdapter.js +1 -1
  47. package/esm/BigWigAdapter/configSchema.js +14 -1
  48. package/esm/LinearWiggleDisplay/model.d.ts +10 -10
  49. package/esm/MultiDensityRenderer/MultiDensityRenderer.js +3 -3
  50. package/esm/MultiLineRenderer/MultiLineRenderer.js +3 -3
  51. package/esm/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialog.d.ts +6 -0
  52. package/esm/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialog.js +24 -0
  53. package/esm/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogAuto.d.ts +7 -0
  54. package/esm/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogAuto.js +74 -0
  55. package/esm/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogManual.d.ts +7 -0
  56. package/esm/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogManual.js +150 -0
  57. package/esm/MultiLinearWiggleDisplay/components/ClusterDialog/types.d.ts +7 -0
  58. package/esm/MultiLinearWiggleDisplay/components/ClusterDialog/types.js +1 -0
  59. package/esm/MultiLinearWiggleDisplay/components/SourcesGrid.js +2 -2
  60. package/esm/MultiLinearWiggleDisplay/model.d.ts +15 -9
  61. package/esm/MultiLinearWiggleDisplay/model.js +44 -14
  62. package/esm/MultiLinearWiggleDisplay/types.d.ts +14 -0
  63. package/esm/MultiLinearWiggleDisplay/types.js +1 -0
  64. package/esm/MultiRowLineRenderer/MultiRowLineRenderer.js +3 -3
  65. package/esm/MultiRowXYPlotRenderer/MultiRowXYPlotRenderer.js +3 -3
  66. package/esm/MultiXYPlotRenderer/MultiXYPlotRenderer.js +4 -4
  67. package/esm/WiggleBaseRenderer.d.ts +1 -0
  68. package/esm/WiggleBaseRenderer.js +4 -4
  69. package/esm/WiggleRPC/MultiWiggleClusterScoreMatrix.d.ts +14 -0
  70. package/esm/WiggleRPC/MultiWiggleClusterScoreMatrix.js +27 -0
  71. package/esm/WiggleRPC/MultiWiggleGetScoreMatrix.d.ts +6 -0
  72. package/esm/WiggleRPC/MultiWiggleGetScoreMatrix.js +15 -0
  73. package/esm/WiggleRPC/cluster.d.ts +17 -0
  74. package/esm/WiggleRPC/cluster.js +79 -0
  75. package/esm/WiggleRPC/getScoreMatrix.d.ts +6 -0
  76. package/esm/WiggleRPC/getScoreMatrix.js +32 -0
  77. package/esm/WiggleRPC/rpcMethods.d.ts +2 -0
  78. package/esm/WiggleRPC/rpcMethods.js +2 -0
  79. package/esm/WiggleRPC/type.d.ts +0 -0
  80. package/esm/WiggleRPC/type.js +1 -0
  81. package/esm/WiggleRPC/types.d.ts +13 -0
  82. package/esm/WiggleRPC/types.js +1 -0
  83. package/esm/drawDensity.d.ts +1 -0
  84. package/esm/drawDensity.js +12 -2
  85. package/esm/drawLine.d.ts +1 -0
  86. package/esm/drawLine.js +9 -3
  87. package/esm/drawXY.js +16 -10
  88. package/esm/index.js +3 -1
  89. package/esm/shared/SharedWiggleMixin.d.ts +8 -8
  90. package/esm/shared/SharedWiggleMixin.js +11 -8
  91. package/package.json +5 -5
@@ -42,7 +42,7 @@ class BigWigAdapter extends BaseAdapter_1.BaseFeatureDataAdapter {
42
42
  }
43
43
  getFeatures(region, opts = {}) {
44
44
  const { refName, start, end } = region;
45
- const { bpPerPx = 0, stopToken, resolution = 1, statusCallback = () => { }, } = opts;
45
+ const { bpPerPx = 0, resolution = 1, stopToken, statusCallback = () => { }, } = opts;
46
46
  return (0, rxjs_1.ObservableCreate)(async (observer) => {
47
47
  const source = this.getConf('source');
48
48
  const resolutionMultiplier = this.getConf('resolutionMultiplier');
@@ -20,5 +20,18 @@ const BigWigAdapter = (0, configuration_1.ConfigurationSchema)('BigWigAdapter',
20
20
  defaultValue: 1,
21
21
  description: 'Initial resolution multiplier',
22
22
  },
23
- }, { explicitlyTyped: true });
23
+ }, {
24
+ explicitlyTyped: true,
25
+ preProcessSnapshot: snap => {
26
+ return snap.uri
27
+ ? {
28
+ ...snap,
29
+ bigWigLocation: {
30
+ uri: snap.uri,
31
+ baseUri: snap.baseUri,
32
+ },
33
+ }
34
+ : snap;
35
+ },
36
+ });
24
37
  exports.default = BigWigAdapter;
@@ -258,11 +258,11 @@ declare function stateModelFactory(pluginManager: PluginManager, configSchema: A
258
258
  setCrossHatches(cross: boolean): void;
259
259
  } & {
260
260
  readonly adapterTypeName: any;
261
- readonly rendererTypeNameSimple: any;
261
+ readonly rendererTypeNameSimple: string;
262
262
  readonly filters: undefined;
263
- readonly scaleType: any;
264
- readonly maxScore: any;
265
- readonly minScore: any;
263
+ readonly scaleType: string;
264
+ readonly maxScore: number;
265
+ readonly minScore: number;
266
266
  } & {
267
267
  readonly adapterCapabilities: string[];
268
268
  readonly rendererConfig: {
@@ -276,7 +276,7 @@ declare function stateModelFactory(pluginManager: PluginManager, configSchema: A
276
276
  } & import("mobx-state-tree/dist/internal").NonEmptyObject & any & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>);
277
277
  } & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>);
278
278
  } & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>;
279
- readonly autoscaleType: any;
279
+ readonly autoscaleType: string;
280
280
  } & {
281
281
  readonly domain: number[] | undefined;
282
282
  } & {
@@ -289,9 +289,9 @@ declare function stateModelFactory(pluginManager: PluginManager, configSchema: A
289
289
  scoreMin: number;
290
290
  scoreMax: number;
291
291
  } | undefined;
292
- autoscaleType: any;
293
- scaleType: any;
294
- inverted: any;
292
+ autoscaleType: string;
293
+ scaleType: string;
294
+ inverted: boolean;
295
295
  };
296
296
  readonly canHaveFill: boolean;
297
297
  readonly displayCrossHatchesSetting: boolean;
@@ -328,7 +328,7 @@ declare function stateModelFactory(pluginManager: PluginManager, configSchema: A
328
328
  readonly rendererTypeName: string;
329
329
  readonly quantitativeStatsRelevantToCurrentZoom: boolean;
330
330
  readonly graphType: boolean;
331
- readonly inverted: any;
331
+ readonly inverted: boolean;
332
332
  } & {
333
333
  adapterProps(): any;
334
334
  readonly ticks: {
@@ -374,7 +374,7 @@ declare function stateModelFactory(pluginManager: PluginManager, configSchema: A
374
374
  } | {
375
375
  label: string;
376
376
  type: string;
377
- checked: any;
377
+ checked: boolean;
378
378
  onClick: () => void;
379
379
  icon?: undefined;
380
380
  subMenu?: undefined;
@@ -40,13 +40,13 @@ const util_1 = require("@jbrowse/core/util");
40
40
  const WiggleBaseRenderer_1 = __importDefault(require("../WiggleBaseRenderer"));
41
41
  class MultiDensityPlotRenderer extends WiggleBaseRenderer_1.default {
42
42
  async draw(ctx, props) {
43
- const { sources, features } = props;
43
+ const { stopToken, sources, features } = props;
44
44
  const groups = (0, util_1.groupBy)(features.values(), f => f.get('source'));
45
45
  const height = props.height / sources.length;
46
46
  let feats = [];
47
47
  const { drawDensity } = await Promise.resolve().then(() => __importStar(require('../drawDensity')));
48
48
  ctx.save();
49
- sources.forEach(source => {
49
+ (0, util_1.forEachWithStopTokenCheck)(sources, stopToken, source => {
50
50
  const features = groups[source.name] || [];
51
51
  const { reducedFeatures } = drawDensity(ctx, {
52
52
  ...props,
@@ -40,11 +40,11 @@ const util_1 = require("@jbrowse/core/util");
40
40
  const WiggleBaseRenderer_1 = __importDefault(require("../WiggleBaseRenderer"));
41
41
  class MultiLineRenderer extends WiggleBaseRenderer_1.default {
42
42
  async draw(ctx, props) {
43
- const { sources, features } = props;
43
+ const { stopToken, sources, features } = props;
44
44
  const groups = (0, util_1.groupBy)(features.values(), f => f.get('source'));
45
45
  const { drawLine } = await Promise.resolve().then(() => __importStar(require('../drawLine')));
46
46
  let feats = [];
47
- sources.forEach(source => {
47
+ (0, util_1.forEachWithStopTokenCheck)(sources, stopToken, source => {
48
48
  const { reducedFeatures } = drawLine(ctx, {
49
49
  ...props,
50
50
  features: groups[source.name] || [],
@@ -0,0 +1,6 @@
1
+ import type { ReducedModel } from './types';
2
+ declare const ClusterDialog: ({ model, handleClose, }: {
3
+ model: ReducedModel;
4
+ handleClose: () => void;
5
+ }) => import("react/jsx-runtime").JSX.Element;
6
+ export default ClusterDialog;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("react");
8
+ const ui_1 = require("@jbrowse/core/ui");
9
+ const material_1 = require("@mui/material");
10
+ const mobx_react_1 = require("mobx-react");
11
+ const ClusterDialogAuto_1 = __importDefault(require("./ClusterDialogAuto"));
12
+ const ClusterDialogManual_1 = __importDefault(require("./ClusterDialogManual"));
13
+ function Header({ activeMode, setActiveMode, }) {
14
+ return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(material_1.RadioGroup, { children: Object.entries({
15
+ auto: ((0, jsx_runtime_1.jsx)("div", { children: "Run in-app clustering (slow for large data, built in JS clustering)" })),
16
+ manual: ((0, jsx_runtime_1.jsx)("div", { children: "Download R script to run clustering (faster for large data, uses hclust, may be more accurate)" })),
17
+ }).map(([key, val]) => ((0, jsx_runtime_1.jsx)(material_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(material_1.Radio, { checked: activeMode === key, onChange: () => {
18
+ setActiveMode(key);
19
+ } }), label: val }, key))) }) }));
20
+ }
21
+ const ClusterDialog = (0, mobx_react_1.observer)(function ({ model, handleClose, }) {
22
+ const [activeMode, setActiveMode] = (0, react_1.useState)('auto');
23
+ return ((0, jsx_runtime_1.jsx)(ui_1.Dialog, { open: true, title: "Cluster by score", maxWidth: "xl", onClose: (_, reason) => {
24
+ if (reason !== 'backdropClick') {
25
+ handleClose();
26
+ }
27
+ }, children: activeMode === 'auto' ? ((0, jsx_runtime_1.jsx)(ClusterDialogAuto_1.default, { model: model, handleClose: handleClose, children: (0, jsx_runtime_1.jsx)(Header, { activeMode: activeMode, setActiveMode: setActiveMode }) })) : ((0, jsx_runtime_1.jsx)(ClusterDialogManual_1.default, { model: model, handleClose: handleClose, children: (0, jsx_runtime_1.jsx)(Header, { activeMode: activeMode, setActiveMode: setActiveMode }) })) }));
28
+ });
29
+ exports.default = ClusterDialog;
@@ -0,0 +1,7 @@
1
+ import type { ReducedModel } from './types';
2
+ declare const ClusterDialogAuto: ({ model, children, handleClose, }: {
3
+ model: ReducedModel;
4
+ children: React.ReactNode;
5
+ handleClose: () => void;
6
+ }) => import("react/jsx-runtime").JSX.Element;
7
+ export default ClusterDialogAuto;
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const jsx_runtime_1 = require("react/jsx-runtime");
4
+ const react_1 = require("react");
5
+ const ui_1 = require("@jbrowse/core/ui");
6
+ const util_1 = require("@jbrowse/core/util");
7
+ const stopToken_1 = require("@jbrowse/core/util/stopToken");
8
+ const tracks_1 = require("@jbrowse/core/util/tracks");
9
+ const material_1 = require("@mui/material");
10
+ const mobx_react_1 = require("mobx-react");
11
+ const mobx_state_tree_1 = require("mobx-state-tree");
12
+ const ClusterDialogAuto = (0, mobx_react_1.observer)(function ({ model, children, handleClose, }) {
13
+ const [progress, setProgress] = (0, react_1.useState)('');
14
+ const [error, setError] = (0, react_1.useState)();
15
+ const [stopToken, setStopToken] = (0, react_1.useState)('');
16
+ const [showAdvanced, setShowAdvanced] = (0, react_1.useState)(false);
17
+ const [samplesPerPixel, setSamplesPerPixel] = (0, util_1.useLocalStorage)('cluster-samplesPerPixel', '1');
18
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.DialogContent, { children: [children, (0, jsx_runtime_1.jsxs)("div", { style: { marginTop: 50 }, children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
19
+ setShowAdvanced(!showAdvanced);
20
+ }, children: showAdvanced ? 'Hide advanced options' : 'Show advanced options' }), showAdvanced ? ((0, jsx_runtime_1.jsxs)("div", { style: { marginTop: 20 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { children: "This procedure samples the data at each 'pixel' across the visible by default" }), (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Samples per pixel (>1 for denser sampling, between 0-1 for sparser sampling)", variant: "outlined", size: "small", value: samplesPerPixel, onChange: event => {
21
+ setSamplesPerPixel(event.target.value);
22
+ } })] })) : null] }), (0, jsx_runtime_1.jsxs)("div", { children: [progress ? ((0, jsx_runtime_1.jsxs)("div", { style: { padding: 50 }, children: [(0, jsx_runtime_1.jsxs)("span", { style: { width: 400 }, children: ["Progress: ", progress] }), (0, jsx_runtime_1.jsx)(material_1.Button, { onClick: () => {
23
+ (0, stopToken_1.stopStopToken)(stopToken);
24
+ }, children: "Stop" })] })) : null, error ? (0, jsx_runtime_1.jsx)(ui_1.ErrorMessage, { error: error }) : null] })] }), (0, jsx_runtime_1.jsxs)(material_1.DialogActions, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: async () => {
25
+ try {
26
+ setError(undefined);
27
+ setProgress('');
28
+ const view = (0, util_1.getContainingView)(model);
29
+ if (!view.initialized) {
30
+ return;
31
+ }
32
+ const { rpcManager } = (0, util_1.getSession)(model);
33
+ const { sourcesWithoutLayout, adapterConfig } = model;
34
+ if (sourcesWithoutLayout) {
35
+ const sessionId = (0, tracks_1.getRpcSessionId)(model);
36
+ const stopToken = (0, stopToken_1.createStopToken)();
37
+ setStopToken(stopToken);
38
+ const ret = (await rpcManager.call(sessionId, 'MultiWiggleClusterScoreMatrix', {
39
+ regions: view.dynamicBlocks.contentBlocks,
40
+ sources: sourcesWithoutLayout,
41
+ sessionId,
42
+ adapterConfig,
43
+ stopToken,
44
+ bpPerPx: view.bpPerPx / +samplesPerPixel,
45
+ statusCallback: (arg) => {
46
+ setProgress(arg);
47
+ },
48
+ }));
49
+ model.setLayout(ret.order.map(idx => {
50
+ const ret = sourcesWithoutLayout[idx];
51
+ if (!ret) {
52
+ throw new Error(`out of bounds at ${idx}`);
53
+ }
54
+ return ret;
55
+ }));
56
+ }
57
+ handleClose();
58
+ }
59
+ catch (e) {
60
+ if (!(0, util_1.isAbortException)(e) && (0, mobx_state_tree_1.isAlive)(model)) {
61
+ console.error(e);
62
+ setError(e);
63
+ }
64
+ }
65
+ finally {
66
+ setProgress('');
67
+ setStopToken('');
68
+ }
69
+ }, children: "Run clustering" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "secondary", onClick: () => {
70
+ handleClose();
71
+ if (stopToken) {
72
+ (0, stopToken_1.stopStopToken)(stopToken);
73
+ }
74
+ }, children: "Cancel" })] })] }));
75
+ });
76
+ exports.default = ClusterDialogAuto;
@@ -0,0 +1,7 @@
1
+ import type { ReducedModel } from './types';
2
+ declare const ClusterDialogManuals: ({ model, handleClose, children, }: {
3
+ model: ReducedModel;
4
+ handleClose: () => void;
5
+ children: React.ReactNode;
6
+ }) => import("react/jsx-runtime").JSX.Element;
7
+ export default ClusterDialogManuals;
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const jsx_runtime_1 = require("react/jsx-runtime");
7
+ const react_1 = require("react");
8
+ const ui_1 = require("@jbrowse/core/ui");
9
+ const util_1 = require("@jbrowse/core/util");
10
+ const tracks_1 = require("@jbrowse/core/util/tracks");
11
+ const Menu_1 = __importDefault(require("@mui/icons-material/Menu"));
12
+ const material_1 = require("@mui/material");
13
+ const copy_to_clipboard_1 = __importDefault(require("copy-to-clipboard"));
14
+ const file_saver_1 = require("file-saver");
15
+ const mobx_react_1 = require("mobx-react");
16
+ const mobx_state_tree_1 = require("mobx-state-tree");
17
+ const mui_1 = require("tss-react/mui");
18
+ const useStyles = (0, mui_1.makeStyles)()(theme => ({
19
+ textAreaFont: {
20
+ fontFamily: 'Courier New',
21
+ },
22
+ mgap: {
23
+ display: 'flex',
24
+ flexDirection: 'column',
25
+ gap: theme.spacing(4),
26
+ },
27
+ }));
28
+ const ClusterDialogManuals = (0, mobx_react_1.observer)(function ({ model, handleClose, children, }) {
29
+ const { classes } = useStyles();
30
+ const [paste, setPaste] = (0, react_1.useState)('');
31
+ const [ret, setRet] = (0, react_1.useState)();
32
+ const [error, setError] = (0, react_1.useState)();
33
+ const [loading, setLoading] = (0, react_1.useState)(false);
34
+ const [showAdvanced, setShowAdvanced] = (0, react_1.useState)(false);
35
+ const [clusterMethod, setClusterMethod] = (0, util_1.useLocalStorage)('cluster-clusterMethod', 'single');
36
+ const [samplesPerPixel, setSamplesPerPixel] = (0, util_1.useLocalStorage)('cluster-samplesPerPixel', '1');
37
+ (0, react_1.useEffect)(() => {
38
+ ;
39
+ (async () => {
40
+ try {
41
+ setError(undefined);
42
+ setRet(undefined);
43
+ setLoading(true);
44
+ const view = (0, util_1.getContainingView)(model);
45
+ const { dynamicBlocks, bpPerPx } = view;
46
+ const { rpcManager } = (0, util_1.getSession)(model);
47
+ const { sourcesWithoutLayout, adapterConfig } = model;
48
+ const sessionId = (0, tracks_1.getRpcSessionId)(model);
49
+ const ret = (await rpcManager.call(sessionId, 'MultiWiggleGetScoreMatrix', {
50
+ regions: dynamicBlocks.contentBlocks,
51
+ sources: sourcesWithoutLayout,
52
+ sessionId,
53
+ adapterConfig,
54
+ bpPerPx: bpPerPx / +samplesPerPixel,
55
+ }));
56
+ setRet(ret);
57
+ }
58
+ catch (e) {
59
+ if (!(0, util_1.isAbortException)(e) && (0, mobx_state_tree_1.isAlive)(model)) {
60
+ console.error(e);
61
+ setError(e);
62
+ }
63
+ }
64
+ finally {
65
+ setLoading(false);
66
+ }
67
+ })();
68
+ }, [model, samplesPerPixel]);
69
+ const results = ret
70
+ ? `inputMatrix<-matrix(c(${Object.values(ret)
71
+ .map(val => val.join(','))
72
+ .join(',\n')}
73
+ ),nrow=${Object.values(ret).length},byrow=TRUE)
74
+ rownames(inputMatrix)<-c(${Object.keys(ret)
75
+ .map(key => `'${key}'`)
76
+ .join(',')})
77
+ resultClusters<-hclust(dist(inputMatrix), method='${clusterMethod}')
78
+ cat(resultClusters$order,sep='\\n')`
79
+ : undefined;
80
+ const resultsTsv = ret
81
+ ? Object.entries(ret)
82
+ .map(([key, val]) => [key, ...val].join('\t'))
83
+ .join('\n')
84
+ : undefined;
85
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)(material_1.DialogContent, { children: [children, (0, jsx_runtime_1.jsxs)("div", { style: { marginTop: 50 }, children: [(0, jsx_runtime_1.jsxs)("div", { style: {
86
+ display: 'flex',
87
+ gap: '8px',
88
+ flexWrap: 'wrap',
89
+ marginBottom: '16px',
90
+ }, children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
91
+ (0, file_saver_1.saveAs)(new Blob([results || ''], {
92
+ type: 'text/plain;charset=utf-8',
93
+ }), 'cluster.R');
94
+ }, children: "Download Rscript" }), ' ', "or", ' ', (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
95
+ (0, copy_to_clipboard_1.default)(results || '');
96
+ }, children: "Copy Rscript to clipboard" }), ' ', (0, jsx_runtime_1.jsx)("div", { style: { float: 'right' }, children: (0, jsx_runtime_1.jsx)(ui_1.CascadingMenuButton, { menuItems: [
97
+ {
98
+ label: 'Download TSV',
99
+ onClick: () => {
100
+ (0, file_saver_1.saveAs)(new Blob([resultsTsv || ''], {
101
+ type: 'text/plain;charset=utf-8',
102
+ }), 'scores.tsv');
103
+ },
104
+ },
105
+ {
106
+ label: showAdvanced
107
+ ? 'Hide advanced options'
108
+ : 'Show advanced options',
109
+ onClick: () => {
110
+ setShowAdvanced(!showAdvanced);
111
+ },
112
+ },
113
+ ], children: (0, jsx_runtime_1.jsx)(Menu_1.default, {}) }) }), (0, jsx_runtime_1.jsx)("div", { children: showAdvanced ? ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "h6", children: "Advanced options" }), (0, jsx_runtime_1.jsx)(material_1.RadioGroup, { children: Object.entries({
114
+ single: 'Single',
115
+ complete: 'Complete',
116
+ }).map(([key, val]) => ((0, jsx_runtime_1.jsx)(material_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(material_1.Radio, { checked: clusterMethod === key, onChange: () => {
117
+ setClusterMethod(key);
118
+ } }), label: val }, key))) }), (0, jsx_runtime_1.jsxs)("div", { style: { marginTop: 20 }, children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { children: "This procedure samples the data at each 'pixel' across the visible by default" }), (0, jsx_runtime_1.jsx)(material_1.TextField, { label: "Samples per pixel (>1 for denser sampling, between 0-1 for sparser sampling)", variant: "outlined", size: "small", value: samplesPerPixel, onChange: event => {
119
+ setSamplesPerPixel(event.target.value);
120
+ } })] })] })) : null }), results ? ((0, jsx_runtime_1.jsx)("div", {})) : loading ? ((0, jsx_runtime_1.jsx)(ui_1.LoadingEllipses, { variant: "h6", title: "Generating score matrix" })) : error ? ((0, jsx_runtime_1.jsx)(ui_1.ErrorMessage, { error: error })) : null] }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { variant: "subtitle2", gutterBottom: true, style: { marginTop: '16px' }, children: "Clustering Results:" }), (0, jsx_runtime_1.jsx)(material_1.TextField, { multiline: true, fullWidth: true, variant: "outlined", placeholder: "Paste results from Rscript here (sequence of numbers, one per line, specifying the new ordering)", rows: 10, value: paste, onChange: event => {
121
+ setPaste(event.target.value);
122
+ }, slotProps: {
123
+ input: {
124
+ classes: {
125
+ input: classes.textAreaFont,
126
+ },
127
+ },
128
+ } })] })] })] }), (0, jsx_runtime_1.jsxs)(material_1.DialogActions, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
129
+ const { sourcesWithoutLayout } = model;
130
+ if (sourcesWithoutLayout) {
131
+ try {
132
+ model.setLayout(paste
133
+ .split('\n')
134
+ .map(t => t.trim())
135
+ .filter(f => !!f)
136
+ .map(r => +r)
137
+ .map(idx => {
138
+ const ret = sourcesWithoutLayout[idx - 1];
139
+ if (!ret) {
140
+ throw new Error(`out of bounds at ${idx}`);
141
+ }
142
+ return ret;
143
+ }));
144
+ }
145
+ catch (e) {
146
+ console.error(e);
147
+ (0, util_1.getSession)(model).notifyError(`${e}`, e);
148
+ }
149
+ }
150
+ handleClose();
151
+ }, children: "Apply clustering" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "secondary", onClick: () => {
152
+ handleClose();
153
+ }, children: "Cancel" })] })] }));
154
+ });
155
+ exports.default = ClusterDialogManuals;
@@ -0,0 +1,7 @@
1
+ import type { Source } from '../../types';
2
+ import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
3
+ export interface ReducedModel {
4
+ sourcesWithoutLayout?: Source[];
5
+ adapterConfig: AnyConfigurationModel;
6
+ setLayout: (arg: Source[]) => void;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -78,12 +78,12 @@ function SourcesGrid({ rows, onChange, showTips, }) {
78
78
  onChange((0, util_2.moveDown)([...rows], selected, rows.length));
79
79
  }, disabled: !selected.length, children: [(0, jsx_runtime_1.jsx)(KeyboardDoubleArrowDown_1.default, {}), showTips ? 'Move selected items to bottom' : null] }), (0, jsx_runtime_1.jsx)(ColorPicker_1.ColorPopover, { anchorEl: anchorEl, color: widgetColor, onChange: c => {
80
80
  setWidgetColor(c);
81
- selected.forEach(id => {
81
+ for (const id of selected) {
82
82
  const elt = rows.find(f => f.name === id);
83
83
  if (elt) {
84
84
  elt.color = c;
85
85
  }
86
- });
86
+ }
87
87
  onChange([...rows]);
88
88
  }, onClose: () => {
89
89
  setAnchorEl(null);
@@ -259,11 +259,11 @@ export declare function stateModelFactory(_pluginManager: PluginManager, configS
259
259
  setCrossHatches(cross: boolean): void;
260
260
  } & {
261
261
  readonly adapterTypeName: any;
262
- readonly rendererTypeNameSimple: any;
262
+ readonly rendererTypeNameSimple: string;
263
263
  readonly filters: undefined;
264
- readonly scaleType: any;
265
- readonly maxScore: any;
266
- readonly minScore: any;
264
+ readonly scaleType: string;
265
+ readonly maxScore: number;
266
+ readonly minScore: number;
267
267
  } & {
268
268
  readonly adapterCapabilities: string[];
269
269
  readonly rendererConfig: {
@@ -277,7 +277,7 @@ export declare function stateModelFactory(_pluginManager: PluginManager, configS
277
277
  } & import("mobx-state-tree/dist/internal").NonEmptyObject & any & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>);
278
278
  } & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>);
279
279
  } & import("mobx-state-tree").IStateTreeNode<AnyConfigurationSchemaType>;
280
- readonly autoscaleType: any;
280
+ readonly autoscaleType: string;
281
281
  } & {
282
282
  readonly domain: number[] | undefined;
283
283
  } & {
@@ -290,9 +290,9 @@ export declare function stateModelFactory(_pluginManager: PluginManager, configS
290
290
  scoreMin: number;
291
291
  scoreMax: number;
292
292
  } | undefined;
293
- autoscaleType: any;
294
- scaleType: any;
295
- inverted: any;
293
+ autoscaleType: string;
294
+ scaleType: string;
295
+ inverted: boolean;
296
296
  };
297
297
  readonly canHaveFill: boolean;
298
298
  readonly displayCrossHatchesSetting: boolean;
@@ -344,6 +344,12 @@ export declare function stateModelFactory(_pluginManager: PluginManager, configS
344
344
  readonly canHaveFill: boolean;
345
345
  readonly renderColorBoxes: boolean;
346
346
  readonly prefersOffset: boolean;
347
+ readonly sourcesWithoutLayout: {
348
+ color: string;
349
+ baseUri?: string;
350
+ name: string;
351
+ group?: string;
352
+ }[] | undefined;
347
353
  readonly sources: {
348
354
  color: string;
349
355
  baseUri?: string;
@@ -354,7 +360,7 @@ export declare function stateModelFactory(_pluginManager: PluginManager, configS
354
360
  } & {
355
361
  readonly rowHeight: number;
356
362
  readonly rowHeightTooSmallForScalebar: boolean;
357
- readonly useMinimalTicks: any;
363
+ readonly useMinimalTicks: boolean;
358
364
  } & {
359
365
  adapterProps(): any;
360
366
  readonly ticks: {
@@ -50,6 +50,7 @@ const util_2 = require("../util");
50
50
  const randomColor = () => '#000000'.replaceAll('0', () => (~~(Math.random() * 16)).toString(16));
51
51
  const Tooltip = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/Tooltip'))));
52
52
  const SetColorDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/SetColorDialog'))));
53
+ const ClusterDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/ClusterDialog/ClusterDialog'))));
53
54
  const rendererTypes = new Map([
54
55
  ['xyplot', 'MultiXYPlotRenderer'],
55
56
  ['multirowxy', 'MultiRowXYPlotRenderer'],
@@ -136,6 +137,19 @@ function stateModelFactory(_pluginManager, configSchema) {
136
137
  get prefersOffset() {
137
138
  return this.isMultiRow;
138
139
  },
140
+ get sourcesWithoutLayout() {
141
+ var _a;
142
+ const sources = Object.fromEntries(((_a = self.sourcesVolatile) === null || _a === void 0 ? void 0 : _a.map(s => [s.name, s])) || []);
143
+ const iter = self.sourcesVolatile;
144
+ return iter === null || iter === void 0 ? void 0 : iter.map(s => ({
145
+ ...sources[s.name],
146
+ ...s,
147
+ })).map((s, i) => ({
148
+ ...s,
149
+ color: s.color ||
150
+ (!this.isMultiRow ? colors_1.set1[i] || randomColor() : 'blue'),
151
+ }));
152
+ },
139
153
  get sources() {
140
154
  var _a;
141
155
  const sources = Object.fromEntries(((_a = self.sourcesVolatile) === null || _a === void 0 ? void 0 : _a.map(s => [s.name, s])) || []);
@@ -163,7 +177,8 @@ function stateModelFactory(_pluginManager, configSchema) {
163
177
  return this.rowHeight < 70;
164
178
  },
165
179
  get useMinimalTicks() {
166
- return ((0, configuration_1.getConf)(self, 'minimalTicks') || this.rowHeightTooSmallForScalebar);
180
+ return ((0, configuration_1.getConf)(self, 'minimalTicks') ||
181
+ this.rowHeightTooSmallForScalebar);
167
182
  },
168
183
  }))
169
184
  .views(self => {
@@ -293,18 +308,6 @@ function stateModelFactory(_pluginManager, configSchema) {
293
308
  },
294
309
  ]
295
310
  : []),
296
- ...(self.graphType
297
- ? [
298
- {
299
- type: 'checkbox',
300
- label: 'Draw cross hatches',
301
- checked: self.displayCrossHatchesSetting,
302
- onClick: () => {
303
- self.toggleCrossHatches();
304
- },
305
- },
306
- ]
307
- : []),
308
311
  ...(hasRenderings
309
312
  ? [
310
313
  {
@@ -326,12 +329,39 @@ function stateModelFactory(_pluginManager, configSchema) {
326
329
  },
327
330
  ]
328
331
  : []),
332
+ ...(self.graphType
333
+ ? [
334
+ {
335
+ type: 'checkbox',
336
+ label: 'Draw cross hatches',
337
+ checked: self.displayCrossHatchesSetting,
338
+ onClick: () => {
339
+ self.toggleCrossHatches();
340
+ },
341
+ },
342
+ ]
343
+ : []),
344
+ {
345
+ label: 'Cluster by score',
346
+ onClick: () => {
347
+ (0, util_1.getSession)(self).queueDialog(handleClose => [
348
+ ClusterDialog,
349
+ {
350
+ model: self,
351
+ handleClose,
352
+ },
353
+ ]);
354
+ },
355
+ },
329
356
  {
330
357
  label: 'Edit colors/arrangement...',
331
358
  onClick: () => {
332
359
  (0, util_1.getSession)(self).queueDialog(handleClose => [
333
360
  SetColorDialog,
334
- { model: self, handleClose },
361
+ {
362
+ model: self,
363
+ handleClose,
364
+ },
335
365
  ]);
336
366
  },
337
367
  },
@@ -0,0 +1,14 @@
1
+ export interface Source {
2
+ baseUri?: string;
3
+ name: string;
4
+ label?: string;
5
+ color?: string;
6
+ group?: string;
7
+ HP?: number;
8
+ id?: string;
9
+ [key: string]: unknown;
10
+ }
11
+ export interface SampleInfo {
12
+ isPhased: boolean;
13
+ maxPloidy: number;
14
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -40,7 +40,7 @@ const util_1 = require("@jbrowse/core/util");
40
40
  const WiggleBaseRenderer_1 = __importDefault(require("../WiggleBaseRenderer"));
41
41
  class MultiRowLineRenderer extends WiggleBaseRenderer_1.default {
42
42
  async draw(ctx, props) {
43
- const { bpPerPx, sources, regions, features } = props;
43
+ const { stopToken, bpPerPx, sources, regions, features } = props;
44
44
  const region = regions[0];
45
45
  const groups = (0, util_1.groupBy)(features.values(), f => f.get('source'));
46
46
  const height = props.height / sources.length;
@@ -48,7 +48,7 @@ class MultiRowLineRenderer extends WiggleBaseRenderer_1.default {
48
48
  const { drawLine } = await Promise.resolve().then(() => __importStar(require('../drawLine')));
49
49
  let feats = [];
50
50
  ctx.save();
51
- sources.forEach(source => {
51
+ (0, util_1.forEachWithStopTokenCheck)(sources, stopToken, source => {
52
52
  const { reducedFeatures } = drawLine(ctx, {
53
53
  ...props,
54
54
  features: groups[source.name] || [],