@vitessce/scatterplot-embedding 3.5.8 → 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/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { D, E } from "./index-5909753b.js";
1
+ import { D, E } from "./index-a37f30c8.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-5909753b.js";
1
+ import { B as BaseDecoder } from "./index-a37f30c8.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-5909753b.js";
2
+ import { g as getDefaultExportFromCjs, B as BaseDecoder } from "./index-a37f30c8.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-5909753b.js";
1
+ import { B as BaseDecoder } from "./index-a37f30c8.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-5909753b.js";
1
+ import { B as BaseDecoder } from "./index-a37f30c8.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-5909753b.js";
1
+ import { B as BaseDecoder } from "./index-a37f30c8.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-5909753b.js";
1
+ import { B as BaseDecoder } from "./index-a37f30c8.js";
2
2
  import "react";
3
3
  import "@vitessce/vit-s";
4
4
  import "react-dom";
@@ -1 +1 @@
1
- {"version":3,"file":"DualEmbeddingScatterplotSubscriber.d.ts","sourceRoot":"","sources":["../src/DualEmbeddingScatterplotSubscriber.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;GAeG;AACH,0DAVG;IAAsB,IAAI,EAAlB,MAAM;IACQ,KAAK,EAAnB,MAAM;IACQ,kBAAkB,EAAhC,MAAM;IAEU,mBAAmB;IAErB,KAAK,EAAnB,MAAM;IACQ,kBAAkB,EAAhC,MAAM;CAEhB,eA4CA"}
1
+ {"version":3,"file":"DualEmbeddingScatterplotSubscriber.d.ts","sourceRoot":"","sources":["../src/DualEmbeddingScatterplotSubscriber.js"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;GAeG;AACH,0DAVG;IAAsB,IAAI,EAAlB,MAAM;IACQ,KAAK,EAAnB,MAAM;IACQ,kBAAkB,EAAhC,MAAM;IAEU,mBAAmB;IAErB,KAAK,EAAnB,MAAM;IACQ,kBAAkB,EAAhC,MAAM;CAEhB,eAmDA"}
@@ -23,11 +23,14 @@ export function DualEmbeddingScatterplotSubscriber(props) {
23
23
  const { uuid, coordinationScopes, } = props;
24
24
  // Get "props" from the coordination space.
25
25
  const [{ embeddingType, sampleSetSelection, }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.DUAL_SCATTERPLOT], coordinationScopes);
26
+ const isCaseCtrl = Array.isArray(sampleSetSelection) && sampleSetSelection.length === 2;
26
27
  const caseSampleSetSelection = useMemo(() => (sampleSetSelection?.[0]
27
28
  ? [sampleSetSelection[0]]
28
29
  : null), [sampleSetSelection]);
29
30
  const ctrlSampleSetSelection = useMemo(() => (sampleSetSelection?.[1]
30
31
  ? [sampleSetSelection[1]]
31
32
  : null), [sampleSetSelection]);
32
- return (_jsxs("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'row' }, children: [_jsx("div", { style: { width: '50%', display: 'flex', flexDirection: 'column' }, children: _jsx(EmbeddingScatterplotSubscriber, { ...props, uuid: `${uuid}-case`, title: `Scatterplot (${embeddingType}), ${caseSampleSetSelection?.[0]?.at(-1)}`, sampleSetSelection: caseSampleSetSelection }) }), _jsx("div", { style: { width: '50%', display: 'flex', flexDirection: 'column' }, children: _jsx(EmbeddingScatterplotSubscriber, { ...props, uuid: `${uuid}-ctrl`, title: `Scatterplot (${embeddingType}), ${ctrlSampleSetSelection?.[0]?.at(-1)}`, sampleSetSelection: ctrlSampleSetSelection }) })] }));
33
+ return (_jsxs("div", { style: { width: '100%', height: '100%', display: 'flex', flexDirection: 'row' }, children: [_jsx("div", { style: { width: isCaseCtrl ? '50%' : '100%', display: 'flex', flexDirection: 'column' }, children: _jsx(EmbeddingScatterplotSubscriber, { ...props, uuid: `${uuid}-case`, title: (isCaseCtrl
34
+ ? `Scatterplot (${embeddingType}), ${caseSampleSetSelection?.[0]?.at(-1)}`
35
+ : null), sampleSetSelection: caseSampleSetSelection }) }), isCaseCtrl ? (_jsx("div", { style: { width: '50%', display: 'flex', flexDirection: 'column' }, children: _jsx(EmbeddingScatterplotSubscriber, { ...props, uuid: `${uuid}-ctrl`, title: `Scatterplot (${embeddingType}), ${ctrlSampleSetSelection?.[0]?.at(-1)}`, sampleSetSelection: ctrlSampleSetSelection }) })) : null] }));
33
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EmbeddingScatterplotSubscriber.d.ts","sourceRoot":"","sources":["../src/EmbeddingScatterplotSubscriber.js"],"names":[],"mappings":"AA0CA;;;;;;;;;;;;GAYG;AACH,sDAVG;IAAsB,IAAI,EAAlB,MAAM;IACQ,KAAK,EAAnB,MAAM;IACQ,kBAAkB,EAAhC,MAAM;IAEU,mBAAmB;IAErB,KAAK,EAAnB,MAAM;IACQ,kBAAkB,EAAhC,MAAM;CAEhB,eAwhBA"}
1
+ {"version":3,"file":"EmbeddingScatterplotSubscriber.d.ts","sourceRoot":"","sources":["../src/EmbeddingScatterplotSubscriber.js"],"names":[],"mappings":"AA2CA;;;;;;;;;;;;GAYG;AACH,sDAVG;IAAsB,IAAI,EAAlB,MAAM;IACQ,KAAK,EAAnB,MAAM;IACQ,kBAAkB,EAAhC,MAAM;IAEU,mBAAmB;IAErB,KAAK,EAAnB,MAAM;IACQ,kBAAkB,EAAhC,MAAM;CAEhB,eAmjBA"}
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import React, { useState, useEffect, useCallback, useMemo, } from 'react';
3
3
  import { extent, quantileSorted } from 'd3-array';
4
4
  import { isEqual } from 'lodash-es';
5
+ import { circle } from '@turf/circle';
5
6
  import { TitleInfo, useReady, useUrls, useDeckCanvasSize, useUint8FeatureSelection, useExpressionValueGetter, useGetObsInfo, useObsEmbeddingData, useObsSetsData, useFeatureSelection, useObsFeatureMatrixIndices, useFeatureLabelsData, useMultiObsLabels, useSampleSetsData, useSampleEdgesData, useCoordination, useLoaders, useSetComponentHover, useSetComponentViewInfo, useInitialCoordination, useExpandedFeatureLabelsMap, } from '@vitessce/vit-s';
6
7
  import { setObsSelection, mergeObsSets, getCellSetPolygons, getCellColors, stratifyArrays, } from '@vitessce/sets-utils';
7
8
  import { pluralize as plur, commaNumber } from '@vitessce/utils';
@@ -189,8 +190,31 @@ export function EmbeddingScatterplotSubscriber(props) {
189
190
  .map(t => Math.max(t, 1.0));
190
191
  return thresholds;
191
192
  }
192
- return null;
193
+ return [1, 10, 100];
193
194
  }, [contourPercentiles, sortedWeights]);
195
+ // Construct a circle polygon using Turf's circle function,
196
+ // which surrounds all points in the scatterplot,
197
+ // which we can use to position text labels along.
198
+ const circleInfo = useMemo(() => {
199
+ if (!originalViewState || !width || !height) {
200
+ return null;
201
+ }
202
+ const center = [
203
+ originalViewState.target[0],
204
+ originalViewState.target[1],
205
+ ];
206
+ const scaleFactor = (2 ** originalViewState.zoom);
207
+ const radius = Math.min(width, height) / 2 / scaleFactor;
208
+ const numPoints = 96;
209
+ const options = { steps: numPoints, units: 'degrees' };
210
+ const circlePolygon = circle(center, radius, options);
211
+ return {
212
+ center,
213
+ radius,
214
+ polygon: circlePolygon,
215
+ steps: numPoints,
216
+ };
217
+ }, [originalViewState, width, height]);
194
218
  // It is possible for the embedding index+data to be out of order
195
219
  // with respect to the matrix index+data. Here, we align the embedding
196
220
  // data so that the rows are ordered the same as the matrix rows.
@@ -265,7 +289,7 @@ export function EmbeddingScatterplotSubscriber(props) {
265
289
  }, updateViewInfo: setComponentViewInfo, getExpressionValue: getExpressionValue, getCellIsSelected: getCellIsSelected, obsSetSelection: cellSetSelection, sampleSetSelection: sampleSetSelection,
266
290
  // InternMap data structures where keys are
267
291
  // obsSet -> sampleSet -> arrayKey -> [].
268
- stratifiedData: stratifiedData, obsSetColor: cellSetColor, sampleSetColor: sampleSetColor, contourThresholds: contourThresholds, contourColorEncoding: contourColorEncoding, contourColor: contourColor, contoursFilled: embeddingContoursFilled, embeddingPointsVisible: embeddingPointsVisible, embeddingContoursVisible: embeddingContoursVisible }), tooltipsVisible && (_jsx(ScatterplotTooltipSubscriber, { parentUuid: uuid, obsHighlight: cellHighlight, width: width, height: height, getObsInfo: getObsInfo, featureType: featureType, featureLabelsMap: featureLabelsMap })), _jsx(Legend, { visible: true, theme: theme, featureType: featureType, featureValueType: featureValueType, obsColorEncoding: cellColorEncoding, featureSelection: geneSelection, featureLabelsMap: featureLabelsMap, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, obsSetSelection: cellSetSelection, extent: expressionExtents?.[0], missing: expressionMissing?.[0],
292
+ stratifiedData: stratifiedData, obsSetColor: cellSetColor, sampleSetColor: sampleSetColor, contourThresholds: contourThresholds, contourColorEncoding: contourColorEncoding, contourColor: contourColor, contoursFilled: embeddingContoursFilled, embeddingPointsVisible: embeddingPointsVisible, embeddingContoursVisible: embeddingContoursVisible, circleInfo: circleInfo, featureSelection: geneSelection }), tooltipsVisible && (_jsx(ScatterplotTooltipSubscriber, { parentUuid: uuid, obsHighlight: cellHighlight, width: width, height: height, getObsInfo: getObsInfo, featureType: featureType, featureLabelsMap: featureLabelsMap })), _jsx(Legend, { visible: true, theme: theme, featureType: featureType, featureValueType: featureValueType, obsColorEncoding: cellColorEncoding, featureSelection: geneSelection, featureLabelsMap: featureLabelsMap, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, obsSetSelection: cellSetSelection, extent: expressionExtents?.[0], missing: expressionMissing?.[0],
269
293
  // Contour percentile legend
270
294
  pointsVisible: embeddingPointsVisible, contoursVisible: embeddingContoursVisible, contoursFilled: embeddingContoursFilled, contourPercentiles: contourPercentiles || DEFAULT_CONTOUR_PERCENTILES, contourThresholds: contourThresholds })] }));
