@vitessce/statistical-plots 3.4.6 → 3.4.7
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/deflate-c8c2f459.js +13 -0
- package/dist/index-a1925e78.js +206649 -0
- package/dist/index.js +13 -91680
- package/dist/jpeg-ffd14ffe.js +840 -0
- package/dist/lerc-9d1dd17e.js +2014 -0
- package/dist/lzw-3705b408.js +128 -0
- package/dist/packbits-6f657116.js +30 -0
- package/dist/pako.esm-68f84e2a.js +4022 -0
- package/dist/raw-0a76dec9.js +12 -0
- package/dist/webimage-fbdf3bdf.js +32 -0
- package/dist-tsc/CellSetExpressionPlot.d.ts.map +1 -1
- package/dist-tsc/CellSetExpressionPlot.js +207 -106
- package/dist-tsc/CellSetExpressionPlotOptions.d.ts.map +1 -1
- package/dist-tsc/CellSetExpressionPlotOptions.js +14 -4
- package/dist-tsc/CellSetExpressionPlotSubscriber.d.ts.map +1 -1
- package/dist-tsc/CellSetExpressionPlotSubscriber.js +15 -31
- package/dist-tsc/CellSetSizesPlot.d.ts.map +1 -1
- package/dist-tsc/CellSetSizesPlotSubscriber.d.ts.map +1 -1
- package/dist-tsc/DotPlot.d.ts +28 -0
- package/dist-tsc/DotPlot.d.ts.map +1 -0
- package/dist-tsc/DotPlot.js +144 -0
- package/dist-tsc/DotPlotSubscriber.d.ts +14 -0
- package/dist-tsc/DotPlotSubscriber.d.ts.map +1 -0
- package/dist-tsc/DotPlotSubscriber.js +54 -0
- package/dist-tsc/ExpressionHistogram.d.ts.map +1 -1
- package/dist-tsc/ExpressionHistogramSubscriber.d.ts.map +1 -1
- package/dist-tsc/dot-plot-hook.d.ts +23 -0
- package/dist-tsc/dot-plot-hook.d.ts.map +1 -0
- package/dist-tsc/dot-plot-hook.js +69 -0
- package/dist-tsc/expr-hooks.d.ts +51 -0
- package/dist-tsc/expr-hooks.d.ts.map +1 -0
- package/dist-tsc/expr-hooks.js +135 -0
- package/dist-tsc/expr-hooks.test.d.ts +2 -0
- package/dist-tsc/expr-hooks.test.d.ts.map +1 -0
- package/dist-tsc/expr-hooks.test.js +97 -0
- package/dist-tsc/index.d.ts +2 -0
- package/dist-tsc/index.js +2 -0
- package/package.json +10 -7
- package/src/CellSetExpressionPlot.js +223 -124
- package/src/CellSetExpressionPlotOptions.js +57 -1
- package/src/CellSetExpressionPlotSubscriber.js +45 -38
- package/src/DotPlot.js +175 -0
- package/src/DotPlotSubscriber.js +173 -0
- package/src/dot-plot-hook.js +107 -0
- package/src/expr-hooks.js +170 -0
- package/src/expr-hooks.test.js +116 -0
- package/src/index.js +2 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gene expression dot plot,
|
|
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 {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
|
+
* Default is allowing the component to automatically determine the margin.
|
|
16
|
+
* @param {string|null} props.featureValueTransformName A name
|
|
17
|
+
* for the feature value transformation function.
|
|
18
|
+
*/
|
|
19
|
+
export default function DotPlot(props: {
|
|
20
|
+
data: object[];
|
|
21
|
+
theme: string;
|
|
22
|
+
width: number;
|
|
23
|
+
height: number;
|
|
24
|
+
marginRight: number;
|
|
25
|
+
marginBottom: number;
|
|
26
|
+
featureValueTransformName: string | null;
|
|
27
|
+
}): JSX.Element;
|
|
28
|
+
//# sourceMappingURL=DotPlot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DotPlot.d.ts","sourceRoot":"","sources":["../src/DotPlot.js"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AACH,uCAdG;IAAwB,IAAI,EAApB,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;CAErB,eAwJA"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { clamp } from 'lodash-es';
|
|
4
|
+
import { VegaPlot, VEGA_THEMES } from '@vitessce/vega';
|
|
5
|
+
import { capitalize, pluralize as plur } from '@vitessce/utils';
|
|
6
|
+
/**
|
|
7
|
+
* Gene expression dot plot,
|
|
8
|
+
* implemented with the VegaPlot component.
|
|
9
|
+
* @param {object} props
|
|
10
|
+
* @param {object[]} props.data The expression data, an array
|
|
11
|
+
* of objects with properties `value`, `gene`, and `set`.
|
|
12
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
|
13
|
+
* @param {number} props.width The container width.
|
|
14
|
+
* @param {number} props.height The container height.
|
|
15
|
+
* @param {number} props.marginRight The size of the margin
|
|
16
|
+
* on the right side of the plot, to account for the vega menu button.
|
|
17
|
+
* By default, 90.
|
|
18
|
+
* @param {number} props.marginBottom The size of the margin
|
|
19
|
+
* on the bottom of the plot, to account for long x-axis labels.
|
|
20
|
+
* Default is allowing the component to automatically determine the margin.
|
|
21
|
+
* @param {string|null} props.featureValueTransformName A name
|
|
22
|
+
* for the feature value transformation function.
|
|
23
|
+
*/
|
|
24
|
+
export default function DotPlot(props) {
|
|
25
|
+
const { isStratified, transpose, data: rawData, theme, width, height, marginRight, marginBottom, obsType, keyLength = 36, featureType, featureValueType, featureValueTransformName, featureValueColormap, cellSetSelection, } = props;
|
|
26
|
+
// Add a property `keyGroup` and `keyFeature` which concatenates the key and the name,
|
|
27
|
+
// which is both unique and can easily be converted
|
|
28
|
+
// back to the name by taking a substring.
|
|
29
|
+
const data = rawData.map(d => ({
|
|
30
|
+
...d,
|
|
31
|
+
keyGroup: d.groupKey + d.group,
|
|
32
|
+
keyFeature: d.featureKey + d.feature,
|
|
33
|
+
keyGroupSecondary: d.secondaryGroupKey + d.secondaryGroup,
|
|
34
|
+
}));
|
|
35
|
+
// Get the max characters in an axis label for autsizing the bottom margin.
|
|
36
|
+
const maxCharactersForGroup = data.reduce((acc, val) => {
|
|
37
|
+
// eslint-disable-next-line no-param-reassign
|
|
38
|
+
acc = acc === undefined || val.group?.length > acc ? val.group?.length : acc;
|
|
39
|
+
return acc;
|
|
40
|
+
}, 0);
|
|
41
|
+
const maxCharactersForFeature = data.reduce((acc, val) => {
|
|
42
|
+
// eslint-disable-next-line no-param-reassign
|
|
43
|
+
acc = acc === undefined || val.feature.length > acc ? val.feature.length : acc;
|
|
44
|
+
return acc;
|
|
45
|
+
}, 0);
|
|
46
|
+
const maxCharactersForSampleSet = isStratified ? data.reduce((acc, val) => {
|
|
47
|
+
// eslint-disable-next-line no-param-reassign
|
|
48
|
+
acc = acc === undefined || val.secondaryGroup.length > acc ? val.secondaryGroup.length : acc;
|
|
49
|
+
return acc;
|
|
50
|
+
}, 0) : 0;
|
|
51
|
+
// Use a square-root term because the angle of the labels is 45 degrees (see below)
|
|
52
|
+
// so the perpendicular distance to the bottom of the labels is proportional to the
|
|
53
|
+
// square root of the length of the labels along the imaginary hypotenuse.
|
|
54
|
+
// 30 is an estimate of the pixel size of a given character and seems to work well.
|
|
55
|
+
const autoMarginForFeature = marginBottom
|
|
56
|
+
|| 30 + Math.sqrt(maxCharactersForFeature / 2) * 30;
|
|
57
|
+
const autoMarginForGroup = marginRight
|
|
58
|
+
|| 30 + Math.sqrt(maxCharactersForGroup / 2) * 30;
|
|
59
|
+
const autoMarginForSampleSet = marginRight
|
|
60
|
+
|| 30 + Math.sqrt(maxCharactersForSampleSet / 2) * 30;
|
|
61
|
+
const plotWidth = transpose
|
|
62
|
+
? clamp(width - autoMarginForFeature - 180, 10, Infinity) / (cellSetSelection?.length || 1)
|
|
63
|
+
: clamp(width - autoMarginForGroup - autoMarginForSampleSet - 200, 10, Infinity);
|
|
64
|
+
const plotHeight = transpose
|
|
65
|
+
? clamp((height - autoMarginForGroup - autoMarginForSampleSet - 50), 10, Infinity)
|
|
66
|
+
: clamp((height - autoMarginForFeature - 80), 10, Infinity) / (cellSetSelection?.length || 1);
|
|
67
|
+
// Get an array of keys for sorting purposes.
|
|
68
|
+
const groupKeys = data.map(d => d.keyGroup);
|
|
69
|
+
const featureKeys = data.map(d => d.keyFeature);
|
|
70
|
+
const groupSecondaryKeys = data.map(d => d.keyGroupSecondary);
|
|
71
|
+
const meanTransform = (featureValueTransformName && featureValueTransformName !== 'None')
|
|
72
|
+
// Mean Log-Transformed Normalized Expression
|
|
73
|
+
? [`Mean ${featureValueTransformName}-transformed`, `normalized ${featureValueType}`, 'in set']
|
|
74
|
+
// Mean Normalized Expression
|
|
75
|
+
: ['Mean normalized', `${featureValueType} in set`];
|
|
76
|
+
const spec = {
|
|
77
|
+
mark: {
|
|
78
|
+
type: 'circle',
|
|
79
|
+
// The Vega-Lite default opacity is 0.7 for point, tick, circle,
|
|
80
|
+
// or square marks.
|
|
81
|
+
// Reference: https://vega.github.io/vega-lite/docs/mark.html
|
|
82
|
+
opacity: 1.0,
|
|
83
|
+
},
|
|
84
|
+
encoding: {
|
|
85
|
+
[(transpose ? 'y' : 'x')]: {
|
|
86
|
+
field: 'keyFeature',
|
|
87
|
+
type: 'nominal',
|
|
88
|
+
axis: { labelExpr: `substring(datum.label, ${keyLength})` },
|
|
89
|
+
title: capitalize(featureType),
|
|
90
|
+
sort: featureKeys,
|
|
91
|
+
},
|
|
92
|
+
[(transpose ? 'column' : 'row')]: {
|
|
93
|
+
field: 'keyGroup',
|
|
94
|
+
type: 'nominal',
|
|
95
|
+
header: transpose
|
|
96
|
+
? { labelExpr: `substring(datum.label, ${keyLength})`, labelAngle: -60, labelAlign: 'right', titleOrient: 'bottom', labelOrient: 'bottom' }
|
|
97
|
+
: { labelExpr: `substring(datum.label, ${keyLength})`, labelAngle: 0, labelAlign: 'left' },
|
|
98
|
+
title: `${capitalize(obsType)} Set`,
|
|
99
|
+
sort: groupKeys,
|
|
100
|
+
spacing: 0,
|
|
101
|
+
},
|
|
102
|
+
color: {
|
|
103
|
+
field: 'meanExpInGroup',
|
|
104
|
+
type: 'quantitative',
|
|
105
|
+
title: meanTransform,
|
|
106
|
+
scale: {
|
|
107
|
+
scheme: featureValueColormap,
|
|
108
|
+
},
|
|
109
|
+
legend: {
|
|
110
|
+
direction: 'horizontal',
|
|
111
|
+
tickCount: 2,
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
[(transpose ? 'x' : 'y')]: {
|
|
115
|
+
field: 'keyGroupSecondary',
|
|
116
|
+
type: 'nominal',
|
|
117
|
+
axis: { labelExpr: `substring(datum.label, ${keyLength})` },
|
|
118
|
+
title: null, // TODO: use sampleType
|
|
119
|
+
sort: groupSecondaryKeys,
|
|
120
|
+
},
|
|
121
|
+
size: {
|
|
122
|
+
field: 'pctPosInGroup',
|
|
123
|
+
type: 'quantitative',
|
|
124
|
+
title: [`Percentage of ${plur(obsType, 2)}`, 'in set'],
|
|
125
|
+
legend: {
|
|
126
|
+
symbolFillColor: 'white',
|
|
127
|
+
},
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
width: plotWidth,
|
|
131
|
+
height: plotHeight,
|
|
132
|
+
config: {
|
|
133
|
+
...VEGA_THEMES[theme],
|
|
134
|
+
...(!isStratified ? {
|
|
135
|
+
// Remove the row/column outlines when
|
|
136
|
+
// not stratified by sample set.
|
|
137
|
+
view: {
|
|
138
|
+
stroke: 'transparent',
|
|
139
|
+
},
|
|
140
|
+
} : {}),
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
return (_jsx(VegaPlot, { data: data, spec: spec }));
|
|
144
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A subscriber component for DotPlot.
|
|
3
|
+
* @param {object} props
|
|
4
|
+
* @param {function} props.removeGridComponent The grid component removal function.
|
|
5
|
+
* @param {object} props.coordinationScopes An object mapping coordination
|
|
6
|
+
* types to coordination scopes.
|
|
7
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
|
8
|
+
*/
|
|
9
|
+
export function DotPlotSubscriber(props: {
|
|
10
|
+
removeGridComponent: Function;
|
|
11
|
+
coordinationScopes: object;
|
|
12
|
+
theme: string;
|
|
13
|
+
}): JSX.Element;
|
|
14
|
+
//# sourceMappingURL=DotPlotSubscriber.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DotPlotSubscriber.d.ts","sourceRoot":"","sources":["../src/DotPlotSubscriber.js"],"names":[],"mappings":"AAmBA;;;;;;;GAOG;AACH,yCALG;IAAwB,mBAAmB;IACrB,kBAAkB,EAAhC,MAAM;IAEQ,KAAK,EAAnB,MAAM;CAChB,eAkJA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { TitleInfo, useCoordination, useLoaders, useUrls, useReady, useGridItemSize, useFeatureSelection, useObsSetsData, useObsFeatureMatrixIndices, useFeatureLabelsData, useSampleSetsData, useSampleEdgesData, } from '@vitessce/vit-s';
|
|
4
|
+
import { ViewType, COMPONENT_COORDINATION_TYPES } from '@vitessce/constants-internal';
|
|
5
|
+
import { VALUE_TRANSFORM_OPTIONS } from '@vitessce/utils';
|
|
6
|
+
import CellSetExpressionPlotOptions from './CellSetExpressionPlotOptions.js';
|
|
7
|
+
import DotPlot from './DotPlot.js';
|
|
8
|
+
import { useStyles } from './styles.js';
|
|
9
|
+
import { useExpressionSummaries } from './dot-plot-hook.js';
|
|
10
|
+
/**
|
|
11
|
+
* A subscriber component for DotPlot.
|
|
12
|
+
* @param {object} props
|
|
13
|
+
* @param {function} props.removeGridComponent The grid component removal function.
|
|
14
|
+
* @param {object} props.coordinationScopes An object mapping coordination
|
|
15
|
+
* types to coordination scopes.
|
|
16
|
+
* @param {string} props.theme The name of the current Vitessce theme.
|
|
17
|
+
*/
|
|
18
|
+
export function DotPlotSubscriber(props) {
|
|
19
|
+
const { coordinationScopes, removeGridComponent, theme, title = 'Dot Plot', transpose = true, } = props;
|
|
20
|
+
const classes = useStyles();
|
|
21
|
+
const loaders = useLoaders();
|
|
22
|
+
// Get "props" from the coordination space.
|
|
23
|
+
const [{ dataset, obsType, featureType, featureValueType, featureSelection: geneSelection, featureValueTransform, featureValueTransformCoefficient, featureValuePositivityThreshold: posThreshold, featureValueColormap, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, additionalObsSets: additionalCellSets, sampleType, sampleSetSelection, }, { setFeatureValueTransform, setFeatureValueTransformCoefficient, setFeatureValuePositivityThreshold: setPosThreshold, setFeatureValueColormap, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.DOT_PLOT], coordinationScopes);
|
|
24
|
+
const [width, height, containerRef] = useGridItemSize();
|
|
25
|
+
const transformOptions = VALUE_TRANSFORM_OPTIONS;
|
|
26
|
+
const isStratified = Array.isArray(sampleSetSelection) && sampleSetSelection.length > 1;
|
|
27
|
+
// Get data from loaders using the data hooks.
|
|
28
|
+
// eslint-disable-next-line no-unused-vars
|
|
29
|
+
const [expressionData, loadedFeatureSelection, featureSelectionStatus] = useFeatureSelection(loaders, dataset, false, geneSelection, { obsType, featureType, featureValueType });
|
|
30
|
+
// TODO: support multiple feature labels using featureLabelsType coordination values.
|
|
31
|
+
const [{ featureLabelsMap }, featureLabelsStatus, featureLabelsUrl] = useFeatureLabelsData(loaders, dataset, false, {}, {}, { featureType });
|
|
32
|
+
const [{ obsIndex }, matrixIndicesStatus, matrixIndicesUrl] = useObsFeatureMatrixIndices(loaders, dataset, false, { obsType, featureType, featureValueType });
|
|
33
|
+
const [{ obsSets: cellSets }, obsSetsStatus, obsSetsUrl] = useObsSetsData(loaders, dataset, true, {}, {}, { obsType });
|
|
34
|
+
const [{ sampleSets }, sampleSetsStatus, sampleSetsUrl] = useSampleSetsData(loaders, dataset, false, {}, {}, { sampleType });
|
|
35
|
+
const [{ sampleEdges }, sampleEdgesStatus, sampleEdgesUrl] = useSampleEdgesData(loaders, dataset, false, {}, {}, { obsType, sampleType });
|
|
36
|
+
const isReady = useReady([
|
|
37
|
+
featureSelectionStatus,
|
|
38
|
+
matrixIndicesStatus,
|
|
39
|
+
obsSetsStatus,
|
|
40
|
+
featureLabelsStatus,
|
|
41
|
+
sampleSetsStatus,
|
|
42
|
+
sampleEdgesStatus,
|
|
43
|
+
]);
|
|
44
|
+
const urls = useUrls([
|
|
45
|
+
featureLabelsUrl,
|
|
46
|
+
matrixIndicesUrl,
|
|
47
|
+
obsSetsUrl,
|
|
48
|
+
sampleSetsUrl,
|
|
49
|
+
sampleEdgesUrl,
|
|
50
|
+
]);
|
|
51
|
+
const [resultArr, meanExpressionMax] = useExpressionSummaries(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, posThreshold, featureLabelsMap);
|
|
52
|
+
const selectedTransformName = transformOptions.find(o => o.value === featureValueTransform)?.name;
|
|
53
|
+
return (_jsx(TitleInfo, { title: title, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, options: (_jsx(CellSetExpressionPlotOptions, { featureValueTransform: featureValueTransform, setFeatureValueTransform: setFeatureValueTransform, featureValueTransformCoefficient: featureValueTransformCoefficient, setFeatureValueTransformCoefficient: setFeatureValueTransformCoefficient, transformOptions: transformOptions, featureValuePositivityThreshold: posThreshold, setFeatureValuePositivityThreshold: setPosThreshold, featureValueColormap: featureValueColormap, setFeatureValueColormap: setFeatureValueColormap })), children: _jsx("div", { ref: containerRef, className: classes.vegaContainer, children: resultArr ? (_jsx(DotPlot, { isStratified: isStratified, transpose: transpose, domainMax: meanExpressionMax, data: resultArr, theme: theme, width: width, height: height, obsType: obsType, featureType: featureType, featureValueType: featureValueType, featureValueTransformName: selectedTransformName, featureValueColormap: featureValueColormap, cellSetSelection: cellSetSelection })) : (_jsxs("span", { children: ["Select at least one ", featureType, "."] })) }) }));
|
|
54
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpressionHistogram.d.ts","sourceRoot":"","sources":["../src/ExpressionHistogram.js"],"names":[],"mappings":"AAKA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH;
|
|
1
|
+
{"version":3,"file":"ExpressionHistogram.d.ts","sourceRoot":"","sources":["../src/ExpressionHistogram.js"],"names":[],"mappings":"AAKA;;;;;GAKG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,mDAdG;IAAwB,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;CAGhB,eAkGA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpressionHistogramSubscriber.d.ts","sourceRoot":"","sources":["../src/ExpressionHistogramSubscriber.js"],"names":[],"mappings":"AAcA;;;;;;;;;GASG;AACH;
|
|
1
|
+
{"version":3,"file":"ExpressionHistogramSubscriber.d.ts","sourceRoot":"","sources":["../src/ExpressionHistogramSubscriber.js"],"names":[],"mappings":"AAcA;;;;;;;;;GASG;AACH,qDALG;IAAwB,mBAAmB;IACrB,kBAAkB,EAAhC,MAAM;IAEQ,KAAK,EAAnB,MAAM;CAChB,eA0HA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get expression data for the cells
|
|
3
|
+
* in the selected cell sets.
|
|
4
|
+
* @param {object} expressionMatrix
|
|
5
|
+
* @param {string[]} expressionMatrix.rows Cell IDs.
|
|
6
|
+
* @param {string[]} expressionMatrix.cols Gene names.
|
|
7
|
+
* @param {Uint8Array} expressionMatrix.matrix The
|
|
8
|
+
* flattened expression matrix as a typed array.
|
|
9
|
+
* @param {object} cellSets The cell sets from the dataset.
|
|
10
|
+
* @param {object} additionalCellSets The user-defined cell sets
|
|
11
|
+
* from the coordination space.
|
|
12
|
+
* @param {array} geneSelection Array of selected genes.
|
|
13
|
+
* @param {array} cellSetSelection Array of selected cell set paths.
|
|
14
|
+
* @param {object[]} cellSetColor Array of objects with properties
|
|
15
|
+
* @param {string|null} featureValueTransform The name of the
|
|
16
|
+
* feature value transform function.
|
|
17
|
+
* @param {number} featureValueTransformCoefficient A coefficient
|
|
18
|
+
* to be used in the transform function.
|
|
19
|
+
* @param {string} theme "light" or "dark" for the vitessce theme
|
|
20
|
+
* `path` and `color`.
|
|
21
|
+
*/
|
|
22
|
+
export function useExpressionSummaries(sampleEdges: any, sampleSets: any, sampleSetSelection: any, expressionData: any, obsIndex: any, cellSets: object, additionalCellSets: object, geneSelection: array, cellSetSelection: array, cellSetColor: object[], featureValueTransform: string | null, featureValueTransformCoefficient: number, posThreshold: any, featureLabelsMap: any): any[];
|
|
23
|
+
//# sourceMappingURL=dot-plot-hook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dot-plot-hook.d.ts","sourceRoot":"","sources":["../src/dot-plot-hook.js"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,iJAbW,MAAM,sBACN,MAAM,iBAEN,KAAK,oBACL,KAAK,gBACL,MAAM,EAAE,yBACR,MAAM,GAAC,IAAI,oCAEX,MAAM,mDA8EhB"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { InternMap } from 'internmap';
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
+
import { mergeObsSets, stratifyExpressionData, } from '@vitessce/sets-utils';
|
|
5
|
+
import { dotStratifiedExpressionData, } from './expr-hooks.js';
|
|
6
|
+
/**
|
|
7
|
+
* Get expression data for the cells
|
|
8
|
+
* in the selected cell sets.
|
|
9
|
+
* @param {object} expressionMatrix
|
|
10
|
+
* @param {string[]} expressionMatrix.rows Cell IDs.
|
|
11
|
+
* @param {string[]} expressionMatrix.cols Gene names.
|
|
12
|
+
* @param {Uint8Array} expressionMatrix.matrix The
|
|
13
|
+
* flattened expression matrix as a typed array.
|
|
14
|
+
* @param {object} cellSets The cell sets from the dataset.
|
|
15
|
+
* @param {object} additionalCellSets The user-defined cell sets
|
|
16
|
+
* from the coordination space.
|
|
17
|
+
* @param {array} geneSelection Array of selected genes.
|
|
18
|
+
* @param {array} cellSetSelection Array of selected cell set paths.
|
|
19
|
+
* @param {object[]} cellSetColor Array of objects with properties
|
|
20
|
+
* @param {string|null} featureValueTransform The name of the
|
|
21
|
+
* feature value transform function.
|
|
22
|
+
* @param {number} featureValueTransformCoefficient A coefficient
|
|
23
|
+
* to be used in the transform function.
|
|
24
|
+
* @param {string} theme "light" or "dark" for the vitessce theme
|
|
25
|
+
* `path` and `color`.
|
|
26
|
+
*/
|
|
27
|
+
export function useExpressionSummaries(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, posThreshold, featureLabelsMap) {
|
|
28
|
+
const mergedCellSets = useMemo(() => mergeObsSets(cellSets, additionalCellSets), [cellSets, additionalCellSets]);
|
|
29
|
+
// From the expression matrix and the list of selected genes / cell sets,
|
|
30
|
+
// generate the array of data points for the plot.
|
|
31
|
+
const [resultArr, meanExpressionMax] = useMemo(() => {
|
|
32
|
+
const [stratifiedData, exprMax] = stratifyExpressionData(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, mergedCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient);
|
|
33
|
+
if (stratifiedData) {
|
|
34
|
+
const dotData = dotStratifiedExpressionData(stratifiedData, posThreshold);
|
|
35
|
+
const geneToUuid = new Map(geneSelection?.map(gene => [gene, uuidv4()]));
|
|
36
|
+
const cellSetToUuid = new InternMap(cellSetSelection?.map(sampleSet => ([sampleSet, uuidv4()])), JSON.stringify);
|
|
37
|
+
const sampleSetToUuid = new InternMap(sampleSetSelection?.map(sampleSet => ([sampleSet, uuidv4()])), JSON.stringify);
|
|
38
|
+
const result = [];
|
|
39
|
+
([...dotData.keys()]).forEach((cellSetKey) => {
|
|
40
|
+
([...dotData.get(cellSetKey).keys()]).forEach((sampleSetKey) => {
|
|
41
|
+
([...dotData.get(cellSetKey).get(sampleSetKey).keys()]).forEach((geneKey) => {
|
|
42
|
+
const dotObj = dotData.get(cellSetKey).get(sampleSetKey).get(geneKey);
|
|
43
|
+
const featureName = geneKey;
|
|
44
|
+
result.push({
|
|
45
|
+
key: uuidv4(), // Unique key for this dot.
|
|
46
|
+
featureKey: geneToUuid.get(geneKey),
|
|
47
|
+
feature: featureLabelsMap?.get(featureName) || featureName,
|
|
48
|
+
groupKey: cellSetToUuid.get(cellSetKey),
|
|
49
|
+
group: cellSetKey?.at(-1),
|
|
50
|
+
secondaryGroup: sampleSetKey?.at(-1),
|
|
51
|
+
secondaryGroupKey: sampleSetToUuid.get(sampleSetKey),
|
|
52
|
+
meanExpInGroup: dotObj.meanExpInGroup,
|
|
53
|
+
fracPosInGroup: dotObj.fracPosInGroup,
|
|
54
|
+
pctPosInGroup: dotObj.fracPosInGroup * 100.0,
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
return [result, exprMax];
|
|
60
|
+
}
|
|
61
|
+
return [null, null];
|
|
62
|
+
}, [expressionData, obsIndex, geneSelection,
|
|
63
|
+
mergedCellSets, cellSetSelection,
|
|
64
|
+
featureValueTransform, featureValueTransformCoefficient,
|
|
65
|
+
posThreshold, featureLabelsMap,
|
|
66
|
+
sampleEdges, sampleSets, sampleSetSelection,
|
|
67
|
+
]);
|
|
68
|
+
return [resultArr, meanExpressionMax];
|
|
69
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supports three-level stratified input
|
|
3
|
+
* (cell set, sample set, gene).
|
|
4
|
+
* @param {*} stratifiedResult
|
|
5
|
+
* @param {*} posThreshold
|
|
6
|
+
* @returns
|
|
7
|
+
*/
|
|
8
|
+
export function dotStratifiedExpressionData(stratifiedResult: any, posThreshold: any): any;
|
|
9
|
+
/**
|
|
10
|
+
* Supports two-level stratified input
|
|
11
|
+
* (cell set, sample set).
|
|
12
|
+
* @param {*} stratifiedResult
|
|
13
|
+
* @param {*} keepZeros
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
export function summarizeStratifiedExpressionData(stratifiedResult: any, keepZeros: any): any;
|
|
17
|
+
/**
|
|
18
|
+
* Supports two-level summarized input
|
|
19
|
+
* (cell set, sample set),
|
|
20
|
+
* the output from summarizeStratifiedExpressionData.
|
|
21
|
+
* @param {*} summarizedResult
|
|
22
|
+
* @param {*} binCount
|
|
23
|
+
* @param {*} yMinProp
|
|
24
|
+
* @returns
|
|
25
|
+
*/
|
|
26
|
+
export function histogramStratifiedExpressionData(summarizedResult: any, binCount: any, yMinProp: any): {
|
|
27
|
+
groupSummaries: {
|
|
28
|
+
key: any;
|
|
29
|
+
value: {
|
|
30
|
+
key: any;
|
|
31
|
+
value: any;
|
|
32
|
+
}[];
|
|
33
|
+
}[];
|
|
34
|
+
groupData: {
|
|
35
|
+
key: any;
|
|
36
|
+
value: {
|
|
37
|
+
key: any;
|
|
38
|
+
value: any;
|
|
39
|
+
}[];
|
|
40
|
+
}[];
|
|
41
|
+
groupBins: {
|
|
42
|
+
key: any;
|
|
43
|
+
value: {
|
|
44
|
+
key: any;
|
|
45
|
+
value: any;
|
|
46
|
+
}[];
|
|
47
|
+
}[];
|
|
48
|
+
groupBinsMax: any;
|
|
49
|
+
y: any;
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=expr-hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expr-hooks.d.ts","sourceRoot":"","sources":["../src/expr-hooks.js"],"names":[],"mappings":"AAgDA;;;;;;GAMG;AACH,8DAJW,GAAC,gBACD,GAAC,OA+BX;AAED;;;;;;GAMG;AACH,oEAJW,GAAC,aACD,GAAC,OAkBX;AAED;;;;;;;;GAQG;AACH,oEALW,GAAC,YACD,GAAC,YACD,GAAC;;;;;;;;;;;;;;;;;;;;;;;;EAsDX"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
import { InternMap } from 'internmap';
|
|
3
|
+
import { scaleLinear } from 'd3-scale';
|
|
4
|
+
import { bin, min, max, mean as d3_mean, deviation as d3_deviation, ascending as d3_ascending, quantileSorted, } from 'd3-array';
|
|
5
|
+
// Reference: https://github.com/d3/d3-array/issues/180#issuecomment-851378012
|
|
6
|
+
function summarize(iterable, keepZeros) {
|
|
7
|
+
const values = iterable
|
|
8
|
+
.filter(d => keepZeros || d !== 0.0)
|
|
9
|
+
.sort(d3_ascending);
|
|
10
|
+
const minVal = values[0];
|
|
11
|
+
const maxVal = values[values.length - 1];
|
|
12
|
+
const q1 = quantileSorted(values, 0.25);
|
|
13
|
+
const q2 = quantileSorted(values, 0.5);
|
|
14
|
+
const q3 = quantileSorted(values, 0.75);
|
|
15
|
+
const iqr = q3 - q1; // interquartile range
|
|
16
|
+
const r0 = Math.max(minVal, q1 - iqr * 1.5);
|
|
17
|
+
const r1 = Math.min(maxVal, q3 + iqr * 1.5);
|
|
18
|
+
let i = -1;
|
|
19
|
+
while (values[++i] < r0)
|
|
20
|
+
;
|
|
21
|
+
const w0 = values[i];
|
|
22
|
+
while (values[++i] <= r1)
|
|
23
|
+
;
|
|
24
|
+
const w1 = values[i - 1];
|
|
25
|
+
// Chauvenet
|
|
26
|
+
// Reference: https://en.wikipedia.org/wiki/Chauvenet%27s_criterion
|
|
27
|
+
const mean = d3_mean(values);
|
|
28
|
+
const stdv = d3_deviation(values);
|
|
29
|
+
const c0 = mean - 3 * stdv;
|
|
30
|
+
const c1 = mean + 3 * stdv;
|
|
31
|
+
return {
|
|
32
|
+
quartiles: [q1, q2, q3],
|
|
33
|
+
range: [r0, r1],
|
|
34
|
+
whiskers: [w0, w1],
|
|
35
|
+
chauvenetRange: [c0, c1],
|
|
36
|
+
nonOutliers: values.filter(v => c0 <= v && v <= c1),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Supports three-level stratified input
|
|
41
|
+
* (cell set, sample set, gene).
|
|
42
|
+
* @param {*} stratifiedResult
|
|
43
|
+
* @param {*} posThreshold
|
|
44
|
+
* @returns
|
|
45
|
+
*/
|
|
46
|
+
export function dotStratifiedExpressionData(stratifiedResult, posThreshold) {
|
|
47
|
+
const result = new InternMap([], JSON.stringify);
|
|
48
|
+
([...stratifiedResult.keys()]).forEach((cellSetKey) => {
|
|
49
|
+
result.set(cellSetKey, new InternMap([], JSON.stringify));
|
|
50
|
+
([...stratifiedResult.get(cellSetKey).keys()]).forEach((sampleSetKey) => {
|
|
51
|
+
result.get(cellSetKey).set(sampleSetKey, new InternMap([], JSON.stringify));
|
|
52
|
+
const allGenes = stratifiedResult.get(cellSetKey).get(sampleSetKey);
|
|
53
|
+
([...allGenes.keys()]).forEach((geneKey) => {
|
|
54
|
+
const values = allGenes.get(geneKey);
|
|
55
|
+
const exprMean = d3_mean(values);
|
|
56
|
+
const numPos = values.reduce((acc, val) => (val > posThreshold ? acc + 1 : acc), 0);
|
|
57
|
+
const fracPos = numPos / values.length;
|
|
58
|
+
const dotSummary = {
|
|
59
|
+
meanExpInGroup: exprMean,
|
|
60
|
+
fracPosInGroup: fracPos,
|
|
61
|
+
};
|
|
62
|
+
result.get(cellSetKey).get(sampleSetKey).set(geneKey, dotSummary);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Supports two-level stratified input
|
|
70
|
+
* (cell set, sample set).
|
|
71
|
+
* @param {*} stratifiedResult
|
|
72
|
+
* @param {*} keepZeros
|
|
73
|
+
* @returns
|
|
74
|
+
*/
|
|
75
|
+
export function summarizeStratifiedExpressionData(stratifiedResult, keepZeros) {
|
|
76
|
+
const summarizedResult = new InternMap([], JSON.stringify);
|
|
77
|
+
([...stratifiedResult.keys()]).forEach((cellSetKey) => {
|
|
78
|
+
summarizedResult.set(cellSetKey, new InternMap([], JSON.stringify));
|
|
79
|
+
([...stratifiedResult.get(cellSetKey).keys()]).forEach((sampleSetKey) => {
|
|
80
|
+
const values = stratifiedResult.get(cellSetKey).get(sampleSetKey);
|
|
81
|
+
const summary = summarize(values, keepZeros);
|
|
82
|
+
summarizedResult.get(cellSetKey).set(sampleSetKey, summary);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
return summarizedResult;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Supports two-level summarized input
|
|
89
|
+
* (cell set, sample set),
|
|
90
|
+
* the output from summarizeStratifiedExpressionData.
|
|
91
|
+
* @param {*} summarizedResult
|
|
92
|
+
* @param {*} binCount
|
|
93
|
+
* @param {*} yMinProp
|
|
94
|
+
* @returns
|
|
95
|
+
*/
|
|
96
|
+
export function histogramStratifiedExpressionData(summarizedResult, binCount, yMinProp) {
|
|
97
|
+
const groupSummaries = ([...summarizedResult.keys()]).map(cellSetKey => ({
|
|
98
|
+
key: cellSetKey,
|
|
99
|
+
value: ([...summarizedResult.get(cellSetKey).keys()]).map(sampleSetKey => ({
|
|
100
|
+
key: sampleSetKey,
|
|
101
|
+
value: summarizedResult.get(cellSetKey).get(sampleSetKey),
|
|
102
|
+
})),
|
|
103
|
+
}));
|
|
104
|
+
const groupData = groupSummaries
|
|
105
|
+
.map(({ key, value }) => ({
|
|
106
|
+
key,
|
|
107
|
+
value: value.map(({ key: subKey, value: subValue }) => ({ key: subKey, value: subValue.nonOutliers })),
|
|
108
|
+
}));
|
|
109
|
+
const trimmedData = groupData.map(kv => kv.value.map(subKv => subKv.value).flat()).flat();
|
|
110
|
+
const yMin = (yMinProp === null ? Math.min(0, min(trimmedData)) : yMinProp);
|
|
111
|
+
// For the y domain, use the yMin prop
|
|
112
|
+
// to support a use case such as 'Aspect Ratio',
|
|
113
|
+
// where the domain minimum should be 1 rather than 0.
|
|
114
|
+
const y = scaleLinear()
|
|
115
|
+
.domain([yMin, max(trimmedData)]);
|
|
116
|
+
const histogram = bin()
|
|
117
|
+
.thresholds(y.ticks(binCount))
|
|
118
|
+
.domain(y.domain());
|
|
119
|
+
const groupBins = groupData.map(kv => ({ key: kv.key,
|
|
120
|
+
value: kv.value.map(subKv => ({ key: subKv.key, value: histogram(subKv.value) })) }));
|
|
121
|
+
const groupBinsMax = max(groupBins
|
|
122
|
+
.flatMap(d => d.value.flatMap(subKv => subKv.value.map(v => v.length))));
|
|
123
|
+
return {
|
|
124
|
+
// Array of [{ key, value: [
|
|
125
|
+
// { key, value: {
|
|
126
|
+
// quartiles, range, whiskers, chauvenetRange, nonOutliers }
|
|
127
|
+
// }
|
|
128
|
+
// ] }]
|
|
129
|
+
groupSummaries,
|
|
130
|
+
groupData, // Array of [{ key, value: [{ key, value: nonOutliers }] }]
|
|
131
|
+
groupBins, // Array of [{ key, value: [{ key, value: histogram(nonOutliers) }] }]
|
|
132
|
+
groupBinsMax, // Number
|
|
133
|
+
y, // d3.scaleLinear without a range set
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expr-hooks.test.d.ts","sourceRoot":"","sources":["../src/expr-hooks.test.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { stratifyExpressionData, aggregateStratifiedExpressionData, } from '@vitessce/sets-utils';
|
|
3
|
+
import { summarizeStratifiedExpressionData, histogramStratifiedExpressionData, } from './expr-hooks.js';
|
|
4
|
+
describe('Utility functions for processing expression data for statistical plots', () => {
|
|
5
|
+
describe('summarizeStratifiedExpressionData function', () => {
|
|
6
|
+
it('computes summarized information accurately', () => {
|
|
7
|
+
const sampleEdges = new Map([
|
|
8
|
+
['cell1-1', 'donor1'],
|
|
9
|
+
['cell1-2', 'donor1'],
|
|
10
|
+
['cell1-3', 'donor1'],
|
|
11
|
+
['cell1-4', 'donor1'],
|
|
12
|
+
['cell2-1', 'donor2'],
|
|
13
|
+
['cell2-2', 'donor2'],
|
|
14
|
+
['cell2-3', 'donor2'],
|
|
15
|
+
['cell2-4', 'donor2'],
|
|
16
|
+
]);
|
|
17
|
+
const sampleSets = {
|
|
18
|
+
tree: [
|
|
19
|
+
{
|
|
20
|
+
name: 'Clinical groups',
|
|
21
|
+
children: [
|
|
22
|
+
{
|
|
23
|
+
name: 'AKI',
|
|
24
|
+
set: [['donor1', null]],
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'CKD',
|
|
28
|
+
set: [['donor2', null]],
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
};
|
|
34
|
+
const sampleSetSelection = [
|
|
35
|
+
['Clinical groups', 'AKI'],
|
|
36
|
+
['Clinical groups', 'CKD'],
|
|
37
|
+
];
|
|
38
|
+
const expressionData = [
|
|
39
|
+
// Gene 1
|
|
40
|
+
[10, 20, 30, 40, 11, 21, 31, 41],
|
|
41
|
+
];
|
|
42
|
+
const obsIndex = ['cell1-1', 'cell1-2', 'cell1-3', 'cell1-4', 'cell2-1', 'cell2-2', 'cell2-3', 'cell2-4'];
|
|
43
|
+
const mergedCellSets = {
|
|
44
|
+
tree: [
|
|
45
|
+
{
|
|
46
|
+
name: 'Cell type',
|
|
47
|
+
children: [
|
|
48
|
+
{
|
|
49
|
+
name: 'T cell',
|
|
50
|
+
set: [['cell1-1', null], ['cell1-3', null], ['cell2-1', null], ['cell2-3', null]],
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
name: 'B cell',
|
|
54
|
+
set: [['cell1-2', null], ['cell1-4', null], ['cell2-2', null], ['cell2-4', null]],
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
const geneSelection = [
|
|
61
|
+
'Gene 1',
|
|
62
|
+
];
|
|
63
|
+
const cellSetSelection = [
|
|
64
|
+
['Cell type', 'T cell'],
|
|
65
|
+
['Cell type', 'B cell'],
|
|
66
|
+
];
|
|
67
|
+
const cellSetColor = [
|
|
68
|
+
{ set: ['Cell type', 'T cell'], color: [255, 0, 0] },
|
|
69
|
+
{ set: ['Cell type', 'B cell'], color: [0, 255, 0] },
|
|
70
|
+
];
|
|
71
|
+
const featureValueTransform = null;
|
|
72
|
+
const featureValueTransformCoefficient = 1;
|
|
73
|
+
const [result] = stratifyExpressionData(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, mergedCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient);
|
|
74
|
+
const aggregateData = aggregateStratifiedExpressionData(result, geneSelection);
|
|
75
|
+
const summaryResult = summarizeStratifiedExpressionData(aggregateData, true);
|
|
76
|
+
expect([...summaryResult.keys()]).toEqual([['Cell type', 'T cell'], ['Cell type', 'B cell']]);
|
|
77
|
+
expect([...summaryResult.get(['Cell type', 'T cell']).keys()]).toEqual([['Clinical groups', 'AKI'], ['Clinical groups', 'CKD']]);
|
|
78
|
+
expect(Object.keys(summaryResult.get(['Cell type', 'T cell']).get(['Clinical groups', 'AKI']))).toEqual([
|
|
79
|
+
'quartiles',
|
|
80
|
+
'range',
|
|
81
|
+
'whiskers',
|
|
82
|
+
'chauvenetRange',
|
|
83
|
+
'nonOutliers',
|
|
84
|
+
]);
|
|
85
|
+
const histogramResult = histogramStratifiedExpressionData(summaryResult, 16, null);
|
|
86
|
+
expect(Object.keys(histogramResult)).toEqual([
|
|
87
|
+
'groupSummaries',
|
|
88
|
+
'groupData',
|
|
89
|
+
'groupBins',
|
|
90
|
+
'groupBinsMax',
|
|
91
|
+
'y',
|
|
92
|
+
]);
|
|
93
|
+
expect(histogramResult.groupSummaries.map(d => d.key)).toEqual([['Cell type', 'T cell'], ['Cell type', 'B cell']]);
|
|
94
|
+
expect(histogramResult.groupBinsMax).toEqual(1);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|