@vitessce/statistical-plots 3.5.10 → 3.5.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{deflate-ad0dcbe4.js → deflate-b8c6daae.js} +1 -1
  2. package/dist/{index-b8398176.js → index-134a71c6.js} +224 -80
  3. package/dist/index.js +1 -1
  4. package/dist/{jpeg-81bd1053.js → jpeg-1b818d11.js} +1 -1
  5. package/dist/{lerc-b15c3a4c.js → lerc-f38cbdfc.js} +1 -1
  6. package/dist/{lzw-503cb795.js → lzw-1120aba9.js} +1 -1
  7. package/dist/{packbits-40cbad40.js → packbits-2d02b5e3.js} +1 -1
  8. package/dist/{raw-9b8d9daf.js → raw-0887baec.js} +1 -1
  9. package/dist/{webimage-bbc59b4a.js → webimage-533922a5.js} +1 -1
  10. package/dist-tsc/CellSetCompositionBarPlot.d.ts.map +1 -1
  11. package/dist-tsc/CellSetCompositionBarPlot.js +28 -7
  12. package/dist-tsc/CellSetExpressionPlotOptions.d.ts.map +1 -1
  13. package/dist-tsc/CellSetExpressionPlotOptions.js +11 -4
  14. package/dist-tsc/CellSetExpressionPlotSubscriber.d.ts.map +1 -1
  15. package/dist-tsc/CellSetExpressionPlotSubscriber.js +43 -11
  16. package/dist-tsc/DotPlot.d.ts.map +1 -1
  17. package/dist-tsc/DotPlot.js +6 -2
  18. package/dist-tsc/FeatureSetEnrichmentBarPlot.d.ts.map +1 -1
  19. package/dist-tsc/FeatureSetEnrichmentBarPlot.js +7 -6
  20. package/dist-tsc/FeatureSetEnrichmentBarPlotSubscriber.d.ts.map +1 -1
  21. package/dist-tsc/FeatureSetEnrichmentBarPlotSubscriber.js +5 -2
  22. package/dist-tsc/TreemapSubscriber.d.ts.map +1 -1
  23. package/dist-tsc/TreemapSubscriber.js +10 -6
  24. package/dist-tsc/expr-hooks.d.ts.map +1 -1
  25. package/dist-tsc/expr-hooks.test.js +2 -1
  26. package/package.json +7 -7
  27. package/src/CellSetCompositionBarPlot.js +35 -9
  28. package/src/CellSetExpressionPlotOptions.js +39 -2
  29. package/src/CellSetExpressionPlotSubscriber.js +47 -11
  30. package/src/DotPlot.js +4 -2
  31. package/src/FeatureSetEnrichmentBarPlot.js +7 -6
  32. package/src/FeatureSetEnrichmentBarPlotSubscriber.js +5 -2
  33. package/src/TreemapSubscriber.js +20 -7
  34. package/src/expr-hooks.js +0 -1
  35. package/src/expr-hooks.test.js +2 -1
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { b, f, C, e, a, i, D, h, E, F, c, d, T, V } from "./index-b8398176.js";
1
+ import { b, f, C, e, a, i, D, h, E, F, c, d, T, V } from "./index-134a71c6.js";
2
2
  import "react";
3
3
  import "@vitessce/vit-s";
4
4
  import "react-dom";
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-b8398176.js";
1
+ import { B as BaseDecoder } from "./index-134a71c6.js";
2
2
  import "react";
3
3
  import "@vitessce/vit-s";
4
4
  import "react-dom";
@@ -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-b8398176.js";
2
+ import { g as getDefaultExportFromCjs, B as BaseDecoder } from "./index-134a71c6.js";
3
3
  import "react";
4
4
  import "@vitessce/vit-s";
5
5
  import "react-dom";
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-b8398176.js";
1
+ import { B as BaseDecoder } from "./index-134a71c6.js";
2
2
  import "react";
3
3
  import "@vitessce/vit-s";
4
4
  import "react-dom";
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-b8398176.js";
1
+ import { B as BaseDecoder } from "./index-134a71c6.js";
2
2
  import "react";
3
3
  import "@vitessce/vit-s";
4
4
  import "react-dom";
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-b8398176.js";
1
+ import { B as BaseDecoder } from "./index-134a71c6.js";
2
2
  import "react";
3
3
  import "@vitessce/vit-s";
4
4
  import "react-dom";
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-b8398176.js";
1
+ import { B as BaseDecoder } from "./index-134a71c6.js";
2
2
  import "react";
3
3
  import "@vitessce/vit-s";
4
4
  import "react-dom";
@@ -1 +1 @@
1
- {"version":3,"file":"CellSetCompositionBarPlot.d.ts","sourceRoot":"","sources":["../src/CellSetCompositionBarPlot.js"],"names":[],"mappings":"AAOA;;GAEG;AACH,2EAkMC"}
1
+ {"version":3,"file":"CellSetCompositionBarPlot.d.ts","sourceRoot":"","sources":["../src/CellSetCompositionBarPlot.js"],"names":[],"mappings":"AAUA;;GAEG;AACH,2EAyNC"}
@@ -2,14 +2,20 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import React, { useCallback, useMemo } from 'react';
3
3
  import { clamp, isEqual } from 'lodash-es';
4
4
  import { v4 as uuidv4 } from 'uuid';
5
+ import { extent } from 'd3-array';
5
6
  import { VegaPlot, VEGA_THEMES } from '@vitessce/vega';
