@vitessce/statistical-plots 2.0.3-beta.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +85871 -6
- package/dist-tsc/CellSetExpressionPlot.d.ts +33 -0
- package/dist-tsc/CellSetExpressionPlot.d.ts.map +1 -0
- package/{dist → dist-tsc}/CellSetExpressionPlot.js +3 -3
- package/dist-tsc/CellSetExpressionPlotOptions.d.ts +2 -0
- package/dist-tsc/CellSetExpressionPlotOptions.d.ts.map +1 -0
- package/{dist → dist-tsc}/CellSetExpressionPlotOptions.js +1 -3
- package/dist-tsc/CellSetExpressionPlotSubscriber.d.ts +16 -0
- package/dist-tsc/CellSetExpressionPlotSubscriber.d.ts.map +1 -0
- package/{dist → dist-tsc}/CellSetExpressionPlotSubscriber.js +7 -11
- package/dist-tsc/CellSetSizesPlot.d.ts +29 -0
- package/dist-tsc/CellSetSizesPlot.d.ts.map +1 -0
- package/dist-tsc/CellSetSizesPlot.js +149 -0
- package/dist-tsc/CellSetSizesPlotSubscriber.d.ts +18 -0
- package/dist-tsc/CellSetSizesPlotSubscriber.d.ts.map +1 -0
- package/dist-tsc/CellSetSizesPlotSubscriber.js +77 -0
- package/dist-tsc/ExpressionHistogram.d.ts +34 -0
- package/dist-tsc/ExpressionHistogram.d.ts.map +1 -0
- package/dist-tsc/ExpressionHistogram.js +93 -0
- package/dist-tsc/ExpressionHistogramSubscriber.d.ts +16 -0
- package/dist-tsc/ExpressionHistogramSubscriber.d.ts.map +1 -0
- package/{dist → dist-tsc}/ExpressionHistogramSubscriber.js +21 -14
- package/dist-tsc/index.d.ts +7 -0
- package/dist-tsc/index.d.ts.map +1 -0
- package/dist-tsc/index.js +6 -0
- package/dist-tsc/styles.d.ts +2 -0
- package/dist-tsc/styles.d.ts.map +1 -0
- package/{dist → dist-tsc}/styles.js +1 -1
- package/package.json +20 -11
- package/src/CellSetExpressionPlot.js +278 -0
- package/src/CellSetExpressionPlotOptions.js +73 -0
- package/src/CellSetExpressionPlotSubscriber.js +220 -0
- package/src/CellSetSizesPlot.js +173 -0
- package/src/CellSetSizesPlotSubscriber.js +151 -0
- package/src/ExpressionHistogram.js +120 -0
- package/src/ExpressionHistogramSubscriber.js +136 -0
- package/src/index.js +6 -0
- package/src/styles.js +9 -0
- package/dist/CellSetSizesPlot.js +0 -77
- package/dist/CellSetSizesPlotSubscriber.js +0 -44
- package/dist/DotPlot.js +0 -110
- package/dist/DotPlotSubscriber.js +0 -126
- package/dist/ExpressionHistogram.js +0 -49
@@ -0,0 +1,33 @@
|
|
1
|
+
/**
|
2
|
+
* Gene expression histogram displayed as a bar chart,
|
3
|
+
* implemented with the VegaPlot component.
|
4
|
+
* @param {object} props
|
5
|
+
* @param {object[]} props.data The expression data, an array
|
6
|
+
* of objects with properties `value`, `gene`, and `set`.
|
7
|
+
* @param {number} props.domainMax The maximum gene expression value.
|
8
|
+
* @param {object[]} props.colors An object for each
|
9
|
+
* cell set, with properties `name` and `color`.
|
10
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
11
|
+
* @param {number} props.width The container width.
|
12
|
+
* @param {number} props.height The container height.
|
13
|
+
* @param {number} props.marginRight The size of the margin
|
14
|
+
* on the right side of the plot, to account for the vega menu button.
|
15
|
+
* By default, 90.
|
16
|
+
* @param {number} props.marginBottom The size of the margin
|
17
|
+
* on the bottom of the plot, to account for long x-axis labels.
|
18
|
+
* Default is allowing the component to automatically determine the margin.
|
19
|
+
* @param {string|null} props.featureValueTransformName A name
|
20
|
+
* for the feature value transformation function.
|
21
|
+
*/
|
22
|
+
export default function CellSetExpressionPlot(props: {
|
23
|
+
data: object[];
|
24
|
+
domainMax: number;
|
25
|
+
colors: object[];
|
26
|
+
theme: string;
|
27
|
+
width: number;
|
28
|
+
height: number;
|
29
|
+
marginRight: number;
|
30
|
+
marginBottom: number;
|
31
|
+
featureValueTransformName: string | null;
|
32
|
+
}): JSX.Element;
|
33
|
+
//# sourceMappingURL=CellSetExpressionPlot.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CellSetExpressionPlot.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlot.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH;IAjB2B,IAAI,EAApB,MAAM,EAAE;IAEM,SAAS,EAAvB,MAAM;IACU,MAAM,EAAtB,MAAM,EAAE;IAEM,KAAK,EAAnB,MAAM;IACQ,KAAK,EAAnB,MAAM;IACQ,MAAM,EAApB,MAAM;IACQ,WAAW,EAAzB,MAAM;IAGQ,YAAY,EAA1B,MAAM;IAGa,yBAAyB,EAA5C,MAAM,GAAC,IAAI;gBA6PrB"}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
-
import clamp from 'lodash
|
3
|
+
import { clamp } from 'lodash-es';
|
4
4
|
import { VegaPlot, VEGA_THEMES, DATASET_NAME } from '@vitessce/vega';
|
5
5
|
import { colorArrayToString } from '@vitessce/sets-utils';
|
6
6
|
import { capitalize } from '@vitessce/utils';
|
@@ -135,8 +135,8 @@ export default function CellSetExpressionPlot(props) {
|
|
135
135
|
scale: 'yscale',
|
136
136
|
zindex: 1,
|
137
137
|
title: (featureValueTransformName && featureValueTransformName !== 'None')
|
138
|
-
? [`${featureValueTransformName}-Transformed`,
|
139
|
-
:
|
138
|
+
? [`${featureValueTransformName}-Transformed`, `${capitalize(featureValueType)} Values`]
|
139
|
+
: `${capitalize(featureValueType)} Values`,
|
140
140
|
},
|
141
141
|
{
|
142
142
|
orient: 'bottom',
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CellSetExpressionPlotOptions.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlotOptions.js"],"names":[],"mappings":"AAIA,8EAoEC"}
|
@@ -1,8 +1,6 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import React from 'react';
|
3
|
-
import TableCell from '@material-ui/core
|
4
|
-
import TableRow from '@material-ui/core/TableRow';
|
5
|
-
import TextField from '@material-ui/core/TextField';
|
3
|
+
import { TableCell, TableRow, TextField } from '@material-ui/core';
|
6
4
|
import { usePlotOptionsStyles, OptionsContainer, OptionSelect } from '@vitessce/vit-s';
|
7
5
|
export default function CellSetExpressionPlotOptions(props) {
|
8
6
|
const { featureValueTransform, setFeatureValueTransform, featureValueTransformCoefficient, setFeatureValueTransformCoefficient, transformOptions, } = props;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
/**
|
2
|
+
* A subscriber component for `CellSetExpressionPlot`,
|
3
|
+
* which listens for gene selection updates and
|
4
|
+
* `GRID_RESIZE` events.
|
5
|
+
* @param {object} props
|
6
|
+
* @param {function} props.removeGridComponent The grid component removal function.
|
7
|
+
* @param {object} props.coordinationScopes An object mapping coordination
|
8
|
+
* types to coordination scopes.
|
9
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
10
|
+
*/
|
11
|
+
export function CellSetExpressionPlotSubscriber(props: {
|
12
|
+
removeGridComponent: Function;
|
13
|
+
coordinationScopes: object;
|
14
|
+
theme: string;
|
15
|
+
}): JSX.Element;
|
16
|
+
//# sourceMappingURL=CellSetExpressionPlotSubscriber.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CellSetExpressionPlotSubscriber.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlotSubscriber.js"],"names":[],"mappings":"AAiGA;;;;;;;;;GASG;AACH;IAL2B,mBAAmB;IACrB,kBAAkB,EAAhC,MAAM;IAEQ,KAAK,EAAnB,MAAM;gBAkHhB"}
|
@@ -1,12 +1,12 @@
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
2
|
import React, { useMemo } from 'react';
|
3
|
-
import { TitleInfo, useCoordination, useLoaders, useUrls, useReady, useGridItemSize, useFeatureSelection, useObsSetsData, useObsFeatureMatrixIndices, useFeatureLabelsData,
|
3
|
+
import { TitleInfo, useCoordination, useLoaders, useUrls, useReady, useGridItemSize, useFeatureSelection, useObsSetsData, useObsFeatureMatrixIndices, useFeatureLabelsData, } from '@vitessce/vit-s';
|
4
4
|
import { ViewType, COMPONENT_COORDINATION_TYPES } from '@vitessce/constants-internal';
|
5
5
|
import { VALUE_TRANSFORM_OPTIONS, capitalize, getValueTransformFunction } from '@vitessce/utils';
|
6
6
|
import { treeToObjectsBySetNames, treeToSetSizesBySetNames, mergeObsSets } from '@vitessce/sets-utils';
|
7
|
-
import CellSetExpressionPlotOptions from './CellSetExpressionPlotOptions';
|
8
|
-
import CellSetExpressionPlot from './CellSetExpressionPlot';
|
9
|
-
import { useStyles } from './styles';
|
7
|
+
import CellSetExpressionPlotOptions from './CellSetExpressionPlotOptions.js';
|
8
|
+
import CellSetExpressionPlot from './CellSetExpressionPlot.js';
|
9
|
+
import { useStyles } from './styles.js';
|
10
10
|
/**
|
11
11
|
* Get expression data for the cells
|
12
12
|
* in the selected cell sets.
|
@@ -28,7 +28,7 @@ import { useStyles } from './styles';
|
|
28
28
|
* @param {string} theme "light" or "dark" for the vitessce theme
|
29
29
|
* `path` and `color`.
|
30
30
|
*/
|
31
|
-
|
31
|
+
function useExpressionByCellSet(expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, theme) {
|
32
32
|
const mergedCellSets = useMemo(() => mergeObsSets(cellSets, additionalCellSets), [cellSets, additionalCellSets]);
|
33
33
|
// From the expression matrix and the list of selected genes / cell sets,
|
34
34
|
// generate the array of data points for the plot.
|
@@ -47,9 +47,8 @@ export function useExpressionByCellSet(expressionData, obsIndex, cellSets, addit
|
|
47
47
|
const exprValues = cellObjects.map((cell) => {
|
48
48
|
const cellIndex = cellIndices[cell.obsId];
|
49
49
|
const value = expressionData[0][cellIndex];
|
50
|
-
const normValue = value * 100 / 255;
|
51
50
|
const transformFunction = getValueTransformFunction(featureValueTransform, featureValueTransformCoefficient);
|
52
|
-
const transformedValue = transformFunction(
|
51
|
+
const transformedValue = transformFunction(value);
|
53
52
|
exprMax = Math.max(transformedValue, exprMax);
|
54
53
|
return { value: transformedValue, gene: firstGeneSelected, set: cell.name };
|
55
54
|
});
|
@@ -63,7 +62,7 @@ export function useExpressionByCellSet(expressionData, obsIndex, cellSets, addit
|
|
63
62
|
// From the cell sets hierarchy and the list of selected cell sets,
|
64
63
|
// generate the array of set sizes data points for the bar plot.
|
65
64
|
const setArr = useMemo(() => (mergedCellSets && cellSetSelection && cellSetColor
|
66
|
-
? treeToSetSizesBySetNames(mergedCellSets, cellSetSelection, cellSetColor, theme)
|
65
|
+
? treeToSetSizesBySetNames(mergedCellSets, cellSetSelection, cellSetSelection, cellSetColor, theme)
|
67
66
|
: []), [mergedCellSets, cellSetSelection, cellSetColor, theme]);
|
68
67
|
return [expressionArr, setArr, expressionMax];
|
69
68
|
}
|
@@ -106,6 +105,3 @@ export function CellSetExpressionPlotSubscriber(props) {
|
|
106
105
|
const selectedTransformName = transformOptions.find(o => o.value === featureValueTransform)?.name;
|
107
106
|
return (_jsx(TitleInfo, { title: `Expression by ${capitalize(obsType)} Set${(firstGeneSelected ? ` (${firstGeneSelected})` : '')}`, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, options: (_jsx(CellSetExpressionPlotOptions, { featureValueTransform: featureValueTransform, setFeatureValueTransform: setFeatureValueTransform, featureValueTransformCoefficient: featureValueTransformCoefficient, setFeatureValueTransformCoefficient: setFeatureValueTransformCoefficient, transformOptions: transformOptions })), children: _jsx("div", { ref: containerRef, className: classes.vegaContainer, children: expressionArr ? (_jsx(CellSetExpressionPlot, { domainMax: expressionMax, colors: setArr, data: expressionArr, theme: theme, width: width, height: height, obsType: obsType, featureValueType: featureValueType, featureValueTransformName: selectedTransformName })) : (_jsxs("span", { children: ["Select a ", featureType, "."] })) }) }));
|
108
107
|
}
|
109
|
-
export function register() {
|
110
|
-
registerPluginViewType(ViewType.OBS_SET_FEATURE_VALUE_DISTRIBUTION, CellSetExpressionPlotSubscriber, COMPONENT_COORDINATION_TYPES[ViewType.OBS_SET_FEATURE_VALUE_DISTRIBUTION]);
|
111
|
-
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
/**
|
2
|
+
* Cell set sizes displayed as a bar chart,
|
3
|
+
* implemented with the VegaPlot component.
|
4
|
+
* @param {object} props
|
5
|
+
* @param {object[]} props.data The set size data, an array
|
6
|
+
* of objects with properties `name`, `key`, `color`, and `size`.
|
7
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
8
|
+
* @param {number} props.width The container width.
|
9
|
+
* @param {number} props.height The container height.
|
10
|
+
* @param {number} props.marginRight The size of the margin
|
11
|
+
* on the right side of the plot, to account for the vega menu button.
|
12
|
+
* By default, 90.
|
13
|
+
* @param {number} props.marginBottom The size of the margin
|
14
|
+
* on the bottom of the plot, to account for long x-axis labels.
|
15
|
+
* By default, 120.
|
16
|
+
* @param {number} props.keyLength The length of the `key` property of
|
17
|
+
* each data point. Assumes all key strings have the same length.
|
18
|
+
* By default, 36.
|
19
|
+
*/
|
20
|
+
export default function CellSetSizesPlot(props: {
|
21
|
+
data: object[];
|
22
|
+
theme: string;
|
23
|
+
width: number;
|
24
|
+
height: number;
|
25
|
+
marginRight: number;
|
26
|
+
marginBottom: number;
|
27
|
+
keyLength: number;
|
28
|
+
}): JSX.Element;
|
29
|
+
//# sourceMappingURL=CellSetSizesPlot.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CellSetSizesPlot.d.ts","sourceRoot":"","sources":["../src/CellSetSizesPlot.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;GAkBG;AACH;IAf2B,IAAI,EAApB,MAAM,EAAE;IAEM,KAAK,EAAnB,MAAM;IACQ,KAAK,EAAnB,MAAM;IACQ,MAAM,EAApB,MAAM;IACQ,WAAW,EAAzB,MAAM;IAGQ,YAAY,EAA1B,MAAM;IAGQ,SAAS,EAAvB,MAAM;gBAuJhB"}
|
@@ -0,0 +1,149 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import React, { useCallback } from 'react';
|
3
|
+
import { clamp } from 'lodash-es';
|
4
|
+
import { VegaPlot, VEGA_THEMES } from '@vitessce/vega';
|
5
|
+
import { colorArrayToString } from '@vitessce/sets-utils';
|
6
|
+
import { capitalize, getDefaultColor } from '@vitessce/utils';
|
7
|
+
/**
|
8
|
+
* Cell set sizes displayed as a bar chart,
|
9
|
+
* implemented with the VegaPlot component.
|
10
|
+
* @param {object} props
|
11
|
+
* @param {object[]} props.data The set size data, an array
|
12
|
+
* of objects with properties `name`, `key`, `color`, and `size`.
|
13
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
14
|
+
* @param {number} props.width The container width.
|
15
|
+
* @param {number} props.height The container height.
|
16
|
+
* @param {number} props.marginRight The size of the margin
|
17
|
+
* on the right side of the plot, to account for the vega menu button.
|
18
|
+
* By default, 90.
|
19
|
+
* @param {number} props.marginBottom The size of the margin
|
20
|
+
* on the bottom of the plot, to account for long x-axis labels.
|
21
|
+
* By default, 120.
|
22
|
+
* @param {number} props.keyLength The length of the `key` property of
|
23
|
+
* each data point. Assumes all key strings have the same length.
|
24
|
+
* By default, 36.
|
25
|
+
*/
|
26
|
+
export default function CellSetSizesPlot(props) {
|
27
|
+
const { data: rawData, theme, width, height, marginRight = 90, marginBottom = 120, keyLength = 36, obsType, onBarSelect, } = props;
|
28
|
+
// Add a property `keyName` which concatenates the key and the name,
|
29
|
+
// which is both unique and can easily be converted
|
30
|
+
// back to the name by taking a substring.
|
31
|
+
// Add a property `colorString` which contains the `[r, g, b]` color
|
32
|
+
// after converting to a color hex string.
|
33
|
+
const data = rawData.map(d => ({
|
34
|
+
...d,
|
35
|
+
keyName: d.key + d.name,
|
36
|
+
colorString: colorArrayToString(d.color),
|
37
|
+
}));
|
38
|
+
// Get an array of keys for sorting purposes.
|
39
|
+
const keys = data.map(d => d.keyName);
|
40
|
+
const colorScale = {
|
41
|
+
// Manually set the color scale so that Vega-Lite does
|
42
|
+
// not choose the colors automatically.
|
43
|
+
domain: data.map(d => d.key),
|
44
|
+
range: data.map((d) => {
|
45
|
+
const [r, g, b] = !d.isGrayedOut ? d.color : getDefaultColor(theme);
|
46
|
+
return `rgba(${r}, ${g}, ${b}, 1)`;
|
47
|
+
}),
|
48
|
+
};
|
49
|
+
const captializedObsType = capitalize(obsType);
|
50
|
+
const spec = {
|
51
|
+
mark: { type: 'bar', stroke: 'black', cursor: 'pointer' },
|
52
|
+
params: [
|
53
|
+
{
|
54
|
+
name: 'highlight',
|
55
|
+
select: {
|
56
|
+
type: 'point',
|
57
|
+
on: 'mouseover',
|
58
|
+
},
|
59
|
+
},
|
60
|
+
{
|
61
|
+
name: 'select',
|
62
|
+
select: 'point',
|
63
|
+
},
|
64
|
+
{
|
65
|
+
name: 'bar_select',
|
66
|
+
select: {
|
67
|
+
type: 'point',
|
68
|
+
on: 'click[event.shiftKey === false]',
|
69
|
+
fields: ['setNamePath', 'isGrayedOut'],
|
70
|
+
empty: 'none',
|
71
|
+
},
|
72
|
+
},
|
73
|
+
{
|
74
|
+
name: 'shift_bar_select',
|
75
|
+
select: {
|
76
|
+
type: 'point',
|
77
|
+
on: 'click[event.shiftKey]',
|
78
|
+
fields: ['setNamePath', 'isGrayedOut'],
|
79
|
+
empty: 'none',
|
80
|
+
},
|
81
|
+
},
|
82
|
+
],
|
83
|
+
encoding: {
|
84
|
+
x: {
|
85
|
+
field: 'keyName',
|
86
|
+
type: 'nominal',
|
87
|
+
axis: { labelExpr: `substring(datum.label, ${keyLength})` },
|
88
|
+
title: 'Cell Set',
|
89
|
+
sort: keys,
|
90
|
+
},
|
91
|
+
y: {
|
92
|
+
field: 'size',
|
93
|
+
type: 'quantitative',
|
94
|
+
title: `${captializedObsType} Set Size`,
|
95
|
+
},
|
96
|
+
color: {
|
97
|
+
field: 'key',
|
98
|
+
type: 'nominal',
|
99
|
+
scale: colorScale,
|
100
|
+
legend: null,
|
101
|
+
},
|
102
|
+
tooltip: {
|
103
|
+
field: 'size',
|
104
|
+
type: 'quantitative',
|
105
|
+
},
|
106
|
+
fillOpacity: {
|
107
|
+
condition: {
|
108
|
+
param: 'select',
|
109
|
+
value: 1,
|
110
|
+
},
|
111
|
+
value: 0.3,
|
112
|
+
},
|
113
|
+
strokeWidth: {
|
114
|
+
condition: [
|
115
|
+
{
|
116
|
+
param: 'select',
|
117
|
+
empty: false,
|
118
|
+
value: 1,
|
119
|
+
},
|
120
|
+
{
|
121
|
+
param: 'highlight',
|
122
|
+
empty: false,
|
123
|
+
value: 2,
|
124
|
+
},
|
125
|
+
],
|
126
|
+
value: 0,
|
127
|
+
},
|
128
|
+
},
|
129
|
+
width: clamp(width - marginRight, 10, Infinity),
|
130
|
+
height: clamp(height - marginBottom, 10, Infinity),
|
131
|
+
config: VEGA_THEMES[theme],
|
132
|
+
};
|
133
|
+
const handleSignal = (name, value) => {
|
134
|
+
if (name === 'bar_select') {
|
135
|
+
onBarSelect(value.setNamePath, value.isGrayedOut[0]);
|
136
|
+
}
|
137
|
+
else if (name === 'shift_bar_select') {
|
138
|
+
const isGrayedOut = false;
|
139
|
+
const selectOnlyEnabled = true;
|
140
|
+
onBarSelect(value.setNamePath, isGrayedOut, selectOnlyEnabled);
|
141
|
+
}
|
142
|
+
};
|
143
|
+
const signalListeners = { bar_select: handleSignal, shift_bar_select: handleSignal };
|
144
|
+
const getTooltipText = useCallback(item => ({
|
145
|
+
[`${captializedObsType} Set`]: item.datum.name,
|
146
|
+
[`${captializedObsType} Set Size`]: item.datum.size,
|
147
|
+
}), [captializedObsType]);
|
148
|
+
return (_jsx(VegaPlot, { data: data, spec: spec, signalListeners: signalListeners, getTooltipText: getTooltipText }));
|
149
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
/**
|
2
|
+
* A subscriber component for `CellSetSizePlot`,
|
3
|
+
* which listens for cell sets data updates and
|
4
|
+
* `GRID_RESIZE` events.
|
5
|
+
* @param {object} props
|
6
|
+
* @param {function} props.removeGridComponent The grid component removal function.
|
7
|
+
* @param {function} props.onReady The function to call when the subscriptions
|
8
|
+
* have been made.
|
9
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
10
|
+
* @param {string} props.title The component title.
|
11
|
+
*/
|
12
|
+
export function CellSetSizesPlotSubscriber(props: {
|
13
|
+
removeGridComponent: Function;
|
14
|
+
onReady: Function;
|
15
|
+
theme: string;
|
16
|
+
title: string;
|
17
|
+
}): JSX.Element;
|
18
|
+
//# sourceMappingURL=CellSetSizesPlotSubscriber.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CellSetSizesPlotSubscriber.d.ts","sourceRoot":"","sources":["../src/CellSetSizesPlotSubscriber.js"],"names":[],"mappings":"AAgBA;;;;;;;;;;GAUG;AACH;IAN2B,mBAAmB;IACnB,OAAO;IAET,KAAK,EAAnB,MAAM;IACQ,KAAK,EAAnB,MAAM;gBA6HhB"}
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import React, { useMemo, useState } from 'react';
|
3
|
+
import { TitleInfo, useCoordination, useLoaders, useUrls, useReady, useGridItemSize, useObsSetsData, } from '@vitessce/vit-s';
|
4
|
+
import { isEqual } from 'lodash-es';
|
5
|
+
import { ViewType, COMPONENT_COORDINATION_TYPES } from '@vitessce/constants-internal';
|
6
|
+
import { mergeObsSets, treeToSetSizesBySetNames, filterPathsByExpansionAndSelection, findChangedHierarchy, } from '@vitessce/sets-utils';
|
7
|
+
import { capitalize } from '@vitessce/utils';
|
8
|
+
import CellSetSizesPlot from './CellSetSizesPlot.js';
|
9
|
+
import { useStyles } from './styles.js';
|
10
|
+
/**
|
11
|
+
* A subscriber component for `CellSetSizePlot`,
|
12
|
+
* which listens for cell sets data updates and
|
13
|
+
* `GRID_RESIZE` events.
|
14
|
+
* @param {object} props
|
15
|
+
* @param {function} props.removeGridComponent The grid component removal function.
|
16
|
+
* @param {function} props.onReady The function to call when the subscriptions
|
17
|
+
* have been made.
|
18
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
19
|
+
* @param {string} props.title The component title.
|
20
|
+
*/
|
21
|
+
export function CellSetSizesPlotSubscriber(props) {
|
22
|
+
const { coordinationScopes, removeGridComponent, theme, title: titleOverride, } = props;
|
23
|
+
const classes = useStyles();
|
24
|
+
const loaders = useLoaders();
|
25
|
+
// Get "props" from the coordination space.
|
26
|
+
const [{ dataset, obsType, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, additionalObsSets: additionalCellSets, obsSetExpansion: cellSetExpansion, }, { setObsSetSelection: setCellSetSelection, setObsSetColor: setCellSetColor, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.OBS_SET_SIZES], coordinationScopes);
|
27
|
+
const title = titleOverride || `${capitalize(obsType)} Set Sizes`;
|
28
|
+
const [width, height, containerRef] = useGridItemSize();
|
29
|
+
const [urls, addUrl] = useUrls(loaders, dataset);
|
30
|
+
// the name of the hierarchy that was clicked on last
|
31
|
+
const [currentHierarchy, setCurrentHierarchy] = useState([]);
|
32
|
+
// the previous cell set that was selected
|
33
|
+
const [prevCellSetSelection, setPrevCellSetSelection] = useState([]);
|
34
|
+
// Get data from loaders using the data hooks.
|
35
|
+
const [{ obsSets: cellSets }, obsSetsStatus] = useObsSetsData(loaders, dataset, addUrl, true, { setObsSetSelection: setCellSetSelection, setObsSetColor: setCellSetColor }, { obsSetSelection: cellSetSelection, obsSetColor: cellSetColor }, { obsType });
|
36
|
+
const isReady = useReady([
|
37
|
+
obsSetsStatus,
|
38
|
+
]);
|
39
|
+
const mergedCellSets = useMemo(() => mergeObsSets(cellSets, additionalCellSets), [cellSets, additionalCellSets]);
|
40
|
+
const data = useMemo(() => {
|
41
|
+
if (cellSetSelection && cellSetColor && mergedCellSets && cellSets) {
|
42
|
+
let newHierarchy = currentHierarchy;
|
43
|
+
if (cellSetSelection) {
|
44
|
+
const changedHierarchy = findChangedHierarchy(prevCellSetSelection, cellSetSelection);
|
45
|
+
setPrevCellSetSelection(cellSetSelection);
|
46
|
+
if (changedHierarchy) {
|
47
|
+
setCurrentHierarchy(changedHierarchy);
|
48
|
+
newHierarchy = changedHierarchy;
|
49
|
+
}
|
50
|
+
}
|
51
|
+
const cellSetPaths = filterPathsByExpansionAndSelection(mergedCellSets, newHierarchy, cellSetExpansion, cellSetSelection);
|
52
|
+
if (mergedCellSets && cellSets && cellSetSelection && cellSetColor) {
|
53
|
+
return treeToSetSizesBySetNames(mergedCellSets, cellSetPaths, cellSetSelection, cellSetColor, theme);
|
54
|
+
}
|
55
|
+
}
|
56
|
+
return [];
|
57
|
+
}, [
|
58
|
+
mergedCellSets,
|
59
|
+
cellSetSelection,
|
60
|
+
cellSetExpansion,
|
61
|
+
cellSetColor,
|
62
|
+
theme,
|
63
|
+
]);
|
64
|
+
const onBarSelect = (setNamePath, wasGrayedOut, selectOnlyEnabled = false) => {
|
65
|
+
if (selectOnlyEnabled) {
|
66
|
+
setCellSetSelection([setNamePath]);
|
67
|
+
return;
|
68
|
+
}
|
69
|
+
if (!wasGrayedOut) {
|
70
|
+
setCellSetSelection(cellSetSelection.filter(d => !isEqual(d, setNamePath)));
|
71
|
+
}
|
72
|
+
else if (wasGrayedOut) {
|
73
|
+
setCellSetSelection([...cellSetSelection, setNamePath]);
|
74
|
+
}
|
75
|
+
};
|
76
|
+
return (_jsx(TitleInfo, { title: title, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, children: _jsx("div", { ref: containerRef, className: classes.vegaContainer, children: _jsx(CellSetSizesPlot, { data: data, onBarSelect: onBarSelect, theme: theme, width: width, height: height, obsType: obsType }) }) }));
|
77
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
/**
|
2
|
+
* We use debounce, so that onSelect is called only after the user has finished the selection.
|
3
|
+
* Due to vega-lite limitations, we cannot use the vega-lite signals to implement this.
|
4
|
+
* See this issue: https://github.com/vega/vega-lite/issues/5728
|
5
|
+
* See this for reference on what is supported: https://vega.github.io/vega-lite/docs/selection.html
|
6
|
+
*/
|
7
|
+
/**
|
8
|
+
* Gene expression histogram displayed as a bar chart,
|
9
|
+
* implemented with the VegaPlot component.
|
10
|
+
* @param {object} props
|
11
|
+
* @param {string[]} props.geneSelection The list of genes
|
12
|
+
* currently selected.
|
13
|
+
* @param {object[]} props.data The expression data, an array
|
14
|
+
* of objects with properties `value` and `gene`.
|
15
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
16
|
+
* @param {number} props.width The container width.
|
17
|
+
* @param {number} props.height The container height.
|
18
|
+
* @param {number} props.marginRight The size of the margin
|
19
|
+
* on the right side of the plot, to account for the vega menu button.
|
20
|
+
* By default, 90.
|
21
|
+
* @param {number} props.marginBottom The size of the margin
|
22
|
+
* on the bottom of the plot, to account for long x-axis labels.
|
23
|
+
* By default, 50.
|
24
|
+
*/
|
25
|
+
export default function ExpressionHistogram(props: {
|
26
|
+
geneSelection: string[];
|
27
|
+
data: object[];
|
28
|
+
theme: string;
|
29
|
+
width: number;
|
30
|
+
height: number;
|
31
|
+
marginRight: number;
|
32
|
+
marginBottom: number;
|
33
|
+
}): JSX.Element;
|
34
|
+
//# sourceMappingURL=ExpressionHistogram.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ExpressionHistogram.d.ts","sourceRoot":"","sources":["../src/ExpressionHistogram.js"],"names":[],"mappings":"AAIA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH;IAd2B,aAAa,EAA7B,MAAM,EAAE;IAEQ,IAAI,EAApB,MAAM,EAAE;IAEM,KAAK,EAAnB,MAAM;IACQ,KAAK,EAAnB,MAAM;IACQ,MAAM,EAApB,MAAM;IACQ,WAAW,EAAzB,MAAM;IAGQ,YAAY,EAA1B,MAAM;gBA8FhB"}
|
@@ -0,0 +1,93 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
3
|
+
import { clamp, debounce } from 'lodash-es';
|
4
|
+
import { VegaPlot, VEGA_THEMES } from '@vitessce/vega';
|
5
|
+
/**
|
6
|
+
* We use debounce, so that onSelect is called only after the user has finished the selection.
|
7
|
+
* Due to vega-lite limitations, we cannot use the vega-lite signals to implement this.
|
8
|
+
* See this issue: https://github.com/vega/vega-lite/issues/5728
|
9
|
+
* See this for reference on what is supported: https://vega.github.io/vega-lite/docs/selection.html
|
10
|
+
*/
|
11
|
+
/**
|
12
|
+
* Gene expression histogram displayed as a bar chart,
|
13
|
+
* implemented with the VegaPlot component.
|
14
|
+
* @param {object} props
|
15
|
+
* @param {string[]} props.geneSelection The list of genes
|
16
|
+
* currently selected.
|
17
|
+
* @param {object[]} props.data The expression data, an array
|
18
|
+
* of objects with properties `value` and `gene`.
|
19
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
20
|
+
* @param {number} props.width The container width.
|
21
|
+
* @param {number} props.height The container height.
|
22
|
+
* @param {number} props.marginRight The size of the margin
|
23
|
+
* on the right side of the plot, to account for the vega menu button.
|
24
|
+
* By default, 90.
|
25
|
+
* @param {number} props.marginBottom The size of the margin
|
26
|
+
* on the bottom of the plot, to account for long x-axis labels.
|
27
|
+
* By default, 50.
|
28
|
+
*/
|
29
|
+
export default function ExpressionHistogram(props) {
|
30
|
+
const { geneSelection, data, theme, width, height, marginRight = 90, marginBottom = 50, onSelect, } = props;
|
31
|
+
const [selectedRanges, setSelectedRanges] = useState([]);
|
32
|
+
const xTitle = geneSelection && geneSelection.length >= 1
|
33
|
+
? 'Normalized Expression Value'
|
34
|
+
: 'Total Normalized Transcript Count';
|
35
|
+
const spec = {
|
36
|
+
data: { values: data },
|
37
|
+
mark: 'bar',
|
38
|
+
encoding: {
|
39
|
+
x: {
|
40
|
+
field: 'value',
|
41
|
+
type: 'quantitative',
|
42
|
+
bin: { maxbins: 50 },
|
43
|
+
title: xTitle,
|
44
|
+
},
|
45
|
+
y: {
|
46
|
+
type: 'quantitative',
|
47
|
+
aggregate: 'count',
|
48
|
+
title: 'Number of Cells',
|
49
|
+
},
|
50
|
+
color: { value: 'gray' },
|
51
|
+
opacity: {
|
52
|
+
condition: { selection: 'brush', value: 1 },
|
53
|
+
value: 0.7,
|
54
|
+
},
|
55
|
+
},
|
56
|
+
params: [
|
57
|
+
{
|
58
|
+
name: 'brush',
|
59
|
+
select: { type: 'interval', encodings: ['x'] },
|
60
|
+
},
|
61
|
+
],
|
62
|
+
width: clamp(width - marginRight, 10, Infinity),
|
63
|
+
height: clamp(height - marginBottom, 10, Infinity),
|
64
|
+
config: VEGA_THEMES[theme],
|
65
|
+
};
|
66
|
+
const handleSignal = (name, value) => {
|
67
|
+
if (name === 'brush') {
|
68
|
+
setSelectedRanges(value.value);
|
69
|
+
}
|
70
|
+
};
|
71
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
72
|
+
const debouncedOnSelect = useCallback(debounce((ranges, latestOnSelect) => {
|
73
|
+
latestOnSelect(ranges);
|
74
|
+
// We set a debounce timer of 1000ms: the assumption here is that the user has
|
75
|
+
// finished the selection when there's been no mouse movement on the histogram for a second.
|
76
|
+
// We do not pass any dependencies for the useCallback
|
77
|
+
// since we only want to define the debounced function once (on the initial render).
|
78
|
+
}, 1000), []);
|
79
|
+
useEffect(() => {
|
80
|
+
if (!selectedRanges || selectedRanges.length === 0)
|
81
|
+
return () => { };
|
82
|
+
// Call the debounced function instead of directly calling onSelect
|
83
|
+
debouncedOnSelect(selectedRanges, onSelect);
|
84
|
+
// Clean up the debounce timer when the component unmounts or the dependency changes
|
85
|
+
return () => {
|
86
|
+
debouncedOnSelect.cancel();
|
87
|
+
};
|
88
|
+
// We only want to call the debounced function when the selectedRanges changes.
|
89
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
90
|
+
}, [selectedRanges]);
|
91
|
+
const signalListeners = { brush: handleSignal };
|
92
|
+
return (_jsx(VegaPlot, { data: data, signalListeners: signalListeners, spec: spec }));
|
93
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
/**
|
2
|
+
* A subscriber component for `ExpressionHistogram`,
|
3
|
+
* which listens for gene selection updates and
|
4
|
+
* `GRID_RESIZE` events.
|
5
|
+
* @param {object} props
|
6
|
+
* @param {function} props.removeGridComponent The grid component removal function.
|
7
|
+
* @param {object} props.coordinationScopes An object mapping coordination
|
8
|
+
* types to coordination scopes.
|
9
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
10
|
+
*/
|
11
|
+
export function ExpressionHistogramSubscriber(props: {
|
12
|
+
removeGridComponent: Function;
|
13
|
+
coordinationScopes: object;
|
14
|
+
theme: string;
|
15
|
+
}): JSX.Element;
|
16
|
+
//# sourceMappingURL=ExpressionHistogramSubscriber.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ExpressionHistogramSubscriber.d.ts","sourceRoot":"","sources":["../src/ExpressionHistogramSubscriber.js"],"names":[],"mappings":"AAcA;;;;;;;;;GASG;AACH;IAL2B,mBAAmB;IACrB,kBAAkB,EAAhC,MAAM;IAEQ,KAAK,EAAnB,MAAM;gBAiHhB"}
|