@jbrowse/plugin-wiggle 3.2.0 → 3.4.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 (55) hide show
  1. package/dist/BigWigAdapter/BigWigAdapter.d.ts +0 -1
  2. package/dist/BigWigAdapter/BigWigAdapter.js +0 -1
  3. package/dist/LinearWiggleDisplay/model.d.ts +1 -1
  4. package/dist/MultiLinearWiggleDisplay/components/SourcesGrid.js +2 -2
  5. package/dist/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialog.d.ts → WiggleClusterDialog/WiggleClusterDialog.d.ts} +2 -2
  6. package/dist/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialog.js → WiggleClusterDialog/WiggleClusterDialog.js} +7 -7
  7. package/{esm/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogAuto.d.ts → dist/MultiLinearWiggleDisplay/components/WiggleClusterDialog/WiggleClusterDialogAuto.d.ts} +2 -2
  8. package/dist/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialogAuto.js → WiggleClusterDialog/WiggleClusterDialogAuto.js} +8 -5
  9. package/dist/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialogAuto.d.ts → WiggleClusterDialog/WiggleClusterDialogManual.d.ts} +3 -3
  10. package/dist/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialogManual.js → WiggleClusterDialog/WiggleClusterDialogManual.js} +32 -42
  11. package/dist/MultiLinearWiggleDisplay/components/YScaleBars.js +2 -2
  12. package/dist/MultiLinearWiggleDisplay/components/util.d.ts +3 -2
  13. package/dist/MultiLinearWiggleDisplay/model.d.ts +3 -1
  14. package/dist/MultiLinearWiggleDisplay/model.js +14 -2
  15. package/dist/MultiWiggleAdapter/MultiWiggleAdapter.d.ts +0 -1
  16. package/dist/MultiWiggleAdapter/MultiWiggleAdapter.js +0 -1
  17. package/dist/WiggleBaseRenderer.d.ts +4 -4
  18. package/dist/WiggleBaseRenderer.js +1 -1
  19. package/dist/WiggleRPC/MultiWiggleClusterScoreMatrix.js +2 -5
  20. package/dist/drawDensity.js +12 -4
  21. package/dist/drawLine.js +4 -2
  22. package/dist/drawXY.js +7 -3
  23. package/dist/shared/SharedWiggleMixin.d.ts +1 -1
  24. package/esm/BigWigAdapter/BigWigAdapter.d.ts +0 -1
  25. package/esm/BigWigAdapter/BigWigAdapter.js +0 -1
  26. package/esm/LinearWiggleDisplay/model.d.ts +1 -1
  27. package/esm/MultiLinearWiggleDisplay/components/SourcesGrid.js +2 -2
  28. package/esm/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialog.d.ts → WiggleClusterDialog/WiggleClusterDialog.d.ts} +2 -2
  29. package/esm/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialog.js → WiggleClusterDialog/WiggleClusterDialog.js} +7 -7
  30. package/{dist/MultiLinearWiggleDisplay/components/ClusterDialog/ClusterDialogManual.d.ts → esm/MultiLinearWiggleDisplay/components/WiggleClusterDialog/WiggleClusterDialogAuto.d.ts} +3 -3
  31. package/esm/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialogAuto.js → WiggleClusterDialog/WiggleClusterDialogAuto.js} +8 -5
  32. package/esm/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialogManual.d.ts → WiggleClusterDialog/WiggleClusterDialogManual.d.ts} +2 -2
  33. package/esm/MultiLinearWiggleDisplay/components/{ClusterDialog/ClusterDialogManual.js → WiggleClusterDialog/WiggleClusterDialogManual.js} +33 -43
  34. package/esm/MultiLinearWiggleDisplay/components/YScaleBars.js +2 -2
  35. package/esm/MultiLinearWiggleDisplay/components/util.d.ts +3 -2
  36. package/esm/MultiLinearWiggleDisplay/model.d.ts +3 -1
  37. package/esm/MultiLinearWiggleDisplay/model.js +14 -2
  38. package/esm/MultiWiggleAdapter/MultiWiggleAdapter.d.ts +0 -1
  39. package/esm/MultiWiggleAdapter/MultiWiggleAdapter.js +0 -1
  40. package/esm/WiggleBaseRenderer.d.ts +4 -4
  41. package/esm/WiggleBaseRenderer.js +1 -1
  42. package/esm/WiggleRPC/MultiWiggleClusterScoreMatrix.js +2 -5
  43. package/esm/drawDensity.js +12 -4
  44. package/esm/drawLine.js +4 -2
  45. package/esm/drawXY.js +7 -3
  46. package/esm/shared/SharedWiggleMixin.d.ts +1 -1
  47. package/package.json +10 -10
  48. package/dist/WiggleRPC/cluster.d.ts +0 -17
  49. package/dist/WiggleRPC/cluster.js +0 -84
  50. package/esm/WiggleRPC/cluster.d.ts +0 -17
  51. package/esm/WiggleRPC/cluster.js +0 -79
  52. /package/dist/MultiLinearWiggleDisplay/components/{ClusterDialog → WiggleClusterDialog}/types.d.ts +0 -0
  53. /package/dist/MultiLinearWiggleDisplay/components/{ClusterDialog → WiggleClusterDialog}/types.js +0 -0
  54. /package/esm/MultiLinearWiggleDisplay/components/{ClusterDialog → WiggleClusterDialog}/types.d.ts +0 -0
  55. /package/esm/MultiLinearWiggleDisplay/components/{ClusterDialog → WiggleClusterDialog}/types.js +0 -0
