@jbrowse/plugin-variants 3.1.0 → 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 (75) hide show
  1. package/dist/MultiLinearVariantDisplay/model.d.ts +19 -0
  2. package/dist/MultiLinearVariantMatrixDisplay/model.d.ts +20 -0
  3. package/dist/MultiLinearVariantMatrixDisplay/model.js +4 -1
  4. package/dist/MultiLinearVariantMatrixRenderer/makeImageData.js +9 -1
  5. package/dist/MultiLinearVariantRenderer/makeImageData.js +9 -1
  6. package/dist/VariantRPC/MultiVariantClusterGenotypeMatrix.d.ts +28 -0
  7. package/dist/VariantRPC/MultiVariantClusterGenotypeMatrix.js +33 -0
  8. package/dist/VariantRPC/MultiVariantGetGenotypeMatrix.d.ts +13 -11
  9. package/dist/VariantRPC/MultiVariantGetGenotypeMatrix.js +5 -57
  10. package/dist/VariantRPC/MultiVariantGetSimplifiedFeatures.d.ts +11 -8
  11. package/dist/VariantRPC/MultiVariantGetSimplifiedFeatures.js +1 -2
  12. package/dist/VariantRPC/cluster.d.ts +17 -0
  13. package/dist/VariantRPC/cluster.js +84 -0
  14. package/dist/VariantRPC/getGenotypeMatrix.d.ts +6 -0
  15. package/dist/VariantRPC/getGenotypeMatrix.js +55 -0
  16. package/dist/VariantRPC/types.d.ts +13 -0
  17. package/dist/VariantRPC/types.js +2 -0
  18. package/dist/VcfAdapter/VcfAdapter.js +6 -3
  19. package/dist/VcfFeature/util.js +2 -2
  20. package/dist/VcfTabixAdapter/VcfTabixAdapter.js +11 -6
  21. package/dist/index.js +2 -0
  22. package/dist/shared/MultiVariantBaseModel.d.ts +19 -0
  23. package/dist/shared/MultiVariantBaseModel.js +27 -35
  24. package/dist/shared/components/ClusterDialog/ClusterDialog.d.ts +6 -0
  25. package/dist/shared/components/ClusterDialog/ClusterDialog.js +29 -0
  26. package/dist/shared/components/ClusterDialog/ClusterDialogAuto.d.ts +7 -0
  27. package/dist/shared/components/ClusterDialog/ClusterDialogAuto.js +69 -0
  28. package/dist/shared/components/ClusterDialog/ClusterDialogManual.d.ts +7 -0
  29. package/dist/shared/components/ClusterDialog/ClusterDialogManual.js +144 -0
  30. package/dist/shared/components/ClusterDialog/types.d.ts +9 -0
  31. package/dist/shared/components/ClusterDialog/types.js +2 -0
  32. package/dist/shared/components/SourcesDataGrid.js +47 -40
  33. package/dist/shared/components/SourcesGridHeader.js +2 -2
  34. package/dist/shared/getSources.d.ts +15 -0
  35. package/dist/shared/getSources.js +34 -0
  36. package/esm/MultiLinearVariantDisplay/model.d.ts +19 -0
  37. package/esm/MultiLinearVariantMatrixDisplay/model.d.ts +20 -0
  38. package/esm/MultiLinearVariantMatrixDisplay/model.js +4 -1
  39. package/esm/MultiLinearVariantMatrixRenderer/makeImageData.js +9 -1
  40. package/esm/MultiLinearVariantRenderer/makeImageData.js +9 -1
  41. package/esm/VariantRPC/MultiVariantClusterGenotypeMatrix.d.ts +28 -0
  42. package/esm/VariantRPC/MultiVariantClusterGenotypeMatrix.js +26 -0
  43. package/esm/VariantRPC/MultiVariantGetGenotypeMatrix.d.ts +13 -11
  44. package/esm/VariantRPC/MultiVariantGetGenotypeMatrix.js +5 -57
  45. package/esm/VariantRPC/MultiVariantGetSimplifiedFeatures.d.ts +11 -8
  46. package/esm/VariantRPC/MultiVariantGetSimplifiedFeatures.js +1 -2
  47. package/esm/VariantRPC/cluster.d.ts +17 -0
  48. package/esm/VariantRPC/cluster.js +79 -0
  49. package/esm/VariantRPC/getGenotypeMatrix.d.ts +6 -0
  50. package/esm/VariantRPC/getGenotypeMatrix.js +52 -0
  51. package/esm/VariantRPC/types.d.ts +13 -0
  52. package/esm/VariantRPC/types.js +1 -0
  53. package/esm/VcfAdapter/VcfAdapter.js +7 -4
  54. package/esm/VcfFeature/util.js +2 -2
  55. package/esm/VcfTabixAdapter/VcfTabixAdapter.js +11 -6
  56. package/esm/index.js +2 -0
  57. package/esm/shared/MultiVariantBaseModel.d.ts +19 -0
  58. package/esm/shared/MultiVariantBaseModel.js +27 -35
  59. package/esm/shared/components/ClusterDialog/ClusterDialog.d.ts +6 -0
  60. package/esm/shared/components/ClusterDialog/ClusterDialog.js +24 -0
  61. package/esm/shared/components/ClusterDialog/ClusterDialogAuto.d.ts +7 -0
  62. package/esm/shared/components/ClusterDialog/ClusterDialogAuto.js +67 -0
  63. package/esm/shared/components/ClusterDialog/ClusterDialogManual.d.ts +7 -0
  64. package/esm/shared/components/ClusterDialog/ClusterDialogManual.js +139 -0
  65. package/esm/shared/components/ClusterDialog/types.d.ts +9 -0
  66. package/esm/shared/components/ClusterDialog/types.js +1 -0
  67. package/esm/shared/components/SourcesDataGrid.js +47 -40
  68. package/esm/shared/components/SourcesGridHeader.js +2 -2
  69. package/esm/shared/getSources.d.ts +15 -0
  70. package/esm/shared/getSources.js +31 -0
  71. package/package.json +6 -6
  72. package/dist/shared/components/ClusterDialog.d.ts +0 -11
  73. package/dist/shared/components/ClusterDialog.js +0 -113
  74. package/esm/shared/components/ClusterDialog.d.ts +0 -11
  75. package/esm/shared/components/ClusterDialog.js +0 -107