271
295
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitessce/scatterplot-embedding",
3
- "version": "3.5.8",
3
+ "version": "3.5.10",
4
4
  "author": "HIDIVE Lab at HMS",
5
5
  "homepage": "http://vitessce.io",
6
6
  "repository": {
@@ -20,12 +20,13 @@
20
20
  "d3-array": "^2.4.0",
21
21
  "lodash-es": "^4.17.21",
22
22
  "react-aria": "^3.28.0",
23
- "@vitessce/constants-internal": "3.5.8",
24
- "@vitessce/legend": "3.5.8",
25
- "@vitessce/scatterplot": "3.5.8",
26
- "@vitessce/sets-utils": "3.5.8",
27
- "@vitessce/utils": "3.5.8",
28
- "@vitessce/vit-s": "3.5.8"
23
+ "@turf/circle": "^7.2.0",
24
+ "@vitessce/constants-internal": "3.5.10",
25
+ "@vitessce/legend": "3.5.10",
26
+ "@vitessce/scatterplot": "3.5.10",
27
+ "@vitessce/sets-utils": "3.5.10",
28
+ "@vitessce/utils": "3.5.10",
29
+ "@vitessce/vit-s": "3.5.10"
29
30
  },
30
31
  "devDependencies": {
31
32
  "react": "^18.0.0",
@@ -34,6 +34,8 @@ export function DualEmbeddingScatterplotSubscriber(props) {
34
34
  sampleSetSelection,
35
35
  }] = useCoordination(COMPONENT_COORDINATION_TYPES[ViewType.DUAL_SCATTERPLOT], coordinationScopes);