6
7
  import { capitalize } from '@vitessce/utils';
7
8
  import { getColorScale } from './utils.js';
9
+ const MAX_BAR_SIZE = 40;
8
10
  /**
9
11
  * Cell set composition results displayed using a bar chart.
10
12
  */
11
13
  export default function CellSetCompositionBarPlot(props) {
12
- const { data, theme, width, height, marginRight = 200, marginBottom = 120, keyLength = 36, obsType, onBarSelect, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, } = props;
14
+ const { data, theme, width, height: heightProp, marginRight = 200, marginBottom = 60, keyLength = 36, obsType, onBarSelect, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, } = props;
15
+ const height = (Array.isArray(obsSetSelection)
16
+ && ((heightProp - marginBottom) / obsSetSelection.length >= MAX_BAR_SIZE))
17
+ ? MAX_BAR_SIZE * obsSetSelection.length + marginBottom
18
+ : heightProp;
13
19
  const [obsSetColorScale, sampleSetColorScale] = useMemo(() => [
14
20
  getColorScale(obsSetSelection, obsSetColor, theme),
15
21
  getColorScale(sampleSetSelection, sampleSetColor, theme),
@@ -20,18 +26,15 @@ export default function CellSetCompositionBarPlot(props) {
20
26
  const { df, metadata } = data[0];
21
27
  // Return in array-of-objects form that Vega-Lite likes.
22
28
  const referenceCellType = metadata?.analysis_params?.reference_cell_type;
29
+ const covariateValue = metadata?.analysis_params?.covariate_value;
23
30
  const coordinationValues = metadata?.coordination_values;
24
31
  const obsSetColumnName = coordinationValues?.obsSetSelection?.[0]?.[0];
25
32
  const obsSetGroupName = obsSetsColumnNameMappingReversed?.[obsSetColumnName];
26
33
  const sampleSetColumnName = coordinationValues?.sampleSetFilter?.[0]?.[0];
27
34
  const sampleSetGroupName = sampleSetsColumnNameMappingReversed?.[sampleSetColumnName];
28
- // See https://github.com/keller-mark/compasce/issues/30 which should simplify this logic once implemented,
29
- // so that we would no longer need to load/check the covariate column in the frontend.
30
- const covariatePrefix = `${sampleSetColumnName}T.`;
31
- const firstCovariateValue = df.covariate?.[0]?.substring(covariatePrefix.length);
32
- const firstCovariateSetPath = [sampleSetGroupName, firstCovariateValue];
35
+ const covariateSetPath = [sampleSetGroupName, covariateValue];
33
36
  let shouldSwapFoldChangeDirection = false;
34
- if (isEqual(firstCovariateSetPath, sampleSetSelection[0])) {
37
+ if (isEqual(covariateSetPath, sampleSetSelection[0])) {
35
38
  shouldSwapFoldChangeDirection = true;
36
39
  }
37
40
  return df.obsSetId.map((obsSetId, i) => {
@@ -85,6 +88,22 @@ export default function CellSetCompositionBarPlot(props) {
85
88
  domain: [true, false],
86
89
  range: [2.0, 0.5],
87
90
  };
91
+ const xExtent = useMemo(() => {
92
+ if (computedData) {
93
+ const [min, max] = extent(computedData.map(d => d.logFoldChange));
94
+ const buffer = 1.05; // Ensure some extra space
95
+ const minAbs = Math.abs(min) * buffer;
96
+ const maxAbs = Math.abs(max) * buffer;
97
+ if (minAbs > maxAbs) {
98
+ return [-minAbs, minAbs];
99
+ }
100
+ return [-maxAbs, maxAbs];
101
+ }
102
+ return undefined;
103
+ }, [computedData]);
104
+ const xScale = {
105
+ domain: xExtent,
106
+ };
88
107
  const spec = {
89
108
  mark: { type: 'bar', stroke: 'black', cursor: 'pointer' },
90
109
  params: [
@@ -120,6 +139,7 @@ export default function CellSetCompositionBarPlot(props) {
120
139
  field: 'logFoldChange',
121
140
  type: 'quantitative',
122
141
  title: 'Log fold-change',
142
+ scale: xScale,
123
143
  },
124
144
  color: {
125
145
  field: 'key',
@@ -136,6 +156,7 @@ export default function CellSetCompositionBarPlot(props) {
136
156
  field: 'isReferenceSet',
137
157
  type: 'nominal',
138
158
  scale: strokeWidthScale,
159
+ legend: null,
139
160
  },
140
161
  tooltip: {
141
162
  field: 'effectExpectedSample',
@@ -1 +1 @@
1
- {"version":3,"file":"CellSetExpressionPlotOptions.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlotOptions.js"],"names":[],"mappings":"AAMA,8EAwIC"}
1
+ {"version":3,"file":"CellSetExpressionPlotOptions.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlotOptions.js"],"names":[],"mappings":"AAUA,8EAyKC"}
@@ -4,16 +4,21 @@ import { useId } from 'react-aria';
4
4
  import { TableCell, TableRow, TextField, Slider } from '@material-ui/core';
5
5
  import { usePlotOptionsStyles, OptionsContainer, OptionSelect } from '@vitessce/vit-s';
6
6
  import { GLSL_COLORMAPS } from '@vitessce/gl';
7
+ import { capitalize } from '@vitessce/utils';
8
+ const FEATURE_AGGREGATION_STRATEGIES = ['first', 'last', 'sum', 'mean'];
7
9
  export default function CellSetExpressionPlotOptions(props) {
8
- const { featureValueTransform, setFeatureValueTransform, featureValueTransformCoefficient, setFeatureValueTransformCoefficient, transformOptions, featureValuePositivityThreshold, setFeatureValuePositivityThreshold, featureValueColormap, setFeatureValueColormap, } = props;
10
+ const { featureValueTransform, setFeatureValueTransform, featureValueTransformCoefficient, setFeatureValueTransformCoefficient, transformOptions, featureValuePositivityThreshold, setFeatureValuePositivityThreshold, featureValueColormap, setFeatureValueColormap, featureAggregationStrategy, setFeatureAggregationStrategy, } = props;
9
11
  const cellSetExpressionPlotOptionsId = useId();
10
12
  const classes = usePlotOptionsStyles();
11
13
  function handleFeatureValueColormapChange(event) {
12
14
  setFeatureValueColormap(event.target.value);
13
15
  }
14
- const handleTransformChange = (event) => {
16
+ function handleTransformChange(event) {
15
17
  setFeatureValueTransform(event.target.value === '' ? null : event.target.value);
16
- };
18
+ }
19
+ function handleFeatureAggregationStrategyChange(event) {
20
+ setFeatureAggregationStrategy(event.target.value);
21
+ }
17
22
  function handlePositivityThresholdChange(event, value) {
18
23
  setFeatureValuePositivityThreshold(value);
19
24
  }
@@ -38,5 +43,7 @@ export default function CellSetExpressionPlotOptions(props) {
38
43
  id: `cellset-expression-transform-select-${cellSetExpressionPlotOptionsId}`,
39
44
  }, children: transformOptions.map(opt => (_jsx("option", { value: opt.value === null ? '' : opt.value, children: opt.name }, opt.name))) }) })] }), _jsxs(TableRow, { children: [_jsx(TableCell, { className: classes.labelCell, variant: "head", scope: "row", children: _jsx("label", { htmlFor: `cellset-expression-transform-coeff-${cellSetExpressionPlotOptionsId}`, children: "Transform Coefficient" }) }), _jsx(TableCell, { className: classes.inputCell, variant: "body", children: _jsx(TextField, { label: "Transform Coefficient", type: "number", onChange: handleTransformCoefficientChange, value: featureValueTransformCoefficient, InputLabelProps: {
40
45
  shrink: true,
41
- }, id: `cellset-expression-transform-coeff-${cellSetExpressionPlotOptionsId}` }) })] }), setFeatureValuePositivityThreshold ? (_jsxs(TableRow, { children: [_jsx(TableCell, { className: classes.labelCell, children: "Positivity Threshold" }), _jsx(TableCell, { className: classes.inputCell, children: _jsx(Slider, { classes: { root: classes.slider, valueLabel: classes.sliderValueLabel }, value: featureValuePositivityThreshold, onChange: handlePositivityThresholdChange, "aria-labelledby": "pos-threshold-slider", valueLabelDisplay: "auto", step: 1.0, min: 0.0, max: 100.0 }) })] }, "transform-coefficient-option-row")) : null] }));
46
+ }, id: `cellset-expression-transform-coeff-${cellSetExpressionPlotOptionsId}` }) })] }), setFeatureAggregationStrategy ? (_jsxs(TableRow, { children: [_jsx(TableCell, { className: classes.labelCell, variant: "head", scope: "row", children: _jsx("label", { htmlFor: `feature-aggregation-strategy-${cellSetExpressionPlotOptionsId}`, children: "Feature Aggregation Strategy" }) }), _jsx(TableCell, { className: classes.inputCell, variant: "body", children: _jsx(OptionSelect, { className: classes.select, value: featureAggregationStrategy ?? 'first', onChange: handleFeatureAggregationStrategyChange, inputProps: {
47
+ id: `feature-aggregation-strategy-${cellSetExpressionPlotOptionsId}`,
48
+ }, children: FEATURE_AGGREGATION_STRATEGIES.map(opt => (_jsx("option", { value: opt, children: capitalize(opt) }, opt))) }) })] })) : null, setFeatureValuePositivityThreshold ? (_jsxs(TableRow, { children: [_jsx(TableCell, { className: classes.labelCell, children: "Positivity Threshold" }), _jsx(TableCell, { className: classes.inputCell, children: _jsx(Slider, { classes: { root: classes.slider, valueLabel: classes.sliderValueLabel }, value: featureValuePositivityThreshold, onChange: handlePositivityThresholdChange, "aria-labelledby": "pos-threshold-slider", valueLabelDisplay: "auto", step: 1.0, min: 0.0, max: 100.0 }) })] }, "transform-coefficient-option-row")) : null] }));
42
49
  }