@@ -3,22 +3,22 @@ import { useState } from 'react';
3
3
  import { Dialog } from '@jbrowse/core/ui';
4
4
  import { FormControlLabel, Radio, RadioGroup } from '@mui/material';
5
5
  import { observer } from 'mobx-react';
6
- import ClusterDialogAuto from './ClusterDialogAuto';
7
- import ClusterDialogManual from './ClusterDialogManual';
6
+ import WiggleClusterDialogAuto from './WiggleClusterDialogAuto';
7
+ import WiggleClusterDialogManual from './WiggleClusterDialogManual';
8
8
  function Header({ activeMode, setActiveMode, }) {
9
9
  return (_jsx("div", { children: _jsx(RadioGroup, { children: Object.entries({
10
- auto: (_jsx("div", { children: "Run in-app clustering (slow for large data, built in JS clustering)" })),
11
- manual: (_jsx("div", { children: "Download R script to run clustering (faster for large data, uses hclust, may be more accurate)" })),
10
+ auto: (_jsx("div", { children: "Run in-app clustering (slower, particularly for large numbers of samples, uses JS implementation of hclust)" })),
11
+ manual: (_jsx("div", { children: "Download R script to run clustering (faster, uses R implementation of hclust)" })),
12
12
  }).map(([key, val]) => (_jsx(FormControlLabel, { control: _jsx(Radio, { checked: activeMode === key, onChange: () => {
13
13
  setActiveMode(key);
14
14
  } }), label: val }, key))) }) }));
15
15
  }
16
- const ClusterDialog = observer(function ({ model, handleClose, }) {
16
+ const WiggleClusterDialog = observer(function ({ model, handleClose, }) {
17
17
  const [activeMode, setActiveMode] = useState('auto');
18
18
  return (_jsx(Dialog, { open: true, title: "Cluster by score", maxWidth: "xl", onClose: (_, reason) => {
19
19
  if (reason !== 'backdropClick') {
20
20
  handleClose();
21
21
  }
22
- }, children: activeMode === 'auto' ? (_jsx(ClusterDialogAuto, { model: model, handleClose: handleClose, children: _jsx(Header, { activeMode: activeMode, setActiveMode: setActiveMode }) })) : (_jsx(ClusterDialogManual, { model: model, handleClose: handleClose, children: _jsx(Header, { activeMode: activeMode, setActiveMode: setActiveMode }) })) }));
22
+ }, children: activeMode === 'auto' ? (_jsx(WiggleClusterDialogAuto, { model: model, handleClose: handleClose, children: _jsx(Header, { activeMode: activeMode, setActiveMode: setActiveMode }) })) : (_jsx(WiggleClusterDialogManual, { model: model, handleClose: handleClose, children: _jsx(Header, { activeMode: activeMode, setActiveMode: setActiveMode }) })) }));
23
23
  });
24
- export default ClusterDialog;
24
+ export default WiggleClusterDialog;
@@ -1,7 +1,7 @@
1
1
  import type { ReducedModel } from './types';
