@vitessce/statistical-plots 3.8.9 → 3.8.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { b, f, C, e, a, i, D, h, E, F, c, d, T, V } from "./index-Bww8vUPc.js";
1
+ import { b, f, C, e, a, i, D, h, E, F, c, d, T, V } from "./index-BmYvVUY8.js";
2
2
  export {
3
3
  b as CellSetCompositionBarPlotSubscriber,
4
4
  f as CellSetExpressionPlot,
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-Bww8vUPc.js";
1
+ import { B as BaseDecoder } from "./index-BmYvVUY8.js";
2
2
  const dctZigZag = new Int32Array([
3
3
  0,
4
4
  1,
@@ -1,5 +1,5 @@
1
1
  import { i as inflate_1 } from "./pako.esm-SxljTded.js";
2
- import { g as getDefaultExportFromCjs, B as BaseDecoder } from "./index-Bww8vUPc.js";
2
+ import { g as getDefaultExportFromCjs, B as BaseDecoder } from "./index-BmYvVUY8.js";
3
3
  const LercParameters = {
4
4
  AddCompression: 1
5
5
  };
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-Bww8vUPc.js";
1
+ import { B as BaseDecoder } from "./index-BmYvVUY8.js";
2
2
  const MIN_BITS = 9;
3
3
  const CLEAR_CODE = 256;
4
4
  const EOI_CODE = 257;
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-Bww8vUPc.js";
1
+ import { B as BaseDecoder } from "./index-BmYvVUY8.js";
2
2
  class PackbitsDecoder extends BaseDecoder {
3
3
  decodeBlock(buffer) {
4
4
  const dataView = new DataView(buffer);
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-Bww8vUPc.js";
1
+ import { B as BaseDecoder } from "./index-BmYvVUY8.js";
2
2
  class RawDecoder extends BaseDecoder {
3
3
  decodeBlock(buffer) {
4
4
  return buffer;
@@ -1,4 +1,4 @@
1
- import { B as BaseDecoder } from "./index-Bww8vUPc.js";
1
+ import { B as BaseDecoder } from "./index-BmYvVUY8.js";
2
2
  class WebImageDecoder extends BaseDecoder {
3
3
  constructor() {
4
4
  super();
@@ -1 +1 @@
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
+ {"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,eA2GA"}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import React, { useState, useEffect, useCallback } from 'react';
2
+ import React, { useState, useEffect, useCallback, useMemo } from 'react';
3
3
  import { clamp, debounce } from 'lodash-es';
4
4
  import { VegaPlot, VEGA_THEMES } from '@vitessce/vega';
5
5
  import { capitalize, pluralize } from '@vitessce/utils';
@@ -32,9 +32,18 @@ export default function ExpressionHistogram(props) {
32
32
  const [selectedRanges, setSelectedRanges] = useState([]);
33
33
  const isExpression = (featureType === 'gene' && featureValueType === 'expression');
34
34
  // eslint-disable-next-line no-nested-ternary
35
- const xTitle = geneSelection && geneSelection.length >= 1
36
- ? (isExpression ? `Expression Value (${geneSelection[0]})` : `${geneSelection[0]}`)
37
- : (isExpression ? 'Total Transcript Count' : 'Sum of Feature Values');
35
+ const xTitle = useMemo(() => {
36
+ if (!geneSelection || geneSelection.length === 0) {
37
+ return isExpression ? 'Total Transcript Count' : 'Sum of Feature Values';
38
+ }
39
+ if (geneSelection.length > 1) {
40
+ // For multiple genes, use a generic label since aggregation strategy
41
+ // is shown in the component title
42
+ return isExpression ? 'Expression Value (aggregated)' : 'Aggregated Feature Value';
43
+ }
44
+ // Single gene selected
45
+ return isExpression ? `Expression Value (${geneSelection[0]})` : `${geneSelection[0]}`;
46
+ }, [geneSelection, isExpression]);
38
47
  const spec = {
39
48
  data: { values: data },
40
49
  mark: 'bar',
@@ -1 +1 @@
1
- {"version":3,"file":"ExpressionHistogramSubscriber.d.ts","sourceRoot":"","sources":["../src/ExpressionHistogramSubscriber.js"],"names":[],"mappings":"AAeA;;;;;;;;;GASG;AACH,qDALG;IAAwB,mBAAmB;IACrB,kBAAkB,EAAhC,MAAM;IAEQ,KAAK,EAAnB,MAAM;CAChB,eAuIA"}
1
+ {"version":3,"file":"ExpressionHistogramSubscriber.d.ts","sourceRoot":"","sources":["../src/ExpressionHistogramSubscriber.js"],"names":[],"mappings":"AAgBA;;;;;;;;;GASG;AACH,qDALG;IAAwB,mBAAmB;IACrB,kBAAkB,EAAhC,MAAM;IAEQ,KAAK,EAAnB,MAAM;CAChB,eA4JA"}
@@ -4,6 +4,7 @@ import { sum } from 'd3-array';
4
4
  import { TitleInfo, useCoordination, useLoaders, useUrls, useReady, useGridItemSize, useObsFeatureMatrixData, useFeatureSelection, useCoordinationScopes, } from '@vitessce/vit-s';
5
5
  import { ViewType, COMPONENT_COORDINATION_TYPES, ViewHelpMapping } from '@vitessce/constants-internal';
6
6
  import { setObsSelection, getObsInfoFromDataWithinRange } from '@vitessce/sets-utils';
7
+ import { aggregateFeatureArrays } from '@vitessce/utils';
7
8
  import ExpressionHistogram from './ExpressionHistogram.js';
8
9
  import { useStyles } from './styles.js';
9
10
  /**
@@ -22,7 +23,7 @@ export function ExpressionHistogramSubscriber(props) {
22
23
  const loaders = useLoaders();
23
24
  const coordinationScopes = useCoordinationScopes(coordinationScopesRaw);
24
25
  // Get "props" from the coordination space.
25
- const [{ dataset, obsType, featureType, featureValueType, featureSelection: geneSelection, additionalObsSets: additionalCellSets, obsSetColor: cellSetColor, }, { setAdditionalObsSets: setAdditionalCellSets, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setObsSetSelection: setCellSetSelection, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.FEATURE_VALUE_HISTOGRAM], coordinationScopes);
26
+ const [{ dataset, obsType, featureType, featureValueType, featureSelection: geneSelection, featureAggregationStrategy, additionalObsSets: additionalCellSets, obsSetColor: cellSetColor, }, { setAdditionalObsSets: setAdditionalCellSets, setObsSetColor: setCellSetColor, setObsColorEncoding: setCellColorEncoding, setObsSetSelection: setCellSetSelection, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.FEATURE_VALUE_HISTOGRAM], coordinationScopes);
26
27
  const [width, height, containerRef] = useGridItemSize();
27
28
  // Get data from loaders using the data hooks.
28
29
  const [{ obsIndex, featureIndex, obsFeatureMatrix }, matrixStatus, matrixUrls, matrixError,] = useObsFeatureMatrixData(loaders, dataset, true, {}, {}, { obsType, featureType, featureValueType });
@@ -41,17 +42,30 @@ export function ExpressionHistogramSubscriber(props) {
41
42
  const urls = useUrls([
42
43
  matrixUrls,
43
44
  ]);
44
- const firstGeneSelected = geneSelection && geneSelection.length >= 1
45
- ? geneSelection[0]
46
- : null;
45
+ const numGenesSelected = geneSelection ? geneSelection.length : 0;
46
+ const aggregationStrategy = featureAggregationStrategy ?? 'first';
47
+ const titleSuffix = (
48
+ // eslint-disable-next-line no-nested-ternary
49
+ numGenesSelected > 1 ? ` (${numGenesSelected} genes, ${aggregationStrategy})`
50
+ : (numGenesSelected === 1 ? ` (${geneSelection[0]})` : ''));
47
51
  // From the expression matrix and the list of selected genes,
48
52
  // generate the array of data points for the histogram.
49
53
  const data = useMemo(() => {
50
- if (firstGeneSelected && obsFeatureMatrix && expressionData) {
54
+ if (numGenesSelected > 0 && obsFeatureMatrix && expressionData) {
55
+ let expressionDataToUse = expressionData;
56
+ if (numGenesSelected > 1) {
57
+ const aggregatedData = aggregateFeatureArrays(expressionData, aggregationStrategy);
58
+ if (aggregatedData) {
59
+ expressionDataToUse = [aggregatedData];
60
+ }
61
+ else {
62
+ console.error('Error aggregating feature arrays');
63
+ }
64
+ }
51
65
  return obsIndex.map((cellId, cellIndex) => {
52
- const value = expressionData[0][cellIndex];
66
+ const value = expressionDataToUse[0][cellIndex];
53
67
  // Create new cellColors map based on the selected gene.
54
- const newItem = { value, gene: firstGeneSelected, cellId };
68
+ const newItem = { value, cellId };
55
69
  return newItem;
56
70
  });
57
71
  }
@@ -61,18 +75,24 @@ export function ExpressionHistogramSubscriber(props) {
61
75
  const values = obsFeatureMatrix.data
62
76
  .subarray(cellIndex * numGenes, (cellIndex + 1) * numGenes);
63
77
  const sumValue = sum(values);
64
- const newItem = { value: sumValue, gene: null, cellId };
78
+ const newItem = { value: sumValue, cellId };
65
79
  return newItem;
66
80
  });
67
81
  }
68
82
  return null;
69
- }, [obsIndex, featureIndex, obsFeatureMatrix, firstGeneSelected, expressionData]);
83
+ }, [obsIndex, featureIndex, obsFeatureMatrix, expressionData,
84
+ numGenesSelected, aggregationStrategy,
85
+ ]);
70
86
  const onSelect = useCallback((value) => {
71
- const geneName = firstGeneSelected ? [firstGeneSelected, 'values'].join(' ') : 'transcript count';
87
+ const geneName = (
88
+ // eslint-disable-next-line no-nested-ternary
89
+ numGenesSelected > 1 ? `${numGenesSelected} genes (${aggregationStrategy})`
90
+ : (numGenesSelected === 1 ? ` ${geneSelection[0]}` : 'transcript count'));
72
91
  const selectedCellIds = getObsInfoFromDataWithinRange(value, data);
73
92
  setObsSelection(selectedCellIds, additionalCellSets, cellSetColor, setCellSetSelection, setAdditionalCellSets, setCellSetColor, setCellColorEncoding, 'Selection ', `: based on ${geneName} in range [${value[0].toFixed(1)}, ${value[1].toFixed(1)}] `);
74
93
  }, [additionalCellSets, cellSetColor, data, setAdditionalCellSets,
75
- setCellColorEncoding, setCellSetColor, setCellSetSelection, firstGeneSelected,
94
+ setCellColorEncoding, setCellSetColor, setCellSetSelection,
95
+ numGenesSelected, aggregationStrategy, geneSelection,
76
96
  ]);
77
- return (_jsx(TitleInfo, { title: `Histogram${(firstGeneSelected ? ` (${firstGeneSelected})` : '')}`, closeButtonVisible: closeButtonVisible, downloadButtonVisible: downloadButtonVisible, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, helpText: helpText, errors: errors, children: _jsx("div", { ref: containerRef, className: classes.vegaContainer, children: _jsx(ExpressionHistogram, { geneSelection: geneSelection, obsType: obsType, featureType: featureType, featureValueType: featureValueType, onSelect: onSelect, data: data, theme: theme, width: width, height: height }) }) }));
97
+ return (_jsx(TitleInfo, { title: `Histogram ${titleSuffix}`, closeButtonVisible: closeButtonVisible, downloadButtonVisible: downloadButtonVisible, removeGridComponent: removeGridComponent, urls: urls, theme: theme, isReady: isReady, helpText: helpText, errors: errors, children: _jsx("div", { ref: containerRef, className: classes.vegaContainer, children: _jsx(ExpressionHistogram, { geneSelection: geneSelection, obsType: obsType, featureType: featureType, featureValueType: featureValueType, onSelect: onSelect, data: data, theme: theme, width: width, height: height }) }) }));
78
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitessce/statistical-plots",
3
- "version": "3.8.9",
3
+ "version": "3.8.13",
4
4
  "author": "HIDIVE Lab at HMS",
5
5
  "homepage": "http://vitessce.io",
6
6
  "repository": {
@@ -28,13 +28,13 @@
28
28
  "react-aria": "^3.28.0",
29
29
  "internmap": "^2.0.3",
30
30
  "uuid": "^9.0.0",
31
- "@vitessce/styles": "3.8.9",
32
- "@vitessce/constants-internal": "3.8.9",
33
- "@vitessce/sets-utils": "3.8.9",
34
- "@vitessce/utils": "3.8.9",
35
- "@vitessce/vega": "3.8.9",
36
- "@vitessce/vit-s": "3.8.9",
37
- "@vitessce/gl": "3.8.9"
31
+ "@vitessce/styles": "3.8.13",
32
+ "@vitessce/constants-internal": "3.8.13",
33
+ "@vitessce/utils": "3.8.13",
34
+ "@vitessce/sets-utils": "3.8.13",
35
+ "@vitessce/vega": "3.8.13",
36
+ "@vitessce/vit-s": "3.8.13",
37
+ "@vitessce/gl": "3.8.13"
38
38
  },
39
39
  "devDependencies": {
40
40
  "react": "18.3.1",
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect, useCallback } from 'react';
1
+ import React, { useState, useEffect, useCallback, useMemo } from 'react';
2
2
  import { clamp, debounce } from 'lodash-es';
3
3
  import { VegaPlot, VEGA_THEMES } from '@vitessce/vega';
4
4
  import { capitalize, pluralize } from '@vitessce/utils';
@@ -49,9 +49,18 @@ export default function ExpressionHistogram(props) {
49
49
  featureType === 'gene' && featureValueType === 'expression'
50
50
  );
51
51
  // eslint-disable-next-line no-nested-ternary
52
- const xTitle = geneSelection && geneSelection.length >= 1
53
- ? (isExpression ? `Expression Value (${geneSelection[0]})` : `${geneSelection[0]}`)
54
- : (isExpression ? 'Total Transcript Count' : 'Sum of Feature Values');
52
+ const xTitle = useMemo(() => {
53
+ if (!geneSelection || geneSelection.length === 0) {
54
+ return isExpression ? 'Total Transcript Count' : 'Sum of Feature Values';
55
+ }
56
+ if (geneSelection.length > 1) {
57
+ // For multiple genes, use a generic label since aggregation strategy
58
+ // is shown in the component title
59
+ return isExpression ? 'Expression Value (aggregated)' : 'Aggregated Feature Value';
60
+ }
61
+ // Single gene selected
62
+ return isExpression ? `Expression Value (${geneSelection[0]})` : `${geneSelection[0]}`;
63
+ }, [geneSelection, isExpression]);
55
64
 
56
65
  const spec = {
57
66
  data: { values: data },
@@ -11,6 +11,7 @@ import {
11
11
  } from '@vitessce/vit-s';
12
12
  import { ViewType, COMPONENT_COORDINATION_TYPES, ViewHelpMapping } from '@vitessce/constants-internal';
13
13
  import { setObsSelection, getObsInfoFromDataWithinRange } from '@vitessce/sets-utils';
14
+ import { aggregateFeatureArrays } from '@vitessce/utils';
14
15
  import ExpressionHistogram from './ExpressionHistogram.js';
15
16
  import { useStyles } from './styles.js';
16
17
  /**
@@ -44,6 +45,7 @@ export function ExpressionHistogramSubscriber(props) {
44
45
  featureType,
45
46
  featureValueType,
46
47
  featureSelection: geneSelection,
48
+ featureAggregationStrategy,
47
49
  additionalObsSets: additionalCellSets,
48
50
  obsSetColor: cellSetColor,
49
51
  }, {
@@ -87,18 +89,31 @@ export function ExpressionHistogramSubscriber(props) {
87
89
  matrixUrls,
88
90
  ]);
89
91
 
90
- const firstGeneSelected = geneSelection && geneSelection.length >= 1
91
- ? geneSelection[0]
92
- : null;
92
+ const numGenesSelected = geneSelection ? geneSelection.length : 0;
93
+ const aggregationStrategy = featureAggregationStrategy ?? 'first';
94
+ const titleSuffix = (
95
+ // eslint-disable-next-line no-nested-ternary
96
+ numGenesSelected > 1 ? ` (${numGenesSelected} genes, ${aggregationStrategy})`
97
+ : (numGenesSelected === 1 ? ` (${geneSelection[0]})` : '')
98
+ );
93
99
 
94
100
  // From the expression matrix and the list of selected genes,
95
101
  // generate the array of data points for the histogram.
96
102
  const data = useMemo(() => {
97
- if (firstGeneSelected && obsFeatureMatrix && expressionData) {
103
+ if (numGenesSelected > 0 && obsFeatureMatrix && expressionData) {
104
+ let expressionDataToUse = expressionData;
105
+ if (numGenesSelected > 1) {
106
+ const aggregatedData = aggregateFeatureArrays(expressionData, aggregationStrategy);
107
+ if (aggregatedData) {
108
+ expressionDataToUse = [aggregatedData];
109
+ } else {
110
+ console.error('Error aggregating feature arrays');
111
+ }
112
+ }
98
113
  return obsIndex.map((cellId, cellIndex) => {
99
- const value = expressionData[0][cellIndex];
114
+ const value = expressionDataToUse[0][cellIndex];
100
115
  // Create new cellColors map based on the selected gene.
101
- const newItem = { value, gene: firstGeneSelected, cellId };
116
+ const newItem = { value, cellId };
102
117
  return newItem;
103
118
  });
104
119
  }
@@ -108,15 +123,21 @@ export function ExpressionHistogramSubscriber(props) {
108
123
  const values = obsFeatureMatrix.data
109
124
  .subarray(cellIndex * numGenes, (cellIndex + 1) * numGenes);
110
125
  const sumValue = sum(values);
111
- const newItem = { value: sumValue, gene: null, cellId };
126
+ const newItem = { value: sumValue, cellId };
112
127
  return newItem;
113
128
  });
114
129
  }
115
130
  return null;
116
- }, [obsIndex, featureIndex, obsFeatureMatrix, firstGeneSelected, expressionData]);
131
+ }, [obsIndex, featureIndex, obsFeatureMatrix, expressionData,
132
+ numGenesSelected, aggregationStrategy,
133
+ ]);
117
134
 
118
135
  const onSelect = useCallback((value) => {
119
- const geneName = firstGeneSelected ? [firstGeneSelected, 'values'].join(' ') : 'transcript count';
136
+ const geneName = (
137
+ // eslint-disable-next-line no-nested-ternary
138
+ numGenesSelected > 1 ? `${numGenesSelected} genes (${aggregationStrategy})`
139
+ : (numGenesSelected === 1 ? ` ${geneSelection[0]}` : 'transcript count')
140
+ );
120
141
 
121
142
  const selectedCellIds = getObsInfoFromDataWithinRange(value, data);
122
143
  setObsSelection(
@@ -127,12 +148,13 @@ export function ExpressionHistogramSubscriber(props) {
127
148
  `: based on ${geneName} in range [${value[0].toFixed(1)}, ${value[1].toFixed(1)}] `,
128
149
  );
129
150
  }, [additionalCellSets, cellSetColor, data, setAdditionalCellSets,
130
- setCellColorEncoding, setCellSetColor, setCellSetSelection, firstGeneSelected,
151
+ setCellColorEncoding, setCellSetColor, setCellSetSelection,
152
+ numGenesSelected, aggregationStrategy, geneSelection,
131
153
  ]);
132
154
 
133
155
  return (
134
156
  <TitleInfo
135
- title={`Histogram${(firstGeneSelected ? ` (${firstGeneSelected})` : '')}`}
157
+ title={`Histogram ${titleSuffix}`}
136
158
  closeButtonVisible={closeButtonVisible}
137
159
  downloadButtonVisible={downloadButtonVisible}
138
160
  removeGridComponent={removeGridComponent}