@@ -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,eA2KA"}
1
+ {"version":3,"file":"CellSetExpressionPlotSubscriber.d.ts","sourceRoot":"","sources":["../src/CellSetExpressionPlotSubscriber.js"],"names":[],"mappings":"AA0HA;;;;;;;;;GASG;AACH,uDALG;IAAwB,mBAAmB;IACrB,kBAAkB,EAAhC,MAAM;IAEQ,KAAK,EAAnB,MAAM;CAChB,eAwLA"}
@@ -8,6 +8,31 @@ import CellSetExpressionPlotOptions from './CellSetExpressionPlotOptions.js';
8
8
  import CellSetExpressionPlot from './CellSetExpressionPlot.js';
9
9
  import { useStyles } from './styles.js';
10
10
  import { summarizeStratifiedExpressionData, histogramStratifiedExpressionData, } from './expr-hooks.js';
11
+ const DEFAULT_FEATURE_AGGREGATION_STRATEGY = 'first';
12
+ function featureSummary(geneSelection, featureAggregationStrategy) {
13
+ if (featureAggregationStrategy === 'first') {
14
+ return geneSelection?.[0];
15
+ }
16
+ if (featureAggregationStrategy === 'last') {
17
+ return geneSelection?.at(-1);
18
+ }
19
+ if (typeof featureAggregationStrategy === 'number') {
20
+ const i = featureAggregationStrategy;
21
+ return geneSelection?.[i];
22
+ }
23
+ if (featureAggregationStrategy === 'sum') {
24
+ // TODO: make these .join()-ed labels more scalable,
25
+ // in particular, if more than 10 or so elements.
26
+ return geneSelection?.join(' + ');
27
+ }
28
+ if (featureAggregationStrategy === 'mean') {
29
+ return `Mean of ${geneSelection?.join(', ')}`;
30
+ }
31
+ if (featureAggregationStrategy === 'difference') {
32
+ return geneSelection?.join(' - ');
33
+ }
34
+ return '';
35
+ }
11
36
  /**
12
37
  * Get expression data for the cells
13
38
  * in the selected cell sets.
@@ -27,14 +52,14 @@ import { summarizeStratifiedExpressionData, histogramStratifiedExpressionData, }
27
52
  * @param {number} featureValueTransformCoefficient A coefficient
28
53
  * to be used in the transform function.
29
54
  */