2
- declare const ClusterDialogManuals: ({ model, handleClose, children, }: {
2
+ declare const WiggleClusterDialogAuto: ({ model, children, handleClose, }: {
3
3
  model: ReducedModel;
4
- handleClose: () => void;
5
4
  children: React.ReactNode;
5
+ handleClose: () => void;
6
6
  }) => import("react/jsx-runtime").JSX.Element;
7
- export default ClusterDialogManuals;
7
+ export default WiggleClusterDialogAuto;
@@ -7,9 +7,10 @@ import { getRpcSessionId } from '@jbrowse/core/util/tracks';
7
7
  import { Button, DialogActions, DialogContent, TextField, Typography, } from '@mui/material';
8
8
  import { observer } from 'mobx-react';
9
9
  import { isAlive } from 'mobx-state-tree';
10
- const ClusterDialogAuto = observer(function ({ model, children, handleClose, }) {
10
+ const WiggleClusterDialogAuto = observer(function ({ model, children, handleClose, }) {
11
11
  const [progress, setProgress] = useState('');
12
12
  const [error, setError] = useState();
13
+ const [loading, setLoading] = useState(false);
13
14
  const [stopToken, setStopToken] = useState('');
14
15
  const [showAdvanced, setShowAdvanced] = useState(false);
15
16
  const [samplesPerPixel, setSamplesPerPixel] = useLocalStorage('cluster-samplesPerPixel', '1');
@@ -17,12 +18,13 @@ const ClusterDialogAuto = observer(function ({ model, children, handleClose, })
17
18
  setShowAdvanced(!showAdvanced);
18
19
  }, children: showAdvanced ? 'Hide advanced options' : 'Show advanced options' }), showAdvanced ? (_jsxs("div", { style: { marginTop: 20 }, children: [_jsx(Typography, { children: "This procedure samples the data at each 'pixel' across the visible by default" }), _jsx(TextField, { label: "Samples per pixel (>1 for denser sampling, between 0-1 for sparser sampling)", variant: "outlined", size: "small", value: samplesPerPixel, onChange: event => {
19
20
  setSamplesPerPixel(event.target.value);
20
- } })] })) : null] }), _jsxs("div", { children: [progress ? (_jsxs("div", { style: { padding: 50 }, children: [_jsxs("span", { style: { width: 400 }, children: ["Progress: ", progress] }), _jsx(Button, { onClick: () => {
21
+ } })] })) : null] }), _jsxs("div", { children: [loading ? (_jsxs("div", { style: { padding: 50 }, children: [_jsx("span", { children: progress || 'Loading...' }), _jsx(Button, { onClick: () => {
21
22
  stopStopToken(stopToken);
22
- }, children: "Stop" })] })) : null, error ? _jsx(ErrorMessage, { error: error }) : null] })] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "contained", onClick: async () => {
23
+ }, children: "Stop" })] })) : null, error ? _jsx(ErrorMessage, { error: error }) : null] })] }), _jsxs(DialogActions, { children: [_jsx(Button, { variant: "contained", disabled: loading, onClick: async () => {
23
24
  try {
24
25
  setError(undefined);
25
- setProgress('');
26
+ setProgress('Initializing');
27
+ setLoading(true);
26
28
  const view = getContainingView(model);
27
29
  if (!view.initialized) {
28
30
  return;
@@ -61,6 +63,7 @@ const ClusterDialogAuto = observer(function ({ model, children, handleClose, })
61
63
  }
62
64
  }
63
65
  finally {
66
+ setLoading(false);
64
67
  setProgress('');
65
68
  setStopToken('');
66
69
  }
@@ -71,4 +74,4 @@ const ClusterDialogAuto = observer(function ({ model, children, handleClose, })
71
74
  }
72
75
  }, children: "Cancel" })] })] }));
73
76
  });
74
- export default ClusterDialogAuto;
77
+ export default WiggleClusterDialogAuto;
@@ -1,7 +1,7 @@
1
1
  import type { ReducedModel } from './types';