@@ -255,6 +255,15 @@ export default function MultiVariantBaseModelF(configSchema: AnyConfigurationSch
255
255
  setSampleInfo(arg: Record<string, SampleInfo>): void;
256
256
  } & {
257
257
  readonly preSources: Source[] | undefined;
258
+ readonly sourcesWithoutLayout: {
259
+ label: string;
260
+ id: string;
261
+ baseUri?: string;
262
+ name: string;
263
+ color?: string;
264
+ group?: string;
265
+ HP?: number;
266
+ }[] | undefined;
258
267
  readonly sources: {
259
268
  label: string;
260
269
  id: string;
@@ -330,10 +339,20 @@ export default function MultiVariantBaseModelF(configSchema: AnyConfigurationSch
330
339
  type?: undefined;
331
340
  checked?: undefined;
332
341
  onClick?: undefined;
342
+ } | {
343
+ label: string;
344
+ icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
345
+ muiName: string;
346
+ };
347
+ onClick: () => void;
348
+ type?: undefined;
349
+ checked?: undefined;
350
+ subMenu?: undefined;
333
351
  })[];
334
352
  } & {
335
353
  readonly canDisplayLabels: boolean;
336
354
  readonly totalHeight: number;
355
+ readonly featuresReady: boolean;
337
356
  } & {
338
357
  renderProps(): any;
339
358
  }, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>;
@@ -42,15 +42,17 @@ const configuration_1 = require("@jbrowse/core/configuration");
42
42
  const util_1 = require("@jbrowse/core/util");
43
43
  const stopToken_1 = require("@jbrowse/core/util/stopToken");
44
44
  const plugin_linear_genome_view_1 = require("@jbrowse/plugin-linear-genome-view");
45
+ const Category_1 = __importDefault(require("@mui/icons-material/Category"));
45
46
  const FilterList_1 = __importDefault(require("@mui/icons-material/FilterList"));
46
47
  const Height_1 = __importDefault(require("@mui/icons-material/Height"));
