@vitessce/statistical-plots 3.5.9 → 3.5.10
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-19841f78.js → deflate-ad0dcbe4.js} +1 -1
- package/dist/{index-dc733355.js → index-b8398176.js} +33528 -15439
- package/dist/index.js +6 -5
- package/dist/{jpeg-a83077be.js → jpeg-81bd1053.js} +1 -1
- package/dist/{lerc-1edd075a.js → lerc-b15c3a4c.js} +1 -1
- package/dist/{lzw-9572eac3.js → lzw-503cb795.js} +1 -1
- package/dist/{packbits-cce11fbc.js → packbits-40cbad40.js} +1 -1
- package/dist/{raw-f7587aff.js → raw-9b8d9daf.js} +1 -1
- package/dist/{webimage-8d38cd8b.js → webimage-bbc59b4a.js} +1 -1
- package/dist-tsc/CellSetCompositionBarPlot.js +3 -3
- package/dist-tsc/CellSetCompositionBarPlotSubscriber.js +1 -1
- package/dist-tsc/CellSetExpressionPlot.d.ts.map +1 -1
- package/dist-tsc/CellSetExpressionPlot.js +26 -10
- package/dist-tsc/CellSetExpressionPlotSubscriber.d.ts.map +1 -1
- package/dist-tsc/CellSetExpressionPlotSubscriber.js +5 -2
- package/dist-tsc/DotPlot.d.ts.map +1 -1
- package/dist-tsc/DotPlot.js +54 -5
- package/dist-tsc/DotPlotSubscriber.d.ts.map +1 -1
- package/dist-tsc/DotPlotSubscriber.js +1 -1
- package/dist-tsc/FeatureStatsTable.d.ts +2 -0
- package/dist-tsc/FeatureStatsTable.d.ts.map +1 -0
- package/dist-tsc/FeatureStatsTable.js +81 -0
- package/dist-tsc/FeatureStatsTableSubscriber.d.ts +2 -0
- package/dist-tsc/FeatureStatsTableSubscriber.d.ts.map +1 -0
- package/dist-tsc/FeatureStatsTableSubscriber.js +28 -0
- package/dist-tsc/Treemap.d.ts.map +1 -1
- package/dist-tsc/Treemap.js +17 -3
- package/dist-tsc/TreemapSubscriber.d.ts.map +1 -1
- package/dist-tsc/TreemapSubscriber.js +5 -3
- package/dist-tsc/VolcanoPlot.d.ts.map +1 -1
- package/dist-tsc/VolcanoPlot.js +15 -46
- package/dist-tsc/VolcanoPlotSubscriber.d.ts.map +1 -1
- package/dist-tsc/VolcanoPlotSubscriber.js +4 -2
- package/dist-tsc/index.d.ts +1 -0
- package/dist-tsc/index.js +1 -0
- package/dist-tsc/utils.d.ts +1 -0
- package/dist-tsc/utils.d.ts.map +1 -1
- package/dist-tsc/utils.js +56 -0
- package/package.json +8 -7
- package/src/CellSetCompositionBarPlot.js +3 -3
- package/src/CellSetCompositionBarPlotSubscriber.js +1 -1
- package/src/CellSetExpressionPlot.js +33 -10
- package/src/CellSetExpressionPlotSubscriber.js +10 -3
- package/src/DotPlot.js +77 -9
- package/src/DotPlotSubscriber.js +3 -1
- package/src/FeatureStatsTable.js +116 -0
- package/src/FeatureStatsTableSubscriber.js +133 -0
- package/src/Treemap.js +21 -3
- package/src/TreemapSubscriber.js +6 -4
- package/src/VolcanoPlot.js +16 -64
- package/src/VolcanoPlotSubscriber.js +6 -1
- package/src/index.js +1 -0
- package/src/utils.js +82 -1
package/dist/index.js
CHANGED
@@ -1,19 +1,20 @@
|
|
1
|
-
import { b,
|
1
|
+
import { b, f, C, e, a, i, D, h, E, F, c, d, T, V } from "./index-b8398176.js";
|
2
2
|
import "react";
|
3
3
|
import "@vitessce/vit-s";
|
4
4
|
import "react-dom";
|
5
5
|
export {
|
6
6
|
b as CellSetCompositionBarPlotSubscriber,
|
7
|
-
|
7
|
+
f as CellSetExpressionPlot,
|
8
8
|
C as CellSetExpressionPlotSubscriber,
|
9
|
-
|
9
|
+
e as CellSetSizesPlot,
|
10
10
|
a as CellSetSizesPlotSubscriber,
|
11
|
-
|
11
|
+
i as DotPlot,
|
12
12
|
D as DotPlotSubscriber,
|
13
|
-
|
13
|
+
h as ExpressionHistogram,
|
14
14
|
E as ExpressionHistogramSubscriber,
|
15
15
|
F as FeatureBarPlotSubscriber,
|
16
16
|
c as FeatureSetEnrichmentBarPlotSubscriber,
|
17
|
+
d as FeatureStatsTableSubscriber,
|
17
18
|
T as TreemapSubscriber,
|
18
19
|
V as VolcanoPlotSubscriber
|
19
20
|
};
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { i as inflate_1 } from "./pako.esm-68f84e2a.js";
|
2
|
-
import { g as getDefaultExportFromCjs, B as BaseDecoder } from "./index-
|
2
|
+
import { g as getDefaultExportFromCjs, B as BaseDecoder } from "./index-b8398176.js";
|
3
3
|
import "react";
|
4
4
|
import "@vitessce/vit-s";
|
5
5
|
import "react-dom";
|
@@ -69,12 +69,12 @@ export default function CellSetCompositionBarPlot(props) {
|
|
69
69
|
obsSetColorScale, sampleSetColorScale,
|
70
70
|
]);
|
71
71
|
// Get an array of keys for sorting purposes.
|
72
|
-
const keys = computedData
|
72
|
+
const keys = computedData?.map(d => d.keyName);
|
73
73
|
const colorScale = {
|
74
74
|
// Manually set the color scale so that Vega-Lite does
|
75
75
|
// not choose the colors automatically.
|
76
|
-
domain: computedData
|
77
|
-
range: computedData
|
76
|
+
domain: computedData?.map(d => d.key),
|
77
|
+
range: computedData?.map(d => d.color),
|
78
78
|
};
|
79
79
|
const captializedObsType = capitalize(obsType);
|
80
80
|
const opacityScale = {
|
@@ -36,5 +36,5 @@ export function CellSetCompositionBarPlotSubscriber(props) {
|
|
36
36
|
// TODO: support the following options
|
37
37
|
// - Use logFoldChange vs. intercept+effect for the bar y-value.
|
38
38
|
// - Boolean flag to allow hiding non-significant bars.
|
39
|
-
return (_jsx(TitleInfo, { title: `${capitalize(obsType)} Set Composition Analysis Plot`, removeGridComponent: removeGridComponent, theme: theme, isReady: isReady, helpText: helpText, children: _jsx("div", { ref: containerRef, className: classes.vegaContainer, children: obsSetStats ? (_jsx(CellSetCompositionBarPlot, { theme: theme, width: width, height: height, obsType: obsType, obsSetsColumnNameMapping: obsSetsColumnNameMapping, obsSetsColumnNameMappingReversed: obsSetsColumnNameMappingReversed, sampleSetsColumnNameMapping: sampleSetsColumnNameMapping, sampleSetsColumnNameMappingReversed: sampleSetsColumnNameMappingReversed, sampleSetSelection: sampleSetSelection, obsSetSelection: obsSetSelection, obsSetColor: obsSetColor, sampleSetColor: sampleSetColor, data: obsSetStats, onBarSelect: onBarSelect })) : (_jsxs("span", { children: ["Select at least one ", obsType, " set."] })) }) }));
|
39
|
+
return (_jsx(TitleInfo, { title: `${capitalize(obsType)} Set Composition Analysis Plot`, removeGridComponent: removeGridComponent, theme: theme, isReady: isReady, helpText: helpText, children: _jsx("div", { ref: containerRef, className: classes.vegaContainer, children: obsSetStats ? (_jsx(CellSetCompositionBarPlot, { theme: theme, width: width, height: height, obsType: obsType, obsSetsColumnNameMapping: obsSetsColumnNameMapping, obsSetsColumnNameMappingReversed: obsSetsColumnNameMappingReversed, sampleSetsColumnNameMapping: sampleSetsColumnNameMapping, sampleSetsColumnNameMappingReversed: sampleSetsColumnNameMappingReversed, sampleSetSelection: sampleSetSelection, obsSetSelection: obsSetSelection, obsSetColor: obsSetColor, sampleSetColor: sampleSetColor, data: obsSetStats, onBarSelect: onBarSelect })) : (_jsxs("span", { children: ["Select at least one ", obsType, " set and a pair of ", sampleType, " sets."] })) }) }));
|
40
40
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"CellSetExpressionPlot.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlot.js"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"CellSetExpressionPlot.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlot.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qDAjBG;IAAwB,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;CAErB,eAgZA"}
|
@@ -9,6 +9,7 @@ import { area as d3_area, curveBasis } from 'd3-shape';
|
|
9
9
|
import { select } from 'd3-selection';
|
10
10
|
import { colorArrayToString } from '@vitessce/sets-utils';
|
11
11
|
import { capitalize } from '@vitessce/utils';
|
12
|
+
import { getColorScale } from './utils.js';
|
12
13
|
const scaleBand = vega_scale('band');
|
13
14
|
/**
|
14
15
|
* Gene expression histogram displayed as a bar chart,
|
@@ -32,20 +33,21 @@ const scaleBand = vega_scale('band');
|
|
32
33
|
* for the feature value transformation function.
|
33
34
|
*/
|
34
35
|
export default function CellSetExpressionPlot(props) {
|
35
|
-
const { yMin: yMinProp, yUnits, jitter,
|
36
|
+
const { yMin: yMinProp, xAxisTitle = null, yUnits, jitter, obsSetSelection, obsSetColor, sampleSetSelection, sampleSetColor, colors, data, theme, width, height, marginTop = 5, marginRight = 5, marginLeft = 50, marginBottom, obsType, featureType, featureValueType, featureValueTransformName, } = props;
|
36
37
|
const svgRef = useRef();
|
38
|
+
const obsSetColorScale = useMemo(() => getColorScale(obsSetSelection, obsSetColor, theme), [obsSetSelection, obsSetColor, theme]);
|
37
39
|
// Get the max characters in an axis label for autsizing the bottom margin.
|
38
40
|
const maxCharactersForLabel = useMemo(() => {
|
39
|
-
if (!
|
41
|
+
if (!obsSetSelection) {
|
40
42
|
return 0;
|
41
43
|
}
|
42
|
-
const cellSetNames =
|
44
|
+
const cellSetNames = obsSetSelection.map(d => d.at(-1));
|
43
45
|
return cellSetNames.reduce((acc, name) => {
|
44
46
|
// eslint-disable-next-line no-param-reassign
|
45
47
|
acc = acc === undefined || name.length > acc ? name.length : acc;
|
46
48
|
return acc;
|
47
49
|
}, 0);
|
48
|
-
}, [
|
50
|
+
}, [obsSetSelection]);
|
49
51
|
const isStratified = (Array.isArray(sampleSetSelection) && sampleSetSelection.length === 2);
|
50
52
|
useEffect(() => {
|
51
53
|
const domElement = svgRef.current;
|
@@ -54,7 +56,7 @@ export default function CellSetExpressionPlot(props) {
|
|
54
56
|
: '';
|
55
57
|
const unitSuffix = yUnits ? ` (${yUnits})` : '';
|
56
58
|
const yTitle = `${transformPrefix}${capitalize(featureValueType)}${unitSuffix}`;
|
57
|
-
const xTitle = `${capitalize(obsType)} Set`;
|
59
|
+
const xTitle = xAxisTitle ?? `${capitalize(obsType)} Set`;
|
58
60
|
// Use a square-root term because the angle of the labels is 45 degrees (see below)
|
59
61
|
// so the perpendicular distance to the bottom of the labels is proportional to the
|
60
62
|
// square root of the length of the labels along the imaginary hypotenuse.
|
@@ -102,7 +104,7 @@ export default function CellSetExpressionPlot(props) {
|
|
102
104
|
const innerHeight = height - autoMarginBottom;
|
103
105
|
const xGroup = scaleBand()
|
104
106
|
.range([marginLeft, width - marginRight])
|
105
|
-
.domain(
|
107
|
+
.domain(obsSetSelection)
|
106
108
|
.padding(0.1);
|
107
109
|
// For the y domain, use the yMin prop
|
108
110
|
// to support a use case such as 'Aspect Ratio',
|
@@ -256,17 +258,30 @@ export default function CellSetExpressionPlot(props) {
|
|
256
258
|
.selectAll('text')
|
257
259
|
.style('font-size', '11px');
|
258
260
|
// X-axis ticks
|
259
|
-
g
|
261
|
+
const xTickG = g
|
260
262
|
.append('g')
|
261
263
|
.attr('transform', `translate(0,${innerHeight})`)
|
262
|
-
.style('font-size', '14px')
|
263
|
-
|
264
|
+
.style('font-size', '14px');
|
265
|
+
xTickG.call(axisBottom(xGroup).tickFormat(d => d.at(-1)))
|
264
266
|
.selectAll('text')
|
265
267
|
.style('font-size', '11px')
|
266
268
|
.attr('dx', '-6px')
|
267
269
|
.attr('dy', '6px')
|
268
270
|
.attr('transform', 'rotate(-45)')
|
269
271
|
.style('text-anchor', 'end');
|
272
|
+
if (isStratified) {
|
273
|
+
// Associate each X tick with a cell type color,
|
274
|
+
// since in the stratified case the violins are colored
|
275
|
+
// by sample set.
|
276
|
+
const tickWidth = xGroup.bandwidth();
|
277
|
+
xTickG.selectAll('.tick')
|
278
|
+
.append('rect')
|
279
|
+
.attr('x', -tickWidth / 2)
|
280
|
+
// .attr("y", -innerHeight)
|
281
|
+
.attr('width', tickWidth)
|
282
|
+
.attr('height', 4)
|
283
|
+
.style('fill', d => obsSetColorScale(d));
|
284
|
+
}
|
270
285
|
// Y-axis title
|
271
286
|
g
|
272
287
|
.append('text')
|
@@ -333,7 +348,8 @@ export default function CellSetExpressionPlot(props) {
|
|
333
348
|
}, [width, height, data, marginLeft, marginBottom, colors,
|
334
349
|
jitter, theme, yMinProp, marginTop, marginRight, featureType,
|
335
350
|
featureValueType, featureValueTransformName, yUnits, obsType,
|
336
|
-
maxCharactersForLabel, sampleSetSelection,
|
351
|
+
maxCharactersForLabel, sampleSetSelection, isStratified,
|
352
|
+
obsSetColorScale,
|
337
353
|
]);
|
338
354
|
return (_jsx("svg", { ref: svgRef, style: {
|
339
355
|
top: 0,
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"CellSetExpressionPlotSubscriber.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlotSubscriber.js"],"names":[],"mappings":"AAmGA;;;;;;;;;GASG;AACH,uDALG;IAAwB,mBAAmB;IACrB,kBAAkB,EAAhC,MAAM;IAEQ,KAAK,EAAnB,MAAM;CAChB,
|
1
|
+
{"version":3,"file":"CellSetExpressionPlotSubscriber.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlotSubscriber.js"],"names":[],"mappings":"AAmGA;;;;;;;;;GASG;AACH,uDALG;IAAwB,mBAAmB;IACrB,kBAAkB,EAAhC,MAAM;IAEQ,KAAK,EAAnB,MAAM;CAChB,eA2KA"}
|
@@ -63,7 +63,7 @@ function useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, exp
|
|
63
63
|
* @param {string} props.theme The name of the current Vitessce theme.
|
64
64
|
*/
|
65
65
|
export function CellSetExpressionPlotSubscriber(props) {
|
66
|
-
const { coordinationScopes, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, jitter = false, yMin = null, yUnits = null, helpText = ViewHelpMapping.OBS_SET_FEATURE_VALUE_DISTRIBUTION, } = props;
|
66
|
+
const { coordinationScopes, closeButtonVisible, downloadButtonVisible, removeGridComponent, theme, title, xAxisTitle, jitter = false, yMin = null, yUnits = null, helpText = ViewHelpMapping.OBS_SET_FEATURE_VALUE_DISTRIBUTION, } = props;
|
67
67
|
const classes = useStyles();
|
68
68
|
const loaders = useLoaders();
|
69
69
|
// Get "props" from the coordination space.
|
@@ -104,5 +104,8 @@ export function CellSetExpressionPlotSubscriber(props) {
|
|
104
104
|
|| geneSelection[0])
|
105
105
|
: null;
|
106
106
|
const selectedTransformName = transformOptions.find(o => o.value === featureValueTransform)?.name;
|
107
|
-
|
107
|
+
// Use empty string when firstGeneSelected is null
|
108
|
+
const titleSuffix = firstGeneSelected ? ` (${firstGeneSelected})` : '';
|
109
|
+
return (_jsx(TitleInfo, { title: title ? `${title}${titleSuffix}`
|
110
|
+
: `Expression by ${capitalize(obsType)} Set${titleSuffix}`, closeButtonVisible: closeButtonVisible, downloadButtonVisible: downloadButtonVisible, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, helpText: helpText, options: (_jsx(CellSetExpressionPlotOptions, { featureValueTransform: featureValueTransform, setFeatureValueTransform: setFeatureValueTransform, featureValueTransformCoefficient: featureValueTransformCoefficient, setFeatureValueTransformCoefficient: setFeatureValueTransformCoefficient, transformOptions: transformOptions })), children: _jsx("div", { ref: containerRef, className: classes.vegaContainer, children: histogramData ? (_jsx(CellSetExpressionPlot, { yMin: yMin, yUnits: yUnits, jitter: jitter, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, sampleSetSelection: sampleSetSelection, sampleSetColor: sampleSetColor, colors: setArr, data: histogramData, exprMax: exprMax, theme: theme, width: width, height: height, obsType: obsType, featureType: featureType, featureValueType: featureValueType, featureValueTransformName: selectedTransformName, xAxisTitle: xAxisTitle })) : (_jsxs("span", { children: ["Select a ", featureType, "."] })) }) }));
|
108
111
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"DotPlot.d.ts","sourceRoot":"","sources":["../src/DotPlot.js"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"DotPlot.d.ts","sourceRoot":"","sources":["../src/DotPlot.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;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,eA0NA"}
|
package/dist-tsc/DotPlot.js
CHANGED
@@ -1,8 +1,10 @@
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
-
import React from 'react';
|
2
|
+
import React, { useRef, useEffect, useCallback, useState, useMemo } from 'react';
|
3
3
|
import { clamp } from 'lodash-es';
|
4
4
|
import { VegaPlot, VEGA_THEMES } from '@vitessce/vega';
|
5
5
|
import { capitalize, pluralize as plur } from '@vitessce/utils';
|
6
|
+
import { select } from 'd3-selection';
|
7
|
+
import { getColorScale } from './utils.js';
|
6
8
|
/**
|
7
9
|
* Gene expression dot plot,
|
8
10
|
* implemented with the VegaPlot component.
|
@@ -22,7 +24,8 @@ import { capitalize, pluralize as plur } from '@vitessce/utils';
|
|
22
24
|
* for the feature value transformation function.
|
23
25
|
*/
|
24
26
|
export default function DotPlot(props) {
|
25
|
-
const { isStratified, transpose, data: rawData, theme, width, height, marginRight, marginBottom, obsType, keyLength = 36, featureType, featureValueType, featureValueTransformName, featureValueColormap,
|
27
|
+
const { isStratified, transpose, data: rawData, theme, width, height, marginRight, marginBottom, obsType, sampleType, keyLength = 36, featureType, featureValueType, featureValueTransformName, featureValueColormap, obsSetSelection, obsSetColor, } = props;
|
28
|
+
const vegaContainerRef = useRef();
|
26
29
|
// Add a property `keyGroup` and `keyFeature` which concatenates the key and the name,
|
27
30
|
// which is both unique and can easily be converted
|
28
31
|
// back to the name by taking a substring.
|
@@ -59,11 +62,11 @@ export default function DotPlot(props) {
|
|
59
62
|
const autoMarginForSampleSet = marginRight
|
60
63
|
|| 30 + Math.sqrt(maxCharactersForSampleSet / 2) * 30;
|
61
64
|
const plotWidth = transpose
|
62
|
-
? clamp(width - autoMarginForFeature - 180, 10, Infinity) / (
|
65
|
+
? clamp(width - autoMarginForFeature - 180, 10, Infinity) / (obsSetSelection?.length || 1)
|
63
66
|
: clamp(width - autoMarginForGroup - autoMarginForSampleSet - 200, 10, Infinity);
|
64
67
|
const plotHeight = transpose
|
65
68
|
? clamp((height - autoMarginForGroup - autoMarginForSampleSet - 50), 10, Infinity)
|
66
|
-
: clamp((height - autoMarginForFeature - 80), 10, Infinity) / (
|
69
|
+
: clamp((height - autoMarginForFeature - 80), 10, Infinity) / (obsSetSelection?.length || 1);
|
67
70
|
// Get an array of keys for sorting purposes.
|
68
71
|
const groupKeys = data.map(d => d.keyGroup);
|
69
72
|
const featureKeys = data.map(d => d.keyFeature);
|
@@ -125,6 +128,11 @@ export default function DotPlot(props) {
|
|
125
128
|
legend: {
|
126
129
|
symbolFillColor: 'white',
|
127
130
|
},
|
131
|
+
scale: { domain: [0, 100] },
|
132
|
+
},
|
133
|
+
tooltip: {
|
134
|
+
field: 'pctPosInGroup',
|
135
|
+
type: 'quantitative',
|
128
136
|
},
|
129
137
|
},
|
130
138
|
width: plotWidth,
|
@@ -140,5 +148,46 @@ export default function DotPlot(props) {
|
|
140
148
|
} : {}),
|
141
149
|
},
|
142
150
|
};
|
143
|
-
|
151
|
+
const getTooltipText = useCallback(item => ({
|
152
|
+
[`${capitalize(featureType)}`]: item.datum.feature,
|
153
|
+
[`${capitalize(obsType)} Set`]: item.datum.group,
|
154
|
+
...(isStratified
|
155
|
+
? ({ [`${capitalize(sampleType)} Set`]: item.datum.secondaryGroup })
|
156
|
+
: {}),
|
157
|
+
[`Percentage of ${plur(obsType, 2)} in set`]: item.datum.pctPosInGroup,
|
158
|
+
[meanTransform.join(' ')]: item.datum.meanExpInGroup,
|
159
|
+
}), [featureType, obsType, featureValueType, featureValueTransformName]);
|
160
|
+
const obsSetColorScale = useMemo(() => getColorScale(obsSetSelection, obsSetColor, theme), [obsSetSelection, obsSetColor, theme]);
|
161
|
+
const [vegaRenderIncrement, setVegaRenderIncrement] = useState(0);
|
162
|
+
useEffect(() => {
|
163
|
+
// If the dot plot is stratified by both obsSet and sampleSet,
|
164
|
+
// then we want to add cell set colors.
|
165
|
+
// TODO: do we also want to add these color bars
|
166
|
+
// when only stratified by obsSet?
|
167
|
+
const domElement = vegaContainerRef.current;
|
168
|
+
// Here, we assume that the Vega SVG renderer is being used.
|
169
|
+
const svg = select(domElement)
|
170
|
+
.select('svg');
|
171
|
+
// We use the following CSS selector to identify all of
|
172
|
+
// the <line> elements that we are interested to modify.
|
173
|
+
const tickEls = svg.selectAll('g.root g.column_footer g.role-axis g.role-axis-domain line');
|
174
|
+
tickEls
|
175
|
+
.attr('stroke-width', 5)
|
176
|
+
.attr('dy', 2.5)
|
177
|
+
.attr('stroke', (d, i) => {
|
178
|
+
const obsSetPath = obsSetSelection?.[i];
|
179
|
+
return obsSetColorScale(obsSetPath);
|
180
|
+
});
|
181
|
+
}, [vegaContainerRef, vegaRenderIncrement, obsSetSelection, obsSetColorScale]);
|
182
|
+
// We want to increment the counter whenever we detect that VegaPlot
|
183
|
+
// has re-rendered.
|
184
|
+
const onNewView = useCallback(() => {
|
185
|
+
setVegaRenderIncrement(prev => prev + 1);
|
186
|
+
}, []);
|
187
|
+
// This is kind of hacky, since it is possible that the useEffect runs prior
|
188
|
+
// to the Vega rendering, but in practice it seems to work.
|
189
|
+
useEffect(() => {
|
190
|
+
setVegaRenderIncrement(prev => prev + 1);
|
191
|
+
}, [rawData]);
|
192
|
+
return (_jsx("div", { ref: vegaContainerRef, children: _jsx(VegaPlot, { data: data, spec: spec, onNewView: onNewView, getTooltipText: getTooltipText, renderer: "svg" }) }));
|
144
193
|
}
|
@@ -1 +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,
|
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,eAsJA"}
|
@@ -50,5 +50,5 @@ export function DotPlotSubscriber(props) {
|
|
50
50
|
]);
|
51
51
|
const [resultArr, meanExpressionMax] = useExpressionSummaries(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, posThreshold, featureLabelsMap);
|
52
52
|
const selectedTransformName = transformOptions.find(o => o.value === featureValueTransform)?.name;
|
53
|
-
return (_jsx(TitleInfo, { title: title, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, helpText: helpText, 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,
|
53
|
+
return (_jsx(TitleInfo, { title: title, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, helpText: helpText, 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, sampleType: sampleType, featureType: featureType, featureValueType: featureValueType, featureValueTransformName: selectedTransformName, featureValueColormap: featureValueColormap, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor })) : (_jsxs("span", { children: ["Select at least one ", featureType, "."] })) }) }));
|
54
54
|
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"FeatureStatsTable.d.ts","sourceRoot":"","sources":["../src/FeatureStatsTable.js"],"names":[],"mappings":"AAWA,mEAwGC"}
|
@@ -0,0 +1,81 @@
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
2
|
+
import React, { useMemo, useState, useCallback } from 'react';
|
3
|
+
import { DataGrid } from '@mui/x-data-grid';
|
4
|
+
import { capitalize } from '@vitessce/utils';
|
5
|
+
import { useFilteredVolcanoData } from './utils.js';
|
6
|
+
const ROW_ID_DELIMITER = '___';
|
7
|
+
const INITIAL_SORT_MODEL = [
|
8
|
+
// We initially set the sorting this way
|
9
|
+
{ field: 'logFoldChange', sort: 'desc' },
|
10
|
+
];
|
11
|
+
export default function FeatureStatsTable(props) {
|
12
|
+
const { obsType, featureType, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, data, setFeatureSelection, featurePointSignificanceThreshold, featurePointFoldChangeThreshold, } = props;
|
13
|
+
const [
|
14
|
+
// eslint-disable-next-line no-unused-vars
|
15
|
+
computedData, filteredData,] = useFilteredVolcanoData({
|
16
|
+
data,
|
17
|
+
obsSetsColumnNameMappingReversed,
|
18
|
+
sampleSetsColumnNameMappingReversed,
|
19
|
+
featurePointFoldChangeThreshold,
|
20
|
+
featurePointSignificanceThreshold,
|
21
|
+
sampleSetSelection,
|
22
|
+
});
|
23
|
+
// Reference: https://v4.mui.com/api/data-grid/data-grid/
|
24
|
+
const columns = useMemo(() => ([
|
25
|
+
{
|
26
|
+
field: 'featureId',
|
27
|
+
headerName: capitalize(featureType),
|
28
|
+
width: 200,
|
29
|
+
editable: false,
|
30
|
+
},
|
31
|
+
{
|
32
|
+
field: 'logFoldChange',
|
33
|
+
headerName: 'Log Fold-Change',
|
34
|
+
width: 200,
|
35
|
+
editable: false,
|
36
|
+
},
|
37
|
+
{
|
38
|
+
field: 'featureSignificance',
|
39
|
+
headerName: 'P-value',
|
40
|
+
width: 200,
|
41
|
+
editable: false,
|
42
|
+
},
|
43
|
+
{
|
44
|
+
field: 'obsSetName',
|
45
|
+
headerName: `${capitalize(obsType)} Set`,
|
46
|
+
width: 200,
|
47
|
+
editable: false,
|
48
|
+
},
|
49
|
+
]), [obsType, featureType]);
|
50
|
+
const rows = useMemo(() => {
|
51
|
+
let result = [];
|
52
|
+
if (filteredData) {
|
53
|
+
filteredData.forEach((comparisonObject) => {
|
54
|
+
const { df, metadata } = comparisonObject;
|
55
|
+
const coordinationValues = metadata.coordination_values;
|
56
|
+
const rawObsSetPath = coordinationValues.obsSetFilter
|
57
|
+
? coordinationValues.obsSetFilter[0]
|
58
|
+
: coordinationValues.obsSetSelection[0];
|
59
|
+
const obsSetPath = [...rawObsSetPath];
|
60
|
+
obsSetPath[0] = obsSetsColumnNameMappingReversed[rawObsSetPath[0]];
|
61
|
+
const obsSetName = obsSetPath.at(-1);
|
62
|
+
result = result.concat(df.map(row => ({
|
63
|
+
...row,
|
64
|
+
id: `${row.featureId}${ROW_ID_DELIMITER}${obsSetName}`,
|
65
|
+
obsSetName,
|
66
|
+
})));
|
67
|
+
});
|
68
|
+
}
|
69
|
+
return result;
|
70
|
+
}, [filteredData, obsSetsColumnNameMappingReversed]);
|
71
|
+
const onSelectionModelChange = useCallback((rowIds) => {
|
72
|
+
const featureIds = rowIds.map(rowId => rowId.split(ROW_ID_DELIMITER)[0]);
|
73
|
+
setFeatureSelection(featureIds);
|
74
|
+
}, []);
|
75
|
+
const rowSelectionModel = useMemo(() => [], []);
|
76
|
+
const [sortModel, setSortModel] = useState(INITIAL_SORT_MODEL);
|
77
|
+
const getRowId = useCallback(row => row.id, []);
|
78
|
+
return (_jsx(DataGrid, { density: "compact", rows: rows, columns: columns, pageSize: 10,
|
79
|
+
// checkboxSelection // TODO: uncomment to enable multiple-row selection
|
80
|
+
onSelectionModelChange: onSelectionModelChange, rowSelectionModel: rowSelectionModel, getRowId: getRowId, sortModel: sortModel, onSortModelChange: setSortModel }));
|
81
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"FeatureStatsTableSubscriber.d.ts","sourceRoot":"","sources":["../src/FeatureStatsTableSubscriber.js"],"names":[],"mappings":"AAoBA,qEAgHC"}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
2
|
+
/* eslint-disable no-unused-vars */
|
3
|
+
import React from 'react';
|
4
|
+
import { TitleInfo, useCoordination, useLoaders, useReady, useFeatureStatsData, useMatchingLoader, useColumnNameMapping, } from '@vitessce/vit-s';
|
5
|
+
import { ViewType, COMPONENT_COORDINATION_TYPES, ViewHelpMapping, DataType, } from '@vitessce/constants-internal';
|
6
|
+
import FeatureStatsTable from './FeatureStatsTable.js';
|
7
|
+
import { useRawSetPaths } from './utils.js';
|
8
|
+
export function FeatureStatsTableSubscriber(props) {
|
9
|
+
const { title = 'Differential Expression Results', coordinationScopes, removeGridComponent, theme, helpText = ViewHelpMapping.FEATURE_STATS_TABLE, } = props;
|
10
|
+
const loaders = useLoaders();
|
11
|
+
// Get "props" from the coordination space.
|
12
|
+
const [{ dataset, obsType, sampleType, featureType, featureValueType, obsFilter: cellFilter, obsHighlight: cellHighlight, obsSetSelection, obsSetColor, obsColorEncoding: cellColorEncoding, additionalObsSets: additionalCellSets, featurePointSignificanceThreshold, featurePointFoldChangeThreshold, featureValueTransform, featureValueTransformCoefficient, gatingFeatureSelectionX, gatingFeatureSelectionY, featureSelection, sampleSetSelection, sampleSetColor, }, { setObsFilter: setCellFilter, setObsSetSelection, setObsHighlight: setCellHighlight, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setAdditionalObsSets: setAdditionalCellSets, setFeaturePointSignificanceThreshold, setFeaturePointFoldChangeThreshold, setFeatureValueTransform, setFeatureValueTransformCoefficient, setGatingFeatureSelectionX, setGatingFeatureSelectionY, setFeatureSelection, setSampleSetSelection, setSampleSetColor, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.FEATURE_STATS_TABLE], coordinationScopes);
|
13
|
+
const obsSetsLoader = useMatchingLoader(loaders, dataset, DataType.OBS_SETS, { obsType });
|
14
|
+
const sampleSetsLoader = useMatchingLoader(loaders, dataset, DataType.SAMPLE_SETS, { sampleType });
|
15
|
+
const obsSetsColumnNameMapping = useColumnNameMapping(obsSetsLoader);
|
16
|
+
const obsSetsColumnNameMappingReversed = useColumnNameMapping(obsSetsLoader, true);
|
17
|
+
const sampleSetsColumnNameMapping = useColumnNameMapping(sampleSetsLoader);
|
18
|
+
const sampleSetsColumnNameMappingReversed = useColumnNameMapping(sampleSetsLoader, true);
|
19
|
+
const rawSampleSetSelection = useRawSetPaths(sampleSetsColumnNameMapping, sampleSetSelection);
|
20
|
+
const rawObsSetSelection = useRawSetPaths(obsSetsColumnNameMapping, obsSetSelection);
|
21
|
+
const [{ featureStats }, featureStatsStatus] = useFeatureStatsData(loaders, dataset, false, { obsType, featureType, sampleType },
|
22
|
+
// These volcanoOptions are passed to FeatureStatsAnndataLoader.loadMulti():
|
23
|
+
{ sampleSetSelection: rawSampleSetSelection, obsSetSelection: rawObsSetSelection });
|
24
|
+
const isReady = useReady([
|
25
|
+
featureStatsStatus,
|
26
|
+
]);
|
27
|
+
return (_jsx(TitleInfo, { title: title, removeGridComponent: removeGridComponent, theme: theme, isReady: isReady, helpText: helpText, withPadding: false, children: featureStats ? (_jsx(FeatureStatsTable, { theme: theme, obsType: obsType, featureType: featureType, obsSetsColumnNameMapping: obsSetsColumnNameMapping, obsSetsColumnNameMappingReversed: obsSetsColumnNameMappingReversed, sampleSetsColumnNameMapping: sampleSetsColumnNameMapping, sampleSetsColumnNameMappingReversed: sampleSetsColumnNameMappingReversed, sampleSetSelection: sampleSetSelection, obsSetSelection: obsSetSelection, obsSetColor: obsSetColor, sampleSetColor: sampleSetColor, data: featureStats, featureSelection: featureSelection, setFeatureSelection: setFeatureSelection, featurePointSignificanceThreshold: featurePointSignificanceThreshold, featurePointFoldChangeThreshold: featurePointFoldChangeThreshold })) : (_jsxs("p", { style: { padding: '12px' }, children: ["Select at least one ", obsType, " set."] })) }));
|
28
|
+
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Treemap.d.ts","sourceRoot":"","sources":["../src/Treemap.js"],"names":[],"mappings":"AAsBA;;;;;;;;GAQG;AACH,
|
1
|
+
{"version":3,"file":"Treemap.d.ts","sourceRoot":"","sources":["../src/Treemap.js"],"names":[],"mappings":"AAsBA;;;;;;;;GAQG;AACH,yDAoMC"}
|
package/dist-tsc/Treemap.js
CHANGED
@@ -71,6 +71,9 @@ export default function Treemap(props) {
|
|
71
71
|
const svgRef = useRef();
|
72
72
|
useEffect(() => {
|
73
73
|
const domElement = svgRef.current;
|
74
|
+
if (!width || !height) {
|
75
|
+
return;
|
76
|
+
}
|
74
77
|
const svg = select(domElement);
|
75
78
|
svg.selectAll('g').remove();
|
76
79
|
svg
|
@@ -78,7 +81,7 @@ export default function Treemap(props) {
|
|
78
81
|
.attr('height', height)
|
79
82
|
.attr('viewBox', [0, 0, width, height])
|
80
83
|
.attr('style', 'font: 10px sans-serif');
|
81
|
-
if (!treemapLeaves || !obsSetSelection
|
84
|
+
if (!treemapLeaves || !obsSetSelection) {
|
82
85
|
return;
|
83
86
|
}
|
84
87
|
// Add a group for each leaf of the hierarchy.
|
@@ -130,14 +133,25 @@ export default function Treemap(props) {
|
|
130
133
|
})
|
131
134
|
.append('use')
|
132
135
|
.attr('xlink:href', d => d.leafUid.href);
|
136
|
+
const hasSampleSetSelection = Array.isArray(sampleSetSelection);
|
133
137
|
// Append multiline text.
|
134
138
|
leaf.append('text')
|
135
139
|
.attr('clip-path', d => `url(${d.clipUid.href})`)
|
136
140
|
.selectAll('tspan')
|
137
141
|
.data(d => ([
|
138
142
|
// Each element in this array corresponds to a line of text.
|
139
|
-
|
140
|
-
|
143
|
+
...(hasSampleSetSelection
|
144
|
+
? ([
|
145
|
+
d.data?.[0]?.at(-1),
|
146
|
+
d.parent?.data?.[0]?.at(-1),
|
147
|
+
]) : ([
|
148
|
+
// Only use the cell set name
|
149
|
+
// for the line of text
|
150
|
+
// (since no sample set selection)
|
151
|
+
hierarchyLevels[0] === 'obsSet'
|
152
|
+
? d.parent?.data?.[0].at(-1)
|
153
|
+
: d.data?.[0].at(-1),
|
154
|
+
])),
|
141
155
|
`${d.data?.[1].toLocaleString()} ${plur(obsType, d.data?.[1])}`,
|
142
156
|
]))
|
143
157
|
.join('tspan')
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"TreemapSubscriber.d.ts","sourceRoot":"","sources":["../src/TreemapSubscriber.js"],"names":[],"mappings":"AAyBA,
|
1
|
+
{"version":3,"file":"TreemapSubscriber.d.ts","sourceRoot":"","sources":["../src/TreemapSubscriber.js"],"names":[],"mappings":"AAyBA,2DAmPC"}
|
@@ -66,9 +66,9 @@ export function TreemapSubscriber(props) {
|
|
66
66
|
obsResult.get(cellSetKey).set(sampleSetKey, 0);
|
67
67
|
});
|
68
68
|
});
|
69
|
-
const sampleSetSizes = treeToSetSizesBySetNames(mergedSampleSets, sampleSetSelection, sampleSetSelection, sampleSetColor, theme);
|
69
|
+
const sampleSetSizes = hasSampleSetSelection ? treeToSetSizesBySetNames(mergedSampleSets, sampleSetSelection, sampleSetSelection, sampleSetColor, theme) : null;
|
70
70
|
sampleSetKeys.forEach((sampleSetKey) => {
|
71
|
-
const sampleSetSize = sampleSetSizes
|
71
|
+
const sampleSetSize = sampleSetSizes?.find(d => isEqual(d.setNamePath, sampleSetKey))?.size;
|
72
72
|
sampleResult.set(sampleSetKey, sampleSetSize || 0);
|
73
73
|
});
|
74
74
|
if (mergedObsSets && obsSetSelection) {
|
@@ -80,7 +80,9 @@ export function TreemapSubscriber(props) {
|
|
80
80
|
const obsId = obsIndex[i];
|
81
81
|
const cellSet = cellIdToSetMap?.get(obsId);
|
82
82
|
const sampleId = sampleEdges?.get(obsId);
|
83
|
-
const sampleSet = sampleId
|
83
|
+
const sampleSet = sampleId && hasSampleSetSelection
|
84
|
+
? sampleIdToSetMap?.get(sampleId)
|
85
|
+
: null;
|
84
86
|
if (hasSampleSetSelection && !sampleSet) {
|
85
87
|
// Skip this sample if it is not in the selected sample set.
|
86
88
|
// eslint-disable-next-line no-continue
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"VolcanoPlot.d.ts","sourceRoot":"","sources":["../src/VolcanoPlot.js"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"VolcanoPlot.d.ts","sourceRoot":"","sources":["../src/VolcanoPlot.js"],"names":[],"mappings":"AAWA,6DAgQC"}
|