2
- declare const ClusterDialogManuals: ({ model, handleClose, children, }: {
2
+ declare const WiggleClusterDialogManuals: ({ model, handleClose, children, }: {
3
3
  model: ReducedModel;
4
4
  handleClose: () => void;
5
5
  children: React.ReactNode;
6
6
  }) => import("react/jsx-runtime").JSX.Element;
7
- export default ClusterDialogManuals;
7
+ export default WiggleClusterDialogManuals;
@@ -1,9 +1,8 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  import { useEffect, useState } from 'react';
3
- import { CascadingMenuButton, ErrorMessage, LoadingEllipses, } from '@jbrowse/core/ui';
3
+ import { ErrorMessage, LoadingEllipses } from '@jbrowse/core/ui';
4
4
  import { getContainingView, getSession, isAbortException, useLocalStorage, } from '@jbrowse/core/util';
5
5
  import { getRpcSessionId } from '@jbrowse/core/util/tracks';
6
- import MenuIcon from '@mui/icons-material/Menu';
7
6
  import { Button, DialogActions, DialogContent, FormControlLabel, Radio, RadioGroup, TextField, Typography, } from '@mui/material';
8
7
  import copy from 'copy-to-clipboard';
9
8
  import { saveAs } from 'file-saver';
@@ -20,15 +19,15 @@ const useStyles = makeStyles()(theme => ({
20
19
  gap: theme.spacing(4),
21
20
  },
22
21
  }));
23
- const ClusterDialogManuals = observer(function ({ model, handleClose, children, }) {
22
+ const WiggleClusterDialogManuals = observer(function ({ model, handleClose, children, }) {
24
23
  const { classes } = useStyles();
25
24
  const [paste, setPaste] = useState('');
26
25
  const [ret, setRet] = useState();
27
26
  const [error, setError] = useState();
28
27
  const [loading, setLoading] = useState(false);
29
- const [showAdvanced, setShowAdvanced] = useState(false);
30
- const [clusterMethod, setClusterMethod] = useLocalStorage('cluster-clusterMethod', 'single');
31
- const [samplesPerPixel, setSamplesPerPixel] = useLocalStorage('cluster-samplesPerPixel', '1');
28
+ const [showAdvanced, setShowAdvanced] = useLocalStorage('cluster-showAdvanced', false);
29
+ const [clusterMethod, setClusterMethod] = useState('single');
30
+ const [samplesPerPixel, setSamplesPerPixel] = useState('1');
32
31
  useEffect(() => {
33
32
  ;
34
33
  (async () => {
@@ -77,42 +76,33 @@ cat(resultClusters$order,sep='\\n')`
77
76
  .map(([key, val]) => [key, ...val].join('\t'))
78
77
  .join('\n')
79
78
  : undefined;
80
- return (_jsxs(_Fragment, { children: [_jsxs(DialogContent, { children: [children, _jsxs("div", { style: { marginTop: 50 }, children: [_jsxs("div", { style: {
81
- display: 'flex',
82
- gap: '8px',
83
- flexWrap: 'wrap',
84
- marginBottom: '16px',
85
- }, children: [_jsx(Button, { variant: "contained", onClick: () => {
86
- saveAs(new Blob([results || ''], {
87
- type: 'text/plain;charset=utf-8',
88
- }), 'cluster.R');
89
- }, children: "Download Rscript" }), ' ', "or", ' ', _jsx(Button, { variant: "contained", onClick: () => {
90
- copy(results || '');
91
- }, children: "Copy Rscript to clipboard" }), ' ', _jsx("div", { style: { float: 'right' }, children: _jsx(CascadingMenuButton, { menuItems: [
92
- {
93
- label: 'Download TSV',
94
- onClick: () => {
95
- saveAs(new Blob([resultsTsv || ''], {
96
- type: 'text/plain;charset=utf-8',
97
- }), 'scores.tsv');
98
- },
99
- },
100
- {
101
- label: showAdvanced
102
- ? 'Hide advanced options'
103
- : 'Show advanced options',
104
- onClick: () => {
105
- setShowAdvanced(!showAdvanced);
106
- },
107
- },
108
- ], children: _jsx(MenuIcon, {}) }) }), _jsx("div", { children: showAdvanced ? (_jsxs("div", { children: [_jsx(Typography, { variant: "h6", children: "Advanced options" }), _jsx(RadioGroup, { children: Object.entries({
109
- single: 'Single',
110
- complete: 'Complete',
111
- }).map(([key, val]) => (_jsx(FormControlLabel, { control: _jsx(Radio, { checked: clusterMethod === key, onChange: () => {
112
- setClusterMethod(key);
113
- } }), label: val }, key))) }), _jsxs("div", { style: { marginTop: 20 }, children: [_jsx(Typography, { children: "This procedure samples the data at each 'pixel' across the visible by default" }), _jsx(TextField, { label: "Samples per pixel (>1 for denser sampling, between 0-1 for sparser sampling)", variant: "outlined", size: "small", value: samplesPerPixel, onChange: event => {
114
- setSamplesPerPixel(event.target.value);
115
- } })] })] })) : null }), results ? (_jsx("div", {})) : loading ? (_jsx(LoadingEllipses, { variant: "h6", title: "Generating score matrix" })) : error ? (_jsx(ErrorMessage, { error: error })) : null] }), _jsxs("div", { children: [_jsx(Typography, { variant: "subtitle2", gutterBottom: true, style: { marginTop: '16px' }, children: "Clustering Results:" }), _jsx(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 => {
79
+ return (_jsxs(_Fragment, { children: [_jsxs(DialogContent, { children: [children, _jsxs("div", { style: { marginTop: 50 }, children: [_jsxs("div", { children: [_jsxs("div", { style: {
80
+ display: 'flex',
81
+ gap: '8px',
82
+ flexWrap: 'wrap',
83
+ marginBottom: '16px',
84
+ }, children: [_jsx(Button, { variant: "contained", onClick: () => {
85
+ saveAs(new Blob([results || ''], {
86
+ type: 'text/plain;charset=utf-8',
87
+ }), 'cluster.R');
88
+ }, children: "Download Rscript" }), ' ', "or", ' ', _jsx(Button, { variant: "contained", onClick: () => {
89
+ copy(results || '');
90
+ }, children: "Copy Rscript to clipboard" }), ' ', "or", ' ', _jsx(Button, { variant: "contained", onClick: () => {
91
+ saveAs(new Blob([resultsTsv || ''], {
92
+ type: 'text/plain;charset=utf-8',
93
+ }), 'scores.tsv');
94
+ }, children: "Download TSV" })] }), _jsx("div", { children: _jsx(Button, { variant: "contained", onClick: () => {
95
+ setShowAdvanced(!showAdvanced);
96
+ }, children: showAdvanced
97
+ ? 'Hide advanced options'
98
+ : 'Show advanced options' }) }), showAdvanced ? (_jsxs("div", { children: [_jsx(Typography, { variant: "h6", children: "Advanced options" }), _jsx(RadioGroup, { children: Object.entries({
99
+ single: 'Single',
100
+ complete: 'Complete',
101
+ }).map(([key, val]) => (_jsx(FormControlLabel, { control: _jsx(Radio, { checked: clusterMethod === key, onChange: () => {
102
+ setClusterMethod(key);
103
+ } }), label: val }, key))) }), _jsxs("div", { style: { marginTop: 20 }, children: [_jsx(Typography, { children: "This procedure samples the data at each 'pixel' across the visible by default" }), _jsx(TextField, { label: "Samples per pixel (>1 for denser sampling, between 0-1 for sparser sampling)", variant: "outlined", size: "small", value: samplesPerPixel, onChange: event => {
104
+ setSamplesPerPixel(event.target.value);
105
+ } })] })] })) : null, results ? (_jsx("div", {})) : loading ? (_jsx(LoadingEllipses, { variant: "h6", title: "Generating score matrix" })) : error ? (_jsx(ErrorMessage, { error: error })) : null] }), _jsxs("div", { children: [_jsx(Typography, { variant: "subtitle2", gutterBottom: true, style: { marginTop: '16px' }, children: "Clustering Results:" }), _jsx(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 => {
116
106
  setPaste(event.target.value);
117
107
  }, slotProps: {
118
108
  input: {
@@ -147,4 +137,4 @@ cat(resultClusters$order,sep='\\n')`
147
137
  handleClose();
148
138
  }, children: "Cancel" })] })] }));