47
48
  const Splitscreen_1 = __importDefault(require("@mui/icons-material/Splitscreen"));
48
49
  const Visibility_1 = __importDefault(require("@mui/icons-material/Visibility"));
49
50
  const fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
50
51
  const mobx_state_tree_1 = require("mobx-state-tree");
52
+ const getSources_1 = require("./getSources");
51
53
  const SetColorDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/SetColorDialog'))));
52
54
  const MAFFilterDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/MAFFilterDialog'))));
53
- const ClusterDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/ClusterDialog'))));
55
+ const ClusterDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/ClusterDialog/ClusterDialog'))));
54
56
  const SetRowHeightDialog = (0, react_1.lazy)(() => Promise.resolve().then(() => __importStar(require('./components/SetRowHeightDialog'))));
55
57
  function MultiVariantBaseModelF(configSchema) {
56
58
  return mobx_state_tree_1.types
@@ -125,40 +127,26 @@ function MultiVariantBaseModelF(configSchema) {
125
127
  get preSources() {
126
128
  return self.layout.length ? self.layout : self.sourcesVolatile;
127
129
  },
130
+ get sourcesWithoutLayout() {
131
+ return self.sourcesVolatile
132
+ ? (0, getSources_1.getSources)({
133
+ sources: self.sourcesVolatile,
134
+ renderingMode: self.renderingMode,
135
+ sampleInfo: self.sampleInfo,
136
+ })
137
+ : undefined;
138
+ },
128
139
  get sources() {
129
- var _a, _b;
130
- if (this.preSources) {
131
- const rows = [];
132
- const sources = Object.fromEntries(((_a = self.sourcesVolatile) === null || _a === void 0 ? void 0 : _a.map(s => [s.name, s])) || []);
133
- for (const row of this.preSources) {
134
- if (self.renderingMode === 'phased') {
135
- const info = (_b = self.sampleInfo) === null || _b === void 0 ? void 0 : _b[row.name];
136
- if (info === null || info === void 0 ? void 0 : info.isPhased) {
137
- const ploidy = info.maxPloidy;
138
- for (let i = 0; i < ploidy; i++) {
139
- const id = `${row.name} HP${i}`;
140
- rows.push({
141
- ...sources[row.name],
142
- ...row,
143
- label: id,
144
- HP: i,
145
- id: id,
146
- });
147
- }
148
- }
149
- }
150
- else {
151
- rows.push({
152
- ...sources[row.name],
153
- ...row,
154
- label: row.name,
155
- id: row.name,
156
- });
157
- }
158
- }
159
- return rows;
160
- }
161
- return undefined;
140
+ const sourcesWithLayout = self.layout.length
141
+ ? self.layout
142
+ : self.sourcesVolatile;
143
+ return sourcesWithLayout
144
+ ? (0, getSources_1.getSources)({
145
+ sources: sourcesWithLayout,
146
+ renderingMode: self.renderingMode,
147
+ sampleInfo: self.sampleInfo,
148
+ })
149
+ : undefined;
162
150
  },
163
151
  }))