30
- function useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, theme, yMinProp) {
55
+ function useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, theme, yMinProp, featureAggregationStrategy) {
31
56
  const mergedCellSets = useMemo(() => mergeObsSets(cellSets, additionalCellSets), [cellSets, additionalCellSets]);
32
57
  // From the expression matrix and the list of selected genes / cell sets,
33
58
  // generate the array of data points for the plot.
34
59
  const [expressionArr, expressionMax] = useMemo(() => {
35
60
  const [stratifiedData, exprMax] = stratifyExpressionData(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, mergedCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient);
36
61
  if (stratifiedData) {
37
- const aggregateData = aggregateStratifiedExpressionData(stratifiedData, geneSelection);
62
+ const aggregateData = aggregateStratifiedExpressionData(stratifiedData, geneSelection, featureAggregationStrategy);
38
63
  const summarizedData = summarizeStratifiedExpressionData(aggregateData, true);
39
64
  const histogramData = histogramStratifiedExpressionData(summarizedData, 16, yMinProp);
40
65
  return [histogramData, exprMax];
@@ -44,6 +69,7 @@ function useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, exp
44
69
  mergedCellSets, cellSetSelection, cellSetColor,
45
70
  featureValueTransform, featureValueTransformCoefficient,
46
71
  yMinProp, sampleEdges, sampleSets, sampleSetSelection,
72
+ featureAggregationStrategy,
47
73
  ]);
48
74
  // From the cell sets hierarchy and the list of selected cell sets,
49
75
  // generate the array of set sizes data points for the bar plot.
@@ -67,7 +93,7 @@ export function CellSetExpressionPlotSubscriber(props) {
67
93
  const classes = useStyles();
68
94
  const loaders = useLoaders();
69
95
  // Get "props" from the coordination space.
70
- const [{ dataset, obsType, featureType, featureValueType, featureSelection: geneSelection, featureValueTransform, featureValueTransformCoefficient, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, additionalObsSets: additionalCellSets, sampleType, sampleSetSelection, sampleSetColor, }, { setFeatureValueTransform, setFeatureValueTransformCoefficient, setSampleSetColor, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.OBS_SET_FEATURE_VALUE_DISTRIBUTION], coordinationScopes);
96
+ const [{ dataset, obsType, featureType, featureValueType, featureSelection: geneSelection, featureValueTransform, featureValueTransformCoefficient, obsSetSelection: cellSetSelection, obsSetColor: cellSetColor, additionalObsSets: additionalCellSets, sampleType, sampleSetSelection, sampleSetColor, featureAggregationStrategy, }, { setFeatureValueTransform, setFeatureValueTransformCoefficient, setSampleSetColor, setFeatureAggregationStrategy, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.OBS_SET_FEATURE_VALUE_DISTRIBUTION], coordinationScopes);
71
97
  const [width, height, containerRef] = useGridItemSize();
72
98
  const transformOptions = VALUE_TRANSFORM_OPTIONS;
73
99
  // Get data from loaders using the data hooks.
@@ -97,15 +123,21 @@ export function CellSetExpressionPlotSubscriber(props) {
97
123
  sampleSetsUrls,
98
124
  sampleEdgesUrls,
99
125
  ]);
100
- const [histogramData, setArr, exprMax] = useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, theme, yMin);
101
- const firstGeneSelected = geneSelection && geneSelection.length >= 1
102
- ? (featureLabelsMap?.get(geneSelection[0])
103
- || featureLabelsMap?.get(cleanFeatureId(geneSelection[0]))
104
- || geneSelection[0])
105
- : null;
126
+ const featureAggregationStrategyToUse = featureAggregationStrategy
127
+ ?? DEFAULT_FEATURE_AGGREGATION_STRATEGY;
128
+ const [histogramData, setArr, exprMax] = useExpressionByCellSet(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, cellSets, additionalCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient, theme, yMin, featureAggregationStrategyToUse);
129
+ const featureSuffix = useMemo(() => {
130
+ const cleanedGeneSelection = geneSelection?.map(geneName => (featureLabelsMap?.get(geneName)
131
+ || featureLabelsMap?.get(cleanFeatureId(geneName))
132
+ || geneName));
133
+ if (Array.isArray(cleanedGeneSelection)) {
134
+ return featureSummary(cleanedGeneSelection, featureAggregationStrategyToUse);
135
+ }
136
+ return null;
137
+ }, [geneSelection, featureAggregationStrategyToUse]);
106
138
  const selectedTransformName = transformOptions.find(o => o.value === featureValueTransform)?.name;
107
139
  // Use empty string when firstGeneSelected is null
108
- const titleSuffix = firstGeneSelected ? ` (${firstGeneSelected})` : '';
140
+ const titleSuffix = featureSuffix ? ` (${featureSuffix})` : '';
109
141
  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, "."] })) }) }));