149
139
  });
150
- export default ClusterDialogManuals;
140
+ export default WiggleClusterDialogManuals;
@@ -16,7 +16,7 @@ const Wrapper = observer(function ({ children, model, exportSVG, }) {
16
16
  });
17
17
  export const YScaleBars = observer(function (props) {
18
18
  const { model, orientation, exportSVG } = props;
19
- const { stats, needsFullHeightScalebar, sources } = model;
20
- return stats && sources ? (_jsx(Wrapper, { ...props, children: needsFullHeightScalebar ? (_jsx(FullHeightScaleBar, { model: model, orientation: orientation, exportSVG: exportSVG })) : (_jsx(IndividualScaleBars, { model: model, orientation: orientation, exportSVG: exportSVG })) })) : null;
19
+ const { showSidebar, stats, needsFullHeightScalebar, sources } = model;
20
+ return stats && sources ? (_jsx(Wrapper, { ...props, children: showSidebar ? (needsFullHeightScalebar ? (_jsx(FullHeightScaleBar, { model: model, orientation: orientation, exportSVG: exportSVG })) : (_jsx(IndividualScaleBars, { model: model, orientation: orientation, exportSVG: exportSVG }))) : null })) : null;
21
21
  });
22
22
  export default YScaleBars;
@@ -1,12 +1,13 @@
1
1
  import type { WiggleDisplayModel } from '../model';
2
+ import type { GridRowId } from '@mui/x-data-grid';
2
3
  export declare function moveUp(arr: {
3
4
  name: string;
4
- }[], sel: string[], by?: number): {
5
+ }[], sel: GridRowId[], by?: number): {
5
6
  name: string;
6
7
  }[];
7
8
  export declare function moveDown(arr: {
8
9
  name: string;
9
- }[], sel: string[], by?: number): {
10
+ }[], sel: GridRowId[], by?: number): {
10
11
  name: string;
11
12
  }[];
12
13
  export declare function getOffset(model: WiggleDisplayModel): number;