164
152
  .views(self => {
@@ -261,6 +249,7 @@ function MultiVariantBaseModelF(configSchema) {
261
249
  },
262
250
  {
263
251
  label: 'Cluster by genotype',
252
+ icon: Category_1.default,
264
253
  onClick: () => {
265
254
  (0, util_1.getSession)(self).queueDialog(handleClose => [
266
255
  ClusterDialog,
@@ -295,13 +284,16 @@ function MultiVariantBaseModelF(configSchema) {
295
284
  var _a;
296
285
  return self.rowHeight * (((_a = self.sources) === null || _a === void 0 ? void 0 : _a.length) || 1);
297
286
  },
287
+ get featuresReady() {
288
+ return !!self.featuresVolatile;
289
+ },
298
290
  }))
299
291
  .views(self => ({
300
292
  renderProps() {
301
293
  const superProps = self.adapterProps();
302
294
  return {
303
295
  ...superProps,
304
- notReady: superProps.notReady || !self.sources || !self.featuresVolatile,
296
+ notReady: superProps.notReady || !self.sources || !self.featuresReady,
305
297
  height: self.height,
306
298
  totalHeight: self.totalHeight,
307
299
  renderingMode: self.renderingMode,
@@ -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.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(material_1.Typography, { style: { marginBottom: 30 }, children: "This procedure will cluster the visible genotype data using hierarchical clustering" }), (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 genotype", 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,69 @@
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
+ 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", { 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: () => {
17
+ (0, stopToken_1.stopStopToken)(stopToken);
18
+ }, 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 () => {
19
+ try {
20
+ setError(undefined);
21
+ const view = (0, util_1.getContainingView)(model);
22
+ if (!view.initialized) {
23
+ return;
24
+ }
25
+ const { rpcManager } = (0, util_1.getSession)(model);
26
+ const { sourcesWithoutLayout, minorAlleleFrequencyFilter, adapterConfig, } = model;
27
+ if (sourcesWithoutLayout) {
28
+ const sessionId = (0, tracks_1.getRpcSessionId)(model);
29
+ const stopToken = (0, stopToken_1.createStopToken)();
30
+ setStopToken(stopToken);
31
+ const ret = (await rpcManager.call(sessionId, 'MultiVariantClusterGenotypeMatrix', {
32
+ regions: view.dynamicBlocks.contentBlocks,
33
+ sources: sourcesWithoutLayout,
34
+ minorAlleleFrequencyFilter,
35
+ sessionId,
36
+ adapterConfig,
37
+ stopToken,
38
+ statusCallback: (arg) => {
39
+ setProgress(arg);
40
+ },
41
+ }));
42
+ model.setLayout(ret.order.map(idx => {
43
+ const ret = sourcesWithoutLayout[idx];
44
+ if (!ret) {
45
+ throw new Error(`out of bounds at ${idx}`);
46
+ }
47
+ return ret;
48
+ }));
49
+ }
50
+ handleClose();
51
+ }
52
+ catch (e) {
53
+ if (!(0, util_1.isAbortException)(e) && (0, mobx_state_tree_1.isAlive)(model)) {
54
+ console.error(e);
55
+ setError(e);
56
+ }
57
+ }
58
+ finally {
59
+ setProgress('');
60
+ setStopToken('');
61
+ }
62
+ }, children: "Run clustering" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "secondary", onClick: () => {
63
+ handleClose();
64
+ if (stopToken) {
65
+ (0, stopToken_1.stopStopToken)(stopToken);
66
+ }
67
+ }, children: "Cancel" })] })] }));
68
+ });
69
+ 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,144 @@
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 material_1 = require("@mui/material");
12
+ const copy_to_clipboard_1 = __importDefault(require("copy-to-clipboard"));
13
+ const file_saver_1 = require("file-saver");
14
+ const mobx_react_1 = require("mobx-react");
15
+ const mobx_state_tree_1 = require("mobx-state-tree");
16
+ const mui_1 = require("tss-react/mui");
17
+ const useStyles = (0, mui_1.makeStyles)()(theme => ({
18
+ textAreaFont: {
19
+ fontFamily: 'Courier New',
20
+ },
21
+ mgap: {
22
+ display: 'flex',
23
+ flexDirection: 'column',
24
+ gap: theme.spacing(4),
25
+ },
26
+ }));
27
+ const ClusterDialogManuals = (0, mobx_react_1.observer)(function ({ model, handleClose, children, }) {
28
+ const { classes } = useStyles();
29
+ const [paste, setPaste] = (0, react_1.useState)('');
30
+ const [ret, setRet] = (0, react_1.useState)();
31
+ const [error, setError] = (0, react_1.useState)();
32
+ const [loading, setLoading] = (0, react_1.useState)(false);
33
+ const [showAdvanced, setShowAdvanced] = (0, react_1.useState)(false);
34
+ const [clusterMethod, setClusterMethod] = (0, util_1.useLocalStorage)('cluster-clusterMethod', 'single');
35
+ (0, react_1.useEffect)(() => {
36
+ ;
37
+ (async () => {
38
+ try {
39
+ setError(undefined);
40
+ setRet(undefined);
41
+ setLoading(true);
42
+ const view = (0, util_1.getContainingView)(model);
43
+ if (!view.initialized) {
44
+ return;
45
+ }
46
+ const { rpcManager } = (0, util_1.getSession)(model);
47
+ const { sourcesWithoutLayout, minorAlleleFrequencyFilter, adapterConfig, } = model;
48
+ const sessionId = (0, tracks_1.getRpcSessionId)(model);
49
+ const ret = (await rpcManager.call(sessionId, 'MultiVariantGetGenotypeMatrix', {
50
+ regions: view.dynamicBlocks.contentBlocks,
51
+ sources: sourcesWithoutLayout,
52
+ minorAlleleFrequencyFilter,
53
+ sessionId,
54
+ adapterConfig,
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]);
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)(material_1.Paper, { style: { padding: 16 }, 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" }), ' ', "or", ' ', (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
97
+ (0, file_saver_1.saveAs)(new Blob([resultsTsv || ''], {
98
+ type: 'text/plain;charset=utf-8',
99
+ }), 'genotypes.tsv');
100
+ }, children: "Download TSV" }), (0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
101
+ setShowAdvanced(!showAdvanced);
102
+ }, children: showAdvanced
103
+ ? 'Hide advanced options'
104
+ : 'Show advanced options' }), 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({
105
+ single: 'Single',
106
+ complete: 'Complete',
107
+ }).map(([key, val]) => ((0, jsx_runtime_1.jsx)(material_1.FormControlLabel, { control: (0, jsx_runtime_1.jsx)(material_1.Radio, { checked: clusterMethod === key, onChange: () => {
108
+ setClusterMethod(key);
109
+ } }), label: val }, key))) })] })) : null] }), results ? ((0, jsx_runtime_1.jsx)("div", {})) : loading ? ((0, jsx_runtime_1.jsx)(ui_1.LoadingEllipses, { variant: "h6", title: "Generating genotype 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 => {
110
+ setPaste(event.target.value);
111
+ }, slotProps: {
112
+ input: {
113
+ classes: {
114
+ input: classes.textAreaFont,
115
+ },
116
+ },
117
+ } })] })] })] }), (0, jsx_runtime_1.jsxs)(material_1.DialogActions, { children: [(0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", onClick: () => {
118
+ const { sourcesWithoutLayout } = model;
119
+ if (sourcesWithoutLayout) {
120
+ try {
121
+ model.setLayout(paste
122
+ .split('\n')
123
+ .map(t => t.trim())
124
+ .filter(f => !!f)
125
+ .map(r => +r)
126
+ .map(idx => {
127
+ const ret = sourcesWithoutLayout[idx - 1];
128
+ if (!ret) {
129
+ throw new Error(`out of bounds at ${idx}`);
130
+ }
131
+ return ret;
132
+ }));
133
+ }
134
+ catch (e) {
135
+ console.error(e);
136
+ (0, util_1.getSession)(model).notifyError(`${e}`, e);
137
+ }
138
+ }
139
+ handleClose();
140
+ }, children: "Apply clustering" }), (0, jsx_runtime_1.jsx)(material_1.Button, { variant: "contained", color: "secondary", onClick: () => {
141
+ handleClose();
142
+ }, children: "Cancel" })] })] }));
143
+ });
144
+ exports.default = ClusterDialogManuals;
@@ -0,0 +1,9 @@
1
+ import type { Source } from '../../types';
2
+ import type { AnyConfigurationModel } from '@jbrowse/core/configuration';
3
+ export interface ReducedModel {
4
+ sourcesWithoutLayout?: Source[];
5
+ minorAlleleFrequencyFilter?: number;
6
+ adapterConfig: AnyConfigurationModel;
7
+ setLayout: (arg: Source[]) => void;
8
+ clearLayout: () => void;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -20,49 +20,56 @@ const useStyles = (0, mui_1.makeStyles)()({
20
20
  });
21
21
  function SourcesDataGrid({ rows, onChange, setSelected, }) {
22
22
  const { classes } = useStyles();
23
- const { id: _id, name: _name, label: _label, color: _color, baseUri: _baseUri, HP: _HP, ...rest } = rows[0];
24
23
  const [currSort, setCurrSort] = (0, react_1.useState)({
25
24
  idx: 0,
26
25
  field: null,
27
26
  });
28
- return ((0, jsx_runtime_1.jsx)("div", { style: { height: 400, width: '100%' }, children: (0, jsx_runtime_1.jsx)(x_data_grid_1.DataGrid, { checkboxSelection: true, disableRowSelectionOnClick: true, onRowSelectionModelChange: arg => {
29
- setSelected(arg);
30
- }, rows: rows, rowHeight: 25, columnHeaderHeight: 33, columns: [
31
- {
32
- field: 'color',
33
- headerName: 'Color',
34
- renderCell: params => {
35
- const { value, id } = params;
36
- return ((0, jsx_runtime_1.jsx)(ColorPicker_1.default, { color: value || 'blue', onChange: c => {
37
- const elt = rows.find(f => f.name === id);
38
- if (elt) {
39
- elt.color = c;
40
- }
41
- onChange([...rows]);
42
- } }));
27
+ if (rows.length) {
28
+ const { id: _id, name: _name, label: _label, color: _color, baseUri: _baseUri, HP: _HP, ...rest } = rows[0];
29
+ return ((0, jsx_runtime_1.jsx)("div", { style: { height: 400, width: '100%' }, children: (0, jsx_runtime_1.jsx)(x_data_grid_1.DataGrid, { checkboxSelection: true, disableRowSelectionOnClick: true, onRowSelectionModelChange: arg => {
30
+ setSelected(arg);
31
+ }, rows: rows, rowHeight: 25, columnHeaderHeight: 33, columns: [
32
+ {
33
+ field: 'color',
34
+ headerName: 'Color',
35
+ renderCell: params => {
36
+ const { value, id } = params;
37
+ return ((0, jsx_runtime_1.jsx)(ColorPicker_1.default, { color: value || 'blue', onChange: c => {
38
+ const elt = rows.find(f => f.name === id);
39
+ if (elt) {
40
+ elt.color = c;
41
+ }
42
+ onChange([...rows]);
43
+ } }));
44
+ },
43
45
  },
44
- },
45
- {
46
- field: 'label',
47
- headerName: 'Name',
48
- width: (0, util_1.measureGridWidth)(rows.map(r => r.label)),
49
- },
50
- ...Object.keys(rest).map(val => ({
51
- field: val,
52
- renderCell: ({ value }) => ((0, jsx_runtime_1.jsx)("div", { className: classes.cell, children: (0, jsx_runtime_1.jsx)(ui_1.SanitizedHTML, { html: (0, util_1.getStr)(value) }) })),
53
- width: (0, util_1.measureGridWidth)(rows.map(r => `${r[val]}`)),
54
- })),
55
- ], sortModel: [], onSortModelChange: args => {
56
- const sort = args[0];
57
- const idx = (currSort.idx + 1) % 2;
58
- const field = sort.field || currSort.field;
59
- setCurrSort({ idx, field });
60
- onChange(field
61
- ? [...rows].sort((a, b) => {
62
- const aa = (0, util_1.getStr)(a[field]);
63
- const bb = (0, util_1.getStr)(b[field]);
64
- return idx === 1 ? aa.localeCompare(bb) : bb.localeCompare(aa);
65
- })
66
- : rows);
67
- } }) }));
46
+ {
47
+ field: 'label',
48
+ headerName: 'Name',
49
+ width: (0, util_1.measureGridWidth)(rows.map(r => r.label)),
50
+ },
51
+ ...Object.keys(rest).map(val => ({
52
+ field: val,
53
+ renderCell: ({ value }) => ((0, jsx_runtime_1.jsx)("div", { className: classes.cell, children: (0, jsx_runtime_1.jsx)(ui_1.SanitizedHTML, { html: (0, util_1.getStr)(value) }) })),
54
+ width: (0, util_1.measureGridWidth)(rows.map(r => `${r[val]}`)),
55
+ })),
56
+ ], sortModel: [], onSortModelChange: args => {
57
+ const sort = args[0];
58
+ const idx = (currSort.idx + 1) % 2;
59
+ const field = sort.field || currSort.field;
60
+ setCurrSort({ idx, field });
61
+ onChange(field
62
+ ? [...rows].sort((a, b) => {
63
+ const aa = (0, util_1.getStr)(a[field]);
64
+ const bb = (0, util_1.getStr)(b[field]);
65
+ return idx === 1
66
+ ? aa.localeCompare(bb)
67
+ : bb.localeCompare(aa);
68
+ })
69
+ : rows);
70
+ } }) }));
71
+ }
72
+ else {
73
+ return (0, jsx_runtime_1.jsx)("div", { children: "No rows, check sample metadata configuration" });
74
+ }
68
75
  }
@@ -28,12 +28,12 @@ function SourcesGridHeader({ selected, onChange, rows, showTips, }) {
28
28
  onChange((0, sourcesGridUtils_1.moveDown)([...rows], selected, rows.length));
29
29
  }, 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 => {
30
30
  setWidgetColor(c);
31
- selected.forEach(id => {
31
+ for (const id of selected) {
32
32
  const elt = rows.find(f => f.name === id);
33
33
  if (elt) {
34
34
  elt.color = c;
35
35
  }
36
- });
36
+ }
37
37
  onChange([...rows]);
38
38
  }, onClose: () => {
39
39
  setAnchorEl(null);
@@ -0,0 +1,15 @@
1
+ import type { SampleInfo, Source } from './types';
2
+ export declare function getSources({ sources, layout, renderingMode, sampleInfo, }: {
3
+ sources: Source[];
4
+ layout?: Source[];
5
+ renderingMode: string;
6
+ sampleInfo?: Record<string, SampleInfo>;
7
+ }): {
8
+ label: string;
9
+ id: string;
10
+ baseUri?: string;
11
+ name: string;
12
+ color?: string;
13
+ group?: string;
14
+ HP?: number;
15
+ }[];
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getSources = getSources;
4
+ function getSources({ sources, layout = sources, renderingMode, sampleInfo, }) {
5
+ const rows = [];
6
+ const sourceMap = Object.fromEntries(sources.map(s => [s.name, s]));
7
+ for (const row of layout) {
8
+ if (renderingMode === 'phased') {
9
+ const info = sampleInfo === null || sampleInfo === void 0 ? void 0 : sampleInfo[row.name];
10
+ if (info === null || info === void 0 ? void 0 : info.isPhased) {
11
+ const ploidy = info.maxPloidy;
12
+ for (let i = 0; i < ploidy; i++) {
13
+ const id = `${row.name} HP${i}`;
14
+ rows.push({
15
+ ...sourceMap[row.name],
16
+ ...row,
17
+ label: id,
18
+ HP: i,
19
+ id: id,
20
+ });
21
+ }
22
+ }
23
+ }
24
+ else {
25
+ rows.push({
26
+ ...sourceMap[row.name],
27
+ ...row,
28
+ label: row.name,
29
+ id: row.name,
30
+ });
31
+ }
32
+ }
33
+ return rows;
34
+ }
@@ -259,6 +259,15 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
259
259
  setSampleInfo(arg: Record<string, import("../shared/types").SampleInfo>): void;
260
260
  } & {
261
261
  readonly preSources: import("../shared/types").Source[] | undefined;
262
+ readonly sourcesWithoutLayout: {
263
+ label: string;
264
+ id: string;
265
+ baseUri?: string;
266
+ name: string;
267
+ color?: string;
268
+ group?: string;
269
+ HP?: number;
270
+ }[] | undefined;
262
271
  readonly sources: {
263
272
  label: string;
264
273
  id: string;
@@ -334,10 +343,20 @@ export declare function stateModelFactory(configSchema: AnyConfigurationSchemaTy
334
343
  type?: undefined;
335
344
  checked?: undefined;
336
345
  onClick?: undefined;
346
+ } | {
347
+ label: string;
348
+ icon: import("@mui/material/OverridableComponent").OverridableComponent<import("@mui/material").SvgIconTypeMap<{}, "svg">> & {
349
+ muiName: string;
350
+ };
351
+ onClick: () => void;
352
+ type?: undefined;
353
+ checked?: undefined;
354
+ subMenu?: undefined;
337
355
  })[];
338
356
  } & {
339
357
  readonly canDisplayLabels: boolean;
340
358
  readonly totalHeight: number;
359
+ readonly featuresReady: boolean;
341
360
  } & {
342
361
  renderProps(): any;
343
362
  } & {