@vitessce/scatterplot-embedding 3.8.8 → 3.8.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-Dr6bxD0w.js → deflate-DV84laLg.js} +1 -1
- package/dist/{index-DXCCF6LM.js → index-BgrJUaQb.js} +349 -76
- package/dist/index.js +1 -1
- package/dist/{jpeg-UKzKGs1t.js → jpeg-V5Wg0DTH.js} +1 -1
- package/dist/{lerc-D62tGpqi.js → lerc-LFwYjack.js} +1 -1
- package/dist/{lzw-Dbo7OpaS.js → lzw-BwAlpbiv.js} +1 -1
- package/dist/{packbits-0X-GrQId.js → packbits-BzaxDQbT.js} +1 -1
- package/dist/{raw-CBdLq0ga.js → raw-BJDJq5QK.js} +1 -1
- package/dist/{webimage-C2vUudNG.js → webimage-6o_3zIHO.js} +1 -1
- package/dist-tsc/EmbeddingScatterplotSubscriber.d.ts.map +1 -1
- package/dist-tsc/EmbeddingScatterplotSubscriber.js +14 -4
- package/package.json +8 -8
- package/src/EmbeddingScatterplotSubscriber.js +16 -4
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as inflate_1 } from "./pako.esm-SxljTded.js";
|
|
2
|
-
import { B as BaseDecoder } from "./index-
|
|
2
|
+
import { B as BaseDecoder } from "./index-BgrJUaQb.js";
|
|
3
3
|
class DeflateDecoder extends BaseDecoder {
|
|
4
4
|
decodeBlock(buffer) {
|
|
5
5
|
return inflate_1(new Uint8Array(buffer)).buffer;
|
|
@@ -3098,6 +3098,59 @@ const PALETTE = [
|
|
|
3098
3098
|
[136, 34, 85],
|
|
3099
3099
|
[170, 68, 153]
|
|
3100
3100
|
];
|
|
3101
|
+
function aggregateFeatureArrays(arrays, strategy) {
|
|
3102
|
+
if (!arrays || arrays.length === 0)
|
|
3103
|
+
return null;
|
|
3104
|
+
let targetArray;
|
|
3105
|
+
if (strategy === "first" || typeof strategy === "number" && strategy === 0) {
|
|
3106
|
+
targetArray = arrays[0];
|
|
3107
|
+
} else if (strategy === "last") {
|
|
3108
|
+
targetArray = arrays[arrays.length - 1];
|
|
3109
|
+
} else if (typeof strategy === "number") {
|
|
3110
|
+
if (strategy >= 0 && strategy < arrays.length) {
|
|
3111
|
+
targetArray = arrays[strategy];
|
|
3112
|
+
} else {
|
|
3113
|
+
throw new Error(`Array index out of bounds: ${strategy}`);
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
if (targetArray) {
|
|
3117
|
+
return targetArray;
|
|
3118
|
+
}
|
|
3119
|
+
const numArrays = arrays.length;
|
|
3120
|
+
const firstArrayLength = arrays[0].length;
|
|
3121
|
+
if (arrays.some((arr) => arr.length !== firstArrayLength)) {
|
|
3122
|
+
throw new Error("All arrays must have the same length for aggregation.");
|
|
3123
|
+
}
|
|
3124
|
+
if (strategy === "sum" || strategy === "mean") {
|
|
3125
|
+
const resultArray = new Float64Array(firstArrayLength);
|
|
3126
|
+
for (let i2 = 0; i2 < numArrays; i2++) {
|
|
3127
|
+
const arr = arrays[i2];
|
|
3128
|
+
for (let j = 0; j < firstArrayLength; j++) {
|
|
3129
|
+
resultArray[j] += arr[j];
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
if (strategy === "mean") {
|
|
3133
|
+
for (let i2 = 0; i2 < firstArrayLength; i2++) {
|
|
3134
|
+
resultArray[i2] /= numArrays;
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
3137
|
+
return resultArray;
|
|
3138
|
+
}
|
|
3139
|
+
if (strategy === "difference") {
|
|
3140
|
+
if (numArrays !== 2) {
|
|
3141
|
+
console.warn("Difference strategy requires exactly 2 arrays.");
|
|
3142
|
+
return arrays[0];
|
|
3143
|
+
}
|
|
3144
|
+
const arr0 = arrays[0];
|
|
3145
|
+
const arr1 = arrays[1];
|
|
3146
|
+
const resultArray = new Float64Array(firstArrayLength);
|
|
3147
|
+
for (let i2 = 0; i2 < firstArrayLength; i2++) {
|
|
3148
|
+
resultArray[i2] = arr0[i2] - arr1[i2];
|
|
3149
|
+
}
|
|
3150
|
+
return resultArray;
|
|
3151
|
+
}
|
|
3152
|
+
throw new Error(`Unknown aggregation strategy: ${strategy}`);
|
|
3153
|
+
}
|
|
3101
3154
|
var util;
|
|
3102
3155
|
(function(util2) {
|
|
3103
3156
|
util2.assertEqual = (val) => val;
|
|
@@ -123348,22 +123401,22 @@ function addDecoder(cases, importFn) {
|
|
|
123348
123401
|
}
|
|
123349
123402
|
cases.forEach((c2) => registry$1.set(c2, importFn));
|
|
123350
123403
|
}
|
|
123351
|
-
addDecoder([void 0, 1], () => import("./raw-
|
|
123352
|
-
addDecoder(5, () => import("./lzw-
|
|
123404
|
+
addDecoder([void 0, 1], () => import("./raw-BJDJq5QK.js").then((m2) => m2.default));
|
|
123405
|
+
addDecoder(5, () => import("./lzw-BwAlpbiv.js").then((m2) => m2.default));
|
|
123353
123406
|
addDecoder(6, () => {
|
|
123354
123407
|
throw new Error("old style JPEG compression is not supported.");
|
|
123355
123408
|
});
|
|
123356
|
-
addDecoder(7, () => import("./jpeg-
|
|
123357
|
-
addDecoder([8, 32946], () => import("./deflate-
|
|
123358
|
-
addDecoder(32773, () => import("./packbits-
|
|
123409
|
+
addDecoder(7, () => import("./jpeg-V5Wg0DTH.js").then((m2) => m2.default));
|
|
123410
|
+
addDecoder([8, 32946], () => import("./deflate-DV84laLg.js").then((m2) => m2.default));
|
|
123411
|
+
addDecoder(32773, () => import("./packbits-BzaxDQbT.js").then((m2) => m2.default));
|
|
123359
123412
|
addDecoder(
|
|
123360
123413
|
34887,
|
|
123361
|
-
() => import("./lerc-
|
|
123414
|
+
() => import("./lerc-LFwYjack.js").then(async (m2) => {
|
|
123362
123415
|
await m2.zstd.init();
|
|
123363
123416
|
return m2;
|
|
123364
123417
|
}).then((m2) => m2.default)
|
|
123365
123418
|
);
|
|
123366
|
-
addDecoder(50001, () => import("./webimage-
|
|
123419
|
+
addDecoder(50001, () => import("./webimage-6o_3zIHO.js").then((m2) => m2.default));
|
|
123367
123420
|
function decodeRowAcc(row, stride) {
|
|
123368
123421
|
let length2 = row.length - stride;
|
|
123369
123422
|
let offset2 = 0;
|
|
@@ -150440,8 +150493,14 @@ function forceCollideRects() {
|
|
|
150440
150493
|
};
|
|
150441
150494
|
return force;
|
|
150442
150495
|
}
|
|
150443
|
-
|
|
150444
|
-
|
|
150496
|
+
const BASE_POINT_SIZE = 5;
|
|
150497
|
+
const LARGE_DATASET_CELL_COUNT = 1e4;
|
|
150498
|
+
const SMALL_DATASET_CELL_COUNT = 100;
|
|
150499
|
+
function getInitialPointSize(numCells = LARGE_DATASET_CELL_COUNT) {
|
|
150500
|
+
return BASE_POINT_SIZE / clamp$4(numCells, SMALL_DATASET_CELL_COUNT, LARGE_DATASET_CELL_COUNT);
|
|
150501
|
+
}
|
|
150502
|
+
function getPointSizeDevicePixels(devicePixelRatio, zoom, xRange, yRange, width2, height2, numCells) {
|
|
150503
|
+
const pointSize = getInitialPointSize(numCells);
|
|
150445
150504
|
const pointScreenSizeMax = 10;
|
|
150446
150505
|
const pointScreenSizeMin = 1 / devicePixelRatio;
|
|
150447
150506
|
const scaleFactor = 2 ** zoom;
|
|
@@ -151999,40 +152058,51 @@ function number$2(x) {
|
|
|
151999
152058
|
const ascendingBisect = bisector(ascending);
|
|
152000
152059
|
const bisectRight = ascendingBisect.right;
|
|
152001
152060
|
bisector(number$2).center;
|
|
152002
|
-
|
|
152061
|
+
const e10 = Math.sqrt(50), e5 = Math.sqrt(10), e2 = Math.sqrt(2);
|
|
152062
|
+
function tickSpec(start, stop, count2) {
|
|
152063
|
+
const step = (stop - start) / Math.max(0, count2), power = Math.floor(Math.log10(step)), error2 = step / Math.pow(10, power), factor = error2 >= e10 ? 10 : error2 >= e5 ? 5 : error2 >= e2 ? 2 : 1;
|
|
152064
|
+
let i1, i2, inc;
|
|
152065
|
+
if (power < 0) {
|
|
152066
|
+
inc = Math.pow(10, -power) / factor;
|
|
152067
|
+
i1 = Math.round(start * inc);
|
|
152068
|
+
i2 = Math.round(stop * inc);
|
|
152069
|
+
if (i1 / inc < start) ++i1;
|
|
152070
|
+
if (i2 / inc > stop) --i2;
|
|
152071
|
+
inc = -inc;
|
|
152072
|
+
} else {
|
|
152073
|
+
inc = Math.pow(10, power) * factor;
|
|
152074
|
+
i1 = Math.round(start / inc);
|
|
152075
|
+
i2 = Math.round(stop / inc);
|
|
152076
|
+
if (i1 * inc < start) ++i1;
|
|
152077
|
+
if (i2 * inc > stop) --i2;
|
|
152078
|
+
}
|
|
152079
|
+
if (i2 < i1 && 0.5 <= count2 && count2 < 2) return tickSpec(start, stop, count2 * 2);
|
|
152080
|
+
return [i1, i2, inc];
|
|
152081
|
+
}
|
|
152003
152082
|
function ticks(start, stop, count2) {
|
|
152004
|
-
var reverse, i2 = -1, n2, ticks2, step;
|
|
152005
152083
|
stop = +stop, start = +start, count2 = +count2;
|
|
152006
|
-
if (
|
|
152007
|
-
if (
|
|
152008
|
-
|
|
152009
|
-
if (
|
|
152010
|
-
|
|
152011
|
-
|
|
152012
|
-
if (
|
|
152013
|
-
|
|
152014
|
-
while (++i2 < n2) ticks2[i2] = (r0 + i2) * step;
|
|
152084
|
+
if (!(count2 > 0)) return [];
|
|
152085
|
+
if (start === stop) return [start];
|
|
152086
|
+
const reverse = stop < start, [i1, i2, inc] = reverse ? tickSpec(stop, start, count2) : tickSpec(start, stop, count2);
|
|
152087
|
+
if (!(i2 >= i1)) return [];
|
|
152088
|
+
const n2 = i2 - i1 + 1, ticks2 = new Array(n2);
|
|
152089
|
+
if (reverse) {
|
|
152090
|
+
if (inc < 0) for (let i3 = 0; i3 < n2; ++i3) ticks2[i3] = (i2 - i3) / -inc;
|
|
152091
|
+
else for (let i3 = 0; i3 < n2; ++i3) ticks2[i3] = (i2 - i3) * inc;
|
|
152015
152092
|
} else {
|
|
152016
|
-
|
|
152017
|
-
let
|
|
152018
|
-
|
|
152019
|
-
if (r1 / step > stop) --r1;
|
|
152020
|
-
ticks2 = new Array(n2 = r1 - r0 + 1);
|
|
152021
|
-
while (++i2 < n2) ticks2[i2] = (r0 + i2) / step;
|
|
152022
|
-
}
|
|
152023
|
-
if (reverse) ticks2.reverse();
|
|
152093
|
+
if (inc < 0) for (let i3 = 0; i3 < n2; ++i3) ticks2[i3] = (i1 + i3) / -inc;
|
|
152094
|
+
else for (let i3 = 0; i3 < n2; ++i3) ticks2[i3] = (i1 + i3) * inc;
|
|
152095
|
+
}
|
|
152024
152096
|
return ticks2;
|
|
152025
152097
|
}
|
|
152026
152098
|
function tickIncrement(start, stop, count2) {
|
|
152027
|
-
|
|
152028
|
-
return
|
|
152099
|
+
stop = +stop, start = +start, count2 = +count2;
|
|
152100
|
+
return tickSpec(start, stop, count2)[2];
|
|
152029
152101
|
}
|
|
152030
152102
|
function tickStep(start, stop, count2) {
|
|
152031
|
-
|
|
152032
|
-
|
|
152033
|
-
|
|
152034
|
-
else if (error2 >= e2) step1 *= 2;
|
|
152035
|
-
return stop < start ? -step1 : step1;
|
|
152103
|
+
stop = +stop, start = +start, count2 = +count2;
|
|
152104
|
+
const reverse = stop < start, inc = reverse ? tickIncrement(stop, start, count2) : tickIncrement(start, stop, count2);
|
|
152105
|
+
return (reverse ? -1 : 1) * (inc < 0 ? 1 / -inc : inc);
|
|
152036
152106
|
}
|
|
152037
152107
|
function initRange(domain, range2) {
|
|
152038
152108
|
switch (arguments.length) {
|
|
@@ -153114,6 +153184,9 @@ function ramp(color2, n2 = 256) {
|
|
|
153114
153184
|
canvas.width = n2;
|
|
153115
153185
|
canvas.height = 1;
|
|
153116
153186
|
const context = canvas.getContext("2d");
|
|
153187
|
+
if (!context) {
|
|
153188
|
+
throw new Error("Could not get 2d context from canvas");
|
|
153189
|
+
}
|
|
153117
153190
|
for (let i2 = 0; i2 < n2; ++i2) {
|
|
153118
153191
|
context.fillStyle = color2(i2 / (n2 - 1));
|
|
153119
153192
|
context.fillRect(i2, 0, 1, 1);
|
|
@@ -153132,6 +153205,8 @@ function getXlinkHref(cmap) {
|
|
|
153132
153205
|
}
|
|
153133
153206
|
const useStyles = makeStyles()(() => ({
|
|
153134
153207
|
legend: {
|
|
153208
|
+
position: "relative",
|
|
153209
|
+
// Needed for absolute positioning of slider overlay
|
|
153135
153210
|
top: "2px",
|
|
153136
153211
|
right: "2px",
|
|
153137
153212
|
fontSize: "10px !important",
|
|
@@ -153163,6 +153238,74 @@ const useStyles = makeStyles()(() => ({
|
|
|
153163
153238
|
},
|
|
153164
153239
|
legendInvisible: {
|
|
153165
153240
|
display: "none"
|
|
153241
|
+
},
|
|
153242
|
+
sliderContainer: {
|
|
153243
|
+
position: "absolute",
|
|
153244
|
+
// Position at the colormap location: top offset = titleHeight
|
|
153245
|
+
top: "10px",
|
|
153246
|
+
// titleHeight
|
|
153247
|
+
left: "2px",
|
|
153248
|
+
// Account for parent padding
|
|
153249
|
+
width: "calc(100% - 4px)",
|
|
153250
|
+
// Account for left and right padding
|
|
153251
|
+
height: "8px",
|
|
153252
|
+
// rectHeight
|
|
153253
|
+
"&:hover $sliderThumb": {
|
|
153254
|
+
opacity: 1
|
|
153255
|
+
}
|
|
153256
|
+
},
|
|
153257
|
+
sliderRoot: {
|
|
153258
|
+
position: "absolute",
|
|
153259
|
+
top: 0,
|
|
153260
|
+
left: 0,
|
|
153261
|
+
width: "100%",
|
|
153262
|
+
height: "8px",
|
|
153263
|
+
// rectHeight
|
|
153264
|
+
padding: 0,
|
|
153265
|
+
"& .MuiSlider-rail": {
|
|
153266
|
+
display: "none"
|
|
153267
|
+
},
|
|
153268
|
+
"& .MuiSlider-track": {
|
|
153269
|
+
display: "none"
|
|
153270
|
+
},
|
|
153271
|
+
"& .MuiSlider-valueLabel": {
|
|
153272
|
+
fontSize: "9px",
|
|
153273
|
+
padding: "2px 4px",
|
|
153274
|
+
backgroundColor: "rgb(0, 0, 0)",
|
|
153275
|
+
borderRadius: "2px"
|
|
153276
|
+
}
|
|
153277
|
+
},
|
|
153278
|
+
sliderThumb: {
|
|
153279
|
+
width: "4px",
|
|
153280
|
+
height: "12px",
|
|
153281
|
+
borderRadius: "2px",
|
|
153282
|
+
backgroundColor: "white",
|
|
153283
|
+
border: "1px solid black",
|
|
153284
|
+
opacity: 0,
|
|
153285
|
+
transition: "opacity 0.15s ease-in-out",
|
|
153286
|
+
"&:hover, &.Mui-focusVisible": {
|
|
153287
|
+
boxShadow: "0 0 0 4px rgba(0, 0, 0, 0.16)",
|
|
153288
|
+
opacity: 1
|
|
153289
|
+
},
|
|
153290
|
+
"&.Mui-active": {
|
|
153291
|
+
boxShadow: "0 0 0 6px rgba(0, 0, 0, 0.16)",
|
|
153292
|
+
opacity: 1
|
|
153293
|
+
}
|
|
153294
|
+
},
|
|
153295
|
+
colormapImage: {
|
|
153296
|
+
position: "absolute",
|
|
153297
|
+
top: "2px",
|
|
153298
|
+
height: "6px",
|
|
153299
|
+
// rectHeight
|
|
153300
|
+
pointerEvents: "none"
|
|
153301
|
+
},
|
|
153302
|
+
grayTrack: {
|
|
153303
|
+
position: "absolute",
|
|
153304
|
+
top: "2px",
|
|
153305
|
+
height: "6px",
|
|
153306
|
+
// rectHeight
|
|
153307
|
+
backgroundColor: "rgba(128, 128, 128, 0.5)",
|
|
153308
|
+
pointerEvents: "none"
|
|
153166
153309
|
}
|
|
153167
153310
|
}));
|
|
153168
153311
|
const titleHeight = 10;
|
|
@@ -153172,21 +153315,23 @@ const rectMarginX = 2;
|
|
|
153172
153315
|
function combineExtents(extents, featureAggregationStrategy) {
|
|
153173
153316
|
if (Array.isArray(extents)) {
|
|
153174
153317
|
if (Array.isArray(extents == null ? void 0 : extents[0])) {
|
|
153318
|
+
const extentsArray = extents;
|
|
153175
153319
|
if (featureAggregationStrategy === "first") {
|
|
153176
|
-
return
|
|
153320
|
+
return extentsArray[0];
|
|
153177
153321
|
}
|
|
153178
153322
|
if (featureAggregationStrategy === "last") {
|
|
153179
|
-
return
|
|
153323
|
+
return extentsArray.at(-1) || null;
|
|
153180
153324
|
}
|
|
153181
153325
|
if (typeof featureAggregationStrategy === "number") {
|
|
153182
153326
|
const i2 = featureAggregationStrategy;
|
|
153183
|
-
return
|
|
153327
|
+
return extentsArray[i2];
|
|
153184
153328
|
}
|
|
153185
153329
|
if (featureAggregationStrategy === "sum") {
|
|
153186
|
-
return
|
|
153330
|
+
return extentsArray.reduce((a2, h) => [a2[0] + h[0], a2[1] + h[1]]);
|
|
153187
153331
|
}
|
|
153188
153332
|
if (featureAggregationStrategy === "mean") {
|
|
153189
|
-
|
|
153333
|
+
const sum2 = extentsArray.reduce((a2, h) => [a2[0] + h[0], a2[1] + h[1]]);
|
|
153334
|
+
return [sum2[0] / extentsArray.length, sum2[1] / extentsArray.length];
|
|
153190
153335
|
}
|
|
153191
153336
|
} else {
|
|
153192
153337
|
return extents;
|
|
@@ -153200,7 +153345,7 @@ function combineMissings(missings, featureAggregationStrategy) {
|
|
|
153200
153345
|
return missings[0];
|
|
153201
153346
|
}
|
|
153202
153347
|
if (featureAggregationStrategy === "last") {
|
|
153203
|
-
return missings.at(-1);
|
|
153348
|
+
return missings.at(-1) || null;
|
|
153204
153349
|
}
|
|
153205
153350
|
if (typeof featureAggregationStrategy === "number") {
|
|
153206
153351
|
const i2 = featureAggregationStrategy;
|
|
@@ -153216,52 +153361,127 @@ function combineMissings(missings, featureAggregationStrategy) {
|
|
|
153216
153361
|
return null;
|
|
153217
153362
|
}
|
|
153218
153363
|
function Legend(props) {
|
|
153219
|
-
const {
|
|
153220
|
-
|
|
153364
|
+
const {
|
|
153365
|
+
visible: visibleProp,
|
|
153366
|
+
positionRelative = false,
|
|
153367
|
+
highContrast = false,
|
|
153368
|
+
obsType,
|
|
153369
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
153370
|
+
featureType: _featureType = void 0,
|
|
153371
|
+
// Unused but accepted for API compatibility
|
|
153372
|
+
featureValueType,
|
|
153373
|
+
considerSelections = true,
|
|
153374
|
+
obsColorEncoding,
|
|
153375
|
+
featureSelection,
|
|
153376
|
+
featureLabelsMap,
|
|
153377
|
+
featureValueColormap,
|
|
153378
|
+
featureValueColormapRange,
|
|
153379
|
+
setFeatureValueColormapRange,
|
|
153380
|
+
spatialChannelColor,
|
|
153381
|
+
spatialLayerColor,
|
|
153382
|
+
obsSetSelection,
|
|
153383
|
+
obsSetColor,
|
|
153384
|
+
featureAggregationStrategy,
|
|
153385
|
+
extent: extent2,
|
|
153386
|
+
missing,
|
|
153387
|
+
width: width2 = 100,
|
|
153388
|
+
height: height2 = 36,
|
|
153389
|
+
maxHeight: maxHeight2 = null,
|
|
153390
|
+
theme,
|
|
153391
|
+
showObsLabel = false,
|
|
153392
|
+
pointsVisible = true,
|
|
153393
|
+
contoursVisible = false,
|
|
153394
|
+
contoursFilled,
|
|
153395
|
+
contourPercentiles,
|
|
153396
|
+
contourThresholds
|
|
153397
|
+
} = props;
|
|
153398
|
+
const svgRef = useRef(null);
|
|
153221
153399
|
const { classes } = useStyles();
|
|
153400
|
+
const [localRange, setLocalRange] = useState(featureValueColormapRange);
|
|
153401
|
+
useEffect(() => {
|
|
153402
|
+
setLocalRange(featureValueColormapRange);
|
|
153403
|
+
}, [featureValueColormapRange]);
|
|
153404
|
+
const debouncedSetRange = useMemo(() => setFeatureValueColormapRange ? debounce$1((value) => {
|
|
153405
|
+
setFeatureValueColormapRange(value);
|
|
153406
|
+
}, 5, { leading: false, trailing: true }) : null, [setFeatureValueColormapRange]);
|
|
153407
|
+
useEffect(() => () => {
|
|
153408
|
+
if (debouncedSetRange) {
|
|
153409
|
+
debouncedSetRange.cancel();
|
|
153410
|
+
}
|
|
153411
|
+
}, [debouncedSetRange]);
|
|
153412
|
+
const handleSliderChange = useCallback((_event, newValue) => {
|
|
153413
|
+
const rangeValue = newValue;
|
|
153414
|
+
setLocalRange(rangeValue);
|
|
153415
|
+
if (debouncedSetRange) {
|
|
153416
|
+
debouncedSetRange(rangeValue);
|
|
153417
|
+
}
|
|
153418
|
+
}, [debouncedSetRange]);
|
|
153222
153419
|
const isDarkTheme = theme === "dark";
|
|
153223
153420
|
const isStaticColor = obsColorEncoding === "spatialChannelColor" || obsColorEncoding === "spatialLayerColor";
|
|
153224
153421
|
const isSetColor = obsColorEncoding === "cellSetSelection";
|
|
153225
|
-
const layerColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : getDefaultColor(theme);
|
|
153226
|
-
const channelColor = Array.isArray(spatialChannelColor) && spatialChannelColor.length === 3 ? spatialChannelColor : getDefaultColor(theme);
|
|
153422
|
+
const layerColor = Array.isArray(spatialLayerColor) && spatialLayerColor.length === 3 ? spatialLayerColor : getDefaultColor(theme ?? "light");
|
|
153423
|
+
const channelColor = Array.isArray(spatialChannelColor) && spatialChannelColor.length === 3 ? spatialChannelColor : getDefaultColor(theme ?? "light");
|
|
153227
153424
|
const staticColor = obsColorEncoding === "spatialChannelColor" ? channelColor : layerColor;
|
|
153228
|
-
const visible = visibleProp && (!considerSelections || obsColorEncoding
|
|
153425
|
+
const visible = visibleProp && (!considerSelections || ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && featureSelection && Array.isArray(featureSelection) && featureSelection.length >= 1 || isSetColor && ((obsSetSelection == null ? void 0 : obsSetSelection.length) ?? 0) > 0 && ((obsSetColor == null ? void 0 : obsSetColor.length) ?? 0) > 0 || isStaticColor);
|
|
153229
153426
|
const levelZeroNames = useMemo(() => Array.from(new Set((obsSetSelection == null ? void 0 : obsSetSelection.map((setPath) => setPath[0])) || [])), [obsSetSelection]);
|
|
153230
|
-
const dynamicHeight = isSetColor && obsSetSelection ? levelZeroNames.length * titleHeight + (obsSetSelection == null ? void 0 : obsSetSelection.length) * (rectHeight + rectMarginY) : height2 + (!pointsVisible && contoursVisible ? 25 : 0);
|
|
153427
|
+
const dynamicHeight = isSetColor && obsSetSelection ? levelZeroNames.length * titleHeight + ((obsSetSelection == null ? void 0 : obsSetSelection.length) ?? 0) * (rectHeight + rectMarginY) : height2 + (!pointsVisible && contoursVisible ? 25 : 0);
|
|
153231
153428
|
const availHeight = maxHeight2 !== null ? Math.max(0, maxHeight2 - 4) : Infinity;
|
|
153232
153429
|
const needsScroll = Number.isFinite(availHeight) && dynamicHeight > availHeight + 1;
|
|
153233
153430
|
useEffect(() => {
|
|
153234
153431
|
const domElement = svgRef.current;
|
|
153432
|
+
if (!domElement)
|
|
153433
|
+
return;
|
|
153235
153434
|
const foregroundColor = highContrast ? "black" : isDarkTheme ? "white" : "black";
|
|
153236
153435
|
const svg = select(domElement);
|
|
153237
153436
|
svg.selectAll("g").remove();
|
|
153238
153437
|
svg.attr("width", width2).attr("height", dynamicHeight);
|
|
153239
153438
|
const g2 = svg.append("g").attr("width", width2).attr("height", dynamicHeight);
|
|
153240
|
-
|
|
153241
|
-
|
|
153439
|
+
const showInteractiveSlider2 = setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
153440
|
+
if (!considerSelections || ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "")) {
|
|
153441
|
+
const combinedExtent = combineExtents(extent2 ?? null, featureAggregationStrategy ?? null) || [0, 1];
|
|
153442
|
+
const [xMin, xMax] = combinedExtent;
|
|
153242
153443
|
if (featureValueColormap && pointsVisible) {
|
|
153243
|
-
const
|
|
153244
|
-
|
|
153245
|
-
const [rMin, rMax] =
|
|
153444
|
+
const xlinkHref2 = getXlinkHref(featureValueColormap);
|
|
153445
|
+
const currentRange = showInteractiveSlider2 ? localRange : featureValueColormapRange;
|
|
153446
|
+
const [rMin, rMax] = currentRange || [0, 1];
|
|
153447
|
+
if (showInteractiveSlider2) ;
|
|
153448
|
+
else if (setFeatureValueColormapRange) {
|
|
153449
|
+
g2.append("image").attr("x", rMin * width2).attr("y", titleHeight).attr("width", (rMax - rMin) * width2).attr("height", rectHeight).attr("preserveAspectRatio", "none").attr("href", xlinkHref2);
|
|
153450
|
+
} else {
|
|
153451
|
+
g2.append("image").attr("x", 0).attr("y", titleHeight).attr("width", width2).attr("height", rectHeight).attr("preserveAspectRatio", "none").attr("href", xlinkHref2);
|
|
153452
|
+
}
|
|
153246
153453
|
const scaledDataExtent = [
|
|
153247
153454
|
xMin + (xMax - xMin) * rMin,
|
|
153248
153455
|
xMax - (xMax - xMin) * (1 - rMax)
|
|
153249
153456
|
];
|
|
153250
|
-
|
|
153251
|
-
|
|
153252
|
-
|
|
153253
|
-
|
|
153254
|
-
|
|
153255
|
-
|
|
153457
|
+
let x;
|
|
153458
|
+
if (setFeatureValueColormapRange || showInteractiveSlider2) {
|
|
153459
|
+
x = linear().domain(scaledDataExtent).range([rMin * width2, rMax * width2]);
|
|
153460
|
+
} else {
|
|
153461
|
+
x = linear().domain(scaledDataExtent).range([0, width2]);
|
|
153462
|
+
}
|
|
153463
|
+
if (showInteractiveSlider2) {
|
|
153464
|
+
const xGlobal = linear().domain([xMin, xMax]).range([0, width2 - 4]);
|
|
153465
|
+
const axisTicks = g2.append("g").attr("transform", `translate(0,${titleHeight + rectHeight})`).style("font-size", "10px").call(axisBottom(xGlobal).tickValues([xMin, xMax]));
|
|
153466
|
+
axisTicks.selectAll("line,path").style("stroke", foregroundColor);
|
|
153467
|
+
axisTicks.selectAll("text").style("fill", foregroundColor);
|
|
153468
|
+
axisTicks.selectAll("text").attr("text-anchor", (_d, i2) => i2 === 0 ? "start" : "end");
|
|
153469
|
+
} else {
|
|
153470
|
+
const axisTicks = g2.append("g").attr("transform", `translate(0,${titleHeight + rectHeight})`).style("font-size", "10px").call(axisBottom(x).tickValues(scaledDataExtent));
|
|
153471
|
+
axisTicks.selectAll("line,path").style("stroke", foregroundColor);
|
|
153472
|
+
axisTicks.selectAll("text").style("fill", foregroundColor);
|
|
153473
|
+
axisTicks.selectAll("text").attr("text-anchor", (_d, i2) => i2 === 0 ? "start" : "end");
|
|
153474
|
+
}
|
|
153475
|
+
} else if (contoursVisible && contourPercentiles) {
|
|
153256
153476
|
const tSize = 12;
|
|
153257
153477
|
const xPercentile = linear().domain([0, 1]).range([tSize / 2, width2 - tSize / 2 - 2]);
|
|
153258
|
-
const axisTicks = g2.append("g").attr("transform", `translate(0,${titleHeight + rectHeight + 15})`).style("font-size", "9px").call(axisBottom(xPercentile).tickValues(contourPercentiles).tickFormat(format(".0%")).tickSizeOuter(0));
|
|
153478
|
+
const axisTicks = g2.append("g").attr("transform", `translate(0,${titleHeight + rectHeight + 15})`).style("font-size", "9px").call(axisBottom(xPercentile).tickValues(contourPercentiles).tickFormat((d) => format(".0%")(d)).tickSizeOuter(0));
|
|
153259
153479
|
axisTicks.selectAll("line,path").style("stroke", foregroundColor);
|
|
153260
153480
|
axisTicks.selectAll("text").style("fill", foregroundColor);
|
|
153261
153481
|
const NEIGHBOR_THRESHOLD = 18;
|
|
153262
|
-
const contourPercentages = contourPercentiles.map((
|
|
153482
|
+
const contourPercentages = contourPercentiles.map((p) => p * 100);
|
|
153263
153483
|
if ((contourPercentages == null ? void 0 : contourPercentages[1]) - (contourPercentages == null ? void 0 : contourPercentages[0]) <= NEIGHBOR_THRESHOLD || (contourPercentages == null ? void 0 : contourPercentages[2]) - (contourPercentages == null ? void 0 : contourPercentages[1]) <= NEIGHBOR_THRESHOLD) {
|
|
153264
|
-
axisTicks.selectAll("text").attr("transform", (
|
|
153484
|
+
axisTicks.selectAll("text").attr("transform", (_d, i2) => `translate(0,${i2 === 0 || i2 === contourPercentiles.length - 1 ? 0 : 10})`);
|
|
153265
153485
|
}
|
|
153266
153486
|
const triangleGroupG = g2.append("g").attr("transform", `translate(0,${titleHeight + rectHeight + 4})`);
|
|
153267
153487
|
contourPercentiles.forEach((p, i2) => {
|
|
@@ -153271,7 +153491,7 @@ function Legend(props) {
|
|
|
153271
153491
|
const thresholdGroupG = g2.append("g").attr("transform", `translate(0,${titleHeight + rectHeight})`);
|
|
153272
153492
|
const thresholdFormatter = format(".0f");
|
|
153273
153493
|
contourPercentiles.forEach((p, i2) => {
|
|
153274
|
-
const contourThreshold = xMin + (xMax - xMin) * ((contourThresholds == null ? void 0 : contourThresholds[i2]) / 255);
|
|
153494
|
+
const contourThreshold = xMin + (xMax - xMin) * (((contourThresholds == null ? void 0 : contourThresholds[i2]) ?? 0) / 255);
|
|
153275
153495
|
const thresholdG = thresholdGroupG.append("g").attr("transform", `translate(${xPercentile(p)},0)`).style("font-size", "7px");
|
|
153276
153496
|
thresholdG.append("text").text(thresholdFormatter(contourThreshold)).style("fill", foregroundColor).attr("text-anchor", "middle");
|
|
153277
153497
|
});
|
|
@@ -153295,9 +153515,9 @@ function Legend(props) {
|
|
|
153295
153515
|
y += titleHeight;
|
|
153296
153516
|
setPaths.forEach((setPath) => {
|
|
153297
153517
|
var _a3;
|
|
153298
|
-
const setColor2 = ((_a3 = obsSetColor == null ? void 0 : obsSetColor.find((d) => isEqual$1(d.path, setPath))) == null ? void 0 : _a3.color) || getDefaultColor(theme);
|
|
153518
|
+
const setColor2 = ((_a3 = obsSetColor == null ? void 0 : obsSetColor.find((d) => isEqual$1(d.path, setPath))) == null ? void 0 : _a3.color) || getDefaultColor(theme ?? "light");
|
|
153299
153519
|
g2.append("rect").attr("x", 0).attr("y", y).attr("width", rectHeight).attr("height", rectHeight).attr("fill", `rgb(${setColor2[0]},${setColor2[1]},${setColor2[2]})`);
|
|
153300
|
-
g2.append("text").attr("text-anchor", "start").attr("dominant-baseline", "hanging").attr("x", rectHeight + rectMarginX).attr("y", y).text(setPath.at(-1)).style("font-size", "9px").style("fill", foregroundColor);
|
|
153520
|
+
g2.append("text").attr("text-anchor", "start").attr("dominant-baseline", "hanging").attr("x", rectHeight + rectMarginX).attr("y", y).text(setPath.at(-1) ?? "").style("font-size", "9px").style("fill", foregroundColor);
|
|
153301
153521
|
y += rectHeight + rectMarginY;
|
|
153302
153522
|
});
|
|
153303
153523
|
});
|
|
@@ -153318,17 +153538,17 @@ function Legend(props) {
|
|
|
153318
153538
|
} else {
|
|
153319
153539
|
featureSelectionLabelRawStr = featureSelectionLabelRaw == null ? void 0 : featureSelectionLabelRaw[0];
|
|
153320
153540
|
}
|
|
153321
|
-
const combinedMissing = combineMissings(missing, featureAggregationStrategy);
|
|
153541
|
+
const combinedMissing = combineMissings(missing ?? null, featureAggregationStrategy ?? null);
|
|
153322
153542
|
const featureSelectionLabel = combinedMissing ? `${featureSelectionLabelRawStr} (${Math.round(combinedMissing * 100)}% NaN)` : featureSelectionLabelRawStr;
|
|
153323
|
-
const obsLabel = capitalize$2(obsType);
|
|
153324
|
-
const featureLabel = considerSelections ? featureSelectionLabel || capitalize$2(featureValueType) : capitalize$2(featureValueType);
|
|
153543
|
+
const obsLabel = capitalize$2(obsType ?? null);
|
|
153544
|
+
const featureLabel = considerSelections ? featureSelectionLabel || capitalize$2(featureValueType ?? null) : capitalize$2(featureValueType ?? null);
|
|
153325
153545
|
const mainLabel = showObsLabel ? obsLabel : featureLabel;
|
|
153326
153546
|
const subLabel = showObsLabel ? featureLabel : null;
|
|
153327
153547
|
const hasSubLabel = subLabel !== null;
|
|
153328
153548
|
if (!isSetColor) {
|
|
153329
|
-
g2.append("text").attr("text-anchor", hasSubLabel ? "start" : "end").attr("dominant-baseline", "hanging").attr("x", hasSubLabel ? 0 : width2).attr("y", 0).text(mainLabel).style("font-size", "10px").style("fill", foregroundColor);
|
|
153549
|
+
g2.append("text").attr("text-anchor", hasSubLabel ? "start" : "end").attr("dominant-baseline", "hanging").attr("x", hasSubLabel ? 0 : width2 - 4).attr("y", 0).text(mainLabel ?? "").style("font-size", "10px").style("fill", foregroundColor);
|
|
153330
153550
|
if (hasSubLabel) {
|
|
153331
|
-
g2.append("text").attr("text-anchor", "end").attr("dominant-baseline", "hanging").attr("x", width2).attr("y", titleHeight).text(subLabel).style("font-size", "9px").style("fill", foregroundColor);
|
|
153551
|
+
g2.append("text").attr("text-anchor", "end").attr("dominant-baseline", "hanging").attr("x", width2).attr("y", titleHeight + rectHeight).text(subLabel ?? "").style("font-size", "9px").style("fill", foregroundColor);
|
|
153332
153552
|
}
|
|
153333
153553
|
}
|
|
153334
153554
|
}, [
|
|
@@ -153336,6 +153556,7 @@ function Legend(props) {
|
|
|
153336
153556
|
height2,
|
|
153337
153557
|
featureValueColormap,
|
|
153338
153558
|
featureValueColormapRange,
|
|
153559
|
+
localRange,
|
|
153339
153560
|
considerSelections,
|
|
153340
153561
|
obsType,
|
|
153341
153562
|
obsColorEncoding,
|
|
@@ -153354,20 +153575,63 @@ function Legend(props) {
|
|
|
153354
153575
|
contoursFilled,
|
|
153355
153576
|
contoursVisible,
|
|
153356
153577
|
pointsVisible,
|
|
153357
|
-
featureAggregationStrategy
|
|
153578
|
+
featureAggregationStrategy,
|
|
153579
|
+
setFeatureValueColormapRange,
|
|
153580
|
+
dynamicHeight,
|
|
153581
|
+
highContrast,
|
|
153582
|
+
isStaticColor,
|
|
153583
|
+
missing,
|
|
153584
|
+
showObsLabel,
|
|
153585
|
+
staticColor
|
|
153358
153586
|
]);
|
|
153359
|
-
|
|
153587
|
+
const showInteractiveSlider = setFeatureValueColormapRange && ["geneSelection", "geneExpression"].includes(obsColorEncoding ?? "") && pointsVisible && featureValueColormap;
|
|
153588
|
+
const globalExtent = useMemo(() => {
|
|
153589
|
+
const combined = combineExtents(extent2 ?? null, featureAggregationStrategy ?? null);
|
|
153590
|
+
return combined || [0, 1];
|
|
153591
|
+
}, [extent2, featureAggregationStrategy]);
|
|
153592
|
+
const formatSliderValue = useCallback((value) => {
|
|
153593
|
+
const [xMin, xMax] = globalExtent;
|
|
153594
|
+
const dataValue = xMin + (xMax - xMin) * value;
|
|
153595
|
+
const range2 = xMax - xMin;
|
|
153596
|
+
if (range2 < 0.01) {
|
|
153597
|
+
return dataValue.toExponential(2);
|
|
153598
|
+
}
|
|
153599
|
+
if (range2 < 1) {
|
|
153600
|
+
return dataValue.toFixed(3);
|
|
153601
|
+
}
|
|
153602
|
+
if (range2 < 100) {
|
|
153603
|
+
return dataValue.toFixed(1);
|
|
153604
|
+
}
|
|
153605
|
+
return Math.round(dataValue).toString();
|
|
153606
|
+
}, [globalExtent]);
|
|
153607
|
+
const xlinkHref = featureValueColormap ? getXlinkHref(featureValueColormap) : null;
|
|
153608
|
+
const currentLocalRange = localRange || [0, 1];
|
|
153609
|
+
return jsxRuntimeExports.jsxs("div", { className: clsx$1(classes.legend, {
|
|
153360
153610
|
[classes.legendRelative]: positionRelative,
|
|
153361
153611
|
[classes.legendAbsolute]: !positionRelative,
|
|
153362
153612
|
[classes.legendHighContrast]: highContrast,
|
|
153363
153613
|
[classes.legendLowContrast]: !highContrast,
|
|
153364
153614
|
[classes.legendInvisible]: !visible
|
|
153365
153615
|
}), style: {
|
|
153366
|
-
...needsScroll ? { maxHeight: `${Math.floor(availHeight)}px`, overflowY: "auto" } : { maxHeight: void 0, overflowY: "visible" }
|
|
153367
|
-
|
|
153616
|
+
...needsScroll ? { maxHeight: `${Math.floor(availHeight)}px`, overflowY: "auto" } : { maxHeight: void 0, overflowY: "visible" },
|
|
153617
|
+
width: `${width2}px`
|
|
153618
|
+
}, children: [jsxRuntimeExports.jsx("svg", { ref: svgRef, style: {
|
|
153368
153619
|
width: `${width2}px`,
|
|
153369
153620
|
height: `${dynamicHeight}px`
|
|
153370
|
-
} })
|
|
153621
|
+
} }), showInteractiveSlider && xlinkHref && jsxRuntimeExports.jsxs("div", { className: classes.sliderContainer, children: [currentLocalRange[0] > 0 && jsxRuntimeExports.jsx("div", { className: classes.grayTrack, style: {
|
|
153622
|
+
left: 0,
|
|
153623
|
+
width: `${currentLocalRange[0] * 100}%`
|
|
153624
|
+
} }), currentLocalRange[1] < 1 && jsxRuntimeExports.jsx("div", { className: classes.grayTrack, style: {
|
|
153625
|
+
left: `${currentLocalRange[1] * 100}%`,
|
|
153626
|
+
width: `${(1 - currentLocalRange[1]) * 100}%`
|
|
153627
|
+
} }), jsxRuntimeExports.jsx("img", { src: xlinkHref, alt: "Colormap gradient", className: classes.colormapImage, style: {
|
|
153628
|
+
left: `${currentLocalRange[0] * 100}%`,
|
|
153629
|
+
width: `${(currentLocalRange[1] - currentLocalRange[0]) * 100}%`
|
|
153630
|
+
} }), jsxRuntimeExports.jsx(Slider, { className: classes.sliderRoot, value: currentLocalRange, onChange: handleSliderChange, min: 0, max: 1, step: 0.01, disableSwap: true, valueLabelDisplay: "auto", valueLabelFormat: formatSliderValue, "aria-label": "Colormap range", getAriaLabel: (index2) => index2 === 0 ? "Colormap minimum" : "Colormap maximum", getAriaValueText: (value) => formatSliderValue(value), slotProps: {
|
|
153631
|
+
thumb: {
|
|
153632
|
+
className: classes.sliderThumb
|
|
153633
|
+
}
|
|
153634
|
+
} })] })] });
|
|
153371
153635
|
}
|
|
153372
153636
|
makeStyles()(() => ({
|
|
153373
153637
|
multiLegend: {
|
|
@@ -153715,7 +153979,8 @@ function EmbeddingScatterplotSubscriber(props) {
|
|
|
153715
153979
|
xRange,
|
|
153716
153980
|
yRange,
|
|
153717
153981
|
width2,
|
|
153718
|
-
height2
|
|
153982
|
+
height2,
|
|
153983
|
+
numCells
|
|
153719
153984
|
);
|
|
153720
153985
|
setDynamicCellRadius(pointSizeDevicePixels);
|
|
153721
153986
|
const nextCellOpacityScale = getPointOpacity(
|
|
@@ -153768,11 +154033,18 @@ function EmbeddingScatterplotSubscriber(props) {
|
|
|
153768
154033
|
const getCellIsSelected = useCallback((object2, { index: index2 }) => (cellSelectionSet || /* @__PURE__ */ new Set([])).has(obsEmbeddingIndex[index2]) ? 1 : 0, [cellSelectionSet, obsEmbeddingIndex]);
|
|
153769
154034
|
const cellRadius = cellRadiusMode === "manual" ? cellRadiusFixed : dynamicCellRadius;
|
|
153770
154035
|
const cellOpacity = cellOpacityMode === "manual" ? cellOpacityFixed : dynamicCellOpacity;
|
|
154036
|
+
const aggregatedExpressionData = useMemo(() => {
|
|
154037
|
+
if (featureAggregationStrategyToUse != null && expressionData && expressionData.length > 1) {
|
|
154038
|
+
const aggregated = aggregateFeatureArrays(expressionData, featureAggregationStrategyToUse);
|
|
154039
|
+
return [aggregated];
|
|
154040
|
+
}
|
|
154041
|
+
return expressionData;
|
|
154042
|
+
}, [expressionData, featureAggregationStrategyToUse]);
|
|
153771
154043
|
const {
|
|
153772
154044
|
normData: uint8ExpressionData,
|
|
153773
154045
|
extents: expressionExtents,
|
|
153774
154046
|
missing: expressionMissing
|
|
153775
|
-
} = useUint8FeatureSelection(
|
|
154047
|
+
} = useUint8FeatureSelection(aggregatedExpressionData);
|
|
153776
154048
|
const getExpressionValue = useExpressionValueGetter({
|
|
153777
154049
|
instanceObsIndex: obsEmbeddingIndex,
|
|
153778
154050
|
matrixObsIndex,
|
|
@@ -154015,6 +154287,7 @@ function EmbeddingScatterplotSubscriber(props) {
|
|
|
154015
154287
|
featureLabelsMap,
|
|
154016
154288
|
featureValueColormap: geneExpressionColormap,
|
|
154017
154289
|
featureValueColormapRange: geneExpressionColormapRange,
|
|
154290
|
+
setFeatureValueColormapRange: setGeneExpressionColormapRange,
|
|
154018
154291
|
obsSetSelection: cellSetSelection,
|
|
154019
154292
|
extent: expressionExtents,
|
|
154020
154293
|
missing: expressionMissing,
|
package/dist/index.js
CHANGED
|
@@ -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-
|
|
2
|
+
import { g as getDefaultExportFromCjs, B as BaseDecoder } from "./index-BgrJUaQb.js";
|
|
3
3
|
const LercParameters = {
|
|
4
4
|
AddCompression: 1
|
|
5
5
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmbeddingScatterplotSubscriber.d.ts","sourceRoot":"","sources":["../src/EmbeddingScatterplotSubscriber.js"],"names":[],"mappings":"AA6CA;;;;;;;;;;;;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,
|
|
1
|
+
{"version":3,"file":"EmbeddingScatterplotSubscriber.d.ts","sourceRoot":"","sources":["../src/EmbeddingScatterplotSubscriber.js"],"names":[],"mappings":"AA6CA;;;;;;;;;;;;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,eA6mBA"}
|
|
@@ -5,7 +5,7 @@ import { isEqual } from 'lodash-es';
|
|
|
5
5
|
import { circle } from '@turf/circle';
|
|
6
6
|
import { TitleInfo, useReady, useUrls, useDeckCanvasSize, useUint8FeatureSelection, useExpressionValueGetter, useGetObsInfo, useObsEmbeddingData, useObsSetsData, useFeatureSelection, useObsFeatureMatrixIndices, useFeatureLabelsData, useMultiObsLabels, useSampleSetsData, useSampleEdgesData, useCoordination, useLoaders, useSetComponentHover, useSetComponentViewInfo, useInitialCoordination, useExpandedFeatureLabelsMap, useCoordinationScopes, } from '@vitessce/vit-s';
|
|
7
7
|
import { setObsSelection, mergeObsSets, getCellSetPolygons, getCellColors, stratifyArrays, } from '@vitessce/sets-utils';
|
|
8
|
-
import { pluralize as plur, commaNumber } from '@vitessce/utils';
|
|
8
|
+
import { pluralize as plur, commaNumber, aggregateFeatureArrays } from '@vitessce/utils';
|
|
9
9
|
import { Scatterplot, ScatterplotTooltipSubscriber, ScatterplotOptions, getPointSizeDevicePixels, getPointOpacity, } from '@vitessce/scatterplot';
|
|
10
10
|
import { Legend } from '@vitessce/legend';
|
|
11
11
|
import { ViewType, COMPONENT_COORDINATION_TYPES, ViewHelpMapping } from '@vitessce/constants-internal';
|
|
@@ -148,7 +148,7 @@ export function EmbeddingScatterplotSubscriber(props) {
|
|
|
148
148
|
// extents of the cell coordinates on the x/y axes.
|
|
149
149
|
useEffect(() => {
|
|
150
150
|
if (xRange && yRange && width && height) {
|
|
151
|
-
const pointSizeDevicePixels = getPointSizeDevicePixels(window.devicePixelRatio, zoom, xRange, yRange, width, height);
|
|
151
|
+
const pointSizeDevicePixels = getPointSizeDevicePixels(window.devicePixelRatio, zoom, xRange, yRange, width, height, numCells);
|
|
152
152
|
setDynamicCellRadius(pointSizeDevicePixels);
|
|
153
153
|
const nextCellOpacityScale = getPointOpacity(zoom, xRange, yRange, width, height, numCells, averageFillDensity);
|
|
154
154
|
setDynamicCellOpacity(nextCellOpacityScale);
|
|
@@ -182,7 +182,17 @@ export function EmbeddingScatterplotSubscriber(props) {
|
|
|
182
182
|
const getCellIsSelected = useCallback((object, { index }) => ((cellSelectionSet || new Set([])).has(obsEmbeddingIndex[index]) ? 1.0 : 0.0), [cellSelectionSet, obsEmbeddingIndex]);
|
|
183
183
|
const cellRadius = (cellRadiusMode === 'manual' ? cellRadiusFixed : dynamicCellRadius);
|
|
184
184
|
const cellOpacity = (cellOpacityMode === 'manual' ? cellOpacityFixed : dynamicCellOpacity);
|
|
185
|
-
|
|
185
|
+
// Compute aggregated expression data if featureAggregationStrategyToUse is not null
|
|
186
|
+
// and we have multiple features to aggregate.
|
|
187
|
+
const aggregatedExpressionData = useMemo(() => {
|
|
188
|
+
if (featureAggregationStrategyToUse != null && expressionData && expressionData.length > 1) {
|
|
189
|
+
const aggregated = aggregateFeatureArrays(expressionData, featureAggregationStrategyToUse);
|
|
190
|
+
// Return as array with single element to match expressionData structure
|
|
191
|
+
return [aggregated];
|
|
192
|
+
}
|
|
193
|
+
return expressionData;
|
|
194
|
+
}, [expressionData, featureAggregationStrategyToUse]);
|
|
195
|
+
const { normData: uint8ExpressionData, extents: expressionExtents, missing: expressionMissing, } = useUint8FeatureSelection(aggregatedExpressionData);
|
|
186
196
|
// Set up a getter function for gene expression values, to be used
|
|
187
197
|
// by the DeckGL layer to obtain values for instanced attributes.
|
|
188
198
|
const getExpressionValue = useExpressionValueGetter({
|
|
@@ -316,7 +326,7 @@ export function EmbeddingScatterplotSubscriber(props) {
|
|
|
316
326
|
}, updateViewInfo: setComponentViewInfo, getExpressionValue: getExpressionValue, getCellIsSelected: getCellIsSelected, obsSetSelection: cellSetSelection, sampleSetSelection: sampleSetSelection,
|
|
317
327
|
// InternMap data structures where keys are
|
|
318
328
|
// obsSet -> sampleSet -> arrayKey -> [].
|
|
319
|
-
stratifiedData: stratifiedData, obsSetColor: cellSetColor, sampleSetColor: sampleSetColor, contourThresholds: contourThresholds, contourColorEncoding: contourColorEncoding, contourColor: contourColor, contoursFilled: embeddingContoursFilled, embeddingPointsVisible: embeddingPointsVisible, embeddingContoursVisible: embeddingContoursVisible, circleInfo: circleInfo, featureSelection: geneSelection }), tooltipsVisible && width && height ? (_jsx(ScatterplotTooltipSubscriber, { parentUuid: uuid, obsHighlight: cellHighlight, width: width, height: height, getObsInfo: getObsInfo, featureType: featureType, featureLabelsMap: featureLabelsMap })) : null, _jsx(Legend, { visible: true, theme: theme, featureType: featureType, featureValueType: featureValueType, obsColorEncoding: cellColorEncoding, featureSelection: geneSelection, featureLabelsMap: featureLabelsMap, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, obsSetSelection: cellSetSelection, extent: expressionExtents, missing: expressionMissing,
|
|
329
|
+
stratifiedData: stratifiedData, obsSetColor: cellSetColor, sampleSetColor: sampleSetColor, contourThresholds: contourThresholds, contourColorEncoding: contourColorEncoding, contourColor: contourColor, contoursFilled: embeddingContoursFilled, embeddingPointsVisible: embeddingPointsVisible, embeddingContoursVisible: embeddingContoursVisible, circleInfo: circleInfo, featureSelection: geneSelection }), tooltipsVisible && width && height ? (_jsx(ScatterplotTooltipSubscriber, { parentUuid: uuid, obsHighlight: cellHighlight, width: width, height: height, getObsInfo: getObsInfo, featureType: featureType, featureLabelsMap: featureLabelsMap })) : null, _jsx(Legend, { visible: true, theme: theme, featureType: featureType, featureValueType: featureValueType, obsColorEncoding: cellColorEncoding, featureSelection: geneSelection, featureLabelsMap: featureLabelsMap, featureValueColormap: geneExpressionColormap, featureValueColormapRange: geneExpressionColormapRange, setFeatureValueColormapRange: setGeneExpressionColormapRange, obsSetSelection: cellSetSelection, extent: expressionExtents, missing: expressionMissing,
|
|
320
330
|
// Contour percentile legend
|
|
321
331
|
pointsVisible: embeddingPointsVisible, contoursVisible: embeddingContoursVisible, contoursFilled: embeddingContoursFilled, contourPercentiles: contourPercentiles || DEFAULT_CONTOUR_PERCENTILES, contourThresholds: contourThresholds, featureAggregationStrategy: featureAggregationStrategyToUse })] }));
|
|
322
332
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vitessce/scatterplot-embedding",
|
|
3
|
-
"version": "3.8.
|
|
3
|
+
"version": "3.8.10",
|
|
4
4
|
"author": "HIDIVE Lab at HMS",
|
|
5
5
|
"homepage": "http://vitessce.io",
|
|
6
6
|
"repository": {
|
|
@@ -20,13 +20,13 @@
|
|
|
20
20
|
"lodash-es": "^4.17.21",
|
|
21
21
|
"react-aria": "^3.28.0",
|
|
22
22
|
"@turf/circle": "^7.2.0",
|
|
23
|
-
"@vitessce/styles": "3.8.
|
|
24
|
-
"@vitessce/constants-internal": "3.8.
|
|
25
|
-
"@vitessce/legend": "3.8.
|
|
26
|
-
"@vitessce/
|
|
27
|
-
"@vitessce/utils": "3.8.
|
|
28
|
-
"@vitessce/
|
|
29
|
-
"@vitessce/
|
|
23
|
+
"@vitessce/styles": "3.8.10",
|
|
24
|
+
"@vitessce/constants-internal": "3.8.10",
|
|
25
|
+
"@vitessce/legend": "3.8.10",
|
|
26
|
+
"@vitessce/scatterplot": "3.8.10",
|
|
27
|
+
"@vitessce/sets-utils": "3.8.10",
|
|
28
|
+
"@vitessce/utils": "3.8.10",
|
|
29
|
+
"@vitessce/vit-s": "3.8.10"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"react": "18.3.1",
|
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
setObsSelection, mergeObsSets, getCellSetPolygons, getCellColors,
|
|
32
32
|
stratifyArrays,
|
|
33
33
|
} from '@vitessce/sets-utils';
|
|
34
|
-
import { pluralize as plur, commaNumber } from '@vitessce/utils';
|
|
34
|
+
import { pluralize as plur, commaNumber, aggregateFeatureArrays } from '@vitessce/utils';
|
|
35
35
|
import {
|
|
36
36
|
Scatterplot, ScatterplotTooltipSubscriber, ScatterplotOptions,
|
|
37
37
|
getPointSizeDevicePixels,
|
|
@@ -335,7 +335,7 @@ export function EmbeddingScatterplotSubscriber(props) {
|
|
|
335
335
|
useEffect(() => {
|
|
336
336
|
if (xRange && yRange && width && height) {
|
|
337
337
|
const pointSizeDevicePixels = getPointSizeDevicePixels(
|
|
338
|
-
window.devicePixelRatio, zoom, xRange, yRange, width, height,
|
|
338
|
+
window.devicePixelRatio, zoom, xRange, yRange, width, height, numCells,
|
|
339
339
|
);
|
|
340
340
|
setDynamicCellRadius(pointSizeDevicePixels);
|
|
341
341
|
|
|
@@ -365,7 +365,7 @@ export function EmbeddingScatterplotSubscriber(props) {
|
|
|
365
365
|
setOriginalViewState({ target: [initialTargetX, initialTargetY, 0], zoom: initialZoom });
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
|
-
|
|
368
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
369
369
|
}, [xRange, yRange, xExtent, yExtent, numCells,
|
|
370
370
|
width, height, initialZoom, zoom, initialTargetX, initialTargetY, averageFillDensity]);
|
|
371
371
|
|
|
@@ -381,11 +381,22 @@ export function EmbeddingScatterplotSubscriber(props) {
|
|
|
381
381
|
const cellRadius = (cellRadiusMode === 'manual' ? cellRadiusFixed : dynamicCellRadius);
|
|
382
382
|
const cellOpacity = (cellOpacityMode === 'manual' ? cellOpacityFixed : dynamicCellOpacity);
|
|
383
383
|
|
|
384
|
+
// Compute aggregated expression data if featureAggregationStrategyToUse is not null
|
|
385
|
+
// and we have multiple features to aggregate.
|
|
386
|
+
const aggregatedExpressionData = useMemo(() => {
|
|
387
|
+
if (featureAggregationStrategyToUse != null && expressionData && expressionData.length > 1) {
|
|
388
|
+
const aggregated = aggregateFeatureArrays(expressionData, featureAggregationStrategyToUse);
|
|
389
|
+
// Return as array with single element to match expressionData structure
|
|
390
|
+
return [aggregated];
|
|
391
|
+
}
|
|
392
|
+
return expressionData;
|
|
393
|
+
}, [expressionData, featureAggregationStrategyToUse]);
|
|
394
|
+
|
|
384
395
|
const {
|
|
385
396
|
normData: uint8ExpressionData,
|
|
386
397
|
extents: expressionExtents,
|
|
387
398
|
missing: expressionMissing,
|
|
388
|
-
} = useUint8FeatureSelection(
|
|
399
|
+
} = useUint8FeatureSelection(aggregatedExpressionData);
|
|
389
400
|
|
|
390
401
|
// Set up a getter function for gene expression values, to be used
|
|
391
402
|
// by the DeckGL layer to obtain values for instanced attributes.
|
|
@@ -651,6 +662,7 @@ export function EmbeddingScatterplotSubscriber(props) {
|
|
|
651
662
|
featureLabelsMap={featureLabelsMap}
|
|
652
663
|
featureValueColormap={geneExpressionColormap}
|
|
653
664
|
featureValueColormapRange={geneExpressionColormapRange}
|
|
665
|
+
setFeatureValueColormapRange={setGeneExpressionColormapRange}
|
|
654
666
|
obsSetSelection={cellSetSelection}
|
|
655
667
|
extent={expressionExtents}
|
|
656
668
|
missing={expressionMissing}
|