36
36
 
37
+ const isCaseCtrl = Array.isArray(sampleSetSelection) && sampleSetSelection.length === 2;
38
+
37
39
  const caseSampleSetSelection = useMemo(() => (
38
40
  sampleSetSelection?.[0]
39
41
  ? [sampleSetSelection[0]]
@@ -47,22 +49,27 @@ export function DualEmbeddingScatterplotSubscriber(props) {
47
49
 
48
50
  return (
49
51
  <div style={{ width: '100%', height: '100%', display: 'flex', flexDirection: 'row' }}>
50
- <div style={{ width: '50%', display: 'flex', flexDirection: 'column' }}>
52
+ <div style={{ width: isCaseCtrl ? '50%' : '100%', display: 'flex', flexDirection: 'column' }}>
51
53
  <EmbeddingScatterplotSubscriber
52
54
  {...props}
53
55
  uuid={`${uuid}-case`}
54
- title={`Scatterplot (${embeddingType}), ${caseSampleSetSelection?.[0]?.at(-1)}`}
56
+ title={(isCaseCtrl
57
+ ? `Scatterplot (${embeddingType}), ${caseSampleSetSelection?.[0]?.at(-1)}`
58
+ : null
59
+ )}
55
60
  sampleSetSelection={caseSampleSetSelection}
56
61
  />
57
62
  </div>
58
- <div style={{ width: '50%', display: 'flex', flexDirection: 'column' }}>
59
- <EmbeddingScatterplotSubscriber
60
- {...props}
61
- uuid={`${uuid}-ctrl`}
62
- title={`Scatterplot (${embeddingType}), ${ctrlSampleSetSelection?.[0]?.at(-1)}`}
63
- sampleSetSelection={ctrlSampleSetSelection}
64
- />
65
- </div>
63
+ {isCaseCtrl ? (
64
+ <div style={{ width: '50%', display: 'flex', flexDirection: 'column' }}>
65
+ <EmbeddingScatterplotSubscriber
66
+ {...props}
67
+ uuid={`${uuid}-ctrl`}
68
+ title={`Scatterplot (${embeddingType}), ${ctrlSampleSetSelection?.[0]?.at(-1)}`}
69
+ sampleSetSelection={ctrlSampleSetSelection}
70
+ />
71
+ </div>
72
+ ) : null}
66
73
  </div>
67
74
  );
68
75
  }
@@ -3,6 +3,7 @@ import React, {
3
3
  } from 'react';
4
4
  import { extent, quantileSorted } from 'd3-array';
5
5
  import { isEqual } from 'lodash-es';
6
+ import { circle } from '@turf/circle';
6
7
  import {
7
8
  TitleInfo,
8
9
  useReady, useUrls,
@@ -379,9 +380,33 @@ export function EmbeddingScatterplotSubscriber(props) {
379
380
  .map(t => Math.max(t, 1.0));
380
381
  return thresholds;
381
382
  }
382
- return null;
383
+ return [1, 10, 100];
383
384
  }, [contourPercentiles, sortedWeights]);
384
385
 
386
+ // Construct a circle polygon using Turf's circle function,
387
+ // which surrounds all points in the scatterplot,
388
+ // which we can use to position text labels along.
389
+ const circleInfo = useMemo(() => {
390
+ if (!originalViewState || !width || !height) {
391
+ return null;
392
+ }
393
+ const center = [
394
+ originalViewState.target[0],
395
+ originalViewState.target[1],
396
+ ];
397
+ const scaleFactor = (2 ** originalViewState.zoom);
398
+ const radius = Math.min(width, height) / 2 / scaleFactor;
399
+ const numPoints = 96;
400
+ const options = { steps: numPoints, units: 'degrees' };
401
+ const circlePolygon = circle(center, radius, options);
402
+ return {
403
+ center,
404
+ radius,
405
+ polygon: circlePolygon,
406
+ steps: numPoints,
407
+ };
408
+ }, [originalViewState, width, height]);
409
+
385
410
  // It is possible for the embedding index+data to be out of order
386
411
  // with respect to the matrix index+data. Here, we align the embedding
387
412
  // data so that the rows are ordered the same as the matrix rows.
@@ -554,6 +579,9 @@ export function EmbeddingScatterplotSubscriber(props) {
554
579
  contoursFilled={embeddingContoursFilled}
555
580
  embeddingPointsVisible={embeddingPointsVisible}
556
581
  embeddingContoursVisible={embeddingContoursVisible}
582
+
583
+ circleInfo={circleInfo}
584
+ featureSelection={geneSelection}
557
585
  />
558
586
  {tooltipsVisible && (
559
587
  <ScatterplotTooltipSubscriber