@@ -101,6 +101,7 @@ export declare function stateModelFactory(_pluginManager: PluginManager, configS
101
101
  } & {
102
102
  type: import("mobx-state-tree").ISimpleType<"MultiLinearWiggleDisplay">;
103
103
  layout: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree").IType<Source[], Source[], Source[]>, [undefined]>;
104
+ showSidebar: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
104
105
  }, {
105
106
  rendererTypeName: string;
106
107
  error: unknown;
@@ -213,7 +214,7 @@ export declare function stateModelFactory(_pluginManager: PluginManager, configS
213
214
  } & {
214
215
  addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
215
216
  deleteBlock(key: string): void;
216
- selectFeature(feature: Feature): void;
217
+ selectFeature(feature: Feature): Promise<void>;
217
218
  navToFeature(feature: Feature): void;
218
219
  clearFeatureSelection(): void;
219
220
  setFeatureIdUnderMouse(feature?: string): void;
@@ -327,6 +328,7 @@ export declare function stateModelFactory(_pluginManager: PluginManager, configS
327
328
  featureUnderMouseVolatile: Feature | undefined;
328
329
  sourcesVolatile: Source[] | undefined;
329
330
  } & {
331
+ setShowSidebar(arg: boolean): void;
330
332
  setSourcesLoading(str: string): void;
331
333
  setLayout(layout: Source[]): void;
332
334
  clearLayout(): void;
@@ -11,7 +11,7 @@ import { YSCALEBAR_LABEL_OFFSET, getScale } from '../util';
11
11
  const randomColor = () => '#000000'.replaceAll('0', () => (~~(Math.random() * 16)).toString(16));
12
12
  const Tooltip = lazy(() => import('./components/Tooltip'));
13
13
  const SetColorDialog = lazy(() => import('./components/SetColorDialog'));
14
- const ClusterDialog = lazy(() => import('./components/ClusterDialog/ClusterDialog'));
14
+ const WiggleClusterDialog = lazy(() => import('./components/WiggleClusterDialog/WiggleClusterDialog'));
15
15
  const rendererTypes = new Map([
16
16
  ['xyplot', 'MultiXYPlotRenderer'],
17
17
  ['multirowxy', 'MultiRowXYPlotRenderer'],
@@ -24,6 +24,7 @@ export function stateModelFactory(_pluginManager, configSchema) {
24
24
  .compose('MultiLinearWiggleDisplay', SharedWiggleMixin(configSchema), types.model({
25
25
  type: types.literal('MultiLinearWiggleDisplay'),
26
26
  layout: types.optional(types.frozen(), []),
27
+ showSidebar: true,
27
28
  }))
28
29
  .volatile(() => ({
29
30
  sourcesLoadingStopToken: undefined,
@@ -31,6 +32,9 @@ export function stateModelFactory(_pluginManager, configSchema) {
31
32
  sourcesVolatile: undefined,
32
33
  }))
33
34
  .actions(self => ({
35
+ setShowSidebar(arg) {
36
+ self.showSidebar = arg;
37
+ },
34
38
  setSourcesLoading(str) {
35
39
  if (self.sourcesLoadingStopToken) {
36
40
  stopStopToken(self.sourcesLoadingStopToken);
@@ -306,7 +310,7 @@ export function stateModelFactory(_pluginManager, configSchema) {
306
310
  label: 'Cluster by score',
307
311
  onClick: () => {
308
312
  getSession(self).queueDialog(handleClose => [
309
- ClusterDialog,
313
+ WiggleClusterDialog,
310
314
  {
311
315
  model: self,
312
316
  handleClose,
@@ -314,6 +318,14 @@ export function stateModelFactory(_pluginManager, configSchema) {
314
318
  ]);
315
319
  },
316
320
  },
321
+ {
322
+ label: 'Show sidebar',
323
+ type: 'checkbox',
324
+ checked: self.showSidebar,
325
+ onClick: () => {
326
+ self.setShowSidebar(!self.showSidebar);
327
+ },
328
+ },
317
329
  {
318
330
  label: 'Edit colors/arrangement...',
319
331
  onClick: () => {
@@ -26,6 +26,5 @@ export default class MultiWiggleAdapter extends BaseFeatureDataAdapter {
26
26
  name: string;
27
27
  __name: unknown;
28
28
  }[]>;
29
- freeResources(): void;
30
29
  }
31
30
  export {};
@@ -74,7 +74,6 @@ class MultiWiggleAdapter extends BaseFeatureDataAdapter {
74
74
  ...rest,
75
75
  }));
76
76
  }
77
- freeResources() { }
78
77
  }
79
78
  MultiWiggleAdapter.capabilities = [
80
79
  'hasResolution',
@@ -33,7 +33,7 @@ export default abstract class WiggleBaseRenderer extends FeatureRendererType {
33
33
  height: number;
34
34
  width: number;
35
35
  containsNoTransferables: boolean;
36
- canvasRecordedData: any;
36
+ canvasRecordedData: Record<string, unknown>;
37
37
  reactElement?: React.ReactElement;
38
38
  html?: string;
39
39
  } | {
@@ -41,15 +41,15 @@ export default abstract class WiggleBaseRenderer extends FeatureRendererType {
41
41
  height: number;
42
42
  width: number;
43
43
  containsNoTransferables: boolean;
44
- reactElement: import("react/jsx-runtime").JSX.Element;
44
+ imageData: any;
45
+ reactElement?: React.ReactElement;
45
46
  html?: string;
46
47
  } | {
47
48
  features: Map<string, Feature>;
48
49
  height: number;
49
50
  width: number;
50
51
  containsNoTransferables: boolean;
51
- imageData: any;
52
- reactElement?: React.ReactElement;
52
+ reactElement: React.ReactElement;
53
53
  html?: string;
54
54
  }>;
55
55
  abstract draw<T extends RenderArgsDeserializedWithFeatures>(ctx: CanvasRenderingContext2D, props: T): Promise<Record<string, unknown> | undefined>;
@@ -26,7 +26,7 @@ export default class WiggleBaseRenderer extends FeatureRendererType {
26
26
  ...results,
27
27
  ...rest,
28
28
  features: reducedFeatures
29
- ? new Map(reducedFeatures.map((r) => [r.id(), r]))
29
+ ? new Map(reducedFeatures.map(r => [r.id(), r]))
30
30
  : results.features,
31
31
  height,
32
32
  width,
@@ -1,5 +1,5 @@
1
1
  import RpcMethodTypeWithFiltersAndRenameRegions from '@jbrowse/core/pluggableElementTypes/RpcMethodTypeWithFiltersAndRenameRegions';
2
- import { clusterData } from './cluster';
2
+ import { clusterData } from '@jbrowse/core/util/cluster';
3
3
  import { getScoreMatrix } from './getScoreMatrix';
4
4
  export class MultiWiggleClusterScoreMatrix extends RpcMethodTypeWithFiltersAndRenameRegions {
5
5
  constructor() {
@@ -17,11 +17,8 @@ export class MultiWiggleClusterScoreMatrix extends RpcMethodTypeWithFiltersAndRe
17
17
  stopToken: deserializedArgs.stopToken,
18
18
  onProgress: a => {
19
19
  var _a;
20
- (_a = deserializedArgs.statusCallback) === null || _a === void 0 ? void 0 : _a.call(deserializedArgs, `${toP(a * 100)}%`);
20
+ (_a = deserializedArgs.statusCallback) === null || _a === void 0 ? void 0 : _a.call(deserializedArgs, a);
21
21
  },
22
22
  });
23
23
  }
24
24
  }
25
- function toP(n) {
26
- return Number.parseFloat(n.toPrecision(3));
27
- }
@@ -36,15 +36,21 @@ export function drawDensity(ctx, props) {
36
36
  start = performance.now();
37
37
  }
38
38
  const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
39
- if (Math.floor(leftPx) !== Math.floor(prevLeftPx)) {
39
+ if (Math.floor(leftPx) !== Math.floor(prevLeftPx) || rightPx - leftPx > 1) {
40
40
  reducedFeatures.push(feature);
41
41
  prevLeftPx = leftPx;
42
42
  }
43
43
  const score = feature.get('score');
44
44
  hasClipping = hasClipping || score > niceMax || score < niceMin;
45
45
  const w = rightPx - leftPx + fudgeFactor;
46
- ctx.fillStyle = cb(feature, score);
47
- ctx.fillRect(leftPx, 0, w, height);
46
+ if (score >= scaleOpts.domain[0]) {
47
+ ctx.fillStyle = cb(feature, score);
48
+ ctx.fillRect(leftPx, 0, w, height);
49
+ }
50
+ else {
51
+ ctx.fillStyle = '#eee';
52
+ ctx.fillRect(leftPx, 0, w, height);
53
+ }
48
54
  }
49
55
  ctx.save();
50
56
  if (hasClipping) {
@@ -66,5 +72,7 @@ export function drawDensity(ctx, props) {
66
72
  }
67
73
  }
68
74
  ctx.restore();
69
- return { reducedFeatures };
75
+ return {
76
+ reducedFeatures,
77
+ };
70
78
  }
package/esm/drawLine.js CHANGED
@@ -25,7 +25,7 @@ export function drawLine(ctx, props) {
25
25
  start = performance.now();
26
26
  }
27
27
  const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
28
- if (Math.floor(leftPx) !== Math.floor(prevLeftPx)) {
28
+ if (Math.floor(leftPx) !== Math.floor(prevLeftPx) || rightPx - leftPx > 1) {
29
29
  reducedFeatures.push(feature);
30
30
  prevLeftPx = leftPx;
31
31
  }
@@ -68,5 +68,7 @@ export function drawLine(ctx, props) {
68
68
  ctx.stroke();
69
69
  }
70
70
  }
71
- return { reducedFeatures };
71
+ return {
72
+ reducedFeatures,
73
+ };
72
74
  }
package/esm/drawXY.js CHANGED
@@ -89,7 +89,8 @@ export function drawXY(ctx, props) {
89
89
  .toString())
90
90
  : c;
91
91
  const w = Math.max(rightPx - leftPx + fudgeFactor, minSize);
92
- if (Math.floor(leftPx) !== Math.floor(prevLeftPx)) {
92
+ if (Math.floor(leftPx) !== Math.floor(prevLeftPx) ||
93
+ rightPx - leftPx > 1) {
93
94
  reducedFeatures.push(feature);
94
95
  prevLeftPx = leftPx;
95
96
  }
@@ -128,7 +129,8 @@ export function drawXY(ctx, props) {
128
129
  start = performance.now();
129
130
  }
130
131
  const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx);
131
- if (Math.floor(leftPx) !== Math.floor(prevLeftPx)) {
132
+ if (Math.floor(leftPx) !== Math.floor(prevLeftPx) ||
133
+ rightPx - leftPx > 1) {
132
134
  reducedFeatures.push(feature);
133
135
  prevLeftPx = leftPx;
134
136
  }
@@ -180,5 +182,7 @@ export function drawXY(ctx, props) {
180
182
  ctx.stroke();
181
183
  }
182
184
  }
183
- return { reducedFeatures };
185
+ return {
186
+ reducedFeatures,
187
+ };
184
188
  }
@@ -206,7 +206,7 @@ export default function SharedWiggleMixin(configSchema: AnyConfigurationSchemaTy
206
206
  } & {
207
207
  addBlock(key: string, block: import("@jbrowse/core/util/blockTypes").BaseBlock): void;
208
208
  deleteBlock(key: string): void;
209
- selectFeature(feature: Feature): void;
209
+ selectFeature(feature: Feature): Promise<void>;
210
210
  navToFeature(feature: Feature): void;
211
211
  clearFeatureSelection(): void;
212
212
  setFeatureIdUnderMouse(feature?: string): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jbrowse/plugin-wiggle",
3
- "version": "3.2.0",
3
+ "version": "3.4.0",
4
4
  "description": "JBrowse 2 wiggle adapters, tracks, etc.",
5
5
  "keywords": [
6
6
  "jbrowse",
@@ -36,14 +36,14 @@
36
36
  "clean": "rimraf dist esm *.tsbuildinfo"
37
37
  },
38
38
  "dependencies": {
39
- "@gmod/bbi": "^6.0.0",
40
- "@jbrowse/core": "^3.2.0",
41
- "@jbrowse/plugin-data-management": "^3.2.0",
42
- "@jbrowse/plugin-linear-genome-view": "^3.2.0",
43
- "@mui/icons-material": "^6.0.0",
44
- "@mui/material": "^6.0.0",
45
- "@mui/x-charts-vendor": "^7.12.0",
46
- "@mui/x-data-grid": "^7.0.0",
39
+ "@gmod/bbi": "^7.0.0",
40
+ "@jbrowse/core": "^3.4.0",
41
+ "@jbrowse/plugin-data-management": "^3.4.0",
42
+ "@jbrowse/plugin-linear-genome-view": "^3.4.0",
43
+ "@mui/icons-material": "^7.0.0",
44
+ "@mui/material": "^7.0.0",
45
+ "@mui/x-charts-vendor": "^8.0.0",
46
+ "@mui/x-data-grid": "^8.0.0",
47
47
  "fast-deep-equal": "^3.1.3",
48
48
  "mobx": "^6.0.0",
49
49
  "mobx-react": "^9.0.0",
@@ -62,5 +62,5 @@
62
62
  "distModule": "esm/index.js",
63
63
  "srcModule": "src/index.ts",
64
64
  "module": "esm/index.js",
65
- "gitHead": "c750e3f56706a490c19ba75abd807fec5e38aebf"
65
+ "gitHead": "a9f1ac35fc2dd810bae92cdaf1fc19995bee4413"
66
66
  }
@@ -1,17 +0,0 @@
1
- export declare function euclideanDistance(a: number[], b: number[]): number;
2
- export declare function averageDistance(setA: number[], setB: number[], distances: number[][]): number;
3
- export declare function clusterData({ data, distance, linkage, onProgress, stopToken, }: {
4
- data: number[][];
5
- distance?: (a: number[], b: number[]) => number;
6
- linkage?: (a: number[], b: number[], distances: number[][]) => number;
7
- onProgress?: (a: number) => void;
8
- stopToken?: string;
9
- }): {
10
- clusters: {
11
- height: number;
12
- indexes: number[];
13
- } | undefined;
14
- distances: number[][];
15
- order: number[];
16
- clustersGivenK: number[][][];
17
- };
@@ -1,84 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.euclideanDistance = euclideanDistance;
4
- exports.averageDistance = averageDistance;
5
- exports.clusterData = clusterData;
6
- const stopToken_1 = require("@jbrowse/core/util/stopToken");
7
- function euclideanDistance(a, b) {
8
- const size = Math.min(a.length, b.length);
9
- let sum = 0;
10
- for (let index = 0; index < size; index++) {
11
- sum += (a[index] - b[index]) * (a[index] - b[index]);
12
- }
13
- return Math.sqrt(sum);
14
- }
15
- function averageDistance(setA, setB, distances) {
16
- let distance = 0;
17
- for (const a of setA) {
18
- for (const b of setB) {
19
- distance += distances[a][b];
20
- }
21
- }
22
- return distance / setA.length / setB.length;
23
- }
24
- function updateProgress(stepNumber, stepProgress, onProgress) {
25
- onProgress(stepNumber / 2 + stepProgress / 2);
26
- }
27
- function clusterData({ data, distance = euclideanDistance, linkage = averageDistance, onProgress, stopToken, }) {
28
- const distances = data.map((datum, index) => {
29
- if (onProgress) {
30
- updateProgress(0, index / (data.length - 1), onProgress);
31
- }
32
- return data.map(otherDatum => distance(datum, otherDatum));
33
- });
34
- const clusters = data.map((_datum, index) => ({
35
- height: 0,
36
- indexes: [Number(index)],
37
- }));
38
- let clustersGivenK = [];
39
- let start = performance.now();
40
- for (let iteration = 0; iteration < data.length; iteration++) {
41
- if (performance.now() - start > 2000) {
42
- (0, stopToken_1.checkStopToken)(stopToken);
43
- start = performance.now();
44
- }
45
- if (onProgress) {
46
- updateProgress(1, (iteration + 1) / data.length, onProgress);
47
- }
48
- clustersGivenK.push(clusters.map(cluster => cluster.indexes));
49
- if (iteration >= data.length - 1) {
50
- break;
51
- }
52
- let nearestDistance = Infinity;
53
- let nearestRow = 0;
54
- let nearestCol = 0;
55
- for (let row = 0; row < clusters.length; row++) {
56
- for (let col = row + 1; col < clusters.length; col++) {
57
- const distance = linkage(clusters[row].indexes, clusters[col].indexes, distances);
58
- if (distance < nearestDistance) {
59
- nearestDistance = distance;
60
- nearestRow = row;
61
- nearestCol = col;
62
- }
63
- }
64
- }
65
- const newCluster = {
66
- indexes: [
67
- ...clusters[nearestRow].indexes,
68
- ...clusters[nearestCol].indexes,
69
- ],
70
- height: nearestDistance,
71
- children: [clusters[nearestRow], clusters[nearestCol]],
72
- };
73
- clusters.splice(Math.max(nearestRow, nearestCol), 1);
74
- clusters.splice(Math.min(nearestRow, nearestCol), 1);
75
- clusters.push(newCluster);
76
- }
77
- clustersGivenK = [[], ...clustersGivenK.reverse()];
78
- return {
79
- clusters: clusters[0],
80
- distances: distances,
81
- order: clusters[0].indexes,
82
- clustersGivenK: clustersGivenK,
83
- };
84
- }