142
+ : `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, featureAggregationStrategy: featureAggregationStrategy, setFeatureAggregationStrategy: setFeatureAggregationStrategy })), 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, "."] })) }) }));
111
143
  }
@@ -1 +1 @@
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"}
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,eA4NA"}
@@ -24,7 +24,10 @@ import { getColorScale } from './utils.js';
24
24
  * for the feature value transformation function.
25
25
  */
26
26
  export default function DotPlot(props) {
27
- const { isStratified, transpose, data: rawData, theme, width, height, marginRight, marginBottom, obsType, sampleType, keyLength = 36, featureType, featureValueType, featureValueTransformName, featureValueColormap, obsSetSelection, obsSetColor, } = props;
27
+ const { isStratified, transpose, data: rawData, theme, width, height, marginRight, marginBottom, obsType, sampleType, keyLength = 36, featureType, featureValueType, featureValueTransformName,
28
+ // TODO: re-enable featureValueColormap coordination
29
+ // featureValueColormap,
30
+ obsSetSelection, obsSetColor, } = props;
28
31
  const vegaContainerRef = useRef();
29
32
  // Add a property `keyGroup` and `keyFeature` which concatenates the key and the name,
30
33
  // which is both unique and can easily be converted
@@ -107,7 +110,8 @@ export default function DotPlot(props) {
107
110
  type: 'quantitative',
108
111
  title: meanTransform,
109
112
  scale: {
110
- scheme: featureValueColormap,
113
+ // scheme: featureValueColormap,
114
+ scheme: 'greys',
111
115
  },
112
116
  legend: {
113
117
  direction: 'horizontal',
@@ -1 +1 @@
1
- {"version":3,"file":"FeatureSetEnrichmentBarPlot.d.ts","sourceRoot":"","sources":["../src/FeatureSetEnrichmentBarPlot.js"],"names":[],"mappings":"AAOA;;GAEG;AACH,6EAgMC"}
1
+ {"version":3,"file":"FeatureSetEnrichmentBarPlot.d.ts","sourceRoot":"","sources":["../src/FeatureSetEnrichmentBarPlot.js"],"names":[],"mappings":"AAOA;;GAEG;AACH,6EAiMC"}
@@ -9,7 +9,7 @@ import { getColorScale } from './utils.js';
9
9
  * Feature set enrichment test results displayed using a bar chart.
10
10
  */
11
11
  export default function FeatureSetEnrichmentBarPlot(props) {
12
- const { data, theme, width, height, marginRight = 200, marginBottom = 120, keyLength = 36, featureType, onBarSelect, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, pValueThreshold, } = props;
12
+ const { data, theme, width, height, marginRight = 300, marginBottom = 120, keyLength = 36, featureType, onBarSelect, obsSetsColumnNameMappingReversed, sampleSetsColumnNameMappingReversed, sampleSetSelection, obsSetSelection, obsSetColor, sampleSetColor, pValueThreshold, } = props;
13
13
  const [obsSetColorScale, sampleSetColorScale] = useMemo(() => [
14
14
  getColorScale(obsSetSelection, obsSetColor, theme),
15
15
  getColorScale(sampleSetSelection, sampleSetColor, theme),
@@ -62,7 +62,7 @@ export default function FeatureSetEnrichmentBarPlot(props) {
62
62
  }
63
63
  return [...a, h];
64
64
  }, []);
65
- const MAX_ROWS = 25;
65
+ const MAX_ROWS = 50;
66
66
  result = result.slice(0, MAX_ROWS);
67
67
  return result;
68
68
  }
@@ -88,7 +88,7 @@ export default function FeatureSetEnrichmentBarPlot(props) {
88
88
  select: {
89
89
  type: 'point',
90
90
  on: 'click[event.shiftKey === false]',
91
- fields: ['name'],
91
+ fields: ['name', 'term'],
92
92
  empty: 'none',
93
93
  },
94
94
  },
@@ -97,7 +97,7 @@ export default function FeatureSetEnrichmentBarPlot(props) {
97
97
  select: {
98
98
  type: 'point',
99
99
  on: 'click[event.shiftKey]',
100
- fields: ['name'],
100
+ fields: ['name', 'term'],
101
101
  empty: 'none',
102
102
  },
103
103
  },
@@ -145,10 +145,11 @@ export default function FeatureSetEnrichmentBarPlot(props) {
145
145
  };
146
146
  const handleSignal = (name, value) => {
147
147
  if (name === 'bar_select') {
148
- onBarSelect(value.obsSetPath);
148
+ onBarSelect(value.name?.[0], value.term?.[0]);
149
149
  }
150
150
  else if (name === 'shift_bar_select') {
151
- onBarSelect(value.obsSetPath, true);
151
+ // Name and term may be arrays
152
+ onBarSelect(value.name, value.term, true);
152
153
  }
153
154
  };
154
155
  const signalListeners = { bar_select: handleSignal, shift_bar_select: handleSignal };
@@ -1 +1 @@
1
- {"version":3,"file":"FeatureSetEnrichmentBarPlotSubscriber.d.ts","sourceRoot":"","sources":["../src/FeatureSetEnrichmentBarPlotSubscriber.js"],"names":[],"mappings":"AA0BA,+EA2IC"}
1
+ {"version":3,"file":"FeatureSetEnrichmentBarPlotSubscriber.d.ts","sourceRoot":"","sources":["../src/FeatureSetEnrichmentBarPlotSubscriber.js"],"names":[],"mappings":"AA0BA,+EA8IC"}
@@ -39,8 +39,11 @@ export function FeatureSetEnrichmentBarPlotSubscriber(props) {
39
39
  // Will not work since transformFeature currently:
40
40
  // - matches based on kgId (rather than term)
41
41
  // - only knows about Reactome pathways (not GO terms).
42
- // console.log(await transformFeature(kgNode, targetFeatureType))
43
- // setFeatureSelection(featureIds);
42
+ const targetsInPathway = await transformFeature(kgNode, targetFeatureType);
43
+ const featureIds = targetsInPathway
44
+ .filter((d, i) => i < 10) // TODO: do not limit the number of genes here
45
+ .map(d => d.label);
46
+ setFeatureSelection(featureIds);
44
47
  }, [setFeatureSelection]);
45
48
  // TODO: support the following options
46
49
  // - p-value threshold for which bars to show
@@ -1 +1 @@
1
- {"version":3,"file":"TreemapSubscriber.d.ts","sourceRoot":"","sources":["../src/TreemapSubscriber.js"],"names":[],"mappings":"AAyBA,2DAmPC"}
1
+ {"version":3,"file":"TreemapSubscriber.d.ts","sourceRoot":"","sources":["../src/TreemapSubscriber.js"],"names":[],"mappings":"AAyBA,2DAgQC"}
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /* eslint-disable no-unused-vars */
3
3
  import React, { useMemo, useCallback } from 'react';
4
4
  import { TitleInfo, useCoordination, useLoaders, useUrls, useReady, useGridItemSize, useObsFeatureMatrixIndices, useObsSetsData, useSampleEdgesData, useSampleSetsData, } from '@vitessce/vit-s';
@@ -43,8 +43,6 @@ export function TreemapSubscriber(props) {
43
43
  ]);
44
44
  const mergedObsSets = useMemo(() => mergeObsSets(obsSets, additionalObsSets), [obsSets, additionalObsSets]);
45
45
  const mergedSampleSets = useMemo(() => mergeObsSets(sampleSets, null), [sampleSets]);
46
- const obsCount = obsIndex?.length || 0;
47
- const sampleCount = sampleIndex?.length || 0;
48
46
  // TODO: use obsFilter / sampleFilter to display
49
47
  // _all_ cells/samples in gray / transparent in background,
50
48
  // and use obsSetSelection/sampleSetSelection to display
@@ -71,7 +69,7 @@ export function TreemapSubscriber(props) {
71
69
  const sampleSetSize = sampleSetSizes?.find(d => isEqual(d.setNamePath, sampleSetKey))?.size;
72
70
  sampleResult.set(sampleSetKey, sampleSetSize || 0);
73
71
  });
74
- if (mergedObsSets && obsSetSelection) {
72
+ if (mergedObsSets && obsSetSelection && obsIndex) {
75
73
  const sampleIdToSetMap = sampleSets && sampleSetSelection
76
74
  ? treeToSelectedSetMap(sampleSets, sampleSetSelection)
77
75
  : null;
@@ -98,11 +96,17 @@ export function TreemapSubscriber(props) {
98
96
  ];
99
97
  }, [obsIndex, sampleEdges, sampleSets, obsSetColor,
100
98
  sampleSetColor, mergedObsSets, obsSetSelection, mergedSampleSets,
101
- sampleSetSelection,
99
+ sampleSetSelection, obsIndex,
102
100
  // TODO: consider filtering-related coordination values
103
101
  ]);
102
+ const totalObsCount = obsIndex?.length || 0;
103
+ const totalSampleCount = sampleIndex?.length || 0;
104
+ const selectedObsCount = obsCounts.reduce((a, h) => a + h.value, 0);
105
+ const selectedSampleCount = sampleCounts.reduce((a, h) => a + h.value, 0);
106
+ const unselectedObsCount = totalObsCount - selectedObsCount;
107
+ const unselectedSampleCount = totalSampleCount - selectedSampleCount;
104
108
  const onNodeClick = useCallback((obsSetPath) => {
105
109
  setObsSetSelection([obsSetPath]);
106
110
  }, [setObsSetSelection]);
107
- return (_jsx(TitleInfo, { title: `Treemap of ${capitalize(plur(obsType, 2))}`, info: `${commaNumber(obsCount)} ${plur(obsType, obsCount)} from ${commaNumber(sampleCount)} ${plur(sampleType, sampleCount)}`, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, helpText: helpText, options: (_jsx(TreemapOptions, { obsType: obsType, sampleType: sampleType, obsColorEncoding: obsColorEncoding, setObsColorEncoding: setObsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, setHierarchyLevels: setHierarchyLevels })), children: _jsx("div", { ref: containerRef, className: classes.vegaContainer, children: _jsx(Treemap, { obsCounts: obsCounts, sampleCounts: sampleCounts, obsColorEncoding: obsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, theme: theme, width: width, height: height, obsType: obsType, sampleType: sampleType, obsSetColor: obsSetColor, sampleSetColor: sampleSetColor, obsSetSelection: obsSetSelection, sampleSetSelection: sampleSetSelection, onNodeClick: onNodeClick }) }) }));
111
+ return (_jsxs(TitleInfo, { title: `Treemap of ${capitalize(plur(obsType, 2))}`, info: `${commaNumber(selectedObsCount)} ${plur(obsType, selectedObsCount)} from ${commaNumber(selectedSampleCount)} ${plur(sampleType, selectedSampleCount)}`, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, helpText: helpText, withPadding: false, options: (_jsx(TreemapOptions, { obsType: obsType, sampleType: sampleType, obsColorEncoding: obsColorEncoding, setObsColorEncoding: setObsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, setHierarchyLevels: setHierarchyLevels })), children: [_jsx("div", { ref: containerRef, className: classes.vegaContainer, children: _jsx(Treemap, { obsCounts: obsCounts, sampleCounts: sampleCounts, obsColorEncoding: obsColorEncoding, hierarchyLevels: hierarchyLevels || DEFAULT_HIERARCHY_LEVELS, theme: theme, width: width, height: Math.max(height * (selectedObsCount / totalObsCount), 40), obsType: obsType, sampleType: sampleType, obsSetColor: obsSetColor, sampleSetColor: sampleSetColor, obsSetSelection: obsSetSelection, sampleSetSelection: sampleSetSelection, onNodeClick: onNodeClick }) }), _jsx("div", { style: { position: 'absolute', right: '2px', bottom: '2px', fontSize: '10px' }, children: unselectedObsCount > 0 ? (_jsx("span", { children: `${commaNumber(unselectedObsCount)} ${plur(obsType, unselectedObsCount)} from ${commaNumber(unselectedSampleCount)} ${plur(sampleType, unselectedSampleCount)} currently omitted` })) : null })] }));
108
112
  }
@@ -1 +1 @@
1
- {"version":3,"file":"expr-hooks.d.ts","sourceRoot":"","sources":["../src/expr-hooks.js"],"names":[],"mappings":"AAiDA;;;;;;GAMG;AACH,8DAJW,GAAC,gBACD,GAAC,OA4BX;AAED;;;;;;GAMG;AACH,oEAJW,GAAC,aACD,GAAC,OAkBX;AAED;;;;;;;;GAQG;AACH,oEALW,GAAC,YACD,GAAC,YACD,GAAC;;;;;;;;;;;;;;;;;;;;;;;;EA4DX"}
1
+ {"version":3,"file":"expr-hooks.d.ts","sourceRoot":"","sources":["../src/expr-hooks.js"],"names":[],"mappings":"AAiDA;;;;;;GAMG;AACH,8DAJW,GAAC,gBACD,GAAC,OA4BX;AAED;;;;;;GAMG;AACH,oEAJW,GAAC,aACD,GAAC,OAiBX;AAED;;;;;;;;GAQG;AACH,oEALW,GAAC,YACD,GAAC,YACD,GAAC;;;;;;;;;;;;;;;;;;;;;;;;EA4DX"}
@@ -70,8 +70,9 @@ describe('Utility functions for processing expression data for statistical plots
70
70
  ];
71
71
  const featureValueTransform = null;
72
72
  const featureValueTransformCoefficient = 1;
73
+ const featureAggregationStrategy = 'first';
73
74
  const [result] = stratifyExpressionData(sampleEdges, sampleSets, sampleSetSelection, expressionData, obsIndex, mergedCellSets, geneSelection, cellSetSelection, cellSetColor, featureValueTransform, featureValueTransformCoefficient);
74
- const aggregateData = aggregateStratifiedExpressionData(result, geneSelection);
75
+ const aggregateData = aggregateStratifiedExpressionData(result, geneSelection, featureAggregationStrategy);
75
76
  const summaryResult = summarizeStratifiedExpressionData(aggregateData, true);
76
77
  expect(Array.from(summaryResult.keys())).toEqual([['Cell type', 'T cell'], ['Cell type', 'B cell']]);
77
78
  expect(Array.from(summaryResult.get(['Cell type', 'T cell']).keys())).toEqual([['Clinical groups', 'AKI'], ['Clinical groups', 'CKD']]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitessce/statistical-plots",
3
- "version": "3.5.10",
3
+ "version": "3.5.11",
4
4
  "author": "HIDIVE Lab at HMS",
5
5
  "homepage": "http://vitessce.io",
6
6
  "repository": {
@@ -30,12 +30,12 @@
30
30
  "react-aria": "^3.28.0",
31
31
  "internmap": "^2.0.3",
32
32
  "uuid": "^9.0.0",
33
- "@vitessce/constants-internal": "3.5.10",
34
- "@vitessce/sets-utils": "3.5.10",
35
- "@vitessce/utils": "3.5.10",
36
- "@vitessce/vega": "3.5.10",
37
- "@vitessce/vit-s": "3.5.10",
38
- "@vitessce/gl": "3.5.10"
33
+ "@vitessce/constants-internal": "3.5.11",
34
+ "@vitessce/sets-utils": "3.5.11",
35
+ "@vitessce/utils": "3.5.11",
36
+ "@vitessce/vega": "3.5.11",
37
+ "@vitessce/vit-s": "3.5.11",
38
+ "@vitessce/gl": "3.5.11"
39
39
  },
40
40
  "devDependencies": {
41
41
  "react": "^18.0.0",
@@ -1,10 +1,13 @@
1
1
  import React, { useCallback, useMemo } from 'react';
2
2
  import { clamp, isEqual } from 'lodash-es';
3
3
  import { v4 as uuidv4 } from 'uuid';
4
+ import { extent } from 'd3-array';
4
5
  import { VegaPlot, VEGA_THEMES } from '@vitessce/vega';
5
6
  import { capitalize } from '@vitessce/utils';
6
7
  import { getColorScale } from './utils.js';
7
8
 
9
+ const MAX_BAR_SIZE = 40;
10
+
8
11
  /**
9
12
  * Cell set composition results displayed using a bar chart.
10
13
  */
@@ -13,9 +16,9 @@ export default function CellSetCompositionBarPlot(props) {
13
16
  data,
14
17
  theme,
15
18
  width,
16
- height,
19
+ height: heightProp,
17
20
  marginRight = 200,
18
- marginBottom = 120,
21
+ marginBottom = 60,
19
22
  keyLength = 36,
20
23
  obsType,
21
24
  onBarSelect,
@@ -27,6 +30,13 @@ export default function CellSetCompositionBarPlot(props) {
27
30
  sampleSetColor,
28
31
  } = props;
29
32
 
33
+ const height = (
34
+ Array.isArray(obsSetSelection)
35
+ && ((heightProp - marginBottom) / obsSetSelection.length >= MAX_BAR_SIZE)
36
+ )
37
+ ? MAX_BAR_SIZE * obsSetSelection.length + marginBottom
38
+ : heightProp;
39
+
30
40
  const [obsSetColorScale, sampleSetColorScale] = useMemo(() => [
31
41
  getColorScale(obsSetSelection, obsSetColor, theme),
32
42
  getColorScale(sampleSetSelection, sampleSetColor, theme),
@@ -39,21 +49,17 @@ export default function CellSetCompositionBarPlot(props) {
39
49
  // Return in array-of-objects form that Vega-Lite likes.
40
50
 
41
51
  const referenceCellType = metadata?.analysis_params?.reference_cell_type;
52
+ const covariateValue = metadata?.analysis_params?.covariate_value;
42
53
  const coordinationValues = metadata?.coordination_values;
43
54
  const obsSetColumnName = coordinationValues?.obsSetSelection?.[0]?.[0];
44
55
  const obsSetGroupName = obsSetsColumnNameMappingReversed?.[obsSetColumnName];
45
56
 
46
57
  const sampleSetColumnName = coordinationValues?.sampleSetFilter?.[0]?.[0];
47
58
  const sampleSetGroupName = sampleSetsColumnNameMappingReversed?.[sampleSetColumnName];
48
-
49
- // See https://github.com/keller-mark/compasce/issues/30 which should simplify this logic once implemented,
50
- // so that we would no longer need to load/check the covariate column in the frontend.
51
- const covariatePrefix = `${sampleSetColumnName}T.`;
52
- const firstCovariateValue = df.covariate?.[0]?.substring(covariatePrefix.length);
53
- const firstCovariateSetPath = [sampleSetGroupName, firstCovariateValue];
59
+ const covariateSetPath = [sampleSetGroupName, covariateValue];
54
60
 
55
61
  let shouldSwapFoldChangeDirection = false;
56
- if (isEqual(firstCovariateSetPath, sampleSetSelection[0])) {
62
+ if (isEqual(covariateSetPath, sampleSetSelection[0])) {
57
63
  shouldSwapFoldChangeDirection = true;
58
64
  }
59
65
 
@@ -114,6 +120,24 @@ export default function CellSetCompositionBarPlot(props) {
114
120
  range: [2.0, 0.5],
115
121
  };
116
122
 
123
+ const xExtent = useMemo(() => {
124
+ if (computedData) {
125
+ const [min, max] = extent(computedData.map(d => d.logFoldChange));
126
+ const buffer = 1.05; // Ensure some extra space
127
+ const minAbs = Math.abs(min) * buffer;
128
+ const maxAbs = Math.abs(max) * buffer;
129
+ if (minAbs > maxAbs) {
130
+ return [-minAbs, minAbs];
131
+ }
132
+ return [-maxAbs, maxAbs];
133
+ }
134
+ return undefined;
135
+ }, [computedData]);
136
+
137
+ const xScale = {
138
+ domain: xExtent,
139
+ };
140
+
117
141
  const spec = {
118
142
  mark: { type: 'bar', stroke: 'black', cursor: 'pointer' },
119
143
  params: [
@@ -149,6 +173,7 @@ export default function CellSetCompositionBarPlot(props) {
149
173
  field: 'logFoldChange',
150
174
  type: 'quantitative',
151
175
  title: 'Log fold-change',
176
+ scale: xScale,
152
177
  },
153
178
  color: {
154
179
  field: 'key',
@@ -165,6 +190,7 @@ export default function CellSetCompositionBarPlot(props) {
165
190
  field: 'isReferenceSet',
166
191
  type: 'nominal',
167
192
  scale: strokeWidthScale,
193
+ legend: null,
168
194
  },
169
195
  tooltip: {
170
196
  field: 'effectExpectedSample',